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