30 #include <tqspinbox.h>
32 #include <tqpushbutton.h>
33 #include <tqcstring.h>
34 #include <tqdatastream.h>
35 #include <tqsplitter.h>
37 #include <dcopclient.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>
47 #include <tdemessagebox.h>
48 #include <knotifyclient.h>
49 #include <kcombobox.h>
50 #include <tdelistview.h>
52 #include <klockfile.h>
54 #include <libkcal/event.h>
55 #include <libkcal/incidenceformatter.h>
57 #include "koeventviewer.h"
59 #include "alarmdialog.h"
60 #include "alarmdialog.moc"
62 static int defSuspendVal = 5;
63 static int defSuspendUnit = 0;
65 class AlarmListItem :
public TDEListViewItem
68 AlarmListItem(
const TQString &uid, TQListView *parent )
69 : TDEListViewItem( parent ), mUid( uid ), mNotified( false )
77 int compare( TQListViewItem *item,
int iCol,
bool bAscending )
const;
79 TQString mDisplayText;
83 TQDateTime mHappening;
87 int AlarmListItem::compare( TQListViewItem *item,
int iCol,
bool bAscending )
const
90 AlarmListItem *pItem =
static_cast<AlarmListItem *
>( item );
91 return pItem->mHappening.secsTo( mHappening );
93 return TDEListViewItem::compare( item, iCol, bAscending );
97 typedef TQValueList<AlarmListItem*> ItemList;
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)
112 connect( calendar, TQ_SIGNAL(calendarChanged()),
113 this, TQ_SLOT(slotCalendarChanged()) );
115 TDEGlobal::iconLoader()->addAppDir(
"tdepim" );
116 setButtonOK( i18n(
"Suspend" ) );
118 TQWidget *topBox = plainPage();
119 TQBoxLayout *topLayout =
new TQVBoxLayout( topBox );
120 topLayout->setSpacing( spacingHint() );
122 TQLabel *label =
new TQLabel( i18n(
"The following items triggered reminders:"), topBox );
123 topLayout->addWidget( label );
125 mSplitter =
new TQSplitter( TQt::Vertical, topBox );
126 mSplitter->setOpaqueResize( TDEGlobalSettings::opaqueResize() );
127 topLayout->addWidget( mSplitter );
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()) );
144 mDetailView->setFocus();
147 TQHBox *suspendBox =
new TQHBox( topBox );
148 suspendBox->setSpacing( spacingHint() );
149 topLayout->addWidget( suspendBox );
151 TQLabel *l =
new TQLabel( i18n(
"Suspend &duration:"), suspendBox );
152 mSuspendSpin =
new TQSpinBox( 1, 9999, 1, suspendBox );
153 mSuspendSpin->setValue( defSuspendVal );
154 l->setBuddy( mSuspendSpin );
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 );
163 connect( &mSuspendTimer, TQ_SIGNAL(timeout()), TQ_SLOT(wakeUp()) );
165 setMainWidget( mIncidenceListView );
166 mIncidenceListView->setMinimumSize( 500, 50 );
171 AlarmDialog::~AlarmDialog()
173 mIncidenceListView->clear();
176 AlarmListItem *AlarmDialog::searchByUid(
const TQString &uid )
178 AlarmListItem *found = 0;
179 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) {
180 AlarmListItem *item =
static_cast<AlarmListItem*
>( it.current() );
181 if ( item->mUid == uid ) {
190 static TQString etc = i18n(
"elipsis",
"..." );
191 static TQString cleanSummary(
const TQString &summary )
194 TQString retStr = summary;
195 retStr.replace(
'\n',
' ' );
196 if ( retStr.length() > maxLen ) {
197 maxLen -= etc.length();
198 retStr = retStr.left( maxLen );
204 void AlarmDialog::readLayout()
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 );
212 mSplitter->setCollapsible( mIncidenceListView,
false );
213 mSplitter->setCollapsible( mDetailView,
false );
216 void AlarmDialog::writeLayout()
218 TDEConfig *config = kapp->config();
219 config->setGroup(
"Layout" );
220 TQValueList<int> list = mSplitter->sizes();
221 config->writeEntry(
"SplitterSizes", list );
224 void AlarmDialog::addIncidence(
Incidence *incidence,
225 const TQDateTime &reminderAt,
226 const TQString &displayText )
228 AlarmListItem *item = searchByUid( incidence->
uid() );
230 item =
new AlarmListItem( incidence->
uid(), mIncidenceListView );
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() );
240 const TQDateTime dateTime = triggerDateForIncidence( incidence, reminderAt, displayStr );
242 item->mHappening = dateTime;
243 item->setText( 1, displayStr );
245 if ( incidence->type() ==
"Event" ) {
246 item->setPixmap( 0, SmallIcon(
"appointment" ) );
248 item->setPixmap( 0, SmallIcon(
"todo" ) );
251 if ( activeCount() == 1 ) {
252 mIncidenceListView->clearSelection();
253 item->setSelected(
true );
258 void AlarmDialog::slotOk()
263 void AlarmDialog::slotUser1()
268 void AlarmDialog::slotUser2()
273 void AlarmDialog::slotUser3()
278 void AlarmDialog::dismissCurrent()
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 );
288 if ( activeCount() == 0 ) {
295 emit reminderCount( activeCount() );
298 void AlarmDialog::dismissAll()
300 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) {
301 AlarmListItem *item =
static_cast<AlarmListItem*
>( it.current() );
302 if ( !item->isVisible() ) {
306 mIncidenceListView->takeItem( item );
312 emit reminderCount( activeCount() );
315 void AlarmDialog::edit()
317 ItemList selection = selectedItems();
318 if ( selection.count() != 1 ) {
321 Incidence *incidence = mCalendar->incidence( selection.first()->mUid );
325 TQDate dt = selection.first()->mRemindAt.date();
330 i18n(
"\"%1\" is a read-only item so modifications are not possible." ).
331 arg( cleanSummary( incidence->
summary() ) ) );
335 if ( !ensureKorganizerRunning() ) {
338 i18n(
"Could not start KOrganizer so editing is not possible." ) );
343 TQDataStream arg( data, IO_WriteOnly );
344 arg << incidence->
uid();
347 if ( !kapp->dcopClient()->send(
"korganizer",
"KOrganizerIface",
348 "editIncidence(TQString,TQDate)",
352 i18n(
"An internal KOrganizer error occurred attempting to start the incidence editor" ) );
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 ) ) {
365 if ( replyType ==
"int" ) {
367 TQDataStream ds( replyData, IO_ReadOnly );
369 desktop = KWin::windowInfo( window ).desktop();
371 if ( KWin::currentDesktop() == desktop ) {
372 KWin::iconifyWindow( winId(),
false );
374 KWin::setCurrentDesktop( desktop );
376 KWin::activateWindow( KWin::transientFor( window ) );
380 void AlarmDialog::suspend()
386 switch (mSuspendUnit->currentItem()) {
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;
411 if ( selitem->itemBelow() ) {
412 selitem->itemBelow()->setSelected(
true );
413 }
else if ( selitem->itemAbove() ) {
414 selitem->itemAbove()->setSelected(
true );
423 if ( activeCount() == 0 ) {
430 emit reminderCount( activeCount() );
433 void AlarmDialog::setTimer()
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 );
444 if ( nextReminderAt >= 0 ) {
445 mSuspendTimer.stop();
446 mSuspendTimer.start( 1000 * (nextReminderAt + 1),
true );
450 void AlarmDialog::show()
452 mIncidenceListView->sort();
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 );
468 mSuspendSpin->setValue( defSuspendVal );
469 mSuspendUnit->setCurrentItem( defSuspendUnit );
472 KWin::deIconifyWindow( winId(),
false );
473 KWin::setState( winId(), NET::KeepAbove | NET::DemandsAttention );
474 KWin::setOnAllDesktops( winId(),
true );
475 KWin::activateWindow( winId() );
478 if ( isMinimized() ) {
484 void AlarmDialog::eventNotification()
486 bool beeped =
false, found =
false;
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 ) {
494 Incidence *incidence = mCalendar->incidence( item->mUid );
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;
505 if (alarm->
type() == Alarm::Procedure) {
507 kdDebug(5890) <<
"Starting program: '" << alarm->
programFile() <<
"'" << endl;
509 proc << TQFile::encodeName(alarm->
programFile()).data();
510 proc.start(TDEProcess::DontCare);
512 else if (alarm->
type() == Alarm::Audio) {
514 KAudioPlayer::play(TQFile::encodeName(alarm->
audioFile()));
519 if ( !beeped && found ) {
520 KNotifyClient::beep();
524 void AlarmDialog::wakeUp()
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 );
535 if ( item->mRemindAt <= TQDateTime::currentDateTime() ) {
536 if ( !item->isVisible() ) {
537 item->setVisible(
true );
538 item->setSelected(
false );
540 activeReminders =
true;
542 item->setVisible(
false );
546 if ( activeReminders )
548 DCOPRef screensaver(
"kdesktop",
"KScreensaverIface");
549 DCOPReply reply = screensaver.call(
"isBlanked");
551 if (reply.isValid()) {
564 emit reminderCount( activeCount() );
567 void AlarmDialog::slotSave()
569 TDEConfig *config = kapp->config();
570 TDELockFile::Ptr lock = config->lockFile();
571 if ( lock.data()->lock() != TDELockFile::LockOK )
574 config->setGroup(
"General" );
575 int numReminders = config->readNumEntry(
"Reminders", 0);
577 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
578 AlarmListItem *item =
static_cast<AlarmListItem*
>( it.current() );
579 Incidence *incidence = mCalendar->incidence( item->mUid );
583 config->setGroup( TQString(
"Incidence-%1").arg(numReminders + 1) );
584 config->writeEntry(
"UID", incidence->
uid() );
585 config->writeEntry(
"RemindAt", item->mRemindAt );
589 config->setGroup(
"General" );
590 config->writeEntry(
"Reminders", numReminders );
592 lock.data()->unlock();
595 void AlarmDialog::closeEvent( TQCloseEvent * )
602 void AlarmDialog::updateButtons()
604 ItemList selection = selectedItems();
605 enableButton( User1, selection.count() == 1 );
606 enableButton( User3, selection.count() > 0 );
607 enableButton( Ok, selection.count() > 0 );
610 TQValueList< AlarmListItem * > AlarmDialog::selectedItems()
const
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() ) );
620 int AlarmDialog::activeCount()
623 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
624 AlarmListItem * item =
static_cast<AlarmListItem*
>( it.current() );
625 if ( item->isVisible() )
631 void AlarmDialog::suspendAll()
633 mIncidenceListView->clearSelection();
634 for ( TQListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
635 if ( it.current()->isVisible() )
636 it.current()->setSelected(
true );
641 void AlarmDialog::showDetails()
643 mDetailView->clearEvents(
true );
644 mDetailView->clear();
645 AlarmListItem *item =
static_cast<AlarmListItem*
>( mIncidenceListView->selectedItems().first() );
646 if ( !item || !item->isVisible() )
649 Incidence *incidence = mCalendar->incidence( item->mUid );
654 if ( !item->mDisplayText.isEmpty() ) {
655 TQString txt =
"<qt><p><b>" + item->mDisplayText +
"</b></p></qt>";
656 mDetailView->addText( txt );
658 item->setText( 0, cleanSummary( incidence->
summary() ) );
659 mDetailView->appendIncidence( incidence, item->mRemindAt.date() );
662 bool AlarmDialog::ensureKorganizerRunning()
const
665 TQCString dcopService;
667 int result = KDCOPServiceStarter::self()->findServiceFor(
668 "DCOP/Organizer", TQString(), TQString(), &error, &dcopService );
674 static const char*
const dcopObjectId =
"KOrganizerIface";
676 if ( !kapp->dcopClient()->findObject(
677 dcopService, dcopObjectId,
"", TQByteArray(), dummy, dummy ) ) {
678 DCOPRef ref( dcopService, dcopService );
679 DCOPReply reply = ref.call(
"load()" );
680 if ( reply.isValid() && (
bool)reply ) {
681 Q_ASSERT( kapp->dcopClient()->findObject(
682 dcopService, dcopObjectId,
"", TQByteArray(), dummy, dummy ) );
684 kdWarning() <<
"Error loading " << dcopService << endl;
692 kdWarning() <<
"Couldn't start DCOP/Organizer: " << dcopService
693 <<
" " << error << endl;
699 TQDateTime AlarmDialog::triggerDateForIncidence(
Incidence *incidence,
700 const TQDateTime &reminderAt,
701 TQString &displayStr )
710 displayStr = TDEGlobal::locale()->formatDateTime( result );
713 if ( incidence->type() ==
"Event" ) {
714 if ( !result.isValid() ) {
715 Event *
event =
static_cast<Event *
>( incidence );
718 displayStr = IncidenceFormatter::dateTimeToString( result,
false,
true );
720 }
else if ( incidence->type() ==
"Todo" ) {
721 if ( !result.isValid() ) {
722 Todo *todo =
static_cast<Todo *
>( incidence );
725 displayStr = IncidenceFormatter::dateTimeToString( result,
false,
true );
732 void AlarmDialog::slotCalendarChanged()
734 Incidence::List incidences = mCalendar->incidences();
735 for ( Incidence::List::ConstIterator it = incidences.begin();
736 it != incidences.constEnd(); ++it ) {
738 AlarmListItem *item = searchByUid( incidence->
uid() );
742 const TQDateTime dateTime = triggerDateForIncidence( incidence,
746 const TQString summary = cleanSummary( incidence->
summary() );
748 if ( displayStr != item->text( 1 ) || summary != item->text( 0 ) ) {
749 item->setText( 1, displayStr );
750 item->setText( 0, summary );
bool hasStartOffset() const
TQString audioFile() const
TQString programFile() const
const Alarm::List & alarms() 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.