00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ktimer.h"
00020
00021 #include <QProcess>
00022 #include <QTimer>
00023
00024 #include <klineedit.h>
00025 #include <kiconloader.h>
00026 #include <kapplication.h>
00027 #include <ksystemtrayicon.h>
00028 #include <kfiledialog.h>
00029 #include <kglobal.h>
00030
00031 class KTimerJobItem : public QTreeWidgetItem {
00032 public:
00033 KTimerJobItem( KTimerJob *job, QTreeWidget *parent )
00034 : QTreeWidgetItem() {
00035 parent->addTopLevelItem(this);
00036 m_job = job;
00037 m_error = false;
00038 update();
00039 }
00040
00041 KTimerJobItem( KTimerJob *job, QTreeWidget * parent, QTreeWidgetItem *after )
00042 : QTreeWidgetItem() {
00043 int otherItemIndex = parent->indexOfTopLevelItem(after);
00044 parent->insertTopLevelItem(otherItemIndex + 1, this);
00045 m_job = job;
00046 m_error = false;
00047 update();
00048 }
00049
00050 virtual ~KTimerJobItem() {
00051 delete m_job;
00052 }
00053
00054 KTimerJob *job() { return m_job; }
00055
00056 void setStatus( bool error ) {
00057 m_error = error;
00058 update();
00059 }
00060
00061 void update() {
00062 setText( 0, QString::number(m_job->value()) );
00063
00064 if( m_error )
00065 setIcon( 0, KIcon("process-stop") );
00066 else
00067 setIcon( 0, QPixmap() );
00068
00069 setText( 1, QString::number(m_job->delay()) );
00070
00071 switch( m_job->state() ) {
00072 case KTimerJob::Stopped: setIcon( 2, KIcon("media-playback-stop") ); break;
00073 case KTimerJob::Paused: setIcon( 2, KIcon("media-playback-pause") ); break;
00074 case KTimerJob::Started: setIcon( 2, KIcon("arrow-right") ); break;
00075 }
00076
00077 setText( 3, m_job->command() );
00078 }
00079
00080 private:
00081 bool m_error;
00082 KTimerJob *m_job;
00083 };
00084
00085
00086
00087
00088
00089 struct KTimerPrefPrivate
00090 {
00091 QList<KTimerJob *> jobs;
00092 };
00093
00094 KTimerPref::KTimerPref( QWidget *parent)
00095 : QDialog( parent )
00096 {
00097 d = new KTimerPrefPrivate;
00098
00099 setupUi(this);
00100
00101
00102 m_stop->setIcon( KIcon("media-playback-stop") );
00103 m_pause->setIcon( KIcon("media-playback-pause") );
00104 m_start->setIcon( KIcon("arrow-right") );
00105
00106
00107 KSystemTrayIcon *tray = new KSystemTrayIcon( this );
00108 tray->show();
00109 tray->setIcon( KIcon( "ktimer" ) );
00110
00111
00112 connect( m_add, SIGNAL(clicked()), SLOT(add()) );
00113 connect( m_remove, SIGNAL(clicked()), SLOT(remove()) );
00114 connect( m_list, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
00115 SLOT(currentChanged(QTreeWidgetItem *, QTreeWidgetItem *)) );
00116 loadJobs( KGlobal::config().data() );
00117
00118 show();
00119 }
00120
00121
00122 KTimerPref::~KTimerPref()
00123 {
00124 delete d;
00125 }
00126
00127 void KTimerPref::saveAllJobs() {
00128 saveJobs( KGlobal::config().data() );
00129 }
00130
00131
00132 void KTimerPref::add()
00133 {
00134 KTimerJob *job = new KTimerJob;
00135 KTimerJobItem *item = new KTimerJobItem( job, m_list );
00136
00137 connect( job, SIGNAL(delayChanged(KTimerJob*,unsigned int)),
00138 SLOT(jobChanged(KTimerJob*)) );
00139 connect( job, SIGNAL(valueChanged(KTimerJob*,unsigned int)),
00140 SLOT(jobChanged(KTimerJob*)) );
00141 connect( job, SIGNAL(stateChanged(KTimerJob*,States)),
00142 SLOT(jobChanged(KTimerJob*)) );
00143 connect( job, SIGNAL(commandChanged(KTimerJob*,const QString&)),
00144 SLOT(jobChanged(KTimerJob*)) );
00145 connect( job, SIGNAL(finished(KTimerJob*,bool)),
00146 SLOT(jobFinished(KTimerJob*,bool)) );
00147
00148 job->setUser( item );
00149
00150
00151 if( m_list->topLevelItemCount()==1 )
00152 currentChanged( item , NULL);
00153
00154 m_list->setCurrentItem( item );
00155 m_list->update();
00156 }
00157
00158
00159 void KTimerPref::remove()
00160 {
00161 delete m_list->currentItem();
00162 m_list->update();
00163 }
00164
00165
00166
00167 void KTimerPref::currentChanged( QTreeWidgetItem *i , QTreeWidgetItem * )
00168 {
00169 KTimerJobItem *item = static_cast<KTimerJobItem*>(i);
00170 if( item ) {
00171 KTimerJob *job = item->job();
00172
00173 m_state->setEnabled( true );
00174 m_settings->setEnabled( true );
00175 m_remove->setEnabled( true );
00176
00177 m_delay->disconnect();
00178 m_loop->disconnect();
00179 m_one->disconnect();
00180 m_start->disconnect();
00181 m_pause->disconnect();
00182 m_stop->disconnect();
00183 m_counter->disconnect();
00184 m_slider->disconnect();
00185 m_commandLine->disconnect();
00186 m_commandLine->lineEdit()->disconnect();
00187
00188 connect( m_commandLine->lineEdit(), SIGNAL(textChanged(const QString &)),
00189 job, SLOT(setCommand(const QString &)) );
00190 connect( m_delay, SIGNAL(valueChanged(int)),
00191 job, SLOT(setDelay(int)) );
00192 connect( m_loop, SIGNAL(toggled(bool)),
00193 job, SLOT(setLoop(bool)) );
00194 connect( m_one, SIGNAL(toggled(bool)),
00195 job, SLOT(setOneInstance(bool)) );
00196 connect( m_stop, SIGNAL(clicked()),
00197 job, SLOT(stop()) );
00198 connect( m_pause, SIGNAL(clicked()),
00199 job, SLOT(pause()) );
00200 connect( m_start, SIGNAL(clicked()),
00201 job, SLOT(start()) );
00202 connect( m_slider, SIGNAL(valueChanged(int)),
00203 job, SLOT(setValue(int)) );
00204
00205 m_commandLine->lineEdit()->setText( job->command() );
00206 m_delay->setValue( job->delay() );
00207 m_loop->setChecked( job->loop() );
00208 m_one->setChecked( job->oneInstance() );
00209 m_counter->display( (int)job->value() );
00210 m_slider->setMaximum( job->delay() );
00211 m_slider->setValue( job->value() );
00212
00213 } else {
00214 m_state->setEnabled( false );
00215 m_settings->setEnabled( false );
00216 m_remove->setEnabled( false );
00217 }
00218 }
00219
00220 const QString KTimerPref::formatSeconds( int seconds ) {
00221 if(seconds<60) return QString("%1").arg(seconds);
00222 return QString("%1:%2").arg( (int)seconds/60, 2, 10, QChar('0') ).arg( (int)seconds%60, 2, 10, QChar('0') );
00223 }
00224
00225 void KTimerPref::jobChanged( KTimerJob *job )
00226 {
00227 KTimerJobItem *item = static_cast<KTimerJobItem*>(job->user());
00228 if( item ) {
00229 item->update();
00230 m_list->update();
00231
00232 if( item==m_list->currentItem() ) {
00233
00234
00235 m_slider->setMaximum( job->delay() );
00236 m_slider->setValue( job->value() );
00237 m_counter->display( (int)job->value() );
00238 }
00239 }
00240 }
00241
00242
00243 void KTimerPref::jobFinished( KTimerJob *job, bool error )
00244 {
00245 KTimerJobItem *item = static_cast<KTimerJobItem*>(job->user());
00246 item->setStatus( error );
00247 m_list->update();
00248 }
00249
00250 void KTimerPref::done(int result) {
00251 saveAllJobs();
00252 QDialog::done(result);
00253 }
00254
00255 void KTimerPref::saveJobs( KConfig *cfg )
00256 {
00257 for (int num = 0; num < m_list->topLevelItemCount(); ++num)
00258 {
00259 KTimerJobItem *item = static_cast<KTimerJobItem*>(m_list->topLevelItem(num));
00260 item->job()->save( cfg, QString("Job%1").arg( num ) );
00261
00262 }
00263
00264 KConfigGroup jobscfg = cfg->group("Jobs");
00265 jobscfg.writeEntry( "Number", m_list->topLevelItemCount());
00266
00267 jobscfg.sync();
00268 }
00269
00270
00271 void KTimerPref::loadJobs( KConfig *cfg )
00272 {
00273 int num = cfg->group("Jobs").readEntry( "Number", 0 );
00274 for( int n=0; n<num; n++ ) {
00275 KTimerJob *job = new KTimerJob;
00276 KTimerJobItem *item = new KTimerJobItem( job, m_list );
00277
00278 connect( job, SIGNAL(delayChanged(KTimerJob*,unsigned int)),
00279 SLOT(jobChanged(KTimerJob*)) );
00280 connect( job, SIGNAL(valueChanged(KTimerJob*,unsigned int)),
00281 SLOT(jobChanged(KTimerJob*)) );
00282 connect( job, SIGNAL(stateChanged(KTimerJob*,States)),
00283 SLOT(jobChanged(KTimerJob*)) );
00284 connect( job, SIGNAL(commandChanged(KTimerJob*,const QString&)),
00285 SLOT(jobChanged(KTimerJob*)) );
00286 connect( job, SIGNAL(finished(KTimerJob*,bool)),
00287 SLOT(jobFinished(KTimerJob*,bool)) );
00288
00289 job->load( cfg, QString( "Job%1" ).arg(n) );
00290
00291 job->setUser( item );
00292 jobChanged ( job);
00293 }
00294
00295 m_list->update();
00296 }
00297
00298
00299
00300
00301
00302 struct KTimerJobPrivate {
00303 unsigned delay;
00304 QString command;
00305 bool loop;
00306 bool oneInstance;
00307 unsigned value;
00308 KTimerJob::States state;
00309 QList<QProcess *> processes;
00310 void *user;
00311
00312 QTimer *timer;
00313 };
00314
00315
00316 KTimerJob::KTimerJob( QObject *parent)
00317 : QObject( parent )
00318 {
00319 d = new KTimerJobPrivate;
00320
00321 d->delay = 100;
00322 d->loop = false;
00323 d->oneInstance = true;
00324 d->value = 100;
00325 d->state = Stopped;
00326 d->user = 0;
00327
00328 d->timer = new QTimer( this );
00329 connect( d->timer, SIGNAL(timeout()), SLOT(timeout()) );
00330 }
00331
00332
00333 KTimerJob::~KTimerJob()
00334 {
00335 delete d;
00336 }
00337
00338
00339 void KTimerJob::save( KConfig *cfg, const QString& grp )
00340 {
00341 KConfigGroup groupcfg = cfg->group(grp);
00342 groupcfg.writeEntry( "Delay", d->delay );
00343 groupcfg.writePathEntry( "Command", d->command );
00344 groupcfg.writeEntry( "Loop", d->loop );
00345 groupcfg.writeEntry( "OneInstance", d->oneInstance );
00346 groupcfg.writeEntry( "State", (int)d->state );
00347 }
00348
00349
00350 void KTimerJob::load( KConfig *cfg, const QString& grp )
00351 {
00352 KConfigGroup groupcfg = cfg->group(grp);
00353 setDelay( groupcfg.readEntry( "Delay", 100 ) );
00354 setCommand( groupcfg.readPathEntry( "Command", QString() ) );
00355 setLoop( groupcfg.readEntry( "Loop", false ) );
00356 setOneInstance( groupcfg.readEntry( "OneInstance", d->oneInstance ) );
00357 setState( (States)groupcfg.readEntry( "State", (int)Stopped ) );
00358 }
00359
00360
00361 void *KTimerJob::user()
00362 {
00363 return d->user;
00364 }
00365
00366
00367 void KTimerJob::setUser( void *user )
00368 {
00369 d->user = user;
00370 }
00371
00372
00373 unsigned KTimerJob::delay() const
00374 {
00375 return d->delay;
00376 }
00377
00378
00379 void KTimerJob::pause()
00380 {
00381 setState( Paused );
00382 }
00383
00384 void KTimerJob::stop()
00385 {
00386 setState( Stopped );
00387 }
00388
00389 void KTimerJob::start()
00390 {
00391 setState( Started );
00392 }
00393
00394 void KTimerJob::setDelay( int sec )
00395 {
00396 setDelay( (unsigned)sec );
00397 }
00398
00399 void KTimerJob::setValue( int value )
00400 {
00401 setValue( (unsigned)value );
00402 }
00403
00404 void KTimerJob::setDelay( unsigned sec )
00405 {
00406 if( d->delay!=sec ) {
00407 d->delay = sec;
00408
00409 if( d->state==Stopped )
00410 setValue( sec );
00411
00412 emit delayChanged( this, sec );
00413 emit changed( this );
00414 }
00415 }
00416
00417
00418 QString KTimerJob::command() const
00419 {
00420 return d->command;
00421 }
00422
00423
00424 void KTimerJob::setCommand( const QString &cmd )
00425 {
00426 if( d->command!=cmd ) {
00427 d->command = cmd;
00428 emit commandChanged( this, cmd );
00429 emit changed( this );
00430 }
00431 }
00432
00433
00434 bool KTimerJob::loop() const
00435 {
00436 return d->loop;
00437 }
00438
00439
00440 void KTimerJob::setLoop( bool loop )
00441 {
00442 if( d->loop!=loop ) {
00443 d->loop = loop;
00444 emit loopChanged( this, loop );
00445 emit changed( this );
00446 }
00447 }
00448
00449
00450 bool KTimerJob::oneInstance() const
00451 {
00452 return d->oneInstance;
00453 }
00454
00455
00456 void KTimerJob::setOneInstance( bool one )
00457 {
00458 if( d->oneInstance!=one ) {
00459 d->oneInstance = one;
00460 emit oneInstanceChanged( this, one );
00461 emit changed( this );
00462 }
00463 }
00464
00465
00466 unsigned KTimerJob::value() const
00467 {
00468 return d->value;
00469 }
00470
00471
00472 void KTimerJob::setValue( unsigned value )
00473 {
00474 if( d->value!=value ) {
00475 d->value = value;
00476 emit valueChanged( this, value );
00477 emit changed( this );
00478 }
00479 }
00480
00481
00482 KTimerJob::States KTimerJob::state() const
00483 {
00484 return d->state;
00485 }
00486
00487
00488 void KTimerJob::setState( KTimerJob::States state )
00489 {
00490 if( d->state!=state ) {
00491 if( state==Started )
00492 d->timer->start( 1000 );
00493 else
00494 d->timer->stop();
00495
00496 if( state==Stopped )
00497 setValue( d->delay );
00498
00499 d->state = state;
00500 emit stateChanged( this, state );
00501 emit changed( this );
00502 }
00503 }
00504
00505
00506 void KTimerJob::timeout()
00507 {
00508 if( d->state==Started && d->value!=0 ) {
00509 setValue( d->value-1 );
00510 if( d->value==0 ) {
00511 fire();
00512 if( d->loop )
00513 setValue( d->delay );
00514 else
00515 stop();
00516 }
00517 }
00518 }
00519
00520
00521 void KTimerJob::processExited(int, QProcess::ExitStatus status)
00522 {
00523 QProcess * proc = static_cast<QProcess*>(sender());
00524 bool ok = status==0;
00525 int i = d->processes.indexOf( proc);
00526 if (i != -1)
00527 delete d->processes.takeAt(i);
00528
00529 if( !ok ) emit error( this );
00530 emit finished( this, !ok );
00531 }
00532
00533
00534
00535
00536 void KTimerJob::fire()
00537 {
00538 if( !d->oneInstance || d->processes.isEmpty() ) {
00539 QProcess *proc = new QProcess;
00540 d->processes.append( proc );
00541 connect( proc, SIGNAL(finished(int, QProcess::ExitStatus)),
00542 SLOT(processExited(int, QProcess::ExitStatus)) );
00543 if (!d->command.isEmpty()) {
00544 proc->start(d->command);
00545 emit fired( this );
00546 }
00547 if(proc->state() == QProcess::NotRunning) {
00548 int i = d->processes.indexOf( proc);
00549 if (i != -1)
00550 delete d->processes.takeAt(i);
00551 emit error( this );
00552 emit finished( this, true );
00553 }
00554 }
00555 }
00556 #include "ktimer.moc"