kalarm Library API Documentation

editdlg.cpp

00001 /*
00002  *  editdlg.cpp  -  dialogue to create or modify an alarm
00003  *  Program:  kalarm
00004  *  (C) 2001, 2002 by David Jarvie  software@astrojar.org.uk
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
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *
00020  *  As a special exception, permission is given to link this program
00021  *  with any edition of Qt, and distribute the resulting executable,
00022  *  without including the source code for Qt in the source distribution.
00023  */
00024 
00025 #include "kalarm.h"
00026 
00027 #include <limits.h>
00028 
00029 #include <qlayout.h>
00030 #include <qpopupmenu.h>
00031 #include <qpushbutton.h>
00032 #include <qlineedit.h>
00033 #include <qmultilineedit.h>
00034 #include <qvbox.h>
00035 #include <qgroupbox.h>
00036 #include <qwidgetstack.h>
00037 #include <qlabel.h>
00038 #include <qmessagebox.h>
00039 #include <qvalidator.h>
00040 #include <qwhatsthis.h>
00041 #include <qtooltip.h>
00042 #include <qdir.h>
00043 
00044 #include <kglobal.h>
00045 #include <klocale.h>
00046 #include <kconfig.h>
00047 #include <kfiledialog.h>
00048 #include <kiconloader.h>
00049 #include <kio/netaccess.h>
00050 #include <kfileitem.h>
00051 #include <kmessagebox.h>
00052 #include <kwinmodule.h>
00053 #include <kstandarddirs.h>
00054 #include <kstdguiitem.h>
00055 #include <kdebug.h>
00056 
00057 #include "kalarmapp.h"
00058 #include "prefsettings.h"
00059 #include "datetime.h"
00060 #include "recurrenceedit.h"
00061 #include "colourcombo.h"
00062 #include "deferdlg.h"
00063 #include "buttongroup.h"
00064 #include "editdlg.moc"
00065 
00066 
00067 EditAlarmDlg::EditAlarmDlg(const QString& caption, QWidget* parent, const char* name,
00068                                 const KAlarmEvent* event)
00069         : KDialogBase(KDialogBase::Tabbed, caption, Ok|Cancel|Try, Ok, parent, name),
00070           recurSetEndDate(true),
00071           deferGroup(0L)
00072 {
00073         QVBox* mainPageBox = addVBoxPage(i18n("&Alarm"));
00074         mainPageIndex = pageIndex(mainPageBox);
00075         PageFrame* mainPage = new PageFrame(mainPageBox);
00076         connect(mainPage, SIGNAL(shown()), SLOT(slotShowMainPage()));
00077         QVBoxLayout* topLayout = new QVBoxLayout(mainPage, marginKDE2, spacingHint());
00078 
00079         // Recurrence tab
00080         QVBox* recurPage = addVBoxPage(i18n("&Recurrence"));
00081         recurPageIndex = pageIndex(recurPage);
00082         recurTabStack = new QWidgetStack(recurPage);
00083 
00084         recurrenceEdit = new RecurrenceEdit(recurTabStack, "recurPage");
00085         recurTabStack->addWidget(recurrenceEdit, 0);
00086         connect(recurrenceEdit, SIGNAL(shown()), SLOT(slotShowRecurrenceEdit()));
00087         connect(recurrenceEdit, SIGNAL(typeChanged(int)), SLOT(slotRecurTypeChange(int)));
00088 
00089         recurDisabled = new QLabel(i18n("The alarm does not recur.\nEnable recurrence in the Alarm tab."), recurTabStack);
00090         recurDisabled->setAlignment(Qt::AlignCenter);
00091         recurTabStack->addWidget(recurDisabled, 1);
00092 
00093         // Alarm action
00094 
00095         QButtonGroup* actionGroup = new QButtonGroup(i18n("Action"), mainPage, "actionGroup");
00096         connect(actionGroup, SIGNAL(clicked(int)), SLOT(slotAlarmTypeClicked(int)));
00097         topLayout->addWidget(actionGroup, 1);
00098         QGridLayout* grid = new QGridLayout(actionGroup, 3, 5, marginKDE2 + marginHint(), spacingHint());
00099         grid->addRowSpacing(0, fontMetrics().lineSpacing()/2);
00100 
00101         // Message radio button
00102         messageRadio = new QRadioButton(i18n("Te&xt"), actionGroup, "messageButton");
00103         messageRadio->setFixedSize(messageRadio->sizeHint());
00104         QWhatsThis::add(messageRadio,
00105               i18n("If checked, the alarm will display a text message."));
00106         grid->addWidget(messageRadio, 1, 0);
00107         grid->setColStretch(1, 1);
00108 
00109         // File radio button
00110         fileRadio = new QRadioButton(i18n("&File"), actionGroup, "fileButton");
00111         fileRadio->setFixedSize(fileRadio->sizeHint());
00112         QWhatsThis::add(fileRadio,
00113               i18n("If checked, the alarm will display the contents of a text file."));
00114         grid->addWidget(fileRadio, 1, 2);
00115         grid->setColStretch(3, 1);
00116 
00117         // Command radio button
00118         commandRadio = new QRadioButton(i18n("Co&mmand"), actionGroup, "cmdButton");
00119         commandRadio->setFixedSize(commandRadio->sizeHint());
00120         QWhatsThis::add(commandRadio,
00121               i18n("If checked, the alarm will execute a shell command."));
00122         grid->addWidget(commandRadio, 1, 4);
00123 
00124 #ifdef KALARM_EMAIL
00125         // Email radio button
00126         emailRadio = new QRadioButton(i18n("&Email"), actionGroup, "emailButton");
00127         emailRadio->setFixedSize(emailRadio->sizeHint());
00128         QWhatsThis::add(emailRadio,
00129               i18n("If checked, the alarm will send an email."));
00130         grid->addWidget(emailRadio, 1, 6);
00131 #endif
00132 
00133         initDisplayAlarms(actionGroup);
00134         initCommand(actionGroup);
00135         alarmTypeStack = new QWidgetStack(actionGroup);
00136         grid->addMultiCellWidget(alarmTypeStack, 2, 2, 0, 6);
00137         grid->setRowStretch(2, 1);
00138         alarmTypeStack->addWidget(displayAlarmsFrame, 0);
00139         alarmTypeStack->addWidget(commandFrame, 1);
00140 
00141         if (event  &&  event->recurs() != KAlarmEvent::NO_RECUR  &&  event->deferred())
00142         {
00143                 // Recurring event's deferred date/time
00144                 deferGroup = new QGroupBox(1, Qt::Vertical, i18n("Deferred Alarm"), mainPage, "deferGroup");
00145                 topLayout->addWidget(deferGroup);
00146                 QLabel* label = new QLabel(i18n("Deferred to:"), deferGroup);
00147                 label->setFixedSize(label->sizeHint());
00148 
00149                 deferDateTime = event->deferDateTime();
00150                 deferTimeLabel = new QLabel(KGlobal::locale()->formatDateTime(deferDateTime), deferGroup);
00151 
00152                 QPushButton* button = new QPushButton(i18n("C&hange..."), deferGroup);
00153                 button->setFixedSize(button->sizeHint());
00154                 connect(button, SIGNAL(clicked()), SLOT(slotEditDeferral()));
00155                 QWhatsThis::add(button, i18n("Change the alarm's deferred time, or cancel the deferral"));
00156                 deferGroup->addSpace(0);
00157         }
00158 
00159         grid = new QGridLayout(topLayout, 3, 2, spacingHint());
00160 
00161         // Date and time entry
00162 
00163         timeWidget = new AlarmTimeWidget(i18n("Time"), AlarmTimeWidget::AT_TIME | AlarmTimeWidget::NARROW,
00164                                          mainPage, "timeGroup");
00165         grid->addMultiCellWidget(timeWidget, 0, 2, 0, 0);
00166 
00167         // Repetition type radio buttons
00168 
00169         ButtonGroup* repeatGroup = new ButtonGroup(1, Qt::Horizontal, i18n("Repetition"), mainPage);
00170         connect(repeatGroup, SIGNAL(buttonSet(int)), SLOT(slotRepeatClicked(int)));
00171         grid->addWidget(repeatGroup, 0, 1);
00172         grid->setRowStretch(1, 1);
00173 
00174         noRepeatRadio = new QRadioButton(i18n("&No repetition"), repeatGroup);
00175         noRepeatRadio->setFixedSize(noRepeatRadio->sizeHint());
00176         QWhatsThis::add(noRepeatRadio,
00177               i18n("Trigger the alarm once only"));
00178 
00179         repeatAtLoginRadio = new QRadioButton(i18n("Repeat at lo&gin"), repeatGroup, "repeatAtLoginButton");
00180         repeatAtLoginRadio->setFixedSize(repeatAtLoginRadio->sizeHint());
00181         QWhatsThis::add(repeatAtLoginRadio,
00182               i18n("Repeat the alarm at every login until the specified time.\n"
00183                    "Note that it will also be repeated any time the alarm daemon is restarted."));
00184 
00185         recurRadio = new QRadioButton(i18n("Rec&ur"), repeatGroup);
00186         recurRadio->setFixedSize(recurRadio->sizeHint());
00187         QWhatsThis::add(recurRadio, i18n("Regularly repeat the alarm"));
00188 
00189         // Late display checkbox - default = allow late display
00190         lateCancel = new QCheckBox(i18n("Cancel &if late"), mainPage);
00191         lateCancel->setFixedSize(lateCancel->sizeHint());
00192         QWhatsThis::add(lateCancel,
00193               i18n("If checked, the alarm will be canceled if it cannot be triggered within 1 "
00194                    "minute of the specified time. Possible reasons for not triggering include your "
00195                    "being logged off, X not running, or the alarm daemon not running.\n\n"
00196                    "If unchecked, the alarm will be triggered at the first opportunity after "
00197                    "the specified time, regardless of how late it is."));
00198         grid->addWidget(lateCancel, 1, 1, Qt::AlignLeft);
00199         grid->setColStretch(1, 1);
00200 
00201         setButtonWhatsThis(Ok, i18n("Schedule the alarm at the specified time."));
00202 
00203         topLayout->activate();
00204 
00205         deferGroupHeight = deferGroup ? deferGroup->height() + spacingHint() : 0;
00206         QSize size = minimumSize();
00207         size.setHeight(size.height() - deferGroupHeight);
00208         basicSize = theApp()->readConfigWindowSize("EditDialog", size);
00209         resize(basicSize);
00210 
00211         // Set up initial values
00212         if (event)
00213         {
00214                 // Set the values to those for the specified event
00215 #ifdef SELECT_FONT
00216                 fontColour->setColour(event->colour());
00217                 fontColour->setFont(?);
00218 #endif
00219                 bgColourChoose->setColour(event->colour());     // set colour before setting alarm type buttons
00220                 timeWidget->setDateTime(event->mainDateTime(), event->anyTime());
00221 
00222                 QRadioButton* radio;
00223                 switch (event->type())
00224                 {
00225                         case KAlarmAlarm::FILE:
00226                                 radio = fileRadio;
00227                                 fileMessageEdit->setText(event->cleanText());
00228                                 break;
00229                         case KAlarmAlarm::COMMAND:
00230                                 radio = commandRadio;
00231                                 commandMessageEdit->setText(event->cleanText());
00232                                 break;
00233                         case KAlarmAlarm::MESSAGE:
00234                         default:
00235                                 radio = messageRadio;
00236                                 textMessageEdit->setText(event->cleanText());
00237                                 break;
00238                 }
00239                 actionGroup->setButton(actionGroup->id(radio));
00240 
00241                 if (event->recurs() != KAlarmEvent::NO_RECUR)
00242                 {
00243                         radio = recurRadio;
00244                         recurSetEndDate = false;
00245                 }
00246                 else if (event->repeatAtLogin())
00247                         radio = repeatAtLoginRadio;
00248                 else
00249                         radio = noRepeatRadio;
00250                 repeatGroup->setButton(repeatGroup->id(radio));
00251 
00252                 lateCancel->setChecked(event->lateCancel());
00253                 confirmAck->setChecked(event->confirmAck());
00254                 recurrenceEdit->set(*event);   // must be called after timeWidget is set up, to ensure correct date-only enabling
00255                 soundFile = event->audioFile();
00256                 sound->setChecked(event->beep() || !soundFile.isEmpty());
00257         }
00258         else
00259         {
00260                 // Set the values to their defaults
00261                 Settings* settings = theApp()->settings();
00262 #ifdef SELECT_FONT
00263                 fontColour->setColour(settings->defaultBgColour());
00264                 fontColour->setFont(settings->messageFont());
00265 #endif
00266                 bgColourChoose->setColour(settings->defaultBgColour());     // set colour before setting alarm type buttons
00267                 QDateTime defaultTime = QDateTime::currentDateTime().addSecs(60);
00268                 timeWidget->setDateTime(defaultTime, false);
00269                 actionGroup->setButton(actionGroup->id(messageRadio));
00270                 repeatGroup->setButton(repeatGroup->id(noRepeatRadio));
00271                 lateCancel->setChecked(settings->defaultLateCancel());
00272                 confirmAck->setChecked(settings->defaultConfirmAck());
00273                 recurrenceEdit->setDefaults(defaultTime);   // must be called after timeWidget is set up, to ensure correct date-only enabling
00274                 sound->setChecked(settings->defaultBeep());
00275         }
00276 
00277         size = basicSize;
00278         size.setHeight(size.height() + deferGroupHeight);
00279         resize(size);
00280 
00281         slotSoundToggled(sound->isChecked());
00282 }
00283 
00284 
00285 EditAlarmDlg::~EditAlarmDlg()
00286 {
00287 }
00288 
00289 /******************************************************************************
00290  * Set up the dialog controls common to display alarms.
00291  */
00292 void EditAlarmDlg::initDisplayAlarms(QWidget* parent)
00293 {
00294         displayAlarmsFrame = new QFrame(parent);
00295         displayAlarmsFrame->setFrameStyle(QFrame::NoFrame);
00296         QBoxLayout* frameLayout = new QVBoxLayout(displayAlarmsFrame, 0, spacingHint());
00297 
00298         // Text message edit box
00299         textMessageEdit = new QMultiLineEdit(displayAlarmsFrame);
00300         QSize tsize = textMessageEdit->sizeHint();
00301         tsize.setHeight(textMessageEdit->fontMetrics().lineSpacing()*13/4 + 2*textMessageEdit->frameWidth());
00302         textMessageEdit->setMinimumSize(tsize);
00303         textMessageEdit->setWordWrap(QMultiLineEdit::NoWrap);
00304         QWhatsThis::add(textMessageEdit, i18n("Enter the text of the alarm message. It may be multi-line."));
00305         frameLayout->addWidget(textMessageEdit);
00306 
00307         // File name edit box
00308         fileBox = new QHBox(displayAlarmsFrame);
00309         frameLayout->addWidget(fileBox);
00310         fileMessageEdit = new QLineEdit(fileBox);
00311         QWhatsThis::add(fileMessageEdit, i18n("Enter the name of a text file, or a URL, to display."));
00312 
00313         // File browse button
00314         fileBrowseButton = new QPushButton(fileBox);
00315         fileBrowseButton->setPixmap(SmallIcon("fileopen"));
00316         fileBrowseButton->setFixedSize(fileBrowseButton->sizeHint());
00317         connect(fileBrowseButton, SIGNAL(clicked()), SLOT(slotBrowseFile()));
00318         QWhatsThis::add(fileBrowseButton, i18n("Select a text file to display."));
00319 
00320         // Sound checkbox
00321         QBoxLayout* layout = new QHBoxLayout(frameLayout);
00322         QFrame* frame = new QFrame(displayAlarmsFrame);
00323         frame->setFrameStyle(QFrame::NoFrame);
00324         QHBoxLayout* soundLayout = new QHBoxLayout(frame, 0, spacingHint());
00325         sound = new QCheckBox(i18n("&Sound"), frame);
00326         sound->setFixedSize(sound->sizeHint());
00327         connect(sound, SIGNAL(toggled(bool)), SLOT(slotSoundToggled(bool)));
00328         QWhatsThis::add(sound,
00329               i18n("If checked, a sound will be played when the message is displayed. Click the "
00330                    "button on the right to select the sound."));
00331         soundLayout->addWidget(sound);
00332 
00333         // Sound picker button
00334         soundPicker = new QPushButton(frame);
00335         soundPicker->setPixmap(SmallIcon("playsound"));
00336         soundPicker->setFixedSize(soundPicker->sizeHint());
00337         soundPicker->setToggleButton(true);
00338         connect(soundPicker, SIGNAL(clicked()), SLOT(slotPickSound()));
00339         QWhatsThis::add(soundPicker,
00340               i18n("Select a sound file to play when the message is displayed. If no sound file is "
00341                    "selected, a beep will sound."));
00342         soundLayout->addWidget(soundPicker);
00343         soundLayout->addStretch();
00344         layout->addWidget(frame);
00345         layout->addStretch();
00346 
00347 #ifdef SELECT_FONT
00348         // Font and colour choice drop-down list
00349         fontButton = new QPushButton(i18n("Font && Co&lor..."), displayAlarmsFrame);
00350         fontColour = new FontColourChooser(displayAlarmsFrame, 0L, false, QStringList(), true, i18n("Font and background color"), false);
00351         size = fontColour->sizeHint();
00352         fontColour->setMinimumHeight(size.height() + 4);
00353         QWhatsThis::add(fontColour,
00354               i18n("Choose the font and background color for the alarm message."));
00355         layout->addWidget(fontColour);
00356 #endif
00357 
00358         // Colour choice drop-down list
00359         bgColourChoose = new ColourCombo(displayAlarmsFrame);
00360         QSize size = bgColourChoose->sizeHint();
00361         bgColourChoose->setMinimumHeight(size.height() + 4);
00362         QToolTip::add(bgColourChoose, i18n("Message color"));
00363         QWhatsThis::add(bgColourChoose,
00364               i18n("Choose the background color for the alarm message."));
00365         layout->addWidget(bgColourChoose);
00366 
00367         // Acknowledgement confirmation required - default = no confirmation
00368         confirmAck = new QCheckBox(i18n("Confirm ac&knowledgement"), displayAlarmsFrame);
00369         confirmAck->setFixedSize(confirmAck->sizeHint());
00370         QWhatsThis::add(confirmAck,
00371               i18n("Check to be prompted for confirmation when you acknowledge the alarm."));
00372         frameLayout->addWidget(confirmAck, 0, Qt::AlignLeft);
00373 
00374         filePadding = new QHBox(displayAlarmsFrame);
00375         frameLayout->addWidget(filePadding);
00376         frameLayout->setStretchFactor(filePadding, 1);
00377 }
00378 
00379 /******************************************************************************
00380  * Set up the command alarm dialog controls.
00381  */
00382 void EditAlarmDlg::initCommand(QWidget* parent)
00383 {
00384         commandFrame = new QFrame(parent);
00385         commandFrame->setFrameStyle(QFrame::NoFrame);
00386         QBoxLayout* layout = new QVBoxLayout(commandFrame);
00387 
00388         commandMessageEdit = new QLineEdit(commandFrame);
00389         QWhatsThis::add(commandMessageEdit, i18n("Enter a shell command to execute."));
00390         layout->addWidget(commandMessageEdit);
00391         layout->addStretch();
00392 }
00393 
00394 #ifdef KALARM_EMAIL
00395 /******************************************************************************
00396  * Set up the email alarm dialog controls.
00397  */
00398 void EditAlarmDlg::initEmail(QWidget* parent)
00399 {
00400         emailFrame = new QFrame(parent);
00401         emailFrame->setFrameStyle(QFrame::NoFrame);
00402         QBoxLayout* layout = new QVBoxLayout(emailFrame, 0, spacingHint());
00403         QGridLayout* grid = new QGridLayout(layout, 2, 2, spacingHint());
00404 
00405         // Email recipients
00406         QLabel* label = new QLabel(i18n("To:"), emailFrame);
00407         label->setFixedSize(label->sizeHint());
00408         grid->addWidget(label, 0, 0);
00409 
00410         emailToEdit = new QLineEdit(emailFrame);
00411         emailToEdit->setMinimumSize(emailToEdit->sizeHint());
00412         QWhatsThis::add(emailToEdit,
00413               i18n("Enter the addresses of the email recipients. Separate multiple addresses by "
00414                    "commas or semicolons."));
00415         grid->addWidget(emailToEdit, 0, 1);
00416 
00417         // Email subject
00418         label = new QLabel(i18n("Sub&ject:"), emailFrame);
00419         label->setFixedSize(label->sizeHint());
00420         grid->addWidget(label, 1, 0);
00421 
00422         emailSubjectEdit = new QLineEdit(emailFrame);
00423         emailSubjectEdit->setMinimumSize(emailSubjectEdit->sizeHint());
00424         label->setBuddy(emailSubjectEdit);
00425         QWhatsThis::add(emailSubjectEdit, i18n("Enter the email subject."));
00426         grid->addWidget(emailSubjectEdit, 1, 1);
00427 
00428         // Email body
00429         emailMessageEdit = new QMultiLineEdit(emailFrame);
00430         QSize size = emailMessageEdit->sizeHint();
00431         size.setHeight(emailMessageEdit->fontMetrics().lineSpacing()*13/4 + 2*emailMessageEdit->frameWidth());
00432         emailMessageEdit->setMinimumSize(size);
00433         QWhatsThis::add(emailMessageEdit, i18n("Enter the email message."));
00434         layout->addWidget(emailMessageEdit);
00435 
00436         // Email attachments
00437         QBoxLayout* attLayout = new QHBoxLayout(layout);
00438         label = new QLabel(i18n("Attachment&s:"), emailFrame);
00439         label->setFixedSize(label->sizeHint());
00440         attLayout->addWidget(label);
00441         attLayout->addStretch();
00442 
00443         emailAttachList = new QComboBox(emailFrame);
00444         emailAttachList->setMinimumSize(emailAttachList->sizeHint());
00445         label->setBuddy(emailAttachList);
00446         QWhatsThis::add(emailAttachList,
00447               i18n("Files to send as attachments to the email."));
00448         attLayout->addWidget(emailAttachList);
00449 
00450         QPushButton* button = new QPushButton(i18n("Add..."), emailFrame);
00451         connect(button, SIGNAL(clicked()), SLOT(slotAddAttachment()));
00452         QWhatsThis::add(button, i18n("Add an attachment to the email."));
00453         attLayout->addWidget(button);
00454 
00455         emailRemoveButton = new QPushButton(i18n("Remo&ve"), emailFrame);
00456         connect(emailRemoveButton, SIGNAL(clicked()), SLOT(slotRemoveAttachment()));
00457         QWhatsThis::add(emailRemoveButton, i18n("Remove the highlighted attachment from the email."));
00458         attLayout->addWidget(emailRemoveButton);
00459 
00460         // BCC email to sender
00461         emailBcc = new QCheckBox(i18n("Co&py email to self"), emailFrame);
00462         emailBcc->setFixedSize(emailBcc->sizeHint());
00463         QWhatsThis::add(emailBcc,
00464               i18n("If checked, the email will be blind copied to you."));
00465         layout->addWidget(emailBcc);
00466 }
00467 #endif
00468 
00469 
00470 /******************************************************************************
00471  * Get the currently entered message data.
00472  * The data is returned in the supplied Event instance.
00473  */
00474 void EditAlarmDlg::getEvent(KAlarmEvent& event)
00475 {
00476         event.set(alarmDateTime, alarmMessage, bgColourChoose->color(), getAlarmType(), getAlarmFlags());
00477         event.setAudioFile(sound->isChecked() ? soundFile : QString());
00478         if (recurRadio->isOn())
00479         {
00480                 recurrenceEdit->updateEvent(event);
00481                 if (deferDateTime.isValid()  &&  deferDateTime < alarmDateTime)
00482                         event.defer(deferDateTime);
00483         }
00484 }
00485 
00486 /******************************************************************************
00487  * Get the currently specified alarm flag bits.
00488  */
00489 int EditAlarmDlg::getAlarmFlags() const
00490 {
00491         bool displayAlarm = messageRadio->isOn() || fileRadio->isOn();
00492         return (displayAlarm && sound->isChecked() && soundFile.isEmpty() ? KAlarmEvent::BEEP : 0)
00493              | (lateCancel->isChecked()                                   ? KAlarmEvent::LATE_CANCEL : 0)
00494              | (displayAlarm && confirmAck->isChecked()                   ? KAlarmEvent::CONFIRM_ACK : 0)
00495              | (repeatAtLoginRadio->isChecked()                           ? KAlarmEvent::REPEAT_AT_LOGIN : 0)
00496              | (alarmAnyTime                                              ? KAlarmEvent::ANY_TIME : 0);
00497 }
00498 
00499 /******************************************************************************
00500  * Get the currently selected alarm type.
00501  */
00502 KAlarmAlarm::Type EditAlarmDlg::getAlarmType() const
00503 {
00504         return fileRadio->isOn()    ? KAlarmAlarm::FILE
00505              : commandRadio->isOn() ? KAlarmAlarm::COMMAND
00506              :                        KAlarmAlarm::MESSAGE;
00507 }
00508 
00509 /******************************************************************************
00510 *  Return the alarm's start date and time.
00511 */
00512 QDateTime EditAlarmDlg::getDateTime(bool* anyTime)
00513 {
00514         timeWidget->getDateTime(alarmDateTime, alarmAnyTime);
00515         if (anyTime)
00516                 *anyTime = alarmAnyTime;
00517         return alarmDateTime;
00518 }
00519 
00520 /******************************************************************************
00521 *  Called when the dialog's size has changed.
00522 *  Records the new size (adjusted to ignore the optional height of the deferred
00523 *  time edit widget) in the config file.
00524 */
00525 void EditAlarmDlg::resizeEvent(QResizeEvent* re)
00526 {
00527         if (isVisible())
00528         {
00529                 basicSize = re->size();
00530                 basicSize.setHeight(basicSize.height() - deferGroupHeight);
00531                 theApp()->writeConfigWindowSize("EditDialog", basicSize);
00532         }
00533         KDialog::resizeEvent(re);
00534 }
00535 
00536 /******************************************************************************
00537 *  Called when the OK button is clicked.
00538 *  Set up the new alarm.
00539 */
00540 void EditAlarmDlg::slotOk()
00541 {
00542         QWidget* errWidget = timeWidget->getDateTime(alarmDateTime, alarmAnyTime, false);
00543         if (errWidget)
00544         {
00545                 showPage(mainPageIndex);
00546                 errWidget->setFocus();
00547                 timeWidget->getDateTime(alarmDateTime, alarmAnyTime);   // display the error message now
00548         }
00549         else
00550         {
00551                 bool noTime;
00552                 errWidget = recurrenceEdit->checkData(alarmDateTime, noTime);
00553                 if (errWidget)
00554                 {
00555                         showPage(recurPageIndex);
00556                         errWidget->setFocus();
00557                         KMessageBox::sorry(this, (noTime ? i18n("End date is earlier than start date")
00558                                                          : i18n("End date/time is earlier than start date/time")));
00559                 }
00560                 else if (checkText(alarmMessage))
00561                         accept();
00562         }
00563 }
00564 
00565 /******************************************************************************
00566 *  Called when the Try button is clicked.
00567 *  Display the alarm immediately for the user to check its configuration.
00568 */
00569 void EditAlarmDlg::slotTry()
00570 {
00571         QString text;
00572         if (checkText(text))
00573         {
00574 #ifdef KALARM_EMAIL
00575                 if (emailRadio->isOn())
00576                 {
00577                         if (!checkEmailAddresses()
00578                         ||  KMessageBox::warningContinueCancel(this, i18n("Do you really want to send the email now to the specified recipient(s)?"),
00579                                                                i18n("Confirm Email"), i18n("&Send")) != KMessageBox::Continue)
00580                                 return;
00581                 }
00582 #endif
00583                 KAlarmEvent event;
00584                 event.set(QDateTime(), text, bgColourChoose->color(), getAlarmType(), getAlarmFlags());
00585                 event.setAudioFile(sound->isChecked() ? soundFile : QString());
00586                 if (theApp()->execAlarm(event, event.firstAlarm(), false, false))
00587                 {
00588                         if (commandRadio->isOn())
00589                                 KMessageBox::information(this, i18n("Command executed:\n%1").arg(text));
00590 #ifdef KALARM_EMAIL
00591                         else if (emailRadio->isOn())
00592                                 KMessageBox::information(this, i18n("Email sent to:\n%1").arg(emailAddresses.join("\n")));
00593 #endif
00594                 }
00595         }
00596 }
00597 
00598 /******************************************************************************
00599 *  Called when the Cancel button is clicked.
00600 */
00601 void EditAlarmDlg::slotCancel()
00602 {
00603         reject();
00604 }
00605 
00606 /******************************************************************************
00607  * Called when the Change deferral button is clicked.
00608  */
00609 void EditAlarmDlg::slotEditDeferral()
00610 {
00611         bool anyTime;
00612         QDateTime start;
00613         if (!timeWidget->getDateTime(start, anyTime))
00614         {
00615                 bool deferred = deferDateTime.isValid();
00616                 DeferAlarmDlg* deferDlg = new DeferAlarmDlg(i18n("Defer Alarm"), (deferred ? deferDateTime : QDateTime::currentDateTime().addSecs(60)),
00617                                                             start, deferred, this, "deferDlg");
00618                 if (deferDlg->exec() == QDialog::Accepted)
00619                 {
00620                         deferDateTime = deferDlg->getDateTime();
00621                         deferTimeLabel->setText(deferDateTime.isValid() ? KGlobal::locale()->formatDateTime(deferDateTime) : QString::null);
00622                 }
00623         }
00624 }
00625 
00626 /******************************************************************************
00627 *  Called when the recurrence type selection changes.
00628 *  Enables/disables date-only alarms as appropriate.
00629 */
00630 void EditAlarmDlg::slotRecurTypeChange(int repeatType)
00631 {
00632         bool recurs = recurRadio->isOn();
00633         timeWidget->enableAnyTime(!recurs || repeatType != RecurrenceEdit::SUBDAILY);
00634         if (deferGroup)
00635                 deferGroup->setEnabled(recurs);
00636 }
00637 
00638 /******************************************************************************
00639 *  Called when the main page is shown.
00640 *  Sets the focus widget to the first edit field.
00641 */
00642 void EditAlarmDlg::slotShowMainPage()
00643 {
00644         slotAlarmTypeClicked(-1);
00645 }
00646 
00647 /******************************************************************************
00648 *  Called when the recurrence edit page is shown.
00649 *  The first time, for a new alarm, the recurrence end date is set according to
00650 *  the alarm start time.
00651 */
00652 void EditAlarmDlg::slotShowRecurrenceEdit()
00653 {
00654         recurPageIndex = activePageIndex();
00655         timeWidget->getDateTime(alarmDateTime, alarmAnyTime, false);
00656         if (recurSetEndDate)
00657         {
00658                 QDateTime now = QDateTime::currentDateTime();
00659                 recurrenceEdit->setEndDate(alarmDateTime >= now ? alarmDateTime.date() : now.date());
00660                 recurSetEndDate = false;
00661         }
00662         recurrenceEdit->setStartDate(alarmDateTime.date());
00663 }
00664 
00665 #ifdef KALARM_EMAIL
00666 /******************************************************************************
00667 *  Convert the email addresses to a list, and validate them.
00668 */
00669 bool EditAlarmDlg::checkEmailAddresses()
00670 {
00671         if (emailRadio->isOn())
00672         {
00673                 QString addrs = emailToEdit->text();
00674                 if (addrs.isEmpty())
00675                         emailAddresses.clear();
00676                 else
00677                 {
00678                         QString bad = KAMail::convertEmailAddresses(addrs, emailAddresses);
00679                         if (!bad.isEmpty())
00680                         {
00681                                 emailToEdit->setFocus();
00682                                 KMessageBox::error(this, i18n("Invalid email address:\n%1").arg(bad));
00683                                 KMessageBox::error(this, i18n("Invalid email attachment:\n%1").arg(att));
00684                                 return false;
00685                         }
00686                 }
00687                 if (emailAddresses.isEmpty())
00688                 {
00689                         emailToEdit->setFocus();
00690                         KMessageBox::error(this, i18n("No email address specified"));
00691                         return false;
00692                 }
00693         }
00694         return true;
00695 }
00696 #endif
00697 
00698 /******************************************************************************
00699 *  Called when one of the message type radio buttons is clicked.
00700 */
00701 void EditAlarmDlg::slotAlarmTypeClicked(int)
00702 {
00703         if (messageRadio->isOn())
00704         {
00705                 fileBox->hide();
00706                 filePadding->hide();
00707                 textMessageEdit->show();
00708                 setButtonWhatsThis(Try, i18n("Display the alarm message now"));
00709                 alarmTypeStack->raiseWidget(displayAlarmsFrame);
00710                 textMessageEdit->setFocus();
00711         }
00712         else if (fileRadio->isOn())
00713         {
00714                 textMessageEdit->hide();
00715                 fileBox->show();
00716                 filePadding->show();
00717                 setButtonWhatsThis(Try, i18n("Display the text file now"));
00718                 alarmTypeStack->raiseWidget(displayAlarmsFrame);
00719                 fileMessageEdit->setFocus();
00720         }
00721         else if (commandRadio->isOn())
00722         {
00723                 setButtonWhatsThis(Try, i18n("Execute the specified command now"));
00724                 alarmTypeStack->raiseWidget(commandFrame);
00725                 commandMessageEdit->setFocus();
00726         }
00727 #ifdef KALARM_EMAIL
00728         else if (emailRadio->isOn())
00729         {
00730                 setButtonWhatsThis(Try, i18n("Send the email to the specified addressees now"));
00731                 alarmTypeStack->raiseWidget(emailFrame);
00732                 emailToEdit->setFocus();
00733         }
00734 #endif
00735 }
00736 
00737 /******************************************************************************
00738 *  Called when one of the repetition radio buttons is clicked.
00739 */
00740 void EditAlarmDlg::slotRepeatClicked(int)
00741 {
00742         bool on = recurRadio->isOn();
00743         if (on)
00744                 recurTabStack->raiseWidget(recurrenceEdit);
00745         else
00746                 recurTabStack->raiseWidget(recurDisabled);
00747         recurrenceEdit->setEnabled(on);
00748 }
00749 
00750 /******************************************************************************
00751 *  Called when the browse button is pressed to select a file to display.
00752 */
00753 void EditAlarmDlg::slotBrowseFile()
00754 {
00755         if (fileDefaultDir.isEmpty())
00756                 fileDefaultDir = QDir::homeDirPath();
00757         KURL url = KFileDialog::getOpenURL(fileDefaultDir, QString::null, this, i18n("Choose Text File to Display"));
00758         if (!url.isEmpty())
00759         {
00760                 alarmMessage = url.prettyURL();
00761                 fileMessageEdit->setText(alarmMessage);
00762                 fileDefaultDir = url.path();
00763         }
00764 }
00765 
00766 /******************************************************************************
00767  * Called when the sound checkbox is toggled.
00768  */
00769 void EditAlarmDlg::slotSoundToggled(bool on)
00770 {
00771         soundPicker->setEnabled(on);
00772         setSoundPicker();
00773 }
00774 
00775 /******************************************************************************
00776  * Called when the sound picker button is clicked.
00777  */
00778 void EditAlarmDlg::slotPickSound()
00779 {
00780         if (soundPicker->isOn())
00781         {
00782                 if (soundDefaultDir.isEmpty())
00783                         soundDefaultDir = KGlobal::dirs()->findResourceDir("sound", "KDE_Notify.wav");
00784                 KURL url = KFileDialog::getOpenURL(soundDefaultDir, i18n("*.wav|Wav Files"), 0, i18n("Choose a Sound File"));
00785                 if (!url.isEmpty())
00786                 {
00787                         soundFile = url.prettyURL();
00788                         soundDefaultDir = url.path();
00789                         setSoundPicker();
00790                 }
00791                 else if (soundFile.isEmpty())
00792                         soundPicker->setOn(false);
00793         }
00794         else
00795         {
00796                 soundFile = "";
00797                 setSoundPicker();
00798         }
00799 }
00800 
00801 /******************************************************************************
00802  * Set the sound picker button according to whether a sound file is selected.
00803  */
00804 void EditAlarmDlg::setSoundPicker()
00805 {
00806         QToolTip::remove(soundPicker);
00807         if (soundPicker->isEnabled())
00808         {
00809                 bool beep = soundFile.isEmpty();
00810                 if (beep)
00811                         QToolTip::add(soundPicker, i18n("Beep"));
00812                 else
00813                         QToolTip::add(soundPicker, i18n("Play '%1'").arg(soundFile));
00814                 soundPicker->setOn(!beep);
00815         }
00816 }
00817 
00818 #ifdef KALARM_EMAIL
00819 /******************************************************************************
00820  * Select a file to attach to the email.
00821  */
00822 void EditAlarmDlg::slotAddAttachment()
00823 {
00824         if (attachDefaultDir.isEmpty())
00825                 attachDefaultDir = QDir::homeDirPath();
00826         KURL url = KFileDialog::getOpenURL(attachDefaultDir, QString::null, this, i18n("Choose File to Attach"));
00827         if (!url.isEmpty())
00828         {
00829                 emailAttachList->insertItem(url.prettyURL());
00830                 attachDefaultDir = url.path();
00831                 emailRemoveButton->setEnabled(true);
00832         }
00833 }
00834 #endif
00835 
00836 /******************************************************************************
00837 *  Clean up the alarm text, and if it's a file, check whether it's valid.
00838 */
00839 bool EditAlarmDlg::checkText(QString& result)
00840 {
00841         if (messageRadio->isOn())
00842                 result = textMessageEdit->text();
00843         else if (commandRadio->isOn())
00844         {
00845                 result = commandMessageEdit->text();
00846                 result.stripWhiteSpace();
00847         }
00848         else if (fileRadio->isOn())
00849         {
00850                 QString alarmtext = fileMessageEdit->text();
00851                 // Convert any relative file path to absolute
00852                 // (using home directory as the default)
00853                 enum Err { NONE = 0, NONEXISTENT, DIRECTORY, UNREADABLE, NOT_TEXT, HTML };
00854                 Err err = NONE;
00855                 KURL url;
00856                 int i = alarmtext.find(QString::fromLatin1("/"));
00857                 if (i > 0  &&  alarmtext[i - 1] == ':')
00858                 {
00859                         url = alarmtext;
00860                         url.cleanPath();
00861                         alarmtext = url.prettyURL();
00862                         KIO::UDSEntry uds;
00863                         if (!KIO::NetAccess::stat(url, uds))
00864                                 err = NONEXISTENT;
00865                         else
00866                         {
00867                                 KFileItem fi(uds, url);
00868                                 if (fi.isDir())             err = DIRECTORY;
00869                                 else if (!fi.isReadable())  err = UNREADABLE;
00870                         }
00871                 }
00872                 else
00873                 {
00874                         // It's a local file - convert to absolute path & check validity
00875                         if (alarmtext.isEmpty())
00876                                 err = DIRECTORY;    // blank file name - need to get its path, for the error message
00877                         QFileInfo info(alarmtext);
00878                         QDir::setCurrent(QDir::homeDirPath());
00879                         alarmtext = info.absFilePath();
00880                         url.setPath(alarmtext);
00881                         alarmtext = QString::fromLatin1("file:") + alarmtext;
00882                         if (!err)
00883                         {
00884                                 if      (info.isDir())        err = DIRECTORY;
00885                                 else if (!info.exists())      err = NONEXISTENT;
00886                                 else if (!info.isReadable())  err = UNREADABLE;
00887                         }
00888                 }
00889                 if (!err)
00890                 {
00891                         switch (KAlarmApp::isTextFile(url))
00892                         {
00893                                 case 1:   break;
00894                                 case 2:   err = HTML;  break;
00895                                 default:  err = NOT_TEXT;  break;
00896                         }
00897                 }
00898                 if (err)
00899                 {
00900                         fileMessageEdit->setFocus();
00901                         QString errmsg;
00902                         switch (err)
00903                         {
00904                                 case NONEXISTENT:  errmsg = i18n("%1\nnot found");  break;
00905                                 case DIRECTORY:    errmsg = i18n("%1\nis a directory");  break;
00906                                 case UNREADABLE:   errmsg = i18n("%1\nis not readable");  break;
00907                                 case NOT_TEXT:     errmsg = i18n("%1\nappears not to be a text file");  break;
00908                                 case HTML:         errmsg = i18n("%1\nis an html/xml file");  break;
00909                                 case NONE:
00910                                 default:
00911                                         break;
00912                         }
00913                         if (KMessageBox::warningContinueCancel(this, errmsg.arg(alarmtext), QString::null, KStdGuiItem::cont().text())    // explicit button text is for KDE2 compatibility
00914                             == KMessageBox::Cancel)
00915                                 return false;
00916                 }
00917                 result = alarmtext;
00918         }
00919         return true;
00920 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sat Oct 18 02:47:26 2003 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001