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
69using namespace KCal;
70
71static const char* UI_FILE = "kalarmui.rc";
72static const char* WINDOW_NAME = "MainWindow";
73
74static const TQString VIEW_GROUP = TQString::fromLatin1("View");
75static const TQString SHOW_TIME_KEY = TQString::fromLatin1("ShowAlarmTime");
76static const TQString SHOW_TIME_TO_KEY = TQString::fromLatin1("ShowTimeToAlarm");
77static const TQString SHOW_ARCHIVED_KEY = TQString::fromLatin1("ShowArchivedAlarms");
78static const TQString SHOW_RESOURCES_KEY = TQString::fromLatin1("ShowResources");
79
80static TQString undoText;
81static TQString undoTextStripped;
82static TQString undoIcon;
83static TDEShortcut undoShortcut;
84static TQString redoText;
85static TQString redoTextStripped;
86static TQString redoIcon;
87static TDEShortcut redoShortcut;
88
89
90/*=============================================================================
91= Class: MainWindow
92=============================================================================*/
93
94MainWindow::WindowList MainWindow::mWindowList;
95TemplateDlg* MainWindow::mTemplateDlg = 0;
96
97// Collect these widget labels together to ensure consistent wording and
98// translations across different modules.
99TQString MainWindow::i18n_a_ShowAlarmTimes() { return i18n("Show &Alarm Times"); }
100TQString MainWindow::i18n_m_ShowAlarmTime() { return i18n("Show alarm ti&me"); }
101TQString MainWindow::i18n_o_ShowTimeToAlarms() { return i18n("Show Time t&o Alarms"); }
102TQString MainWindow::i18n_l_ShowTimeToAlarm() { return i18n("Show time unti&l alarm"); }
103TQString MainWindow::i18n_ShowExpiredAlarms() { return i18n("Show Expired Alarms"); }
104TQString MainWindow::i18n_e_ShowExpiredAlarms() { return i18n("Show &Expired Alarms"); }
105TQString MainWindow::i18n_HideExpiredAlarms() { return i18n("Hide Expired Alarms"); }
106TQString 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*/
114MainWindow* MainWindow::create(bool restored)
115{
116 theApp()->checkCalendarDaemon(); // ensure calendar is open and daemon started
117 return new MainWindow(restored);
118}
119
120MainWindow::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(tdeApp->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
174MainWindow::~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*/
202void 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*/
215void 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*/
228MainWindow* 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*/
246bool MainWindow::isTrayParent() const
247{
248 return theApp()->wantRunInSystemTray() && theApp()->trayMainWindow() == this;
249}
250
251/******************************************************************************
252* Close all main windows.
253*/
254void 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*/
266void 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*/
279void MainWindow::showEvent(TQShowEvent* se)
280{
281 setUpdateTimer();
282 slotUpdateTimeTo();
283 MainWindowBase::showEvent(se);
284}
285
286/******************************************************************************
287* Display the window.
288*/
289void 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*/
305void 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*/
315void 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*/
326void 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*/
425void 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*/
434void 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*/
446void 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*/
469void 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*/
501void 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*/
515void 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*/
530void 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*/
539void 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*/
562void 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*/
571void 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*/
585void 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*/
596void 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*/
609void 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*/
640void 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*/
657void 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*/
718void 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*/
762void 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*/
786void 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*/
805void 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*/
825void 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*/
841void 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*/
851void 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*/
892void 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*/
906void 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*/
919void MainWindow::slotToggleTrayIcon()
920{
921 theApp()->displayTrayIcon(!theApp()->trayIconDisplayed(), this);
922}
923
924/******************************************************************************
925* Called when the user preferences have changed.
926*/
927void 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*/
938void 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*/
948void 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*/
956void 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*/
965void MainWindow::slotUndo()
966{
967 Undo::undo(this, KAlarm::stripAccel(mActionUndo->text()));
968}
969
970/******************************************************************************
971* Called when the Redo action is selected.
972*/
973void MainWindow::slotRedo()
974{
975 Undo::redo(this, KAlarm::stripAccel(mActionRedo->text()));
976}
977
978/******************************************************************************
979* Called when an Undo item is selected.
980*/
981void 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*/
989void 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*/
998void 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*/
1007void MainWindow::slotInitRedoMenu()
1008{
1009 initUndoMenu(mActionRedo->popupMenu(), Undo::REDO);
1010}
1011
1012/******************************************************************************
1013* Populate the undo or redo menu.
1014*/
1015void 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*/
1036void 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*/
1063void MainWindow::slotResetDaemon()
1064{
1065 KAlarm::resetDaemon();
1066}
1067
1068/******************************************************************************
1069* Called when the "Configure KAlarm" menu item is selected.
1070*/
1071void MainWindow::slotPreferences()
1072{
1073 KAlarmPrefDlg::display();
1074}
1075
1076/******************************************************************************
1077* Called when the Configure Keys menu item is selected.
1078*/
1079void MainWindow::slotConfigureKeys()
1080{
1081 KKeyDialog::configure(actionCollection(), this);
1082}
1083
1084/******************************************************************************
1085* Called when the Configure Toolbars menu item is selected.
1086*/
1087void 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*/
1099void 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*/
1108void 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*/
1116void 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*/
1135void 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*/
1153void 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*/
1162void 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*/
1176void MainWindow::dropEvent(TQDropEvent* e)
1177{
1178 executeDropEvent(this, e);
1179}
1180
1181static 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*/
1191void 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*/
1292void 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*/
1339void 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*/
1351void 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*/
1371void 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*/
1388void 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*/
1398MainWindow* 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)