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

kalarm

editdlgtypes.cpp

Go to the documentation of this file.
00001 /*
00002 *  editdlgtypes.cpp  -  dialogs to create or edit alarm or alarm template types
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 #include "editdlgtypes.moc"
00023 #include "editdlgprivate.h"
00024 
00025 #include "buttongroup.h"
00026 #include "checkbox.h"
00027 #include "colourbutton.h"
00028 #include "emailidcombo.h"
00029 #include "fontcolourbutton.h"
00030 #include "functions.h"
00031 #include "kalarmapp.h"
00032 #include "kamail.h"
00033 #include "latecancel.h"
00034 #include "lineedit.h"
00035 #include "mainwindow.h"
00036 #include "pickfileradio.h"
00037 #include "preferences.h"
00038 #include "radiobutton.h"
00039 #include "reminder.h"
00040 #include "shellprocess.h"
00041 #include "soundpicker.h"
00042 #include "specialactions.h"
00043 #include "templatepickdlg.h"
00044 #include "timespinbox.h"
00045 
00046 #include <QLabel>
00047 #include <QDir>
00048 #include <QStyle>
00049 #include <QGroupBox>
00050 #include <QGridLayout>
00051 #include <QHBoxLayout>
00052 #include <QVBoxLayout>
00053 #include <QDragEnterEvent>
00054 
00055 #include <klocale.h>
00056 #include <kiconloader.h>
00057 #include <kio/netaccess.h>
00058 #include <kfileitem.h>
00059 #include <kmessagebox.h>
00060 #include <khbox.h>
00061 #include <kabc/addresseedialog.h>
00062 #include <kdebug.h>
00063 
00064 #include <kcal/icaldrag.h>
00065 
00066 using namespace KCal;
00067 
00068 enum { tTEXT, tFILE, tCOMMAND };  // order of mTypeCombo items
00069 
00070 
00071 /*=============================================================================
00072 = Class PickLogFileRadio
00073 =============================================================================*/
00074 class PickLogFileRadio : public PickFileRadio
00075 {
00076     public:
00077     PickLogFileRadio(QPushButton* b, LineEdit* e, const QString& text, ButtonGroup* group, QWidget* parent)
00078         : PickFileRadio(b, e, text, group, parent) { }
00079     virtual QString pickFile()    // called when browse button is pressed to select a log file
00080     {
00081         return KAlarm::browseFile(i18nc("@title:window", "Choose Log File"), mDefaultDir, fileEdit()->text(), QString(),
00082                                   KFile::LocalOnly, parentWidget());
00083     }
00084     private:
00085     QString mDefaultDir;   // default directory for log file browse button
00086 };
00087 
00088 
00089 /*=============================================================================
00090 = Class EditDisplayAlarmDlg
00091 = Dialog to edit display alarms.
00092 =============================================================================*/
00093 
00094 QString EditDisplayAlarmDlg::i18n_chk_ConfirmAck()    { return i18nc("@option:check", "Confirm acknowledgment"); }
00095 
00096 
00097 /******************************************************************************
00098 * Constructor.
00099 * Parameters:
00100 *   Template = true to edit/create an alarm template
00101 *            = false to edit/create an alarm.
00102 *   event   != to initialise the dialog to show the specified event's data.
00103 */
00104 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, bool newAlarm, QWidget* parent, GetResourceType getResource)
00105     : EditAlarmDlg(Template, KAEvent::MESSAGE, parent, getResource),
00106       mSpecialActionsButton(0),
00107       mReminderDeferral(false),
00108       mReminderArchived(false)
00109 {
00110     kDebug() << "New";
00111     init(0, newAlarm);
00112 }
00113 
00114 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
00115                                          GetResourceType getResource, bool readOnly)
00116     : EditAlarmDlg(Template, event, parent, getResource, readOnly),
00117       mSpecialActionsButton(0),
00118       mReminderDeferral(false),
00119       mReminderArchived(false)
00120 {
00121     kDebug() << "Event.id()";
00122     init(event, newAlarm);
00123 }
00124 
00125 /******************************************************************************
00126 * Return the window caption.
00127 */
00128 QString EditDisplayAlarmDlg::type_caption(bool newAlarm) const
00129 {
00130     return isTemplate() ? (newAlarm ? i18nc("@title:window", "New Display Alarm Template") : i18nc("@title:window", "Edit Display Alarm Template"))
00131                         : (newAlarm ? i18nc("@title:window", "New Display Alarm") : i18nc("@title:window", "Edit Display Alarm"));
00132 }
00133 
00134 /******************************************************************************
00135 * Set up the dialog controls common to display alarms.
00136 */
00137 void EditDisplayAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
00138 {
00139     // Display type combo box
00140     KHBox* box = new KHBox(parent);    // to group widgets for QWhatsThis text
00141     box->setMargin(0);
00142     box->setSpacing(KDialog::spacingHint());
00143     QLabel* label = new QLabel(i18nc("@label:listbox", "Display type:"), box);
00144     label->setFixedSize(label->sizeHint());
00145     mTypeCombo = new ComboBox(box);
00146     QString textItem    = i18nc("@item:inlistbox", "Text message");
00147     QString fileItem    = i18nc("@item:inlistbox", "File contents");
00148     QString commandItem = i18nc("@item:inlistbox", "Command output");
00149     mTypeCombo->addItem(textItem);     // index = tTEXT
00150     mTypeCombo->addItem(fileItem);     // index = tFILE
00151     mTypeCombo->addItem(commandItem);  // index = tCOMMAND
00152     mTypeCombo->setFixedSize(mTypeCombo->sizeHint());
00153     mTypeCombo->setCurrentIndex(-1);    // ensure slotAlarmTypeChanged() is called when index is set
00154     connect(mTypeCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotAlarmTypeChanged(int)));
00155     label->setBuddy(mTypeCombo);
00156     box->setWhatsThis(i18nc("@info:whatsthis", "<para>Select what the alarm should display:"
00157           "<list><item><interface>%1</interface>: the alarm will display the text message you type in.</item>"
00158           "<item><interface>%2</interface>: the alarm will display the contents of a text or image file.</item>"
00159           "<item><interface>%3</interface>: the alarm will display the output from a command.</item></list></para>",
00160           textItem, fileItem, commandItem));
00161     box->setStretchFactor(new QWidget(box), 1);    // left adjust the control
00162     frameLayout->addWidget(box);
00163 
00164     // Text message edit box
00165     mTextMessageEdit = new TextEdit(parent);
00166     mTextMessageEdit->setLineWrapMode(KTextEdit::NoWrap);
00167     mTextMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the text of the alarm message. It may be multi-line."));
00168     frameLayout->addWidget(mTextMessageEdit);
00169 
00170     // File name edit box
00171     mFileBox = new KHBox(parent);
00172     mFileBox->setMargin(0);
00173     frameLayout->addWidget(mFileBox);
00174     mFileMessageEdit = new LineEdit(LineEdit::Url, mFileBox);
00175     mFileMessageEdit->setAcceptDrops(true);
00176     mFileMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or URL of a text or image file to display."));
00177 
00178     // File browse button
00179     mFileBrowseButton = new QPushButton(mFileBox);
00180     mFileBrowseButton->setIcon(SmallIcon("document-open"));
00181     int size = mFileBrowseButton->sizeHint().height();
00182     mFileBrowseButton->setFixedSize(size, size);
00183     mFileBrowseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
00184     mFileBrowseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a text or image file to display."));
00185     connect(mFileBrowseButton, SIGNAL(clicked()), SLOT(slotPickFile()));
00186 
00187     // Command type checkbox and edit box
00188     mCmdEdit = new CommandEdit(parent);
00189     frameLayout->addWidget(mCmdEdit);
00190     connect(mCmdEdit, SIGNAL(scriptToggled(bool)), SLOT(slotCmdScriptToggled(bool)));
00191 
00192     // Background colour for file display alarms
00193     QHBoxLayout* hlayout = new QHBoxLayout();
00194     hlayout->setMargin(0);
00195     frameLayout->addLayout(hlayout);
00196     mBgColourBox = new KHBox(parent);
00197     mBgColourBox->setMargin(0);
00198     mBgColourBox->setSpacing(KDialog::spacingHint());
00199     hlayout->addWidget(mBgColourBox);
00200     hlayout->addStretch();
00201     label = new QLabel(i18nc("@label:listbox", "Background color:"), mBgColourBox);
00202     mBgColourButton = new ColourButton(mBgColourBox);
00203     label->setBuddy(mBgColourButton);
00204     mBgColourBox->setWhatsThis(i18nc("@info:whatsthis", "Select the alarm message background color"));
00205 
00206     // Sound checkbox and file selector
00207     mSpecialActionsLayout1 = new QHBoxLayout();
00208     mSpecialActionsLayout1->setMargin(0);
00209     frameLayout->addLayout(mSpecialActionsLayout1);
00210     mSoundPicker = new SoundPicker(parent);
00211     mSoundPicker->setFixedSize(mSoundPicker->sizeHint());
00212     mSpecialActionsLayout1->addWidget(mSoundPicker);
00213     mSpecialActionsLayout1->addSpacing(2*spacingHint());
00214     mSpecialActionsLayout1->addStretch();
00215 
00216     // Font and colour choice button and sample text
00217     mFontColourButton = new FontColourButton(parent);
00218     mFontColourButton->setMaximumHeight(mFontColourButton->sizeHint().height() * 3/2);
00219     mSpecialActionsLayout1->addWidget(mFontColourButton);
00220     connect(mFontColourButton, SIGNAL(selected(const QColor&, const QColor&)), SLOT(setColours(const QColor&, const QColor&)));
00221 
00222     if (ShellProcess::authorised())    // don't display if shell commands not allowed (e.g. kiosk mode)
00223     {
00224         // Special actions button
00225         mSpecialActionsLayout2 = new QHBoxLayout();
00226         mSpecialActionsLayout2->setMargin(0);
00227         frameLayout->addLayout(mSpecialActionsLayout2);
00228         mSpecialActionsLayout2->addStretch();
00229         mSpecialActionsButton = new SpecialActionsButton(false, parent);
00230         mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
00231         mSpecialActionsLayout2->addWidget(mSpecialActionsButton);
00232         mSpecialActionsInLayout1 = false;
00233     }
00234 
00235     // Top-adjust the controls
00236     mFilePadding = new KHBox(parent);
00237     mFilePadding->setMargin(0);
00238     frameLayout->addWidget(mFilePadding);
00239     frameLayout->setStretchFactor(mFilePadding, 1);
00240 }
00241 
00242 /******************************************************************************
00243 * Create a reminder control.
00244 */
00245 Reminder* EditDisplayAlarmDlg::createReminder(QWidget* parent)
00246 {
00247     static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of the main alarm to display a reminder alarm.");
00248     return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of the main alarm time(s)."),
00249                         i18nc("@info:whatsthis", "<para>Enter how long in advance of the main alarm to display a reminder alarm.</para><para>%1</para>", TimeSpinBox::shiftWhatsThis()),
00250                         true, true, parent);
00251 }
00252 
00253 /******************************************************************************
00254 * Create an "acknowledgement confirmation required" checkbox.
00255 */
00256 CheckBox* EditDisplayAlarmDlg::createConfirmAckCheckbox(QWidget* parent)
00257 {
00258     CheckBox* confirmAck = new CheckBox(i18n_chk_ConfirmAck(), parent);
00259     confirmAck->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation when you acknowledge the alarm."));
00260     return confirmAck;
00261 }
00262 
00263 /******************************************************************************
00264 * Initialise the dialog controls from the specified event.
00265 */
00266 void EditDisplayAlarmDlg::type_initValues(const KAEvent* event)
00267 {
00268     mKMailSerialNumber = 0;
00269     lateCancel()->showAutoClose(true);
00270     if (event)
00271     {
00272         if (mAlarmType == KAEvent::MESSAGE  &&  event->kmailSerialNumber()
00273         &&  AlarmText::checkIfEmail(event->cleanText()))
00274             mKMailSerialNumber = event->kmailSerialNumber();
00275         lateCancel()->setAutoClose(event->autoClose());
00276         if (event->defaultFont())
00277             mFontColourButton->setDefaultFont();
00278         else
00279             mFontColourButton->setFont(event->font());
00280         mFontColourButton->setBgColour(event->bgColour());
00281         mFontColourButton->setFgColour(event->fgColour());
00282         mBgColourButton->setColour(event->bgColour());
00283         setColours(event->fgColour(), event->bgColour());
00284         mConfirmAck->setChecked(event->confirmAck());
00285         bool recurs = event->recurs();
00286         int reminderMins = event->reminder();
00287         if (!reminderMins  &&  event->reminderDeferral()  &&  !recurs)
00288         {
00289             reminderMins = event->reminderDeferral();
00290             mReminderDeferral = true;
00291         }
00292         if (!reminderMins  &&  event->reminderArchived()  &&  recurs)
00293         {
00294             reminderMins = event->reminderArchived();
00295             mReminderArchived = true;
00296         }
00297         reminder()->setMinutes(reminderMins, dateOnly());
00298         reminder()->setOnceOnly(event->reminderOnceOnly());
00299         reminder()->enableOnceOnly(recurs);
00300         if (mSpecialActionsButton)
00301             mSpecialActionsButton->setActions(event->preAction(), event->postAction(), event->cancelOnPreActionError());
00302         Preferences::SoundType soundType = event->speak()                ? Preferences::Sound_Speak
00303                                          : event->beep()                 ? Preferences::Sound_Beep
00304                                          : !event->audioFile().isEmpty() ? Preferences::Sound_File
00305                                          :                                 Preferences::Sound_None;
00306         mSoundPicker->set(soundType, event->audioFile(), event->soundVolume(),
00307                           event->fadeVolume(), event->fadeSeconds(), event->repeatSound());
00308     }
00309     else
00310     {
00311         // Set the values to their defaults
00312         if (!ShellProcess::authorised())
00313         {
00314             // Don't allow shell commands in kiosk mode
00315             if (mSpecialActionsButton)
00316                 mSpecialActionsButton->setEnabled(false);
00317         }
00318         lateCancel()->setAutoClose(Preferences::defaultAutoClose());
00319         mTypeCombo->setCurrentIndex(0);
00320         mFontColourButton->setDefaultFont();
00321         mFontColourButton->setBgColour(Preferences::defaultBgColour());
00322         mFontColourButton->setFgColour(Preferences::defaultFgColour());
00323         mBgColourButton->setColour(Preferences::defaultBgColour());
00324         setColours(Preferences::defaultFgColour(), Preferences::defaultBgColour());
00325         mConfirmAck->setChecked(Preferences::defaultConfirmAck());
00326         reminder()->setMinutes(0, false);
00327         reminder()->enableOnceOnly(isTimedRecurrence());   // must be called after mRecurrenceEdit is set up
00328         if (mSpecialActionsButton)
00329             mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(), Preferences::defaultCancelOnPreActionError());
00330         mSoundPicker->set(Preferences::defaultSoundType(), Preferences::defaultSoundFile(),
00331                           Preferences::defaultSoundVolume(), -1, 0, Preferences::defaultSoundRepeat());
00332     }
00333 }
00334 
00335 /******************************************************************************
00336 * Called when the font/color button has been clicked.
00337 * Set the colors in the message text entry control.
00338 */
00339 void EditDisplayAlarmDlg::setColours(const QColor& fgColour, const QColor& bgColour)
00340 {
00341     QPalette pal = mTextMessageEdit->palette();
00342     pal.setColor(mTextMessageEdit->backgroundRole(), bgColour);
00343     pal.setColor(QPalette::Text, fgColour);
00344     mTextMessageEdit->setPalette(pal);
00345     pal = mTextMessageEdit->viewport()->palette();
00346     pal.setColor(mTextMessageEdit->viewport()->backgroundRole(), bgColour);
00347     pal.setColor(QPalette::Text, fgColour);
00348     mTextMessageEdit->viewport()->setPalette(pal);
00349     // Change the color of existing text
00350     QTextCursor cursor = mTextMessageEdit->textCursor();
00351     mTextMessageEdit->selectAll();
00352     mTextMessageEdit->setTextColor(fgColour);
00353     mTextMessageEdit->setTextCursor(cursor);
00354 }
00355 
00356 /******************************************************************************
00357 * Set the dialog's action and the action's text.
00358 */
00359 void EditDisplayAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText)
00360 {
00361     QString text = alarmText.displayText();
00362     switch (action)
00363     {
00364         case KAEvent::MESSAGE:
00365             mTypeCombo->setCurrentIndex(tTEXT);
00366             mTextMessageEdit->setPlainText(text);
00367             mKMailSerialNumber = alarmText.isEmail() ? alarmText.kmailSerialNumber() : 0;
00368             break;
00369         case KAEvent::FILE:
00370             mTypeCombo->setCurrentIndex(tFILE);
00371             mFileMessageEdit->setText(text);
00372             break;
00373         case KAEvent::COMMAND:
00374             mTypeCombo->setCurrentIndex(tCOMMAND);
00375             mCmdEdit->setText(alarmText);
00376             break;
00377         default:
00378             Q_ASSERT(0);
00379             break;
00380     }
00381 }
00382 
00383 /******************************************************************************
00384 * Set the read-only status of all non-template controls.
00385 */
00386 void EditDisplayAlarmDlg::setReadOnly(bool readOnly)
00387 {
00388     mTypeCombo->setReadOnly(readOnly);
00389     mTextMessageEdit->setReadOnly(readOnly);
00390     mFileMessageEdit->setReadOnly(readOnly);
00391     mCmdEdit->setReadOnly(readOnly);
00392     mFontColourButton->setReadOnly(readOnly);
00393     mBgColourButton->setReadOnly(readOnly);
00394     mSoundPicker->setReadOnly(readOnly);
00395     mConfirmAck->setReadOnly(readOnly);
00396     reminder()->setReadOnly(readOnly);
00397     if (mSpecialActionsButton)
00398         mSpecialActionsButton->setReadOnly(readOnly);
00399     if (readOnly)
00400         mFileBrowseButton->hide();
00401     else
00402         mFileBrowseButton->show();
00403     EditAlarmDlg::setReadOnly(readOnly);
00404 }
00405 
00406 /******************************************************************************
00407 * Save the state of all controls.
00408 */
00409 void EditDisplayAlarmDlg::saveState(const KAEvent* event)
00410 {
00411     EditAlarmDlg::saveState(event);
00412     mSavedType        = mTypeCombo->currentIndex();
00413     mSavedCmdScript   = mCmdEdit->isScript();
00414     mSavedSoundType   = mSoundPicker->sound();
00415     mSavedSoundFile   = mSoundPicker->file();
00416     mSavedSoundVolume = mSoundPicker->volume(mSavedSoundFadeVolume, mSavedSoundFadeSeconds);
00417     mSavedRepeatSound = mSoundPicker->repeat();
00418     mSavedConfirmAck  = mConfirmAck->isChecked();
00419     mSavedFont        = mFontColourButton->font();
00420     mSavedFgColour    = mFontColourButton->fgColour();
00421     mSavedBgColour    = (mTypeCombo->currentIndex() == tFILE) ? mBgColourButton->colour() : mFontColourButton->bgColour();
00422     mSavedReminder    = reminder()->minutes();
00423     mSavedOnceOnly    = reminder()->isOnceOnly();
00424     mSavedAutoClose   = lateCancel()->isAutoClose();
00425     if (mSpecialActionsButton)
00426     {
00427         mSavedPreAction       = mSpecialActionsButton->preAction();
00428         mSavedPostAction      = mSpecialActionsButton->postAction();
00429         mSavedPreActionCancel = mSpecialActionsButton->cancelOnError();
00430     }
00431 }
00432 
00433 /******************************************************************************
00434 * Check whether any of the controls has changed state since the dialog was
00435 * first displayed.
00436 * Reply = true if any controls have changed, or if it's a new event.
00437 *       = false if no controls have changed.
00438 */
00439 bool EditDisplayAlarmDlg::type_stateChanged() const
00440 {
00441     if (mSavedType       != mTypeCombo->currentIndex()
00442     ||  mSavedCmdScript  != mCmdEdit->isScript()
00443     ||  mSavedSoundType  != mSoundPicker->sound()
00444     ||  mSavedConfirmAck != mConfirmAck->isChecked()
00445     ||  mSavedFont       != mFontColourButton->font()
00446     ||  mSavedFgColour   != mFontColourButton->fgColour()
00447     ||  mSavedBgColour   != (mTypeCombo->currentIndex() == tFILE ? mBgColourButton->colour() : mFontColourButton->bgColour())
00448     ||  mSavedReminder   != reminder()->minutes()
00449     ||  mSavedOnceOnly   != reminder()->isOnceOnly()
00450     ||  mSavedAutoClose  != lateCancel()->isAutoClose())
00451         return true;
00452     if (mSpecialActionsButton)
00453     {
00454         if (mSavedPreAction       != mSpecialActionsButton->preAction()
00455         ||  mSavedPostAction      != mSpecialActionsButton->postAction()
00456         ||  mSavedPreActionCancel != mSpecialActionsButton->cancelOnError())
00457             return true;
00458     }
00459     if (mSavedSoundType == Preferences::Sound_File)
00460     {
00461         if (mSavedSoundFile != mSoundPicker->file())
00462             return true;
00463         if (!mSavedSoundFile.isEmpty())
00464         {
00465             float fadeVolume;
00466             int   fadeSecs;
00467             if (mSavedRepeatSound != mSoundPicker->repeat()
00468             ||  mSavedSoundVolume != mSoundPicker->volume(fadeVolume, fadeSecs)
00469             ||  mSavedSoundFadeVolume != fadeVolume
00470             ||  mSavedSoundFadeSeconds != fadeSecs)
00471                 return true;
00472         }
00473     }
00474     return false;
00475 }
00476 
00477 /******************************************************************************
00478 * Extract the data in the dialog specific to the alarm type and set up a
00479 * KAEvent from it.
00480 */
00481 void EditDisplayAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
00482 {
00483     KAEvent::Action type;
00484     switch (mTypeCombo->currentIndex())
00485     {
00486         case tFILE:     type = KAEvent::FILE; break;
00487         case tCOMMAND:  type = KAEvent::COMMAND; break;
00488         default:
00489         case tTEXT:     type = KAEvent::MESSAGE; break;
00490     }
00491     event.set(dt, text, (mTypeCombo->currentIndex() == tFILE ? mBgColourButton->colour() : mFontColourButton->bgColour()),
00492               mFontColourButton->fgColour(), mFontColourButton->font(),
00493               type, lateCancel, getAlarmFlags());
00494     if (type == KAEvent::MESSAGE)
00495     {
00496         if (AlarmText::checkIfEmail(text))
00497             event.setKMailSerialNumber(mKMailSerialNumber);
00498     }
00499     float fadeVolume;
00500     int   fadeSecs;
00501     float volume = mSoundPicker->volume(fadeVolume, fadeSecs);
00502     event.setAudioFile(mSoundPicker->file().prettyUrl(), volume, fadeVolume, fadeSecs);
00503     if (!trial)
00504         event.setReminder(reminder()->minutes(), reminder()->isOnceOnly());
00505     if (mSpecialActionsButton  &&  mSpecialActionsButton->isEnabled())
00506         event.setActions(mSpecialActionsButton->preAction(), mSpecialActionsButton->postAction(), mSpecialActionsButton->cancelOnError());
00507 }
00508 
00509 /******************************************************************************
00510 * Get the currently specified alarm flag bits.
00511 */
00512 int EditDisplayAlarmDlg::getAlarmFlags() const
00513 {
00514     bool cmd = (mTypeCombo->currentIndex() == tCOMMAND);
00515     return EditAlarmDlg::getAlarmFlags()
00516          | (mSoundPicker->sound() == Preferences::Sound_Beep  ? KAEvent::BEEP : 0)
00517          | (mSoundPicker->sound() == Preferences::Sound_Speak ? KAEvent::SPEAK : 0)
00518          | (mSoundPicker->repeat()                            ? KAEvent::REPEAT_SOUND : 0)
00519          | (mConfirmAck->isChecked()                          ? KAEvent::CONFIRM_ACK : 0)
00520          | (lateCancel()->isAutoClose()                       ? KAEvent::AUTO_CLOSE : 0)
00521          | (mFontColourButton->defaultFont()                  ? KAEvent::DEFAULT_FONT : 0)
00522          | (cmd                                               ? KAEvent::DISPLAY_COMMAND : 0)
00523          | (cmd && mCmdEdit->isScript()                       ? KAEvent::SCRIPT : 0);
00524 }
00525 
00526 /******************************************************************************
00527 *  Called when one of the alarm display type combo box is changed, to display
00528 *  the appropriate set of controls for that action type.
00529 */
00530 void EditDisplayAlarmDlg::slotAlarmTypeChanged(int index)
00531 {
00532     QWidget* focus = 0;
00533     switch (index)
00534     {
00535         case tTEXT:    // text message
00536             mFileBox->hide();
00537             mFilePadding->hide();
00538             mCmdEdit->hide();
00539             mTextMessageEdit->show();
00540             mFontColourButton->show();
00541             mBgColourBox->hide();
00542             mSoundPicker->showSpeak(true);
00543             if (mSpecialActionsButton)
00544             {
00545                 if (mSpecialActionsInLayout1)
00546                 {
00547                     mSpecialActionsLayout1->removeWidget(mSpecialActionsButton);
00548                     mSpecialActionsLayout2->addWidget(mSpecialActionsButton);
00549                     mSpecialActionsInLayout1 = false;
00550                 }
00551                 mSpecialActionsButton->show();
00552             }
00553             setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the alarm message now"));
00554             focus = mTextMessageEdit;
00555             break;
00556         case tFILE:    // file contents
00557             mTextMessageEdit->hide();
00558             mFileBox->show();
00559             mFilePadding->show();
00560             mCmdEdit->hide();
00561             mFontColourButton->hide();
00562             mBgColourBox->show();
00563             mSoundPicker->showSpeak(false);
00564             if (mSpecialActionsButton)
00565             {
00566                 if (!mSpecialActionsInLayout1)
00567                 {
00568                     mSpecialActionsLayout2->removeWidget(mSpecialActionsButton);
00569                     mSpecialActionsLayout1->addWidget(mSpecialActionsButton);
00570                     mSpecialActionsInLayout1 = true;
00571                 }
00572                 mSpecialActionsButton->show();
00573             }
00574             setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the file now"));
00575             mFileMessageEdit->setNoSelect();
00576             focus = mFileMessageEdit;
00577             break;
00578         case tCOMMAND:    // command output
00579             mTextMessageEdit->hide();
00580             mFileBox->hide();
00581             slotCmdScriptToggled(mCmdEdit->isScript());  // show/hide mFilePadding
00582             mCmdEdit->show();
00583             mFontColourButton->show();
00584             mBgColourBox->hide();
00585             mSoundPicker->showSpeak(true);
00586             if (mSpecialActionsButton)
00587                 mSpecialActionsButton->hide();
00588             setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the command output now"));
00589             focus = mCmdEdit;
00590             break;
00591     }
00592     if (focus)
00593         focus->setFocus();
00594 }
00595 
00596 /******************************************************************************
00597 * Called when the file browse button is pressed to select a file to display.
00598 */
00599 void EditDisplayAlarmDlg::slotPickFile()
00600 {
00601     static QString defaultDir;   // default directory for file browse button
00602     QString file = KAlarm::browseFile(i18nc("@title:window", "Choose Text or Image File to Display"),
00603                                       defaultDir, mFileMessageEdit->text(), QString(), KFile::ExistingOnly, this);
00604     mFileMessageEdit->setText(file);
00605 }
00606 
00607 /******************************************************************************
00608 * Called when one of the command type radio buttons is clicked,
00609 * to display the appropriate edit field.
00610 */
00611 void EditDisplayAlarmDlg::slotCmdScriptToggled(bool on)
00612 {
00613     if (on)
00614         mFilePadding->hide();
00615     else
00616         mFilePadding->show();
00617 }
00618 
00619 /******************************************************************************
00620 * Clean up the alarm text, and if it's a file, check whether it's valid.
00621 */
00622 bool EditDisplayAlarmDlg::checkText(QString& result, bool showErrorMessage) const
00623 {
00624     switch (mTypeCombo->currentIndex())
00625     {
00626         case tTEXT:
00627             result = mTextMessageEdit->toPlainText();
00628             break;
00629 
00630         case tFILE:
00631         {
00632             QString alarmtext = mFileMessageEdit->text().trimmed();
00633             // Convert any relative file path to absolute
00634             // (using home directory as the default)
00635             enum Err { NONE = 0, BLANK, NONEXISTENT, DIRECTORY, UNREADABLE, NOT_TEXT_IMAGE };
00636             Err err = NONE;
00637             KUrl url;
00638             int i = alarmtext.indexOf(QLatin1Char('/'));
00639             if (i > 0  &&  alarmtext[i - 1] == QLatin1Char(':'))
00640             {
00641                 url = alarmtext;
00642                 url.cleanPath();
00643                 alarmtext = url.prettyUrl();
00644                 KIO::UDSEntry uds;
00645                 if (!KIO::NetAccess::stat(url, uds, MainWindow::mainMainWindow()))
00646                     err = NONEXISTENT;
00647                 else
00648                 {
00649                     KFileItem fi(uds, url);
00650                     if (fi.isDir())             err = DIRECTORY;
00651                     else if (!fi.isReadable())  err = UNREADABLE;
00652                 }
00653             }
00654             else if (alarmtext.isEmpty())
00655                 err = BLANK;    // blank file name
00656             else
00657             {
00658                 // It's a local file - convert to absolute path & check validity
00659                 QFileInfo info(alarmtext);
00660                 QDir::setCurrent(QDir::homePath());
00661                 alarmtext = info.absoluteFilePath();
00662                 url.setPath(alarmtext);
00663                 alarmtext = QLatin1String("file:") + alarmtext;
00664                 if (!err)
00665                 {
00666                     if      (info.isDir())        err = DIRECTORY;
00667                     else if (!info.exists())      err = NONEXISTENT;
00668                     else if (!info.isReadable())  err = UNREADABLE;
00669                 }
00670             }
00671             if (!err)
00672             {
00673                 switch (KAlarm::fileType(KFileItem(KFileItem::Unknown, KFileItem::Unknown, url).mimeTypePtr()))
00674                 {
00675                     case KAlarm::TextFormatted:
00676                     case KAlarm::TextPlain:
00677                     case KAlarm::TextApplication:
00678                     case KAlarm::Image:
00679                         break;
00680                     default:
00681                         err = NOT_TEXT_IMAGE;
00682                         break;
00683                 }
00684             }
00685             if (err  &&  showErrorMessage)
00686             {
00687                 mFileMessageEdit->setFocus();
00688                 QString errmsg;
00689                 switch (err)
00690                 {
00691                     case BLANK:
00692                         KMessageBox::sorry(const_cast<EditDisplayAlarmDlg*>(this), i18nc("@info", "Please select a file to display"));
00693                         return false;
00694                     case NONEXISTENT:     errmsg = i18nc("@info", "<filename>%1</filename> not found", alarmtext);  break;
00695                     case DIRECTORY:       errmsg = i18nc("@info", "<filename>%1</filename> is a folder", alarmtext);  break;
00696                     case UNREADABLE:      errmsg = i18nc("@info", "<filename>%1</filename> is not readable", alarmtext);  break;
00697                     case NOT_TEXT_IMAGE:  errmsg = i18nc("@info", "<filename>%1</filename> appears not to be a text or image file", alarmtext);  break;
00698                     case NONE:
00699                     default:
00700                         break;
00701                 }
00702                 if (KMessageBox::warningContinueCancel(const_cast<EditDisplayAlarmDlg*>(this), errmsg)
00703                     == KMessageBox::Cancel)
00704                     return false;
00705             }
00706             result = alarmtext;
00707             break;
00708         }
00709         case tCOMMAND:
00710             result = mCmdEdit->text();
00711             break;
00712     }
00713     return true;
00714 }
00715 
00716 
00717 /*=============================================================================
00718 = Class EditCommandAlarmDlg
00719 = Dialog to edit command alarms.
00720 =============================================================================*/
00721 
00722 QString EditCommandAlarmDlg::i18n_chk_EnterScript()        { return i18nc("@option:check", "Enter a script"); }
00723 QString EditCommandAlarmDlg::i18n_radio_ExecInTermWindow() { return i18nc("@option:radio", "Execute in terminal window"); }
00724 QString EditCommandAlarmDlg::i18n_chk_ExecInTermWindow()   { return i18nc("@option:check", "Execute in terminal window"); }
00725 
00726 
00727 /******************************************************************************
00728 * Constructor.
00729 * Parameters:
00730 *   Template = true to edit/create an alarm template
00731 *            = false to edit/create an alarm.
00732 *   event   != to initialise the dialog to show the specified event's data.
00733 */
00734 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, bool newAlarm, QWidget* parent, GetResourceType getResource)
00735     : EditAlarmDlg(Template, KAEvent::COMMAND, parent, getResource)
00736 {
00737     kDebug() << "New";
00738     init(0, newAlarm);
00739 }
00740 
00741 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
00742                                          GetResourceType getResource, bool readOnly)
00743     : EditAlarmDlg(Template, event, parent, getResource, readOnly)
00744 {
00745     kDebug() << "Event.id()";
00746     init(event, newAlarm);
00747 }
00748 
00749 /******************************************************************************
00750 * Return the window caption.
00751 */
00752 QString EditCommandAlarmDlg::type_caption(bool newAlarm) const
00753 {
00754     return isTemplate() ? (newAlarm ? i18nc("@title:window", "New Command Alarm Template") : i18nc("@title:window", "Edit Command Alarm Template"))
00755                         : (newAlarm ? i18nc("@title:window", "New Command Alarm") : i18nc("@title:window", "Edit Command Alarm"));
00756 }
00757 
00758 /******************************************************************************
00759 * Set up the command alarm dialog controls.
00760 */
00761 void EditCommandAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
00762 {
00763     setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Execute the specified command now"));
00764 
00765     mCmdEdit = new CommandEdit(parent);
00766     connect(mCmdEdit, SIGNAL(scriptToggled(bool)), SLOT(slotCmdScriptToggled(bool)));
00767     frameLayout->addWidget(mCmdEdit);
00768 
00769     // What to do with command output
00770 
00771     QGroupBox* cmdOutputBox = new QGroupBox(i18nc("@title:group", "Command Output"), parent);
00772     frameLayout->addWidget(cmdOutputBox);
00773     QVBoxLayout* vlayout = new QVBoxLayout(cmdOutputBox);
00774     vlayout->setMargin(marginHint());
00775     vlayout->setSpacing(spacingHint());
00776     mCmdOutputGroup = new ButtonGroup(cmdOutputBox);
00777 
00778     // Execute in terminal window
00779     mCmdExecInTerm = new RadioButton(i18n_radio_ExecInTermWindow(), cmdOutputBox);
00780     mCmdExecInTerm->setFixedSize(mCmdExecInTerm->sizeHint());
00781     mCmdExecInTerm->setWhatsThis(i18nc("@info:whatsthis", "Check to execute the command in a terminal window"));
00782     mCmdOutputGroup->addButton(mCmdExecInTerm, Preferences::Log_Terminal);
00783     vlayout->addWidget(mCmdExecInTerm, 0, Qt::AlignLeft);
00784 
00785     // Log file name edit box
00786     KHBox* box = new KHBox(cmdOutputBox);
00787     box->setMargin(0);
00788     (new QWidget(box))->setFixedWidth(mCmdExecInTerm->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth));   // indent the edit box
00789     mCmdLogFileEdit = new LineEdit(LineEdit::Url, box);
00790     mCmdLogFileEdit->setAcceptDrops(true);
00791     mCmdLogFileEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or path of the log file."));
00792 
00793     // Log file browse button.
00794     // The file browser dialog is activated by the PickLogFileRadio class.
00795     QPushButton* browseButton = new QPushButton(box);
00796     browseButton->setIcon(SmallIcon("document-open"));
00797     int size = browseButton->sizeHint().height();
00798     browseButton->setFixedSize(size, size);
00799     browseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
00800     browseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a log file."));
00801 
00802     // Log output to file
00803     mCmdLogToFile = new PickLogFileRadio(browseButton, mCmdLogFileEdit, i18nc("@option:radio", "Log to file"), mCmdOutputGroup, cmdOutputBox);
00804     mCmdLogToFile->setFixedSize(mCmdLogToFile->sizeHint());
00805     mCmdLogToFile->setWhatsThis(i18nc("@info:whatsthis", "Check to log the command output to a local file. The output will be appended to any existing contents of the file."));
00806     mCmdOutputGroup->addButton(mCmdLogToFile, Preferences::Log_File);
00807     vlayout->addWidget(mCmdLogToFile, 0, Qt::AlignLeft);
00808     vlayout->addWidget(box);
00809 
00810     // Discard output
00811     mCmdDiscardOutput = new RadioButton(i18nc("@option:radio", "Discard"), cmdOutputBox);
00812     mCmdDiscardOutput->setFixedSize(mCmdDiscardOutput->sizeHint());
00813     mCmdDiscardOutput->setWhatsThis(i18nc("@info:whatsthis", "Check to discard command output."));
00814     mCmdOutputGroup->addButton(mCmdDiscardOutput, Preferences::Log_Discard);
00815     vlayout->addWidget(mCmdDiscardOutput, 0, Qt::AlignLeft);
00816 
00817     // Top-adjust the controls
00818     mCmdPadding = new KHBox(parent);
00819     mCmdPadding->setMargin(0);
00820     frameLayout->addWidget(mCmdPadding);
00821     frameLayout->setStretchFactor(mCmdPadding, 1);
00822 }
00823 
00824 /******************************************************************************
00825 * Initialise the dialog controls from the specified event.
00826 */
00827 void EditCommandAlarmDlg::type_initValues(const KAEvent* event)
00828 {
00829     if (event)
00830     {
00831         // Set the values to those for the specified event
00832         RadioButton* logType = event->commandXterm()       ? mCmdExecInTerm
00833                              : !event->logFile().isEmpty() ? mCmdLogToFile
00834                              :                               mCmdDiscardOutput;
00835         if (logType == mCmdLogToFile)
00836             mCmdLogFileEdit->setText(event->logFile());    // set file name before setting radio button
00837         logType->setChecked(true);
00838     }
00839     else
00840     {
00841         // Set the values to their defaults
00842         mCmdEdit->setScript(Preferences::defaultCmdScript());
00843         mCmdLogFileEdit->setText(Preferences::defaultCmdLogFile());    // set file name before setting radio button
00844         mCmdOutputGroup->setButton(Preferences::defaultCmdLogType());
00845     }
00846     slotCmdScriptToggled(mCmdEdit->isScript());
00847 }
00848 
00849 /******************************************************************************
00850 * Set the dialog's action and the action's text.
00851 */
00852 void EditCommandAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText)
00853 {
00854     Q_ASSERT(action == KAEvent::COMMAND);
00855     mCmdEdit->setText(alarmText);
00856 }
00857 
00858 /******************************************************************************
00859 * Set the read-only status of all non-template controls.
00860 */
00861 void EditCommandAlarmDlg::setReadOnly(bool readOnly)
00862 {
00863     if (!isTemplate()  &&  !ShellProcess::authorised())
00864         readOnly = true;     // don't allow editing of existing command alarms in kiosk mode
00865     mCmdEdit->setReadOnly(readOnly);
00866     mCmdExecInTerm->setReadOnly(readOnly);
00867     mCmdLogToFile->setReadOnly(readOnly);
00868     mCmdDiscardOutput->setReadOnly(readOnly);
00869     EditAlarmDlg::setReadOnly(readOnly);
00870 }
00871