Build with clang.
[kdepim.git] / kalarm / editdlgtypes.cpp
blobf08f948c8da470ef3eb3e54c869f385475a2dd8d
1 /*
2 * editdlgtypes.cpp - dialogs to create or edit alarm or alarm template types
3 * Program: kalarm
4 * Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "kalarm.h"
22 #include "editdlgtypes.moc"
23 #include "editdlg_p.h"
25 #include "autoqpointer.h"
26 #include "buttongroup.h"
27 #include "checkbox.h"
28 #include "colourbutton.h"
29 #include "emailidcombo.h"
30 #include "fontcolourbutton.h"
31 #include "functions.h"
32 #include "identities.h"
33 #include "kalarmapp.h"
34 #include "kamail.h"
35 #include "latecancel.h"
36 #include "lineedit.h"
37 #include "mainwindow.h"
38 #include "messagebox.h"
39 #include "pickfileradio.h"
40 #include "preferences.h"
41 #include "radiobutton.h"
42 #include "reminder.h"
43 #include "shellprocess.h"
44 #include "soundpicker.h"
45 #include "sounddlg.h"
46 #include "specialactions.h"
47 #include "templatepickdlg.h"
48 #include "timespinbox.h"
50 #include <akonadi/contact/emailaddressselectiondialog.h>
51 #ifdef USE_AKONADI
52 #include <kcalcore/person.h>
53 #include <kcalutils/icaldrag.h>
54 using namespace KCalCore;
55 #else
56 #include <kcal/person.h>
57 #include <kcal/icaldrag.h>
58 using namespace KCal;
59 #endif
61 #include <klocale.h>
62 #include <kiconloader.h>
63 #include <kio/netaccess.h>
64 #include <kfileitem.h>
65 #include <khbox.h>
66 #include <kdebug.h>
68 #include <QLabel>
69 #include <QDir>
70 #include <QStyle>
71 #include <QGroupBox>
72 #include <QGridLayout>
73 #include <QHBoxLayout>
74 #include <QVBoxLayout>
75 #include <QDragEnterEvent>
76 #include <QStandardItemModel>
78 enum { tTEXT, tFILE, tCOMMAND }; // order of mTypeCombo items
81 /*=============================================================================
82 = Class PickLogFileRadio
83 =============================================================================*/
84 class PickLogFileRadio : public PickFileRadio
86 public:
87 PickLogFileRadio(QPushButton* b, LineEdit* e, const QString& text, ButtonGroup* group, QWidget* parent)
88 : PickFileRadio(b, e, text, group, parent) { }
89 virtual QString pickFile() // called when browse button is pressed to select a log file
91 return KAlarm::browseFile(i18nc("@title:window", "Choose Log File"), mDefaultDir, fileEdit()->text(), QString(),
92 KFile::LocalOnly, parentWidget());
94 private:
95 QString mDefaultDir; // default directory for log file browse button
99 /*=============================================================================
100 = Class EditDisplayAlarmDlg
101 = Dialog to edit display alarms.
102 =============================================================================*/
104 QString EditDisplayAlarmDlg::i18n_chk_ConfirmAck() { return i18nc("@option:check", "Confirm acknowledgment"); }
107 /******************************************************************************
108 * Constructor.
109 * Parameters:
110 * Template = true to edit/create an alarm template
111 * = false to edit/create an alarm.
112 * event != to initialise the dialog to show the specified event's data.
114 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
115 : EditAlarmDlg(Template, KAEvent::MESSAGE, parent, getResource),
116 mSpecialActionsButton(0),
117 mReminderDeferral(false),
118 mReminderArchived(false)
120 kDebug() << "New";
121 init(0);
124 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
125 GetResourceType getResource, bool readOnly)
126 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
127 mSpecialActionsButton(0),
128 mReminderDeferral(false),
129 mReminderArchived(false)
131 kDebug() << "Event.id()";
132 init(event);
135 /******************************************************************************
136 * Return the window caption.
138 QString EditDisplayAlarmDlg::type_caption() const
140 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Display Alarm Template") : i18nc("@title:window", "Edit Display Alarm Template"))
141 : (isNewAlarm() ? i18nc("@title:window", "New Display Alarm") : i18nc("@title:window", "Edit Display Alarm"));
144 /******************************************************************************
145 * Set up the dialog controls common to display alarms.
147 void EditDisplayAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
149 // Display type combo box
150 KHBox* box = new KHBox(parent); // to group widgets for QWhatsThis text
151 box->setMargin(0);
152 box->setSpacing(KDialog::spacingHint());
153 QLabel* label = new QLabel(i18nc("@label:listbox", "Display type:"), box);
154 label->setFixedSize(label->sizeHint());
155 mTypeCombo = new ComboBox(box);
156 QString textItem = i18nc("@item:inlistbox", "Text message");
157 QString fileItem = i18nc("@item:inlistbox", "File contents");
158 QString commandItem = i18nc("@item:inlistbox", "Command output");
159 mTypeCombo->addItem(textItem); // index = tTEXT
160 mTypeCombo->addItem(fileItem); // index = tFILE
161 mTypeCombo->addItem(commandItem); // index = tCOMMAND
162 mTypeCombo->setFixedSize(mTypeCombo->sizeHint());
163 mTypeCombo->setCurrentIndex(-1); // ensure slotAlarmTypeChanged() is called when index is set
164 if (!ShellProcess::authorised())
166 // User not authorised to issue shell commands - disable Command Output option
167 QStandardItemModel* model = qobject_cast<QStandardItemModel*>(mTypeCombo->model());
168 if (model)
170 QModelIndex index = model->index(2, mTypeCombo->modelColumn(), mTypeCombo->rootModelIndex());
171 QStandardItem* item = model->itemFromIndex(index);
172 if (item)
173 item->setEnabled(false);
176 connect(mTypeCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotAlarmTypeChanged(int)));
177 connect(mTypeCombo, SIGNAL(currentIndexChanged(int)), SLOT(contentsChanged()));
178 label->setBuddy(mTypeCombo);
179 box->setWhatsThis(i18nc("@info:whatsthis", "<para>Select what the alarm should display:"
180 "<list><item><interface>%1</interface>: the alarm will display the text message you type in.</item>"
181 "<item><interface>%2</interface>: the alarm will display the contents of a text or image file.</item>"
182 "<item><interface>%3</interface>: the alarm will display the output from a command.</item></list></para>",
183 textItem, fileItem, commandItem));
184 box->setStretchFactor(new QWidget(box), 1); // left adjust the control
185 frameLayout->addWidget(box);
187 // Text message edit box
188 mTextMessageEdit = new TextEdit(parent);
189 mTextMessageEdit->setLineWrapMode(KTextEdit::NoWrap);
190 mTextMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the text of the alarm message. It may be multi-line."));
191 connect(mTextMessageEdit, SIGNAL(textChanged()), SLOT(contentsChanged()));
192 frameLayout->addWidget(mTextMessageEdit);
194 // File name edit box
195 mFileBox = new KHBox(parent);
196 mFileBox->setMargin(0);
197 frameLayout->addWidget(mFileBox);
198 mFileMessageEdit = new LineEdit(LineEdit::Url, mFileBox);
199 mFileMessageEdit->setAcceptDrops(true);
200 mFileMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or URL of a text or image file to display."));
201 connect(mFileMessageEdit, SIGNAL(textChanged(QString)), SLOT(contentsChanged()));
203 // File browse button
204 mFileBrowseButton = new QPushButton(mFileBox);
205 mFileBrowseButton->setIcon(SmallIcon("document-open"));
206 int size = mFileBrowseButton->sizeHint().height();
207 mFileBrowseButton->setFixedSize(size, size);
208 mFileBrowseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
209 mFileBrowseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a text or image file to display."));
210 connect(mFileBrowseButton, SIGNAL(clicked()), SLOT(slotPickFile()));
212 // Command type checkbox and edit box
213 mCmdEdit = new CommandEdit(parent);
214 connect(mCmdEdit, SIGNAL(scriptToggled(bool)), SLOT(slotCmdScriptToggled(bool)));
215 connect(mCmdEdit, SIGNAL(changed()), SLOT(contentsChanged()));
216 frameLayout->addWidget(mCmdEdit);
218 // Sound checkbox and file selector
219 QHBoxLayout* hlayout = new QHBoxLayout();
220 hlayout->setMargin(0);
221 frameLayout->addLayout(hlayout);
222 mSoundPicker = new SoundPicker(parent);
223 mSoundPicker->setFixedSize(mSoundPicker->sizeHint());
224 connect(mSoundPicker, SIGNAL(changed()), SLOT(contentsChanged()));
225 hlayout->addWidget(mSoundPicker);
226 hlayout->addSpacing(2*spacingHint());
227 hlayout->addStretch();
229 // Font and colour choice button and sample text
230 mFontColourButton = new FontColourButton(parent);
231 mFontColourButton->setMaximumHeight(mFontColourButton->sizeHint().height() * 3/2);
232 hlayout->addWidget(mFontColourButton);
233 connect(mFontColourButton, SIGNAL(selected(QColor,QColor)), SLOT(setColours(QColor,QColor)));
234 connect(mFontColourButton, SIGNAL(selected(QColor,QColor)), SLOT(contentsChanged()));
236 if (ShellProcess::authorised()) // don't display if shell commands not allowed (e.g. kiosk mode)
238 // Special actions button
239 mSpecialActionsButton = new SpecialActionsButton(false, parent);
240 mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
241 connect(mSpecialActionsButton, SIGNAL(selected()), SLOT(contentsChanged()));
242 frameLayout->addWidget(mSpecialActionsButton, 0, Qt::AlignRight);
245 // Top-adjust the controls
246 mFilePadding = new KHBox(parent);
247 mFilePadding->setMargin(0);
248 frameLayout->addWidget(mFilePadding);
249 frameLayout->setStretchFactor(mFilePadding, 1);
252 /******************************************************************************
253 * Create a reminder control.
255 Reminder* EditDisplayAlarmDlg::createReminder(QWidget* parent)
257 static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of or after the main alarm to display a reminder alarm.");
258 return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of or after the main alarm time(s)."),
259 i18nc("@info:whatsthis", "<para>Enter how long in advance of or after the main alarm to display a reminder alarm.</para><para>%1</para>", TimeSpinBox::shiftWhatsThis()),
260 i18nc("@info:whatsthis", "Select whether the reminder should be triggered before or after the main alarm"),
261 true, true, parent);
264 /******************************************************************************
265 * Create an "acknowledgement confirmation required" checkbox.
267 CheckBox* EditDisplayAlarmDlg::createConfirmAckCheckbox(QWidget* parent)
269 CheckBox* confirmAck = new CheckBox(i18n_chk_ConfirmAck(), parent);
270 confirmAck->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation when you acknowledge the alarm."));
271 return confirmAck;
274 /******************************************************************************
275 * Initialise the dialog controls from the specified event.
277 void EditDisplayAlarmDlg::type_initValues(const KAEvent* event)
279 mKMailSerialNumber = 0;
280 lateCancel()->showAutoClose(true);
281 if (event)
283 if (mAlarmType == KAEvent::MESSAGE && event->kmailSerialNumber()
284 && AlarmText::checkIfEmail(event->cleanText()))
285 mKMailSerialNumber = event->kmailSerialNumber();
286 lateCancel()->setAutoClose(event->autoClose());
287 if (event->useDefaultFont())
288 mFontColourButton->setDefaultFont();
289 else
290 mFontColourButton->setFont(event->font());
291 mFontColourButton->setBgColour(event->bgColour());
292 mFontColourButton->setFgColour(event->fgColour());
293 setColours(event->fgColour(), event->bgColour());
294 mConfirmAck->setChecked(event->confirmAck());
295 bool recurs = event->recurs();
296 int reminderMins = event->reminderMinutes();
297 if (reminderMins > 0 && !event->reminderActive())
298 reminderMins = 0; // don't show advance reminder which has already passed
299 if (!reminderMins)
301 if (event->reminderDeferral() && !recurs)
303 reminderMins = event->deferDateTime().minsTo(event->mainDateTime());
304 mReminderDeferral = true;
306 else if (event->reminderMinutes() && recurs)
308 reminderMins = event->reminderMinutes();
309 mReminderArchived = true;
312 reminder()->setMinutes(reminderMins, dateOnly());
313 reminder()->setOnceOnly(event->reminderOnceOnly());
314 reminder()->enableOnceOnly(recurs);
315 if (mSpecialActionsButton)
316 mSpecialActionsButton->setActions(event->preAction(), event->postAction(), event->cancelOnPreActionError(), event->dontShowPreActionError());
317 Preferences::SoundType soundType = event->speak() ? Preferences::Sound_Speak
318 : event->beep() ? Preferences::Sound_Beep
319 : !event->audioFile().isEmpty() ? Preferences::Sound_File
320 : Preferences::Sound_None;
321 mSoundPicker->set(soundType, event->audioFile(), event->soundVolume(),
322 event->fadeVolume(), event->fadeSeconds(), event->repeatSound());
324 else
326 // Set the values to their defaults
327 if (!ShellProcess::authorised())
329 // Don't allow shell commands in kiosk mode
330 if (mSpecialActionsButton)
331 mSpecialActionsButton->setEnabled(false);
333 lateCancel()->setAutoClose(Preferences::defaultAutoClose());
334 mTypeCombo->setCurrentIndex(0);
335 mFontColourButton->setDefaultFont();
336 mFontColourButton->setBgColour(Preferences::defaultBgColour());
337 mFontColourButton->setFgColour(Preferences::defaultFgColour());
338 setColours(Preferences::defaultFgColour(), Preferences::defaultBgColour());
339 mConfirmAck->setChecked(Preferences::defaultConfirmAck());
340 reminder()->setMinutes(0, false);
341 reminder()->enableOnceOnly(isTimedRecurrence()); // must be called after mRecurrenceEdit is set up
342 if (mSpecialActionsButton)
343 mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(),
344 Preferences::defaultCancelOnPreActionError(), Preferences::defaultDontShowPreActionError());
345 mSoundPicker->set(Preferences::defaultSoundType(), Preferences::defaultSoundFile(),
346 Preferences::defaultSoundVolume(), -1, 0, Preferences::defaultSoundRepeat());
350 /******************************************************************************
351 * Called when the More/Less Options button is clicked.
352 * Show/hide the optional options.
354 void EditDisplayAlarmDlg::type_showOptions(bool more)
356 if (mSpecialActionsButton)
358 if (more)
359 mSpecialActionsButton->show();
360 else
361 mSpecialActionsButton->hide();
365 /******************************************************************************
366 * Called when the font/color button has been clicked.
367 * Set the colors in the message text entry control.
369 void EditDisplayAlarmDlg::setColours(const QColor& fgColour, const QColor& bgColour)
371 QPalette pal = mTextMessageEdit->palette();
372 pal.setColor(mTextMessageEdit->backgroundRole(), bgColour);
373 pal.setColor(QPalette::Text, fgColour);
374 mTextMessageEdit->setPalette(pal);
375 pal = mTextMessageEdit->viewport()->palette();
376 pal.setColor(mTextMessageEdit->viewport()->backgroundRole(), bgColour);
377 pal.setColor(QPalette::Text, fgColour);
378 mTextMessageEdit->viewport()->setPalette(pal);
379 // Change the color of existing text
380 QTextCursor cursor = mTextMessageEdit->textCursor();
381 mTextMessageEdit->selectAll();
382 mTextMessageEdit->setTextColor(fgColour);
383 mTextMessageEdit->setTextCursor(cursor);
386 /******************************************************************************
387 * Set the dialog's action and the action's text.
389 void EditDisplayAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
391 QString text = alarmText.displayText();
392 switch (action)
394 case KAEvent::MESSAGE:
395 mTypeCombo->setCurrentIndex(tTEXT);
396 mTextMessageEdit->setPlainText(text);
397 mKMailSerialNumber = alarmText.isEmail() ? alarmText.kmailSerialNumber() : 0;
398 break;
399 case KAEvent::FILE:
400 mTypeCombo->setCurrentIndex(tFILE);
401 mFileMessageEdit->setText(text);
402 break;
403 case KAEvent::COMMAND:
404 mTypeCombo->setCurrentIndex(tCOMMAND);
405 mCmdEdit->setText(alarmText);
406 break;
407 default:
408 Q_ASSERT(0);
409 break;
413 /******************************************************************************
414 * Initialise various values in the New Alarm dialogue.
416 void EditDisplayAlarmDlg::setBgColour(const QColor& colour)
418 mFontColourButton->setBgColour(colour);
419 setColours(mFontColourButton->fgColour(), colour);
421 void EditDisplayAlarmDlg::setFgColour(const QColor& colour)
423 mFontColourButton->setFgColour(colour);
424 setColours(colour, mFontColourButton->bgColour());
426 void EditDisplayAlarmDlg::setConfirmAck(bool confirm)
428 mConfirmAck->setChecked(confirm);
430 void EditDisplayAlarmDlg::setAutoClose(bool close)
432 lateCancel()->setAutoClose(close);
434 void EditDisplayAlarmDlg::setAudio(Preferences::SoundType type, const QString& file, float volume, bool repeat)
436 mSoundPicker->set(type, file, volume, -1, 0, repeat);
438 void EditDisplayAlarmDlg::setReminder(int minutes, bool onceOnly)
440 reminder()->setMinutes(minutes, dateOnly());
441 reminder()->setOnceOnly(onceOnly);
442 reminder()->enableOnceOnly(isTimedRecurrence());
445 /******************************************************************************
446 * Set the read-only status of all non-template controls.
448 void EditDisplayAlarmDlg::setReadOnly(bool readOnly)
450 mTypeCombo->setReadOnly(readOnly);
451 mTextMessageEdit->setReadOnly(readOnly);
452 mFileMessageEdit->setReadOnly(readOnly);
453 mCmdEdit->setReadOnly(readOnly);
454 mFontColourButton->setReadOnly(readOnly);
455 mSoundPicker->setReadOnly(readOnly);
456 mConfirmAck->setReadOnly(readOnly);
457 reminder()->setReadOnly(readOnly);
458 if (mSpecialActionsButton)
459 mSpecialActionsButton->setReadOnly(readOnly);
460 if (readOnly)
461 mFileBrowseButton->hide();
462 else
463 mFileBrowseButton->show();
464 EditAlarmDlg::setReadOnly(readOnly);
467 /******************************************************************************
468 * Save the state of all controls.
470 void EditDisplayAlarmDlg::saveState(const KAEvent* event)
472 EditAlarmDlg::saveState(event);
473 mSavedType = mTypeCombo->currentIndex();
474 mSavedCmdScript = mCmdEdit->isScript();
475 mSavedSoundType = mSoundPicker->sound();
476 mSavedSoundFile = mSoundPicker->file();
477 mSavedSoundVolume = mSoundPicker->volume(mSavedSoundFadeVolume, mSavedSoundFadeSeconds);
478 mSavedRepeatSound = mSoundPicker->repeat();
479 mSavedConfirmAck = mConfirmAck->isChecked();
480 mSavedFont = mFontColourButton->font();
481 mSavedFgColour = mFontColourButton->fgColour();
482 mSavedBgColour = mFontColourButton->bgColour();
483 mSavedReminder = reminder()->minutes();
484 mSavedOnceOnly = reminder()->isOnceOnly();
485 mSavedAutoClose = lateCancel()->isAutoClose();
486 if (mSpecialActionsButton)
488 mSavedPreAction = mSpecialActionsButton->preAction();
489 mSavedPostAction = mSpecialActionsButton->postAction();
490 mSavedPreActionCancel = mSpecialActionsButton->cancelOnError();
494 /******************************************************************************
495 * Check whether any of the controls has changed state since the dialog was
496 * first displayed.
497 * Reply = true if any controls have changed, or if it's a new event.
498 * = false if no controls have changed.
500 bool EditDisplayAlarmDlg::type_stateChanged() const
502 if (mSavedType != mTypeCombo->currentIndex()
503 || mSavedCmdScript != mCmdEdit->isScript()
504 || mSavedSoundType != mSoundPicker->sound()
505 || mSavedConfirmAck != mConfirmAck->isChecked()
506 || mSavedFont != mFontColourButton->font()
507 || mSavedFgColour != mFontColourButton->fgColour()
508 || mSavedBgColour != mFontColourButton->bgColour()
509 || mSavedReminder != reminder()->minutes()
510 || mSavedOnceOnly != reminder()->isOnceOnly()
511 || mSavedAutoClose != lateCancel()->isAutoClose())
512 return true;
513 if (mSpecialActionsButton)
515 if (mSavedPreAction != mSpecialActionsButton->preAction()
516 || mSavedPostAction != mSpecialActionsButton->postAction()
517 || mSavedPreActionCancel != mSpecialActionsButton->cancelOnError())
518 return true;
520 if (mSavedSoundType == Preferences::Sound_File)
522 if (mSavedSoundFile != mSoundPicker->file())
523 return true;
524 if (!mSavedSoundFile.isEmpty())
526 float fadeVolume;
527 int fadeSecs;
528 if (mSavedRepeatSound != mSoundPicker->repeat()
529 || mSavedSoundVolume != mSoundPicker->volume(fadeVolume, fadeSecs)
530 || mSavedSoundFadeVolume != fadeVolume
531 || mSavedSoundFadeSeconds != fadeSecs)
532 return true;
535 return false;
538 /******************************************************************************
539 * Extract the data in the dialog specific to the alarm type and set up a
540 * KAEvent from it.
542 void EditDisplayAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
544 KAEvent::SubAction type;
545 switch (mTypeCombo->currentIndex())
547 case tFILE: type = KAEvent::FILE; break;
548 case tCOMMAND: type = KAEvent::COMMAND; break;
549 default:
550 case tTEXT: type = KAEvent::MESSAGE; break;
552 event.set(dt, text, mFontColourButton->bgColour(), mFontColourButton->fgColour(), mFontColourButton->font(),
553 type, lateCancel, getAlarmFlags());
554 if (type == KAEvent::MESSAGE)
556 if (AlarmText::checkIfEmail(text))
557 event.setKMailSerialNumber(mKMailSerialNumber);
559 float fadeVolume;
560 int fadeSecs;
561 float volume = mSoundPicker->volume(fadeVolume, fadeSecs);
562 event.setAudioFile(mSoundPicker->file().prettyUrl(), volume, fadeVolume, fadeSecs);
563 if (!trial && reminder()->isEnabled())
564 event.setReminder(reminder()->minutes(), reminder()->isOnceOnly());
565 if (mSpecialActionsButton && mSpecialActionsButton->isEnabled())
566 event.setActions(mSpecialActionsButton->preAction(), mSpecialActionsButton->postAction(),
567 mSpecialActionsButton->cancelOnError(), mSpecialActionsButton->dontShowError());
570 /******************************************************************************
571 * Get the currently specified alarm flag bits.
573 int EditDisplayAlarmDlg::getAlarmFlags() const
575 bool cmd = (mTypeCombo->currentIndex() == tCOMMAND);
576 return EditAlarmDlg::getAlarmFlags()
577 | (mSoundPicker->sound() == Preferences::Sound_Beep ? KAEvent::BEEP : 0)
578 | (mSoundPicker->sound() == Preferences::Sound_Speak ? KAEvent::SPEAK : 0)
579 | (mSoundPicker->repeat() ? KAEvent::REPEAT_SOUND : 0)
580 | (mConfirmAck->isChecked() ? KAEvent::CONFIRM_ACK : 0)
581 | (lateCancel()->isAutoClose() ? KAEvent::AUTO_CLOSE : 0)
582 | (mFontColourButton->defaultFont() ? KAEvent::DEFAULT_FONT : 0)
583 | (cmd ? KAEvent::DISPLAY_COMMAND : 0)
584 | (cmd && mCmdEdit->isScript() ? KAEvent::SCRIPT : 0);
587 /******************************************************************************
588 * Called when one of the alarm display type combo box is changed, to display
589 * the appropriate set of controls for that action type.
591 void EditDisplayAlarmDlg::slotAlarmTypeChanged(int index)
593 QWidget* focus = 0;
594 switch (index)
596 case tTEXT: // text message
597 mFileBox->hide();
598 mFilePadding->hide();
599 mCmdEdit->hide();
600 mTextMessageEdit->show();
601 mSoundPicker->showSpeak(true);
602 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the alarm message now"));
603 focus = mTextMessageEdit;
604 break;
605 case tFILE: // file contents
606 mTextMessageEdit->hide();
607 mFileBox->show();
608 mFilePadding->show();
609 mCmdEdit->hide();
610 mSoundPicker->showSpeak(false);
611 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the file now"));
612 mFileMessageEdit->setNoSelect();
613 focus = mFileMessageEdit;
614 break;
615 case tCOMMAND: // command output
616 mTextMessageEdit->hide();
617 mFileBox->hide();
618 slotCmdScriptToggled(mCmdEdit->isScript()); // show/hide mFilePadding
619 mCmdEdit->show();
620 mSoundPicker->showSpeak(true);
621 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the command output now"));
622 focus = mCmdEdit;
623 break;
625 if (focus)
626 focus->setFocus();
629 /******************************************************************************
630 * Called when the file browse button is pressed to select a file to display.
632 void EditDisplayAlarmDlg::slotPickFile()
634 static QString defaultDir; // default directory for file browse button
635 QString file = KAlarm::browseFile(i18nc("@title:window", "Choose Text or Image File to Display"),
636 defaultDir, mFileMessageEdit->text(), QString(), KFile::ExistingOnly, this);
637 if (!file.isEmpty())
639 mFileMessageEdit->setText(KAlarm::pathOrUrl(file));
640 contentsChanged();
644 /******************************************************************************
645 * Called when one of the command type radio buttons is clicked,
646 * to display the appropriate edit field.
648 void EditDisplayAlarmDlg::slotCmdScriptToggled(bool on)
650 if (on)
651 mFilePadding->hide();
652 else
653 mFilePadding->show();
656 /******************************************************************************
657 * Clean up the alarm text, and if it's a file, check whether it's valid.
659 bool EditDisplayAlarmDlg::checkText(QString& result, bool showErrorMessage) const
661 switch (mTypeCombo->currentIndex())
663 case tTEXT:
664 result = mTextMessageEdit->toPlainText();
665 break;
667 case tFILE:
669 QString alarmtext = mFileMessageEdit->text().trimmed();
670 KUrl url;
671 KAlarm::FileErr err = KAlarm::checkFileExists(alarmtext, url);
672 if (err == KAlarm::FileErr_None)
674 switch (KAlarm::fileType(KFileItem(KFileItem::Unknown, KFileItem::Unknown, url).mimeTypePtr()))
676 case KAlarm::TextFormatted:
677 case KAlarm::TextPlain:
678 case KAlarm::TextApplication:
679 case KAlarm::Image:
680 break;
681 default:
682 err = KAlarm::FileErr_NotTextImage;
683 break;
686 if (err != KAlarm::FileErr_None && showErrorMessage)
688 mFileMessageEdit->setFocus();
689 if (!KAlarm::showFileErrMessage(alarmtext, err, KAlarm::FileErr_BlankDisplay, const_cast<EditDisplayAlarmDlg*>(this)))
690 return false;
692 result = alarmtext;
693 break;
695 case tCOMMAND:
696 result = mCmdEdit->text(const_cast<EditDisplayAlarmDlg*>(this), showErrorMessage);
697 if (result.isEmpty())
698 return false;
699 break;
701 return true;
705 /*=============================================================================
706 = Class EditCommandAlarmDlg
707 = Dialog to edit command alarms.
708 =============================================================================*/
710 QString EditCommandAlarmDlg::i18n_chk_EnterScript() { return i18nc("@option:check", "Enter a script"); }
711 QString EditCommandAlarmDlg::i18n_radio_ExecInTermWindow() { return i18nc("@option:radio", "Execute in terminal window"); }
712 QString EditCommandAlarmDlg::i18n_chk_ExecInTermWindow() { return i18nc("@option:check", "Execute in terminal window"); }
715 /******************************************************************************
716 * Constructor.
717 * Parameters:
718 * Template = true to edit/create an alarm template
719 * = false to edit/create an alarm.
720 * event != to initialise the dialog to show the specified event's data.
722 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
723 : EditAlarmDlg(Template, KAEvent::COMMAND, parent, getResource)
725 kDebug() << "New";
726 init(0);
729 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
730 GetResourceType getResource, bool readOnly)
731 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly)
733 kDebug() << "Event.id()";
734 init(event);
737 /******************************************************************************
738 * Return the window caption.
740 QString EditCommandAlarmDlg::type_caption() const
742 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Command Alarm Template") : i18nc("@title:window", "Edit Command Alarm Template"))
743 : (isNewAlarm() ? i18nc("@title:window", "New Command Alarm") : i18nc("@title:window", "Edit Command Alarm"));
746 /******************************************************************************
747 * Set up the command alarm dialog controls.
749 void EditCommandAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
751 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Execute the specified command now"));
753 mCmdEdit = new CommandEdit(parent);
754 connect(mCmdEdit, SIGNAL(scriptToggled(bool)), SLOT(slotCmdScriptToggled(bool)));
755 connect(mCmdEdit, SIGNAL(changed()), SLOT(contentsChanged()));
756 frameLayout->addWidget(mCmdEdit);
758 // What to do with command output
760 mCmdOutputBox = new QGroupBox(i18nc("@title:group", "Command Output"), parent);
761 frameLayout->addWidget(mCmdOutputBox);
762 QVBoxLayout* vlayout = new QVBoxLayout(mCmdOutputBox);
763 vlayout->setMargin(marginHint());
764 vlayout->setSpacing(spacingHint());
765 mCmdOutputGroup = new ButtonGroup(mCmdOutputBox);
766 connect(mCmdOutputGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(contentsChanged()));
768 // Execute in terminal window
769 mCmdExecInTerm = new RadioButton(i18n_radio_ExecInTermWindow(), mCmdOutputBox);
770 mCmdExecInTerm->setFixedSize(mCmdExecInTerm->sizeHint());
771 mCmdExecInTerm->setWhatsThis(i18nc("@info:whatsthis", "Check to execute the command in a terminal window"));
772 mCmdOutputGroup->addButton(mCmdExecInTerm, Preferences::Log_Terminal);
773 vlayout->addWidget(mCmdExecInTerm, 0, Qt::AlignLeft);
775 // Log file name edit box
776 KHBox* box = new KHBox(mCmdOutputBox);
777 box->setMargin(0);
778 (new QWidget(box))->setFixedWidth(mCmdExecInTerm->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth)); // indent the edit box
779 mCmdLogFileEdit = new LineEdit(LineEdit::Url, box);
780 mCmdLogFileEdit->setAcceptDrops(true);
781 mCmdLogFileEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or path of the log file."));
782 connect(mCmdLogFileEdit, SIGNAL(textChanged(QString)), SLOT(contentsChanged()));
784 // Log file browse button.
785 // The file browser dialog is activated by the PickLogFileRadio class.
786 QPushButton* browseButton = new QPushButton(box);
787 browseButton->setIcon(SmallIcon("document-open"));
788 int size = browseButton->sizeHint().height();
789 browseButton->setFixedSize(size, size);
790 browseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
791 browseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a log file."));
793 // Log output to file
794 mCmdLogToFile = new PickLogFileRadio(browseButton, mCmdLogFileEdit, i18nc("@option:radio", "Log to file"), mCmdOutputGroup, mCmdOutputBox);
795 mCmdLogToFile->setFixedSize(mCmdLogToFile->sizeHint());
796 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."));
797 connect(mCmdLogToFile, SIGNAL(fileChanged()), SLOT(contentsChanged()));
798 mCmdOutputGroup->addButton(mCmdLogToFile, Preferences::Log_File);
799 vlayout->addWidget(mCmdLogToFile, 0, Qt::AlignLeft);
800 vlayout->addWidget(box);
802 // Discard output
803 mCmdDiscardOutput = new RadioButton(i18nc("@option:radio", "Discard"), mCmdOutputBox);
804 mCmdDiscardOutput->setFixedSize(mCmdDiscardOutput->sizeHint());
805 mCmdDiscardOutput->setWhatsThis(i18nc("@info:whatsthis", "Check to discard command output."));
806 mCmdOutputGroup->addButton(mCmdDiscardOutput, Preferences::Log_Discard);
807 vlayout->addWidget(mCmdDiscardOutput, 0, Qt::AlignLeft);
809 // Top-adjust the controls
810 mCmdPadding = new KHBox(parent);
811 mCmdPadding->setMargin(0);
812 frameLayout->addWidget(mCmdPadding);
813 frameLayout->setStretchFactor(mCmdPadding, 1);
816 /******************************************************************************
817 * Initialise the dialog controls from the specified event.
819 void EditCommandAlarmDlg::type_initValues(const KAEvent* event)
821 if (event)
823 // Set the values to those for the specified event
824 RadioButton* logType = event->commandXterm() ? mCmdExecInTerm
825 : !event->logFile().isEmpty() ? mCmdLogToFile
826 : mCmdDiscardOutput;
827 if (logType == mCmdLogToFile)
828 mCmdLogFileEdit->setText(event->logFile()); // set file name before setting radio button
829 logType->setChecked(true);
831 else
833 // Set the values to their defaults
834 mCmdEdit->setScript(Preferences::defaultCmdScript());
835 mCmdLogFileEdit->setText(Preferences::defaultCmdLogFile()); // set file name before setting radio button
836 mCmdOutputGroup->setButton(Preferences::defaultCmdLogType());
838 slotCmdScriptToggled(mCmdEdit->isScript());
841 /******************************************************************************
842 * Called when the More/Less Options button is clicked.
843 * Show/hide the optional options.
845 void EditCommandAlarmDlg::type_showOptions(bool more)
847 if (more)
848 mCmdOutputBox->show();
849 else
850 mCmdOutputBox->hide();
853 /******************************************************************************
854 * Set the dialog's action and the action's text.
856 void EditCommandAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
858 Q_UNUSED(action);
859 Q_ASSERT(action == KAEvent::COMMAND);
860 mCmdEdit->setText(alarmText);
863 /******************************************************************************
864 * Set the read-only status of all non-template controls.
866 void EditCommandAlarmDlg::setReadOnly(bool readOnly)
868 if (!isTemplate() && !ShellProcess::authorised())
869 readOnly = true; // don't allow editing of existing command alarms in kiosk mode
870 mCmdEdit->setReadOnly(readOnly);
871 mCmdExecInTerm->setReadOnly(readOnly);
872 mCmdLogToFile->setReadOnly(readOnly);
873 mCmdDiscardOutput->setReadOnly(readOnly);
874 EditAlarmDlg::setReadOnly(readOnly);
877 /******************************************************************************
878 * Save the state of all controls.
880 void EditCommandAlarmDlg::saveState(const KAEvent* event)
882 EditAlarmDlg::saveState(event);
883 mSavedCmdScript = mCmdEdit->isScript();
884 mSavedCmdOutputRadio = mCmdOutputGroup->checkedButton();
885 mSavedCmdLogFile = mCmdLogFileEdit->text();
888 /******************************************************************************
889 * Check whether any of the controls has changed state since the dialog was
890 * first displayed.
891 * Reply = true if any controls have changed, or if it's a new event.
892 * = false if no controls have changed.
894 bool EditCommandAlarmDlg::type_stateChanged() const
896 if (mSavedCmdScript != mCmdEdit->isScript()
897 || mSavedCmdOutputRadio != mCmdOutputGroup->checkedButton())
898 return true;
899 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
901 if (mSavedCmdLogFile != mCmdLogFileEdit->text())
902 return true;
904 return false;
907 /******************************************************************************
908 * Extract the data in the dialog specific to the alarm type and set up a
909 * KAEvent from it.
911 void EditCommandAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
913 Q_UNUSED(trial);
914 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::COMMAND, lateCancel, getAlarmFlags());
915 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
916 event.setLogFile(mCmdLogFileEdit->text());
919 /******************************************************************************
920 * Get the currently specified alarm flag bits.
922 int EditCommandAlarmDlg::getAlarmFlags() const
924 return EditAlarmDlg::getAlarmFlags()
925 | (mCmdEdit->isScript() ? KAEvent::SCRIPT : 0)
926 | (mCmdOutputGroup->checkedButton() == mCmdExecInTerm ? KAEvent::EXEC_IN_XTERM : 0);
929 /******************************************************************************
930 * Validate and convert command alarm data.
932 bool EditCommandAlarmDlg::type_validate(bool trial)
934 Q_UNUSED(trial);
935 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
937 // Validate the log file name
938 QString file = mCmdLogFileEdit->text();
939 QFileInfo info(file);
940 QDir::setCurrent(QDir::homePath());
941 bool err = file.isEmpty() || info.isDir();
942 if (!err)
944 if (info.exists())
946 err = !info.isWritable();
948 else
950 QFileInfo dirinfo(info.absolutePath()); // get absolute directory path
951 err = (!dirinfo.isDir() || !dirinfo.isWritable());
954 if (err)
956 showMainPage();
957 mCmdLogFileEdit->setFocus();
958 KAMessageBox::sorry(this, i18nc("@info", "Log file must be the name or path of a local file, with write permission."));
959 return false;
961 // Convert the log file to an absolute path
962 mCmdLogFileEdit->setText(info.absoluteFilePath());
964 return true;
967 /******************************************************************************
968 * Tell the user the result of the Try action.
970 void EditCommandAlarmDlg::type_trySuccessMessage(ShellProcess* proc, const QString& text)
972 if (mCmdOutputGroup->checkedButton() != mCmdExecInTerm)
974 theApp()->commandMessage(proc, this);
975 KAMessageBox::information(this, i18nc("@info", "Command executed: <icode>%1</icode>", text));
976 theApp()->commandMessage(proc, 0);
980 /******************************************************************************
981 * Called when one of the command type radio buttons is clicked,
982 * to display the appropriate edit field.
984 void EditCommandAlarmDlg::slotCmdScriptToggled(bool on)
986 if (on)
987 mCmdPadding->hide();
988 else
989 mCmdPadding->show();
992 /******************************************************************************
993 * Clean up the alarm text.
995 bool EditCommandAlarmDlg::checkText(QString& result, bool showErrorMessage) const
997 result = mCmdEdit->text(const_cast<EditCommandAlarmDlg*>(this), showErrorMessage);
998 if (result.isEmpty())
999 return false;
1000 return true;
1004 /*=============================================================================
1005 = Class EditEmailAlarmDlg
1006 = Dialog to edit email alarms.
1007 =============================================================================*/
1009 QString EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf() { return i18nc("@option:check", "Copy email to self"); }
1012 /******************************************************************************
1013 * Constructor.
1014 * Parameters:
1015 * Template = true to edit/create an alarm template
1016 * = false to edit/create an alarm.
1017 * event != to initialise the dialog to show the specified event's data.
1019 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1020 : EditAlarmDlg(Template, KAEvent::EMAIL, parent, getResource),
1021 mEmailRemoveButton(0)
1023 kDebug() << "New";
1024 init(0);
1027 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1028 GetResourceType getResource, bool readOnly)
1029 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
1030 mEmailRemoveButton(0)
1032 kDebug() << "Event.id()";
1033 init(event);
1036 /******************************************************************************
1037 * Return the window caption.
1039 QString EditEmailAlarmDlg::type_caption() const
1041 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Email Alarm Template") : i18nc("@title:window", "Edit Email Alarm Template"))
1042 : (isNewAlarm() ? i18nc("@title:window", "New Email Alarm") : i18nc("@title:window", "Edit Email Alarm"));
1045 /******************************************************************************
1046 * Set up the email alarm dialog controls.
1048 void EditEmailAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1050 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Send the email to the specified addressees now"));
1052 QGridLayout* grid = new QGridLayout();
1053 grid->setMargin(0);
1054 grid->setColumnStretch(1, 1);
1055 frameLayout->addLayout(grid);
1057 mEmailFromList = 0;
1058 if (Preferences::emailFrom() == Preferences::MAIL_FROM_KMAIL)
1060 // Email sender identity
1061 QLabel* label = new QLabel(i18nc("@label:listbox 'From' email address", "From:"), parent);
1062 label->setFixedSize(label->sizeHint());
1063 grid->addWidget(label, 0, 0);
1065 mEmailFromList = new EmailIdCombo(Identities::identityManager(), parent);
1066 mEmailFromList->setMinimumSize(mEmailFromList->sizeHint());
1067 label->setBuddy(mEmailFromList);
1068 mEmailFromList->setWhatsThis(i18nc("@info:whatsthis", "Your email identity, used to identify you as the sender when sending email alarms."));
1069 connect(mEmailFromList, SIGNAL(identityChanged(uint)), SLOT(contentsChanged()));
1070 grid->addWidget(mEmailFromList, 0, 1, 1, 2);
1073 // Email recipients
1074 QLabel* label = new QLabel(i18nc("@label:textbox Email addressee", "To:"), parent);
1075 label->setFixedSize(label->sizeHint());
1076 grid->addWidget(label, 1, 0);
1078 mEmailToEdit = new LineEdit(LineEdit::Emails, parent);
1079 mEmailToEdit->setMinimumSize(mEmailToEdit->sizeHint());
1080 mEmailToEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the addresses of the email recipients. Separate multiple addresses by "
1081 "commas or semicolons."));
1082 connect(mEmailToEdit, SIGNAL(textChanged(QString)), SLOT(contentsChanged()));
1083 grid->addWidget(mEmailToEdit, 1, 1);
1085 mEmailAddressButton = new QPushButton(parent);
1086 mEmailAddressButton->setIcon(SmallIcon("help-contents"));
1087 int size = mEmailAddressButton->sizeHint().height();
1088 mEmailAddressButton->setFixedSize(size, size);
1089 connect(mEmailAddressButton, SIGNAL(clicked()), SLOT(openAddressBook()));
1090 mEmailAddressButton->setToolTip(i18nc("@info:tooltip", "Open address book"));
1091 mEmailAddressButton->setWhatsThis(i18nc("@info:whatsthis", "Select email addresses from your address book."));
1092 grid->addWidget(mEmailAddressButton, 1, 2);
1094 // Email subject
1095 label = new QLabel(i18nc("@label:textbox Email subject", "Subject:"), parent);
1096 label->setFixedSize(label->sizeHint());
1097 grid->addWidget(label, 2, 0);
1099 mEmailSubjectEdit = new LineEdit(parent);
1100 mEmailSubjectEdit->setMinimumSize(mEmailSubjectEdit->sizeHint());
1101 label->setBuddy(mEmailSubjectEdit);
1102 mEmailSubjectEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email subject."));
1103 connect(mEmailSubjectEdit, SIGNAL(textChanged(QString)), SLOT(contentsChanged()));
1104 grid->addWidget(mEmailSubjectEdit, 2, 1, 1, 2);
1106 // Email body
1107 mEmailMessageEdit = new TextEdit(parent);
1108 mEmailMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email message."));
1109 connect(mEmailMessageEdit, SIGNAL(textChanged()), SLOT(contentsChanged()));
1110 frameLayout->addWidget(mEmailMessageEdit);
1112 // Email attachments
1113 grid = new QGridLayout();
1114 grid->setMargin(0);
1115 frameLayout->addLayout(grid);
1116 label = new QLabel(i18nc("@label:listbox", "Attachments:"), parent);
1117 label->setFixedSize(label->sizeHint());
1118 grid->addWidget(label, 0, 0);
1120 mEmailAttachList = new KComboBox(parent);
1121 mEmailAttachList->setEditable(true);
1122 mEmailAttachList->setMinimumSize(mEmailAttachList->sizeHint());
1123 if (mEmailAttachList->lineEdit())
1124 mEmailAttachList->lineEdit()->setReadOnly(true);
1125 //Q3ListBox* list = mEmailAttachList->listBox();
1126 //QRect rect = list->geometry();
1127 //list->setGeometry(rect.left() - 50, rect.top(), rect.width(), rect.height());
1128 label->setBuddy(mEmailAttachList);
1129 mEmailAttachList->setWhatsThis(i18nc("@info:whatsthis", "Files to send as attachments to the email."));
1130 grid->addWidget(mEmailAttachList, 0, 1);
1131 grid->setColumnStretch(1, 1);
1133 mEmailAddAttachButton = new QPushButton(i18nc("@action:button", "Add..."), parent);
1134 connect(mEmailAddAttachButton, SIGNAL(clicked()), SLOT(slotAddAttachment()));
1135 mEmailAddAttachButton->setWhatsThis(i18nc("@info:whatsthis", "Add an attachment to the email."));
1136 grid->addWidget(mEmailAddAttachButton, 0, 2);
1138 mEmailRemoveButton = new QPushButton(i18nc("@action:button", "Remove"), parent);
1139 connect(mEmailRemoveButton, SIGNAL(clicked()), SLOT(slotRemoveAttachment()));
1140 mEmailRemoveButton->setWhatsThis(i18nc("@info:whatsthis", "Remove the highlighted attachment from the email."));
1141 grid->addWidget(mEmailRemoveButton, 1, 2);
1143 // BCC email to sender
1144 mEmailBcc = new CheckBox(i18n_chk_CopyEmailToSelf(), parent);
1145 mEmailBcc->setFixedSize(mEmailBcc->sizeHint());
1146 mEmailBcc->setWhatsThis(i18nc("@info:whatsthis", "If checked, the email will be blind copied to you."));
1147 connect(mEmailBcc, SIGNAL(toggled(bool)), SLOT(contentsChanged()));
1148 grid->addWidget(mEmailBcc, 1, 0, 1, 2, Qt::AlignLeft);
1151 /******************************************************************************
1152 * Initialise the dialog controls from the specified event.
1154 void EditEmailAlarmDlg::type_initValues(const KAEvent* event)
1156 if (event)
1158 // Set the values to those for the specified event
1159 mEmailAttachList->addItems(event->emailAttachments());
1160 mEmailToEdit->setText(event->emailAddresses(", "));
1161 mEmailSubjectEdit->setText(event->emailSubject());
1162 mEmailBcc->setChecked(event->emailBcc());
1163 if (mEmailFromList)
1164 mEmailFromList->setCurrentIdentity(event->emailFromId());
1166 else
1168 // Set the values to their defaults
1169 mEmailBcc->setChecked(Preferences::defaultEmailBcc());
1171 attachmentEnable();
1174 /******************************************************************************
1175 * Enable/disable controls depending on whether any attachments are entered.
1177 void EditEmailAlarmDlg::attachmentEnable()
1179 bool enable = mEmailAttachList->count();
1180 mEmailAttachList->setEnabled(enable);
1181 if (mEmailRemoveButton)
1182 mEmailRemoveButton->setEnabled(enable);
1185 /******************************************************************************
1186 * Set the dialog's action and the action's text.
1188 void EditEmailAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
1190 Q_UNUSED(action);
1191 Q_ASSERT(action == KAEvent::EMAIL);
1192 if (alarmText.isEmail())
1194 mEmailToEdit->setText(alarmText.to());
1195 mEmailSubjectEdit->setText(alarmText.subject());
1196 mEmailMessageEdit->setPlainText(alarmText.body());
1198 else
1199 mEmailMessageEdit->setPlainText(alarmText.displayText());
1202 /******************************************************************************
1203 * Initialise various values in the New Alarm dialogue.
1205 void EditEmailAlarmDlg::setEmailFields(uint fromID, const EmailAddressList& addresses,
1206 const QString& subject, const QStringList& attachments)
1208 if (fromID)
1209 mEmailFromList->setCurrentIdentity(fromID);
1210 if (!addresses.isEmpty())
1211 mEmailToEdit->setText(addresses.join(", "));
1212 if (!subject.isEmpty())
1213 mEmailSubjectEdit->setText(subject);
1214 if (!attachments.isEmpty())
1216 mEmailAttachList->addItems(attachments);
1217 attachmentEnable();
1220 void EditEmailAlarmDlg::setBcc(bool bcc)
1222 mEmailBcc->setChecked(bcc);
1225 /******************************************************************************
1226 * Set the read-only status of all non-template controls.
1228 void EditEmailAlarmDlg::setReadOnly(bool readOnly)
1230 mEmailToEdit->setReadOnly(readOnly);
1231 mEmailSubjectEdit->setReadOnly(readOnly);
1232 mEmailMessageEdit->setReadOnly(readOnly);
1233 mEmailBcc->setReadOnly(readOnly);
1234 if (mEmailFromList)
1235 mEmailFromList->setReadOnly(readOnly);
1236 if (readOnly)
1238 mEmailAddressButton->hide();
1239 mEmailAddAttachButton->hide();
1240 mEmailRemoveButton->hide();
1242 else
1244 mEmailAddressButton->show();
1245 mEmailAddAttachButton->show();
1246 mEmailRemoveButton->show();
1248 EditAlarmDlg::setReadOnly(readOnly);
1251 /******************************************************************************
1252 * Save the state of all controls.
1254 void EditEmailAlarmDlg::saveState(const KAEvent* event)
1256 EditAlarmDlg::saveState(event);
1257 if (mEmailFromList)
1258 mSavedEmailFrom = mEmailFromList->currentIdentityName();
1259 mSavedEmailTo = mEmailToEdit->text();
1260 mSavedEmailSubject = mEmailSubjectEdit->text();
1261 mSavedEmailAttach.clear();
1262 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1263 mSavedEmailAttach += mEmailAttachList->itemText(i);
1264 mSavedEmailBcc = mEmailBcc->isChecked();
1267 /******************************************************************************
1268 * Check whether any of the controls has changed state since the dialog was
1269 * first displayed.
1270 * Reply = true if any controls have changed, or if it's a new event.
1271 * = false if no controls have changed.
1273 bool EditEmailAlarmDlg::type_stateChanged() const
1275 QStringList emailAttach;
1276 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1277 emailAttach += mEmailAttachList->itemText(i);
1278 if ((mEmailFromList && mSavedEmailFrom != mEmailFromList->currentIdentityName())
1279 || mSavedEmailTo != mEmailToEdit->text()
1280 || mSavedEmailSubject != mEmailSubjectEdit->text()
1281 || mSavedEmailAttach != emailAttach
1282 || mSavedEmailBcc != mEmailBcc->isChecked())
1283 return true;
1284 return false;
1287 /******************************************************************************
1288 * Extract the data in the dialog specific to the alarm type and set up a
1289 * KAEvent from it.
1291 void EditEmailAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1293 Q_UNUSED(trial);
1294 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::EMAIL, lateCancel, getAlarmFlags());
1295 uint from = mEmailFromList ? mEmailFromList->currentIdentity() : 0;
1296 event.setEmail(from, mEmailAddresses, mEmailSubjectEdit->text(), mEmailAttachments);
1299 /******************************************************************************
1300 * Get the currently specified alarm flag bits.
1302 int EditEmailAlarmDlg::getAlarmFlags() const
1304 return EditAlarmDlg::getAlarmFlags()
1305 | (mEmailBcc->isChecked() ? KAEvent::EMAIL_BCC : 0);
1308 /******************************************************************************
1309 * Convert the email addresses to a list, and validate them. Convert the email
1310 * attachments to a list.
1312 bool EditEmailAlarmDlg::type_validate(bool trial)
1314 QString addrs = mEmailToEdit->text();
1315 if (addrs.isEmpty())
1316 mEmailAddresses.clear();
1317 else
1319 QString bad = KAMail::convertAddresses(addrs, mEmailAddresses);
1320 if (!bad.isEmpty())
1322 mEmailToEdit->setFocus();
1323 KAMessageBox::error(this, i18nc("@info", "Invalid email address: <email>%1</email>", bad));
1324 return false;
1327 if (mEmailAddresses.isEmpty())
1329 mEmailToEdit->setFocus();
1330 KAMessageBox::error(this, i18nc("@info", "No email address specified"));
1331 return false;
1334 mEmailAttachments.clear();
1335 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1337 QString att = mEmailAttachList->itemText(i);
1338 switch (KAMail::checkAttachment(att))
1340 case 1:
1341 mEmailAttachments.append(att);
1342 break;
1343 case 0:
1344 break; // empty
1345 case -1:
1346 mEmailAttachList->setFocus();
1347 KAMessageBox::error(this, i18nc("@info", "Invalid email attachment: <filename>%1</filename>", att));
1348 return false;
1351 if (trial && KAMessageBox::warningContinueCancel(this, i18nc("@info", "Do you really want to send the email now to the specified recipient(s)?"),
1352 i18nc("@action:button", "Confirm Email"), KGuiItem(i18nc("@action:button", "Send"))) != KMessageBox::Continue)
1353 return false;
1354 return true;
1357 /******************************************************************************
1358 * Tell the user the result of the Try action.
1360 void EditEmailAlarmDlg::type_trySuccessMessage(ShellProcess*, const QString&)
1362 QString msg;
1363 QString to = mEmailAddresses.join("<nl/>");
1364 to.replace('<', "&lt;");
1365 to.replace('>', "&gt;");
1366 if (mEmailBcc->isChecked())
1367 msg = "<qt>" + i18nc("@info", "Email sent to:<nl/>%1<nl/>Bcc: <email>%2</email>",
1368 to, Preferences::emailBccAddress()) + "</qt>";
1369 else
1370 msg = "<qt>" + i18nc("@info", "Email sent to:<nl/>%1", to) + "</qt>";
1371 KAMessageBox::information(this, msg);
1374 /******************************************************************************
1375 * Get a selection from the Address Book.
1377 void EditEmailAlarmDlg::openAddressBook()
1379 // Use AutoQPointer to guard against crash on application exit while
1380 // the dialogue is still open. It prevents double deletion (both on
1381 // deletion of MainWindow, and on return from this function).
1382 AutoQPointer<Akonadi::EmailAddressSelectionDialog> dlg = new Akonadi::EmailAddressSelectionDialog(this);
1383 if (dlg->exec() != QDialog::Accepted)
1384 return;
1386 Akonadi::EmailAddressSelection::List selections = dlg->selectedAddresses();
1387 if (selections.isEmpty())
1388 return;
1389 Person person(selections.first().name(), selections.first().email());
1390 QString addrs = mEmailToEdit->text().trimmed();
1391 if (!addrs.isEmpty())
1392 addrs += ", ";
1393 addrs += person.fullName();
1394 mEmailToEdit->setText(addrs);
1397 /******************************************************************************
1398 * Select a file to attach to the email.
1400 void EditEmailAlarmDlg::slotAddAttachment()
1402 QString url = KAlarm::browseFile(i18nc("@title:window", "Choose File to Attach"), mAttachDefaultDir, QString(),
1403 QString(), KFile::ExistingOnly, this);
1404 if (!url.isEmpty())
1406 mEmailAttachList->addItem(url);
1407 mEmailAttachList->setCurrentIndex(mEmailAttachList->count() - 1); // select the new item
1408 mEmailRemoveButton->setEnabled(true);
1409 mEmailAttachList->setEnabled(true);
1410 contentsChanged();
1414 /******************************************************************************
1415 * Remove the currently selected attachment from the email.
1417 void EditEmailAlarmDlg::slotRemoveAttachment()
1419 int item = mEmailAttachList->currentIndex();
1420 mEmailAttachList->removeItem(item);
1421 int count = mEmailAttachList->count();
1422 if (item >= count)
1423 mEmailAttachList->setCurrentIndex(count - 1);
1424 if (!count)
1426 mEmailRemoveButton->setEnabled(false);
1427 mEmailAttachList->setEnabled(false);
1429 contentsChanged();
1432 /******************************************************************************
1433 * Clean up the alarm text.
1435 bool EditEmailAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1437 Q_UNUSED(showErrorMessage);
1438 result = mEmailMessageEdit->toPlainText();
1439 return true;
1443 /*=============================================================================
1444 = Class EditAudioAlarmDlg
1445 = Dialog to edit audio alarms with no display window.
1446 =============================================================================*/
1448 /******************************************************************************
1449 * Constructor.
1450 * Parameters:
1451 * Template = true to edit/create an alarm template
1452 * = false to edit/create an alarm.
1453 * event != to initialise the dialog to show the specified event's data.
1455 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1456 : EditAlarmDlg(Template, KAEvent::AUDIO, parent, getResource)
1458 kDebug() << "New";
1459 init(0);
1462 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1463 GetResourceType getResource, bool readOnly)
1464 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly)
1466 kDebug() << "Event.id()";
1467 init(event);
1470 /******************************************************************************
1471 * Return the window caption.
1473 QString EditAudioAlarmDlg::type_caption() const
1475 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm Template") : i18nc("@title:window", "Edit Audio Alarm Template"))
1476 : (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm") : i18nc("@title:window", "Edit Audio Alarm"));
1479 /******************************************************************************
1480 * Set up the dialog controls common to display alarms.
1482 void EditAudioAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1484 // File name edit box
1485 mSoundConfig = new SoundWidget(false, true, parent);
1486 if (isTemplate())
1487 mSoundConfig->setAllowEmptyFile();
1488 connect(mSoundConfig, SIGNAL(changed()), SLOT(contentsChanged()));
1489 frameLayout->addWidget(mSoundConfig);
1491 // Top-adjust the controls
1492 mPadding = new KHBox(parent);
1493 mPadding->setMargin(0);
1494 frameLayout->addWidget(mPadding);
1495 frameLayout->setStretchFactor(mPadding, 1);
1498 /******************************************************************************
1499 * Initialise the dialog controls from the specified event.
1501 void EditAudioAlarmDlg::type_initValues(const KAEvent* event)
1503 if (event)
1505 mSoundConfig->set(event->audioFile(), event->soundVolume(), event->fadeVolume(), event->fadeSeconds(),
1506 (event->flags() & KAEvent::REPEAT_SOUND));
1508 else
1510 // Set the values to their defaults
1511 mSoundConfig->set(Preferences::defaultSoundFile(), Preferences::defaultSoundVolume());
1515 /******************************************************************************
1516 * Initialise various values in the New Alarm dialogue.
1518 void EditAudioAlarmDlg::setAudio(const QString& file, float volume)
1520 mSoundConfig->set(file, volume);
1523 /******************************************************************************
1524 * Set the dialog's action and the action's text.
1526 void EditAudioAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
1528 Q_UNUSED(action);
1529 Q_ASSERT(action == KAEvent::AUDIO);
1530 mSoundConfig->set(alarmText.displayText(), Preferences::defaultSoundVolume());
1533 /******************************************************************************
1534 * Set the read-only status of all non-template controls.
1536 void EditAudioAlarmDlg::setReadOnly(bool readOnly)
1538 mSoundConfig->setReadOnly(readOnly);
1539 EditAlarmDlg::setReadOnly(readOnly);
1542 /******************************************************************************
1543 * Save the state of all controls.
1545 void EditAudioAlarmDlg::saveState(const KAEvent* event)
1547 EditAlarmDlg::saveState(event);
1548 mSavedFile = mSoundConfig->fileName();
1549 mSavedRepeat = mSoundConfig->getVolume(mSavedVolume, mSavedFadeVolume, mSavedFadeSeconds);
1552 /******************************************************************************
1553 * Check whether any of the controls has changed state since the dialog was
1554 * first displayed.
1555 * Reply = true if any controls have changed, or if it's a new event.
1556 * = false if no controls have changed.
1558 bool EditAudioAlarmDlg::type_stateChanged() const
1560 if (mSavedFile != mSoundConfig->fileName())
1561 return true;
1562 if (!mSavedFile.isEmpty() || isTemplate())
1564 float volume, fadeVolume;
1565 int fadeSecs;
1566 if (mSavedRepeat != mSoundConfig->getVolume(volume, fadeVolume, fadeSecs)
1567 || mSavedVolume != volume
1568 || mSavedFadeVolume != fadeVolume
1569 || mSavedFadeSeconds != fadeSecs)
1570 return true;
1572 return false;
1575 /******************************************************************************
1576 * Extract the data in the dialog specific to the alarm type and set up a
1577 * KAEvent from it.
1579 void EditAudioAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1581 Q_UNUSED(text);
1582 Q_UNUSED(trial);
1583 event.set(dt, QString(), QColor(), QColor(), QFont(), KAEvent::AUDIO, lateCancel, getAlarmFlags());
1584 float volume, fadeVolume;
1585 int fadeSecs;
1586 mSoundConfig->getVolume(volume, fadeVolume, fadeSecs);
1587 KUrl url;
1588 mSoundConfig->file(url, false);
1589 event.setAudioFile(url.prettyUrl(), volume, fadeVolume, fadeSecs, isTemplate());
1592 /******************************************************************************
1593 * Get the currently specified alarm flag bits.
1595 int EditAudioAlarmDlg::getAlarmFlags() const
1597 return EditAlarmDlg::getAlarmFlags()
1598 | (mSoundConfig->getRepeat() ? KAEvent::REPEAT_SOUND : 0);
1601 /******************************************************************************
1602 * Check whether the file name is valid.
1604 bool EditAudioAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1606 KUrl url;
1607 if (!mSoundConfig->file(url, showErrorMessage))
1609 result.clear();
1610 return false;
1612 result = url.pathOrUrl();
1613 return true;
1617 /*=============================================================================
1618 = Class CommandEdit
1619 = A widget to allow entry of a command or a command script.
1620 =============================================================================*/
1621 CommandEdit::CommandEdit(QWidget* parent)
1622 : QWidget(parent)
1624 QVBoxLayout* vlayout = new QVBoxLayout(this);
1625 vlayout->setMargin(0);
1626 vlayout->setSpacing(KDialog::spacingHint());
1627 mTypeScript = new CheckBox(EditCommandAlarmDlg::i18n_chk_EnterScript(), this);
1628 mTypeScript->setFixedSize(mTypeScript->sizeHint());
1629 mTypeScript->setWhatsThis(i18nc("@info:whatsthis", "Check to enter the contents of a script instead of a shell command line"));
1630 connect(mTypeScript, SIGNAL(toggled(bool)), SLOT(slotCmdScriptToggled(bool)));
1631 connect(mTypeScript, SIGNAL(toggled(bool)), SIGNAL(changed()));
1632 vlayout->addWidget(mTypeScript, 0, Qt::AlignLeft);
1634 mCommandEdit = new LineEdit(LineEdit::Url, this);
1635 mCommandEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter a shell command to execute."));
1636 connect(mCommandEdit, SIGNAL(textChanged(QString)), SIGNAL(changed()));
1637 vlayout->addWidget(mCommandEdit);
1639 mScriptEdit = new TextEdit(this);
1640 mScriptEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the contents of a script to execute"));
1641 connect(mScriptEdit, SIGNAL(textChanged()), SIGNAL(changed()));
1642 vlayout->addWidget(mScriptEdit);
1644 slotCmdScriptToggled(mTypeScript->isChecked());
1647 /******************************************************************************
1648 * Initialise the widget controls from the specified event.
1650 void CommandEdit::setScript(bool script)
1652 mTypeScript->setChecked(script);
1655 bool CommandEdit::isScript() const
1657 return mTypeScript->isChecked();
1660 /******************************************************************************
1661 * Set the widget's text.
1663 void CommandEdit::setText(const AlarmText& alarmText)
1665 QString text = alarmText.displayText();
1666 bool script = alarmText.isScript();
1667 mTypeScript->setChecked(script);
1668 if (script)
1669 mScriptEdit->setPlainText(text);
1670 else
1671 mCommandEdit->setText(KAlarm::pathOrUrl(text));
1674 /******************************************************************************
1675 * Return the widget's text.
1677 QString CommandEdit::text() const
1679 QString result;
1680 if (mTypeScript->isChecked())
1681 result = mScriptEdit->toPlainText();
1682 else
1683 result = mCommandEdit->text();
1684 return result.trimmed();
1687 /******************************************************************************
1688 * Return the alarm text.
1689 * If 'showErrorMessage' is true and the text is empty, an error message is
1690 * displayed.
1692 QString CommandEdit::text(EditAlarmDlg* dlg, bool showErrorMessage) const
1694 QString result = text();
1695 if (showErrorMessage && result.isEmpty())
1696 KAMessageBox::sorry(dlg, i18nc("@info", "Please enter a command or script to execute"));
1697 return result;
1700 /******************************************************************************
1701 * Set the read-only status of all controls.
1703 void CommandEdit::setReadOnly(bool readOnly)
1705 mTypeScript->setReadOnly(readOnly);
1706 mCommandEdit->setReadOnly(readOnly);
1707 mScriptEdit->setReadOnly(readOnly);
1710 /******************************************************************************
1711 * Called when one of the command type radio buttons is clicked,
1712 * to display the appropriate edit field.
1714 void CommandEdit::slotCmdScriptToggled(bool on)
1716 if (on)
1718 mCommandEdit->hide();
1719 mScriptEdit->show();
1720 mScriptEdit->setFocus();
1722 else
1724 mScriptEdit->hide();
1725 mCommandEdit->show();
1726 mCommandEdit->setFocus();
1728 emit scriptToggled(on);
1731 /******************************************************************************
1732 * Returns the minimum size of the widget.
1734 QSize CommandEdit::minimumSizeHint() const
1736 QSize t(mTypeScript->minimumSizeHint());
1737 QSize s(mCommandEdit->minimumSizeHint().expandedTo(mScriptEdit->minimumSizeHint()));
1738 s.setHeight(s.height() + KDialog::spacingHint() + t.height());
1739 if (s.width() < t.width())
1740 s.setWidth(t.width());
1741 return s;
1746 /*=============================================================================
1747 = Class TextEdit
1748 = A text edit field with a minimum height of 3 text lines.
1749 =============================================================================*/
1750 TextEdit::TextEdit(QWidget* parent)
1751 : KTextEdit(parent)
1753 QSize tsize = sizeHint();
1754 tsize.setHeight(fontMetrics().lineSpacing()*13/4 + 2*frameWidth());
1755 setMinimumSize(tsize);
1758 void TextEdit::dragEnterEvent(QDragEnterEvent* e)
1760 #ifdef USE_AKONADI
1761 if (KCalUtils::ICalDrag::canDecode(e->mimeData()))
1762 #else
1763 if (KCal::ICalDrag::canDecode(e->mimeData()))
1764 #endif
1765 e->ignore(); // don't accept "text/calendar" objects
1766 KTextEdit::dragEnterEvent(e);
1769 // vim: et sw=4: