2
#warning Update a calendar format, enable the calendar, copy old version on top -> crash
3
#warning Add a directory resource containing 2 alarm types, right click on it -> crash
4
#warning Set default template calendar to read-only -> crash
5
#warning Set default archived calendar to read-only, then read-write -> now "other format"
6
#warning Create new email template, get valgrind uninitialised errors from serialize()
2
9
* akonadimodel.cpp - KAlarm calendar file access using Akonadi
21
28
#include "akonadimodel.h"
22
#include "alarmtext.h"
23
29
#include "autoqpointer.h"
24
30
#include "calendarmigrator.h"
25
#include "collectionattribute.h"
26
#include "compatibilityattribute.h"
27
#include "eventattribute.h"
31
#include "mainwindow.h"
28
32
#include "messagebox.h"
29
33
#include "preferences.h"
30
34
#include "synchtimer.h"
35
#include "kalarmsettings.h"
31
36
#include "kalarmdirsettings.h"
38
#include <kalarmcal/alarmtext.h>
39
#include <kalarmcal/collectionattribute.h>
40
#include <kalarmcal/compatibilityattribute.h>
41
#include <kalarmcal/eventattribute.h>
33
43
#include <akonadi/agentfilterproxymodel.h>
34
44
#include <akonadi/agentinstancecreatejob.h>
35
45
#include <akonadi/agentmanager.h>
98
107
monitor->setCollectionMonitored(Collection::root());
99
108
monitor->setResourceMonitored("akonadi_kalarm_resource");
100
109
monitor->setResourceMonitored("akonadi_kalarm_dir_resource");
101
monitor->setMimeTypeMonitored(KAlarm::MIME_ACTIVE);
102
monitor->setMimeTypeMonitored(KAlarm::MIME_ARCHIVED);
103
monitor->setMimeTypeMonitored(KAlarm::MIME_TEMPLATE);
110
monitor->setMimeTypeMonitored(KAlarmCal::MIME_ACTIVE);
111
monitor->setMimeTypeMonitored(KAlarmCal::MIME_ARCHIVED);
112
monitor->setMimeTypeMonitored(KAlarmCal::MIME_TEMPLATE);
104
113
monitor->itemFetchScope().fetchFullPayload();
105
114
monitor->itemFetchScope().fetchAttribute<EventAttribute>();
122
131
#warning Only want to monitor collection properties, not content, when this becomes possible
124
connect(monitor, SIGNAL(collectionChanged(const Akonadi::Collection&, const QSet<QByteArray>&)), SLOT(slotCollectionChanged(const Akonadi::Collection&, const QSet<QByteArray>&)));
125
connect(monitor, SIGNAL(collectionRemoved(const Akonadi::Collection&)), SLOT(slotCollectionRemoved(const Akonadi::Collection&)));
133
connect(monitor, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)), SLOT(slotCollectionChanged(Akonadi::Collection,QSet<QByteArray>)));
134
connect(monitor, SIGNAL(collectionRemoved(Akonadi::Collection)), SLOT(slotCollectionRemoved(Akonadi::Collection)));
135
connect(CalendarMigrator::instance(), SIGNAL(creating(QString,bool)), SLOT(slotCollectionBeingCreated(QString,bool)));
126
136
MinuteTimer::connect(this, SLOT(slotUpdateTimeTo()));
127
Preferences::connect(SIGNAL(archivedColourChanged(const QColor&)), this, SLOT(slotUpdateArchivedColour(const QColor&)));
128
Preferences::connect(SIGNAL(disabledColourChanged(const QColor&)), this, SLOT(slotUpdateDisabledColour(const QColor&)));
129
Preferences::connect(SIGNAL(holidaysChanged(const KHolidays::HolidayRegion&)), this, SLOT(slotUpdateHolidays()));
130
Preferences::connect(SIGNAL(workTimeChanged(const QTime&, const QTime&, const QBitArray&)), this, SLOT(slotUpdateWorkingHours()));
137
Preferences::connect(SIGNAL(archivedColourChanged(QColor)), this, SLOT(slotUpdateArchivedColour(QColor)));
138
Preferences::connect(SIGNAL(disabledColourChanged(QColor)), this, SLOT(slotUpdateDisabledColour(QColor)));
139
Preferences::connect(SIGNAL(holidaysChanged(KHolidays::HolidayRegion)), this, SLOT(slotUpdateHolidays()));
140
Preferences::connect(SIGNAL(workTimeChanged(QTime,QTime,QBitArray)), this, SLOT(slotUpdateWorkingHours()));
132
connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(slotRowsInserted(const QModelIndex&, int, int)));
133
connect(this, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), SLOT(slotRowsAboutToBeRemoved(const QModelIndex&, int, int)));
134
connect(monitor, SIGNAL(itemChanged(const Akonadi::Item&, const QSet<QByteArray>&)), SLOT(slotMonitoredItemChanged(const Akonadi::Item&, const QSet<QByteArray>&)));
142
connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(slotRowsInserted(QModelIndex,int,int)));
143
connect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)));
144
connect(monitor, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)), SLOT(slotMonitoredItemChanged(Akonadi::Item,QSet<QByteArray>)));
136
146
// Check whether there are any KAlarm resources configured
137
147
bool found = false;
212
223
case Qt::ForegroundRole:
214
QStringList mimeTypes = collection.contentMimeTypes();
215
if (mimeTypes.contains(KAlarm::MIME_ACTIVE))
216
return (collection.rights() & writableRights) == writableRights ? Qt::black : Qt::darkGray;
217
if (mimeTypes.contains(KAlarm::MIME_ARCHIVED))
218
return (collection.rights() & writableRights) == writableRights ? Qt::darkGreen : Qt::green;
219
if (mimeTypes.contains(KAlarm::MIME_TEMPLATE))
220
return (collection.rights() & writableRights) == writableRights ? Qt::darkBlue : Qt::blue;
224
return foregroundColor(collection, collection.contentMimeTypes());
223
225
case Qt::ToolTipRole:
224
return tooltip(collection, KAlarm::CalEvent::ALL);
226
return tooltip(collection, CalEvent::ACTIVE | CalEvent::ARCHIVED | CalEvent::TEMPLATE);
225
227
case AlarmTypeRole:
226
228
return static_cast<int>(types(collection));
227
229
case IsStandardRole:
241
247
// This is an Item row
242
248
QString mime = item.mimeType();
243
if ((mime != KAlarm::MIME_ACTIVE && mime != KAlarm::MIME_ARCHIVED && mime != KAlarm::MIME_TEMPLATE)
249
if ((mime != KAlarmCal::MIME_ACTIVE && mime != KAlarmCal::MIME_ARCHIVED && mime != KAlarmCal::MIME_TEMPLATE)
244
250
|| !item.hasPayload<KAEvent>())
245
251
return QVariant();
249
255
// Mime type has a one-to-one relationship to event's category()
250
if (mime == KAlarm::MIME_ACTIVE)
251
return KAlarm::CalEvent::ACTIVE;
252
if (mime == KAlarm::MIME_ARCHIVED)
253
return KAlarm::CalEvent::ARCHIVED;
254
if (mime == KAlarm::MIME_TEMPLATE)
255
return KAlarm::CalEvent::TEMPLATE;
256
if (mime == KAlarmCal::MIME_ACTIVE)
257
return CalEvent::ACTIVE;
258
if (mime == KAlarmCal::MIME_ARCHIVED)
259
return CalEvent::ARCHIVED;
260
if (mime == KAlarmCal::MIME_TEMPLATE)
261
return CalEvent::TEMPLATE;
256
262
return QVariant();
257
263
case CommandErrorRole:
258
264
if (!item.hasAttribute<EventAttribute>())
340
346
case Qt::BackgroundRole:
341
if (event.action() == KAEvent::MESSAGE
342
|| event.action() == KAEvent::FILE
343
|| (event.action() == KAEvent::COMMAND && event.commandDisplay()))
348
KAEvent::Actions type = event.actionTypes();
349
if (type & KAEvent::ACT_DISPLAY)
344
350
return event.bgColour();
345
if (event.action() == KAEvent::COMMAND)
351
if (type == KAEvent::ACT_COMMAND)
347
353
if (event.commandError() != KAEvent::CMD_NO_ERROR)
351
358
case Qt::ForegroundRole:
352
359
if (event.commandError() != KAEvent::CMD_NO_ERROR)
354
if (event.action() == KAEvent::COMMAND && !event.commandDisplay())
361
if (event.actionTypes() == KAEvent::ACT_COMMAND)
355
362
return Qt::white;
356
363
QColor colour = Qt::red;
491
498
// This is a Collection row
492
499
bool updateCollection = false;
500
CollectionAttribute* attr = 0;
495
503
case Qt::BackgroundRole:
497
505
QColor colour = value.value<QColor>();
498
CollectionAttribute* attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
506
attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
499
507
if (attr->backgroundColor() == colour)
500
508
return true; // no change
501
509
attr->setBackgroundColor(colour);
502
510
updateCollection = true;
513
case EnabledTypesRole:
507
KAlarm::CalEvent::Types types = static_cast<KAlarm::CalEvent::Types>(value.value<int>());
508
CollectionAttribute* attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
515
CalEvent::Types types = static_cast<CalEvent::Types>(value.value<int>());
516
attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
509
517
if (attr->enabled() == types)
510
518
return true; // no change
511
519
kDebug() << "Set enabled:" << types << ", was=" << attr->enabled();
517
525
if (collection.hasAttribute<CollectionAttribute>()
518
526
&& isCompatible(collection))
520
KAlarm::CalEvent::Types types = static_cast<KAlarm::CalEvent::Types>(value.value<int>());
521
CollectionAttribute* attr = collection.attribute<CollectionAttribute>();
528
CalEvent::Types types = static_cast<CalEvent::Types>(value.value<int>());
529
attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
522
530
kDebug()<<"Set standard:"<<types<<", was="<<attr->standard();
523
collection.attribute<CollectionAttribute>()->setStandard(types);
531
attr->setStandard(types);
524
532
updateCollection = true;
537
bool keepFormat = value.value<bool>();
538
attr = collection.attribute<CollectionAttribute>(Entity::AddIfMissing);
539
if (attr->keepFormat() == keepFormat)
540
return true; // no change
541
attr->setKeepFormat(keepFormat);
542
updateCollection = true;
530
548
if (updateCollection)
532
CollectionModifyJob* job = new CollectionModifyJob(collection, this);
550
// Update the CollectionAttribute value.
551
// Note that we can't supply 'collection' to CollectionModifyJob since
552
// that also contains the CompatibilityAttribute value, which is read-only
553
// for applications. So create a new Collection instance and only set a
554
// value for CollectionAttribute.
555
Collection c(collection.id());
556
CollectionAttribute* att = c.attribute<CollectionAttribute>(Entity::AddIfMissing);
558
CollectionModifyJob* job = new CollectionModifyJob(c, this);
533
559
connect(job, SIGNAL(result(KJob*)), this, SLOT(modifyCollectionJobDone(KJob*)));
850
876
/******************************************************************************
877
* Return the foreground color for displaying a collection, based on the
878
* supplied mime types which it contains, and on whether it is fully writable.
880
QColor AkonadiModel::foregroundColor(const Akonadi::Collection& collection, const QStringList& mimeTypes)
883
if (mimeTypes.contains(KAlarmCal::MIME_ACTIVE))
884
colour = KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color();
885
else if (mimeTypes.contains(KAlarmCal::MIME_ARCHIVED))
886
colour = Preferences::archivedColour();
887
else if (mimeTypes.contains(KAlarmCal::MIME_TEMPLATE))
888
colour = KColorScheme(QPalette::Active).foreground(KColorScheme::LinkText).color();
889
if (colour.isValid() && (collection.rights() & writableRights) != writableRights)
890
return KColorUtils::lighten(colour, 0.25);
894
/******************************************************************************
851
895
* Set the background color for displaying the collection and its alarms.
853
897
void AkonadiModel::setBackgroundColor(Collection& collection, const QColor& colour)
925
969
QString locn = url.pathOrUrl();
926
970
bool inactive = !collection.hasAttribute<CollectionAttribute>()
927
971
|| !(collection.attribute<CollectionAttribute>()->enabled() & types);
928
bool writable = (collection.rights() & writableRights) == writableRights;
929
972
QString disabled = i18nc("@info/plain", "Disabled");
930
QString readonly = i18nc("@info/plain", "Read-only");
973
QString readonly = readOnlyTooltip(collection);
974
bool writable = readonly.isEmpty();
931
975
//if (!collection.hasAttribute<CollectionAttribute>()) { kDebug()<<"Tooltip: no collection attribute"; } else { kDebug()<<"Tooltip: enabled="<<collection.attribute<CollectionAttribute>()->enabled(); } //disabled="<<inactive;
932
976
if (inactive && !writable)
933
977
return i18nc("@info:tooltip",
950
994
/******************************************************************************
995
* Return the read-only status tooltip for a collection.
996
* A null string is returned if the collection is fully writable.
998
QString AkonadiModel::readOnlyTooltip(const Collection& collection)
1000
KACalendar::Compat compat;
1001
switch (AkonadiModel::isWritable(collection, compat))
1006
return i18nc("@info/plain", "Read-only (old format)");
1008
if (compat == KACalendar::Current)
1009
return i18nc("@info/plain", "Read-only");
1010
return i18nc("@info/plain", "Read-only (other format)");
1014
/******************************************************************************
951
1015
* Return the repetition text.
953
1017
QString AkonadiModel::repeatText(const KAEvent& event) const
1003
1067
QPixmap* AkonadiModel::eventIcon(const KAEvent& event) const
1005
switch (event.action())
1069
switch (event.actionTypes())
1009
case KAAlarm::EMAIL:
1071
case KAEvent::ACT_EMAIL:
1010
1072
return mEmailIcon;
1011
case KAAlarm::AUDIO:
1073
case KAEvent::ACT_AUDIO:
1012
1074
return mAudioIcon;
1013
case KAAlarm::COMMAND:
1014
if (!event.commandDisplay())
1015
return mCommandIcon;
1016
// fall through to MESSAGE
1017
case KAAlarm::MESSAGE:
1075
case KAEvent::ACT_COMMAND:
1076
return mCommandIcon;
1077
case KAEvent::ACT_DISPLAY:
1078
if (event.actionSubType() == KAEvent::FILE)
1080
// fall through to ACT_DISPLAY_COMMAND
1081
case KAEvent::ACT_DISPLAY_COMMAND:
1019
1083
return mTextIcon;
1049
1113
/******************************************************************************
1050
* Add a new collection. The user will be prompted to enter its configuration.
1052
AgentInstanceCreateJob* AkonadiModel::addCollection(KAlarm::CalEvent::Type type, QWidget* parent)
1054
// Use AutoQPointer to guard against crash on application exit while
1055
// the dialogue is still open. It prevents double deletion (both on
1056
// deletion of parent, and on return from this function).
1057
AutoQPointer<AgentTypeDialog> dlg = new AgentTypeDialog(parent);
1061
case KAlarm::CalEvent::ACTIVE:
1062
mimeType = KAlarm::MIME_ACTIVE;
1064
case KAlarm::CalEvent::ARCHIVED:
1065
mimeType = KAlarm::MIME_ARCHIVED;
1067
case KAlarm::CalEvent::TEMPLATE:
1068
mimeType = KAlarm::MIME_TEMPLATE;
1073
dlg->agentFilterProxyModel()->addMimeTypeFilter(mimeType);
1074
dlg->agentFilterProxyModel()->addCapabilityFilter(QLatin1String("Resource"));
1075
if (dlg->exec() != QDialog::Accepted)
1077
const AgentType agentType = dlg->agentType();
1078
if (!agentType.isValid())
1080
AgentInstanceCreateJob* job = new AgentInstanceCreateJob(agentType, parent);
1081
if (agentType.identifier() == QLatin1String("akonadi_kalarm_dir_resource"))
1082
mPendingColCreateJobs[job] = CollTypeData(type, parent);
1084
job->configure(parent); // cause the user to be prompted for configuration
1085
connect(job, SIGNAL(result(KJob*)), SLOT(addCollectionJobDone(KJob*)));
1090
/******************************************************************************
1091
* Called when an agent creation job has completed.
1092
* Checks for any error.
1094
void AkonadiModel::addCollectionJobDone(KJob* j)
1096
AgentInstanceCreateJob* job = static_cast<AgentInstanceCreateJob*>(j);
1099
kError() << "Failed to create new calendar resource:" << j->errorString();
1100
KAMessageBox::error(MainWindow::mainMainWindow(), i18nc("@info", "%1<nl/>(%2)",
1101
i18nc("@info/plain", "Failed to create new calendar resource"), j->errorString()));
1102
emit collectionAdded(job, false);
1106
QMap<KJob*, CollTypeData>::iterator it = mPendingColCreateJobs.find(j);
1107
if (it != mPendingColCreateJobs.end())
1109
// Set the default alarm type for a directory resource config dialog
1110
AgentInstance agent = static_cast<AgentInstanceCreateJob*>(job)->instance();
1111
OrgKdeAkonadiKAlarmDirSettingsInterface *iface = new OrgKdeAkonadiKAlarmDirSettingsInterface("org.freedesktop.Akonadi.Resource." + agent.identifier(),
1112
"/Settings", QDBusConnection::sessionBus(), this);
1113
if (!iface->isValid())
1114
kError() << "Error creating D-Bus interface for KAlarmDir configuration.";
1117
iface->setAlarmTypes(KAlarm::CalEvent::mimeTypes(it.value().alarmType));
1118
iface->writeConfig();
1119
agent.reconfigure();
1121
agent.configure(it.value().parent);
1124
emit collectionAdded(job, true);
1128
/******************************************************************************
1129
1114
* Remove a collection from Akonadi. The calendar file is not removed.
1131
1116
bool AkonadiModel::removeCollection(const Akonadi::Collection& collection)
1217
1202
void AkonadiModel::modifyCollectionJobDone(KJob* j)
1219
1204
Collection collection = static_cast<CollectionModifyJob*>(j)->collection();
1205
Collection::Id id = collection.id();
1220
1206
if (j->error())
1222
emit collectionModified(collection.id(), false);
1223
QString errMsg = i18nc("@info", "Failed to update calendar <resource>%1</resource>.", displayName(collection));
1224
kError() << errMsg << ":" << j->errorString();
1225
KAMessageBox::error(MainWindow::mainMainWindow(), i18nc("@info", "%1<nl/>(%2)", errMsg, j->errorString()));
1208
emit collectionModified(id, false);
1209
if (mCollectionsDeleted.contains(id))
1210
mCollectionsDeleted.removeAll(id);
1213
QString errMsg = i18nc("@info", "Failed to update calendar <resource>%1</resource>.", displayName(collection));
1214
kError() << "Id:" << collection.id() << errMsg << ":" << j->errorString();
1215
KAMessageBox::error(MainWindow::mainMainWindow(), i18nc("@info", "%1<nl/>(%2)", errMsg, j->errorString()));
1228
emit collectionModified(collection.id(), true);
1219
emit collectionModified(id, true);
1231
1222
/******************************************************************************
1594
1585
// A collection has been inserted
1595
1586
kDebug() << "Collection" << collection.id() << collection.name();
1596
1588
QSet<QByteArray> attrs;
1597
1589
attrs += CollectionAttribute::name();
1598
setCollectionChanged(collection, attrs, false);
1590
setCollectionChanged(collection, attrs, true);
1599
1591
emit collectionAdded(collection);
1593
if (!mCollectionsBeingCreated.contains(collection.remoteId())
1594
&& (collection.rights() & writableRights) == writableRights)
1596
// Update to current KAlarm format if necessary, and if the user agrees
1597
CalendarMigrator::updateToCurrentFormat(collection, false, MainWindow::mainMainWindow());
1650
1649
* Called when a monitored collection's properties or content have changed.
1651
1650
* Optionally emits a signal if properties of interest have changed.
1653
void AkonadiModel::setCollectionChanged(const Collection& collection, const QSet<QByteArray>& attributeNames, bool signal)
1652
void AkonadiModel::setCollectionChanged(const Collection& collection, const QSet<QByteArray>& attributeNames, bool rowInserted)
1655
1654
// Check for a read/write permission change
1656
1655
Collection::Rights oldRights = mCollectionRights.value(collection.id(), Collection::AllRights);
1657
1656
Collection::Rights newRights = collection.rights() & writableRights;
1658
1657
if (newRights != oldRights)
1659
kDebug() << "Collection" << collection.id() << ": rights ->" << newRights;
1660
1660
mCollectionRights[collection.id()] = newRights;
1662
emit collectionStatusChanged(collection, ReadOnly, (newRights != writableRights));
1661
emit collectionStatusChanged(collection, ReadOnly, (newRights != writableRights), rowInserted);
1665
1664
// Check for a change in content mime types
1666
1665
// (e.g. when a collection is first created at startup).
1667
KAlarm::CalEvent::Types oldAlarmTypes = mCollectionAlarmTypes.value(collection.id(), KAlarm::CalEvent::EMPTY);
1668
KAlarm::CalEvent::Types newAlarmTypes = KAlarm::CalEvent::types(collection.contentMimeTypes());
1666
CalEvent::Types oldAlarmTypes = mCollectionAlarmTypes.value(collection.id(), CalEvent::EMPTY);
1667
CalEvent::Types newAlarmTypes = CalEvent::types(collection.contentMimeTypes());
1669
1668
if (newAlarmTypes != oldAlarmTypes)
1671
1670
kDebug() << "Collection" << collection.id() << ": alarm types ->" << newAlarmTypes;
1672
1671
mCollectionAlarmTypes[collection.id()] = newAlarmTypes;
1674
emit collectionStatusChanged(collection, AlarmTypes, static_cast<int>(newAlarmTypes));
1672
emit collectionStatusChanged(collection, AlarmTypes, static_cast<int>(newAlarmTypes), rowInserted);
1677
1675
// Check for the collection being enabled/disabled
1678
1676
if (attributeNames.contains(CollectionAttribute::name()))
1680
1678
static bool first = true;
1681
kDebug()<<"COLLECTION ATTRIBUTE changed";
1682
KAlarm::CalEvent::Types oldEnabled = mCollectionEnabled.value(collection.id(), KAlarm::CalEvent::EMPTY);
1683
KAlarm::CalEvent::Types newEnabled = collection.hasAttribute<CollectionAttribute>() ? collection.attribute<CollectionAttribute>()->enabled() : KAlarm::CalEvent::EMPTY;
1679
CalEvent::Types oldEnabled = mCollectionEnabled.value(collection.id(), CalEvent::EMPTY);
1680
CalEvent::Types newEnabled = collection.hasAttribute<CollectionAttribute>() ? collection.attribute<CollectionAttribute>()->enabled() : CalEvent::EMPTY;
1684
1681
if (first || newEnabled != oldEnabled)
1686
1683
kDebug() << "Collection" << collection.id() << ": enabled ->" << newEnabled;
1688
1685
mCollectionEnabled[collection.id()] = newEnabled;
1690
emit collectionStatusChanged(collection, Enabled, static_cast<int>(newEnabled));
1686
emit collectionStatusChanged(collection, Enabled, static_cast<int>(newEnabled), rowInserted);
1690
// Check for the backend calendar format changing
1691
if (attributeNames.contains(CompatibilityAttribute::name()))
1693
// Update to current KAlarm format if necessary, and if the user agrees
1694
kDebug() << "CompatibilityAttribute";
1695
Collection col(collection);
1697
CalendarMigrator::updateToCurrentFormat(col, false, MainWindow::mainMainWindow());
1695
1701
/******************************************************************************
1698
1704
void AkonadiModel::slotCollectionRemoved(const Collection& collection)
1700
kDebug() << collection.id();
1701
mCollectionRights.remove(collection.id());
1702
mCollectionsDeleting.removeAll(collection.id());
1706
Collection::Id id = collection.id();
1708
mCollectionRights.remove(id);
1709
mCollectionsDeleting.removeAll(id);
1710
while (mCollectionsDeleted.count() > 20) // don't let list grow indefinitely
1711
mCollectionsDeleted.removeFirst();
1712
mCollectionsDeleted << id;
1715
/******************************************************************************
1716
* Called when a collection creation is about to start, or has completed.
1718
void AkonadiModel::slotCollectionBeingCreated(const QString& path, bool finished)
1721
mCollectionsBeingCreated.removeAll(path);
1723
mCollectionsBeingCreated << path;
1705
1726
/******************************************************************************
1824
1845
bool AkonadiModel::isCompatible(const Collection& collection)
1826
1847
return collection.hasAttribute<CompatibilityAttribute>()
1827
&& collection.attribute<CompatibilityAttribute>()->compatibility() == KAlarm::Calendar::Current;
1830
KAlarm::CalEvent::Types AkonadiModel::types(const Collection& collection)
1832
KAlarm::CalEvent::Types types = 0;
1833
QStringList mimeTypes = collection.contentMimeTypes();
1834
if (mimeTypes.contains(KAlarm::MIME_ACTIVE))
1835
types |= KAlarm::CalEvent::ACTIVE;
1836
if (mimeTypes.contains(KAlarm::MIME_ARCHIVED))
1837
types |= KAlarm::CalEvent::ARCHIVED;
1838
if (mimeTypes.contains(KAlarm::MIME_TEMPLATE))
1839
types |= KAlarm::CalEvent::TEMPLATE;
1848
&& collection.attribute<CompatibilityAttribute>()->compatibility() == KACalendar::Current;
1843
1851
/******************************************************************************
1844
* Check whether the alarm types in a calendar correspond with a collection's
1846
* Reply = true if at least 1 alarm is the right type.
1852
* Return whether a collection is fully writable.
1848
bool AkonadiModel::checkAlarmTypes(const Akonadi::Collection& collection, KCalCore::Calendar::Ptr& calendar)
1850
KAlarm::CalEvent::Types etypes = types(collection);
1855
const KCalCore::Event::List events = calendar->rawEvents();
1856
for (int i = 0, iend = events.count(); i < iend; ++i)
1858
KAlarm::CalEvent::Type s = KAlarm::CalEvent::status(events[i]);
1867
return false; // contains only wrong alarm types
1854
int AkonadiModel::isWritable(const Akonadi::Collection& collection)
1856
KACalendar::Compat format;
1857
return isWritable(collection, format);
1860
int AkonadiModel::isWritable(const Akonadi::Collection& collection, KACalendar::Compat& format)
1862
format = KACalendar::Incompatible;
1863
if (!collection.isValid())
1865
Collection col = collection;
1866
instance()->refresh(col); // update with latest data
1867
if ((col.rights() & writableRights) != writableRights)
1869
format = KACalendar::Current;
1872
if (!col.hasAttribute<CompatibilityAttribute>())
1874
format = col.attribute<CompatibilityAttribute>()->compatibility();
1877
case KACalendar::Current:
1879
case KACalendar::Converted:
1880
case KACalendar::Convertible:
1887
CalEvent::Types AkonadiModel::types(const Collection& collection)
1889
return CalEvent::types(collection.contentMimeTypes());
1872
1892
// vim: et sw=4: