SVN_SILENT made messages (after extraction)
[kdepim.git] / kalarm / editdlgtypes.cpp
blob175f58947261b3e0f18846950da65ac63b1b6859
1 /*
2 * editdlgtypes.cpp - dialogs to create or edit alarm or alarm template types
3 * Program: kalarm
4 * Copyright © 2001-2014 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.h"
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 "kalarmapp.h"
33 #include "kamail.h"
34 #include "latecancel.h"
35 #include "lineedit.h"
36 #include "mainwindow.h"
37 #include "messagebox.h"
38 #include "messagewin.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 <kalarmcal/identities.h>
52 #include <Akonadi/Contact/EmailAddressSelectionDialog>
53 #include <KCalCore/Person>
54 #include <KCalUtils/kcalutils/icaldrag.h>
55 using namespace KCalCore;
57 #include <KLocalizedString>
58 #include <kfileitem.h>
60 #include <QComboBox>
61 #include <QLabel>
62 #include <QDir>
63 #include <QStyle>
64 #include <QGroupBox>
65 #include <QGridLayout>
66 #include <QHBoxLayout>
67 #include <QVBoxLayout>
68 #include <QDragEnterEvent>
69 #include <QStandardItemModel>
70 #include "kalarm_debug.h"
72 using namespace KAlarmCal;
74 enum { tTEXT, tFILE, tCOMMAND }; // order of mTypeCombo items
77 /*=============================================================================
78 = Class PickLogFileRadio
79 =============================================================================*/
80 class PickLogFileRadio : public PickFileRadio
82 public:
83 PickLogFileRadio(QPushButton* b, LineEdit* e, const QString& text, ButtonGroup* group, QWidget* parent)
84 : PickFileRadio(b, e, text, group, parent) { }
85 QString pickFile() Q_DECL_OVERRIDE // called when browse button is pressed to select a log file
87 return KAlarm::browseFile(i18nc("@title:window", "Choose Log File"), mDefaultDir, fileEdit()->text(), QString(),
88 KFile::LocalOnly, parentWidget());
90 private:
91 QString mDefaultDir; // default directory for log file browse button
95 /*=============================================================================
96 = Class EditDisplayAlarmDlg
97 = Dialog to edit display alarms.
98 =============================================================================*/
100 QString EditDisplayAlarmDlg::i18n_chk_ConfirmAck() { return i18nc("@option:check", "Confirm acknowledgment"); }
103 /******************************************************************************
104 * Constructor.
105 * Parameters:
106 * Template = true to edit/create an alarm template
107 * = false to edit/create an alarm.
108 * event != to initialise the dialog to show the specified event's data.
110 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
111 : EditAlarmDlg(Template, KAEvent::MESSAGE, parent, getResource),
112 mSpecialActionsButton(Q_NULLPTR),
113 mReminderDeferral(false),
114 mReminderArchived(false)
116 qCDebug(KALARM_LOG) << "New";
117 init(Q_NULLPTR);
120 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
121 GetResourceType getResource, bool readOnly)
122 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
123 mSpecialActionsButton(Q_NULLPTR),
124 mReminderDeferral(false),
125 mReminderArchived(false)
127 qCDebug(KALARM_LOG) << "Event.id()";
128 init(event);
131 /******************************************************************************
132 * Return the window caption.
134 QString EditDisplayAlarmDlg::type_caption() const
136 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Display Alarm Template") : i18nc("@title:window", "Edit Display Alarm Template"))
137 : (isNewAlarm() ? i18nc("@title:window", "New Display Alarm") : i18nc("@title:window", "Edit Display Alarm"));
140 /******************************************************************************
141 * Set up the dialog controls common to display alarms.
143 void EditDisplayAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
145 // Display type combo box
146 QWidget* box = new QWidget(parent); // to group widgets for QWhatsThis text
148 QHBoxLayout* boxHLayout = new QHBoxLayout(box);
149 boxHLayout->setMargin(0);
150 QLabel* label = new QLabel(i18nc("@label:listbox", "Display type:"), box);
151 boxHLayout->addWidget(label);
152 label->setFixedSize(label->sizeHint());
153 mTypeCombo = new ComboBox(box);
154 boxHLayout->addWidget(mTypeCombo);
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 if (!ShellProcess::authorised())
165 // User not authorised to issue shell commands - disable Command Output option
166 QStandardItemModel* model = qobject_cast<QStandardItemModel*>(mTypeCombo->model());
167 if (model)
169 QModelIndex index = model->index(2, mTypeCombo->modelColumn(), mTypeCombo->rootModelIndex());
170 QStandardItem* item = model->itemFromIndex(index);
171 if (item)
172 item->setEnabled(false);
175 connect(mTypeCombo, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged), this, &EditDisplayAlarmDlg::slotAlarmTypeChanged);
176 connect(mTypeCombo, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged), this, &EditDisplayAlarmDlg::contentsChanged);
177 label->setBuddy(mTypeCombo);
178 box->setWhatsThis(xi18nc("@info:whatsthis", "<para>Select what the alarm should display:"
179 "<list><item><interface>%1</interface>: the alarm will display the text message you type in.</item>"
180 "<item><interface>%2</interface>: the alarm will display the contents of a text or image file.</item>"
181 "<item><interface>%3</interface>: the alarm will display the output from a command.</item></list></para>",
182 textItem, fileItem, commandItem));
183 boxHLayout->setStretchFactor(new QWidget(box), 1); // left adjust the control
184 frameLayout->addWidget(box);
186 // Text message edit box
187 mTextMessageEdit = new TextEdit(parent);
188 mTextMessageEdit->setLineWrapMode(KTextEdit::NoWrap);
189 mTextMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the text of the alarm message. It may be multi-line."));
190 connect(mTextMessageEdit, &TextEdit::textChanged, this, &EditDisplayAlarmDlg::contentsChanged);
191 frameLayout->addWidget(mTextMessageEdit);
193 // File name edit box
194 mFileBox = new QWidget(parent);
195 frameLayout->addWidget(mFileBox);
196 QHBoxLayout* fileBoxHLayout = new QHBoxLayout(mFileBox);
197 fileBoxHLayout->setMargin(0);
198 fileBoxHLayout->setSpacing(0);
199 mFileMessageEdit = new LineEdit(LineEdit::Url, mFileBox);
200 fileBoxHLayout->addWidget(mFileMessageEdit);
201 mFileMessageEdit->setAcceptDrops(true);
202 mFileMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or URL of a text or image file to display."));
203 connect(mFileMessageEdit, &LineEdit::textChanged, this, &EditDisplayAlarmDlg::contentsChanged);
205 // File browse button
206 mFileBrowseButton = new QPushButton(mFileBox);
207 fileBoxHLayout->addWidget(mFileBrowseButton);
208 mFileBrowseButton->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
209 int size = mFileBrowseButton->sizeHint().height();
210 mFileBrowseButton->setFixedSize(size, size);
211 mFileBrowseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
212 mFileBrowseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a text or image file to display."));
213 connect(mFileBrowseButton, &QPushButton::clicked, this, &EditDisplayAlarmDlg::slotPickFile);
215 // Command type checkbox and edit box
216 mCmdEdit = new CommandEdit(parent);
217 connect(mCmdEdit, &CommandEdit::scriptToggled, this, &EditDisplayAlarmDlg::slotCmdScriptToggled);
218 connect(mCmdEdit, &CommandEdit::changed, this, &EditDisplayAlarmDlg::contentsChanged);
219 frameLayout->addWidget(mCmdEdit);
221 // Sound checkbox and file selector
222 QHBoxLayout* hlayout = new QHBoxLayout();
223 hlayout->setMargin(0);
224 frameLayout->addLayout(hlayout);
225 mSoundPicker = new SoundPicker(parent);
226 mSoundPicker->setFixedSize(mSoundPicker->sizeHint());
227 connect(mSoundPicker, &SoundPicker::changed, this, &EditDisplayAlarmDlg::contentsChanged);
228 hlayout->addWidget(mSoundPicker);
229 hlayout->addSpacing(2 * style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
230 hlayout->addStretch();
232 // Font and colour choice button and sample text
233 mFontColourButton = new FontColourButton(parent);
234 mFontColourButton->setMaximumHeight(mFontColourButton->sizeHint().height() * 3/2);
235 hlayout->addWidget(mFontColourButton);
236 connect(mFontColourButton, &FontColourButton::selected, this, &EditDisplayAlarmDlg::setColours);
237 connect(mFontColourButton, &FontColourButton::selected, this, &EditDisplayAlarmDlg::contentsChanged);
239 if (ShellProcess::authorised()) // don't display if shell commands not allowed (e.g. kiosk mode)
241 // Special actions button
242 mSpecialActionsButton = new SpecialActionsButton(false, parent);
243 mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
244 connect(mSpecialActionsButton, &SpecialActionsButton::selected, this, &EditDisplayAlarmDlg::contentsChanged);
245 frameLayout->addWidget(mSpecialActionsButton, 0, Qt::AlignRight);
248 // Top-adjust the controls
249 mFilePadding = new QWidget(parent);
250 hlayout = new QHBoxLayout(mFilePadding);
251 hlayout->setMargin(0);
252 hlayout->setSpacing(0);
253 frameLayout->addWidget(mFilePadding);
254 frameLayout->setStretchFactor(mFilePadding, 1);
257 /******************************************************************************
258 * Create a reminder control.
260 Reminder* EditDisplayAlarmDlg::createReminder(QWidget* parent)
262 static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of or after the main alarm to display a reminder alarm.");
263 return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of or after the main alarm time(s)."),
264 xi18nc("@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()),
265 i18nc("@info:whatsthis", "Select whether the reminder should be triggered before or after the main alarm"),
266 true, true, parent);
269 /******************************************************************************
270 * Create an "acknowledgement confirmation required" checkbox.
272 CheckBox* EditDisplayAlarmDlg::createConfirmAckCheckbox(QWidget* parent)
274 CheckBox* confirmAck = new CheckBox(i18n_chk_ConfirmAck(), parent);
275 confirmAck->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation when you acknowledge the alarm."));
276 return confirmAck;
279 /******************************************************************************
280 * Initialise the dialog controls from the specified event.
282 void EditDisplayAlarmDlg::type_initValues(const KAEvent* event)
284 mKMailSerialNumber = 0;
285 lateCancel()->showAutoClose(true);
286 if (event)
288 if (mAlarmType == KAEvent::MESSAGE && event->kmailSerialNumber()
289 && AlarmText::checkIfEmail(event->cleanText()))
290 mKMailSerialNumber = event->kmailSerialNumber();
291 lateCancel()->setAutoClose(event->autoClose());
292 if (event->useDefaultFont())
293 mFontColourButton->setDefaultFont();
294 else
295 mFontColourButton->setFont(event->font());
296 mFontColourButton->setBgColour(event->bgColour());
297 mFontColourButton->setFgColour(event->fgColour());
298 setColours(event->fgColour(), event->bgColour());
299 mConfirmAck->setChecked(event->confirmAck());
300 bool recurs = event->recurs();
301 int reminderMins = event->reminderMinutes();
302 if (reminderMins > 0 && !event->reminderActive())
303 reminderMins = 0; // don't show advance reminder which has already passed
304 if (!reminderMins)
306 if (event->reminderDeferral() && !recurs)
308 reminderMins = event->deferDateTime().minsTo(event->mainDateTime());
309 mReminderDeferral = true;
311 else if (event->reminderMinutes() && recurs)
313 reminderMins = event->reminderMinutes();
314 mReminderArchived = true;
317 reminder()->setMinutes(reminderMins, dateOnly());
318 reminder()->setOnceOnly(event->reminderOnceOnly());
319 reminder()->enableOnceOnly(recurs);
320 if (mSpecialActionsButton)
321 mSpecialActionsButton->setActions(event->preAction(), event->postAction(), event->extraActionOptions());
322 Preferences::SoundType soundType = event->speak() ? Preferences::Sound_Speak
323 : event->beep() ? Preferences::Sound_Beep
324 : !event->audioFile().isEmpty() ? Preferences::Sound_File
325 : Preferences::Sound_None;
326 mSoundPicker->set(soundType, event->audioFile(), event->soundVolume(),
327 event->fadeVolume(), event->fadeSeconds(), event->repeatSoundPause());
329 else
331 // Set the values to their defaults
332 if (!ShellProcess::authorised())
334 // Don't allow shell commands in kiosk mode
335 if (mSpecialActionsButton)
336 mSpecialActionsButton->setEnabled(false);
338 lateCancel()->setAutoClose(Preferences::defaultAutoClose());
339 mTypeCombo->setCurrentIndex(0);
340 mFontColourButton->setDefaultFont();
341 mFontColourButton->setBgColour(Preferences::defaultBgColour());
342 mFontColourButton->setFgColour(Preferences::defaultFgColour());
343 setColours(Preferences::defaultFgColour(), Preferences::defaultBgColour());
344 mConfirmAck->setChecked(Preferences::defaultConfirmAck());
345 reminder()->setMinutes(0, false);
346 reminder()->enableOnceOnly(isTimedRecurrence()); // must be called after mRecurrenceEdit is set up
347 if (mSpecialActionsButton)
349 KAEvent::ExtraActionOptions opts(Q_NULLPTR);
350 if (Preferences::defaultExecPreActionOnDeferral())
351 opts |= KAEvent::ExecPreActOnDeferral;
352 if (Preferences::defaultCancelOnPreActionError())
353 opts |= KAEvent::CancelOnPreActError;
354 if (Preferences::defaultDontShowPreActionError())
355 opts |= KAEvent::DontShowPreActError;
356 mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(), opts);
358 mSoundPicker->set(Preferences::defaultSoundType(), Preferences::defaultSoundFile(),
359 Preferences::defaultSoundVolume(), -1, 0, (Preferences::defaultSoundRepeat() ? 0 : -1));
363 /******************************************************************************
364 * Called when the More/Less Options button is clicked.
365 * Show/hide the optional options.
367 void EditDisplayAlarmDlg::type_showOptions(bool more)
369 if (mSpecialActionsButton)
371 if (more)
372 mSpecialActionsButton->show();
373 else
374 mSpecialActionsButton->hide();
378 /******************************************************************************
379 * Called when the font/color button has been clicked.
380 * Set the colors in the message text entry control.
382 void EditDisplayAlarmDlg::setColours(const QColor& fgColour, const QColor& bgColour)
384 QPalette pal = mTextMessageEdit->palette();
385 pal.setColor(mTextMessageEdit->backgroundRole(), bgColour);
386 pal.setColor(QPalette::Text, fgColour);
387 mTextMessageEdit->setPalette(pal);
388 pal = mTextMessageEdit->viewport()->palette();
389 pal.setColor(mTextMessageEdit->viewport()->backgroundRole(), bgColour);
390 pal.setColor(QPalette::Text, fgColour);
391 mTextMessageEdit->viewport()->setPalette(pal);
392 // Change the color of existing text
393 QTextCursor cursor = mTextMessageEdit->textCursor();
394 mTextMessageEdit->selectAll();
395 mTextMessageEdit->setTextColor(fgColour);
396 mTextMessageEdit->setTextCursor(cursor);
399 /******************************************************************************
400 * Set the dialog's action and the action's text.
402 void EditDisplayAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
404 QString text = alarmText.displayText();
405 switch (action)
407 case KAEvent::MESSAGE:
408 mTypeCombo->setCurrentIndex(tTEXT);
409 mTextMessageEdit->setPlainText(text);
410 mKMailSerialNumber = alarmText.isEmail() ? alarmText.kmailSerialNumber() : 0;
411 break;
412 case KAEvent::FILE:
413 mTypeCombo->setCurrentIndex(tFILE);
414 mFileMessageEdit->setText(text);
415 break;
416 case KAEvent::COMMAND:
417 mTypeCombo->setCurrentIndex(tCOMMAND);
418 mCmdEdit->setText(alarmText);
419 break;
420 default:
421 Q_ASSERT(0);
422 break;
426 /******************************************************************************
427 * Initialise various values in the New Alarm dialogue.
429 void EditDisplayAlarmDlg::setBgColour(const QColor& colour)
431 mFontColourButton->setBgColour(colour);
432 setColours(mFontColourButton->fgColour(), colour);
434 void EditDisplayAlarmDlg::setFgColour(const QColor& colour)
436 mFontColourButton->setFgColour(colour);
437 setColours(colour, mFontColourButton->bgColour());
439 void EditDisplayAlarmDlg::setConfirmAck(bool confirm)
441 mConfirmAck->setChecked(confirm);
443 void EditDisplayAlarmDlg::setAutoClose(bool close)
445 lateCancel()->setAutoClose(close);
447 void EditDisplayAlarmDlg::setAudio(Preferences::SoundType type, const QString& file, float volume, int repeatPause)
449 mSoundPicker->set(type, file, volume, -1, 0, repeatPause);
451 void EditDisplayAlarmDlg::setReminder(int minutes, bool onceOnly)
453 reminder()->setMinutes(minutes, dateOnly());
454 reminder()->setOnceOnly(onceOnly);
455 reminder()->enableOnceOnly(isTimedRecurrence());
458 /******************************************************************************
459 * Set the read-only status of all non-template controls.
461 void EditDisplayAlarmDlg::setReadOnly(bool readOnly)
463 mTypeCombo->setReadOnly(readOnly);
464 mTextMessageEdit->setReadOnly(readOnly);
465 mFileMessageEdit->setReadOnly(readOnly);
466 mCmdEdit->setReadOnly(readOnly);
467 mFontColourButton->setReadOnly(readOnly);
468 mSoundPicker->setReadOnly(readOnly);
469 mConfirmAck->setReadOnly(readOnly);
470 reminder()->setReadOnly(readOnly);
471 if (mSpecialActionsButton)
472 mSpecialActionsButton->setReadOnly(readOnly);
473 if (readOnly)
474 mFileBrowseButton->hide();
475 else
476 mFileBrowseButton->show();
477 EditAlarmDlg::setReadOnly(readOnly);
480 /******************************************************************************
481 * Save the state of all controls.
483 void EditDisplayAlarmDlg::saveState(const KAEvent* event)
485 EditAlarmDlg::saveState(event);
486 mSavedType = mTypeCombo->currentIndex();
487 mSavedCmdScript = mCmdEdit->isScript();
488 mSavedSoundType = mSoundPicker->sound();
489 mSavedSoundFile = mSoundPicker->file();
490 mSavedSoundVolume = mSoundPicker->volume(mSavedSoundFadeVolume, mSavedSoundFadeSeconds);
491 mSavedRepeatPause = mSoundPicker->repeatPause();
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 if (mSpecialActionsButton)
501 mSavedPreAction = mSpecialActionsButton->preAction();
502 mSavedPostAction = mSpecialActionsButton->postAction();
503 mSavedPreActionOptions = mSpecialActionsButton->options();
507 /******************************************************************************
508 * Check whether any of the controls has changed state since the dialog was
509 * first displayed.
510 * Reply = true if any controls have changed, or if it's a new event.
511 * = false if no controls have changed.
513 bool EditDisplayAlarmDlg::type_stateChanged() const
515 if (mSavedType != mTypeCombo->currentIndex()
516 || mSavedCmdScript != mCmdEdit->isScript()
517 || mSavedSoundType != mSoundPicker->sound()
518 || mSavedConfirmAck != mConfirmAck->isChecked()
519 || mSavedFont != mFontColourButton->font()
520 || mSavedFgColour != mFontColourButton->fgColour()
521 || mSavedBgColour != mFontColourButton->bgColour()
522 || mSavedReminder != reminder()->minutes()
523 || mSavedOnceOnly != reminder()->isOnceOnly()
524 || mSavedAutoClose != lateCancel()->isAutoClose())
525 return true;
526 if (mSpecialActionsButton)
528 if (mSavedPreAction != mSpecialActionsButton->preAction()
529 || mSavedPostAction != mSpecialActionsButton->postAction()
530 || mSavedPreActionOptions != mSpecialActionsButton->options())
531 return true;
533 if (mSavedSoundType == Preferences::Sound_File)
535 if (mSavedSoundFile != mSoundPicker->file())
536 return true;
537 if (!mSavedSoundFile.isEmpty())
539 float fadeVolume;
540 int fadeSecs;
541 if (mSavedRepeatPause != mSoundPicker->repeatPause()
542 || mSavedSoundVolume != mSoundPicker->volume(fadeVolume, fadeSecs)
543 || mSavedSoundFadeVolume != fadeVolume
544 || mSavedSoundFadeSeconds != fadeSecs)
545 return true;
548 return false;
551 /******************************************************************************
552 * Extract the data in the dialog specific to the alarm type and set up a
553 * KAEvent from it.
555 void EditDisplayAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
557 KAEvent::SubAction type;
558 switch (mTypeCombo->currentIndex())
560 case tFILE: type = KAEvent::FILE; break;
561 case tCOMMAND: type = KAEvent::COMMAND; break;
562 default:
563 case tTEXT: type = KAEvent::MESSAGE; break;
565 event.set(dt, text, mFontColourButton->bgColour(), mFontColourButton->fgColour(), mFontColourButton->font(),
566 type, lateCancel, getAlarmFlags());
567 if (type == KAEvent::MESSAGE)
569 if (AlarmText::checkIfEmail(text))
570 event.setKMailSerialNumber(mKMailSerialNumber);
572 float fadeVolume;
573 int fadeSecs;
574 float volume = mSoundPicker->volume(fadeVolume, fadeSecs);
575 int repeatPause = mSoundPicker->repeatPause();
576 event.setAudioFile(mSoundPicker->file().toDisplayString(), volume, fadeVolume, fadeSecs, repeatPause);
577 if (!trial && reminder()->isEnabled())
578 event.setReminder(reminder()->minutes(), reminder()->isOnceOnly());
579 if (mSpecialActionsButton && mSpecialActionsButton->isEnabled())
580 event.setActions(mSpecialActionsButton->preAction(), mSpecialActionsButton->postAction(),
581 mSpecialActionsButton->options());
584 /******************************************************************************
585 * Get the currently specified alarm flag bits.
587 KAEvent::Flags EditDisplayAlarmDlg::getAlarmFlags() const
589 bool cmd = (mTypeCombo->currentIndex() == tCOMMAND);
590 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
591 if (mSoundPicker->sound() == Preferences::Sound_Beep) flags |= KAEvent::BEEP;
592 if (mSoundPicker->sound() == Preferences::Sound_Speak) flags |= KAEvent::SPEAK;
593 if (mSoundPicker->repeatPause() >= 0) flags |= KAEvent::REPEAT_SOUND;
594 if (mConfirmAck->isChecked()) flags |= KAEvent::CONFIRM_ACK;
595 if (lateCancel()->isAutoClose()) flags |= KAEvent::AUTO_CLOSE;
596 if (mFontColourButton->defaultFont()) flags |= KAEvent::DEFAULT_FONT;
597 if (cmd) flags |= KAEvent::DISPLAY_COMMAND;
598 if (cmd && mCmdEdit->isScript()) flags |= KAEvent::SCRIPT;
599 return flags;
602 /******************************************************************************
603 * Called when one of the alarm display type combo box is changed, to display
604 * the appropriate set of controls for that action type.
606 void EditDisplayAlarmDlg::slotAlarmTypeChanged(int index)
608 QWidget* focus = Q_NULLPTR;
609 switch (index)
611 case tTEXT: // text message
612 mFileBox->hide();
613 mFilePadding->hide();
614 mCmdEdit->hide();
615 mTextMessageEdit->show();
616 mSoundPicker->showSpeak(true);
617 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Display the alarm message now"));
618 focus = mTextMessageEdit;
619 break;
620 case tFILE: // file contents
621 mTextMessageEdit->hide();
622 mFileBox->show();
623 mFilePadding->show();
624 mCmdEdit->hide();
625 mSoundPicker->showSpeak(false);
626 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Display the file now"));
627 mFileMessageEdit->setNoSelect();
628 focus = mFileMessageEdit;
629 break;
630 case tCOMMAND: // command output
631 mTextMessageEdit->hide();
632 mFileBox->hide();
633 slotCmdScriptToggled(mCmdEdit->isScript()); // show/hide mFilePadding
634 mCmdEdit->show();
635 mSoundPicker->showSpeak(true);
636 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Display the command output now"));
637 focus = mCmdEdit;
638 break;
640 if (focus)
641 focus->setFocus();
644 /******************************************************************************
645 * Called when the file browse button is pressed to select a file to display.
647 void EditDisplayAlarmDlg::slotPickFile()
649 static QString defaultDir; // default directory for file browse button
650 QString file = KAlarm::browseFile(i18nc("@title:window", "Choose Text or Image File to Display"),
651 defaultDir, mFileMessageEdit->text(), QString(), KFile::ExistingOnly, this);
652 if (!file.isEmpty())
654 mFileMessageEdit->setText(KAlarm::pathOrUrl(file));
655 contentsChanged();
659 /******************************************************************************
660 * Called when one of the command type radio buttons is clicked,
661 * to display the appropriate edit field.
663 void EditDisplayAlarmDlg::slotCmdScriptToggled(bool on)
665 if (on)
666 mFilePadding->hide();
667 else
668 mFilePadding->show();
671 /******************************************************************************
672 * Clean up the alarm text, and if it's a file, check whether it's valid.
674 bool EditDisplayAlarmDlg::checkText(QString& result, bool showErrorMessage) const
676 switch (mTypeCombo->currentIndex())
678 case tTEXT:
679 result = mTextMessageEdit->toPlainText();
680 break;
682 case tFILE:
684 QString alarmtext = mFileMessageEdit->text().trimmed();
685 QUrl url;
686 KAlarm::FileErr err = KAlarm::checkFileExists(alarmtext, url);
687 if (err == KAlarm::FileErr_None)
689 KFileItem fi(url);
690 switch (KAlarm::fileType(fi.currentMimeType()))
692 case KAlarm::TextFormatted:
693 case KAlarm::TextPlain:
694 case KAlarm::TextApplication:
695 case KAlarm::Image:
696 break;
697 default:
698 err = KAlarm::FileErr_NotTextImage;
699 break;
702 if (err != KAlarm::FileErr_None && showErrorMessage)
704 mFileMessageEdit->setFocus();
705 if (!KAlarm::showFileErrMessage(alarmtext, err, KAlarm::FileErr_BlankDisplay, const_cast<EditDisplayAlarmDlg*>(this)))
706 return false;
708 result = alarmtext;
709 break;
711 case tCOMMAND:
712 result = mCmdEdit->text(const_cast<EditDisplayAlarmDlg*>(this), showErrorMessage);
713 if (result.isEmpty())
714 return false;
715 break;
717 return true;
721 /*=============================================================================
722 = Class EditCommandAlarmDlg
723 = Dialog to edit command alarms.
724 =============================================================================*/
726 QString EditCommandAlarmDlg::i18n_chk_EnterScript() { return i18nc("@option:check", "Enter a script"); }
727 QString EditCommandAlarmDlg::i18n_radio_ExecInTermWindow() { return i18nc("@option:radio", "Execute in terminal window"); }
728 QString EditCommandAlarmDlg::i18n_chk_ExecInTermWindow() { return i18nc("@option:check", "Execute in terminal window"); }
731 /******************************************************************************
732 * Constructor.
733 * Parameters:
734 * Template = true to edit/create an alarm template
735 * = false to edit/create an alarm.
736 * event != to initialise the dialog to show the specified event's data.
738 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
739 : EditAlarmDlg(Template, KAEvent::COMMAND, parent, getResource)
741 qCDebug(KALARM_LOG) << "New";
742 init(Q_NULLPTR);
745 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
746 GetResourceType getResource, bool readOnly)
747 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly)
749 qCDebug(KALARM_LOG) << "Event.id()";
750 init(event);
753 /******************************************************************************
754 * Return the window caption.
756 QString EditCommandAlarmDlg::type_caption() const
758 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Command Alarm Template") : i18nc("@title:window", "Edit Command Alarm Template"))
759 : (isNewAlarm() ? i18nc("@title:window", "New Command Alarm") : i18nc("@title:window", "Edit Command Alarm"));
762 /******************************************************************************
763 * Set up the command alarm dialog controls.
765 void EditCommandAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
767 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Execute the specified command now"));
769 mCmdEdit = new CommandEdit(parent);
770 connect(mCmdEdit, &CommandEdit::scriptToggled, this, &EditCommandAlarmDlg::slotCmdScriptToggled);
771 connect(mCmdEdit, &CommandEdit::changed, this, &EditCommandAlarmDlg::contentsChanged);
772 frameLayout->addWidget(mCmdEdit);
774 // What to do with command output
776 mCmdOutputBox = new QGroupBox(i18nc("@title:group", "Command Output"), parent);
777 frameLayout->addWidget(mCmdOutputBox);
778 QVBoxLayout* vlayout = new QVBoxLayout(mCmdOutputBox);
779 vlayout->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
780 vlayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
781 mCmdOutputGroup = new ButtonGroup(mCmdOutputBox);
782 connect(mCmdOutputGroup, &ButtonGroup::buttonSet, this, &EditCommandAlarmDlg::contentsChanged);
784 // Execute in terminal window
785 mCmdExecInTerm = new RadioButton(i18n_radio_ExecInTermWindow(), mCmdOutputBox);
786 mCmdExecInTerm->setFixedSize(mCmdExecInTerm->sizeHint());
787 mCmdExecInTerm->setWhatsThis(i18nc("@info:whatsthis", "Check to execute the command in a terminal window"));
788 mCmdOutputGroup->addButton(mCmdExecInTerm, Preferences::Log_Terminal);
789 vlayout->addWidget(mCmdExecInTerm, 0, Qt::AlignLeft);
791 // Log file name edit box
792 QWidget* box = new QWidget(mCmdOutputBox);
793 QHBoxLayout* boxHLayout = new QHBoxLayout(box);
794 boxHLayout->setMargin(0);
795 boxHLayout->setSpacing(0);
796 (new QWidget(box))->setFixedWidth(mCmdExecInTerm->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth)); // indent the edit box
797 mCmdLogFileEdit = new LineEdit(LineEdit::Url, box);
798 boxHLayout->addWidget(mCmdLogFileEdit);
799 mCmdLogFileEdit->setAcceptDrops(true);
800 mCmdLogFileEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or path of the log file."));
801 connect(mCmdLogFileEdit, &LineEdit::textChanged, this, &EditCommandAlarmDlg::contentsChanged);
803 // Log file browse button.
804 // The file browser dialog is activated by the PickLogFileRadio class.
805 QPushButton* browseButton = new QPushButton(box);
806 boxHLayout->addWidget(browseButton);
807 browseButton->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
808 int size = browseButton->sizeHint().height();
809 browseButton->setFixedSize(size, size);
810 browseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
811 browseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a log file."));
813 // Log output to file
814 mCmdLogToFile = new PickLogFileRadio(browseButton, mCmdLogFileEdit, i18nc("@option:radio", "Log to file"), mCmdOutputGroup, mCmdOutputBox);
815 mCmdLogToFile->setFixedSize(mCmdLogToFile->sizeHint());
816 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."));
817 connect(mCmdLogToFile, &PickLogFileRadio::fileChanged, this, &EditCommandAlarmDlg::contentsChanged);
818 mCmdOutputGroup->addButton(mCmdLogToFile, Preferences::Log_File);
819 vlayout->addWidget(mCmdLogToFile, 0, Qt::AlignLeft);
820 vlayout->addWidget(box);
822 // Discard output
823 mCmdDiscardOutput = new RadioButton(i18nc("@option:radio", "Discard"), mCmdOutputBox);
824 mCmdDiscardOutput->setFixedSize(mCmdDiscardOutput->sizeHint());
825 mCmdDiscardOutput->setWhatsThis(i18nc("@info:whatsthis", "Check to discard command output."));
826 mCmdOutputGroup->addButton(mCmdDiscardOutput, Preferences::Log_Discard);
827 vlayout->addWidget(mCmdDiscardOutput, 0, Qt::AlignLeft);
829 // Top-adjust the controls
830 mCmdPadding = new QWidget(parent);
831 QHBoxLayout* hlayout = new QHBoxLayout(mCmdPadding);
832 hlayout->setMargin(0);
833 hlayout->setSpacing(0);
834 frameLayout->addWidget(mCmdPadding);
835 frameLayout->setStretchFactor(mCmdPadding, 1);
838 /******************************************************************************
839 * Initialise the dialog controls from the specified event.
841 void EditCommandAlarmDlg::type_initValues(const KAEvent* event)
843 if (event)
845 // Set the values to those for the specified event
846 RadioButton* logType = event->commandXterm() ? mCmdExecInTerm
847 : !event->logFile().isEmpty() ? mCmdLogToFile
848 : mCmdDiscardOutput;
849 if (logType == mCmdLogToFile)
850 mCmdLogFileEdit->setText(event->logFile()); // set file name before setting radio button
851 logType->setChecked(true);
853 else
855 // Set the values to their defaults
856 mCmdEdit->setScript(Preferences::defaultCmdScript());
857 mCmdLogFileEdit->setText(Preferences::defaultCmdLogFile()); // set file name before setting radio button
858 mCmdOutputGroup->setButton(Preferences::defaultCmdLogType());
860 slotCmdScriptToggled(mCmdEdit->isScript());
863 /******************************************************************************
864 * Called when the More/Less Options button is clicked.
865 * Show/hide the optional options.
867 void EditCommandAlarmDlg::type_showOptions(bool more)
869 if (more)
870 mCmdOutputBox->show();
871 else
872 mCmdOutputBox->hide();
875 /******************************************************************************
876 * Set the dialog's action and the action's text.
878 void EditCommandAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
880 Q_UNUSED(action);
881 Q_ASSERT(action == KAEvent::COMMAND);
882 mCmdEdit->setText(alarmText);
885 /******************************************************************************
886 * Set the read-only status of all non-template controls.
888 void EditCommandAlarmDlg::setReadOnly(bool readOnly)
890 if (!isTemplate() && !ShellProcess::authorised())
891 readOnly = true; // don't allow editing of existing command alarms in kiosk mode
892 mCmdEdit->setReadOnly(readOnly);
893 mCmdExecInTerm->setReadOnly(readOnly);
894 mCmdLogToFile->setReadOnly(readOnly);
895 mCmdDiscardOutput->setReadOnly(readOnly);
896 EditAlarmDlg::setReadOnly(readOnly);
899 /******************************************************************************
900 * Save the state of all controls.
902 void EditCommandAlarmDlg::saveState(const KAEvent* event)
904 EditAlarmDlg::saveState(event);
905 mSavedCmdScript = mCmdEdit->isScript();
906 mSavedCmdOutputRadio = mCmdOutputGroup->checkedButton();
907 mSavedCmdLogFile = mCmdLogFileEdit->text();
910 /******************************************************************************
911 * Check whether any of the controls has changed state since the dialog was
912 * first displayed.
913 * Reply = true if any controls have changed, or if it's a new event.
914 * = false if no controls have changed.
916 bool EditCommandAlarmDlg::type_stateChanged() const
918 if (mSavedCmdScript != mCmdEdit->isScript()
919 || mSavedCmdOutputRadio != mCmdOutputGroup->checkedButton())
920 return true;
921 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
923 if (mSavedCmdLogFile != mCmdLogFileEdit->text())
924 return true;
926 return false;
929 /******************************************************************************
930 * Extract the data in the dialog specific to the alarm type and set up a
931 * KAEvent from it.
933 void EditCommandAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
935 Q_UNUSED(trial);
936 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::COMMAND, lateCancel, getAlarmFlags());
937 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
938 event.setLogFile(mCmdLogFileEdit->text());
941 /******************************************************************************
942 * Get the currently specified alarm flag bits.
944 KAEvent::Flags EditCommandAlarmDlg::getAlarmFlags() const
946 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
947 if (mCmdEdit->isScript()) flags |= KAEvent::SCRIPT;
948 if (mCmdOutputGroup->checkedButton() == mCmdExecInTerm) flags |= KAEvent::EXEC_IN_XTERM;
949 return flags;
952 /******************************************************************************
953 * Validate and convert command alarm data.
955 bool EditCommandAlarmDlg::type_validate(bool trial)
957 Q_UNUSED(trial);
958 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
960 // Validate the log file name
961 QString file = mCmdLogFileEdit->text();
962 QFileInfo info(file);
963 QDir::setCurrent(QDir::homePath());
964 bool err = file.isEmpty() || info.isDir();
965 if (!err)
967 if (info.exists())
969 err = !info.isWritable();
971 else
973 QFileInfo dirinfo(info.absolutePath()); // get absolute directory path
974 err = (!dirinfo.isDir() || !dirinfo.isWritable());
977 if (err)
979 showMainPage();
980 mCmdLogFileEdit->setFocus();
981 KAMessageBox::sorry(this, i18nc("@info", "Log file must be the name or path of a local file, with write permission."));
982 return false;
984 // Convert the log file to an absolute path
985 mCmdLogFileEdit->setText(info.absoluteFilePath());
987 return true;
990 /******************************************************************************
991 * Called when the Try action has been executed.
992 * Tell the user the result of the Try action.
994 void EditCommandAlarmDlg::type_executedTry(const QString& text, void* result)
996 ShellProcess* proc = (ShellProcess*)result;
997 if (proc && proc != (void*)-1
998 && mCmdOutputGroup->checkedButton() != mCmdExecInTerm)
1000 theApp()->commandMessage(proc, this);
1001 KAMessageBox::information(this, xi18nc("@info", "Command executed: <icode>%1</icode>", text));
1002 theApp()->commandMessage(proc, Q_NULLPTR);
1006 /******************************************************************************
1007 * Called when one of the command type radio buttons is clicked,
1008 * to display the appropriate edit field.
1010 void EditCommandAlarmDlg::slotCmdScriptToggled(bool on)
1012 if (on)
1013 mCmdPadding->hide();
1014 else
1015 mCmdPadding->show();
1018 /******************************************************************************
1019 * Clean up the alarm text.
1021 bool EditCommandAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1023 result = mCmdEdit->text(const_cast<EditCommandAlarmDlg*>(this), showErrorMessage);
1024 if (result.isEmpty())
1025 return false;
1026 return true;
1030 /*=============================================================================
1031 = Class EditEmailAlarmDlg
1032 = Dialog to edit email alarms.
1033 =============================================================================*/
1035 QString EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf() { return i18nc("@option:check", "Copy email to self"); }
1038 /******************************************************************************
1039 * Constructor.
1040 * Parameters:
1041 * Template = true to edit/create an alarm template
1042 * = false to edit/create an alarm.
1043 * event != to initialise the dialog to show the specified event's data.
1045 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1046 : EditAlarmDlg(Template, KAEvent::EMAIL, parent, getResource),
1047 mEmailRemoveButton(Q_NULLPTR)
1049 qCDebug(KALARM_LOG) << "New";
1050 init(Q_NULLPTR);
1053 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1054 GetResourceType getResource, bool readOnly)
1055 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
1056 mEmailRemoveButton(Q_NULLPTR)
1058 qCDebug(KALARM_LOG) << "Event.id()";
1059 init(event);
1062 /******************************************************************************
1063 * Return the window caption.
1065 QString EditEmailAlarmDlg::type_caption() const
1067 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Email Alarm Template") : i18nc("@title:window", "Edit Email Alarm Template"))
1068 : (isNewAlarm() ? i18nc("@title:window", "New Email Alarm") : i18nc("@title:window", "Edit Email Alarm"));
1071 /******************************************************************************
1072 * Set up the email alarm dialog controls.
1074 void EditEmailAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1076 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Send the email to the specified addressees now"));
1078 QGridLayout* grid = new QGridLayout();
1079 grid->setMargin(0);
1080 grid->setColumnStretch(1, 1);
1081 frameLayout->addLayout(grid);
1083 mEmailFromList = Q_NULLPTR;
1084 if (Preferences::emailFrom() == Preferences::MAIL_FROM_KMAIL)
1086 // Email sender identity
1087 QLabel* label = new QLabel(i18nc("@label:listbox 'From' email address", "From:"), parent);
1088 label->setFixedSize(label->sizeHint());
1089 grid->addWidget(label, 0, 0);
1091 mEmailFromList = new EmailIdCombo(Identities::identityManager(), parent);
1092 mEmailFromList->setMinimumSize(mEmailFromList->sizeHint());
1093 label->setBuddy(mEmailFromList);
1094 mEmailFromList->setWhatsThis(i18nc("@info:whatsthis", "Your email identity, used to identify you as the sender when sending email alarms."));
1095 connect(mEmailFromList, &EmailIdCombo::identityChanged, this, &EditEmailAlarmDlg::contentsChanged);
1096 grid->addWidget(mEmailFromList, 0, 1, 1, 2);
1099 // Email recipients
1100 QLabel* label = new QLabel(i18nc("@label:textbox Email addressee", "To:"), parent);
1101 label->setFixedSize(label->sizeHint());
1102 grid->addWidget(label, 1, 0);
1104 mEmailToEdit = new LineEdit(LineEdit::Emails, parent);
1105 mEmailToEdit->setMinimumSize(mEmailToEdit->sizeHint());
1106 mEmailToEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the addresses of the email recipients. Separate multiple addresses by "
1107 "commas or semicolons."));
1108 connect(mEmailToEdit, &LineEdit::textChanged, this, &EditEmailAlarmDlg::contentsChanged);
1109 grid->addWidget(mEmailToEdit, 1, 1);
1111 mEmailAddressButton = new QPushButton(parent);
1112 mEmailAddressButton->setIcon(QIcon::fromTheme(QStringLiteral("help-contents")));
1113 int size = mEmailAddressButton->sizeHint().height();
1114 mEmailAddressButton->setFixedSize(size, size);
1115 connect(mEmailAddressButton, &QPushButton::clicked, this, &EditEmailAlarmDlg::openAddressBook);
1116 mEmailAddressButton->setToolTip(i18nc("@info:tooltip", "Open address book"));
1117 mEmailAddressButton->setWhatsThis(i18nc("@info:whatsthis", "Select email addresses from your address book."));
1118 grid->addWidget(mEmailAddressButton, 1, 2);
1120 // Email subject
1121 label = new QLabel(i18nc("@label:textbox Email subject", "Subject:"), parent);
1122 label->setFixedSize(label->sizeHint());
1123 grid->addWidget(label, 2, 0);
1125 mEmailSubjectEdit = new LineEdit(parent);
1126 mEmailSubjectEdit->setMinimumSize(mEmailSubjectEdit->sizeHint());
1127 label->setBuddy(mEmailSubjectEdit);
1128 mEmailSubjectEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email subject."));
1129 connect(mEmailSubjectEdit, &LineEdit::textChanged, this, &EditEmailAlarmDlg::contentsChanged);
1130 grid->addWidget(mEmailSubjectEdit, 2, 1, 1, 2);
1132 // Email body
1133 mEmailMessageEdit = new TextEdit(parent);
1134 mEmailMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email message."));
1135 connect(mEmailMessageEdit, &TextEdit::textChanged, this, &EditEmailAlarmDlg::contentsChanged);
1136 frameLayout->addWidget(mEmailMessageEdit);
1138 // Email attachments
1139 grid = new QGridLayout();
1140 grid->setMargin(0);
1141 frameLayout->addLayout(grid);
1142 label = new QLabel(i18nc("@label:listbox", "Attachments:"), parent);
1143 label->setFixedSize(label->sizeHint());
1144 grid->addWidget(label, 0, 0);
1146 mEmailAttachList = new QComboBox(parent);
1147 mEmailAttachList->setEditable(true);
1148 mEmailAttachList->setMinimumSize(mEmailAttachList->sizeHint());
1149 if (mEmailAttachList->lineEdit())
1150 mEmailAttachList->lineEdit()->setReadOnly(true);
1151 label->setBuddy(mEmailAttachList);
1152 mEmailAttachList->setWhatsThis(i18nc("@info:whatsthis", "Files to send as attachments to the email."));
1153 grid->addWidget(mEmailAttachList, 0, 1);
1154 grid->setColumnStretch(1, 1);
1156 mEmailAddAttachButton = new QPushButton(i18nc("@action:button", "Add..."), parent);
1157 connect(mEmailAddAttachButton, &QPushButton::clicked, this, &EditEmailAlarmDlg::slotAddAttachment);
1158 mEmailAddAttachButton->setWhatsThis(i18nc("@info:whatsthis", "Add an attachment to the email."));
1159 grid->addWidget(mEmailAddAttachButton, 0, 2);
1161 mEmailRemoveButton = new QPushButton(i18nc("@action:button", "Remove"), parent);
1162 connect(mEmailRemoveButton, &QPushButton::clicked, this, &EditEmailAlarmDlg::slotRemoveAttachment);
1163 mEmailRemoveButton->setWhatsThis(i18nc("@info:whatsthis", "Remove the highlighted attachment from the email."));
1164 grid->addWidget(mEmailRemoveButton, 1, 2);
1166 // BCC email to sender
1167 mEmailBcc = new CheckBox(i18n_chk_CopyEmailToSelf(), parent);
1168 mEmailBcc->setFixedSize(mEmailBcc->sizeHint());
1169 mEmailBcc->setWhatsThis(i18nc("@info:whatsthis", "If checked, the email will be blind copied to you."));
1170 connect(mEmailBcc, &CheckBox::toggled, this, &EditEmailAlarmDlg::contentsChanged);
1171 grid->addWidget(mEmailBcc, 1, 0, 1, 2, Qt::AlignLeft);
1174 /******************************************************************************
1175 * Initialise the dialog controls from the specified event.
1177 void EditEmailAlarmDlg::type_initValues(const KAEvent* event)
1179 if (event)
1181 // Set the values to those for the specified event
1182 mEmailAttachList->addItems(event->emailAttachments());
1183 mEmailToEdit->setText(event->emailAddresses(QStringLiteral(", ")));
1184 mEmailSubjectEdit->setText(event->emailSubject());
1185 mEmailBcc->setChecked(event->emailBcc());
1186 if (mEmailFromList)
1187 mEmailFromList->setCurrentIdentity(event->emailFromId());
1189 else
1191 // Set the values to their defaults
1192 mEmailBcc->setChecked(Preferences::defaultEmailBcc());
1194 attachmentEnable();
1197 /******************************************************************************
1198 * Enable/disable controls depending on whether any attachments are entered.
1200 void EditEmailAlarmDlg::attachmentEnable()
1202 bool enable = mEmailAttachList->count();
1203 mEmailAttachList->setEnabled(enable);
1204 if (mEmailRemoveButton)
1205 mEmailRemoveButton->setEnabled(enable);
1208 /******************************************************************************
1209 * Set the dialog's action and the action's text.
1211 void EditEmailAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
1213 Q_UNUSED(action);
1214 Q_ASSERT(action == KAEvent::EMAIL);
1215 if (alarmText.isEmail())
1217 mEmailToEdit->setText(alarmText.to());
1218 mEmailSubjectEdit->setText(alarmText.subject());
1219 mEmailMessageEdit->setPlainText(alarmText.body());
1221 else
1222 mEmailMessageEdit->setPlainText(alarmText.displayText());
1225 /******************************************************************************
1226 * Initialise various values in the New Alarm dialogue.
1228 void EditEmailAlarmDlg::setEmailFields(uint fromID, const KCalCore::Person::List& addresses,
1229 const QString& subject, const QStringList& attachments)
1231 if (fromID)
1232 mEmailFromList->setCurrentIdentity(fromID);
1233 if (!addresses.isEmpty())
1234 mEmailToEdit->setText(KAEvent::joinEmailAddresses(addresses, QStringLiteral(", ")));
1235 if (!subject.isEmpty())
1236 mEmailSubjectEdit->setText(subject);
1237 if (!attachments.isEmpty())
1239 mEmailAttachList->addItems(attachments);
1240 attachmentEnable();
1243 void EditEmailAlarmDlg::setBcc(bool bcc)
1245 mEmailBcc->setChecked(bcc);
1248 /******************************************************************************
1249 * Set the read-only status of all non-template controls.
1251 void EditEmailAlarmDlg::setReadOnly(bool readOnly)
1253 mEmailToEdit->setReadOnly(readOnly);
1254 mEmailSubjectEdit->setReadOnly(readOnly);
1255 mEmailMessageEdit->setReadOnly(readOnly);
1256 mEmailBcc->setReadOnly(readOnly);
1257 if (mEmailFromList)
1258 mEmailFromList->setReadOnly(readOnly);
1259 if (readOnly)
1261 mEmailAddressButton->hide();
1262 mEmailAddAttachButton->hide();
1263 mEmailRemoveButton->hide();
1265 else
1267 mEmailAddressButton->show();
1268 mEmailAddAttachButton->show();
1269 mEmailRemoveButton->show();
1271 EditAlarmDlg::setReadOnly(readOnly);
1274 /******************************************************************************
1275 * Save the state of all controls.
1277 void EditEmailAlarmDlg::saveState(const KAEvent* event)
1279 EditAlarmDlg::saveState(event);
1280 if (mEmailFromList)
1281 mSavedEmailFrom = mEmailFromList->currentIdentityName();
1282 mSavedEmailTo = mEmailToEdit->text();
1283 mSavedEmailSubject = mEmailSubjectEdit->text();
1284 mSavedEmailAttach.clear();
1285 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1286 mSavedEmailAttach += mEmailAttachList->itemText(i);
1287 mSavedEmailBcc = mEmailBcc->isChecked();
1290 /******************************************************************************
1291 * Check whether any of the controls has changed state since the dialog was
1292 * first displayed.
1293 * Reply = true if any controls have changed, or if it's a new event.
1294 * = false if no controls have changed.
1296 bool EditEmailAlarmDlg::type_stateChanged() const
1298 QStringList emailAttach;
1299 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1300 emailAttach += mEmailAttachList->itemText(i);
1301 if ((mEmailFromList && mSavedEmailFrom != mEmailFromList->currentIdentityName())
1302 || mSavedEmailTo != mEmailToEdit->text()
1303 || mSavedEmailSubject != mEmailSubjectEdit->text()
1304 || mSavedEmailAttach != emailAttach
1305 || mSavedEmailBcc != mEmailBcc->isChecked())
1306 return true;
1307 return false;
1310 /******************************************************************************
1311 * Extract the data in the dialog specific to the alarm type and set up a
1312 * KAEvent from it.
1314 void EditEmailAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1316 Q_UNUSED(trial);
1317 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::EMAIL, lateCancel, getAlarmFlags());
1318 uint from = mEmailFromList ? mEmailFromList->currentIdentity() : 0;
1319 event.setEmail(from, mEmailAddresses, mEmailSubjectEdit->text(), mEmailAttachments);
1322 /******************************************************************************
1323 * Get the currently specified alarm flag bits.
1325 KAEvent::Flags EditEmailAlarmDlg::getAlarmFlags() const
1327 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
1328 if (mEmailBcc->isChecked()) flags |= KAEvent::EMAIL_BCC;
1329 return flags;
1332 /******************************************************************************
1333 * Convert the email addresses to a list, and validate them. Convert the email
1334 * attachments to a list.
1336 bool EditEmailAlarmDlg::type_validate(bool trial)
1338 QString addrs = mEmailToEdit->text();
1339 if (addrs.isEmpty())
1340 mEmailAddresses.clear();
1341 else
1343 QString bad = KAMail::convertAddresses(addrs, mEmailAddresses);
1344 if (!bad.isEmpty())
1346 mEmailToEdit->setFocus();
1347 KAMessageBox::error(this, xi18nc("@info", "Invalid email address: <email>%1</email>", bad));
1348 return false;
1351 if (mEmailAddresses.isEmpty())
1353 mEmailToEdit->setFocus();
1354 KAMessageBox::error(this, i18nc("@info", "No email address specified"));
1355 return false;
1358 mEmailAttachments.clear();
1359 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1361 QString att = mEmailAttachList->itemText(i);
1362 switch (KAMail::checkAttachment(att))
1364 case 1:
1365 mEmailAttachments.append(att);
1366 break;
1367 case 0:
1368 break; // empty
1369 case -1:
1370 mEmailAttachList->setFocus();
1371 KAMessageBox::error(this, xi18nc("@info", "Invalid email attachment: <filename>%1</filename>", att));
1372 return false;
1375 if (trial && KAMessageBox::warningContinueCancel(this, i18nc("@info", "Do you really want to send the email now to the specified recipient(s)?"),
1376 i18nc("@action:button", "Confirm Email"), KGuiItem(i18nc("@action:button", "Send"))) != KMessageBox::Continue)
1377 return false;
1378 return true;
1381 /******************************************************************************
1382 * Called when the Try action is about to be executed.
1384 void EditEmailAlarmDlg::type_aboutToTry()
1386 // Disconnect any previous connections, to prevent multiple messages being output
1387 disconnect(theApp(), &KAlarmApp::execAlarmSuccess, this, &EditEmailAlarmDlg::slotTrySuccess);
1388 connect(theApp(), &KAlarmApp::execAlarmSuccess, this, &EditEmailAlarmDlg::slotTrySuccess);
1391 /******************************************************************************
1392 * Tell the user the result of the Try action.
1394 void EditEmailAlarmDlg::slotTrySuccess()
1396 disconnect(theApp(), &KAlarmApp::execAlarmSuccess, this, &EditEmailAlarmDlg::slotTrySuccess);
1397 QString msg;
1398 QString to = KAEvent::joinEmailAddresses(mEmailAddresses, QStringLiteral("<nl/>"));
1399 to.replace(QLatin1Char('<'), QStringLiteral("&lt;"));
1400 to.replace(QLatin1Char('>'), QStringLiteral("&gt;"));
1401 if (mEmailBcc->isChecked())
1402 msg = QLatin1String("<qt>") + xi18nc("@info", "Email sent to:<nl/>%1<nl/>Bcc: <email>%2</email>",
1403 to, Preferences::emailBccAddress()) + QLatin1String("</qt>");
1404 else
1405 msg = QLatin1String("<qt>") + xi18nc("@info", "Email sent to:<nl/>%1", to) + QLatin1String("</qt>");
1406 KAMessageBox::information(this, msg);
1409 /******************************************************************************
1410 * Get a selection from the Address Book.
1412 void EditEmailAlarmDlg::openAddressBook()
1414 // Use AutoQPointer to guard against crash on application exit while
1415 // the dialogue is still open. It prevents double deletion (both on
1416 // deletion of MainWindow, and on return from this function).
1417 AutoQPointer<Akonadi::EmailAddressSelectionDialog> dlg = new Akonadi::EmailAddressSelectionDialog(this);
1418 if (dlg->exec() != QDialog::Accepted)
1419 return;
1421 Akonadi::EmailAddressSelection::List selections = dlg->selectedAddresses();
1422 if (selections.isEmpty())
1423 return;
1424 Person person(selections.first().name(), selections.first().email());
1425 QString addrs = mEmailToEdit->text().trimmed();
1426 if (!addrs.isEmpty())
1427 addrs += QLatin1String(", ");
1428 addrs += person.fullName();
1429 mEmailToEdit->setText(addrs);
1432 /******************************************************************************
1433 * Select a file to attach to the email.
1435 void EditEmailAlarmDlg::slotAddAttachment()
1437 QString url = KAlarm::browseFile(i18nc("@title:window", "Choose File to Attach"), mAttachDefaultDir, QString(),
1438 QString(), KFile::ExistingOnly, this);
1439 if (!url.isEmpty())
1441 mEmailAttachList->addItem(url);
1442 mEmailAttachList->setCurrentIndex(mEmailAttachList->count() - 1); // select the new item
1443 mEmailRemoveButton->setEnabled(true);
1444 mEmailAttachList->setEnabled(true);
1445 contentsChanged();
1449 /******************************************************************************
1450 * Remove the currently selected attachment from the email.
1452 void EditEmailAlarmDlg::slotRemoveAttachment()
1454 int item = mEmailAttachList->currentIndex();
1455 mEmailAttachList->removeItem(item);
1456 int count = mEmailAttachList->count();
1457 if (item >= count)
1458 mEmailAttachList->setCurrentIndex(count - 1);
1459 if (!count)
1461 mEmailRemoveButton->setEnabled(false);
1462 mEmailAttachList->setEnabled(false);
1464 contentsChanged();
1467 /******************************************************************************
1468 * Clean up the alarm text.
1470 bool EditEmailAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1472 Q_UNUSED(showErrorMessage);
1473 result = mEmailMessageEdit->toPlainText();
1474 return true;
1478 /*=============================================================================
1479 = Class EditAudioAlarmDlg
1480 = Dialog to edit audio alarms with no display window.
1481 =============================================================================*/
1483 /******************************************************************************
1484 * Constructor.
1485 * Parameters:
1486 * Template = true to edit/create an alarm template
1487 * = false to edit/create an alarm.
1488 * event != to initialise the dialog to show the specified event's data.
1490 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1491 : EditAlarmDlg(Template, KAEvent::AUDIO, parent, getResource),
1492 mMessageWin(Q_NULLPTR)
1494 qCDebug(KALARM_LOG) << "New";
1495 init(Q_NULLPTR);
1498 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1499 GetResourceType getResource, bool readOnly)
1500 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
1501 mMessageWin(Q_NULLPTR)
1503 qCDebug(KALARM_LOG) << "Event.id()";
1504 init(event);
1505 mTryButton->setEnabled(!MessageWin::isAudioPlaying());
1506 connect(theApp(), &KAlarmApp::audioPlaying, this, &EditAudioAlarmDlg::slotAudioPlaying);
1509 /******************************************************************************
1510 * Return the window caption.
1512 QString EditAudioAlarmDlg::type_caption() const
1514 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm Template") : i18nc("@title:window", "Edit Audio Alarm Template"))
1515 : (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm") : i18nc("@title:window", "Edit Audio Alarm"));
1518 /******************************************************************************
1519 * Set up the dialog controls common to display alarms.
1521 void EditAudioAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1523 // File name edit box
1524 mSoundConfig = new SoundWidget(false, true, parent);
1525 if (isTemplate())
1526 mSoundConfig->setAllowEmptyFile();
1527 connect(mSoundConfig, &SoundWidget::changed, this, &EditAudioAlarmDlg::contentsChanged);
1528 frameLayout->addWidget(mSoundConfig);
1530 // Top-adjust the controls
1531 mPadding = new QWidget(parent);
1532 QHBoxLayout* hlayout = new QHBoxLayout(mPadding);
1533 hlayout->setMargin(0);
1534 hlayout->setSpacing(0);
1535 frameLayout->addWidget(mPadding);
1536 frameLayout->setStretchFactor(mPadding, 1);
1539 /******************************************************************************
1540 * Initialise the dialog controls from the specified event.
1542 void EditAudioAlarmDlg::type_initValues(const KAEvent* event)
1544 if (event)
1546 mSoundConfig->set(event->audioFile(), event->soundVolume(), event->fadeVolume(), event->fadeSeconds(),
1547 (event->flags() & KAEvent::REPEAT_SOUND) ? event->repeatSoundPause() : -1);
1549 else
1551 // Set the values to their defaults
1552 mSoundConfig->set(Preferences::defaultSoundFile(), Preferences::defaultSoundVolume(),
1553 -1, 0, (Preferences::defaultSoundRepeat() ? 0 : -1));
1557 /******************************************************************************
1558 * Initialise various values in the New Alarm dialogue.
1560 void EditAudioAlarmDlg::setAudio(const QString& file, float volume)
1562 mSoundConfig->set(file, volume);
1565 /******************************************************************************
1566 * Set the dialog's action and the action's text.
1568 void EditAudioAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
1570 Q_UNUSED(action);
1571 Q_ASSERT(action == KAEvent::AUDIO);
1572 mSoundConfig->set(alarmText.displayText(), Preferences::defaultSoundVolume());
1575 /******************************************************************************
1576 * Set the read-only status of all non-template controls.
1578 void EditAudioAlarmDlg::setReadOnly(bool readOnly)
1580 mSoundConfig->setReadOnly(readOnly);
1581 EditAlarmDlg::setReadOnly(readOnly);
1584 /******************************************************************************
1585 * Save the state of all controls.
1587 void EditAudioAlarmDlg::saveState(const KAEvent* event)
1589 EditAlarmDlg::saveState(event);
1590 mSavedFile = mSoundConfig->fileName();
1591 mSoundConfig->getVolume(mSavedVolume, mSavedFadeVolume, mSavedFadeSeconds);
1592 mSavedRepeatPause = mSoundConfig->repeatPause();
1595 /******************************************************************************
1596 * Check whether any of the controls has changed state since the dialog was
1597 * first displayed.
1598 * Reply = true if any controls have changed, or if it's a new event.
1599 * = false if no controls have changed.
1601 bool EditAudioAlarmDlg::type_stateChanged() const
1603 if (mSavedFile != mSoundConfig->fileName())
1604 return true;
1605 if (!mSavedFile.isEmpty() || isTemplate())
1607 float volume, fadeVolume;
1608 int fadeSecs;
1609 mSoundConfig->getVolume(volume, fadeVolume, fadeSecs);
1610 if (mSavedRepeatPause != mSoundConfig->repeatPause()
1611 || mSavedVolume != volume
1612 || mSavedFadeVolume != fadeVolume
1613 || mSavedFadeSeconds != fadeSecs)
1614 return true;
1616 return false;
1619 /******************************************************************************
1620 * Extract the data in the dialog specific to the alarm type and set up a
1621 * KAEvent from it.
1623 void EditAudioAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1625 Q_UNUSED(text);
1626 Q_UNUSED(trial);
1627 event.set(dt, QString(), QColor(), QColor(), QFont(), KAEvent::AUDIO, lateCancel, getAlarmFlags());
1628 float volume, fadeVolume;
1629 int fadeSecs;
1630 mSoundConfig->getVolume(volume, fadeVolume, fadeSecs);
1631 int repeatPause = mSoundConfig->repeatPause();
1632 QUrl url;
1633 mSoundConfig->file(url, false);
1634 event.setAudioFile(url.toString(), volume, fadeVolume, fadeSecs, repeatPause, isTemplate());
1637 /******************************************************************************
1638 * Get the currently specified alarm flag bits.
1640 KAEvent::Flags EditAudioAlarmDlg::getAlarmFlags() const
1642 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
1643 if (mSoundConfig->repeatPause() >= 0) flags |= KAEvent::REPEAT_SOUND;
1644 return flags;
1647 /******************************************************************************
1648 * Check whether the file name is valid.
1650 bool EditAudioAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1652 QUrl url;
1653 if (!mSoundConfig->file(url, showErrorMessage))
1655 result.clear();
1656 return false;
1658 result = url.isLocalFile() ? url.toLocalFile() : url.toString();
1659 return true;
1662 /******************************************************************************
1663 * Called when the Try button is clicked.
1664 * If the audio file is currently playing (as a result of previously clicking
1665 * the Try button), cancel playback. Otherwise, play the audio file.
1667 void EditAudioAlarmDlg::slotTry()
1669 if (!MessageWin::isAudioPlaying())
1670 EditAlarmDlg::slotTry(); // play the audio file
1671 else if (mMessageWin)
1673 mMessageWin->stopAudio();
1674 mMessageWin = Q_NULLPTR;
1678 /******************************************************************************
1679 * Called when the Try action has been executed.
1681 void EditAudioAlarmDlg::type_executedTry(const QString&, void* result)
1683 mMessageWin = (MessageWin*)result; // note which MessageWin controls the audio playback
1684 if (mMessageWin)
1686 slotAudioPlaying(true);
1687 connect(mMessageWin, &MessageWin::destroyed, this, &EditAudioAlarmDlg::audioWinDestroyed);
1691 /******************************************************************************
1692 * Called when audio playing starts or stops.
1693 * Enable/disable/toggle the Try button.
1695 void EditAudioAlarmDlg::slotAudioPlaying(bool playing)
1697 if (!playing)
1699 // Nothing is playing, so enable the Try button
1700 mTryButton->setEnabled(true);
1701 mTryButton->setCheckable(false);
1702 mTryButton->setChecked(false);
1703 mMessageWin = Q_NULLPTR;
1705 else if (mMessageWin)
1707 // The test sound file is playing, so enable the Try button and depress it
1708 mTryButton->setEnabled(true);
1709 mTryButton->setCheckable(true);
1710 mTryButton->setChecked(true);
1712 else
1714 // An alarm is playing, so disable the Try button
1715 mTryButton->setEnabled(false);
1716 mTryButton->setCheckable(false);
1717 mTryButton->setChecked(false);
1722 /*=============================================================================
1723 = Class CommandEdit
1724 = A widget to allow entry of a command or a command script.
1725 =============================================================================*/
1726 CommandEdit::CommandEdit(QWidget* parent)
1727 : QWidget(parent)
1729 QVBoxLayout* vlayout = new QVBoxLayout(this);
1730 vlayout->setMargin(0);
1731 vlayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
1732 mTypeScript = new CheckBox(EditCommandAlarmDlg::i18n_chk_EnterScript(), this);
1733 mTypeScript->setFixedSize(mTypeScript->sizeHint());
1734 mTypeScript->setWhatsThis(i18nc("@info:whatsthis", "Check to enter the contents of a script instead of a shell command line"));
1735 connect(mTypeScript, &CheckBox::toggled, this, &CommandEdit::slotCmdScriptToggled);
1736 connect(mTypeScript, &CheckBox::toggled, this, &CommandEdit::changed);
1737 vlayout->addWidget(mTypeScript, 0, Qt::AlignLeft);
1739 mCommandEdit = new LineEdit(LineEdit::Url, this);
1740 mCommandEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter a shell command to execute."));
1741 connect(mCommandEdit, &LineEdit::textChanged, this, &CommandEdit::changed);
1742 vlayout->addWidget(mCommandEdit);
1744 mScriptEdit = new TextEdit(this);
1745 mScriptEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the contents of a script to execute"));
1746 connect(mScriptEdit, &TextEdit::textChanged, this, &CommandEdit::changed);
1747 vlayout->addWidget(mScriptEdit);
1749 slotCmdScriptToggled(mTypeScript->isChecked());
1752 /******************************************************************************
1753 * Initialise the widget controls from the specified event.
1755 void CommandEdit::setScript(bool script)
1757 mTypeScript->setChecked(script);
1760 bool CommandEdit::isScript() const
1762 return mTypeScript->isChecked();
1765 /******************************************************************************
1766 * Set the widget's text.
1768 void CommandEdit::setText(const AlarmText& alarmText)
1770 QString text = alarmText.displayText();
1771 bool script = alarmText.isScript();
1772 mTypeScript->setChecked(script);
1773 if (script)
1774 mScriptEdit->setPlainText(text);
1775 else
1776 mCommandEdit->setText(KAlarm::pathOrUrl(text));
1779 /******************************************************************************
1780 * Return the widget's text.
1782 QString CommandEdit::text() const
1784 QString result;
1785 if (mTypeScript->isChecked())
1786 result = mScriptEdit->toPlainText();
1787 else
1788 result = mCommandEdit->text();
1789 return result.trimmed();
1792 /******************************************************************************
1793 * Return the alarm text.
1794 * If 'showErrorMessage' is true and the text is empty, an error message is
1795 * displayed.
1797 QString CommandEdit::text(EditAlarmDlg* dlg, bool showErrorMessage) const
1799 QString result = text();
1800 if (showErrorMessage && result.isEmpty())
1801 KAMessageBox::sorry(dlg, i18nc("@info", "Please enter a command or script to execute"));
1802 return result;
1805 /******************************************************************************
1806 * Set the read-only status of all controls.
1808 void CommandEdit::setReadOnly(bool readOnly)
1810 mTypeScript->setReadOnly(readOnly);
1811 mCommandEdit->setReadOnly(readOnly);
1812 mScriptEdit->setReadOnly(readOnly);
1815 /******************************************************************************
1816 * Called when one of the command type radio buttons is clicked,
1817 * to display the appropriate edit field.
1819 void CommandEdit::slotCmdScriptToggled(bool on)
1821 if (on)
1823 mCommandEdit->hide();
1824 mScriptEdit->show();
1825 mScriptEdit->setFocus();
1827 else
1829 mScriptEdit->hide();
1830 mCommandEdit->show();
1831 mCommandEdit->setFocus();
1833 Q_EMIT scriptToggled(on);
1836 /******************************************************************************
1837 * Returns the minimum size of the widget.
1839 QSize CommandEdit::minimumSizeHint() const
1841 QSize t(mTypeScript->minimumSizeHint());
1842 QSize s(mCommandEdit->minimumSizeHint().expandedTo(mScriptEdit->minimumSizeHint()));
1843 s.setHeight(s.height() + style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing) + t.height());
1844 if (s.width() < t.width())
1845 s.setWidth(t.width());
1846 return s;
1851 /*=============================================================================
1852 = Class TextEdit
1853 = A text edit field with a minimum height of 3 text lines.
1854 =============================================================================*/
1855 TextEdit::TextEdit(QWidget* parent)
1856 : KTextEdit(parent)
1858 QSize tsize = sizeHint();
1859 tsize.setHeight(fontMetrics().lineSpacing()*13/4 + 2*frameWidth());
1860 setMinimumSize(tsize);
1863 void TextEdit::dragEnterEvent(QDragEnterEvent* e)
1865 if (KCalUtils::ICalDrag::canDecode(e->mimeData()))
1866 e->ignore(); // don't accept "text/calendar" objects
1867 KTextEdit::dragEnterEvent(e);
1870 // vim: et sw=4: