mainwindow.cpp 60.5 KB
Newer Older
1
2
3
/*
 *  mainwindow.cpp  -  main application window
 *  Program:  kalarm
4
 *  Copyright © 2001-2014 by David Jarvie <djarvie@kde.org>
5
 *
David Jarvie's avatar
David Jarvie committed
6
7
8
9
10
11
12
13
14
15
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
David Jarvie's avatar
David Jarvie committed
16
17
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
David Jarvie's avatar
David Jarvie committed
18
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20
21
 */

#include "kalarm.h"
Laurent Montel's avatar
Laurent Montel committed
22
#include "mainwindow.h"
David Jarvie's avatar
David Jarvie committed
23
24
25

#include "alarmcalendar.h"
#include "alarmlistdelegate.h"
26
#include "autoqpointer.h"
David Jarvie's avatar
David Jarvie committed
27
28
29
30
31
#include "alarmlistview.h"
#include "birthdaydlg.h"
#include "functions.h"
#include "kalarmapp.h"
#include "kamail.h"
32
#include "messagebox.h"
David Jarvie's avatar
David Jarvie committed
33
#include "newalarmaction.h"
David Jarvie's avatar
David Jarvie committed
34
35
36
37
38
39
40
41
#include "prefdlg.h"
#include "preferences.h"
#include "resourceselector.h"
#include "synchtimer.h"
#include "templatedlg.h"
#include "templatemenuaction.h"
#include "templatepickdlg.h"
#include "traywindow.h"
42
#include "wakedlg.h"
43

Laurent Montel's avatar
Laurent Montel committed
44
45
#include <kalarmcal/alarmtext.h>
#include <kalarmcal/kaevent.h>
46

Laurent Montel's avatar
Laurent Montel committed
47
#include <libkdepim/misc/maillistdrag.h>
Laurent Montel's avatar
Laurent Montel committed
48
#include <kmime/kmime_content.h>
Christophe Giboudeaux's avatar
Christophe Giboudeaux committed
49
#include <KCalCore/MemoryCalendar>
Laurent Montel's avatar
Laurent Montel committed
50
#include <KCalUtils/kcalutils/icaldrag.h>
Laurent Montel's avatar
Laurent Montel committed
51
#include <AkonadiCore/control.h>
52
53
using namespace KCalCore;
using namespace KCalUtils;
Laurent Montel's avatar
Laurent Montel committed
54
55
#include <KLocale>
#include <K4AboutData>
56
#include <ktoolbar.h>
57
#include <kactioncollection.h>
58
#include <ksystemtrayicon.h>
Aaron J. Seigo's avatar
Aaron J. Seigo committed
59
#include <kstandardaction.h>
60
#include <kiconloader.h>
David Jarvie's avatar
David Jarvie committed
61
#include <kurl.h>
Laurent Montel's avatar
Laurent Montel committed
62
#include <KLocalizedString>
David Jarvie's avatar
Spacing    
David Jarvie committed
63
#include <KSharedConfig>
David Jarvie's avatar
David Jarvie committed
64
#include <kconfiggroup.h>
65
#include <kshortcutsdialog.h>
David Jarvie's avatar
David Jarvie committed
66
#include <kedittoolbar.h>
David Jarvie's avatar
David Jarvie committed
67
#include <kxmlguifactory.h>
Laurent Montel's avatar
Port++    
Laurent Montel committed
68
69
#include <ktoggleaction.h>
#include <ktoolbarpopupaction.h>
Laurent Montel's avatar
Laurent Montel committed
70
#include <KTimeZone>
71

David Jarvie's avatar
Tidy up    
David Jarvie committed
72
#include <QAction>
73
74
75
76
77
78
#include <QSplitter>
#include <QByteArray>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QResizeEvent>
#include <QCloseEvent>
Laurent Montel's avatar
Laurent Montel committed
79
#include <QDesktopWidget>
David Jarvie's avatar
Spacing    
David Jarvie committed
80
81
82
#include <QMenu>
#include <qinputdialog.h>
#include <qdebug.h>
David Jarvie's avatar
David Jarvie committed
83

84
85
using namespace KAlarmCal;

Laurent Montel's avatar
Laurent Montel committed
86
static const QString UI_FILE     = QLatin1String("kalarmui.rc");
David Jarvie's avatar
David Jarvie committed
87
static const char*   WINDOW_NAME = "MainWindow";
88

David Jarvie's avatar
David Jarvie committed
89
90
91
92
93
static const char*   VIEW_GROUP         = "View";
static const char*   SHOW_TIME_KEY      = "ShowAlarmTime";
static const char*   SHOW_TIME_TO_KEY   = "ShowTimeToAlarm";
static const char*   SHOW_ARCHIVED_KEY  = "ShowArchivedAlarms";
static const char*   SHOW_RESOURCES_KEY = "ShowResources";
94

95
96
static QString   undoText;
static QString   undoTextStripped;
Laurent Montel's avatar
Laurent Montel committed
97
static QList<QKeySequence>  undoShortcut;
98
99
static QString   redoText;
static QString   redoTextStripped;
Laurent Montel's avatar
Laurent Montel committed
100
static QList<QKeySequence> redoShortcut;
101

102

103
/*=============================================================================
104
=  Class: MainWindow
105
=============================================================================*/
106

107
108
MainWindow::WindowList   MainWindow::mWindowList;
TemplateDlg*             MainWindow::mTemplateDlg = 0;
David Jarvie's avatar
David Jarvie committed
109
110
111

// Collect these widget labels together to ensure consistent wording and
// translations across different modules.
112
113
114
115
QString MainWindow::i18n_a_ShowAlarmTimes()        { return i18nc("@action", "Show &Alarm Times"); }
QString MainWindow::i18n_chk_ShowAlarmTime()       { return i18nc("@option:check", "Show alarm time"); }
QString MainWindow::i18n_o_ShowTimeToAlarms()      { return i18nc("@action", "Show Time t&o Alarms"); }
QString MainWindow::i18n_chk_ShowTimeToAlarm()     { return i18nc("@option:check", "Show time until alarm"); }
116
117


118
119
120
121
122
/******************************************************************************
* Construct an instance.
* To avoid resize() events occurring while still opening the calendar (and
* resultant crashes), the calendar is opened before constructing the instance.
*/
123
MainWindow* MainWindow::create(bool restored)
124
{
125
126
    theApp()->checkCalendar();    // ensure calendar is open
    return new MainWindow(restored);
127
128
}

129
MainWindow::MainWindow(bool restored)
130
131
132
133
134
135
    : MainWindowBase(0, Qt::WindowContextHelpButtonHint),
      mResourcesWidth(-1),
      mHiddenTrayParent(false),
      mShown(false),
      mResizing(false)
{
Laurent Montel's avatar
Laurent Montel committed
136
    qDebug();
137
138
    setAttribute(Qt::WA_DeleteOnClose);
    setWindowModality(Qt::WindowModal);
Laurent Montel's avatar
Laurent Montel committed
139
    setObjectName(QLatin1String("MainWin"));    // used by LikeBack
Laurent Montel's avatar
Laurent Montel committed
140
    setPlainCaption(KComponentData::mainComponent().aboutData()->programName());
141
    KConfigGroup config(KSharedConfig::openConfig(), VIEW_GROUP);
142
143
144
145
146
147
    mShowResources = config.readEntry(SHOW_RESOURCES_KEY, false);
    mShowArchived  = config.readEntry(SHOW_ARCHIVED_KEY, false);
    mShowTime      = config.readEntry(SHOW_TIME_KEY, true);
    mShowTimeTo    = config.readEntry(SHOW_TIME_TO_KEY, false);
    if (!restored)
    {
148
        KConfigGroup wconfig(KSharedConfig::openConfig(), WINDOW_NAME);
149
150
151
152
153
154
155
156
157
158
159
160
161
        mResourcesWidth = wconfig.readEntry(QString::fromLatin1("Splitter %1").arg(KApplication::desktop()->width()), (int)0);
    }

    setAcceptDrops(true);         // allow drag-and-drop onto this window
    if (!mShowTimeTo)
        mShowTime = true;     // ensure at least one time column is visible

    mSplitter = new QSplitter(Qt::Horizontal, this);
    mSplitter->setChildrenCollapsible(false);
    mSplitter->installEventFilter(this);
    setCentralWidget(mSplitter);

    // Create the calendar resource selector widget
162
    Akonadi::Control::widgetNeedsAkonadi(this);
163
164
165
    mResourceSelector = new ResourceSelector(mSplitter);
    mSplitter->setStretchFactor(0, 0);   // don't resize resource selector when window is resized
    mSplitter->setStretchFactor(1, 1);
David Jarvie's avatar
David Jarvie committed
166

167
168
    // Create the alarm list widget
    mListFilterModel = new AlarmListModel(this);
169
    mListFilterModel->setEventTypeFilter(mShowArchived ? CalEvent::ACTIVE | CalEvent::ARCHIVED : CalEvent::ACTIVE);
170
171
172
173
174
    mListView = new AlarmListView(WINDOW_NAME, mSplitter);
    mListView->setModel(mListFilterModel);
    mListView->selectTimeColumns(mShowTime, mShowTimeTo);
    mListView->sortByColumn(mShowTime ? AlarmListModel::TimeColumn : AlarmListModel::TimeToColumn, Qt::AscendingOrder);
    mListView->setItemDelegate(new AlarmListDelegate(mListView));
Laurent Montel's avatar
Laurent Montel committed
175
    connect(mListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(slotSelection()));
Laurent Montel's avatar
Laurent Montel committed
176
    connect(mListView, &AlarmListView::contextMenuRequested, this, &MainWindow::slotContextMenuRequested);
Laurent Montel's avatar
Laurent Montel committed
177
    connect(AkonadiModel::instance(), SIGNAL(collectionStatusChanged(Akonadi::Collection,AkonadiModel::Change,QVariant,bool)),
178
                       SLOT(slotCalendarStatusChanged()));
Laurent Montel's avatar
Laurent Montel committed
179
    connect(mResourceSelector, &ResourceSelector::resized, this, &MainWindow::resourcesResized);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
    mListView->installEventFilter(this);
    initActions();

    setAutoSaveSettings(QLatin1String(WINDOW_NAME), true);    // save toolbars, window sizes etc.
    mWindowList.append(this);
    if (mWindowList.count() == 1)
    {
        // It's the first main window
        if (theApp()->wantShowInSystemTray())
            theApp()->displayTrayIcon(true, this);     // create system tray icon for run-in-system-tray mode
        else if (theApp()->trayWindow())
            theApp()->trayWindow()->setAssocMainWindow(this);    // associate this window with the system tray icon
    }
    slotCalendarStatusChanged();   // initialise action states now that window is registered
194
195
}

196
MainWindow::~MainWindow()
197
{
Laurent Montel's avatar
Laurent Montel committed
198
    qDebug();
199
200
    bool trayParent = isTrayParent();   // must call before removing from window list
    mWindowList.removeAt(mWindowList.indexOf(this));
David Jarvie's avatar
David Jarvie committed
201

202
203
204
205
206
    // Prevent view updates during window destruction
    delete mResourceSelector;
    mResourceSelector = 0;
    delete mListView;
    mListView = 0;
David Jarvie's avatar
David Jarvie committed
207

208
209
210
211
212
213
214
    if (theApp()->trayWindow())
    {
        if (trayParent)
            delete theApp()->trayWindow();
        else
            theApp()->trayWindow()->removeWindow(this);
    }
215
    KSharedConfig::openConfig()->sync();    // save any new window size to disc
216
    theApp()->quitIf();
217
218
}

219
220
221
222
/******************************************************************************
* Save settings to the session managed config file, for restoration
* when the program is restored.
*/
David Jarvie's avatar
David Jarvie committed
223
void MainWindow::saveProperties(KConfigGroup& config)
224
{
225
226
227
228
229
    config.writeEntry("HiddenTrayParent", isTrayParent() && isHidden());
    config.writeEntry("ShowArchived", mShowArchived);
    config.writeEntry("ShowTime", mShowTime);
    config.writeEntry("ShowTimeTo", mShowTimeTo);
    config.writeEntry("ResourcesWidth", mResourceSelector->isHidden() ? 0 : mResourceSelector->width());
230
231
232
233
234
235
236
}

