french -> French
[kdepim.git] / kalarm / prefdlg.cpp
blobf887858ec891984e315a34cdbc1348347b3e2264
1 /*
2 * prefdlg.cpp - program preferences dialog
3 * Program: kalarm
4 * Copyright © 2001-2012 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 "itembox.h"
37 #include "kalarmapp.h"
38 #include "kalocale.h"
39 #include "kamail.h"
40 #include "label.h"
41 #include "latecancel.h"
42 #include "mainwindow.h"
43 #include "messagebox.h"
44 #include "preferences.h"
45 #include "radiobutton.h"
46 #include "recurrenceedit.h"
47 #include "sounddlg.h"
48 #include "soundpicker.h"
49 #include "specialactions.h"
50 #include "stackedwidgets.h"
51 #include "timeedit.h"
52 #include "timespinbox.h"
53 #include "timezonecombo.h"
54 #include "traywindow.h"
55 #include "prefdlg_p.h"
56 #include "prefdlg.h"
58 #include <kalarmcal/identities.h>
60 #include <kholidays/holidays.h>
61 using namespace KHolidays;
63 #include <kvbox.h>
64 #include <kglobal.h>
65 #include <klocale.h>
66 #include <kstandarddirs.h>
67 #include <kshell.h>
68 #include <klineedit.h>
69 #include <kaboutdata.h>
70 #include <kapplication.h>
71 #include <kiconloader.h>
72 #include <kcombobox.h>
73 #include <ktabwidget.h>
74 #include <kstandardguiitem.h>
75 #include <ksystemtimezone.h>
76 #include <kicon.h>
77 #ifdef Q_WS_X11
78 #include <kwindowinfo.h>
79 #include <kwindowsystem.h>
80 #endif
81 #include <ktoolinvocation.h>
82 #include <kdebug.h>
84 #include <QLabel>
85 #include <QCheckBox>
86 #include <QRadioButton>
87 #include <QPushButton>
88 #include <QSpinBox>
89 #include <QGroupBox>
90 #include <QGridLayout>
91 #include <QHBoxLayout>
92 #include <QVBoxLayout>
93 #include <QStyle>
94 #include <QResizeEvent>
95 #include <QTimer>
97 #ifdef USE_AKONADI
98 using namespace KCalCore;
99 #else
100 using namespace KCal;
101 #endif
102 using namespace KAlarmCal;
104 static const char PREF_DIALOG_NAME[] = "PrefDialog";
106 // Command strings for executing commands in different types of terminal windows.
107 // %t = window title parameter
108 // %c = command to execute in terminal
109 // %w = command to execute in terminal, with 'sleep 86400' appended
110 // %C = temporary command file to execute in terminal
111 // %W = temporary command file to execute in terminal, with 'sleep 86400' appended
112 static QString xtermCommands[] = {
113 QLatin1String("xterm -sb -hold -title %t -e %c"),
114 QLatin1String("konsole --noclose -p tabtitle=%t -e ${SHELL:-sh} -c %c"),
115 QLatin1String("gnome-terminal -t %t -e %W"),
116 QLatin1String("eterm --pause -T %t -e %C"), // some systems use eterm...
117 QLatin1String("Eterm --pause -T %t -e %C"), // while some use Eterm
118 QLatin1String("rxvt -title %t -e ${SHELL:-sh} -c %w"),
119 QString() // end of list indicator - don't change!
123 /*=============================================================================
124 = Class KAlarmPrefDlg
125 =============================================================================*/
127 KAlarmPrefDlg* KAlarmPrefDlg::mInstance = 0;
129 void KAlarmPrefDlg::display()
131 if (!mInstance)
133 mInstance = new KAlarmPrefDlg;
134 QSize s;
135 if (KAlarm::readConfigWindowSize(PREF_DIALOG_NAME, s))
136 mInstance->resize(s);
137 mInstance->show();
139 else
141 #ifdef Q_WS_X11
142 KWindowInfo info = KWindowSystem::windowInfo(mInstance->winId(), NET::WMGeometry | NET::WMDesktop);
143 KWindowSystem::setCurrentDesktop(info.desktop());
144 #endif
145 mInstance->setWindowState(mInstance->windowState() & ~Qt::WindowMinimized); // un-minimize it if necessary
146 mInstance->raise();
147 mInstance->activateWindow();
151 KAlarmPrefDlg::KAlarmPrefDlg()
152 : KPageDialog(),
153 mShown(false)
155 setAttribute(Qt::WA_DeleteOnClose);
156 setObjectName(QLatin1String("PrefDlg")); // used by LikeBack
157 setCaption(i18nc("@title:window", "Configure"));
158 setButtons(Help | Default | Ok | Apply | Cancel);
159 setDefaultButton(Ok);
160 setFaceType(List);
161 showButtonSeparator(true);
162 mTabScrollGroup = new StackedScrollGroup(this, this);
164 mMiscPage = new MiscPrefTab(mTabScrollGroup);
165 mMiscPageItem = new KPageWidgetItem(mMiscPage, i18nc("@title:tab General preferences", "General"));
166 mMiscPageItem->setHeader(i18nc("@title General preferences", "General"));
167 mMiscPageItem->setIcon(KIcon(DesktopIcon(QLatin1String("preferences-other"))));
168 addPage(mMiscPageItem);
170 mTimePage = new TimePrefTab(mTabScrollGroup);
171 mTimePageItem = new KPageWidgetItem(mTimePage, i18nc("@title:tab", "Time & Date"));
172 mTimePageItem->setHeader(i18nc("@title", "Time and Date"));
173 mTimePageItem->setIcon(KIcon(DesktopIcon(QLatin1String("preferences-system-time"))));
174 addPage(mTimePageItem);
176 mStorePage = new StorePrefTab(mTabScrollGroup);
177 mStorePageItem = new KPageWidgetItem(mStorePage, i18nc("@title:tab", "Storage"));
178 mStorePageItem->setHeader(i18nc("@title", "Alarm Storage"));
179 mStorePageItem->setIcon(KIcon(DesktopIcon(QLatin1String("system-file-manager"))));
180 addPage(mStorePageItem);
182 mEmailPage = new EmailPrefTab(mTabScrollGroup);
183 mEmailPageItem = new KPageWidgetItem(mEmailPage, i18nc("@title:tab Email preferences", "Email"));
184 mEmailPageItem->setHeader(i18nc("@title", "Email Alarm Settings"));
185 mEmailPageItem->setIcon(KIcon(DesktopIcon(QLatin1String("internet-mail"))));
186 addPage(mEmailPageItem);
188 mViewPage = new ViewPrefTab(mTabScrollGroup);
189 mViewPageItem = new KPageWidgetItem(mViewPage, i18nc("@title:tab", "View"));
190 mViewPageItem->setHeader(i18nc("@title", "View Settings"));
191 mViewPageItem->setIcon(KIcon(DesktopIcon(QLatin1String("preferences-desktop-theme"))));
192 addPage(mViewPageItem);
194 mEditPage = new EditPrefTab(mTabScrollGroup);
195 mEditPageItem = new KPageWidgetItem(mEditPage, i18nc("@title:tab", "Edit"));
196 mEditPageItem->setHeader(i18nc("@title", "Default Alarm Edit Settings"));
197 mEditPageItem->setIcon(KIcon(DesktopIcon(QLatin1String("document-properties"))));
198 addPage(mEditPageItem);
200 connect(this, SIGNAL(okClicked()), SLOT(slotOk()));
201 connect(this, SIGNAL(cancelClicked()), SLOT(slotCancel()));
202 connect(this, SIGNAL(applyClicked()), SLOT(slotApply()));
203 connect(this, SIGNAL(defaultClicked()), SLOT(slotDefault()));
204 connect(this, SIGNAL(helpClicked()), SLOT(slotHelp()));
205 restore(false);
206 adjustSize();
209 KAlarmPrefDlg::~KAlarmPrefDlg()
211 mInstance = 0;
214 void KAlarmPrefDlg::slotHelp()
216 KToolInvocation::invokeHelp(QLatin1String("preferences"));
219 // Apply the preferences that are currently selected
220 void KAlarmPrefDlg::slotApply()
222 kDebug();
223 QString errmsg = mEmailPage->validate();
224 if (!errmsg.isEmpty())
226 setCurrentPage(mEmailPageItem);
227 if (KAMessageBox::warningYesNo(this, errmsg) != KMessageBox::Yes)
229 mValid = false;
230 return;
233 errmsg = mEditPage->validate();
234 if (!errmsg.isEmpty())
236 setCurrentPage(mEditPageItem);
237 KAMessageBox::sorry(this, errmsg);
238 mValid = false;
239 return;
241 mValid = true;
242 mEmailPage->apply(false);
243 mViewPage->apply(false);
244 mEditPage->apply(false);
245 mStorePage->apply(false);
246 mTimePage->apply(false);
247 mMiscPage->apply(false);
248 Preferences::self()->writeConfig();
251 // Apply the preferences that are currently selected
252 void KAlarmPrefDlg::slotOk()
254 kDebug();
255 mValid = true;
256 slotApply();
257 if (mValid)
258 KDialog::accept();
261 // Discard the current preferences and close the dialog
262 void KAlarmPrefDlg::slotCancel()
264 kDebug();
265 restore(false);
266 KDialog::reject();
269 // Reset all controls to the application defaults
270 void KAlarmPrefDlg::slotDefault()
272 switch (KAMessageBox::questionYesNoCancel(this, i18nc("@info", "Reset all tabs to their default values, or only reset the current tab?"),
273 QString(),
274 KGuiItem(i18nc("@action:button Reset ALL tabs", "&All")),
275 KGuiItem(i18nc("@action:button Reset the CURRENT tab", "C&urrent"))))
277 case KMessageBox::Yes:
278 restore(true); // restore all tabs
279 break;
280 case KMessageBox::No:
281 Preferences::self()->useDefaults(true);
282 static_cast<PrefsTabBase*>(currentPage()->widget())->restore(true, false);
283 Preferences::self()->useDefaults(false);
284 break;
285 default:
286 break;
290 // Discard the current preferences and use the present ones
291 void KAlarmPrefDlg::restore(bool defaults)
293 kDebug() << (defaults ? "defaults" : "");
294 if (defaults)
295 Preferences::self()->useDefaults(true);
296 mEmailPage->restore(defaults, true);
297 mViewPage->restore(defaults, true);
298 mEditPage->restore(defaults, true);
299 mStorePage->restore(defaults, true);
300 mTimePage->restore(defaults, true);
301 mMiscPage->restore(defaults, true);
302 if (defaults)
303 Preferences::self()->useDefaults(false);
306 /******************************************************************************
307 * Return the minimum size for the dialog.
308 * If the minimum size would be too high to fit the desktop, the tab contents
309 * are made scrollable.
311 QSize KAlarmPrefDlg::minimumSizeHint() const
313 if (!mTabScrollGroup->sized())
315 QSize s = mTabScrollGroup->adjustSize();
316 if (s.isValid())
318 if (mTabScrollGroup->heightReduction())
320 s = QSize(s.width(), s.height() - mTabScrollGroup->heightReduction());
321 const_cast<KAlarmPrefDlg*>(this)->resize(s);
323 return s;
326 return KDialog::minimumSizeHint();
329 void KAlarmPrefDlg::showEvent(QShowEvent* e)
331 KDialog::showEvent(e);
332 if (!mShown)
334 mTabScrollGroup->adjustSize(true);
335 mShown = true;
339 /******************************************************************************
340 * Called when the dialog's size has changed.
341 * Records the new size in the config file.
343 void KAlarmPrefDlg::resizeEvent(QResizeEvent* re)
345 if (isVisible())
346 KAlarm::writeConfigWindowSize(PREF_DIALOG_NAME, re->size());
347 KPageDialog::resizeEvent(re);
351 /*=============================================================================
352 = Class PrefsTabBase
353 =============================================================================*/
354 int PrefsTabBase::mIndentWidth = 0;
356 PrefsTabBase::PrefsTabBase(StackedScrollGroup* scrollGroup)
357 : StackedScrollWidget(scrollGroup),
358 mLabelsAligned(false)
360 mTopWidget = new KVBox(this);
361 mTopWidget->setMargin(0);
362 mTopWidget->setSpacing(KDialog::spacingHint());
363 setWidget(mTopWidget);
364 if (!mIndentWidth)
366 QRadioButton radio(this);
367 QStyleOptionButton opt;
368 opt.initFrom(&radio);
369 mIndentWidth = style()->subElementRect(QStyle::SE_RadioButtonIndicator, &opt).width();
371 mTopLayout = qobject_cast<QVBoxLayout*>(mTopWidget->layout());
372 Q_ASSERT(mTopLayout);
375 void PrefsTabBase::apply(bool syncToDisc)
377 if (syncToDisc)
378 Preferences::self()->writeConfig();
381 void PrefsTabBase::addAlignedLabel(QLabel* label)
383 mLabels += label;
386 void PrefsTabBase::showEvent(QShowEvent*)
388 if (!mLabelsAligned)
390 int wid = 0;
391 int i;
392 int end = mLabels.count();
393 QList<int> xpos;
394 for (i = 0; i < end; ++i)
396 int x = mLabels[i]->mapTo(this, QPoint(0, 0)).x();
397 xpos += x;
398 int w = x + mLabels[i]->sizeHint().width();
399 if (w > wid)
400 wid = w;
402 for (i = 0; i < end; ++i)
404 mLabels[i]->setFixedWidth(wid - xpos[i]);
405 mLabels[i]->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
407 mLabelsAligned = true;
412 /*=============================================================================
413 = Class MiscPrefTab
414 =============================================================================*/
416 MiscPrefTab::MiscPrefTab(StackedScrollGroup* scrollGroup)
417 : PrefsTabBase(scrollGroup)
419 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Run Mode"), topWidget());
420 QVBoxLayout* vlayout = new QVBoxLayout(group);
421 vlayout->setMargin(KDialog::marginHint());
422 vlayout->setSpacing(KDialog::spacingHint());
424 // Start at login
425 mAutoStart = new QCheckBox(i18nc("@option:check", "Start at login"), group);
426 connect(mAutoStart, SIGNAL(clicked()), SLOT(slotAutostartClicked()));
427 mAutoStart->setWhatsThis(i18nc("@info:whatsthis",
428 "<para>Automatically start <application>KAlarm</application> whenever you start KDE.</para>"
429 "<para>This option should always be checked unless you intend to discontinue use of <application>KAlarm</application>.</para>"));
430 vlayout->addWidget(mAutoStart, 0, Qt::AlignLeft);
432 mQuitWarn = new QCheckBox(i18nc("@option:check", "Warn before quitting"), group);
433 mQuitWarn->setWhatsThis(i18nc("@info:whatsthis", "Check to display a warning prompt before quitting <application>KAlarm</application>."));
434 vlayout->addWidget(mQuitWarn, 0, Qt::AlignLeft);
436 group->setFixedHeight(group->sizeHint().height());
438 // Confirm alarm deletion?
439 KHBox* itemBox = new KHBox(topWidget()); // this is to allow left adjustment
440 itemBox->setMargin(0);
441 mConfirmAlarmDeletion = new QCheckBox(i18nc("@option:check", "Confirm alarm deletions"), itemBox);
442 mConfirmAlarmDeletion->setMinimumSize(mConfirmAlarmDeletion->sizeHint());
443 mConfirmAlarmDeletion->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation each time you delete an alarm."));
444 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
445 itemBox->setFixedHeight(itemBox->sizeHint().height());
447 // Default alarm deferral time
448 itemBox = new KHBox(topWidget()); // this is to allow left adjustment
449 KHBox* box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
450 box->setSpacing(KDialog::spacingHint());
451 QLabel* label = new QLabel(i18nc("@label:spinbox", "Default defer time interval:"), box);
452 mDefaultDeferTime = new TimeSpinBox(1, 5999, box);
453 mDefaultDeferTime->setMinimumSize(mDefaultDeferTime->sizeHint());
454 box->setWhatsThis(i18nc("@info:whatsthis",
455 "Enter the default time interval (hours & minutes) to defer alarms, used by the Defer Alarm dialog."));
456 label->setBuddy(mDefaultDeferTime);
457 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
458 itemBox->setFixedHeight(itemBox->sizeHint().height());
460 // Terminal window to use for command alarms
461 group = new QGroupBox(i18nc("@title:group", "Terminal for Command Alarms"), topWidget());
462 group->setWhatsThis(i18nc("@info:whatsthis", "Choose which application to use when a command alarm is executed in a terminal window"));
463 QGridLayout* grid = new QGridLayout(group);
464 grid->setMargin(KDialog::marginHint());
465 grid->setSpacing(KDialog::spacingHint());
466 int row = 0;
468 mXtermType = new ButtonGroup(group);
469 int index = 0;
470 mXtermFirst = -1;
471 for (mXtermCount = 0; !xtermCommands[mXtermCount].isNull(); ++mXtermCount)
473 QString cmd = xtermCommands[mXtermCount];
474 QStringList args = KShell::splitArgs(cmd);
475 if (args.isEmpty() || KStandardDirs::findExe(args[0]).isEmpty())
476 continue;
477 QRadioButton* radio = new QRadioButton(args[0], group);
478 radio->setMinimumSize(radio->sizeHint());
479 mXtermType->addButton(radio, mXtermCount);
480 if (mXtermFirst < 0)
481 mXtermFirst = mXtermCount; // note the id of the first button
482 cmd.replace(QLatin1String("%t"), KGlobal::mainComponent().aboutData()->programName());
483 cmd.replace(QLatin1String("%c"), QLatin1String("<command>"));
484 cmd.replace(QLatin1String("%w"), QLatin1String("<command; sleep>"));
485 cmd.replace(QLatin1String("%C"), QLatin1String("[command]"));
486 cmd.replace(QLatin1String("%W"), QLatin1String("[command; sleep]"));
487 radio->setWhatsThis(
488 i18nc("@info:whatsthis", "Check to execute command alarms in a terminal window by <icode>%1</icode>", cmd));
489 grid->addWidget(radio, (row = index/3), index % 3, Qt::AlignLeft);
490 ++index;
493 // QHBox used here doesn't allow the KLineEdit to expand!?
494 QHBoxLayout* hlayout = new QHBoxLayout();
495 hlayout->setSpacing(KDialog::spacingHint());
496 grid->addLayout(hlayout, row + 1, 0, 1, 3, Qt::AlignLeft);
497 QRadioButton* radio = new QRadioButton(i18nc("@option:radio Other terminal window command", "Other:"), group);
498 hlayout->addWidget(radio);
499 connect(radio, SIGNAL(toggled(bool)), SLOT(slotOtherTerminalToggled(bool)));
500 mXtermType->addButton(radio, mXtermCount);
501 if (mXtermFirst < 0)
502 mXtermFirst = mXtermCount; // note the id of the first button
503 mXtermCommand = new KLineEdit(group);
504 mXtermCommand->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
505 hlayout->addWidget(mXtermCommand);
506 QString wt =
507 i18nc("@info:whatsthis", "Enter the full command line needed to execute a command in your chosen terminal window. "
508 "By default the alarm's command string will be appended to what you enter here. "
509 "See the <application>KAlarm</application> Handbook for details of special codes to tailor the command line.");
510 radio->setWhatsThis(wt);
511 mXtermCommand->setWhatsThis(wt);
513 topLayout()->addStretch(); // top adjust the widgets
516 void MiscPrefTab::restore(bool defaults, bool)
518 mAutoStart->setChecked(defaults ? true : Preferences::autoStart());
519 mQuitWarn->setChecked(Preferences::quitWarn());
520 mConfirmAlarmDeletion->setChecked(Preferences::confirmAlarmDeletion());
521 mDefaultDeferTime->setValue(Preferences::defaultDeferTime());
522 QString xtermCmd = Preferences::cmdXTermCommand();
523 int id = mXtermFirst;
524 if (!xtermCmd.isEmpty())
526 for ( ; id < mXtermCount; ++id)
528 if (mXtermType->find(id) && xtermCmd == xtermCommands[id])
529 break;
532 mXtermType->setButton(id);
533 mXtermCommand->setEnabled(id == mXtermCount);
534 mXtermCommand->setText(id == mXtermCount ? xtermCmd : QString());
537 void MiscPrefTab::apply(bool syncToDisc)
539 // First validate anything entered in Other X-terminal command
540 int xtermID = mXtermType->selectedId();
541 if (xtermID >= mXtermCount)
543 QString cmd = mXtermCommand->text();
544 if (cmd.isEmpty())
545 xtermID = -1; // 'Other' is only acceptable if it's non-blank
546 else
548 QStringList args = KShell::splitArgs(cmd);
549 cmd = args.isEmpty() ? QString() : args[0];
550 if (KStandardDirs::findExe(cmd).isEmpty())
552 mXtermCommand->setFocus();
553 if (KAMessageBox::warningContinueCancel(topWidget(), i18nc("@info", "Command to invoke terminal window not found: <command>%1</command>", cmd))
554 != KMessageBox::Continue)
555 return;
559 if (xtermID < 0)
561 xtermID = mXtermFirst;
562 mXtermType->setButton(mXtermFirst);
565 if (mQuitWarn->isEnabled())
567 bool b = mQuitWarn->isChecked();
568 if (b != Preferences::quitWarn())
569 Preferences::setQuitWarn(b);
571 bool b = mAutoStart->isChecked();
572 if (b != Preferences::autoStart())
574 Preferences::setAutoStart(b);
575 Preferences::setAskAutoStart(true); // cancel any start-at-login prompt suppression
576 if (b)
577 Preferences::setNoAutoStart(false);
578 Preferences::setAutoStartChangedByUser(true); // prevent prompting the user on quit, about start-at-login
580 b = mConfirmAlarmDeletion->isChecked();
581 if (b != Preferences::confirmAlarmDeletion())
582 Preferences::setConfirmAlarmDeletion(b);
583 int i = mDefaultDeferTime->value();
584 if (i != Preferences::defaultDeferTime())
585 Preferences::setDefaultDeferTime(i);
586 QString text = (xtermID < mXtermCount) ? xtermCommands[xtermID] : mXtermCommand->text();
587 if (text != Preferences::cmdXTermCommand())
588 Preferences::setCmdXTermCommand(text);
589 PrefsTabBase::apply(syncToDisc);
592 void MiscPrefTab::slotAutostartClicked()
594 if (!mAutoStart->isChecked()
595 && KAMessageBox::warningYesNo(topWidget(),
596 i18nc("@info", "You should not uncheck this option unless you intend to discontinue use of <application>KAlarm</application>"),
597 QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()
598 ) != KMessageBox::Yes)
599 mAutoStart->setChecked(true);
602 void MiscPrefTab::slotOtherTerminalToggled(bool on)
604 mXtermCommand->setEnabled(on);
608 /*=============================================================================
609 = Class TimePrefTab
610 =============================================================================*/
612 TimePrefTab::TimePrefTab(StackedScrollGroup* scrollGroup)
613 : PrefsTabBase(scrollGroup)
615 // Default time zone
616 ItemBox* itemBox = new ItemBox(topWidget());
617 itemBox->setMargin(0);
618 KHBox* box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
619 box->setMargin(0);
620 box->setSpacing(KDialog::spacingHint());
621 QLabel* label = new QLabel(i18nc("@label:listbox", "Time zone:"), box);
622 addAlignedLabel(label);
623 #if 1
624 mTimeZone = new TimeZoneCombo(box);
625 mTimeZone->setMaxVisibleItems(15);
626 #else
627 mTimeZone = new KComboBox(box);
628 mTimeZone->setMaxVisibleItems(15);
629 const KTimeZones::ZoneMap zones = KSystemTimeZones::zones();
630 for (KTimeZones::ZoneMap::ConstIterator it = zones.constBegin(); it != zones.constEnd(); ++it)
631 mTimeZone->addItem(it.key());
632 #endif
633 box->setWhatsThis(i18nc("@info:whatsthis",
634 "Select the time zone which <application>KAlarm</application> should use "
635 "as its default for displaying and entering dates and times."));
636 label->setBuddy(mTimeZone);
637 itemBox->leftAlign();
638 itemBox->setFixedHeight(box->sizeHint().height());
640 // Holiday region
641 itemBox = new ItemBox(topWidget());
642 itemBox->setMargin(0);
643 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
644 box->setMargin(0);
645 box->setSpacing(KDialog::spacingHint());
646 label = new QLabel(i18nc("@label:listbox", "Holiday region:"), box);
647 addAlignedLabel(label);
648 mHolidays = new KComboBox(box);
649 mHolidays->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
650 itemBox->leftAlign();
651 label->setBuddy(mHolidays);
652 box->setWhatsThis(i18nc("@info:whatsthis",
653 "Select which holiday region to use"));
655 QStringList regions = HolidayRegion::regionCodes();
656 QMap<QString, QString> regionsMap;
657 foreach (const QString& regionCode, regions)
659 QString name = HolidayRegion::name(regionCode);
660 QString languageName = KGlobal::locale()->languageCodeToName(HolidayRegion::languageCode(regionCode));
661 QString label = languageName.isEmpty() ? name : i18nc("Holiday region, region language", "%1 (%2)", name, languageName);
662 regionsMap.insert(label, regionCode);
665 mHolidays->addItem(i18nc("No holiday region", "None"), QString());
666 for (QMapIterator<QString, QString> it(regionsMap); it.hasNext(); )
668 it.next();
669 mHolidays->addItem(it.key(), it.value());
672 // Start-of-day time
673 itemBox = new ItemBox(topWidget());
674 itemBox->setMargin(0);
675 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
676 box->setMargin(0);
677 box->setSpacing(KDialog::spacingHint());
678 label = new QLabel(i18nc("@label:spinbox", "Start of day for date-only alarms:"), box);
679 addAlignedLabel(label);
680 mStartOfDay = new TimeEdit(box);
681 label->setBuddy(mStartOfDay);
682 box->setWhatsThis(i18nc("@info:whatsthis",
683 "<para>The earliest time of day at which a date-only alarm will be triggered.</para>"
684 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
685 itemBox->leftAlign();
686 itemBox->setFixedHeight(box->sizeHint().height());
688 // Working hours
689 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Working Hours"), topWidget());
690 QBoxLayout* layout = new QVBoxLayout(group);
691 layout->setMargin(KDialog::marginHint());
692 layout->setSpacing(KDialog::spacingHint());
694 QWidget* daybox = new QWidget(group); // this is to control the QWhatsThis text display area
695 layout->addWidget(daybox);
696 QGridLayout* wgrid = new QGridLayout(daybox);
697 wgrid->setSpacing(KDialog::spacingHint());
698 const KLocale* locale = KGlobal::locale();
699 for (int i = 0; i < 7; ++i)
701 int day = KAlarm::localeDayInWeek_to_weekDay(i);
702 mWorkDays[i] = new QCheckBox(KAlarm::weekDayName(day, locale), daybox);
703 wgrid->addWidget(mWorkDays[i], i/3, i%3, Qt::AlignLeft);
705 daybox->setFixedHeight(daybox->sizeHint().height());
706 daybox->setWhatsThis(i18nc("@info:whatsthis", "Check the days in the week which are work days"));
708 itemBox = new ItemBox(group);
709 itemBox->setMargin(0);
710 layout->addWidget(itemBox);
711 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
712 box->setMargin(0);
713 box->setSpacing(KDialog::spacingHint());
714 label = new QLabel(i18nc("@label:spinbox", "Daily start time:"), box);
715 addAlignedLabel(label);
716 mWorkStart = new TimeEdit(box);
717 label->setBuddy(mWorkStart);
718 box->setWhatsThis(i18nc("@info:whatsthis",
719 "<para>Enter the start time of the working day.</para>"
720 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
721 itemBox->leftAlign();
723 itemBox = new ItemBox(group);
724 itemBox->setMargin(0);
725 layout->addWidget(itemBox);
726 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
727 box->setMargin(0);
728 box->setSpacing(KDialog::spacingHint());
729 label = new QLabel(i18nc("@label:spinbox", "Daily end time:"), box);
730 addAlignedLabel(label);
731 mWorkEnd = new TimeEdit(box);
732 label->setBuddy(mWorkEnd);
733 box->setWhatsThis(i18nc("@info:whatsthis",
734 "<para>Enter the end time of the working day.</para>"
735 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
736 itemBox->leftAlign();
737 box->setFixedHeight(box->sizeHint().height());
739 // KOrganizer event duration
740 group = new QGroupBox(i18nc("@title:group", "KOrganizer"), topWidget());
741 layout = new QVBoxLayout(group);
742 layout->setMargin(KDialog::marginHint());
743 layout->setSpacing(KDialog::spacingHint());
745 itemBox = new ItemBox(group);
746 itemBox->setMargin(0);
747 layout->addWidget(itemBox);
748 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
749 box->setMargin(0);
750 box->setSpacing(KDialog::spacingHint());
751 label = new QLabel(i18nc("@label:spinbox", "KOrganizer event duration:"), box);
752 addAlignedLabel(label);
753 mKOrgEventDuration = new TimeSpinBox(0, 5999, box);
754 mKOrgEventDuration->setMinimumSize(mKOrgEventDuration->sizeHint());
755 box->setWhatsThis(i18nc("@info:whatsthis",
756 "<para>Enter the event duration in hours and minutes, for alarms which are copied to KOrganizer.</para>"
757 "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
758 label->setBuddy(mKOrgEventDuration);
759 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
760 itemBox->setFixedHeight(itemBox->sizeHint().height());
762 topLayout()->addStretch(); // top adjust the widgets
765 void TimePrefTab::restore(bool, bool)
767 #if 1
768 mTimeZone->setTimeZone(Preferences::timeZone());
769 #else
770 int tzindex = 0;
771 KTimeZone tz = Preferences::timeZone();
772 if (tz.isValid())
774 QString zone = tz.name();
775 int count = mTimeZone->count();
776 while (tzindex < count && mTimeZone->itemText(tzindex) != zone)
777 ++tzindex;
778 if (tzindex >= count)
779 tzindex = 0;
781 mTimeZone->setCurrentIndex(tzindex);
782 #endif
783 int i = Preferences::holidays().isValid() ? mHolidays->findData(Preferences::holidays().regionCode()) : 0;
784 mHolidays->setCurrentIndex(i);
785 mStartOfDay->setValue(Preferences::startOfDay());
786 mWorkStart->setValue(Preferences::workDayStart());
787 mWorkEnd->setValue(Preferences::workDayEnd());
788 QBitArray days = Preferences::workDays();
789 for (int i = 0; i < 7; ++i)
791 bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1);
792 mWorkDays[i]->setChecked(x);
794 mKOrgEventDuration->setValue(Preferences::kOrgEventDuration());
797 void TimePrefTab::apply(bool syncToDisc)
799 #if 1
800 KTimeZone tz = mTimeZone->timeZone();
801 if (tz.isValid())
802 Preferences::setTimeZone(tz);
803 #else
804 KTimeZone tz = KSystemTimeZones::zone(mTimeZone->currentText());
805 if (tz.isValid() && tz != Preferences::timeZone())
806 Preferences::setTimeZone(tz);
807 #endif
808 QString hol = mHolidays->itemData(mHolidays->currentIndex()).toString();
809 if (hol != Preferences::holidays().regionCode())
810 Preferences::setHolidayRegion(hol);
811 int t = mStartOfDay->value();
812 QTime sodt(t/60, t%60, 0);
813 if (sodt != Preferences::startOfDay())
814 Preferences::setStartOfDay(sodt);
815 t = mWorkStart->value();
816 Preferences::setWorkDayStart(QTime(t/60, t%60, 0));
817 t = mWorkEnd->value();
818 Preferences::setWorkDayEnd(QTime(t/60, t%60, 0));
819 QBitArray workDays(7);
820 for (int i = 0; i < 7; ++i)
821 if (mWorkDays[i]->isChecked())
822 workDays.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1);
823 Preferences::setWorkDays(workDays);
824 Preferences::setKOrgEventDuration(mKOrgEventDuration->value());
825 t = mKOrgEventDuration->value();
826 if (t != Preferences::kOrgEventDuration())
827 Preferences::setKOrgEventDuration(t);
828 PrefsTabBase::apply(syncToDisc);
832 /*=============================================================================
833 = Class StorePrefTab
834 =============================================================================*/
836 StorePrefTab::StorePrefTab(StackedScrollGroup* scrollGroup)
837 : PrefsTabBase(scrollGroup),
838 mCheckKeepChanges(false)
840 // Which resource to save to
841 QGroupBox* group = new QGroupBox(i18nc("@title:group", "New Alarms && Templates"), topWidget());
842 QButtonGroup* bgroup = new QButtonGroup(group);
843 QBoxLayout* layout = new QVBoxLayout(group);
844 layout->setMargin(KDialog::marginHint());
845 layout->setSpacing(KDialog::spacingHint());
847 mDefaultResource = new QRadioButton(i18nc("@option:radio", "Store in default calendar"), group);
848 bgroup->addButton(mDefaultResource);
849 mDefaultResource->setWhatsThis(i18nc("@info:whatsthis", "Add all new alarms and alarm templates to the default calendars, without prompting."));
850 layout->addWidget(mDefaultResource, 0, Qt::AlignLeft);
851 mAskResource = new QRadioButton(i18nc("@option:radio", "Prompt for which calendar to store in"), group);
852 bgroup->addButton(mAskResource);
853 mAskResource->setWhatsThis(i18nc("@info:whatsthis",
854 "<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>"
855 "<para>Note that archived alarms are always stored in the default archived alarm calendar.</para>"));
856 layout->addWidget(mAskResource, 0, Qt::AlignLeft);
858 // Archived alarms
859 group = new QGroupBox(i18nc("@title:group", "Archived Alarms"), topWidget());
860 QGridLayout* grid = new QGridLayout(group);
861 grid->setMargin(KDialog::marginHint());
862 grid->setSpacing(KDialog::spacingHint());
863 grid->setColumnStretch(1, 1);
864 grid->setColumnMinimumWidth(0, indentWidth());
865 mKeepArchived = new QCheckBox(i18nc("@option:check", "Keep alarms after expiry"), group);
866 connect(mKeepArchived, SIGNAL(toggled(bool)), SLOT(slotArchivedToggled(bool)));
867 mKeepArchived->setWhatsThis(
868 i18nc("@info:whatsthis", "Check to archive alarms after expiry or deletion (except deleted alarms which were never triggered)."));
869 grid->addWidget(mKeepArchived, 0, 0, 1, 2, Qt::AlignLeft);
871 KHBox* box = new KHBox(group);
872 box->setMargin(0);
873 box->setSpacing(KDialog::spacingHint());
874 mPurgeArchived = new QCheckBox(i18nc("@option:check", "Discard archived alarms after:"), box);
875 mPurgeArchived->setMinimumSize(mPurgeArchived->sizeHint());
876 connect(mPurgeArchived, SIGNAL(toggled(bool)), SLOT(slotArchivedToggled(bool)));
877 mPurgeAfter = new SpinBox(box);
878 mPurgeAfter->setMinimum(1);
879 mPurgeAfter->setSingleShiftStep(10);
880 mPurgeAfter->setMinimumSize(mPurgeAfter->sizeHint());
881 mPurgeAfterLabel = new QLabel(i18nc("@label Time unit for user-entered number", "days"), box);
882 mPurgeAfterLabel->setMinimumSize(mPurgeAfterLabel->sizeHint());
883 mPurgeAfterLabel->setBuddy(mPurgeAfter);
884 box->setWhatsThis(i18nc("@info:whatsthis", "Uncheck to store archived alarms indefinitely. Check to enter how long archived alarms should be stored."));
885 grid->addWidget(box, 1, 1, Qt::AlignLeft);
887 mClearArchived = new QPushButton(i18nc("@action:button", "Clear Archived Alarms"), group);
888 mClearArchived->setFixedSize(mClearArchived->sizeHint());
889 connect(mClearArchived, SIGNAL(clicked()), SLOT(slotClearArchived()));
890 #ifdef USE_AKONADI
891 mClearArchived->setWhatsThis((CollectionControlModel::enabledCollections(CalEvent::ARCHIVED, false).count() <= 1)
892 #else
893 mClearArchived->setWhatsThis((AlarmResources::instance()->activeCount(CalEvent::ARCHIVED, false) <= 1)
894 #endif
895 ? i18nc("@info:whatsthis", "Delete all existing archived alarms.")
896 : i18nc("@info:whatsthis", "Delete all existing archived alarms (from the default archived alarm calendar only)."));
897 grid->addWidget(mClearArchived, 2, 1, Qt::AlignLeft);
898 group->setFixedHeight(group->sizeHint().height());
900 topLayout()->addStretch(); // top adjust the widgets
903 void StorePrefTab::restore(bool defaults, bool)
905 mCheckKeepChanges = defaults;
906 if (Preferences::askResource())
907 mAskResource->setChecked(true);
908 else
909 mDefaultResource->setChecked(true);
910 int keepDays = Preferences::archivedKeepDays();
911 if (!defaults)
912 mOldKeepArchived = keepDays;
913 setArchivedControls(keepDays);
914 mCheckKeepChanges = true;
917 void StorePrefTab::apply(bool syncToDisc)
919 bool b = mAskResource->isChecked();
920 if (b != Preferences::askResource())
921 Preferences::setAskResource(mAskResource->isChecked());
922 int days = !mKeepArchived->isChecked() ? 0 : mPurgeArchived->isChecked() ? mPurgeAfter->value() : -1;
923 if (days != Preferences::archivedKeepDays())
924 Preferences::setArchivedKeepDays(days);
925 PrefsTabBase::apply(syncToDisc);
928 void StorePrefTab::setArchivedControls(int purgeDays)
930 mKeepArchived->setChecked(purgeDays);
931 mPurgeArchived->setChecked(purgeDays > 0);
932 mPurgeAfter->setValue(purgeDays > 0 ? purgeDays : 0);
933 slotArchivedToggled(true);
936 void StorePrefTab::slotArchivedToggled(bool)
938 bool keep = mKeepArchived->isChecked();
939 if (keep && !mOldKeepArchived && mCheckKeepChanges
940 #ifdef USE_AKONADI
941 && !CollectionControlModel::getStandard(CalEvent::ARCHIVED).isValid())
942 #else
943 && !AlarmResources::instance()->getStandardResource(CalEvent::ARCHIVED))
944 #endif
946 KAMessageBox::sorry(topWidget(),
947 i18nc("@info", "<para>A default calendar is required in order to archive alarms, but none is currently enabled.</para>"
948 "<para>If you wish to keep expired alarms, please first use the calendars view to select a default "
949 "archived alarms calendar.</para>"));
950 mKeepArchived->setChecked(false);
951 return;
953 mOldKeepArchived = keep;
954 mPurgeArchived->setEnabled(keep);
955 mPurgeAfter->setEnabled(keep && mPurgeArchived->isChecked());
956 mPurgeAfterLabel->setEnabled(keep);
957 mClearArchived->setEnabled(keep);
960 void StorePrefTab::slotClearArchived()
962 #ifdef USE_AKONADI
963 bool single = CollectionControlModel::enabledCollections(CalEvent::ARCHIVED, false).count() <= 1;
964 #else
965 bool single = AlarmResources::instance()->activeCount(CalEvent::ARCHIVED, false) <= 1;
966 #endif
967 if (KAMessageBox::warningContinueCancel(topWidget(), single ? i18nc("@info", "Do you really want to delete all archived alarms?")
968 : i18nc("@info", "Do you really want to delete all alarms in the default archived alarm calendar?"))
969 != KMessageBox::Continue)
970 return;
971 theApp()->purgeAll();
975 /*=============================================================================
976 = Class EmailPrefTab
977 =============================================================================*/
979 EmailPrefTab::EmailPrefTab(StackedScrollGroup* scrollGroup)
980 : PrefsTabBase(scrollGroup),
981 mAddressChanged(false),
982 mBccAddressChanged(false)
984 KHBox* box = new KHBox(topWidget());
985 box->setMargin(0);
986 box->setSpacing(2*KDialog::spacingHint());
987 new QLabel(i18nc("@label", "Email client:"), box);
988 mEmailClient = new ButtonGroup(box);
989 QString kmailOption = i18nc("@option:radio", "KMail");
990 QString sendmailOption = i18nc("@option:radio", "Sendmail");
991 mKMailButton = new RadioButton(kmailOption, box);
992 mKMailButton->setMinimumSize(mKMailButton->sizeHint());
993 mEmailClient->addButton(mKMailButton, Preferences::kmail);
994 mSendmailButton = new RadioButton(sendmailOption, box);
995 mSendmailButton->setMinimumSize(mSendmailButton->sizeHint());
996 mEmailClient->addButton(mSendmailButton, Preferences::sendmail);
997 connect(mEmailClient, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotEmailClientChanged(QAbstractButton*)));
998 box->setFixedHeight(box->sizeHint().height());
999 box->setWhatsThis(i18nc("@info:whatsthis",
1000 "<para>Choose how to send email when an email alarm is triggered."
1001 "<list><item><interface>%1</interface>: The email is sent automatically via <application>KMail</application>. <application>KMail</application> is started first if necessary.</item>"
1002 "<item><interface>%2</interface>: The email is sent automatically. This option will only work if "
1003 "your system is configured to use <application>sendmail</application> or a sendmail compatible mail transport agent.</item></list></para>",
1004 kmailOption, sendmailOption));
1006 box = new KHBox(topWidget()); // this is to allow left adjustment
1007 box->setMargin(0);
1008 mEmailCopyToKMail = new QCheckBox(i18nc("@option:check", "Copy sent emails into <application>KMail</application>'s <resource>%1</resource> folder", KAMail::i18n_sent_mail()), box);
1009 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()));
1010 box->setStretchFactor(new QWidget(box), 1); // left adjust the controls
1011 box->setFixedHeight(box->sizeHint().height());
1013 box = new KHBox(topWidget()); // this is to allow left adjustment
1014 box->setMargin(0);
1015 mEmailQueuedNotify = new QCheckBox(i18nc("@option:check", "Notify when remote emails are queued"), box);
1016 mEmailQueuedNotify->setWhatsThis(
1017 i18nc("@info:whatsthis", "Display a notification message whenever an email alarm has queued an email for sending to a remote system. "
1018 "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."));
1019 box->setStretchFactor(new QWidget(box), 1); // left adjust the controls
1020 box->setFixedHeight(box->sizeHint().height());
1022 // Your Email Address group box
1023 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Your Email Address"), topWidget());
1024 QGridLayout* grid = new QGridLayout(group);
1025 grid->setMargin(KDialog::marginHint());
1026 grid->setSpacing(KDialog::spacingHint());
1027 grid->setColumnStretch(2, 1);
1029 // 'From' email address controls ...
1030 QLabel *label = new Label(i18nc("@label 'From' email address", "From:"), group);
1031 grid->addWidget(label, 1, 0);
1032 mFromAddressGroup = new ButtonGroup(group);
1033 connect(mFromAddressGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotFromAddrChanged(QAbstractButton*)));
1035 // Line edit to enter a 'From' email address
1036 mFromAddrButton = new RadioButton(group);
1037 mFromAddressGroup->addButton(mFromAddrButton, Preferences::MAIL_FROM_ADDR);
1038 label->setBuddy(mFromAddrButton);
1039 grid->addWidget(mFromAddrButton, 1, 1);
1040 mEmailAddress = new KLineEdit(group);
1041 connect(mEmailAddress, SIGNAL(textChanged(QString)), SLOT(slotAddressChanged()));
1042 QString whatsThis = i18nc("@info:whatsthis", "Your email address, used to identify you as the sender when sending email alarms.");
1043 mFromAddrButton->setWhatsThis(whatsThis);
1044 mEmailAddress->setWhatsThis(whatsThis);
1045 mFromAddrButton->setFocusWidget(mEmailAddress);
1046 grid->addWidget(mEmailAddress, 1, 2);
1048 // 'From' email address to be taken from System Settings
1049 mFromCCentreButton = new RadioButton(i18nc("@option:radio", "Use address from System Settings"), group);
1050 mFromAddressGroup->addButton(mFromCCentreButton, Preferences::MAIL_FROM_SYS_SETTINGS);
1051 mFromCCentreButton->setWhatsThis(
1052 i18nc("@info:whatsthis", "Check to use the email address set in KDE System Settings, to identify you as the sender when sending email alarms."));
1053 grid->addWidget(mFromCCentreButton, 2, 1, 1, 2, Qt::AlignLeft);
1055 // 'From' email address to be picked from KMail's identities when the email alarm is configured
1056 mFromKMailButton = new RadioButton(i18nc("@option:radio", "Use <application>KMail</application> identities"), group);
1057 mFromAddressGroup->addButton(mFromKMailButton, Preferences::MAIL_FROM_KMAIL);
1058 mFromKMailButton->setWhatsThis(
1059 i18nc("@info:whatsthis", "Check to use <application>KMail</application>'s email identities to identify you as the sender when sending email alarms. "
1060 "For existing email alarms, <application>KMail</application>'s default identity will be used. "
1061 "For new email alarms, you will be able to pick which of <application>KMail</application>'s identities to use."));
1062 grid->addWidget(mFromKMailButton, 3, 1, 1, 2, Qt::AlignLeft);
1064 // 'Bcc' email address controls ...
1065 grid->setRowMinimumHeight(4, KDialog::spacingHint());
1066 label = new Label(i18nc("@label 'Bcc' email address", "Bcc:"), group);
1067 grid->addWidget(label, 5, 0);
1068 mBccAddressGroup = new ButtonGroup(group);
1069 connect(mBccAddressGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotBccAddrChanged(QAbstractButton*)));
1071 // Line edit to enter a 'Bcc' email address
1072 mBccAddrButton = new RadioButton(group);
1073 mBccAddressGroup->addButton(mBccAddrButton, Preferences::MAIL_FROM_ADDR);
1074 label->setBuddy(mBccAddrButton);
1075 grid->addWidget(mBccAddrButton, 5, 1);
1076 mEmailBccAddress = new KLineEdit(group);
1077 whatsThis = i18nc("@info:whatsthis", "Your email address, used for blind copying email alarms to yourself. "
1078 "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.");
1079 mBccAddrButton->setWhatsThis(whatsThis);
1080 mEmailBccAddress->setWhatsThis(whatsThis);
1081 mBccAddrButton->setFocusWidget(mEmailBccAddress);
1082 grid->addWidget(mEmailBccAddress, 5, 2);
1084 // 'Bcc' email address to be taken from System Settings
1085 mBccCCentreButton = new RadioButton(i18nc("@option:radio", "Use address from System Settings"), group);
1086 mBccAddressGroup->addButton(mBccCCentreButton, Preferences::MAIL_FROM_SYS_SETTINGS);
1087 mBccCCentreButton->setWhatsThis(
1088 i18nc("@info:whatsthis", "Check to use the email address set in KDE System Settings, for blind copying email alarms to yourself."));
1089 grid->addWidget(mBccCCentreButton, 6, 1, 1, 2, Qt::AlignLeft);
1091 group->setFixedHeight(group->sizeHint().height());
1093 topLayout()->addStretch(); // top adjust the widgets
1096 void EmailPrefTab::restore(bool defaults, bool)
1098 mEmailClient->setButton(Preferences::emailClient());
1099 mEmailCopyToKMail->setChecked(Preferences::emailCopyToKMail());
1100 setEmailAddress(Preferences::emailFrom(), Preferences::emailAddress());
1101 setEmailBccAddress((Preferences::emailBccFrom() == Preferences::MAIL_FROM_SYS_SETTINGS), Preferences::emailBccAddress());
1102 mEmailQueuedNotify->setChecked(Preferences::emailQueuedNotify());
1103 if (!defaults)
1104 mAddressChanged = mBccAddressChanged = false;
1107 void EmailPrefTab::apply(bool syncToDisc)
1109 int client = mEmailClient->selectedId();
1110 if (client >= 0 && static_cast<Preferences::MailClient>(client) != Preferences::emailClient())
1111 Preferences::setEmailClient(static_cast<Preferences::MailClient>(client));
1112 bool b = mEmailCopyToKMail->isChecked();
1113 if (b != Preferences::emailCopyToKMail())
1114 Preferences::setEmailCopyToKMail(b);
1115 int from = mFromAddressGroup->selectedId();
1116 QString text = mEmailAddress->text().trimmed();
1117 if ((from >= 0 && static_cast<Preferences::MailFrom>(from) != Preferences::emailFrom())
1118 || text != Preferences::emailAddress())
1119 Preferences::setEmailAddress(static_cast<Preferences::MailFrom>(from), text);
1120 b = (mBccAddressGroup->checkedButton() == mBccCCentreButton);
1121 Preferences::MailFrom bfrom = b ? Preferences::MAIL_FROM_SYS_SETTINGS : Preferences::MAIL_FROM_ADDR;;
1122 text = mEmailBccAddress->text().trimmed();
1123 if (bfrom != Preferences::emailBccFrom() || text != Preferences::emailBccAddress())
1124 Preferences::setEmailBccAddress(b, text);
1125 b = mEmailQueuedNotify->isChecked();
1126 if (b != Preferences::emailQueuedNotify())
1127 Preferences::setEmailQueuedNotify(mEmailQueuedNotify->isChecked());
1128 PrefsTabBase::apply(syncToDisc);
1131 void EmailPrefTab::setEmailAddress(Preferences::MailFrom from, const QString& address)
1133 mFromAddressGroup->setButton(from);
1134 mEmailAddress->setText(from == Preferences::MAIL_FROM_ADDR ? address.trimmed() : QString());
1137 void EmailPrefTab::setEmailBccAddress(bool useSystemSettings, const QString& address)
1139 mBccAddressGroup->setButton(useSystemSettings ? Preferences::MAIL_FROM_SYS_SETTINGS : Preferences::MAIL_FROM_ADDR);
1140 mEmailBccAddress->setText(useSystemSettings ? QString() : address.trimmed());
1143 void EmailPrefTab::slotEmailClientChanged(QAbstractButton* button)
1145 mEmailCopyToKMail->setEnabled(button == mSendmailButton);
1148 void EmailPrefTab::slotFromAddrChanged(QAbstractButton* button)
1150 mEmailAddress->setEnabled(button == mFromAddrButton);
1151 mAddressChanged = true;
1154 void EmailPrefTab::slotBccAddrChanged(QAbstractButton* button)
1156 mEmailBccAddress->setEnabled(button == mBccAddrButton);
1157 mBccAddressChanged = true;
1160 QString EmailPrefTab::validate()
1162 if (mAddressChanged)
1164 mAddressChanged = false;
1165 QString errmsg = validateAddr(mFromAddressGroup, mEmailAddress, KAMail::i18n_NeedFromEmailAddress());
1166 if (!errmsg.isEmpty())
1167 return errmsg;
1169 if (mBccAddressChanged)
1171 mBccAddressChanged = false;
1172 return validateAddr(mBccAddressGroup, mEmailBccAddress, i18nc("@info/plain", "No valid 'Bcc' email address is specified."));
1174 return QString();
1177 QString EmailPrefTab::validateAddr(ButtonGroup* group, KLineEdit* addr, const QString& msg)
1179 QString errmsg = i18nc("@info", "<para>%1</para><para>Are you sure you want to save your changes?</para>", msg);
1180 switch (group->selectedId())
1182 case Preferences::MAIL_FROM_SYS_SETTINGS:
1183 if (!KAMail::controlCentreAddress().isEmpty())
1184 return QString();
1185 errmsg = i18nc("@info", "No email address is currently set in KDE System Settings. %1", errmsg);
1186 break;
1187 case Preferences::MAIL_FROM_KMAIL:
1188 if (Identities::identitiesExist())
1189 return QString();
1190 errmsg = i18nc("@info", "No <application>KMail</application> identities currently exist. %1", errmsg);
1191 break;
1192 case Preferences::MAIL_FROM_ADDR:
1193 if (!addr->text().trimmed().isEmpty())
1194 return QString();
1195 break;
1197 return errmsg;
1201 /*=============================================================================
1202 = Class EditPrefTab
1203 =============================================================================*/
1205 EditPrefTab::EditPrefTab(StackedScrollGroup* scrollGroup)
1206 : PrefsTabBase(scrollGroup)
1208 KLocalizedString defsetting = ki18nc("@info:whatsthis", "The default setting for <interface>%1</interface> in the alarm edit dialog.");
1210 mTabs = new KTabWidget(topWidget());
1211 StackedGroupT<KVBox>* tabgroup = new StackedGroupT<KVBox>(mTabs);
1212 StackedWidgetT<KVBox>* topGeneral = new StackedWidgetT<KVBox>(tabgroup);
1213 topGeneral->setMargin(KDialog::marginHint()/2);
1214 topGeneral->setSpacing(KDialog::spacingHint());
1215 mTabGeneral = mTabs->addTab(topGeneral, i18nc("@title:tab", "General"));
1216 StackedWidgetT<KVBox>* topTypes = new StackedWidgetT<KVBox>(tabgroup);
1217 topTypes->setMargin(KDialog::marginHint()/2);
1218 topTypes->setSpacing(KDialog::spacingHint());
1219 mTabTypes = mTabs->addTab(topTypes, i18nc("@title:tab", "Alarm Types"));
1220 StackedWidgetT<KVBox>* topFontColour = new StackedWidgetT<KVBox>(tabgroup);
1221 topFontColour->setMargin(KDialog::marginHint()/2);
1222 topFontColour->setSpacing(KDialog::spacingHint());
1223 mTabFontColour = mTabs->addTab(topFontColour, i18nc("@title:tab", "Font && Color"));
1225 // MISCELLANEOUS
1226 // Show in KOrganizer
1227 mCopyToKOrganizer = new QCheckBox(EditAlarmDlg::i18n_chk_ShowInKOrganizer(), topGeneral);
1228 mCopyToKOrganizer->setMinimumSize(mCopyToKOrganizer->sizeHint());
1229 mCopyToKOrganizer->setWhatsThis(defsetting.subs(EditAlarmDlg::i18n_chk_ShowInKOrganizer()).toString());
1231 // Late cancellation
1232 KHBox* box = new KHBox(topGeneral);
1233 box->setMargin(0);
1234 box->setSpacing(KDialog::spacingHint());
1235 mLateCancel = new QCheckBox(LateCancelSelector::i18n_chk_CancelIfLate(), box);
1236 mLateCancel->setMinimumSize(mLateCancel->sizeHint());
1237 mLateCancel->setWhatsThis(defsetting.subs(LateCancelSelector::i18n_chk_CancelIfLate()).toString());
1238 box->setStretchFactor(new QWidget(box), 1); // left adjust the control
1240 // Recurrence
1241 QFrame* iBox = new QFrame(topGeneral); // this is to control the QWhatsThis text display area
1242 QHBoxLayout* hlayout = new QHBoxLayout(iBox);
1243 hlayout->setSpacing(KDialog::spacingHint());
1244 QLabel* label = new QLabel(i18nc("@label:listbox", "Recurrence:"), iBox);
1245 hlayout->addWidget(label);
1246 mRecurPeriod = new KComboBox(iBox);
1247 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_NoRecur());
1248 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_AtLogin());
1249 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_HourlyMinutely());
1250 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Daily());
1251 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Weekly());
1252 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Monthly());
1253 mRecurPeriod->addItem(RecurrenceEdit::i18n_combo_Yearly());
1254 mRecurPeriod->setFixedSize(mRecurPeriod->sizeHint());
1255 hlayout->addWidget(mRecurPeriod);
1256 label->setBuddy(mRecurPeriod);
1257 iBox->setWhatsThis(i18nc("@info:whatsthis", "The default setting for the recurrence rule in the alarm edit dialog."));
1258 hlayout->addStretch(); // left adjust the control
1260 // How to handle February 29th in yearly recurrences
1261 KVBox* vbox = new KVBox(topGeneral); // this is to control the QWhatsThis text display area
1262 vbox->setMargin(0);
1263 vbox->setSpacing(KDialog::spacingHint());
1264 label = new QLabel(i18nc("@label", "In non-leap years, repeat yearly February 29th alarms on:"), vbox);
1265 label->setAlignment(Qt::AlignLeft);
1266 label->setWordWrap(true);
1267 KHBox* itemBox = new KHBox(vbox);
1268 // itemBox->setMargin(0);
1269 itemBox->setSpacing(2*KDialog::spacingHint());
1270 mFeb29 = new ButtonGroup(itemBox);
1271 QWidget* widget = new QWidget(itemBox);
1272 widget->setFixedWidth(3*KDialog::spacingHint());
1273 QRadioButton* radio = new QRadioButton(i18nc("@option:radio", "February 2&8th"), itemBox);
1274 radio->setMinimumSize(radio->sizeHint());
1275 mFeb29->addButton(radio, Preferences::Feb29_Feb28);
1276 radio = new QRadioButton(i18nc("@option:radio", "March &1st"), itemBox);
1277 radio->setMinimumSize(radio->sizeHint());
1278 mFeb29->addButton(radio, Preferences::Feb29_Mar1);
1279 radio = new QRadioButton(i18nc("@option:radio", "Do not repeat"), itemBox);
1280 radio->setMinimumSize(radio->sizeHint());
1281 mFeb29->addButton(radio, Preferences::Feb29_None);
1282 itemBox->setFixedHeight(itemBox->sizeHint().height());
1283 vbox->setWhatsThis(i18nc("@info:whatsthis",
1284 "For yearly recurrences, choose what date, if any, alarms due on February 29th should occur in non-leap years."
1285 "<note>The next scheduled occurrence of existing alarms is not re-evaluated when you change this setting.</note>"));
1287 QVBoxLayout* lay = qobject_cast<QVBoxLayout*>(topGeneral->layout());
1288 if (lay)
1289 lay->addStretch(); // top adjust the widgets
1291 // DISPLAY ALARMS
1292 QGroupBox* group = new QGroupBox(i18nc("@title:group", "Display Alarms"), topTypes);
1293 QVBoxLayout* vlayout = new QVBoxLayout(group);
1294 vlayout->setMargin(KDialog::marginHint());
1295 vlayout->setSpacing(KDialog::spacingHint());
1297 mConfirmAck = new QCheckBox(EditDisplayAlarmDlg::i18n_chk_ConfirmAck(), group);
1298 mConfirmAck->setMinimumSize(mConfirmAck->sizeHint());
1299 mConfirmAck->setWhatsThis(defsetting.subs(EditDisplayAlarmDlg::i18n_chk_ConfirmAck()).toString());
1300 vlayout->addWidget(mConfirmAck, 0, Qt::AlignLeft);
1302 mAutoClose = new QCheckBox(LateCancelSelector::i18n_chk_AutoCloseWinLC(), group);
1303 mAutoClose->setMinimumSize(mAutoClose->sizeHint());
1304 mAutoClose->setWhatsThis(defsetting.subs(LateCancelSelector::i18n_chk_AutoCloseWin()).toString());
1305 vlayout->addWidget(mAutoClose, 0, Qt::AlignLeft);
1307 box = new KHBox(group);
1308 // box->setMargin(0);
1309 box->setSpacing(KDialog::spacingHint());
1310 vlayout->addWidget(box);
1311 label = new QLabel(i18nc("@label:listbox", "Reminder units:"), box);
1312 mReminderUnits = new KComboBox(box);
1313 mReminderUnits->addItem(i18nc("@item:inlistbox", "Minutes"), TimePeriod::Minutes);
1314 mReminderUnits->addItem(i18nc("@item:inlistbox", "Hours/Minutes"), TimePeriod::HoursMinutes);
1315 mReminderUnits->setFixedSize(mReminderUnits->sizeHint());
1316 label->setBuddy(mReminderUnits);
1317 box->setWhatsThis(i18nc("@info:whatsthis", "The default units for the reminder in the alarm edit dialog, for alarms due soon."));
1318 box->setStretchFactor(new QWidget(box), 1); // left adjust the control
1320 mSpecialActionsButton = new SpecialActionsButton(true, box);
1321 mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
1323 // SOUND
1324 QGroupBox* bbox = new QGroupBox(i18nc("@title:group Audio options group", "Sound"), topTypes);
1325 vlayout = new QVBoxLayout(bbox);
1326 vlayout->setMargin(KDialog::marginHint());
1327 vlayout->setSpacing(KDialog::spacingHint());
1329 hlayout = new QHBoxLayout();
1330 hlayout->setMargin(0);
1331 vlayout->addLayout(hlayout);
1332 mSound = new KComboBox(bbox);
1333 mSound->addItem(SoundPicker::i18n_combo_None()); // index 0
1334 mSound->addItem(SoundPicker::i18n_combo_Beep()); // index 1
1335 mSound->addItem(SoundPicker::i18n_combo_File()); // index 2
1336 if (theApp()->speechEnabled())
1337 mSound->addItem(SoundPicker::i18n_combo_Speak()); // index 3
1338 mSound->setMinimumSize(mSound->sizeHint());
1339 mSound->setWhatsThis(defsetting.subs(SoundPicker::i18n_label_Sound()).toString());
1340 hlayout->addWidget(mSound);
1341 hlayout->addStretch();
1343 mSoundRepeat = new QCheckBox(i18nc("@option:check", "Repeat sound file"), bbox);
1344 mSoundRepeat->setMinimumSize(mSoundRepeat->sizeHint());
1345 mSoundRepeat->setWhatsThis(
1346 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()));
1347 hlayout->addWidget(mSoundRepeat);
1349 box = new KHBox(bbox); // this is to control the QWhatsThis text display area
1350 box->setMargin(0);
1351 box->setSpacing(KDialog::spacingHint());
1352 mSoundFileLabel = new QLabel(i18nc("@label:textbox", "Sound file:"), box);
1353 mSoundFile = new KLineEdit(box);
1354 mSoundFileLabel->setBuddy(mSoundFile);
1355 mSoundFileBrowse = new QPushButton(box);
1356 mSoundFileBrowse->setIcon(KIcon(SmallIcon(QLatin1String("document-open"))));
1357 int size = mSoundFileBrowse->sizeHint().height();
1358 mSoundFileBrowse->setFixedSize(size, size);
1359 connect(mSoundFileBrowse, SIGNAL(clicked()), SLOT(slotBrowseSoundFile()));
1360 mSoundFileBrowse->setToolTip(i18nc("@info:tooltip", "Choose a sound file"));
1361 box->setWhatsThis(i18nc("@info:whatsthis", "Enter the default sound file to use in the alarm edit dialog."));
1362 box->setFixedHeight(box->sizeHint().height());
1363 vlayout->addWidget(box);
1364 bbox->setFixedHeight(bbox->sizeHint().height());
1366 // COMMAND ALARMS
1367 group = new QGroupBox(i18nc("@title:group", "Command Alarms"), topTypes);
1368 vlayout = new QVBoxLayout(group);
1369 vlayout->setMargin(KDialog::marginHint());
1370 vlayout->setSpacing(KDialog::spacingHint());
1371 hlayout = new QHBoxLayout();
1372 hlayout->setMargin(0);
1373 vlayout->addLayout(hlayout);
1375 mCmdScript = new QCheckBox(EditCommandAlarmDlg::i18n_chk_EnterScript(), group);
1376 mCmdScript->setMinimumSize(mCmdScript->sizeHint());
1377 mCmdScript->setWhatsThis(defsetting.subs(EditCommandAlarmDlg::i18n_chk_EnterScript()).toString());
1378 hlayout->addWidget(mCmdScript);
1379 hlayout->addStretch();
1381 mCmdXterm = new QCheckBox(EditCommandAlarmDlg::i18n_chk_ExecInTermWindow(), group);
1382 mCmdXterm->setMinimumSize(mCmdXterm->sizeHint());
1383 mCmdXterm->setWhatsThis(defsetting.subs(EditCommandAlarmDlg::i18n_radio_ExecInTermWindow()).toString());
1384 hlayout->addWidget(mCmdXterm);
1386 // EMAIL ALARMS
1387 group = new QGroupBox(i18nc("@title:group", "Email Alarms"), topTypes);
1388 vlayout = new QVBoxLayout(group);
1389 vlayout->setMargin(KDialog::marginHint());
1390 vlayout->setSpacing(KDialog::spacingHint());
1392 // BCC email to sender
1393 mEmailBcc = new QCheckBox(EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf(), group);
1394 mEmailBcc->setMinimumSize(mEmailBcc->sizeHint());
1395 mEmailBcc->setWhatsThis(defsetting.subs(EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf()).toString());
1396 vlayout->addWidget(mEmailBcc, 0, Qt::AlignLeft);
1398 lay = qobject_cast<QVBoxLayout*>(topTypes->layout());
1399 if (lay)
1400 lay->addStretch(); // top adjust the widgets
1402 // FONT / COLOUR TAB
1403 mFontChooser = new FontColourChooser(topFontColour, QStringList(), i18nc("@title:group", "Message Font && Color"), true);
1406 void EditPrefTab::restore(bool, bool allTabs)
1408 int index;
1409 if (allTabs || mTabs->currentIndex() == mTabGeneral)
1411 mCopyToKOrganizer->setChecked(Preferences::defaultCopyToKOrganizer());
1412 mLateCancel->setChecked(Preferences::defaultLateCancel());
1413 switch (Preferences::defaultRecurPeriod())
1415 case Preferences::Recur_Yearly: index = 6; break;
1416 case Preferences::Recur_Monthly: index = 5; break;
1417 case Preferences::Recur_Weekly: index = 4; break;
1418 case Preferences::Recur_Daily: index = 3; break;
1419 case Preferences::Recur_SubDaily: index = 2; break;
1420 case Preferences::Recur_Login: index = 1; break;
1421 case Preferences::Recur_None:
1422 default: index = 0; break;
1424 mRecurPeriod->setCurrentIndex(index);
1425 mFeb29->setButton(Preferences::defaultFeb29Type());
1427 if (allTabs || mTabs->currentIndex() == mTabTypes)
1429 mConfirmAck->setChecked(Preferences::defaultConfirmAck());
1430 mAutoClose->setChecked(Preferences::defaultAutoClose());
1431 switch (Preferences::defaultReminderUnits())
1433 case TimePeriod::Weeks: index = 3; break;
1434 case TimePeriod::Days: index = 2; break;
1435 default:
1436 case TimePeriod::HoursMinutes: index = 1; break;
1437 case TimePeriod::Minutes: index = 0; break;
1439 mReminderUnits->setCurrentIndex(index);
1440 KAEvent::ExtraActionOptions opts(0);
1441 if (Preferences::defaultExecPreActionOnDeferral())
1442 opts |= KAEvent::ExecPreActOnDeferral;
1443 if (Preferences::defaultCancelOnPreActionError())
1444 opts |= KAEvent::CancelOnPreActError;
1445 if (Preferences::defaultDontShowPreActionError())
1446 opts |= KAEvent::DontShowPreActError;
1447 mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(), opts);
1448 mSound->setCurrentIndex(soundIndex(Preferences::defaultSoundType()));
1449 mSoundFile->setText(Preferences::defaultSoundFile());
1450 mSoundRepeat->setChecked(Preferences::defaultSoundRepeat());
1451 mCmdScript->setChecked(Preferences::defaultCmdScript());
1452 mCmdXterm->setChecked(Preferences::defaultCmdLogType() == Preferences::Log_Terminal);
1453 mEmailBcc->setChecked(Preferences::defaultEmailBcc());
1455 if (allTabs || mTabs->currentIndex() == mTabFontColour)
1457 mFontChooser->setFgColour(Preferences::defaultFgColour());
1458 mFontChooser->setBgColour(Preferences::defaultBgColour());
1459 mFontChooser->setFont(Preferences::messageFont());
1463 void EditPrefTab::apply(bool syncToDisc)
1465 bool b = mAutoClose->isChecked();
1466 if (b != Preferences::defaultAutoClose())
1467 Preferences::setDefaultAutoClose(b);
1468 b = mConfirmAck->isChecked();
1469 if (b != Preferences::defaultConfirmAck())
1470 Preferences::setDefaultConfirmAck(b);
1471 TimePeriod::Units units;
1472 switch (mReminderUnits->currentIndex())
1474 case 3: units = TimePeriod::Weeks; break;
1475 case 2: units = TimePeriod::Days; break;
1476 default:
1477 case 1: units = TimePeriod::HoursMinutes; break;
1478 case 0: units = TimePeriod::Minutes; break;
1480 if (units != Preferences::defaultReminderUnits())
1481 Preferences::setDefaultReminderUnits(units);
1482 QString text = mSpecialActionsButton->preAction();
1483 if (text != Preferences::defaultPreAction())
1484 Preferences::setDefaultPreAction(text);
1485 text = mSpecialActionsButton->postAction();
1486 if (text != Preferences::defaultPostAction())
1487 Preferences::setDefaultPostAction(text);
1488 KAEvent::ExtraActionOptions opts = mSpecialActionsButton->options();
1489 b = opts & KAEvent::ExecPreActOnDeferral;
1490 if (b != Preferences::defaultExecPreActionOnDeferral())
1491 Preferences::setDefaultExecPreActionOnDeferral(b);
1492 b = opts & KAEvent::CancelOnPreActError;
1493 if (b != Preferences::defaultCancelOnPreActionError())
1494 Preferences::setDefaultCancelOnPreActionError(b);
1495 b = opts & KAEvent::DontShowPreActError;
1496 if (b != Preferences::defaultDontShowPreActionError())
1497 Preferences::setDefaultDontShowPreActionError(b);
1498 Preferences::SoundType snd;
1499 switch (mSound->currentIndex())
1501 case 3: snd = Preferences::Sound_Speak; break;
1502 case 2: snd = Preferences::Sound_File; break;
1503 case 1: snd = Preferences::Sound_Beep; break;
1504 case 0:
1505 default: snd = Preferences::Sound_None; break;
1507 if (snd != Preferences::defaultSoundType())
1508 Preferences::setDefaultSoundType(snd);
1509 text = mSoundFile->text();
1510 if (text != Preferences::defaultSoundFile())
1511 Preferences::setDefaultSoundFile(text);
1512 b = mSoundRepeat->isChecked();
1513 if (b != Preferences::defaultSoundRepeat())
1514 Preferences::setDefaultSoundRepeat(b);
1515 b = mCmdScript->isChecked();
1516 if (b != Preferences::defaultCmdScript())
1517 Preferences::setDefaultCmdScript(b);
1518 Preferences::CmdLogType log = mCmdXterm->isChecked() ? Preferences::Log_Terminal : Preferences::Log_Discard;
1519 if (log != Preferences::defaultCmdLogType())
1520 Preferences::setDefaultCmdLogType(log);
1521 b = mEmailBcc->isChecked();
1522 if (b != Preferences::defaultEmailBcc())
1523 Preferences::setDefaultEmailBcc(b);
1524 b = mCopyToKOrganizer->isChecked();
1525 if (b != Preferences::defaultCopyToKOrganizer())
1526 Preferences::setDefaultCopyToKOrganizer(b);
1527 int i = mLateCancel->isChecked() ? 1 : 0;
1528 if (i != Preferences::defaultLateCancel())
1529 Preferences::setDefaultLateCancel(i);
1530 Preferences::RecurType period;
1531 switch (mRecurPeriod->currentIndex())
1533 case 6: period = Preferences::Recur_Yearly; break;
1534 case 5: period = Preferences::Recur_Monthly; break;
1535 case 4: period = Preferences::Recur_Weekly; break;
1536 case 3: period = Preferences::Recur_Daily; break;
1537 case 2: period = Preferences::Recur_SubDaily; break;
1538 case 1: period = Preferences::Recur_Login; break;
1539 case 0:
1540 default: period = Preferences::Recur_None; break;
1542 if (period != Preferences::defaultRecurPeriod())
1543 Preferences::setDefaultRecurPeriod(period);
1544 int feb29 = mFeb29->selectedId();
1545 if (feb29 >= 0 && static_cast<Preferences::Feb29Type>(feb29) != Preferences::defaultFeb29Type())
1546 Preferences::setDefaultFeb29Type(static_cast<Preferences::Feb29Type>(feb29));
1547 QColor colour = mFontChooser->fgColour();
1548 if (colour != Preferences::defaultFgColour())
1549 Preferences::setDefaultFgColour(colour);
1550 colour = mFontChooser->bgColour();
1551 if (colour != Preferences::defaultBgColour())
1552 Preferences::setDefaultBgColour(colour);
1553 QFont font = mFontChooser->font();
1554 if (font != Preferences::messageFont())
1555 Preferences::setMessageFont(font);
1556 PrefsTabBase::apply(syncToDisc);
1559 void EditPrefTab::slotBrowseSoundFile()
1561 QString defaultDir;
1562 QString url = SoundPicker::browseFile(defaultDir, mSoundFile->text());
1563 if (!url.isEmpty())
1564 mSoundFile->setText(url);
1567 int EditPrefTab::soundIndex(Preferences::SoundType type)
1569 switch (type)
1571 case Preferences::Sound_Speak: return 3;
1572 case Preferences::Sound_File: return 2;
1573 case Preferences::Sound_Beep: return 1;
1574 case Preferences::Sound_None:
1575 default: return 0;
1579 QString EditPrefTab::validate()
1581 if (mSound->currentIndex() == soundIndex(Preferences::Sound_File) && mSoundFile->text().isEmpty())
1583 mSoundFile->setFocus();
1584 return i18nc("@info", "You must enter a sound file when <interface>%1</interface> is selected as the default sound type", SoundPicker::i18n_combo_File());;
1586 return QString();
1590 /*=============================================================================
1591 = Class ViewPrefTab
1592 =============================================================================*/
1594 ViewPrefTab::ViewPrefTab(StackedScrollGroup* scrollGroup)
1595 : PrefsTabBase(scrollGroup)
1597 mTabs = new KTabWidget(topWidget());
1598 KVBox* topGeneral = new KVBox();
1599 topGeneral->setMargin(KDialog::marginHint()/2);
1600 topGeneral->setSpacing(KDialog::spacingHint());
1601 mTabGeneral = mTabs->addTab(topGeneral, i18nc("@title:tab", "General"));
1602 KVBox* topWindows = new KVBox();
1603 topWindows->setMargin(KDialog::marginHint()/2);
1604 topWindows->setSpacing(KDialog::spacingHint());
1605 mTabWindows = mTabs->addTab(topWindows, i18nc("@title:tab", "Alarm Windows"));
1607 // Run-in-system-tray group box
1608 mShowInSystemTray = new QGroupBox(i18nc("@option:check", "Show in system tray"), topGeneral);
1609 mShowInSystemTray->setCheckable(true);
1610 mShowInSystemTray->setWhatsThis(
1611 i18nc("@info:whatsthis", "<para>Check to show <application>KAlarm</application>'s icon in the system tray."
1612 " Showing it in the system tray provides easy access and a status indication.</para>"));
1613 QGridLayout* grid = new QGridLayout(mShowInSystemTray);
1614 grid->setMargin(KDialog::marginHint());
1615 grid->setSpacing(KDialog::spacingHint());
1616 grid->setColumnStretch(1, 1);
1617 grid->setColumnMinimumWidth(0, indentWidth());
1619 mAutoHideSystemTray = new ButtonGroup(mShowInSystemTray);
1620 connect(mAutoHideSystemTray, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotAutoHideSysTrayChanged(QAbstractButton*)));
1622 QRadioButton* radio = new QRadioButton(i18nc("@option:radio Always show KAlarm icon", "Always show"), mShowInSystemTray);
1623 mAutoHideSystemTray->addButton(radio, 0);
1624 radio->setWhatsThis(
1625 i18nc("@info:whatsthis",
1626 "Check to show <application>KAlarm</application>'s icon in the system tray "
1627 "regardless of whether alarms are due."));
1628 grid->addWidget(radio, 0, 0, 1, 2, Qt::AlignLeft);
1630 radio = new QRadioButton(i18nc("@option:radio", "Automatically hide if no active alarms"), mShowInSystemTray);
1631 mAutoHideSystemTray->addButton(radio, 1);
1632 radio->setWhatsThis(
1633 i18nc("@info:whatsthis",
1634 "Check to automatically hide <application>KAlarm</application>'s icon in "
1635 "the system tray if there are no active alarms. When hidden, the icon can "
1636 "always be made visible by use of the system tray option to show hidden icons."));
1637 grid->addWidget(radio, 1, 0, 1, 2, Qt::AlignLeft);
1639 QString text = i18nc("@info:whatsthis",
1640 "Check to automatically hide <application>KAlarm</application>'s icon in the "
1641 "system tray if no alarms are due within the specified time period. When hidden, "
1642 "the icon can always be made visible by use of the system tray option to show hidden icons.");
1643 radio = new QRadioButton(i18nc("@option:radio", "Automatically hide if no alarm due within time period:"), mShowInSystemTray);
1644 radio->setWhatsThis(text);
1645 mAutoHideSystemTray->addButton(radio, 2);
1646 grid->addWidget(radio, 2, 0, 1, 2, Qt::AlignLeft);
1647 mAutoHideSystemTrayPeriod = new TimePeriod(true, mShowInSystemTray);
1648 mAutoHideSystemTrayPeriod->setWhatsThis(text);
1649 mAutoHideSystemTrayPeriod->setMaximumWidth(mAutoHideSystemTrayPeriod->sizeHint().width());
1650 grid->addWidget(mAutoHideSystemTrayPeriod, 3, 1, 1, 1, Qt::AlignLeft);
1651 mShowInSystemTray->setMaximumHeight(mShowInSystemTray->sizeHint().height());
1653 // System tray tooltip group box
1654 QGroupBox* group = new QGroupBox(i18nc("@title:group", "System Tray Tooltip"), topGeneral);
1655 grid = new QGridLayout(group);
1656 grid->setMargin(KDialog::marginHint());
1657 grid->setSpacing(KDialog::spacingHint());
1658 grid->setColumnStretch(2, 1);
1659 grid->setColumnMinimumWidth(0, indentWidth());
1660 grid->setColumnMinimumWidth(1, indentWidth());
1662 mTooltipShowAlarms = new QCheckBox(i18nc("@option:check", "Show next &24 hours' alarms"), group);
1663 mTooltipShowAlarms->setMinimumSize(mTooltipShowAlarms->sizeHint());
1664 connect(mTooltipShowAlarms, SIGNAL(toggled(bool)), SLOT(slotTooltipAlarmsToggled(bool)));
1665 mTooltipShowAlarms->setWhatsThis(
1666 i18nc("@info:whatsthis", "Specify whether to include in the system tray tooltip, a summary of alarms due in the next 24 hours."));
1667 grid->addWidget(mTooltipShowAlarms, 0, 0, 1, 3, Qt::AlignLeft);
1669 KHBox* box = new KHBox(group);
1670 box->setMargin(0);
1671 box->setSpacing(KDialog::spacingHint());
1672 mTooltipMaxAlarms = new QCheckBox(i18nc("@option:check", "Maximum number of alarms to show:"), box);
1673 mTooltipMaxAlarms->setMinimumSize(mTooltipMaxAlarms->sizeHint());
1674 connect(mTooltipMaxAlarms, SIGNAL(toggled(bool)), SLOT(slotTooltipMaxToggled(bool)));
1675 mTooltipMaxAlarmCount = new SpinBox(1, 99, box);
1676 mTooltipMaxAlarmCount->setSingleShiftStep(5);
1677 mTooltipMaxAlarmCount->setMinimumSize(mTooltipMaxAlarmCount->sizeHint());
1678 box->setWhatsThis(
1679 i18nc("@info:whatsthis", "Uncheck to display all of the next 24 hours' alarms in the system tray tooltip. "
1680 "Check to enter an upper limit on the number to be displayed."));
1681 grid->addWidget(box, 1, 1, 1, 2, Qt::AlignLeft);
1683 mTooltipShowTime = new QCheckBox(MainWindow::i18n_chk_ShowAlarmTime(), group);
1684 mTooltipShowTime->setMinimumSize(mTooltipShowTime->sizeHint());
1685 connect(mTooltipShowTime, SIGNAL(toggled(bool)), SLOT(slotTooltipTimeToggled(bool)));
1686 mTooltipShowTime->setWhatsThis(i18nc("@info:whatsthis", "Specify whether to show in the system tray tooltip, the time at which each alarm is due."));
1687 grid->addWidget(mTooltipShowTime, 2, 1, 1, 2, Qt::AlignLeft);
1689 mTooltipShowTimeTo = new QCheckBox(MainWindow::i18n_chk_ShowTimeToAlarm(), group);
1690 mTooltipShowTimeTo->setMinimumSize(mTooltipShowTimeTo->sizeHint());
1691 connect(mTooltipShowTimeTo, SIGNAL(toggled(bool)), SLOT(slotTooltipTimeToToggled(bool)));
1692 mTooltipShowTimeTo->setWhatsThis(i18nc("@info:whatsthis", "Specify whether to show in the system tray tooltip, how long until each alarm is due."));
1693 grid->addWidget(mTooltipShowTimeTo, 3, 1, 1, 2, Qt::AlignLeft);
1695 box = new KHBox(group); // this is to control the QWhatsThis text display area
1696 box->setMargin(0);
1697 box->setSpacing(KDialog::spacingHint());
1698 mTooltipTimeToPrefixLabel = new QLabel(i18nc("@label:textbox", "Prefix:"), box);
1699 mTooltipTimeToPrefix = new KLineEdit(box);
1700 mTooltipTimeToPrefixLabel->setBuddy(mTooltipTimeToPrefix);
1701 box->setWhatsThis(i18nc("@info:whatsthis", "Enter the text to be displayed in front of the time until the alarm, in the system tray tooltip."));
1702 box->setFixedHeight(box->sizeHint().height());
1703 grid->addWidget(box, 4, 2, Qt::AlignLeft);
1704 group->setMaximumHeight(group->sizeHint().height());
1706 group = new QGroupBox(i18nc("@title:group", "Alarm List"), topGeneral);
1707 QHBoxLayout* hlayout = new QHBoxLayout(group);
1708 hlayout->setMargin(KDialog::marginHint());
1709 QVBoxLayout* colourLayout = new QVBoxLayout();
1710 colourLayout->setMargin(0);
1711 hlayout->addLayout(colourLayout);
1713 box = new KHBox(group); // to group widgets for QWhatsThis text
1714 box->setMargin(0);
1715 box->setSpacing(KDialog::spacingHint()/2);
1716 colourLayout->addWidget(box);
1717 QLabel* label1 = new QLabel(i18nc("@label:listbox", "Disabled alarm color:"), box);
1718 box->setStretchFactor(new QWidget(box), 0);
1719 mDisabledColour = new ColourButton(box);
1720 label1->setBuddy(mDisabledColour);
1721 box->setWhatsThis(i18nc("@info:whatsthis", "Choose the text color in the alarm list for disabled alarms."));
1723 box = new KHBox(group); // to group widgets for QWhatsThis text
1724 box->setMargin(0);
1725 box->setSpacing(KDialog::spacingHint()/2);
1726 colourLayout->addWidget(box);
1727 QLabel* label2 = new QLabel(i18nc("@label:listbox", "Archived alarm color:"), box);
1728 box->setStretchFactor(new QWidget(box), 0);
1729 mArchivedColour = new ColourButton(box);
1730 label2->setBuddy(mArchivedColour);
1731 box->setWhatsThis(i18nc("@info:whatsthis", "Choose the text color in the alarm list for archived alarms."));
1732 hlayout->addStretch();
1734 QVBoxLayout* lay = qobject_cast<QVBoxLayout*>(topGeneral->layout());
1735 if (lay)
1736 lay->addStretch(); // top adjust the widgets
1738 group = new QGroupBox(i18nc("@title:group", "Alarm Message Windows"), topWindows);
1739 grid = new QGridLayout(group);
1740 grid->setMargin(KDialog::marginHint());
1741 grid->setSpacing(KDialog::spacingHint());
1742 grid->setColumnStretch(1, 1);
1743 grid->setColumnMinimumWidth(0, indentWidth());
1744 mWindowPosition = new ButtonGroup(group);
1745 connect(mWindowPosition, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotWindowPosChanged(QAbstractButton*)));
1747 QString whatsthis = i18nc("@info:whatsthis",
1748 "<para>Choose how to reduce the chance of alarm messages being accidentally acknowledged:"
1749 "<list><item>Position alarm message windows as far as possible from the current mouse cursor location, or</item>"
1750 "<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>");
1751 radio = new QRadioButton(i18nc("@option:radio", "Position windows far from mouse cursor"), group);
1752 mWindowPosition->addButton(radio, 0);
1753 radio->setWhatsThis(whatsthis);
1754 grid->addWidget(radio, 0, 0, 1, 2, Qt::AlignLeft);
1755 radio = new QRadioButton(i18nc("@option:radio", "Center windows, delay activating window buttons"), group);
1756 mWindowPosition->addButton(radio, 1);
1757 radio->setWhatsThis(whatsthis);
1758 grid->addWidget(radio, 1, 0, 1, 2, Qt::AlignLeft);
1760 KHBox* itemBox = new KHBox(group);
1761 itemBox->setMargin(0);
1762 box = new KHBox(itemBox); // this is to control the QWhatsThis text display area
1763 box->setMargin(0);
1764 box->setSpacing(KDialog::spacingHint());
1765 mWindowButtonDelayLabel = new QLabel(i18nc("@label:spinbox", "Button activation delay (seconds):"), box);
1766 mWindowButtonDelay = new QSpinBox(box);
1767 mWindowButtonDelay->setRange(1, 10);
1768 mWindowButtonDelayLabel->setBuddy(mWindowButtonDelay);
1769 box->setWhatsThis(i18nc("@info:whatsthis",
1770 "Enter how long its buttons should remain disabled after the alarm message window is shown."));
1771 itemBox->setStretchFactor(new QWidget(itemBox), 1); // left adjust the controls
1772 grid->addWidget(itemBox, 2, 1, Qt::AlignLeft);
1774 grid->setRowMinimumHeight(3, KDialog::spacingHint());
1776 mModalMessages = new QCheckBox(i18nc("@option:check", "Message windows have a title bar and take keyboard focus"), group);
1777 mModalMessages->setMinimumSize(mModalMessages->sizeHint());
1778 mModalMessages->setWhatsThis(i18nc("@info:whatsthis",
1779 "<para>Specify the characteristics of alarm message windows:"
1780 "<list><item>If checked, the window is a normal window with a title bar, which grabs keyboard input when it is displayed.</item>"
1781 "<item>If unchecked, the window does not interfere with your typing when "
1782 "it is displayed, but it has no title bar and cannot be moved or resized.</item></list></para>"));
1783 grid->addWidget(mModalMessages, 4, 0, 1, 2, Qt::AlignLeft);
1785 lay = qobject_cast<QVBoxLayout*>(topWindows->layout());
1786 if (lay)
1787 lay->addStretch(); // top adjust the widgets
1790 void ViewPrefTab::restore(bool, bool allTabs)
1792 if (allTabs || mTabs->currentIndex() == mTabGeneral)
1794 mShowInSystemTray->setChecked(Preferences::showInSystemTray());
1795 int id;
1796 int mins = Preferences::autoHideSystemTray();
1797 switch (mins)
1799 case -1: id = 1; break; // hide if no active alarms
1800 case 0: id = 0; break; // never hide
1801 default:
1803 id = 2;
1804 int days = 0;
1805 int secs = 0;
1806 if (mins % 1440)
1807 secs = mins * 60;
1808 else
1809 days = mins / 1440;
1810 TimePeriod::Units units = secs ? TimePeriod::HoursMinutes
1811 : (days % 7) ? TimePeriod::Days : TimePeriod::Weeks;
1812 Duration duration((secs ? secs : days), (secs ? Duration::Seconds : Duration::Days));
1813 mAutoHideSystemTrayPeriod->setPeriod(duration, false, units);
1814 break;
1817 mAutoHideSystemTray->setButton(id);
1818 setTooltip(Preferences::tooltipAlarmCount(),
1819 Preferences::showTooltipAlarmTime(),
1820 Preferences::showTooltipTimeToAlarm(),
1821 Preferences::tooltipTimeToPrefix());
1822 mDisabledColour->setColor(Preferences::disabledColour());
1823 mArchivedColour->setColor(Preferences::archivedColour());
1825 if (allTabs || mTabs->currentIndex() == mTabWindows)
1827 mWindowPosition->setButton(Preferences::messageButtonDelay() ? 1 : 0);
1828 mWindowButtonDelay->setValue(Preferences::messageButtonDelay());
1829 mModalMessages->setChecked(Preferences::modalMessages());
1833 void ViewPrefTab::apply(bool syncToDisc)
1835 QColor colour = mDisabledColour->color();
1836 if (colour != Preferences::disabledColour())
1837 Preferences::setDisabledColour(colour);
1838 colour = mArchivedColour->color();
1839 if (colour != Preferences::archivedColour())
1840 Preferences::setArchivedColour(colour);
1841 int n = mTooltipShowAlarms->isChecked() ? -1 : 0;
1842 if (n && mTooltipMaxAlarms->isChecked())
1843 n = mTooltipMaxAlarmCount->value();
1844 if (n != Preferences::tooltipAlarmCount())
1845 Preferences::setTooltipAlarmCount(n);
1846 bool b = mTooltipShowTime->isChecked();
1847 if (b != Preferences::showTooltipAlarmTime())
1848 Preferences::setShowTooltipAlarmTime(b);
1849 b = mTooltipShowTimeTo->isChecked();
1850 if (b != Preferences::showTooltipTimeToAlarm())
1851 Preferences::setShowTooltipTimeToAlarm(b);
1852 QString text = mTooltipTimeToPrefix->text();
1853 if (text != Preferences::tooltipTimeToPrefix())
1854 Preferences::setTooltipTimeToPrefix(text);
1855 b = mShowInSystemTray->isChecked();
1856 if (b != Preferences::showInSystemTray())
1857 Preferences::setShowInSystemTray(b);
1858 if (b)
1860 switch (mAutoHideSystemTray->selectedId())
1862 case 0: n = 0; break; // never hide
1863 case 1: n = -1; break; // hide if no active alarms
1864 case 2: // hide if no alarms due within period
1865 n = mAutoHideSystemTrayPeriod->period().asSeconds() / 60;
1866 break;
1868 if (n != Preferences::autoHideSystemTray())
1869 Preferences::setAutoHideSystemTray(n);
1871 n = mWindowPosition->selectedId();
1872 if (n)
1873 n = mWindowButtonDelay->value();
1874 if (n != Preferences::messageButtonDelay())
1875 Preferences::setMessageButtonDelay(n);
1876 b = mModalMessages->isChecked();
1877 if (b != Preferences::modalMessages())
1878 Preferences::setModalMessages(b);
1879 PrefsTabBase::apply(syncToDisc);
1882 void ViewPrefTab::setTooltip(int maxAlarms, bool time, bool timeTo, const QString& prefix)
1884 if (!timeTo)
1885 time = true; // ensure that at least one time option is ticked
1887 // Set the states of the controls without calling signal
1888 // handlers, since these could change the checkboxes' states.
1889 mTooltipShowAlarms->blockSignals(true);
1890 mTooltipShowTime->blockSignals(true);
1891 mTooltipShowTimeTo->blockSignals(true);
1893 mTooltipShowAlarms->setChecked(maxAlarms);
1894 mTooltipMaxAlarms->setChecked(maxAlarms > 0);
1895 mTooltipMaxAlarmCount->setValue(maxAlarms > 0 ? maxAlarms : 1);
1896 mTooltipShowTime->setChecked(time);
1897 mTooltipShowTimeTo->setChecked(timeTo);
1898 mTooltipTimeToPrefix->setText(prefix);
1900 mTooltipShowAlarms->blockSignals(false);
1901 mTooltipShowTime->blockSignals(false);
1902 mTooltipShowTimeTo->blockSignals(false);
1904 // Enable/disable controls according to their states
1905 slotTooltipTimeToToggled(timeTo);
1906 slotTooltipAlarmsToggled(maxAlarms);
1909 void ViewPrefTab::slotTooltipAlarmsToggled(bool on)
1911 mTooltipMaxAlarms->setEnabled(on);
1912 mTooltipMaxAlarmCount->setEnabled(on && mTooltipMaxAlarms->isChecked());
1913 mTooltipShowTime->setEnabled(on);
1914 mTooltipShowTimeTo->setEnabled(on);
1915 on = on && mTooltipShowTimeTo->isChecked();
1916 mTooltipTimeToPrefix->setEnabled(on);
1917 mTooltipTimeToPrefixLabel->setEnabled(on);
1920 void ViewPrefTab::slotTooltipMaxToggled(bool on)
1922 mTooltipMaxAlarmCount->setEnabled(on && mTooltipMaxAlarms->isEnabled());
1925 void ViewPrefTab::slotTooltipTimeToggled(bool on)
1927 if (!on && !mTooltipShowTimeTo->isChecked())
1928 mTooltipShowTimeTo->setChecked(true);
1931 void ViewPrefTab::slotTooltipTimeToToggled(bool on)
1933 if (!on && !mTooltipShowTime->isChecked())
1934 mTooltipShowTime->setChecked(true);
1935 on = on && mTooltipShowTimeTo->isEnabled();
1936 mTooltipTimeToPrefix->setEnabled(on);
1937 mTooltipTimeToPrefixLabel->setEnabled(on);
1940 void ViewPrefTab::slotAutoHideSysTrayChanged(QAbstractButton* button)
1942 mAutoHideSystemTrayPeriod->setEnabled(mAutoHideSystemTray->id(button) == 2);
1945 void ViewPrefTab::slotWindowPosChanged(QAbstractButton* button)
1947 bool enable = mWindowPosition->id(button);
1948 mWindowButtonDelay->setEnabled(enable);
1949 mWindowButtonDelayLabel->setEnabled(enable);
1951 #include "moc_prefdlg_p.cpp"
1952 #include "moc_prefdlg.cpp"
1954 // vim: et sw=4: