kalarm

mainwindow.cpp

00001 /*
00002  *  mainwindow.cpp  -  main application window
00003  *  Program:  kalarm
00004  *  Copyright (c) 2001 - 2005 by David Jarvie <software@astrojar.org.uk>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "kalarm.h"
00022 
00023 #include <qiconset.h>
00024 #include <qdragobject.h>
00025 
00026 #include <kmenubar.h>
00027 #include <ktoolbar.h>
00028 #include <kpopupmenu.h>
00029 #include <kaccel.h>
00030 #include <kaction.h>
00031 #include <kactionclasses.h>
00032 #include <kstdaction.h>
00033 #include <kiconloader.h>
00034 #include <kmessagebox.h>
00035 #include <kurldrag.h>
00036 #include <klocale.h>
00037 #include <kglobalsettings.h>
00038 #include <kconfig.h>
00039 #include <kkeydialog.h>
00040 #include <kedittoolbar.h>
00041 #include <kaboutdata.h>
00042 #include <dcopclient.h>
00043 #include <kdebug.h>
00044 
00045 #include <libkdepim/maillistdrag.h>
00046 #include <libkmime/kmime_content.h>
00047 #include <libkcal/calendarlocal.h>
00048 #include <libkcal/icaldrag.h>
00049 
00050 #include "alarmcalendar.h"
00051 #include "alarmevent.h"
00052 #include "alarmlistview.h"
00053 #include "alarmtext.h"
00054 #include "birthdaydlg.h"
00055 #include "daemon.h"
00056 #include "editdlg.h"
00057 #include "functions.h"
00058 #include "kalarmapp.h"
00059 #include "kamail.h"
00060 #include "prefdlg.h"
00061 #include "preferences.h"
00062 #include "synchtimer.h"
00063 #include "templatepickdlg.h"
00064 #include "templatedlg.h"
00065 #include "traywindow.h"
00066 #include "mainwindow.moc"
00067 
00068 using namespace KCal;
00069 
00070 static const char* UI_FILE = "kalarmui.rc";
00071 QString   undoText;
00072 QString   undoTextStripped;
00073 QString   undoIcon;
00074 KShortcut undoShortcut;
00075 QString   redoText;
00076 QString   redoTextStripped;
00077 QString   redoIcon;
00078 KShortcut redoShortcut;
00079 
00080 
00081 /*=============================================================================
00082 =  Class: MainWindow
00083 =============================================================================*/
00084 
00085 MainWindow::WindowList   MainWindow::mWindowList;
00086 TemplateDlg*             MainWindow::mTemplateDlg = 0;
00087 
00088 // Collect these widget labels together to ensure consistent wording and
00089 // translations across different modules.
00090 QString MainWindow::i18n_a_ShowAlarmTimes()    { return i18n("Show &Alarm Times"); }
00091 QString MainWindow::i18n_t_ShowAlarmTime()     { return i18n("Show alarm &time"); }
00092 QString MainWindow::i18n_m_ShowAlarmTime()     { return i18n("Show alarm ti&me"); }
00093 QString MainWindow::i18n_o_ShowTimeToAlarms()  { return i18n("Show Time t&o Alarms"); }
00094 QString MainWindow::i18n_n_ShowTimeToAlarm()   { return i18n("Show time u&ntil alarm"); }
00095 QString MainWindow::i18n_l_ShowTimeToAlarm()   { return i18n("Show time unti&l alarm"); }
00096 QString MainWindow::i18n_ShowExpiredAlarms()   { return i18n("Show Expired Alarms"); }
00097 QString MainWindow::i18n_e_ShowExpiredAlarms() { return i18n("Show &Expired Alarms"); }
00098 QString MainWindow::i18n_HideExpiredAlarms()   { return i18n("Hide Expired Alarms"); }
00099 QString MainWindow::i18n_e_HideExpiredAlarms() { return i18n("Hide &Expired Alarms"); }
00100 
00101 
00102 /******************************************************************************
00103 * Construct an instance.
00104 * To avoid resize() events occurring while still opening the calendar (and
00105 * resultant crashes), the calendar is opened before constructing the instance.
00106 */
00107 MainWindow* MainWindow::create(bool restored)
00108 {
00109     theApp()->checkCalendarDaemon();    // ensure calendar is open and daemon started
00110     return new MainWindow(restored);
00111 }
00112 
00113 MainWindow::MainWindow(bool restored)
00114     : MainWindowBase(0, 0, WGroupLeader | WStyle_ContextHelp | WDestructiveClose),
00115       mMinuteTimerActive(false),
00116       mHiddenTrayParent(false),
00117       mShowExpired(Preferences::showExpiredAlarms()),
00118       mShowTime(Preferences::showAlarmTime()),
00119       mShowTimeTo(Preferences::showTimeToAlarm())
00120 {
00121     kdDebug(5950) << "MainWindow::MainWindow()\n";
00122     setAutoSaveSettings(QString::fromLatin1("MainWindow"));    // save window sizes etc.
00123     setPlainCaption(kapp->aboutData()->programName());
00124     if (!restored)
00125     {
00126         QSize s;
00127         if (KAlarm::readConfigWindowSize("MainWindow", s))
00128             resize(s);
00129     }
00130 
00131     setAcceptDrops(true);         // allow drag-and-drop onto this window
00132     if (!mShowTimeTo)
00133         mShowTime = true;     // ensure at least one time column is visible
00134     mListView = new AlarmListView(this, "listView");
00135     mListView->selectTimeColumns(mShowTime, mShowTimeTo);
00136     mListView->showExpired(mShowExpired);
00137     setCentralWidget(mListView);
00138     mListView->refresh();          // populate the alarm list
00139     mListView->clearSelection();
00140 
00141     connect(mListView, SIGNAL(itemDeleted()), SLOT(slotDeletion()));
00142     connect(mListView, SIGNAL(selectionChanged()), SLOT(slotSelection()));
00143     connect(mListView, SIGNAL(mouseButtonClicked(int, QListViewItem*, const QPoint&, int)),
00144             SLOT(slotMouseClicked(int, QListViewItem*, const QPoint&, int)));
00145     connect(mListView, SIGNAL(executed(QListViewItem*)), SLOT(slotDoubleClicked(QListViewItem*)));
00146     initActions();
00147 
00148     mWindowList.append(this);
00149     if (mWindowList.count() == 1  &&  Daemon::isDcopHandlerReady())
00150     {
00151         // It's the first main window, and the DCOP handler is ready
00152         if (theApp()->wantRunInSystemTray())
00153             theApp()->displayTrayIcon(true, this);     // create system tray icon for run-in-system-tray mode
00154         else if (theApp()->trayWindow())
00155             theApp()->trayWindow()->setAssocMainWindow(this);    // associate this window with the system tray icon
00156     }
00157     setUpdateTimer();
00158 }
00159 
00160 MainWindow::~MainWindow()
00161 {
00162     kdDebug(5950) << "MainWindow::~MainWindow()\n";
00163     mWindowList.remove(this);
00164     if (theApp()->trayWindow())
00165     {
00166         if (isTrayParent())
00167             delete theApp()->trayWindow();
00168         else
00169             theApp()->trayWindow()->removeWindow(this);
00170     }
00171     MinuteTimer::disconnect(this);
00172     mMinuteTimerActive = false;    // to ensure that setUpdateTimer() works correctly
00173     setUpdateTimer();
00174     MainWindow* main = mainMainWindow();
00175     if (main)
00176         KAlarm::writeConfigWindowSize("MainWindow", main->size());
00177     KToolBar* tb = toolBar();
00178     if (tb)
00179         tb->saveSettings(KGlobal::config(), "Toolbars");
00180     KGlobal::config()->sync();    // save any new window size to disc
00181     theApp()->quitIf();
00182 }
00183 
00184 /******************************************************************************
00185 * Save settings to the session managed config file, for restoration
00186 * when the program is restored.
00187 */
00188 void MainWindow::saveProperties(KConfig* config)
00189 {
00190     config->writeEntry(QString::fromLatin1("HiddenTrayParent"), isTrayParent() && isHidden());
00191     config->writeEntry(QString::fromLatin1("ShowExpired"), mShowExpired);
00192     config->writeEntry(QString::fromLatin1("ShowTime"), mShowTime);
00193     config->writeEntry(QString::fromLatin1("ShowTimeTo"), mShowTimeTo);
00194 }
00195 
00196 /******************************************************************************
00197 * Read settings from the session managed config file.
00198 * This function is automatically called whenever the app is being
00199 * restored. Read in whatever was saved in saveProperties().
00200 */
00201 void MainWindow::readProperties(KConfig* config)
00202 {
00203     mHiddenTrayParent = config->readBoolEntry(QString::fromLatin1("HiddenTrayParent"));
00204     mShowExpired      = config->readBoolEntry(QString::fromLatin1("ShowExpired"));
00205     mShowTime         = config->readBoolEntry(QString::fromLatin1("ShowTime"));
00206     mShowTimeTo       = config->readBoolEntry(QString::fromLatin1("ShowTimeTo"));
00207 }
00208 
00209 /******************************************************************************
00210 * Get the main main window, i.e. the parent of the system tray icon, or if
00211 * none, the first main window to be created. Visible windows take precedence
00212 * over hidden ones.
00213 */
00214 MainWindow* MainWindow::mainMainWindow()
00215 {
00216     MainWindow* tray = theApp()->trayWindow() ? theApp()->trayWindow()->assocMainWindow() : 0;
00217     if (tray  &&  tray->isVisible())
00218         return tray;
00219     for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00220         if ((*it)->isVisible())
00221             return *it;
00222     if (tray)
00223         return tray;
00224     if (!mWindowList.count())
00225         return 0;
00226     return mWindowList.first();
00227 }
00228 
00229 /******************************************************************************
00230 * Check whether this main window is the parent of the system tray icon.
00231 */
00232 bool MainWindow::isTrayParent() const
00233 {
00234     return theApp()->wantRunInSystemTray()  &&  theApp()->trayMainWindow() == this;
00235 }
00236 
00237 /******************************************************************************
00238 *  Close all main windows.
00239 */
00240 void MainWindow::closeAll()
00241 {
00242     while (mWindowList.first())
00243         delete mWindowList.first();    // N.B. the destructor removes the window from the list
00244 }
00245 
00246 /******************************************************************************
00247 *  Called when the window's size has changed (before it is painted).
00248 *  Sets the last column in the list view to extend at least to the right hand
00249 *  edge of the list view.
00250 *  Records the new size in the config file.
00251 */
00252 void MainWindow::resizeEvent(QResizeEvent* re)
00253 {
00254     // Save the window's new size only if it's the first main window
00255     if (mainMainWindow() == this)
00256         KAlarm::writeConfigWindowSize("MainWindow", re->size());
00257     MainWindowBase::resizeEvent(re);
00258 }
00259 
00260 /******************************************************************************
00261 *  Called when the window is first displayed.
00262 *  Sets the last column in the list view to extend at least to the right hand
00263 *  edge of the list view.
00264 */
00265 void MainWindow::showEvent(QShowEvent* se)
00266 {
00267     setUpdateTimer();
00268     slotUpdateTimeTo();
00269     MainWindowBase::showEvent(se);
00270 }
00271 
00272 /******************************************************************************
00273 *  Display the window.
00274 */
00275 void MainWindow::show()
00276 {
00277     MainWindowBase::show();
00278     if (mMenuError)
00279     {
00280         // Show error message now that the main window has been displayed.
00281         // Waiting until now lets the user easily associate the message with
00282         // the main window which is faulty.
00283         KMessageBox::error(this, i18n("Failure to create menus\n(perhaps %1 missing or corrupted)").arg(QString::fromLatin1(UI_FILE)));
00284         mMenuError = false;
00285     }
00286 }
00287 
00288 /******************************************************************************
00289 *  Called after the window is hidden.
00290 */
00291 void MainWindow::hideEvent(QHideEvent* he)
00292 {
00293     setUpdateTimer();
00294     MainWindowBase::hideEvent(he);
00295 }
00296 
00297 /******************************************************************************
00298 *  Initialise the menu, toolbar and main window actions.
00299 */
00300 void MainWindow::initActions()
00301 {
00302     KActionCollection* actions = actionCollection();
00303     mActionTemplates       = new KAction(i18n("&Templates..."), 0, this, SLOT(slotTemplates()), actions, "templates");
00304     mActionNew             = KAlarm::createNewAlarmAction(i18n("&New..."), this, SLOT(slotNew()), actions, "new");
00305     mActionNewFromTemplate = KAlarm::createNewFromTemplateAction(i18n("New &From Template"), this, SLOT(slotNewFromTemplate(const KAEvent&)), actions, "newFromTempl");
00306     mActionCreateTemplate  = new KAction(i18n("Create Tem&plate..."), 0, this, SLOT(slotNewTemplate()), actions, "createTemplate");
00307     mActionCopy            = new KAction(i18n("&Copy..."), "editcopy", Qt::SHIFT+Qt::Key_Insert, this, SLOT(slotCopy()), actions, "copy");
00308     mActionModify          = new KAction(i18n("&Edit..."), "edit", Qt::CTRL+Qt::Key_E, this, SLOT(slotModify()), actions, "modify");
00309     mActionDelete          = new KAction(i18n("&Delete"), "editdelete", Qt::Key_Delete, this, SLOT(slotDelete()), actions, "delete");
00310     mActionReactivate      = new KAction(i18n("Reac&tivate"), 0, Qt::CTRL+Qt::Key_R, this, SLOT(slotReactivate()), actions, "undelete");
00311     mActionEnable          = new KAction(QString::null, 0, Qt::CTRL+Qt::Key_B, this, SLOT(slotEnable()), actions, "disable");
00312     mActionView            = new KAction(i18n("&View"), "viewmag", Qt::CTRL+Qt::Key_W, this, SLOT(slotView()), actions, "view");
00313     mActionShowTime        = new KToggleAction(i18n_a_ShowAlarmTimes(), Qt::CTRL+Qt::Key_M, this, SLOT(slotShowTime()), actions, "showAlarmTimes");
00314     mActionShowTime->setCheckedState(i18n("Hide &Alarm Times"));
00315     mActionShowTimeTo      = new KToggleAction(i18n_o_ShowTimeToAlarms(), Qt::CTRL+Qt::Key_I, this, SLOT(slotShowTimeTo()), actions, "showTimeToAlarms");
00316     mActionShowTimeTo->setCheckedState(i18n("Hide Time t&o Alarms"));
00317     mActionShowExpired     = new KToggleAction(i18n_e_ShowExpiredAlarms(), "history", Qt::CTRL+Qt::Key_P, this, SLOT(slotShowExpired()), actions, "showExpiredAlarms");
00318     mActionShowExpired->setCheckedState(i18n_e_HideExpiredAlarms());
00319     mActionToggleTrayIcon  = new KToggleAction(i18n("Show in System &Tray"), Qt::CTRL+Qt::Key_Y, this, SLOT(slotToggleTrayIcon()), actions, "showInSystemTray");
00320     mActionToggleTrayIcon->setCheckedState(i18n("Hide From System &Tray"));
00321     new KAction(i18n("Import &Birthdays..."), 0, this, SLOT(slotBirthdays()), actions, "importBirthdays");
00322     new KAction(i18n("&Refresh Alarms"), "reload", 0, this, SLOT(slotResetDaemon()), actions, "refreshAlarms");
00323     Daemon::createAlarmEnableAction(actions, "alarmEnable");
00324     if (undoText.isNull())
00325     {
00326         // Get standard texts, etc., for Undo and Redo actions
00327         KAction* act = KStdAction::undo(this, 0, actions);
00328         undoIcon         = act->icon();
00329         undoShortcut     = act->shortcut();
00330         undoText         = act->text();
00331         undoTextStripped = KAlarm::stripAccel(undoText);
00332         delete act;
00333         act = KStdAction::redo(this, 0, actions);
00334         redoIcon         = act->icon();
00335         redoShortcut     = act->shortcut();
00336         redoText         = act->text();
00337         redoTextStripped = KAlarm::stripAccel(redoText);
00338         delete act;
00339     }
00340     mActionUndo = new KToolBarPopupAction(undoText, undoIcon, undoShortcut, this, SLOT(slotUndo()), actions, "edit_undo");
00341     mActionRedo = new KToolBarPopupAction(redoText, redoIcon, redoShortcut, this, SLOT(slotRedo()), actions, "edit_redo");
00342     KStdAction::find(mListView, SLOT(slotFind()), actions);
00343     mActionFindNext = KStdAction::findNext(mListView, SLOT(slotFindNext()), actions);
00344     mActionFindPrev = KStdAction::findPrev(mListView, SLOT(slotFindPrev()), actions);
00345     KStdAction::quit(this, SLOT(slotQuit()), actions);
00346     KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actions);
00347     KStdAction::configureToolbars(this, SLOT(slotConfigureToolbar()), actions);
00348     KStdAction::preferences(this, SLOT(slotPreferences()), actions);
00349     setStandardToolBarMenuEnabled(true);
00350     createGUI(UI_FILE);
00351 
00352     mContextMenu = static_cast<KPopupMenu*>(factory()->container("listContext", this));
00353     mActionsMenu = static_cast<KPopupMenu*>(factory()->container("actions", this));
00354     mMenuError = (!mContextMenu  ||  !mActionsMenu);
00355     connect(mActionsMenu, SIGNAL(aboutToShow()), SLOT(updateActionsMenu()));
00356     connect(mActionUndo->popupMenu(), SIGNAL(aboutToShow()), SLOT(slotInitUndoMenu()));
00357     connect(mActionUndo->popupMenu(), SIGNAL(activated(int)), SLOT(slotUndoItem(int)));
00358     connect(mActionRedo->popupMenu(), SIGNAL(aboutToShow()), SLOT(slotInitRedoMenu()));
00359     connect(mActionRedo->popupMenu(), SIGNAL(activated(int)), SLOT(slotRedoItem(int)));
00360     connect(Undo::instance(), SIGNAL(changed(const QString&, const QString&)), SLOT(slotUndoStatus(const QString&, const QString&)));
00361     connect(mListView, SIGNAL(findActive(bool)), SLOT(slotFindActive(bool)));
00362     Preferences::connect(SIGNAL(preferencesChanged()), this, SLOT(updateTrayIconAction()));
00363     connect(theApp(), SIGNAL(trayIconToggled()), SLOT(updateTrayIconAction()));
00364 
00365     // Set menu item states
00366     setEnableText(true);
00367     mActionShowTime->setChecked(mShowTime);
00368     mActionShowTimeTo->setChecked(mShowTimeTo);
00369     mActionShowExpired->setChecked(mShowExpired);
00370     if (!Preferences::expiredKeepDays())
00371         mActionShowExpired->setEnabled(false);
00372     updateTrayIconAction();         // set the correct text for this action
00373     mActionUndo->setEnabled(Undo::haveUndo());
00374     mActionRedo->setEnabled(Undo::haveRedo());
00375     mActionFindNext->setEnabled(false);
00376     mActionFindPrev->setEnabled(false);
00377 
00378     mActionCopy->setEnabled(false);
00379     mActionModify->setEnabled(false);
00380     mActionDelete->setEnabled(false);
00381     mActionReactivate->setEnabled(false);
00382     mActionView->setEnabled(false);
00383     mActionEnable->setEnabled(false);
00384     mActionCreateTemplate->setEnabled(false);
00385 
00386     KToolBar* tb = toolBar();
00387     if (tb)
00388         tb->applySettings(KGlobal::config(), "Toolbars");
00389 
00390     Undo::emitChanged();     // set the Undo/Redo menu texts
00391     Daemon::checkStatus();
00392     Daemon::monitoringAlarms();
00393 }
00394 
00395 /******************************************************************************
00396 * Enable or disable the Templates menu item in every main window instance.
00397 */
00398 void MainWindow::enableTemplateMenuItem(bool enable)
00399 {
00400     for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00401         (*it)->mActionTemplates->setEnabled(enable);
00402 }
00403 
00404 /******************************************************************************
00405 * Refresh the alarm list in every main window instance.
00406 */
00407 void MainWindow::refresh()
00408 {
00409     kdDebug(5950) << "MainWindow::refresh()\n";
00410     for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00411         (*it)->mListView->refresh();
00412 }
00413 
00414 /******************************************************************************
00415 * Refresh the alarm list in every main window instance which is displaying
00416 * expired alarms.
00417 * Called when an expired alarm setting changes in the user preferences.
00418 */
00419 void MainWindow::updateExpired()
00420 {
00421     kdDebug(5950) << "MainWindow::updateExpired()\n";
00422     bool enableShowExpired = Preferences::expiredKeepDays();
00423     for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00424     {
00425         MainWindow* w = *it;
00426         if (w->mShowExpired)
00427         {
00428             if (!enableShowExpired)
00429                 w->slotShowExpired();
00430             else
00431                 w->mListView->refresh();
00432         }
00433         w->mActionShowExpired->setEnabled(enableShowExpired);
00434     }
00435 }
00436 
00437 /******************************************************************************
00438 * Called when the show-alarm-time or show-time-to-alarm setting changes in the
00439 * user preferences.
00440 * Update the alarm list in every main window instance to show the new default
00441 * columns. No change is made if a window isn't using the old settings.
00442 */
00443 void MainWindow::updateTimeColumns(bool oldTime, bool oldTimeTo)
00444 {
00445     kdDebug(5950) << "MainWindow::updateShowAlarmTimes()\n";
00446     bool newTime   = Preferences::showAlarmTime();
00447     bool newTimeTo = Preferences::showTimeToAlarm();
00448     if (!newTime  &&  !newTimeTo)
00449         newTime = true;     // at least one time column must be displayed
00450     if (!oldTime  &&  !oldTimeTo)
00451         oldTime = true;     // at least one time column must have been displayed
00452     if (newTime != oldTime  ||  newTimeTo != oldTimeTo)
00453     {
00454         for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00455         {
00456             MainWindow* w = *it;
00457             if (w->mShowTime   == oldTime
00458             &&  w->mShowTimeTo == oldTimeTo)
00459             {
00460                 w->mShowTime   = newTime;
00461                 w->mShowTimeTo = newTimeTo;
00462                 w->mActionShowTime->setChecked(newTime);
00463                 w->mActionShowTimeTo->setChecked(newTimeTo);
00464                 w->mListView->selectTimeColumns(newTime, newTimeTo);
00465             }
00466         }
00467         setUpdateTimer();
00468     }
00469 }
00470 
00471 /******************************************************************************
00472 * Start or stop the timer which updates the time-to-alarm values every minute.
00473 * Should be called whenever a main window is created or destroyed, or shown or
00474 * hidden.
00475 */
00476 void MainWindow::setUpdateTimer()
00477 {
00478     // Check whether any windows need to be updated
00479     MainWindow* needTimer = 0;
00480     MainWindow* timerWindow = 0;
00481     for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00482     {
00483         MainWindow* w = *it;
00484         if (w->isVisible()  &&  w->mListView->showingTimeTo())
00485             needTimer = w;
00486         if (w->mMinuteTimerActive)
00487             timerWindow = w;
00488     }
00489 
00490     // Start or stop the update timer if necessary
00491     if (needTimer  &&  !timerWindow)
00492     {
00493         // Timeout every minute.
00494         needTimer->mMinuteTimerActive = true;
00495         MinuteTimer::connect(needTimer, SLOT(slotUpdateTimeTo()));
00496         kdDebug(5950) << "MainWindow::setUpdateTimer(): started timer" << endl;
00497     }
00498     else if (!needTimer  &&  timerWindow)
00499     {
00500         timerWindow->mMinuteTimerActive = false;
00501         MinuteTimer::disconnect(timerWindow);
00502         kdDebug(5950) << "MainWindow::setUpdateTimer(): stopped timer" << endl;
00503     }
00504 }
00505 /******************************************************************************
00506 * Update the time-to-alarm values for each main window which is displaying them.
00507 */
00508 void MainWindow::slotUpdateTimeTo()
00509 {
00510     kdDebug(5950) << "MainWindow::slotUpdateTimeTo()" << endl;
00511     for (WindowList::Iterator it = mWindowList.begin();  it != mWindowList.end();  ++it)
00512     {
00513         MainWindow* w = *it;
00514         if (w->isVisible()  &&  w->mListView->showingTimeTo())
00515             w->mListView->updateTimeToAlarms();
00516     }
00517 }
00518 
00519 /******************************************************************************
00520 * Select an alarm in the displayed list.
00521 */
00522 void MainWindow::selectEvent(const QString& eventID)
00523 {
00524     mListView->clearSelection();
00525     AlarmListViewItem* item = mListView->getEntry(eventID);
00526     if (item)
00527     {
00528         mListView->setSelected(item, true);
00529         mListView->setCurrentItem(item);
00530         mListView->ensureItemVisible(item);
00531     }
00532 }
00533 
00534 /******************************************************************************
00535 *  Called when the New button is clicked to edit a new alarm to add to the list.
00536 */
00537 void MainWindow::slotNew()
00538 {
00539     executeNew(this);
00540 }
00541 
00542 /******************************************************************************
00543 *  Execute a New Alarm dialog, optionally either presetting it to the supplied
00544 *  event, or setting the action and text.
00545 */
00546 void MainWindow::executeNew(MainWindow* win, const KAEvent* evnt, KAEvent::Action action, const AlarmText& text)
00547 {
00548     EditAlarmDlg editDlg(false, i18n("New Alarm"), win, "editDlg", evnt);
00549     if (!text.isEmpty())
00550         editDlg.setAction(action, text);
00551     if (editDlg.exec() == QDialog::Accepted)
00552     {
00553         KAEvent event;
00554         editDlg.getEvent(event);
00555 
00556         // Add the alarm to the displayed lists and to the calendar file
00557         if (KAlarm::addEvent(event, (win ? win->mListView : 0)) == KAlarm::UPDATE_KORG_ERR)
00558             KAlarm::displayUpdateError(win, KAlarm::KORG_ERR_ADD);
00559         Undo::saveAdd(event);
00560 
00561         KAlarm::outputAlarmWarnings(&editDlg, &event);
00562     }
00563 }
00564 
00565 /******************************************************************************
00566 *  Called when a template is selected from the New From Template popup menu.
00567 *  Executes a New Alarm dialog, preset from the selected template.
00568 */
00569 void MainWindow::slotNewFromTemplate(const KAEvent& tmplate)
00570 {
00571     executeNew(this, &tmplate);
00572 }
00573 
00574 /******************************************************************************
00575 *  Called when the New Template button is clicked to create a new template
00576 *  based on the currently selected alarm.
00577 */
00578 void MainWindow::slotNewTemplate()
00579 {
00580     AlarmListViewItem* item = mListView->selectedItem();
00581     if (item)
00582     {
00583         KAEvent event = item->event();
00584         TemplateDlg::createTemplate(&event, this);
00585     }
00586 }
00587 
00588 /******************************************************************************
00589 *  Called when the Copy button is clicked to edit a copy of an existing alarm,
00590 *  to add to the list.
00591 */
00592 void MainWindow::slotCopy()
00593 {
00594     AlarmListViewItem* item = mListView->selectedItem();
00595     if (item)
00596         executeNew(this, &item->event());
00597 }
00598 
00599 /******************************************************************************
00600 *  Called when the Modify button is clicked to edit the currently highlighted
00601 *  alarm in the list.
00602 */
00603 void MainWindow::slotModify()
00604 {
00605     AlarmListViewItem* item = mListView->selectedItem();
00606     if (item)
00607     {
00608         KAEvent event = item->event();
00609         EditAlarmDlg editDlg(false, i18n("Edit Alarm"), this, "editDlg", &event);
00610         if (editDlg.exec() == QDialog::Accepted)
00611         {
00612             KAEvent newEvent;
00613             bool changeDeferral = !editDlg.getEvent(newEvent);
00614 
00615             // Update the event in the displays and in the calendar file
00616             if (changeDeferral)
00617             {
00618                 // The only change has been to an existing deferral
00619                 KAlarm::updateEvent(newEvent, mListView, true, false);   // keep the same event ID
00620             }
00621             else
00622             {
00623                 if (KAlarm::modifyEvent(event, newEvent, mListView) == KAlarm::UPDATE_KORG_ERR)
00624                     KAlarm::displayUpdateError(this, KAlarm::KORG_ERR_MODIFY);
00625             }
00626             Undo::saveEdit(event, newEvent);
00627 
00628             KAlarm::outputAlarmWarnings(&editDlg, &newEvent);
00629         }
00630     }
00631 }
00632 
00633 /******************************************************************************
00634 *  Called when the View button is clicked to view the currently highlighted
00635 *  alarm in the list.
00636 */
00637 void MainWindow::slotView()
00638 {
00639     AlarmListViewItem* item = mListView->selectedItem();
00640     if (item)
00641     {
00642         KAEvent event = item->event();
00643         EditAlarmDlg editDlg(false, (event.expired() ? i18n("Expired Alarm") + " [" + i18n("read-only") + "]"
00644                                                      : i18n("View Alarm")),
00645                              this, "editDlg", &event, true);
00646         editDlg.exec();
00647     }
00648 }
00649 
00650 /******************************************************************************
00651 *  Called when the Delete button is clicked to delete the currently highlighted
00652 *  alarms in the list.
00653 */
00654 void MainWindow::slotDelete()
00655 {
00656     QValueList<EventListViewItemBase*> items = mListView->selectedItems();
00657     if (Preferences::confirmAlarmDeletion())
00658     {
00659         int n = items.count();
00660         if (KMessageBox::warningContinueCancel(this, i18n("Do you really want to delete the selected alarm?",
00661                                                           "Do you really want to delete the %n selected alarms?", n),
00662                                                i18n("Delete Alarm", "Delete Alarms", n),
00663                                                KGuiItem(i18n("&Delete"), "editdelete"),
00664                                                Preferences::CONFIRM_ALARM_DELETION)
00665             != KMessageBox::Continue)
00666             return;
00667     }
00668 
00669     int warnKOrg = 0;
00670     QValueList<KAEvent> events;
00671     AlarmCalendar::activeCalendar()->startUpdate();    // prevent multiple saves of the calendars until we're finished
00672     AlarmCalendar::expiredCalendar()->startUpdate();
00673     for (QValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
00674     {
00675         AlarmListViewItem* item = (AlarmListViewItem*)(*it);
00676         KAEvent event = item->event();
00677 
00678         // Delete the event from the calendar and displays
00679         events.append(event);
00680         if (KAlarm::deleteEvent(event) == KAlarm::UPDATE_KORG_ERR)
00681             ++warnKOrg;
00682     }
00683     AlarmCalendar::activeCalendar()->endUpdate();      // save the calendars now
00684     AlarmCalendar::expiredCalendar()->endUpdate();
00685     Undo::saveDeletes(events);
00686 
00687     if (warnKOrg)
00688         KAlarm::displayUpdateError(this, KAlarm::KORG_ERR_DELETE, (warnKOrg > 1));
00689 }
00690 
00691 /******************************************************************************
00692 *  Called when the Reactivate button is clicked to reinstate the currently
00693 *  highlighted expired alarms in the list.
00694 */
00695 void MainWindow::slotReactivate()
00696 {
00697     int warnKOrg = 0;
00698     QValueList<KAEvent> events;
00699     QValueList<EventListViewItemBase*> items = mListView->selectedItems();
00700     mListView->clearSelection();
00701     AlarmCalendar::activeCalendar()->startUpdate();    // prevent multiple saves of the calendars until we're finished
00702     AlarmCalendar::expiredCalendar()->startUpdate();
00703     for (QValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
00704     {
00705         // Add the alarm to the displayed lists and to the calendar file
00706         AlarmListViewItem* item = (AlarmListViewItem*)(*it);
00707         KAEvent event = item->event();
00708         events.append(event);
00709         if (KAlarm::reactivateEvent(event, mListView, true) == KAlarm::UPDATE_KORG_ERR)
00710             ++warnKOrg;
00711     }
00712     AlarmCalendar::activeCalendar()->endUpdate();      // save the calendars now
00713     AlarmCalendar::expiredCalendar()->endUpdate();
00714     Undo::saveReactivates(events);
00715 
00716     if (warnKOrg)
00717         KAlarm::displayUpdateError(this, KAlarm::KORG_ERR_ADD, (warnKOrg > 1));
00718 }
00719 
00720 /******************************************************************************
00721 *  Called when the Enable/Disable button is clicked to enable or disable the
00722 *  currently highlighted alarms in the list.
00723 */
00724 void MainWindow::slotEnable()
00725 {
00726     bool enable = mActionEnableEnable;    // save since changed in response to KAlarm::enableEvent()
00727     QValueList<EventListViewItemBase*> items = mListView->selectedItems();
00728     AlarmCalendar::activeCalendar()->startUpdate();    // prevent multiple saves of the calendars until we're finished
00729     for (QValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
00730     {
00731         AlarmListViewItem* item = (AlarmListViewItem*)(*it);
00732         KAEvent event = item->event();
00733 
00734         // Enable the alarm in the displayed lists and in the calendar file
00735         KAlarm::enableEvent(event, mListView, enable);
00736     }
00737     AlarmCalendar::activeCalendar()->endUpdate();      // save the calendars now
00738 }
00739 
00740 /******************************************************************************
00741 *  Called when the Show Alarm Times menu item is selected or deselected.
00742 */
00743 void MainWindow::slotShowTime()
00744 {
00745     mShowTime = !mShowTime;
00746     mActionShowTime->setChecked(mShowTime);
00747     if (!mShowTime  &&  !mShowTimeTo)
00748         slotShowTimeTo();    // at least one time column must be displayed
00749     else
00750         mListView->selectTimeColumns(mShowTime, mShowTimeTo);
00751 }
00752 
00753 /******************************************************************************
00754 *  Called when the Show Time To Alarms menu item is selected or deselected.
00755 */
00756 void MainWindow::slotShowTimeTo()
00757 {
00758     mShowTimeTo = !mShowTimeTo;
00759     mActionShowTimeTo->setChecked(mShowTimeTo);
00760     if (!mShowTimeTo  &&  !mShowTime)
00761         slotShowTime();    // at least one time column must be displayed
00762     else
00763         mListView->selectTimeColumns(mShowTime, mShowTimeTo);
00764     setUpdateTimer();
00765 }
00766 
00767 /******************************************************************************
00768 *  Called when the Show Expired Alarms menu item is selected or deselected.
00769 */
00770 void MainWindow::slotShowExpired()
00771 {
00772     mShowExpired = !mShowExpired;
00773     mActionShowExpired->setChecked(mShowExpired);
00774     mActionShowExpired->setToolTip(mShowExpired ? i18n_HideExpiredAlarms() : i18n_ShowExpiredAlarms());
00775     mListView->showExpired(mShowExpired);
00776     mListView->refresh();
00777 }
00778 
00779 /******************************************************************************
00780 *  Called when the Import Birthdays menu item is selected, to display birthdays
00781 *  from the address book for selection as alarms.
00782 */
00783 void MainWindow::slotBirthdays()
00784 {
00785     BirthdayDlg dlg(this);
00786     if (dlg.exec() == QDialog::Accepted)
00787     {
00788         QValueList<KAEvent> events = dlg.events();
00789         if (events.count())
00790         {
00791             mListView->clearSelection();
00792             int warnKOrg = 0;
00793             for (QValueList<KAEvent>::Iterator ev = events.begin();  ev != events.end();  ++ev)
00794             {
00795                 // Add alarm to the displayed lists and to the calendar file
00796                 if (KAlarm::addEvent(*ev, mListView) == KAlarm::UPDATE_KORG_ERR)
00797                     ++warnKOrg;
00798             }
00799             if (warnKOrg)
00800                 KAlarm::displayUpdateError(this, KAlarm::KORG_ERR_ADD, (warnKOrg > 1));
00801             KAlarm::outputAlarmWarnings(&dlg);
00802         }
00803     }
00804 }
00805 
00806 /******************************************************************************
00807 *  Called when the Templates menu item is selected, to display the alarm
00808 *  template editing dialogue.
00809 */
00810 void MainWindow::slotTemplates()
00811 {
00812     if (!mTemplateDlg)
00813     {
00814         mTemplateDlg = TemplateDlg::create(this);
00815         enableTemplateMenuItem(false);     // disable menu item in all windows
00816         connect(mTemplateDlg, SIGNAL(finished()), SLOT(slotTemplatesEnd()));
00817         mTemplateDlg->show();
00818     }
00819 }
00820 
00821 /******************************************************************************
00822 *  Called when the alarm template editing dialogue has exited.
00823 */
00824 void MainWindow::slotTemplatesEnd()
00825 {
00826     if (mTemplateDlg)
00827     {
00828         mTemplateDlg->delayedDestruct();   // this deletes the dialogue once it is safe to do so
00829         mTemplateDlg = 0;
00830         enableTemplateMenuItem(true);      // re-enable menu item in all windows
00831     }
00832 }
00833 
00834 /******************************************************************************
00835 *  Called when the Display System Tray Icon menu item is selected.
00836 */
00837 void MainWindow::slotToggleTrayIcon()
00838 {
00839     theApp()->displayTrayIcon(!theApp()->trayIconDisplayed(), this);
00840 }
00841 
00842 /******************************************************************************
00843 * Called when the system tray icon is created or destroyed.
00844 * Set the system tray icon menu text according to whether or not the system
00845 * tray icon is currently visible.
00846 */
00847 void MainWindow::updateTrayIconAction()
00848 {
00849     mActionToggleTrayIcon->setEnabled(theApp()->KDEDesktop() && !theApp()->wantRunInSystemTray());
00850     mActionToggleTrayIcon->setChecked(theApp()->trayIconDisplayed());
00851 }
00852 
00853 /******************************************************************************
00854 * Called when the Actions menu is about to be displayed.
00855 * Update the status of the Alarms Enabled menu item.
00856 */
00857 void MainWindow::updateActionsMenu()
00858 {
00859     Daemon::checkStatus();   // update the Alarms Enabled item status
00860 }
00861 
00862 /******************************************************************************
00863 *  Called when the active status of Find changes.
00864 */
00865 void MainWindow::slotFindActive(bool active)
00866 {
00867     mActionFindNext->setEnabled(active);
00868     mActionFindPrev->setEnabled(active);
00869 }
00870 
00871 /******************************************************************************
00872 *  Called when the Undo action is selected.
00873 */
00874 void MainWindow::slotUndo()
00875 {
00876     Undo::undo(this, KAlarm::stripAccel(mActionUndo->text()));
00877 }
00878 
00879 /******************************************************************************
00880 *  Called when the Redo action is selected.
00881 */
00882 void MainWindow::slotRedo()
00883 {
00884     Undo::redo(this, KAlarm::stripAccel(mActionRedo->text()));
00885 }
00886 
00887 /******************************************************************************
00888 *  Called when an Undo item is selected.
00889 */
00890 void MainWindow::slotUndoItem(int id)
00891 {
00892     Undo::undo(id, this, Undo::actionText(Undo::UNDO, id));
00893 }
00894 
00895 /******************************************************************************
00896 *  Called when a Redo item is selected.
00897 */
00898 void MainWindow::slotRedoItem(int id)
00899 {
00900     Undo::redo(id, this, Undo::actionText(Undo::REDO, id));
00901 }
00902 
00903 /******************************************************************************
00904 *  Called when the Undo menu is about to show.
00905 *  Populates the menu.
00906 */
00907 void MainWindow::slotInitUndoMenu()
00908 {
00909     initUndoMenu(mActionUndo->popupMenu(), Undo::UNDO);
00910 }
00911 
00912 /******************************************************************************
00913 *  Called when the Redo menu is about to show.
00914 *  Populates the menu.
00915 */
00916 void MainWindow::slotInitRedoMenu()
00917 {
00918     initUndoMenu(mActionRedo->popupMenu(), Undo::REDO);
00919 }
00920 
00921 /******************************************************************************
00922 *  Populate the undo or redo menu.
00923 */
00924 void MainWindow::initUndoMenu(KPopupMenu* menu, Undo::Type type)
00925 {
00926     menu->clear();
00927     const QString& action = (type == Undo::UNDO) ? undoTextStripped : redoTextStripped;
00928     QValueList<int> ids = Undo::ids(type);
00929     for (QValueList<int>::ConstIterator it = ids.begin();  it != ids.end();  ++it)
00930     {
00931         int id = *it;
00932         menu->insertItem(i18n("Undo [action]: message", "%1 %2: %3")
00933                                .arg(action).arg(Undo::actionText(type, id)).arg(Undo::description(type, id)), id);
00934     }
00935 }
00936 
00937 /******************************************************************************
00938 *  Called when the status of the Undo or Redo list changes.
00939 *  Change the Undo or Redo text to include the action which would be undone/redone.
00940 */
00941 void MainWindow::slotUndoStatus(const QString& undo, const QString& redo)
00942 {
00943     if (undo.isNull())
00944     {
00945         mActionUndo->setEnabled(false);
00946         mActionUndo->setText(undoText);
00947     }
00948     else
00949     {
00950         mActionUndo->setEnabled(true);
00951         mActionUndo->setText(QString("%1 %2").arg(undoText).arg(undo));
00952     }
00953     if (redo.isNull())
00954     {
00955         mActionRedo->setEnabled(false);
00956         mActionRedo->setText(redoText);
00957     }
00958     else
00959     {
00960         mActionRedo->setEnabled(true);
00961         mActionRedo->setText(QString("%1 %2").arg(redoText).arg(redo));
00962     }
00963 }
00964 
00965 /******************************************************************************
00966 *  Called when the Reset Daemon menu item is selected.
00967 */
00968 void MainWindow::slotResetDaemon()
00969 {
00970     KAlarm::resetDaemon();
00971 }
00972 
00973 /******************************************************************************
00974 *  Called when the "Configure KAlarm" menu item is selected.
00975 */
00976 void MainWindow::slotPreferences()
00977 {
00978     KAlarmPrefDlg prefDlg;
00979     prefDlg.exec();
00980 }
00981 
00982 /******************************************************************************
00983 *  Called when the Configure Keys menu item is selected.
00984 */
00985 void MainWindow::slotConfigureKeys()
00986 {
00987     KKeyDialog::configure(actionCollection(), this);
00988 }
00989 
00990 /******************************************************************************
00991 *  Called when the Configure Toolbars menu item is selected.
00992 */
00993 void MainWindow::slotConfigureToolbar()
00994 {
00995     saveMainWindowSettings(KGlobal::config(), "MainWindow");
00996     KEditToolbar dlg(factory());
00997     connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(slotNewToolbarConfig()));
00998     dlg.exec();
00999 }
01000 
01001 /******************************************************************************
01002 *  Called when OK or Apply is clicked in the Configure Toolbars dialog, to save
01003 *  the new configuration.
01004 */
01005 void MainWindow::slotNewToolbarConfig()
01006 {
01007     createGUI(UI_FILE);
01008     applyMainWindowSettings(KGlobal::config(), "MainWindow");
01009 }
01010 
01011 /******************************************************************************
01012 *  Called when the Quit menu item is selected.
01013 */
01014 void MainWindow::slotQuit()
01015 {
01016     theApp()->doQuit(this);
01017 }
01018 
01019 /******************************************************************************
01020 *  Called when the user or the session manager attempts to close the window.
01021 */
01022 void MainWindow::closeEvent(QCloseEvent* ce)
01023 {
01024     if (!theApp()->sessionClosingDown()  &&  isTrayParent())
01025     {
01026         // The user (not the session manager) wants to close the window.
01027         // It's the parent window of the system tray icon, so just hide
01028         // it to prevent the system tray icon closing.
01029         hide();
01030         theApp()->quitIf();
01031         ce->ignore();
01032     }
01033     else
01034         ce->accept();
01035 }
01036 
01037 /******************************************************************************
01038 *  Called when an item is deleted from the ListView.
01039 *  Disables the actions if no item is still selected.
01040 */
01041 void MainWindow::slotDeletion()
01042 {
01043     if (!mListView->selectedCount())
01044     {
01045         kdDebug(5950) << "MainWindow::slotDeletion(true)\n";
01046         mActionCreateTemplate->setEnabled(false);
01047         mActionCopy->setEnabled(false);
01048         mActionModify->setEnabled(false);
01049         mActionView->setEnabled(false);
01050         mActionDelete->setEnabled(false);
01051         mActionReactivate->setEnabled(false);
01052         mActionEnable->setEnabled(false);
01053     }
01054 }
01055 
01056 /******************************************************************************
01057 *  Called when the drag cursor enters the window.
01058 */
01059 void MainWindow::dragEnterEvent(QDragEnterEvent* e)
01060 {
01061     executeDragEnterEvent(e);
01062 }
01063 
01064 /******************************************************************************
01065 *  Called when the drag cursor enters a main or system tray window, to accept
01066 *  or reject the dragged object.
01067 */
01068 void MainWindow::executeDragEnterEvent(QDragEnterEvent* e)
01069 {
01070     if (KCal::ICalDrag::canDecode(e))
01071         e->accept(!AlarmListView::dragging());   // don't accept "text/calendar" objects from KAlarm
01072     else
01073         e->accept(QTextDrag::canDecode(e)
01074                || KURLDrag::canDecode(e)
01075                || KPIM::MailListDrag::canDecode(e));
01076 }
01077 
01078 /******************************************************************************
01079 *  Called when an object is dropped on the window.
01080 *  If the object is recognised, the edit alarm dialog is opened appropriately.
01081 */
01082 void MainWindow::dropEvent(QDropEvent* e)
01083 {
01084     executeDropEvent(this, e);
01085 }
01086 
01087 static QString getMailHeader(const char* header, KMime::Content& content)
01088 {
01089     KMime::Headers::Base* hd = content.getHeaderByType(header);
01090     return hd ? hd->asUnicodeString() : QString::null;
01091 }
01092 
01093 /******************************************************************************
01094 *  Called when an object is dropped on a main or system tray window, to
01095 *  evaluate the action required and extract the text.
01096 */
01097 void MainWindow::executeDropEvent(MainWindow* win, QDropEvent* e)
01098 {
01099     KAEvent::Action action = KAEvent::MESSAGE;
01100     QString        text;
01101     QByteArray     bytes;
01102     AlarmText      alarmText;
01103     KPIM::MailList mailList;
01104     KURL::List     files;
01105     KCal::CalendarLocal calendar(QString::fromLatin1("UTC"));
01106     calendar.setLocalTime();    // default to local time (i.e. no time zone)
01107 #ifndef NDEBUG
01108     QCString fmts;
01109     for (int idbg = 0;  e->format(idbg);  ++idbg)
01110     {
01111         if (idbg) fmts += ", ";
01112         fmts += e->format(idbg);
01113     }
01114     kdDebug(5950) << "MainWindow::executeDropEvent(): " << fmts << endl;
01115 #endif
01116 
01117     /* The order of the tests below matters, since some dropped objects
01118      * provide more than one mime type.
01119      * Don't change them without careful thought !!
01120      */
01121     if (e->provides("message/rfc822")
01122     &&  !(bytes = e->encodedData("message/rfc822")).isEmpty())
01123     {
01124         // Email message(s). Ignore all but the first.
01125         kdDebug(5950) << "MainWindow::executeDropEvent(email)" << endl;
01126         QCString mails(bytes.data(), bytes.size());
01127         KMime::Content content;
01128         content.setContent(mails);
01129         content.parse();
01130         QString body;
01131         content.textContent()->decodedText(body, true, true);    // strip trailing newlines & spaces
01132         unsigned long sernum = 0;
01133         if (e->provides(KPIM::MailListDrag::format())
01134         &&  KPIM::MailListDrag::decode(e, mailList)
01135         &&  mailList.count())
01136         {
01137             // Get its KMail serial number to allow the KMail message
01138             // to be called up from the alarm message window.
01139             sernum = mailList.first().serialNumber();
01140         }
01141         alarmText.setEmail(getMailHeader("To", content),
01142                            getMailHeader("From", content),
01143                            getMailHeader("Cc", content),
01144                            getMailHeader("Date", content),
01145                            getMailHeader("Subject", content),
01146                    body, sernum);
01147     }
01148     else if (KURLDrag::decode(e, files)  &&  files.count())
01149     {
01150         kdDebug(5950) << "MainWindow::executeDropEvent(URL)" << endl;
01151         action = KAEvent::FILE;
01152         alarmText.setText(files.first().prettyURL());
01153     }
01154     else if (e->provides(KPIM::MailListDrag::format())
01155     &&       KPIM::MailListDrag::decode(e, mailList))
01156     {
01157         // KMail message(s). Ignore all but the first.
01158         kdDebug(5950) << "MainWindow::executeDropEvent(KMail_list)" << endl;
01159         if (!mailList.count())
01160             return;
01161         KPIM::MailSummary& summary = mailList.first();
01162         QDateTime dt;
01163         dt.setTime_t(summary.date());
01164         QString body = KAMail::getMailBody(summary.serialNumber());
01165         alarmText.setEmail(summary.to(), summary.from(), QString::null,
01166                            KGlobal::locale()->formatDateTime(dt), summary.subject(),
01167                            body, summary.serialNumber());
01168     }
01169     else if (KCal::ICalDrag::decode(e, &calendar))
01170     {
01171         // iCalendar - ignore all but the first event
01172         kdDebug(5950) << "MainWindow::executeDropEvent(iCalendar)" << endl;
01173         KCal::Event::List events = calendar.rawEvents();
01174         if (!events.isEmpty())
01175         {
01176             KAEvent ev(*events.first());
01177             executeNew(win, &ev);
01178         }
01179         return;
01180     }
01181     else if (QTextDrag::decode(e, text))
01182     {
01183         kdDebug(5950) << "MainWindow::executeDropEvent(text)" << endl;
01184         alarmText.setText(text);
01185     }
01186     else
01187         return;
01188 
01189     if (!alarmText.isEmpty())
01190         executeNew(win, 0, action, alarmText);
01191 }
01192 
01193 /******************************************************************************
01194 *  Called when the selected items in the ListView changes.
01195 *  Selects the new current item, and enables the actions appropriately.
01196 */
01197 void MainWindow::slotSelection()
01198 {
01199     // Find which item has been selected, and whether more than one is selected
01200     QValueList<EventListViewItemBase*> items = mListView->selectedItems();
01201     int count = items.count();
01202     AlarmListViewItem* item = (AlarmListViewItem*)((count == 1) ? items.first() : 0);
01203     bool enableReactivate = true;
01204     bool enableEnableDisable = true;
01205     bool enableEnable = false;
01206     bool enableDisable = false;
01207     QDateTime now = QDateTime::currentDateTime();
01208     for (QValueList<EventListViewItemBase*>::Iterator it = items.begin();  it != items.end();  ++it)
01209     {
01210         const KAEvent& event = ((AlarmListViewItem*)(*it))->event();
01211         if (enableReactivate
01212         &&  (!event.expired()  ||  !event.occursAfter(now, true)))
01213             enableReactivate = false;
01214         if (enableEnableDisable)
01215         {
01216             if (event.expired())
01217                 enableEnableDisable = enableEnable = enableDisable = false;
01218             else
01219             {
01220                 if (!enableEnable  &&  !event.enabled())
01221                     enableEnable = true;
01222                 if (!enableDisable  &&  event.enabled())
01223                     enableDisable = true;
01224             }
01225         }
01226     }
01227 
01228     kdDebug(5950) << "MainWindow::slotSelection(true)\n";
01229     mActionCreateTemplate->setEnabled(count == 1);
01230     mActionCopy->setEnabled(count == 1);
01231     mActionModify->setEnabled(item && !mListView->expired(item));
01232     mActionView->setEnabled(count == 1);
01233     mActionDelete->setEnabled(count);
01234     mActionReactivate->setEnabled(count && enableReactivate);
01235     mActionEnable->setEnabled(enableEnable || enableDisable);
01236     if (enableEnable || enableDisable)
01237         setEnableText(enableEnable);
01238 }
01239 
01240 /******************************************************************************
01241 *  Called when the mouse is clicked on the ListView.
01242 *  Deselects the current item and disables the actions if appropriate, or
01243 *  displays a context menu to modify or delete the selected item.
01244 */
01245 void MainWindow::slotMouseClicked(int button, QListViewItem* item, const QPoint& pt, int)
01246 {
01247     if (button == Qt::RightButton)
01248     {
01249         kdDebug(5950) << "MainWindow::slotMouseClicked(right)\n";
01250         if (mContextMenu)
01251             mContextMenu->popup(pt);
01252     }
01253     else if (!item)
01254     {
01255         kdDebug(5950) << "MainWindow::slotMouseClicked(left)\n";
01256         mListView->clearSelection();
01257         mActionCreateTemplate->setEnabled(false);
01258         mActionCopy->setEnabled(false);
01259         mActionModify->setEnabled(false);
01260         mActionView->setEnabled(false);
01261         mActionDelete->setEnabled(false);
01262         mActionReactivate->setEnabled(false);
01263         mActionEnable->setEnabled(false);
01264     }
01265 }
01266 
01267 /******************************************************************************
01268 *  Called when the mouse is double clicked on the ListView.
01269 *  Displays the Edit Alarm dialog, for the clicked item if applicable.
01270 */
01271 void MainWindow::slotDoubleClicked(QListViewItem* item)
01272 {
01273     kdDebug(5950) << "MainWindow::slotDoubleClicked()\n";
01274     if (item)
01275     {
01276         if (mListView->expired((AlarmListViewItem*)item))
01277             slotView();
01278         else
01279             slotModify();
01280     }
01281     else
01282         slotNew();
01283 }
01284 
01285 /******************************************************************************
01286 *  Set the text of the Enable/Disable menu action.
01287 */
01288 void MainWindow::setEnableText(bool enable)
01289 {
01290     mActionEnableEnable = enable;
01291     mActionEnable->setText(enable ? i18n("Ena&ble") : i18n("Disa&ble"));
01292 }
01293 
01294 /******************************************************************************
01295 *  Display or hide the specified main window.
01296 *  This should only be called when the application doesn't run in the system tray.
01297 */
01298 MainWindow* MainWindow::toggleWindow(MainWindow* win)
01299 {
01300     if (win  &&  mWindowList.find(win) != mWindowList.end())
01301     {
01302         // A window is specified (and it exists)
01303         if (win->isVisible())
01304         {
01305             // The window is visible, so close it
01306             win->close();
01307             return 0;
01308         }
01309         else
01310         {
01311             // The window is hidden, so display it
01312             win->hide();        // in case it's on a different desktop
01313             win->showNormal();
01314             win->raise();
01315             win->setActiveWindow();
01316             return win;
01317         }
01318     }
01319 
01320     // No window is specified, or the window doesn't exist. Open a new one.
01321     win = create();
01322     win->show();
01323     return win;
01324 }
KDE Home | KDE Accessibility Home | Description of Access Keys