/******************************************************************************
* Read settings from the session managed config file.
* This function is automatically called whenever the app is being
* restored. Read in whatever was saved in saveProperties().
*/
David Jarvie's avatar
David Jarvie committed
237
void MainWindow::readProperties(const KConfigGroup& config)
238
{
239
240
241
242
243
244
    mHiddenTrayParent = config.readEntry("HiddenTrayParent", true);
    mShowArchived     = config.readEntry("ShowArchived", false);
    mShowTime         = config.readEntry("ShowTime", true);
    mShowTimeTo       = config.readEntry("ShowTimeTo", false);
    mResourcesWidth   = config.readEntry("ResourcesWidth", (int)0);
    mShowResources    = (mResourcesWidth > 0);
245
246
247
}

/******************************************************************************
David Jarvie's avatar
David Jarvie committed
248
249
250
251
* Get the main main window, i.e. the parent of the system tray icon, or if
* none, the first main window to be created. Visible windows take precedence
* over hidden ones.
*/
252
MainWindow* MainWindow::mainMainWindow()
David Jarvie's avatar
David Jarvie committed
253
{
254
255
256
257
258
259
260
261
262
263
264
    MainWindow* tray = theApp()->trayWindow() ? theApp()->trayWindow()->assocMainWindow() : 0;
    if (tray  &&  tray->isVisible())
        return tray;
    for (int i = 0, end = mWindowList.count();  i < end;  ++i)
        if (mWindowList[i]->isVisible())
            return mWindowList[i];
    if (tray)
        return tray;
    if (mWindowList.isEmpty())
        return 0;
    return mWindowList[0];
David Jarvie's avatar
David Jarvie committed
265
266
267
}

/******************************************************************************
268
* Check whether this main window is effectively the parent of the system tray icon.
269
*/
270
bool MainWindow::isTrayParent() const
271
{
272
273
274
275
276
277
    TrayWindow* tray = theApp()->trayWindow();
    if (!tray  ||  !KSystemTrayIcon::isSystemTrayAvailable())
        return false;
    if (tray->assocMainWindow() == this)
        return true;
    return mWindowList.count() == 1;
278
279
}

280
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
281
* Close all main windows.
282
*/
283
void MainWindow::closeAll()
284
{
285
286
    while (!mWindowList.isEmpty())
        delete mWindowList[0];    // N.B. the destructor removes the window from the list
287
288
}

289
290
291
292
293
/******************************************************************************
* Intercept events for the splitter widget.
*/
bool MainWindow::eventFilter(QObject* obj, QEvent* e)
{
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
    if (obj == mSplitter)
    {
        switch (e->type())
        {
            case QEvent::Resize:
                // Don't change resources size while WINDOW is being resized.
                // Resize event always occurs before Paint.
                mResizing = true;
                break;
            case QEvent::Paint:
                // Allow resources to be resized again
                mResizing = false;
                break;
            default:
                break;
        }
    }
    else if (obj == mListView)
    {
        switch (e->type())
        {
            case QEvent::KeyPress:
            {
                QKeyEvent* ke = static_cast<QKeyEvent*>(e);
                if (ke->key() == Qt::Key_Delete  &&  ke->modifiers() == Qt::ShiftModifier)
                {
                    // Prevent Shift-Delete being processed by EventListDelegate
                    mActionDeleteForce->trigger();
                    return true;
                }
                break;
            }
            default:
                break;
        }
    }
    return false;
331
332
}

333
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
334
335
336
337
* Called when the window's size has changed (before it is painted).
* Sets the last column in the list view to extend at least to the right hand
* edge of the list view.
* Records the new size in the config file.
338
*/
339
void MainWindow::resizeEvent(QResizeEvent* re)
340
{
341
342
343
344
345
346
347
348
349
    // Save the window's new size only if it's the first main window
    MainWindowBase::resizeEvent(re);
    if (mResourcesWidth > 0)
    {
        QList<int> widths;
        widths.append(mResourcesWidth);
        widths.append(width() - mResourcesWidth - mSplitter->handleWidth());
        mSplitter->setSizes(widths);
    }
350
351
}

David Jarvie's avatar
David Jarvie committed
352
353
void MainWindow::resourcesResized()
{
354
355
356
357
358
359
360
361
362
363
364
365
    if (!mShown  ||  mResizing)
        return;
    QList<int> widths = mSplitter->sizes();
    if (widths.count() > 1)
    {
        mResourcesWidth = widths[0];
        // Width is reported as non-zero when resource selector is
        // actually invisible, so note a zero width in these circumstances.
        if (mResourcesWidth <= 5)
            mResourcesWidth = 0;
        else if (mainMainWindow() == this)
        {
366
            KConfigGroup config(KSharedConfig::openConfig(), WINDOW_NAME);
367
368
369
            config.writeEntry(QString::fromLatin1("Splitter %1").arg(KApplication::desktop()->width()), mResourcesWidth);
        }
    }
David Jarvie's avatar
David Jarvie committed
370
371
}

372
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
373
374
375
* Called when the window is first displayed.
* Sets the last column in the list view to extend at least to the right hand
* edge of the list view.
376
*/
377
void MainWindow::showEvent(QShowEvent* se)
378
{
379
380
381
382
383
384
385
386
387
    if (mResourcesWidth > 0)
    {
        QList<int> widths;
        widths.append(mResourcesWidth);
        widths.append(width() - mResourcesWidth - mSplitter->handleWidth());
        mSplitter->setSizes(widths);
    }
    MainWindowBase::showEvent(se);
    mShown = true;
388
389
}

390
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
391
* Display the window.
392
*/
393
void MainWindow::show()
394
{
395
396
397
398
399
400
    MainWindowBase::show();
    if (mMenuError)
    {
        // Show error message now that the main window has been displayed.
        // Waiting until now lets the user easily associate the message with
        // the main window which is faulty.
Laurent Montel's avatar
Laurent Montel committed
401
        KAMessageBox::error(this, xi18nc("@info", "Failure to create menus (perhaps <filename>%1</filename> missing or corrupted)", UI_FILE));
402
403
        mMenuError = false;
    }
404
405
}

406
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
407
* Called after the window is hidden.
408
*/
409
void MainWindow::hideEvent(QHideEvent* he)
410
{
411
    MainWindowBase::hideEvent(he);
412
413
}

