prefdlg.cpp 86.7 KB
Newer Older
1
2
3
/*
 *  prefdlg.cpp  -  program preferences dialog
 *  Program:  kalarm
4
 *  Copyright © 2001-2012 by David Jarvie <djarvie@kde.org>
5
 *
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.
 *
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
22
#include "kalarm.h"

23
#include "alarmcalendar.h"
24
#include "collectionmodel.h"
25
26
27
28
29
30
31
32
33
#include "alarmtimewidget.h"
#include "buttongroup.h"
#include "colourbutton.h"
#include "editdlg.h"
#include "editdlgtypes.h"
#include "fontcolour.h"
#include "functions.h"
#include "itembox.h"
#include "kalarmapp.h"
David Jarvie's avatar
David Jarvie committed
34
#include "kalocale.h"
35
36
37
38
#include "kamail.h"
#include "label.h"
#include "latecancel.h"
#include "mainwindow.h"
39
#include "messagebox.h"
40
41
42
43
44
45
46
47
48
49
50
#include "preferences.h"
#include "radiobutton.h"
#include "recurrenceedit.h"
#include "sounddlg.h"
#include "soundpicker.h"
#include "specialactions.h"
#include "stackedwidgets.h"
#include "timeedit.h"
#include "timespinbox.h"
#include "timezonecombo.h"
#include "traywindow.h"
Laurent Montel's avatar
Laurent Montel committed
51
52
#include "prefdlg_p.h"
#include "prefdlg.h"
53

David Jarvie's avatar
David Jarvie committed
54
55
#include "config-kdepim.h"

Laurent Montel's avatar
Laurent Montel committed
56
#include <kalarmcal/identities.h>
57

John Layt's avatar
John Layt committed
58
#include <KHolidays/HolidayRegion>
59
using namespace KHolidays;
60

Laurent Montel's avatar
Laurent Montel committed
61
#include <kpimtextedit/texttospeech.h>
62

63
#include <kglobal.h>
Laurent Montel's avatar
Laurent Montel committed
64
#include <KLocalizedString>
David Jarvie's avatar
David Jarvie committed
65
#include <kshell.h>
66
#include <klineedit.h>
Laurent Montel's avatar
Laurent Montel committed
67
#include <K4AboutData>
68
#include <kapplication.h>
69
#include <kiconloader.h>
70
#include <kstandardguiitem.h>
71
#include <ksystemtimezone.h>
Laurent Montel's avatar
Laurent Montel committed
72
#include <qicon.h>
Laurent Montel's avatar
Laurent Montel committed
73
#if KDEPIM_HAVE_X11
74
75
76
#include <kwindowinfo.h>
#include <kwindowsystem.h>
#endif
77
#include <ktoolinvocation.h>
David Jarvie's avatar
David Jarvie committed
78
#include <KHelpClient>
79

80
81
82
83
#include <QLabel>
#include <QCheckBox>
#include <QRadioButton>
#include <QPushButton>
David Jarvie's avatar
David Jarvie committed
84
#include <QTabWidget>
85
86
87
88
89
90
91
#include <QSpinBox>
#include <QGroupBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStyle>
#include <QResizeEvent>
Laurent Montel's avatar
Laurent Montel committed
92
#include <QStandardPaths>
93
#include <QComboBox>
Laurent Montel's avatar
Laurent Montel committed
94
#include "kalarm_debug.h"
David Jarvie's avatar
David Jarvie committed
95

96
using namespace KCalCore;
97
98
using namespace KAlarmCal;

99
100
static const char PREF_DIALOG_NAME[] = "PrefDialog";

101
102
// Command strings for executing commands in different types of terminal windows.
// %t = window title parameter
103
// %c = command to execute in terminal
104
105
106
// %w = command to execute in terminal, with 'sleep 86400' appended
// %C = temporary command file to execute in terminal
// %W = temporary command file to execute in terminal, with 'sleep 86400' appended
107
static QString xtermCommands[] = {
David Jarvie's avatar
David Jarvie committed
108
109
110
111
112
113
    QStringLiteral("xterm -sb -hold -title %t -e %c"),
    QStringLiteral("konsole --noclose -p tabtitle=%t -e ${SHELL:-sh} -c %c"),
    QStringLiteral("gnome-terminal -t %t -e %W"),
    QStringLiteral("eterm --pause -T %t -e %C"),    // some systems use eterm...
    QStringLiteral("Eterm --pause -T %t -e %C"),    // while some use Eterm
    QStringLiteral("rxvt -title %t -e ${SHELL:-sh} -c %w"),
114
    QString()       // end of list indicator - don't change!
115
116
};

117

118
119
120
121
/*=============================================================================
= Class KAlarmPrefDlg
=============================================================================*/

Laurent Montel's avatar
Laurent Montel committed
122
KAlarmPrefDlg* KAlarmPrefDlg::mInstance = Q_NULLPTR;
123
124
125

void KAlarmPrefDlg::display()
{
126
127
128
129
130
131
132
133
134
135
    if (!mInstance)
    {
        mInstance = new KAlarmPrefDlg;
        QSize s;
        if (KAlarm::readConfigWindowSize(PREF_DIALOG_NAME, s))
            mInstance->resize(s);
        mInstance->show();
    }
    else
    {
Laurent Montel's avatar
Laurent Montel committed
136
#if KDEPIM_HAVE_X11
137
        KWindowInfo info = KWindowInfo(mInstance->winId(), NET::WMGeometry | NET::WMDesktop);
138
        KWindowSystem::setCurrentDesktop(info.desktop());
139
#endif
140
141
142
143
        mInstance->setWindowState(mInstance->windowState() & ~Qt::WindowMinimized); // un-minimize it if necessary
        mInstance->raise();
        mInstance->activateWindow();
    }
144
145
}

David Jarvie's avatar
David Jarvie committed
146
KAlarmPrefDlg::KAlarmPrefDlg()
147
148
    : KPageDialog(),
      mShown(false)
149
{
150
    setAttribute(Qt::WA_DeleteOnClose);
David Jarvie's avatar
David Jarvie committed
151
    setObjectName(QStringLiteral("PrefDlg"));    // used by LikeBack
Laurent Montel's avatar
Laurent Montel committed
152
    setWindowTitle(i18nc("@title:window", "Configure"));
David Jarvie's avatar
David Jarvie committed
153
    setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Apply);
Laurent Montel's avatar
Port++    
Laurent Montel committed
154
    button(QDialogButtonBox::Ok)->setDefault(true); 
