mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 10:52:52 +00:00
444 lines
14 KiB
C++
444 lines
14 KiB
C++
/*
|
|
* alarmresource.cpp - base class for a KAlarm alarm calendar resource
|
|
* Program: kalarm
|
|
* Copyright © 2006-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
|
|
* 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 "kalarm.h"
|
|
|
|
#include "alarmresource.moc"
|
|
using namespace KCal;
|
|
#include "alarmresources.h"
|
|
|
|
#include <kabc/lock.h>
|
|
#include <kabc/locknull.h>
|
|
#include <kcal/calendarlocal.h>
|
|
|
|
#include <kconfig.h>
|
|
#include <kconfiggroup.h>
|
|
#include <klocale.h>
|
|
#include <kstandarddirs.h>
|
|
|
|
|
|
|
|
void (*AlarmResource::mCalIDFunction)(CalendarLocal&) = 0;
|
|
void (*AlarmResource::mCustomEventFunction)(AlarmResource*, CalendarLocal*) = 0;
|
|
KACalendar::Compat (*AlarmResource::mFixFunction)(CalendarLocal&, const QString&, AlarmResource*, AlarmResource::FixFunc, bool* wrongType) = 0;
|
|
int AlarmResource::mDebugArea = 0;
|
|
bool AlarmResource::mNoGui = false;
|
|
|
|
|
|
AlarmResource::AlarmResource()
|
|
: ResourceCached(),
|
|
mLock(0),
|
|
mType(static_cast<CalEvent::Type>(0)), // invalid
|
|
mStandard(false),
|
|
mCloseAfterSave(false),
|
|
mWrongAlarmType(false),
|
|
mCompatibility(KACalendar::Incompatible),
|
|
mReconfiguring(0),
|
|
mLoaded(false),
|
|
mLoading(false)
|
|
{
|
|
// Prevent individual events being set read-only when loading a read-only resource
|
|
setNoReadOnlyOnLoad(true);
|
|
init();
|
|
}
|
|
|
|
AlarmResource::AlarmResource(const KConfigGroup& group)
|
|
: ResourceCached(group),
|
|
mLock(0),
|
|
mType(static_cast<CalEvent::Type>(0)), // invalid
|
|
mStandard(false),
|
|
mCloseAfterSave(false),
|
|
mWrongAlarmType(false),
|
|
mCompatibility(KACalendar::Incompatible),
|
|
mReconfiguring(0),
|
|
mLoaded(false),
|
|
mLoading(false)
|
|
{
|
|
// Prevent individual events being set read-only when loading a read-only resource
|
|
setNoReadOnlyOnLoad(true);
|
|
|
|
ResourceCached::readConfig(group);
|
|
int type = group.readEntry("AlarmType", static_cast<int>(CalEvent::ACTIVE));
|
|
switch (type)
|
|
{
|
|
case CalEvent::ACTIVE:
|
|
case CalEvent::ARCHIVED:
|
|
case CalEvent::TEMPLATE:
|
|
mType = static_cast<CalEvent::Type>(type);
|
|
mStandard = group.readEntry("Standard", true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
mColour = group.readEntry("Color", QColor());
|
|
init();
|
|
}
|
|
|
|
AlarmResource::AlarmResource(CalEvent::Type type)
|
|
: ResourceCached(),
|
|
mLock(0),
|
|
mType(type),
|
|
mStandard(false),
|
|
mCloseAfterSave(false),
|
|
mCompatibility(KACalendar::Incompatible),
|
|
mReconfiguring(0),
|
|
mLoaded(false),
|
|
mLoading(false)
|
|
{
|
|
init();
|
|
}
|
|
|
|
void AlarmResource::init()
|
|
{
|
|
enableChangeNotification();
|
|
if (mType == CalEvent::ARCHIVED)
|
|
{
|
|
// Prevent unnecessary multiple saves of archived alarm resources.
|
|
// When multiple alarms are deleted as a group, the archive
|
|
// resource would be saved once for each alarm. Ironically, setting
|
|
// the resource to be automatically saved will prevent this, since
|
|
// automatic saving delays for a second after each change before
|
|
// actually saving the resource, thereby ensuring that they are
|
|
// saved as a group.
|
|
setSavePolicy(SaveAlways);
|
|
}
|
|
}
|
|
|
|
AlarmResource::~AlarmResource()
|
|
{
|
|
delete mLock;
|
|
}
|
|
|
|
void AlarmResource::writeConfig(KConfigGroup& group)
|
|
{
|
|
group.writeEntry("AlarmType", static_cast<int>(mType));
|
|
if (mColour.isValid())
|
|
group.writeEntry("Color", mColour);
|
|
else
|
|
group.deleteEntry("Color");
|
|
group.writeEntry("Standard", mStandard);
|
|
ResourceCached::writeConfig(group);
|
|
ResourceCalendar::writeConfig(group);
|
|
}
|
|
|
|
void AlarmResource::startReconfig()
|
|
{
|
|
mOldReadOnly = ResourceCached::readOnly();
|
|
mNewReadOnly = mOldReadOnly;
|
|
mReconfiguring = 1;
|
|
}
|
|
|
|
void AlarmResource::applyReconfig()
|
|
{
|
|
if (!mReconfiguring)
|
|
return;
|
|
if (mReconfiguring == 1)
|
|
{
|
|
// Called before derived classes do their stuff
|
|
ResourceCached::setReadOnly(mNewReadOnly);
|
|
mReconfiguring = 2;
|
|
}
|
|
else
|
|
{
|
|
// Called when derived classes have done their stuff
|
|
setReadOnly(mNewReadOnly);
|
|
mReconfiguring = 0;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* If a function is defined to convert alarms to the current format, call it.
|
|
* Set the resource to read-only if it isn't the current format version, or if
|
|
* its format is unknown.
|
|
*/
|
|
void AlarmResource::checkCompatibility(const QString& filename)
|
|
{
|
|
bool wrongType = false;
|
|
bool oldReadOnly = readOnly();
|
|
mCompatibility = KACalendar::Incompatible; // assume the worst
|
|
if (mFixFunction)
|
|
{
|
|
// Check whether the version is compatible (and convert it if desired)
|
|
mCompatibility = (*mFixFunction)(*calendar(), filename, this, PROMPT, &wrongType);
|
|
if (wrongType)
|
|
kDebug(KARES_DEBUG) << resourceName() << ": contains wrong alarm type(s)";
|
|
if (mCompatibility == KACalendar::Converted)
|
|
{
|
|
// Set mCompatibility first to ensure that readOnly() returns
|
|
// the correct value and that save() therefore works.
|
|
mCompatibility = KACalendar::Current;
|
|
save();
|
|
}
|
|
if (mCompatibility != KACalendar::Current && mCompatibility != KACalendar::ByEvent)
|
|
{
|
|
// It's not in the current KAlarm format, so it will be read-only to prevent incompatible updates
|
|
kDebug(KARES_DEBUG) << resourceName() << ": opened read-only (not current KAlarm format)";
|
|
}
|
|
}
|
|
setWrongAlarmType(wrongType);
|
|
if (readOnly() != oldReadOnly)
|
|
emit readOnlyChanged(this); // the effective read-only status has changed
|
|
}
|
|
|
|
/******************************************************************************
|
|
* If a function is defined to convert alarms to the current format, call it to
|
|
* convert an individual file within the overall resource.
|
|
*/
|
|
KACalendar::Compat AlarmResource::checkCompatibility(CalendarLocal& calendar, const QString& filename, FixFunc conv, bool* wrongType)
|
|
{
|
|
if (wrongType)
|
|
*wrongType = false;
|
|
KACalendar::Compat compat = KACalendar::Incompatible; // assume the worst
|
|
if (mFixFunction)
|
|
{
|
|
// Check whether the version is compatible (and convert it if desired)
|
|
compat = (*mFixFunction)(calendar, filename, this, conv, wrongType);
|
|
if (compat == KACalendar::Converted)
|
|
calendar.save(filename);
|
|
}
|
|
return compat;
|
|
}
|
|
|
|
KACalendar::Compat AlarmResource::compatibility(const Event* event) const
|
|
{
|
|
if (mCompatibility != KACalendar::ByEvent)
|
|
return mCompatibility;
|
|
CompatibilityMap::ConstIterator it = mCompatibilityMap.find(event);
|
|
if (it == mCompatibilityMap.constEnd())
|
|
return KACalendar::Incompatible; // event not found!?! - assume the worst
|
|
return it.value();
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Set whether the resource contains only the wrong alarm types.
|
|
* If the wrong types, disable the resource.
|
|
*/
|
|
void AlarmResource::setWrongAlarmType(bool wrongType, bool emitSignal)
|
|
{
|
|
if (wrongType != mWrongAlarmType)
|
|
{
|
|
mWrongAlarmType = wrongType;
|
|
if (emitSignal)
|
|
emit wrongAlarmTypeChanged(this);
|
|
if (mWrongAlarmType)
|
|
setEnabled(false);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* If a function is defined to update KAlarm event instances, call it.
|
|
*/
|
|
void AlarmResource::updateCustomEvents(bool useCalendar)
|
|
{
|
|
if (mCustomEventFunction && isEnabled())
|
|
(*mCustomEventFunction)(this, useCalendar ? calendar() : 0);
|
|
}
|
|
|
|
bool AlarmResource::writable(const Event* event) const
|
|
{
|
|
return isActive() && !KCal::ResourceCached::readOnly()
|
|
&& compatibility(event) == KACalendar::Current;
|
|
}
|
|
|
|
bool AlarmResource::readOnly() const
|
|
{
|
|
return KCal::ResourceCached::readOnly()
|
|
|| (isActive() && mCompatibility != KACalendar::Current && mCompatibility != KACalendar::ByEvent);
|
|
}
|
|
|
|
void AlarmResource::setReadOnly(bool ronly)
|
|
{
|
|
if (mReconfiguring == 1)
|
|
{
|
|
mNewReadOnly = ronly;
|
|
return;
|
|
}
|
|
kDebug(KARES_DEBUG) << ronly;
|
|
bool oldRCronly = (mReconfiguring == 2) ? mOldReadOnly : ResourceCached::readOnly();
|
|
bool oldronly = (oldRCronly || (mCompatibility != KACalendar::Current && mCompatibility != KACalendar::ByEvent));
|
|
if (!ronly && isActive())
|
|
{
|
|
// Trying to change the resource to read-write.
|
|
// Only allow this if it is in, or can be converted to, the current KAlarm format.
|
|
switch (mCompatibility)
|
|
{
|
|
case KACalendar::Incompatible:
|
|
emit notWritable(this); // allow an error message to be output
|
|
return;
|
|
case KACalendar::Convertible:
|
|
if (mReconfiguring <= 2)
|
|
{
|
|
if (!isOpen())
|
|
return;
|
|
load(NoSyncCache); // give user the option of converting it
|
|
}
|
|
if (mCompatibility != KACalendar::Current)
|
|
return; // not converted, so keep as read-only
|
|
break;
|
|
case KACalendar::Current:
|
|
case KACalendar::ByEvent:
|
|
case KACalendar::Converted: // shouldn't ever happen
|
|
break;
|
|
}
|
|
}
|
|
if (ronly != oldRCronly)
|
|
ResourceCached::setReadOnly(ronly);
|
|
if ((ronly || (mCompatibility != KACalendar::Current && mCompatibility != KACalendar::ByEvent)) != oldronly)
|
|
emit readOnlyChanged(this); // the effective read-only status has changed
|
|
}
|
|
|
|
void AlarmResource::setEnabled(bool enable)
|
|
{
|
|
if (mWrongAlarmType)
|
|
enable = false;
|
|
if (isActive() != enable)
|
|
{
|
|
setActive(enable);
|
|
enableResource(enable);
|
|
emit enabledChanged(this);
|
|
}
|
|
}
|
|
|
|
void AlarmResource::setColour(const QColor& colour)
|
|
{
|
|
if (colour != mColour)
|
|
{
|
|
mColour = colour;
|
|
emit colourChanged(this);
|
|
}
|
|
}
|
|
|
|
bool AlarmResource::saveAndClose(CacheAction action, Incidence* incidence)
|
|
{
|
|
bool result = save(action, incidence);
|
|
if (isSaving())
|
|
mCloseAfterSave = true; // ensure it's closed if saving is asynchronous
|
|
else
|
|
close();
|
|
return result;
|
|
}
|
|
|
|
void AlarmResource::doClose()
|
|
{
|
|
mCloseAfterSave = false;
|
|
emit invalidate(this);
|
|
KCal::ResourceCached::doClose();
|
|
mLoaded = mLoading = false;
|
|
mCompatibilityMap.clear();
|
|
}
|
|
|
|
QString AlarmResource::infoText() const
|
|
{
|
|
KRES::Factory* factory = KRES::Factory::self("alarms");
|
|
QString atype;
|
|
switch (mType)
|
|
{
|
|
case CalEvent::ACTIVE: atype = i18nc("@info/plain", "Active alarms"); break;
|
|
case CalEvent::ARCHIVED: atype = i18nc("@info/plain", "Archived alarms"); break;
|
|
case CalEvent::TEMPLATE: atype = i18nc("@info/plain", "Alarm templates"); break;
|
|
default: break;
|
|
}
|
|
QString perms = readOnly() ? i18nc("@info/plain", "Read-only") : i18nc("@info/plain", "Read-write");
|
|
QString enabled = isEnabled() ? i18nc("@info/plain", "Enabled") : mWrongAlarmType ? i18nc("@info/plain", "Disabled (wrong alarm type)") : i18nc("@info/plain", "Disabled");
|
|
QString std = (AlarmResources::instance()->getStandardResource(mType) == this) ? i18nc("@info/plain Parameter in 'Default calendar: Yes/No'", "Yes") : i18nc("@info/plain Parameter in 'Default calendar: Yes/No'", "No");
|
|
return i18nc("@info",
|
|
"<title>%1</title>"
|
|
"<para>Calendar type: %2<nl/>"
|
|
"Contents: %3<nl/>"
|
|
"%4: <filename>%5</filename><nl/>"
|
|
"Permissions: %6<nl/>"
|
|
"Status: %7<nl/>"
|
|
"Default calendar: %8</para>",
|
|
resourceName(), factory->typeName(type()), atype, displayType(), displayLocation(), perms, enabled, std);
|
|
}
|
|
|
|
void AlarmResource::lock(const QString& path)
|
|
{
|
|
delete mLock;
|
|
if (path.isNull())
|
|
mLock = 0;
|
|
else if (path.isEmpty())
|
|
mLock = new KABC::LockNull(true);
|
|
else
|
|
mLock = new KABC::Lock(path);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Check whether the alarm types in a calendar correspond with the resource's
|
|
* alarm type.
|
|
* Reply = true if at least 1 alarm is the right type.
|
|
*/
|
|
bool AlarmResource::checkAlarmTypes(KCal::CalendarLocal& calendar) const
|
|
{
|
|
if (mType != CalEvent::EMPTY)
|
|
{
|
|
bool have = false;
|
|
bool other = false;
|
|
const Event::List events = calendar.rawEvents();
|
|
for (int i = 0, iend = events.count(); i < iend; ++i)
|
|
{
|
|
CalEvent::Type s = CalEvent::status(events[i]);
|
|
if (mType == s)
|
|
have = true;
|
|
else
|
|
other = true;
|
|
if (have && other)
|
|
break;
|
|
}
|
|
if (!have && other)
|
|
return false; // contains only wrong alarm types
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
void AlarmResource::kaCheckCalendar(CalendarLocal& cal)
|
|
{
|
|
mTypes = CalEvent::EMPTY;
|
|
Event::List events = cal.rawEvents();
|
|
for (int i = 0, iend = events.count(); i < iend; ++i)
|
|
{
|
|
switch (CalEvent::status(events[i]))
|
|
{
|
|
case CalEvent::ACTIVE: mTypes = static_cast<CalEvent::Type>(mTypes | CalEvent::ACTIVE); break;
|
|
case CalEvent::ARCHIVED: mTypes = static_cast<CalEvent::Type>(mTypes | CalEvent::ARCHIVED); break;
|
|
case CalEvent::TEMPLATE: mTypes = static_cast<CalEvent::Type>(mTypes | CalEvent::TEMPLATE); break;
|
|
default: break;
|
|
}
|
|
if (mTypes == CalEvent::ALL)
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
#ifndef NDEBUG
|
|
QByteArray AlarmResource::typeName() const
|
|
{
|
|
switch (mType)
|
|
{
|
|
case CalEvent::ACTIVE: return "Active";
|
|
case CalEvent::ARCHIVED: return "Archived";
|
|
case CalEvent::TEMPLATE: return "Template";
|
|
default: return "Empty";
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// vim: et sw=4:
|