414
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
415
* Initialise the menu, toolbar and main window actions.
416
*/
417
void MainWindow::initActions()
418
{
Laurent Montel's avatar
Laurent Montel committed
419
    //KShortcut dummy;
420
421
    KActionCollection* actions = actionCollection();

Laurent Montel's avatar
Laurent Montel committed
422
    mActionTemplates = new QAction(i18nc("@action", "&Templates..."), this);
423
    actions->addAction(QLatin1String("templates"), mActionTemplates);
Laurent Montel's avatar
Laurent Montel committed
424
    connect(mActionTemplates, &QAction::triggered, this, &MainWindow::slotTemplates);
425
426
427
428

    mActionNew = new NewAlarmAction(false, i18nc("@action", "&New"), this);
    actions->addAction(QLatin1String("new"), mActionNew);

David Jarvie's avatar
Spacing    
David Jarvie committed
429
    QAction* action = mActionNew->displayAlarmAction();
430
    actions->addAction(QLatin1String("newDisplay"), action);
Laurent Montel's avatar
Laurent Montel committed
431
    //QT5 action->setGlobalShortcut(dummy);   // actions->addAction() must be called first!
Laurent Montel's avatar
Laurent Montel committed
432
    connect(action, &QAction::triggered, this, &MainWindow::slotNewDisplay);
433

434
435
    action = mActionNew->commandAlarmAction();
    actions->addAction(QLatin1String("newCommand"), action);
Laurent Montel's avatar
Laurent Montel committed
436
    //QT5 action->setGlobalShortcut(dummy);   // actions->addAction() must be called first!
Laurent Montel's avatar
Laurent Montel committed
437
    connect(action, &QAction::triggered, this, &MainWindow::slotNewCommand);
438

439
440
    action = mActionNew->emailAlarmAction();
    actions->addAction(QLatin1String("newEmail"), action);
Laurent Montel's avatar
Laurent Montel committed
441
    //QT5 action->setGlobalShortcut(dummy);   // actions->addAction() must be called first!
Laurent Montel's avatar
Laurent Montel committed
442
    connect(action, &QAction::triggered, this, &MainWindow::slotNewEmail);
443

444
445
    action = mActionNew->audioAlarmAction();
    actions->addAction(QLatin1String("newAudio"), action);
Laurent Montel's avatar
Laurent Montel committed
446
    //QT5 action->setGlobalShortcut(dummy);   // actions->addAction() must be called first!
Laurent Montel's avatar
Laurent Montel committed
447
    connect(action, &QAction::triggered, this, &MainWindow::slotNewAudio);
448

Laurent Montel's avatar
Laurent Montel committed
449
450
451
    TemplateMenuAction *templateMenuAction = mActionNew->fromTemplateAlarmAction();
    actions->addAction(QLatin1String("newFromTemplate"), templateMenuAction);
    connect(templateMenuAction, &TemplateMenuAction::selected, this, &MainWindow::slotNewFromTemplate);
452

Laurent Montel's avatar
Laurent Montel committed
453
    mActionCreateTemplate = new QAction(i18nc("@action", "Create Tem&plate..."), this);
454
    actions->addAction(QLatin1String("createTemplate"), mActionCreateTemplate);
Laurent Montel's avatar
Laurent Montel committed
455
    connect(mActionCreateTemplate, &QAction::triggered, this, &MainWindow::slotNewTemplate);
456

Laurent Montel's avatar
Laurent Montel committed
457
    mActionCopy = new QAction(QIcon::fromTheme(QLatin1String("edit-copy")), i18nc("@action", "&Copy..."), this);
458
    actions->addAction(QLatin1String("copy"), mActionCopy);
David Jarvie's avatar
Spacing    
David Jarvie committed
459
    actions->setDefaultShortcut(mActionCopy, QKeySequence(Qt::SHIFT + Qt::Key_Insert));
Laurent Montel's avatar
Laurent Montel committed
460
    connect(mActionCopy, &QAction::triggered, this, &MainWindow::slotCopy);
461

Laurent Montel's avatar
Laurent Montel committed
462
    mActionModify = new QAction(QIcon::fromTheme(QLatin1String("document-properties")), i18nc("@action", "&Edit..."), this);
463
    actions->addAction(QLatin1String("modify"), mActionModify);
David Jarvie's avatar
Spacing    
David Jarvie committed
464
    actions->setDefaultShortcut(mActionModify, QKeySequence(Qt::CTRL + Qt::Key_E));
Laurent Montel's avatar
Laurent Montel committed
465
    connect(mActionModify, &QAction::triggered, this, &MainWindow::slotModify);
466

Laurent Montel's avatar
Laurent Montel committed
467
    mActionDelete = new QAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("@action", "&Delete"), this);
468
    actions->addAction(QLatin1String("delete"), mActionDelete);
David Jarvie's avatar
Spacing    
David Jarvie committed
469
    actions->setDefaultShortcut(mActionDelete, QKeySequence::Delete);
Laurent Montel's avatar
Laurent Montel committed
470
    connect(mActionDelete, &QAction::triggered, this, &MainWindow::slotDeleteIf);
471
472

    // Set up Shift-Delete as a shortcut to delete without confirmation
Laurent Montel's avatar
Laurent Montel committed
473
    mActionDeleteForce = new QAction(i18nc("@action", "Delete Without Confirmation"), this);
474
    actions->addAction(QLatin1String("delete-force"), mActionDeleteForce);
David Jarvie's avatar
Spacing    
David Jarvie committed
475
    actions->setDefaultShortcut(mActionDeleteForce, QKeySequence::Delete + Qt::SHIFT);
Laurent Montel's avatar
Laurent Montel committed
476
    connect(mActionDeleteForce, &QAction::triggered, this, &MainWindow::slotDeleteForce);
477

Laurent Montel's avatar
Laurent Montel committed
478
    mActionReactivate = new QAction(i18nc("@action", "Reac&tivate"), this);
479
    actions->addAction(QLatin1String("undelete"), mActionReactivate);
Laurent Montel's avatar
Laurent Montel committed
480
    actions->setDefaultShortcut(mActionReactivate, QKeySequence(Qt::CTRL + Qt::Key_R));
Laurent Montel's avatar
Laurent Montel committed
481
    connect(mActionReactivate, &QAction::triggered, this, &MainWindow::slotReactivate);
482

Laurent Montel's avatar
Laurent Montel committed
483
    mActionEnable = new QAction(this);
