Build with clang.
[kdepim.git] / kalarm / prefdlg.cpp
blobc2c51622e54f2a6d04da44b5282922b97055bb34
1 /*
2 * prefdlg.cpp - program preferences dialog
3 * Program: kalarm
4 * Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "kalarm.h"
23 #include "alarmcalendar.h"
24 #ifdef USE_AKONADI
25 #include "collectionmodel.h"
26 #else
27 #include "alarmresources.h"
28 #endif
29 #include "alarmtimewidget.h"
30 #include "buttongroup.h"
31 #include "colourbutton.h"
32 #include "editdlg.h"
33 #include "editdlgtypes.h"
34 #include "fontcolour.h"
35 #include "functions.h"
36 #include "identities.h"
37 #include "itembox.h"
38 #include "kalarmapp.h"
39 #include "kalocale.h"
40 #include "kamail.h"
41 #include "label.h"
42 #include "latecancel.h"
43 #include "mainwindow.h"
44 #include "messagebox.h"
45 #include "preferences.h"
46 #include "radiobutton.h"
47 #include "recurrenceedit.h"
48 #include "sounddlg.h"
49 #include "soundpicker.h"
50 #include "specialactions.h"
51 #include "stackedwidgets.h"
52 #include "timeedit.h"
53 #include "timespinbox.h"
54 #include "timezonecombo.h"
55 #include "traywindow.h"
56 #include "prefdlg_p.moc"
57 #include "prefdlg.moc"
59 #include <kholidays/holidays.h>
60 using namespace KHolidays;
62 #include <kvbox.h>
63 #include <kglobal.h>
64 #include <klocale.h>
65 #include <kstandarddirs.h>
66 #include <kshell.h>
67 #include <klineedit.h>
68 #include <kaboutdata.h>
69 #include <kapplication.h>
70 #include <kiconloader.h>
71 #include <kcombobox.h>
72 #include <ktabwidget.h>
73 #include <kstandardguiitem.h>
74 #include <ksystemtimezone.h>
75 #include <kicon.h>
76 #ifdef Q_WS_X11
77 #include <kwindowinfo.h>
78 #include <kwindowsystem.h>
79 #endif
80 #include <ktoolinvocation.h>
81 #include <kdebug.h>
83 #include <QLabel>
84 #include <QCheckBox>
85 #include <QRadioButton>
86 #include <QPushButton>
87 #include <QSpinBox>
88 #include <QGroupBox>
89 #include <QGridLayout>
90 #include <QHBoxLayout>
91 #include <QVBoxLayout>
92 #include <QStyle>
93 #include <QResizeEvent>
94 #include <QTimer>
96 static const char PREF_DIALOG_NAME[] = "PrefDialog";
98 // Command strings for executing commands in different types of terminal windows.
99 // %t = window title parameter
100 // %c = command to execute in terminal
101 // %w = command to execute in terminal, with 'sleep 86400' appended
102 // %C = temporary command file to execute in terminal
103 // %W = temporary command file to execute in terminal, with 'sleep 86400' appended
104 static QString xtermCommands[] = {
105 QLatin1String("xterm -sb -hold -title %t -e %c"),
106 QLatin1String("konsole --noclose -p tabtitle=%t -e ${SHELL:-sh} -c %c"),
107 QLatin1String("gnome-terminal -t %t -e %W"),
108 QLatin1String("eterm --pause -T %t -e %C"), // some systems use eterm...
109 QLatin1String("Eterm --pause -T %t -e %C"), // while some use Eterm
110 QLatin1String("rxvt -title %t -e ${SHELL:-sh} -c %w"),
111 QString() // end of list indicator - don't change!
115 /*=============================================================================
116 = Class KAlarmPrefDlg
117 =============================================================================*/
119 KAlarmPrefDlg* KAlarmPrefDlg::mInstance = 0;
121 void KAlarmPrefDlg::display()
123 if (!mInstance)
125 mInstance = new KAlarmPrefDlg;
126 QSize s;
127 if (KAlarm::readConfigWindowSize(PREF_DIALOG_NAME, s))
128 mInstance->resize(s);
129 mInstance->show();
131 else
133 #ifdef Q_WS_X11
134 KWindowInfo info = KWindowSystem::windowInfo(mInstance->winId(), NET::WMGeometry | NET::WMDesktop);
135 KWindowSystem::setCurrentDesktop(info.desktop());
136 #endif
137 mInstance->setWindowState(mInstance->windowState() & ~Qt::WindowMinimized); // un-minimize it if necessary
138 mInstance->raise();
139 mInstance->activateWindow();
143 KAlarmPrefDlg::KAlarmPrefDlg()
144 : KPageDialog(),
145 mShown(false)
147 setAttribute(Qt::WA_DeleteOnClose);
148 setObjectName("PrefDlg"); // used by LikeBack
149 setCaption(i18nc("@title:window", "Configure"));
150 setButtons(Help | Default | Ok | Apply | Cancel);
151 setDefaultButton(Ok);
152 setFaceType(List);
153 showButtonSeparator(true);
154 mTabScrollGroup = new StackedScrollGroup(this, this);
156 mMiscPage = new MiscPrefTab(mTabScrollGroup);
157 mMiscPageItem = new KPageWidgetItem(mMiscPage, i18nc("@title:tab General preferences", "General"));
158 mMiscPageItem->setHeader(i18nc("@title General preferences", "General"));
159 mMiscPageItem->setIcon(KIcon(DesktopIcon("preferences-other")));
160 addPage(mMiscPageItem);
162 mTimePage = new TimePrefTab(mTabScrollGroup);
163 mTimePageItem = new KPageWidgetItem(mTimePage, i18nc("@title:tab", "Time & Date"));
164 mTimePageItem->setHeader(i18nc("@title", "Time and Date"));
165 mTimePageItem->setIcon(KIcon(DesktopIcon("preferences-system-time")));
166 addPage(mTimePageItem);
168 mStorePage = new StorePrefTab(mTabScrollGroup);
169 mStorePageItem = new KPageWidgetItem(mStorePage, i18nc("@title:tab", "Storage"));
170 mStorePageItem->setHeader(i18nc("@title", "Alarm Storage"));
171 mStorePageItem->setIcon(KIcon(DesktopIcon("system-file-manager")));
172 addPage(mStorePageItem);
174 mEmailPage = new EmailPrefTab(mTabScrollGroup);
175 mEmailPageItem = new KPageWidgetItem(mEmailPage, i18nc("@title:tab Email preferences", "Email"));
176 mEmailPageItem->setHeader(i18nc("@title", "Email Alarm Settings"));
177 mEmailPageItem->setIcon(KIcon(DesktopIcon("internet-mail")));
178 addPage(mEmailPageItem);
180 mViewPage = new ViewPrefTab(mTabScrollGroup);
181 mViewPageItem = new KPageWidgetItem(mViewPage, i18nc("@title:tab", "View"));
182 mViewPageItem->setHeader(i18nc("@title", "View Settings"));
183 mViewPageItem->setIcon(KIcon(DesktopIcon("preferences-desktop-theme")));
184 addPage(mViewPageItem);
186 mEditPage = new EditPrefTab(mTabScrollGroup);
187 mEditPageItem = new KPageWidgetItem(mEditPage, i18nc("@title:tab", "Edit"));
188 mEditPageItem->setHeader(i18nc("@title", "Default Alarm Edit Settings"));
189 mEditPageItem->setIcon(KIcon(DesktopIcon("document-properties")));
190 addPage(mEditPageItem);
192 connect(this, SIGNAL(okClicked()), SLOT(slotOk()));
193 connect(this, SIGNAL(cancelClicked()), SLOT(slotCancel()));
194 connect(this, SIGNAL(applyClicked()), SLOT(slotApply()));
195 connect(this, SIGNAL(defaultClicked()), SLOT(slotDefault()));
196 connect(this, SIGNAL(helpClicked()), SLOT(slotHelp()));
197 restore(false);
198 adjustSize();
201 KAlarmPrefDlg::~KAlarmPrefDlg()
203 mInstance = 0;
206 void KAlarmPrefDlg::slotHelp()
208 KToolInvocation::invokeHelp("preferences");
211 // Apply the preferences that are currently selected
212 void KAlarmPrefDlg::slotApply()
214 kDebug();
215 QString errmsg = mEmailPage->validate();
216 if (!errmsg.isEmpty())
218 setCurrentPage(mEmailPageItem);
219 if (KAMessageBox::warningYesNo(this, errmsg) != KMessageBox::Yes)
221 mValid = false;
222 return;
225 errmsg = mEditPage->validate();
226 if (!errmsg.isEmpty())
228 setCurrentPage(mEditPageItem);
229 KAMessageBox::sorry(this, errmsg);
230 mValid = false;
231 return;
233 mValid = true;
234 mEmailPage->apply(false);
235 mViewPage->apply(false);
236 mEditPage->apply(false);
237 mStorePage->apply(false);
238 mTimePage->apply(false);
239 mMiscPage->apply(false);
240 Preferences::self()->writeConfig();
243 // Apply the preferences that are currently selected
244 void KAlarmPrefDlg::slotOk()
246 kDebug();
247 mValid = true;
248 slotApply();
249 if (mValid)
250 KDialog::accept();
253 // Discard the current preferences and close the dialog
254 void KAlarmPrefDlg::slotCancel()
256 kDebug();
257 restore(false);
258 KDialog::reject();
261 // Reset all controls to the application defaults
262 void KAlarmPrefDlg::slotDefault()
264 switch (KAMessageBox::questionYesNoCancel(this, i18nc("@info", "Reset all tabs to their default values, or only reset the current tab?"),
265 QString(),
266 KGuiItem(i18nc("@action:button Reset ALL tabs", "&All")),
267 KGuiItem(i18nc("@action:button Reset the CURRENT tab", "C&urrent"))))
269 case KMessageBox::Yes:
270 restore(true); // restore all tabs
271 break;
272 case KMessageBox::No:
273 Preferences::self()->useDefaults(true);
274 static_cast<PrefsTabBase*>(currentPage()->widget())->restore(true, false);
275 Preferences::self()->useDefaults(false);
276 break;
277 default:
278 break;
282 // Discard the current preferences and use the present ones
283 void KAlarmPrefDlg::restore(bool defaults)
285 kDebug() << (defaults ? "defaults" : "");
286 if (defaults)
287 Preferences::self()->useDefaults(true);
288 mEmailPage->restore(defaults, true);
289 mViewPage->restore(defaults, true);
290 mEditPage->restore(defaults, true);
291 mStorePage->restore(defaults, true);
292 mTimePage->restore(defaults, true);
293 mMiscPage->restore(defaults, true);
294 if (defaults)
295 Preferences::self()->useDefaults(false);
298 /******************************************************************************
299 * Return the minimum size for the dialog.
300 * If the minimum size would be too high to fit the desktop, the tab contents
301 * are made scrollable.
303 QSize KAlarmPrefDlg::minimumSizeHint() const
305 if (!mTabScrollGroup->sized())
307 QSize s = mTabScrollGroup->adjustSize();
308 if (s.isValid())
310 if (mTabScrollGroup->heightReduction())
312 s = QSize(s.width(), s.height() - mTabScrollGroup->heightReduction());
313 const_cast<KAlarmPrefDlg*>(this)->resize(s);
315 return s;
318 return KDialog::minimumSizeHint();
321 void KAlarmPrefDlg::showEvent(QShowEvent* e)
323 KDialog::showEvent(e);
324 if (!mShown)
326 mTabScrollGroup->adjustSize(true);
327 mShown = true;
331 /******************************************************************************
332 * Called when the dialog's size has changed.
333 * Records the new size in the config file.
335 void KAlarmPrefDlg::resizeEvent(QResizeEvent* re)
337 if (isVisible())
338 KAlarm::writeConfigWindowSize(PREF_DIALOG_NAME, re->size());
339 KPageDialog::resizeEvent(re);
343 /*=============================================================================
344 = Class PrefsTabBase
345 =============================================================================*/
346 int PrefsTabBase::mIndentWidth = 0;
348 PrefsTabBase::PrefsTabBase(StackedScrollGroup* scrollGroup)
349 : StackedScrollWidget(scrollGroup),
350 mLabelsAligned(false)
352 mTopWidget = new KVBox(this);
353 mTopWidget->setMargin(0);
354 mTopWidget->setSpacing(KDialog::spacingHint());
355 setWidget(mTopWidget);
356 if (!mIndentWidth)
358 QRadioButton radio(this);
359 QStyleOptionButton opt;
360 opt.initFrom(&radio);
361 mIndentWidth = style()->subElementRect(QStyle::SE_RadioButtonIndicator, &opt).width();
363 mTopLayout = qobject_cast<QVBoxLayout*>(mTopWidget->layout());
364 Q_ASSERT(mTopLayout);
367 void PrefsTabBase::apply(bool syncToDisc)
369 if (syncToDisc)
370 Preferences::self()->writeConfig();
373 void PrefsTabBase::addAlignedLabel(QLabel* label)
375 mLabels += label;
378 void PrefsTabBase::showEvent(QShowEvent*)
380 if (!mLabelsAligned)
382 int wid = 0;
383 int i;
384 int end = mLabels.count();
385 QList<int> xpos;
386 for (i = 0; i < end; ++i)
388 int x = mLabels[i]->mapTo(this, QPoint(0, 0)).x();
389 xpos += x;
390 int w = x + mLabels[i]->sizeHint().width();
391 if (w > wid)
392 wid = w;
394 for (i = 0; i < end; ++i)
396 mLabels[i]->setFixedWidth(wid - xpos[i]);
397 mLabels[i]->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
399 mLabelsAligned = true;
404 /*=============================================================================
405 = Class MiscPrefTab
406 =============================================================================*/
408 MiscPrefTab::MiscPrefTab(StackedScrollGroup* scrollGroup)
409 : PrefsTabBase(scrollGroup)
411 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Run Mode"), topWidget());
412 QVBoxLayout* vlayout = new QVBoxLayout(group);
413 vlayout->setMargin(KDialog::marginHint());
414 vlayout->setSpacing(KDialog::spacingHint());
416 // Start at login
417 mAutoStart = new QCheckBox(i18nc("@option:check", "Start at login"), group);
418 connect(mAutoStart, SIGNAL(clicked()), SLOT(slotAutostartClicked()));
419 mAutoStart->setWhatsThis(i18nc("@info:whatsthis",
420 "<para>Automatically start <application>KAlarm</application> whenever you start KDE.</para>"
421 "<para>This option should always be checked unless you intend to discontinue use of <application>KAlarm</application>.</para>"));
422 vlayout->addWidget(mAutoStart, 0, Qt::AlignLeft);
424 mQuitWarn = new QCheckBox(i18nc("@option:check", "Warn before quitting"), group);
425 mQuitWarn->setWhatsThis(i18nc("@info:whatsthis", "Check to display a warning prompt before quitting <application>KAlarm</application>."));
426 vlayout->addWidget(mQuitWarn, 0, Qt::AlignLeft);
428 group->setFixedHeight(group->sizeHint().height());
430 // Confirm alarm deletion?
431 KHBox* itemBox = new KHBox(topWidget()); // this is to allow left adjustment
432 itemBox->setMargin(0);
433 mConfirmAlarmDeletion = new QCheckBox(i18nc("@option:check", "Confirm alarm deletions"), itemBox);
434 mConfirmAlarmDeletion->setMinimumSize(mConfirmAlarmDeletion->sizeHint());
435 mConfirmAlarmDeletion->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation each time you delete an alarm."));
436 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
437 itemBox->setFixedHeight(itemBox->sizeHint().height());
439 // Default alarm deferral time
440 itemBox = new KHBox(topWidget()); // this is to allow left adjustment
441 KHBox* box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
442 box->setSpacing(KDialog::spacingHint());
443 QLabel* label = new QLabel(i18nc("@label:spinbox", "Default defer time interval:"), box);
444 mDefaultDeferTime = new TimeSpinBox(1, 5999, box);
445 mDefaultDeferTime->setMinimumSize(mDefaultDeferTime->sizeHint());
446 box->setWhatsThis(i18nc("@info:whatsthis",
447 "Enter the default time interval (hours & minutes) to defer alarms, used by the Defer Alarm dialog."));
448 label->setBuddy(mDefaultDeferTime);
449 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
450 itemBox->setFixedHeight(itemBox->sizeHint().height());
452 // Terminal window to use for command alarms
453 group = new QGroupBox(i18nc("@title:group", "Terminal for Command Alarms"), topWidget());
454 group->setWhatsThis(i18nc("@info:whatsthis", "Choose which application to use when a command alarm is executed in a terminal window"));
455 QGridLayout* grid = new QGridLayout(group);
456 grid->setMargin(KDialog::marginHint());
457 grid->setSpacing(KDialog::spacingHint());
458 int row = 0;
460 mXtermType = new ButtonGroup(group);
461 int index = 0;
462 mXtermFirst = -1;
463 for (mXtermCount = 0; !xtermCommands[mXtermCount].isNull(); ++mXtermCount)
465 QString cmd = xtermCommands[mXtermCount];
466 QStringList args = KShell::splitArgs(cmd);
467 if (args.isEmpty() || KStandardDirs::findExe(args[0]).isEmpty())
468 continue;
469 QRadioButton* radio = new QRadioButton(args[0], group);
470 radio->setMinimumSize(radio->sizeHint());
471 mXtermType->addButton(radio, mXtermCount);
472 if (mXtermFirst < 0)
473 mXtermFirst = mXtermCount; // note the id of the first button
474 cmd.replace("%t", KGlobal::mainComponent().aboutData()->programName());
475 cmd.replace("%c", "<command>");
476 cmd.replace("%w", "<command; sleep>");
477 cmd.replace("%C", "[command]");
478 cmd.replace("%W", "[command; sleep]");
479 radio->setWhatsThis(
480 i18nc("@info:whatsthis", "Check to execute command alarms in a terminal window by <icode>%1</icode>", cmd));
481 grid->addWidget(radio, (row = index/3), index % 3, Qt::AlignLeft);
482 ++index;
485 // QHBox used here doesn't allow the KLineEdit to expand!?
486 QHBoxLayout* hlayout = new QHBoxLayout();
487 hlayout->setSpacing(KDialog::spacingHint());
488 grid->addLayout(hlayout, row + 1, 0, 1, 3, Qt::AlignLeft);
489 QRadioButton* radio = new QRadioButton(i18nc("@option:radio Other terminal window command", "Other:"), group);
490 hlayout->addWidget(radio);
491 connect(radio, SIGNAL(toggled(bool)), SLOT(slotOtherTerminalToggled(bool)));
492 mXtermType->addButton(radio, mXtermCount);
493 if (mXtermFirst < 0)
494 mXtermFirst = mXtermCount; // note the id of the first button
495 mXtermCommand = new KLineEdit(group);
496 mXtermCommand->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
497 hlayout->addWidget(mXtermCommand);
498 QString wt =
499 i18nc("@info:whatsthis", "Enter the full command line needed to execute a command in your chosen terminal window. "
500 "By default the alarm's command string will be appended to what you enter here. "
501 "See the <application>KAlarm</application> Handbook for details of special codes to tailor the command line.");
502 radio->setWhatsThis(wt);
503 mXtermCommand->setWhatsThis(wt);
505 topLayout()->addStretch(); // top adjust the widgets
508 void MiscPrefTab::restore(bool defaults, bool)
510 mAutoStart->setChecked(defaults ? true : Preferences::autoStart());
511 mQuitWarn->setChecked(Preferences::quitWarn());
512 mConfirmAlarmDeletion->setChecked(Preferences::confirmAlarmDeletion());
513 mDefaultDeferTime->setValue(Preferences::defaultDeferTime());
514 QString xtermCmd = Preferences::cmdXTermCommand();
515 int id = mXtermFirst;
516 if (!xtermCmd.isEmpty())
518 for ( ; id < mXtermCount; ++id)
520 if (mXtermType->find(id) && xtermCmd == xtermCommands[id])
521 break;
524 mXtermType->setButton(id);
525 mXtermCommand->setEnabled(id == mXtermCount);
526 mXtermCommand->setText(id == mXtermCount ? xtermCmd : "");
529 void MiscPrefTab::apply(bool syncToDisc)
531 // First validate anything entered in Other X-terminal command
532 int xtermID = mXtermType->selectedId();
533 if (xtermID >= mXtermCount)
535 QString cmd = mXtermCommand->text();
536 if (cmd.isEmpty())
537 xtermID = -1; // 'Other' is only acceptable if it's non-blank
538 else
540 QStringList args = KShell::splitArgs(cmd);
541 cmd = args.isEmpty() ? QString() : args[0];
542 if (KStandardDirs::findExe(cmd).isEmpty())
544 mXtermCommand->setFocus();
545 if (KAMessageBox::warningContinueCancel(topWidget(), i18nc("@info", "Command to invoke terminal window not found: <command>%1</command>", cmd))
546 != KMessageBox::Continue)
547 return;
551 if (xtermID < 0)
553 xtermID = mXtermFirst;
554 mXtermType->setButton(mXtermFirst);
557 if (mQuitWarn->isEnabled())
559 bool b = mQuitWarn->isChecked();
560 if (b != Preferences::quitWarn())
561 Preferences::setQuitWarn(b);
563 bool b = mAutoStart->isChecked();
564 if (b != Preferences::autoStart())
566 Preferences::setAutoStart(b);
567 Preferences::setAskAutoStart(true); // cancel any start-at-login prompt suppression
568 if (b)
569 Preferences::setNoAutoStart(false);
570 Preferences::setAutoStartChangedByUser(true); // prevent prompting the user on quit, about start-at-login
572 b = mConfirmAlarmDeletion->isChecked();
573 if (b != Preferences::confirmAlarmDeletion())
574 Preferences::setConfirmAlarmDeletion(b);
575 int i = mDefaultDeferTime->value();
576 if (i != Preferences::defaultDeferTime())
577 Preferences::setDefaultDeferTime(i);
578 QString text = (xtermID < mXtermCount) ? xtermCommands[xtermID] : mXtermCommand->text();
579 if (text != Preferences::cmdXTermCommand())
580 Preferences::setCmdXTermCommand(text);
581 PrefsTabBase::apply(syncToDisc);
584 void MiscPrefTab::slotAutostartClicked()
586 if (!mAutoStart->isChecked()
587 && KAMessageBox::warningYesNo(topWidget(),
588 i18nc("@info", "You should not uncheck this option unless you intend to discontinue use of <application>KAlarm</application>"),
589 QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()
590 ) != KMessageBox::Yes)
591 mAutoStart->setChecked(true);
594 void MiscPrefTab::slotOtherTerminalToggled(bool on)
596 mXtermCommand->setEnabled(on);
600 /*=============================================================================
601 = Class TimePrefTab
602 =============================================================================*/
604 TimePrefTab::TimePrefTab(StackedScrollGroup* scrollGroup)
605 : PrefsTabBase(scrollGroup)
607 // Default time zone
608 ItemBox* itemBox = new ItemBox(topWidget());
609 itemBox->setMargin(0);
610 KHBox* box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
611 box->setMargin(0);
612 box->setSpacing(KDialog::spacingHint());
613 QLabel* label = new QLabel(i18nc("@label:listbox", "Time zone:"), box);
614 addAlignedLabel(label);
615 #if 1
616 mTimeZone = new TimeZoneCombo(box);
617 mTimeZone->setMaxVisibleItems(15);
618 #else
619 mTimeZone = new KComboBox(box);
620 mTimeZone->setMaxVisibleItems(15);
621 const KTimeZones::ZoneMap zones = KSystemTimeZones::zones();
622 for (KTimeZones::ZoneMap::ConstIterator it = zones.constBegin(); it != zones.constEnd(); ++it)
623 mTimeZone->addItem(it.key());
624 #endif
625 box->setWhatsThis(i18nc("@info:whatsthis",
626 "Select the time zone which <application>KAlarm</application> should use "
627 "as its default for displaying and entering dates and times."));
628 label->setBuddy(mTimeZone);
629 itemBox->leftAlign();
630 itemBox->setFixedHeight(box->sizeHint().height());
632 // Holiday region
633 itemBox = new ItemBox(topWidget());
634 itemBox->setMargin(0);
635 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
636 box->setMargin(0);
637 box->setSpacing(KDialog::spacingHint());
638 label = new QLabel(i18nc("@label:listbox", "Holiday region:"), box);
639 addAlignedLabel(label);
640 mHolidays = new KComboBox(box);
641 mHolidays->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
642 itemBox->leftAlign();
643 label->setBuddy(mHolidays);
644 box->setWhatsThis(i18nc("@info:whatsthis",
645 "Select which holiday region to use"));
647 QStringList regions = HolidayRegion::regionCodes();
648 QMap<QString, QString> regionsMap;
649 foreach (const QString& regionCode, regions)
651 QString name = HolidayRegion::name(regionCode);
652 QString languageName = KGlobal::locale()->languageCodeToName(HolidayRegion::languageCode(regionCode));
653 QString label = languageName.isEmpty() ? name : i18nc("Holiday region, region language", "%1 (%2)", name, languageName);
654 regionsMap.insert(label, regionCode);
657 mHolidays->addItem(i18nc("No holiday region", "None"), QString());
658 for (QMapIterator<QString, QString> it(regionsMap); it.hasNext(); )
660 it.next();
661 mHolidays->addItem(it.key(), it.value());
664 // Start-of-day time
665 itemBox = new ItemBox(topWidget());
666 itemBox->setMargin(0);
667 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
668 box->setMargin(0);
669 box->setSpacing(KDialog::spacingHint());
670 label = new QLabel(i18nc("@label:spinbox", "Start of day for date-only alarms:"), box);
671 addAlignedLabel(label);
672 mStartOfDay = new TimeEdit(box);
673 label->setBuddy(mStartOfDay);
674 box->setWhatsThis(i18nc("@info:whatsthis",
675 "<para>The earliest time of day at which a date-only alarm will be triggered.</para>"
676 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
677 itemBox->leftAlign();
678 itemBox->setFixedHeight(box->sizeHint().height());
680 // Working hours
681 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Working Hours"), topWidget());
682 QBoxLayout* layout = new QVBoxLayout(group);
683 layout->setMargin(KDialog::marginHint());
684 layout->setSpacing(KDialog::spacingHint());
686 QWidget* daybox = new QWidget(group); // this is to control the QWhatsThis text display area
687 layout->addWidget(daybox);
688 QGridLayout* wgrid = new QGridLayout(daybox);
689 wgrid->setSpacing(KDialog::spacingHint());
690 const KLocale* locale = KGlobal::locale();
691 for (int i = 0; i < 7; ++i)
693 int day = KAlarm::localeDayInWeek_to_weekDay(i);
694 mWorkDays[i] = new QCheckBox(KAlarm::weekDayName(day, locale), daybox);
695 wgrid->addWidget(mWorkDays[i], i/3, i%3, Qt::AlignLeft);
697 daybox->setFixedHeight(daybox->sizeHint().height());
698 daybox->setWhatsThis(i18nc("@info:whatsthis", "Check the days in the week which are work days"));
700 itemBox = new ItemBox(group);
701 itemBox->setMargin(0);
702 layout->addWidget(itemBox);
703 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
704 box->setMargin(0);
705 box->setSpacing(KDialog::spacingHint());
706 label = new QLabel(i18nc("@label:spinbox", "Daily start time:"), box);
707 addAlignedLabel(label);
708 mWorkStart = new TimeEdit(box);
709 label->setBuddy(mWorkStart);
710 box->setWhatsThis(i18nc("@info:whatsthis",
711 "<para>Enter the start time of the working day.</para>"
712 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
713 itemBox->leftAlign();
715 itemBox = new ItemBox(group);
716 itemBox->setMargin(0);
717 layout->addWidget(itemBox);
718 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
719 box->setMargin(0);
720 box->setSpacing(KDialog::spacingHint());
721 label = new QLabel(i18nc("@label:spinbox", "Daily end time:"), box);
722 addAlignedLabel(label);
723 mWorkEnd = new TimeEdit(box);
724 label->setBuddy(mWorkEnd);
725 box->setWhatsThis(i18nc("@info:whatsthis",
726 "<para>Enter the end time of the working day.</para>"
727 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
728 itemBox->leftAlign();
729 box->setFixedHeight(box->sizeHint().height());
731 // KOrganizer event duration
732 group = new QGroupBox(i18nc("@title:group", "KOrganizer"), topWidget());
733 layout = new QVBoxLayout(group);
734 layout->setMargin(KDialog::marginHint());
735 layout->setSpacing(KDialog::spacingHint());
737 itemBox = new ItemBox(group);
738 itemBox->setMargin(0);
739 layout->addWidget(itemBox);
740 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
741 box->setMargin(0);
742 box->setSpacing(KDialog::spacingHint());
743 label = new QLabel(i18nc("@label:spinbox", "KOrganizer event duration:"), box);
744 addAlignedLabel(label);
745 mKOrgEventDuration = new TimeSpinBox(0, 5999, box);
746 mKOrgEventDuration->setMinimumSize(mKOrgEventDuration->sizeHint());
747 box->setWhatsThis(i18nc("@info:whatsthis",
748 "<para>Enter the event duration in hours and minutes, for alarms which are copied to KOrganizer.</para>"
749 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
750 label->setBuddy(mKOrgEventDuration);
751 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
752 itemBox->setFixedHeight(itemBox->sizeHint().height());
754 topLayout()->addStretch(); // top adjust the widgets
757 void TimePrefTab::restore(bool, bool)
759 #if 1
760 mTimeZone->setTimeZone(Preferences::timeZone());
761 #else
762 int tzindex = 0;
763 KTimeZone tz = Preferences::timeZone();
764 if (tz.isValid())
766 QString zone = tz.name();
767 int count = mTimeZone->count();
768 while (tzindex < count && mTimeZone->itemText(tzindex) != zone)
769 ++tzindex;
770 if (tzindex >= count)
771 tzindex = 0;
773 mTimeZone->setCurrentIndex(tzindex);
774 #endif
775 int i = Preferences::holidays().isValid() ? mHolidays->findData(Preferences::holidays().regionCode()) : 0;
776 mHolidays->setCurrentIndex(i);
777 mStartOfDay->setValue(Preferences::startOfDay());
778 mWorkStart->setValue(Preferences::workDayStart());
779 mWorkEnd->setValue(Preferences::workDayEnd());
780 QBitArray days = Preferences::workDays();
781 for (int i = 0; i < 7; ++i)
783 bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1);
784 mWorkDays[i]->setChecked(x);
786 mKOrgEventDuration->setValue(Preferences::kOrgEventDuration());
789 void TimePrefTab::apply(bool syncToDisc)
791 #if 1
792 KTimeZone tz = mTimeZone->timeZone();
793 if (tz.isValid())
794 Preferences::setTimeZone(tz);
795 #else
796 KTimeZone tz = KSystemTimeZones::zone(mTimeZone->currentText());
797 if (tz.isValid() && tz != Preferences::timeZone())
798 Preferences::setTimeZone(tz);
799 #endif
800 QString hol = mHolidays->itemData(mHolidays->currentIndex()).toString();
801 if (hol != Preferences::holidays().regionCode())
802 Preferences::setHolidayRegion(hol);
803 int t = mStartOfDay->value();
804 QTime sodt(t/60, t%60, 0);
805 if (sodt != Preferences::startOfDay())
806 Preferences::setStartOfDay(sodt);
807 t = mWorkStart->value();
808 Preferences::setWorkDayStart(QTime(t/60, t%60, 0));
809 t = mWorkEnd->value();
810 Preferences::setWorkDayEnd(QTime(t/60, t%60, 0));
811 QBitArray workDays(7);
812 for (int i = 0; i < 7; ++i)
813 if (mWorkDays[i]->isChecked())
814 workDays.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1);
815 Preferences::setWorkDays(workDays);
816 Preferences::setKOrgEventDuration(mKOrgEventDuration->value());
817 t = mKOrgEventDuration->value();
818 if (t != Preferences::kOrgEventDuration())
819 Preferences::setKOrgEventDuration(t);
820 PrefsTabBase::apply(syncToDisc);
824 /*=============================================================================
825 = Class StorePrefTab
826 =============================================================================*/
828 StorePrefTab::StorePrefTab(StackedScrollGroup* scrollGroup)
829 : PrefsTabBase(scrollGroup),
830 mCheckKeepChanges(false)
832 // Which resource to save to
833 QGroupBox* group = new QGroupBox(i18nc("@title:group", "New Alarms && Templates"), topWidget());
834 QButtonGroup* bgroup = new QButtonGroup(group);
835 QBoxLayout* layout = new QVBoxLayout(group);
836 layout->setMargin(KDialog::marginHint());
837 layout->setSpacing(KDialog::spacingHint());
839 mDefaultResource = new QRadioButton(i18nc("@option:radio", "Store in default calendar"), group);
840 bgroup->addButton(mDefaultResource);
841 mDefaultResource->setWhatsThis(i18nc("@info:whatsthis", "Add all new alarms and alarm templates to the default calendars, without prompting."));
842 layout->addWidget(mDefaultResource, 0, Qt::AlignLeft);
843 mAskResource = new QRadioButton(i18nc("@option:radio", "Prompt for which calendar to store in"), group);
844 bgroup->addButton(mAskResource);
845 mAskResource->setWhatsThis(i18nc("@info:whatsthis",
846 "<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>"
847 "<para>Note that archived alarms are always stored in the default archived alarm calendar.</para>"));
848 layout->addWidget(mAskResource, 0, Qt::AlignLeft);
850 // Archived alarms
851 group = new QGroupBox(i18nc("@title:group", "Archived Alarms"), topWidget());
852 QGridLayout* grid = new QGridLayout(group);
853 grid->setMargin(KDialog::marginHint());
854 grid->setSpacing(KDialog::spacingHint());
855 grid->setColumnStretch(1, 1);
856 grid->setColumnMinimumWidth(0, indentWidth());
857 mKeepArchived = new QCheckBox(i18nc("@option:check", "Keep alarms after expiry"), group);
858 connect(mKeepArchived, SIGNAL(toggled(bool)), SLOT(slotArchivedToggled(bool)));
859 mKeepArchived->setWhatsThis(
860 i18nc("@info:whatsthis", "Check to archive alarms after expiry or deletion (except deleted alarms which were never triggered)."));
861 grid->addWidget(mKeepArchived, 0, 0, 1, 2, Qt::AlignLeft);
863 KHBox* box = new KHBox(group);
864 box->setMargin(0);
865 box->setSpacing(KDialog::spacingHint());
866 mPurgeArchived = new QCheckBox(i18nc("@option:check", "Discard archived alarms after:"), box);
867 mPurgeArchived->setMinimumSize(mPurgeArchived->sizeHint());
868 connect(mPurgeArchived, SIGNAL(toggled(bool)), SLOT(slotArchivedToggled(bool)));
869 mPurgeAfter = new SpinBox(box);
870 mPurgeAfter->setMinimum(1);
871 mPurgeAfter->setSingleShiftStep(10);
872 mPurgeAfter->setMinimumSize(mPurgeAfter->sizeHint());
873 mPurgeAfterLabel = new QLabel(i18nc("@label Time unit for user-entered number", "days"), box);
874 mPurgeAfterLabel->setMinimumSize(mPurgeAfterLabel->sizeHint());
875 mPurgeAfterLabel->setBuddy(mPurgeAfter);
876 box->setWhatsThis(i18nc("@info:whatsthis", "Uncheck to store archived alarms indefinitely. Check to enter how long archived alarms should be stored."));
877 grid->addWidget(box, 1, 1, Qt::AlignLeft);
879 mClearArchived = new QPushButton(i18nc("@action:button", "Clear Archived Alarms"), group);
880 mClearArchived->setFixedSize(mClearArchived->sizeHint());
881 connect(mClearArchived, SIGNAL(clicked()), SLOT(slotClearArchived()));
882 #ifdef USE_AKONADI
883 mClearArchived->setWhatsThis((CollectionControlModel::enabledCollections(KAlarm::CalEvent::ARCHIVED, false).count() <= 1)
884 #else
885 mClearArchived->setWhatsThis((AlarmResources::instance()->activeCount(KAlarm::CalEvent::ARCHIVED, false) <= 1)
886 #endif
887 ? i18nc("@info:whatsthis", "Delete all existing archived alarms.")
888 : i18nc("@info:whatsthis", "Delete all existing archived alarms (from the default archived alarm calendar only)."));
889 grid->addWidget(mClearArchived, 2, 1, Qt::AlignLeft);
890 group->setFixedHeight(group->sizeHint().height());
892 topLayout()->addStretch(); // top adjust the widgets
895 void StorePrefTab::restore(bool defaults, bool)
897 mCheckKeepChanges = defaults;
898 if (Preferences::askResource())
899 mAskResource->setChecked(true);
900 else
901 mDefaultResource->setChecked(true);
902 int keepDays = Preferences::archivedKeepDays();
903 if (!defaults)
904 mOldKeepArchived = keepDays;
905 setArchivedControls(keepDays);
906 mCheckKeepChanges = true;
909 void StorePrefTab::apply(bool syncToDisc)
911 bool b = mAskResource->isChecked();
912 if (b != Preferences::askResource())
913 Preferences::setAskResource(mAskResource->isChecked());
914 int days = !mKeepArchived->isChecked() ? 0 : mPurgeArchived->isChecked() ? mPurgeAfter->value() : -1;
915 if (days != Preferences::archivedKeepDays())
916 Preferences::setArchivedKeepDays(days);
917 PrefsTabBase::apply(syncToDisc);
920 void StorePrefTab::setArchivedControls(int purgeDays)
922 mKeepArchived->setChecked(purgeDays);
923 mPurgeArchived->setChecked(purgeDays > 0);
924 mPurgeAfter->setValue(purgeDays > 0 ? purgeDays : 0);
925 slotArchivedToggled(true);
928 void StorePrefTab::slotArchivedToggled(bool)
930 bool keep = mKeepArchived->isChecked();
931 if (keep && !mOldKeepArchived && mCheckKeepChanges
932 #ifdef USE_AKONADI
933 && !CollectionControlModel::getStandard(KAlarm::CalEvent::ARCHIVED).isValid())
934 #else
935 && !AlarmResources::instance()->getStandardResource(KAlarm::CalEvent::ARCHIVED))
936 #endif
938 KAMessageBox::sorry(topWidget(),
939 i18nc("@info", "<para>A default calendar is required in order to archive alarms, but none is currently enabled.</para>"
940 "<para>If you wish to keep expired alarms, please first use the calendars view to select a default "
941 "archived alarms calendar.</para>"));
942 mKeepArchived->setChecked(false);
943 return;
945 mOldKeepArchived = keep;
946 mPurgeArchived->setEnabled(keep);
947 mPurgeAfter->setEnabled(keep && mPurgeArchived->isChecked());
948 mPurgeAfterLabel->setEnabled(keep);
949 mClearArchived->setEnabled(keep);
952 void StorePrefTab::slotClearArchived()
954 #ifdef USE_AKONADI
955 bool single = CollectionControlModel::enabledCollections(KAlarm::CalEvent::ARCHIVED, false).count() <= 1;
956 #else
957 bool single = AlarmResources::instance()->activeCount(KAlarm::CalEvent::ARCHIVED, false) <= 1;
958 #endif
959 if (KAMessageBox::warningContinueCancel(topWidget(), single ? i18nc("@info", "Do you really want to delete all archived alarms?")
960 : i18nc("@info", "Do you really want to delete all alarms in the default archived alarm calendar?"))
961 != KMessageBox::Continue)
962 return;
963 theApp()->purgeAll();
967 /*=============================================================================
968 = Class EmailPrefTab
969 =============================================================================*/
971 EmailPrefTab::EmailPrefTab(StackedScrollGroup* scrollGroup)
972 : PrefsTabBase(scrollGroup),
973 mAddressChanged(false),
974 mBccAddressChanged(false)
976 KHBox* box = new KHBox(topWidget());
977 box->setMargin(0);
978 box->setSpacing(2*KDialog::spacingHint());
979 QLabel* label = new QLabel(i18nc("@label", "Email client:"), box);
980 mEmailClient = new ButtonGroup(box);
981 QString kmailOption = i18nc("@option:radio", "KMail");
982 QString sendmailOption = i18nc("@option:radio", "Sendmail");
983 mKMailButton = new RadioButton(kmailOption, box);
984 mKMailButton->setMinimumSize(mKMailButton->sizeHint());
985 mEmailClient->addButton(mKMailButton, Preferences::kmail);
986 mSendmailButton = new RadioButton(sendmailOption, box);
987 mSendmailButton->setMinimumSize(mSendmailButton->sizeHint());
988 mEmailClient->addButton(mSendmailButton, Preferences::sendmail);
989 connect(mEmailClient, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotEmailClientChanged(QAbstractButton*)));
990 box->setFixedHeight(box->sizeHint().height());
991 box->setWhatsThis(i18nc("@info:whatsthis",
992 "<para>Choose how to send email when an email alarm is triggered."
993 "<list><item><interface>%1</interface>: The email is sent automatically via <application>KMail</application>. <application>KMail</application> is started first if necessary.</item>"
994 "<item><interface>%2</interface>: The email is sent automatically. This option will only work if "
995 "your system is configured to use <application>sendmail</application> or a sendmail compatible mail transport agent.</item></list></para>",
996 kmailOption, sendmailOption));
998 box = new KHBox(topWidget()); // this is to allow left adjustment
999 box->setMargin(0);
1000 mEmailCopyToKMail = new QCheckBox(i18nc("@option:check", "Copy sent emails into <application>KMail</application>'s <resource>%1</resource> folder", KAMail::i18n_sent_mail()), box);
1001 mEmailCopyToKMail->setWhatsThis(i18nc("@info:whatsthis", "After sending an email, store a copy in <application>KMail</application>'s <resource>%1</resource> folder", KAMail::i18n_sent_mail()));
1002 box->setStretchFactor(new QWidget(box), 1); // left adjust the controls
1003 box->setFixedHeight(box->sizeHint().height());
1005 box = new KHBox(topWidget()); // this is to allow left adjustment
1006 box->setMargin(0);
1007 mEmailQueuedNotify = new QCheckBox(i18nc("@option:check", "Notify when remote emails are queued"), box);
1008 mEmailQueuedNotify->setWhatsThis(
1009 i18nc("@info:whatsthis", "Display a notification message whenever an email alarm has queued an email for sending to a remote system. "
1010 "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."));
1011 box->setStretchFactor(new QWidget(box), 1); // left adjust the controls
1012 box->setFixedHeight(box->sizeHint().height());
1014 // Your Email Address group box
1015 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Your Email Address"), topWidget());
1016 QGridLayout* grid = new QGridLayout(group);
1017 grid->setMargin(KDialog::marginHint());
1018 grid->setSpacing(KDialog::spacingHint());
1019 grid->setColumnStretch(2, 1);
1021 // 'From' email address controls ...
1022 label = new Label(i18nc("@label 'From' email address", "From:"), group);
1023 grid->addWidget(label, 1, 0);
1024 mFromAddressGroup = new ButtonGroup(group);
1025 connect(mFromAddressGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotFromAddrChanged(QAbstractButton*)));
1027 // Line edit to enter a 'From' email address
1028 mFromAddrButton = new RadioButton(group);
1029 mFromAddressGroup->addButton(mFromAddrButton, Preferences::MAIL_FROM_ADDR);
1030 label->setBuddy(mFromAddrButton);
1031 grid->addWidget(mFromAddrButton, 1, 1);
1032 mEmailAddress = new KLineEdit(group);
1033 connect(mEmailAddress, SIGNAL(textChanged(QString)), SLOT(slotAddressChanged()));
1034 QString whatsThis = i18nc("@info:whatsthis", "Your email address, used to identify you as the sender when sending email alarms.");
1035 mFromAddrButton->setWhatsThis(whatsThis);
1036 mEmailAddress->setWhatsThis(whatsThis);
1037 mFromAddrButton->setFocusWidget(mEmailAddress);
1038 grid->addWidget(mEmailAddress, 1, 2);
1040 // 'From' email address to be taken from System Settings
1041 mFromCCentreButton = new RadioButton(i18nc("@option:radio", "Use address from System Settings"), group);
1042 mFromAddressGroup->addButton(mFromCCentreButton, Preferences::MAIL_FROM_SYS_SETTINGS);
1043 mFromCCentreButton->setWhatsThis(
1044 i18nc("@info:whatsthis", "Check to use the email address set in KDE System Settings, to identify you as the sender when sending email alarms."));
1045 grid->addWidget(mFromCCentreButton, 2, 1, 1, 2, Qt::AlignLeft);
1047 // 'From' email address to be picked from KMail's identities when the email alarm is configured
1048 mFromKMailButton = new RadioButton(i18nc("@option:radio", "Use <application>KMail</application> identities"), group);
1049 mFromAddressGroup->addButton(mFromKMailButton, Preferences::MAIL_FROM_KMAIL);
1050 mFromKMailButton->setWhatsThis(
1051 i18nc("@info:whatsthis", "Check to use <application>KMail</application>'s email identities to identify you as the sender when sending email alarms. "
1052 "For existing email alarms, <application>KMail</application>'s default identity will be used. "
1053 "For new email alarms, you will be able to pick which of <application>KMail</application>'s identities to use."));
1054 grid->addWidget(mFromKMailButton, 3, 1, 1, 2, Qt::AlignLeft);
1056 // 'Bcc' email address controls ...
1057 grid->setRowMinimumHeight(4, KDialog::spacingHint());
1058 label = new Label(i18nc("@label 'Bcc' email address", "Bcc:"), group);
1059 grid->addWidget(label, 5, 0);
1060 mBccAddressGroup = new ButtonGroup(group);
1061 connect(mBccAddressGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotBccAddrChanged(QAbstractButton*)));
1063 // Line edit to enter a 'Bcc' email address
1064 mBccAddrButton = new RadioButton(group);
1065 mBccAddressGroup->addButton(mBccAddrButton, Preferences::MAIL_FROM_ADDR);
1066 label->setBuddy(mBccAddrButton);
1067 grid->addWidget(mBccAddrButton, 5, 1);
1068 mEmailBccAddress = new KLineEdit(group);
1069 whatsThis = i18nc("@info:whatsthis", "Your email address, used for blind copying email alarms to yourself. "
1070 "If you want blind copies to be sent to your account on the computer which <application>KAlarm</application> runs on, you can simply enter your user login name.");
1071 mBccAddrButton->setWhatsThis(whatsThis);
1072 mEmailBccAddress->setWhatsThis(whatsThis);
1073 mBccAddrButton->setFocusWidget(mEmailBccAddress);
1074 grid->addWidget(mEmailBccAddress, 5, 2);
1076 // 'Bcc' email address to be taken from System Settings
1077 mBccCCentreButton = new RadioButton(i18nc("@option:radio", "Use address from System Settings"), group);
1078 mBccAddressGroup->addButton(mBccCCentreButton, Preferences::MAIL_FROM_SYS_SETTINGS);
1079 mBccCCentreButton->setWhatsThis(
1080 i18nc("@info:whatsthis", "Check to use the email address set in KDE System Settings, for blind copying email alarms to yourself."));
1081 grid->addWidget(mBccCCentreButton, 6, 1, 1, 2, Qt::AlignLeft);
1083 group->setFixedHeight(group->sizeHint().height());
1085 topLayout()->addStretch(); // top adjust the widgets
1088 void EmailPrefTab::restore(bool defaults, bool)
1090 mEmailClient->setButton(Preferences::emailClient());
1091 mEmailCopyToKMail->setChecked(Preferences::emailCopyToKMail());
1092 setEmailAddress(Preferences::emailFrom(), Preferences::emailAddress());
1093 setEmailBccAddress((Preferences::emailBccFrom() == Preferences::MAIL_FROM_SYS_SETTINGS), Preferences::emailBccAddress());
1094 mEmailQueuedNotify->setChecked(Preferences::emailQueuedNotify());
1095 if (!defaults)
1096 mAddressChanged = mBccAddressChanged = false;
1099 void EmailPrefTab::apply(bool syncToDisc)
1101 int client = mEmailClient->selectedId();
1102 if (client >= 0 && static_cast<Preferences::MailClient>(client) != Preferences::emailClient())
1103 Preferences::setEmailClient(static_cast<Preferences::MailClient>(client));
1104 bool b = mEmailCopyToKMail->isChecked();
1105 if (b != Preferences::emailCopyToKMail())
1106 Preferences::setEmailCopyToKMail(b);
1107 int from = mFromAddressGroup->selectedId();
1108 QString text = mEmailAddress->text().trimmed();
1109 if ((from >= 0 && static_cast<Preferences::MailFrom>(from) != Preferences::emailFrom())
1110 || text != Preferences::emailAddress())
1111 Preferences::setEmailAddress(static_cast<Preferences::MailFrom>(from), text);
1112 b = (mBccAddressGroup->checkedButton() == mBccCCentreButton);
1113 Preferences::MailFrom bfrom = b ? Preferences::MAIL_FROM_SYS_SETTINGS : Preferences::MAIL_FROM_ADDR;;
1114 text = mEmailBccAddress->text().trimmed();
1115 if (bfrom != Preferences::emailBccFrom() || text != Preferences::emailBccAddress())
1116 Preferences::setEmailBccAddress(b, text);
1117 b = mEmailQueuedNotify->isChecked();
1118 if (b != Preferences::emailQueuedNotify())
1119 Preferences::setEmailQueuedNotify(mEmailQueuedNotify->isChecked());
1120 PrefsTabBase::apply(syncToDisc);
1123 void EmailPrefTab::setEmailAddress(Preferences::MailFrom from, const QString& address)
1125 mFromAddressGroup->setButton(from);
1126 mEmailAddress->setText(from == Preferences::MAIL_FROM_ADDR ? address.trimmed() : QString());
1129 void EmailPrefTab::setEmailBccAddress(bool useSystemSettings, const QString& address)
1131 mBccAddressGroup->setButton(useSystemSettings ? Preferences::MAIL_FROM_SYS_SETTINGS : Preferences::MAIL_FROM_ADDR);
1132 mEmailBccAddress->setText(useSystemSettings ? QString() : address.trimmed());
1135 void EmailPrefTab::slotEmailClientChanged(QAbstractButton* button)
1137 mEmailCopyToKMail->setEnabled(button == mSendmailButton);
1140 void EmailPrefTab::slotFromAddrChanged(QAbstractButton* button)
1142 mEmailAddress->setEnabled(button == mFromAddrButton);
1143 mAddressChanged = true;
1146 void EmailPrefTab::slotBccAddrChanged(QAbstractButton* button)
1148 mEmailBccAddress->setEnabled(button == mBccAddrButton);
1149 mBccAddressChanged = true;
1152 QString EmailPrefTab::validate()
1154 if (mAddressChanged)
1156 mAddressChanged = false;
1157 QString errmsg = validateAddr(mFromAddressGroup, mEmailAddress, KAMail::i18n_NeedFromEmailAddress());
1158 if (!errmsg.isEmpty())
1159 return errmsg;
1161 if (mBccAddressChanged)
1163 mBccAddressChanged = false;
1164 return validateAddr(mBccAddressGroup, mEmailBccAddress, i18nc("@info/plain", "No valid 'Bcc' email address is specified."));
1166 return QString();
1169 QString EmailPrefTab::validateAddr(ButtonGroup* group, KLineEdit* addr, const QString& msg)
1171 QString errmsg = i18nc("@info", "<para>%1</para><para>Are you sure you want to save your changes?</para>", msg);
1172 switch (group->selectedId())
1174 case Preferences::MAIL_FROM_SYS_SETTINGS:
1175 if (!KAMail::controlCentreAddress().isEmpty())
1176 return QString();
1177 errmsg = i18nc("@info", "No email address is currently set in KDE System Settings. %1", errmsg);
1178 break;
1179 case Preferences::MAIL_FROM_KMAIL:
1180 if (Identities::identitiesExist())
1181 return QString();
1182 errmsg = i18nc("@info", "No <application>KMail</application> identities currently exist. %1", errmsg);
1183 break;
1184 case Preferences::MAIL_FROM_ADDR:
1185 if (!addr->text().trimmed().isEmpty())
1186 return QString();
1187 break;
1189 return errmsg;
1193 /*=============================================================================
1194 = Class EditPrefTab
1195 =============================================================================*/
1197 EditPrefTab::EditPrefTab(StackedScrollGroup* scrollGroup)
1198 : PrefsTabBase(scrollGroup)
1200 KLocalizedString defsetting = ki18nc("@info:whatsthis", "The default setting for <interface>%1</interface> in the alarm edit dialog.");
1202 mTabs = new KTabWidget(topWidget());
1203 StackedGroupT<KVBox>* tabgroup = new StackedGroupT<KVBox>(mTabs);
1204 StackedWidgetT<KVBox>* topGeneral = new StackedWidgetT<KVBox>(tabgroup);
1205 topGeneral->setMargin(KDialog::marginHint()/2);
1206 topGeneral->setSpacing(KDialog::spacingHint());
1207 mTabGeneral = mTabs->addTab(topGeneral, i18nc("@title:tab", "General"));
1208 StackedWidgetT<KVBox>* topTypes = new StackedWidgetT<KVBox>(tabgroup);
1209 topTypes->setMargin(KDialog::marginHint()/2);
1210 topTypes->setSpacing(KDialog::spacingHint());
1211 mTabTypes = mTabs->addTab(topTypes, i18nc("@title:tab", "Alarm Types"));
1212 StackedWidgetT<KVBox>* topFontColour = new StackedWidgetT<KVBox>(tabgroup);
1213 topFontColour->setMargin(KDialog::marginHint()/2);
1214 topFontColour->setSpacing(KDialog::spacingHint());
1215 mTabFontColour = mTabs->addTab(topFontColour, i18nc("@title:tab", "Font && Color"));
1217 // MISCELLANEOUS
1218 // Show in KOrganizer
1219 mCopyToKOrganizer = new QCheckBox(EditAlarmDlg::i18n_chk_ShowInKOrganizer(), topGeneral);
1220 mCopyToKOrganizer->setMinimumSize(mCopyToKOrganizer->sizeHint());
1221 mCopyToKOrganizer->setWhatsThis(defsetting.subs(EditAlarmDlg::i18n_chk_ShowInKOrganizer()).toString());
1223 // Late cancellation
1224 KHBox* box = new KHBox(topGeneral);
1225 box->setMargin(0);
1226 box->setSpacing(KDialog::spacingHint());
1227 mLateCancel = new QCheckBox(LateCancelSelector::i18n_chk_CancelIfLate(), box);
1228 mLateCancel->setMinimumSize(mLateCancel->sizeHint());
1229 mLateCancel->setWhatsThis(defsetting.subs(LateCancelSelector::i18n_chk_CancelIfLate()).toString());
1230 box->setStretchFactor(new QWidget(box), 1); // left adjust the control
1232 // Recurrence
1233 QFrame* iBox = new QFrame(topGeneral); // this is to control the QWhatsThis text display area
1234 QHBoxLayout* hlayout = new QHBoxLayout(iBox);
1235 hlayout->setSpacing(KDialog::spacingHint());
1236 QLabel* label = new QLabel(i18nc("@label:listbox", "Recurrence:"), iBox);
1237 hlayout->addWidget(label);
1238 mRecurPeriod = new KComboBox(iBox);
1239 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_NoRecur());
1240 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_AtLogin());
1241 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_HourlyMinutely());
1242 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Daily());
1243 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Weekly());
1244 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Monthly());
1245 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Yearly());
1246 mRecurPeriod->setFixedSize(mRecurPeriod->sizeHint());
1247 hlayout->addWidget(mRecurPeriod);
1248 label->setBuddy(mRecurPeriod);
1249 iBox->setWhatsThis(i18nc("@info:whatsthis", "The default setting for the recurrence rule in the alarm edit dialog."));
1250 hlayout->addStretch(); // left adjust the control
1252 // How to handle February 29th in yearly recurrences
1253 KVBox* vbox = new KVBox(topGeneral); // this is to control the QWhatsThis text display area
1254 vbox->setMargin(0);
1255 vbox->setSpacing(KDialog::spacingHint());
1256 label = new QLabel(i18nc("@label", "In non-leap years, repeat yearly February 29th alarms on:"), vbox);
1257 label->setAlignment(Qt::AlignLeft);
1258 label->setWordWrap(true);
1259 KHBox* itemBox = new KHBox(vbox);
1260 // itemBox->setMargin(0);
1261 itemBox->setSpacing(2*KDialog::spacingHint());
1262 mFeb29 = new ButtonGroup(itemBox);
1263 QWidget* widget = new QWidget(itemBox);
1264 widget->setFixedWidth(3*KDialog::spacingHint());
1265 QRadioButton* radio = new QRadioButton(i18nc("@option:radio", "February 2&8th"), itemBox);
1266 radio->setMinimumSize(radio->sizeHint());
1267 mFeb29->addButton(radio, Preferences::Feb29_Feb28);
1268 radio = new QRadioButton(i18nc("@option:radio", "March &1st"), itemBox);
1269 radio->setMinimumSize(radio->sizeHint());
1270 mFeb29->addButton(radio, Preferences::Feb29_Mar1);
1271 radio = new QRadioButton(i18nc("@option:radio", "Do not repeat"), itemBox);
1272 radio->setMinimumSize(radio->sizeHint());
1273 mFeb29->addButton(radio, Preferences::Feb29_None);
1274 itemBox->setFixedHeight(itemBox->sizeHint().height());
1275 vbox->setWhatsThis(i18nc("@info:whatsthis",
1276 "For yearly recurrences, choose what date, if any, alarms due on February 29th should occur in non-leap years."
1277 "<note>The next scheduled occurrence of existing alarms is not re-evaluated when you change this setting.</note>"));
1279 QVBoxLayout* lay = qobject_cast<QVBoxLayout*>(topGeneral->layout());
1280 if (lay)
1281 lay->addStretch(); // top adjust the widgets
1283 // DISPLAY ALARMS
1284 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Display Alarms"), topTypes);
1285 QVBoxLayout* vlayout = new QVBoxLayout(group);
1286 vlayout->setMargin(KDialog::marginHint());
1287 vlayout->setSpacing(KDialog::spacingHint());
1289 mConfirmAck = new QCheckBox(EditDisplayAlarmDlg::i18n_chk_ConfirmAck(), group);
1290 mConfirmAck->setMinimumSize(mConfirmAck->sizeHint());
1291 mConfirmAck->setWhatsThis(defsetting.subs(EditDisplayAlarmDlg::i18n_chk_ConfirmAck()).toString());
1292 vlayout->addWidget(mConfirmAck, 0, Qt::AlignLeft);
1294 mAutoClose = new QCheckBox(LateCancelSelector::i18n_chk_AutoCloseWinLC(), group);
1295 mAutoClose->setMinimumSize(mAutoClose->sizeHint());
1296 mAutoClose->setWhatsThis(defsetting.subs(LateCancelSelector::i18n_chk_AutoCloseWin()).toString());
1297 vlayout->addWidget(mAutoClose, 0, Qt::AlignLeft);
1299 box = new KHBox(group);
1300 // box->setMargin(0);
1301 box->setSpacing(KDialog::spacingHint());
1302 vlayout->addWidget(box);
1303 label = new QLabel(i18nc("@label:listbox", "Reminder units:"), box);
1304 mReminderUnits = new KComboBox(box);
1305 mReminderUnits->addItem(i18nc("@item:inlistbox", "Minutes"), TimePeriod::Minutes);
1306 mReminderUnits->addItem(i18nc("@item:inlistbox", "Hours/Minutes"), TimePeriod::HoursMinutes);
1307 mReminderUnits->setFixedSize(mReminderUnits->sizeHint());
1308 label->setBuddy(mReminderUnits);
1309 box->setWhatsThis(i18nc("@info:whatsthis", "The default units for the reminder in the alarm edit dialog, for alarms due soon."));
1310 box->setStretchFactor(new QWidget(box), 1); // left adjust the control
1312 mSpecialActionsButton = new SpecialActionsButton(true, box);
1313 mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
1315 // SOUND
1316 QGroupBox* bbox = new QGroupBox(i18nc("@title:group Audio options group", "Sound"), topTypes);
1317 vlayout = new QVBoxLayout(bbox);
1318 vlayout->setMargin(KDialog::marginHint());
1319 vlayout->setSpacing(KDialog::spacingHint());
1321 hlayout = new QHBoxLayout();
1322 hlayout->setMargin(0);
1323 vlayout->addLayout(hlayout);
1324 mSound = new KComboBox(bbox);
1325 mSound->addItem(SoundPicker::i18n_combo_None()); // index 0
1326 mSound->addItem(SoundPicker::i18n_combo_Beep()); // index 1
1327 mSound->addItem(SoundPicker::i18n_combo_File()); // index 2
1328 if (theApp()->speechEnabled())
1329 mSound->addItem(SoundPicker::i18n_combo_Speak()); // index 3
1330 mSound->setMinimumSize(mSound->sizeHint());
1331 mSound->setWhatsThis(defsetting.subs(SoundPicker::i18n_label_Sound()).toString());
1332 hlayout->addWidget(mSound);
1333 hlayout->addStretch();
1335 mSoundRepeat = new QCheckBox(i18nc("@option:check", "Repeat sound file"), bbox);
1336 mSoundRepeat->setMinimumSize(mSoundRepeat->sizeHint());
1337 mSoundRepeat->setWhatsThis(
1338 i18nc("@info:whatsthis sound file 'Repeat' checkbox", "The default setting for sound file <interface>%1</interface> in the alarm edit dialog.", SoundWidget::i18n_chk_Repeat()));
1339 hlayout->addWidget(mSoundRepeat);
1341 box = new KHBox(bbox); // this is to control the QWhatsThis text display area
1342 box->setMargin(0);
1343 box->setSpacing(KDialog::spacingHint());
1344 mSoundFileLabel = new QLabel(i18nc("@label:textbox", "Sound file:"), box);
1345 mSoundFile = new KLineEdit(box);
1346 mSoundFileLabel->setBuddy(mSoundFile);
1347 mSoundFileBrowse = new QPushButton(box);
1348 mSoundFileBrowse->setIcon(KIcon(SmallIcon("document-open")));
1349 int size = mSoundFileBrowse->sizeHint().height();
1350 mSoundFileBrowse->setFixedSize(size, size);
1351 connect(mSoundFileBrowse, SIGNAL(clicked()), SLOT(slotBrowseSoundFile()));
1352 mSoundFileBrowse->setToolTip(i18nc("@info:tooltip", "Choose a sound file"));
1353 box->setWhatsThis(i18nc("@info:whatsthis", "Enter the default sound file to use in the alarm edit dialog."));
1354 box->setFixedHeight(box->sizeHint().height());
1355 vlayout->addWidget(box);
1356 bbox->setFixedHeight(bbox->sizeHint().height());
1358 // COMMAND ALARMS
1359 group = new QGroupBox(i18nc("@title:group", "Command Alarms"), topTypes);
1360 vlayout = new QVBoxLayout(group);
1361 vlayout->setMargin(KDialog::marginHint());
1362 vlayout->setSpacing(KDialog::spacingHint());
1363 hlayout = new QHBoxLayout();
1364 hlayout->setMargin(0);
1365 vlayout->addLayout(hlayout);
1367 mCmdScript = new QCheckBox(EditCommandAlarmDlg::i18n_chk_EnterScript(), group);
1368 mCmdScript->setMinimumSize(mCmdScript->sizeHint());
1369 mCmdScript->setWhatsThis(defsetting.subs(EditCommandAlarmDlg::i18n_chk_EnterScript()).toString());
1370 hlayout->addWidget(mCmdScript);
1371 hlayout->addStretch();
1373 mCmdXterm = new QCheckBox(EditCommandAlarmDlg::i18n_chk_ExecInTermWindow(), group);
1374 mCmdXterm->setMinimumSize(mCmdXterm->sizeHint());
1375 mCmdXterm->setWhatsThis(defsetting.subs(EditCommandAlarmDlg::i18n_radio_ExecInTermWindow()).toString());
1376 hlayout->addWidget(mCmdXterm);
1378 // EMAIL ALARMS
1379 group = new QGroupBox(i18nc("@title:group", "Email Alarms"), topTypes);
1380 vlayout = new QVBoxLayout(group);
1381 vlayout->setMargin(KDialog::marginHint());
1382 vlayout->setSpacing(KDialog::spacingHint());
1384 // BCC email to sender
1385 mEmailBcc = new QCheckBox(EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf(), group);
1386 mEmailBcc->setMinimumSize(mEmailBcc->sizeHint());
1387 mEmailBcc->setWhatsThis(defsetting.subs(EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf()).toString());
1388 vlayout->addWidget(mEmailBcc, 0, Qt::AlignLeft);
1390 lay = qobject_cast<QVBoxLayout*>(topTypes->layout());
1391 if (lay)
1392 lay->addStretch(); // top adjust the widgets
1394 // FONT / COLOUR TAB
1395 mFontChooser = new FontColourChooser(topFontColour, QStringList(), i18nc("@title:group", "Message Font && Color"), true);
1398 void EditPrefTab::restore(bool, bool allTabs)
1400 int index;
1401 if (allTabs || mTabs->currentIndex() == mTabGeneral)
1403 mCopyToKOrganizer->setChecked(Preferences::defaultCopyToKOrganizer());
1404 mLateCancel->setChecked(Preferences::defaultLateCancel());
1405 switch (Preferences::defaultRecurPeriod())
1407 case Preferences::Recur_Yearly: index = 6; break;
1408 case Preferences::Recur_Monthly: index = 5; break;
1409 case Preferences::Recur_Weekly: index = 4; break;
1410 case Preferences::Recur_Daily: index = 3; break;
1411 case Preferences::Recur_SubDaily: index = 2; break;
1412 case Preferences::Recur_Login: index = 1; break;
1413 case Preferences::Recur_None:
1414 default: index = 0; break;
1416 mRecurPeriod->setCurrentIndex(index);
1417 mFeb29->setButton(Preferences::defaultFeb29Type());
1419 if (allTabs || mTabs->currentIndex() == mTabTypes)
1421 mConfirmAck->setChecked(Preferences::defaultConfirmAck());
1422 mAutoClose->setChecked(Preferences::defaultAutoClose());
1423 switch (Preferences::defaultReminderUnits())
1425 case TimePeriod::Weeks: index = 3; break;
1426 case TimePeriod::Days: index = 2; break;
1427 default:
1428 case TimePeriod::HoursMinutes: index = 1; break;
1429 case TimePeriod::Minutes: index = 0; break;
1431 mReminderUnits->setCurrentIndex(index);
1432 mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(),
1433 Preferences::defaultCancelOnPreActionError(), Preferences::defaultDontShowPreActionError());
1434 mSound->setCurrentIndex(soundIndex(Preferences::defaultSoundType()));
1435 mSoundFile->setText(Preferences::defaultSoundFile());
1436 mSoundRepeat->setChecked(Preferences::defaultSoundRepeat());
1437 mCmdScript->setChecked(Preferences::defaultCmdScript());
1438 mCmdXterm->setChecked(Preferences::defaultCmdLogType() == Preferences::Log_Terminal);
1439 mEmailBcc->setChecked(Preferences::defaultEmailBcc());
1441 if (allTabs || mTabs->currentIndex() == mTabFontColour)
1443 mFontChooser->setFgColour(Preferences::defaultFgColour());
1444 mFontChooser->setBgColour(Preferences::defaultBgColour());
1445 mFontChooser->setFont(Preferences::messageFont());
1449 void EditPrefTab::apply(bool syncToDisc)
1451 bool b = mAutoClose->isChecked();
1452 if (b != Preferences::defaultAutoClose())
1453 Preferences::setDefaultAutoClose(b);
1454 b = mConfirmAck->isChecked();
1455 if (b != Preferences::defaultConfirmAck())
1456 Preferences::setDefaultConfirmAck(b);
1457 TimePeriod::Units units;
1458 switch (mReminderUnits->currentIndex())
1460 case 3: units = TimePeriod::Weeks; break;
1461 case 2: units = TimePeriod::Days; break;
1462 default:
1463 case 1: units = TimePeriod::HoursMinutes; break;
1464 case 0: units = TimePeriod::Minutes; break;
1466 if (units != Preferences::defaultReminderUnits())
1467 Preferences::setDefaultReminderUnits(units);
1468 QString text = mSpecialActionsButton->preAction();
1469 if (text != Preferences::defaultPreAction())
1470 Preferences::setDefaultPreAction(text);
1471 b = mSpecialActionsButton->cancelOnError();
1472 if (b != Preferences::defaultCancelOnPreActionError())
1473 Preferences::setDefaultCancelOnPreActionError(b);
1474 b = mSpecialActionsButton->dontShowError();
1475 if (b != Preferences::defaultDontShowPreActionError())
1476 Preferences::setDefaultDontShowPreActionError(b);
1477 text = mSpecialActionsButton->postAction();
1478 if (text != Preferences::defaultPostAction())
1479 Preferences::setDefaultPostAction(text);
1480 Preferences::SoundType snd;
1481 switch (mSound->currentIndex())
1483 case 3: snd = Preferences::Sound_Speak; break;
1484 case 2: snd = Preferences::Sound_File; break;
1485 case 1: snd = Preferences::Sound_Beep; break;
1486 case 0:
1487 default: snd = Preferences::Sound_None; break;
1489 if (snd != Preferences::defaultSoundType())
1490 Preferences::setDefaultSoundType(snd);
1491 text = mSoundFile->text();
1492 if (text != Preferences::defaultSoundFile())
1493 Preferences::setDefaultSoundFile(text);
1494 b = mSoundRepeat->isChecked();
1495 if (b != Preferences::defaultSoundRepeat())
1496 Preferences::setDefaultSoundRepeat(b);
1497 b = mCmdScript->isChecked();
1498 if (b != Preferences::defaultCmdScript())
1499 Preferences::setDefaultCmdScript(b);
1500 Preferences::CmdLogType log = mCmdXterm->isChecked() ? Preferences::Log_Terminal : Preferences::Log_Discard;
1501 if (log != Preferences::defaultCmdLogType())
1502 Preferences::setDefaultCmdLogType(log);
1503 b = mEmailBcc->isChecked();
1504 if (b != Preferences::defaultEmailBcc())
1505 Preferences::setDefaultEmailBcc(b);
1506 b = mCopyToKOrganizer->isChecked();
1507 if (b != Preferences::defaultCopyToKOrganizer())
1508 Preferences::setDefaultCopyToKOrganizer(b);
1509 int i = mLateCancel->isChecked() ? 1 : 0;
1510 if (i != Preferences::defaultLateCancel())
1511 Preferences::setDefaultLateCancel(i);
1512 Preferences::RecurType period;
1513 switch (mRecurPeriod->currentIndex())
1515 case 6: period = Preferences::Recur_Yearly; break;
1516 case 5: period = Preferences::Recur_Monthly; break;
1517 case 4: period = Preferences::Recur_Weekly; break;
1518 case 3: period = Preferences::Recur_Daily; break;
1519 case 2: period = Preferences::Recur_SubDaily; break;
1520 case 1: period = Preferences::Recur_Login; break;
1521 case 0:
1522 default: period = Preferences::Recur_None; break;
1524 if (period != Preferences::defaultRecurPeriod())
1525 Preferences::setDefaultRecurPeriod(period);
1526 int feb29 = mFeb29->selectedId();
1527 if (feb29 >= 0 && static_cast<Preferences::Feb29Type>(feb29) != Preferences::defaultFeb29Type())
1528 Preferences::setDefaultFeb29Type(static_cast<Preferences::Feb29Type>(feb29));
1529 QColor colour = mFontChooser->fgColour();
1530 if (colour != Preferences::defaultFgColour())
1531 Preferences::setDefaultFgColour(colour);
1532 colour = mFontChooser->bgColour();
1533 if (colour != Preferences::defaultBgColour())
1534 Preferences::setDefaultBgColour(colour);
1535 QFont font = mFontChooser->font();
1536 if (font != Preferences::messageFont())
1537 Preferences::setMessageFont(font);
1538 PrefsTabBase::apply(syncToDisc);
1541 void EditPrefTab::slotBrowseSoundFile()
1543 QString defaultDir;
1544 QString url = SoundPicker::browseFile(defaultDir, mSoundFile->text());
1545 if (!url.isEmpty())
1546 mSoundFile->setText(url);
1549 int EditPrefTab::soundIndex(Preferences::SoundType type)
1551 switch (type)
1553 case Preferences::Sound_Speak: return 3;
1554 case Preferences::Sound_File: return 2;
1555 case Preferences::Sound_Beep: return 1;
1556 case Preferences::Sound_None:
1557 default: return 0;
1561 QString EditPrefTab::validate()
1563 if (mSound->currentIndex() == soundIndex(Preferences::Sound_File) && mSoundFile->text().isEmpty())
1565 mSoundFile->setFocus();
1566 return i18nc("@info", "You must enter a sound file when <interface>%1</interface> is selected as the default sound type", SoundPicker::i18n_combo_File());;
1568 return QString();
1572 /*=============================================================================
1573 = Class ViewPrefTab
1574 =============================================================================*/
1576 ViewPrefTab::ViewPrefTab(StackedScrollGroup* scrollGroup)
1577 : PrefsTabBase(scrollGroup)
1579 mTabs = new KTabWidget(topWidget());
1580 KVBox* topGeneral = new KVBox();
1581 topGeneral->setMargin(KDialog::marginHint()/2);
1582 topGeneral->setSpacing(KDialog::spacingHint());
1583 mTabGeneral = mTabs->addTab(topGeneral, i18nc("@title:tab", "General"));
1584 KVBox* topWindows = new KVBox();
1585 topWindows->setMargin(KDialog::marginHint()/2);
1586 topWindows->setSpacing(KDialog::spacingHint());
1587 mTabWindows = mTabs->addTab(topWindows, i18nc("@title:tab", "Alarm Windows"));
1589 // Run-in-system-tray radio button
1590 KHBox* box = new KHBox(topGeneral); // this is to allow left adjustment
1591 box->setMargin(0);
1592 mShowInSystemTray = new QCheckBox(i18nc("@option:check", "Show in system tray"), box);
1593 mShowInSystemTray->setWhatsThis(
1594 i18nc("@info:whatsthis", "<para>Check to show <application>KAlarm</application>'s icon in the system tray."
1595 " Showing it in the system tray provides easy access and a status indication.</para>"));
1596 box->setStretchFactor(new QWidget(box), 1); // left adjust the controls
1597 box->setFixedHeight(box->sizeHint().height());
1599 QGroupBox* group = new QGroupBox(i18nc("@title:group", "System Tray Tooltip"), topGeneral);
1600 QGridLayout* grid = new QGridLayout(group);
1601 grid->setMargin(KDialog::marginHint());
1602 grid->setSpacing(KDialog::spacingHint());
1603 grid->setColumnStretch(2, 1);
1604 grid->setColumnMinimumWidth(0, indentWidth());
1605 grid->setColumnMinimumWidth(1, indentWidth());
1607 mTooltipShowAlarms = new QCheckBox(i18nc("@option:check", "Show next &24 hours' alarms"), group);
1608 mTooltipShowAlarms->setMinimumSize(mTooltipShowAlarms->sizeHint());
1609 connect(mTooltipShowAlarms, SIGNAL(toggled(bool)), SLOT(slotTooltipAlarmsToggled(bool)));
1610 mTooltipShowAlarms->setWhatsThis(
1611 i18nc("@info:whatsthis", "Specify whether to include in the system tray tooltip, a summary of alarms due in the next 24 hours."));
1612 grid->addWidget(mTooltipShowAlarms, 0, 0, 1, 3, Qt::AlignLeft);
1614 box = new KHBox(group);
1615 box->setMargin(0);
1616 box->setSpacing(KDialog::spacingHint());
1617 mTooltipMaxAlarms = new QCheckBox(i18nc("@option:check", "Maximum number of alarms to show:"), box);
1618 mTooltipMaxAlarms->setMinimumSize(mTooltipMaxAlarms->sizeHint());
1619 connect(mTooltipMaxAlarms, SIGNAL(toggled(bool)), SLOT(slotTooltipMaxToggled(bool)));
1620 mTooltipMaxAlarmCount = new SpinBox(1, 99, box);
1621 mTooltipMaxAlarmCount->setSingleShiftStep(5);
1622 mTooltipMaxAlarmCount->setMinimumSize(mTooltipMaxAlarmCount->sizeHint());
1623 box->setWhatsThis(
1624 i18nc("@info:whatsthis", "Uncheck to display all of the next 24 hours' alarms in the system tray tooltip. "
1625 "Check to enter an upper limit on the number to be displayed."));
1626 grid->addWidget(box, 1, 1, 1, 2, Qt::AlignLeft);
1628 mTooltipShowTime = new QCheckBox(MainWindow::i18n_chk_ShowAlarmTime(), group);
1629 mTooltipShowTime->setMinimumSize(mTooltipShowTime->sizeHint());
1630 connect(mTooltipShowTime, SIGNAL(toggled(bool)), SLOT(slotTooltipTimeToggled(bool)));
1631 mTooltipShowTime->setWhatsThis(i18nc("@info:whatsthis", "Specify whether to show in the system tray tooltip, the time at which each alarm is due."));
1632 grid->addWidget(mTooltipShowTime, 2, 1, 1, 2, Qt::AlignLeft);
1634 mTooltipShowTimeTo = new QCheckBox(MainWindow::i18n_chk_ShowTimeToAlarm(), group);
1635 mTooltipShowTimeTo->setMinimumSize(mTooltipShowTimeTo->sizeHint());
1636 connect(mTooltipShowTimeTo, SIGNAL(toggled(bool)), SLOT(slotTooltipTimeToToggled(bool)));
1637 mTooltipShowTimeTo->setWhatsThis(i18nc("@info:whatsthis", "Specify whether to show in the system tray tooltip, how long until each alarm is due."));
1638 grid->addWidget(mTooltipShowTimeTo, 3, 1, 1, 2, Qt::AlignLeft);
1640 box = new KHBox(group); // this is to control the QWhatsThis text display area
1641 box->setMargin(0);
1642 box->setSpacing(KDialog::spacingHint());
1643 mTooltipTimeToPrefixLabel = new QLabel(i18nc("@label:textbox", "Prefix:"), box);
1644 mTooltipTimeToPrefix = new KLineEdit(box);
1645 mTooltipTimeToPrefixLabel->setBuddy(mTooltipTimeToPrefix);
1646 box->setWhatsThis(i18nc("@info:whatsthis", "Enter the text to be displayed in front of the time until the alarm, in the system tray tooltip."));
1647 box->setFixedHeight(box->sizeHint().height());
1648 grid->addWidget(box, 4, 2, Qt::AlignLeft);
1649 group->setMaximumHeight(group->sizeHint().height());
1651 group = new QGroupBox(i18nc("@title:group", "Alarm List"), topGeneral);
1652 QHBoxLayout* hlayout = new QHBoxLayout(group);
1653 hlayout->setMargin(KDialog::marginHint());
1654 QVBoxLayout* colourLayout = new QVBoxLayout();
1655 colourLayout->setMargin(0);
1656 hlayout->addLayout(colourLayout);
1658 box = new KHBox(group); // to group widgets for QWhatsThis text
1659 box->setMargin(0);
1660 box->setSpacing(KDialog::spacingHint()/2);
1661 colourLayout->addWidget(box);
1662 QLabel* label1 = new QLabel(i18nc("@label:listbox", "Disabled alarm color:"), box);
1663 box->setStretchFactor(new QWidget(box), 0);
1664 mDisabledColour = new ColourButton(box);
1665 label1->setBuddy(mDisabledColour);
1666 box->setWhatsThis(i18nc("@info:whatsthis", "Choose the text color in the alarm list for disabled alarms."));
1668 box = new KHBox(group); // to group widgets for QWhatsThis text
1669 box->setMargin(0);
1670 box->setSpacing(KDialog::spacingHint()/2);
1671 colourLayout->addWidget(box);
1672 QLabel* label2 = new QLabel(i18nc("@label:listbox", "Archived alarm color:"), box);
1673 box->setStretchFactor(new QWidget(box), 0);
1674 mArchivedColour = new ColourButton(box);
1675 label2->setBuddy(mArchivedColour);
1676 box->setWhatsThis(i18nc("@info:whatsthis", "Choose the text color in the alarm list for archived alarms."));
1677 hlayout->addStretch();
1679 QVBoxLayout* lay = qobject_cast<QVBoxLayout*>(topGeneral->layout());
1680 if (lay)
1681 lay->addStretch(); // top adjust the widgets
1683 group = new QGroupBox(i18nc("@title:group", "Alarm Message Windows"), topWindows);
1684 grid = new QGridLayout(group);
1685 grid->setMargin(KDialog::marginHint());
1686 grid->setSpacing(KDialog::spacingHint());
1687 grid->setColumnStretch(1, 1);
1688 grid->setColumnMinimumWidth(0, indentWidth());
1689 mWindowPosition = new ButtonGroup(group);
1690 connect(mWindowPosition, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotWindowPosChanged(QAbstractButton*)));
1692 QString whatsthis = i18nc("@info:whatsthis",
1693 "<para>Choose how to reduce the chance of alarm messages being accidentally acknowledged:"
1694 "<list><item>Position alarm message windows as far as possible from the current mouse cursor location, or</item>"
1695 "<item>Position alarm message windows in the center of the screen, but disable buttons for a short time after the window is displayed.</item></list></para>");
1696 QRadioButton* radio = new QRadioButton(i18nc("@option:radio", "Position windows far from mouse cursor"), group);
1697 mWindowPosition->addButton(radio, 0);
1698 radio->setWhatsThis(whatsthis);
1699 grid->addWidget(radio, 0, 0, 1, 2, Qt::AlignLeft);
1700 radio = new QRadioButton(i18nc("@option:radio", "Center windows, delay activating window buttons"), group);
1701 mWindowPosition->addButton(radio, 1);
1702 radio->setWhatsThis(whatsthis);
1703 grid->addWidget(radio, 1, 0, 1, 2, Qt::AlignLeft);
1705 KHBox* itemBox = new KHBox(group);
1706 itemBox->setMargin(0);
1707 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
1708 box->setMargin(0);
1709 box->setSpacing(KDialog::spacingHint());
1710 mWindowButtonDelayLabel = new QLabel(i18nc("@label:spinbox", "Button activation delay (seconds):"), box);
1711 mWindowButtonDelay = new QSpinBox(box);
1712 mWindowButtonDelay->setRange(1, 10);
1713 mWindowButtonDelayLabel->setBuddy(mWindowButtonDelay);
1714 box->setWhatsThis(i18nc("@info:whatsthis",
1715 "Enter how long its buttons should remain disabled after the alarm message window is shown."));
1716 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
1717 grid->addWidget(itemBox, 2, 1, Qt::AlignLeft);
1719 grid->setRowMinimumHeight(3, KDialog::spacingHint());
1721 mModalMessages = new QCheckBox(i18nc("@option:check", "Message windows have a title bar and take keyboard focus"), group);
1722 mModalMessages->setMinimumSize(mModalMessages->sizeHint());
1723 mModalMessages->setWhatsThis(i18nc("@info:whatsthis",
1724 "<para>Specify the characteristics of alarm message windows:"
1725 "<list><item>If checked, the window is a normal window with a title bar, which grabs keyboard input when it is displayed.</item>"
1726 "<item>If unchecked, the window does not interfere with your typing when "
1727 "it is displayed, but it has no title bar and cannot be moved or resized.</item></list></para>"));
1728 grid->addWidget(mModalMessages, 4, 0, 1, 2, Qt::AlignLeft);
1730 lay = qobject_cast<QVBoxLayout*>(topWindows->layout());
1731 if (lay)
1732 lay->addStretch(); // top adjust the widgets
1735 void ViewPrefTab::restore(bool, bool allTabs)
1737 if (allTabs || mTabs->currentIndex() == mTabGeneral)
1739 mShowInSystemTray->setChecked(Preferences::showInSystemTray());
1740 setTooltip(Preferences::tooltipAlarmCount(),
1741 Preferences::showTooltipAlarmTime(),
1742 Preferences::showTooltipTimeToAlarm(),
1743 Preferences::tooltipTimeToPrefix());
1744 mDisabledColour->setColor(Preferences::disabledColour());
1745 mArchivedColour->setColor(Preferences::archivedColour());
1747 if (allTabs || mTabs->currentIndex() == mTabWindows)
1749 mWindowPosition->setButton(Preferences::messageButtonDelay() ? 1 : 0);
1750 mWindowButtonDelay->setValue(Preferences::messageButtonDelay());
1751 mModalMessages->setChecked(Preferences::modalMessages());
1755 void ViewPrefTab::apply(bool syncToDisc)
1757 QColor colour = mDisabledColour->color();
1758 if (colour != Preferences::disabledColour())
1759 Preferences::setDisabledColour(colour);
1760 colour = mArchivedColour->color();
1761 if (colour != Preferences::archivedColour())
1762 Preferences::setArchivedColour(colour);
1763 int n = mTooltipShowAlarms->isChecked() ? -1 : 0;
1764 if (n && mTooltipMaxAlarms->isChecked())
1765 n = mTooltipMaxAlarmCount->value();
1766 if (n != Preferences::tooltipAlarmCount())
1767 Preferences::setTooltipAlarmCount(n);
1768 bool b = mTooltipShowTime->isChecked();
1769 if (b != Preferences::showTooltipAlarmTime())
1770 Preferences::setShowTooltipAlarmTime(b);
1771 b = mTooltipShowTimeTo->isChecked();
1772 if (b != Preferences::showTooltipTimeToAlarm())
1773 Preferences::setShowTooltipTimeToAlarm(b);
1774 QString text = mTooltipTimeToPrefix->text();
1775 if (text != Preferences::tooltipTimeToPrefix())
1776 Preferences::setTooltipTimeToPrefix(text);
1777 b = mShowInSystemTray->isChecked();
1778 if (b != Preferences::showInSystemTray())
1779 Preferences::setShowInSystemTray(b);
1780 n = mWindowPosition->selectedId();
1781 if (n)
1782 n = mWindowButtonDelay->value();
1783 if (n != Preferences::messageButtonDelay())
1784 Preferences::setMessageButtonDelay(n);
1785 b = mModalMessages->isChecked();
1786 if (b != Preferences::modalMessages())
1787 Preferences::setModalMessages(b);
1788 PrefsTabBase::apply(syncToDisc);
1791 void ViewPrefTab::setTooltip(int maxAlarms, bool time, bool timeTo, const QString& prefix)
1793 if (!timeTo)
1794 time = true; // ensure that at least one time option is ticked
1796 // Set the states of the controls without calling signal
1797 // handlers, since these could change the checkboxes' states.
1798 mTooltipShowAlarms->blockSignals(true);
1799 mTooltipShowTime->blockSignals(true);
1800 mTooltipShowTimeTo->blockSignals(true);
1802 mTooltipShowAlarms->setChecked(maxAlarms);
1803 mTooltipMaxAlarms->setChecked(maxAlarms > 0);
1804 mTooltipMaxAlarmCount->setValue(maxAlarms > 0 ? maxAlarms : 1);
1805 mTooltipShowTime->setChecked(time);
1806 mTooltipShowTimeTo->setChecked(timeTo);
1807 mTooltipTimeToPrefix->setText(prefix);
1809 mTooltipShowAlarms->blockSignals(false);
1810 mTooltipShowTime->blockSignals(false);
1811 mTooltipShowTimeTo->blockSignals(false);
1813 // Enable/disable controls according to their states
1814 slotTooltipTimeToToggled(timeTo);
1815 slotTooltipAlarmsToggled(maxAlarms);
1818 void ViewPrefTab::slotTooltipAlarmsToggled(bool on)
1820 mTooltipMaxAlarms->setEnabled(on);
1821 mTooltipMaxAlarmCount->setEnabled(on && mTooltipMaxAlarms->isChecked());
1822 mTooltipShowTime->setEnabled(on);
1823 mTooltipShowTimeTo->setEnabled(on);
1824 on = on && mTooltipShowTimeTo->isChecked();
1825 mTooltipTimeToPrefix->setEnabled(on);
1826 mTooltipTimeToPrefixLabel->setEnabled(on);
1829 void ViewPrefTab::slotTooltipMaxToggled(bool on)
1831 mTooltipMaxAlarmCount->setEnabled(on && mTooltipMaxAlarms->isEnabled());
1834 void ViewPrefTab::slotTooltipTimeToggled(bool on)
1836 if (!on && !mTooltipShowTimeTo->isChecked())
1837 mTooltipShowTimeTo->setChecked(true);
1840 void ViewPrefTab::slotTooltipTimeToToggled(bool on)
1842 if (!on && !mTooltipShowTime->isChecked())
1843 mTooltipShowTime->setChecked(true);
1844 on = on && mTooltipShowTimeTo->isEnabled();
1845 mTooltipTimeToPrefix->setEnabled(on);
1846 mTooltipTimeToPrefixLabel->setEnabled(on);
1849 void ViewPrefTab::slotWindowPosChanged(QAbstractButton* button)
1851 bool enable = mWindowPosition->id(button);
1852 mWindowButtonDelay->setEnabled(enable);
1853 mWindowButtonDelayLabel->setEnabled(enable);
1856 // vim: et sw=4: