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 saveJobs( KGlobal::config().data() );
00125 delete d;
00126 }
00127
00128
00129 void KTimerPref::add()
00130 {
00131 KTimerJob *job = new KTimerJob;
00132 KTimerJobItem *item = new KTimerJobItem( job, m_list );
00133
00134 connect( job, SIGNAL(delayChanged(KTimerJob*,unsigned int)),
00135 SLOT(jobChanged(KTimerJob*)) );
00136 connect( job, SIGNAL(valueChanged(KTimerJob*,unsigned int)),
00137 SLOT(jobChanged(KTimerJob*)) );
00138 connect( job, SIGNAL(stateChanged(KTimerJob*,States)),
00139 SLOT(jobChanged(KTimerJob*)) );
00140 connect( job, SIGNAL(commandChanged(KTimerJob*,const QString&)),
00141 SLOT(jobChanged(KTimerJob*)) );
00142 connect( job, SIGNAL(finished(KTimerJob*,bool)),
00143 SLOT(jobFinished(KTimerJob*,bool)) );
00144
00145 job->setUser( item );
00146
00147
00148 if( m_list->topLevelItemCount()==1 )
00149 currentChanged( item , NULL);
00150
00151 m_list->setCurrentItem( item );
00152 m_list->update();
00153 }
00154
00155
00156 void KTimerPref::remove()
00157 {
00158 delete m_list->currentItem();
00159 m_list->update();
00160 }
00161
00162
00163
00164 void KTimerPref::currentChanged( QTreeWidgetItem *i , QTreeWidgetItem * )
00165 {
00166 KTimerJobItem *item = static_cast<KTimerJobItem*>(i);
00167 if( item ) {
00168 KTimerJob *job = item->job();
00169
00170 m_state->setEnabled( true );
00171 m_settings->setEnabled( true );
00172 m_remove->setEnabled( true );
00173
00174 m_delay->disconnect();
00175 m_loop->disconnect();
00176 m_one->disconnect();
00177 m_start->disconnect();
00178 m_pause->disconnect();
00179 m_stop->disconnect();
00180 m_counter->disconnect();
00181 m_slider->disconnect();
00182 m_commandLine->disconnect();
00183 m_commandLine->lineEdit()->disconnect();
00184
00185 connect( m_commandLine->lineEdit(), SIGNAL(textChanged(const QString &)),
00186 job, SLOT(setCommand(const QString &)) );
00187 connect( m_delay, SIGNAL(valueChanged(int)),
00188 job, SLOT(setDelay(int)) );
00189 connect( m_loop, SIGNAL(toggled(bool)),
00190 job, SLOT(setLoop(bool)) );
00191 connect( m_one, SIGNAL(toggled(bool)),
00192 job, SLOT(setOneInstance(bool)) );
00193 connect( m_stop, SIGNAL(clicked()),
00194 job, SLOT(stop()) );
00195 connect( m_pause, SIGNAL(clicked()),
00196 job, SLOT(pause()) );
00197 connect( m_start, SIGNAL(clicked()),
00198 job, SLOT(start()) );
00199 connect( m_slider, SIGNAL(valueChanged(int)),
00200 job, SLOT(setValue(int)) );
00201
00202 m_commandLine->lineEdit()->setText( job->command() );
00203 m_delay->setValue( job->delay() );
00204 m_loop->setChecked( job->loop() );
00205 m_one->setChecked( job->oneInstance() );
00206 m_counter->display( (int)job->value() );
00207 m_slider->setMaximum( job->delay() );
00208 m_slider->setValue( job->value() );
00209
00210 } else {
00211 m_state->setEnabled( false );
00212 m_settings->setEnabled( false );
00213 m_remove->setEnabled( false );
00214 }
00215 }
00216
00217
00218 void KTimerPref::jobChanged( KTimerJob *job )
00219 {
00220 KTimerJobItem *item = static_cast<KTimerJobItem*>(job->user());
00221 if( item ) {
00222 item->update();
00223 m_list->update();
00224
00225 if( item==m_list->currentItem() ) {
00226
00227
00228 m_slider->setMaximum( job->delay() );
00229 m_slider->setValue( job->value() );
00230 m_counter->display( (int)job->value() );
00231 }
00232 }
00233 }
00234
00235
00236 void KTimerPref::jobFinished( KTimerJob *job, bool error )
00237 {
00238 KTimerJobItem *item = static_cast<KTimerJobItem*>(job->user());
00239 item->setStatus( error );
00240 m_list->update();
00241 }
00242
00243
00244 void KTimerPref::saveJobs( KConfig *cfg )
00245 {
00246 for (int num = 0; num < m_list->topLevelItemCount(); ++num)
00247 {
00248 KTimerJobItem *item = static_cast<KTimerJobItem*>(m_list->topLevelItem(num));
00249 item->job()->save( cfg, QString("Job%1").arg( num ) );
00250
00251 }
00252
00253 KConfigGroup jobscfg = cfg->group("Jobs");
00254 jobscfg.writeEntry( "Number", m_list->topLevelItemCount());
00255
00256 jobscfg.sync();
00257 }
00258
00259
00260 void KTimerPref::loadJobs( KConfig *cfg )
00261 {
00262 int num = cfg->group("Jobs").readEntry( "Number", 0 );
00263 for( int n=0; n<num; n++ ) {
00264 KTimerJob *job = new KTimerJob;
00265 KTimerJobItem *item = new KTimerJobItem( job, m_list );
00266
00267 connect( job, SIGNAL(delayChanged(KTimerJob*,unsigned int)),
00268 SLOT(jobChanged(KTimerJob*)) );
00269 connect( job, SIGNAL(valueChanged(KTimerJob*,unsigned int)),
00270 SLOT(jobChanged(KTimerJob*)) );
00271 connect( job, SIGNAL(stateChanged(KTimerJob*,States)),
00272 SLOT(jobChanged(KTimerJob*)) );
00273 connect( job, SIGNAL(commandChanged(KTimerJob*,const QString&)),
00274 SLOT(jobChanged(KTimerJob*)) );
00275 connect( job, SIGNAL(finished(KTimerJob*,bool)),
00276 SLOT(jobFinished(KTimerJob*,bool)) );
00277
00278 job->load( cfg, QString( "Job%1" ).arg(n) );
00279
00280 job->setUser( item );
00281 }
00282
00283 m_list->update();
00284 }
00285
00286
00287
00288
00289
00290 struct KTimerJobPrivate {
00291 unsigned delay;
00292 QString command;
00293 bool loop;
00294 bool oneInstance;
00295 unsigned value;
00296 KTimerJob::States state;
00297 QList<QProcess *> processes;
00298 void *user;
00299
00300 QTimer *timer;
00301 };
00302
00303
00304 KTimerJob::KTimerJob( QObject *parent)
00305 : QObject( parent )
00306 {
00307 d = new KTimerJobPrivate;
00308
00309 d->delay = 100;
00310 d->loop = false;
00311 d->oneInstance = true;
00312 d->value = 100;
00313 d->state = Stopped;
00314 d->user = 0;
00315
00316 d->timer = new QTimer( this );
00317 connect( d->timer, SIGNAL(timeout()), SLOT(timeout()) );
00318 }
00319
00320
00321 KTimerJob::~KTimerJob()
00322 {
00323 delete d;
00324 }
00325
00326
00327 void KTimerJob::load( KConfig *cfg, const QString& grp )
00328 {
00329 KConfigGroup groupcfg = cfg->group(grp);
00330 groupcfg.writeEntry( "Delay", d->delay );
00331 groupcfg.writePathEntry( "Command", d->command );
00332 groupcfg.writeEntry( "Loop", d->loop );
00333 groupcfg.writeEntry( "OneInstance", d->oneInstance );
00334 groupcfg.writeEntry( "State", (int)d->state );
00335 }
00336
00337
00338 void KTimerJob::save( KConfig *cfg, const QString& grp )
00339 {
00340 KConfigGroup groupcfg = cfg->group(grp);
00341 setDelay( groupcfg.readEntry( "Delay", 100 ) );
00342 setCommand( groupcfg.readPathEntry( "Command", QString() ) );
00343 setLoop( groupcfg.readEntry( "Loop", false ) );
00344 setOneInstance( groupcfg.readEntry( "OneInstance", d->oneInstance ) );
00345 setState( (States)groupcfg.readEntry( "State", (int)Stopped ) );
00346 }
00347
00348
00349 void *KTimerJob::user()
00350 {
00351 return d->user;
00352 }
00353
00354
00355 void KTimerJob::setUser( void *user )
00356 {
00357 d->user = user;
00358 }
00359
00360
00361 unsigned KTimerJob::delay() const
00362 {
00363 return d->delay;
00364 }
00365
00366
00367 void KTimerJob::pause()
00368 {
00369 setState( Paused );
00370 }
00371
00372 void KTimerJob::stop()
00373 {
00374 setState( Stopped );
00375 }
00376
00377 void KTimerJob::start()
00378 {
00379 setState( Started );
00380 }
00381
00382 void KTimerJob::setDelay( int sec )
00383 {
00384 setDelay( (unsigned)sec );
00385 }
00386
00387 void KTimerJob::setValue( int value )
00388 {
00389 setValue( (unsigned)value );
00390 }
00391
00392 void KTimerJob::setDelay( unsigned sec )
00393 {
00394 if( d->delay!=sec ) {
00395 d->delay = sec;
00396
00397 if( d->state==Stopped )
00398 setValue( sec );
00399
00400 emit delayChanged( this, sec );
00401 emit changed( this );
00402 }
00403 }
00404
00405
00406 QString KTimerJob::command() const
00407 {
00408 return d->command;
00409 }
00410
00411
00412 void KTimerJob::setCommand( const QString &cmd )
00413 {
00414 if( d->command!=cmd ) {
00415 d->command = cmd;
00416 emit commandChanged( this, cmd );
00417 emit changed( this );
00418 }
00419 }
00420
00421
00422 bool KTimerJob::loop() const
00423 {
00424 return d->loop;
00425 }
00426
00427
00428 void KTimerJob::setLoop( bool loop )
00429 {
00430 if( d->loop!=loop ) {
00431 d->loop = loop;
00432 emit loopChanged( this, loop );
00433 emit changed( this );
00434 }
00435 }
00436
00437
00438 bool KTimerJob::oneInstance() const
00439 {
00440 return d->oneInstance;
00441 }
00442
00443
00444 void KTimerJob::setOneInstance( bool one )
00445 {
00446 if( d->oneInstance!=one ) {
00447 d->oneInstance = one;
00448 emit oneInstanceChanged( this, one );
00449 emit changed( this );
00450 }
00451 }
00452
00453
00454 unsigned KTimerJob::value() const
00455 {
00456 return d->value;
00457 }
00458
00459
00460 void KTimerJob::setValue( unsigned value )
00461 {
00462 if( d->value!=value ) {
00463 d->value = value;
00464 emit valueChanged( this, value );
00465 emit changed( this );
00466 }
00467 }
00468
00469
00470 KTimerJob::States KTimerJob::state() const
00471 {
00472 return d->state;
00473 }
00474
00475
00476 void KTimerJob::setState( KTimerJob::States state )
00477 {
00478 if( d->state!=state ) {
00479 if( state==Started )
00480 d->timer->start( 1000 );
00481 else
00482 d->timer->stop();
00483
00484 if( state==Stopped )
00485 setValue( d->delay );
00486
00487 d->state = state;
00488 emit stateChanged( this, state );
00489 emit changed( this );
00490 }
00491 }
00492
00493
00494 void KTimerJob::timeout()
00495 {
00496 if( d->state==Started && d->value!=0 ) {
00497 setValue( d->value-1 );
00498 if( d->value==0 ) {
00499 fire();
00500 if( d->loop )
00501 setValue( d->delay );
00502 else
00503 stop();
00504 }
00505 }
00506 }
00507
00508
00509 void KTimerJob::processExited(int, QProcess::ExitStatus status)
00510 {
00511 QProcess * proc = static_cast<QProcess*>(sender());
00512 bool ok = status==0;
00513 int i = d->processes.indexOf( proc);
00514 if (i != -1)
00515 delete d->processes.takeAt(i);
00516
00517 if( !ok ) emit error( this );
00518 emit finished( this, !ok );
00519 }
00520
00521
00522 void KTimerJob::fire()
00523 {
00524 if( !d->oneInstance || d->processes.isEmpty() ) {
00525 QProcess *proc = new QProcess;
00526 d->processes.append( proc );
00527 connect( proc, SIGNAL(finished(int, QProcess::ExitStatus)),
00528 SLOT(processExited(int, QProcess::ExitStatus)) );
00529 if (!d->command.isEmpty()) {
00530 proc->start(d->command);
00531 emit fired( this );
00532 }
00533 if(proc->state() == QProcess::NotRunning) {
00534 int i = d->processes.indexOf( proc);
00535 if (i != -1)
00536 delete d->processes.takeAt(i);
00537 emit error( this );
00538 emit finished( this, true );
00539 }
00540 }
00541 }
00542 #include "ktimer.moc"