47 #include "kspeechinterface.h"
49 #include <kalarmcal/datetime.h>
50 #include <kalarmcal/karecurrence.h>
53 #include <kstandarddirs.h>
55 #include <kaboutdata.h>
56 #include <ktemporaryfile.h>
57 #include <kfileitem.h>
59 #include <kstandardguiitem.h>
60 #include <kservicetypetrader.h>
62 #include <ktoolinvocation.h>
66 #include <ksystemtrayicon.h>
67 #include <ksystemtimezone.h>
72 #include <QTextStream>
73 #include <QtDBus/QtDBus>
84 static const int AKONADI_TIMEOUT = 30;
97 static const int LATENESS_LEEWAY = 5;
98 int lc = (lateCancel >= 1) ? (lateCancel - 1)*60 : 0;
99 return LATENESS_LEEWAY + lc;
104 int KAlarmApp::mActiveCount = 0;
105 int KAlarmApp::mFatalError = 0;
106 QString KAlarmApp::mFatalMessage;
115 mRedisplayAlarms(false),
118 mLoginAlarmsDone(false),
122 mArchivedPurgeDays(-1),
123 mPurgeDaysQueued(-1),
126 mCancelRtcWake(false),
127 mProcessingQueue(false),
128 mSessionClosingDown(false),
129 mAlarmsEnabled(true),
130 mSpeechEnabled(false)
132 KGlobal::locale()->insertCatalog(
QLatin1String(
"libkdepim"));
133 KGlobal::locale()->insertCatalog(
QLatin1String(
"libkpimutils"));
136 KAlarm::setTestModeConditions();
139 setQuitOnLastWindowClosed(
false);
143 Preferences::setAutoStart(
true);
148 Preferences::connect(SIGNAL(holidaysChanged(KHolidays::HolidayRegion)),
this, SLOT(slotHolidaysChanged(KHolidays::HolidayRegion)));
149 Preferences::connect(SIGNAL(feb29TypeChanged(Feb29Type)),
this, SLOT(slotFeb29TypeChanged(Feb29Type)));
150 Preferences::connect(SIGNAL(showInSystemTrayChanged(
bool)),
this, SLOT(slotShowInSystemTrayChanged()));
153 slotFeb29TypeChanged(Preferences::defaultFeb29Type());
156 SLOT(slotDBusServiceUnregistered(
QString)));
160 KAEvent::setDefaultFont(Preferences::messageFont());
165 SLOT(purgeNewArchivedDefault(Akonadi::Collection)));
167 SLOT(checkWritableCalendar()));
169 SLOT(checkWritableCalendar()));
172 KConfigGroup config(KGlobal::config(),
"General");
173 mNoSystemTray = config.readEntry(
"NoSystemTray",
false);
176 mPrefsArchivedColour = Preferences::archivedColour();
180 mSpeechEnabled = (KServiceTypeTrader::self()->query(
QLatin1String(
"DBUS/Text-to-Speech"),
QLatin1String(
"Name == 'KTTSD'")).count() > 0);
181 if (!mSpeechEnabled) { kDebug() <<
"Speech synthesis disabled (KTTSD not found)"; }
184 mKOrganizerEnabled = !KStandardDirs::locate(
"exe", korg).isNull() || !KStandardDirs::findExe(korg).isNull();
185 if (!mKOrganizerEnabled) { kDebug() <<
"KOrganizer options disabled (KOrganizer not found)"; }
188 if (mWindowFocusBroken) kDebug() <<
"Window keyboard focus broken";
195 while (!mCommandProcesses.
isEmpty())
197 ProcData* pd = mCommandProcesses[0];
215 theInstance->quitFatal();
228 bool KAlarmApp::initialise()
232 mAlarmTimer =
new QTimer(
this);
234 connect(mAlarmTimer, SIGNAL(timeout()), SLOT(checkNextDueAlarm()));
238 kDebug() <<
"initialising calendars";
256 if (!isSessionRestored())
265 kDebug() <<
"Restoring";
271 kapp->sessionConfig();
275 Preferences::setAutoStart(
true);
280 if (!initCheck(
true))
287 for (
int i = 1; KMainWindow::canBeRestored(i); ++i)
289 QString type = KMainWindow::classNameOfToplevel(i);
293 win->restore(i,
false);
302 win->restore(i,
false);
319 kWarning() <<
"no main window to be restored!?";
355 static bool firstInstance =
true;
356 bool dontRedisplay =
false;
357 if (!firstInstance || !isSessionRestored())
377 if (!initCheck(
true,
true, options.
eventId().collectionId()))
379 if (!initCheck(
true))
385 dontRedisplay =
true;
387 if (!handleEvent(options.
eventId(),
function,
true))
389 if (!handleEvent(options.
eventId(),
function))
408 if (!initCheck(
true,
true))
410 if (!initCheck(
true))
415 dontRedisplay =
true;
417 for (
int i = 0, count = alarms.
count(); i < count; ++i)
418 std::cout << alarms[i].toUtf8().constData() << std::endl;
425 if (!initCheck(
false,
true, options.
eventId().collectionId()))
430 else if (!KAlarm::editAlarmById(options.
eventId()))
456 else if (options.
flags() & KAEvent::REPEAT_AT_LOGIN)
461 if (options.
flags() & KAEvent::COPY_KORGANIZER)
474 || options.
flags() & (KAEvent::BEEP | KAEvent::SPEAK))
476 KAEvent::Flags flags = options.
flags();
477 Preferences::SoundType type = (flags & KAEvent::BEEP) ? Preferences::Sound_Beep
478 : (flags & KAEvent::SPEAK) ? Preferences::Sound_Speak
479 : Preferences::Sound_File;
484 if (options.
flags() & KAEvent::CONFIRM_ACK)
486 if (options.
flags() & KAEvent::AUTO_CLOSE)
501 if (options.
flags() & KAEvent::EMAIL_BCC)
516 KAlarm::execNewAlarmDlg(editDlg);
543 if (Preferences::showInSystemTray() && KSystemTrayIcon::isSystemTrayAvailable())
563 win->setWindowState(win->windowState() | Qt::WindowMinimized);
577 if (firstInstance && !dontRedisplay && !exitCode)
590 mRedisplayAlarms =
false;
594 mRedisplayAlarms =
true;
602 firstInstance =
false;
615 void KAlarmApp::checkKtimezoned()
618 static bool done =
false;
622 #if KDE_IS_VERSION(4,5,70)
623 if (!KSystemTimeZones::isTimeZoneDaemonAvailable())
625 kDebug() <<
"ktimezoned not running: using UTC only";
627 i18nc(
"@info",
"Time zones are not accessible:<nl/>KAlarm will use the UTC time zone.<nl/><nl/>(The KDE time zone service is not available:<nl/>check that <application>ktimezoned</application> is installed.)"),
654 mPendingQuit =
false;
659 if (mwcount > 1 || (mwcount && (!mw->isHidden() || !mw->
isTrayParent())))
667 if (checkSystemTray())
670 if (!mActionQueue.isEmpty() || !mCommandProcesses.
isEmpty())
674 mPendingQuitCode = exitCode;
683 kDebug() << exitCode <<
": quitting";
687 KAlarm::setRtcWakeTime(0, 0);
688 KAlarm::deleteRtcWakeConfig();
692 mInitialised =
false;
707 i18nc(
"@info",
"Quitting will disable alarms (once any alarm message windows are closed)."),
708 QString(), KStandardGuiItem::quit(),
710 ) != KMessageBox::Continue)
712 if (!KAlarm::checkRtcWakeConfig(
true).isEmpty())
716 i18nc(
"@info",
"Quitting will cancel the scheduled Wake from Suspend."),
717 QString(), KStandardGuiItem::quit()
718 ) != KMessageBox::Continue)
720 mCancelRtcWake =
true;
722 if (!Preferences::autoStart())
724 int option = KMessageBox::No;
728 i18nc(
"@info",
"Do you want to start KAlarm at login?<nl/>"
729 "(Note that alarms will be disabled if KAlarm is not started.)"),
730 QString(), KStandardGuiItem::yes(), KStandardGuiItem::no(),
735 case KMessageBox::Yes:
736 Preferences::setAutoStart(
true);
739 case KMessageBox::No:
742 case KMessageBox::Cancel:
756 mSessionClosingDown =
true;
757 KUniqueApplication::commitData(sm);
758 mSessionClosingDown =
false;
770 mFatalMessage = message;
779 void KAlarmApp::quitFatal()
788 KMessageBox::error(0, mFatalMessage);
793 theInstance->
quitIf(1,
true);
804 void KAlarmApp::checkNextDueAlarm()
812 KDateTime nextDt = nextEvent->nextTrigger(KAEvent::ALL_TRIGGER).effectiveKDateTime();
814 qint64 interval = now.secsTo_long(nextDt);
815 kDebug() <<
"now:" << qPrintable(now.toString(
QLatin1String(
"%Y-%m-%d %H:%M %:Z"))) <<
", next:" << qPrintable(nextDt.toString(
QLatin1String(
"%Y-%m-%d %H:%M %:Z"))) <<
", due:" << interval;
819 queueAlarmId(*nextEvent);
820 kDebug() << nextEvent->id() <<
": due now";
827 #ifndef HIBERNATION_SIGNAL
840 if (interval > INT_MAX)
842 kDebug() << nextEvent->id() <<
"wait" << interval/1000 <<
"seconds";
843 mAlarmTimer->
start(static_cast<int>(interval));
852 void KAlarmApp::queueAlarmId(
const KAEvent& event)
859 for (
int i = 0, end = mActionQueue.count(); i < end; ++i)
861 if (mActionQueue[i].
function == EVENT_HANDLE && mActionQueue[i].eventId ==
id)
864 mActionQueue.
enqueue(ActionQEntry(EVENT_HANDLE,
id));
870 void KAlarmApp::startProcessQueue()
893 if (mInitialised && !mProcessingQueue)
896 mProcessingQueue =
true;
899 KAlarm::refreshAlarmsIfQueued();
901 if (!mLoginAlarmsDone)
907 for (
int i = 0, end = events.count(); i < end; ++i)
909 KAEvent
event = *events[i];
910 if (!cancelReminderAndDeferral(event))
916 mLoginAlarmsDone =
true;
920 while (!mActionQueue.isEmpty())
922 ActionQEntry& entry = mActionQueue.
head();
923 if (entry.eventId.isEmpty())
926 switch (entry.function)
929 execAlarm(entry.event, entry.event.firstAlarm(),
false);
932 KAlarm::addEvent(entry.event, 0, 0, KAlarm::ALLOW_KORG_UPDATE | KAlarm::NO_RESOURCE_PROMPT);
939 handleEvent(entry.eventId, entry.function);
944 if (mPurgeDaysQueued >= 0)
946 KAlarm::purgeArchive(mPurgeDaysQueued);
947 mPurgeDaysQueued = -1;
953 if (
quitIf(mPendingQuitCode))
957 mProcessingQueue =
false;
971 void KAlarmApp::atLoginEventAdded(
const KAEvent& event)
974 if (!cancelReminderAndDeferral(ev))
1000 static bool creating =
false;
1003 if (!mTrayWindow && !creating)
1005 if (!KSystemTrayIcon::isSystemTrayAvailable())
1016 mTrayWindow =
new TrayWindow(parent ? parent : MainWindow::firstWindow());
1020 if (!checkSystemTray())
1035 bool KAlarmApp::checkSystemTray()
1039 if (KSystemTrayIcon::isSystemTrayAvailable() == mNoSystemTray)
1041 kDebug() <<
"changed ->" << mNoSystemTray;
1042 mNoSystemTray = !mNoSystemTray;
1046 KConfigGroup config(KGlobal::config(),
"General");
1047 config.writeEntry(
"NoSystemTray", mNoSystemTray);
1051 slotShowInSystemTrayChanged();
1053 return !mNoSystemTray;
1068 void KAlarmApp::slotShowInSystemTrayChanged()
1071 if (newShowInSysTray != mOldShowInSystemTray)
1078 mOldShowInSystemTray = newShowInSysTray;
1079 if (newShowInSysTray)
1087 if (win && win->isHidden())
1093 win->setWindowState(win->windowState() | Qt::WindowMinimized);
1106 void KAlarmApp::changeStartOfDay()
1117 void KAlarmApp::slotMessageFontChanged(
const QFont& font)
1119 KAEvent::setDefaultFont(font);
1126 void KAlarmApp::slotWorkTimeChanged(
const QTime& start,
const QTime& end,
const QBitArray& days)
1128 KAEvent::setWorkTime(days, start, end);
1135 void KAlarmApp::slotHolidaysChanged(
const KHolidays::HolidayRegion& holidays)
1137 KAEvent::setHolidays(holidays);
1144 void KAlarmApp::slotFeb29TypeChanged(Preferences::Feb29Type type)
1146 KARecurrence::Feb29Type rtype;
1150 case Preferences::Feb29_None: rtype = KARecurrence::Feb29_None;
break;
1151 case Preferences::Feb29_Feb28: rtype = KARecurrence::Feb29_Feb28;
break;
1152 case Preferences::Feb29_Mar1: rtype = KARecurrence::Feb29_Mar1;
break;
1154 KARecurrence::setDefaultFeb29Type(rtype);
1162 return Preferences::showInSystemTray() && KSystemTrayIcon::isSystemTrayAvailable();
1170 void KAlarmApp::checkWritableCalendar()
1176 if (treeFetched && mRedisplayAlarms)
1178 mRedisplayAlarms =
false;
1185 static bool done =
false;
1194 bool active = AlarmResources::instance()->activeCount(CalEvent::ACTIVE,
true);
1198 kWarning() <<
"No writable active calendar";
1200 i18nc(
"@info",
"Alarms cannot be created or updated, because no writable active alarm calendar is enabled.<nl/><nl/>"
1201 "To fix this, use <interface>View | Show Calendars</interface> to check or change calendar statuses."),
1212 void KAlarmApp::purgeNewArchivedDefault(
const Akonadi::Collection& collection)
1214 Akonadi::Collection col(collection);
1219 kDebug() << collection.id() <<
": standard archived...";
1229 void KAlarmApp::purgeAfterDelay()
1231 if (mArchivedPurgeDays >= 0)
1232 purge(mArchivedPurgeDays);
1234 setArchivePurgeDays();
1244 void KAlarmApp::setArchivePurgeDays()
1246 int newDays = Preferences::archivedKeepDays();
1247 if (newDays != mArchivedPurgeDays)
1249 int oldDays = mArchivedPurgeDays;
1250 mArchivedPurgeDays = newDays;
1251 if (mArchivedPurgeDays <= 0)
1253 if (mArchivedPurgeDays < 0)
1255 if (oldDays < 0 || mArchivedPurgeDays < oldDays)
1258 purge(mArchivedPurgeDays);
1259 if (!mArchivedPurgeDays)
1272 void KAlarmApp::purge(
int daysToKeep)
1274 if (mPurgeDaysQueued < 0 || daysToKeep < mPurgeDaysQueued)
1275 mPurgeDaysQueued = daysToKeep;
1290 KAEvent::List events = KAlarm::getSortedActiveEvents();
1293 for (
int i = 0, count = events.count(); i < count; ++i)
1296 KAEvent*
event = &events[i];
1298 KAEvent*
event = events[i];
1300 KDateTime dateTime =
event->nextTrigger(KAEvent::DISPLAY_TRIGGER).effectiveKDateTime().toLocalZone();
1302 Akonadi::Collection c(event->collectionId());
1310 + AlarmText::summary(*event, 1);
1321 if (enabled != mAlarmsEnabled)
1323 mAlarmsEnabled = enabled;
1326 KAlarm::cancelRtcWake(0);
1327 else if (!mProcessingQueue)
1328 checkNextDueAlarm();
1358 return mWindowFocusBroken;
1377 int lateCancel, KAEvent::Flags flags,
const QColor& bg,
const QColor& fg,
1378 const QFont& font,
const QString& audioFile,
float audioVolume,
int reminderMinutes,
1379 const KARecurrence& recurrence, KCalCore::Duration repeatInterval,
int repeatCount,
1381 uint mailFromID,
const KCalCore::Person::List& mailAddresses,
1388 if (!dateTime.isValid())
1390 KDateTime now = KDateTime::currentUtcDateTime();
1391 if (lateCancel && dateTime < now.addSecs(-
maxLateness(lateCancel)))
1393 KDateTime alarmTime = dateTime;
1395 if (!dateTime.isDateOnly())
1396 alarmTime.setTime(
QTime(alarmTime.time().hour(), alarmTime.time().minute(), 0));
1398 KAEvent event(alarmTime, text, bg, fg, font, action, lateCancel, flags,
true);
1399 if (reminderMinutes)
1401 bool onceOnly = flags & KAEvent::REMINDER_ONCE;
1402 event.setReminder(reminderMinutes, onceOnly);
1405 event.setAudioFile(audioFile, audioVolume, -1, 0, (flags & KAEvent::REPEAT_SOUND) ? 0 : -1);
1407 event.setEmail(mailFromID, mailAddresses, mailSubject, mailAttachments);
1408 event.setRecurrence(recurrence);
1409 event.setFirstRecurrence();
1410 event.setRepetition(Repetition(repeatInterval, repeatCount - 1));
1412 if (alarmTime <= now)
1417 mActionQueue.
enqueue(ActionQEntry(event, EVENT_TRIGGER));
1419 execAlarm(event, event.firstAlarm(),
false);
1422 ||
event.setNextOccurrence(now) == KAEvent::NO_OCCURRENCE)
1428 mActionQueue.
enqueue(ActionQEntry(event));
1440 bool KAlarmApp::dbusHandleEvent(
const EventId& eventID, EventFunc
function)
1442 bool KAlarmApp::dbusHandleEvent(
const QString& eventID, EventFunc
function)
1445 kDebug() << eventID;
1446 mActionQueue.
append(ActionQEntry(
function, eventID));
1472 bool KAlarmApp::handleEvent(
const EventId&
id, EventFunc
function,
bool checkDuplicates)
1474 bool KAlarmApp::handleEvent(
const QString& eventID, EventFunc
function)
1478 KAlarm::checkRtcWakeConfig();
1481 const QString eventID(
id.eventId());
1485 if (
id.collectionId() != -1)
1486 kWarning() <<
"Event ID not found, or duplicated:" << eventID;
1488 kWarning() <<
"Event ID not found:" << eventID;
1495 kWarning() <<
"Event ID not found:" << eventID;
1502 kDebug() << eventID <<
", CANCEL";
1503 KAlarm::deleteEvent(*event,
true);
1509 KDateTime now = KDateTime::currentUtcDateTime();
1510 kDebug() << eventID <<
"," << (
function==EVENT_TRIGGER?
"TRIGGER:":
"HANDLE:") << qPrintable(now.dateTime().toString(
QLatin1String(
"yyyy-MM-dd hh:mm"))) <<
"UTC";
1511 bool updateCalAndDisplay =
false;
1512 bool alarmToExecuteValid =
false;
1513 KAAlarm alarmToExecute;
1514 bool restart =
false;
1517 for (KAAlarm alarm = event->firstAlarm();
1519 alarm = (restart ?
event->firstAlarm() :
event->nextAlarm(alarm)), restart =
false)
1522 KDateTime nextDT = alarm.dateTime(
true).effectiveKDateTime();
1523 int secs = nextDT.secsTo(now);
1529 if (alarm.dateTime().timeSpec() != KDateTime::ClockTime
1530 || nextDT > now.toTimeSpec(KDateTime::ClockTime))
1533 kDebug() <<
"Alarm" << alarm.type() <<
"at" << nextDT.dateTime() <<
": not due";
1537 bool reschedule =
false;
1538 bool rescheduleWork =
false;
1539 if ((event->workTimeOnly() ||
event->holidaysExcluded()) && !alarm.deferred())
1544 if (alarm.dateTime().isDateOnly())
1546 KDateTime dt(nextDT);
1547 dt.setDateOnly(
true);
1548 reschedule = !
event->isWorkingTime(dt);
1551 reschedule = !
event->isWorkingTime(nextDT);
1552 rescheduleWork = reschedule;
1554 kDebug() <<
"Alarm" << alarm.type() <<
"at" << nextDT.dateTime() <<
": not during working hours";
1556 if (!reschedule && alarm.repeatAtLogin())
1559 kDebug() <<
"REPEAT_AT_LOGIN";
1562 if (alarmToExecute.isValid())
1568 if (!reschedule && event->lateCancel())
1571 kDebug() <<
"LATE_CANCEL";
1572 bool cancel =
false;
1573 if (alarm.dateTime().isDateOnly())
1576 int maxlate =
event->lateCancel() / 1440;
1577 KDateTime limit(DateTime(nextDT.addDays(maxlate + 1)).effectiveKDateTime());
1583 KAEvent::OccurType type =
event->previousOccurrence(now, next,
true);
1584 switch (type & ~KAEvent::OCCURRENCE_REPEAT)
1586 case KAEvent::FIRST_OR_ONLY_OCCURRENCE:
1587 case KAEvent::RECURRENCE_DATE:
1588 case KAEvent::RECURRENCE_DATE_TIME:
1589 case KAEvent::LAST_RECURRENCE:
1590 limit.setDate(next.date().addDays(maxlate + 1));
1593 if (type == KAEvent::LAST_RECURRENCE
1594 || (type == KAEvent::FIRST_OR_ONLY_OCCURRENCE && !event->recurs()))
1600 case KAEvent::NO_OCCURRENCE:
1616 KAEvent::OccurType type =
event->previousOccurrence(now, next,
true);
1617 switch (type & ~KAEvent::OCCURRENCE_REPEAT)
1619 case KAEvent::FIRST_OR_ONLY_OCCURRENCE:
1620 case KAEvent::RECURRENCE_DATE:
1621 case KAEvent::RECURRENCE_DATE_TIME:
1622 case KAEvent::LAST_RECURRENCE:
1623 if (next.effectiveKDateTime().secsTo(now) > maxlate)
1625 if (type == KAEvent::LAST_RECURRENCE
1626 || (type == KAEvent::FIRST_OR_ONLY_OCCURRENCE && !event->recurs()))
1632 case KAEvent::NO_OCCURRENCE:
1643 event->setArchive();
1644 if (cancelAlarm(*event, alarm.type(),
false))
1646 updateCalAndDisplay =
true;
1653 switch (rescheduleAlarm(*event, alarm,
false, (rescheduleWork ? nextDT : KDateTime())))
1659 alarmToExecuteValid =
false;
1667 updateCalAndDisplay =
true;
1670 if (!alarmToExecuteValid)
1672 kDebug() <<
"Alarm" << alarm.type() <<
": execute";
1673 alarmToExecute = alarm;
1674 alarmToExecuteValid =
true;
1677 kDebug() <<
"Alarm" << alarm.type() <<
": skip";
1682 if (alarmToExecute.isValid())
1683 execAlarm(*event, alarmToExecute,
true, !alarmToExecute.repeatAtLogin());
1686 if (
function == EVENT_TRIGGER)
1691 KAAlarm alarm =
event->firstAlarm();
1692 if (alarm.isValid())
1693 execAlarm(*event, alarm,
false);
1695 if (updateCalAndDisplay)
1696 KAlarm::updateEvent(*event);
1697 else if (
function != EVENT_TRIGGER) { kDebug() <<
"No action"; }
1710 if (!event.postAction().isEmpty())
1714 QString command =
event.postAction();
1715 kDebug() <<
event.id() <<
":" << command;
1716 doShellCommand(command, event, 0, ProcData::POST_ACTION);
1733 kDebug() <<
"Alarm type:" << alarm.type();
1735 bool update =
false;
1736 event.startChanges();
1737 if (alarm.repeatAtLogin())
1740 if (!event.reminderActive() &&
event.reminderMinutes() < 0)
1744 event.activateReminderAfter(KDateTime::currentUtcDateTime());
1748 else if (alarm.isReminder() || alarm.deferred())
1751 event.removeExpiredAlarm(alarm.type());
1757 bool cancelled =
false;
1758 DateTime last =
event.mainDateTime(
false);
1759 if (last != event.mainDateTime(
true))
1761 bool next = nextDt.isValid();
1762 KDateTime next_dt = nextDt;
1763 KDateTime now = KDateTime::currentUtcDateTime();
1766 KAEvent::OccurType type =
event.setNextOccurrence(next ? next_dt : now);
1769 case KAEvent::NO_OCCURRENCE:
1771 kDebug() <<
"No occurrence";
1772 if (event.reminderMinutes() < 0 && last.isValid()
1773 && alarm.type() != KAAlarm::AT_LOGIN_ALARM && !
event.mainExpired())
1777 event.activateReminderAfter(last);
1778 updateCalAndDisplay =
true;
1780 if (cancelAlarm(event, alarm.type(), updateCalAndDisplay))
1784 if (!(type & KAEvent::OCCURRENCE_REPEAT))
1787 case KAEvent::RECURRENCE_DATE:
1788 case KAEvent::RECURRENCE_DATE_TIME:
1789 case KAEvent::LAST_RECURRENCE:
1791 if (updateCalAndDisplay)
1794 case KAEvent::FIRST_OR_ONLY_OCCURRENCE:
1800 if (event.deferred())
1803 event.removeExpiredAlarm(KAAlarm::DEFERRED_ALARM);
1810 next_dt =
event.mainDateTime(
true).effectiveKDateTime();
1811 if (event.mainDateTime(
false).isDateOnly())
1813 KDateTime dt(next_dt);
1814 dt.setDateOnly(
true);
1815 next = !
event.isWorkingTime(dt);
1818 next = !
event.isWorkingTime(next_dt);
1820 }
while (next && next_dt <= now);
1821 reply = (!cancelled && next_dt.isValid() && (next_dt <= now)) ? 1 : 0;
1823 if (event.reminderMinutes() < 0 && last.isValid()
1824 && alarm.type() != KAAlarm::AT_LOGIN_ALARM)
1828 event.activateReminderAfter(last);
1833 KAlarm::updateEvent(event);
1842 bool KAlarmApp::cancelAlarm(KAEvent& event, KAAlarm::Type alarmType,
bool updateCalAndDisplay)
1845 if (alarmType == KAAlarm::MAIN_ALARM && !event.displaying() &&
event.toBeArchived())
1849 KAlarm::addArchivedEvent(ev);
1851 event.removeExpiredAlarm(alarmType);
1852 if (!event.alarmCount())
1854 KAlarm::deleteEvent(event,
false);
1857 if (updateCalAndDisplay)
1858 KAlarm::updateEvent(event);
1869 bool KAlarmApp::cancelReminderAndDeferral(KAEvent& event)
1871 return cancelAlarm(event, KAAlarm::REMINDER_ALARM,
false)
1872 || cancelAlarm(event, KAAlarm::DEFERRED_REMINDER_ALARM,
false)
1873 || cancelAlarm(event, KAAlarm::DEFERRED_ALARM,
true);
1884 void*
KAlarmApp::execAlarm(KAEvent& event,
const KAAlarm& alarm,
bool reschedule,
bool allowDefer,
bool noPreAction)
1886 if (!mAlarmsEnabled || !event.enabled())
1889 kDebug() <<
event.id() <<
": disabled";
1895 void* result = (
void*)1;
1898 switch (alarm.action())
1900 case KAAlarm::COMMAND:
1901 if (!event.commandDisplay())
1911 case KAAlarm::MESSAGE:
1922 bool reminder = (alarm.type() & KAAlarm::REMINDER_ALARM);
1923 bool replaceReminder = !reminder && win && (win->
alarmType() & KAAlarm::REMINDER_ALARM);
1925 && (!event.deferred() || (
event.extraActionOptions() & KAEvent::ExecPreActOnDeferral))
1926 && (replaceReminder || !win) && !noPreAction
1927 && !event.preAction().isEmpty())
1937 for (
int i = 0, end = mCommandProcesses.
count(); i < end; ++i)
1939 ProcData* pd = mCommandProcesses[i];
1940 if (pd->event->id() ==
event.id() && (pd->flags & ProcData::PRE_ACTION))
1942 kDebug() <<
"Already executing pre-DISPLAY command";
1949 QString command =
event.preAction();
1950 kDebug() <<
"Pre-DISPLAY command:" << command;
1951 int flags = (reschedule ? ProcData::RESCHEDULE : 0) | (allowDefer ? ProcData::ALLOW_DEFER : 0);
1952 if (doShellCommand(command, event, &alarm, (flags | ProcData::PRE_ACTION)))
1958 if (event.cancelOnPreActionError())
1961 kDebug() <<
event.id() <<
": pre-action failed: cancelled";
1973 (
new MessageWin(&event, alarm, flags))->show();
1975 else if (replaceReminder)
1980 else if (!win->
hasDefer() && !alarm.repeatAtLogin())
1999 case KAAlarm::EMAIL:
2001 kDebug() <<
"EMAIL to:" <<
event.emailAddresses(
QLatin1String(
","));
2003 KAMail::JobData data(event, alarm, reschedule, (reschedule || allowDefer));
2022 case KAAlarm::AUDIO:
2058 if (errmsgs.
count() > 1)
2059 kDebug() << (copyerr ?
"Copy error:" :
"Failed:") << errmsgs[1];
2075 int flags = (
event.commandXterm() ? ProcData::EXEC_IN_XTERM : 0)
2076 | (event.commandDisplay() ? ProcData::DISP_OUTPUT : 0);
2077 QString command =
event.cleanText();
2078 if (event.commandScript())
2081 kDebug() <<
"Script";
2082 QString tmpfile = createTempScriptFile(command,
false, event, alarm);
2088 return doShellCommand(tmpfile, event, &alarm, (flags | ProcData::TEMP_FILE), receiver, slot);
2092 kDebug() << command;
2093 return doShellCommand(command, event, &alarm, flags, receiver, slot);
2110 ShellProcess* KAlarmApp::doShellCommand(
const QString& command,
const KAEvent& event,
const KAAlarm* alarm,
int flags,
const QObject* receiver,
const char* slot)
2112 kDebug() << command <<
"," <<
event.id();
2116 if (flags & ProcData::EXEC_IN_XTERM)
2119 cmd = composeXTermCommand(command, event, alarm, flags, tmpXtermFile);
2124 mode = QIODevice::ReadWrite;
2134 proc->setEnv(
QLatin1String(
"KALARM_UID"), event.id(),
true);
2135 proc->setOutputChannelMode(KProcess::MergedChannels);
2137 if ((flags & ProcData::DISP_OUTPUT) && receiver && slot)
2139 connect(proc, SIGNAL(receivedStdout(
ShellProcess*)), receiver, slot);
2140 connect(proc, SIGNAL(receivedStderr(
ShellProcess*)), receiver, slot);
2142 if (mode == QIODevice::ReadWrite && !event.logFile().isEmpty())
2147 if (alarm && alarm->dateTime().isValid())
2149 QString dateTime = alarm->dateTime().formatLocale();
2154 QFile logfile(event.logFile());
2155 if (logfile.open(QIODevice::Append | QIODevice::Text))
2161 proc->setStandardOutputFile(event.logFile(), QIODevice::Append);
2163 pd =
new ProcData(proc,
new KAEvent(event), (alarm ?
new KAAlarm(*alarm) : 0), flags);
2164 if (flags & ProcData::TEMP_FILE)
2165 pd->tempFiles += command;
2167 pd->tempFiles += tmpXtermFile;
2168 mCommandProcesses.
append(pd);
2169 if (proc->
start(mode))
2174 kWarning() <<
"Command failed to start";
2175 commandErrorMsg(proc, event, alarm, flags);
2190 QString KAlarmApp::composeXTermCommand(
const QString& command,
const KAEvent& event,
const KAAlarm* alarm,
int flags,
QString& tempScriptFile)
const
2192 kDebug() << command <<
"," <<
event.id();
2193 tempScriptFile.
clear();
2199 if (flags & ProcData::TEMP_FILE)
2203 tempScriptFile = createTempScriptFile(command,
true, event, *alarm);
2213 tempScriptFile = createTempScriptFile(command +
QLatin1String(
"\nsleep 86400\n"),
true, event, *alarm);
2229 QString exec = KShell::quoteArg(command);
2242 QString KAlarmApp::createTempScriptFile(
const QString& command,
bool insertShell,
const KAEvent& event,
const KAAlarm& alarm)
const
2244 KTemporaryFile tmpFile;
2245 tmpFile.setAutoRemove(
false);
2246 if (!tmpFile.open())
2247 kError() <<
"Unable to create a temporary script file";
2250 tmpFile.setPermissions(QFile::ReadUser | QFile::WriteUser | QFile::ExeUser);
2256 if (tmpFile.error() != QFile::NoError)
2257 kError() <<
"Error" << tmpFile.errorString() <<
" writing to temporary script file";
2259 return tmpFile.fileName();
2262 QStringList errmsgs(i18nc(
"@info",
"Error creating temporary script file"));
2274 for (
int i = 0, end = mCommandProcesses.
count(); i < end; ++i)
2276 ProcData* pd = mCommandProcesses[i];
2277 if (pd->process == proc)
2280 bool executeAlarm = pd->preAction();
2284 kDebug() << pd->event->id() <<
": SUCCESS";
2286 : pd->postAction() ? KAEvent::CMD_ERROR_POST
2287 : KAEvent::CMD_ERROR);
2293 kWarning() << pd->event->id() <<
":" << errmsg <<
"exit status =" << status <<
", code =" << proc->
exitCode();
2295 kWarning() << pd->event->id() <<
":" << errmsg <<
"exit status =" << status;
2296 if (pd->messageBoxParent)
2303 : pd->postAction() ? KAEvent::CMD_ERROR_POST
2304 : KAEvent::CMD_ERROR);
2305 if (!pd->tempFile())
2313 commandErrorMsg(proc, *pd->event, pd->alarm, pd->flags);
2315 if (executeAlarm && pd->event->cancelOnPreActionError())
2317 kDebug() << pd->event->id() <<
": pre-action failed: cancelled";
2318 if (pd->reschedule())
2320 executeAlarm =
false;
2323 if (pd->preAction())
2326 execAlarm(*pd->event, *pd->alarm, pd->reschedule(), pd->allowDefer(),
true);
2334 if (mPendingQuit && mCommandProcesses.
isEmpty())
2335 quitIf(mPendingQuitCode);
2341 void KAlarmApp::commandErrorMsg(
const ShellProcess* proc,
const KAEvent& event,
const KAAlarm* alarm,
int flags)
2343 KAEvent::CmdErrType cmderr;
2346 if (flags & ProcData::PRE_ACTION)
2348 if (event.dontShowPreActionError())
2350 errmsgs += i18nc(
"@info",
"Pre-alarm action:");
2352 cmderr = KAEvent::CMD_ERROR_PRE;
2354 else if (flags & ProcData::POST_ACTION)
2356 errmsgs += i18nc(
"@info",
"Post-alarm action:");
2358 cmderr = (
event.commandError() == KAEvent::CMD_ERROR_PRE)
2359 ? KAEvent::CMD_ERROR_PRE_POST : KAEvent::CMD_ERROR_POST;
2364 cmderr = KAEvent::CMD_ERROR;
2373 if (!(flags & ProcData::TEMP_FILE))
2386 for (
int i = 0, end = mCommandProcesses.
count(); i < end; ++i)
2388 ProcData* pd = mCommandProcesses[i];
2389 if (pd->process == proc)
2391 pd->messageBoxParent = parent;
2413 kDebug() <<
"Failed to start kttsd:" << error;
2420 mKSpeech->setParent(
theApp());
2421 mKSpeech->setApplicationName(KGlobal::mainComponent().aboutData()->programName());
2422 mKSpeech->setDefaultPriority(KSpeech::jpMessage);
2431 void KAlarmApp::slotDBusServiceUnregistered(
const QString& serviceName)
2445 bool KAlarmApp::initCheck(
bool calendarOnly,
bool waitForCollection, Akonadi::Collection::Id collectionId)
2447 bool KAlarmApp::initCheck(
bool calendarOnly)
2450 static bool firstTime =
true;
2452 kDebug() <<
"first time";
2454 if (initialise() || firstTime)
2468 setArchivePurgeDays();
2471 checkWritableCalendar();
2477 startProcessQueue();
2480 if (waitForCollection)
2482 #if KDE_IS_VERSION(4,9,80)
2511 if (err == KAEvent::CMD_ERROR_POST && event.commandError() == KAEvent::CMD_ERROR_PRE)
2512 err = KAEvent::CMD_ERROR_PRE_POST;
2513 event.setCommandError(err);
2519 if (ev && ev->commandError() != err)
2520 ev->setCommandError(err);
2530 KAEvent::CmdErrType newerr =
static_cast<KAEvent::CmdErrType
>(
event.commandError() & ~err);
2531 event.setCommandError(newerr);
2539 newerr =
static_cast<KAEvent::CmdErrType
>(ev->commandError() & ~err);
2540 ev->setCommandError(newerr);
2550 KAlarmApp::ProcData::ProcData(
ShellProcess* p, KAEvent* e, KAAlarm* a,
int f)
2554 messageBoxParent(0),
2558 KAlarmApp::ProcData::~ProcData()
2560 while (!tempFiles.isEmpty())
2563 QFile f(tempFiles.first());
2565 tempFiles.removeFirst();
2571 #include "moc_kalarmapp.cpp"
QStringList attachments() const
KARecurrence * recurrence() const
static int questionYesNoCancel(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Options(Notify|WindowModal))
KDateTime alarmTime() const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QList< KCal::Person > addressees() const
void rescheduleAlarm(KAEvent &e, const KAAlarm &a)
void setAlarmsEnabled(bool)
static int maxLateness(int lateCancel)
QString & append(QChar ch)
static EventListModel * alarms()
bool scheduleEvent(KAEvent::SubAction, const QString &text, const KDateTime &, int lateCancel, KAEvent::Flags flags, const QColor &bg, const QColor &fg, const QFont &, const QString &audioFile, float audioVolume, int reminderMinutes, const KARecurrence &recurrence, KCalCore::Duration repeatInterval, int repeatCount, uint mailFromID=0, const QList< KCal::Person > &mailAddresses=QList< KCal::Person >(), const QString &mailSubject=QString(), const QStringList &mailAttachments=QStringList())
void setTime(const DateTime &)
void setAudio(Preferences::SoundType, const QString &file=QString(), float volume=-1, int repeatPause=-1)
static void printError(const QString &errmsg)
void emailSent(KAMail::JobData &, const QStringList &errmsgs, bool copyerr=false)
KAEvent::List atLoginAlarms() const
virtual QByteArray text(quint32 serialNumber) const =0
static bool spread(bool scatter)
void setLateCancel(int minutes)
static void setNoAutoStart(bool yes)
QDBusConnectionInterface * interface() const
bool wantShowInSystemTray() const
static AlarmCalendar * resources()
void updateCommandError(const QString &eventId)
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Options(Notify|WindowModal))
static bool isStandard(Akonadi::Collection &, CalEvent::Type)
Return whether a collection is the standard collection for a specified mime type. ...
void spreadWindowsToggled(bool)
bool refresh(Akonadi::Collection &) const
Refresh the specified collection instance with up to date data.
static void terminateCalendars()
QDBusConnection sessionBus()
MainWindow * assocMainWindow() const
void commandMessage(ShellProcess *, QWidget *parent)
QString join(const QString &separator) const
QDBusReply< bool > isServiceRegistered(const QString &serviceName) const
static void setEventCommandError(const KAEvent &, KAEvent::CmdErrType)
static MainWindow * firstWindow()
static void setAskAutoStart(bool yes)
static MessageWin * findEvent(const QString &eventId, MessageWin *exclude=0)
static void clearEventCommandError(const KAEvent &, KAEvent::CmdErrType)
QString value(const QString &name, const QString &defaultValue) const
static void connect(QObject *receiver, const char *member)
Connect to the timer signal.
static const QByteArray & shellPath()
int indexOf(const T &value, int from) const
bool isTrayParent() const
the KAlarm application object
KAEvent * earliestAlarm() const
QString number(int n, int base)
MessageWin: A window to display an alarm or error message.
int count(const T &value) const
void append(const T &value)
QString commandName() const
static QTime startOfDay()
int reminderMinutes() const
static CollectionControlModel * instance()
static QString cmdXTermCommand()
MainWindow * trayMainWindow() const
void setReminder(int minutes, bool onceOnly)
void setBgColour(const QColor &)
void removeWindow(TrayWindow *)
void alarmEnabledToggled(bool)
ShellProcess * execCommandAlarm(const KAEvent &, const KAAlarm &, const QObject *receiver=0, const char *slot=0)
static KTimeZone timeZone(bool reload=false)
void notifyAudioPlaying(bool playing)
static bool autoStartChangedByUser()
static void disconnect(QObject *receiver, const char *member=0)
Disconnect from the timer signal.
static const QLatin1String QUIT_WARN
KCalCore::Duration subRepeatInterval() const
static AkonadiModel * instance()
QString audioFile() const
QString templateName() const
virtual void setAction(KAEvent::SubAction, const AlarmText &=AlarmText())=0
static const QLatin1String ASK_AUTO_START
bool needWindowFocusFix() const
static void stopAudio(bool wait=false)
displays an alarm message
static KAlarmApp * getInstance()
virtual void commitData(QSessionManager &)
void setShowInKOrganizer(bool)
void setFgColour(const QColor &)
void setEmailFields(uint fromID, const QList< KCal::Person > &, const QString &subject, const QStringList &attachments)
static EditAlarmDlg * create(bool Template, Type, QWidget *parent=0, GetResourceType=RES_PROMPT)
QString errorMessage() const
bool isHiddenTrayParent() const
static MainWindow * create(bool restored=false)
float audioVolume() const
KAAlarm::Type alarmType() const
static int instanceCount()
static int instanceCount(bool excludeAlwaysHidden=false)
static void redisplayAlarms()
KAEvent::Flags flags() const
static QTime workDayEnd()
static void connect(const char *signal, const QObject *receiver, const char *member)
static const KHolidays::HolidayRegion & holidays()
static Akonadi::Collection::List enabledCollections(CalEvent::Type, bool writable)
Return the enabled collections which contain a specified mime type.
static QBitArray workDays()
static bool noAutoStart()
QString & replace(int position, int n, QChar after)
void showDateTime(const KAEvent &, const KAAlarm &)
Unique event identifier for Akonadi.
QByteArray toLatin1() const
void repeat(const KAAlarm &)
int subRepeatCount() const
void setRecurrence(const KARecurrence &, int subRepeatInterval, int subRepeatCount)
static const QLatin1String KTTSD_DBUS_SERVICE("org.kde.kttsd")
EditAlarmDlg::Type editType() const
static void showError(const KAEvent &, const DateTime &alarmDateTime, const QStringList &errmsgs, const QString &dontShowAgain=QString())
QString & sprintf(const char *cformat,...)
void cancelReminder(const KAEvent &, const KAAlarm &)
void setAlarmPending(KAEvent *, bool pending=true)
void setAudio(const QString &file, float volume=-1)
bool displayTrayIcon(bool show, MainWindow *=0)
static bool initialiseCalendars()
static Preferences * self()
void * execAlarm(KAEvent &, const KAAlarm &, bool reschedule, bool allowDefer=true, bool noPreAction=false)
OrgKdeKSpeechInterface * kspeechInterface(QString &error) const
static int send(JobData &, QStringList &errmsgs)
KAEvent::SubAction editAction() const
QProcessEnvironment systemEnvironment()
KAEvent * event(const QString &uniqueId)
static MainWindow * mainMainWindow()
static const QLatin1String KTTDS_DBUS_PATH("/KSpeech")
const QString & command() const
static void displayFatalError(const QString &message)
static int warningCancelContinue(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Options(Notify|WindowModal))
static AlarmCalendar * displayCalendar()
void doQuit(QWidget *parent)
KDateTime simulationTime() const
static QTime workDayStart()
void setSpreadWindowsState(bool spread)
bool windowFocusBroken() const
virtual int newInstance()
bool start(OpenMode=ReadWrite)
void alarmCompleted(const KAEvent &)
void updateCommandError(const KAEvent &)
To be called when the command error status of an alarm has changed, to set in the Akonadi database an...
void setSingleShot(bool singleShot)
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Options(Notify|WindowModal))