/* * editdlg.cpp - dialogue to create or modify an alarm or alarm template * Program: kalarm * Copyright © 2001-2008 by David Jarvie * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kalarm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "alarmcalendar.h" #include "alarmtimewidget.h" #include "checkbox.h" #include "colourcombo.h" #include "deferdlg.h" #include "emailidcombo.h" #include "fontcolourbutton.h" #include "functions.h" #include "kalarmapp.h" #include "kamail.h" #include "latecancel.h" #include "lineedit.h" #include "mainwindow.h" #include "pickfileradio.h" #include "preferences.h" #include "radiobutton.h" #include "recurrenceedit.h" #include "reminder.h" #include "shellprocess.h" #include "soundpicker.h" #include "specialactions.h" #include "spinbox.h" #include "templatepickdlg.h" #include "timeedit.h" #include "timespinbox.h" #include "editdlg.moc" #include "editdlgprivate.moc" using namespace KCal; static const char EDIT_DIALOG_NAME[] = "EditDialog"; static const int maxDelayTime = 99*60 + 59; // < 100 hours /*============================================================================= = Class PickAlarmFileRadio =============================================================================*/ class PickAlarmFileRadio : public PickFileRadio { public: PickAlarmFileRadio(const TQString& text, TQButtonGroup* parent, const char* name = 0) : PickFileRadio(text, parent, name) { } virtual TQString pickFile() // called when browse button is pressed to select a file to display { return KAlarm::browseFile(i18n("Choose Text or Image File to Display"), mDefaultDir, fileEdit()->text(), TQString(), KFile::ExistingOnly, parentWidget(), "pickAlarmFile"); } private: TQString mDefaultDir; // default directory for file browse button }; /*============================================================================= = Class PickLogFileRadio =============================================================================*/ class PickLogFileRadio : public PickFileRadio { public: PickLogFileRadio(TQPushButton* b, LineEdit* e, const TQString& text, TQButtonGroup* parent, const char* name = 0) : PickFileRadio(b, e, text, parent, name) { } virtual TQString pickFile() // called when browse button is pressed to select a log file { return KAlarm::browseFile(i18n("Choose Log File"), mDefaultDir, fileEdit()->text(), TQString(), KFile::LocalOnly, parentWidget(), "pickLogFile"); } private: TQString mDefaultDir; // default directory for log file browse button }; inline TQString recurText(const KAEvent& event) { TQString r; if (event.repeatCount()) r = TQString::fromLatin1("%1 / %2").arg(event.recurrenceText()).arg(event.repetitionText()); else r = event.recurrenceText(); return i18n("&Recurrence - [%1]").arg(r); } // Collect these widget labels together to ensure consistent wording and // translations across different modules. TQString EditAlarmDlg::i18n_ConfirmAck() { return i18n("Confirm acknowledgment"); } TQString EditAlarmDlg::i18n_k_ConfirmAck() { return i18n("Confirm ac&knowledgment"); } TQString EditAlarmDlg::i18n_SpecialActions() { return i18n("Special Actions..."); } TQString EditAlarmDlg::i18n_ShowInKOrganizer() { return i18n("Show in KOrganizer"); } TQString EditAlarmDlg::i18n_g_ShowInKOrganizer() { return i18n("Show in KOr&ganizer"); } TQString EditAlarmDlg::i18n_EnterScript() { return i18n("Enter a script"); } TQString EditAlarmDlg::i18n_p_EnterScript() { return i18n("Enter a scri&pt"); } TQString EditAlarmDlg::i18n_ExecInTermWindow() { return i18n("Execute in terminal window"); } TQString EditAlarmDlg::i18n_w_ExecInTermWindow() { return i18n("Execute in terminal &window"); } TQString EditAlarmDlg::i18n_u_ExecInTermWindow() { return i18n("Exec&ute in terminal window"); } TQString EditAlarmDlg::i18n_g_LogToFile() { return i18n("Lo&g to file"); } TQString EditAlarmDlg::i18n_CopyEmailToSelf() { return i18n("Copy email to self"); } TQString EditAlarmDlg::i18n_e_CopyEmailToSelf() { return i18n("Copy &email to self"); } TQString EditAlarmDlg::i18n_s_CopyEmailToSelf() { return i18n("Copy email to &self"); } TQString EditAlarmDlg::i18n_EmailFrom() { return i18n("'From' email address", "From:"); } TQString EditAlarmDlg::i18n_f_EmailFrom() { return i18n("'From' email address", "&From:"); } TQString EditAlarmDlg::i18n_EmailTo() { return i18n("Email addressee", "To:"); } TQString EditAlarmDlg::i18n_EmailSubject() { return i18n("Email subject", "Subject:"); } TQString EditAlarmDlg::i18n_j_EmailSubject() { return i18n("Email subject", "Sub&ject:"); } /****************************************************************************** * Constructor. * Parameters: * Template = true to edit/create an alarm template * = false to edit/create an alarm. * event != to initialise the dialogue to show the specified event's data. */ EditAlarmDlg::EditAlarmDlg(bool Template, const TQString& caption, TQWidget* parent, const char* name, const KAEvent* event, bool readOnly) : KDialogBase(parent, (name ? name : Template ? "TemplEditDlg" : "EditDlg"), true, caption, (readOnly ? Cancel|Try : Template ? Ok|Cancel|Try : Ok|Cancel|Try|Default), (readOnly ? Cancel : Ok)), mMainPageShown(false), mRecurPageShown(false), mRecurSetDefaultEndDate(true), mTemplateName(0), mSpecialActionsButton(0), mReminderDeferral(false), mReminderArchived(false), mEmailRemoveButton(0), mDeferGroup(0), mTimeWidget(0), mShowInKorganizer(0), mDeferGroupHeight(0), mTemplate(Template), mDesiredReadOnly(readOnly), mReadOnly(readOnly), mSavedEvent(0) { setButtonText(Default, i18n("Load Template...")); TQVBox* mainWidget = new TQVBox(this); mainWidget->setSpacing(spacingHint()); setMainWidget(mainWidget); if (mTemplate) { TQHBox* box = new TQHBox(mainWidget); box->setSpacing(spacingHint()); TQLabel* label = new TQLabel(i18n("Template name:"), box); label->setFixedSize(label->sizeHint()); mTemplateName = new TQLineEdit(box); mTemplateName->setReadOnly(mReadOnly); label->setBuddy(mTemplateName); TQWhatsThis::add(box, i18n("Enter the name of the alarm template")); box->setFixedHeight(box->sizeHint().height()); } mTabs = new TQTabWidget(mainWidget); mTabs->setMargin(marginHint()); TQVBox* mainPageBox = new TQVBox(mTabs); mainPageBox->setSpacing(spacingHint()); mTabs->addTab(mainPageBox, i18n("&Alarm")); mMainPageIndex = 0; PageFrame* mainPage = new PageFrame(mainPageBox); connect(mainPage, TQT_SIGNAL(shown()), TQT_SLOT(slotShowMainPage())); TQVBoxLayout* topLayout = new TQVBoxLayout(mainPage, 0, spacingHint()); // Recurrence tab TQVBox* recurTab = new TQVBox(mTabs); mainPageBox->setSpacing(spacingHint()); mTabs->addTab(recurTab, TQString()); mRecurPageIndex = 1; mRecurrenceEdit = new RecurrenceEdit(readOnly, recurTab, "recurPage"); connect(mRecurrenceEdit, TQT_SIGNAL(shown()), TQT_SLOT(slotShowRecurrenceEdit())); connect(mRecurrenceEdit, TQT_SIGNAL(typeChanged(int)), TQT_SLOT(slotRecurTypeChange(int))); connect(mRecurrenceEdit, TQT_SIGNAL(frequencyChanged()), TQT_SLOT(slotRecurFrequencyChange())); connect(mRecurrenceEdit, TQT_SIGNAL(repeatNeedsInitialisation()), TQT_SLOT(slotSetSubRepetition())); // Alarm action mActionGroup = new ButtonGroup(i18n("Action"), mainPage, "actionGroup"); connect(mActionGroup, TQT_SIGNAL(buttonSet(int)), TQT_SLOT(slotAlarmTypeChanged(int))); topLayout->addWidget(mActionGroup, 1); TQBoxLayout* layout = new TQVBoxLayout(mActionGroup, marginHint(), spacingHint()); layout->addSpacing(fontMetrics().lineSpacing()/2); TQGridLayout* grid = new TQGridLayout(layout, 1, 5); // Message radio button mMessageRadio = new RadioButton(i18n("Te&xt"), mActionGroup, "messageButton"); mMessageRadio->setFixedSize(mMessageRadio->sizeHint()); TQWhatsThis::add(mMessageRadio, i18n("If checked, the alarm will display a text message.")); grid->addWidget(mMessageRadio, 1, 0); grid->setColStretch(1, 1); // File radio button mFileRadio = new PickAlarmFileRadio(i18n("&File"), mActionGroup, "fileButton"); mFileRadio->setFixedSize(mFileRadio->sizeHint()); TQWhatsThis::add(mFileRadio, i18n("If checked, the alarm will display the contents of a text or image file.")); grid->addWidget(mFileRadio, 1, 2); grid->setColStretch(3, 1); // Command radio button mCommandRadio = new RadioButton(i18n("Co&mmand"), mActionGroup, "cmdButton"); mCommandRadio->setFixedSize(mCommandRadio->sizeHint()); TQWhatsThis::add(mCommandRadio, i18n("If checked, the alarm will execute a shell command.")); grid->addWidget(mCommandRadio, 1, 4); grid->setColStretch(5, 1); // Email radio button mEmailRadio = new RadioButton(i18n("&Email"), mActionGroup, "emailButton"); mEmailRadio->setFixedSize(mEmailRadio->sizeHint()); TQWhatsThis::add(mEmailRadio, i18n("If checked, the alarm will send an email.")); grid->addWidget(mEmailRadio, 1, 6); initDisplayAlarms(mActionGroup); layout->addWidget(mDisplayAlarmsFrame); initCommand(mActionGroup); layout->addWidget(mCommandFrame); initEmail(mActionGroup); layout->addWidget(mEmailFrame); // Deferred date/time: visible only for a deferred recurring event. mDeferGroup = new TQGroupBox(1, Qt::Vertical, i18n("Deferred Alarm"), mainPage, "deferGroup"); topLayout->addWidget(mDeferGroup); TQLabel* label = new TQLabel(i18n("Deferred to:"), mDeferGroup); label->setFixedSize(label->sizeHint()); mDeferTimeLabel = new TQLabel(mDeferGroup); mDeferChangeButton = new TQPushButton(i18n("C&hange..."), mDeferGroup); mDeferChangeButton->setFixedSize(mDeferChangeButton->sizeHint()); connect(mDeferChangeButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotEditDeferral())); TQWhatsThis::add(mDeferChangeButton, i18n("Change the alarm's deferred time, or cancel the deferral")); mDeferGroup->addSpace(0); layout = new TQHBoxLayout(topLayout); // Date and time entry if (mTemplate) { mTemplateTimeGroup = new ButtonGroup(i18n("Time"), mainPage, "templateGroup"); connect(mTemplateTimeGroup, TQT_SIGNAL(buttonSet(int)), TQT_SLOT(slotTemplateTimeType(int))); layout->addWidget(mTemplateTimeGroup); grid = new TQGridLayout(mTemplateTimeGroup, 2, 2, marginHint(), spacingHint()); grid->addRowSpacing(0, fontMetrics().lineSpacing()/2); // Get alignment to use in TQGridLayout (AlignAuto doesn't work correctly there) int alignment = TQApplication::reverseLayout() ? TQt::AlignRight : TQt::AlignLeft; mTemplateDefaultTime = new RadioButton(i18n("&Default time"), mTemplateTimeGroup, "templateDefTimeButton"); mTemplateDefaultTime->setFixedSize(mTemplateDefaultTime->sizeHint()); mTemplateDefaultTime->setReadOnly(mReadOnly); TQWhatsThis::add(mTemplateDefaultTime, i18n("Do not specify a start time for alarms based on this template. " "The normal default start time will be used.")); grid->addWidget(mTemplateDefaultTime, 0, 0, alignment); TQHBox* box = new TQHBox(mTemplateTimeGroup); box->setSpacing(spacingHint()); mTemplateUseTime = new RadioButton(i18n("Time:"), box, "templateTimeButton"); mTemplateUseTime->setFixedSize(mTemplateUseTime->sizeHint()); mTemplateUseTime->setReadOnly(mReadOnly); TQWhatsThis::add(mTemplateUseTime, i18n("Specify a start time for alarms based on this template.")); mTemplateTimeGroup->insert(mTemplateUseTime); mTemplateTime = new TimeEdit(box, "templateTimeEdit"); mTemplateTime->setFixedSize(mTemplateTime->sizeHint()); mTemplateTime->setReadOnly(mReadOnly); TQWhatsThis::add(mTemplateTime, TQString("%1\n\n%2").arg(i18n("Enter the start time for alarms based on this template.")) .arg(TimeSpinBox::shiftWhatsThis())); box->setStretchFactor(new TQWidget(box), 1); // left adjust the controls box->setFixedHeight(box->sizeHint().height()); grid->addWidget(box, 0, 1, alignment); mTemplateAnyTime = new RadioButton(i18n("An&y time"), mTemplateTimeGroup, "templateAnyTimeButton"); mTemplateAnyTime->setFixedSize(mTemplateAnyTime->sizeHint()); mTemplateAnyTime->setReadOnly(mReadOnly); TQWhatsThis::add(mTemplateAnyTime, i18n("Set the '%1' option for alarms based on this template.").arg(i18n("Any time"))); grid->addWidget(mTemplateAnyTime, 1, 0, alignment); box = new TQHBox(mTemplateTimeGroup); box->setSpacing(spacingHint()); mTemplateUseTimeAfter = new RadioButton(AlarmTimeWidget::i18n_w_TimeFromNow(), box, "templateFromNowButton"); mTemplateUseTimeAfter->setFixedSize(mTemplateUseTimeAfter->sizeHint()); mTemplateUseTimeAfter->setReadOnly(mReadOnly); TQWhatsThis::add(mTemplateUseTimeAfter, i18n("Set alarms based on this template to start after the specified time " "interval from when the alarm is created.")); mTemplateTimeGroup->insert(mTemplateUseTimeAfter); mTemplateTimeAfter = new TimeSpinBox(1, maxDelayTime, box); mTemplateTimeAfter->setValue(1439); mTemplateTimeAfter->setFixedSize(mTemplateTimeAfter->sizeHint()); mTemplateTimeAfter->setReadOnly(mReadOnly); TQWhatsThis::add(mTemplateTimeAfter, TQString("%1\n\n%2").arg(AlarmTimeWidget::i18n_TimeAfterPeriod()) .arg(TimeSpinBox::shiftWhatsThis())); box->setFixedHeight(box->sizeHint().height()); grid->addWidget(box, 1, 1, alignment); layout->addStretch(); } else { mTimeWidget = new AlarmTimeWidget(i18n("Time"), AlarmTimeWidget::AT_TIME, mainPage, "timeGroup"); connect(mTimeWidget, TQT_SIGNAL(anyTimeToggled(bool)), TQT_SLOT(slotAnyTimeToggled(bool))); topLayout->addWidget(mTimeWidget); } // Reminder static const TQString reminderText = i18n("Enter how long in advance of the main alarm to display a reminder alarm."); mReminder = new Reminder(i18n("Rem&inder:"), i18n("Check to additionally display a reminder in advance of the main alarm time(s)."), TQString("%1\n\n%2").arg(reminderText).arg(TimeSpinBox::shiftWhatsThis()), true, true, mainPage); mReminder->setFixedSize(mReminder->sizeHint()); topLayout->addWidget(mReminder, 0, TQt::AlignAuto); // Late cancel selector - default = allow late display mLateCancel = new LateCancelSelector(true, mainPage); topLayout->addWidget(mLateCancel, 0, TQt::AlignAuto); // Acknowledgement confirmation required - default = no confirmation layout = new TQHBoxLayout(topLayout, 0); mConfirmAck = createConfirmAckCheckbox(mainPage); mConfirmAck->setFixedSize(mConfirmAck->sizeHint()); layout->addWidget(mConfirmAck); layout->addSpacing(2*spacingHint()); layout->addStretch(); if (theApp()->korganizerEnabled()) { // Show in KOrganizer checkbox mShowInKorganizer = new CheckBox(i18n_ShowInKOrganizer(), mainPage); mShowInKorganizer->setFixedSize(mShowInKorganizer->sizeHint()); TQWhatsThis::add(mShowInKorganizer, i18n("Check to copy the alarm into KOrganizer's calendar")); layout->addWidget(mShowInKorganizer); } setButtonWhatsThis(Ok, i18n("Schedule the alarm at the specified time.")); // Initialise the state of all controls according to the specified event, if any initialise(event); if (mTemplateName) mTemplateName->setFocus(); // Save the initial state of all controls so that we can later tell if they have changed saveState((event && (mTemplate || !event->isTemplate())) ? event : 0); // Note the current desktop so that the dialog can be shown on it. // If a main window is visible, the dialog will by KDE default always appear on its // desktop. If the user invokes the dialog via the system tray on a different desktop, // that can cause confusion. mDesktop = KWin::currentDesktop(); } EditAlarmDlg::~EditAlarmDlg() { delete mSavedEvent; } /****************************************************************************** * Set up the dialog controls common to display alarms. */ void EditAlarmDlg::initDisplayAlarms(TQWidget* parent) { mDisplayAlarmsFrame = new TQFrame(parent); mDisplayAlarmsFrame->setFrameStyle(TQFrame::NoFrame); TQBoxLayout* frameLayout = new TQVBoxLayout(mDisplayAlarmsFrame, 0, spacingHint()); // Text message edit box mTextMessageEdit = new TextEdit(mDisplayAlarmsFrame); mTextMessageEdit->setWordWrap(KTextEdit::NoWrap); TQWhatsThis::add(mTextMessageEdit, i18n("Enter the text of the alarm message. It may be multi-line.")); frameLayout->addWidget(mTextMessageEdit); // File name edit box mFileBox = new TQHBox(mDisplayAlarmsFrame); frameLayout->addWidget(mFileBox); mFileMessageEdit = new LineEdit(LineEdit::Url, mFileBox); mFileMessageEdit->setAcceptDrops(true); TQWhatsThis::add(mFileMessageEdit, i18n("Enter the name or URL of a text or image file to display.")); // File browse button mFileBrowseButton = new TQPushButton(mFileBox); mFileBrowseButton->setPixmap(SmallIcon("document-open")); mFileBrowseButton->setFixedSize(mFileBrowseButton->sizeHint()); TQToolTip::add(mFileBrowseButton, i18n("Choose a file")); TQWhatsThis::add(mFileBrowseButton, i18n("Select a text or image file to display.")); mFileRadio->init(mFileBrowseButton, mFileMessageEdit); // Font and colour choice button and sample text mFontColourButton = new FontColourButton(mDisplayAlarmsFrame); mFontColourButton->setMaximumHeight(mFontColourButton->sizeHint().height()); frameLayout->addWidget(mFontColourButton); TQHBoxLayout* layout = new TQHBoxLayout(frameLayout, 0, 0); mBgColourBox = new TQHBox(mDisplayAlarmsFrame); mBgColourBox->setSpacing(spacingHint()); layout->addWidget(mBgColourBox); layout->addStretch(); TQLabel* label = new TQLabel(i18n("&Background color:"), mBgColourBox); mBgColourButton = new ColourCombo(mBgColourBox); label->setBuddy(mBgColourButton); TQWhatsThis::add(mBgColourBox, i18n("Select the alarm message background color")); // Sound checkbox and file selector layout = new TQHBoxLayout(frameLayout); mSoundPicker = new SoundPicker(mDisplayAlarmsFrame); mSoundPicker->setFixedSize(mSoundPicker->sizeHint()); layout->addWidget(mSoundPicker); layout->addSpacing(2*spacingHint()); layout->addStretch(); if (ShellProcess::authorised()) // don't display if shell commands not allowed (e.g. kiosk mode) { // Special actions button mSpecialActionsButton = new SpecialActionsButton(i18n_SpecialActions(), mDisplayAlarmsFrame); mSpecialActionsButton->setFixedSize(mSpecialActionsButton->sizeHint()); layout->addWidget(mSpecialActionsButton); } // Top-adjust the controls mFilePadding = new TQHBox(mDisplayAlarmsFrame); frameLayout->addWidget(mFilePadding); frameLayout->setStretchFactor(mFilePadding, 1); } /****************************************************************************** * Set up the command alarm dialog controls. */ void EditAlarmDlg::initCommand(TQWidget* parent) { mCommandFrame = new TQFrame(parent); mCommandFrame->setFrameStyle(TQFrame::NoFrame); TQBoxLayout* frameLayout = new TQVBoxLayout(mCommandFrame, 0, spacingHint()); mCmdTypeScript = new CheckBox(i18n_p_EnterScript(), mCommandFrame); mCmdTypeScript->setFixedSize(mCmdTypeScript->sizeHint()); connect(mCmdTypeScript, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotCmdScriptToggled(bool))); TQWhatsThis::add(mCmdTypeScript, i18n("Check to enter the contents of a script instead of a shell command line")); frameLayout->addWidget(mCmdTypeScript, 0, TQt::AlignAuto); mCmdCommandEdit = new LineEdit(LineEdit::Url, mCommandFrame); TQWhatsThis::add(mCmdCommandEdit, i18n("Enter a shell command to execute.")); frameLayout->addWidget(mCmdCommandEdit); mCmdScriptEdit = new TextEdit(mCommandFrame); TQWhatsThis::add(mCmdScriptEdit, i18n("Enter the contents of a script to execute")); frameLayout->addWidget(mCmdScriptEdit); // What to do with command output mCmdOutputGroup = new ButtonGroup(i18n("Command Output"), mCommandFrame); frameLayout->addWidget(mCmdOutputGroup); TQBoxLayout* layout = new TQVBoxLayout(mCmdOutputGroup, marginHint(), spacingHint()); layout->addSpacing(fontMetrics().lineSpacing()/2); // Execute in terminal window RadioButton* button = new RadioButton(i18n_u_ExecInTermWindow(), mCmdOutputGroup, "execInTerm"); button->setFixedSize(button->sizeHint()); TQWhatsThis::add(button, i18n("Check to execute the command in a terminal window")); mCmdOutputGroup->insert(button, EXEC_IN_TERMINAL); layout->addWidget(button, 0, TQt::AlignAuto); // Log file name edit box TQHBox* box = new TQHBox(mCmdOutputGroup); (new TQWidget(box))->setFixedWidth(button->style().subRect(TQStyle::SR_RadioButtonIndicator, button).width()); // indent the edit box // (new TQWidget(box))->setFixedWidth(button->style().pixelMetric(TQStyle::PM_ExclusiveIndicatorWidth)); // indent the edit box mCmdLogFileEdit = new LineEdit(LineEdit::Url, box); mCmdLogFileEdit->setAcceptDrops(true); TQWhatsThis::add(mCmdLogFileEdit, i18n("Enter the name or path of the log file.")); // Log file browse button. // The file browser dialogue is activated by the PickLogFileRadio class. TQPushButton* browseButton = new TQPushButton(box); browseButton->setPixmap(SmallIcon("document-open")); browseButton->setFixedSize(browseButton->sizeHint()); TQToolTip::add(browseButton, i18n("Choose a file")); TQWhatsThis::add(browseButton, i18n("Select a log file.")); // Log output to file button = new PickLogFileRadio(browseButton, mCmdLogFileEdit, i18n_g_LogToFile(), mCmdOutputGroup, "cmdLog"); button->setFixedSize(button->sizeHint()); TQWhatsThis::add(button, i18n("Check to log the command output to a local file. The output will be appended to any existing contents of the file.")); mCmdOutputGroup->insert(button, LOG_TO_FILE); layout->addWidget(button, 0, TQt::AlignAuto); layout->addWidget(box); // Discard output button = new RadioButton(i18n("Discard"), mCmdOutputGroup, "cmdDiscard"); button->setFixedSize(button->sizeHint()); TQWhatsThis::add(button, i18n("Check to discard command output.")); mCmdOutputGroup->insert(button, DISCARD_OUTPUT); layout->addWidget(button, 0, TQt::AlignAuto); // Top-adjust the controls mCmdPadding = new TQHBox(mCommandFrame); frameLayout->addWidget(mCmdPadding); frameLayout->setStretchFactor(mCmdPadding, 1); } /****************************************************************************** * Set up the email alarm dialog controls. */ void EditAlarmDlg::initEmail(TQWidget* parent) { mEmailFrame = new TQFrame(parent); mEmailFrame->setFrameStyle(TQFrame::NoFrame); TQBoxLayout* layout = new TQVBoxLayout(mEmailFrame, 0, spacingHint()); TQGridLayout* grid = new TQGridLayout(layout, 3, 3, spacingHint()); grid->setColStretch(1, 1); mEmailFromList = 0; if (Preferences::emailFrom() == Preferences::MAIL_FROM_KMAIL) { // Email sender identity TQLabel* label = new TQLabel(i18n_EmailFrom(), mEmailFrame); label->setFixedSize(label->sizeHint()); grid->addWidget(label, 0, 0); mEmailFromList = new EmailIdCombo(KAMail::identityManager(), mEmailFrame); mEmailFromList->setMinimumSize(mEmailFromList->sizeHint()); label->setBuddy(mEmailFromList); TQWhatsThis::add(mEmailFromList, i18n("Your email identity, used to identify you as the sender when sending email alarms.")); grid->addMultiCellWidget(mEmailFromList, 0, 0, 1, 2); } // Email recipients TQLabel* label = new TQLabel(i18n_EmailTo(), mEmailFrame); label->setFixedSize(label->sizeHint()); grid->addWidget(label, 1, 0); mEmailToEdit = new LineEdit(LineEdit::Emails, mEmailFrame); mEmailToEdit->setMinimumSize(mEmailToEdit->sizeHint()); TQWhatsThis::add(mEmailToEdit, i18n("Enter the addresses of the email recipients. Separate multiple addresses by " "commas or semicolons.")); grid->addWidget(mEmailToEdit, 1, 1); mEmailAddressButton = new TQPushButton(mEmailFrame); mEmailAddressButton->setPixmap(SmallIcon("contents")); mEmailAddressButton->setFixedSize(mEmailAddressButton->sizeHint()); connect(mEmailAddressButton, TQT_SIGNAL(clicked()), TQT_SLOT(openAddressBook())); TQToolTip::add(mEmailAddressButton, i18n("Open address book")); TQWhatsThis::add(mEmailAddressButton, i18n("Select email addresses from your address book.")); grid->addWidget(mEmailAddressButton, 1, 2); // Email subject label = new TQLabel(i18n_j_EmailSubject(), mEmailFrame); label->setFixedSize(label->sizeHint()); grid->addWidget(label, 2, 0); mEmailSubjectEdit = new LineEdit(mEmailFrame); mEmailSubjectEdit->setMinimumSize(mEmailSubjectEdit->sizeHint()); label->setBuddy(mEmailSubjectEdit); TQWhatsThis::add(mEmailSubjectEdit, i18n("Enter the email subject.")); grid->addMultiCellWidget(mEmailSubjectEdit, 2, 2, 1, 2); // Email body mEmailMessageEdit = new TextEdit(mEmailFrame); TQWhatsThis::add(mEmailMessageEdit, i18n("Enter the email message.")); layout->addWidget(mEmailMessageEdit); // Email attachments grid = new TQGridLayout(layout, 2, 3, spacingHint()); label = new TQLabel(i18n("Attachment&s:"), mEmailFrame); label->setFixedSize(label->sizeHint()); grid->addWidget(label, 0, 0); mEmailAttachList = new TQComboBox(true, mEmailFrame); mEmailAttachList->setMinimumSize(mEmailAttachList->sizeHint()); mEmailAttachList->lineEdit()->setReadOnly(true); TQListBox* list = mEmailAttachList->listBox(); TQRect rect = list->geometry(); list->setGeometry(rect.left() - 50, rect.top(), rect.width(), rect.height()); label->setBuddy(mEmailAttachList); TQWhatsThis::add(mEmailAttachList, i18n("Files to send as attachments to the email.")); grid->addWidget(mEmailAttachList, 0, 1); grid->setColStretch(1, 1); mEmailAddAttachButton = new TQPushButton(i18n("Add..."), mEmailFrame); connect(mEmailAddAttachButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotAddAttachment())); TQWhatsThis::add(mEmailAddAttachButton, i18n("Add an attachment to the email.")); grid->addWidget(mEmailAddAttachButton, 0, 2); mEmailRemoveButton = new TQPushButton(i18n("Remo&ve"), mEmailFrame); connect(mEmailRemoveButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotRemoveAttachment())); TQWhatsThis::add(mEmailRemoveButton, i18n("Remove the highlighted attachment from the email.")); grid->addWidget(mEmailRemoveButton, 1, 2); // BCC email to sender mEmailBcc = new CheckBox(i18n_s_CopyEmailToSelf(), mEmailFrame); mEmailBcc->setFixedSize(mEmailBcc->sizeHint()); TQWhatsThis::add(mEmailBcc, i18n("If checked, the email will be blind copied to you.")); grid->addMultiCellWidget(mEmailBcc, 1, 1, 0, 1, TQt::AlignAuto); } /****************************************************************************** * Initialise the dialogue controls from the specified event. */ void EditAlarmDlg::initialise(const KAEvent* event) { mReadOnly = mDesiredReadOnly; if (!mTemplate && event && event->action() == KAEvent::COMMAND && !ShellProcess::authorised()) mReadOnly = true; // don't allow editing of existing command alarms in kiosk mode setReadOnly(); mChanged = false; mOnlyDeferred = false; mExpiredRecurrence = false; mKMailSerialNumber = 0; bool deferGroupVisible = false; if (event) { // Set the values to those for the specified event if (mTemplate) mTemplateName->setText(event->templateName()); bool recurs = event->recurs(); if ((recurs || event->repeatCount()) && !mTemplate && event->deferred()) { deferGroupVisible = true; mDeferDateTime = event->deferDateTime(); mDeferTimeLabel->setText(mDeferDateTime.formatLocale()); mDeferGroup->show(); } if (event->defaultFont()) mFontColourButton->setDefaultFont(); else mFontColourButton->setFont(event->font()); mFontColourButton->setBgColour(event->bgColour()); mFontColourButton->setFgColour(event->fgColour()); mBgColourButton->setColour(event->bgColour()); if (mTemplate) { // Editing a template int afterTime = event->isTemplate() ? event->templateAfterTime() : -1; bool noTime = !afterTime; bool useTime = !event->mainDateTime().isDateOnly(); int button = mTemplateTimeGroup->id(noTime ? mTemplateDefaultTime : (afterTime > 0) ? mTemplateUseTimeAfter : useTime ? mTemplateUseTime : mTemplateAnyTime); mTemplateTimeGroup->setButton(button); mTemplateTimeAfter->setValue(afterTime > 0 ? afterTime : 1); if (!noTime && useTime) mTemplateTime->setValue(event->mainDateTime().time()); else mTemplateTime->setValue(0); } else { if (event->isTemplate()) { // Initialising from an alarm template: use current date TQDateTime now = TQDateTime::currentDateTime(); int afterTime = event->templateAfterTime(); if (afterTime >= 0) { mTimeWidget->setDateTime(TQDateTime(now.addSecs(afterTime * 60))); mTimeWidget->selectTimeFromNow(); } else { TQDate d = now.date(); TQTime t = event->startDateTime().time(); bool dateOnly = event->startDateTime().isDateOnly(); if (!dateOnly && now.time() >= t) d = d.addDays(1); // alarm time has already passed, so use tomorrow mTimeWidget->setDateTime(DateTime(TQDateTime(d, t), dateOnly)); } } else { mExpiredRecurrence = recurs && event->mainExpired(); mTimeWidget->setDateTime(recurs || event->uidStatus() == KAEvent::EXPIRED ? event->startDateTime() : event->mainExpired() ? event->deferDateTime() : event->mainDateTime()); } } KAEvent::Action action = event->action(); AlarmText altext; if (event->commandScript()) altext.setScript(event->cleanText()); else altext.setText(event->cleanText()); setAction(action, altext); if (action == KAEvent::MESSAGE && event->kmailSerialNumber() && AlarmText::checkIfEmail(event->cleanText())) mKMailSerialNumber = event->kmailSerialNumber(); if (action == KAEvent::EMAIL) mEmailAttachList->insertStringList(event->emailAttachments()); mLateCancel->setMinutes(event->lateCancel(), event->startDateTime().isDateOnly(), TimePeriod::HOURS_MINUTES); mLateCancel->showAutoClose(action == KAEvent::MESSAGE || action == KAEvent::FILE); mLateCancel->setAutoClose(event->autoClose()); mLateCancel->setFixedSize(mLateCancel->sizeHint()); if (mShowInKorganizer) mShowInKorganizer->setChecked(event->copyToKOrganizer()); mConfirmAck->setChecked(event->confirmAck()); int reminder = event->reminder(); if (!reminder && event->reminderDeferral() && !recurs) { reminder = event->reminderDeferral(); mReminderDeferral = true; } if (!reminder && event->reminderArchived() && recurs) { reminder = event->reminderArchived(); mReminderArchived = true; } mReminder->setMinutes(reminder, (mTimeWidget ? mTimeWidget->anyTime() : mTemplateAnyTime->isOn())); mReminder->setOnceOnly(event->reminderOnceOnly()); mReminder->enableOnceOnly(event->recurs()); if (mSpecialActionsButton) mSpecialActionsButton->setActions(event->preAction(), event->postAction()); mRecurrenceEdit->set(*event, (mTemplate || event->isTemplate())); // must be called after mTimeWidget is set up, to ensure correct date-only enabling mTabs->setTabLabel(mTabs->page(mRecurPageIndex), recurText(*event)); SoundPicker::Type soundType = event->speak() ? SoundPicker::SPEAK : event->beep() ? SoundPicker::BEEP : !event->audioFile().isEmpty() ? SoundPicker::PLAY_FILE : SoundPicker::NONE; mSoundPicker->set(soundType, event->audioFile(), event->soundVolume(), event->fadeVolume(), event->fadeSeconds(), event->repeatSound()); CmdLogType logType = event->commandXterm() ? EXEC_IN_TERMINAL : !event->logFile().isEmpty() ? LOG_TO_FILE : DISCARD_OUTPUT; if (logType == LOG_TO_FILE) mCmdLogFileEdit->setText(event->logFile()); // set file name before setting radio button mCmdOutputGroup->setButton(logType); mEmailToEdit->setText(event->emailAddresses(", ")); mEmailSubjectEdit->setText(event->emailSubject()); mEmailBcc->setChecked(event->emailBcc()); if (mEmailFromList) mEmailFromList->setCurrentIdentity(event->emailFromId()); } else { // Set the values to their defaults if (!ShellProcess::authorised()) { // Don't allow shell commands in kiosk mode mCommandRadio->setEnabled(false); if (mSpecialActionsButton) mSpecialActionsButton->setEnabled(false); } mFontColourButton->setDefaultFont(); mFontColourButton->setBgColour(Preferences::defaultBgColour()); mFontColourButton->setFgColour(Preferences::defaultFgColour()); mBgColourButton->setColour(Preferences::defaultBgColour()); TQDateTime defaultTime = TQDateTime::currentDateTime().addSecs(60); if (mTemplate) { mTemplateTimeGroup->setButton(mTemplateTimeGroup->id(mTemplateDefaultTime)); mTemplateTime->setValue(0); mTemplateTimeAfter->setValue(1); } else mTimeWidget->setDateTime(defaultTime); mActionGroup->setButton(mActionGroup->id(mMessageRadio)); mLateCancel->setMinutes((Preferences::defaultLateCancel() ? 1 : 0), false, TimePeriod::HOURS_MINUTES); mLateCancel->showAutoClose(true); mLateCancel->setAutoClose(Preferences::defaultAutoClose()); mLateCancel->setFixedSize(mLateCancel->sizeHint()); if (mShowInKorganizer) mShowInKorganizer->setChecked(Preferences::defaultCopyToKOrganizer()); mConfirmAck->setChecked(Preferences::defaultConfirmAck()); if (mSpecialActionsButton) mSpecialActionsButton->setActions(Preferences::defaultPreAction(), Preferences::defaultPostAction()); mRecurrenceEdit->setDefaults(defaultTime); // must be called after mTimeWidget is set up, to ensure correct date-only enabling slotRecurFrequencyChange(); // update the Recurrence text mReminder->setMinutes(0, false); mReminder->enableOnceOnly(mRecurrenceEdit->isTimedRepeatType()); // must be called after mRecurrenceEdit is set up mSoundPicker->set(Preferences::defaultSoundType(), Preferences::defaultSoundFile(), Preferences::defaultSoundVolume(), -1, 0, Preferences::defaultSoundRepeat()); mCmdTypeScript->setChecked(Preferences::defaultCmdScript()); mCmdLogFileEdit->setText(Preferences::defaultCmdLogFile()); // set file name before setting radio button mCmdOutputGroup->setButton(Preferences::defaultCmdLogType()); mEmailBcc->setChecked(Preferences::defaultEmailBcc()); } slotCmdScriptToggled(mCmdTypeScript->isChecked()); if (!deferGroupVisible) mDeferGroup->hide(); bool enable = !!mEmailAttachList->count(); mEmailAttachList->setEnabled(enable); if (mEmailRemoveButton) mEmailRemoveButton->setEnabled(enable); AlarmCalendar* cal = AlarmCalendar::templateCalendar(); bool empty = cal->isOpen() && !cal->events().count(); enableButton(Default, !empty); } /****************************************************************************** * Set the read-only status of all non-template controls. */ void EditAlarmDlg::setReadOnly() { // Common controls mMessageRadio->setReadOnly(mReadOnly); mFileRadio->setReadOnly(mReadOnly); mCommandRadio->setReadOnly(mReadOnly); mEmailRadio->setReadOnly(mReadOnly); if (mTimeWidget) mTimeWidget->setReadOnly(mReadOnly); mLateCancel->setReadOnly(mReadOnly); if (mReadOnly) mDeferChangeButton->hide(); else mDeferChangeButton->show(); if (mShowInKorganizer) mShowInKorganizer->setReadOnly(mReadOnly); // Message alarm controls mTextMessageEdit->setReadOnly(mReadOnly); mFileMessageEdit->setReadOnly(mReadOnly); mFontColourButton->setReadOnly(mReadOnly); mBgColourButton->setReadOnly(mReadOnly); mSoundPicker->setReadOnly(mReadOnly); mConfirmAck->setReadOnly(mReadOnly); mReminder->setReadOnly(mReadOnly); if (mSpecialActionsButton) mSpecialActionsButton->setReadOnly(mReadOnly); if (mReadOnly) { mFileBrowseButton->hide(); mFontColourButton->hide(); } else { mFileBrowseButton->show(); mFontColourButton->show(); } // Command alarm controls mCmdTypeScript->setReadOnly(mReadOnly); mCmdCommandEdit->setReadOnly(mReadOnly); mCmdScriptEdit->setReadOnly(mReadOnly); for (int id = DISCARD_OUTPUT; id < EXEC_IN_TERMINAL; ++id) ((RadioButton*)mCmdOutputGroup->find(id))->setReadOnly(mReadOnly); // Email alarm controls mEmailToEdit->setReadOnly(mReadOnly); mEmailSubjectEdit->setReadOnly(mReadOnly); mEmailMessageEdit->setReadOnly(mReadOnly); mEmailBcc->setReadOnly(mReadOnly); if (mEmailFromList) mEmailFromList->setReadOnly(mReadOnly); if (mReadOnly) { mEmailAddressButton->hide(); mEmailAddAttachButton->hide(); mEmailRemoveButton->hide(); } else { mEmailAddressButton->show(); mEmailAddAttachButton->show(); mEmailRemoveButton->show(); } } /****************************************************************************** * Set the dialog's action and the action's text. */ void EditAlarmDlg::setAction(KAEvent::Action action, const AlarmText& alarmText) { TQString text = alarmText.displayText(); bool script; TQRadioButton* radio; switch (action) { case KAEvent::FILE: radio = mFileRadio; mFileMessageEdit->setText(text); break; case KAEvent::COMMAND: radio = mCommandRadio; script = alarmText.isScript(); mCmdTypeScript->setChecked(script); if (script) mCmdScriptEdit->setText(text); else mCmdCommandEdit->setText(text); break; case KAEvent::EMAIL: radio = mEmailRadio; mEmailMessageEdit->setText(text); break; case KAEvent::MESSAGE: default: radio = mMessageRadio; mTextMessageEdit->setText(text); mKMailSerialNumber = 0; if (alarmText.isEmail()) { mKMailSerialNumber = alarmText.kmailSerialNumber(); // Set up email fields also, in case the user wants an email alarm mEmailToEdit->setText(alarmText.to()); mEmailSubjectEdit->setText(alarmText.subject()); mEmailMessageEdit->setText(alarmText.body()); } else if (alarmText.isScript()) { // Set up command script field also, in case the user wants a command alarm mCmdScriptEdit->setText(text); mCmdTypeScript->setChecked(true); } break; } mActionGroup->setButton(mActionGroup->id(radio)); } /****************************************************************************** * Create an "acknowledgement confirmation required" checkbox. */ CheckBox* EditAlarmDlg::createConfirmAckCheckbox(TQWidget* parent, const char* name) { CheckBox* widget = new CheckBox(i18n_k_ConfirmAck(), parent, name); TQWhatsThis::add(widget, i18n("Check to be prompted for confirmation when you acknowledge the alarm.")); return widget; } /****************************************************************************** * Save the state of all controls. */ void EditAlarmDlg::saveState(const KAEvent* event) { delete mSavedEvent; mSavedEvent = 0; if (event) mSavedEvent = new KAEvent(*event); if (mTemplate) { mSavedTemplateName = mTemplateName->text(); mSavedTemplateTimeType = mTemplateTimeGroup->selected(); mSavedTemplateTime = mTemplateTime->time(); mSavedTemplateAfterTime = mTemplateTimeAfter->value(); } mSavedTypeRadio = mActionGroup->selected(); mSavedSoundType = mSoundPicker->sound(); mSavedSoundFile = mSoundPicker->file(); mSavedSoundVolume = mSoundPicker->volume(mSavedSoundFadeVolume, mSavedSoundFadeSeconds); mSavedRepeatSound = mSoundPicker->repeat(); mSavedConfirmAck = mConfirmAck->isChecked(); mSavedFont = mFontColourButton->font(); mSavedFgColour = mFontColourButton->fgColour(); mSavedBgColour = mFileRadio->isOn() ? mBgColourButton->colour() : mFontColourButton->bgColour(); mSavedReminder = mReminder->minutes(); mSavedOnceOnly = mReminder->isOnceOnly(); if (mSpecialActionsButton) { mSavedPreAction = mSpecialActionsButton->preAction(); mSavedPostAction = mSpecialActionsButton->postAction(); } checkText(mSavedTextFileCommandMessage, false); mSavedCmdScript = mCmdTypeScript->isChecked(); mSavedCmdOutputRadio = mCmdOutputGroup->selected(); mSavedCmdLogFile = mCmdLogFileEdit->text(); if (mEmailFromList) mSavedEmailFrom = mEmailFromList->currentIdentityName(); mSavedEmailTo = mEmailToEdit->text(); mSavedEmailSubject = mEmailSubjectEdit->text(); mSavedEmailAttach.clear(); for (int i = 0; i < mEmailAttachList->count(); ++i) mSavedEmailAttach += mEmailAttachList->text(i); mSavedEmailBcc = mEmailBcc->isChecked(); if (mTimeWidget) mSavedDateTime = mTimeWidget->getDateTime(0, false, false); mSavedLateCancel = mLateCancel->minutes(); mSavedAutoClose = mLateCancel->isAutoClose(); if (mShowInKorganizer) mSavedShowInKorganizer = mShowInKorganizer->isChecked(); mSavedRecurrenceType = mRecurrenceEdit->repeatType(); } /****************************************************************************** * Check whether any of the controls has changed state since the dialog was * first displayed. * Reply = true if any non-deferral controls have changed, or if it's a new event. * = false if no non-deferral controls have changed. In this case, * mOnlyDeferred indicates whether deferral controls may have changed. */ bool EditAlarmDlg::stateChanged() const { mChanged = true; mOnlyDeferred = false; if (!mSavedEvent) return true; TQString textFileCommandMessage; checkText(textFileCommandMessage, false); if (mTemplate) { if (mSavedTemplateName != mTemplateName->text() || mSavedTemplateTimeType != mTemplateTimeGroup->selected() || (mTemplateUseTime->isOn() && mSavedTemplateTime != mTemplateTime->time()) || (mTemplateUseTimeAfter->isOn() && mSavedTemplateAfterTime != mTemplateTimeAfter->value())) return true; } else if (mSavedDateTime != mTimeWidget->getDateTime(0, false, false)) return true; if (mSavedTypeRadio != mActionGroup->selected() || mSavedLateCancel != mLateCancel->minutes() || (mShowInKorganizer && mSavedShowInKorganizer != mShowInKorganizer->isChecked()) || textFileCommandMessage != mSavedTextFileCommandMessage || mSavedRecurrenceType != mRecurrenceEdit->repeatType()) return true; if (mMessageRadio->isOn() || mFileRadio->isOn()) { if (mSavedSoundType != mSoundPicker->sound() || mSavedConfirmAck != mConfirmAck->isChecked() || mSavedFont != mFontColourButton->font() || mSavedFgColour != mFontColourButton->fgColour() || mSavedBgColour != (mFileRadio->isOn() ? mBgColourButton->colour() : mFontColourButton->bgColour()) || mSavedReminder != mReminder->minutes() || mSavedOnceOnly != mReminder->isOnceOnly() || mSavedAutoClose != mLateCancel->isAutoClose()) return true; if (mSpecialActionsButton) { if (mSavedPreAction != mSpecialActionsButton->preAction() || mSavedPostAction != mSpecialActionsButton->postAction()) return true; } if (mSavedSoundType == SoundPicker::PLAY_FILE) { if (mSavedSoundFile != mSoundPicker->file()) return true; if (!mSavedSoundFile.isEmpty()) { float fadeVolume; int fadeSecs; if (mSavedRepeatSound != mSoundPicker->repeat() || mSavedSoundVolume != mSoundPicker->volume(fadeVolume, fadeSecs) || mSavedSoundFadeVolume != fadeVolume || mSavedSoundFadeSeconds != fadeSecs) return true; } } } else if (mCommandRadio->isOn()) { if (mSavedCmdScript != mCmdTypeScript->isChecked() || mSavedCmdOutputRadio != mCmdOutputGroup->selected()) return true; if (mCmdOutputGroup->selectedId() == LOG_TO_FILE) { if (mSavedCmdLogFile != mCmdLogFileEdit->text()) return true; } } else if (mEmailRadio->isOn()) { TQStringList emailAttach; for (int i = 0; i < mEmailAttachList->count(); ++i) emailAttach += mEmailAttachList->text(i); if ((mEmailFromList && mSavedEmailFrom != mEmailFromList->currentIdentityName()) || mSavedEmailTo != mEmailToEdit->text() || mSavedEmailSubject != mEmailSubjectEdit->text() || mSavedEmailAttach != emailAttach || mSavedEmailBcc != mEmailBcc->isChecked()) return true; } if (mRecurrenceEdit->stateChanged()) return true; if (mSavedEvent && mSavedEvent->deferred()) mOnlyDeferred = true; mChanged = false; return false; } /****************************************************************************** * Get the currently entered dialogue data. * The data is returned in the supplied KAEvent instance. * Reply = false if the only change has been to an existing deferral. */ bool EditAlarmDlg::getEvent(KAEvent& event) { if (mChanged) { // It's a new event, or the edit controls have changed setEvent(event, mAlarmMessage, false); return true; } // Only the deferral time may have changed event = *mSavedEvent; if (mOnlyDeferred) { // Just modify the original event, to avoid expired recurring events // being returned as rubbish. if (mDeferDateTime.isValid()) event.defer(mDeferDateTime, event.reminderDeferral(), false); else event.cancelDefer(); } return false; } /****************************************************************************** * Extract the data in the dialogue and set up a KAEvent from it. * If 'trial' is true, the event is set up for a simple one-off test, ignoring * recurrence, reminder, template etc. data. */ void EditAlarmDlg::setEvent(KAEvent& event, const TQString& text, bool trial) { TQDateTime dt; if (!trial) { if (!mTemplate) dt = mAlarmDateTime.dateTime(); else if (mTemplateUseTime->isOn()) dt = TQDateTime(TQDate(2000,1,1), mTemplateTime->time()); } KAEvent::Action type = getAlarmType(); event.set(dt, text, (mFileRadio->isOn() ? mBgColourButton->colour() : mFontColourButton->bgColour()), mFontColourButton->fgColour(), mFontColourButton->font(), type, (trial ? 0 : mLateCancel->minutes()), getAlarmFlags()); switch (type) { case KAEvent::MESSAGE: if (AlarmText::checkIfEmail(text)) event.setKMailSerialNumber(mKMailSerialNumber); // fall through to FILE case KAEvent::FILE: { float fadeVolume; int fadeSecs; float volume = mSoundPicker->volume(fadeVolume, fadeSecs); event.setAudioFile(mSoundPicker->file(), volume, fadeVolume, fadeSecs); if (!trial) event.setReminder(mReminder->minutes(), mReminder->isOnceOnly()); if (mSpecialActionsButton) event.setActions(mSpecialActionsButton->preAction(), mSpecialActionsButton->postAction()); break; } case KAEvent::EMAIL: { uint from = mEmailFromList ? mEmailFromList->currentIdentity() : 0; event.setEmail(from, mEmailAddresses, mEmailSubjectEdit->text(), mEmailAttachments); break; } case KAEvent::COMMAND: if (mCmdOutputGroup->selectedId() == LOG_TO_FILE) event.setLogFile(mCmdLogFileEdit->text()); break; default: break; } if (!trial) { if (mRecurrenceEdit->repeatType() != RecurrenceEdit::NO_RECUR) { mRecurrenceEdit->updateEvent(event, !mTemplate); TQDateTime now = TQDateTime::currentDateTime(); bool dateOnly = mAlarmDateTime.isDateOnly(); if ((dateOnly && mAlarmDateTime.date() < now.date()) || (!dateOnly && mAlarmDateTime.rawDateTime() < now)) { // A timed recurrence has an entered start date which has // already expired, so we must adjust the next repetition. event.setNextOccurrence(now); } mAlarmDateTime = event.startDateTime(); if (mDeferDateTime.isValid() && mDeferDateTime < mAlarmDateTime) { bool deferral = true; bool deferReminder = false; int reminder = mReminder->minutes(); if (reminder) { DateTime remindTime = mAlarmDateTime.addMins(-reminder); if (mDeferDateTime >= remindTime) { if (remindTime > TQDateTime::currentDateTime()) deferral = false; // ignore deferral if it's after next reminder else if (mDeferDateTime > remindTime) deferReminder = true; // it's the reminder which is being deferred } } if (deferral) event.defer(mDeferDateTime, deferReminder, false); } } if (mTemplate) { int afterTime = mTemplateDefaultTime->isOn() ? 0 : mTemplateUseTimeAfter->isOn() ? mTemplateTimeAfter->value() : -1; event.setTemplate(mTemplateName->text(), afterTime); } } } /****************************************************************************** * Get the currently specified alarm flag bits. */ int EditAlarmDlg::getAlarmFlags() const { bool displayAlarm = mMessageRadio->isOn() || mFileRadio->isOn(); bool cmdAlarm = mCommandRadio->isOn(); bool emailAlarm = mEmailRadio->isOn(); return (displayAlarm && mSoundPicker->sound() == SoundPicker::BEEP ? KAEvent::BEEP : 0) | (displayAlarm && mSoundPicker->sound() == SoundPicker::SPEAK ? KAEvent::SPEAK : 0) | (displayAlarm && mSoundPicker->repeat() ? KAEvent::REPEAT_SOUND : 0) | (displayAlarm && mConfirmAck->isChecked() ? KAEvent::CONFIRM_ACK : 0) | (displayAlarm && mLateCancel->isAutoClose() ? KAEvent::AUTO_CLOSE : 0) | (cmdAlarm && mCmdTypeScript->isChecked() ? KAEvent::SCRIPT : 0) | (cmdAlarm && mCmdOutputGroup->selectedId() == EXEC_IN_TERMINAL ? KAEvent::EXEC_IN_XTERM : 0) | (emailAlarm && mEmailBcc->isChecked() ? KAEvent::EMAIL_BCC : 0) | (mShowInKorganizer && mShowInKorganizer->isChecked() ? KAEvent::COPY_KORGANIZER : 0) | (mRecurrenceEdit->repeatType() == RecurrenceEdit::AT_LOGIN ? KAEvent::REPEAT_AT_LOGIN : 0) | ((mTemplate ? mTemplateAnyTime->isOn() : mAlarmDateTime.isDateOnly()) ? KAEvent::ANY_TIME : 0) | (mFontColourButton->defaultFont() ? KAEvent::DEFAULT_FONT : 0); } /****************************************************************************** * Get the currently selected alarm type. */ KAEvent::Action EditAlarmDlg::getAlarmType() const { return mFileRadio->isOn() ? KAEvent::FILE : mCommandRadio->isOn() ? KAEvent::COMMAND : mEmailRadio->isOn() ? KAEvent::EMAIL : KAEvent::MESSAGE; } /****************************************************************************** * Called when the dialog is displayed. * The first time through, sets the size to the same as the last time it was * displayed. */ void EditAlarmDlg::showEvent(TQShowEvent* se) { if (!mDeferGroupHeight) { mDeferGroupHeight = mDeferGroup->height() + spacingHint(); TQSize s; if (KAlarm::readConfigWindowSize(EDIT_DIALOG_NAME, s)) s.setHeight(s.height() + (mDeferGroup->isHidden() ? 0 : mDeferGroupHeight)); else s = minimumSize(); resize(s); } KWin::setOnDesktop(winId(), mDesktop); // ensure it displays on the desktop expected by the user KDialog::showEvent(se); } /****************************************************************************** * Called when the dialog's size has changed. * Records the new size (adjusted to ignore the optional height of the deferred * time edit widget) in the config file. */ void EditAlarmDlg::resizeEvent(TQResizeEvent* re) { if (isVisible()) { TQSize s = re->size(); s.setHeight(s.height() - (mDeferGroup->isHidden() ? 0 : mDeferGroupHeight)); KAlarm::writeConfigWindowSize(EDIT_DIALOG_NAME, s); } KDialog::resizeEvent(re); } /****************************************************************************** * Called when the OK button is clicked. * Validate the input data. */ void EditAlarmDlg::slotOk() { if (!stateChanged()) { // No changes have been made except possibly to an existing deferral if (!mOnlyDeferred) reject(); else accept(); return; } RecurrenceEdit::RepeatType recurType = mRecurrenceEdit->repeatType(); if (mTimeWidget && mTabs->currentPageIndex() == mRecurPageIndex && recurType == RecurrenceEdit::AT_LOGIN) mTimeWidget->setDateTime(mRecurrenceEdit->endDateTime()); bool timedRecurrence = mRecurrenceEdit->isTimedRepeatType(); // does it recur other than at login? if (mTemplate) { // Check that the template name is not blank and is unique TQString errmsg; TQString name = mTemplateName->text(); if (name.isEmpty()) errmsg = i18n("You must enter a name for the alarm template"); else if (name != mSavedTemplateName) { AlarmCalendar* cal = AlarmCalendar::templateCalendarOpen(); if (cal && KAEvent::findTemplateName(*cal, name).valid()) errmsg = i18n("Template name is already in use"); } if (!errmsg.isEmpty()) { mTemplateName->setFocus(); KMessageBox::sorry(this, errmsg); return; } } else { TQWidget* errWidget; mAlarmDateTime = mTimeWidget->getDateTime(0, !timedRecurrence, false, &errWidget); if (errWidget) { // It's more than just an existing deferral being changed, so the time matters mTabs->setCurrentPage(mMainPageIndex); errWidget->setFocus(); mTimeWidget->getDateTime(); // display the error message now return; } } if (!checkCommandData() || !checkEmailData()) return; if (!mTemplate) { if (timedRecurrence) { TQDateTime now = TQDateTime::currentDateTime(); if (mAlarmDateTime.date() < now.date() || (mAlarmDateTime.date() == now.date() && !mAlarmDateTime.isDateOnly() && mAlarmDateTime.time() < now.time())) { // A timed recurrence has an entered start date which // has already expired, so we must adjust it. KAEvent event; getEvent(event); // this may adjust mAlarmDateTime if (( mAlarmDateTime.date() < now.date() || (mAlarmDateTime.date() == now.date() && !mAlarmDateTime.isDateOnly() && mAlarmDateTime.time() < now.time())) && event.nextOccurrence(now, mAlarmDateTime, KAEvent::ALLOW_FOR_REPETITION) == KAEvent::NO_OCCURRENCE) { KMessageBox::sorry(this, i18n("Recurrence has already expired")); return; } } } TQString errmsg; TQWidget* errWidget = mRecurrenceEdit->checkData(mAlarmDateTime.dateTime(), errmsg); if (errWidget) { mTabs->setCurrentPage(mRecurPageIndex); errWidget->setFocus(); KMessageBox::sorry(this, errmsg); return; } } if (recurType != RecurrenceEdit::NO_RECUR) { KAEvent recurEvent; int longestRecurInterval = -1; int reminder = mReminder->minutes(); if (reminder && !mReminder->isOnceOnly()) { mRecurrenceEdit->updateEvent(recurEvent, false); longestRecurInterval = recurEvent.longestRecurrenceInterval(); if (longestRecurInterval && reminder >= longestRecurInterval) { mTabs->setCurrentPage(mMainPageIndex); mReminder->setFocusOnCount(); KMessageBox::sorry(this, i18n("Reminder period must be less than the recurrence interval, unless '%1' is checked." ).arg(Reminder::i18n_first_recurrence_only())); return; } } if (mRecurrenceEdit->subRepeatCount()) { if (longestRecurInterval < 0) { mRecurrenceEdit->updateEvent(recurEvent, false); longestRecurInterval = recurEvent.longestRecurrenceInterval(); } if (longestRecurInterval > 0 && recurEvent.repeatInterval() * recurEvent.repeatCount() >= longestRecurInterval - reminder) { KMessageBox::sorry(this, i18n("The duration of a repetition within the recurrence must be less than the recurrence interval minus any reminder period")); mRecurrenceEdit->activateSubRepetition(); // display the alarm repetition dialog again return; } if (recurEvent.repeatInterval() % 1440 && ((mTemplate && mTemplateAnyTime->isOn()) || (!mTemplate && mAlarmDateTime.isDateOnly()))) { KMessageBox::sorry(this, i18n("For a repetition within the recurrence, its period must be in units of days or weeks for a date-only alarm")); mRecurrenceEdit->activateSubRepetition(); // display the alarm repetition dialog again return; } } } if (checkText(mAlarmMessage)) accept(); } /****************************************************************************** * Called when the Try button is clicked. * Display/execute the alarm immediately for the user to check its configuration. */ void EditAlarmDlg::slotTry() { TQString text; if (checkText(text)) { if (mEmailRadio->isOn()) { if (!checkEmailData() || KMessageBox::warningContinueCancel(this, i18n("Do you really want to send the email now to the specified recipient(s)?"), i18n("Confirm Email"), i18n("&Send")) != KMessageBox::Continue) return; } KAEvent event; setEvent(event, text, true); void* proc = theApp()->execAlarm(event, event.firstAlarm(), false, false); if (proc) { if (mCommandRadio->isOn() && mCmdOutputGroup->selectedId() != EXEC_IN_TERMINAL) { theApp()->commandMessage((ShellProcess*)proc, this); KMessageBox::information(this, i18n("Command executed:\n%1").arg(text)); theApp()->commandMessage((ShellProcess*)proc, 0); } else if (mEmailRadio->isOn()) { TQString bcc; if (mEmailBcc->isChecked()) bcc = i18n("\nBcc: %1").arg(Preferences::emailBccAddress()); KMessageBox::information(this, i18n("Email sent to:\n%1%2").arg(mEmailAddresses.join("\n")).arg(bcc)); } } } } /****************************************************************************** * Called when the Cancel button is clicked. */ void EditAlarmDlg::slotCancel() { reject(); } /****************************************************************************** * Called when the Load Template button is clicked. * Prompt to select a template and initialise the dialogue with its contents. */ void EditAlarmDlg::slotDefault() { TemplatePickDlg dlg(this, "templPickDlg"); if (dlg.exec() == TQDialog::Accepted) initialise(dlg.selectedTemplate()); } /****************************************************************************** * Called when the Change deferral button is clicked. */ void EditAlarmDlg::slotEditDeferral() { if (!mTimeWidget) return; bool limit = true; int repeatInterval; int repeatCount = mRecurrenceEdit->subRepeatCount(&repeatInterval); DateTime start = mSavedEvent->recurs() ? (mExpiredRecurrence ? DateTime() : mSavedEvent->mainDateTime()) : mTimeWidget->getDateTime(0, !repeatCount, !mExpiredRecurrence); if (!start.isValid()) { if (!mExpiredRecurrence) return; limit = false; } TQDateTime now = TQDateTime::currentDateTime(); if (limit) { if (repeatCount && start < now) { // Sub-repetition - find the time of the next one repeatInterval *= 60; int repetition = (start.secsTo(now) + repeatInterval - 1) / repeatInterval; if (repetition > repeatCount) { mTimeWidget->getDateTime(); // output the appropriate error message return; } start = start.addSecs(repetition * repeatInterval); } } bool deferred = mDeferDateTime.isValid(); DeferAlarmDlg deferDlg(i18n("Defer Alarm"), (deferred ? mDeferDateTime : DateTime(now.addSecs(60))), deferred, this, "EditDeferDlg"); if (limit) { // Don't allow deferral past the next recurrence int reminder = mReminder->minutes(); if (reminder) { DateTime remindTime = start.addMins(-reminder); if (TQDateTime::currentDateTime() < remindTime) start = remindTime; } deferDlg.setLimit(start.addSecs(-60)); } if (deferDlg.exec() == TQDialog::Accepted) { mDeferDateTime = deferDlg.getDateTime(); mDeferTimeLabel->setText(mDeferDateTime.isValid() ? mDeferDateTime.formatLocale() : TQString()); } } /****************************************************************************** * Called when the main page is shown. * Sets the focus widget to the first edit field. */ void EditAlarmDlg::slotShowMainPage() { slotAlarmTypeChanged(-1); if (!mMainPageShown) { if (mTemplateName) mTemplateName->setFocus(); mMainPageShown = true; } if (mTimeWidget) { if (!mReadOnly && mRecurPageShown && mRecurrenceEdit->repeatType() == RecurrenceEdit::AT_LOGIN) mTimeWidget->setDateTime(mRecurrenceEdit->endDateTime()); if (mReadOnly || mRecurrenceEdit->isTimedRepeatType()) mTimeWidget->setMinDateTime(); // don't set a minimum date/time else mTimeWidget->setMinDateTimeIsCurrent(); // set the minimum date/time to track the clock } } /****************************************************************************** * Called when the recurrence edit page is shown. * The recurrence defaults are set to correspond to the start date. * The first time, for a new alarm, the recurrence end date is set according to * the alarm start time. */ void EditAlarmDlg::slotShowRecurrenceEdit() { mRecurPageIndex = mTabs->currentPageIndex(); if (!mReadOnly && !mTemplate) { TQDateTime now = TQDateTime::currentDateTime(); mAlarmDateTime = mTimeWidget->getDateTime(0, false, false); bool expired = (mAlarmDateTime.dateTime() < now); if (mRecurSetDefaultEndDate) { mRecurrenceEdit->setDefaultEndDate(expired ? now.date() : mAlarmDateTime.date()); mRecurSetDefaultEndDate = false; } mRecurrenceEdit->setStartDate(mAlarmDateTime.date(), now.date()); if (mRecurrenceEdit->repeatType() == RecurrenceEdit::AT_LOGIN) mRecurrenceEdit->setEndDateTime(expired ? now : mAlarmDateTime); } mRecurPageShown = true; } /****************************************************************************** * Called when the recurrence type selection changes. * Enables/disables date-only alarms as appropriate. * Enables/disables controls depending on at-login setting. */ void EditAlarmDlg::slotRecurTypeChange(int repeatType) { bool atLogin = (mRecurrenceEdit->repeatType() == RecurrenceEdit::AT_LOGIN); if (!mTemplate) { bool recurs = (mRecurrenceEdit->repeatType() != RecurrenceEdit::NO_RECUR); if (mDeferGroup) mDeferGroup->setEnabled(recurs); mTimeWidget->enableAnyTime(!recurs || repeatType != RecurrenceEdit::SUBDAILY); if (atLogin) { mAlarmDateTime = mTimeWidget->getDateTime(0, false, false); mRecurrenceEdit->setEndDateTime(mAlarmDateTime.dateTime()); } mReminder->enableOnceOnly(recurs && !atLogin); } mReminder->setEnabled(!atLogin); mLateCancel->setEnabled(!atLogin); if (mShowInKorganizer) mShowInKorganizer->setEnabled(!atLogin); slotRecurFrequencyChange(); } /****************************************************************************** * Called when the recurrence frequency selection changes, or the sub- * repetition interval changes. * Updates the recurrence frequency text. */ void EditAlarmDlg::slotRecurFrequencyChange() { slotSetSubRepetition(); KAEvent event; mRecurrenceEdit->updateEvent(event, false); mTabs->setTabLabel(mTabs->page(mRecurPageIndex), recurText(event)); } /****************************************************************************** * Called when the Repetition within Recurrence button has been pressed to * display the sub-repetition dialog. * Alarm repetition has the following restrictions: * 1) Not allowed for a repeat-at-login alarm * 2) For a date-only alarm, the repeat interval must be a whole number of days. * 3) The overall repeat duration must be less than the recurrence interval. */ void EditAlarmDlg::slotSetSubRepetition() { bool dateOnly = mTemplate ? mTemplateAnyTime->isOn() : mTimeWidget->anyTime(); mRecurrenceEdit->setSubRepetition(mReminder->minutes(), dateOnly); } /****************************************************************************** * Validate and convert command alarm data. */ bool EditAlarmDlg::checkCommandData() { if (mCommandRadio->isOn() && mCmdOutputGroup->selectedId() == LOG_TO_FILE) { // Validate the log file name TQString file = mCmdLogFileEdit->text(); TQFileInfo info(file); TQDir::setCurrent(TQDir::homeDirPath()); bool err = file.isEmpty() || info.isDir(); if (!err) { if (info.exists()) { err = !info.isWritable(); } else { TQFileInfo dirinfo(info.dirPath(true)); // get absolute directory path err = (!dirinfo.isDir() || !dirinfo.isWritable()); } } if (err) { mTabs->setCurrentPage(mMainPageIndex); mCmdLogFileEdit->setFocus(); KMessageBox::sorry(this, i18n("Log file must be the name or path of a local file, with write permission.")); return false; } // Convert the log file to an absolute path mCmdLogFileEdit->setText(info.absFilePath()); } return true; } /****************************************************************************** * Convert the email addresses to a list, and validate them. Convert the email * attachments to a list. */ bool EditAlarmDlg::checkEmailData() { if (mEmailRadio->isOn()) { TQString addrs = mEmailToEdit->text(); if (addrs.isEmpty()) mEmailAddresses.clear(); else { TQString bad = KAMail::convertAddresses(addrs, mEmailAddresses); if (!bad.isEmpty()) { mEmailToEdit->setFocus(); KMessageBox::error(this, i18n("Invalid email address:\n%1").arg(bad)); return false; } } if (mEmailAddresses.isEmpty()) { mEmailToEdit->setFocus(); KMessageBox::error(this, i18n("No email address specified")); return false; } mEmailAttachments.clear(); for (int i = 0; i < mEmailAttachList->count(); ++i) { TQString att = mEmailAttachList->text(i); switch (KAMail::checkAttachment(att)) { case 1: mEmailAttachments.append(att); break; case 0: break; // empty case -1: mEmailAttachList->setFocus(); KMessageBox::error(this, i18n("Invalid email attachment:\n%1").arg(att)); return false; } } } return true; } /****************************************************************************** * Called when one of the alarm action type radio buttons is clicked, * to display the appropriate set of controls for that action type. */ void EditAlarmDlg::slotAlarmTypeChanged(int) { bool displayAlarm = false; TQWidget* focus = 0; if (mMessageRadio->isOn()) { mFileBox->hide(); mFilePadding->hide(); mTextMessageEdit->show(); mFontColourButton->show(); mBgColourBox->hide(); mSoundPicker->showSpeak(true); mDisplayAlarmsFrame->show(); mCommandFrame->hide(); mEmailFrame->hide(); mReminder->show(); mConfirmAck->show(); setButtonWhatsThis(Try, i18n("Display the alarm message now")); focus = mTextMessageEdit; displayAlarm = true; } else if (mFileRadio->isOn()) { mTextMessageEdit->hide(); mFileBox->show(); mFilePadding->show(); mFontColourButton->hide(); mBgColourBox->show(); mSoundPicker->showSpeak(false); mDisplayAlarmsFrame->show(); mCommandFrame->hide(); mEmailFrame->hide(); mReminder->show(); mConfirmAck->show(); setButtonWhatsThis(Try, i18n("Display the file now")); mFileMessageEdit->setNoSelect(); focus = mFileMessageEdit; displayAlarm = true; } else if (mCommandRadio->isOn()) { mDisplayAlarmsFrame->hide(); mCommandFrame->show(); mEmailFrame->hide(); mReminder->hide(); mConfirmAck->hide(); setButtonWhatsThis(Try, i18n("Execute the specified command now")); mCmdCommandEdit->setNoSelect(); focus = mCmdCommandEdit; } else if (mEmailRadio->isOn()) { mDisplayAlarmsFrame->hide(); mCommandFrame->hide(); mEmailFrame->show(); mReminder->hide(); mConfirmAck->hide(); setButtonWhatsThis(Try, i18n("Send the email to the specified addressees now")); mEmailToEdit->setNoSelect(); focus = mEmailToEdit; } mLateCancel->showAutoClose(displayAlarm); mLateCancel->setFixedSize(mLateCancel->sizeHint()); if (focus) focus->setFocus(); } /****************************************************************************** * Called when one of the command type radio buttons is clicked, * to display the appropriate edit field. */ void EditAlarmDlg::slotCmdScriptToggled(bool on) { if (on) { mCmdCommandEdit->hide(); mCmdPadding->hide(); mCmdScriptEdit->show(); mCmdScriptEdit->setFocus(); } else { mCmdScriptEdit->hide(); mCmdCommandEdit->show(); mCmdPadding->show(); mCmdCommandEdit->setFocus(); } } /****************************************************************************** * Called when one of the template time radio buttons is clicked, * to enable or disable the template time entry spin boxes. */ void EditAlarmDlg::slotTemplateTimeType(int) { mTemplateTime->setEnabled(mTemplateUseTime->isOn()); mTemplateTimeAfter->setEnabled(mTemplateUseTimeAfter->isOn()); } /****************************************************************************** * Called when the "Any time" checkbox is toggled in the date/time widget. * Sets the advance reminder and late cancel units to days if any time is checked. */ void EditAlarmDlg::slotAnyTimeToggled(bool anyTime) { if (mReminder->isReminder()) mReminder->setDateOnly(anyTime); mLateCancel->setDateOnly(anyTime); } /****************************************************************************** * Get a selection from the Address Book. */ void EditAlarmDlg::openAddressBook() { TDEABC::Addressee a = TDEABC::AddresseeDialog::getAddressee(this); if (a.isEmpty()) return; Person person(a.realName(), a.preferredEmail()); TQString addrs = mEmailToEdit->text().stripWhiteSpace(); if (!addrs.isEmpty()) addrs += ", "; addrs += person.fullName(); mEmailToEdit->setText(addrs); } /****************************************************************************** * Select a file to attach to the email. */ void EditAlarmDlg::slotAddAttachment() { TQString url = KAlarm::browseFile(i18n("Choose File to Attach"), mAttachDefaultDir, TQString(), TQString(), KFile::ExistingOnly, this, "pickAttachFile"); if (!url.isEmpty()) { mEmailAttachList->insertItem(url); mEmailAttachList->setCurrentItem(mEmailAttachList->count() - 1); // select the new item mEmailRemoveButton->setEnabled(true); mEmailAttachList->setEnabled(true); } } /****************************************************************************** * Remove the currently selected attachment from the email. */ void EditAlarmDlg::slotRemoveAttachment() { int item = mEmailAttachList->currentItem(); mEmailAttachList->removeItem(item); int count = mEmailAttachList->count(); if (item >= count) mEmailAttachList->setCurrentItem(count - 1); if (!count) { mEmailRemoveButton->setEnabled(false); mEmailAttachList->setEnabled(false); } } /****************************************************************************** * Clean up the alarm text, and if it's a file, check whether it's valid. */ bool EditAlarmDlg::checkText(TQString& result, bool showErrorMessage) const { if (mMessageRadio->isOn()) result = mTextMessageEdit->text(); else if (mEmailRadio->isOn()) result = mEmailMessageEdit->text(); else if (mCommandRadio->isOn()) { if (mCmdTypeScript->isChecked()) result = mCmdScriptEdit->text(); else result = mCmdCommandEdit->text(); result = result.stripWhiteSpace(); } else if (mFileRadio->isOn()) { TQString alarmtext = mFileMessageEdit->text().stripWhiteSpace(); // Convert any relative file path to absolute // (using home directory as the default) enum Err { NONE = 0, BLANK, NONEXISTENT, DIRECTORY, UNREADABLE, NOT_TEXT_IMAGE }; Err err = NONE; KURL url; int i = alarmtext.find(TQString::fromLatin1("/")); if (i > 0 && alarmtext[i - 1] == ':') { url = alarmtext; url.cleanPath(); alarmtext = url.prettyURL(); TDEIO::UDSEntry uds; if (!TDEIO::NetAccess::stat(url, uds, MainWindow::mainMainWindow())) err = NONEXISTENT; else { KFileItem fi(uds, url); if (fi.isDir()) err = DIRECTORY; else if (!fi.isReadable()) err = UNREADABLE; } } else if (alarmtext.isEmpty()) err = BLANK; // blank file name else { // It's a local file - convert to absolute path & check validity TQFileInfo info(alarmtext); TQDir::setCurrent(TQDir::homeDirPath()); alarmtext = info.absFilePath(); url.setPath(alarmtext); alarmtext = TQString::fromLatin1("file:") + alarmtext; if (!err) { if (info.isDir()) err = DIRECTORY; else if (!info.exists()) err = NONEXISTENT; else if (!info.isReadable()) err = UNREADABLE; } } if (!err) { switch (KAlarm::fileType(KFileItem(KFileItem::Unknown, KFileItem::Unknown, url).mimetype())) { case KAlarm::TextFormatted: case KAlarm::TextPlain: case KAlarm::TextApplication: case KAlarm::Image: break; default: err = NOT_TEXT_IMAGE; break; } } if (err && showErrorMessage) { mFileMessageEdit->setFocus(); TQString errmsg; switch (err) { case BLANK: KMessageBox::sorry(const_cast(this), i18n("Please select a file to display")); return false; case NONEXISTENT: errmsg = i18n("%1\nnot found"); break; case DIRECTORY: errmsg = i18n("%1\nis a folder"); break; case UNREADABLE: errmsg = i18n("%1\nis not readable"); break; case NOT_TEXT_IMAGE: errmsg = i18n("%1\nappears not to be a text or image file"); break; case NONE: default: break; } if (KMessageBox::warningContinueCancel(const_cast(this), errmsg.arg(alarmtext)) == KMessageBox::Cancel) return false; } result = alarmtext; } return true; } /*============================================================================= = Class TextEdit = A text edit field with a minimum height of 3 text lines. = Provides KDE 2 compatibility. =============================================================================*/ TextEdit::TextEdit(TQWidget* parent, const char* name) : KTextEdit(parent, name) { TQSize tsize = sizeHint(); tsize.setHeight(fontMetrics().lineSpacing()*13/4 + 2*frameWidth()); setMinimumSize(tsize); } void TextEdit::dragEnterEvent(TQDragEnterEvent* e) { if (KCal::ICalDrag::canDecode(e)) e->accept(false); // don't accept "text/calendar" objects KTextEdit::dragEnterEvent(e); }