Commit ec0f679a authored by David Jarvie's avatar David Jarvie
Browse files

Move functions in alarmtime.cpp into functions.cpp & resourcedatamodelbase.cpp

Move functions in alarmtime.cpp which are only used in
resourcedatamodelbase.cpp into that file.
Move the remaining functions in alarmtime.cpp into functions.cpp.
parent cfcf2196
......@@ -75,7 +75,6 @@ set(kalarm_bin_SRCS ${libkalarm_SRCS}
functions.cpp
fontcolour.cpp
fontcolourbutton.cpp
alarmtime.cpp
alarmtimewidget.cpp
specialactions.cpp
reminder.cpp
......
......@@ -642,10 +642,7 @@ bool ResourcesCalendar::addEvent(KAEvent& evnt, QWidget* promptParent, bool useE
{
res = Resources::destination(type, promptParent, noPrompt, cancelled);
if (!res.isValid())
{
const char* typeStr = (type == CalEvent::ACTIVE) ? "Active alarm" : (type == CalEvent::ARCHIVED) ? "Archived alarm" : "alarm Template";
qCWarning(KALARM_LOG) << "ResourcesCalendar::addEvent: Error! Cannot create" << typeStr << "(No default calendar is defined)";
}
qCWarning(KALARM_LOG) << "ResourcesCalendar::addEvent: Error! Cannot create" << type << "(No default calendar is defined)";
}
if (res.isValid())
{
......
/*
* alarmtime.cpp - conversion functions for alarm times
* Program: kalarm
* Copyright © 2007-2016,2018 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 "kalarm_debug.h"
#include <KAlarmCal/DateTime>
#include <KLocalizedString>
#include <QLocale>
#include <QApplication>
using namespace KAlarmCal;
// Whether the date and time contain leading zeroes.
QString AlarmTime::mDateFormat; // date format for current locale
QString AlarmTime::mTimeFormat; // time format for current locale
QString AlarmTime::mTimeFullFormat; // time format with leading zero, if different from mTimeFormat
int AlarmTime::mHourOffset = 0; // offset within time string to the hour
bool AlarmTime::mLeadingZeroesChecked = false;
/******************************************************************************
* Return the alarm time text in the form "date time".
* Parameters:
* dateTime = the date/time to format.
* leadingZero = the character to represent a leading zero, or '\0' for no leading zeroes.
*/
QString AlarmTime::alarmTimeText(const DateTime& dateTime, char leadingZero)
{
if (!dateTime.isValid())
return i18nc("@info Alarm never occurs", "Never");
if (!mLeadingZeroesChecked && QApplication::isLeftToRight()) // don't try to align right-to-left languages
{
// Check whether the day number and/or hour have no leading zeroes, if
// they are at the start of the date/time. If no leading zeroes, they
// will need to be padded when displayed, so that displayed dates/times
// can be aligned with each other.
// Note that if leading zeroes are not included in other components, no
// alignment will be attempted.
QLocale locale;
{
// Check the date format. 'dd' provides leading zeroes; single 'd'
// provides no leading zeroes.
mDateFormat = locale.dateFormat(QLocale::ShortFormat);
}
{
// Check the time format.
// Remove all but hours, minutes and AM/PM, since alarms are on minute
// boundaries. Preceding separators are also removed.
mTimeFormat = locale.timeFormat(QLocale::ShortFormat);
for (int del = 0, predel = 0, c = 0; c < mTimeFormat.size(); ++c)
{
char ch = mTimeFormat.at(c).toLatin1();
switch (ch)
{
case 'H':
case 'h':
case 'm':
case 'a':
case 'A':
if (predel == 1)
{
mTimeFormat.remove(del, c - del);
c = del;
}
del = c + 1; // start deleting from the next character
if ((ch == 'A' && del < mTimeFormat.size() && mTimeFormat.at(del).toLatin1() == 'P')
|| (ch == 'a' && del < mTimeFormat.size() && mTimeFormat.at(del).toLatin1() == 'p'))
++c, ++del;
predel = -1;
break;
case 's':
case 'z':
case 't':
mTimeFormat.remove(del, c + 1 - del);
c = del - 1;
if (!predel)
predel = 1;
break;
default:
break;
}
}
// 'HH' and 'hh' provide leading zeroes; single 'H' or 'h' provide no
// leading zeroes.
int i = mTimeFormat.indexOf(QRegExp(QLatin1String("[hH]")));
int first = mTimeFormat.indexOf(QRegExp(QLatin1String("[hHmaA]")));
if (i >= 0 && i == first && (i == mTimeFormat.size() - 1 || mTimeFormat.at(i) != mTimeFormat.at(i + 1)))
{
mTimeFullFormat = mTimeFormat;
mTimeFullFormat.insert(i, mTimeFormat.at(i));
// Find index to hour in formatted times
const QTime t(1,30,30);
const QString nozero = t.toString(mTimeFormat);
const QString zero = t.toString(mTimeFullFormat);
for (int i = 0; i < nozero.size(); ++i)
if (nozero[i] != zero[i])
{
mHourOffset = i;
break;
}
}
}
}
mLeadingZeroesChecked = true;
const KADateTime kdt = dateTime.effectiveKDateTime().toTimeSpec(Preferences::timeSpec());
QString dateTimeText = kdt.date().toString(mDateFormat);
if (!dateTime.isDateOnly() || 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(' ');
bool useFullFormat = leadingZero && !mTimeFullFormat.isEmpty();
QString timeText = kdt.time().toString(useFullFormat ? mTimeFullFormat : mTimeFormat);
if (useFullFormat && leadingZero != '0' && timeText.at(mHourOffset) == QLatin1Char('0'))
timeText[mHourOffset] = leadingZero;
dateTimeText += timeText;
}
return dateTimeText + QLatin1Char(' ');
}
/******************************************************************************
* Return the time-to-alarm text.
*/
QString AlarmTime::timeToAlarmText(const DateTime& dateTime)
{
if (!dateTime.isValid())
return i18nc("@info Alarm never occurs", "Never");
KADateTime now = KADateTime::currentUtcDateTime();
if (dateTime.isDateOnly())
{
int days = now.date().daysTo(dateTime.date());
// xgettext: no-c-format
return i18nc("@info 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 hours:minutes", "%1:%2", mins/60, QLatin1String(minutes));
// If we render a day count, then we zero-pad the hours, to make the days line up and be more scanable.
int hrs = mins / 60;
char hours[3] = "00";
hours[0] = (hrs%24) / 10 + '0';
hours[1] = (hrs%24) % 10 + '0';
int days = hrs / 24;
return i18nc("@info days hours:minutes", "%1d %2:%3", days, QLatin1String(hours), QLatin1String(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, KADateTime& dateTime, const KADateTime& 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).constData());
int dt[5] = { -1, -1, -1, -1, -1 };
char* s;
char* end;
bool noTime;
// Get the minute value
if ((s = strchr(timeStr, ':')) == nullptr)
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, '-')) == nullptr)
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, '-')) == nullptr)
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, '-')) == nullptr)
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.setDate(dt[0],
(dt[1] < 0 ? defaultDt.date().month() : dt[1]),
(dt[2] < 0 ? defaultDt.date().day() : dt[2]));
}
else
date.setDate(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.
const KADateTime now = KADateTime::currentDateTime(dateTime.timeSpec());
date = dateTime.date();
date.setDate(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" or
* "UTC". 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.
*/
KADateTime AlarmTime::applyTimeZone(const QString& tzstring, const QDate& date, const QTime& time,
bool haveTime, const KADateTime& defaultDt)
{
bool error = false;
KADateTime::Spec spec = KADateTime::LocalZone;
const QString zone = tzstring.trimmed();
if (!zone.isEmpty())
{
if (zone == QLatin1String("UTC"))
spec = KADateTime::UTC;
else
{
const QTimeZone tz(zone.toLatin1());
error = !tz.isValid();
if (!error)
spec = tz;
}
}
else if (defaultDt.isValid())
spec = defaultDt.timeSpec();
KADateTime result;
if (!error)
{
if (!date.isValid())
{
// It's a time without a date
if (defaultDt.isValid())
result = KADateTime(defaultDt.date(), time, spec);
else if (spec == KADateTime::LocalZone)
result = KADateTime(KADateTime::currentLocalDate(), time, spec);
}
else if (haveTime)
{
// It's a date and time
result = KADateTime(date, time, spec);
}
else
{
// It's a date without a time
result = KADateTime(date, spec);
}
}
return result;
}
// vim: et sw=4:
/*
* alarmtime.h - conversion functions for alarm times
* Program: kalarm
* Copyright © 2012,2018 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.
*/
#ifndef ALARMTIME_H
#define ALARMTIME_H
#include <KAlarmCal/KADateTime>
namespace KAlarmCal { class DateTime; }
using namespace KAlarmCal;
class AlarmTime
{
public:
static QString alarmTimeText(const DateTime& dateTime, char leadingZero = '\0');
static QString timeToAlarmText(const DateTime& dateTime);
static bool convertTimeString(const QByteArray& timeString, KADateTime& dateTime,
const KADateTime& defaultDt = KADateTime(), bool allowTZ = true);
static KADateTime applyTimeZone(const QString& tzstring, const QDate& date, const QTime& time,
bool haveTime, const KADateTime& defaultDt = KADateTime());
private:
static QString mDateFormat;
static QString mTimeFormat;
static QString mTimeFullFormat;
static int mHourOffset;
static bool mLeadingZeroesChecked;
};
#endif // ALARMTIME_H
// vim: et sw=4:
/*
* commandoptions.cpp - extract command line options
* Program: kalarm
* Copyright © 2001-2019 David Jarvie <djarvie@kde.org>
* Copyright © 2001-2020 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 "commandoptions.h"
#include "alarmtime.h"
#include "functions.h"
#include "kalarmapp.h"
#include "kamail.h"
#include "kalarm_debug.h"
......@@ -255,7 +255,7 @@ void CommandOptions::process()
if (mParser->isSet(*mOptions.at(TEST_SET_TIME)))
{
const QString time = mParser->value(*mOptions.at(TEST_SET_TIME));
if (!AlarmTime::convertTimeString(time.toLatin1(), mSimulationTime, KADateTime::realCurrentLocalDateTime(), true))
if (!KAlarm::convertTimeString(time.toLatin1(), mSimulationTime, KADateTime::realCurrentLocalDateTime(), true))
setErrorParameter(TEST_SET_TIME);
}
#endif
......@@ -442,7 +442,7 @@ void CommandOptions::process()
if (mParser->isSet(*mOptions.at(TIME)))
{
const QByteArray dateTime = mParser->value(*mOptions.at(TIME)).toLocal8Bit();
if (!AlarmTime::convertTimeString(dateTime, mAlarmTime))
if (!KAlarm::convertTimeString(dateTime, mAlarmTime))
setErrorParameter(TIME);
}
else
......@@ -481,9 +481,9 @@ void CommandOptions::process()
const QByteArray dateTime = mParser->value(*mOptions.at(UNTIL)).toLocal8Bit();
bool ok;
if (mParser->isSet(*mOptions.at(TIME)))
ok = AlarmTime::convertTimeString(dateTime, endTime, mAlarmTime);
ok = KAlarm::convertTimeString(dateTime, endTime, mAlarmTime);
else
ok = AlarmTime::convertTimeString(dateTime, endTime);
ok = KAlarm::convertTimeString(dateTime, endTime);
if (!ok)
setErrorParameter(UNTIL);
else if (mAlarmTime.isDateOnly() && !endTime.isDateOnly())
......
/*
* dbushandler.cpp - handler for D-Bus calls by other applications
* Program: kalarm
* Copyright © 2002-2019 David Jarvie <djarvie@kde.org>
* Copyright © 2002-2020 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
......@@ -21,7 +21,6 @@
#include "dbushandler.h"
#include "alarmcalendar.h"
#include "alarmtime.h"
#include "functions.h"
#include "kalarmapp.h"
#include "kamail.h"
......@@ -461,7 +460,7 @@ KADateTime DBusHandler::convertDateTime(const QString& dateTime, const KADateTim
}
KADateTime result;
if (!error)
result = AlarmTime::applyTimeZone(zone, date, time, haveTime, defaultDt);
result = KAlarm::applyTimeZone(zone, date, time, haveTime, defaultDt);
if (error || !result.isValid())
{
if (!defaultDt.isValid())
......
......@@ -23,7 +23,6 @@
#include "akonadicollectionsearch.h"
#include "alarmcalendar.h"
#include "alarmtime.h"
#include "editdlg.h"
#include "kalarmapp.h"
#include "kamail.h"
......@@ -1608,6 +1607,184 @@ void setDontShowErrors(const EventId& eventId, const QString& tag)
}
}
/******************************************************************************
* 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 convertTimeString(const QByteArray& timeString, KADateTime& dateTime, const KADateTime& 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).constData());
int dt[5] = { -1, -1, -1, -1, -1 };
char* s;
char* end;
bool noTime;
// Get the minute value
if ((s = strchr(timeStr, ':')) == nullptr)
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, '-')) == nullptr)
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, '-')) == nullptr)
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, '-')) == nullptr)
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.setDate(dt[0],
(dt[1] < 0 ? defaultDt.date().month() : dt[1]),
(dt[2] < 0 ? defaultDt.date().day() : dt[2]));
}
else