Commit bc5f5b8a authored by David Jarvie's avatar David Jarvie

Add option for reminder after the main alarm

Add new option for a reminder AFTER the main alarm, as an alternative
to a reminder before it.
parent 313f5df7
KAlarm Change Log
=== Version 2.7.1 --- 18 April 2011 ===
- Add option to set a reminder AFTER the main alarm.
=== Version 2.6.3 --- 27 April 2011 ===
- Add option to not notify execution errors for pre-alarm actions.
- Set environment variable KALARM_UID to event UID for pre- & post-alarm actions.
......
This diff is collapsed.
/*
* kaeventformatter.cpp - converts KAEvent properties to text
* Program: kalarm
* Copyright © 2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2010,2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -224,7 +224,7 @@ QString KAEventFormatter::value(Parameter param) const
case Recurs: return trueFalse(mEvent.recurs());
case Recurrence:
{
if (mEvent.repeatAtLogin())
if (mEvent.repeatAtLogin(true))
return i18nc("@info/plain Repeat at login", "At login until %1", dateTime(mEvent.mainDateTime().kDateTime()));
KCalCore::Event::Ptr eptr(new KCalCore::Event);
mEvent.updateKCalEvent(eptr, KAEvent::UID_SET);
......@@ -241,17 +241,7 @@ QString KAEventFormatter::value(Parameter param) const
case AutoClose: return trueFalse(mEvent.lateCancel() ? mEvent.autoClose() : false);
case CopyKOrganizer: return trueFalse(mEvent.copyToKOrganizer());
case Enabled: return trueFalse(mEvent.enabled());
case Archive:
{
if (!mEvent.toBeArchived())
return trueFalse(false);
KCalCore::Event::Ptr eptr(new KCalCore::Event);
mEvent.updateKCalEvent(eptr, KAEvent::UID_SET);
QString prop;
if (!KAEvent::archivePropertyValue(eptr, prop))
return trueFalse(true);
return prop;
}
case Archive: return trueFalse(mEvent.toBeArchived());
case Revision: return number(mEvent.revision());
case MessageText: return (mEvent.action() == KAEvent::MESSAGE) ? mEvent.cleanText() : QString();
......
......@@ -1594,7 +1594,11 @@ void AkonadiModel::slotRowsAboutToBeRemoved(const QModelIndex& parent, int start
kDebug() << start << "-" << end << "(parent =" << parent << ")";
EventList events = eventList(parent, start, end);
if (!events.isEmpty())
{
foreach (const Event& event, events)
kDebug() << "Collection:" << event.collection.id() << ", Event ID:" << event.event.id();
emit eventsToBeRemoved(events);
}
}
/******************************************************************************
......
/*
* birthdaydlg.cpp - dialog to pick birthdays from address book
* Program: kalarm
* Copyright © 2002-2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2002-2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -180,9 +180,10 @@ BirthdayDlg::BirthdayDlg(QWidget* parent)
connect(mFontColourButton, SIGNAL(selected(const QColor&, const QColor&)), SLOT(setColours(const QColor&, const QColor&)));
// How much advance warning to give
mReminder = new Reminder(i18nc("@info:whatsthis", "Check to display a reminder in advance of the birthday."),
i18nc("@info:whatsthis", "Enter the number of days before each birthday to display a reminder. "
mReminder = new Reminder(i18nc("@info:whatsthis", "Check to display a reminder in advance of or after the birthday."),
i18nc("@info:whatsthis", "Enter the number of days before or after each birthday to display a reminder. "
"This is in addition to the alarm which is displayed on the birthday."),
i18nc("@info:whatsthis", "Select whether the reminder should be triggered before or after the birthday."),
false, false, group);
mReminder->setFixedSize(mReminder->sizeHint());
mReminder->setMaximum(0, 364);
......
This diff is collapsed.
......@@ -89,7 +89,6 @@ class KALARM_CAL_EXPORT KAAlarmEventBase
public:
~KAAlarmEventBase() { }
int lateCancel() const { return mLateCancel; }
bool repeatAtLogin() const { return mRepeatAtLogin; }
protected:
enum Type { T_MESSAGE, T_FILE, T_COMMAND, T_EMAIL, T_AUDIO };
......@@ -164,6 +163,7 @@ class KALARM_CAL_EXPORT KAAlarm : public KAAlarmEventBase
{
INVALID__ALARM = INVALID_ALARM,
MAIN__ALARM = MAIN_ALARM,
AT_LOGIN__ALARM = AT_LOGIN_ALARM,
// The following values may be used in combination as a bitmask 0x0E
REMINDER__ALARM = REMINDER_ALARM,
TIMED_DEFERRAL_FLAG = 0x08, // deferral has a time; if clear, it is date-only
......@@ -173,7 +173,6 @@ class KALARM_CAL_EXPORT KAAlarm : public KAAlarmEventBase
DEFERRED_REMINDER_TIME__ALARM = REMINDER_ALARM | DEFERRED_ALARM | TIMED_DEFERRAL_FLAG, // deferred early warning (date/time)
// The following values must be greater than the preceding ones, to
// ensure that in ordered processing they are processed afterwards.
AT_LOGIN__ALARM = AT_LOGIN_ALARM,
DISPLAYING__ALARM = DISPLAYING_ALARM,
// The following values are for internal KAEvent use only
AUDIO__ALARM = AUDIO_ALARM, // audio alarm for main display alarm
......@@ -194,6 +193,7 @@ class KALARM_CAL_EXPORT KAAlarm : public KAAlarmEventBase
? mRepetition.duration(mNextRepeat).end(mNextMainDateTime.kDateTime()) : mNextMainDateTime; }
QDate date() const { return mNextMainDateTime.date(); }
QTime time() const { return mNextMainDateTime.effectiveTime(); }
bool repeatAtLogin() const { return mRepeatAtLogin; }
bool isReminder() const { return mType == REMINDER__ALARM; }
bool deferred() const { return mDeferred; }
void setTime(const DateTime& dt) { mNextMainDateTime = dt; }
......@@ -238,6 +238,7 @@ class KALARM_CAL_EXPORT KAEvent
EXCL_HOLIDAYS = 0x4000, // don't trigger alarm on holidays
WORK_TIME_ONLY = 0x8000, // trigger alarm only during working hours
DISPLAY_COMMAND = 0x10000, // display command output in alarm window
REMINDER_ONCE = 0x20000, // only trigger reminder on first recurrence
// The following are read-only internal values
REMINDER = 0x100000,
DEFERRAL = 0x200000,
......@@ -357,6 +358,7 @@ class KALARM_CAL_EXPORT KAEvent
void setKMailSerialNumber(unsigned long n) { d->mKMailSerialNumber = n; }
void setLogFile(const QString& logfile);
void setReminder(int minutes, bool onceOnly) { d->setReminder(minutes, onceOnly); }
void activateReminderAfter(const DateTime& mainAlarmTime) { d->activateReminderAfter(mainAlarmTime); }
bool defer(const DateTime& dt, bool reminder, bool adjustRecurrence = false)
{ return d->defer(dt, reminder, adjustRecurrence); }
void cancelDefer() { d->cancelDefer(); }
......@@ -412,7 +414,7 @@ class KALARM_CAL_EXPORT KAEvent
bool autoClose() const { return d->mAutoClose; }
bool commandScript() const { return d->mCommandScript; }
bool confirmAck() const { return d->mConfirmAck; }
bool repeatAtLogin() const { return d->repeatAtLogin(); }
bool repeatAtLogin(bool includeArchived = false) const { return d->mRepeatAtLogin || (includeArchived && d->mArchiveRepeatAtLogin); }
const Repetition& repetition() const { return d->mRepetition; }
int nextRepetition() const { return d->mNextRepeat; }
bool beep() const { return d->mBeep; }
......@@ -453,7 +455,8 @@ class KALARM_CAL_EXPORT KAEvent
QTime mainTime() const { return d->mNextMainDateTime.effectiveTime(); }
DateTime mainEndRepeatTime() const { return d->mainEndRepeatTime(); }
DateTime nextTrigger(TriggerType) const;
int reminderMinutes(bool active = false) const { return (!active || d->mReminderActive) ? d->mReminderMinutes : 0; }
int reminderMinutes() const { return d->mReminderMinutes; }
bool reminderActive() const { return d->mReminderActive == Private::ACTIVE_REMINDER; }
bool reminderOnceOnly() const { return d->mReminderOnceOnly; }
bool reminderDeferral() const { return d->mDeferral == Private::REMINDER_DEFERRAL; }
DateTime deferDateTime() const { return d->mDeferralTime; }
......@@ -546,7 +549,6 @@ class KALARM_CAL_EXPORT KAEvent
static bool convertKCalEvents(const KCalCore::Calendar::Ptr&, int calendarVersion, bool adjustSummerTime);
// static bool convertRepetitions(KCalCore::MemoryCalendar&);
static List ptrList(QList<KAEvent>&);
static bool archivePropertyValue(const KCalCore::ConstEventPtr&, QString& value);
#else
static bool convertKCalEvents(KCal::CalendarLocal&, int calendarVersion, bool adjustSummerTime);
// static bool convertRepetitions(KCal::CalendarLocal&);
......@@ -576,10 +578,16 @@ class KALARM_CAL_EXPORT KAEvent
class Private : public KAAlarmEventBase, public QSharedData
{
public:
enum ReminderType // current active state of reminder
{
NO_REMINDER, // reminder is not due
ACTIVE_REMINDER, // reminder is due
HIDDEN_REMINDER // reminder-after is disabled due to main alarm being deferred past it
};
enum DeferType {
NO_DEFERRAL = 0, // there is no deferred alarm
NORMAL_DEFERRAL, // the main alarm, a recurrence or a repeat is deferred
REMINDER_DEFERRAL // a reminder alarm is deferred
NO_DEFERRAL = 0, // there is no deferred alarm
NORMAL_DEFERRAL, // the main alarm, a recurrence or a repeat is deferred
REMINDER_DEFERRAL // a reminder alarm is deferred
};
Private();
......@@ -605,6 +613,7 @@ class KALARM_CAL_EXPORT KAEvent
void setCategory(KAlarm::CalEvent::Type);
void setRepeatAtLogin(bool);
void setReminder(int minutes, bool onceOnly);
void activateReminderAfter(const DateTime& mainAlarmTime);
bool defer(const DateTime&, bool reminder, bool adjustRecurrence = false);
void cancelDefer();
#ifdef USE_AKONADI
......@@ -710,8 +719,9 @@ class KALARM_CAL_EXPORT KAEvent
DateTime mDeferralTime; // extra time to trigger alarm (if alarm or reminder deferred)
DateTime mDisplayingTime; // date/time shown in the alarm currently being displayed
int mDisplayingFlags; // type of alarm which is currently being displayed
int mReminderMinutes; // how long in advance reminder is to be, or 0 if none
bool mReminderActive; // reminder will be due for next main alarm/recurrence
int mReminderMinutes; // how long in advance reminder is to be, or 0 if none (<0 for reminder AFTER the alarm)
DateTime mReminderAfterTime; // if mReminderActive true, time to trigger reminder AFTER the main alarm, or invalid if not pending
ReminderType mReminderActive; // whether a reminder is due (before next, or after last, main alarm/recurrence)
int mDeferDefaultMinutes; // default number of minutes for deferral dialog, or 0 to select time control
bool mDeferDefaultDateOnly;// select date-only by default in deferral dialog
int mRevision; // SEQUENCE: revision number of the original alarm, or 0
......@@ -765,15 +775,15 @@ class KALARM_CAL_EXPORT KAEvent
static const QString KORGANIZER_FLAG;
static const QString EXCLUDE_HOLIDAYS_FLAG;
static const QString WORK_TIME_ONLY_FLAG;
static const QString REMINDER_ONCE_FLAG;
static const QString DEFER_FLAG;
static const QString LATE_CANCEL_FLAG;
static const QString AUTO_CLOSE_FLAG;
static const QString TEMPL_AFTER_TIME_FLAG;
static const QString KMAIL_SERNUM_FLAG;
static const QString ARCHIVE_FLAG;
static const QByteArray NEXT_RECUR_PROPERTY;
static const QByteArray REPEAT_PROPERTY;
static const QByteArray ARCHIVE_PROPERTY;
static const QString ARCHIVE_REMINDER_ONCE_TYPE;
static const QByteArray LOG_PROPERTY;
static const QString xtermURL;
static const QString displayURL;
......@@ -789,6 +799,7 @@ class KALARM_CAL_EXPORT KAEvent
static const QString POST_ACTION_TYPE;
static const QString SOUND_REPEAT_TYPE;
static const QByteArray NEXT_REPEAT_PROPERTY;
static const QByteArray HIDDEN_REMINDER_FLAG;
static const QByteArray FONT_COLOUR_PROPERTY;
static const QByteArray EMAIL_ID_PROPERTY;
static const QByteArray VOLUME_PROPERTY;
......
/*
* commandoptions.cpp - extract command line options
* Program: kalarm
* Copyright © 2001-2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -304,8 +304,7 @@ CommandOptions::CommandOptions()
// Get the recurrence interval
int interval;
KARecurrence::Type recurType;
if (!convInterval(mArgs->getOption("interval").toLocal8Bit(), recurType, interval, !haveRecurrence)
|| interval < 0)
if (!convInterval(mArgs->getOption("interval").toLocal8Bit(), recurType, interval, !haveRecurrence))
setErrorParameter("--interval");
else if (mAlarmTime.isDateOnly() && recurType == KARecurrence::MINUTELY)
setError(i18nc("@info:shell", "Invalid <icode>%1</icode> parameter for date-only alarm", QLatin1String("--interval")));
......@@ -372,25 +371,30 @@ CommandOptions::CommandOptions()
bool onceOnly = mArgs->isSet("reminder-once");
if (mArgs->isSet("reminder") || onceOnly)
{
// Issue a reminder alarm in advance of the main alarm
// Issue a reminder alarm in advance of or after the main alarm
if (onceOnly && mArgs->isSet("reminder"))
setErrorIncompatible("--reminder", "--reminder-once");
const char* opt = onceOnly ? "--reminder-once" : "--reminder";
KARecurrence::Type recurType;
QString optval = mArgs->getOption(onceOnly ? "reminder-once" : "reminder");
if (!convInterval(mArgs->getOption(onceOnly ? "reminder-once" : "reminder").toLocal8Bit(), recurType, mReminderMinutes))
QByteArray optval = mArgs->getOption(onceOnly ? "reminder-once" : "reminder").toLocal8Bit();
bool after = (optval[0] == '+');
if (after)
optval = optval.right(1);
if (!convInterval(optval, recurType, mReminderMinutes))
setErrorParameter(opt);
else if (recurType == KARecurrence::MINUTELY && mAlarmTime.isDateOnly())
setError(i18nc("@info:shell", "Invalid <icode>%1</icode> parameter for date-only alarm", QLatin1String(opt)));
if (onceOnly)
if (after)
mReminderMinutes = -mReminderMinutes;
if (onceOnly)
mFlags |= KAEvent::REMINDER_ONCE;
}
if (mArgs->isSet("late-cancel"))
{
KARecurrence::Type recurType;
bool ok = convInterval(mArgs->getOption("late-cancel").toLocal8Bit(), recurType, mLateCancel);
if (!ok || mLateCancel <= 0)
if (!ok)
setErrorParameter("--late-cancel");
}
else if (mArgs->isSet("auto-close"))
......@@ -542,7 +546,7 @@ void CommandOptions::checkEditType(EditAlarmDlg::Type type1, EditAlarmDlg::Type
}
/******************************************************************************
* Convert a time interval command line parameter.
* Convert a non-zero positive time interval command line parameter.
* 'timeInterval' receives the count for the recurType. If 'allowMonthYear' is
* false, weeks are converted to days in 'timeInterval'.
* Reply = true if successful.
......@@ -553,9 +557,6 @@ static bool convInterval(const QByteArray& timeParam, KARecurrence::Type& recurT
// Get the recurrence interval
bool ok = true;
uint interval = 0;
bool negative = (timeString[0] == '-');
if (negative)
timeString = timeString.right(1);
uint length = timeString.length();
switch (timeString[length - 1])
{
......@@ -613,9 +614,7 @@ static bool convInterval(const QByteArray& timeParam, KARecurrence::Type& recurT
}
}
timeInterval = static_cast<int>(interval);
if (negative)
timeInterval = -timeInterval;
return ok;
return ok && interval;
}
// vim: et sw=4:
/*
* commandoptions.h - extract command line options
* Program: kalarm
* Copyright © 2001-2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -100,7 +100,7 @@ class CommandOptions
int mLateCancel; // NEW: late-cancellation interval
QColor mBgColour; // NEW: background colour
QColor mFgColour; // NEW: foreground colour
int mReminderMinutes;// NEW: reminder period, < 0 if once only reminder
int mReminderMinutes;// NEW: reminder period
QString mAudioFile; // NEW: audio file path
float mAudioVolume; // NEW: audio file volume
EmailAddressList mAddressees; // NEW: email addressees
......
......@@ -988,7 +988,7 @@ bool EditAlarmDlg::validate()
KAEvent event;
setEvent(event, mAlarmMessage, false);
mAlarmDateTime = dt; // restore
KDateTime pre = dt.effectiveKDateTime();
KDateTime pre = dt.effectiveKDateTime();
bool dateOnly = dt.isDateOnly();
if (dateOnly)
pre = pre.addDays(-1);
......@@ -1397,7 +1397,7 @@ void EditAlarmDlg::slotRecurTypeChange(int repeatType)
mReminder->enableOnceOnly(recurs && !atLogin);
}
if (mReminder)
mReminder->setEnabled(!atLogin);
mReminder->setAfterOnly(atLogin);
mLateCancel->setEnabled(!atLogin);
if (mShowInKorganizer)
mShowInKorganizer->setEnabled(!atLogin);
......
/*
* editdlgtypes.cpp - dialogs to create or edit alarm or alarm template types
* Program: kalarm
* Copyright © 2001-2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -241,9 +241,10 @@ void EditDisplayAlarmDlg::type_init(QWidget* parent, QVBoxLayout* frameLayout)
*/
Reminder* EditDisplayAlarmDlg::createReminder(QWidget* parent)
{
static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of the main alarm to display a reminder alarm.");
return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of the main alarm time(s)."),
i18nc("@info:whatsthis", "<para>Enter how long in advance of the main alarm to display a reminder alarm.</para><para>%1</para>", TimeSpinBox::shiftWhatsThis()),
static const QString reminderText = i18nc("@info:whatsthis", "Enter how long in advance of or after the main alarm to display a reminder alarm.");
return new Reminder(i18nc("@info:whatsthis", "Check to additionally display a reminder in advance of or after the main alarm time(s)."),
i18nc("@info:whatsthis", "<para>Enter how long in advance of or after the main alarm to display a reminder alarm.</para><para>%1</para>", TimeSpinBox::shiftWhatsThis()),
i18nc("@info:whatsthis", "Select whether the reminder should be triggered before or after the main alarm"),
true, true, parent);
}
......@@ -279,7 +280,9 @@ void EditDisplayAlarmDlg::type_initValues(const KAEvent* event)
setColours(event->fgColour(), event->bgColour());
mConfirmAck->setChecked(event->confirmAck());
bool recurs = event->recurs();
int reminderMins = event->reminderMinutes(true);
int reminderMins = event->reminderMinutes();
if (reminderMins > 0 && !event->reminderActive())
reminderMins = 0; // don't show advance reminder which has already passed
if (!reminderMins)
{
if (event->reminderDeferral() && !recurs)
......@@ -419,11 +422,8 @@ void EditDisplayAlarmDlg::setAudio(Preferences::SoundType type, const QString& f
{
mSoundPicker->set(type, file, volume, -1, 0, repeat);
}
void EditDisplayAlarmDlg::setReminder(int minutes)
void EditDisplayAlarmDlg::setReminder(int minutes, bool onceOnly)
{
bool onceOnly = (minutes < 0);
if (onceOnly)
minutes = -minutes;
reminder()->setMinutes(minutes, dateOnly());
reminder()->setOnceOnly(onceOnly);
reminder()->enableOnceOnly(isTimedRecurrence());
......
/*
* editdlgtypes.h - dialogues to create or edit alarm or alarm template types
* Program: kalarm
* Copyright © 2001-2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -65,7 +65,7 @@ class EditDisplayAlarmDlg : public EditAlarmDlg
void setConfirmAck(bool);
void setAutoClose(bool);
void setAudio(Preferences::SoundType, const QString& file = QString(), float volume = -1, bool repeat = false);
void setReminder(int minutes); // minutes < 0 for once only option
void setReminder(int minutes, bool onceOnly);
virtual Reminder* createReminder(QWidget* parent);
static CheckBox* createConfirmAckCheckbox(QWidget* parent);
......
......@@ -30,7 +30,7 @@
#define KALARM_VERSION "2.6.90" VERSION_SUFFIX
#else
#define VERSION_SUFFIX "-R"
#define KALARM_VERSION "2.6.3"
#define KALARM_VERSION "2.7.0"
#endif
//#define KALARM_VERSION "2.6.90" VERSION_SUFFIX
#define KALARM_NAME "KAlarm"
......
......@@ -380,7 +380,7 @@ int KAlarmApp::newInstance()
dlg->setAudio(type, options.audioFile(), options.audioVolume(), flags & KAEvent::REPEAT_SOUND);
}
if (options.reminderMinutes())
dlg->setReminder(options.reminderMinutes());
dlg->setReminder(options.reminderMinutes(), (options.flags() & KAEvent::REMINDER_ONCE));
if (options.flags() & KAEvent::CONFIRM_ACK)
dlg->setConfirmAck(true);
if (options.flags() & KAEvent::AUTO_CLOSE)
......@@ -759,12 +759,21 @@ void KAlarmApp::processQueue()
// Refresh alarms if that's been queued
KAlarm::refreshAlarmsIfQueued();
if (!mLoginAlarmsDone && mAlarmsEnabled)
if (!mLoginAlarmsDone)
{
// Queue all at-login alarms once only, at program start-up
// Queue all at-login alarms once only, at program start-up.
// First, cancel any scheduled reminders or deferrals for them,
// since these will be superseded by the new at-login trigger.
KAEvent::List events = AlarmCalendar::resources()->atLoginAlarms();
for (int i = 0, end = events.count(); i < end; ++i)
queueAlarmId(events[i]->id());
{
KAEvent event = *events[i];
if (!cancelReminderAndDeferral(event))
{
if (mAlarmsEnabled)
queueAlarmId(event.id());
}
}
mLoginAlarmsDone = true;
}
......@@ -816,15 +825,21 @@ void KAlarmApp::processQueue()
#ifdef USE_AKONADI
/******************************************************************************
* Called when a repeat-at-login alarm has been added externally.
* Queues it for triggering.
* Queues the alarm for triggering.
* First, cancel any scheduled reminder or deferral for it, since these will be
* superseded by the new at-login trigger.
*/
void KAlarmApp::atLoginEventAdded(const KAEvent& event)
{
if (mAlarmsEnabled)
KAEvent ev = event;
if (!cancelReminderAndDeferral(ev))
{
mDcopQueue.enqueue(DcopQEntry(EVENT_HANDLE, event.id()));
if (mInitialised)
QTimer::singleShot(0, this, SLOT(processQueue()));
if (mAlarmsEnabled)
{
mDcopQueue.enqueue(DcopQEntry(EVENT_HANDLE, ev.id()));
if (mInitialised)
QTimer::singleShot(0, this, SLOT(processQueue()));
}
}
}
#endif
......@@ -1111,8 +1126,8 @@ bool KAlarmApp::scheduleEvent(KAEvent::Action action, const QString& text, const
KAEvent event(alarmTime, text, bg, fg, font, action, lateCancel, flags, true);
if (reminderMinutes)
{
bool onceOnly = (reminderMinutes < 0);
event.setReminder((onceOnly ? -reminderMinutes : reminderMinutes), onceOnly);
bool onceOnly = flags & KAEvent::REMINDER_ONCE;
event.setReminder(reminderMinutes, onceOnly);
}
if (!audioFile.isEmpty())
event.setAudioFile(audioFile, audioVolume, -1, 0);
......@@ -1165,6 +1180,7 @@ bool KAlarmApp::dbusHandleEvent(const QString& eventID, EventFunc function)
* c) Reschedule the event for its next repetition. If none remain, delete it.
* If the event is deleted, it is removed from the calendar file and from every
* main window instance.
* Reply = false if event ID not found.
*/
bool KAlarmApp::handleEvent(const QString& eventID, EventFunc function)
{
......@@ -1404,20 +1420,33 @@ void KAlarmApp::alarmCompleted(const KAEvent& event)
bool KAlarmApp::rescheduleAlarm(KAEvent& event, const KAAlarm& alarm, bool updateCalAndDisplay, const KDateTime& nextDt)
{
kDebug() << "Alarm type:" << alarm.type();
if (alarm.repeatAtLogin())
return false; // leave an alarm which repeats at every login until its main alarm triggers
bool reply = false;
bool update = false;
event.startChanges();
if (alarm.isReminder() || alarm.deferred())
if (alarm.repeatAtLogin())
{
// Leave an alarm which repeats at every login until its main alarm triggers
if (!event.reminderActive() && event.reminderMinutes() < 0)
{
// Executing an at-login alarm: first schedule the reminder
// which occurs AFTER the main alarm.
event.activateReminderAfter(KDateTime::currentUtcDateTime());
update = true;
}
}
else if (alarm.isReminder() || alarm.deferred())
{
// It's an advance warning alarm or an extra deferred alarm, so delete it
// It's a reminder alarm or an extra deferred alarm, so delete it
event.removeExpiredAlarm(alarm.type());
update = true;
}
else
{
// Reschedule the alarm for its next occurrence.
bool cancelled = false;
DateTime last = event.mainDateTime(false); // note this trigger time
if (last != event.mainDateTime(true))
last = DateTime(); // but ignore sub-repetition triggers
bool next = nextDt.isValid();
KDateTime next_dt = nextDt;
KDateTime now = KDateTime::currentUtcDateTime();
......@@ -1428,6 +1457,14 @@ bool KAlarmApp::rescheduleAlarm(KAEvent& event, const KAAlarm& alarm, bool updat
{
case KAEvent::NO_OCCURRENCE:
// All repetitions are finished, so cancel the event
if (event.reminderMinutes() < 0 && last.isValid()
&& alarm.type() != KAAlarm::AT_LOGIN_ALARM && !event.mainExpired())
{
// Set the reminder which is now due after the last main alarm trigger.
// Note that at-login reminders are scheduled in execAlarm().
event.activateReminderAfter(last);
updateCalAndDisplay = true;
}
if (cancelAlarm(event, alarm.type(), updateCalAndDisplay))
return false;
break;
......@@ -1446,6 +1483,8 @@ bool KAlarmApp::rescheduleAlarm(KAEvent& event, const KAAlarm& alarm, bool updat
// The first occurrence is still due?!?, so don't do anything
break;
}
if (cancelled)
break;
if (event.deferred())
{
// Just in case there's also a deferred alarm, ensure it's removed
......@@ -1467,7 +1506,15 @@ bool KAlarmApp::rescheduleAlarm(KAEvent& event, const KAAlarm& alarm, bool updat
next = !event.isWorkingTime(next_dt);
}
} while (next && next_dt <= now);
reply = next_dt.isValid() && (next_dt <= now);
reply = !cancelled && next_dt.isValid() && (next_dt <= now);
if (event.reminderMinutes() < 0 && last.isValid()
&& alarm.type() != KAAlarm::AT_LOGIN_ALARM)
{
// Set the reminder which is now due after the last main alarm trigger.
// Note that at-login reminders are scheduled in execAlarm().
event.activateReminderAfter(last);
}
}
event.endChanges();
if (update)
......@@ -1500,6 +1547,20 @@ bool KAlarmApp::cancelAlarm(KAEvent& event, KAAlarm::Type alarmType, bool update
return false;
}
/******************************************************************************
* Cancel any reminder or deferred alarms in an repeat-at-login event.
* This should be called when the event is first loaded.
* If there are no more alarms left in the event, the event is removed from the
* calendar file and from every main window instance.
* Reply = true if event has been deleted.
*/
bool KAlarmApp::cancelReminderAndDeferral(KAEvent& event)
{
return cancelAlarm(event, KAAlarm::REMINDER_ALARM, false)
|| cancelAlarm(event, KAAlarm::DEFERRED_REMINDER_ALARM, false)
|| cancelAlarm(event, KAAlarm::DEFERRED_ALARM, true);
}
/******************************************************************************
* Execute an alarm by displaying its message or file, or executing its command.
* Reply = ShellProcess instance if a command alarm
......
......@@ -175,6 +175,7 @@ class KAlarmApp : public KUniqueApplication
bool handleEvent(const QString& eventID, EventFunc);
bool rescheduleAlarm(KAEvent&, const KAAlarm&, bool updateCalAndDisplay, const KDateTime& nextDt = KDateTime());
bool cancelAlarm(KAEvent&, KAAlarm::Type, bool updateCalAndDisplay);
bool cancelReminderAndDeferral(KAEvent&);
ShellProcess* doShellCommand(const QString& command, const KAEvent&, const KAAlarm*, int flags = 0, const QObject* receiver = 0, const char* slot = 0);
QString composeXTermCommand(const QString& command, const KAEvent&, const KAAlarm*, int flags, QString& tempScriptFile) const;
QString createTempScriptFile(const QString& command, bool insertShell, const KAEvent&, const KAAlarm&) const;
......
/*
* latecancel.cpp - widget to specify cancellation if late
* Program: kalarm
* Copyright © 2004,2005,2007-2010 by David Jarvie <djarvie@kde.org>
* Copyright © 2004,2005,2007-2011 by David Jarvie <djarvie@kde.org>
*
* 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
......@@ -79,7 +79,7 @@ LateCancelSelector::LateCancelSelector(bool allowHourMinute, QWidget* parent)
mStack->addWidget(mTimeSelectorFrame);
hlayout = new QHBoxLayout(mTimeSelectorFrame);
hlayout->setMargin(0);
mTimeSelector = new TimeSelector(i18nc("@option:check Cancel if late by 10 minutes", "Cancel if late by"), QString(),