korganizer

alarmdialog.cpp
1 /*
2  This file is part of the KOrganizer alarm daemon.
3 
4  Copyright (c) 2000,2003 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (c) 2009-2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, permission is given to link this program
22  with any edition of TQt, and distribute the resulting executable,
23  without including the source code for TQt in the source distribution.
24 */
25 
26 #include <tqhbox.h>
27 #include <tqvbox.h>
28 #include <tqlabel.h>
29 #include <tqfile.h>
30 #include <tqspinbox.h>
31 #include <tqlayout.h>
32 #include <tqpushbutton.h>
33 #include <tqcstring.h>
34 #include <tqdatastream.h>
35 #include <tqsplitter.h>
36 
37 #include <dcopclient.h>
38 #include <dcopref.h>
39 #include <tdeapplication.h>
40 #include <tdeconfig.h>
41 #include <kdcopservicestarter.h>
42 #include <kiconloader.h>
43 #include <tdelocale.h>
44 #include <tdeprocess.h>
45 #include <kaudioplayer.h>
46 #include <kdebug.h>
47 #include <tdemessagebox.h>
48 #include <knotifyclient.h>
49 #include <kcombobox.h>
50 #include <tdelistview.h>
51 #include <twin.h>
52 #include <klockfile.h>
53 
54 #include <libkcal/event.h>
55 #include <libkcal/incidenceformatter.h>
56 
57 #include "koeventviewer.h"
58 
59 #include "alarmdialog.h"
60 #include "alarmdialog.moc"
61 
62 static int defSuspendVal = 5;
63 static int defSuspendUnit = 0; // 0=>minutes, 1=>hours, 2=>days, 3=>weeks
64 
65 class AlarmListItem : public TDEListViewItem
66 {
67  public:
68  AlarmListItem( const TQString &uid, TQListView *parent )
69  : TDEListViewItem( parent ), mUid( uid ), mNotified( false )
70  {
71  }
72 
73  ~AlarmListItem()
74  {
75  }
76 
77  int compare( TQListViewItem *item, int iCol, bool bAscending ) const;
78 
79  TQString mDisplayText;
80 
81  TQString mUid;
82  TQDateTime mRemindAt;
83  TQDateTime mHappening;
84  bool mNotified;
85 };
86 
87 int AlarmListItem::compare( TQListViewItem *item, int iCol, bool bAscending ) const
88 {
89  if ( iCol == 1 ) {
90  AlarmListItem *pItem = static_cast<AlarmListItem *>( item );
91  return pItem->mHappening.secsTo( mHappening );
92  } else {
93  return TDEListViewItem::compare( item, iCol, bAscending );
94  }
95 }
96 
97 typedef TQValueList<AlarmListItem*> ItemList;
98 
99 AlarmDialog::AlarmDialog( KCal::CalendarResources *calendar, TQWidget *parent, const char *name )
100  : KDialogBase( Plain,
101  WType_TopLevel | WStyle_Customize | WStyle_StaysOnTop | WStyle_DialogBorder,
102  parent, name, false, i18n("Reminder"),
103  Ok | User1 | User2 | User3, NoDefault,
104  false, i18n("Edit..."), i18n("Dismiss All"), i18n("Dismiss Reminder") ),
105  mCalendar( calendar ), mSuspendTimer(this)
106 {
107  // User1 => Edit...
108  // User2 => Dismiss All
109  // User3 => Dismiss Selected
110  // Ok => Suspend
111 
112  connect( calendar, TQ_SIGNAL(calendarChanged()),
113  this, TQ_SLOT(slotCalendarChanged()) );
114 
115  TDEGlobal::iconLoader()->addAppDir( "tdepim" );
116  setButtonOK( i18n( "Suspend" ) );
117 
118  TQWidget *topBox = plainPage();
119  TQBoxLayout *topLayout = new TQVBoxLayout( topBox );
120  topLayout->setSpacing( spacingHint() );
121 
122  TQLabel *label = new TQLabel( i18n("The following items triggered reminders:"), topBox );
123  topLayout->addWidget( label );
124 
125  mSplitter = new TQSplitter( TQt::Vertical, topBox );
126  mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() );
127  topLayout->addWidget( mSplitter );
128 
129  mIncidenceListView = new TDEListView( mSplitter );
130  mIncidenceListView->addColumn( i18n( "Summary" ) );
131  mIncidenceListView->addColumn( i18n( "Date, Time" ) );
132  mIncidenceListView->setSorting( 0, true );
133  mIncidenceListView->setSorting( 1, true );
134  mIncidenceListView->setSortColumn( 1 );
135  mIncidenceListView->setShowSortIndicator( true );
136  mIncidenceListView->setAllColumnsShowFocus( true );
137  mIncidenceListView->setSelectionMode( TQListView::Extended );
138  connect( mIncidenceListView, TQ_SIGNAL(selectionChanged()), TQ_SLOT(updateButtons()) );
139  connect( mIncidenceListView, TQ_SIGNAL(doubleClicked(TQListViewItem*)), TQ_SLOT(edit()) );
140  connect( mIncidenceListView, TQ_SIGNAL(currentChanged(TQListViewItem*)), TQ_SLOT(showDetails()) );
141  connect( mIncidenceListView, TQ_SIGNAL(selectionChanged()), TQ_SLOT(showDetails()) );
142 
143  mDetailView = new KOEventViewer( mCalendar, mSplitter );
144  mDetailView->setFocus(); // set focus here to start with to make it harder
145  // to hit return by mistake and dismiss a reminder.
146 
147  TQHBox *suspendBox = new TQHBox( topBox );
148  suspendBox->setSpacing( spacingHint() );
149  topLayout->addWidget( suspendBox );
150 
151  TQLabel *l = new TQLabel( i18n("Suspend &duration:"), suspendBox );
152  mSuspendSpin = new TQSpinBox( 1, 9999, 1, suspendBox );
153  mSuspendSpin->setValue( defSuspendVal ); // default suspend duration
154  l->setBuddy( mSuspendSpin );
155 
156  mSuspendUnit = new KComboBox( suspendBox );
157  mSuspendUnit->insertItem( i18n("minute(s)") );
158  mSuspendUnit->insertItem( i18n("hour(s)") );
159  mSuspendUnit->insertItem( i18n("day(s)") );
160  mSuspendUnit->insertItem( i18n("week(s)") );
161  mSuspendUnit->setCurrentItem( defSuspendUnit );
162 
163  connect( &mSuspendTimer, TQ_SIGNAL(timeout()), TQ_SLOT(wakeUp()) );
164 
165  setMainWidget( mIncidenceListView );
166  mIncidenceListView->setMinimumSize( 500, 50 );
167 
168  readLayout();
169 }
170 
171 AlarmDialog::~AlarmDialog()
172 {
173  mIncidenceListView->clear();
174 }
175 
176 AlarmListItem *AlarmDialog::searchByUid( const TQString &uid )
177 {
178  AlarmListItem *found = 0;
179  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) {
180  AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
181  if ( item->mUid == uid ) {
182  found = item;
183  break;
184  }
185  ++it;
186  }
187  return found;
188 }
189 
190 static TQString etc = i18n( "elipsis", "..." );
191 static TQString cleanSummary( const TQString &summary )
192 {
193  uint maxLen = 45;
194  TQString retStr = summary;
195  retStr.replace( '\n', ' ' );
196  if ( retStr.length() > maxLen ) {
197  maxLen -= etc.length();
198  retStr = retStr.left( maxLen );
199  retStr += etc;
200  }
201  return retStr;
202 }
203 
204 void AlarmDialog::readLayout()
205 {
206  TDEConfig *config = kapp->config();
207  config->setGroup( "Layout" );
208  TQValueList<int> sizes = config->readIntListEntry( "SplitterSizes" );
209  if ( sizes.count() == 2 ) {
210  mSplitter->setSizes( sizes );
211  }
212  mSplitter->setCollapsible( mIncidenceListView, false );
213  mSplitter->setCollapsible( mDetailView, false );
214 }
215 
216 void AlarmDialog::writeLayout()
217 {
218  TDEConfig *config = kapp->config();
219  config->setGroup( "Layout" );
220  TQValueList<int> list = mSplitter->sizes();
221  config->writeEntry( "SplitterSizes", list );
222 }
223 
224 void AlarmDialog::addIncidence( Incidence *incidence,
225  const TQDateTime &reminderAt,
226  const TQString &displayText )
227 {
228  AlarmListItem *item = searchByUid( incidence->uid() );
229  if ( !item ) {
230  item = new AlarmListItem( incidence->uid(), mIncidenceListView );
231  }
232  item->mNotified = false;
233  item->mHappening = TQDateTime();
234  item->mRemindAt = reminderAt;
235  item->mDisplayText = displayText;
236  item->setText( 0, cleanSummary( incidence->summary() ) );
237  item->setText( 1, TQString() );
238 
239  TQString displayStr;
240  const TQDateTime dateTime = triggerDateForIncidence( incidence, reminderAt, displayStr );
241 
242  item->mHappening = dateTime;
243  item->setText( 1, displayStr );
244 
245  if ( incidence->type() == "Event" ) {
246  item->setPixmap( 0, SmallIcon( "appointment" ) );
247  } else {
248  item->setPixmap( 0, SmallIcon( "todo" ) );
249  }
250 
251  if ( activeCount() == 1 ) { // previously empty
252  mIncidenceListView->clearSelection();
253  item->setSelected( true );
254  }
255  showDetails();
256 }
257 
258 void AlarmDialog::slotOk()
259 {
260  suspend();
261 }
262 
263 void AlarmDialog::slotUser1()
264 {
265  edit();
266 }
267 
268 void AlarmDialog::slotUser2()
269 {
270  dismissAll();
271 }
272 
273 void AlarmDialog::slotUser3()
274 {
275  dismissCurrent();
276 }
277 
278 void AlarmDialog::dismissCurrent()
279 {
280  ItemList selection = selectedItems();
281  for ( ItemList::Iterator it = selection.begin(); it != selection.end(); ++it ) {
282  if ( (*it)->itemBelow() )
283  (*it)->itemBelow()->setSelected( true );
284  else if ( (*it)->itemAbove() )
285  (*it)->itemAbove()->setSelected( true );
286  delete *it;
287  }
288  if ( activeCount() == 0 ) {
289  writeLayout();
290  accept();
291  } else {
292  updateButtons();
293  showDetails();
294  }
295  emit reminderCount( activeCount() );
296 }
297 
298 void AlarmDialog::dismissAll()
299 {
300  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) {
301  AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
302  if ( !item->isVisible() ) {
303  ++it;
304  continue;
305  }
306  mIncidenceListView->takeItem( item );
307  delete item;
308  }
309  setTimer();
310  writeLayout();
311  accept();
312  emit reminderCount( activeCount() );
313 }
314 
315 void AlarmDialog::edit()
316 {
317  ItemList selection = selectedItems();
318  if ( selection.count() != 1 ) {
319  return;
320  }
321  Incidence *incidence = mCalendar->incidence( selection.first()->mUid );
322  if ( !incidence ) {
323  return;
324  }
325  TQDate dt = selection.first()->mRemindAt.date();
326 
327  if ( incidence->isReadOnly() ) {
328  KMessageBox::sorry(
329  this,
330  i18n( "\"%1\" is a read-only item so modifications are not possible." ).
331  arg( cleanSummary( incidence->summary() ) ) );
332  return;
333  }
334 
335  if ( !ensureKorganizerRunning() ) {
336  KMessageBox::error(
337  this,
338  i18n( "Could not start KOrganizer so editing is not possible." ) );
339  return;
340  }
341 
342  TQByteArray data;
343  TQDataStream arg( data, IO_WriteOnly );
344  arg << incidence->uid();
345  arg << dt;
346  //kdDebug(5890) << "editing incidence " << incidence->summary() << endl;
347  if ( !kapp->dcopClient()->send( "korganizer", "KOrganizerIface",
348  "editIncidence(TQString,TQDate)",
349  data ) ) {
350  KMessageBox::error(
351  this,
352  i18n( "An internal KOrganizer error occurred attempting to start the incidence editor" ) );
353  return;
354  }
355 
356  // get desktop # where korganizer (or kontact) runs
357  TQByteArray replyData;
358  TQCString object, replyType;
359  object = kapp->dcopClient()->isApplicationRegistered( "kontact" ) ?
360  "kontact-mainwindow#1" : "KOrganizer MainWindow";
361  if (!kapp->dcopClient()->call( "korganizer", object,
362  "getWinID()", 0, replyType, replyData, true, -1 ) ) {
363  }
364 
365  if ( replyType == "int" ) {
366  int desktop, window;
367  TQDataStream ds( replyData, IO_ReadOnly );
368  ds >> window;
369  desktop = KWin::windowInfo( window ).desktop();
370 
371  if ( KWin::currentDesktop() == desktop ) {
372  KWin::iconifyWindow( winId(), false );
373  } else {
374  KWin::setCurrentDesktop( desktop );
375  }
376  KWin::activateWindow( KWin::transientFor( window ) );
377  }
378 }
379 
380 void AlarmDialog::suspend()
381 {
382  if ( !isVisible() )
383  return;
384 
385  int unit=1;
386  switch (mSuspendUnit->currentItem()) {
387  case 3: // weeks
388  unit *= 7;
389  case 2: // days
390  unit *= 24;
391  case 1: // hours
392  unit *= 60;
393  case 0: // minutes
394  unit *= 60;
395  default:
396  break;
397  }
398 
399  AlarmListItem *selitem = 0;
400  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
401  AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
402  if ( item->isSelected() && item->isVisible() ) {
403  item->setVisible( false );
404  item->setSelected( false );
405  item->mRemindAt = TQDateTime::currentDateTime().addSecs( unit * mSuspendSpin->value() );
406  item->mNotified = false;
407  selitem = item;
408  }
409  }
410  if ( selitem ) {
411  if ( selitem->itemBelow() ) {
412  selitem->itemBelow()->setSelected( true );
413  } else if ( selitem->itemAbove() ) {
414  selitem->itemAbove()->setSelected( true );
415  }
416  }
417 
418  // save suspended alarms too so they can be restored on restart
419  // kolab/issue4108
420  slotSave();
421 
422  setTimer();
423  if ( activeCount() == 0 ) {
424  writeLayout();
425  accept();
426  } else {
427  updateButtons();
428  showDetails();
429  }
430  emit reminderCount( activeCount() );
431 }
432 
433 void AlarmDialog::setTimer()
434 {
435  int nextReminderAt = -1;
436  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
437  AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
438  if ( item->mRemindAt > TQDateTime::currentDateTime() ) {
439  int secs = TQDateTime::currentDateTime().secsTo( item->mRemindAt );
440  nextReminderAt = nextReminderAt <= 0 ? secs : TQMIN( nextReminderAt, secs );
441  }
442  }
443 
444  if ( nextReminderAt >= 0 ) {
445  mSuspendTimer.stop();
446  mSuspendTimer.start( 1000 * (nextReminderAt + 1), true );
447  }
448 }
449 
450 void AlarmDialog::show()
451 {
452  mIncidenceListView->sort();
453 
454  // select the first item that hasn't already been notified
455  mIncidenceListView->clearSelection();
456  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
457  AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
458  if ( !item->mNotified ) {
459  (*it)->setSelected( true );
460  break;
461  }
462  }
463 
464  updateButtons();
465  showDetails();
466 
467  // reset the default suspend time
468  mSuspendSpin->setValue( defSuspendVal );
469  mSuspendUnit->setCurrentItem( defSuspendUnit );
470 
471  KDialogBase::show();
472  KWin::deIconifyWindow( winId(), false );
473  KWin::setState( winId(), NET::KeepAbove | NET::DemandsAttention );
474  KWin::setOnAllDesktops( winId(), true );
475  KWin::activateWindow( winId() );
476  raise();
477  setActiveWindow();
478  if ( isMinimized() ) {
479  showNormal();
480  }
481  eventNotification();
482 }
483 
484 void AlarmDialog::eventNotification()
485 {
486  bool beeped = false, found = false;
487 
488  TQValueList<AlarmListItem*> list;
489  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
490  AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
491  if ( !item->isVisible() || item->mNotified ) {
492  continue;
493  }
494  Incidence *incidence = mCalendar->incidence( item->mUid );
495  if ( !incidence ) {
496  continue;
497  }
498  found = true;
499  item->mNotified = true;
500  Alarm::List alarms = incidence->alarms();
501  Alarm::List::ConstIterator c_it;
502  for ( c_it = alarms.begin(); c_it != alarms.end(); ++c_it ) {
503  Alarm *alarm = *c_it;
504  // FIXME: Check whether this should be done for all multiple alarms
505  if (alarm->type() == Alarm::Procedure) {
506  // FIXME: Add a message box asking whether the procedure should really be executed
507  kdDebug(5890) << "Starting program: '" << alarm->programFile() << "'" << endl;
508  TDEProcess proc;
509  proc << TQFile::encodeName(alarm->programFile()).data();
510  proc.start(TDEProcess::DontCare);
511  }
512  else if (alarm->type() == Alarm::Audio) {
513  beeped = true;
514  KAudioPlayer::play(TQFile::encodeName(alarm->audioFile()));
515  }
516  }
517  }
518 
519  if ( !beeped && found ) {
520  KNotifyClient::beep();
521  }
522 }
523 
524 void AlarmDialog::wakeUp()
525 {
526  bool activeReminders = false;
527  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
528  AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
529  Incidence *incidence = mCalendar->incidence( item->mUid );
530  if ( !incidence ) {
531  delete item;
532  continue;
533  }
534 
535  if ( item->mRemindAt <= TQDateTime::currentDateTime() ) {
536  if ( !item->isVisible() ) {
537  item->setVisible( true );
538  item->setSelected( false );
539  }
540  activeReminders = true;
541  } else {
542  item->setVisible( false );
543  }
544  }
545 
546  if ( activeReminders )
547  {
548  DCOPRef screensaver("kdesktop", "KScreensaverIface");
549  DCOPReply reply = screensaver.call("isBlanked");
550  bool res = true;
551  if (reply.isValid()) {
552  reply.get(res);
553  }
554  show();
555  if (res)
556  {
557  // Lower the dialog if the screensaver is active or its status unknown.
558  // This prevents reminders to show on a locked screen.
559  lower();
560  }
561  }
562  setTimer();
563  showDetails();
564  emit reminderCount( activeCount() );
565 }
566 
567 void AlarmDialog::slotSave()
568 {
569  TDEConfig *config = kapp->config();
570  TDELockFile::Ptr lock = config->lockFile();
571  if ( lock.data()->lock() != TDELockFile::LockOK )
572  return;
573 
574  config->setGroup( "General" );
575  int numReminders = config->readNumEntry("Reminders", 0);
576 
577  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
578  AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
579  Incidence *incidence = mCalendar->incidence( item->mUid );
580  if ( !incidence ) {
581  continue;
582  }
583  config->setGroup( TQString("Incidence-%1").arg(numReminders + 1) );
584  config->writeEntry( "UID", incidence->uid() );
585  config->writeEntry( "RemindAt", item->mRemindAt );
586  ++numReminders;
587  }
588 
589  config->setGroup( "General" );
590  config->writeEntry( "Reminders", numReminders );
591  config->sync();
592  lock.data()->unlock();
593 }
594 
595 void AlarmDialog::closeEvent( TQCloseEvent * )
596 {
597  slotSave();
598  writeLayout();
599  accept();
600 }
601 
602 void AlarmDialog::updateButtons()
603 {
604  ItemList selection = selectedItems();
605  enableButton( User1, selection.count() == 1 ); // can only edit 1 at a time
606  enableButton( User3, selection.count() > 0 ); // dismiss 1 or more
607  enableButton( Ok, selection.count() > 0 ); // suspend 1 or more
608 }
609 
610 TQValueList< AlarmListItem * > AlarmDialog::selectedItems() const
611 {
612  TQValueList<AlarmListItem*> list;
613  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
614  if ( it.current()->isSelected() )
615  list.append( static_cast<AlarmListItem*>( it.current() ) );
616  }
617  return list;
618 }
619 
620 int AlarmDialog::activeCount()
621 {
622  int count = 0;
623  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
624  AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
625  if ( item->isVisible() )
626  ++count;
627  }
628  return count;
629 }
630 
631 void AlarmDialog::suspendAll()
632 {
633  mIncidenceListView->clearSelection();
634  for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
635  if ( it.current()->isVisible() )
636  it.current()->setSelected( true );
637  }
638  suspend();
639 }
640 
641 void AlarmDialog::showDetails()
642 {
643  mDetailView->clearEvents( true );
644  mDetailView->clear();
645  AlarmListItem *item = static_cast<AlarmListItem*>( mIncidenceListView->selectedItems().first() );
646  if ( !item || !item->isVisible() )
647  return;
648 
649  Incidence *incidence = mCalendar->incidence( item->mUid );
650  if ( !incidence ) {
651  return;
652  }
653 
654  if ( !item->mDisplayText.isEmpty() ) {
655  TQString txt = "<qt><p><b>" + item->mDisplayText + "</b></p></qt>";
656  mDetailView->addText( txt );
657  }
658  item->setText( 0, cleanSummary( incidence->summary() ) );
659  mDetailView->appendIncidence( incidence, item->mRemindAt.date() );
660 }
661 
662 bool AlarmDialog::ensureKorganizerRunning() const
663 {
664  TQString error;
665  TQCString dcopService;
666 
667  int result = KDCOPServiceStarter::self()->findServiceFor(
668  "DCOP/Organizer", TQString(), TQString(), &error, &dcopService );
669 
670  if ( result == 0 ) {
671  // OK, so korganizer (or kontact) is running. Now ensure the object we
672  // want is available [that's not the case when kontact was already running,
673  // but korganizer not loaded into it...]
674  static const char* const dcopObjectId = "KOrganizerIface";
675  TQCString dummy;
676  if ( !kapp->dcopClient()->findObject(
677  dcopService, dcopObjectId, "", TQByteArray(), dummy, dummy ) ) {
678  DCOPRef ref( dcopService, dcopService ); // talk to TDEUniqueApplication or its kontact wrapper
679  DCOPReply reply = ref.call( "load()" );
680  if ( reply.isValid() && (bool)reply ) {
681  Q_ASSERT( kapp->dcopClient()->findObject(
682  dcopService, dcopObjectId, "", TQByteArray(), dummy, dummy ) );
683  } else {
684  kdWarning() << "Error loading " << dcopService << endl;
685  }
686  }
687 
688  // We don't do anything with it we just need it to be running
689  return true;
690 
691  } else {
692  kdWarning() << "Couldn't start DCOP/Organizer: " << dcopService
693  << " " << error << endl;
694  }
695  return false;
696 }
697 
699 TQDateTime AlarmDialog::triggerDateForIncidence( Incidence *incidence,
700  const TQDateTime &reminderAt,
701  TQString &displayStr )
702 {
703  // Will be simplified in trunk, with roles.
704  TQDateTime result;
705 
706  Alarm *alarm = incidence->alarms().first();
707 
708  if ( incidence->doesRecur() ) {
709  result = incidence->recurrence()->getNextDateTime( reminderAt );
710  displayStr = TDEGlobal::locale()->formatDateTime( result );
711  }
712 
713  if ( incidence->type() == "Event" ) {
714  if ( !result.isValid() ) {
715  Event *event = static_cast<Event *>( incidence );
716  result = alarm->hasStartOffset() ? event->dtStart() :
717  event->dtEnd();
718  displayStr = IncidenceFormatter::dateTimeToString( result, false, true );
719  }
720  } else if ( incidence->type() == "Todo" ) {
721  if ( !result.isValid() ) {
722  Todo *todo = static_cast<Todo *>( incidence );
723  result = alarm->hasStartOffset() && todo->dtStart().isValid() ? todo->dtStart():
724  todo->dtDue();
725  displayStr = IncidenceFormatter::dateTimeToString( result, false, true );
726  }
727  }
728 
729  return result;
730 }
731 
732 void AlarmDialog::slotCalendarChanged()
733 {
734  Incidence::List incidences = mCalendar->incidences();
735  for ( Incidence::List::ConstIterator it = incidences.begin();
736  it != incidences.constEnd(); ++it ) {
737  Incidence *incidence = *it;
738  AlarmListItem *item = searchByUid( incidence->uid() );
739 
740  if ( item ) {
741  TQString displayStr;
742  const TQDateTime dateTime = triggerDateForIncidence( incidence,
743  item->mRemindAt,
744  displayStr );
745 
746  const TQString summary = cleanSummary( incidence->summary() );
747 
748  if ( displayStr != item->text( 1 ) || summary != item->text( 0 ) ) {
749  item->setText( 1, displayStr );
750  item->setText( 0, summary );
751  }
752  }
753  }
754 }
bool hasStartOffset() const
TQString audioFile() const
TQString programFile() const
Type type() const
TQString uid() const
bool isReadOnly() const
const Alarm::List & alarms() const
bool doesRecur() const
TQString summary() const
Recurrence * recurrence() const
TQDateTime getNextDateTime(const TQDateTime &preDateTime) const
TQDateTime dtStart(bool first=false) const
TQDateTime dtDue(bool first=false) const
Viewer widget for events.
Definition: koeventviewer.h:41