summaryrefslogtreecommitdiffstats
path: root/korganizer/korgac/alarmdialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'korganizer/korgac/alarmdialog.cpp')
-rw-r--r--korganizer/korgac/alarmdialog.cpp444
1 files changed, 444 insertions, 0 deletions
diff --git a/korganizer/korgac/alarmdialog.cpp b/korganizer/korgac/alarmdialog.cpp
new file mode 100644
index 000000000..68e1822dc
--- /dev/null
+++ b/korganizer/korgac/alarmdialog.cpp
@@ -0,0 +1,444 @@
+/*
+ This file is part of the KOrganizer alarm daemon.
+
+ Copyright (c) 2000,2003 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qhbox.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qfile.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qcstring.h>
+#include <qdatastream.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <dcopclient.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <kaudioplayer.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <kcombobox.h>
+#include <klistview.h>
+#include <kwin.h>
+#include <klockfile.h>
+
+#include <libkcal/event.h>
+
+#include "koeventviewer.h"
+
+#include "alarmdialog.h"
+#include "alarmdialog.moc"
+
+class AlarmListItem : public KListViewItem
+{
+ public:
+ AlarmListItem( Incidence *incidence, QListView *parent ) :
+ KListViewItem( parent ),
+ mIncidence( incidence->clone() ),
+ mNotified( false )
+ {}
+
+ ~AlarmListItem()
+ {
+ delete mIncidence;
+ }
+
+ Incidence *mIncidence;
+ QDateTime mRemindAt;
+ bool mNotified;
+};
+
+typedef QValueList<AlarmListItem*> ItemList;
+
+AlarmDialog::AlarmDialog( QWidget *parent, const char *name )
+ : KDialogBase( Plain, WType_TopLevel | WStyle_Customize | WStyle_StaysOnTop |
+ WStyle_DialogBorder,
+ parent, name, false, i18n("Reminder"), Ok | User1 | User2 | User3, User1/*3*/,
+ false, i18n("Dismiss all"), i18n("Edit..."), i18n("Suspend") ),
+ mSuspendTimer(this)
+{
+ KGlobal::iconLoader()->addAppDir( "kdepim" );
+ setButtonOK( i18n( "Dismiss" ) );
+
+ QWidget *topBox = plainPage();
+ QBoxLayout *topLayout = new QVBoxLayout( topBox );
+ topLayout->setSpacing( spacingHint() );
+
+ QLabel *label = new QLabel( i18n("The following events triggered reminders:"),
+ topBox );
+ topLayout->addWidget( label );
+
+ mIncidenceListView = new KListView( topBox );
+ mIncidenceListView->addColumn( i18n( "Summary" ) );
+ mIncidenceListView->addColumn( i18n( "Due" ) );
+ mIncidenceListView->setAllColumnsShowFocus( true );
+ mIncidenceListView->setSelectionMode( QListView::Extended );
+ topLayout->addWidget( mIncidenceListView );
+ connect( mIncidenceListView, SIGNAL(selectionChanged()), SLOT(updateButtons()) );
+ connect( mIncidenceListView, SIGNAL(doubleClicked(QListViewItem*)), SLOT(slotUser2()) );
+ connect( mIncidenceListView, SIGNAL(currentChanged(QListViewItem*)), SLOT(showDetails()) );
+ connect( mIncidenceListView, SIGNAL(selectionChanged()), SLOT(showDetails()) );
+
+ mDetailView = new KOEventViewer( topBox );
+ topLayout->addWidget( mDetailView );
+
+ QHBox *suspendBox = new QHBox( topBox );
+ suspendBox->setSpacing( spacingHint() );
+ topLayout->addWidget( suspendBox );
+
+ QLabel *l = new QLabel( i18n("Suspend &duration:"), suspendBox );
+ mSuspendSpin = new QSpinBox( 1, 9999, 1, suspendBox );
+ mSuspendSpin->setValue( 5 ); // default suspend duration
+ l->setBuddy( mSuspendSpin );
+
+ mSuspendUnit = new KComboBox( suspendBox );
+ mSuspendUnit->insertItem( i18n("minute(s)") );
+ mSuspendUnit->insertItem( i18n("hour(s)") );
+ mSuspendUnit->insertItem( i18n("day(s)") );
+ mSuspendUnit->insertItem( i18n("week(s)") );
+ connect( &mSuspendTimer, SIGNAL(timeout()), SLOT(wakeUp()) );
+
+ // showButton( User2/*3*/, false );
+
+ setMinimumSize( 300, 200 );
+}
+
+AlarmDialog::~AlarmDialog()
+{
+ mIncidenceListView->clear();
+}
+
+void AlarmDialog::addIncidence( Incidence *incidence, const QDateTime &reminderAt )
+{
+ AlarmListItem *item = new AlarmListItem( incidence, mIncidenceListView );
+ item->setText( 0, incidence->summary() );
+ item->mRemindAt = reminderAt;
+ Todo *todo;
+ if ( dynamic_cast<Event*>( incidence ) ) {
+ item->setPixmap( 0, SmallIcon( "appointment" ) );
+ if ( incidence->doesRecur() ) {
+ QDateTime nextStart = incidence->recurrence()->getNextDateTime( reminderAt );
+ if ( nextStart.isValid() )
+ item->setText( 1, KGlobal::locale()->formatDateTime( nextStart ) );
+ }
+ if ( item->text( 1 ).isEmpty() )
+ item->setText( 1, incidence->dtStartStr() );
+ } else if ( (todo = dynamic_cast<Todo*>( incidence )) ) {
+ item->setPixmap( 0, SmallIcon( "todo" ) );
+ item->setText( 1, todo->dtDueStr() );
+ }
+ if ( activeCount() == 1 ) {// previously empty
+ mIncidenceListView->clearSelection();
+ item->setSelected( true );
+ }
+ showDetails();
+}
+
+void AlarmDialog::slotOk()
+{
+ ItemList selection = selectedItems();
+ for ( ItemList::Iterator it = selection.begin(); it != selection.end(); ++it ) {
+ if ( (*it)->itemBelow() )
+ (*it)->itemBelow()->setSelected( true );
+ else if ( (*it)->itemAbove() )
+ (*it)->itemAbove()->setSelected( true );
+ delete *it;
+ }
+ if ( activeCount() == 0 )
+ accept();
+ else {
+ updateButtons();
+ showDetails();
+ }
+ emit reminderCount( activeCount() );
+}
+
+void AlarmDialog::slotUser1()
+{
+ dismissAll();
+}
+
+void AlarmDialog::suspend()
+{
+ if ( !isVisible() )
+ return;
+
+ int unit=1;
+ switch (mSuspendUnit->currentItem()) {
+ case 3: // weeks
+ unit *= 7;
+ case 2: // days
+ unit *= 24;
+ case 1: // hours
+ unit *= 60;
+ case 0: // minutes
+ unit *= 60;
+ default:
+ break;
+ }
+
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
+ if ( item->isSelected() && item->isVisible() ) {
+ item->setVisible( false );
+ item->setSelected( false );
+ item->mRemindAt = QDateTime::currentDateTime().addSecs( unit * mSuspendSpin->value() );
+ item->mNotified = false;
+ }
+ }
+
+ setTimer();
+ if ( activeCount() == 0 )
+ accept();
+ else {
+ updateButtons();
+ showDetails();
+ }
+ emit reminderCount( activeCount() );
+}
+
+void AlarmDialog::setTimer()
+{
+ int nextReminderAt = -1;
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
+ if ( item->mRemindAt > QDateTime::currentDateTime() ) {
+ int secs = QDateTime::currentDateTime().secsTo( item->mRemindAt );
+ nextReminderAt = nextReminderAt <= 0 ? secs : QMIN( nextReminderAt, secs );
+ }
+ }
+
+ if ( nextReminderAt >= 0 ) {
+ mSuspendTimer.stop();
+ mSuspendTimer.start( 1000 * (nextReminderAt + 1), true );
+ }
+}
+
+void AlarmDialog::slotUser2()
+{
+ ItemList selection = selectedItems();
+ if ( selection.count() != 1 )
+ return;
+ Incidence *incidence = selection.first()->mIncidence;
+
+ if ( !kapp->dcopClient()->isApplicationRegistered( "korganizer" ) ) {
+ if ( kapp->startServiceByDesktopName( "korganizer", QString::null ) )
+ KMessageBox::error( 0, i18n("Could not start KOrganizer.") );
+ }
+
+ kapp->dcopClient()->send( "korganizer", "KOrganizerIface",
+ "editIncidence(QString)",
+ incidence->uid() );
+
+ // get desktop # where korganizer (or kontact) runs
+ QByteArray replyData;
+ QCString object, replyType;
+ object = kapp->dcopClient()->isApplicationRegistered( "kontact" ) ?
+ "kontact-mainwindow#1" : "KOrganizer MainWindow";
+ if (!kapp->dcopClient()->call( "korganizer", object,
+ "getWinID()", 0, replyType, replyData, true, -1 ) ) {
+ }
+
+ if ( replyType == "int" ) {
+ int desktop, window;
+ QDataStream ds( replyData, IO_ReadOnly );
+ ds >> window;
+ desktop = KWin::windowInfo( window ).desktop();
+
+ if ( KWin::currentDesktop() == desktop ) {
+ KWin::iconifyWindow( winId(), false );
+ }
+ else
+ KWin::setCurrentDesktop( desktop );
+
+ KWin::activateWindow( KWin::transientFor( window ) );
+ }
+}
+
+void AlarmDialog::slotUser3()
+{
+ suspend();
+}
+
+void AlarmDialog::dismissAll()
+{
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ) {
+ AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
+ if ( !item->isVisible() ) {
+ ++it;
+ continue;
+ }
+ delete item;
+ }
+ setTimer();
+ accept();
+ emit reminderCount( activeCount() );
+}
+
+void AlarmDialog::show()
+{
+ mIncidenceListView->clearSelection();
+ if ( mIncidenceListView->firstChild() )
+ mIncidenceListView->firstChild()->setSelected( true );
+ updateButtons();
+ KDialogBase::show();
+ KWin::setState( winId(), NET::KeepAbove );
+ KWin::setOnAllDesktops( winId(), true );
+ eventNotification();
+}
+
+void AlarmDialog::eventNotification()
+{
+ bool beeped = false, found = false;
+
+ QValueList<AlarmListItem*> list;
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ AlarmListItem *item = static_cast<AlarmListItem*>( it.current() );
+ if ( !item->isVisible() || item->mNotified )
+ continue;
+ found = true;
+ item->mNotified = true;
+ Alarm::List alarms = item->mIncidence->alarms();
+ Alarm::List::ConstIterator it;
+ for ( it = alarms.begin(); it != alarms.end(); ++it ) {
+ Alarm *alarm = *it;
+ // FIXME: Check whether this should be done for all multiple alarms
+ if (alarm->type() == Alarm::Procedure) {
+ // FIXME: Add a message box asking whether the procedure should really be executed
+ kdDebug(5890) << "Starting program: '" << alarm->programFile() << "'" << endl;
+ KProcess proc;
+ proc << QFile::encodeName(alarm->programFile());
+ proc.start(KProcess::DontCare);
+ }
+ else if (alarm->type() == Alarm::Audio) {
+ beeped = true;
+ KAudioPlayer::play(QFile::encodeName(alarm->audioFile()));
+ }
+ }
+ }
+
+ if ( !beeped && found ) {
+ KNotifyClient::beep();
+ }
+}
+
+void AlarmDialog::wakeUp()
+{
+ bool activeReminders = false;
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
+ if ( item->mRemindAt <= QDateTime::currentDateTime() ) {
+ if ( !item->isVisible() ) {
+ item->setVisible( true );
+ item->setSelected( false );
+ }
+ activeReminders = true;
+ } else {
+ item->setVisible( false );
+ }
+ }
+
+ if ( activeReminders )
+ show();
+ setTimer();
+ showDetails();
+ emit reminderCount( activeCount() );
+}
+
+void AlarmDialog::slotSave()
+{
+ KConfig *config = kapp->config();
+ KLockFile::Ptr lock = config->lockFile();
+ if ( lock.data()->lock() != KLockFile::LockOK )
+ return;
+
+ config->setGroup( "General" );
+ int numReminders = config->readNumEntry("Reminders", 0);
+
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
+ config->setGroup( QString("Incidence-%1").arg(numReminders) );
+ config->writeEntry( "UID", item->mIncidence->uid() );
+ config->writeEntry( "RemindAt", item->mRemindAt );
+ ++numReminders;
+ }
+
+ config->setGroup( "General" );
+ config->writeEntry( "Reminders", numReminders );
+ config->sync();
+ lock.data()->unlock();
+}
+
+void AlarmDialog::updateButtons()
+{
+ ItemList selection = selectedItems();
+ enableButton( User2, selection.count() == 1 );
+ enableButton( Ok, selection.count() > 0 );
+ enableButton( User3, selection.count() > 0 );
+}
+
+QValueList< AlarmListItem * > AlarmDialog::selectedItems() const
+{
+ QValueList<AlarmListItem*> list;
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ if ( it.current()->isSelected() )
+ list.append( static_cast<AlarmListItem*>( it.current() ) );
+ }
+ return list;
+}
+
+int AlarmDialog::activeCount()
+{
+ int count = 0;
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ AlarmListItem * item = static_cast<AlarmListItem*>( it.current() );
+ if ( item->isVisible() )
+ ++count;
+ }
+ return count;
+}
+
+void AlarmDialog::suspendAll()
+{
+ mIncidenceListView->clearSelection();
+ for ( QListViewItemIterator it( mIncidenceListView ) ; it.current() ; ++it ) {
+ if ( it.current()->isVisible() )
+ it.current()->setSelected( true );
+ }
+ suspend();
+}
+
+void AlarmDialog::showDetails()
+{
+ mDetailView->clearEvents( true );
+ mDetailView->clear();
+ AlarmListItem *item = static_cast<AlarmListItem*>( mIncidenceListView->currentItem() );
+ if ( !item || !item->isVisible() )
+ return;
+ mDetailView->appendIncidence( item->mIncidence );
+}