Rename method
[kdepim.git] / kalarm / editdlgtypes.cpp
blobb1db45b6cdf28fabd37a496ecb3a956772778954
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 <kiconloader.h>
59 #include <kfileitem.h>
61 #include <QComboBox>
62 #include <QLabel>
63 #include <QDir>
64 #include <QStyle>
65 #include <QGroupBox>
66 #include <QGridLayout>
67 #include <QHBoxLayout>
68 #include <QVBoxLayout>
69 #include <QDragEnterEvent>
70 #include <QStandardItemModel>
71 #include "kalarm_debug.h"
73 using namespace KAlarmCal;
75 enum { tTEXT, tFILE, tCOMMAND }; // order of mTypeCombo items
78 /*=============================================================================
79 = Class PickLogFileRadio
80 =============================================================================*/
81 class PickLogFileRadio : public PickFileRadio
83 public:
84 PickLogFileRadio(QPushButton* b, LineEdit* e, const QString& text, ButtonGroup* group, QWidget* parent)
85 : PickFileRadio(b, e, text, group, parent) { }
86 QString pickFile() Q_DECL_OVERRIDE // called when browse button is pressed to select a log file
88 return KAlarm::browseFile(i18nc("@title:window", "Choose Log File"), mDefaultDir, fileEdit()->text(), QString(),
89 KFile::LocalOnly, parentWidget());
91 private:
92 QString mDefaultDir; // default directory for log file browse button
96 /*=============================================================================
97 = Class EditDisplayAlarmDlg
98 = Dialog to edit display alarms.
99 =============================================================================*/
101 QString EditDisplayAlarmDlg::i18n_chk_ConfirmAck() { return i18nc("@option:check", "Confirm acknowledgment"); }
104 /******************************************************************************
105 * Constructor.
106 * Parameters:
107 * Template = true to edit/create an alarm template
108 * = false to edit/create an alarm.
109 * event != to initialise the dialog to show the specified event's data.
111 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
112 : EditAlarmDlg(Template, KAEvent::MESSAGE, parent, getResource),
113 mSpecialActionsButton(Q_NULLPTR),
114 mReminderDeferral(false),
115 mReminderArchived(false)
117 qCDebug(KALARM_LOG) << "New";
118 init(Q_NULLPTR);
121 EditDisplayAlarmDlg::EditDisplayAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
122 GetResourceType getResource, bool readOnly)
123 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
124 mSpecialActionsButton(Q_NULLPTR),
125 mReminderDeferral(false),
126 mReminderArchived(false)
128 qCDebug(KALARM_LOG) << "Event.id()";
129 init(event);
132 /******************************************************************************
133 * Return the window caption.
135 QString EditDisplayAlarmDlg::type_caption() const
137 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Display Alarm Template") : i18nc("@title:window", "Edit Display Alarm Template"))
138 : (isNewAlarm() ? i18nc("@title:window", "New Display Alarm") : i18nc("@title:window", "Edit Display Alarm"));
141 /******************************************************************************
142 * Set up the dialog controls common to display alarms.
144 void EditDisplayAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
146 // Display type combo box
147 QWidget* box = new QWidget(parent); // to group widgets for QWhatsThis text
149 QHBoxLayout* boxHLayout = new QHBoxLayout(box);
150 boxHLayout->setMargin(0);
151 QLabel* label = new QLabel(i18nc("@label:listbox", "Display type:"), box);
152 boxHLayout->addWidget(label);
153 label->setFixedSize(label->sizeHint());
154 mTypeCombo = new ComboBox(box);
155 boxHLayout->addWidget(mTypeCombo);
156 QString textItem = i18nc("@item:inlistbox", "Text message");
157 QString fileItem = i18nc("@item:inlistbox", "File contents");
158 QString commandItem = i18nc("@item:inlistbox", "Command output");
159 mTypeCombo->addItem(textItem); // index = tTEXT
160 mTypeCombo->addItem(fileItem); // index = tFILE
161 mTypeCombo->addItem(commandItem); // index = tCOMMAND
162 mTypeCombo->setFixedSize(mTypeCombo->sizeHint());
163 mTypeCombo->setCurrentIndex(-1); // ensure slotAlarmTypeChanged() is called when index is set
164 if (!ShellProcess::authorised())
166 // User not authorised to issue shell commands - disable Command Output option
167 QStandardItemModel* model = qobject_cast<QStandardItemModel*>(mTypeCombo->model());
168 if (model)
170 QModelIndex index = model->index(2, mTypeCombo->modelColumn(), mTypeCombo->rootModelIndex());
171 QStandardItem* item = model->itemFromIndex(index);
172 if (item)
173 item->setEnabled(false);
176 connect(mTypeCombo, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged), this, &EditDisplayAlarmDlg::slotAlarmTypeChanged);
177 connect(mTypeCombo, static_cast<void (ComboBox::*)(int)>(&ComboBox::currentIndexChanged), this, &EditDisplayAlarmDlg::contentsChanged);
178 label->setBuddy(mTypeCombo);
179 box->setWhatsThis(xi18nc("@info:whatsthis", "<para>Select what the alarm should display:"
180 "<list><item><interface>%1</interface>: the alarm will display the text message you type in.</item>"
181 "<item><interface>%2</interface>: the alarm will display the contents of a text or image file.</item>"
182 "<item><interface>%3</interface>: the alarm will display the output from a command.</item></list></para>",
183 textItem, fileItem, commandItem));
184 boxHLayout->setStretchFactor(new QWidget(box), 1); // left adjust the control
185 frameLayout->addWidget(box);
187 // Text message edit box
188 mTextMessageEdit = new TextEdit(parent);
189 mTextMessageEdit->setLineWrapMode(KTextEdit::NoWrap);
190 mTextMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the text of the alarm message. It may be multi-line."));
191 connect(mTextMessageEdit, &TextEdit::textChanged, this, &EditDisplayAlarmDlg::contentsChanged);
192 frameLayout->addWidget(mTextMessageEdit);
194 // File name edit box
195 mFileBox = new QWidget(parent);
196 frameLayout->addWidget(mFileBox);
197 QHBoxLayout* fileBoxHLayout = new QHBoxLayout(mFileBox);
198 fileBoxHLayout->setMargin(0);
199 fileBoxHLayout->setSpacing(0);
200 mFileMessageEdit = new LineEdit(LineEdit::Url, mFileBox);
201 fileBoxHLayout->addWidget(mFileMessageEdit);
202 mFileMessageEdit->setAcceptDrops(true);
203 mFileMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or URL of a text or image file to display."));
204 connect(mFileMessageEdit, &LineEdit::textChanged, this, &EditDisplayAlarmDlg::contentsChanged);
206 // File browse button
207 mFileBrowseButton = new QPushButton(mFileBox);
208 fileBoxHLayout->addWidget(mFileBrowseButton);
209 mFileBrowseButton->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
210 int size = mFileBrowseButton->sizeHint().height();
211 mFileBrowseButton->setFixedSize(size, size);
212 mFileBrowseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
213 mFileBrowseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a text or image file to display."));
214 connect(mFileBrowseButton, &QPushButton::clicked, this, &EditDisplayAlarmDlg::slotPickFile);
216 // Command type checkbox and edit box
217 mCmdEdit = new CommandEdit(parent);
218 connect(mCmdEdit, &CommandEdit::scriptToggled, this, &EditDisplayAlarmDlg::slotCmdScriptToggled);
219 connect(mCmdEdit, &CommandEdit::changed, this, &EditDisplayAlarmDlg::contentsChanged);
220 frameLayout->addWidget(mCmdEdit);
222 // Sound checkbox and file selector
223 QHBoxLayout* hlayout = new QHBoxLayout();
224 hlayout->setMargin(0);
225 frameLayout->addLayout(hlayout);
226 mSoundPicker = new SoundPicker(parent);
227 mSoundPicker->setFixedSize(mSoundPicker->sizeHint());
228 connect(mSoundPicker, &SoundPicker::changed, this, &EditDisplayAlarmDlg::contentsChanged);
229 hlayout->addWidget(mSoundPicker);
230 hlayout->addSpacing(2 * style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
231 hlayout->addStretch();
233 // Font and colour choice button and sample text
234 mFontColourButton = new FontColourButton(parent);
235 mFontColourButton->setMaximumHeight(mFontColourButton->sizeHint().height() * 3/2);
236 hlayout->addWidget(mFontColourButton);
237 connect(mFontColourButton, &FontColourButton::selected, this, &EditDisplayAlarmDlg::setColours);
238 connect(mFontColourButton, &FontColourButton::selected, this, &EditDisplayAlarmDlg::contentsChanged);
240 if (ShellProcess::authorised()) // don't display if shell commands not allowed (e.g. kiosk mode)
242 // Special actions button
243 mSpecialActionsButton = new SpecialActionsButton(false, parent);
244 mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint());
245 connect(mSpecialActionsButton, &SpecialActionsButton::selected, this, &EditDisplayAlarmDlg::contentsChanged);
246 frameLayout->addWidget(mSpecialActionsButton, 0, Qt::AlignRight);
249 // Top-adjust the controls
250 mFilePadding = new QWidget(parent);
251 hlayout = new QHBoxLayout(mFilePadding);
252 hlayout->setMargin(0);
253 hlayout->setSpacing(0);
254 frameLayout->addWidget(mFilePadding);
255 frameLayout->setStretchFactor(mFilePadding, 1);
258 /******************************************************************************
259 * Create a reminder control.
261 Reminder* EditDisplayAlarmDlg::createReminder(QWidget* parent)
263 static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of or after the main alarm to display a reminder alarm.");
264 return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of or after the main alarm time(s)."),
265 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()),
266 i18nc("@info:whatsthis", "Select whether the reminder should be triggered before or after the main alarm"),
267 true, true, parent);
270 /******************************************************************************
271 * Create an "acknowledgement confirmation required" checkbox.
273 CheckBox* EditDisplayAlarmDlg::createConfirmAckCheckbox(QWidget* parent)
275 CheckBox* confirmAck = new CheckBox(i18n_chk_ConfirmAck(), parent);
276 confirmAck->setWhatsThis(i18nc("@info:whatsthis", "Check to be prompted for confirmation when you acknowledge the alarm."));
277 return confirmAck;
280 /******************************************************************************
281 * Initialise the dialog controls from the specified event.
283 void EditDisplayAlarmDlg::type_initValues(const KAEvent* event)
285 mKMailSerialNumber = 0;
286 lateCancel()->showAutoClose(true);
287 if (event)
289 if (mAlarmType == KAEvent::MESSAGE && event->kmailSerialNumber()
290 && AlarmText::checkIfEmail(event->cleanText()))
291 mKMailSerialNumber = event->kmailSerialNumber();
292 lateCancel()->setAutoClose(event->autoClose());
293 if (event->useDefaultFont())
294 mFontColourButton->setDefaultFont();
295 else
296 mFontColourButton->setFont(event->font());
297 mFontColourButton->setBgColour(event->bgColour());
298 mFontColourButton->setFgColour(event->fgColour());
299 setColours(event->fgColour(), event->bgColour());
300 mConfirmAck->setChecked(event->confirmAck());
301 bool recurs = event->recurs();
302 int reminderMins = event->reminderMinutes();
303 if (reminderMins > 0 && !event->reminderActive())
304 reminderMins = 0; // don't show advance reminder which has already passed
305 if (!reminderMins)
307 if (event->reminderDeferral() && !recurs)
309 reminderMins = event->deferDateTime().minsTo(event->mainDateTime());
310 mReminderDeferral = true;
312 else if (event->reminderMinutes() && recurs)
314 reminderMins = event->reminderMinutes();
315 mReminderArchived = true;
318 reminder()->setMinutes(reminderMins, dateOnly());
319 reminder()->setOnceOnly(event->reminderOnceOnly());
320 reminder()->enableOnceOnly(recurs);
321 if (mSpecialActionsButton)
322 mSpecialActionsButton->setActions(event->preAction(), event->postAction(), event->extraActionOptions());
323 Preferences::SoundType soundType = event->speak() ? Preferences::Sound_Speak
324 : event->beep() ? Preferences::Sound_Beep
325 : !event->audioFile().isEmpty() ? Preferences::Sound_File
326 : Preferences::Sound_None;
327 mSoundPicker->set(soundType, event->audioFile(), event->soundVolume(),
328 event->fadeVolume(), event->fadeSeconds(), event->repeatSoundPause());
330 else
332 // Set the values to their defaults
333 if (!ShellProcess::authorised())
335 // Don't allow shell commands in kiosk mode
336 if (mSpecialActionsButton)
337 mSpecialActionsButton->setEnabled(false);
339 lateCancel()->setAutoClose(Preferences::defaultAutoClose());
340 mTypeCombo->setCurrentIndex(0);
341 mFontColourButton->setDefaultFont();
342 mFontColourButton->setBgColour(Preferences::defaultBgColour());
343 mFontColourButton->setFgColour(Preferences::defaultFgColour());
344 setColours(Preferences::defaultFgColour(), Preferences::defaultBgColour());
345 mConfirmAck->setChecked(Preferences::defaultConfirmAck());
346 reminder()->setMinutes(0, false);
347 reminder()->enableOnceOnly(isTimedRecurrence()); // must be called after mRecurrenceEdit is set up
348 if (mSpecialActionsButton)
350 KAEvent::ExtraActionOptions opts(Q_NULLPTR);
351 if (Preferences::defaultExecPreActionOnDeferral())
352 opts |= KAEvent::ExecPreActOnDeferral;
353 if (Preferences::defaultCancelOnPreActionError())
354 opts |= KAEvent::CancelOnPreActError;
355 if (Preferences::defaultDontShowPreActionError())
356 opts |= KAEvent::DontShowPreActError;
357 mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction(), opts);
359 mSoundPicker->set(Preferences::defaultSoundType(), Preferences::defaultSoundFile(),
360 Preferences::defaultSoundVolume(), -1, 0, (Preferences::defaultSoundRepeat() ? 0 : -1));
364 /******************************************************************************
365 * Called when the More/Less Options button is clicked.
366 * Show/hide the optional options.
368 void EditDisplayAlarmDlg::type_showOptions(bool more)
370 if (mSpecialActionsButton)
372 if (more)
373 mSpecialActionsButton->show();
374 else
375 mSpecialActionsButton->hide();
379 /******************************************************************************
380 * Called when the font/color button has been clicked.
381 * Set the colors in the message text entry control.
383 void EditDisplayAlarmDlg::setColours(const QColor& fgColour, const QColor& bgColour)
385 QPalette pal = mTextMessageEdit->palette();
386 pal.setColor(mTextMessageEdit->backgroundRole(), bgColour);
387 pal.setColor(QPalette::Text, fgColour);
388 mTextMessageEdit->setPalette(pal);
389 pal = mTextMessageEdit->viewport()->palette();
390 pal.setColor(mTextMessageEdit->viewport()->backgroundRole(), bgColour);
391 pal.setColor(QPalette::Text, fgColour);
392 mTextMessageEdit->viewport()->setPalette(pal);
393 // Change the color of existing text
394 QTextCursor cursor = mTextMessageEdit->textCursor();
395 mTextMessageEdit->selectAll();
396 mTextMessageEdit->setTextColor(fgColour);
397 mTextMessageEdit->setTextCursor(cursor);
400 /******************************************************************************
401 * Set the dialog's action and the action's text.
403 void EditDisplayAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
405 QString text = alarmText.displayText();
406 switch (action)
408 case KAEvent::MESSAGE:
409 mTypeCombo->setCurrentIndex(tTEXT);
410 mTextMessageEdit->setPlainText(text);
411 mKMailSerialNumber = alarmText.isEmail() ? alarmText.kmailSerialNumber() : 0;
412 break;
413 case KAEvent::FILE:
414 mTypeCombo->setCurrentIndex(tFILE);
415 mFileMessageEdit->setText(text);
416 break;
417 case KAEvent::COMMAND:
418 mTypeCombo->setCurrentIndex(tCOMMAND);
419 mCmdEdit->setText(alarmText);
420 break;
421 default:
422 Q_ASSERT(0);
423 break;
427 /******************************************************************************
428 * Initialise various values in the New Alarm dialogue.
430 void EditDisplayAlarmDlg::setBgColour(const QColor& colour)
432 mFontColourButton->setBgColour(colour);
433 setColours(mFontColourButton->fgColour(), colour);
435 void EditDisplayAlarmDlg::setFgColour(const QColor& colour)
437 mFontColourButton->setFgColour(colour);
438 setColours(colour, mFontColourButton->bgColour());
440 void EditDisplayAlarmDlg::setConfirmAck(bool confirm)
442 mConfirmAck->setChecked(confirm);
444 void EditDisplayAlarmDlg::setAutoClose(bool close)
446 lateCancel()->setAutoClose(close);
448 void EditDisplayAlarmDlg::setAudio(Preferences::SoundType type, const QString& file, float volume, int repeatPause)
450 mSoundPicker->set(type, file, volume, -1, 0, repeatPause);
452 void EditDisplayAlarmDlg::setReminder(int minutes, bool onceOnly)
454 reminder()->setMinutes(minutes, dateOnly());
455 reminder()->setOnceOnly(onceOnly);
456 reminder()->enableOnceOnly(isTimedRecurrence());
459 /******************************************************************************
460 * Set the read-only status of all non-template controls.
462 void EditDisplayAlarmDlg::setReadOnly(bool readOnly)
464 mTypeCombo->setReadOnly(readOnly);
465 mTextMessageEdit->setReadOnly(readOnly);
466 mFileMessageEdit->setReadOnly(readOnly);
467 mCmdEdit->setReadOnly(readOnly);
468 mFontColourButton->setReadOnly(readOnly);
469 mSoundPicker->setReadOnly(readOnly);
470 mConfirmAck->setReadOnly(readOnly);
471 reminder()->setReadOnly(readOnly);
472 if (mSpecialActionsButton)
473 mSpecialActionsButton->setReadOnly(readOnly);
474 if (readOnly)
475 mFileBrowseButton->hide();
476 else
477 mFileBrowseButton->show();
478 EditAlarmDlg::setReadOnly(readOnly);
481 /******************************************************************************
482 * Save the state of all controls.
484 void EditDisplayAlarmDlg::saveState(const KAEvent* event)
486 EditAlarmDlg::saveState(event);
487 mSavedType = mTypeCombo->currentIndex();
488 mSavedCmdScript = mCmdEdit->isScript();
489 mSavedSoundType = mSoundPicker->sound();
490 mSavedSoundFile = mSoundPicker->file();
491 mSavedSoundVolume = mSoundPicker->volume(mSavedSoundFadeVolume, mSavedSoundFadeSeconds);
492 mSavedRepeatPause = mSoundPicker->repeatPause();
493 mSavedConfirmAck = mConfirmAck->isChecked();
494 mSavedFont = mFontColourButton->font();
495 mSavedFgColour = mFontColourButton->fgColour();
496 mSavedBgColour = mFontColourButton->bgColour();
497 mSavedReminder = reminder()->minutes();
498 mSavedOnceOnly = reminder()->isOnceOnly();
499 mSavedAutoClose = lateCancel()->isAutoClose();
500 if (mSpecialActionsButton)
502 mSavedPreAction = mSpecialActionsButton->preAction();
503 mSavedPostAction = mSpecialActionsButton->postAction();
504 mSavedPreActionOptions = mSpecialActionsButton->options();
508 /******************************************************************************
509 * Check whether any of the controls has changed state since the dialog was
510 * first displayed.
511 * Reply = true if any controls have changed, or if it's a new event.
512 * = false if no controls have changed.
514 bool EditDisplayAlarmDlg::type_stateChanged() const
516 if (mSavedType != mTypeCombo->currentIndex()
517 || mSavedCmdScript != mCmdEdit->isScript()
518 || mSavedSoundType != mSoundPicker->sound()
519 || mSavedConfirmAck != mConfirmAck->isChecked()
520 || mSavedFont != mFontColourButton->font()
521 || mSavedFgColour != mFontColourButton->fgColour()
522 || mSavedBgColour != mFontColourButton->bgColour()
523 || mSavedReminder != reminder()->minutes()
524 || mSavedOnceOnly != reminder()->isOnceOnly()
525 || mSavedAutoClose != lateCancel()->isAutoClose())
526 return true;
527 if (mSpecialActionsButton)
529 if (mSavedPreAction != mSpecialActionsButton->preAction()
530 || mSavedPostAction != mSpecialActionsButton->postAction()
531 || mSavedPreActionOptions != mSpecialActionsButton->options())
532 return true;
534 if (mSavedSoundType == Preferences::Sound_File)
536 if (mSavedSoundFile != mSoundPicker->file())
537 return true;
538 if (!mSavedSoundFile.isEmpty())
540 float fadeVolume;
541 int fadeSecs;
542 if (mSavedRepeatPause != mSoundPicker->repeatPause()
543 || mSavedSoundVolume != mSoundPicker->volume(fadeVolume, fadeSecs)
544 || mSavedSoundFadeVolume != fadeVolume
545 || mSavedSoundFadeSeconds != fadeSecs)
546 return true;
549 return false;
552 /******************************************************************************
553 * Extract the data in the dialog specific to the alarm type and set up a
554 * KAEvent from it.
556 void EditDisplayAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
558 KAEvent::SubAction type;
559 switch (mTypeCombo->currentIndex())
561 case tFILE: type = KAEvent::FILE; break;
562 case tCOMMAND: type = KAEvent::COMMAND; break;
563 default:
564 case tTEXT: type = KAEvent::MESSAGE; break;
566 event.set(dt, text, mFontColourButton->bgColour(), mFontColourButton->fgColour(), mFontColourButton->font(),
567 type, lateCancel, getAlarmFlags());
568 if (type == KAEvent::MESSAGE)
570 if (AlarmText::checkIfEmail(text))
571 event.setKMailSerialNumber(mKMailSerialNumber);
573 float fadeVolume;
574 int fadeSecs;
575 float volume = mSoundPicker->volume(fadeVolume, fadeSecs);
576 int repeatPause = mSoundPicker->repeatPause();
577 event.setAudioFile(mSoundPicker->file().toDisplayString(), volume, fadeVolume, fadeSecs, repeatPause);
578 if (!trial && reminder()->isEnabled())
579 event.setReminder(reminder()->minutes(), reminder()->isOnceOnly());
580 if (mSpecialActionsButton && mSpecialActionsButton->isEnabled())
581 event.setActions(mSpecialActionsButton->preAction(), mSpecialActionsButton->postAction(),
582 mSpecialActionsButton->options());
585 /******************************************************************************
586 * Get the currently specified alarm flag bits.
588 KAEvent::Flags EditDisplayAlarmDlg::getAlarmFlags() const
590 bool cmd = (mTypeCombo->currentIndex() == tCOMMAND);
591 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
592 if (mSoundPicker->sound() == Preferences::Sound_Beep) flags |= KAEvent::BEEP;
593 if (mSoundPicker->sound() == Preferences::Sound_Speak) flags |= KAEvent::SPEAK;
594 if (mSoundPicker->repeatPause() >= 0) flags |= KAEvent::REPEAT_SOUND;
595 if (mConfirmAck->isChecked()) flags |= KAEvent::CONFIRM_ACK;
596 if (lateCancel()->isAutoClose()) flags |= KAEvent::AUTO_CLOSE;
597 if (mFontColourButton->defaultFont()) flags |= KAEvent::DEFAULT_FONT;
598 if (cmd) flags |= KAEvent::DISPLAY_COMMAND;
599 if (cmd && mCmdEdit->isScript()) flags |= KAEvent::SCRIPT;
600 return flags;
603 /******************************************************************************
604 * Called when one of the alarm display type combo box is changed, to display
605 * the appropriate set of controls for that action type.
607 void EditDisplayAlarmDlg::slotAlarmTypeChanged(int index)
609 QWidget* focus = Q_NULLPTR;
610 switch (index)
612 case tTEXT: // text message
613 mFileBox->hide();
614 mFilePadding->hide();
615 mCmdEdit->hide();
616 mTextMessageEdit->show();
617 mSoundPicker->showSpeak(true);
618 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Display the alarm message now"));
619 focus = mTextMessageEdit;
620 break;
621 case tFILE: // file contents
622 mTextMessageEdit->hide();
623 mFileBox->show();
624 mFilePadding->show();
625 mCmdEdit->hide();
626 mSoundPicker->showSpeak(false);
627 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Display the file now"));
628 mFileMessageEdit->setNoSelect();
629 focus = mFileMessageEdit;
630 break;
631 case tCOMMAND: // command output
632 mTextMessageEdit->hide();
633 mFileBox->hide();
634 slotCmdScriptToggled(mCmdEdit->isScript()); // show/hide mFilePadding
635 mCmdEdit->show();
636 mSoundPicker->showSpeak(true);
637 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Display the command output now"));
638 focus = mCmdEdit;
639 break;
641 if (focus)
642 focus->setFocus();
645 /******************************************************************************
646 * Called when the file browse button is pressed to select a file to display.
648 void EditDisplayAlarmDlg::slotPickFile()
650 static QString defaultDir; // default directory for file browse button
651 QString file = KAlarm::browseFile(i18nc("@title:window", "Choose Text or Image File to Display"),
652 defaultDir, mFileMessageEdit->text(), QString(), KFile::ExistingOnly, this);
653 if (!file.isEmpty())
655 mFileMessageEdit->setText(KAlarm::pathOrUrl(file));
656 contentsChanged();
660 /******************************************************************************
661 * Called when one of the command type radio buttons is clicked,
662 * to display the appropriate edit field.
664 void EditDisplayAlarmDlg::slotCmdScriptToggled(bool on)
666 if (on)
667 mFilePadding->hide();
668 else
669 mFilePadding->show();
672 /******************************************************************************
673 * Clean up the alarm text, and if it's a file, check whether it's valid.
675 bool EditDisplayAlarmDlg::checkText(QString& result, bool showErrorMessage) const
677 switch (mTypeCombo->currentIndex())
679 case tTEXT:
680 result = mTextMessageEdit->toPlainText();
681 break;
683 case tFILE:
685 QString alarmtext = mFileMessageEdit->text().trimmed();
686 QUrl url;
687 KAlarm::FileErr err = KAlarm::checkFileExists(alarmtext, url);
688 if (err == KAlarm::FileErr_None)
690 KFileItem fi(url);
691 switch (KAlarm::fileType(fi.currentMimeType()))
693 case KAlarm::TextFormatted:
694 case KAlarm::TextPlain:
695 case KAlarm::TextApplication:
696 case KAlarm::Image:
697 break;
698 default:
699 err = KAlarm::FileErr_NotTextImage;
700 break;
703 if (err != KAlarm::FileErr_None && showErrorMessage)
705 mFileMessageEdit->setFocus();
706 if (!KAlarm::showFileErrMessage(alarmtext, err, KAlarm::FileErr_BlankDisplay, const_cast<EditDisplayAlarmDlg*>(this)))
707 return false;
709 result = alarmtext;
710 break;
712 case tCOMMAND:
713 result = mCmdEdit->text(const_cast<EditDisplayAlarmDlg*>(this), showErrorMessage);
714 if (result.isEmpty())
715 return false;
716 break;
718 return true;
722 /*=============================================================================
723 = Class EditCommandAlarmDlg
724 = Dialog to edit command alarms.
725 =============================================================================*/
727 QString EditCommandAlarmDlg::i18n_chk_EnterScript() { return i18nc("@option:check", "Enter a script"); }
728 QString EditCommandAlarmDlg::i18n_radio_ExecInTermWindow() { return i18nc("@option:radio", "Execute in terminal window"); }
729 QString EditCommandAlarmDlg::i18n_chk_ExecInTermWindow() { return i18nc("@option:check", "Execute in terminal window"); }
732 /******************************************************************************
733 * Constructor.
734 * Parameters:
735 * Template = true to edit/create an alarm template
736 * = false to edit/create an alarm.
737 * event != to initialise the dialog to show the specified event's data.
739 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
740 : EditAlarmDlg(Template, KAEvent::COMMAND, parent, getResource)
742 qCDebug(KALARM_LOG) << "New";
743 init(Q_NULLPTR);
746 EditCommandAlarmDlg::EditCommandAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
747 GetResourceType getResource, bool readOnly)
748 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly)
750 qCDebug(KALARM_LOG) << "Event.id()";
751 init(event);
754 /******************************************************************************
755 * Return the window caption.
757 QString EditCommandAlarmDlg::type_caption() const
759 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Command Alarm Template") : i18nc("@title:window", "Edit Command Alarm Template"))
760 : (isNewAlarm() ? i18nc("@title:window", "New Command Alarm") : i18nc("@title:window", "Edit Command Alarm"));
763 /******************************************************************************
764 * Set up the command alarm dialog controls.
766 void EditCommandAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
768 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Execute the specified command now"));
770 mCmdEdit = new CommandEdit(parent);
771 connect(mCmdEdit, &CommandEdit::scriptToggled, this, &EditCommandAlarmDlg::slotCmdScriptToggled);
772 connect(mCmdEdit, &CommandEdit::changed, this, &EditCommandAlarmDlg::contentsChanged);
773 frameLayout->addWidget(mCmdEdit);
775 // What to do with command output
777 mCmdOutputBox = new QGroupBox(i18nc("@title:group", "Command Output"), parent);
778 frameLayout->addWidget(mCmdOutputBox);
779 QVBoxLayout* vlayout = new QVBoxLayout(mCmdOutputBox);
780 vlayout->setMargin(style()->pixelMetric(QStyle::PM_DefaultChildMargin));
781 vlayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
782 mCmdOutputGroup = new ButtonGroup(mCmdOutputBox);
783 connect(mCmdOutputGroup, &ButtonGroup::buttonSet, this, &EditCommandAlarmDlg::contentsChanged);
785 // Execute in terminal window
786 mCmdExecInTerm = new RadioButton(i18n_radio_ExecInTermWindow(), mCmdOutputBox);
787 mCmdExecInTerm->setFixedSize(mCmdExecInTerm->sizeHint());
788 mCmdExecInTerm->setWhatsThis(i18nc("@info:whatsthis", "Check to execute the command in a terminal window"));
789 mCmdOutputGroup->addButton(mCmdExecInTerm, Preferences::Log_Terminal);
790 vlayout->addWidget(mCmdExecInTerm, 0, Qt::AlignLeft);
792 // Log file name edit box
793 QWidget* box = new QWidget(mCmdOutputBox);
794 QHBoxLayout* boxHLayout = new QHBoxLayout(box);
795 boxHLayout->setMargin(0);
796 boxHLayout->setSpacing(0);
797 (new QWidget(box))->setFixedWidth(mCmdExecInTerm->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth)); // indent the edit box
798 mCmdLogFileEdit = new LineEdit(LineEdit::Url, box);
799 boxHLayout->addWidget(mCmdLogFileEdit);
800 mCmdLogFileEdit->setAcceptDrops(true);
801 mCmdLogFileEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the name or path of the log file."));
802 connect(mCmdLogFileEdit, &LineEdit::textChanged, this, &EditCommandAlarmDlg::contentsChanged);
804 // Log file browse button.
805 // The file browser dialog is activated by the PickLogFileRadio class.
806 QPushButton* browseButton = new QPushButton(box);
807 boxHLayout->addWidget(browseButton);
808 browseButton->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
809 int size = browseButton->sizeHint().height();
810 browseButton->setFixedSize(size, size);
811 browseButton->setToolTip(i18nc("@info:tooltip", "Choose a file"));
812 browseButton->setWhatsThis(i18nc("@info:whatsthis", "Select a log file."));
814 // Log output to file
815 mCmdLogToFile = new PickLogFileRadio(browseButton, mCmdLogFileEdit, i18nc("@option:radio", "Log to file"), mCmdOutputGroup, mCmdOutputBox);
816 mCmdLogToFile->setFixedSize(mCmdLogToFile->sizeHint());
817 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."));
818 connect(mCmdLogToFile, &PickLogFileRadio::fileChanged, this, &EditCommandAlarmDlg::contentsChanged);
819 mCmdOutputGroup->addButton(mCmdLogToFile, Preferences::Log_File);
820 vlayout->addWidget(mCmdLogToFile, 0, Qt::AlignLeft);
821 vlayout->addWidget(box);
823 // Discard output
824 mCmdDiscardOutput = new RadioButton(i18nc("@option:radio", "Discard"), mCmdOutputBox);
825 mCmdDiscardOutput->setFixedSize(mCmdDiscardOutput->sizeHint());
826 mCmdDiscardOutput->setWhatsThis(i18nc("@info:whatsthis", "Check to discard command output."));
827 mCmdOutputGroup->addButton(mCmdDiscardOutput, Preferences::Log_Discard);
828 vlayout->addWidget(mCmdDiscardOutput, 0, Qt::AlignLeft);
830 // Top-adjust the controls
831 mCmdPadding = new QWidget(parent);
832 QHBoxLayout* hlayout = new QHBoxLayout(mCmdPadding);
833 hlayout->setMargin(0);
834 hlayout->setSpacing(0);
835 frameLayout->addWidget(mCmdPadding);
836 frameLayout->setStretchFactor(mCmdPadding, 1);
839 /******************************************************************************
840 * Initialise the dialog controls from the specified event.
842 void EditCommandAlarmDlg::type_initValues(const KAEvent* event)
844 if (event)
846 // Set the values to those for the specified event
847 RadioButton* logType = event->commandXterm() ? mCmdExecInTerm
848 : !event->logFile().isEmpty() ? mCmdLogToFile
849 : mCmdDiscardOutput;
850 if (logType == mCmdLogToFile)
851 mCmdLogFileEdit->setText(event->logFile()); // set file name before setting radio button
852 logType->setChecked(true);
854 else
856 // Set the values to their defaults
857 mCmdEdit->setScript(Preferences::defaultCmdScript());
858 mCmdLogFileEdit->setText(Preferences::defaultCmdLogFile()); // set file name before setting radio button
859 mCmdOutputGroup->setButton(Preferences::defaultCmdLogType());
861 slotCmdScriptToggled(mCmdEdit->isScript());
864 /******************************************************************************
865 * Called when the More/Less Options button is clicked.
866 * Show/hide the optional options.
868 void EditCommandAlarmDlg::type_showOptions(bool more)
870 if (more)
871 mCmdOutputBox->show();
872 else
873 mCmdOutputBox->hide();
876 /******************************************************************************
877 * Set the dialog's action and the action's text.
879 void EditCommandAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
881 Q_UNUSED(action);
882 Q_ASSERT(action == KAEvent::COMMAND);
883 mCmdEdit->setText(alarmText);
886 /******************************************************************************
887 * Set the read-only status of all non-template controls.
889 void EditCommandAlarmDlg::setReadOnly(bool readOnly)
891 if (!isTemplate() && !ShellProcess::authorised())
892 readOnly = true; // don't allow editing of existing command alarms in kiosk mode
893 mCmdEdit->setReadOnly(readOnly);
894 mCmdExecInTerm->setReadOnly(readOnly);
895 mCmdLogToFile->setReadOnly(readOnly);
896 mCmdDiscardOutput->setReadOnly(readOnly);
897 EditAlarmDlg::setReadOnly(readOnly);
900 /******************************************************************************
901 * Save the state of all controls.
903 void EditCommandAlarmDlg::saveState(const KAEvent* event)
905 EditAlarmDlg::saveState(event);
906 mSavedCmdScript = mCmdEdit->isScript();
907 mSavedCmdOutputRadio = mCmdOutputGroup->checkedButton();
908 mSavedCmdLogFile = mCmdLogFileEdit->text();
911 /******************************************************************************
912 * Check whether any of the controls has changed state since the dialog was
913 * first displayed.
914 * Reply = true if any controls have changed, or if it's a new event.
915 * = false if no controls have changed.
917 bool EditCommandAlarmDlg::type_stateChanged() const
919 if (mSavedCmdScript != mCmdEdit->isScript()
920 || mSavedCmdOutputRadio != mCmdOutputGroup->checkedButton())
921 return true;
922 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
924 if (mSavedCmdLogFile != mCmdLogFileEdit->text())
925 return true;
927 return false;
930 /******************************************************************************
931 * Extract the data in the dialog specific to the alarm type and set up a
932 * KAEvent from it.
934 void EditCommandAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
936 Q_UNUSED(trial);
937 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::COMMAND, lateCancel, getAlarmFlags());
938 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
939 event.setLogFile(mCmdLogFileEdit->text());
942 /******************************************************************************
943 * Get the currently specified alarm flag bits.
945 KAEvent::Flags EditCommandAlarmDlg::getAlarmFlags() const
947 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
948 if (mCmdEdit->isScript()) flags |= KAEvent::SCRIPT;
949 if (mCmdOutputGroup->checkedButton() == mCmdExecInTerm) flags |= KAEvent::EXEC_IN_XTERM;
950 return flags;
953 /******************************************************************************
954 * Validate and convert command alarm data.
956 bool EditCommandAlarmDlg::type_validate(bool trial)
958 Q_UNUSED(trial);
959 if (mCmdOutputGroup->checkedButton() == mCmdLogToFile)
961 // Validate the log file name
962 QString file = mCmdLogFileEdit->text();
963 QFileInfo info(file);
964 QDir::setCurrent(QDir::homePath());
965 bool err = file.isEmpty() || info.isDir();
966 if (!err)
968 if (info.exists())
970 err = !info.isWritable();
972 else
974 QFileInfo dirinfo(info.absolutePath()); // get absolute directory path
975 err = (!dirinfo.isDir() || !dirinfo.isWritable());
978 if (err)
980 showMainPage();
981 mCmdLogFileEdit->setFocus();
982 KAMessageBox::sorry(this, i18nc("@info", "Log file must be the name or path of a local file, with write permission."));
983 return false;
985 // Convert the log file to an absolute path
986 mCmdLogFileEdit->setText(info.absoluteFilePath());
988 return true;
991 /******************************************************************************
992 * Called when the Try action has been executed.
993 * Tell the user the result of the Try action.
995 void EditCommandAlarmDlg::type_executedTry(const QString& text, void* result)
997 ShellProcess* proc = (ShellProcess*)result;
998 if (proc && proc != (void*)-1
999 && mCmdOutputGroup->checkedButton() != mCmdExecInTerm)
1001 theApp()->commandMessage(proc, this);
1002 KAMessageBox::information(this, xi18nc("@info", "Command executed: <icode>%1</icode>", text));
1003 theApp()->commandMessage(proc, Q_NULLPTR);
1007 /******************************************************************************
1008 * Called when one of the command type radio buttons is clicked,
1009 * to display the appropriate edit field.
1011 void EditCommandAlarmDlg::slotCmdScriptToggled(bool on)
1013 if (on)
1014 mCmdPadding->hide();
1015 else
1016 mCmdPadding->show();
1019 /******************************************************************************
1020 * Clean up the alarm text.
1022 bool EditCommandAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1024 result = mCmdEdit->text(const_cast<EditCommandAlarmDlg*>(this), showErrorMessage);
1025 if (result.isEmpty())
1026 return false;
1027 return true;
1031 /*=============================================================================
1032 = Class EditEmailAlarmDlg
1033 = Dialog to edit email alarms.
1034 =============================================================================*/
1036 QString EditEmailAlarmDlg::i18n_chk_CopyEmailToSelf() { return i18nc("@option:check", "Copy email to self"); }
1039 /******************************************************************************
1040 * Constructor.
1041 * Parameters:
1042 * Template = true to edit/create an alarm template
1043 * = false to edit/create an alarm.
1044 * event != to initialise the dialog to show the specified event's data.
1046 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1047 : EditAlarmDlg(Template, KAEvent::EMAIL, parent, getResource),
1048 mEmailRemoveButton(Q_NULLPTR)
1050 qCDebug(KALARM_LOG) << "New";
1051 init(Q_NULLPTR);
1054 EditEmailAlarmDlg::EditEmailAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1055 GetResourceType getResource, bool readOnly)
1056 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
1057 mEmailRemoveButton(Q_NULLPTR)
1059 qCDebug(KALARM_LOG) << "Event.id()";
1060 init(event);
1063 /******************************************************************************
1064 * Return the window caption.
1066 QString EditEmailAlarmDlg::type_caption() const
1068 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Email Alarm Template") : i18nc("@title:window", "Edit Email Alarm Template"))
1069 : (isNewAlarm() ? i18nc("@title:window", "New Email Alarm") : i18nc("@title:window", "Edit Email Alarm"));
1072 /******************************************************************************
1073 * Set up the email alarm dialog controls.
1075 void EditEmailAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1077 mTryButton->setWhatsThis(i18nc("@info:whatsthis", "Send the email to the specified addressees now"));
1079 QGridLayout* grid = new QGridLayout();
1080 grid->setMargin(0);
1081 grid->setColumnStretch(1, 1);
1082 frameLayout->addLayout(grid);
1084 mEmailFromList = Q_NULLPTR;
1085 if (Preferences::emailFrom() == Preferences::MAIL_FROM_KMAIL)
1087 // Email sender identity
1088 QLabel* label = new QLabel(i18nc("@label:listbox 'From' email address", "From:"), parent);
1089 label->setFixedSize(label->sizeHint());
1090 grid->addWidget(label, 0, 0);
1092 mEmailFromList = new EmailIdCombo(Identities::identityManager(), parent);
1093 mEmailFromList->setMinimumSize(mEmailFromList->sizeHint());
1094 label->setBuddy(mEmailFromList);
1095 mEmailFromList->setWhatsThis(i18nc("@info:whatsthis", "Your email identity, used to identify you as the sender when sending email alarms."));
1096 connect(mEmailFromList, &EmailIdCombo::identityChanged, this, &EditEmailAlarmDlg::contentsChanged);
1097 grid->addWidget(mEmailFromList, 0, 1, 1, 2);
1100 // Email recipients
1101 QLabel* label = new QLabel(i18nc("@label:textbox Email addressee", "To:"), parent);
1102 label->setFixedSize(label->sizeHint());
1103 grid->addWidget(label, 1, 0);
1105 mEmailToEdit = new LineEdit(LineEdit::Emails, parent);
1106 mEmailToEdit->setMinimumSize(mEmailToEdit->sizeHint());
1107 mEmailToEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the addresses of the email recipients. Separate multiple addresses by "
1108 "commas or semicolons."));
1109 connect(mEmailToEdit, &LineEdit::textChanged, this, &EditEmailAlarmDlg::contentsChanged);
1110 grid->addWidget(mEmailToEdit, 1, 1);
1112 mEmailAddressButton = new QPushButton(parent);
1113 mEmailAddressButton->setIcon(QIcon::fromTheme(QStringLiteral("help-contents")));
1114 int size = mEmailAddressButton->sizeHint().height();
1115 mEmailAddressButton->setFixedSize(size, size);
1116 connect(mEmailAddressButton, &QPushButton::clicked, this, &EditEmailAlarmDlg::openAddressBook);
1117 mEmailAddressButton->setToolTip(i18nc("@info:tooltip", "Open address book"));
1118 mEmailAddressButton->setWhatsThis(i18nc("@info:whatsthis", "Select email addresses from your address book."));
1119 grid->addWidget(mEmailAddressButton, 1, 2);
1121 // Email subject
1122 label = new QLabel(i18nc("@label:textbox Email subject", "Subject:"), parent);
1123 label->setFixedSize(label->sizeHint());
1124 grid->addWidget(label, 2, 0);
1126 mEmailSubjectEdit = new LineEdit(parent);
1127 mEmailSubjectEdit->setMinimumSize(mEmailSubjectEdit->sizeHint());
1128 label->setBuddy(mEmailSubjectEdit);
1129 mEmailSubjectEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email subject."));
1130 connect(mEmailSubjectEdit, &LineEdit::textChanged, this, &EditEmailAlarmDlg::contentsChanged);
1131 grid->addWidget(mEmailSubjectEdit, 2, 1, 1, 2);
1133 // Email body
1134 mEmailMessageEdit = new TextEdit(parent);
1135 mEmailMessageEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the email message."));
1136 connect(mEmailMessageEdit, &TextEdit::textChanged, this, &EditEmailAlarmDlg::contentsChanged);
1137 frameLayout->addWidget(mEmailMessageEdit);
1139 // Email attachments
1140 grid = new QGridLayout();
1141 grid->setMargin(0);
1142 frameLayout->addLayout(grid);
1143 label = new QLabel(i18nc("@label:listbox", "Attachments:"), parent);
1144 label->setFixedSize(label->sizeHint());
1145 grid->addWidget(label, 0, 0);
1147 mEmailAttachList = new QComboBox(parent);
1148 mEmailAttachList->setEditable(true);
1149 mEmailAttachList->setMinimumSize(mEmailAttachList->sizeHint());
1150 if (mEmailAttachList->lineEdit())
1151 mEmailAttachList->lineEdit()->setReadOnly(true);
1152 label->setBuddy(mEmailAttachList);
1153 mEmailAttachList->setWhatsThis(i18nc("@info:whatsthis", "Files to send as attachments to the email."));
1154 grid->addWidget(mEmailAttachList, 0, 1);
1155 grid->setColumnStretch(1, 1);
1157 mEmailAddAttachButton = new QPushButton(i18nc("@action:button", "Add..."), parent);
1158 connect(mEmailAddAttachButton, &QPushButton::clicked, this, &EditEmailAlarmDlg::slotAddAttachment);
1159 mEmailAddAttachButton->setWhatsThis(i18nc("@info:whatsthis", "Add an attachment to the email."));
1160 grid->addWidget(mEmailAddAttachButton, 0, 2);
1162 mEmailRemoveButton = new QPushButton(i18nc("@action:button", "Remove"), parent);
1163 connect(mEmailRemoveButton, &QPushButton::clicked, this, &EditEmailAlarmDlg::slotRemoveAttachment);
1164 mEmailRemoveButton->setWhatsThis(i18nc("@info:whatsthis", "Remove the highlighted attachment from the email."));
1165 grid->addWidget(mEmailRemoveButton, 1, 2);
1167 // BCC email to sender
1168 mEmailBcc = new CheckBox(i18n_chk_CopyEmailToSelf(), parent);
1169 mEmailBcc->setFixedSize(mEmailBcc->sizeHint());
1170 mEmailBcc->setWhatsThis(i18nc("@info:whatsthis", "If checked, the email will be blind copied to you."));
1171 connect(mEmailBcc, &CheckBox::toggled, this, &EditEmailAlarmDlg::contentsChanged);
1172 grid->addWidget(mEmailBcc, 1, 0, 1, 2, Qt::AlignLeft);
1175 /******************************************************************************
1176 * Initialise the dialog controls from the specified event.
1178 void EditEmailAlarmDlg::type_initValues(const KAEvent* event)
1180 if (event)
1182 // Set the values to those for the specified event
1183 mEmailAttachList->addItems(event->emailAttachments());
1184 mEmailToEdit->setText(event->emailAddresses(QStringLiteral(", ")));
1185 mEmailSubjectEdit->setText(event->emailSubject());
1186 mEmailBcc->setChecked(event->emailBcc());
1187 if (mEmailFromList)
1188 mEmailFromList->setCurrentIdentity(event->emailFromId());
1190 else
1192 // Set the values to their defaults
1193 mEmailBcc->setChecked(Preferences::defaultEmailBcc());
1195 attachmentEnable();
1198 /******************************************************************************
1199 * Enable/disable controls depending on whether any attachments are entered.
1201 void EditEmailAlarmDlg::attachmentEnable()
1203 bool enable = mEmailAttachList->count();
1204 mEmailAttachList->setEnabled(enable);
1205 if (mEmailRemoveButton)
1206 mEmailRemoveButton->setEnabled(enable);
1209 /******************************************************************************
1210 * Set the dialog's action and the action's text.
1212 void EditEmailAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
1214 Q_UNUSED(action);
1215 Q_ASSERT(action == KAEvent::EMAIL);
1216 if (alarmText.isEmail())
1218 mEmailToEdit->setText(alarmText.to());
1219 mEmailSubjectEdit->setText(alarmText.subject());
1220 mEmailMessageEdit->setPlainText(alarmText.body());
1222 else
1223 mEmailMessageEdit->setPlainText(alarmText.displayText());
1226 /******************************************************************************
1227 * Initialise various values in the New Alarm dialogue.
1229 void EditEmailAlarmDlg::setEmailFields(uint fromID, const KCalCore::Person::List& addresses,
1230 const QString& subject, const QStringList& attachments)
1232 if (fromID)
1233 mEmailFromList->setCurrentIdentity(fromID);
1234 if (!addresses.isEmpty())
1235 mEmailToEdit->setText(KAEvent::joinEmailAddresses(addresses, QStringLiteral(", ")));
1236 if (!subject.isEmpty())
1237 mEmailSubjectEdit->setText(subject);
1238 if (!attachments.isEmpty())
1240 mEmailAttachList->addItems(attachments);
1241 attachmentEnable();
1244 void EditEmailAlarmDlg::setBcc(bool bcc)
1246 mEmailBcc->setChecked(bcc);
1249 /******************************************************************************
1250 * Set the read-only status of all non-template controls.
1252 void EditEmailAlarmDlg::setReadOnly(bool readOnly)
1254 mEmailToEdit->setReadOnly(readOnly);
1255 mEmailSubjectEdit->setReadOnly(readOnly);
1256 mEmailMessageEdit->setReadOnly(readOnly);
1257 mEmailBcc->setReadOnly(readOnly);
1258 if (mEmailFromList)
1259 mEmailFromList->setReadOnly(readOnly);
1260 if (readOnly)
1262 mEmailAddressButton->hide();
1263 mEmailAddAttachButton->hide();
1264 mEmailRemoveButton->hide();
1266 else
1268 mEmailAddressButton->show();
1269 mEmailAddAttachButton->show();
1270 mEmailRemoveButton->show();
1272 EditAlarmDlg::setReadOnly(readOnly);
1275 /******************************************************************************
1276 * Save the state of all controls.
1278 void EditEmailAlarmDlg::saveState(const KAEvent* event)
1280 EditAlarmDlg::saveState(event);
1281 if (mEmailFromList)
1282 mSavedEmailFrom = mEmailFromList->currentIdentityName();
1283 mSavedEmailTo = mEmailToEdit->text();
1284 mSavedEmailSubject = mEmailSubjectEdit->text();
1285 mSavedEmailAttach.clear();
1286 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1287 mSavedEmailAttach += mEmailAttachList->itemText(i);
1288 mSavedEmailBcc = mEmailBcc->isChecked();
1291 /******************************************************************************
1292 * Check whether any of the controls has changed state since the dialog was
1293 * first displayed.
1294 * Reply = true if any controls have changed, or if it's a new event.
1295 * = false if no controls have changed.
1297 bool EditEmailAlarmDlg::type_stateChanged() const
1299 QStringList emailAttach;
1300 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1301 emailAttach += mEmailAttachList->itemText(i);
1302 if ((mEmailFromList && mSavedEmailFrom != mEmailFromList->currentIdentityName())
1303 || mSavedEmailTo != mEmailToEdit->text()
1304 || mSavedEmailSubject != mEmailSubjectEdit->text()
1305 || mSavedEmailAttach != emailAttach
1306 || mSavedEmailBcc != mEmailBcc->isChecked())
1307 return true;
1308 return false;
1311 /******************************************************************************
1312 * Extract the data in the dialog specific to the alarm type and set up a
1313 * KAEvent from it.
1315 void EditEmailAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1317 Q_UNUSED(trial);
1318 event.set(dt, text, QColor(), QColor(), QFont(), KAEvent::EMAIL, lateCancel, getAlarmFlags());
1319 uint from = mEmailFromList ? mEmailFromList->currentIdentity() : 0;
1320 event.setEmail(from, mEmailAddresses, mEmailSubjectEdit->text(), mEmailAttachments);
1323 /******************************************************************************
1324 * Get the currently specified alarm flag bits.
1326 KAEvent::Flags EditEmailAlarmDlg::getAlarmFlags() const
1328 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
1329 if (mEmailBcc->isChecked()) flags |= KAEvent::EMAIL_BCC;
1330 return flags;
1333 /******************************************************************************
1334 * Convert the email addresses to a list, and validate them. Convert the email
1335 * attachments to a list.
1337 bool EditEmailAlarmDlg::type_validate(bool trial)
1339 QString addrs = mEmailToEdit->text();
1340 if (addrs.isEmpty())
1341 mEmailAddresses.clear();
1342 else
1344 QString bad = KAMail::convertAddresses(addrs, mEmailAddresses);
1345 if (!bad.isEmpty())
1347 mEmailToEdit->setFocus();
1348 KAMessageBox::error(this, xi18nc("@info", "Invalid email address: <email>%1</email>", bad));
1349 return false;
1352 if (mEmailAddresses.isEmpty())
1354 mEmailToEdit->setFocus();
1355 KAMessageBox::error(this, i18nc("@info", "No email address specified"));
1356 return false;
1359 mEmailAttachments.clear();
1360 for (int i = 0, end = mEmailAttachList->count(); i < end; ++i)
1362 QString att = mEmailAttachList->itemText(i);
1363 switch (KAMail::checkAttachment(att))
1365 case 1:
1366 mEmailAttachments.append(att);
1367 break;
1368 case 0:
1369 break; // empty
1370 case -1:
1371 mEmailAttachList->setFocus();
1372 KAMessageBox::error(this, xi18nc("@info", "Invalid email attachment: <filename>%1</filename>", att));
1373 return false;
1376 if (trial && KAMessageBox::warningContinueCancel(this, i18nc("@info", "Do you really want to send the email now to the specified recipient(s)?"),
1377 i18nc("@action:button", "Confirm Email"), KGuiItem(i18nc("@action:button", "Send"))) != KMessageBox::Continue)
1378 return false;
1379 return true;
1382 /******************************************************************************
1383 * Called when the Try action is about to be executed.
1385 void EditEmailAlarmDlg::type_aboutToTry()
1387 // Disconnect any previous connections, to prevent multiple messages being output
1388 disconnect(theApp(), &KAlarmApp::execAlarmSuccess, this, &EditEmailAlarmDlg::slotTrySuccess);
1389 connect(theApp(), &KAlarmApp::execAlarmSuccess, this, &EditEmailAlarmDlg::slotTrySuccess);
1392 /******************************************************************************
1393 * Tell the user the result of the Try action.
1395 void EditEmailAlarmDlg::slotTrySuccess()
1397 disconnect(theApp(), &KAlarmApp::execAlarmSuccess, this, &EditEmailAlarmDlg::slotTrySuccess);
1398 QString msg;
1399 QString to = KAEvent::joinEmailAddresses(mEmailAddresses, QStringLiteral("<nl/>"));
1400 to.replace(QLatin1Char('<'), QStringLiteral("&lt;"));
1401 to.replace(QLatin1Char('>'), QStringLiteral("&gt;"));
1402 if (mEmailBcc->isChecked())
1403 msg = QLatin1String("<qt>") + xi18nc("@info", "Email sent to:<nl/>%1<nl/>Bcc: <email>%2</email>",
1404 to, Preferences::emailBccAddress()) + QLatin1String("</qt>");
1405 else
1406 msg = QLatin1String("<qt>") + xi18nc("@info", "Email sent to:<nl/>%1", to) + QLatin1String("</qt>");
1407 KAMessageBox::information(this, msg);
1410 /******************************************************************************
1411 * Get a selection from the Address Book.
1413 void EditEmailAlarmDlg::openAddressBook()
1415 // Use AutoQPointer to guard against crash on application exit while
1416 // the dialogue is still open. It prevents double deletion (both on
1417 // deletion of MainWindow, and on return from this function).
1418 AutoQPointer<Akonadi::EmailAddressSelectionDialog> dlg = new Akonadi::EmailAddressSelectionDialog(this);
1419 if (dlg->exec() != QDialog::Accepted)
1420 return;
1422 Akonadi::EmailAddressSelection::List selections = dlg->selectedAddresses();
1423 if (selections.isEmpty())
1424 return;
1425 Person person(selections.first().name(), selections.first().email());
1426 QString addrs = mEmailToEdit->text().trimmed();
1427 if (!addrs.isEmpty())
1428 addrs += QLatin1String(", ");
1429 addrs += person.fullName();
1430 mEmailToEdit->setText(addrs);
1433 /******************************************************************************
1434 * Select a file to attach to the email.
1436 void EditEmailAlarmDlg::slotAddAttachment()
1438 QString url = KAlarm::browseFile(i18nc("@title:window", "Choose File to Attach"), mAttachDefaultDir, QString(),
1439 QString(), KFile::ExistingOnly, this);
1440 if (!url.isEmpty())
1442 mEmailAttachList->addItem(url);
1443 mEmailAttachList->setCurrentIndex(mEmailAttachList->count() - 1); // select the new item
1444 mEmailRemoveButton->setEnabled(true);
1445 mEmailAttachList->setEnabled(true);
1446 contentsChanged();
1450 /******************************************************************************
1451 * Remove the currently selected attachment from the email.
1453 void EditEmailAlarmDlg::slotRemoveAttachment()
1455 int item = mEmailAttachList->currentIndex();
1456 mEmailAttachList->removeItem(item);
1457 int count = mEmailAttachList->count();
1458 if (item >= count)
1459 mEmailAttachList->setCurrentIndex(count - 1);
1460 if (!count)
1462 mEmailRemoveButton->setEnabled(false);
1463 mEmailAttachList->setEnabled(false);
1465 contentsChanged();
1468 /******************************************************************************
1469 * Clean up the alarm text.
1471 bool EditEmailAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1473 Q_UNUSED(showErrorMessage);
1474 result = mEmailMessageEdit->toPlainText();
1475 return true;
1479 /*=============================================================================
1480 = Class EditAudioAlarmDlg
1481 = Dialog to edit audio alarms with no display window.
1482 =============================================================================*/
1484 /******************************************************************************
1485 * Constructor.
1486 * Parameters:
1487 * Template = true to edit/create an alarm template
1488 * = false to edit/create an alarm.
1489 * event != to initialise the dialog to show the specified event's data.
1491 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, QWidget* parent, GetResourceType getResource)
1492 : EditAlarmDlg(Template, KAEvent::AUDIO, parent, getResource),
1493 mMessageWin(Q_NULLPTR)
1495 qCDebug(KALARM_LOG) << "New";
1496 init(Q_NULLPTR);
1499 EditAudioAlarmDlg::EditAudioAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent,
1500 GetResourceType getResource, bool readOnly)
1501 : EditAlarmDlg(Template, event, newAlarm, parent, getResource, readOnly),
1502 mMessageWin(Q_NULLPTR)
1504 qCDebug(KALARM_LOG) << "Event.id()";
1505 init(event);
1506 mTryButton->setEnabled(!MessageWin::isAudioPlaying());
1507 connect(theApp(), &KAlarmApp::audioPlaying, this, &EditAudioAlarmDlg::slotAudioPlaying);
1510 /******************************************************************************
1511 * Return the window caption.
1513 QString EditAudioAlarmDlg::type_caption() const
1515 return isTemplate() ? (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm Template") : i18nc("@title:window", "Edit Audio Alarm Template"))
1516 : (isNewAlarm() ? i18nc("@title:window", "New Audio Alarm") : i18nc("@title:window", "Edit Audio Alarm"));
1519 /******************************************************************************
1520 * Set up the dialog controls common to display alarms.
1522 void EditAudioAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
1524 // File name edit box
1525 mSoundConfig = new SoundWidget(false, true, parent);
1526 if (isTemplate())
1527 mSoundConfig->setAllowEmptyFile();
1528 connect(mSoundConfig, &SoundWidget::changed, this, &EditAudioAlarmDlg::contentsChanged);
1529 frameLayout->addWidget(mSoundConfig);
1531 // Top-adjust the controls
1532 mPadding = new QWidget(parent);
1533 QHBoxLayout* hlayout = new QHBoxLayout(mPadding);
1534 hlayout->setMargin(0);
1535 hlayout->setSpacing(0);
1536 frameLayout->addWidget(mPadding);
1537 frameLayout->setStretchFactor(mPadding, 1);
1540 /******************************************************************************
1541 * Initialise the dialog controls from the specified event.
1543 void EditAudioAlarmDlg::type_initValues(const KAEvent* event)
1545 if (event)
1547 mSoundConfig->set(event->audioFile(), event->soundVolume(), event->fadeVolume(), event->fadeSeconds(),
1548 (event->flags() & KAEvent::REPEAT_SOUND) ? event->repeatSoundPause() : -1);
1550 else
1552 // Set the values to their defaults
1553 mSoundConfig->set(Preferences::defaultSoundFile(), Preferences::defaultSoundVolume(),
1554 -1, 0, (Preferences::defaultSoundRepeat() ? 0 : -1));
1558 /******************************************************************************
1559 * Initialise various values in the New Alarm dialogue.
1561 void EditAudioAlarmDlg::setAudio(const QString& file, float volume)
1563 mSoundConfig->set(file, volume);
1566 /******************************************************************************
1567 * Set the dialog's action and the action's text.
1569 void EditAudioAlarmDlg::setAction(KAEvent::SubAction action, const AlarmText& alarmText)
1571 Q_UNUSED(action);
1572 Q_ASSERT(action == KAEvent::AUDIO);
1573 mSoundConfig->set(alarmText.displayText(), Preferences::defaultSoundVolume());
1576 /******************************************************************************
1577 * Set the read-only status of all non-template controls.
1579 void EditAudioAlarmDlg::setReadOnly(bool readOnly)
1581 mSoundConfig->setReadOnly(readOnly);
1582 EditAlarmDlg::setReadOnly(readOnly);
1585 /******************************************************************************
1586 * Save the state of all controls.
1588 void EditAudioAlarmDlg::saveState(const KAEvent* event)
1590 EditAlarmDlg::saveState(event);
1591 mSavedFile = mSoundConfig->fileName();
1592 mSoundConfig->getVolume(mSavedVolume, mSavedFadeVolume, mSavedFadeSeconds);
1593 mSavedRepeatPause = mSoundConfig->repeatPause();
1596 /******************************************************************************
1597 * Check whether any of the controls has changed state since the dialog was
1598 * first displayed.
1599 * Reply = true if any controls have changed, or if it's a new event.
1600 * = false if no controls have changed.
1602 bool EditAudioAlarmDlg::type_stateChanged() const
1604 if (mSavedFile != mSoundConfig->fileName())
1605 return true;
1606 if (!mSavedFile.isEmpty() || isTemplate())
1608 float volume, fadeVolume;
1609 int fadeSecs;
1610 mSoundConfig->getVolume(volume, fadeVolume, fadeSecs);
1611 if (mSavedRepeatPause != mSoundConfig->repeatPause()
1612 || mSavedVolume != volume
1613 || mSavedFadeVolume != fadeVolume
1614 || mSavedFadeSeconds != fadeSecs)
1615 return true;
1617 return false;
1620 /******************************************************************************
1621 * Extract the data in the dialog specific to the alarm type and set up a
1622 * KAEvent from it.
1624 void EditAudioAlarmDlg::type_setEvent(KAEvent& event, const KDateTime& dt, const QString& text, int lateCancel, bool trial)
1626 Q_UNUSED(text);
1627 Q_UNUSED(trial);
1628 event.set(dt, QString(), QColor(), QColor(), QFont(), KAEvent::AUDIO, lateCancel, getAlarmFlags());
1629 float volume, fadeVolume;
1630 int fadeSecs;
1631 mSoundConfig->getVolume(volume, fadeVolume, fadeSecs);
1632 int repeatPause = mSoundConfig->repeatPause();
1633 QUrl url;
1634 mSoundConfig->file(url, false);
1635 event.setAudioFile(url.toString(), volume, fadeVolume, fadeSecs, repeatPause, isTemplate());
1638 /******************************************************************************
1639 * Get the currently specified alarm flag bits.
1641 KAEvent::Flags EditAudioAlarmDlg::getAlarmFlags() const
1643 KAEvent::Flags flags = EditAlarmDlg::getAlarmFlags();
1644 if (mSoundConfig->repeatPause() >= 0) flags |= KAEvent::REPEAT_SOUND;
1645 return flags;
1648 /******************************************************************************
1649 * Check whether the file name is valid.
1651 bool EditAudioAlarmDlg::checkText(QString& result, bool showErrorMessage) const
1653 QUrl url;
1654 if (!mSoundConfig->file(url, showErrorMessage))
1656 result.clear();
1657 return false;
1659 result = url.isLocalFile() ? url.toLocalFile() : url.toString();
1660 return true;
1663 /******************************************************************************
1664 * Called when the Try button is clicked.
1665 * If the audio file is currently playing (as a result of previously clicking
1666 * the Try button), cancel playback. Otherwise, play the audio file.
1668 void EditAudioAlarmDlg::slotTry()
1670 if (!MessageWin::isAudioPlaying())
1671 EditAlarmDlg::slotTry(); // play the audio file
1672 else if (mMessageWin)
1674 mMessageWin->stopAudio();
1675 mMessageWin = Q_NULLPTR;
1679 /******************************************************************************
1680 * Called when the Try action has been executed.
1682 void EditAudioAlarmDlg::type_executedTry(const QString&, void* result)
1684 mMessageWin = (MessageWin*)result; // note which MessageWin controls the audio playback
1685 if (mMessageWin)
1687 slotAudioPlaying(true);
1688 connect(mMessageWin, &MessageWin::destroyed, this, &EditAudioAlarmDlg::audioWinDestroyed);
1692 /******************************************************************************
1693 * Called when audio playing starts or stops.
1694 * Enable/disable/toggle the Try button.
1696 void EditAudioAlarmDlg::slotAudioPlaying(bool playing)
1698 if (!playing)
1700 // Nothing is playing, so enable the Try button
1701 mTryButton->setEnabled(true);
1702 mTryButton->setCheckable(false);
1703 mTryButton->setChecked(false);
1704 mMessageWin = Q_NULLPTR;
1706 else if (mMessageWin)
1708 // The test sound file is playing, so enable the Try button and depress it
1709 mTryButton->setEnabled(true);
1710 mTryButton->setCheckable(true);
1711 mTryButton->setChecked(true);
1713 else
1715 // An alarm is playing, so disable the Try button
1716 mTryButton->setEnabled(false);
1717 mTryButton->setCheckable(false);
1718 mTryButton->setChecked(false);
1723 /*=============================================================================
1724 = Class CommandEdit
1725 = A widget to allow entry of a command or a command script.
1726 =============================================================================*/
1727 CommandEdit::CommandEdit(QWidget* parent)
1728 : QWidget(parent)
1730 QVBoxLayout* vlayout = new QVBoxLayout(this);
1731 vlayout->setMargin(0);
1732 vlayout->setSpacing(style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
1733 mTypeScript = new CheckBox(EditCommandAlarmDlg::i18n_chk_EnterScript(), this);
1734 mTypeScript->setFixedSize(mTypeScript->sizeHint());
1735 mTypeScript->setWhatsThis(i18nc("@info:whatsthis", "Check to enter the contents of a script instead of a shell command line"));
1736 connect(mTypeScript, &CheckBox::toggled, this, &CommandEdit::slotCmdScriptToggled);
1737 connect(mTypeScript, &CheckBox::toggled, this, &CommandEdit::changed);
1738 vlayout->addWidget(mTypeScript, 0, Qt::AlignLeft);
1740 mCommandEdit = new LineEdit(LineEdit::Url, this);
1741 mCommandEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter a shell command to execute."));
1742 connect(mCommandEdit, &LineEdit::textChanged, this, &CommandEdit::changed);
1743 vlayout->addWidget(mCommandEdit);
1745 mScriptEdit = new TextEdit(this);
1746 mScriptEdit->setWhatsThis(i18nc("@info:whatsthis", "Enter the contents of a script to execute"));
1747 connect(mScriptEdit, &TextEdit::textChanged, this, &CommandEdit::changed);
1748 vlayout->addWidget(mScriptEdit);
1750 slotCmdScriptToggled(mTypeScript->isChecked());
1753 /******************************************************************************
1754 * Initialise the widget controls from the specified event.
1756 void CommandEdit::setScript(bool script)
1758 mTypeScript->setChecked(script);
1761 bool CommandEdit::isScript() const
1763 return mTypeScript->isChecked();
1766 /******************************************************************************
1767 * Set the widget's text.
1769 void CommandEdit::setText(const AlarmText& alarmText)
1771 QString text = alarmText.displayText();
1772 bool script = alarmText.isScript();
1773 mTypeScript->setChecked(script);
1774 if (script)
1775 mScriptEdit->setPlainText(text);
1776 else
1777 mCommandEdit->setText(KAlarm::pathOrUrl(text));
1780 /******************************************************************************
1781 * Return the widget's text.
1783 QString CommandEdit::text() const
1785 QString result;
1786 if (mTypeScript->isChecked())
1787 result = mScriptEdit->toPlainText();
1788 else
1789 result = mCommandEdit->text();
1790 return result.trimmed();
1793 /******************************************************************************
1794 * Return the alarm text.
1795 * If 'showErrorMessage' is true and the text is empty, an error message is
1796 * displayed.
1798 QString CommandEdit::text(EditAlarmDlg* dlg, bool showErrorMessage) const
1800 QString result = text();
1801 if (showErrorMessage && result.isEmpty())
1802 KAMessageBox::sorry(dlg, i18nc("@info", "Please enter a command or script to execute"));
1803 return result;
1806 /******************************************************************************
1807 * Set the read-only status of all controls.
1809 void CommandEdit::setReadOnly(bool readOnly)
1811 mTypeScript->setReadOnly(readOnly);
1812 mCommandEdit->setReadOnly(readOnly);
1813 mScriptEdit->setReadOnly(readOnly);
1816 /******************************************************************************
1817 * Called when one of the command type radio buttons is clicked,
1818 * to display the appropriate edit field.
1820 void CommandEdit::slotCmdScriptToggled(bool on)
1822 if (on)
1824 mCommandEdit->hide();
1825 mScriptEdit->show();
1826 mScriptEdit->setFocus();
1828 else
1830 mScriptEdit->hide();
1831 mCommandEdit->show();
1832 mCommandEdit->setFocus();
1834 Q_EMIT scriptToggled(on);
1837 /******************************************************************************
1838 * Returns the minimum size of the widget.
1840 QSize CommandEdit::minimumSizeHint() const
1842 QSize t(mTypeScript->minimumSizeHint());
1843 QSize s(mCommandEdit->minimumSizeHint().expandedTo(mScriptEdit->minimumSizeHint()));
1844 s.setHeight(s.height() + style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing) + t.height());
1845 if (s.width() < t.width())
1846 s.setWidth(t.width());
1847 return s;
1852 /*=============================================================================
1853 = Class TextEdit
1854 = A text edit field with a minimum height of 3 text lines.
1855 =============================================================================*/
1856 TextEdit::TextEdit(QWidget* parent)
1857 : KTextEdit(parent)
1859 QSize tsize = sizeHint();
1860 tsize.setHeight(fontMetrics().lineSpacing()*13/4 + 2*frameWidth());
1861 setMinimumSize(tsize);
1864 void TextEdit::dragEnterEvent(QDragEnterEvent* e)
1866 if (KCalUtils::ICalDrag::canDecode(e->mimeData()))
1867 e->ignore(); // don't accept "text/calendar" objects
1868 KTextEdit::dragEnterEvent(e);
1871 // vim: et sw=4: