diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e176279..7089acb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,124 +1,124 @@ project(kalarm) cmake_minimum_required(VERSION 3.1) set(KF5_VERSION "5.25.0") find_package(ECM ${KF5_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${kalarm_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) include(ECMInstallIcons) include(ECMOptionalAddSubdirectory) include(ECMSetupVersion) include(ECMAddTests) include(ECMMarkNonGuiExecutable) include(GenerateExportHeader) include(ECMGenerateHeaders) include(CMakePackageConfigHelpers) include(FeatureSummary) include(CheckFunctionExists) include(ECMGeneratePriFile) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMAddAppIcon) include(ECMQtDeclareLoggingCategory) # Do NOT add quote set(KDEPIM_DEV_VERSION pre) # add an extra space if(DEFINED KDEPIM_DEV_VERSION) set(KDEPIM_DEV_VERSION " ${KDEPIM_DEV_VERSION}") endif() set(KDEPIM_VERSION_NUMBER "5.3.43") set(KDEPIM_VERSION "${KDEPIM_VERSION_NUMBER}${KDEPIM_DEV_VERSION}") set(AKONADI_MIMELIB_VERSION "5.3.40") set(AKONADI_CONTACT_VERSION "5.3.40") set(KHOLIDAYS_LIB_VERSION "5.3.40") set(KMAILTRANSPORT_LIB_VERSION "5.3.40") set(KPIMTEXTEDIT_LIB_VERSION "5.3.43") set(IDENTITYMANAGEMENT_LIB_VERSION "5.3.41") -set(AKONADI_VERSION "5.3.43") +set(AKONADI_VERSION "5.3.45") set(KMIME_LIB_VERSION "5.3.40") set(AKONADIKALARM_LIB_VERSION "5.3.40") set(PIMCOMMON_LIB_VERSION_LIB "5.3.41") set(KDEPIM_LIB_VERSION "${KDEPIM_VERSION_NUMBER}") set(KDEPIM_LIB_SOVERSION "5") set(QT_REQUIRED_VERSION "5.6.0") find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED DBus Gui Network Widgets) find_package(Qt5X11Extras NO_MODULE) set(MAILCOMMON_LIB_VERSION_LIB "5.3.42") set(LIBKDEPIM_LIB_VERSION_LIB "5.3.42") set(KCALENDARCORE_LIB_VERSION "5.3.40") set(CALENDARUTILS_LIB_VERSION "5.3.40") set(KDEPIM_APPS_LIB_VERSION_LIB "5.3.40") # Find KF5 package find_package(KF5Auth ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Codecs ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Completion ${KF5_VERSION} REQUIRED) find_package(KF5Config ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5DocTools ${KF5_VERSION} REQUIRED) find_package(KF5GuiAddons ${KF5_VERSION} REQUIRED) find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_VERSION} REQUIRED) find_package(KF5JobWidgets ${KF5_VERSION} REQUIRED) find_package(KF5KCMUtils ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KDELibs4Support ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Notifications ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Service ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5WindowSystem ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_VERSION} CONFIG REQUIRED) find_package(Phonon4Qt5 CONFIG REQUIRED) # Find KdepimLibs Package find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADI_CONTACT_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiMime ${AKONADI_MIMELIB_VERSION} CONFIG REQUIRED) find_package(KF5AlarmCalendar ${AKONADIKALARM_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarCore ${KCALENDARCORE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarUtils ${CALENDARUTILS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Holidays ${KHOLIDAYS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5KdepimDBusInterfaces ${KDEPIM_APPS_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5Libkdepim ${LIBKDEPIM_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MailCommon ${MAILCOMMON_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MailTransport ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimCommon ${PIMCOMMON_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5PimTextEdit ${KPIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED) if (NOT APPLE) find_package(X11) endif() add_definitions(-DQT_NO_URL_CAST_FROM_STRING) add_definitions(-DQT_USE_QSTRINGBUILDER) set(CMAKE_MODULE_PATH ${kalarm_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) find_package(Xsltproc) set_package_properties(Xsltproc PROPERTIES DESCRIPTION "XSLT processor from libxslt" TYPE REQUIRED PURPOSE "Required to generate D-Bus interfaces for all Akonadi resources.") set(KDEPIM_HAVE_X11 ${X11_FOUND}) configure_file(src/config-kalarm.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kalarm.h ) include_directories(${kalarm_SOURCE_DIR} ${kalarm_BINARY_DIR}) add_definitions(-DQT_STRICT_ITERATORS) add_definitions(-DQT_NO_CAST_FROM_ASCII) add_definitions(-DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_MESSAGELOGCONTEXT) add_subdirectory(src) install( FILES kalarm.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) add_subdirectory(doc) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/akonadimodel.h b/src/akonadimodel.h index c961baaf..1284d999 100644 --- a/src/akonadimodel.h +++ b/src/akonadimodel.h @@ -1,339 +1,344 @@ /* * akonadimodel.h - KAlarm calendar file access using Akonadi * Program: kalarm * Copyright © 2010-2014 by David Jarvie * * 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 AKONADIMODEL_H #define AKONADIMODEL_H #include "eventid.h" #include #include #include #include #include #include #include #include +namespace Akonadi +{ +class ChangeRecorder; +} + class QPixmap; class KJob; using namespace KAlarmCal; class AkonadiModel : public Akonadi::EntityTreeModel { Q_OBJECT public: enum Change { Added, Deleted, Invalidated, Enabled, ReadOnly, AlarmTypes, WrongType, Location, Colour }; enum { // data columns // Item columns TimeColumn = 0, TimeToColumn, RepeatColumn, ColourColumn, TypeColumn, TextColumn, TemplateNameColumn, ColumnCount }; enum { // additional data roles // Collection roles EnabledTypesRole = UserRole, // alarm types which are enabled for the collection BaseColourRole, // background colour ignoring collection colour AlarmTypeRole, // OR of event types which collection contains IsStandardRole, // OR of event types which collection is standard for KeepFormatRole, // user has chosen not to update collection's calendar storage format // Item roles EnabledRole, // true for enabled alarm, false for disabled StatusRole, // KAEvent::ACTIVE/ARCHIVED/TEMPLATE AlarmActionsRole, // KAEvent::Actions AlarmSubActionRole, // KAEvent::Action ValueRole, // numeric value SortRole, // the value to use for sorting CommandErrorRole // last command execution error for alarm (per user) }; /** Struct containing a KAEvent and its parent Collection. */ struct Event { Event(const KAEvent& e, const Akonadi::Collection& c) : event(e), collection(c) {} EventId eventId() const { return EventId(collection.id(), event.id()); } bool isConsistent() const { return event.collectionId() == collection.id(); } KAEvent event; Akonadi::Collection collection; }; typedef QList EventList; static AkonadiModel* instance(); ~AkonadiModel(); /** Return the display name for a collection. */ QString displayName(Akonadi::Collection&) const; /** Return the storage type (file/directory/URL etc.) for a collection. */ QString storageType(const Akonadi::Collection&) const; /** Get the foreground color for a collection, based on specified mime types. */ static QColor foregroundColor(const Akonadi::Collection&, const QStringList& mimeTypes); /** Set the background color for a collection and its alarms. */ void setBackgroundColor(Akonadi::Collection&, const QColor&); /** Get the background color for a collection and its alarms. */ QColor backgroundColor(Akonadi::Collection&) const; /** Get the tooltip for a collection. The collection's enabled status is * evaluated for specified alarm types. */ QString tooltip(const Akonadi::Collection&, CalEvent::Types) const; /** Return the read-only status tooltip for a collection. * A null string is returned if the collection is fully writable. */ static QString readOnlyTooltip(const Akonadi::Collection&); /** To be called when the command error status of an alarm has changed, * to set in the Akonadi database and update the visual command error indications. */ void updateCommandError(const KAEvent&); QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; bool setData(const QModelIndex&, const QVariant& value, int role) Q_DECL_OVERRIDE; /** Refresh the specified collection instance with up to date data. */ bool refresh(Akonadi::Collection&) const; /** Refresh the specified item instance with up to date data. */ bool refresh(Akonadi::Item&) const; QModelIndex collectionIndex(Akonadi::Collection::Id id) const { return collectionIndex(Akonadi::Collection(id)); } QModelIndex collectionIndex(const Akonadi::Collection&) const; Akonadi::Collection collectionById(Akonadi::Collection::Id) const; Akonadi::Collection collectionForItem(Akonadi::Item::Id) const; Akonadi::Collection collection(const KAEvent& e) const { return collectionForItem(e.itemId()); } /** Remove a collection from Akonadi. The calendar file is not removed. * @return true if a removal job has been scheduled. */ bool removeCollection(const Akonadi::Collection&); /** Reload a collection's data from Akonadi storage (not from the backend). */ bool reloadCollection(const Akonadi::Collection&); /** Reload all collections' data from Akonadi storage (not from the backend). */ void reload(); /** Return whether calendar migration/creation at initialisation has completed. */ bool isMigrationCompleted() const; bool isCollectionBeingDeleted(Akonadi::Collection::Id) const; QModelIndex itemIndex(Akonadi::Item::Id id) const { return itemIndex(Akonadi::Item(id)); } QModelIndex itemIndex(const Akonadi::Item&) const; Akonadi::Item itemById(Akonadi::Item::Id) const; /** Return the alarm with the specified unique identifier. * @return the event, or invalid event if no such event exists. */ KAEvent event(const Akonadi::Item& item) const { return event(item, QModelIndex(), Q_NULLPTR); } KAEvent event(Akonadi::Item::Id) const; KAEvent event(const QModelIndex&) const; using QObject::event; // prevent warning about hidden virtual method /** Return an event's model index, based on its itemId() value. */ QModelIndex eventIndex(const KAEvent&); /** Search for an event's item ID. This method ignores any itemId() value * contained in the KAEvent. The collectionId() is used if available. */ Akonadi::Item::Id findItemId(const KAEvent&); #if 0 /** Return all events in a collection, optionally of a specified type. */ KAEvent::List events(Akonadi::Collection&, CalEvent::Type = CalEvent::EMPTY) const; #endif bool addEvent(KAEvent&, Akonadi::Collection&); bool addEvents(const KAEvent::List&, Akonadi::Collection&); bool updateEvent(KAEvent& event); bool updateEvent(Akonadi::Item::Id oldId, KAEvent& newEvent); bool deleteEvent(const KAEvent& event); bool deleteEvent(Akonadi::Item::Id itemId); /** Check whether a collection is stored in the current KAlarm calendar format. */ static bool isCompatible(const Akonadi::Collection&); /** Return whether a collection is fully writable, i.e. with * create/delete/change rights and compatible with the current KAlarm * calendar format. * * @return 1 = fully writable, * 0 = writable except that backend calendar is in an old KAlarm format, * -1 = read-only or incompatible format. */ static int isWritable(const Akonadi::Collection&); /** Return whether a collection is fully writable, i.e. with * create/delete/change rights and compatible with the current KAlarm * calendar format. * * @param format Updated to contain the backend calendar storage format. * If read-only, = KACalendar::Current; * if unknown format, = KACalendar::Incompatible; * otherwise = the backend calendar storage format. * @return 1 = fully writable, * 0 = writable except that backend calendar is in an old KAlarm format, * -1 = read-only (if @p compat == KACalendar::Current), or * incompatible format otherwise. */ static int isWritable(const Akonadi::Collection&, KACalendar::Compat& format); static CalEvent::Types types(const Akonadi::Collection&); static QSize iconSize() { return mIconSize; } Q_SIGNALS: /** Signal emitted when a collection has been added to the model. */ void collectionAdded(const Akonadi::Collection&); /** Signal emitted when a collection's enabled or read-only status has changed. * @param inserted true if the reason for the change is that the collection * has been inserted into the model */ void collectionStatusChanged(const Akonadi::Collection&, AkonadiModel::Change, const QVariant& newValue, bool inserted); /** Signal emitted when events have been added to the model. */ void eventsAdded(const AkonadiModel::EventList&); /** Signal emitted when events are about to be removed from the model. */ void eventsToBeRemoved(const AkonadiModel::EventList&); /** Signal emitted when an event in the model has changed. */ void eventChanged(const AkonadiModel::Event&); /** Signal emitted when Akonadi has completed a collection modification. * @param id Akonadi ID for the collection * @param status true if successful, false if error */ void collectionModified(Akonadi::Collection::Id, bool status = true); /** Signal emitted when Akonadi has completed a collection deletion. * @param id Akonadi ID for the collection * @param status true if successful, false if error */ void collectionDeleted(Akonadi::Collection::Id, bool status = true); /** Signal emitted when Akonadi has completed an item creation, update * or deletion. * @param id Akonadi ID for the item * @param status true if successful, false if error */ void itemDone(Akonadi::Item::Id, bool status = true); /** Signal emitted when calendar migration/creation has completed. */ void migrationCompleted(); /** Signal emitted when the Akonadi server has stopped. */ void serverStopped(); protected: QVariant entityHeaderData(int section, Qt::Orientation, int role, HeaderGroup) const Q_DECL_OVERRIDE; int entityColumnCount(HeaderGroup) const Q_DECL_OVERRIDE; private Q_SLOTS: void checkResources(Akonadi::ServerManager::State); void slotMigrationCompleted(); void slotCollectionChanged(const Akonadi::Collection& c, const QSet& attrNames) { setCollectionChanged(c, attrNames, false); } void slotCollectionRemoved(const Akonadi::Collection&); void slotCollectionBeingCreated(const QString& path, Akonadi::Collection::Id, bool finished); void slotUpdateTimeTo(); void slotUpdateArchivedColour(const QColor&); void slotUpdateDisabledColour(const QColor&); void slotUpdateHolidays(); void slotUpdateWorkingHours(); void slotRowsInserted(const QModelIndex& parent, int start, int end); void slotRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); void slotMonitoredItemChanged(const Akonadi::Item&, const QSet&); void slotEmitEventChanged(); void modifyCollectionJobDone(KJob*); void itemJobDone(KJob*); private: struct CalData // data per collection { CalData() : enabled(false) { } CalData(bool e, const QColor& c) : colour(c), enabled(e) { } QColor colour; // user selected color for the calendar bool enabled; // whether the collection is enabled }; struct CollJobData // collection data for jobs in progress { CollJobData() : id(-1) {} CollJobData(Akonadi::Collection::Id i, const QString& d) : id(i), displayName(d) {} Akonadi::Collection::Id id; QString displayName; }; struct CollTypeData // data for configuration dialog for collection creation job { CollTypeData() : parent(Q_NULLPTR), alarmType(CalEvent::EMPTY) {} CollTypeData(CalEvent::Type t, QWidget* p) : parent(p), alarmType(t) {} QWidget* parent; CalEvent::Type alarmType; }; AkonadiModel(Akonadi::ChangeRecorder*, QObject* parent); void initCalendarMigrator(); KAEvent event(const Akonadi::Item&, const QModelIndex&, Akonadi::Collection*) const; void signalDataChanged(bool (*checkFunc)(const Akonadi::Item&), int startColumn, int endColumn, const QModelIndex& parent); void setCollectionChanged(const Akonadi::Collection&, const QSet&, bool rowInserted); void queueItemModifyJob(const Akonadi::Item&); void checkQueuedItemModifyJob(const Akonadi::Item&); #if 0 void getChildEvents(const QModelIndex& parent, CalEvent::Type, KAEvent::List&) const; #endif QColor backgroundColor_p(const Akonadi::Collection&) const; QString repeatText(const KAEvent&) const; QString repeatOrder(const KAEvent&) const; QPixmap* eventIcon(const KAEvent&) const; QString whatsThisText(int column) const; EventList eventList(const QModelIndex& parent, int start, int end); static AkonadiModel* mInstance; static QPixmap* mTextIcon; static QPixmap* mFileIcon; static QPixmap* mCommandIcon; static QPixmap* mEmailIcon; static QPixmap* mAudioIcon; static QSize mIconSize; static int mTimeHourPos; // position of hour within time string, or -1 if leading zeroes included Akonadi::ChangeRecorder* mMonitor; QMap mCollectionAlarmTypes; // last content mime types of each collection QMap mCollectionRights; // last writable status of each collection QMap mCollectionEnabled; // last enabled mime types of each collection QMap mPendingCollectionJobs; // pending collection creation/deletion jobs, with collection ID & name QMap mPendingColCreateJobs; // default alarm type for pending collection creation jobs QMap mPendingItemJobs; // pending item creation/deletion jobs, with event ID QMap mItemModifyJobQueue; // pending item modification jobs, invalid item = queue empty but job active QList mCollectionsBeingCreated; // path names of new collections being created by migrator QList mCollectionIdsBeingCreated; // ids of new collections being created by migrator QList mItemsBeingCreated; // new items not fully initialised yet QList mCollectionsDeleting; // collections currently being removed QList mCollectionsDeleted; // collections recently removed QQueue mPendingEventChanges; // changed events with changedEvent() signal pending bool mResourcesChecked; // whether resource existence has been checked yet bool mMigrating; // currently migrating calendars }; #endif // AKONADIMODEL_H // vim: et sw=4: