kalarm

mainwindow.cpp
1 /*
2  * mainwindow.cpp - main application window
3  * Program: kalarm
4  * Copyright © 2001-2007 by David Jarvie <djarvie@kde.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include "kalarm.h"
22 
23 #include <tqiconset.h>
24 #include <tqdragobject.h>
25 #include <tqheader.h>
26 
27 #include <tdemenubar.h>
28 #include <tdetoolbar.h>
29 #include <tdepopupmenu.h>
30 #include <tdeaccel.h>
31 #include <tdeaction.h>
32 #include <tdeactionclasses.h>
33 #include <kstdaction.h>
34 #include <kiconloader.h>
35 #include <tdemessagebox.h>
36 #include <kurldrag.h>
37 #include <tdelocale.h>
38 #include <tdeglobalsettings.h>
39 #include <tdeconfig.h>
40 #include <kkeydialog.h>
41 #include <kedittoolbar.h>
42 #include <tdeaboutdata.h>
43 #include <dcopclient.h>
44 #include <kdebug.h>
45 
46 #include <libtdepim/maillistdrag.h>
47 #include <libkmime/kmime_content.h>
48 #include <libkcal/calendarlocal.h>
49 #include <libkcal/icaldrag.h>
50 
51 #include "alarmcalendar.h"
52 #include "alarmevent.h"
53 #include "alarmlistview.h"
54 #include "alarmtext.h"
55 #include "birthdaydlg.h"
56 #include "daemon.h"
57 #include "editdlg.h"
58 #include "functions.h"
59 #include "kalarmapp.h"
60 #include "kamail.h"
61 #include "prefdlg.h"
62 #include "preferences.h"
63 #include "synchtimer.h"
64 #include "templatepickdlg.h"
65 #include "templatedlg.h"
66 #include "traywindow.h"
67 #include "mainwindow.moc"
68 
69 using namespace KCal;
70 
71 static const char* UI_FILE = "kalarmui.rc";
72 static const char* WINDOW_NAME = "MainWindow";
73 
74 static const TQString VIEW_GROUP = TQString::fromLatin1("View");
75 static const TQString SHOW_TIME_KEY = TQString::fromLatin1("ShowAlarmTime");
76 static const TQString SHOW_TIME_TO_KEY = TQString::fromLatin1("ShowTimeToAlarm");
77 static const TQString SHOW_ARCHIVED_KEY = TQString::fromLatin1("ShowArchivedAlarms");
78 static const TQString SHOW_RESOURCES_KEY = TQString::fromLatin1("ShowResources");
79 
80 static TQString undoText;
81 static TQString undoTextStripped;
82 static TQString undoIcon;
83 static TDEShortcut undoShortcut;
84 static TQString redoText;
85 static TQString redoTextStripped;
86 static TQString redoIcon;
87 static TDEShortcut redoShortcut;
88 
89 
90 /*=============================================================================
91 = Class: MainWindow
92 =============================================================================*/
93 
94 MainWindow::WindowList MainWindow::mWindowList;
95 TemplateDlg* MainWindow::mTemplateDlg = 0;
96 
97 // Collect these widget labels together to ensure consistent wording and
98 // translations across different modules.
99 TQString MainWindow::i18n_a_ShowAlarmTimes() { return i18n("Show &Alarm Times"); }
100 TQString MainWindow::i18n_m_ShowAlarmTime() { return i18n("Show alarm ti&me"); }
101 TQString MainWindow::i18n_o_ShowTimeToAlarms() { return i18n("Show Time t&o Alarms"); }
102 TQString MainWindow::i18n_l_ShowTimeToAlarm() { return i18n("Show time unti&l alarm"); }
103 TQString MainWindow::i18n_ShowExpiredAlarms() { return i18n("Show Expired Alarms"); }
104 TQString MainWindow::i18n_e_ShowExpiredAlarms() { return i18n("Show &Expired Alarms"); }
105 TQString MainWindow::i18n_HideExpiredAlarms() { return i18n("Hide Expired Alarms"); }
106 TQString MainWindow::i18n_e_HideExpiredAlarms() { return i18n("Hide &Expired Alarms"); }
107 
108 
109 /******************************************************************************
110 * Construct an instance.
111 * To avoid resize() events occurring while still opening the calendar (and
112 * resultant crashes), the calendar is opened before constructing the instance.
113 */
114 MainWindow* MainWindow::create(bool restored)
115 {
116  theApp()->checkCalendarDaemon(); // ensure calendar is open and daemon started
117  return new MainWindow(restored);
118 }
119 
120 MainWindow::MainWindow(bool restored)
121  : MainWindowBase(0, "MainWin", WGroupLeader | WStyle_ContextHelp | WDestructiveClose),
122  mMinuteTimerActive(false),
123  mHiddenTrayParent(false)
124 {
125  kdDebug(5950) << "MainWindow::MainWindow()\n";
126  setAutoSaveSettings(TQString::fromLatin1(WINDOW_NAME)); // save window sizes etc.
127  setPlainCaption(kapp->aboutData()->programName());
128  TDEConfig* config = TDEGlobal::config();
129  config->setGroup(VIEW_GROUP);
130  mShowExpired = config->readBoolEntry(SHOW_ARCHIVED_KEY, false);
131  mShowTime = config->readBoolEntry(SHOW_TIME_KEY, true);
132  mShowTimeTo = config->readBoolEntry(SHOW_TIME_TO_KEY, false);
133  if (!restored)
134  {
135  TQSize s;
136  if (KAlarm::readConfigWindowSize(WINDOW_NAME, s))
137  resize(s);
138  }
139  config->setGroup(TQString::fromLatin1(WINDOW_NAME));
140  TQValueList<int> order = config->readIntListEntry(TQString::fromLatin1("ColumnOrder"));
141 
142  setAcceptDrops(true); // allow drag-and-drop onto this window
143  if (!mShowTimeTo)
144  mShowTime = true; // ensure at least one time column is visible
145  mListView = new AlarmListView(order, this, "listView");
146  mListView->selectTimeColumns(mShowTime, mShowTimeTo);
147  mListView->showExpired(mShowExpired);
148  setCentralWidget(mListView);
149  mListView->refresh(); // populate the alarm list
150  mListView->clearSelection();
151 
152  connect(mListView, TQ_SIGNAL(itemDeleted()), TQ_SLOT(slotDeletion()));
153  connect(mListView, TQ_SIGNAL(selectionChanged()), TQ_SLOT(slotSelection()));
154  connect(mListView, TQ_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
155  TQ_SLOT(slotContextMenuRequested(TQListViewItem*, const TQPoint&, int)));
156  connect(mListView, TQ_SIGNAL(mouseButtonClicked(int, TQListViewItem*, const TQPoint&, int)),
157  TQ_SLOT(slotMouseClicked(int, TQListViewItem*, const TQPoint&, int)));
158  connect(mListView, TQ_SIGNAL(executed(TQListViewItem*)), TQ_SLOT(slotDoubleClicked(TQListViewItem*)));
159  connect(mListView->header(), TQ_SIGNAL(indexChange(int, int, int)), TQ_SLOT(columnsReordered()));
160  initActions();
161 
162  mWindowList.append(this);
163  if (mWindowList.count() == 1 && Daemon::isDcopHandlerReady())
164  {
165  // It's the first main window, and the DCOP handler is ready
166  if (theApp()->wantRunInSystemTray())
167  theApp()->displayTrayIcon(true, this); // create system tray icon for run-in-system-tray mode
168  else if (theApp()->trayWindow())
169  theApp()->trayWindow()->setAssocMainWindow(this); // associate this window with the system tray icon
170  }
171  setUpdateTimer();
172 }
173 
174 MainWindow::~MainWindow()
175 {
176  kdDebug(5950) << "MainWindow::~MainWindow()\n";
177  mWindowList.remove(this);
178  if (theApp()->trayWindow())
179  {
180  if (isTrayParent())
181  delete theApp()->trayWindow();
182  else
183  theApp()->trayWindow()->removeWindow(this);
184  }
185  MinuteTimer::disconnect(this);
186  mMinuteTimerActive = false; // to ensure that setUpdateTimer() works correctly
187  setUpdateTimer();
188  MainWindow* main = mainMainWindow();
189  if (main)
190  KAlarm::writeConfigWindowSize(WINDOW_NAME, main->size());
191  TDEToolBar* tb = toolBar();
192  if (tb)
193  tb->saveSettings(TDEGlobal::config(), "Toolbars");
194  TDEGlobal::config()->sync(); // save any new window size to disc
195  theApp()->quitIf();
196 }
197 
198 /******************************************************************************
199 * Save settings to the session managed config file, for restoration
200 * when the program is restored.
201 */
202 void MainWindow::saveProperties(TDEConfig* config)
203 {
204  config->writeEntry(TQString::fromLatin1("HiddenTrayParent"), isTrayParent() && isHidden());
205  config->writeEntry(TQString::fromLatin1("ShowExpired"), mShowExpired);
206  config->writeEntry(TQString::fromLatin1("ShowTime"), mShowTime);
207  config->writeEntry(TQString::fromLatin1("ShowTimeTo"), mShowTimeTo);
208 }
209 
210 /******************************************************************************
211 * Read settings from the session managed config file.
212 * This function is automatically called whenever the app is being
213 * restored. Read in whatever was saved in saveProperties().
214 */
215 void MainWindow::readProperties(TDEConfig* config)
216 {
217  mHiddenTrayParent = config->readBoolEntry(TQString::fromLatin1("HiddenTrayParent"));
218  mShowExpired = config->readBoolEntry(TQString::fromLatin1("ShowExpired"));
219  mShowTime = config->readBoolEntry(TQString::fromLatin1("ShowTime"));
220  mShowTimeTo = config->readBoolEntry(TQString::fromLatin1("ShowTimeTo"));
221 }
222 
223 /******************************************************************************
224 * Get the main main window, i.e. the parent of the system tray icon, or if
225 * none, the first main window to be created. Visible windows take precedence
226 * over hidden ones.
227 */
228 MainWindow* MainWindow::mainMainWindow()
229 {
230  MainWindow* tray = theApp()->trayWindow() ? theApp()->trayWindow()->assocMainWindow() : 0;
231  if (tray && tray->isVisible())
232  return tray;
233  for (WindowList::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
234  if ((*it)->isVisible())
235  return *it;
236  if (tray)
237  return tray;
238  if (mWindowList.isEmpty())
239  return 0;
240  return mWindowList.first();
241 }
242 
243 /******************************************************************************
244 * Check whether this main window is the parent of the system tray icon.
245 */
246 bool MainWindow::isTrayParent() const
247 {
248  return theApp()->wantRunInSystemTray() && theApp()->trayMainWindow() == this;
249 }
250 
251 /******************************************************************************
252 * Close all main windows.
253 */
254 void MainWindow::closeAll()
255 {
256  while (!mWindowList.isEmpty())
257  delete mWindowList.first(); // N.B. the destructor removes the window from the list
258 }
259 
260 /******************************************************************************
261 * Called when the window's size has changed (before it is painted).
262 * Sets the last column in the list view to extend at least to the right hand
263 * edge of the list view.
264 * Records the new size in the config file.
265 */
266 void MainWindow::resizeEvent(TQResizeEvent* re)
267 {
268  // Save the window's new size only if it's the first main window
269  if (mainMainWindow() == this)
270  KAlarm::writeConfigWindowSize(WINDOW_NAME, re->size());
271  MainWindowBase::resizeEvent(re);
272 }
273 
274 /******************************************************************************
275 * Called when the window is first displayed.
276 * Sets the last column in the list view to extend at least to the right hand
277 * edge of the list view.
278 */
279 void MainWindow::showEvent(TQShowEvent* se)
280 {
281  setUpdateTimer();
282  slotUpdateTimeTo();
283  MainWindowBase::showEvent(se);
284 }
285 
286 /******************************************************************************
287 * Display the window.
288 */
289 void MainWindow::show()
290 {
291  MainWindowBase::show();
292  if (mMenuError)
293  {
294  // Show error message now that the main window has been displayed.
295  // Waiting until now lets the user easily associate the message with
296  // the main window which is faulty.
297  KMessageBox::error(this, i18n("Failure to create menus\n(perhaps %1 missing or corrupted)").arg(TQString::fromLatin1(UI_FILE)));
298  mMenuError = false;
299  }
300 }
301 
302 /******************************************************************************
303 * Called after the window is hidden.
304 */
305 void MainWindow::hideEvent(TQHideEvent* he)
306 {
307  setUpdateTimer();
308  MainWindowBase::hideEvent(he);
309 }
310 
311 /******************************************************************************
312 * Called when the list's column order is changed.
313 * Save the new column order as the default the next time the program is run.
314 */
315 void MainWindow::columnsReordered()
316 {
317  TDEConfig* config = TDEGlobal::config();
318  config->setGroup(TQString::fromLatin1(WINDOW_NAME));
319  config->writeEntry(TQString::fromLatin1("ColumnOrder"), mListView->columnOrder());
320  config->sync();
321 }
322 
323 /******************************************************************************
324 * Initialise the menu, toolbar and main window actions.
325 */
326 void MainWindow::initActions()
327 {
328  TDEActionCollection* actions = actionCollection();
329  mActionTemplates = new TDEAction(i18n("&Templates..."), 0, this, TQ_SLOT(slotTemplates()), actions, "templates");
330  mActionNew = KAlarm::createNewAlarmAction(i18n("&New..."), this, TQ_SLOT(slotNew()), actions, "new");
331  mActionNewFromTemplate = KAlarm::createNewFromTemplateAction(i18n("New &From Template"), this, TQ_SLOT(slotNewFromTemplate(const KAEvent&)), actions, "newFromTempl");
332  mActionCreateTemplate = new TDEAction(i18n("Create Tem&plate..."), 0, this, TQ_SLOT(slotNewTemplate()), actions, "createTemplate");
333  mActionCopy = new TDEAction(i18n("&Copy..."), "edit-copy", TQt::SHIFT+TQt::Key_Insert, this, TQ_SLOT(slotCopy()), actions, "copy");
334  mActionModify = new TDEAction(i18n("&Edit..."), "edit", TQt::CTRL+TQt::Key_E, this, TQ_SLOT(slotModify()), actions, "modify");
335  mActionDelete = new TDEAction(i18n("&Delete"), "edit-delete", TQt::Key_Delete, this, TQ_SLOT(slotDelete()), actions, "delete");
336  mActionReactivate = new TDEAction(i18n("Reac&tivate"), 0, TQt::CTRL+TQt::Key_R, this, TQ_SLOT(slotReactivate()), actions, "undelete");
337  mActionEnable = new TDEAction(TQString(), 0, TQt::CTRL+TQt::Key_B, this, TQ_SLOT(slotEnable()), actions, "disable");
338  mActionView = new TDEAction(i18n("&View"), "viewmag", TQt::CTRL+TQt::Key_W, this, TQ_SLOT(slotView()), actions, "view");
339  mActionShowTime = new TDEToggleAction(i18n_a_ShowAlarmTimes(), TQt::CTRL+TQt::Key_M, this, TQ_SLOT(slotShowTime()), actions, "showAlarmTimes");
340  mActionShowTime->setCheckedState(i18n("Hide &Alarm Times"));
341  mActionShowTimeTo = new TDEToggleAction(i18n_o_ShowTimeToAlarms(), TQt::CTRL+TQt::Key_I, this, TQ_SLOT(slotShowTimeTo()), actions, "showTimeToAlarms");
342  mActionShowTimeTo->setCheckedState(i18n("Hide Time t&o Alarms"));
343  mActionShowExpired = new TDEToggleAction(i18n_e_ShowExpiredAlarms(), "history", TQt::CTRL+TQt::Key_P, this, TQ_SLOT(slotShowExpired()), actions, "showExpiredAlarms");
344  mActionShowExpired->setCheckedState(i18n_e_HideExpiredAlarms());
345  mActionToggleTrayIcon = new TDEToggleAction(i18n("Show in System &Tray"), 0, this, TQ_SLOT(slotToggleTrayIcon()), actions, "showInSystemTray");
346  mActionToggleTrayIcon->setCheckedState(i18n("Hide From System &Tray"));
347  new TDEAction(i18n("Import &Alarms..."), 0, this, TQ_SLOT(slotImportAlarms()), actions, "importAlarms");
348  new TDEAction(i18n("Import &Birthdays..."), 0, this, TQ_SLOT(slotBirthdays()), actions, "importBirthdays");
349  new TDEAction(i18n("&Refresh Alarms"), "reload", 0, this, TQ_SLOT(slotResetDaemon()), actions, "refreshAlarms");
350  Daemon::createAlarmEnableAction(actions, "alarmEnable");
351  if (undoText.isNull())
352  {
353  // Get standard texts, etc., for Undo and Redo actions
354  TDEAction* act = KStdAction::undo(this, 0, actions);
355  undoIcon = act->icon();
356  undoShortcut = act->shortcut();
357  undoText = act->text();
358  undoTextStripped = KAlarm::stripAccel(undoText);
359  delete act;
360  act = KStdAction::redo(this, 0, actions);
361  redoIcon = act->icon();
362  redoShortcut = act->shortcut();
363  redoText = act->text();
364  redoTextStripped = KAlarm::stripAccel(redoText);
365  delete act;
366  }
367  mActionUndo = new TDEToolBarPopupAction(undoText, undoIcon, undoShortcut, this, TQ_SLOT(slotUndo()), actions, "edit_undo");
368  mActionRedo = new TDEToolBarPopupAction(redoText, redoIcon, redoShortcut, this, TQ_SLOT(slotRedo()), actions, "edit_redo");
369  KStdAction::find(mListView, TQ_SLOT(slotFind()), actions);
370  mActionFindNext = KStdAction::findNext(mListView, TQ_SLOT(slotFindNext()), actions);
371  mActionFindPrev = KStdAction::findPrev(mListView, TQ_SLOT(slotFindPrev()), actions);
372  KStdAction::selectAll(mListView, TQ_SLOT(slotSelectAll()), actions);
373  KStdAction::deselect(mListView, TQ_SLOT(slotDeselect()), actions);
374  KStdAction::quit(this, TQ_SLOT(slotQuit()), actions);
375  KStdAction::keyBindings(this, TQ_SLOT(slotConfigureKeys()), actions);
376  KStdAction::configureToolbars(this, TQ_SLOT(slotConfigureToolbar()), actions);
377  KStdAction::preferences(this, TQ_SLOT(slotPreferences()), actions);
378  setStandardToolBarMenuEnabled(true);
379  createGUI(UI_FILE);
380 
381  mContextMenu = static_cast<TDEPopupMenu*>(factory()->container("listContext", this));
382  mActionsMenu = static_cast<TDEPopupMenu*>(factory()->container("actions", this));
383  mMenuError = (!mContextMenu || !mActionsMenu);
384  connect(mActionsMenu, TQ_SIGNAL(aboutToShow()), TQ_SLOT(updateActionsMenu()));
385  connect(mActionUndo->popupMenu(), TQ_SIGNAL(aboutToShow()), TQ_SLOT(slotInitUndoMenu()));
386  connect(mActionUndo->popupMenu(), TQ_SIGNAL(activated(int)), TQ_SLOT(slotUndoItem(int)));
387  connect(mActionRedo->popupMenu(), TQ_SIGNAL(aboutToShow()), TQ_SLOT(slotInitRedoMenu()));
388  connect(mActionRedo->popupMenu(), TQ_SIGNAL(activated(int)), TQ_SLOT(slotRedoItem(int)));
389  connect(Undo::instance(), TQ_SIGNAL(changed(const TQString&, const TQString&)), TQ_SLOT(slotUndoStatus(const TQString&, const TQString&)));
390  connect(mListView, TQ_SIGNAL(findActive(bool)), TQ_SLOT(slotFindActive(bool)));
391  Preferences::connect(TQ_SIGNAL(preferencesChanged()), this, TQ_SLOT(slotPrefsChanged()));
392  connect(theApp(), TQ_SIGNAL(trayIconToggled()), TQ_SLOT(updateTrayIconAction()));
393 
394  // Set menu item states
395  setEnableText(true);
396  mActionShowTime->setChecked(mShowTime);
397  mActionShowTimeTo->setChecked(mShowTimeTo);
398  mActionShowExpired->setChecked(mShowExpired);
399  slotPrefsChanged(); // set the correct text for this action
400  mActionUndo->setEnabled(Undo::haveUndo());
401  mActionRedo->setEnabled(Undo::haveRedo());
402  mActionFindNext->setEnabled(false);
403  mActionFindPrev->setEnabled(false);
404 
405  mActionCopy->setEnabled(false);
406  mActionModify->setEnabled(false);
407  mActionDelete->setEnabled(false);
408  mActionReactivate->setEnabled(false);
409  mActionView->setEnabled(false);
410  mActionEnable->setEnabled(false);
411  mActionCreateTemplate->setEnabled(false);
412 
413  TDEToolBar* tb = toolBar();
414  if (tb)
415  tb->applySettings(TDEGlobal::config(), "Toolbars");
416 
417  Undo::emitChanged(); // set the Undo/Redo menu texts
418  Daemon::checkStatus();
419  Daemon::monitoringAlarms();
420 }
421 
422 /******************************************************************************
423 * Enable or disable the Templates menu item in every main window instance.
424 */
425 void MainWindow::enableTemplateMenuItem(bool enable)
426 {
427  for (WindowList::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
428  (*it)->mActionTemplates->setEnabled(enable);
429 }
430 
431 /******************************************************************************
432 * Refresh the alarm list in every main window instance.
433 */
434 void MainWindow::refresh()
435 {
436  kdDebug(5950) << "MainWindow::refresh()\n";
437  for (WindowList::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
438  (*it)->mListView->refresh();
439 }
440 
441 /******************************************************************************
442 * Refresh the alarm list in every main window instance which is displaying
443 * expired alarms.
444 * Called when an expired alarm setting changes in the user preferences.
445 */
446 void MainWindow::updateExpired()
447 {
448  kdDebug(5950) << "MainWindow::updateExpired()\n";
449  bool enableShowExpired = Preferences::expiredKeepDays();
450  for (WindowList::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
451  {
452  MainWindow* w = *it;
453  if (w->mShowExpired)
454  {
455  if (!enableShowExpired)
456  w->slotShowExpired();
457  else
458  w->mListView->refresh();
459  }
460  w->mActionShowExpired->setEnabled(enableShowExpired);
461  }
462 }
463 
464 /******************************************************************************
465 * Start or stop the timer which updates the time-to-alarm values every minute.
466 * Should be called whenever a main window is created or destroyed, or shown or
467 * hidden.
468 */
469 void MainWindow::setUpdateTimer()
470 {
471  // Check whether any windows need to be updated
472  MainWindow* needTimer = 0;
473  MainWindow* timerWindow = 0;
474  for (WindowList::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
475  {
476  MainWindow* w = *it;
477  if (w->isVisible() && w->mListView->showingTimeTo())
478  needTimer = w;
479  if (w->mMinuteTimerActive)
480  timerWindow = w;
481  }
482 
483  // Start or stop the update timer if necessary
484  if (needTimer && !timerWindow)
485  {
486  // Timeout every minute.
487  needTimer->mMinuteTimerActive = true;
488  MinuteTimer::connect(needTimer, TQ_SLOT(slotUpdateTimeTo()));
489  kdDebug(5950) << "MainWindow::setUpdateTimer(): started timer" << endl;
490  }
491  else if (!needTimer && timerWindow)
492  {
493  timerWindow->mMinuteTimerActive = false;
494  MinuteTimer::disconnect(timerWindow);
495  kdDebug(5950) << "MainWindow::setUpdateTimer(): stopped timer" << endl;
496  }
497 }
498 /******************************************************************************
499 * Update the time-to-alarm values for each main window which is displaying them.
500 */
501 void MainWindow::slotUpdateTimeTo()
502 {
503  kdDebug(5950) << "MainWindow::slotUpdateTimeTo()" << endl;
504  for (WindowList::Iterator it = mWindowList.begin(); it != mWindowList.end(); ++it)
505  {
506  MainWindow* w = *it;
507  if (w->isVisible() && w->mListView->showingTimeTo())
508  w->mListView->updateTimeToAlarms();
509  }
510 }
511 
512 /******************************************************************************
513 * Select an alarm in the displayed list.
514 */
515 void MainWindow::selectEvent(const TQString& eventID)
516 {
517  mListView->clearSelection();
518  AlarmListViewItem* item = mListView->getEntry(eventID);
519  if (item)
520  {
521  mListView->setSelected(item, true);
522  mListView->setCurrentItem(item);
523  mListView->ensureItemVisible(item);
524  }
525 }
526 
527 /******************************************************************************
528 * Called when the New button is clicked to edit a new alarm to add to the list.
529 */
530 void MainWindow::slotNew()
531 {
532  executeNew(this);
533 }
534 
535 /******************************************************************************
536 * Execute a New Alarm dialog, optionally either presetting it to the supplied
537 * event, or setting the action and text.
538 */
539 void MainWindow::executeNew(MainWindow* win, const KAEvent* evnt, KAEvent::Action action, const AlarmText& text)
540 {
541  EditAlarmDlg editDlg(false, i18n("New Alarm"), win, 0, evnt);
542  if (!text.isEmpty())
543  editDlg.setAction(action, text);
544  if (editDlg.exec() == TQDialog::Accepted)
545  {
546  KAEvent event;
547  editDlg.getEvent(event);
548 
549  // Add the alarm to the displayed lists and to the calendar file
550  if (KAlarm::addEvent(event, (win ? win->mListView : 0), &editDlg) == KAlarm::UPDATE_KORG_ERR)
551  KAlarm::displayKOrgUpdateError(&editDlg, KAlarm::KORG_ERR_ADD, 1);
552  Undo::saveAdd(event);
553 
554  KAlarm::outputAlarmWarnings(&editDlg, &event);
555  }
556 }
557 
558 /******************************************************************************
559 * Called when a template is selected from the New From Template popup menu.
560 * Executes a New Alarm dialog, preset from the selected template.
561 */
562 void MainWindow::slotNewFromTemplate(const KAEvent& tmplate)
563 {
564  executeNew(this, &tmplate);
565 }
566 
567 /******************************************************************************
568 * Called when the New Template button is clicked to create a new template
569 * based on the currently selected alarm.
570 */
571 void MainWindow::slotNewTemplate()
572 {
573  AlarmListViewItem* item = mListView->selectedItem();
574  if (item)
575  {
576  KAEvent event = item->event();
577  TemplateDlg::createTemplate(&event, this);
578  }
579 }
580 
581 /******************************************************************************
582 * Called when the Copy button is clicked to edit a copy of an existing alarm,
583 * to add to the list.
584 */
585 void MainWindow::slotCopy()
586 {
587  AlarmListViewItem* item = mListView->selectedItem();
588  if (item)
589  executeNew(this, &item->event());
590 }
591 
592 /******************************************************************************
593 * Called when the Modify button is clicked to edit the currently highlighted
594 * alarm in the list.
595 */
596 void MainWindow::slotModify()
597 {
598  AlarmListViewItem* item = mListView->selectedItem();
599  if (item)
600  {
601  KAEvent event = item->event();
602  executeEdit(event, this);
603  }
604 }
605 
606 /******************************************************************************
607 * Open the Edit Alarm dialogue to edit the specified alarm.
608 */
609 void MainWindow::executeEdit(KAEvent& event, MainWindow* win)
610 {
611  EditAlarmDlg editDlg(false, i18n("Edit Alarm"), win, 0, &event);
612  if (editDlg.exec() == TQDialog::Accepted)
613  {
614  KAEvent newEvent;
615  bool changeDeferral = !editDlg.getEvent(newEvent);
616 
617  // Update the event in the displays and in the calendar file
618  AlarmListView* view = win ? win->mListView : 0;
619  if (changeDeferral)
620  {
621  // The only change has been to an existing deferral
622  if (KAlarm::updateEvent(newEvent, view, &editDlg, true, false) != KAlarm::UPDATE_OK) // keep the same event ID
623  return; // failed to save event
624  }
625  else
626  {
627  if (KAlarm::modifyEvent(event, newEvent, view, &editDlg) == KAlarm::UPDATE_KORG_ERR)
628  KAlarm::displayKOrgUpdateError(&editDlg, KAlarm::KORG_ERR_MODIFY, 1);
629  }
630  Undo::saveEdit(event, newEvent);
631 
632  KAlarm::outputAlarmWarnings(&editDlg, &newEvent);
633  }
634 }
635 
636 /******************************************************************************
637 * Called when the View button is clicked to view the currently highlighted
638 * alarm in the list.
639 */
640 void MainWindow::slotView()
641 {
642  AlarmListViewItem* item = mListView->selectedItem();
643  if (item)
644  {
645  KAEvent event = item->event();
646  EditAlarmDlg editDlg(false, (event.expired() ? i18n("Expired Alarm") + " [" + i18n("read-only") + ']'
647  : i18n("View Alarm")),
648  this, 0, &event, true);
649  editDlg.exec();
650  }
651 }
652 
653 /******************************************************************************
654 * Called when the Delete button is clicked to delete the currently highlighted
655 * alarms in the list.
656 */
657 void MainWindow::slotDelete()
658 {
659  TQValueList<EventListViewItemBase*> items = mListView->selectedItems();
660  // Copy the events to be deleted, in case any are deleted by being
661  // triggered while the confirmation prompt is displayed.
662  TQValueList<KAEvent> events;
663  TQValueList<KAEvent> origEvents;
664  for (TQValueList<EventListViewItemBase*>::Iterator iit = items.begin(); iit != items.end(); ++iit)
665  {
666  AlarmListViewItem* item = (AlarmListViewItem*)(*iit);
667  events.append(item->event());
668  origEvents.append(item->event());
669  }
670  if (Preferences::confirmAlarmDeletion())
671  {
672  int n = items.count();
673  if (KMessageBox::warningContinueCancel(this, i18n("Do you really want to delete the selected alarm?",
674  "Do you really want to delete the %n selected alarms?", n),
675  i18n("Delete Alarm", "Delete Alarms", n),
676  KGuiItem(i18n("&Delete"), "edit-delete"),
677  Preferences::CONFIRM_ALARM_DELETION)
678  != KMessageBox::Continue)
679  return;
680  }
681 
682  int warnErr = 0;
683  int warnKOrg = 0;
684  AlarmCalendar::activeCalendar()->startUpdate(); // prevent multiple saves of the calendars until we're finished
685  AlarmCalendar::expiredCalendar()->startUpdate();
686  for (TQValueList<KAEvent>::Iterator it = events.begin(); it != events.end(); ++it)
687  {
688  // Delete the event from the calendar and displays
689  switch (KAlarm::deleteEvent(*it))
690  {
691  case KAlarm::UPDATE_ERROR:
692  case KAlarm::UPDATE_FAILED:
693  case KAlarm::SAVE_FAILED:
694  ++warnErr;
695  break;
696  case KAlarm::UPDATE_KORG_ERR:
697  ++warnKOrg;
698  break;
699  default:
700  break;
701  }
702  }
703  if (!AlarmCalendar::activeCalendar()->endUpdate()) // save the calendars now
704  warnErr = events.count();
705  AlarmCalendar::expiredCalendar()->endUpdate();
706  Undo::saveDeletes(origEvents);
707 
708  if (warnErr)
709  KAlarm::displayUpdateError(this, KAlarm::UPDATE_FAILED, KAlarm::ERR_DELETE, warnErr);
710  else if (warnKOrg)
711  KAlarm::displayKOrgUpdateError(this, KAlarm::KORG_ERR_DELETE, warnKOrg);
712 }
713 
714 /******************************************************************************
715 * Called when the Reactivate button is clicked to reinstate the currently
716 * highlighted expired alarms in the list.
717 */
718 void MainWindow::slotReactivate()
719 {
720  int warnErr = 0;
721  int warnKOrg = 0;
722  TQValueList<KAEvent> events;
723  TQValueList<EventListViewItemBase*> items = mListView->selectedItems();
724  mListView->clearSelection();
725  AlarmCalendar::activeCalendar()->startUpdate(); // prevent multiple saves of the calendars until we're finished
726  AlarmCalendar::expiredCalendar()->startUpdate();
727  for (TQValueList<EventListViewItemBase*>::Iterator it = items.begin(); it != items.end(); ++it)
728  {
729  // Add the alarm to the displayed lists and to the calendar file
730  AlarmListViewItem* item = (AlarmListViewItem*)(*it);
731  KAEvent event = item->event();
732  events.append(event);
733  switch (KAlarm::reactivateEvent(event, mListView, true))
734  {
735  case KAlarm::UPDATE_ERROR:
736  case KAlarm::UPDATE_FAILED:
737  case KAlarm::SAVE_FAILED:
738  ++warnErr;
739  break;
740  case KAlarm::UPDATE_KORG_ERR:
741  ++warnKOrg;
742  break;
743  default:
744  break;
745  }
746  }
747  if (!AlarmCalendar::activeCalendar()->endUpdate()) // save the calendars now
748  warnErr = items.count();
749  AlarmCalendar::expiredCalendar()->endUpdate();
750  Undo::saveReactivates(events);
751 
752  if (warnErr)
753  KAlarm::displayUpdateError(this, KAlarm::UPDATE_FAILED, KAlarm::ERR_REACTIVATE, warnErr);
754  else if (warnKOrg)
755  KAlarm::displayKOrgUpdateError(this, KAlarm::KORG_ERR_ADD, warnKOrg);
756 }
757 
758 /******************************************************************************
759 * Called when the Enable/Disable button is clicked to enable or disable the
760 * currently highlighted alarms in the list.
761 */
762 void MainWindow::slotEnable()
763 {
764  bool enable = mActionEnableEnable; // save since changed in response to KAlarm::enableEvent()
765  int warnErr = 0;
766  TQValueList<EventListViewItemBase*> items = mListView->selectedItems();
767  AlarmCalendar::activeCalendar()->startUpdate(); // prevent multiple saves of the calendars until we're finished
768  for (TQValueList<EventListViewItemBase*>::Iterator it = items.begin(); it != items.end(); ++it)
769  {
770  AlarmListViewItem* item = (AlarmListViewItem*)(*it);
771  KAEvent event = item->event();
772 
773  // Enable the alarm in the displayed lists and in the calendar file
774  if (KAlarm::enableEvent(event, mListView, enable) != KAlarm::UPDATE_OK)
775  ++warnErr;
776  }
777  if (!AlarmCalendar::activeCalendar()->endUpdate()) // save the calendars now
778  warnErr = items.count();
779  if (warnErr)
780  KAlarm::displayUpdateError(this, KAlarm::UPDATE_FAILED, KAlarm::ERR_ADD, warnErr);
781 }
782 
783 /******************************************************************************
784 * Called when the Show Alarm Times menu item is selected or deselected.
785 */
786 void MainWindow::slotShowTime()
787 {
788  mShowTime = !mShowTime;
789  mActionShowTime->setChecked(mShowTime);
790  if (!mShowTime && !mShowTimeTo)
791  slotShowTimeTo(); // at least one time column must be displayed
792  else
793  {
794  mListView->selectTimeColumns(mShowTime, mShowTimeTo);
795  TDEConfig* config = TDEGlobal::config();
796  config->setGroup(VIEW_GROUP);
797  config->writeEntry(SHOW_TIME_KEY, mShowTime);
798  config->writeEntry(SHOW_TIME_TO_KEY, mShowTimeTo);
799  }
800 }
801 
802 /******************************************************************************
803 * Called when the Show Time To Alarms menu item is selected or deselected.
804 */
805 void MainWindow::slotShowTimeTo()
806 {
807  mShowTimeTo = !mShowTimeTo;
808  mActionShowTimeTo->setChecked(mShowTimeTo);
809  if (!mShowTimeTo && !mShowTime)
810  slotShowTime(); // at least one time column must be displayed
811  else
812  {
813  mListView->selectTimeColumns(mShowTime, mShowTimeTo);
814  TDEConfig* config = TDEGlobal::config();
815  config->setGroup(VIEW_GROUP);
816  config->writeEntry(SHOW_TIME_KEY, mShowTime);
817  config->writeEntry(SHOW_TIME_TO_KEY, mShowTimeTo);
818  }
819  setUpdateTimer();
820 }
821 
822 /******************************************************************************
823 * Called when the Show Expired Alarms menu item is selected or deselected.
824 */
825 void MainWindow::slotShowExpired()
826 {
827  mShowExpired = !mShowExpired;
828  mActionShowExpired->setChecked(mShowExpired);
829  mActionShowExpired->setToolTip(mShowExpired ? i18n_HideExpiredAlarms() : i18n_ShowExpiredAlarms());
830  mListView->showExpired(mShowExpired);
831  mListView->refresh();
832  TDEConfig* config = TDEGlobal::config();
833  config->setGroup(VIEW_GROUP);
834  config->writeEntry(SHOW_ARCHIVED_KEY, mShowExpired);
835 }
836 
837 /******************************************************************************
838 * Called when the Import Alarms menu item is selected, to merge alarms from an
839 * external calendar into the current calendars.
840 */
841 void MainWindow::slotImportAlarms()
842 {
843  if (AlarmCalendar::importAlarms(this))
844  mListView->refresh();
845 }
846 
847 /******************************************************************************
848 * Called when the Import Birthdays menu item is selected, to display birthdays
849 * from the address book for selection as alarms.
850 */
851 void MainWindow::slotBirthdays()
852 {
853  BirthdayDlg dlg(this);
854  if (dlg.exec() == TQDialog::Accepted)
855  {
856  TQValueList<KAEvent> events = dlg.events();
857  if (events.count())
858  {
859  mListView->clearSelection();
860  int warnErr = 0;
861  int warnKOrg = 0;
862  for (TQValueList<KAEvent>::Iterator ev = events.begin(); ev != events.end(); ++ev)
863  {
864  // Add alarm to the displayed lists and to the calendar file
865  switch (KAlarm::addEvent(*ev, mListView))
866  {
867  case KAlarm::UPDATE_ERROR:
868  case KAlarm::UPDATE_FAILED:
869  case KAlarm::SAVE_FAILED:
870  ++warnErr;
871  break;
872  case KAlarm::UPDATE_KORG_ERR:
873  ++warnKOrg;
874  break;
875  default:
876  break;
877  }
878  }
879  if (warnErr)
880  KAlarm::displayUpdateError(this, KAlarm::UPDATE_FAILED, KAlarm::ERR_ADD, warnErr);
881  else if (warnKOrg)
882  KAlarm::displayKOrgUpdateError(this, KAlarm::KORG_ERR_ADD, warnKOrg);
883  KAlarm::outputAlarmWarnings(&dlg);
884  }
885  }
886 }
887 
888 /******************************************************************************
889 * Called when the Templates menu item is selected, to display the alarm
890 * template editing dialogue.
891 */
892 void MainWindow::slotTemplates()
893 {
894  if (!mTemplateDlg)
895  {
896  mTemplateDlg = TemplateDlg::create(this);
897  enableTemplateMenuItem(false); // disable menu item in all windows
898  connect(mTemplateDlg, TQ_SIGNAL(finished()), TQ_SLOT(slotTemplatesEnd()));
899  mTemplateDlg->show();
900  }
901 }
902 
903 /******************************************************************************
904 * Called when the alarm template editing dialogue has exited.
905 */
906 void MainWindow::slotTemplatesEnd()
907 {
908  if (mTemplateDlg)
909  {
910  mTemplateDlg->delayedDestruct(); // this deletes the dialogue once it is safe to do so
911  mTemplateDlg = 0;
912  enableTemplateMenuItem(true); // re-enable menu item in all windows
913  }
914 }
915 
916 /******************************************************************************
917 * Called when the Display System Tray Icon menu item is selected.
918 */
919 void MainWindow::slotToggleTrayIcon()
920 {
921  theApp()->displayTrayIcon(!theApp()->trayIconDisplayed(), this);
922 }
923 
924 /******************************************************************************
925 * Called when the user preferences have changed.
926 */
927 void MainWindow::slotPrefsChanged()
928 {
929  mActionShowExpired->setEnabled(Preferences::expiredKeepDays());
930  updateTrayIconAction();
931 }
932 
933 /******************************************************************************
934 * Called when the system tray icon is created or destroyed.
935 * Set the system tray icon menu text according to whether or not the system
936 * tray icon is currently visible.
937 */
938 void MainWindow::updateTrayIconAction()
939 {
940  mActionToggleTrayIcon->setEnabled(theApp()->haveSystemTray() && !theApp()->wantRunInSystemTray());
941  mActionToggleTrayIcon->setChecked(theApp()->trayIconDisplayed());
942 }
943 
944 /******************************************************************************
945 * Called when the Actions menu is about to be displayed.
946 * Update the status of the Alarms Enabled menu item.
947 */
948 void MainWindow::updateActionsMenu()
949 {
950  Daemon::checkStatus(); // update the Alarms Enabled item status
951 }
952 
953 /******************************************************************************
954 * Called when the active status of Find changes.
955 */
956 void MainWindow::slotFindActive(bool active)
957 {
958  mActionFindNext->setEnabled(active);
959  mActionFindPrev->setEnabled(active);
960 }
961 
962 /******************************************************************************
963 * Called when the Undo action is selected.
964 */
965 void MainWindow::slotUndo()
966 {
967  Undo::undo(this, KAlarm::stripAccel(mActionUndo->text()));
968 }
969 
970 /******************************************************************************
971 * Called when the Redo action is selected.
972 */
973 void MainWindow::slotRedo()
974 {
975  Undo::redo(this, KAlarm::stripAccel(mActionRedo->text()));
976 }
977 
978 /******************************************************************************
979 * Called when an Undo item is selected.
980 */
981 void MainWindow::slotUndoItem(int id)
982 {
983  Undo::undo(id, this, Undo::actionText(Undo::UNDO, id));
984 }
985 
986 /******************************************************************************
987 * Called when a Redo item is selected.
988 */
989 void MainWindow::slotRedoItem(int id)
990 {
991  Undo::redo(id, this, Undo::actionText(Undo::REDO, id));
992 }
993 
994 /******************************************************************************
995 * Called when the Undo menu is about to show.
996 * Populates the menu.
997 */
998 void MainWindow::slotInitUndoMenu()
999 {
1000  initUndoMenu(mActionUndo->popupMenu(), Undo::UNDO);
1001 }
1002 
1003 /******************************************************************************
1004 * Called when the Redo menu is about to show.
1005 * Populates the menu.
1006 */
1007 void MainWindow::slotInitRedoMenu()
1008 {
1009  initUndoMenu(mActionRedo->popupMenu(), Undo::REDO);
1010 }
1011 
1012 /******************************************************************************
1013 * Populate the undo or redo menu.
1014 */
1015 void MainWindow::initUndoMenu(TDEPopupMenu* menu, Undo::Type type)
1016 {
1017  menu->clear();
1018  const TQString& action = (type == Undo::UNDO) ? undoTextStripped : redoTextStripped;
1019  TQValueList<int> ids = Undo::ids(type);
1020  for (TQValueList<int>::ConstIterator it = ids.begin(); it != ids.end(); ++it)
1021  {
1022  int id = *it;
1023  TQString actText = Undo::actionText(type, id);
1024  TQString descrip = Undo::description(type, id);
1025  TQString text = descrip.isEmpty()
1026  ? i18n("Undo/Redo [action]", "%1 %2").arg(action).arg(actText)
1027  : i18n("Undo [action]: message", "%1 %2: %3").arg(action).arg(actText).arg(descrip);
1028  menu->insertItem(text, id);
1029  }
1030 }
1031 
1032 /******************************************************************************
1033 * Called when the status of the Undo or Redo list changes.
1034 * Change the Undo or Redo text to include the action which would be undone/redone.
1035 */
1036 void MainWindow::slotUndoStatus(const TQString& undo, const TQString& redo)
1037 {
1038  if (undo.isNull())
1039  {
1040  mActionUndo->setEnabled(false);
1041  mActionUndo->setText(undoText);
1042  }
1043  else
1044  {
1045  mActionUndo->setEnabled(true);
1046  mActionUndo->setText(TQString("%1 %2").arg(undoText).arg(undo));
1047  }
1048  if (redo.isNull())
1049  {
1050  mActionRedo->setEnabled(false);
1051  mActionRedo->setText(redoText);
1052  }
1053  else
1054  {
1055  mActionRedo->setEnabled(true);
1056  mActionRedo->setText(TQString("%1 %2").arg(redoText).arg(redo));
1057  }
1058 }
1059 
1060 /******************************************************************************
1061 * Called when the Reset Daemon menu item is selected.
1062 */
1063 void MainWindow::slotResetDaemon()
1064 {
1065  KAlarm::resetDaemon();
1066 }
1067 
1068 /******************************************************************************
1069 * Called when the "Configure KAlarm" menu item is selected.
1070 */
1071 void MainWindow::slotPreferences()
1072 {
1073  KAlarmPrefDlg::display();
1074 }
1075 
1076 /******************************************************************************
1077 * Called when the Configure Keys menu item is selected.
1078 */
1079 void MainWindow::slotConfigureKeys()
1080 {
1081  KKeyDialog::configure(actionCollection(), this);
1082 }
1083 
1084 /******************************************************************************
1085 * Called when the Configure Toolbars menu item is selected.
1086 */
1087 void MainWindow::slotConfigureToolbar()
1088 {
1089  saveMainWindowSettings(TDEGlobal::config(), WINDOW_NAME);
1090  KEditToolbar dlg(factory());
1091  connect(&dlg, TQ_SIGNAL(newToolbarConfig()), this, TQ_SLOT(slotNewToolbarConfig()));
1092  dlg.exec();
1093 }
1094 
1095 /******************************************************************************
1096 * Called when OK or Apply is clicked in the Configure Toolbars dialog, to save
1097 * the new configuration.
1098 */
1099 void MainWindow::slotNewToolbarConfig()
1100 {
1101  createGUI(UI_FILE);
1102  applyMainWindowSettings(TDEGlobal::config(), WINDOW_NAME);
1103 }
1104 
1105 /******************************************************************************
1106 * Called when the Quit menu item is selected.
1107 */
1108 void MainWindow::slotQuit()
1109 {
1110  theApp()->doQuit(this);
1111 }
1112 
1113 /******************************************************************************
1114 * Called when the user or the session manager attempts to close the window.
1115 */
1116 void MainWindow::closeEvent(TQCloseEvent* ce)
1117 {
1118  if (!theApp()->sessionClosingDown() && isTrayParent())
1119  {
1120  // The user (not the session manager) wants to close the window.
1121  // It's the parent window of the system tray icon, so just hide
1122  // it to prevent the system tray icon closing.
1123  hide();
1124  theApp()->quitIf();
1125  ce->ignore();
1126  }
1127  else
1128  ce->accept();
1129 }
1130 
1131 /******************************************************************************
1132 * Called when an item is deleted from the ListView.
1133 * Disables the actions if no item is still selected.
1134 */
1135 void MainWindow::slotDeletion()
1136 {
1137  if (!mListView->selectedCount())
1138  {
1139  kdDebug(5950) << "MainWindow::slotDeletion(true)\n";
1140  mActionCreateTemplate->setEnabled(false);
1141  mActionCopy->setEnabled(false);
1142  mActionModify->setEnabled(false);
1143  mActionView->setEnabled(false);
1144  mActionDelete->setEnabled(false);
1145  mActionReactivate->setEnabled(false);
1146  mActionEnable->setEnabled(false);
1147  }
1148 }
1149 
1150 /******************************************************************************
1151 * Called when the drag cursor enters the window.
1152 */
1153 void MainWindow::dragEnterEvent(TQDragEnterEvent* e)
1154 {
1155  executeDragEnterEvent(e);
1156 }
1157 
1158 /******************************************************************************
1159 * Called when the drag cursor enters a main or system tray window, to accept
1160 * or reject the dragged object.
1161 */
1162 void MainWindow::executeDragEnterEvent(TQDragEnterEvent* e)
1163 {
1165  e->accept(!AlarmListView::dragging()); // don't accept "text/calendar" objects from KAlarm
1166  else
1167  e->accept(TQTextDrag::canDecode(e)
1168  || KURLDrag::canDecode(e)
1169  || KPIM::MailListDrag::canDecode(e));
1170 }
1171 
1172 /******************************************************************************
1173 * Called when an object is dropped on the window.
1174 * If the object is recognised, the edit alarm dialog is opened appropriately.
1175 */
1176 void MainWindow::dropEvent(TQDropEvent* e)
1177 {
1178  executeDropEvent(this, e);
1179 }
1180 
1181 static TQString getMailHeader(const char* header, KMime::Content& content)
1182 {
1183  KMime::Headers::Base* hd = content.getHeaderByType(header);
1184  return hd ? hd->asUnicodeString() : TQString();
1185 }
1186 
1187 /******************************************************************************
1188 * Called when an object is dropped on a main or system tray window, to
1189 * evaluate the action required and extract the text.
1190 */
1191 void MainWindow::executeDropEvent(MainWindow* win, TQDropEvent* e)
1192 {
1193  KAEvent::Action action = KAEvent::MESSAGE;
1194  TQString text;
1195  TQByteArray bytes;
1196  AlarmText alarmText;
1197  KPIM::MailList mailList;
1198  KURL::List files;
1199  KCal::CalendarLocal calendar(TQString::fromLatin1("UTC"));
1200  calendar.setLocalTime(); // default to local time (i.e. no time zone)
1201 #ifndef NDEBUG
1202  TQCString fmts;
1203  for (int idbg = 0; e->format(idbg); ++idbg)
1204  {
1205  if (idbg) fmts += ", ";
1206  fmts += e->format(idbg);
1207  }
1208  kdDebug(5950) << "MainWindow::executeDropEvent(): " << fmts << endl;
1209 #endif
1210 
1211  /* The order of the tests below matters, since some dropped objects
1212  * provide more than one mime type.
1213  * Don't change them without careful thought !!
1214  */
1215  if (e->provides("message/rfc822")
1216  && !(bytes = e->encodedData("message/rfc822")).isEmpty())
1217  {
1218  // Email message(s). Ignore all but the first.
1219  kdDebug(5950) << "MainWindow::executeDropEvent(email)" << endl;
1220  TQCString mails(bytes.data(), bytes.size());
1221  KMime::Content content;
1222  content.setContent(mails);
1223  content.parse();
1224  TQString body;
1225  if (content.textContent())
1226  content.textContent()->decodedText(body, true, true); // strip trailing newlines & spaces
1227  unsigned long sernum = 0;
1228  if (e->provides(KPIM::MailListDrag::format())
1229  && KPIM::MailListDrag::decode(e, mailList)
1230  && mailList.count())
1231  {
1232  // Get its KMail serial number to allow the KMail message
1233  // to be called up from the alarm message window.
1234  sernum = mailList.first().serialNumber();
1235  }
1236  alarmText.setEmail(getMailHeader("To", content),
1237  getMailHeader("From", content),
1238  getMailHeader("Cc", content),
1239  getMailHeader("Date", content),
1240  getMailHeader("Subject", content),
1241  body, sernum);
1242  }
1243  else if (KURLDrag::decode(e, files) && files.count())
1244  {
1245  kdDebug(5950) << "MainWindow::executeDropEvent(URL)" << endl;
1246  action = KAEvent::FILE;
1247  alarmText.setText(files.first().prettyURL());
1248  }
1249  else if (e->provides(KPIM::MailListDrag::format())
1250  && KPIM::MailListDrag::decode(e, mailList))
1251  {
1252  // KMail message(s). Ignore all but the first.
1253  kdDebug(5950) << "MainWindow::executeDropEvent(KMail_list)" << endl;
1254  if (!mailList.count())
1255  return;
1256  KPIM::MailSummary& summary = mailList.first();
1257  TQDateTime dt;
1258  dt.setTime_t(summary.date());
1259  TQString body = KAMail::getMailBody(summary.serialNumber());
1260  alarmText.setEmail(summary.to(), summary.from(), TQString(),
1261  TDEGlobal::locale()->formatDateTime(dt), summary.subject(),
1262  body, summary.serialNumber());
1263  }
1264  else if (KCal::ICalDrag::decode(e, &calendar))
1265  {
1266  // iCalendar - ignore all but the first event
1267  kdDebug(5950) << "MainWindow::executeDropEvent(iCalendar)" << endl;
1268  KCal::Event::List events = calendar.rawEvents();
1269  if (!events.isEmpty())
1270  {
1271  KAEvent ev(*events.first());
1272  executeNew(win, &ev);
1273  }
1274  return;
1275  }
1276  else if (TQTextDrag::decode(e, text))
1277  {
1278  kdDebug(5950) << "MainWindow::executeDropEvent(text)" << endl;
1279  alarmText.setText(text);
1280  }
1281  else
1282  return;
1283 
1284  if (!alarmText.isEmpty())
1285  executeNew(win, 0, action, alarmText);
1286 }
1287 
1288 /******************************************************************************
1289 * Called when the selected items in the ListView changes.
1290 * Selects the new current item, and enables the actions appropriately.
1291 */
1292 void MainWindow::slotSelection()
1293 {
1294  // Find which item has been selected, and whether more than one is selected
1295  TQValueList<EventListViewItemBase*> items = mListView->selectedItems();
1296  int count = items.count();
1297  AlarmListViewItem* item = (AlarmListViewItem*)((count == 1) ? items.first() : 0);
1298  bool enableReactivate = true;
1299  bool enableEnableDisable = true;
1300  bool enableEnable = false;
1301  bool enableDisable = false;
1302  TQDateTime now = TQDateTime::currentDateTime();
1303  for (TQValueList<EventListViewItemBase*>::Iterator it = items.begin(); it != items.end(); ++it)
1304  {
1305  const KAEvent& event = ((AlarmListViewItem*)(*it))->event();
1306  if (enableReactivate
1307  && (!event.expired() || !event.occursAfter(now, true)))
1308  enableReactivate = false;
1309  if (enableEnableDisable)
1310  {
1311  if (event.expired())
1312  enableEnableDisable = enableEnable = enableDisable = false;
1313  else
1314  {
1315  if (!enableEnable && !event.enabled())
1316  enableEnable = true;
1317  if (!enableDisable && event.enabled())
1318  enableDisable = true;
1319  }
1320  }
1321  }
1322 
1323  kdDebug(5950) << "MainWindow::slotSelection(true)\n";
1324  mActionCreateTemplate->setEnabled(count == 1);
1325  mActionCopy->setEnabled(count == 1);
1326  mActionModify->setEnabled(item && !mListView->expired(item));
1327  mActionView->setEnabled(count == 1);
1328  mActionDelete->setEnabled(count);
1329  mActionReactivate->setEnabled(count && enableReactivate);
1330  mActionEnable->setEnabled(enableEnable || enableDisable);
1331  if (enableEnable || enableDisable)
1332  setEnableText(enableEnable);
1333 }
1334 
1335 /******************************************************************************
1336 * Called when a context menu is requested either by a mouse click or by a
1337 * key press.
1338 */
1339 void MainWindow::slotContextMenuRequested(TQListViewItem* item, const TQPoint& pt, int)
1340 {
1341  kdDebug(5950) << "MainWindow::slotContextMenuRequested()" << endl;
1342  if (mContextMenu)
1343  mContextMenu->popup(pt);
1344 }
1345 
1346 /******************************************************************************
1347 * Called when the mouse is clicked on the ListView.
1348 * Deselects the current item and disables the actions if appropriate.
1349 * Note that if a right button click is handled by slotContextMenuRequested().
1350 */
1351 void MainWindow::slotMouseClicked(int button, TQListViewItem* item, const TQPoint& pt, int)
1352 {
1353  if (button != TQt::RightButton && !item)
1354  {
1355  kdDebug(5950) << "MainWindow::slotMouseClicked(left)" << endl;
1356  mListView->clearSelection();
1357  mActionCreateTemplate->setEnabled(false);
1358  mActionCopy->setEnabled(false);
1359  mActionModify->setEnabled(false);
1360  mActionView->setEnabled(false);
1361  mActionDelete->setEnabled(false);
1362  mActionReactivate->setEnabled(false);
1363  mActionEnable->setEnabled(false);
1364  }
1365 }
1366 
1367 /******************************************************************************
1368 * Called when the mouse is double clicked on the ListView.
1369 * Displays the Edit Alarm dialog, for the clicked item if applicable.
1370 */
1371 void MainWindow::slotDoubleClicked(TQListViewItem* item)
1372 {
1373  kdDebug(5950) << "MainWindow::slotDoubleClicked()\n";
1374  if (item)
1375  {
1376  if (mListView->expired((AlarmListViewItem*)item))
1377  slotView();
1378  else
1379  slotModify();
1380  }
1381  else
1382  slotNew();
1383 }
1384 
1385 /******************************************************************************
1386 * Set the text of the Enable/Disable menu action.
1387 */
1388 void MainWindow::setEnableText(bool enable)
1389 {
1390  mActionEnableEnable = enable;
1391  mActionEnable->setText(enable ? i18n("Ena&ble") : i18n("Disa&ble"));
1392 }
1393 
1394 /******************************************************************************
1395 * Display or hide the specified main window.
1396 * This should only be called when the application doesn't run in the system tray.
1397 */
1398 MainWindow* MainWindow::toggleWindow(MainWindow* win)
1399 {
1400  if (win && mWindowList.find(win) != mWindowList.end())
1401  {
1402  // A window is specified (and it exists)
1403  if (win->isVisible())
1404  {
1405  // The window is visible, so close it
1406  win->close();
1407  return 0;
1408  }
1409  else
1410  {
1411  // The window is hidden, so display it
1412  win->hide(); // in case it's on a different desktop
1413  win->showNormal();
1414  win->raise();
1415  win->setActiveWindow();
1416  return win;
1417  }
1418  }
1419 
1420  // No window is specified, or the window doesn't exist. Open a new one.
1421  win = create();
1422  win->show();
1423  return win;
1424 }
represents calendar alarms and events
KAEvent corresponds to a KCal::Event instance.
Definition: alarmevent.h:232
static bool canDecode(TQMimeSource *)
static bool decode(TQMimeSource *e, Calendar *cal)
The MainWindowBase class is a base class for KAlarm's main window and message window.
miscellaneous functions
the KAlarm application object
bool view(TQWidget *parent, Attachment *attachment)