484
    actions->addAction(QLatin1String("disable"), mActionEnable);
Laurent Montel's avatar
Laurent Montel committed
485
    actions->setDefaultShortcut(mActionEnable, QKeySequence(Qt::CTRL + Qt::Key_B));
Laurent Montel's avatar
Laurent Montel committed
486
    connect(mActionEnable, &QAction::triggered, this, &MainWindow::slotEnable);
487

Laurent Montel's avatar
Laurent Montel committed
488
    action = new QAction(i18nc("@action", "Wake From Suspend..."), this);
489
    actions->addAction(QLatin1String("wakeSuspend"), action);
Laurent Montel's avatar
Laurent Montel committed
490
    connect(action, &QAction::triggered, this, &MainWindow::slotWakeFromSuspend);
491

492
    action = KAlarm::createStopPlayAction(this);
493
    actions->addAction(QLatin1String("stopAudio"), action);
Laurent Montel's avatar
Laurent Montel committed
494
    //QT5 action->setGlobalShortcut(dummy);   // actions->addAction() must be called first!
495
496
497

    mActionShowTime = new KToggleAction(i18n_a_ShowAlarmTimes(), this);
    actions->addAction(QLatin1String("showAlarmTimes"), mActionShowTime);
Laurent Montel's avatar
Laurent Montel committed
498
    connect(mActionShowTime, &KToggleAction::triggered, this, &MainWindow::slotShowTime);
499
500
501

    mActionShowTimeTo = new KToggleAction(i18n_o_ShowTimeToAlarms(), this);
    actions->addAction(QLatin1String("showTimeToAlarms"), mActionShowTimeTo);
David Jarvie's avatar
Spacing    
David Jarvie committed
502
    actions->setDefaultShortcut(mActionShowTimeTo, QKeySequence(Qt::CTRL + Qt::Key_I));
Laurent Montel's avatar
Laurent Montel committed
503
    connect(mActionShowTimeTo, &KToggleAction::triggered, this, &MainWindow::slotShowTimeTo);
504
505
506

    mActionShowArchived = new KToggleAction(i18nc("@action", "Show Archi&ved Alarms"), this);
    actions->addAction(QLatin1String("showArchivedAlarms"), mActionShowArchived);
David Jarvie's avatar
Spacing    
David Jarvie committed
507
    actions->setDefaultShortcut(mActionShowArchived, QKeySequence(Qt::CTRL + Qt::Key_P));
Laurent Montel's avatar
Laurent Montel committed
508
    connect(mActionShowArchived, &KToggleAction::triggered, this, &MainWindow::slotShowArchived);
509
510
511

    mActionToggleTrayIcon = new KToggleAction(i18nc("@action", "Show in System &Tray"), this);
    actions->addAction(QLatin1String("showInSystemTray"), mActionToggleTrayIcon);
Laurent Montel's avatar
Laurent Montel committed
512
    connect(mActionToggleTrayIcon, &KToggleAction::triggered, this, &MainWindow::slotToggleTrayIcon);
513

Laurent Montel's avatar
Laurent Montel committed
514
    mActionToggleResourceSel = new KToggleAction(QIcon::fromTheme(QLatin1String("view-choose")), i18nc("@action", "Show &Calendars"), this);
515
    actions->addAction(QLatin1String("showResources"), mActionToggleResourceSel);
Laurent Montel's avatar
Laurent Montel committed
516
    connect(mActionToggleResourceSel, &KToggleAction::triggered, this, &MainWindow::slotToggleResourceSelector);
517
518
519

    mActionSpreadWindows = KAlarm::createSpreadWindowsAction(this);
    actions->addAction(QLatin1String("spread"), mActionSpreadWindows);
Laurent Montel's avatar
Laurent Montel committed
520
    //QT5 mActionSpreadWindows->setGlobalShortcut(dummy);   // actions->addAction() must be called first!
521

Laurent Montel's avatar
Laurent Montel committed
522
    mActionImportAlarms = new QAction(i18nc("@action", "Import &Alarms..."), this);
523
    actions->addAction(QLatin1String("importAlarms"), mActionImportAlarms);
Laurent Montel's avatar
Laurent Montel committed
524
    connect(mActionImportAlarms, &QAction::triggered, this, &MainWindow::slotImportAlarms);
525

Laurent Montel's avatar
Laurent Montel committed
526
    mActionImportBirthdays = new QAction(i18nc("@action", "Import &Birthdays..."), this);
527
    actions->addAction(QLatin1String("importBirthdays"), mActionImportBirthdays);
Laurent Montel's avatar
Laurent Montel committed
528
    connect(mActionImportBirthdays, &QAction::triggered, this, &MainWindow::slotBirthdays);
529

Laurent Montel's avatar
Laurent Montel committed
530
    mActionExportAlarms = new QAction(i18nc("@action", "E&xport Selected Alarms..."), this);
531
    actions->addAction(QLatin1String("exportAlarms"), mActionExportAlarms);
Laurent Montel's avatar
Laurent Montel committed
532
    connect(mActionExportAlarms, &QAction::triggered, this, &MainWindow::slotExportAlarms);
533

Laurent Montel's avatar
Laurent Montel committed
534
    mActionExport = new QAction(i18nc("@action", "E&xport..."), this);
535
    actions->addAction(QLatin1String("export"), mActionExport);
Laurent Montel's avatar
Laurent Montel committed
536
    connect(mActionExport, &QAction::triggered, this, &MainWindow::slotExportAlarms);
537

Laurent Montel's avatar
Laurent Montel committed
538
    action = new QAction(QIcon::fromTheme(QLatin1String("view-refresh")), i18nc("@action", "&Refresh Alarms"), this);
539
    actions->addAction(QLatin1String("refreshAlarms"), action);
Laurent Montel's avatar
Laurent Montel committed
540
    connect(action, &QAction::triggered, this, &MainWindow::slotRefreshAlarms);
541

David Jarvie's avatar
Spacing    
David Jarvie committed
542
    KToggleAction* toggleAction = KAlarm::createAlarmEnableAction(this);
Laurent Montel's avatar
Laurent Montel committed
543
    actions->addAction(QLatin1String("alarmsEnable"), toggleAction);
544
545
546
    if (undoText.isNull())
    {
        // Get standard texts, etc., for Undo and Redo actions
David Jarvie's avatar
Spacing    
David Jarvie committed
547
        QAction* act = KStandardAction::undo(this, 0, actions);
Laurent Montel's avatar
Laurent Montel committed
548
        undoShortcut     = act->shortcuts();
549
        undoText         = act->text();
550
        undoTextStripped = KLocalizedString::removeAcceleratorMarker(undoText);
551
552
        delete act;
        act = KStandardAction::redo(this, 0, actions);
Laurent Montel's avatar
Laurent Montel committed
553
        redoShortcut     = act->shortcuts();
554
        redoText         = act->text();
555
        redoTextStripped = KLocalizedString::removeAcceleratorMarker(redoText);
556
557
        delete act;
    }
Laurent Montel's avatar
Laurent Montel committed
558
    mActionUndo = new KToolBarPopupAction(QIcon::fromTheme(QLatin1String("edit-undo")), undoText, this);
559
    actions->addAction(QLatin1String("edit_undo"), mActionUndo);
Laurent Montel's avatar
Laurent Montel committed
560
    mActionUndo->setShortcuts(undoShortcut);
Laurent Montel's avatar
Laurent Montel committed
561
    connect(mActionUndo, &KToolBarPopupAction::triggered, this, &MainWindow::slotUndo);
562

Laurent Montel's avatar
Laurent Montel committed
563
    mActionRedo = new KToolBarPopupAction(QIcon::fromTheme(QLatin1String("edit-redo")), redoText, this);
564
    actions->addAction(QLatin1String("edit_redo"), mActionRedo);
Laurent Montel's avatar
Laurent Montel committed
565
    mActionRedo->setShortcuts(redoShortcut);
Laurent Montel's avatar
Laurent Montel committed
566
    connect(mActionRedo, &KToolBarPopupAction::triggered, this, &MainWindow::slotRedo);
567
568
569
570
571
572
573
574

    KStandardAction::find(mListView, SLOT(slotFind()), actions);
    mActionFindNext = KStandardAction::findNext(mListView, SLOT(slotFindNext()), actions);
    mActionFindPrev = KStandardAction::findPrev(mListView, SLOT(slotFindPrev()), actions);
    KStandardAction::selectAll(mListView, SLOT(selectAll()), actions);
    KStandardAction::deselect(mListView, SLOT(clearSelection()), actions);
    // Quit only once the event loop is called; otherwise, the parent window will
    // be deleted while still processing the action, resulting in a crash.
Laurent Montel's avatar
Laurent Montel committed
575
    QAction* act = KStandardAction::quit(0, 0, actions);
Laurent Montel's avatar
Laurent Montel committed
576
    connect(act, &QAction::triggered, this, &MainWindow::slotQuit, Qt::QueuedConnection);
577
578
579
580
581
582
583
    KStandardAction::keyBindings(this, SLOT(slotConfigureKeys()), actions);
    KStandardAction::configureToolbars(this, SLOT(slotConfigureToolbar()), actions);
    KStandardAction::preferences(this, SLOT(slotPreferences()), actions);
    mResourceSelector->initActions(actions);
    setStandardToolBarMenuEnabled(true);
    createGUI(UI_FILE);
    // Load menu and toolbar settings
584
    applyMainWindowSettings(KSharedConfig::openConfig()->group(WINDOW_NAME));
585

Laurent Montel's avatar
Laurent Montel committed
586
587
588
    mContextMenu = static_cast<QMenu*>(factory()->container(QLatin1String("listContext"), this));
    mActionsMenu = static_cast<QMenu*>(factory()->container(QLatin1String("actions"), this));
    QMenu* resourceMenu = static_cast<QMenu*>(factory()->container(QLatin1String("resourceContext"), this));
589
590
591
592
593
594
    mResourceSelector->setContextMenu(resourceMenu);
    mMenuError = (!mContextMenu  ||  !mActionsMenu  ||  !resourceMenu);
    connect(mActionUndo->menu(), SIGNAL(aboutToShow()), SLOT(slotInitUndoMenu()));
    connect(mActionUndo->menu(), SIGNAL(triggered(QAction*)), SLOT(slotUndoItem(QAction*)));
    connect(mActionRedo->menu(), SIGNAL(aboutToShow()), SLOT(slotInitRedoMenu()));
    connect(mActionRedo->menu(), SIGNAL(triggered(QAction*)), SLOT(slotRedoItem(QAction*)));
Laurent Montel's avatar
Laurent Montel committed
595
    connect(Undo::instance(), SIGNAL(changed(QString,QString)), SLOT(slotUndoStatus(QString,QString)));
Laurent Montel's avatar
Laurent Montel committed
596
    connect(mListView, &AlarmListView::findActive, this, &MainWindow::slotFindActive);
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
    Preferences::connect(SIGNAL(archivedKeepDaysChanged(int)), this, SLOT(updateKeepArchived(int)));
    Preferences::connect(SIGNAL(showInSystemTrayChanged(bool)), this, SLOT(updateTrayIconAction()));
    connect(theApp(), SIGNAL(trayIconToggled()), SLOT(updateTrayIconAction()));

    // Set menu item states
    setEnableText(true);
    mActionShowTime->setChecked(mShowTime);
    mActionShowTimeTo->setChecked(mShowTimeTo);
    mActionShowArchived->setChecked(mShowArchived);
    if (!Preferences::archivedKeepDays())
        mActionShowArchived->setEnabled(false);
    mActionToggleResourceSel->setChecked(mShowResources);
    slotToggleResourceSelector();
    updateTrayIconAction();         // set the correct text for this action
    mActionUndo->setEnabled(Undo::haveUndo());
    mActionRedo->setEnabled(Undo::haveRedo());
    mActionFindNext->setEnabled(false);
    mActionFindPrev->setEnabled(false);

    mActionCopy->setEnabled(false);
    mActionModify->setEnabled(false);
    mActionDelete->setEnabled(false);
    mActionReactivate->setEnabled(false);
    mActionEnable->setEnabled(false);
    mActionCreateTemplate->setEnabled(false);
    mActionExport->setEnabled(false);

    Undo::emitChanged();     // set the Undo/Redo menu texts
//    Daemon::monitoringAlarms();
626
627
}

