MauiKit Calendar

colorproxymodel.cpp
1// SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
2// SPDX-FileCopyrightText: 2022 Claudio Cambra <claudio.cambra@gmail.com>
3// SPDX-License-Identifier: GPL-2.0-or-later
4
5#include "colorproxymodel.h"
6
7#include <Akonadi/AgentInstance>
8#include <Akonadi/AgentManager>
9#include <Akonadi/AttributeFactory>
10#include <Akonadi/CollectionColorAttribute>
11#include <Akonadi/CollectionModifyJob>
12#include <Akonadi/CollectionUtils>
13#include <Akonadi/EntityDisplayAttribute>
14#include <KCalendarCore/Event>
15#include <KCalendarCore/Journal>
16#include <KCalendarCore/Todo>
17#include <KConfigGroup>
18#include <KContacts/Addressee>
19#include <KContacts/ContactGroup>
20#include <KLocalizedString>
21#include <KSharedConfig>
22#include <QColor>
23#include <QFont>
24#include <QRandomGenerator>
25
26namespace
27{
28 static bool hasCompatibleMimeTypes(const Akonadi::Collection &collection)
29 {
30 static QStringList goodMimeTypes;
31
32 if (goodMimeTypes.isEmpty()) {
33 goodMimeTypes << QStringLiteral("text/calendar") << KCalendarCore::Event::eventMimeType() << KCalendarCore::Todo::todoMimeType()
35 }
36
37 for (int i = 0; i < goodMimeTypes.count(); ++i) {
38 if (collection.contentMimeTypes().contains(goodMimeTypes.at(i))) {
39 return true;
40 }
41 }
42
43 return false;
44 }
45}
46
47ColorProxyModel::ColorProxyModel(QObject *parent)
49, mInitDefaultCalendar(false)
50{
51 // Needed to read colorattribute of collections for incidence colors
53}
54
55QVariant ColorProxyModel::data(const QModelIndex &index, int role) const
56{
57 if (!index.isValid()) {
58 return {};
59 }
60
61 if (role == Qt::DecorationRole) {
63
64 if (hasCompatibleMimeTypes(collection)) {
66 return collection.attribute<Akonadi::EntityDisplayAttribute>()->iconName();
67 }
68 }
69 } else if (role == Qt::FontRole) {
71 if (!collection.contentMimeTypes().isEmpty() && collection.id() == m_standardCollectionId && collection.rights() & Akonadi::Collection::CanCreateItem) {
72 auto font = qvariant_cast<QFont>(QSortFilterProxyModel::data(index, Qt::FontRole));
73 font.setBold(true);
74 return font;
75 }
76 } else if (role == Qt::DisplayRole) {
78 const Akonadi::Collection::Id colId = collection.id();
80
81 if (!instance.isOnline() && !collection.isVirtual()) {
82 return i18nc("@item this is the default calendar", "%1 (Offline)", collection.displayName());
83 }
84 if (colId == m_standardCollectionId) {
85 return i18nc("@item this is the default calendar", "%1 (Default)", collection.displayName());
86 }
87 } else if (role == Qt::BackgroundRole) {
88 auto color = getCollectionColor(Akonadi::CollectionUtils::fromIndex(index));
89 // Otherwise QML will get black
90 if (color.isValid()) {
91 return color;
92 } else {
93 return {};
94 }
95 } else if (role == isResource) {
96 return Akonadi::CollectionUtils::isResource(Akonadi::CollectionUtils::fromIndex(index));
97 }
98
100}
101
102Qt::ItemFlags ColorProxyModel::flags(const QModelIndex &index) const
103{
105}
106
107QHash<int, QByteArray> ColorProxyModel::roleNames() const
108{
110 roleNames[Qt::CheckStateRole] = "checkState";
111 roleNames[Qt::BackgroundRole] = "collectionColor";
112 roleNames[isResource] = "isResource";
113 return roleNames;
114}
115
116QColor ColorProxyModel::getCollectionColor(Akonadi::Collection collection) const
117{
118 const auto id = collection.id();
119 auto supportsMimeType = collection.contentMimeTypes().contains(QLatin1String("application/x-vnd.akonadi.calendar.event"))
120 || collection.contentMimeTypes().contains(QLatin1String("application/x-vnd.akonadi.calendar.todo"))
121 || collection.contentMimeTypes().contains(QLatin1String("application/x-vnd.akonadi.calendar.journal"))
124
125 if (!supportsMimeType) {
126 return {};
127 }
128
129 if (colorCache.contains(id)) {
130 return colorCache[id];
131 }
132
134 const auto colorAttr = collection.attribute<Akonadi::CollectionColorAttribute>();
135 if (colorAttr && colorAttr->color().isValid()) {
136 colorCache[id] = colorAttr->color();
137 return colorAttr->color();
138 }
139 }
140
141 KSharedConfig::Ptr config = KSharedConfig::openConfig();
142 KConfigGroup resourcesColorsConfig(config, QStringLiteral("Resources Colors"));
143 const QStringList colorKeyList = resourcesColorsConfig.keyList();
144
145 QColor color;
146 for (const QString &key : colorKeyList) {
147 if (key.toLongLong() == id) {
148 color = resourcesColorsConfig.readEntry(key, QColor("blue"));
149 }
150 }
151
152 if (!color.isValid()) {
153 QColor color;
154 color.setRgb(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256));
155 colorCache[id] = color;
156 }
157
159 colorAttr->setColor(color);
160
161 auto modifyJob = new Akonadi::CollectionModifyJob(collection);
162 connect(modifyJob, &Akonadi::CollectionModifyJob::result, this, [](KJob *job) {
163 if (job->error()) {
164 qWarning() << "Error occurred modifying collection color: " << job->errorString();
165 }
166 });
167
168 return color;
169}
170
171QColor ColorProxyModel::color(Akonadi::Collection::Id collectionId) const
172{
173 return colorCache[collectionId];
174}
175
176void ColorProxyModel::setColor(Akonadi::Collection::Id collectionId, const QColor &color)
177{
178 colorCache[collectionId] = color;
179}
180
181void ColorProxyModel::setStandardCollectionId(Akonadi::Collection::Id standardCollectionId)
182{
183 m_standardCollectionId = standardCollectionId;
184}
static AgentManager * self()
AgentInstance instance(const QString &identifier) const
static void registerAttribute()
QString resource() const
QStringList contentMimeTypes() const
QString displayName() const
const T * attribute() const
Rights rights() const
bool hasAttribute() const
bool isVirtual() const
static QLatin1String eventMimeType()
static QLatin1String journalMimeType()
static QLatin1String todoMimeType()
static QString mimeType()
static QString mimeType()
virtual QString errorString() const
int error() const
void result(KJob *job)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
AKONADICORE_EXPORT Collection fromIndex(const QModelIndex &index)
virtual QHash< int, QByteArray > roleNames() const const
bool isValid() const const
void setRgb(QRgb rgb)
bool contains(const Key &key) const const
const_reference at(qsizetype i) const const
qsizetype count() const const
bool isEmpty() const const
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QRandomGenerator * global()
virtual QVariant data(const QModelIndex &index, int role) const const override
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
bool isEmpty() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
DecorationRole
typedef ItemFlags
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:02:37 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.