155
    setFaceType(List);
Laurent Montel's avatar
Port++    
Laurent Montel committed
156
    mTabScrollGroup = new StackedScrollGroup(this, this);
157
158
159
160

    mMiscPage = new MiscPrefTab(mTabScrollGroup);
    mMiscPageItem = new KPageWidgetItem(mMiscPage, i18nc("@title:tab General preferences", "General"));
    mMiscPageItem->setHeader(i18nc("@title General preferences", "General"));
161
    mMiscPageItem->setIcon(QIcon::fromTheme(QStringLiteral("preferences-other")));
162
163
164
165
166
    addPage(mMiscPageItem);

    mTimePage = new TimePrefTab(mTabScrollGroup);
    mTimePageItem = new KPageWidgetItem(mTimePage, i18nc("@title:tab", "Time & Date"));
    mTimePageItem->setHeader(i18nc("@title", "Time and Date"));
167
    mTimePageItem->setIcon(QIcon::fromTheme(QStringLiteral("preferences-system-time")));
168
169
170
171
172
    addPage(mTimePageItem);

    mStorePage = new StorePrefTab(mTabScrollGroup);
    mStorePageItem = new KPageWidgetItem(mStorePage, i18nc("@title:tab", "Storage"));
    mStorePageItem->setHeader(i18nc("@title", "Alarm Storage"));
173
    mStorePageItem->setIcon(QIcon::fromTheme(QStringLiteral("system-file-manager")));
174
175
176
177
178
    addPage(mStorePageItem);

    mEmailPage = new EmailPrefTab(mTabScrollGroup);
    mEmailPageItem = new KPageWidgetItem(mEmailPage, i18nc("@title:tab Email preferences", "Email"));
    mEmailPageItem->setHeader(i18nc("@title", "Email Alarm Settings"));
179
    mEmailPageItem->setIcon(QIcon::fromTheme(QStringLiteral("internet-mail")));
180
181
182
183
184
    addPage(mEmailPageItem);

    mViewPage = new ViewPrefTab(mTabScrollGroup);
    mViewPageItem = new KPageWidgetItem(mViewPage, i18nc("@title:tab", "View"));
    mViewPageItem->setHeader(i18nc("@title", "View Settings"));
185
    mViewPageItem->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-theme")));
186
187
188
189
190
    addPage(mViewPageItem);

    mEditPage = new EditPrefTab(mTabScrollGroup);
    mEditPageItem = new KPageWidgetItem(mEditPage, i18nc("@title:tab", "Edit"));
    mEditPageItem->setHeader(i18nc("@title", "Default Alarm Edit Settings"));
191
    mEditPageItem->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
192
    addPage(mEditPageItem);
Laurent Montel's avatar
Laurent Montel committed
193
194
195
196
197
    connect(button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &KAlarmPrefDlg::slotOk);
    connect(button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &KAlarmPrefDlg::slotCancel);
    connect(button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &KAlarmPrefDlg::slotApply);
    connect(button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, this, &KAlarmPrefDlg::slotDefault);
    connect(button(QDialogButtonBox::Help), &QAbstractButton::clicked, this, &KAlarmPrefDlg::slotHelp);
198
199
    restore(false);
    adjustSize();
200
201
202
203
}

KAlarmPrefDlg::~KAlarmPrefDlg()
{
Laurent Montel's avatar
Laurent Montel committed
204
    mInstance = Q_NULLPTR;
205
206
207
208
}

void KAlarmPrefDlg::slotHelp()
{
David Jarvie's avatar
David Jarvie committed
209
    KHelpClient::invokeHelp(QStringLiteral("preferences"));
210
211
}

212
// Apply the preferences that are currently selected
213
214
void KAlarmPrefDlg::slotApply()
{
Laurent Montel's avatar
Laurent Montel committed
215
    qCDebug(KALARM_LOG);
216
217
218
219
    QString errmsg = mEmailPage->validate();
    if (!errmsg.isEmpty())
    {
        setCurrentPage(mEmailPageItem);
220
        if (KAMessageBox::warningYesNo(this, errmsg) != KMessageBox::Yes)
221
222
223
224
225
226
227
228
229
        {
            mValid = false;
            return;
        }
    }
    errmsg = mEditPage->validate();
    if (!errmsg.isEmpty())
    {
        setCurrentPage(mEditPageItem);
230
        KAMessageBox::sorry(this, errmsg);
231
232
233
234
235
236
237
238
239
240
        mValid = false;
        return;
    }
    mValid = true;
    mEmailPage->apply(false);
    mViewPage->apply(false);
    mEditPage->apply(false);
    mStorePage->apply(false);
    mTimePage->apply(false);
    mMiscPage->apply(false);
Laurent Montel's avatar
Laurent Montel committed
241
    Preferences::self()->save();
242
243
}

244
// Apply the preferences that are currently selected
245
246
void KAlarmPrefDlg::slotOk()
{
Laurent Montel's avatar
Laurent Montel committed
247
    qCDebug(KALARM_LOG);
248
249
250
    mValid = true;
    slotApply();
    if (mValid)
Laurent Montel's avatar
Laurent Montel committed
251
        QDialog::accept();
252
253
}

254
// Discard the current preferences and close the dialog
255
256
void KAlarmPrefDlg::slotCancel()
{
Laurent Montel's avatar
Laurent Montel committed
257
    qCDebug(KALARM_LOG);
258
    restore(false);
Laurent Montel's avatar
Laurent Montel committed
259
    KPageDialog::reject();
David Jarvie's avatar
David Jarvie committed
260
261
}

262
263
264
// Reset all controls to the application defaults
void KAlarmPrefDlg::slotDefault()
{
265
266
    switch (KAMessageBox::questionYesNoCancel(this, i18nc("@info", "Reset all tabs to their default values, or only reset the current tab?"),
                                              QString(),
267
                                            KGuiItem(i18nc("@action:button Reset ALL tabs", "&All")),
268
269
270
271
272
273
274
                         KGuiItem(i18nc("@action:button Reset the CURRENT tab", "C&urrent"))))
    {
        case KMessageBox::Yes:
            restore(true);   // restore all tabs
            break;
        case KMessageBox::No:
            Preferences::self()->useDefaults(true);
275
            static_cast<PrefsTabBase*>(currentPage()->widget())->restore(true, false);
276
277
278
279
280
            Preferences::self()->useDefaults(false);
            break;
        default:
            break;
    }
281
282
}

