• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kalarm

prefdlg.cpp

Go to the documentation of this file.
00001 /*
00002  *  prefdlg.cpp  -  program preferences dialog
00003  *  Program:  kalarm
00004  *  Copyright © 2001-2008 by David Jarvie <djarvie@kde.org>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "kalarm.h"
00022 
00023 #include <QLabel>
00024 #include <QCheckBox>
00025 #include <QRadioButton>
00026 #include <QPushButton>
00027 #include <QSpinBox>
00028 #include <QGroupBox>
00029 #include <QGridLayout>
00030 #include <QHBoxLayout>
00031 #include <QVBoxLayout>
00032 #include <QStyle>
00033 #include <QResizeEvent>
00034 
00035 #include <kvbox.h>
00036 #include <kglobal.h>
00037 #include <klocale.h>
00038 #include <kstandarddirs.h>
00039 #include <kshell.h>
00040 #include <klineedit.h>
00041 #include <kmessagebox.h>
00042 #include <kaboutdata.h>
00043 #include <kapplication.h>
00044 #include <kiconloader.h>
00045 #include <kcombobox.h>
00046 #include <ktabwidget.h>
00047 #include <KStandardGuiItem>
00048 #include <ksystemtimezone.h>
00049 #include <kicon.h>
00050 #ifdef Q_WS_X11
00051 #include <kwindowinfo.h>
00052 #include <kwindowsystem.h>
00053 #endif
00054 #include <kdebug.h>
00055 
00056 #include <ktoolinvocation.h>
00057 #include <libkholidays/kholidays.h>
00058 using namespace LibKHolidays;
00059 
00060 #include "alarmcalendar.h"
00061 #include "alarmresources.h"
00062 #include "alarmtimewidget.h"
00063 #include "buttongroup.h"
00064 #include "colourbutton.h"
00065 #include "editdlg.h"
00066 #include "editdlgtypes.h"
00067 #include "fontcolour.h"
00068 #include "functions.h"
00069 #include "itembox.h"
00070 #include "kalarmapp.h"
00071 #include "kamail.h"
00072 #include "label.h"
00073 #include "latecancel.h"
00074 #include "mainwindow.h"
00075 #include "preferences.h"
00076 #include "radiobutton.h"
00077 #include "recurrenceedit.h"
00078 #include "sounddlg.h"
00079 #include "soundpicker.h"
00080 #include "specialactions.h"
00081 #include "timeedit.h"
00082 #include "timespinbox.h"
00083 #include "timezonecombo.h"
00084 #include "traywindow.h"
00085 #include "prefdlg_p.moc"
00086 #include "prefdlg.moc"
00087 
00088 static const char PREF_DIALOG_NAME[] = "PrefDialog";
00089 
00090 // Command strings for executing commands in different types of terminal windows.
00091 // %t = window title parameter
00092 // %c = command to execute in terminal
00093 // %w = command to execute in terminal, with 'sleep 86400' appended
00094 // %C = temporary command file to execute in terminal
00095 // %W = temporary command file to execute in terminal, with 'sleep 86400' appended
00096 static QString xtermCommands[] = {
00097     QLatin1String("xterm -sb -hold -title %t -e %c"),
00098     QLatin1String("konsole --noclose -T %t -e ${SHELL:-sh} -c %c"),
00099     QLatin1String("gnome-terminal -t %t -e %W"),
00100     QLatin1String("eterm --pause -T %t -e %C"),    // some systems use eterm...
00101     QLatin1String("Eterm --pause -T %t -e %C"),    // while some use Eterm
00102     QLatin1String("rxvt -title %t -e ${SHELL:-sh} -c %w"),
00103     QString()       // end of list indicator - don't change!
00104 };
00105 
00106 
00107 /*=============================================================================
00108 = Class KAlarmPrefDlg
00109 =============================================================================*/
00110 
00111 KAlarmPrefDlg* KAlarmPrefDlg::mInstance = 0;
00112 
00113 void KAlarmPrefDlg::display()
00114 {
00115     if (!mInstance)
00116     {
00117         mInstance = new KAlarmPrefDlg;
00118         if (DialogScroll<KAlarmPrefDlg>::heightReduction())
00119         {
00120             // Evaluating the scroll size and then displaying the dialog
00121             // doesn't adjust the dialog size to fit the minimum height of
00122             // the pages. The only way to size the dialog correctly seems
00123             // to be to delete the dialog and create it a second time!?!
00124             delete mInstance;
00125             mInstance = new KAlarmPrefDlg;
00126         }
00127         QSize s;
00128         if (KAlarm::readConfigWindowSize(PREF_DIALOG_NAME, s))
00129             mInstance->resize(s);
00130         mInstance->show();
00131     }
00132     else
00133     {
00134 #ifdef Q_WS_X11
00135         KWindowInfo info = KWindowSystem::windowInfo(mInstance->winId(), NET::WMGeometry | NET::WMDesktop);
00136         KWindowSystem::setCurrentDesktop(info.desktop());
00137 #endif
00138         mInstance->setWindowState(mInstance->windowState() & ~Qt::WindowMinimized); // un-minimize it if necessary
00139         mInstance->raise();
00140         mInstance->activateWindow();
00141     }
00142 }
00143 
00144 KAlarmPrefDlg::KAlarmPrefDlg()
00145     : KPageDialog()
00146 {
00147     setAttribute(Qt::WA_DeleteOnClose);
00148     setObjectName("PrefDlg");    // used by LikeBack
00149     setCaption(i18nc("@title:window", "Configure"));
00150     setButtons(Help | Default | Ok | Apply | Cancel);
00151     setDefaultButton(Ok);
00152     setFaceType(List);
00153     showButtonSeparator(true);
00154     //setIconListAllVisible(true);
00155 
00156     mMiscPage = new MiscPrefTab;
00157     mMiscPageItem = new KPageWidgetItem(mMiscPage, i18nc("@title:tab General preferences", "General"));
00158     mMiscPageItem->setHeader(i18nc("@title General preferences", "General"));
00159     mMiscPageItem->setIcon(KIcon(DesktopIcon("preferences-other")));
00160     addPage(mMiscPageItem);
00161 
00162     mTimePage = new TimePrefTab;
00163     mTimePageItem = new KPageWidgetItem(mTimePage, i18nc("@title:tab", "Time & Date"));
00164     mTimePageItem->setHeader(i18nc("@title", "Time and Date"));
00165     mTimePageItem->setIcon(KIcon(DesktopIcon("preferences-system-time")));
00166     addPage(mTimePageItem);
00167 
00168     mStorePage = new StorePrefTab;
00169     mStorePageItem = new KPageWidgetItem(mStorePage, i18nc("@title:tab", "Storage"));
00170     mStorePageItem->setHeader(i18nc("@title", "Alarm Storage"));
00171     mStorePageItem->setIcon(KIcon(DesktopIcon("system-file-manager")));
00172     addPage(mStorePageItem);
00173 
00174     mEmailPage = new EmailPrefTab;
00175     mEmailPageItem = new KPageWidgetItem(mEmailPage, i18nc("@title:tab Email preferences", "Email"));
00176     mEmailPageItem->setHeader(i18nc("@title", "Email Alarm Settings"));
00177     mEmailPageItem->setIcon(KIcon(DesktopIcon("internet-mail")));
00178     addPage(mEmailPageItem);
00179 
00180     mViewPage = new ViewPrefTab;
00181     mViewPageItem = new KPageWidgetItem(mViewPage, i18nc("@title:tab", "View"));
00182     mViewPageItem->setHeader(i18nc("@title", "View Settings"));
00183     mViewPageItem->setIcon(KIcon(DesktopIcon("preferences-desktop-theme")));
00184     addPage(mViewPageItem);
00185 
00186     mEditPage = new EditPrefTab;
00187     mEditPageItem = new KPageWidgetItem(mEditPage, i18nc("@title:tab", "Edit"));
00188     mEditPageItem->setHeader(i18nc("@title", "Default Alarm Edit Settings"));
00189     mEditPageItem->setIcon(KIcon(DesktopIcon("document-properties")));
00190     addPage(mEditPageItem);
00191 
00192     connect(this, SIGNAL(okClicked()), SLOT(slotOk()));
00193     connect(this, SIGNAL(cancelClicked()), SLOT(slotCancel()));
00194     connect(this, SIGNAL(applyClicked()), SLOT(slotApply()));
00195     connect(this, SIGNAL(defaultClicked()), SLOT(slotDefault()));
00196     connect(this, SIGNAL(helpClicked()), SLOT(slotHelp()));
00197     restore(false);
00198     adjustSize();
00199 }
00200 
00201 KAlarmPrefDlg::~KAlarmPrefDlg()
00202 {
00203     mInstance = 0;
00204 }
00205 
00206 void KAlarmPrefDlg::slotHelp()
00207 {
00208     KToolInvocation::invokeHelp("preferences");
00209 }
00210 
00211 // Apply the preferences that are currently selected
00212 void KAlarmPrefDlg::slotApply()
00213 {
00214     kDebug();
00215     QString errmsg = mEmailPage->validate();
00216     if (!errmsg.isEmpty())
00217     {
00218         setCurrentPage(mEmailPageItem);
00219         if (KMessageBox::warningYesNo(this, errmsg) != KMessageBox::Yes)
00220         {
00221             mValid = false;
00222             return;
00223         }
00224     }
00225     errmsg = mEditPage->validate();
00226     if (!errmsg.isEmpty())
00227     {
00228         setCurrentPage(mEditPageItem);
00229         KMessageBox::sorry(this, errmsg);
00230         mValid = false;
00231         return;
00232     }
00233     mValid = true;
00234     mEmailPage->apply(false);
00235     mViewPage->apply(false);
00236     mEditPage->apply(false);
00237     mStorePage->apply(false);
00238     mTimePage->apply(false);
00239     mMiscPage->apply(false);
00240     Preferences::self()->writeConfig();
00241 }
00242 
00243 // Apply the preferences that are currently selected
00244 void KAlarmPrefDlg::slotOk()
00245 {
00246     kDebug();
00247     mValid = true;
00248     slotApply();
00249     if (mValid)
00250         KDialog::accept();
00251 }
00252 
00253 // Discard the current preferences and close the dialog
00254 void KAlarmPrefDlg::slotCancel()
00255 {
00256     kDebug();
00257     restore(false);
00258     KDialog::reject();
00259 }
00260 
00261 // Discard the current preferences and use the present ones
00262 void KAlarmPrefDlg::restore(bool defaults)
00263 {
00264     kDebug() << (defaults ? "defaults" : "");
00265     if (defaults)
00266         Preferences::self()->useDefaults(true);
00267     mEmailPage->restore(defaults);
00268     mViewPage->restore(defaults);
00269     mEditPage->restore(defaults);
00270     mStorePage->restore(defaults);
00271     mTimePage->restore(defaults);
00272     mMiscPage->restore(defaults);
00273     if (defaults)
00274         Preferences::self()->useDefaults(false);
00275 }
00276 
00277 /******************************************************************************
00278 * Return the minimum size for the dialog.
00279 * If the minimum size would be too high to fit the desktop, the tab contents
00280 * are made scrollable.
00281 */
00282 QSize KAlarmPrefDlg::minimumSizeHint() const
00283 {
00284     if (!DialogScroll<KAlarmPrefDlg>::sized())
00285     {
00286         KAlarmPrefDlg* thisvar = const_cast<KAlarmPrefDlg*>(this);
00287         QSize s = DialogScroll<KAlarmPrefDlg>::initMinimumHeight(thisvar);
00288         if (s.isValid())
00289         {
00290             if (DialogScroll<KAlarmPrefDlg>::heightReduction())
00291             {
00292                 s = QSize(s.width(), s.height() - DialogScroll<KAlarmPrefDlg>::heightReduction());
00293                 thisvar->resize(s);
00294             }
00295             return s;
00296         }
00297     }
00298     return KDialog::minimumSizeHint();
00299 }
00300 
00301 /******************************************************************************
00302 *  Called when the dialog's size has changed.
00303 *  Records the new size in the config file.
00304 */
00305 void KAlarmPrefDlg::resizeEvent(QResizeEvent* re)
00306 {
00307     if (isVisible())
00308         KAlarm::writeConfigWindowSize(PREF_DIALOG_NAME, re->size());
00309     KPageDialog::resizeEvent(re);
00310 }
00311 
00312 
00313 /*=============================================================================
00314 = Class PrefsTabBase
00315 =============================================================================*/
00316 int PrefsTabBase::mIndentWidth = 0;
00317 
00318 PrefsTabBase::PrefsTabBase()
00319     : mLabelsAligned(false)
00320 {
00321     mTopWidget = new KVBox(this);
00322     mTopWidget->setMargin(0);
00323     mTopWidget->setSpacing(KDialog::spacingHint());
00324     setWidget(mTopWidget);
00325     if (!mIndentWidth)
00326     {
00327         QRadioButton radio(this);
00328         QStyleOptionButton opt;
00329         opt.initFrom(&radio);
00330         mIndentWidth = style()->subElementRect(QStyle::SE_RadioButtonIndicator, &opt).width();
00331     }
00332     mTopLayout = qobject_cast<QVBoxLayout*>(mTopWidget->layout());
00333     Q_ASSERT(mTopLayout);
00334 }
00335 
00336 void PrefsTabBase::apply(bool syncToDisc)
00337 {
00338     if (syncToDisc)
00339         Preferences::self()->writeConfig();
00340 }
00341 
00342 void PrefsTabBase::addAlignedLabel(QLabel* label)
00343 {
00344     mLabels += label;
00345 }
00346 
00347 void PrefsTabBase::showEvent(QShowEvent*)
00348 {
00349     if (!mLabelsAligned)
00350     {
00351         int wid = 0;
00352         int i;
00353         int end = mLabels.count();
00354         QList<int> xpos;
00355         for (i = 0;  i < end;  ++i)
00356         {
00357             int x = mLabels[i]->mapTo(this, QPoint(0, 0)).x();
00358             xpos += x;
00359             int w = x + mLabels[i]->sizeHint().width();
00360             if (w > wid)
00361                 wid = w;
00362         }
00363         for (i = 0;  i < end;  ++i)
00364         {
00365             mLabels[i]->setFixedWidth(wid - xpos[i]);
00366             mLabels[i]->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
00367         }
00368         mLabelsAligned = true;
00369     }
00370 }
00371 
00372 
00373 /*=============================================================================
00374 = Class MiscPrefTab
00375 =============================================================================*/
00376 
00377 MiscPrefTab::MiscPrefTab()
00378     : PrefsTabBase()
00379 {
00380     QGroupBox* group = new QGroupBox(i18nc("@title:group", "Run Mode"), topWidget());
00381     QVBoxLayout* vlayout = new QVBoxLayout(group);
00382     vlayout->setMargin(KDialog::marginHint());
00383     vlayout->setSpacing(KDialog::spacingHint());
00384 
00385     // Start at login
00386     mAutoStart = new QCheckBox(i18nc("@option:check", "Start at login"), group);
00387     connect(mAutoStart, SIGNAL(clicked()), SLOT(slotAutostartClicked()));
00388     mAutoStart->setWhatsThis(i18nc("@info:whatsthis",
00389           "<para>Automatically start <application>KAlarm</application> whenever you start KDE.</para>"
00390           "<para>This option should always be checked unless you intend to discontinue use of <application>KAlarm</application>.</para>"));
00391     vlayout->addWidget(mAutoStart, 0, Qt::AlignLeft);
00392 
00393     mQuitWarn = new QCheckBox(i18nc("@option:check", "Warn before quitting"), group);
00394     mQuitWarn->setWhatsThis(i18nc("@info:whatsthis", "Check to display a warning prompt before quitting <application>KAlarm</application>."));
00395     vlayout->addWidget(mQuitWarn, 0, Qt::AlignLeft);
00396 
00397     group->setFixedHeight(group->sizeHint().height());
00398 
00399     // Confirm alarm deletion?
00400     KHBox* itemBox = new KHBox(topWidget());   // this is to allow left adjustment
00401     itemBox->setMargin(0);
00402     mConfirmAlarmDeletion = new QCheckBox(i18nc("@option:check", "Confirm alarm deletions"), itemBox);
00403     mConfirmAlarmDeletion->setMinimumSize(mConfirmAlarmDeletion->sizeHint());
00404     mConfirmAlarmDeletion->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation each time you delete an alarm."));
00405     itemBox->setStretchFactor(new QWidget(itemBox), 1);    // left adjust the controls
00406     itemBox->setFixedHeight(itemBox->sizeHint().height());
00407 
00408     // Terminal window to use for command alarms
00409     group = new QGroupBox(i18nc("@title:group", "Terminal for Command Alarms"), topWidget());
00410     group->setWhatsThis(i18nc("@info:whatsthis", "Choose which application to use when a command alarm is executed in a terminal window"));
00411     QGridLayout* grid = new QGridLayout(group);
00412     grid->setMargin(KDialog::marginHint());
00413     grid->setSpacing(KDialog::spacingHint());
00414     int row = 0;
00415 
00416     mXtermType = new ButtonGroup(group);
00417     int index = 0;
00418     mXtermFirst = -1;
00419     for (mXtermCount = 0;  !xtermCommands[mXtermCount].isNull();  ++mXtermCount)
00420     {
00421         QString cmd = xtermCommands[mXtermCount];
00422         QStringList args = KShell::splitArgs(cmd);
00423         if (args.isEmpty()  ||  KStandardDirs::findExe(args[0]).isEmpty())
00424             continue;
00425         QRadioButton* radio = new QRadioButton(args[0], group);
00426         radio->setMinimumSize(radio->sizeHint());
00427         mXtermType->addButton(radio, mXtermCount);
00428         if (mXtermFirst < 0)
00429             mXtermFirst = mXtermCount;   // note the id of the first button
00430         cmd.replace("%t", KGlobal::mainComponent().aboutData()->programName());
00431         cmd.replace("%c", "<command>");
00432         cmd.replace("%w", "<command; sleep>");
00433         cmd.replace("%C", "[command]");
00434         cmd.replace("%W", "[command; sleep]");
00435         radio->setWhatsThis(
00436                 i18nc("@info:whatsthis", "Check to execute command alarms in a terminal window by <icode>%1</icode>", cmd));
00437         grid->addWidget(radio, (row = index/3), index % 3, Qt::AlignLeft);
00438         ++index;
00439     }
00440 
00441     // QHBox used here doesn't allow the KLineEdit to expand!?
00442     QHBoxLayout* hlayout = new QHBoxLayout();
00443     hlayout->setSpacing(KDialog::spacingHint());
00444     grid->addLayout(hlayout, row + 1, 0, 1, 3, Qt::AlignLeft);
00445     QRadioButton* radio = new QRadioButton(i18nc("@option:radio Other terminal window command", "Other:"), group);
00446     hlayout->addWidget(radio);
00447     connect(radio, SIGNAL(toggled(bool)), SLOT(slotOtherTerminalToggled(bool)));
00448     mXtermType->addButton(radio, mXtermCount);
00449     if (mXtermFirst < 0)
00450         mXtermFirst = mXtermCount;   // note the id of the first button
00451     mXtermCommand = new KLineEdit(group);
00452     mXtermCommand->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
00453     hlayout->addWidget(mXtermCommand);
00454     QString wt = 
00455           i18nc("@info:whatsthis", "Enter the full command line needed to execute a command in your chosen terminal window. "
00456                "By default the alarm's command string will be appended to what you enter here. "
00457                "See the <application>KAlarm</application> Handbook for details of special codes to tailor the command line.");
00458     radio->setWhatsThis(wt);
00459     mXtermCommand->setWhatsThis(wt);
00460 
00461     topLayout()->addStretch();    // top adjust the widgets
00462 }
00463 
00464 void MiscPrefTab::restore(bool defaults)
00465 {
00466     Q_UNUSED(defaults);
00467     mAutoStart->setChecked(Preferences::autoStart());
00468     mQuitWarn->setChecked(Preferences::quitWarn());
00469     mConfirmAlarmDeletion->setChecked(Preferences::confirmAlarmDeletion());
00470     QString xtermCmd = Preferences::cmdXTermCommand();
00471     int id = mXtermFirst;
00472     if (!xtermCmd.isEmpty())
00473     {
00474         for ( ;  id < mXtermCount;  ++id)
00475         {
00476             if (mXtermType->find(id)  &&  xtermCmd == xtermCommands[id])
00477                 break;
00478         }
00479     }
00480     mXtermType->setButton(id);
00481     mXtermCommand->setEnabled(id == mXtermCount);
00482     mXtermCommand->setText(id == mXtermCount ? xtermCmd : "");
00483 }
00484 
00485 void MiscPrefTab::apply(bool syncToDisc)
00486 {
00487     // First validate anything entered in Other X-terminal command
00488     int xtermID = mXtermType->selectedId();
00489     if (xtermID >= mXtermCount)
00490     {
00491         QString cmd = mXtermCommand->text();
00492         if (cmd.isEmpty())
00493             xtermID = -1;       // 'Other' is only acceptable if it's non-blank
00494         else
00495         {
00496             QStringList args = KShell::splitArgs(cmd);
00497             cmd = args.isEmpty() ? QString() : args[0];
00498             if (KStandardDirs::findExe(cmd).isEmpty())
00499             {
00500                 mXtermCommand->setFocus();
00501                 if (KMessageBox::warningContinueCancel(topWidget(), i18nc("@info", "Command to invoke terminal window not found: <command>%1</command>", cmd))
00502                                 != KMessageBox::Continue)
00503                     return;
00504             }
00505         }
00506     }
00507     if (xtermID < 0)
00508     {
00509         xtermID = mXtermFirst;
00510         mXtermType->setButton(mXtermFirst);
00511     }
00512 
00513     if (mQuitWarn->isEnabled())
00514     {
00515         bool b = mQuitWarn->isChecked();
00516         if (b != Preferences::quitWarn())
00517             Preferences::setQuitWarn(b);
00518     }
00519     bool b = mAutoStart->isChecked();
00520     if (b != Preferences::autoStart())
00521         Preferences::setAutoStart(b);
00522     b = mConfirmAlarmDeletion->isChecked();
00523     if (b != Preferences::confirmAlarmDeletion())
00524         Preferences::setConfirmAlarmDeletion(b);
00525     QString text = (xtermID < mXtermCount) ? xtermCommands[xtermID] : mXtermCommand->text();
00526     if (text != Preferences::cmdXTermCommand())
00527         Preferences::setCmdXTermCommand(text);
00528     PrefsTabBase::apply(syncToDisc);
00529 }
00530 
00531 void MiscPrefTab::slotAutostartClicked()
00532 {
00533     if (!mAutoStart->isChecked()
00534     &&  KMessageBox::warningYesNo(topWidget(),
00535                               i18nc("@info", "You should not uncheck this option unless you intend to discontinue use of <application>KAlarm</application>"),
00536                               QString(), KStandardGuiItem::cont(), KStandardGuiItem::cancel()
00537                              ) != KMessageBox::Yes)
00538         mAutoStart->setChecked(true);
00539 }
00540 
00541 void MiscPrefTab::slotOtherTerminalToggled(bool on)
00542 {
00543     mXtermCommand->setEnabled(on);
00544 }
00545 
00546 
00547 /*=============================================================================
00548 = Class TimePrefTab
00549 =============================================================================*/
00550 
00551 TimePrefTab::TimePrefTab()
00552     : PrefsTabBase()
00553 {
00554     // Default time zone
00555     ItemBox* itemBox = new ItemBox(topWidget());
00556     itemBox->setMargin(0);
00557     KHBox* box = new KHBox(itemBox);   // this is to control the QWhatsThis text display area
00558     box->setMargin(0);
00559     box->setSpacing(KDialog::spacingHint());
00560     QLabel* label = new QLabel(i18nc("@label:listbox", "Time zone:"), box);
00561     addAlignedLabel(label);
00562 #if 1
00563     mTimeZone = new TimeZoneCombo(box);
00564     mTimeZone->setMaxVisibleItems(15);
00565 #else
00566     mTimeZone = new KComboBox(box);
00567     mTimeZone->setMaxVisibleItems(15);
00568     const KTimeZones::ZoneMap zones = KSystemTimeZones::zones();
00569     for (KTimeZones::ZoneMap::ConstIterator it = zones.begin();  it != zones.end();  ++it)
00570         mTimeZone->addItem(it.key());
00571 #endif
00572     box->setWhatsThis(i18nc("@info:whatsthis",
00573                             "Select the time zone which <application>KAlarm</application> should use "
00574                             "as its default for displaying and entering dates and times."));
00575     label->setBuddy(mTimeZone);
00576     itemBox->leftAlign();
00577     itemBox->setFixedHeight(box->sizeHint().height());
00578 
00579     // Holiday region
00580     itemBox = new ItemBox(topWidget());
00581     itemBox->setMargin(0);
00582     box = new KHBox(itemBox);   // this is to control the QWhatsThis text display area
00583     box->setMargin(0);
00584     box->setSpacing(KDialog::spacingHint());
00585     label = new QLabel(i18nc("@label:listbox", "Holiday region:"), box);
00586     addAlignedLabel(label);
00587     mHolidays = new KComboBox(box);
00588     mHolidays->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
00589     itemBox->leftAlign();
00590     label->setBuddy(mHolidays);
00591     box->setWhatsThis(i18nc("@info:whatsthis",
00592                             "Select which holiday region to use"));
00593     QStringList holidays;
00594     QStringList countryList = KHolidays::locations();
00595     foreach (const QString& country, countryList)
00596     {
00597         QString countryFile = KStandardDirs::locate("locale", "l10n/" + country + "/entry.desktop");
00598         QString regionName;  // name to display
00599         if (!countryFile.isEmpty())
00600         {
00601             KConfig config(countryFile, KConfig::SimpleConfig);
00602             KConfigGroup cfg(&config, "KCM Locale");
00603             regionName = cfg.readEntry("Name");
00604         }
00605         if (regionName.isEmpty())
00606             regionName = country;   // default to file name
00607 
00608         holidays << regionName;
00609         mHolidayNames[regionName] = country; // store region for saving to config file
00610     }
00611     qSort(holidays.begin(), holidays.end(), caseInsensitiveLessThan);
00612     holidays.push_front(i18nc("@item:inlistbox Do not use holidays", "(None)"));
00613     mHolidays->addItems(holidays);
00614 
00615     // Start-of-day time
00616     itemBox = new ItemBox(topWidget());
00617     itemBox->setMargin(0);
00618     box = new KHBox(itemBox);   // this is to control the QWhatsThis text display area
00619     box->setMargin(0);
00620     box->setSpacing(KDialog::spacingHint());
00621     label = new QLabel(i18nc("@label:spinbox", "Start of day for date-only alarms:"), box);
00622     addAlignedLabel(label);
00623     mStartOfDay = new TimeEdit(box);
00624     label->setBuddy(mStartOfDay);
00625     box->setWhatsThis(i18nc("@info:whatsthis",
00626           "<para>The earliest time of day at which a date-only alarm will be triggered.</para>"
00627           "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
00628     itemBox->leftAlign();
00629     itemBox->setFixedHeight(box->sizeHint().height());
00630 
00631     // Working hours
00632     QGroupBox* group = new QGroupBox(i18nc("@title:group", "Working Hours"), topWidget());
00633     QBoxLayout* layout = new QVBoxLayout(group);
00634     layout->setMargin(KDialog::marginHint());
00635     layout->setSpacing(KDialog::spacingHint());
00636 
00637     QWidget* daybox = new QWidget(group);   // this is to control the QWhatsThis text display area
00638     layout->addWidget(daybox);
00639     QGridLayout* wgrid = new QGridLayout(daybox);
00640     wgrid->setSpacing(KDialog::spacingHint());
00641     const KLocale* locale = KGlobal::locale();
00642     for (int i = 0;  i < 7;  ++i)
00643     {
00644         int day = KAlarm::localeDayInWeek_to_weekDay(i);
00645         mWorkDays[i] = new QCheckBox(KAlarm::weekDayName(day, locale), daybox);
00646         wgrid->addWidget(mWorkDays[i], i/3, i%3, Qt::AlignLeft);
00647     }
00648     daybox->setFixedHeight(daybox->sizeHint().height());
00649     daybox->setWhatsThis(i18nc("@info:whatsthis", "Check the days in the week which are work days"));
00650 
00651     itemBox = new ItemBox(group);
00652     itemBox->setMargin(0);
00653     layout->addWidget(itemBox);
00654     box = new KHBox(itemBox);   // this is to control the QWhatsThis text display area
00655     box->setMargin(0);
00656     box->setSpacing(KDialog::spacingHint());
00657     label = new QLabel(i18nc("@label:spinbox", "Daily start time:"), box);
00658     addAlignedLabel(label);
00659     mWorkStart = new TimeEdit(box);
00660     label->setBuddy(mWorkStart);
00661     box->setWhatsThis(i18nc("@info:whatsthis",
00662           "<para>Enter the start time of the working day.</para>"
00663           "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
00664     itemBox->leftAlign();
00665 
00666     itemBox = new ItemBox(group);
00667     itemBox->setMargin(0);
00668     layout->addWidget(itemBox);
00669     box = new KHBox(itemBox);   // this is to control the QWhatsThis text display area
00670     box->setMargin(0);
00671     box->setSpacing(KDialog::spacingHint());
00672     label = new QLabel(i18nc("@label:spinbox", "Daily end time:"), box);
00673     addAlignedLabel(label);
00674     mWorkEnd = new TimeEdit(box);
00675     label->setBuddy(mWorkEnd);
00676     box->setWhatsThis(i18nc("@info:whatsthis",
00677           "<para>Enter the end time of the working day.</para>"
00678           "<para>%1</para>", TimeSpinBox::shiftWhatsThis()));
00679     itemBox->leftAlign();
00680     box->setFixedHeight(box->sizeHint().height());
00681 
00682     topLayout()->addStretch();    // top adjust the widgets
00683 }
00684 
00685 void TimePrefTab::restore(bool)
00686 {
00687 #if 1
00688     mTimeZone->setTimeZone(Preferences::timeZone());
00689 #else
00690     int tzindex = 0;
00691     KTimeZone tz = Preferences::timeZone();
00692     if (tz.isValid())
00693     {
00694         QString zone = tz.name();
00695         int count = mTimeZone->count();
00696         while (tzindex < count  &&  mTimeZone->itemText(tzindex) != zone)
00697             ++tzindex;
00698         if (tzindex >= count)
00699             tzindex = 0;
00700     }
00701     mTimeZone->setCurrentIndex(tzindex);
00702 #endif
00703     QString region;
00704     QString hol = Preferences::holidays().location();
00705     if (!hol.isEmpty())
00706     {
00707         for (QMap<QString, QString>::const_iterator it = mHolidayNames.constBegin();  it != mHolidayNames.constEnd();  ++it)
00708         {
00709             if (it.value() == hol)
00710             {
00711                 region = it.key();
00712                 break;
00713             }
00714         }
00715     }
00716     int i;
00717     for (i = mHolidays->count();  --i > 0 && mHolidays->itemText(i) != region; ) ;
00718     mHolidays->setCurrentIndex(i);
00719     mStartOfDay->setValue(Preferences::startOfDay());
00720     mWorkStart->setValue(Preferences::workDayStart());
00721     mWorkEnd->setValue(Preferences::workDayEnd());
00722     QBitArray days = Preferences::workDays();
00723     for (i = 0;  i < 7;  ++i)
00724     {
00725         bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1);
00726         mWorkDays[i]->setChecked(x);
00727     }
00728 }
00729 
00730 void TimePrefTab::apply(bool syncToDisc)
00731 {
00732 #if 1
00733     KTimeZone tz = mTimeZone->timeZone();
00734     if (tz.isValid())
00735         Preferences::setTimeZone(tz);
00736 #else
00737     KTimeZone tz = KSystemTimeZones::zone(mTimeZone->currentText());
00738     if (tz.isValid()  &&  tz != Preferences::timeZone())
00739         Preferences::setTimeZone(tz);
00740 #endif
00741     QString hol = mHolidays->currentIndex() ? mHolidayNames[mHolidays->currentText()] : QString();
00742     if (hol != Preferences::holidays().location())
00743         Preferences::setHolidayRegion(hol);
00744     int t = mStartOfDay->value();
00745     QTime sodt(t/60, t%60, 0);
00746     if (sodt != Preferences::startOfDay())
00747         Preferences::setStartOfDay(sodt);
00748     t = mWorkStart->value();
00749     Preferences::setWorkDayStart(QTime(t/60, t%60, 0));
00750     t = mWorkEnd->value();
00751     Preferences::setWorkDayEnd(QTime(t/60, t%60, 0));
00752     QBitArray workDays(7);
00753     for (int i = 0;  i < 7;  ++i)
00754         if (mWorkDays[i]->isChecked())
00755             workDays.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1);
00756     Preferences::setWorkDays(workDays);
00757     PrefsTabBase::apply(syncToDisc);
00758 }
00759 
00760 
00761 /*=============================================================================
00762 = Class StorePrefTab
00763 =============================================================================*/
00764 
00765 StorePrefTab::StorePrefTab()
00766     : PrefsTabBase(),
00767       mCheckKeepChanges(false)
00768 {
00769     // Which resource to save to
00770     QGroupBox* group = new QGroupBox(i18nc("@title:group", "New Alarms && Templates"), topWidget());
00771     QButtonGroup* bgroup = new QButtonGroup(group);
00772     QBoxLayout* layout = new QVBoxLayout(group);
00773     layout->setMargin(KDialog::marginHint());
00774     layout->setSpacing(KDialog::spacingHint());
00775 
00776     mDefaultResource = new QRadioButton(i18nc("@option:radio", "Store in default resource"), group);
00777     bgroup->addButton(mDefaultResource);
00778     mDefaultResource->setWhatsThis(i18nc("@info:whatsthis", "Add all new alarms and alarm templates to the default resources, without prompting."));
00779     layout->addWidget(mDefaultResource, 0, Qt::AlignLeft);
00780     mAskResource = new QRadioButton(i18nc("@option:radio", "Prompt for which resource to store in"), group);
00781     bgroup->addButton(mAskResource);
00782     mAskResource->setWhatsThis(i18nc("@info:whatsthis",
00783           "<para>When saving a new alarm or alarm template, prompt for which resource to store it in, if there is more than one active resource.</para>"
00784           "<para>Note that archived alarms are always stored in the default archived alarm resource.</para>"));
00785     layout->addWidget(mAskResource, 0, Qt::AlignLeft);
00786 
00787     // Archived alarms
00788     group = new QGroupBox(i18nc("@title:group", "Archived Alarms"), topWidget());
00789     QGridLayout* grid = new QGridLayout(group);
00790     grid->setMargin(KDialog::marginHint());
00791     grid->setSpacing(KDialog::spacingHint());
00792     grid->setColumnStretch(1, 1);
00793     grid->setColumnMinimumWidth(0, indentWidth());
00794     mKeepArchived = new QCheckBox(i18nc("@option:check", "Keep alarms after expiry"), group);
00795     connect(mKeepArchived, SIGNAL(toggled(bool)), SLOT(slotArchivedToggled(bool)));
00796     mKeepArchived->setWhatsThis(
00797           i18nc("@info:whatsthis", "Check to archive alarms after expiry or deletion (except deleted alarms which were never triggered)."));
00798     grid->addWidget(mKeepArchived, 0, 0, 1, 2, Qt::AlignLeft);
00799 
00800     KHBox* box = new KHBox(group);
00801     box->setMargin(0);
00802     box->setSpacing(KDialog::spacingHint());
00803     mPurgeArchived = new QCheckBox(i18nc("@option:check", "Discard archived alarms after:"), box);
00804     mPurgeArchived->setMinimumSize(mPurgeArchived->sizeHint());
00805     connect(mPurgeArchived, SIGNAL(toggled(bool)), SLOT(slotArchivedToggled(bool)));
00806     mPurgeAfter = new SpinBox(box);
00807     mPurgeAfter->setMinimum(1);
00808     mPurgeAfter->setSingleShiftStep(10);
00809     mPurgeAfter->setMinimumSize(mPurgeAfter->sizeHint());
00810     mPurgeAfterLabel = new QLabel(i18nc("@label Time unit for user-entered number", "days"), box);
00811     mPurgeAfterLabel->setMinimumSize(mPurgeAfterLabel->sizeHint());
00812     mPurgeAfterLabel->setBuddy(mPurgeAfter);
00813     box->setWhatsThis(i18nc("@info:whatsthis", "Uncheck to store archived alarms indefinitely. Check to enter how long archived alarms should be stored."));
00814     grid->addWidget(box, 1, 1, Qt::AlignLeft);
00815 
00816     mClearArchived = new QPushButton(i18nc("@action:button", "Clear Archived Alarms"), group);
00817     mClearArchived->setFixedSize(mClearArchived->sizeHint());
00818     connect(mClearArchived, SIGNAL(clicked()), SLOT(slotClearArchived()));
00819     mClearArchived->setWhatsThis((AlarmResources::instance()->activeCount(AlarmResource::ARCHIVED, false) <= 1)
00820             ? i18nc("@info:whatsthis", "Delete all existing archived alarms.")
00821             : i18nc("@info:whatsthis", "Delete all existing archived alarms (from the default archived alarm resource only)."));
00822     grid->addWidget(mClearArchived, 2, 1, Qt::AlignLeft);
00823     group->setFixedHeight(group->sizeHint().height());
00824 
00825     topLayout()->addStretch();    // top adjust the widgets
00826 }
00827 
00828 void StorePrefTab::restore(bool defaults)
00829 {
00830     mCheckKeepChanges = defaults;
00831     mAskResource->setChecked(Preferences::askResource());
00832     int keepDays = Preferences::archivedKeepDays();
00833     if (!defaults)
00834         mOldKeepArchived = keepDays;
00835     setArchivedControls(keepDays);
00836     mCheckKeepChanges = true;
00837 }
00838 
00839 void StorePrefTab::apply(bool syncToDisc)
00840 {
00841     bool b = mAskResource->isChecked();
00842     if (b != Preferences::askResource())
00843         Preferences::setAskResource(mAskResource->isChecked());
00844     int days = !mKeepArchived->isChecked() ? 0 : mPurgeArchived->isChecked() ? mPurgeAfter->value() : -1;
00845     if (days != Preferences::archivedKeepDays())
00846         Preferences::setArchivedKeepDays(days);
00847     PrefsTabBase::apply(syncToDisc);
00848 }
00849 
00850 void StorePrefTab::setArchivedControls(int purgeDays)
00851 {
00852     mKeepArchived->setChecked(purgeDays);
00853     mPurgeArchived->setChecked(purgeDays > 0);
00854     mPurgeAfter->setValue(purgeDays > 0 ? purgeDays : 0);
00855     slotArchivedToggled(true);
00856 }
00857 
00858 void StorePrefTab::slotArchivedToggled(bool)
00859 {
00860     bool keep = mKeepArchived->isChecked();
00861     if (keep  &&  !mOldKeepArchived  &&  mCheckKeepChanges
00862     &&  !AlarmResources::instance()->getStandardResource(AlarmResource::ARCHIVED))
00863     {
00864         KMessageBox::sorry(topWidget(),
00865              i18nc("@info", "<para>A default resource is required in order to archive alarms, but none is currently enabled.</para>"
00866                   "<para>If you wish to keep expired alarms, please first use the resources view to select a default "
00867                   "archived alarms resource.</para>"));
00868         mKeepArchived->setChecked(false);
00869         return;
00870     }
00871     mOldKeepArchived = keep;
00872     mPurgeArchived->setEnabled(keep);
00873     mPurgeAfter->setEnabled(keep && mPurgeArchived->isChecked());
00874     mPurgeAfterLabel->setEnabled(keep);
00875     mClearArchived->setEnabled(keep);
00876 }
00877 
00878 void StorePrefTab::slotClearArchived()
00879 {
00880     bool single = AlarmResources::instance()->activeCount(AlarmResource::ARCHIVED, false) <= 1;
00881     if (KMessageBox::warningContinueCancel(topWidget(), single ? i18nc("@info", "Do you really want to delete all archived alarms?")
00882                                                         : i18nc("@info", "Do you really want to delete all alarms in the default archived alarm resource?"))
00883             != KMessageBox::Continue)
00884         return;
00885     theApp()->purgeAll();
00886 }
00887 
00888 
00889 /*=============================================================================
00890 = Class EmailPrefTab
00891 =============================================================================*/
00892 
00893 EmailPrefTab::EmailPrefTab()
00894     : PrefsTabBase(),
00895       mAddressChanged(false),
00896       mBccAddressChanged(false)
00897 {
00898     KHBox* box = new KHBox(topWidget());
00899     box->setMargin(0);
00900     box->setSpacing(2*KDialog::spacingHint());
00901     QLabel* label = new QLabel(i18nc("@label", "Email client:"), box);
00902     mEmailClient = new ButtonGroup(box);
00903     QString kmailOption = i18nc("@option:radio", "KMail");
00904     QString sendmailOption = i18nc("@option:radio", "Sendmail");
00905     mKMailButton = new RadioButton(kmailOption, box);
00906     mKMailButton->setMinimumSize(mKMailButton->sizeHint());
00907     mEmailClient->addButton(mKMailButton, Preferences::kmail);
00908     mSendmailButton = new RadioButton(sendmailOption, box);
00909     mSendmailButton->setMinimumSize(mSendmailButton->sizeHint());
00910     mEmailClient->addButton(mSendmailButton, Preferences::sendmail);
00911     connect(mEmailClient, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotEmailClientChanged(QAbstractButton*)));
00912     box->setFixedHeight(box->sizeHint().height());
00913     box->setWhatsThis(i18nc("@info:whatsthis",
00914           "<para>Choose how to send email when an email alarm is triggered."
00915           "<list><item><interface>%1</interface>: The email is sent automatically via <application>KMail</application>. <application>KMail</application> is started first if necessary.</item>"
00916           "<item><interface>%2</interface>: The email is sent automatically. This option will only work if "
00917           "your system is configured to use <application>sendmail</application> or a sendmail compatible mail transport agent.</item></list></para>",
00918           kmailOption, sendmailOption));
00919 
00920     box = new KHBox(topWidget());   // this is to allow left adjustment
00921     box->setMargin(0);
00922     mEmailCopyToKMail = new QCheckBox(i18nc("@option:check", "Copy sent emails into <application>KMail</application>'s <resource>%1</resource> folder", KAMail::i18n_sent_mail()), box);
00923     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()));
00924     box->setStretchFactor(new QWidget(box), 1);    // left adjust the controls
00925     box->setFixedHeight(box->sizeHint().height());
00926 
00927     box = new KHBox(topWidget());   // this is to allow left adjustment
00928     box->setMargin(0);
00929     mEmailQueuedNotify = new QCheckBox(i18nc("@option:check", "Notify when remote emails are queued"), box);
00930     mEmailQueuedNotify->setWhatsThis(
00931           i18nc("@info:whatsthis", "Display a notification message whenever an email alarm has queued an email for sending to a remote system. "
00932                "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."));
00933     box->setStretchFactor(new QWidget(box), 1);    // left adjust the controls
00934     box->setFixedHeight(box->sizeHint().height());
00935 
00936     // Your Email Address group box
00937     QGroupBox* group = new QGroupBox(i18nc("@title:group", "Your Email Address"), topWidget());
00938     QGridLayout* grid = new QGridLayout(group);
00939     grid->setMargin(KDialog::marginHint());
00940     grid->setSpacing(KDialog::spacingHint());
00941     grid->setColumnStretch(2, 1);
00942 
00943     // 'From' email address controls ...
00944     label = new Label(i18nc("@label 'From' email address", "From:"), group);
00945     grid->addWidget(label, 1, 0);
00946     mFromAddressGroup = new ButtonGroup(group);
00947     connect(mFromAddressGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(slotFromAddrChanged(QAbstractButton*)));
00948 
00949     // Line edit to enter a 'From' email address
00950     mFromAddrButton = new RadioButton(group);
00951     mFromAddressGroup->addButton(mFromAddrButton, Preferences::MAIL_FROM_ADDR);
00952     label->setBuddy(mFromAddrButton);
00953     grid->addWidget(mFromAddrButton, 1, 1);
00954     mEmailAddress = new KLineEdit(group);
00955     connect(mEmailAddress, SIGNAL(textChanged(const QString&)), SLOT(slotAddressChanged()));
00956     QString whatsThis = i18nc("@info:whatsthis", "Your email address, used to identify you as the sender when sending email alarms.");
00957     mFromAddrButton->setWhatsThis(whatsThis);
00958     mEmailAddress->setWhatsThis(whatsThis);
00959     mFromAddrButton->setFocusWidget(mEmailAddress);
00960     grid->addWidget(mEmailAddress, 1, 2);
00961 
00962     // 'From' email address to be taken from System Settings
00963     mFromCCentreButton = new RadioButton(i18nc("@option:radio", "Use address from System Settings"), group);
00964     mFromAddressGroup->addButton(mFromCCentreButton, Preferences::MAIL_FROM_SYS_SETTINGS);
00965     mFromCCentreButton->setWhatsThis(
00966           i18nc("@info:whatsthis", "Check to use the email address set in KDE System Settings, to identify you as the sender when sending email alarms."));
00967     grid->addWidget(mFromCCentreButton, 2, 1, 1, 2, Qt::AlignLeft);
00968 
00969     // 'From' email address to be picked from KMail's identities when the email alarm is configured
00970     mFromKMailButton = new RadioButton(i18nc("@option:radio", "Use <application>KMail</application> identities"), group);
00971     mFromAddressGroup->addButton(mFromKMailButton, Preferences::MAIL_FROM_KMAIL);
00972     mFromKMailButton->setWhatsThis(
<