Remove KActionCollection::setComponentData: this does not work on a KActionCollection...
[kdepim.git] / kalarm / editdlgtypes.cpp
bloba2edd8324eb122e9dd127e21fd2edcf0670f8629
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 "pickfileradio.h"
39 #include "preferences.h"
40 #include "radiobutton.h"
41 #include "reminder.h"
42 #include "shellprocess.h"
43 #include "soundpicker.h"
44 #include "sounddlg.h"
45 #include "specialactions.h"
46 #include "templatepickdlg.h"
47 #include "timespinbox.h"
49 #include <akonadi/contact/emailaddressselectiondialog.h>
50 #ifdef USE_AKONADI
51 #include <kcalcore/person.h>
52 #include <kcalutils/icaldrag.h>
53 using namespace KCalCore;
54 #else
55 #include <kcal/person.h>
56 #include <kcal/icaldrag.h>
57 using namespace KCal;
58 #endif
60 #include <klocale.h>
61 #include <kiconloader.h>
62 #include <kio/netaccess.h>
63 #include <kfileitem.h>
64 #include <kmessagebox.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>
77 enum { tTEXT, tFILE, tCOMMAND }; // order of mTypeCombo items
80 /*=============================================================================
81 = Class PickLogFileRadio
82 =============================================================================*/
83 class PickLogFileRadio : public PickFileRadio
85 public:
86 PickLogFileRadio(QPushButton* b, LineEdit* e, const QString& text, ButtonGroup* group, QWidget* parent)
87 : PickFileRadio(b, e, text, group, parent) { }
88 virtual QString pickFile() // called when browse button is pressed to select a log file
90 return KAlarm::browseFile(i18nc("@title:window", "Choose Log File"), mDefaultDir, fileEdit()->text(), QString(),
91 KFile::LocalOnly, parentWidget());
93 private:
94 QString mDefaultDir; // default directory for log file browse button
98 /*=============================================================================
99 = Class EditDisplayAlarmDlg
100 = Dialog to edit display alarms.
101 =============================================================================*/
103 QString EditDisplayAlarmDlg::i18n_chk_ConfirmAck() { return i18nc("@option:check", "Confirm acknowledgment"); }
106 /******************************************************************************
107 * Constructor.
108 * Parameters:
109 * Template = true to edit/create an alarm template
110 * = false to edit/create an alarm.
111 * event != to initialise the dialog to show the specified event's data.
113 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
114 : EditAlarmDlg(Template, KAEvent::MESSAGE, parent, getResource),
115 mSpecialActionsButton(0),
116 mReminderDeferral(false),
117 mReminderArchived(false)
119 kDebug() << "New";
120 init(0);
123 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
124 GetResourceType getResource, bool readOnly)
125 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
126 mSpecialActionsButton(0),
127 mReminderDeferral(false),
128 mReminderArchived(false)
130 kDebug() << "Event.id()";
131 init(event);
134 /******************************************************************************
135 * Return the window caption.
137 QString EditDisplayAlarmDlg::type_caption() const
139 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Display Alarm Template") : i18nc("@title:window", "Edit Display Alarm Template"))
140 : (isNewAlarm() ? i18nc("@title:window", "New Display Alarm") : i18nc("@title:window", "Edit Display Alarm"));
143 /******************************************************************************
144 * Set up the dialog controls common to display alarms.
146 void EditDisplayAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
148 // Display type combo box
149 KHBox* box = new KHBox(parent); // to group widgets for QWhatsThis text
150 box->setMargin(0);
151 box->setSpacing(KDialog::spacingHint());
152 QLabel* label = new QLabel(i18nc("@label:listbox", "Display type:"), box);
153 label->setFixedSize(label->sizeHint());
154 mTypeCombo = new ComboBox(box);
155 QString textItem = i18nc("@item:inlistbox", "Text message");
156 QString fileItem = i18nc("@item:inlistbox", "File contents");
157 QString commandItem = i18nc("@item:inlistbox", "Command output");
158 mTypeCombo->addItem(textItem); // index = tTEXT
159 mTypeCombo->addItem(fileItem); // index = tFILE
160 mTypeCombo->addItem(commandItem); // index = tCOMMAND
161 mTypeCombo->setFixedSize(mTypeCombo->sizeHint());
162 mTypeCombo->setCurrentIndex(-1); // ensure slotAlarmTypeChanged() is called when index is set
163 connect(mTypeCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotAlarmTypeChanged(int)));
164 connect(mTypeCombo, SIGNAL(currentIndexChanged(int)), SLOT(contentsChanged()));
165 label->setBuddy(mTypeCombo);
166 box->setWhatsThis(i18nc("@info:whatsthis", "<para>Select what the alarm should display:"
167 "<list><item><interface>%1</interface>: the alarm will display the text message you type in.</item>"
168 "<item><interface>%2</interface>: the alarm will display the contents of a text or image file.</item>"
169 "<item><interface>%3</interface>: the alarm will display the output from a command.</item></list></para>",
170 textItem, fileItem, commandItem));
171 box->setStretchFactor(new QWidget(box), 1); // left adjust the control
172 frameLayout->addWidget(box);
174 // Text message edit box
175 mTextMessageEdit = new TextEdit(parent);
176 mTextMessageEdit->setLineWrapMode(KTextEdit::NoWrap);
177 mTextMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the text of the alarm message. It may be multi-line."));
178 connect(mTextMessageEdit, SIGNAL(textChanged()), SLOT(contentsChanged()));
179 frameLayout->addWidget(mTextMessageEdit);
181 // File name edit box
182 mFileBox = new KHBox(parent);
183 mFileBox->setMargin(0);
184 frameLayout->addWidget(mFileBox);
185 mFileMessageEdit = new LineEdit(LineEdit::Url, mFileBox);
186 mFileMessageEdit->setAcceptDrops(true);
187 mFileMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or URL of a text or image file to display."));
188 connect(mFileMessageEdit, SIGNAL(textChanged(const QString&)), SLOT(contentsChanged()));
190 // File browse button
191 mFileBrowseButton = new QPushButton(mFileBox);
192 mFileBrowseButton->setIcon(SmallIcon("document-open"));
193 int size = mFileBrowseButton->sizeHint().height();
194 mFileBrowseButton->setFixedSize(size, size);
195 mFileBrowseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
196 mFileBrowseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a text or image file to display."));
197 connect(mFileBrowseButton, SIGNAL(clicked()), SLOT(slotPickFile()));
199 // Command type checkbox and edit box
200 mCmdEdit = new CommandEdit(parent);
201 connect(mCmdEdit, SIGNAL(scriptToggled(bool)), SLOT(slotCmdScriptToggled(bool)));
202 connect(mCmdEdit, SIGNAL(changed()), SLOT(contentsChanged()));
203 frameLayout->addWidget(mCmdEdit);
205 // Sound checkbox and file selector
206 QHBoxLayout* hlayout = new QHBoxLayout();
207 hlayout->setMargin(0);
208 frameLayout->addLayout(hlayout);
209 mSoundPicker = new SoundPicker(parent);
210 mSoundPicker->setFixedSize(mSoundPicker->sizeHint());
211 connect(mSoundPicker, SIGNAL(changed()), SLOT(contentsChanged()));
212 hlayout->addWidget(mSoundPicker);
213 hlayout->addSpacing(2*spacingHint());
214 hlayout->addStretch();
216 // Font and colour choice button and sample text
217 mFontColourButton = new FontColourButton(parent);
218 mFontColourButton->setMaximumHeight(mFontColourButton->sizeHint().height() * 3/2);
219 hlayout->addWidget(mFontColourButton);
220 connect(mFontColourButton, SIGNAL(selected(const QColor&, const QColor&)), SLOT(setColours(const QColor&, const QColor&)));
221 connect(mFontColourButton, SIGNAL(selected(const QColor&, const QColor&)), SLOT(contentsChanged()));
223 if (ShellProcess::authorised()) // don't display if shell commands not allowed (e.g. kiosk mode)
225 // Special actions button
226 mSpecialActionsButton = new SpecialActionsButton(false, parent);
227 mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
228 connect(mSpecialActionsButton, SIGNAL(selected()), SLOT(contentsChanged()));
229 frameLayout->addWidget(mSpecialActionsButton, 0, Qt::AlignRight);
232 // Top-adjust the controls
233 mFilePadding = new KHBox(parent);
234 mFilePadding->setMargin(0);
235 frameLayout->addWidget(mFilePadding);
236 frameLayout->setStretchFactor(mFilePadding, 1);
239 /******************************************************************************
240 * Create a reminder control.
242 Reminder* EditDisplayAlarmDlg::createReminder(QWidget* parent)
244 static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of or after the main alarm to display a reminder alarm.");
245 return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of or after the main alarm time(s)."),
246 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()),
247 i18nc("@info:whatsthis", "Select whether the reminder should be triggered before or after the main alarm"),
248 true, true, parent);
251 /******************************************************************************
252 * Create an "acknowledgement confirmation required" checkbox.
254 CheckBox* EditDisplayAlarmDlg::createConfirmAckCheckbox(QWidget* parent)
256 CheckBox* confirmAck = new CheckBox(i18n_chk_ConfirmAck(), parent);
257 confirmAck->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation when you acknowledge the alarm."));
258 return confirmAck;
261 /******************************************************************************
262 * Initialise the dialog controls from the specified event.
264 void EditDisplayAlarmDlg::type_initValues(const KAEvent* event)
266 mKMailSerialNumber = 0;
267 lateCancel()->showAutoClose(true);
268 if (event)
270 if (mAlarmType == KAEvent::MESSAGE && event->kmailSerialNumber()
271 && AlarmText::checkIfEmail(event->cleanText()))
272 mKMailSerialNumber = event->kmailSerialNumber();
273 lateCancel()->setAutoClose(event->autoClose());
274 if (event->useDefaultFont())
275 mFontColourButton->setDefaultFont();
276 else
277 mFontColourButton->setFont(event->font());
278 mFontColourButton->setBgColour(event->bgColour());
279 mFontColourButton->setFgColour(event->fgColour());
280 setColours(event->fgColour(), event->bgColour());
281 mConfirmAck->setChecked(event->confirmAck());
282 bool recurs = event->recurs();
283 int reminderMins = event->reminderMinutes();
284 if (reminderMins > 0 && !event->reminderActive())
285 reminderMins = 0; // don't show advance reminder which has already passed
286 if (!reminderMins)
288 if (event->reminderDeferral() && !recurs)
290 reminderMins = event->deferDateTime().minsTo(event->mainDateTime());
291 mReminderDeferral = true;
293 else if (event->reminderMinutes() && recurs)
295 reminderMins = event->reminderMinutes();
296 mReminderArchived = true;
299 reminder()->setMinutes(reminderMins, dateOnly());
300 reminder()->setOnceOnly(event->reminderOnceOnly());
301 reminder()->enableOnceOnly(recurs);
302 if (mSpecialActionsButton)
303 mSpecialActionsButton->setActions(event->preAction(), event->postAction(), event->cancelOnPreActionError(), event->dontShowPreActionError());
304 Preferences::SoundType soundType = event->speak() ? Preferences::Sound_Speak
305 : event->beep() ? Preferences::Sound_Beep
306 : !event->audioFile().isEmpty() ? Preferences::Sound_File
307 : Preferences::Sound_None;
308 mSoundPicker->set(soundType, event->audioFile(), event->soundVolume(),
309 event->fadeVolume(), event->fadeSeconds(), event->repeatSound());
311 else
313 // Set the values to their defaults
314 if (!ShellProcess::authorised())
316 // Don't allow shell commands in kiosk mode
317 if (mSpecialActionsButton)
318 mSpecialActionsButton->setEnabled(false);
320 lateCancel()->setAutoClose(Preferences::defaultAutoClose());
321 mTypeCombo->setCurrentIndex(0);
322 mFontColourButton->setDefaultFont();
323 mFontColourButton->setBgColour(Preferences::defaultBgColour());
324 mFontColourButton->setFgColour(Preferences::defaultFgColour());
325 setColours(Preferences::defaultFgColour(), Preferences::defaultBgColour());
326 mConfirmAck->setChecked(Preferences::defaultConfirmAck());
327 reminder()->setMinutes(0, false);
328 reminder()->enableOnceOnly(isTimedRecurrence()); // must be called after mRecurrenceEdit is set up
329 if (mSpecialActionsButton)
330 mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(),
331 Preferences::defaultCancelOnPreActionError(), Preferences::defaultDontShowPreActionError());
332 mSoundPicker->set(Preferences::defaultSoundType(), Preferences::defaultSoundFile(),
333 Preferences::defaultSoundVolume(), -1, 0, Preferences::defaultSoundRepeat());
337 /******************************************************************************
338 * Called when the More/Less Options button is clicked.
339 * Show/hide the optional options.
341 void EditDisplayAlarmDlg::type_showOptions(bool more)
343 if (mSpecialActionsButton)
345 if (more)
346 mSpecialActionsButton->show();
347 else
348 mSpecialActionsButton->hide();
352 /******************************************************************************
353 * Called when the font/color button has been clicked.
354 * Set the colors in the message text entry control.
356 void EditDisplayAlarmDlg::setColours(const QColor& fgColour, const QColor& bgColour)
358 QPalette pal = mTextMessageEdit->palette();
359 pal.setColor(mTextMessageEdit->backgroundRole(), bgColour);
360 pal.setColor(QPalette::Text, fgColour);
361 mTextMessageEdit->setPalette(pal);
362 pal = mTextMessageEdit->viewport()->palette();
363 pal.setColor(mTextMessageEdit->viewport()->backgroundRole(), bgColour);
364 pal.setColor(QPalette::Text, fgColour);
365 mTextMessageEdit->viewport()->setPalette(pal);
366 // Change the color of existing text
367 QTextCursor cursor = mTextMessageEdit->textCursor();
368 mTextMessageEdit->selectAll();
369 mTextMessageEdit->setTextColor(fgColour);
370 mTextMessageEdit->setTextCursor(cursor);
373 /******************************************************************************
374 * Set the dialog's action and the action's text.
376 void EditDisplayAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText)
378 QString text = alarmText.displayText();
379 switch (action)
381 case KAEvent::MESSAGE:
382 mTypeCombo->setCurrentIndex(tTEXT);
383 mTextMessageEdit->setPlainText(text);
384 mKMailSerialNumber = alarmText.isEmail() ? alarmText.kmailSerialNumber() : 0;
385 break;
386 case KAEvent::FILE:
387 mTypeCombo->setCurrentIndex(tFILE);
388 mFileMessageEdit->setText(text);
389 break;
390 case KAEvent::COMMAND:
391 mTypeCombo->setCurrentIndex(tCOMMAND);
392 mCmdEdit->setText(alarmText);
393 break;
394 default:
395 Q_ASSERT(0);
396 break;
400 /******************************************************************************
401 * Initialise various values in the New Alarm dialogue.
403 void EditDisplayAlarmDlg::setBgColour(const QColor& colour)
405 mFontColourButton->setBgColour(colour);
406 setColours(mFontColourButton->fgColour(), colour);
408 void EditDisplayAlarmDlg::setFgColour(const QColor& colour)
410 mFontColourButton->setFgColour(colour);
411 setColours(colour, mFontColourButton->bgColour());
413 void EditDisplayAlarmDlg::setConfirmAck(bool confirm)
415 mConfirmAck->setChecked(confirm);
417 void EditDisplayAlarmDlg::setAutoClose(bool close)
419 lateCancel()->setAutoClose(close);
421 void EditDisplayAlarmDlg::setAudio(Preferences::SoundType type, const QString& file, float volume, bool repeat)
423 mSoundPicker->set(type, file, volume, -1, 0, repeat);
425 void EditDisplayAlarmDlg::setReminder(int minutes, bool onceOnly)
427 reminder()->setMinutes(minutes, dateOnly());
428 reminder()->setOnceOnly(onceOnly);
429 reminder()->enableOnceOnly(isTimedRecurrence());
432 /******************************************************************************
433 * Set the read-only status of all non-template controls.
435 void EditDisplayAlarmDlg::setReadOnly(bool readOnly)
437 mTypeCombo->setReadOnly(readOnly);
438 mTextMessageEdit->setReadOnly(readOnly);
439 mFileMessageEdit->setReadOnly(readOnly);
440 mCmdEdit->setReadOnly(readOnly);
441 mFontColourButton->setReadOnly(readOnly);
442 mSoundPicker->setReadOnly(readOnly);
443 mConfirmAck->setReadOnly(readOnly);
444 reminder()->setReadOnly(readOnly);
445 if (mSpecialActionsButton)
446 mSpecialActionsButton->setReadOnly(readOnly);
447 if (readOnly)
448 mFileBrowseButton->hide();
449 else
450 mFileBrowseButton->show();
451 EditAlarmDlg::setReadOnly(readOnly);
454 /******************************************************************************
455 * Save the state of all controls.
457 void EditDisplayAlarmDlg::saveState(const KAEvent* event)
459 EditAlarmDlg::saveState(event);
460 mSavedType = mTypeCombo->currentIndex();
461 mSavedCmdScript = mCmdEdit->isScript();
462 mSavedSoundType = mSoundPicker->sound();
463 mSavedSoundFile = mSoundPicker->file();
464 mSavedSoundVolume = mSoundPicker->volume(mSavedSoundFadeVolume, mSavedSoundFadeSeconds);
465 mSavedRepeatSound = mSoundPicker->repeat();
466 mSavedConfirmAck = mConfirmAck->isChecked();
467 mSavedFont = mFontColourButton->font();
468 mSavedFgColour = mFontColourButton->fgColour();
469 mSavedBgColour = mFontColourButton->bgColour();
470 mSavedReminder = reminder()->minutes();
471 mSavedOnceOnly = reminder()->isOnceOnly();
472 mSavedAutoClose = lateCancel()->isAutoClose();
473 if (mSpecialActionsButton)
475 mSavedPreAction = mSpecialActionsButton->preAction();
476 mSavedPostAction = mSpecialActionsButton->postAction();
477 mSavedPreActionCancel = mSpecialActionsButton->cancelOnError();
481 /******************************************************************************
482 * Check whether any of the controls has changed state since the dialog was
483 * first displayed.
484 * Reply = true if any controls have changed, or if it's a new event.
485 * = false if no controls have changed.
487 bool EditDisplayAlarmDlg::type_stateChanged() const
489 if (mSavedType != mTypeCombo->currentIndex()
490 || mSavedCmdScript != mCmdEdit->isScript()
491 || mSavedSoundType != mSoundPicker->sound()
492 || mSavedConfirmAck != mConfirmAck->isChecked()
493 || mSavedFont != mFontColourButton->font()
494 || mSavedFgColour != mFontColourButton->fgColour()
495 || mSavedBgColour != mFontColourButton->bgColour()
496 || mSavedReminder != reminder()->minutes()
497 || mSavedOnceOnly != reminder()->isOnceOnly()
498 || mSavedAutoClose != lateCancel()->isAutoClose())
499 return true;
500 if (mSpecialActionsButton)
502 if (mSavedPreAction != mSpecialActionsButton->preAction()
503 || mSavedPostAction != mSpecialActionsButton->postAction()
504 || mSavedPreActionCancel != mSpecialActionsButton->cancelOnError())
505 return true;
507 if (mSavedSoundType == Preferences::Sound_File)
509 if (mSavedSoundFile != mSoundPicker->file())
510 return true;
511 if (!mSavedSoundFile.isEmpty())
513 float fadeVolume;
514 int fadeSecs;
515 if (mSavedRepeatSound != mSoundPicker->repeat()
516 || mSavedSoundVolume != mSoundPicker->volume(fadeVolume, fadeSecs)
517 || mSavedSoundFadeVolume != fadeVolume
518 || mSavedSoundFadeSeconds != fadeSecs)
519 return true;
522 return false;
525 /******************************************************************************
526 * Extract the data in the dialog specific to the alarm type and set up a
527 * KAEvent from it.
529 void EditDisplayAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
531 KAEvent::Action type;
532 switch (mTypeCombo->currentIndex())
534 case tFILE: type = KAEvent::FILE; break;
535 case tCOMMAND: type = KAEvent::COMMAND; break;
536 default:
537 case tTEXT: type = KAEvent::MESSAGE; break;
539 event.set(dt, text, mFontColourButton->bgColour(), mFontColourButton->fgColour(), mFontColourButton->font(),
540 type, lateCancel, getAlarmFlags());
541 if (type == KAEvent::MESSAGE)
543 if (AlarmText::checkIfEmail(text))
544 event.setKMailSerialNumber(mKMailSerialNumber);
546 float fadeVolume;
547 int fadeSecs;
548 float volume = mSoundPicker->volume(fadeVolume, fadeSecs);
549 event.setAudioFile(mSoundPicker->file().prettyUrl(), volume, fadeVolume, fadeSecs);
550 if (!trial && reminder()->isEnabled())
551 event.setReminder(reminder()->minutes(), reminder()->isOnceOnly());
552 if (mSpecialActionsButton && mSpecialActionsButton->isEnabled())
553 event.setActions(mSpecialActionsButton->preAction(), mSpecialActionsButton->postAction(),
554 mSpecialActionsButton->cancelOnError(), mSpecialActionsButton->dontShowError());
557 /******************************************************************************
558 * Get the currently specified alarm flag bits.
560 int EditDisplayAlarmDlg::getAlarmFlags() const
562 bool cmd = (mTypeCombo->currentIndex() == tCOMMAND);
563 return EditAlarmDlg::getAlarmFlags()
564 | (mSoundPicker->sound() == Preferences::Sound_Beep ? KAEvent::BEEP : 0)
565 | (mSoundPicker->sound() == Preferences::Sound_Speak ? KAEvent::SPEAK : 0)
566 | (mSoundPicker->repeat() ? KAEvent::REPEAT_SOUND : 0)
567 | (mConfirmAck->isChecked() ? KAEvent::CONFIRM_ACK : 0)
568 | (lateCancel()->isAutoClose() ? KAEvent::AUTO_CLOSE : 0)
569 | (mFontColourButton->defaultFont() ? KAEvent::DEFAULT_FONT : 0)
570 | (cmd ? KAEvent::DISPLAY_COMMAND : 0)
571 | (cmd && mCmdEdit->isScript() ? KAEvent::SCRIPT : 0);
574 /******************************************************************************
575 * Called when one of the alarm display type combo box is changed, to display
576 * the appropriate set of controls for that action type.
578 void EditDisplayAlarmDlg::slotAlarmTypeChanged(int index)
580 QWidget* focus = 0;
581 switch (index)
583 case tTEXT: // text message
584 mFileBox->hide();
585 mFilePadding->hide();
586 mCmdEdit->hide();
587 mTextMessageEdit->show();
588 mSoundPicker->showSpeak(true);
589 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the alarm message now"));
590 focus = mTextMessageEdit;
591 break;
592 case tFILE: // file contents
593 mTextMessageEdit->hide();
594 mFileBox->show();
595 mFilePadding->show();
596 mCmdEdit->hide();
597 mSoundPicker->showSpeak(false);
598 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the file now"));
599 mFileMessageEdit->setNoSelect();
600 focus = mFileMessageEdit;
601 break;
602 case tCOMMAND: // command output
603 mTextMessageEdit->hide();
604 mFileBox->hide();
605 slotCmdScriptToggled(mCmdEdit->isScript()); // show/hide mFilePadding
606 mCmdEdit->show();
607 mSoundPicker->showSpeak(true);
608 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Display the command output now"));
609 focus = mCmdEdit;
610 break;
612 if (focus)
613 focus->setFocus();
616 /******************************************************************************
617 * Called when the file browse button is pressed to select a file to display.
619 void EditDisplayAlarmDlg::slotPickFile()
621 static QString defaultDir; // default directory for file browse button
622 QString file = KAlarm::browseFile(i18nc("@title:window", "Choose Text or Image File to Display"),
623 defaultDir, mFileMessageEdit->text(), QString(), KFile::ExistingOnly, this);
624 if (!file.isEmpty())
626 mFileMessageEdit->setText(KAlarm::pathOrUrl(file));
627 contentsChanged();
631 /******************************************************************************
632 * Called when one of the command type radio buttons is clicked,
633 * to display the appropriate edit field.
635 void EditDisplayAlarmDlg::slotCmdScriptToggled(bool on)
637 if (on)
638 mFilePadding->hide();
639 else
640 mFilePadding->show();
643 /******************************************************************************
644 * Clean up the alarm text, and if it's a file, check whether it's valid.
646 bool EditDisplayAlarmDlg::checkText(QString& result, bool showErrorMessage) const
648 switch (mTypeCombo->currentIndex())
650 case tTEXT:
651 result = mTextMessageEdit->toPlainText();
652 break;
654 case tFILE:
656 QString alarmtext = mFileMessageEdit->text().trimmed();
657 KUrl url;
658 KAlarm::FileErr err = KAlarm::checkFileExists(alarmtext, url);
659 if (err == KAlarm::FileErr_None)
661 switch (KAlarm::fileType(KFileItem(KFileItem::Unknown, KFileItem::Unknown, url).mimeTypePtr()))
663 case KAlarm::TextFormatted:
664 case KAlarm::TextPlain:
665 case KAlarm::TextApplication:
666 case KAlarm::Image:
667 break;
668 default:
669 err = KAlarm::FileErr_NotTextImage;
670 break;
673 if (err != KAlarm::FileErr_None && showErrorMessage)
675 mFileMessageEdit->setFocus();
676 if (!KAlarm::showFileErrMessage(alarmtext, err, KAlarm::FileErr_BlankDisplay, const_cast<EditDisplayAlarmDlg*>(this)))
677 return false;
679 result = alarmtext;
680 break;
682 case tCOMMAND:
683 result = mCmdEdit->text(const_cast<EditDisplayAlarmDlg*>(this), showErrorMessage);
684 if (result.isEmpty())
685 return false;
686 break;
688 return true;
692 /*=============================================================================
693 = Class EditCommandAlarmDlg
694 = Dialog to edit command alarms.
695 =============================================================================*/
697 QString EditCommandAlarmDlg::i18n_chk_EnterScript() { return i18nc("@option:check", "Enter a script"); }
698 QString EditCommandAlarmDlg::i18n_radio_ExecInTermWindow() { return i18nc("@option:radio", "Execute in terminal window"); }
699 QString EditCommandAlarmDlg::i18n_chk_ExecInTermWindow() { return i18nc("@option:check", "Execute in terminal window"); }
702 /******************************************************************************
703 * Constructor.
704 * Parameters:
705 * Template = true to edit/create an alarm template
706 * = false to edit/create an alarm.
707 * event != to initialise the dialog to show the specified event's data.
709 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
710 : EditAlarmDlg(Template, KAEvent::COMMAND, parent, getResource)
712 kDebug() << "New";
713 init(0);
716 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
717 GetResourceType getResource, bool readOnly)
718 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly)
720 kDebug() << "Event.id()";
721 init(event);
724 /******************************************************************************
725 * Return the window caption.
727 QString EditCommandAlarmDlg::type_caption() const
729 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Command Alarm Template") : i18nc("@title:window", "Edit Command Alarm Template"))
730 : (isNewAlarm() ? i18nc("@title:window", "New Command Alarm") : i18nc("@title:window", "Edit Command Alarm"));
733 /******************************************************************************
734 * Set up the command alarm dialog controls.
736 void EditCommandAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
738 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Execute the specified command now"));
740 mCmdEdit = new CommandEdit(parent);
741 connect(mCmdEdit, SIGNAL(scriptToggled(bool)), SLOT(slotCmdScriptToggled(bool)));
742 connect(mCmdEdit, SIGNAL(changed()), SLOT(contentsChanged()));
743 frameLayout->addWidget(mCmdEdit);
745 // What to do with command output
747 mCmdOutputBox = new QGroupBox(i18nc("@title:group", "Command Output"), parent);
748 frameLayout->addWidget(mCmdOutputBox);
749 QVBoxLayout* vlayout = new QVBoxLayout(mCmdOutputBox);
750 vlayout->setMargin(marginHint());
751 vlayout->setSpacing(spacingHint());
752 mCmdOutputGroup = new ButtonGroup(mCmdOutputBox);
753 connect(mCmdOutputGroup, SIGNAL(buttonSet(QAbstractButton*)), SLOT(contentsChanged()));
755 // Execute in terminal window
756 mCmdExecInTerm = new RadioButton(i18n_radio_ExecInTermWindow(), mCmdOutputBox);
757 mCmdExecInTerm->setFixedSize(mCmdExecInTerm->sizeHint());
758 mCmdExecInTerm->setWhatsThis(i18nc("@info:whatsthis", "Check to execute the command in a terminal window"));
759 mCmdOutputGroup->addButton(mCmdExecInTerm, Preferences::Log_Terminal);
760 vlayout->addWidget(mCmdExecInTerm, 0, Qt::AlignLeft);
762 // Log file name edit box
763 KHBox* box = new KHBox(mCmdOutputBox);
764 box->setMargin(0);
765 (new QWidget(box))->setFixedWidth(mCmdExecInTerm->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth)); // indent the edit box
766 mCmdLogFileEdit = new LineEdit(LineEdit::Url, box);
767 mCmdLogFileEdit->setAcceptDrops(true);
768 mCmdLogFileEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or path of the log file."));
769 connect(mCmdLogFileEdit, SIGNAL(textChanged(const QString&)), SLOT(contentsChanged()));
771 // Log file browse button.
772 // The file browser dialog is activated by the PickLogFileRadio class.
773 QPushButton* browseButton = new QPushButton(box);
774 browseButton->setIcon(SmallIcon("document-open"));
775 int size = browseButton->sizeHint().height();
776 browseButton->setFixedSize(size, size);
777 browseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
778 browseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a log file."));
780 // Log output to file
781 mCmdLogToFile = new PickLogFileRadio(browseButton, mCmdLogFileEdit, i18nc("@option:radio", "Log to file"), mCmdOutputGroup, mCmdOutputBox);
782 mCmdLogToFile->setFixedSize(mCmdLogToFile->sizeHint());
783 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."));
784 connect(mCmdLogToFile, SIGNAL(fileChanged()), SLOT(contentsChanged()));
785 mCmdOutputGroup->addButton(mCmdLogToFile, Preferences::Log_File);
786 vlayout->addWidget(mCmdLogToFile, 0, Qt::AlignLeft);
787 vlayout->addWidget(box);
789 // Discard output
790 mCmdDiscardOutput = new RadioButton(i18nc("@option:radio", "Discard"), mCmdOutputBox);
791 mCmdDiscardOutput->setFixedSize(mCmdDiscardOutput->sizeHint());
792 mCmdDiscardOutput->setWhatsThis(i18nc("@info:whatsthis", "Check to discard command output."));
793 mCmdOutputGroup->addButton(mCmdDiscardOutput, Preferences::Log_Discard);
794 vlayout->addWidget(mCmdDiscardOutput, 0, Qt::AlignLeft);
796 // Top-adjust the controls
797 mCmdPadding = new KHBox(parent);
798 mCmdPadding->setMargin(0);
799 frameLayout->addWidget(mCmdPadding);
800 frameLayout->setStretchFactor(mCmdPadding, 1);
803 /******************************************************************************
804 * Initialise the dialog controls from the specified event.
806 void EditCommandAlarmDlg::type_initValues(const KAEvent* event)
808 if (event)
810 // Set the values to those for the specified event
811 RadioButton* logType = event->commandXterm() ? mCmdExecInTerm
812 : !event->logFile().isEmpty() ? mCmdLogToFile
813 : mCmdDiscardOutput;
814 if (logType == mCmdLogToFile)
815 mCmdLogFileEdit->setText(event->logFile()); // set file name before setting radio button
816 logType->setChecked(true);
818 else
820 // Set the values to their defaults
821 mCmdEdit->setScript(Preferences::defaultCmdScript());
822 mCmdLogFileEdit->setText(Preferences::defaultCmdLogFile()); // set file name before setting radio button
823 mCmdOutputGroup->setButton(Preferences::defaultCmdLogType());
825 slotCmdScriptToggled(mCmdEdit->isScript());
828 /******************************************************************************
829 * Called when the More/Less Options button is clicked.
830 * Show/hide the optional options.
832 void EditCommandAlarmDlg::type_showOptions(bool more)
834 if (more)
835 mCmdOutputBox->show();
836 else
837 mCmdOutputBox->hide();
840 /******************************************************************************
841 * Set the dialog's action and the action's text.
843 void EditCommandAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText)
845 Q_UNUSED(action);
846 Q_ASSERT(action == KAEvent::COMMAND);
847 mCmdEdit->setText(alarmText);
850 /******************************************************************************
851 * Set the read-only status of all non-template controls.
853 void EditCommandAlarmDlg::setReadOnly(bool readOnly)
855 if (!isTemplate() && !ShellProcess::authorised())
856 readOnly = true; // don't allow editing of existing command alarms in kiosk mode
857 mCmdEdit->setReadOnly(readOnly);
858 mCmdExecInTerm->setReadOnly(readOnly);
859 mCmdLogToFile->setReadOnly(readOnly);
860 mCmdDiscardOutput->setReadOnly(readOnly);
861 EditAlarmDlg::setReadOnly(readOnly);
864 /******************************************************************************
865 * Save the state of all controls.
867 void EditCommandAlarmDlg::saveState(const KAEvent* event)
869 EditAlarmDlg::saveState(event);
870 mSavedCmdScript = mCmdEdit->isScript();
871 mSavedCmdOutputRadio = mCmdOutputGroup->checkedButton();
872 mSavedCmdLogFile = mCmdLogFileEdit->text();
875 /******************************************************************************
876 * Check whether any of the controls has changed state since the dialog was
877 * first displayed.
878 * Reply = true if any controls have changed, or if it's a new event.
879 * = false if no controls have changed.
881 bool EditCommandAlarmDlg::type_stateChanged() const
883 if (mSavedCmdScript != mCmdEdit->isScript()
884 || mSavedCmdOutputRadio != mCmdOutputGroup->checkedButton())
885 return true;
886 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
888 if (mSavedCmdLogFile != mCmdLogFileEdit->text())
889 return true;
891 return false;
894 /******************************************************************************
895 * Extract the data in the dialog specific to the alarm type and set up a
896 * KAEvent from it.
898 void EditCommandAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
900 Q_UNUSED(trial);
901 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::COMMAND, lateCancel, getAlarmFlags());
902 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
903 event.setLogFile(mCmdLogFileEdit->text());
906 /******************************************************************************
907 * Get the currently specified alarm flag bits.
909 int EditCommandAlarmDlg::getAlarmFlags() const
911 return EditAlarmDlg::getAlarmFlags()
912 | (mCmdEdit->isScript() ? KAEvent::SCRIPT : 0)
913 | (mCmdOutputGroup->checkedButton() == mCmdExecInTerm ? KAEvent::EXEC_IN_XTERM : 0);
916 /******************************************************************************
917 * Validate and convert command alarm data.
919 bool EditCommandAlarmDlg::type_validate(bool trial)
921 Q_UNUSED(trial);
922 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
924 // Validate the log file name
925 QString file = mCmdLogFileEdit->text();
926 QFileInfo info(file);
927 QDir::setCurrent(QDir::homePath());
928 bool err = file.isEmpty() || info.isDir();
929 if (!err)
931 if (info.exists())
933 err = !info.isWritable();
935 else
937 QFileInfo dirinfo(info.absolutePath()); // get absolute directory path
938 err = (!dirinfo.isDir() || !dirinfo.isWritable());
941 if (err)
943 showMainPage();
944 mCmdLogFileEdit->setFocus();
945 KMessageBox::sorry(this, i18nc("@info", "Log file must be the name or path of a local file, with write permission."));
946 return false;
948 // Convert the log file to an absolute path
949 mCmdLogFileEdit->setText(info.absoluteFilePath());
951 return true;
954 /******************************************************************************
955 * Tell the user the result of the Try action.
957 void EditCommandAlarmDlg::type_trySuccessMessage(ShellProcess* proc, const QString& text)
959 if (mCmdOutputGroup->checkedButton() != mCmdExecInTerm)
961 theApp()->commandMessage(proc, this);
962 KMessageBox::information(this, i18nc("@info", "Command executed: <icode>%1</icode>", text));
963 theApp()->commandMessage(proc, 0);
967 /******************************************************************************
968 * Called when one of the command type radio buttons is clicked,
969 * to display the appropriate edit field.
971 void EditCommandAlarmDlg::slotCmdScriptToggled(bool on)
973 if (on)
974 mCmdPadding->hide();
975 else
976 mCmdPadding->show();
979 /******************************************************************************
980 * Clean up the alarm text.
982 bool EditCommandAlarmDlg::checkText(QString& result, bool showErrorMessage) const
984 result = mCmdEdit->text(const_cast<EditCommandAlarmDlg*>(this), showErrorMessage);
985 if (result.isEmpty())
986 return false;
987 return true;
991 /*=============================================================================
992 = Class EditEmailAlarmDlg
993 = Dialog to edit email alarms.
994 =============================================================================*/
996 QString EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf() { return i18nc("@option:check", "Copy email to self"); }
999 /******************************************************************************
1000 * Constructor.
1001 * Parameters:
1002 * Template = true to edit/create an alarm template
1003 * = false to edit/create an alarm.
1004 * event != to initialise the dialog to show the specified event's data.
1006 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1007 : EditAlarmDlg(Template, KAEvent::EMAIL, parent, getResource),
1008 mEmailRemoveButton(0)
1010 kDebug() << "New";
1011 init(0);
1014 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1015 GetResourceType getResource, bool readOnly)
1016 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
1017 mEmailRemoveButton(0)
1019 kDebug() << "Event.id()";
1020 init(event);
1023 /******************************************************************************
1024 * Return the window caption.
1026 QString EditEmailAlarmDlg::type_caption() const
1028 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Email Alarm Template") : i18nc("@title:window", "Edit Email Alarm Template"))
1029 : (isNewAlarm() ? i18nc("@title:window", "New Email Alarm") : i18nc("@title:window", "Edit Email Alarm"));
1032 /******************************************************************************
1033 * Set up the email alarm dialog controls.
1035 void EditEmailAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1037 setButtonWhatsThis(Try, i18nc("@info:whatsthis", "Send the email to the specified addressees now"));
1039 QGridLayout* grid = new QGridLayout();
1040 grid->setMargin(0);
1041 grid->setColumnStretch(1, 1);
1042 frameLayout->addLayout(grid);
1044 mEmailFromList = 0;
1045 if (Preferences::emailFrom() == Preferences::MAIL_FROM_KMAIL)
1047 // Email sender identity
1048 QLabel* label = new QLabel(i18nc("@label:listbox 'From' email address", "From:"), parent);
1049 label->setFixedSize(label->sizeHint());
1050 grid->addWidget(label, 0, 0);
1052 mEmailFromList = new EmailIdCombo(Identities::identityManager(), parent);
1053 mEmailFromList->setMinimumSize(mEmailFromList->sizeHint());
1054 label->setBuddy(mEmailFromList);
1055 mEmailFromList->setWhatsThis(i18nc("@info:whatsthis", "Your email identity, used to identify you as the sender when sending email alarms."));
1056 connect(mEmailFromList, SIGNAL(identityChanged(uint)), SLOT(contentsChanged()));
1057 grid->addWidget(mEmailFromList, 0, 1, 1, 2);
1060 // Email recipients
1061 QLabel* label = new QLabel(i18nc("@label:textbox Email addressee", "To:"), parent);
1062 label->setFixedSize(label->sizeHint());
1063 grid->addWidget(label, 1, 0);
1065 mEmailToEdit = new LineEdit(LineEdit::Emails, parent);
1066 mEmailToEdit->setMinimumSize(mEmailToEdit->sizeHint());
1067 mEmailToEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the addresses of the email recipients. Separate multiple addresses by "
1068 "commas or semicolons."));
1069 connect(mEmailToEdit, SIGNAL(textChanged(const QString&)), SLOT(contentsChanged()));
1070 grid->addWidget(mEmailToEdit, 1, 1);
1072 mEmailAddressButton = new QPushButton(parent);
1073 mEmailAddressButton->setIcon(SmallIcon("help-contents"));
1074 int size = mEmailAddressButton->sizeHint().height();
1075 mEmailAddressButton->setFixedSize(size, size);
1076 connect(mEmailAddressButton, SIGNAL(clicked()), SLOT(openAddressBook()));
1077 mEmailAddressButton->setToolTip(i18nc("@info:tooltip", "Open address book"));
1078 mEmailAddressButton->setWhatsThis(i18nc("@info:whatsthis", "Select email addresses from your address book."));
1079 grid->addWidget(mEmailAddressButton, 1, 2);
1081 // Email subject
1082 label = new QLabel(i18nc("@label:textbox Email subject", "Subject:"), parent);
1083 label->setFixedSize(label->sizeHint());
1084 grid->addWidget(label, 2, 0);
1086 mEmailSubjectEdit = new LineEdit(parent);
1087 mEmailSubjectEdit->setMinimumSize(mEmailSubjectEdit->sizeHint());
1088 label->setBuddy(mEmailSubjectEdit);
1089 mEmailSubjectEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email subject."));
1090 connect(mEmailSubjectEdit, SIGNAL(textChanged(const QString&)), SLOT(contentsChanged()));
1091 grid->addWidget(mEmailSubjectEdit, 2, 1, 1, 2);
1093 // Email body
1094 mEmailMessageEdit = new TextEdit(parent);
1095 mEmailMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email message."));
1096 connect(mEmailMessageEdit, SIGNAL(textChanged()), SLOT(contentsChanged()));
1097 frameLayout->addWidget(mEmailMessageEdit);
1099 // Email attachments
1100 grid = new QGridLayout();
1101 grid->setMargin(0);
1102 frameLayout->addLayout(grid);
1103 label = new QLabel(i18nc("@label:listbox", "Attachments:"), parent);
1104 label->setFixedSize(label->sizeHint());
1105 grid->addWidget(label, 0, 0);
1107 mEmailAttachList = new KComboBox(parent);
1108 mEmailAttachList->setEditable(true);
1109 mEmailAttachList->setMinimumSize(mEmailAttachList->sizeHint());
1110 if (mEmailAttachList->lineEdit())
1111 mEmailAttachList->lineEdit()->setReadOnly(true);
1112 //Q3ListBox* list = mEmailAttachList->listBox();
1113 //QRect rect = list->geometry();
1114 //list->setGeometry(rect.left() - 50, rect.top(), rect.width(), rect.height());
1115 label->setBuddy(mEmailAttachList);
1116 mEmailAttachList->setWhatsThis(i18nc("@info:whatsthis", "Files to send as attachments to the email."));
1117 grid->addWidget(mEmailAttachList, 0, 1);
1118 grid->setColumnStretch(1, 1);
1120 mEmailAddAttachButton = new QPushButton(i18nc("@action:button", "Add..."), parent);
1121 connect(mEmailAddAttachButton, SIGNAL(clicked()), SLOT(slotAddAttachment()));
1122 mEmailAddAttachButton->setWhatsThis(i18nc("@info:whatsthis", "Add an attachment to the email."));
1123 grid->addWidget(mEmailAddAttachButton, 0, 2);
1125 mEmailRemoveButton = new QPushButton(i18nc("@action:button", "Remove"), parent);
1126 connect(mEmailRemoveButton, SIGNAL(clicked()), SLOT(slotRemoveAttachment()));
1127 mEmailRemoveButton->setWhatsThis(i18nc("@info:whatsthis", "Remove the highlighted attachment from the email."));
1128 grid->addWidget(mEmailRemoveButton, 1, 2);
1130 // BCC email to sender
1131 mEmailBcc = new CheckBox(i18n_chk_CopyEmailToSelf(), parent);
1132 mEmailBcc->setFixedSize(mEmailBcc->sizeHint());
1133 mEmailBcc->setWhatsThis(i18nc("@info:whatsthis", "If checked, the email will be blind copied to you."));
1134 connect(mEmailBcc, SIGNAL(toggled(bool)), SLOT(contentsChanged()));
1135 grid->addWidget(mEmailBcc, 1, 0, 1, 2, Qt::AlignLeft);
1138 /******************************************************************************
1139 * Initialise the dialog controls from the specified event.
1141 void EditEmailAlarmDlg::type_initValues(const KAEvent* event)
1143 if (event)
1145 // Set the values to those for the specified event
1146 mEmailAttachList->addItems(event->emailAttachments());
1147 mEmailToEdit->setText(event->emailAddresses(", "));
1148 mEmailSubjectEdit->setText(event->emailSubject());
1149 mEmailBcc->setChecked(event->emailBcc());
1150 if (mEmailFromList)
1151 mEmailFromList->setCurrentIdentity(event->emailFromId());
1153 else
1155 // Set the values to their defaults
1156 mEmailBcc->setChecked(Preferences::defaultEmailBcc());
1158 attachmentEnable();
1161 /******************************************************************************
1162 * Enable/disable controls depending on whether any attachments are entered.
1164 void EditEmailAlarmDlg::attachmentEnable()
1166 bool enable = mEmailAttachList->count();
1167 mEmailAttachList->setEnabled(enable);
1168 if (mEmailRemoveButton)
1169 mEmailRemoveButton->setEnabled(enable);
1172 /******************************************************************************
1173 * Set the dialog's action and the action's text.
1175 void EditEmailAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText)
1177 Q_UNUSED(action);
1178 Q_ASSERT(action == KAEvent::EMAIL);
1179 if (alarmText.isEmail())
1181 mEmailToEdit->setText(alarmText.to());
1182 mEmailSubjectEdit->setText(alarmText.subject());
1183 mEmailMessageEdit->setPlainText(alarmText.body());
1185 else
1186 mEmailMessageEdit->setPlainText(alarmText.displayText());
1189 /******************************************************************************
1190 * Initialise various values in the New Alarm dialogue.
1192 void EditEmailAlarmDlg::setEmailFields(uint fromID, const EmailAddressList& addresses,
1193 const QString& subject, const QStringList& attachments)
1195 if (fromID)
1196 mEmailFromList->setCurrentIdentity(fromID);
1197 if (!addresses.isEmpty())
1198 mEmailToEdit->setText(addresses.join(", "));
1199 if (!subject.isEmpty())
1200 mEmailSubjectEdit->setText(subject);
1201 if (!attachments.isEmpty())
1203 mEmailAttachList->addItems(attachments);
1204 attachmentEnable();
1207 void EditEmailAlarmDlg::setBcc(bool bcc)
1209 mEmailBcc->setChecked(bcc);
1212 /******************************************************************************
1213 * Set the read-only status of all non-template controls.
1215 void EditEmailAlarmDlg::setReadOnly(bool readOnly)
1217 mEmailToEdit->setReadOnly(readOnly);
1218 mEmailSubjectEdit->setReadOnly(readOnly);
1219 mEmailMessageEdit->setReadOnly(readOnly);
1220 mEmailBcc->setReadOnly(readOnly);
1221 if (mEmailFromList)
1222 mEmailFromList->setReadOnly(readOnly);
1223 if (readOnly)
1225 mEmailAddressButton->hide();
1226 mEmailAddAttachButton->hide();
1227 mEmailRemoveButton->hide();
1229 else
1231 mEmailAddressButton->show();
1232 mEmailAddAttachButton->show();
1233 mEmailRemoveButton->show();
1235 EditAlarmDlg::setReadOnly(readOnly);
1238 /******************************************************************************
1239 * Save the state of all controls.
1241 void EditEmailAlarmDlg::saveState(const KAEvent* event)
1243 EditAlarmDlg::saveState(event);
1244 if (mEmailFromList)
1245 mSavedEmailFrom = mEmailFromList->currentIdentityName();
1246 mSavedEmailTo = mEmailToEdit->text();
1247 mSavedEmailSubject = mEmailSubjectEdit->text();
1248 mSavedEmailAttach.clear();
1249 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1250 mSavedEmailAttach += mEmailAttachList->itemText(i);
1251 mSavedEmailBcc = mEmailBcc->isChecked();
1254 /******************************************************************************
1255 * Check whether any of the controls has changed state since the dialog was
1256 * first displayed.
1257 * Reply = true if any controls have changed, or if it's a new event.
1258 * = false if no controls have changed.
1260 bool EditEmailAlarmDlg::type_stateChanged() const
1262 QStringList emailAttach;
1263 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1264 emailAttach += mEmailAttachList->itemText(i);
1265 if ((mEmailFromList && mSavedEmailFrom != mEmailFromList->currentIdentityName())
1266 || mSavedEmailTo != mEmailToEdit->text()
1267 || mSavedEmailSubject != mEmailSubjectEdit->text()
1268 || mSavedEmailAttach != emailAttach
1269 || mSavedEmailBcc != mEmailBcc->isChecked())
1270 return true;
1271 return false;
1274 /******************************************************************************
1275 * Extract the data in the dialog specific to the alarm type and set up a
1276 * KAEvent from it.
1278 void EditEmailAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1280 Q_UNUSED(trial);
1281 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::EMAIL, lateCancel, getAlarmFlags());
1282 uint from = mEmailFromList ? mEmailFromList->currentIdentity() : 0;
1283 event.setEmail(from, mEmailAddresses, mEmailSubjectEdit->text(), mEmailAttachments);
1286 /******************************************************************************
1287 * Get the currently specified alarm flag bits.
1289 int EditEmailAlarmDlg::getAlarmFlags() const
1291 return EditAlarmDlg::getAlarmFlags()
1292 | (mEmailBcc->isChecked() ? KAEvent::EMAIL_BCC : 0);
1295 /******************************************************************************
1296 * Convert the email addresses to a list, and validate them. Convert the email
1297 * attachments to a list.
1299 bool EditEmailAlarmDlg::type_validate(bool trial)
1301 QString addrs = mEmailToEdit->text();
1302 if (addrs.isEmpty())
1303 mEmailAddresses.clear();
1304 else
1306 QString bad = KAMail::convertAddresses(addrs, mEmailAddresses);
1307 if (!bad.isEmpty())
1309 mEmailToEdit->setFocus();
1310 KMessageBox::error(this, i18nc("@info", "Invalid email address: <email>%1</email>", bad));
1311 return false;
1314 if (mEmailAddresses.isEmpty())
1316 mEmailToEdit->setFocus();
1317 KMessageBox::error(this, i18nc("@info", "No email address specified"));
1318 return false;
1321 mEmailAttachments.clear();
1322 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1324 QString att = mEmailAttachList->itemText(i);
1325 switch (KAMail::checkAttachment(att))
1327 case 1:
1328 mEmailAttachments.append(att);
1329 break;
1330 case 0:
1331 break; // empty
1332 case -1:
1333 mEmailAttachList->setFocus();
1334 KMessageBox::error(this, i18nc("@info", "Invalid email attachment: <filename>%1</filename>", att));
1335 return false;
1338 if (trial && KMessageBox::warningContinueCancel(this, i18nc("@info", "Do you really want to send the email now to the specified recipient(s)?"),
1339 i18nc("@action:button", "Confirm Email"), KGuiItem(i18nc("@action:button", "Send"))) != KMessageBox::Continue)
1340 return false;
1341 return true;
1344 /******************************************************************************
1345 * Tell the user the result of the Try action.
1347 void EditEmailAlarmDlg::type_trySuccessMessage(ShellProcess*, const QString&)
1349 QString msg;
1350 QString to = mEmailAddresses.join("<nl/>");
1351 to.replace('<', "&lt;");
1352 to.replace('>', "&gt;");
1353 if (mEmailBcc->isChecked())
1354 msg = "<qt>" + i18nc("@info", "Email sent to:<nl/>%1<nl/>Bcc: <email>%2</email>",
1355 to, Preferences::emailBccAddress()) + "</qt>";
1356 else
1357 msg = "<qt>" + i18nc("@info", "Email sent to:<nl/>%1", to) + "</qt>";
1358 KMessageBox::information(this, msg);
1361 /******************************************************************************
1362 * Get a selection from the Address Book.
1364 void EditEmailAlarmDlg::openAddressBook()
1366 // Use AutoQPointer to guard against crash on application exit while
1367 // the dialogue is still open. It prevents double deletion (both on
1368 // deletion of MainWindow, and on return from this function).
1369 AutoQPointer<Akonadi::EmailAddressSelectionDialog> dlg = new Akonadi::EmailAddressSelectionDialog(this);
1370 if (dlg->exec() != QDialog::Accepted)
1371 return;
1373 Akonadi::EmailAddressSelection::List selections = dlg->selectedAddresses();
1374 if (selections.isEmpty())
1375 return;
1376 Person person(selections.first().name(), selections.first().email());
1377 QString addrs = mEmailToEdit->text().trimmed();
1378 if (!addrs.isEmpty())
1379 addrs += ", ";
1380 addrs += person.fullName();
1381 mEmailToEdit->setText(addrs);
1384 /******************************************************************************
1385 * Select a file to attach to the email.
1387 void EditEmailAlarmDlg::slotAddAttachment()
1389 QString url = KAlarm::browseFile(i18nc("@title:window", "Choose File to Attach"), mAttachDefaultDir, QString(),
1390 QString(), KFile::ExistingOnly, this);
1391 if (!url.isEmpty())
1393 mEmailAttachList->addItem(url);
1394 mEmailAttachList->setCurrentIndex(mEmailAttachList->count() - 1); // select the new item
1395 mEmailRemoveButton->setEnabled(true);
1396 mEmailAttachList->setEnabled(true);
1397 contentsChanged();
1401 /******************************************************************************
1402 * Remove the currently selected attachment from the email.
1404 void EditEmailAlarmDlg::slotRemoveAttachment()
1406 int item = mEmailAttachList->currentIndex();
1407 mEmailAttachList->removeItem(item);
1408 int count = mEmailAttachList->count();
1409 if (item >= count)
1410 mEmailAttachList->setCurrentIndex(count - 1);
1411 if (!count)
1413 mEmailRemoveButton->setEnabled(false);
1414 mEmailAttachList->setEnabled(false);
1416 contentsChanged();
1419 /******************************************************************************
1420 * Clean up the alarm text.
1422 bool EditEmailAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1424 Q_UNUSED(showErrorMessage);
1425 result = mEmailMessageEdit->toPlainText();
1426 return true;
1430 /*=============================================================================
1431 = Class EditAudioAlarmDlg
1432 = Dialog to edit audio alarms with no display window.
1433 =============================================================================*/
1435 /******************************************************************************
1436 * Constructor.
1437 * Parameters:
1438 * Template = true to edit/create an alarm template
1439 * = false to edit/create an alarm.
1440 * event != to initialise the dialog to show the specified event's data.
1442 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1443 : EditAlarmDlg(Template, KAEvent::AUDIO, parent, getResource)
1445 kDebug() << "New";
1446 init(0);
1449 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1450 GetResourceType getResource, bool readOnly)
1451 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly)
1453 kDebug() << "Event.id()";
1454 init(event);
1457 /******************************************************************************
1458 * Return the window caption.
1460 QString EditAudioAlarmDlg::type_caption() const
1462 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm Template") : i18nc("@title:window", "Edit Audio Alarm Template"))
1463 : (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm") : i18nc("@title:window", "Edit Audio Alarm"));
1466 /******************************************************************************
1467 * Set up the dialog controls common to display alarms.
1469 void EditAudioAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1471 // File name edit box
1472 mSoundConfig = new SoundWidget(false, true, parent);
1473 if (isTemplate())
1474 mSoundConfig->setAllowEmptyFile();
1475 connect(mSoundConfig, SIGNAL(changed()), SLOT(contentsChanged()));
1476 frameLayout->addWidget(mSoundConfig);
1478 // Top-adjust the controls
1479 mPadding = new KHBox(parent);
1480 mPadding->setMargin(0);
1481 frameLayout->addWidget(mPadding);
1482 frameLayout->setStretchFactor(mPadding, 1);
1485 /******************************************************************************
1486 * Initialise the dialog controls from the specified event.
1488 void EditAudioAlarmDlg::type_initValues(const KAEvent* event)
1490 if (event)
1492 mSoundConfig->set(event->audioFile(), event->soundVolume(), event->fadeVolume(), event->fadeSeconds(),
1493 (event->flags() & KAEvent::REPEAT_SOUND));
1495 else
1497 // Set the values to their defaults
1498 mSoundConfig->set(Preferences::defaultSoundFile(), Preferences::defaultSoundVolume());
1502 /******************************************************************************
1503 * Initialise various values in the New Alarm dialogue.
1505 void EditAudioAlarmDlg::setAudio(const QString& file, float volume)
1507 mSoundConfig->set(file, volume);
1510 /******************************************************************************
1511 * Set the dialog's action and the action's text.
1513 void EditAudioAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText)
1515 Q_UNUSED(action);
1516 Q_ASSERT(action == KAEvent::AUDIO);
1517 mSoundConfig->set(alarmText.displayText(), Preferences::defaultSoundVolume());
1520 /******************************************************************************
1521 * Set the read-only status of all non-template controls.
1523 void EditAudioAlarmDlg::setReadOnly(bool readOnly)
1525 mSoundConfig->setReadOnly(readOnly);
1526 EditAlarmDlg::setReadOnly(readOnly);
1529 /******************************************************************************
1530 * Save the state of all controls.
1532 void EditAudioAlarmDlg::saveState(const KAEvent* event)
1534 EditAlarmDlg::saveState(event);
1535 mSavedFile = mSoundConfig->fileName();
1536 mSavedRepeat = mSoundConfig->getVolume(mSavedVolume, mSavedFadeVolume, mSavedFadeSeconds);
1539 /******************************************************************************
1540 * Check whether any of the controls has changed state since the dialog was
1541 * first displayed.
1542 * Reply = true if any controls have changed, or if it's a new event.
1543 * = false if no controls have changed.
1545 bool EditAudioAlarmDlg::type_stateChanged() const
1547 if (mSavedFile != mSoundConfig->fileName())
1548 return true;
1549 if (!mSavedFile.isEmpty() || isTemplate())
1551 float volume, fadeVolume;
1552 int fadeSecs;
1553 if (mSavedRepeat != mSoundConfig->getVolume(volume, fadeVolume, fadeSecs)
1554 || mSavedVolume != volume
1555 || mSavedFadeVolume != fadeVolume
1556 || mSavedFadeSeconds != fadeSecs)
1557 return true;
1559 return false;
1562 /******************************************************************************
1563 * Extract the data in the dialog specific to the alarm type and set up a
1564 * KAEvent from it.
1566 void EditAudioAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1568 Q_UNUSED(text);
1569 Q_UNUSED(trial);
1570 event.set(dt, QString(), QColor(), QColor(), QFont(), KAEvent::AUDIO, lateCancel, getAlarmFlags());
1571 float volume, fadeVolume;
1572 int fadeSecs;
1573 mSoundConfig->getVolume(volume, fadeVolume, fadeSecs);
1574 KUrl url;
1575 mSoundConfig->file(url, false);
1576 event.setAudioFile(url.prettyUrl(), volume, fadeVolume, fadeSecs, isTemplate());
1579 /******************************************************************************
1580 * Get the currently specified alarm flag bits.
1582 int EditAudioAlarmDlg::getAlarmFlags() const
1584 return EditAlarmDlg::getAlarmFlags()
1585 | (mSoundConfig->getRepeat() ? KAEvent::REPEAT_SOUND : 0);
1588 /******************************************************************************
1589 * Check whether the file name is valid.
1591 bool EditAudioAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1593 KUrl url;
1594 if (!mSoundConfig->file(url, showErrorMessage))
1596 result.clear();
1597 return false;
1599 result = url.pathOrUrl();
1600 return true;
1604 /*=============================================================================
1605 = Class CommandEdit
1606 = A widget to allow entry of a command or a command script.
1607 =============================================================================*/
1608 CommandEdit::CommandEdit(QWidget* parent)
1609 : QWidget(parent)
1611 QVBoxLayout* vlayout = new QVBoxLayout(this);
1612 vlayout->setMargin(0);
1613 vlayout->setSpacing(KDialog::spacingHint());
1614 mTypeScript = new CheckBox(EditCommandAlarmDlg::i18n_chk_EnterScript(), this);
1615 mTypeScript->setFixedSize(mTypeScript->sizeHint());
1616 mTypeScript->setWhatsThis(i18nc("@info:whatsthis", "Check to enter the contents of a script instead of a shell command line"));
1617 connect(mTypeScript, SIGNAL(toggled(bool)), SLOT(slotCmdScriptToggled(bool)));
1618 connect(mTypeScript, SIGNAL(toggled(bool)), SIGNAL(changed()));
1619 vlayout->addWidget(mTypeScript, 0, Qt::AlignLeft);
1621 mCommandEdit = new LineEdit(LineEdit::Url, this);
1622 mCommandEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter a shell command to execute."));
1623 connect(mCommandEdit, SIGNAL(textChanged(const QString&)), SIGNAL(changed()));
1624 vlayout->addWidget(mCommandEdit);
1626 mScriptEdit = new TextEdit(this);
1627 mScriptEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the contents of a script to execute"));
1628 connect(mScriptEdit, SIGNAL(textChanged()), SIGNAL(changed()));
1629 vlayout->addWidget(mScriptEdit);
1631 slotCmdScriptToggled(mTypeScript->isChecked());
1634 /******************************************************************************
1635 * Initialise the widget controls from the specified event.
1637 void CommandEdit::setScript(bool script)
1639 mTypeScript->setChecked(script);
1642 bool CommandEdit::isScript() const
1644 return mTypeScript->isChecked();
1647 /******************************************************************************
1648 * Set the widget's text.
1650 void CommandEdit::setText(const AlarmText& alarmText)
1652 QString text = alarmText.displayText();
1653 bool script = alarmText.isScript();
1654 mTypeScript->setChecked(script);
1655 if (script)
1656 mScriptEdit->setPlainText(text);
1657 else
1658 mCommandEdit->setText(KAlarm::pathOrUrl(text));
1661 /******************************************************************************
1662 * Return the widget's text.
1664 QString CommandEdit::text() const
1666 QString result;
1667 if (mTypeScript->isChecked())
1668 result = mScriptEdit->toPlainText();
1669 else
1670 result = mCommandEdit->text();
1671 return result.trimmed();
1674 /******************************************************************************
1675 * Return the alarm text.
1676 * If 'showErrorMessage' is true and the text is empty, an error message is
1677 * displayed.
1679 QString CommandEdit::text(EditAlarmDlg* dlg, bool showErrorMessage) const
1681 QString result = text();
1682 if (showErrorMessage && result.isEmpty())
1683 KMessageBox::sorry(dlg, i18nc("@info", "Please enter a command or script to execute"));
1684 return result;
1687 /******************************************************************************
1688 * Set the read-only status of all controls.
1690 void CommandEdit::setReadOnly(bool readOnly)
1692 mTypeScript->setReadOnly(readOnly);
1693 mCommandEdit->setReadOnly(readOnly);
1694 mScriptEdit->setReadOnly(readOnly);
1697 /******************************************************************************
1698 * Called when one of the command type radio buttons is clicked,
1699 * to display the appropriate edit field.
1701 void CommandEdit::slotCmdScriptToggled(bool on)
1703 if (on)
1705 mCommandEdit->hide();
1706 mScriptEdit->show();
1707 mScriptEdit->setFocus();
1709 else
1711 mScriptEdit->hide();
1712 mCommandEdit->show();
1713 mCommandEdit->setFocus();
1715 emit scriptToggled(on);
1718 /******************************************************************************
1719 * Returns the minimum size of the widget.
1721 QSize CommandEdit::minimumSizeHint() const
1723 QSize t(mTypeScript->minimumSizeHint());
1724 QSize s(mCommandEdit->minimumSizeHint().expandedTo(mScriptEdit->minimumSizeHint()));
1725 s.setHeight(s.height() + KDialog::spacingHint() + t.height());
1726 if (s.width() < t.width())
1727 s.setWidth(t.width());
1728 return s;
1733 /*=============================================================================
1734 = Class TextEdit
1735 = A text edit field with a minimum height of 3 text lines.
1736 =============================================================================*/
1737 TextEdit::TextEdit(QWidget* parent)
1738 : KTextEdit(parent)
1740 QSize tsize = sizeHint();
1741 tsize.setHeight(fontMetrics().lineSpacing()*13/4 + 2*frameWidth());
1742 setMinimumSize(tsize);
1745 void TextEdit::dragEnterEvent(QDragEnterEvent* e)
1747 #ifdef USE_AKONADI
1748 if (KCalUtils::ICalDrag::canDecode(e->mimeData()))
1749 #else
1750 if (KCal::ICalDrag::canDecode(e->mimeData()))
1751 #endif
1752 e->ignore(); // don't accept "text/calendar" objects
1753 KTextEdit::dragEnterEvent(e);
1756 // vim: et sw=4: