alarmdialog.cpp
00001 /* 00002 This file is part of the KOrganizer alarm daemon. 00003 00004 Copyright (c) 2000,2003 Cornelius Schumacher <schumacher@kde.org> 00005 Copyright (c) 2009-2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 00021 As a special exception, permission is given to link this program 00022 with any edition of TQt, and distribute the resulting executable, 00023 without including the source code for TQt in the source distribution. 00024 */ 00025 00026 #include <tqhbox.h> 00027 #include <tqvbox.h> 00028 #include <tqlabel.h> 00029 #include <tqfile.h> 00030 #include <tqspinbox.h> 00031 #include <tqlayout.h> 00032 #include <tqpushbutton.h> 00033 #include <tqcstring.h> 00034 #include <tqdatastream.h> 00035 #include <tqsplitter.h> 00036 00037 #include <dcopclient.h> 00038 #include <dcopref.h> 00039 #include <tdeapplication.h> 00040 #include <tdeconfig.h> 00041 #include <kdcopservicestarter.h> 00042 #include <kiconloader.h> 00043 #include <tdelocale.h> 00044 #include <kprocess.h> 00045 #include <kaudioplayer.h> 00046 #include <kdebug.h> 00047 #include <tdemessagebox.h> 00048 #include <knotifyclient.h> 00049 #include <kcombobox.h> 00050 #include <tdelistview.h> 00051 #include <twin.h> 00052 #include <klockfile.h> 00053 00054 #include <libkcal/event.h> 00055 #include <libkcal/incidenceformatter.h> 00056 00057 #include "koeventviewer.h" 00058 00059 #include "alarmdialog.h" 00060 #include "alarmdialog.moc" 00061 00062 static int defSuspendVal = 5; 00063 static int defSuspendUnit = 0; // 0=>minutes, 1=>hours, 2=>days, 3=>weeks 00064 00065 class AlarmListItem : public TDEListViewItem 00066 { 00067 public: 00068 AlarmListItem( const TQString &uid, TQListView *parent ) 00069 : TDEListViewItem( parent ), mUid( uid ), mNotified( false ) 00070 { 00071 } 00072 00073 ~AlarmListItem() 00074 { 00075 } 00076 00077 int compare( TQListViewItem *item, int iCol, bool bAscending ) const; 00078 00079 TQString mDisplayText; 00080 00081 TQString mUid; 00082 TQDateTime mRemindAt; 00083 TQDateTime mHappening; 00084 bool mNotified; 00085 }; 00086 00087 int AlarmListItem::compare( TQListViewItem *item, int iCol, bool bAscending ) const 00088 { 00089 if ( iCol == 1 ) { 00090 AlarmListItem *pItem = static_cast<AlarmListItem *>( item ); 00091 return pItem->mHappening.secsTo( mHappening ); 00092 } else { 00093 return TDEListViewItem::compare( item, iCol, bAscending ); 00094 } 00095 } 00096 00097 typedef TQValueList<AlarmListItem*> ItemList; 00098 00099 AlarmDialog::AlarmDialog( KCal::CalendarResources *calendar, TQWidget *parent, const char *name ) 00100 : KDialogBase( Plain, 00101 WType_TopLevel | WStyle_Customize | WStyle_StaysOnTop | WStyle_DialogBorder, 00102 parent, name, false, i18n("Reminder"), 00103 Ok | User1 | User2 | User3, NoDefault, 00104 false, i18n("Edit..."), i18n("Dismiss All"), i18n("Dismiss Reminder") ), 00105 mCalendar( calendar ), mSuspendTimer(this) 00106 { 00107 // User1 => Edit... 00108 // User2 => Dismiss All 00109 // User3 => Dismiss Selected 00110 // Ok => Suspend 00111 00112 connect( calendar, TQT_SIGNAL(calendarChanged()), 00113 this, TQT_SLOT(slotCalendarChanged()) ); 00114 00115 TDEGlobal::iconLoader()->addAppDir( "tdepim" ); 00116 setButtonOK( i18n( "Suspend" ) ); 00117 00118 TQWidget *topBox = plainPage(); 00119 TQBoxLayout *topLayout = new TQVBoxLayout( topBox ); 00120 topLayout->setSpacing( spacingHint() ); 00121 00122 TQLabel *label = new TQLabel( i18n("The following items triggered reminders:"), topBox ); 00123 topLayout->addWidget( label ); 00124 00125 mSplitter = new TQSplitter( Qt::Vertical, topBox ); 00126 mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() ); 00127 topLayout->addWidget( mSplitter ); 00128 00129 mIncidenceListView = new TDEListView( mSplitter ); 00130 mIncidenceListView->addColumn( i18n( "Summary" ) ); 00131 mIncidenceListView->addColumn( i18n( "Date, Time" ) ); 00132 mIncidenceListView->setSorting( 0, true ); 00133 mIncidenceListView->setSorting( 1, true ); 00134 mIncidenceListView->setSortColumn( 1 ); 00135 mIncidenceListView->setShowSortIndicator( true ); 00136 mIncidenceListView->setAllColumnsShowFocus( true ); 00137 mIncidenceListView->setSelectionMode( TQListView::Extended ); 00138 connect( mIncidenceListView, TQT_SIGNAL(selectionChanged()), TQT_SLOT(updateButtons()) ); 00139 connect( mIncidenceListView, TQT_SIGNAL(doubleClicked(TQListViewItem*)), TQT_SLOT(edit()) ); 00140 connect( mIncidenceListView, TQT_SIGNAL(currentChanged(TQListViewItem*)), TQT_SLOT(showDetails()) ); 00141 connect( mIncidenceListView, TQT_SIGNAL(selectionChanged()), TQT_SLOT(showDetails()) ); 00142 00143 mDetailView = new KOEventViewer( mCalendar, mSplitter ); 00144 mDetailView->setFocus(); // set focus here to start with to make it harder 00145 // to hit return by mistake and dismiss a reminder. 00146 00147 TQHBox *suspendBox = new TQHBox( topBox ); 00148 suspendBox->setSpacing( spacingHint() ); 00149 topLayout->addWidget( suspendBox ); 00150 00151 TQLabel *l = new TQLabel( i18n("Suspend &duration:"), suspendBox ); 00152 mSuspendSpin = new TQSpinBox( 1, 9999, 1, suspendBox ); 00153 mSuspendSpin->setValue( defSuspendVal ); // default suspend duration 00154 l->setBuddy( mSuspendSpin ); 00155 00156 mSuspendUnit = new KComboBox( suspendBox ); 00157 mSuspendUnit->insertItem( i18n("minute(s)") ); 00158 mSuspendUnit->insertItem( i18n("hour(s)") ); 00159 mSuspendUnit->insertItem( i18n("day(s)") ); 00160 mSuspendUnit->insertItem( i18n("week(s)") ); 00161 mSuspendUnit->setCurrentItem( defSuspendUnit ); 00162 00163 connect( &mSuspendTimer, TQT_SIGNAL(timeout()), TQT_SLOT(wakeUp()) ); 00164 00165 setMainWidget( mIncidenceListView ); 00166 mIncidenceListView->setMinimumSize( 500, 50 ); 00167 00168 readLayout(); 00169 } 00170 00171 AlarmDialog::~AlarmDialog() 00172 { 00173 mIncidenceListView->clear(); 00174 } 00175 00176 AlarmListItem *AlarmDialog::searchByUid( const TQString &uid ) 00177 { 00178 AlarmListItem *found = 0; 00179 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) { 00180 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); 00181 if ( item->mUid == uid ) { 00182 found = item; 00183 break; 00184 } 00185 ++it; 00186 } 00187 return found; 00188 } 00189 00190 static TQString etc = i18n( "elipsis", "..." ); 00191 static TQString cleanSummary( const TQString &summary ) 00192 { 00193 uint maxLen = 45; 00194 TQString retStr = summary; 00195 retStr.replace( '\n', ' ' ); 00196 if ( retStr.length() > maxLen ) { 00197 maxLen -= etc.length(); 00198 retStr = retStr.left( maxLen ); 00199 retStr += etc; 00200 } 00201 return retStr; 00202 } 00203 00204 void AlarmDialog::readLayout() 00205 { 00206 TDEConfig *config = kapp->config(); 00207 config->setGroup( "Layout" ); 00208 TQValueList<int> sizes = config->readIntListEntry( "SplitterSizes" ); 00209 if ( sizes.count() == 2 ) { 00210 mSplitter->setSizes( sizes ); 00211 } 00212 mSplitter->setCollapsible( mIncidenceListView, false ); 00213 mSplitter->setCollapsible( mDetailView, false ); 00214 } 00215 00216 void AlarmDialog::writeLayout() 00217 { 00218 TDEConfig *config = kapp->config(); 00219 config->setGroup( "Layout" ); 00220 TQValueList<int> list = mSplitter->sizes(); 00221 config->writeEntry( "SplitterSizes", list ); 00222 } 00223 00224 void AlarmDialog::addIncidence( Incidence *incidence, 00225 const TQDateTime &reminderAt, 00226 const TQString &displayText ) 00227 { 00228 AlarmListItem *item = searchByUid( incidence->uid() ); 00229 if ( !item ) { 00230 item = new AlarmListItem( incidence->uid(), mIncidenceListView ); 00231 } 00232 item->mNotified = false; 00233 item->mHappening = TQDateTime(); 00234 item->mRemindAt = reminderAt; 00235 item->mDisplayText = displayText; 00236 item->setText( 0, cleanSummary( incidence->summary() ) ); 00237 item->setText( 1, TQString() ); 00238 00239 TQString displayStr; 00240 const TQDateTime dateTime = triggerDateForIncidence( incidence, reminderAt, displayStr ); 00241 00242 item->mHappening = dateTime; 00243 item->setText( 1, displayStr ); 00244 00245 if ( incidence->type() == "Event" ) { 00246 item->setPixmap( 0, SmallIcon( "appointment" ) ); 00247 } else { 00248 item->setPixmap( 0, SmallIcon( "todo" ) ); 00249 } 00250 00251 if ( activeCount() == 1 ) { // previously empty 00252 mIncidenceListView->clearSelection(); 00253 item->setSelected( true ); 00254 } 00255 showDetails(); 00256 } 00257 00258 void AlarmDialog::slotOk() 00259 { 00260 suspend(); 00261 } 00262 00263 void AlarmDialog::slotUser1() 00264 { 00265 edit(); 00266 } 00267 00268 void AlarmDialog::slotUser2() 00269 { 00270 dismissAll(); 00271 } 00272 00273 void AlarmDialog::slotUser3() 00274 { 00275 dismissCurrent(); 00276 } 00277 00278 void AlarmDialog::dismissCurrent() 00279 { 00280 ItemList selection = selectedItems(); 00281 for ( ItemList::Iterator it = selection.begin(); it != selection.end(); ++it ) { 00282 if ( (*it)->itemBelow() ) 00283 (*it)->itemBelow()->setSelected( true ); 00284 else if ( (*it)->itemAbove() ) 00285 (*it)->itemAbove()->setSelected( true ); 00286 delete *it; 00287 } 00288 if ( activeCount() == 0 ) { 00289 writeLayout(); 00290 accept(); 00291 } else { 00292 updateButtons(); 00293 showDetails(); 00294 } 00295 emit reminderCount( activeCount() ); 00296 } 00297 00298 void AlarmDialog::dismissAll() 00299 { 00300 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) { 00301 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); 00302 if ( !item->isVisible() ) { 00303 ++it; 00304 continue; 00305 } 00306 mIncidenceListView->takeItem( item ); 00307 delete item; 00308 } 00309 setTimer(); 00310 writeLayout(); 00311 accept(); 00312 emit reminderCount( activeCount() ); 00313 } 00314 00315 void AlarmDialog::edit() 00316 { 00317 ItemList selection = selectedItems(); 00318 if ( selection.count() != 1 ) { 00319 return; 00320 } 00321 Incidence *incidence = mCalendar->incidence( selection.first()->mUid ); 00322 if ( !incidence ) { 00323 return; 00324 } 00325 TQDate dt = selection.first()->mRemindAt.date(); 00326 00327 if ( incidence->isReadOnly() ) { 00328 KMessageBox::sorry( 00329 this, 00330 i18n( "\"%1\" is a read-only item so modifications are not possible." ). 00331 arg( cleanSummary( incidence->summary() ) ) ); 00332 return; 00333 } 00334 00335 if ( !ensureKorganizerRunning() ) { 00336 KMessageBox::error( 00337 this, 00338 i18n( "Could not start KOrganizer so editing is not possible." ) ); 00339 return; 00340 } 00341 00342 TQByteArray data; 00343 TQDataStream arg( data, IO_WriteOnly ); 00344 arg << incidence->uid(); 00345 arg << dt; 00346 //kdDebug(5890) << "editing incidence " << incidence->summary() << endl; 00347 if ( !kapp->dcopClient()->send( "korganizer", "KOrganizerIface", 00348 "editIncidence(TQString,TQDate)", 00349 data ) ) { 00350 KMessageBox::error( 00351 this, 00352 i18n( "An internal KOrganizer error occurred attempting to start the incidence editor" ) ); 00353 return; 00354 } 00355 00356 // get desktop # where korganizer (or kontact) runs 00357 TQByteArray replyData; 00358 TQCString object, replyType; 00359 object = kapp->dcopClient()->isApplicationRegistered( "kontact" ) ? 00360 "kontact-mainwindow#1" : "KOrganizer MainWindow"; 00361 if (!kapp->dcopClient()->call( "korganizer", object, 00362 "getWinID()", 0, replyType, replyData, true, -1 ) ) { 00363 } 00364 00365 if ( replyType == "int" ) { 00366 int desktop, window; 00367 TQDataStream ds( replyData, IO_ReadOnly ); 00368 ds >> window; 00369 desktop = KWin::windowInfo( window ).desktop(); 00370 00371 if ( KWin::currentDesktop() == desktop ) { 00372 KWin::iconifyWindow( winId(), false ); 00373 } else { 00374 KWin::setCurrentDesktop( desktop ); 00375 } 00376 KWin::activateWindow( KWin::transientFor( window ) ); 00377 } 00378 } 00379 00380 void AlarmDialog::suspend() 00381 { 00382 if ( !isVisible() ) 00383 return; 00384 00385 int unit=1; 00386 switch (mSuspendUnit->currentItem()) { 00387 case 3: // weeks 00388 unit *= 7; 00389 case 2: // days 00390 unit *= 24; 00391 case 1: // hours 00392 unit *= 60; 00393 case 0: // minutes 00394 unit *= 60; 00395 default: 00396 break; 00397 } 00398 00399 AlarmListItem *selitem = 0; 00400 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00401 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() ); 00402 if ( item->isSelected() && item->isVisible() ) { 00403 item->setVisible( false ); 00404 item->setSelected( false ); 00405 item->mRemindAt = TQDateTime::currentDateTime().addSecs( unit * mSuspendSpin->value() ); 00406 item->mNotified = false; 00407 selitem = item; 00408 } 00409 } 00410 if ( selitem ) { 00411 if ( selitem->itemBelow() ) { 00412 selitem->itemBelow()->setSelected( true ); 00413 } else if ( selitem->itemAbove() ) { 00414 selitem->itemAbove()->setSelected( true ); 00415 } 00416 } 00417 00418 // save suspended alarms too so they can be restored on restart 00419 // kolab/issue4108 00420 slotSave(); 00421 00422 setTimer(); 00423 if ( activeCount() == 0 ) { 00424 writeLayout(); 00425 accept(); 00426 } else { 00427 updateButtons(); 00428 showDetails(); 00429 } 00430 emit reminderCount( activeCount() ); 00431 } 00432 00433 void AlarmDialog::setTimer() 00434 { 00435 int nextReminderAt = -1; 00436 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00437 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() ); 00438 if ( item->mRemindAt > TQDateTime::currentDateTime() ) { 00439 int secs = TQDateTime::currentDateTime().secsTo( item->mRemindAt ); 00440 nextReminderAt = nextReminderAt <= 0 ? secs : TQMIN( nextReminderAt, secs ); 00441 } 00442 } 00443 00444 if ( nextReminderAt >= 0 ) { 00445 mSuspendTimer.stop(); 00446 mSuspendTimer.start( 1000 * (nextReminderAt + 1), true ); 00447 } 00448 } 00449 00450 void AlarmDialog::show() 00451 { 00452 mIncidenceListView->sort(); 00453 00454 // select the first item that hasn't already been notified 00455 mIncidenceListView->clearSelection(); 00456 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00457 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); 00458 if ( !item->mNotified ) { 00459 (*it)->setSelected( true ); 00460 break; 00461 } 00462 } 00463 00464 updateButtons(); 00465 showDetails(); 00466 00467 // reset the default suspend time 00468 mSuspendSpin->setValue( defSuspendVal ); 00469 mSuspendUnit->setCurrentItem( defSuspendUnit ); 00470 00471 KDialogBase::show(); 00472 KWin::deIconifyWindow( winId(), false ); 00473 KWin::setState( winId(), NET::KeepAbove | NET::DemandsAttention ); 00474 KWin::setOnAllDesktops( winId(), true ); 00475 KWin::activateWindow( winId() ); 00476 raise(); 00477 setActiveWindow(); 00478 if ( isMinimized() ) { 00479 showNormal(); 00480 } 00481 eventNotification(); 00482 } 00483 00484 void AlarmDialog::eventNotification() 00485 { 00486 bool beeped = false, found = false; 00487 00488 TQValueList<AlarmListItem*> list; 00489 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00490 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); 00491 if ( !item->isVisible() || item->mNotified ) { 00492 continue; 00493 } 00494 Incidence *incidence = mCalendar->incidence( item->mUid ); 00495 if ( !incidence ) { 00496 continue; 00497 } 00498 found = true; 00499 item->mNotified = true; 00500 Alarm::List alarms = incidence->alarms(); 00501 Alarm::List::ConstIterator c_it; 00502 for ( c_it = alarms.begin(); c_it != alarms.end(); ++c_it ) { 00503 Alarm *alarm = *c_it; 00504 // FIXME: Check whether this should be done for all multiple alarms 00505 if (alarm->type() == Alarm::Procedure) { 00506 // FIXME: Add a message box asking whether the procedure should really be executed 00507 kdDebug(5890) << "Starting program: '" << alarm->programFile() << "'" << endl; 00508 TDEProcess proc; 00509 proc << TQFile::encodeName(alarm->programFile()).data(); 00510 proc.start(TDEProcess::DontCare); 00511 } 00512 else if (alarm->type() == Alarm::Audio) { 00513 beeped = true; 00514 KAudioPlayer::play(TQFile::encodeName(alarm->audioFile())); 00515 } 00516 } 00517 } 00518 00519 if ( !beeped && found ) { 00520 KNotifyClient::beep(); 00521 } 00522 } 00523 00524 void AlarmDialog::wakeUp() 00525 { 00526 bool activeReminders = false; 00527 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00528 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); 00529 Incidence *incidence = mCalendar->incidence( item->mUid ); 00530 if ( !incidence ) { 00531 delete item; 00532 continue; 00533 } 00534 00535 if ( item->mRemindAt <= TQDateTime::currentDateTime() ) { 00536 if ( !item->isVisible() ) { 00537 item->setVisible( true ); 00538 item->setSelected( false ); 00539 } 00540 activeReminders = true; 00541 } else { 00542 item->setVisible( false ); 00543 } 00544 } 00545 00546 if ( activeReminders ) 00547 show(); 00548 setTimer(); 00549 showDetails(); 00550 emit reminderCount( activeCount() ); 00551 } 00552 00553 void AlarmDialog::slotSave() 00554 { 00555 TDEConfig *config = kapp->config(); 00556 TDELockFile::Ptr lock = config->lockFile(); 00557 if ( lock.data()->lock() != TDELockFile::LockOK ) 00558 return; 00559 00560 config->setGroup( "General" ); 00561 int numReminders = config->readNumEntry("Reminders", 0); 00562 00563 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00564 AlarmListItem *item = static_cast<AlarmListItem*>( it.current() ); 00565 Incidence *incidence = mCalendar->incidence( item->mUid ); 00566 if ( !incidence ) { 00567 continue; 00568 } 00569 config->setGroup( TQString("Incidence-%1").arg(numReminders + 1) ); 00570 config->writeEntry( "UID", incidence->uid() ); 00571 config->writeEntry( "RemindAt", item->mRemindAt ); 00572 ++numReminders; 00573 } 00574 00575 config->setGroup( "General" ); 00576 config->writeEntry( "Reminders", numReminders ); 00577 config->sync(); 00578 lock.data()->unlock(); 00579 } 00580 00581 void AlarmDialog::closeEvent( TQCloseEvent * ) 00582 { 00583 slotSave(); 00584 writeLayout(); 00585 accept(); 00586 } 00587 00588 void AlarmDialog::updateButtons() 00589 { 00590 ItemList selection = selectedItems(); 00591 enableButton( User1, selection.count() == 1 ); // can only edit 1 at a time 00592 enableButton( User3, selection.count() > 0 ); // dismiss 1 or more 00593 enableButton( Ok, selection.count() > 0 ); // suspend 1 or more 00594 } 00595 00596 TQValueList< AlarmListItem * > AlarmDialog::selectedItems() const 00597 { 00598 TQValueList<AlarmListItem*> list; 00599 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00600 if ( it.current()->isSelected() ) 00601 list.append( static_cast<AlarmListItem*>( it.current() ) ); 00602 } 00603 return list; 00604 } 00605 00606 int AlarmDialog::activeCount() 00607 { 00608 int count = 0; 00609 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00610 AlarmListItem * item = static_cast<AlarmListItem*>( it.current() ); 00611 if ( item->isVisible() ) 00612 ++count; 00613 } 00614 return count; 00615 } 00616 00617 void AlarmDialog::suspendAll() 00618 { 00619 mIncidenceListView->clearSelection(); 00620 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) { 00621 if ( it.current()->isVisible() ) 00622 it.current()->setSelected( true ); 00623 } 00624 suspend(); 00625 } 00626 00627 void AlarmDialog::showDetails() 00628 { 00629 mDetailView->clearEvents( true ); 00630 mDetailView->clear(); 00631 AlarmListItem *item = static_cast<AlarmListItem*>( mIncidenceListView->selectedItems().first() ); 00632 if ( !item || !item->isVisible() ) 00633 return; 00634 00635 Incidence *incidence = mCalendar->incidence( item->mUid ); 00636 if ( !incidence ) { 00637 return; 00638 } 00639 00640 if ( !item->mDisplayText.isEmpty() ) { 00641 TQString txt = "<qt><p><b>" + item->mDisplayText + "</b></p></qt>"; 00642 mDetailView->addText( txt ); 00643 } 00644 item->setText( 0, cleanSummary( incidence->summary() ) ); 00645 mDetailView->appendIncidence( incidence, item->mRemindAt.date() ); 00646 } 00647 00648 bool AlarmDialog::ensureKorganizerRunning() const 00649 { 00650 TQString error; 00651 TQCString dcopService; 00652 00653 int result = KDCOPServiceStarter::self()->findServiceFor( 00654 "DCOP/Organizer", TQString(), TQString(), &error, &dcopService ); 00655 00656 if ( result == 0 ) { 00657 // OK, so korganizer (or kontact) is running. Now ensure the object we 00658 // want is available [that's not the case when kontact was already running, 00659 // but korganizer not loaded into it...] 00660 static const char* const dcopObjectId = "KOrganizerIface"; 00661 TQCString dummy; 00662 if ( !kapp->dcopClient()->findObject( 00663 dcopService, dcopObjectId, "", TQByteArray(), dummy, dummy ) ) { 00664 DCOPRef ref( dcopService, dcopService ); // talk to KUniqueApplication or its kontact wrapper 00665 DCOPReply reply = ref.call( "load()" ); 00666 if ( reply.isValid() && (bool)reply ) { 00667 Q_ASSERT( kapp->dcopClient()->findObject( 00668 dcopService, dcopObjectId, "", TQByteArray(), dummy, dummy ) ); 00669 } else { 00670 kdWarning() << "Error loading " << dcopService << endl; 00671 } 00672 } 00673 00674 // We don't do anything with it we just need it to be running 00675 return true; 00676 00677 } else { 00678 kdWarning() << "Couldn't start DCOP/Organizer: " << dcopService 00679 << " " << error << endl; 00680 } 00681 return false; 00682 } 00683 00685 TQDateTime AlarmDialog::triggerDateForIncidence( Incidence *incidence, 00686 const TQDateTime &reminderAt, 00687 TQString &displayStr ) 00688 { 00689 // Will be simplified in trunk, with roles. 00690 TQDateTime result; 00691 00692 Alarm *alarm = incidence->alarms().first(); 00693 00694 if ( incidence->doesRecur() ) { 00695 result = incidence->recurrence()->getNextDateTime( reminderAt ); 00696 displayStr = TDEGlobal::locale()->formatDateTime( result ); 00697 } 00698 00699 if ( incidence->type() == "Event" ) { 00700 if ( !result.isValid() ) { 00701 Event *event = static_cast<Event *>( incidence ); 00702 result = alarm->hasStartOffset() ? event->dtStart() : 00703 event->dtEnd(); 00704 displayStr = IncidenceFormatter::dateTimeToString( result, false, true ); 00705 } 00706 } else if ( incidence->type() == "Todo" ) { 00707 if ( !result.isValid() ) { 00708 Todo *todo = static_cast<Todo *>( incidence ); 00709 result = alarm->hasStartOffset() && todo->dtStart().isValid() ? todo->dtStart(): 00710 todo->dtDue(); 00711 displayStr = IncidenceFormatter::dateTimeToString( result, false, true ); 00712 } 00713 } 00714 00715 return result; 00716 } 00717 00718 void AlarmDialog::slotCalendarChanged() 00719 { 00720 Incidence::List incidences = mCalendar->incidences(); 00721 for ( Incidence::List::ConstIterator it = incidences.begin(); 00722 it != incidences.constEnd(); ++it ) { 00723 Incidence *incidence = *it; 00724 AlarmListItem *item = searchByUid( incidence->uid() ); 00725 00726 if ( item ) { 00727 TQString displayStr; 00728 const TQDateTime dateTime = triggerDateForIncidence( incidence, 00729 item->mRemindAt, 00730 displayStr ); 00731 00732 const TQString summary = cleanSummary( incidence->summary() ); 00733 00734 if ( displayStr != item->text( 1 ) || summary != item->text( 0 ) ) { 00735 item->setText( 1, displayStr ); 00736 item->setText( 0, summary ); 00737 } 00738 } 00739 } 00740 }