Commit 25c89315 authored by David Jarvie's avatar David Jarvie

Add command line option --list to list scheduled alarms to stdout

parent 3ee50fa2
......@@ -108,6 +108,7 @@ set(kalarm_bin_SRCS ${libkalarm_SRCS}
functions.cpp
fontcolour.cpp
fontcolourbutton.cpp
alarmtime.cpp
alarmtimewidget.cpp
specialactions.cpp
reminder.cpp
......
......@@ -19,6 +19,7 @@
*/
#include "akonadimodel.h"
#include "alarmtime.h"
#include "autoqpointer.h"
#include "calendarmigrator.h"
#include "mainwindow.h"
......@@ -281,8 +282,8 @@ QVariant AkonadiModel::data(const QModelIndex& index, int role) const
break;
case Qt::DisplayRole:
if (event.expired())
return alarmTimeText(event.startDateTime());
return alarmTimeText(event.nextTrigger(KAEvent::DISPLAY_TRIGGER));
return AlarmTime::alarmTimeText(event.startDateTime());
return AlarmTime::alarmTimeText(event.nextTrigger(KAEvent::DISPLAY_TRIGGER));
case SortRole:
{
DateTime due;
......@@ -306,7 +307,7 @@ QVariant AkonadiModel::data(const QModelIndex& index, int role) const
case Qt::DisplayRole:
if (event.expired())
return QString();
return timeToAlarmText(event.nextTrigger(KAEvent::DISPLAY_TRIGGER));
return AlarmTime::timeToAlarmText(event.nextTrigger(KAEvent::DISPLAY_TRIGGER));
case SortRole:
{
if (event.expired())
......@@ -668,71 +669,6 @@ QVariant AkonadiModel::entityHeaderData(int section, Qt::Orientation orientation
return EntityTreeModel::entityHeaderData(section, orientation, role, group);
}
/******************************************************************************
* Return the alarm time text in the form "date time".
*/
QString AkonadiModel::alarmTimeText(const DateTime& dateTime) const
{
if (!dateTime.isValid())
return i18nc("@info/plain Alarm never occurs", "Never");
KLocale* locale = KGlobal::locale();
KDateTime kdt = dateTime.effectiveKDateTime().toTimeSpec(Preferences::timeZone());
QString dateTimeText = locale->formatDate(kdt.date(), KLocale::ShortDate);
if (!dateTime.isDateOnly()
|| (!dateTime.isClockTime() && kdt.utcOffset() != dateTime.utcOffset()))
{
// Display the time of day if it's a date/time value, or if it's
// a date-only value but it's in a different time zone
dateTimeText += QLatin1Char(' ');
QString time = locale->formatTime(kdt.time());
if (mTimeHourPos == -2)
{
// Initialise the position of the hour within the time string, if leading
// zeroes are omitted, so that displayed times can be aligned with each other.
mTimeHourPos = -1; // default = alignment isn't possible/sensible
if (QApplication::isLeftToRight()) // don't try to align right-to-left languages
{
QString fmt = locale->timeFormat();
int i = fmt.indexOf(QRegExp("%[kl]")); // check if leading zeroes are omitted
if (i >= 0 && i == fmt.indexOf(QLatin1Char('%'))) // and whether the hour is first
mTimeHourPos = i; // yes, so need to align
}
}
if (mTimeHourPos >= 0 && (int)time.length() > mTimeHourPos + 1
&& time[mTimeHourPos].isDigit() && !time[mTimeHourPos + 1].isDigit())
dateTimeText += QLatin1Char('~'); // improve alignment of times with no leading zeroes
dateTimeText += time;
}
return dateTimeText + QLatin1Char(' ');
}
/******************************************************************************
* Return the time-to-alarm text.
*/
QString AkonadiModel::timeToAlarmText(const DateTime& dateTime) const
{
if (!dateTime.isValid())
return i18nc("@info/plain Alarm never occurs", "Never");
KDateTime now = KDateTime::currentUtcDateTime();
if (dateTime.isDateOnly())
{
int days = now.date().daysTo(dateTime.date());
// xgettext: no-c-format
return i18nc("@info/plain n days", "%1d", days);
}
int mins = (now.secsTo(dateTime.effectiveKDateTime()) + 59) / 60;
if (mins < 0)
return QString();
char minutes[3] = "00";
minutes[0] = (mins%60) / 10 + '0';
minutes[1] = (mins%60) % 10 + '0';
if (mins < 24*60)
return i18nc("@info/plain hours:minutes", "%1:%2", mins/60, minutes);
int days = mins / (24*60);
mins = mins % (24*60);
return i18nc("@info/plain days hours:minutes", "%1d %2:%3", days, mins/60, minutes);
}
/******************************************************************************
* Recursive function to emit the dataChanged() signal for all items in a
* specified column range.
......
......@@ -280,8 +280,6 @@ class AkonadiModel : public Akonadi::EntityTreeModel
AkonadiModel(Akonadi::ChangeRecorder*, QObject* parent);
KAEvent event(const Akonadi::Item&, const QModelIndex&, Akonadi::Collection*) const;
QString alarmTimeText(const DateTime&) const;
QString timeToAlarmText(const DateTime&) const;
void signalDataChanged(bool (*checkFunc)(const Akonadi::Item&), int startColumn, int endColumn, const QModelIndex& parent);
void setCollectionChanged(const Akonadi::Collection&, const QSet<QByteArray>&, bool rowInserted);
void queueItemModifyJob(const Akonadi::Item&);
......
/*
* alarmtime.cpp - conversion functions for alarm times
* Program: kalarm
* Copyright © 2007-2012 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
* 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 "alarmtime.h"
#include "preferences.h"
#include <kalarmcal/datetime.h>
#include <ksystemtimezone.h>
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <qapplication.h>
using namespace KAlarmCal;
int AlarmTime::mTimeHourPos = -2;
/******************************************************************************
* Return the alarm time text in the form "date time".
*/
QString AlarmTime::alarmTimeText(const DateTime& dateTime)
{
if (!dateTime.isValid())
return i18nc("@info/plain Alarm never occurs", "Never");
KLocale* locale = KGlobal::locale();
KDateTime kdt = dateTime.effectiveKDateTime().toTimeSpec(Preferences::timeZone());
QString dateTimeText = locale->formatDate(kdt.date(), KLocale::ShortDate);
if (!dateTime.isDateOnly()
|| (!dateTime.isClockTime() && kdt.utcOffset() != dateTime.utcOffset()))
{
// Display the time of day if it's a date/time value, or if it's
// a date-only value but it's in a different time zone
dateTimeText += QLatin1Char(' ');
QString time = locale->formatTime(kdt.time());
if (mTimeHourPos == -2)
{
// Initialise the position of the hour within the time string, if leading
// zeroes are omitted, so that displayed times can be aligned with each other.
mTimeHourPos = -1; // default = alignment isn't possible/sensible
if (QApplication::isLeftToRight()) // don't try to align right-to-left languages
{
QString fmt = locale->timeFormat();
int i = fmt.indexOf(QRegExp("%[kl]")); // check if leading zeroes are omitted
if (i >= 0 && i == fmt.indexOf(QLatin1Char('%'))) // and whether the hour is first
mTimeHourPos = i; // yes, so need to align
}
}
if (mTimeHourPos >= 0 && (int)time.length() > mTimeHourPos + 1
&& time[mTimeHourPos].isDigit() && !time[mTimeHourPos + 1].isDigit())
dateTimeText += QLatin1Char('~'); // improve alignment of times with no leading zeroes
dateTimeText += time;
}
return dateTimeText + QLatin1Char(' ');
}
/******************************************************************************
* Return the time-to-alarm text.
*/
QString AlarmTime::timeToAlarmText(const DateTime& dateTime)
{
if (!dateTime.isValid())
return i18nc("@info/plain Alarm never occurs", "Never");
KDateTime now = KDateTime::currentUtcDateTime();
if (dateTime.isDateOnly())
{
int days = now.date().daysTo(dateTime.date());
// xgettext: no-c-format
return i18nc("@info/plain n days", "%1d", days);
}
int mins = (now.secsTo(dateTime.effectiveKDateTime()) + 59) / 60;
if (mins < 0)
return QString();
char minutes[3] = "00";
minutes[0] = (mins%60) / 10 + '0';
minutes[1] = (mins%60) % 10 + '0';
if (mins < 24*60)
return i18nc("@info/plain hours:minutes", "%1:%2", mins/60, minutes);
int days = mins / (24*60);
mins = mins % (24*60);
return i18nc("@info/plain days hours:minutes", "%1d %2:%3", days, mins/60, minutes);
}
/******************************************************************************
* Convert a date/time specification string into a local date/time or date value.
* Parameters:
* timeString = in the form [[[yyyy-]mm-]dd-]hh:mm [TZ] or yyyy-mm-dd [TZ].
* dateTime = receives converted date/time value.
* defaultDt = default date/time used for missing parts of timeString, or null
* to use current date/time.
* allowTZ = whether to allow a time zone specifier in timeString.
* Reply = true if successful.
*/
bool AlarmTime::convertTimeString(const QByteArray& timeString, KDateTime& dateTime, const KDateTime& defaultDt, bool allowTZ)
{
#define MAX_DT_LEN 19
int i = timeString.indexOf(' ');
if (i > MAX_DT_LEN || (i >= 0 && !allowTZ))
return false;
QString zone = (i >= 0) ? QString::fromLatin1(timeString.mid(i)) : QString();
char timeStr[MAX_DT_LEN+1];
strcpy(timeStr, timeString.left(i >= 0 ? i : MAX_DT_LEN));
int dt[5] = { -1, -1, -1, -1, -1 };
char* s;
char* end;
bool noTime;
// Get the minute value
if ((s = strchr(timeStr, ':')) == 0)
noTime = true;
else
{
noTime = false;
*s++ = 0;
dt[4] = strtoul(s, &end, 10);
if (end == s || *end || dt[4] >= 60)
return false;
// Get the hour value
if ((s = strrchr(timeStr, '-')) == 0)
s = timeStr;
else
*s++ = 0;
dt[3] = strtoul(s, &end, 10);
if (end == s || *end || dt[3] >= 24)
return false;
}
bool noDate = true;
if (s != timeStr)
{
noDate = false;
// Get the day value
if ((s = strrchr(timeStr, '-')) == 0)
s = timeStr;
else
*s++ = 0;
dt[2] = strtoul(s, &end, 10);
if (end == s || *end || dt[2] == 0 || dt[2] > 31)
return false;
if (s != timeStr)
{
// Get the month value
if ((s = strrchr(timeStr, '-')) == 0)
s = timeStr;
else
*s++ = 0;
dt[1] = strtoul(s, &end, 10);
if (end == s || *end || dt[1] == 0 || dt[1] > 12)
return false;
if (s != timeStr)
{
// Get the year value
dt[0] = strtoul(timeStr, &end, 10);
if (end == timeStr || *end)
return false;
}
}
}
QDate date;
if (dt[0] >= 0)
date = QDate(dt[0], dt[1], dt[2]);
QTime time(0, 0, 0);
if (noTime)
{
// No time was specified, so the full date must have been specified
if (dt[0] < 0 || !date.isValid())
return false;
dateTime = applyTimeZone(zone, date, time, false, defaultDt);
}
else
{
// Compile the values into a date/time structure
time.setHMS(dt[3], dt[4], 0);
if (dt[0] < 0)
{
// Some or all of the date was omitted.
// Use the default date/time if provided.
if (defaultDt.isValid())
{
dt[0] = defaultDt.date().year();
date.setYMD(dt[0],
(dt[1] < 0 ? defaultDt.date().month() : dt[1]),
(dt[2] < 0 ? defaultDt.date().day() : dt[2]));
}
else
date.setYMD(2000, 1, 1); // temporary substitute for date
}
dateTime = applyTimeZone(zone, date, time, true, defaultDt);
if (!dateTime.isValid())
return false;
if (dt[0] < 0)
{
// Some or all of the date was omitted.
// Use the current date in the specified time zone as default.
KDateTime now = KDateTime::currentDateTime(dateTime.timeSpec());
date = dateTime.date();
date.setYMD(now.date().year(),
(dt[1] < 0 ? now.date().month() : dt[1]),
(dt[2] < 0 ? now.date().day() : dt[2]));
if (!date.isValid())
return false;
if (noDate && time < now.time())
date = date.addDays(1);
dateTime.setDate(date);
}
}
return dateTime.isValid();
}
/******************************************************************************
* Convert a time zone specifier string and apply it to a given date and/or time.
* The time zone specifier is a system time zone name, e.g. "Europe/London",
* "UTC" or "Clock". If no time zone is specified, it defaults to the local time
* zone.
* If 'defaultDt' is valid, it supplies the time spec and default date.
*/
KDateTime AlarmTime::applyTimeZone(const QString& tzstring, const QDate& date, const QTime& time,
bool haveTime, const KDateTime& defaultDt)
{
bool error = false;
KDateTime::Spec spec = KDateTime::LocalZone;
QString zone = tzstring.trimmed();
if (!zone.isEmpty())
{
if (zone == QLatin1String("Clock"))
spec = KDateTime::ClockTime;
else if (zone == QLatin1String("UTC"))
spec = KDateTime::UTC;
else
{
KTimeZone tz = KSystemTimeZones::zone(zone);
error = !tz.isValid();
if (!error)
spec = tz;
}
}
else if (defaultDt.isValid())
spec = defaultDt.timeSpec();
KDateTime result;
if (!error)
{
if (!date.isValid())
{
// It's a time without a date
if (defaultDt.isValid())
result = KDateTime(defaultDt.date(), time, spec);
else if (spec == KDateTime::LocalZone || spec == KDateTime::ClockTime)
result = KDateTime(KDateTime::currentLocalDate(), time, spec);
}
else if (haveTime)
{
// It's a date and time
result = KDateTime(date, time, spec);
}
else
{
// It's a date without a time
result = KDateTime(date, spec);
}
}
return result;
}
// vim: et sw=4:
/*
* alarmtime.h - conversion functions for alarm times
* Program: kalarm
* Copyright © 2012 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
* 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 <kdatetime.h>
namespace KAlarmCal { class DateTime; }
class AlarmTime
{
public:
static QString alarmTimeText(const KAlarmCal::DateTime& dateTime);
static QString timeToAlarmText(const KAlarmCal::DateTime& dateTime);
static bool convertTimeString(const QByteArray& timeString, KDateTime& dateTime,
const KDateTime& defaultDt = KDateTime(), bool allowTZ = true);
static KDateTime applyTimeZone(const QString& tzstring, const QDate& date, const QTime& time,
bool haveTime, const KDateTime& defaultDt = KDateTime());
private:
static int mTimeHourPos;
};
// vim: et sw=4:
/*
* commandoptions.cpp - extract command line options
* Program: kalarm
* Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2012 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
......@@ -20,7 +20,7 @@
#include "kalarm.h" //krazy:exclude=includes (kalarm.h must be first)
#include "commandoptions.h"
#include "functions.h"
#include "alarmtime.h"
#include "kalarmapp.h"
#include "kamail.h"
......@@ -58,13 +58,18 @@ CommandOptions::CommandOptions()
if (mArgs->isSet("test-set-time"))
{
QString time = mArgs->getOption("test-set-time");
if (!KAlarm::convertTimeString(time.toLatin1(), mSimulationTime, KDateTime::realCurrentLocalDateTime(), true))
if (!AlarmTime::convertTimeString(time.toLatin1(), mSimulationTime, KDateTime::realCurrentLocalDateTime(), true))
setErrorParameter("--test-set-time");
}
#endif
if (checkCommand("tray", TRAY))
{
}
if (checkCommand("list", LIST))
{
if (mArgs->count())
setErrorParameter("--list");
}
if (checkCommand("triggerEvent", TRIGGER_EVENT))
{
mEventId = mArgs->getOption(mCommandName);
......@@ -199,7 +204,7 @@ CommandOptions::CommandOptions()
}
if (mArgs->isSet("disable-all"))
{
if (mCommand == TRIGGER_EVENT)
if (mCommand == TRIGGER_EVENT || mCommand == LIST)
setErrorIncompatible("--disable-all", mCommandName);
mDisableAll = true;
}
......@@ -255,7 +260,7 @@ CommandOptions::CommandOptions()
if (mArgs->isSet("time"))
{
QByteArray dateTime = mArgs->getOption("time").toLocal8Bit();
if (!KAlarm::convertTimeString(dateTime, mAlarmTime))
if (!AlarmTime::convertTimeString(dateTime, mAlarmTime))
setErrorParameter("--time");
}
else
......@@ -294,9 +299,9 @@ CommandOptions::CommandOptions()
QByteArray dateTime = mArgs->getOption("until").toLocal8Bit();
bool ok;
if (mArgs->isSet("time"))
ok = KAlarm::convertTimeString(dateTime, endTime, mAlarmTime);
ok = AlarmTime::convertTimeString(dateTime, endTime, mAlarmTime);
else
ok = KAlarm::convertTimeString(dateTime, endTime);
ok = AlarmTime::convertTimeString(dateTime, endTime);
if (!ok)
setErrorParameter("--until");
else if (mAlarmTime.isDateOnly() && !endTime.isDateOnly())
......
/*
* commandoptions.h - extract command line options
* Program: kalarm
* Copyright © 2001-2011 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2012 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
......@@ -47,7 +47,8 @@ class CommandOptions
EDIT, // --edit
EDIT_NEW_PRESET, // --edit-new-preset
EDIT_NEW, // --edit-new-display, --edit-new-command, --edit-new-email
NEW // --file, --exec-display, --exec, --mail, message
NEW, // --file, --exec-display, --exec, --mail, message
LIST // --list
};
CommandOptions();
Command command() const { return mCommand; }
......
......@@ -21,6 +21,7 @@
#include "kalarm.h"
#include "alarmcalendar.h"
#include "alarmtime.h"
#include "functions.h"
#include "kalarmapp.h"
#include "kamail.h"
......@@ -445,7 +446,7 @@ KDateTime DBusHandler::convertDateTime(const QString& dateTime, const KDateTime&
}
KDateTime result;
if (!error)
result = KAlarm::applyTimeZone(zone, date, time, haveTime, defaultDt);
result = AlarmTime::applyTimeZone(zone, date, time, haveTime, defaultDt);
if (error || !result.isValid())
{
if (!defaultDt.isValid())
......
/*
* eventlistmodel.cpp - model class for lists of alarms or templates
* Program: kalarm
* Copyright © 2007-2011 by David Jarvie <djarvie@kde.org>
* Copyright © 2007-2012 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
......@@ -23,6 +23,7 @@
#include "resources/alarmresource.h"
#include "resources/alarmresources.h"
#include "alarmcalendar.h"
#include "alarmtime.h"
#include "preferences.h"
#include "synchtimer.h"
#include "eventlistmodel.moc"
......@@ -149,7 +150,7 @@ QVariant EventListModel::data(const QModelIndex& index, int role) const
case Qt::DisplayRole:
{
DateTime due = event->expired() ? event->startDateTime() : event->nextTrigger(KAEvent::DISPLAY_TRIGGER);
return alarmTimeText(due);
return AlarmTime::alarmTimeText(due);
}
case SortRole:
{
......@@ -170,7 +171,7 @@ QVariant EventListModel::data(const QModelIndex& index, int role) const
case Qt::DisplayRole:
if (event->expired())
return QString();
return timeToAlarmText(event->nextTrigger(KAEvent::DISPLAY_TRIGGER));
return AlarmTime::timeToAlarmText(event->nextTrigger(KAEvent::DISPLAY_TRIGGER));
case SortRole:
{
if (event->expired())
......@@ -819,71 +820,6 @@ KAEvent* EventListModel::event(const QModelIndex& index)
return static_cast<KAEvent*>(index.internalPointer());
}
/******************************************************************************
* Return the alarm time text in the form "date time".
*/
QString EventListModel::alarmTimeText(const DateTime& dateTime) const
{
if (!dateTime.isValid())
return i18nc("@info/plain Alarm never occurs", "Never");
KLocale* locale = KGlobal::locale();
KDateTime kdt = dateTime.effectiveKDateTime().toTimeSpec(Preferences::timeZone());
QString dateTimeText = locale->formatDate(kdt.date(), KLocale::ShortDate);
if (!dateTime.isDateOnly()
|| (!dateTime.isClockTime() && kdt.utcOffset() != dateTime.utcOffset()))
{
// Display the time of day if it's a date/time value, or if it's
// a date-only value but it's in a different time zone
dateTimeText += QLatin1Char(' ');
QString time = locale->formatTime(kdt.time());
if (mTimeHourPos == -2)
{
// Initialise the position of the hour within the time string, if leading
// zeroes are omitted, so that displayed times can be aligned with each other.
mTimeHourPos = -1; // default = alignment isn't possible/sensible
if (QApplication::isLeftToRight()) // don't try to align right-to-left languages
{
QString fmt = locale->timeFormat();
int i = fmt.indexOf(QRegExp("%[kl]")); // check if leading zeroes are omitted
if (i >= 0 && i == fmt.indexOf(QLatin1Char('%'))) // and whether the hour is first
mTimeHourPos = i; // yes, so need to align
}
}
if (mTimeHourPos >= 0 && (int)time.length() > mTimeHourPos + 1
&& time[mTimeHourPos].isDigit() && !time[mTimeHourPos + 1].isDigit())
dateTimeText += QLatin1Char('~'); // improve alignment of times with no leading zeroes
dateTimeText += time;
}
return dateTimeText + QLatin1Char(' ');
}
/******************************************************************************
* Return the time-to-alarm text.
*/
QString EventListModel::timeToAlarmText(const DateTime& dateTime) const
{
if (!dateTime.isValid())
return i18nc("@info/plain Alarm never occurs", "Never");
KDateTime now = KDateTime::currentUtcDateTime();
if (dateTime.isDateOnly())
{
int days = now.date().daysTo(dateTime.date());
// xgettext: no-c-format
return i18nc("@info/plain n days", "%1d", days);
}
int mins = (now.secsTo(dateTime.effectiveKDateTime()) + 59) / 60;
if (mins < 0)
return QString();
char minutes[3] = "00";
minutes[0] = (mins%60) / 10 + '0';
minutes[1] = (mins%60) % 10 + '0';
if (mins < 24*60)