David Jarvie's avatar
David Jarvie committed
283
// Discard the current preferences and use the present ones
David Jarvie's avatar
David Jarvie committed
284
void KAlarmPrefDlg::restore(bool defaults)
David Jarvie's avatar
David Jarvie committed
285
{
Laurent Montel's avatar
Laurent Montel committed
286
    qCDebug(KALARM_LOG) << (defaults ? "defaults" : "");
287
288
    if (defaults)
        Preferences::self()->useDefaults(true);
289
290
291
292
293
294
    mEmailPage->restore(defaults, true);
    mViewPage->restore(defaults, true);
    mEditPage->restore(defaults, true);
    mStorePage->restore(defaults, true);
    mTimePage->restore(defaults, true);
    mMiscPage->restore(defaults, true);
295
296
    if (defaults)
        Preferences::self()->useDefaults(false);
297
}
298

299
300
301
302
303
304
305
/******************************************************************************
* Return the minimum size for the dialog.
* If the minimum size would be too high to fit the desktop, the tab contents
* are made scrollable.
*/
QSize KAlarmPrefDlg::minimumSizeHint() const
{
306
307
308
309
310
311
312
313
314
315
316
317
318
    if (!mTabScrollGroup->sized())
    {
        QSize s = mTabScrollGroup->adjustSize();
        if (s.isValid())
        {
            if (mTabScrollGroup->heightReduction())
            {
                s = QSize(s.width(), s.height() - mTabScrollGroup->heightReduction());
                const_cast<KAlarmPrefDlg*>(this)->resize(s);
            }
            return s;
        }
    }
Laurent Montel's avatar
Laurent Montel committed
319
    return KPageDialog::minimumSizeHint();
320
321
}

322
323
void KAlarmPrefDlg::showEvent(QShowEvent* e)
{
Laurent Montel's avatar
Laurent Montel committed
324
    KPageDialog::showEvent(e);
325
326
327
328
329
    if (!mShown)
    {
        mTabScrollGroup->adjustSize(true);
        mShown = true;
    }
330
331
}

332
/******************************************************************************
David Jarvie's avatar
David Jarvie committed
333
334
* Called when the dialog's size has changed.
* Records the new size in the config file.
335
336
337
*/
void KAlarmPrefDlg::resizeEvent(QResizeEvent* re)
{
338
339
340
    if (isVisible())
        KAlarm::writeConfigWindowSize(PREF_DIALOG_NAME, re->size());
    KPageDialog::resizeEvent(re);
341
342
}

343
344
345
346

/*=============================================================================
= Class PrefsTabBase
=============================================================================*/
David Jarvie's avatar
David Jarvie committed
347
int PrefsTabBase::mIndentWidth = 0;
348

349
PrefsTabBase::PrefsTabBase(StackedScrollGroup* scrollGroup)
350
351
    : StackedScrollWidget(scrollGroup),
      mLabelsAligned(false)
352
{
353
354
355
356
    QFrame *topWidget = new QFrame(this);
    setWidget(topWidget);
    mTopLayout = new QVBoxLayout(topWidget);
    mTopLayout->setMargin(0);
357
    mTopLayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
358
359
360
361
362
363
364
    if (!mIndentWidth)
    {
        QRadioButton radio(this);
        QStyleOptionButton opt;
        opt.initFrom(&radio);
        mIndentWidth = style()->subElementRect(QStyle::SE_RadioButtonIndicator, &opt).width();
    }
365
366
367
368
}

void PrefsTabBase::apply(bool syncToDisc)
{
369
    if (syncToDisc)
Laurent Montel's avatar
Laurent Montel committed
370
        Preferences::self()->save();
371
372
}

373
374
void PrefsTabBase::addAlignedLabel(QLabel* label)
{
375
    mLabels += label;
376
377
378
379
}

void PrefsTabBase::showEvent(QShowEvent*)
{
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    if (!mLabelsAligned)
    {
        int wid = 0;
        int i;
        int end = mLabels.count();
        QList<int> xpos;
        for (i = 0;  i < end;  ++i)
        {
            int x = mLabels[i]->mapTo(this, QPoint(0, 0)).x();
            xpos += x;
            int w = x + mLabels[i]->sizeHint().width();
            if (w > wid)
                wid = w;
        }
        for (i = 0;  i < end;  ++i)
        {
            mLabels[i]->setFixedWidth(wid - xpos[i]);
            mLabels[i]->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        }
        mLabelsAligned = true;
    }
401
}
402
403
404
405
406
407


/*=============================================================================
= Class MiscPrefTab
=============================================================================*/

408
MiscPrefTab::MiscPrefTab(StackedScrollGroup* scrollGroup)
409
    : PrefsTabBase(scrollGroup)
