00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <qhbox.h>
00026 #include <qvbox.h>
00027 #include <qlabel.h>
00028 #include <qfile.h>
00029 #include <qspinbox.h>
00030 #include <qlayout.h>
00031 #include <qpushbutton.h>
00032 #include <qcstring.h>
00033 #include <qdatastream.h>
00034
00035 #include <kapplication.h>
00036 #include <kconfig.h>
00037 #include <kiconloader.h>
00038 #include <dcopclient.h>
00039 #include <klocale.h>
00040 #include <kprocess.h>
00041 #include <kaudioplayer.h>
00042 #include <kdebug.h>
00043 #include <kmessagebox.h>
00044 #include <knotifyclient.h>
00045 #include <kcombobox.h>
00046 #include <klistview.h>
00047 #include <kwin.h>
00048 #include <klockfile.h>
00049
00050 #include <libkcal/event.h>
00051
00052 #include "koeventviewer.h"
00053
00054 #include "alarmdialog.h"
00055 #include "alarmdialog.moc"
00056
00057 class AlarmListItem : public KListViewItem
00058 {
00059 public:
00060 AlarmListItem( Incidence *incidence, QListView *parent ) :
00061 KListViewItem( parent ),
00062 mIncidence( incidence->clone() ),
00063 mNotified( false )
00064 {}
00065
00066 ~AlarmListItem()
00067 {
00068 delete mIncidence;
00069 }
00070
00071 Incidence *mIncidence;
00072 QDateTime mRemindAt;
00073 bool mNotified;
00074 };
00075
00076 typedef QValueList<AlarmListItem*> ItemList;
00077
00078 AlarmDialog::AlarmDialog( QWidget *parent, const char *name )
00079 : KDialogBase( Plain, WType_TopLevel | WStyle_Customize | WStyle_StaysOnTop |
00080 WStyle_DialogBorder,
00081 parent, name, false, i18n("Reminder"), Ok | User1 | User2 | User3, User1,
00082 false, i18n("Dismiss all"), i18n("Edit..."), i18n("Suspend") ),
00083 mSuspendTimer(this)
00084 {
00085 KGlobal::iconLoader()->addAppDir( "kdepim" );
00086 setButtonOK( i18n( "Dismiss" ) );
00087
00088 QWidget *topBox = plainPage();
00089 QBoxLayout *topLayout = new QVBoxLayout( topBox );
00090 topLayout->setSpacing( spacingHint() );
00091
00092 QLabel *label = new QLabel( i18n("The following events triggered reminders:"),
00093 topBox );
00094 topLayout->addWidget( label );
00095
00096 mIncidenceListView = new KListView( topBox );
00097 mIncidenceListView->addColumn( i18n( "Summary" ) );
00098 mIncidenceListView->addColumn( i18n( "Due" ) );
00099 mIncidenceListView->setAllColumnsShowFocus( true );
00100 mIncidenceListView->setSelectionMode( QListView::Extended );
00101 topLayout->addWidget( mIncidenceListView );
00102 connect( mIncidenceListView, SIGNAL(selectionChanged()), SLOT(updateButtons()) );
00103 connect( mIncidenceListView, SIGNAL(doubleClicked(QListViewItem*)), SLOT(slotUser2()) );
00104 connect( mIncidenceListView, SIGNAL(currentChanged(QListViewItem*)), SLOT(showDetails()) );
00105 connect( mIncidenceListView, SIGNAL(selectionChanged()), SLOT(showDetails()) );
00106
00107 mDetailView = new KOEventViewer( topBox );
00108 topLayout->addWidget( mDetailView );
00109
00110 QHBox *suspendBox = new QHBox( topBox );
00111 suspendBox->setSpacing( spacingHint() );
00112 topLayout->addWidget( suspendBox );
00113
00114 QLabel *l = new QLabel( i18n("Suspend &duration:"), suspendBox );
00115 mSuspendSpin = new QSpinBox( 1, 9999, 1, suspendBox );
00116 mSuspendSpin->setValue( 5 );
00117 l->setBuddy( mSuspendSpin );
00118
00119 mSuspendUnit = new KComboBox( suspendBox );
00120 mSuspendUnit->insertItem( i18n("minute(s)") );
00121 mSuspendUnit->insertItem( i18n("hour(s)") );
00122 mSuspendUnit->insertItem( i18n("day(s)") );
00123 mSuspendUnit->insertItem( i18n("week(s)") );
00124 connect( &mSuspendTimer, SIGNAL(timeout()), SLOT(wakeUp()) );
00125
00126
00127
00128 setMinimumSize( 300, 200 );
00129 }
00130
00131 AlarmDialog::~AlarmDialog()
00132 {
00133 mIncidenceListView->clear();
00134 }
00135
00136 void AlarmDialog::addIncidence( Incidence *incidence, const QDateTime &reminderAt )
00137 {
00138 AlarmListItem *item = new AlarmListItem( incidence, mIncidenceListView );
00139 item->setText( 0, incidence->summary() );
00140 item->mRemindAt = reminderAt;
00141 Todo *todo;
00142 if ( dynamic_cast<Event*>( incidence ) ) {
00143 item->setPixmap( 0, SmallIcon( "appointment" ) );
00144 if ( incidence->doesRecur() ) {
00145 QDateTime nextStart = incidence->recurrence()->getNextDateTime( reminderAt );
00146 if ( nextStart.isValid() )
00147 item->setText( 1, KGlobal::locale()->formatDateTime( nextStart ) );
00148 }
00149 if ( item->text( 1 ).isEmpty() )
00150 item->setText( 1, incidence->dtStartStr() );
00151 } else if ( (todo = dynamic_cast<Todo*>( incidence )) ) {
00152 item->setPixmap( 0, SmallIcon( "todo" ) );
00153 item->setText( 1, todo->dtDueStr() );
00154 }
00155 if ( activeCount() == 1 ) {
00156 mIncidenceListView->clearSelection();
00157 item->setSelected( true );
00158 }
00159 showDetails();
00160 }
00161
00162 void AlarmDialog::slotOk()
00163 {
00164 ItemList selection = selectedItems();
00165 for ( ItemList::Iterator it = selection.begin(); it != selection.end(); ++it ) {
00166 if ( (*it)->itemBelow() )
00167 (*it)->itemBelow()->setSelected( true );
00168 else if ( (*it)->itemAbove() )
00169 (*it)->itemAbove()->setSelected( true );
00170 delete *it;
00171 }
00172 if ( activeCount() == 0 )
00173 accept();
00174 else {
00175 updateButtons();
00176 showDetails();
00177 }
00178 emit reminderCount( activeCount() );
00179 }
00180
00181 void AlarmDialog::slotUser1()
00182 {
00183 dismissAll();
00184 }
00185
00186 void AlarmDialog::suspend()
00187 {
00188 if ( !isVisible() )
00189 return;
00190
00191 int unit=1;
00192 switch (mSuspendUnit->currentItem()) {
00193 case 3:
00194 unit *= 7;
00195 case 2:
00196 unit *= 24;
00197 case 1:
00198 unit *= 60;
00199 case 0:
00200 unit *= 60;
00201 default:
00202 break;
00203 }
00204
00205 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00206 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
00207 if ( item->isSelected() && item->isVisible() ) {
00208 item->setVisible( false );
00209 item->setSelected( false );
00210 item->mRemindAt = QDateTime::currentDateTime().addSecs( unit * mSuspendSpin->value() );
00211 item->mNotified = false;
00212 }
00213 }
00214
00215 setTimer();
00216 if ( activeCount() == 0 )
00217 accept();
00218 else {
00219 updateButtons();
00220 showDetails();
00221 }
00222 emit reminderCount( activeCount() );
00223 }
00224
00225 void AlarmDialog::setTimer()
00226 {
00227 int nextReminderAt = -1;
00228 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00229 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
00230 if ( item->mRemindAt > QDateTime::currentDateTime() ) {
00231 int secs = QDateTime::currentDateTime().secsTo( item->mRemindAt );
00232 nextReminderAt = nextReminderAt <= 0 ? secs : QMIN( nextReminderAt, secs );
00233 }
00234 }
00235
00236 if ( nextReminderAt >= 0 ) {
00237 mSuspendTimer.stop();
00238 mSuspendTimer.start( 1000 * (nextReminderAt + 1), true );
00239 }
00240 }
00241
00242 void AlarmDialog::slotUser2()
00243 {
00244 ItemList selection = selectedItems();
00245 if ( selection.count() != 1 )
00246 return;
00247 Incidence *incidence = selection.first()->mIncidence;
00248
00249 if ( !kapp->dcopClient()->isApplicationRegistered( "korganizer" ) ) {
00250 if ( kapp->startServiceByDesktopName( "korganizer", QString::null ) )
00251 KMessageBox::error( 0, i18n("Could not start KOrganizer.") );
00252 }
00253
00254 kapp->dcopClient()->send( "korganizer", "KOrganizerIface",
00255 "editIncidence(QString)",
00256 incidence->uid() );
00257
00258
00259 QByteArray replyData;
00260 QCString object, replyType;
00261 object = kapp->dcopClient()->isApplicationRegistered( "kontact" ) ?
00262 "kontact-mainwindow#1" : "KOrganizer MainWindow";
00263 if (!kapp->dcopClient()->call( "korganizer", object,
00264 "getWinID()", 0, replyType, replyData, true, -1 ) ) {
00265 }
00266
00267 if ( replyType == "int" ) {
00268 int desktop, window;
00269 QDataStream ds( replyData, IO_ReadOnly );
00270 ds >> window;
00271 desktop = KWin::windowInfo( window ).desktop();
00272
00273 if ( KWin::currentDesktop() == desktop ) {
00274 KWin::iconifyWindow( winId(), false );
00275 }
00276 else
00277 KWin::setCurrentDesktop( desktop );
00278
00279 KWin::activateWindow( KWin::transientFor( window ) );
00280 }
00281 }
00282
00283 void AlarmDialog::slotUser3()
00284 {
00285 suspend();
00286 }
00287
00288 void AlarmDialog::dismissAll()
00289 {
00290 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) {
00291 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
00292 if ( !item->isVisible() ) {
00293 ++it;
00294 continue;
00295 }
00296 delete item;
00297 }
00298 setTimer();
00299 accept();
00300 emit reminderCount( activeCount() );
00301 }
00302
00303 void AlarmDialog::show()
00304 {
00305 mIncidenceListView->clearSelection();
00306 if ( mIncidenceListView->firstChild() )
00307 mIncidenceListView->firstChild()->setSelected( true );
00308 updateButtons();
00309 KDialogBase::show();
00310 KWin::setState( winId(), NET::KeepAbove );
00311 KWin::setOnAllDesktops( winId(), true );
00312 eventNotification();
00313 }
00314
00315 void AlarmDialog::eventNotification()
00316 {
00317 bool beeped = false, found = false;
00318
00319 QValueList<AlarmListItem*> list;
00320 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00321 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
00322 if ( !item->isVisible() || item->mNotified )
00323 continue;
00324 found = true;
00325 item->mNotified = true;
00326 Alarm::List alarms = item->mIncidence->alarms();
00327 Alarm::List::ConstIterator it;
00328 for ( it = alarms.begin(); it != alarms.end(); ++it ) {
00329 Alarm *alarm = *it;
00330
00331 if (alarm->type() == Alarm::Procedure) {
00332
00333 kdDebug(5890) << "Starting program: '" << alarm->programFile() << "'" << endl;
00334 KProcess proc;
00335 proc << QFile::encodeName(alarm->programFile());
00336 proc.start(KProcess::DontCare);
00337 }
00338 else if (alarm->type() == Alarm::Audio) {
00339 beeped = true;
00340 KAudioPlayer::play(QFile::encodeName(alarm->audioFile()));
00341 }
00342 }
00343 }
00344
00345 if ( !beeped && found ) {
00346 KNotifyClient::beep();
00347 }
00348 }
00349
00350 void AlarmDialog::wakeUp()
00351 {
00352 bool activeReminders = false;
00353 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00354 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
00355 if ( item->mRemindAt <= QDateTime::currentDateTime() ) {
00356 if ( !item->isVisible() ) {
00357 item->setVisible( true );
00358 item->setSelected( false );
00359 }
00360 activeReminders = true;
00361 } else {
00362 item->setVisible( false );
00363 }
00364 }
00365
00366 if ( activeReminders )
00367 show();
00368 setTimer();
00369 showDetails();
00370 emit reminderCount( activeCount() );
00371 }
00372
00373 void AlarmDialog::slotSave()
00374 {
00375 KConfig *config = kapp->config();
00376 KLockFile::Ptr lock = config->lockFile();
00377 if ( lock.data()->lock() != KLockFile::LockOK )
00378 return;
00379
00380 config->setGroup( "General" );
00381 int numReminders = config->readNumEntry("Reminders", 0);
00382
00383 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00384 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
00385 config->setGroup( QString("Incidence-%1").arg(numReminders) );
00386 config->writeEntry( "UID", item->mIncidence->uid() );
00387 config->writeEntry( "RemindAt", item->mRemindAt );
00388 ++numReminders;
00389 }
00390
00391 config->setGroup( "General" );
00392 config->writeEntry( "Reminders", numReminders );
00393 config->sync();
00394 lock.data()->unlock();
00395 }
00396
00397 void AlarmDialog::updateButtons()
00398 {
00399 ItemList selection = selectedItems();
00400 enableButton( User2, selection.count() == 1 );
00401 enableButton( Ok, selection.count() > 0 );
00402 enableButton( User3, selection.count() > 0 );
00403 }
00404
00405 QValueList< AlarmListItem * > AlarmDialog::selectedItems() const
00406 {
00407 QValueList<AlarmListItem*> list;
00408 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00409 if ( it.current()->isSelected() )
00410 list.append( static_cast<AlarmListItem*>( it.current() ) );
00411 }
00412 return list;
00413 }
00414
00415 int AlarmDialog::activeCount()
00416 {
00417 int count = 0;
00418 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00419 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
00420 if ( item->isVisible() )
00421 ++count;
00422 }
00423 return count;
00424 }
00425
00426 void AlarmDialog::suspendAll()
00427 {
00428 mIncidenceListView->clearSelection();
00429 for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
00430 if ( it.current()->isVisible() )
00431 it.current()->setSelected( true );
00432 }
00433 suspend();
00434 }
00435
00436 void AlarmDialog::showDetails()
00437 {
00438 mDetailView->clearEvents( true );
00439 mDetailView->clear();
00440 AlarmListItem *item = static_cast<AlarmListItem*>( mIncidenceListView->currentItem() );
00441 if ( !item || !item->isVisible() )
00442 return;
00443 mDetailView->appendIncidence( item->mIncidence );
00444 }