David Jarvie's avatar
David Jarvie committed
628
629
630
/******************************************************************************
* Enable or disable the Templates menu item in every main window instance.
*/
631
void MainWindow::enableTemplateMenuItem(bool enable)
David Jarvie's avatar
David Jarvie committed
632
{
633
634
    for (int i = 0, end = mWindowList.count();  i < end;  ++i)
        mWindowList[i]->mActionTemplates->setEnabled(enable);
David Jarvie's avatar
David Jarvie committed
635
636
}

637
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
638
* Refresh the alarm list in every main window instance.
639
*/
640
void MainWindow::refresh()
641
{
Laurent Montel's avatar
Laurent Montel committed
642
    qDebug();
643
    AkonadiModel::instance()->reload();
644
645
}

David Jarvie's avatar
David Jarvie committed
646
/******************************************************************************
647
648
* Called when the keep archived alarm setting changes in the user preferences.
* Enable/disable Show archived alarms option.
David Jarvie's avatar
David Jarvie committed
649
*/
650
void MainWindow::updateKeepArchived(int days)
David Jarvie's avatar
David Jarvie committed
651
{
Laurent Montel's avatar
Laurent Montel committed
652
    qDebug() << (bool)days;
653
654
655
    if (mShowArchived  &&  !days)
        slotShowArchived();   // toggle Show Archived option setting
    mActionShowArchived->setEnabled(days);
David Jarvie's avatar
David Jarvie committed
656
657
}

David Jarvie's avatar
David Jarvie committed
658
659
660
/******************************************************************************
* Select an alarm in the displayed list.
*/
661
void MainWindow::selectEvent(Akonadi::Item::Id eventId)
David Jarvie's avatar
David Jarvie committed
662
{
663
664
665
666
667
668
669
    mListView->clearSelection();
    QModelIndex index = mListFilterModel->eventIndex(eventId);
    if (index.isValid())
    {
        mListView->select(index);
        mListView->scrollTo(index);
    }
David Jarvie's avatar
David Jarvie committed
670
671
}

672
673
674
/******************************************************************************
* Return the single selected alarm in the displayed list.
*/
675
676
677
KAEvent MainWindow::selectedEvent() const
{
    return mListView->selectedEvent();
678
679
}

680
681
682
683
684
685
686
687
/******************************************************************************
* Deselect all alarms in the displayed list.
*/
void MainWindow::clearSelection()
{
    mListView->clearSelection();
}

688
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
689
* Called when the New button is clicked to edit a new alarm to add to the list.
690
*/
David Jarvie's avatar
David Jarvie committed
691
void MainWindow::slotNew(EditAlarmDlg::Type type)
692
{
693
    KAlarm::editNewAlarm(type, mListView);
David Jarvie's avatar
David Jarvie committed
694
695
}

696
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
697
698
* Called when a template is selected from the New From Template popup menu.
* Executes a New Alarm dialog, preset from the selected template.
699
*/
700
void MainWindow::slotNewFromTemplate(const KAEvent* tmplate)
701
{
702
    KAlarm::editNewAlarm(tmplate, mListView);
703
704
}

David Jarvie's avatar
David Jarvie committed
705
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
706
707
* Called when the New Template button is clicked to create a new template
* based on the currently selected alarm.
David Jarvie's avatar
David Jarvie committed
708
*/
709
void MainWindow::slotNewTemplate()
David Jarvie's avatar
David Jarvie committed
710
{
711
712
713
    KAEvent event = mListView->selectedEvent();
    if (event.isValid())
        KAlarm::editNewTemplate(&event, this);
714
715
}

David Jarvie's avatar
David Jarvie committed
716
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
717
718
* Called when the Copy button is clicked to edit a copy of an existing alarm,
* to add to the list.
David Jarvie's avatar
David Jarvie committed
719
*/
720
void MainWindow::slotCopy()
David Jarvie's avatar
David Jarvie committed
721
{
722
723
724
    KAEvent event = mListView->selectedEvent();
    if (event.isValid())
        KAlarm::editNewAlarm(&event, this);
David Jarvie's avatar
David Jarvie committed
725
726
}

727
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
728
729
* Called when the Modify button is clicked to edit the currently highlighted
* alarm in the list.
730
*/
731
void MainWindow::slotModify()
732
{
733
734
735
    KAEvent event = mListView->selectedEvent();
    if (event.isValid())
        KAlarm::editAlarm(&event, this);   // edit alarm (view-only mode if archived or read-only)
David Jarvie's avatar
David Jarvie committed
736
737
}

738
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
739
740
* Called when the Delete button is clicked to delete the currently highlighted
* alarms in the list.
741
*/
742
void MainWindow::slotDelete(bool force)
743
{
744
    QVector<KAEvent> events = mListView->selectedEvents();
745
746
747
    if (!force  &&  Preferences::confirmAlarmDeletion())
    {
        int n = events.count();
748
749
750
        if (KAMessageBox::warningContinueCancel(this, i18ncp("@info", "Do you really want to delete the selected alarm?",
                                                             "Do you really want to delete the %1 selected alarms?", n),
                                                i18ncp("@title:window", "Delete Alarm", "Delete Alarms", n),
Laurent Montel's avatar
Laurent Montel committed
751
                                                KGuiItem(i18nc("@action:button", "&Delete"), QLatin1String("edit-delete")),
752
                                                KStandardGuiItem::cancel(),
David Jarvie's avatar
David Jarvie committed
753
                                                Preferences::CONFIRM_ALARM_DELETION)
754
755
756
757
758
759
760
            != KMessageBox::Continue)
            return;
    }

    // Remove any events which have just triggered, from the list to delete.
    Undo::EventList undos;
    AlarmCalendar* resources = AlarmCalendar::resources();
761
    for (int i = 0;  i < events.count();  )
762
    {
763
        Akonadi::Collection c = resources->collectionForEvent(events[i].itemId());
764
        if (!c.isValid())
765
            events.remove(i);
766
        else
767
            undos.append(events[i++], c);
768
    }
769

770
    if (events.isEmpty())
Laurent Montel's avatar
Laurent Montel committed
771
        qDebug() << "No alarms left to delete";
772
773
774
775
776
777
    else
    {
        // Delete the events from the calendar and displays
        KAlarm::deleteEvents(events, true, this);
        Undo::saveDeletes(undos);
    }
778
779
}