410
{
411
412
    QGroupBox* group = new QGroupBox(i18nc("@title:group", "Run Mode"));
    topLayout()->addWidget(group);
413
    QVBoxLayout* vlayout = new QVBoxLayout(group);
414
415
    vlayout->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    vlayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
416
417
418

    // Start at login
    mAutoStart = new QCheckBox(i18nc("@option:check", "Start at login"), group);
419
    connect(mAutoStart, &QAbstractButton::clicked, this, &MiscPrefTab::slotAutostartClicked);
Laurent Montel's avatar
Laurent Montel committed
420
    mAutoStart->setWhatsThis(xi18nc("@info:whatsthis",
421
422
423
424
425
          "<para>Automatically start <application>KAlarm</application> whenever you start KDE.</para>"
          "<para>This option should always be checked unless you intend to discontinue use of <application>KAlarm</application>.</para>"));
    vlayout->addWidget(mAutoStart, 0, Qt::AlignLeft);

    mQuitWarn = new QCheckBox(i18nc("@option:check", "Warn before quitting"), group);
Laurent Montel's avatar
Laurent Montel committed
426
    mQuitWarn->setWhatsThis(xi18nc("@info:whatsthis", "Check to display a warning prompt before quitting <application>KAlarm</application>."));
427
428
429
    vlayout->addWidget(mQuitWarn, 0, Qt::AlignLeft);

    // Confirm alarm deletion?
430
431
432
433
    group = new QGroupBox(i18nc("@title:group", "Deletion"));
    topLayout()->addWidget(group);   // this is to allow left adjustment
    QVBoxLayout *box = new QVBoxLayout(group);
    mConfirmAlarmDeletion = new QCheckBox(i18nc("@option:check", "Confirm alarm deletions"));
434
435
    mConfirmAlarmDeletion->setMinimumSize(mConfirmAlarmDeletion->sizeHint());
    mConfirmAlarmDeletion->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation each time you delete an alarm."));
436
    box->addWidget(mConfirmAlarmDeletion);
437
438

    // Default alarm deferral time
439
440
441
    QWidget *widget = new QWidget;
    box->addWidget(widget);
    QHBoxLayout *hbox = new QHBoxLayout(widget);
442
    hbox->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
443
444
445
    QLabel* label = new QLabel(i18nc("@label:spinbox", "Default defer time interval:"));
    hbox->addWidget(label);
    mDefaultDeferTime = new TimeSpinBox(1, 5999);
446
    mDefaultDeferTime->setMinimumSize(mDefaultDeferTime->sizeHint());
447
448
449
    hbox->addWidget(mDefaultDeferTime);
    widget->setWhatsThis(i18nc("@info:whatsthis",
            "Enter the default time interval (hours & minutes) to defer alarms, used by the Defer Alarm dialog."));
450
    label->setBuddy(mDefaultDeferTime);
451
    hbox->addStretch(1);    // left adjust the controls
452
453

    // Terminal window to use for command alarms
454
    group = new QGroupBox(i18nc("@title:group", "Terminal for Command Alarms"));
455
    group->setWhatsThis(i18nc("@info:whatsthis", "Choose which application to use when a command alarm is executed in a terminal window"));
456
    topLayout()->addWidget(group);
457
    QGridLayout* grid = new QGridLayout(group);
458
459
    grid->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    grid->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
460
461
462
463
464
465
466
467
468
    int row = 0;

    mXtermType = new ButtonGroup(group);
    int index = 0;
    mXtermFirst = -1;
    for (mXtermCount = 0;  !xtermCommands[mXtermCount].isNull();  ++mXtermCount)
    {
        QString cmd = xtermCommands[mXtermCount];
        QStringList args = KShell::splitArgs(cmd);
469
        if (args.isEmpty()  ||  QStandardPaths::findExecutable(args[0]).isEmpty())
470
471
472
473
474
475
            continue;
        QRadioButton* radio = new QRadioButton(args[0], group);
        radio->setMinimumSize(radio->sizeHint());
        mXtermType->addButton(radio, mXtermCount);
        if (mXtermFirst < 0)
            mXtermFirst = mXtermCount;   // note the id of the first button
David Jarvie's avatar
David Jarvie committed
476
477
478
479
480
        cmd.replace(QStringLiteral("%t"), KComponentData::mainComponent().aboutData()->programName());
        cmd.replace(QStringLiteral("%c"), QStringLiteral("<command>"));
        cmd.replace(QStringLiteral("%w"), QStringLiteral("<command; sleep>"));
        cmd.replace(QStringLiteral("%C"), QStringLiteral("[command]"));
        cmd.replace(QStringLiteral("%W"), QStringLiteral("[command; sleep]"));
481
        radio->setWhatsThis(
Laurent Montel's avatar
Laurent Montel committed
482
                xi18nc("@info:whatsthis", "Check to execute command alarms in a terminal window by <icode>%1</icode>", cmd));
483
484
485
486
        grid->addWidget(radio, (row = index/3), index % 3, Qt::AlignLeft);
        ++index;
    }

Laurent Montel's avatar
Laurent Montel committed
487
    // QHBox used here doesn't allow the QLineEdit to expand!?
488
    QHBoxLayout* hlayout = new QHBoxLayout();
489
    hlayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
490
491
492
    grid->addLayout(hlayout, row + 1, 0, 1, 3, Qt::AlignLeft);
    QRadioButton* radio = new QRadioButton(i18nc("@option:radio Other terminal window command", "Other:"), group);
    hlayout->addWidget(radio);
493
    connect(radio, &QAbstractButton::toggled, this, &MiscPrefTab::slotOtherTerminalToggled);
494
495
496
    mXtermType->addButton(radio, mXtermCount);
    if (mXtermFirst < 0)
        mXtermFirst = mXtermCount;   // note the id of the first button
Laurent Montel's avatar
Laurent Montel committed
497
    mXtermCommand = new QLineEdit(group);
498
499
500
    mXtermCommand->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
    hlayout->addWidget(mXtermCommand);
    QString wt = 
Laurent Montel's avatar
Laurent Montel committed
501
          xi18nc("@info:whatsthis", "Enter the full command line needed to execute a command in your chosen terminal window. "
502
503
504
505
506
507
               "By default the alarm's command string will be appended to what you enter here. "
               "See the <application>KAlarm</application> Handbook for details of special codes to tailor the command line.");
    radio->setWhatsThis(wt);
    mXtermCommand->setWhatsThis(wt);

    topLayout()->addStretch();    // top adjust the widgets
508
509
}

510
void MiscPrefTab::restore(bool defaults, bool)
511
{
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
    mAutoStart->setChecked(defaults ? true : Preferences::autoStart());
    mQuitWarn->setChecked(Preferences::quitWarn());
    mConfirmAlarmDeletion->setChecked(Preferences::confirmAlarmDeletion());
    mDefaultDeferTime->setValue(Preferences::defaultDeferTime());
    QString xtermCmd = Preferences::cmdXTermCommand();
    int id = mXtermFirst;
    if (!xtermCmd.isEmpty())
    {
        for ( ;  id < mXtermCount;  ++id)
        {
            if (mXtermType->find(id)  &&  xtermCmd == xtermCommands[id])
                break;
        }
    }
    mXtermType->setButton(id);
    mXtermCommand->setEnabled(id == mXtermCount);
Laurent Montel's avatar
Laurent Montel committed
528
    mXtermCommand->setText(id == mXtermCount ? xtermCmd : QString());
529
530
531
532
}

void MiscPrefTab::apply(bool syncToDisc)
{
533
534
535
536
537
538
539
540
541
542
543
    // First validate anything entered in Other X-terminal command
    int xtermID = mXtermType->selectedId();
    if (xtermID >= mXtermCount)
    {
        QString cmd = mXtermCommand->text();
        if (cmd.isEmpty())
            xtermID = -1;       // 'Other' is only acceptable if it's non-blank
        else
        {
            QStringList args = KShell::splitArgs(cmd);
            cmd = args.isEmpty() ? QString() : args[0];
544
            if (QStandardPaths::findExecutable(cmd).isEmpty())
545
546
            {
                mXtermCommand->setFocus();
547
                if (KAMessageBox::warningContinueCancel(topLayout()->parentWidget(), xi18nc("@info", "Command to invoke terminal window not found: <command>%1</command>", cmd))
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
                                != KMessageBox::Continue)
                    return;
            }
        }
    }
    if (xtermID < 0)
    {
        xtermID = mXtermFirst;
        mXtermType->setButton(mXtermFirst);
    }

    if (mQuitWarn->isEnabled())
    {
        bool b = mQuitWarn->isChecked();
        if (b != Preferences::quitWarn())
            Preferences::setQuitWarn(b);
    }
    bool b = mAutoStart->isChecked();
    if (b != Preferences::autoStart())
    {
        Preferences::setAutoStart(b);
        Preferences::setAskAutoStart(true);  // cancel any start-at-login prompt suppression
        if (b)
            Preferences::setNoAutoStart(false);
        Preferences::setAutoStartChangedByUser(true);  // prevent prompting the user on quit, about start-at-login
    }
    b = mConfirmAlarmDeletion->isChecked();
    if (b != Preferences::confirmAlarmDeletion())
        Preferences::setConfirmAlarmDeletion(b);
    int i = mDefaultDeferTime->value();
    if (i != Preferences::defaultDeferTime())
        Preferences::setDefaultDeferTime(i);
    QString text = (xtermID < mXtermCount) ? xtermCommands[xtermID] : mXtermCommand->text();
    if (text != Preferences::cmdXTermCommand())
        Preferences::setCmdXTermCommand(text);
    PrefsTabBase::apply(syncToDisc);
584
585
}

586
void MiscPrefTab::slotAutostartClicked()
David Jarvie's avatar
David Jarvie committed
587
{
588
    if (!mAutoStart->isChecked()
589
    &&  KAMessageBox::warningYesNo(topLayout()->parentWidget(),
Laurent Montel's avatar
Laurent Montel committed
590
                                   xi18nc("@info", "You should not uncheck this option unless you intend to discontinue use of <application>KAlarm</application>"),
591
592
                                   QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()
                                  ) != KMessageBox::Yes)
593
        mAutoStart->setChecked(true);
594
595
}

David Jarvie's avatar
David Jarvie committed
596
597
void MiscPrefTab::slotOtherTerminalToggled(bool on)
{
598
    mXtermCommand->setEnabled(on);
David Jarvie's avatar
David Jarvie committed
599
600
601
}


602
603
604
605
/*=============================================================================
= Class TimePrefTab
=============================================================================*/

606
TimePrefTab::TimePrefTab(StackedScrollGroup* scrollGroup)
607
    : PrefsTabBase(scrollGroup)
