1 /* 2 * messagedisplayhelper.h - helper class to display an alarm or error message 3 * Program: kalarm 4 * SPDX-FileCopyrightText: 2001-2020 David Jarvie <djarvie@kde.org> 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #pragma once 10 11 #include "eventid.h" 12 #include "resources/resource.h" 13 #include "lib/file.h" 14 #include "lib/shellprocess.h" 15 16 #include <KAlarmCal/KAEvent> 17 18 #include <QObject> 19 #include <QHash> 20 #include <QPointer> 21 #include <QDateTime> 22 23 class KConfigGroup; 24 class QTemporaryFile; 25 class AudioThread; 26 class PushButton; 27 class EditAlarmDlg; 28 class MessageDisplay; 29 30 using namespace KAlarmCal; 31 32 /** 33 * Class for use by alarm message display classes, to handle common functions 34 * for displaying an alarm. 35 * In order for this class to use signals and slots, it needs to derive from 36 * QObject. As a result, it has to be a separate class from MessageDisplay; 37 * otherwise, MessageWindow would derive from two QObject classes, which is 38 * prohibited. 39 */ 40 class MessageDisplayHelper : public QObject 41 { 42 Q_OBJECT 43 public: 44 /** Contains the texts to display in the alarm. */ 45 struct DisplayTexts 46 { 47 /** Identifiers for the fields in DisplayTexts. */ 48 enum TextId 49 { 50 Title = 0x01, //!< DisplayTexts::title 51 Time = 0x02, //!< DisplayTexts::time 52 TimeFull = 0x04, //!< DisplayTexts::timeFull 53 FileName = 0x08, //!< DisplayTexts::fileName 54 Message = 0x10, //!< DisplayTexts::message 55 MessageAppend = 0x20, //!< Text has been appended to DisplayTexts::message 56 RemainingTime = 0x40 //!< DisplayTexts::remainingTime 57 }; 58 Q_DECLARE_FLAGS(TextIds, TextId) 59 60 QString title; // window/notification title 61 QString time; // header showing alarm trigger time 62 QString timeFull; // header showing alarm trigger time and "Reminder" if appropriate 63 QString fileName; // if message is a file's contents, the file name 64 QString message; // the alarm message 65 QString remainingTime; // if advance reminder, the remaining time until the actual alarm 66 QString errorEmail[4]; // if email alarm error message, the 'To' and 'Subject' contents 67 File::FileType fileType; // if message is a file's contents, the file type 68 bool newLine {false}; // 'message' has a newline stripped from the end 69 }; 70 71 explicit MessageDisplayHelper(MessageDisplay* parent); // for session management restoration only 72 MessageDisplayHelper(MessageDisplay* parent, const KAEvent&, const KAAlarm&, int flags); 73 MessageDisplayHelper(MessageDisplay* parent, const KAEvent&, const DateTime& alarmDateTime, 74 const QStringList& errmsgs, const QString& dontShowAgain); 75 MessageDisplayHelper(const MessageDisplayHelper&) = delete; 76 MessageDisplayHelper& operator=(const MessageDisplayHelper&) = delete; 77 ~MessageDisplayHelper() override; setParent(MessageDisplay * parent)78 void setParent(MessageDisplay* parent) { mParent = parent; } setSilenceButton(PushButton * b)79 void setSilenceButton(PushButton* b) { mSilenceButton = b; } 80 void repeat(const KAAlarm&); dateTime()81 const DateTime& dateTime() { return mDateTime; } alarmType()82 KAAlarm::Type alarmType() const { return mAlarmType; } 83 bool cancelReminder(const KAEvent&, const KAAlarm&); 84 bool updateDateTime(const KAEvent&, const KAAlarm&); isValid()85 bool isValid() const { return !mInvalid; } alwaysHidden()86 bool alwaysHidden() const { return mAlwaysHide; } 87 void initTexts(); texts()88 const DisplayTexts& texts() const { return mTexts; } 89 bool activateAutoClose(); 90 void displayComplete(bool audio); 91 bool alarmShowing(KAEvent&); 92 void playAudio(); 93 EditAlarmDlg* createEdit(); 94 void executeEdit(); 95 void setDeferralLimit(const KAEvent&); 96 97 /** Called when a close request has been received. 98 * @return true to close the alarm message, false to keep it open. 99 */ 100 bool closeEvent(); 101 102 bool saveProperties(KConfigGroup&); 103 bool readProperties(const KConfigGroup&); 104 bool readPropertyValues(const KConfigGroup&); 105 bool processPropertyValues(); 106 107 static int instanceCount(bool excludeAlwaysHidden = false); 108 static bool shouldShowError(const KAEvent& event, const QStringList& errmsgs, const QString& dontShowAgain = QString()); 109 static MessageDisplay* findEvent(const EventId& eventId, MessageDisplay* exclude = nullptr); 110 static void stopAudio(bool wait = false); 111 static bool isAudioPlaying(); 112 113 Q_SIGNALS: 114 /** Signal emitted when texts in the alarm message have changed. 115 * @param id Which text has changed. 116 * @param change If id == MessageAppend, the text which has been appended. 117 */ 118 void textsChanged(DisplayTexts::TextIds, const QString& change = QString()); 119 120 /** Signal emitted on completion of the command providing the alarm message text. */ 121 void commandExited(bool success); 122 123 /** Signal emitted when the alarm should close, after the auto-close time. */ 124 void autoCloseNow(); 125 126 private Q_SLOTS: 127 void showRestoredAlarm(); 128 void editCloseOk(); 129 void editCloseCancel(); 130 void checkDeferralLimit(); 131 void slotSpeak(); 132 void audioTerminating(); 133 void startAudio(); 134 void playReady(); 135 void playFinished(); slotSetRemainingTextDay()136 void slotSetRemainingTextDay() { setRemainingTextDay(true); } slotSetRemainingTextMinute()137 void slotSetRemainingTextMinute() { setRemainingTextMinute(true); } 138 void readProcessOutput(ShellProcess*); 139 void commandCompleted(ShellProcess::Status); 140 141 private: 142 QString dateTimeToDisplay() const; 143 void setRemainingTextDay(bool notify); 144 void setRemainingTextMinute(bool notify); 145 bool haveErrorMessage(unsigned msg) const; 146 void clearErrorMessage(unsigned msg) const; 147 void redisplayAlarm(); 148 149 static QVector<MessageDisplayHelper*> mInstanceList; // list of existing message displays 150 static QHash<EventId, unsigned> mErrorMessages; // error messages currently displayed, by event ID 151 // Sound file playing 152 static QPointer<AudioThread> mAudioThread; // thread to play audio file 153 154 public: 155 MessageDisplay* mParent; 156 // Properties needed by readProperties() 157 QString mMessage; 158 QFont mFont; 159 QColor mBgColour, mFgColour; 160 DateTime mDateTime; // date/time displayed in the message window 161 QDateTime mCloseTime; // UTC time at which window should be auto-closed 162 EventId mEventId; 163 QString mAudioFile; 164 float mVolume; 165 float mFadeVolume; 166 int mFadeSeconds; 167 int mDefaultDeferMinutes; 168 KAAlarm::Type mAlarmType; 169 KAEvent::SubAction mAction; 170 Akonadi::Item::Id mAkonadiItemId; // if email text, message's Akonadi Item ID, else -1 171 KAEvent::CmdErrType mCommandError; 172 QStringList mErrorMsgs; 173 QString mDontShowAgain; // non-null for don't-show-again option with error message 174 int mAudioRepeatPause; 175 bool mConfirmAck; 176 bool mShowEdit; // display the Edit button 177 bool mNoDefer; // don't display a Defer option 178 bool mInvalid; // restored window is invalid 179 // Miscellaneous 180 KAEvent mEvent; // the whole event, for updating the calendar file 181 KAEvent mOriginalEvent; // the original event supplied to the constructor 182 Resource mResource; // resource which the event comes/came from 183 PushButton* mSilenceButton {nullptr}; // button to stop audio, enabled when audio playing 184 EditAlarmDlg* mEditDlg {nullptr}; // alarm edit dialog invoked by Edit button 185 QDateTime mDeferLimit; // last UTC time to which the message can currently be deferred 186 bool mDisableDeferral {false}; // true if past deferral limit, so don't enable Defer button 187 bool mNoCloseConfirm {false}; // the Defer or Edit button is closing the dialog 188 bool mAlwaysHide {false}; // the window should never be displayed 189 bool mErrorWindow {false}; // the window is simply an error message 190 bool mNoPostAction; // don't execute any post-alarm action 191 bool mBeep; 192 bool mSpeak; // the message should be spoken via kttsd 193 private: 194 DisplayTexts mTexts; // texts to display in alarm message 195 QTemporaryFile* mTempFile {nullptr}; // temporary file used to display image/HTML 196 QByteArray mCommandOutput; // cumulative output from command 197 bool mCommandHaveStdout {false}; // true if some stdout has been received from command 198 bool mNoRecordCmdError {false}; // don't record command alarm errors 199 bool mInitialised {false}; // initTexts() has been called to create the alarm's texts 200 bool mRescheduleEvent {false}; // true to delete event after message has been displayed 201 202 //friend class MessageDisplay; 203 }; 204 205 Q_DECLARE_OPERATORS_FOR_FLAGS(MessageDisplayHelper::DisplayTexts::TextIds) 206 207 208 // vim: et sw=4: 209