David Jarvie's avatar
David Jarvie committed
780
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
781
782
* Called when the Reactivate button is clicked to reinstate the currently
* highlighted archived alarms in the list.
David Jarvie's avatar
David Jarvie committed
783
*/
784
void MainWindow::slotReactivate()
David Jarvie's avatar
David Jarvie committed
785
{
786
    QVector<KAEvent> events = mListView->selectedEvents();
787
    mListView->clearSelection();
788

789
790
    // Add the alarms to the displayed lists and to the calendar file
    Undo::EventList undos;
791
792
    QVector<EventId> ineligibleIDs;
    KAlarm::reactivateEvents(events, ineligibleIDs, 0, this);
793

794
795
796
797
    // Create the undo list, excluding ineligible events
    AlarmCalendar* resources = AlarmCalendar::resources();
    for (int i = 0, end = events.count();  i < end;  ++i)
    {
798
        if (!ineligibleIDs.contains(EventId(events[i])))
799
        {
800
            undos.append(events[i], resources->collectionForEvent(events[i].itemId()));
801
802
803
        }
    }
    Undo::saveReactivates(undos);
David Jarvie's avatar
David Jarvie committed
804
805
}

806
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
807
808
* Called when the Enable/Disable button is clicked to enable or disable the
* currently highlighted alarms in the list.
809
*/
810
void MainWindow::slotEnable()
811
{
812
    bool enable = mActionEnableEnable;    // save since changed in response to KAlarm::enableEvent()
813
814
    QVector<KAEvent> events = mListView->selectedEvents();
    QVector<KAEvent> eventCopies;
815
816
817
818
    for (int i = 0, end = events.count();  i < end;  ++i)
        eventCopies += events[i];
    KAlarm::enableEvents(eventCopies, enable, this);
    slotSelection();   // update Enable/Disable action text
819
820
}

821
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
822
* Called when the Show Alarm Times menu item is selected or deselected.
823
*/
824
void MainWindow::slotShowTime()
825
{
826
827
828
829
830
831
832
    mShowTime = !mShowTime;
    mActionShowTime->setChecked(mShowTime);
    if (!mShowTime  &&  !mShowTimeTo)
        slotShowTimeTo();    // at least one time column must be displayed
    else
    {
        mListView->selectTimeColumns(mShowTime, mShowTimeTo);
833
        KConfigGroup config(KSharedConfig::openConfig(), VIEW_GROUP);
834
835
836
        config.writeEntry(SHOW_TIME_KEY, mShowTime);
        config.writeEntry(SHOW_TIME_TO_KEY, mShowTimeTo);
    }
837
838
839
}

/******************************************************************************
David Jarvie's avatar
David Jarvie committed
840
* Called when the Show Time To Alarms menu item is selected or deselected.
841
*/
842
void MainWindow::slotShowTimeTo()
843
{
844
845
846
847
848
849
850
    mShowTimeTo = !mShowTimeTo;
    mActionShowTimeTo->setChecked(mShowTimeTo);
    if (!mShowTimeTo  &&  !mShowTime)
        slotShowTime();    // at least one time column must be displayed
    else
    {
        mListView->selectTimeColumns(mShowTime, mShowTimeTo);
851
        KConfigGroup config(KSharedConfig::openConfig(), VIEW_GROUP);
852
853
854
        config.writeEntry(SHOW_TIME_KEY, mShowTime);
        config.writeEntry(SHOW_TIME_TO_KEY, mShowTimeTo);
    }
855
856
}

David Jarvie's avatar
David Jarvie committed
857
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
858
* Called when the Show Archived Alarms menu item is selected or deselected.
David Jarvie's avatar
David Jarvie committed
859
*/
860
void MainWindow::slotShowArchived()
David Jarvie's avatar
David Jarvie committed
861
{
862
863
864
865
    mShowArchived = !mShowArchived;
    mActionShowArchived->setChecked(mShowArchived);
    mActionShowArchived->setToolTip(mShowArchived ? i18nc("@info:tooltip", "Hide Archived Alarms")
                                                  : i18nc("@info:tooltip", "Show Archived Alarms"));
866
    mListFilterModel->setEventTypeFilter(mShowArchived ? CalEvent::ACTIVE | CalEvent::ARCHIVED : CalEvent::ACTIVE);
867
    mListView->reset();
868
    KConfigGroup config(KSharedConfig::openConfig(), VIEW_GROUP);
869
    config.writeEntry(SHOW_ARCHIVED_KEY, mShowArchived);
David Jarvie's avatar
David Jarvie committed
870
871
}

872
873
874
875
876
877
/******************************************************************************
* Called when the Spread Windows global shortcut is selected, to spread alarm
* windows so that they are all visible.
*/
void MainWindow::slotSpreadWindowsShortcut()
{
878
    mActionSpreadWindows->trigger();
879
880
}

881
882
883
884
885
886
887
888
/******************************************************************************
* Called when the Wake From Suspend menu option is selected.
*/
void MainWindow::slotWakeFromSuspend()
{
    (WakeFromSuspendDlg::create(this))->show();
}

889
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
890
891
* Called when the Import Alarms menu item is selected, to merge alarms from an
* external calendar into the current calendars.
892
893
894
*/
void MainWindow::slotImportAlarms()
{
895
    AlarmCalendar::importAlarms(this);
896
897
}

898
899
900
901
902
903
/******************************************************************************
* Called when the Export Alarms menu item is selected, to export the selected
* alarms to an external calendar.
*/
void MainWindow::slotExportAlarms()
{
904
    QVector<KAEvent> events = mListView->selectedEvents();
905
906
907
908
909
    if (!events.isEmpty())
    {
        KAEvent::List evts = KAEvent::ptrList(events);
        AlarmCalendar::exportAlarms(evts, this);
    }
910
911
}

912
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
913
914
* Called when the Import Birthdays menu item is selected, to display birthdays
* from the address book for selection as alarms.
915
*/
916
void MainWindow::slotBirthdays()
917
{
918
919
920
921
922
923
    // Use AutoQPointer to guard against crash on application exit while
    // the dialogue is still open. It prevents double deletion (both on
    // deletion of MainWindow, and on return from this function).
    AutoQPointer<BirthdayDlg> dlg = new BirthdayDlg(this);
    if (dlg->exec() == QDialog::Accepted)
    {
924
        QVector<KAEvent> events = dlg->events();