608
{
609
    // Default time zone
610
    ItemBox* itemBox = new ItemBox();
611
    itemBox->setMargin(0);
612
613
614
615
616
    qobject_cast<QBoxLayout*>(topLayout())->addLayout(itemBox);

    QWidget *widget = new QWidget; // this is to control the QWhatsThis text display area
    itemBox->addWidget(widget);
    QHBoxLayout *box =  new QHBoxLayout(widget);
617
    box->setMargin(0);
618
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
619
620
    QLabel* label = new QLabel(i18nc("@label:listbox", "Time zone:"));
    box->addWidget(label);
621
    addAlignedLabel(label);
622
#if 1
623
    mTimeZone = new TimeZoneCombo(widget);
624
    mTimeZone->setMaxVisibleItems(15);
625
    box->addWidget(mTimeZone);
626
#else
627
628
629
630
631
    mTimeZone = new KComboBox(box);
    mTimeZone->setMaxVisibleItems(15);
    const KTimeZones::ZoneMap zones = KSystemTimeZones::zones();
    for (KTimeZones::ZoneMap::ConstIterator it = zones.constBegin();  it != zones.constEnd();  ++it)
        mTimeZone->addItem(it.key());
632
#endif
633
634
635
    widget->setWhatsThis(xi18nc("@info:whatsthis",
                                "Select the time zone which <application>KAlarm</application> should use "
                                "as its default for displaying and entering dates and times."));
636
637
638
639
    label->setBuddy(mTimeZone);
    itemBox->leftAlign();

    // Holiday region
640
    itemBox = new ItemBox();
641
    itemBox->setMargin(0);
642
643
644
645
646
    qobject_cast<QBoxLayout*>(topLayout())->addLayout(itemBox);

    widget = new QWidget;    // this is to control the QWhatsThis text display area
    itemBox->addWidget(widget);
    box = new QHBoxLayout(widget);
647
    box->setMargin(0);
648
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
649
    label = new QLabel(i18nc("@label:listbox", "Holiday region:"));
650
    addAlignedLabel(label);
651
652
    box->addWidget(label);
    mHolidays = new QComboBox();
653
    mHolidays->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
654
    box->addWidget(mHolidays);
655
656
    itemBox->leftAlign();
    label->setBuddy(mHolidays);
657
658
    widget->setWhatsThis(i18nc("@info:whatsthis",
                               "Select which holiday region to use"));
659
660
661
662
663
664

    QStringList regions = HolidayRegion::regionCodes();
    QMap<QString, QString> regionsMap;
    foreach (const QString& regionCode, regions)
    {
        QString name = HolidayRegion::name(regionCode);
665
        QString languageName = KLocale::global()->languageCodeToName(HolidayRegion::languageCode(regionCode));
666
667
668
669
670
671
672
673
674
675
676
677
        QString label = languageName.isEmpty() ? name : i18nc("Holiday region, region language", "%1 (%2)", name, languageName);
        regionsMap.insert(label, regionCode);
    }

    mHolidays->addItem(i18nc("No holiday region", "None"), QString());
    for (QMapIterator<QString, QString> it(regionsMap);  it.hasNext();  )
    {
        it.next();
        mHolidays->addItem(it.key(), it.value());
    }

    // Start-of-day time
678
    itemBox = new ItemBox();
679
    itemBox->setMargin(0);
680
681
682
683
684
    qobject_cast<QBoxLayout*>(topLayout())->addLayout(itemBox);

    widget = new QWidget;   // this is to control the QWhatsThis text display area
    itemBox->addWidget(widget);
    box = new QHBoxLayout(widget);
685
    box->setMargin(0);
686
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
687
    label = new QLabel(i18nc("@label:spinbox", "Start of day for date-only alarms:"));
688
    addAlignedLabel(label);
689
690
691
    box->addWidget(label);
    mStartOfDay = new TimeEdit();
    box->addWidget(mStartOfDay);
692
    label->setBuddy(mStartOfDay);
693
    widget->setWhatsThis(xi18nc("@info:whatsthis",
694
695
696
697
698
          "<para>The earliest time of day at which a date-only alarm will be triggered.</para>"
          "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
    itemBox->leftAlign();

    // Working hours
699
700
    QGroupBox* group = new QGroupBox(i18nc("@title:group", "Working Hours"));
    topLayout()->addWidget(group);
701
    QBoxLayout* layout = new QVBoxLayout(group);
702
703
    layout->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    layout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
704
705
706
707

    QWidget* daybox = new QWidget(group);   // this is to control the QWhatsThis text display area
    layout->addWidget(daybox);
    QGridLayout* wgrid = new QGridLayout(daybox);
708
    wgrid->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
709
    const KLocale* locale = KLocale::global();
710
711
712
713
714
715
716
717
718
719
    for (int i = 0;  i < 7;  ++i)
    {
        int day = KAlarm::localeDayInWeek_to_weekDay(i);
        mWorkDays[i] = new QCheckBox(KAlarm::weekDayName(day, locale), daybox);
        wgrid->addWidget(mWorkDays[i], i/3, i%3, Qt::AlignLeft);
    }
    daybox->setWhatsThis(i18nc("@info:whatsthis", "Check the days in the week which are work days"));

    itemBox = new ItemBox(group);
    itemBox->setMargin(0);
720
721
722
723
724
    layout->addLayout(itemBox);

    widget = new QWidget;  // this is to control the QWhatsThis text display area
    itemBox->addWidget(widget);
    box = new QHBoxLayout(widget);
725
    box->setMargin(0);
726
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
727
    label = new QLabel(i18nc("@label:spinbox", "Daily start time:"));
728
    addAlignedLabel(label);
729
730
731
    box->addWidget(label);
    mWorkStart = new TimeEdit();
    box->addWidget(mWorkStart);
732
    label->setBuddy(mWorkStart);
733
734
735
    widget->setWhatsThis(xi18nc("@info:whatsthis",
            "<para>Enter the start time of the working day.</para>"
            "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
736
737
738
739
    itemBox->leftAlign();

    itemBox = new ItemBox(group);
    itemBox->setMargin(0);
740
741
742
743
744
    layout->addLayout(itemBox);

    widget = new QWidget;   // this is to control the QWhatsThis text display area
    itemBox->addWidget(widget);
    box = new QHBoxLayout(widget);
745
    box->setMargin(0);
746
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
747
    label = new QLabel(i18nc("@label:spinbox", "Daily end time:"));
748
    addAlignedLabel(label);
749
750
751
    box->addWidget(label);
    mWorkEnd = new TimeEdit();
    box->addWidget(mWorkEnd);
752
    label->setBuddy(mWorkEnd);
753
    widget->setWhatsThis(xi18nc("@info:whatsthis",
754
755
756
757
758
          "<para>Enter the end time of the working day.</para>"
          "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
    itemBox->leftAlign();

    // KOrganizer event duration
759
760
    group = new QGroupBox(i18nc("@title:group", "KOrganizer"));
    topLayout()->addWidget(group);
761
    layout = new QVBoxLayout(group);
762
763
    layout->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    layout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
764

765
766
767
    widget = new QWidget;   // this is to control the QWhatsThis text display area
    layout->addWidget(widget);
    box = new QHBoxLayout(widget);
768
    box->setMargin(0);
769
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
770
    label = new QLabel(i18nc("@label:spinbox", "KOrganizer event duration:"));
771
    addAlignedLabel(label);
772
773
    box->addWidget(label);
    mKOrgEventDuration = new TimeSpinBox(0, 5999);
774
    mKOrgEventDuration->setMinimumSize(mKOrgEventDuration->sizeHint());
775
776
777
778
    box->addWidget(mKOrgEventDuration);
    widget->setWhatsThis(xi18nc("@info:whatsthis",
            "<para>Enter the event duration in hours and minutes, for alarms which are copied to KOrganizer.</para>"
            "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
779
    label->setBuddy(mKOrgEventDuration);
780
    box->addStretch(1);    // left adjust the controls
781
782

    topLayout()->addStretch();    // top adjust the widgets
783
784
}

785
void TimePrefTab::restore(bool, bool)
786
787
{
#if 1
788
    mTimeZone->setTimeZone(Preferences::timeZone());
789
#else
790
791
792
793
794
795
796
797
798
799
800
801
    int tzindex = 0;
    KTimeZone tz = Preferences::timeZone();
    if (tz.isValid())
    {
        QString zone = tz.name();
        int count = mTimeZone->count();
        while (tzindex < count  &&  mTimeZone->itemText(tzindex) != zone)
            ++tzindex;
        if (tzindex >= count)
            tzindex = 0;
    }
    mTimeZone->setCurrentIndex(tzindex);
802
#endif
803
804
805
806
807
808
809
810
811
812
813
814
    int i = Preferences::holidays().isValid() ? mHolidays->findData(Preferences::holidays().regionCode()) : 0;
    mHolidays->setCurrentIndex(i);
    mStartOfDay->setValue(Preferences::startOfDay());
    mWorkStart->setValue(Preferences::workDayStart());
    mWorkEnd->setValue(Preferences::workDayEnd());
    QBitArray days = Preferences::workDays();
    for (int i = 0;  i < 7;  ++i)
    {
        bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1);
        mWorkDays[i]->setChecked(x);
    }
    mKOrgEventDuration->setValue(Preferences::kOrgEventDuration());
815
816
817
818
819
}

void TimePrefTab::apply(bool syncToDisc)
{
#if 1
820
821
822
    KTimeZone tz = mTimeZone->timeZone();
    if (tz.isValid())
        Preferences::setTimeZone(tz);
823
#else
824
825
826
    KTimeZone tz = KSystemTimeZones::zone(mTimeZone->currentText());
    if (tz.isValid()  &&  tz != Preferences::timeZone())
        Preferences::setTimeZone(tz);
827
#endif
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
    QString hol = mHolidays->itemData(mHolidays->currentIndex()).toString();
    if (hol != Preferences::holidays().regionCode())
        Preferences::setHolidayRegion(hol);
    int t = mStartOfDay->value();
    QTime sodt(t/60, t%60, 0);
    if (sodt != Preferences::startOfDay())
        Preferences::setStartOfDay(sodt);
    t = mWorkStart->value();
    Preferences::setWorkDayStart(QTime(t/60, t%60, 0));
    t = mWorkEnd->value();
    Preferences::setWorkDayEnd(QTime(t/60, t%60, 0));
    QBitArray workDays(7);
    for (int i = 0;  i < 7;  ++i)
        if (mWorkDays[i]->isChecked())
            workDays.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1);
    Preferences::setWorkDays(workDays);
    Preferences::setKOrgEventDuration(mKOrgEventDuration->value());
    t = mKOrgEventDuration->value();
    if (t != Preferences::kOrgEventDuration())
        Preferences::setKOrgEventDuration(t);
    PrefsTabBase::apply(syncToDisc);
849
850
851
}


David Jarvie's avatar
David Jarvie committed
852
853
854
855
/*=============================================================================
= Class StorePrefTab
=============================================================================*/

856
StorePrefTab::StorePrefTab(StackedScrollGroup* scrollGroup)
857
858
    : PrefsTabBase(scrollGroup),
      mCheckKeepChanges(false)
David Jarvie's avatar
David Jarvie committed
859
{
860
    // Which resource to save to
861
862
    QGroupBox* group = new QGroupBox(i18nc("@title:group", "New Alarms && Templates"));
    topLayout()->addWidget(group);
863
864
    QButtonGroup* bgroup = new QButtonGroup(group);
    QBoxLayout* layout = new QVBoxLayout(group);
865
866
    layout->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    layout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
867
868
869
870
871
872
873

    mDefaultResource = new QRadioButton(i18nc("@option:radio", "Store in default calendar"), group);
    bgroup->addButton(mDefaultResource);
    mDefaultResource->setWhatsThis(i18nc("@info:whatsthis", "Add all new alarms and alarm templates to the default calendars, without prompting."));
    layout->addWidget(mDefaultResource, 0, Qt::AlignLeft);
    mAskResource = new QRadioButton(i18nc("@option:radio", "Prompt for which calendar to store in"), group);
    bgroup->addButton(mAskResource);
Laurent Montel's avatar
Laurent Montel committed
874
    mAskResource->setWhatsThis(xi18nc("@info:whatsthis",
875
876
877
878
879
          "<para>When saving a new alarm or alarm template, prompt for which calendar to store it in, if there is more than one active calendar.</para>"
          "<para>Note that archived alarms are always stored in the default archived alarm calendar.</para>"));
    layout->addWidget(mAskResource, 0, Qt::AlignLeft);

    // Archived alarms
880
881
    group = new QGroupBox(i18nc("@title:group", "Archived Alarms"));
    topLayout()->addWidget(group);
882
    QGridLayout* grid = new QGridLayout(group);
883
884
    grid->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    grid->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
885
886
887
    grid->setColumnStretch(1, 1);
    grid->setColumnMinimumWidth(0, indentWidth());
    mKeepArchived = new QCheckBox(i18nc("@option:check", "Keep alarms after expiry"), group);
888
    connect(mKeepArchived, &QAbstractButton::toggled, this, &StorePrefTab::slotArchivedToggled);
889
890
891
892
    mKeepArchived->setWhatsThis(
          i18nc("@info:whatsthis", "Check to archive alarms after expiry or deletion (except deleted alarms which were never triggered)."));
    grid->addWidget(mKeepArchived, 0, 0, 1, 2, Qt::AlignLeft);

893
894
    QWidget *widget = new QWidget;
    QHBoxLayout *box = new QHBoxLayout(widget);
895
    box->setMargin(0);
896
    box->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
897
    mPurgeArchived = new QCheckBox(i18nc("@option:check", "Discard archived alarms after:"));
898
    mPurgeArchived->setMinimumSize(mPurgeArchived->sizeHint());
899
    box->addWidget(mPurgeArchived);
900
    connect(mPurgeArchived, &QAbstractButton::toggled, this, &StorePrefTab::slotArchivedToggled);
901
    mPurgeAfter = new SpinBox();
902
903
904
    mPurgeAfter->setMinimum(1);
    mPurgeAfter->setSingleShiftStep(10);
    mPurgeAfter->setMinimumSize(mPurgeAfter->sizeHint());
905
906
    box->addWidget(mPurgeAfter);
    mPurgeAfterLabel = new QLabel(i18nc("@label Time unit for user-entered number", "days"));
907
908
    mPurgeAfterLabel->setMinimumSize(mPurgeAfterLabel->sizeHint());
    mPurgeAfterLabel->setBuddy(mPurgeAfter);
909
910
911
    box->addWidget(mPurgeAfterLabel);
    widget->setWhatsThis(i18nc("@info:whatsthis", "Uncheck to store archived alarms indefinitely. Check to enter how long archived alarms should be stored."));
    grid->addWidget(widget, 1, 1, Qt::AlignLeft);
912
913

    mClearArchived = new QPushButton(i18nc("@action:button", "Clear Archived Alarms"), group);
914
    connect(mClearArchived, &QAbstractButton::clicked, this, &StorePrefTab::slotClearArchived);
915
    mClearArchived->setWhatsThis((CollectionControlModel::enabledCollections(CalEvent::ARCHIVED, false).count() <= 1)
916
917
918
            ? i18nc("@info:whatsthis", "Delete all existing archived alarms.")
            : i18nc("@info:whatsthis", "Delete all existing archived alarms (from the default archived alarm calendar only)."));
    grid->addWidget(mClearArchived, 2, 1, Qt::AlignLeft);
David Jarvie's avatar
David Jarvie committed
919

920
    topLayout()->addStretch();    // top adjust the widgets
David Jarvie's avatar
David Jarvie committed
921
922
}

923
void StorePrefTab::restore(bool defaults, bool)
David Jarvie's avatar
David Jarvie committed
924
{
925
926
927
928
929
930
931
932
933
934
    mCheckKeepChanges = defaults;
    if (Preferences::askResource())
        mAskResource->setChecked(true);
    else
        mDefaultResource->setChecked(true);
    int keepDays = Preferences::archivedKeepDays();
    if (!defaults)
        mOldKeepArchived = keepDays;
    setArchivedControls(keepDays);
    mCheckKeepChanges = true;
David Jarvie's avatar
David Jarvie committed
935
936
937
938
}

void StorePrefTab::apply(bool syncToDisc)
{
939
940
941
942
943
944
945
    bool b = mAskResource->isChecked();
    if (b != Preferences::askResource())
        Preferences::setAskResource(mAskResource->isChecked());
    int days = !mKeepArchived->isChecked() ? 0 : mPurgeArchived->isChecked() ? mPurgeAfter->value() : -1;
    if (days != Preferences::archivedKeepDays())
        Preferences::setArchivedKeepDays(days);
    PrefsTabBase::apply(syncToDisc);
David Jarvie's avatar
David Jarvie committed
946
947
948
}

void StorePrefTab::setArchivedControls(int purgeDays)
949
{
950
951
952
953
    mKeepArchived->setChecked(purgeDays);
    mPurgeArchived->setChecked(purgeDays > 0);
    mPurgeAfter->setValue(purgeDays > 0 ? purgeDays : 0);
    slotArchivedToggled(true);
954
955
}

David Jarvie's avatar
David Jarvie committed
956
void StorePrefTab::slotArchivedToggled(bool)
957
{
958
959
    bool keep = mKeepArchived->isChecked();
    if (keep  &&  !mOldKeepArchived  &&  mCheckKeepChanges
960
    &&  !CollectionControlModel::getStandard(CalEvent::ARCHIVED).isValid())
961
    {
962
        KAMessageBox::sorry(topLayout()->parentWidget(),
Laurent Montel's avatar
Laurent Montel committed
963
             xi18nc("@info", "<para>A default calendar is required in order to archive alarms, but none is currently enabled.</para>"
964
965
966
967
968
969
970
971
972
973
                  "<para>If you wish to keep expired alarms, please first use the calendars view to select a default "
                  "archived alarms calendar.</para>"));
        mKeepArchived->setChecked(false);
        return;
    }
    mOldKeepArchived = keep;
    mPurgeArchived->setEnabled(keep);
    mPurgeAfter->setEnabled(keep && mPurgeArchived->isChecked());
    mPurgeAfterLabel->setEnabled(keep);
    mClearArchived->setEnabled(keep);
974
975
}

David Jarvie's avatar
David Jarvie committed
976
void StorePrefTab::slotClearArchived()
977
{
978
    bool single = CollectionControlModel::enabledCollections(CalEvent::ARCHIVED, false).count() <= 1;
979
980
981
    if (KAMessageBox::warningContinueCancel(topLayout()->parentWidget(),
                                            single ? i18nc("@info", "Do you really want to delete all archived alarms?")
                                                   : i18nc("@info", "Do you really want to delete all alarms in the default archived alarm calendar?"))
982
983
984
            != KMessageBox::Continue)
        return;
    theApp()->purgeAll();
985
986
}

David Jarvie's avatar
David Jarvie committed
987
988
989
990
991

/*=============================================================================
= Class EmailPrefTab
=============================================================================*/

992
EmailPrefTab::EmailPrefTab(StackedScrollGroup* scrollGroup)
993
994
995
    : PrefsTabBase(scrollGroup),
      mAddressChanged(false),
      mBccAddressChanged(false)
David Jarvie's avatar
David Jarvie committed
996
{
997
998
999
    QWidget *widget = new QWidget;
    topLayout()->addWidget(widget);
    QHBoxLayout *box = new QHBoxLayout(widget);
1000
    box->setSpacing(2 * style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
1001
1002
1003
    QLabel *label = new QLabel(i18nc("@label", "Email client:"));
    box->addWidget(label);
    mEmailClient = new ButtonGroup(widget);
1004
1005
    QString kmailOption = i18nc("@option:radio", "KMail");
    QString sendmailOption = i18nc("@option:radio", "Sendmail");
1006
    mKMailButton = new RadioButton(kmailOption);
1007
    mKMailButton->setMinimumSize(mKMailButton->sizeHint());
1008
    box->addWidget(mKMailButton);
1009
    mEmailClient->addButton(mKMailButton, Preferences::kmail);
1010
    mSendmailButton = new RadioButton(sendmailOption);
1011
    mSendmailButton->setMinimumSize(mSendmailButton->sizeHint());
1012
    box->addWidget(mSendmailButton);
1013
    mEmailClient->addButton(mSendmailButton, Preferences::sendmail);
1014
    connect(mEmailClient, &ButtonGroup::buttonSet, this, &EmailPrefTab::slotEmailClientChanged);
1015
    widget->setWhatsThis(xi18nc("@info:whatsthis",
1016
1017
1018
1019
1020
1021
          "<para>Choose how to send email when an email alarm is triggered."
          "<list><item><interface>%1</interface>: The email is sent automatically via <application>KMail</application>. <application>KMail</application> is started first if necessary.</item>"
          "<item><interface>%2</interface>: The email is sent automatically. This option will only work if "
          "your system is configured to use <application>sendmail</application> or a sendmail compatible mail transport agent.</item></list></para>",
          kmailOption, sendmailOption));

1022
1023
1024
1025
    widget = new QWidget;  // this is to allow left adjustment
    topLayout()->addWidget(widget);
    box = new QHBoxLayout(widget);
    mEmailCopyToKMail = new QCheckBox(xi18nc("@option:check", "Copy sent emails into <application>KMail</application>'s <resource>%1</resource> folder", KAMail::i18n_sent_mail()));
Laurent Montel's avatar
Laurent Montel committed
1026
    mEmailCopyToKMail->setWhatsThis(xi18nc("@info:whatsthis", "After sending an email, store a copy in <application>KMail</application>'s <resource>%1</resource> folder", KAMail::i18n_sent_mail()));
1027
1028
    box->addWidget(mEmailCopyToKMail);
    box->setStretchFactor(new QWidget(widget), 1);    // left adjust the controls
1029

1030
1031
1032
1033
    widget = new QWidget;   // this is to allow left adjustment
    topLayout()->addWidget(widget);
    box = new QHBoxLayout(widget);
    mEmailQueuedNotify = new QCheckBox(i18nc("@option:check", "Notify when remote emails are queued"));
1034
1035
1036
    mEmailQueuedNotify->setWhatsThis(
          i18nc("@info:whatsthis", "Display a notification message whenever an email alarm has queued an email for sending to a remote system. "
               "This could be useful if, for example, you have a dial-up connection, so that you can then ensure that the email is actually transmitted."));
1037
1038
    box->addWidget(mEmailQueuedNotify);
    box->setStretchFactor(new QWidget(widget), 1);    // left adjust the controls
1039
1040

    // Your Email Address group box
1041
1042
    QGroupBox* group = new QGroupBox(i18nc("@title:group", "Your Email Address"));
    topLayout()->addWidget(group);
1043
    QGridLayout* grid = new QGridLayout(group);
1044
1045
    grid->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
    grid->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));