diff --git a/framework/src/domain/eventmodel.cpp b/framework/src/domain/eventmodel.cpp index c04703cc..1fd65883 100644 --- a/framework/src/domain/eventmodel.cpp +++ b/framework/src/domain/eventmodel.cpp @@ -1,210 +1,233 @@ /* Copyright (c) 2018 Michael Bohlender Copyright (c) 2018 Christian Mollekopf Copyright (c) 2018 Rémi Nicole This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "eventmodel.h" #include #include #include #include #include #include #include #include #include #include using Event = Sink::ApplicationDomain::Event; using Calendar = Sink::ApplicationDomain::Calendar; EventModel::EventModel(QObject *parent) : QAbstractItemModel(parent), mCalendarCache{EntityCache::Ptr::create()}, mCalendar{new KCalCore::MemoryCalendar{QTimeZone::systemTimeZone()}} { mRefreshTimer.setSingleShot(true); QObject::connect(&mRefreshTimer, &QTimer::timeout, this, &EventModel::updateFromSource); } -void EventModel::updateQuery(const QDate &start, const QDate &end, const QSet &calendarFilter) +void EventModel::setStart(const QDate &start) { - qWarning() << "Update query" << start << end << calendarFilter; - mCalendarFilter = calendarFilter; mStart = start; - mEnd = end; + updateQuery(); +} + +QDate EventModel::start() const +{ + return mStart; +} + +void EventModel::setLength(int length) +{ + mLength = length; + updateQuery(); +} + +void EventModel::setCalendarFilter(const QSet &calendarFilter) +{ + mCalendarFilter = calendarFilter; + updateQuery(); +} + +void EventModel::updateQuery() +{ + if (mCalendarFilter.isEmpty() || !mLength || !mStart.isValid()) { + return; + } + mEnd = mStart.addDays(mLength); Sink::Query query; query.setFlags(Sink::Query::LiveQuery); query.request(); query.request(); query.request(); query.request(); query.request(); query.request(); query.request(); - query.filter(Sink::Query::Comparator(QVariantList{start, end}, Sink::Query::Comparator::Overlap)); + query.filter(Sink::Query::Comparator(QVariantList{mStart, mEnd}, Sink::Query::Comparator::Overlap)); mSourceModel = Sink::Store::loadModel(query); QObject::connect(mSourceModel.data(), &QAbstractItemModel::dataChanged, this, &EventModel::refreshView); QObject::connect(mSourceModel.data(), &QAbstractItemModel::layoutChanged, this, &EventModel::refreshView); QObject::connect(mSourceModel.data(), &QAbstractItemModel::modelReset, this, &EventModel::refreshView); QObject::connect(mSourceModel.data(), &QAbstractItemModel::rowsInserted, this, &EventModel::refreshView); QObject::connect(mSourceModel.data(), &QAbstractItemModel::rowsMoved, this, &EventModel::refreshView); QObject::connect(mSourceModel.data(), &QAbstractItemModel::rowsRemoved, this, &EventModel::refreshView); refreshView(); } void EventModel::refreshView() { if (!mRefreshTimer.isActive()) { //Instant update, but then only refresh every 50ms max. updateFromSource(); mRefreshTimer.start(50); } } void EventModel::updateFromSource() { beginResetModel(); mEvents.clear(); for (int i = 0; i < mSourceModel->rowCount(); ++i) { auto event = mSourceModel->index(i, 0).data(Sink::Store::DomainObjectRole).value(); if (!mCalendarFilter.contains(event->getCalendar())) { continue; } //Parse the event auto icalEvent = KCalCore::ICalFormat().readIncidence(event->getIcal()).dynamicCast(); if(!icalEvent) { SinkWarning() << "Invalid ICal to process, ignoring..."; continue; } if (icalEvent->recurs()) { const auto duration = icalEvent->hasDuration() ? icalEvent->duration().asSeconds() : 0; KCalCore::OccurrenceIterator occurrenceIterator{*mCalendar, icalEvent, QDateTime{mStart, {0, 0, 0}}, QDateTime{mEnd, {12, 59, 59}}}; while (occurrenceIterator.hasNext()) { occurrenceIterator.next(); const auto start = occurrenceIterator.occurrenceStartDate(); const auto end = start.addSecs(duration); if (start.date() < mEnd && end.date() >= mStart) { mEvents.append({start, end, occurrenceIterator.incidence(), getColor(event->getCalendar()), event->getAllDay()}); } } } else { if (icalEvent->dtStart().date() < mEnd && icalEvent->dtEnd().date() >= mStart) { mEvents.append({icalEvent->dtStart(), icalEvent->dtEnd(), icalEvent, getColor(event->getCalendar()), event->getAllDay()}); } } } endResetModel(); } QModelIndex EventModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) { return {}; } if (!parent.isValid()) { return createIndex(row, column); } return {}; } QModelIndex EventModel::parent(const QModelIndex &index) const { return {}; } int EventModel::rowCount(const QModelIndex &parent) const { if (!parent.isValid()) { return mEvents.size(); } return 0; } int EventModel::columnCount(const QModelIndex &parent) const { return 1; } QByteArray EventModel::getColor(const QByteArray &calendar) const { const auto color = mCalendarCache->getProperty(calendar, "color").toByteArray(); if (color.isEmpty()) { qWarning() << "Failed to get color for calendar " << calendar; } return color; } // QDateTime EventModel::getStartTimeOfDay(const QDateTime &dateTime, int day) const // { // if (bucketOf(dateTime.date()) < day) { // return QDateTime{mPeriodStart.addDays(day), QTime{0,0}}; // } // return dateTime; // } // QDateTime EventModel::getEndTimeOfDay(const QDateTime &dateTime, int day) const // { // if (bucketOf(dateTime.date()) > day) { // return QDateTime{mPeriodStart.addDays(day), QTime{23, 59, 59}}; // } // return dateTime; // } QVariant EventModel::data(const QModelIndex &idx, int role) const { if (!hasIndex(idx.row(), idx.column())) { return {}; } auto event = mEvents.at(idx.row()); auto icalEvent = event.incidence; switch (role) { case Summary: return icalEvent->summary(); case Description: return icalEvent->description(); case StartTime: return event.start; case EndTime: return event.end; case Color: return event.color; case AllDay: return event.allDay; default: SinkWarning() << "Unknown role for event:" << QMetaEnum::fromType().valueToKey(role); return {}; } } diff --git a/framework/src/domain/eventmodel.h b/framework/src/domain/eventmodel.h index a64f2a43..a5c11a4f 100644 --- a/framework/src/domain/eventmodel.h +++ b/framework/src/domain/eventmodel.h @@ -1,90 +1,100 @@ /* Copyright (c) 2018 Michael Bohlender Copyright (c) 2018 Christian Mollekopf Copyright (c) 2018 Rémi Nicole This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "kube_export.h" #include #include #include #include #include #include namespace KCalCore { class MemoryCalendar; class Incidence; } class EntityCacheInterface; class KUBE_EXPORT EventModel : public QAbstractItemModel { Q_OBJECT + Q_PROPERTY(QDate start READ start WRITE setStart) + Q_PROPERTY(int length WRITE setLength) + Q_PROPERTY(QSet calendarFilter WRITE setCalendarFilter) + public: enum Roles { Summary = Qt::UserRole + 1, Description, StartTime, EndTime, Color, AllDay, LastRole }; Q_ENUM(Roles); EventModel(QObject *parent = nullptr); ~EventModel() = default; QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override; QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent) const override; + int rowCount(const QModelIndex &parent = {}) const override; int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; void updateQuery(const QDate &start, const QDate &end, const QSet &calendarFilter); + void setStart(const QDate &); + QDate start() const; + void setLength(int); + void setCalendarFilter(const QSet &); + private: void updateQuery(); void refreshView(); void updateFromSource(); QByteArray getColor(const QByteArray &calendar) const; QSharedPointer mSourceModel; QSet mCalendarFilter; QDate mStart; QDate mEnd; + int mLength{0}; QSharedPointer mCalendarCache; QSharedPointer mCalendar; QTimer mRefreshTimer; struct Occurrence { QDateTime start; QDateTime end; QSharedPointer incidence; QByteArray color; bool allDay; }; QList mEvents; }; diff --git a/framework/src/domain/multidayeventmodel.cpp b/framework/src/domain/multidayeventmodel.cpp index 8e0b9df8..9bae64be 100644 --- a/framework/src/domain/multidayeventmodel.cpp +++ b/framework/src/domain/multidayeventmodel.cpp @@ -1,280 +1,165 @@ /* Copyright (c) 2018 Michael Bohlender Copyright (c) 2018 Christian Mollekopf Copyright (c) 2018 Rémi Nicole This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "multidayeventmodel.h" #include #include #include -#include -#include -#include - -#include -#include -#include - -#include #include enum Roles { Events = EventModel::LastRole }; MultiDayEventModel::MultiDayEventModel(QObject *parent) : QAbstractItemModel(parent) { - // mRefreshTimer.setSingleShot(true); - // QObject::connect(&mRefreshTimer, &QTimer::timeout, this, &MultiDayEventModel::updateFromSource); } -// void MultiDayEventModel::setSourceModel(QAbstractItemModel *model) -// { - // qWarning() << "Update query"; - // mCalendarFilter = calendarFilter; - // Sink::Query query; - // query.setFlags(Sink::Query::LiveQuery); - // query.request(); - // query.request(); - // query.request(); - // query.request(); - // query.request(); - // query.request(); - // query.request(); - - // query.filter(Sink::Query::Comparator(QVariantList{start, end}, Sink::Query::Comparator::Overlap)); - - // mSourceModel = Sink::Store::loadModel(query); - - // QObject::connect(model, &QAbstractItemModel::dataChanged, this, &MultiDayEventModel::modelReset); - // QObject::connect(model, &QAbstractItemModel::layoutChanged, this, &MultiDayEventModel::refreshView); - // QObject::connect(model, &QAbstractItemModel::modelReset, this, &MultiDayEventModel::refreshView); - // QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &MultiDayEventModel::refreshView); - // QObject::connect(model, &QAbstractItemModel::rowsMoved, this, &MultiDayEventModel::refreshView); - // QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &MultiDayEventModel::refreshView); - - // refreshView(); -// } - -//void MultiDayEventModel::refreshView() -//{ -// if (!mRefreshTimer.isActive()) { -// //Instant update, but then only refresh every 50ms max. -// updateFromSource(); -// mRefreshTimer.start(50); -// } -//} - -//void MultiDayEventModel::updateFromSource() -//{ -// beginResetModel(); - -// mEvents.clear(); - -// for (int i = 0; i < mSourceModel->rowCount(); ++i) { -// auto event = mSourceModel->index(i, 0).data(Sink::Store::DomainObjectRole).value(); -// if (!mCalendarFilter.contains(event->getCalendar())) { -// continue; -// } - -// //Parse the event -// auto icalEvent = KCalCore::ICalFormat().readIncidence(event->getIcal()).dynamicCast(); -// if(!icalEvent) { -// SinkWarning() << "Invalid ICal to process, ignoring..."; -// continue; -// } - -// if (icalEvent->recurs()) { -// const auto duration = icalEvent->hasDuration() ? icalEvent->duration().asSeconds() : 0; -// KCalCore::OccurrenceIterator occurrenceIterator{*mCalendar, icalEvent, QDateTime{mStart, {0, 0, 0}}, QDateTime{mEnd, {12, 59, 59}}}; -// while (occurrenceIterator.hasNext()) { -// occurrenceIterator.next(); -// const auto start = occurrenceIterator.occurrenceStartDate(); -// const auto end = start.addSecs(duration); -// if (start.date() < mEnd && end.date() >= mStart) { -// mEvents.append({start, end, occurrenceIterator.incidence(), getColor(event->getCalendar()), event->getAllDay()}); -// } -// } -// } else { -// if (icalEvent->dtStart().date() < mEnd && icalEvent->dtEnd().date() >= mStart) { -// mEvents.append({icalEvent->dtStart(), icalEvent->dtEnd(), icalEvent, getColor(event->getCalendar()), event->getAllDay()}); -// } -// } -// } - -// endResetModel(); -//} - QModelIndex MultiDayEventModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) { return {}; } if (!parent.isValid()) { return createIndex(row, column); } return {}; } -QModelIndex MultiDayEventModel::parent(const QModelIndex &index) const +QModelIndex MultiDayEventModel::parent(const QModelIndex &) const { return {}; } int MultiDayEventModel::rowCount(const QModelIndex &parent) const { - //Numbe of weeks + //Number of weeks if (!parent.isValid()) { return 1; } return 0; } -int MultiDayEventModel::columnCount(const QModelIndex &parent) const +int MultiDayEventModel::columnCount(const QModelIndex &) const { return 1; } QVariant MultiDayEventModel::data(const QModelIndex &idx, int role) const { if (!hasIndex(idx.row(), idx.column())) { return {}; } switch (role) { case Events: { if (!mSourceModel) { - qWarning() << "no source model"; return {}; } - qWarning() << "Getting events"; //FIXME set start date of this row - QDate rowStart = mStart; + QDate rowStart = mSourceModel->start(); auto getStart = [&] (const QDate &start) { return qMax(rowStart.daysTo(start), 0ll); }; auto getDuration = [&] (const QDate &start, const QDate &end) { return qMax(start.daysTo(end), 1ll); }; - //TODO iterate over source model, filter by allday, and get sorted list of indexes QMultiMap sorted; //Sort by duration for (int row = 0; row < mSourceModel->rowCount(); row++) { const auto srcIdx = mSourceModel->index(row, 0, {}); //Filter for allday only if (!srcIdx.data(EventModel::AllDay).toBool()) { continue; } - qWarning() << "Get start "<< srcIdx.data(EventModel::Summary) << srcIdx.data(EventModel::StartTime).toDateTime(); sorted.insert(getDuration(srcIdx.data(EventModel::StartTime).toDateTime().date(), srcIdx.data(EventModel::EndTime).toDateTime().date()), srcIdx); } auto result = QVariantList{}; auto currentLine = QVariantList{}; int lastStart = -1; int lastDuration = 0; for (const auto &srcIdx : sorted) { const auto start = getStart(srcIdx.data(EventModel::StartTime).toDateTime().date()); const auto duration = qMin(getDuration(srcIdx.data(EventModel::StartTime).toDateTime().date(), srcIdx.data(EventModel::EndTime).toDateTime().date()), mPeriodLength - start); - qWarning() << "Get start2 " << srcIdx.data(EventModel::Summary) << start << duration; const auto end = start + duration; currentLine.append(QVariantMap{ {"text", srcIdx.data(EventModel::Summary)}, {"description", srcIdx.data(EventModel::Description)}, {"starts", start}, {"duration", duration}, {"color", srcIdx.data(EventModel::Color)}, }); if (lastStart >= 0) { const auto lastEnd = lastStart + lastDuration; //Does intersect if (((start >= lastStart) && (start <= lastEnd)) || ((end >= lastStart) && (end <= lastStart)) || ((start <= lastStart) && (end >= lastEnd))) { result.append(QVariant::fromValue(currentLine)); - qWarning() << "Found intersection " << currentLine; + // qDebug() << "Found intersection " << currentLine; currentLine = {}; } } lastStart = start; lastDuration = duration; } if (!currentLine.isEmpty()) { result.append(QVariant::fromValue(currentLine)); } - qWarning() << "Getting events" << result; + // qDebug() << "Found events " << result; return result; } default: - // SinkWarning() << "Unknown role for event:" << QMetaEnum::fromType().valueToKey(role); Q_ASSERT(false); return {}; } } -void MultiDayEventModel::setConfiguration(const QVariantMap &configuration) -{ - mStart = configuration.value("start").toDate(); - mLength = configuration.value("length").toInt(); - setupModel(mStart, mLength, mFilter); -} - -void MultiDayEventModel::setupModel(const QDate &start, int length, const QSet &filter) +void MultiDayEventModel::setModel(EventModel *model) { beginResetModel(); - auto sourceModel = QSharedPointer::create(); - - sourceModel->updateQuery(start, start.addDays(length), filter); - + mSourceModel = model; auto resetModel = [this] { beginResetModel(); endResetModel(); }; - auto model = sourceModel.data(); QObject::connect(model, &QAbstractItemModel::dataChanged, this, resetModel); QObject::connect(model, &QAbstractItemModel::layoutChanged, this, resetModel); QObject::connect(model, &QAbstractItemModel::modelReset, this, resetModel); QObject::connect(model, &QAbstractItemModel::rowsInserted, this, resetModel); - // QObject::connect(model, &QAbstractItemModel::rowsMoved, this, &MultiDayEventModel::refreshView); - // QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &MultiDayEventModel::refreshView); - - mSourceModel = sourceModel; endResetModel(); } -void MultiDayEventModel::setCalendarFilter(const QSet &filter) -{ - mFilter = filter; - setupModel(mStart, mLength, mFilter); -} - QHash MultiDayEventModel::roleNames() const { return { {Events, "events"} }; } diff --git a/framework/src/domain/multidayeventmodel.h b/framework/src/domain/multidayeventmodel.h index fe425d9f..caac6c3a 100644 --- a/framework/src/domain/multidayeventmodel.h +++ b/framework/src/domain/multidayeventmodel.h @@ -1,86 +1,68 @@ /* Copyright (c) 2018 Michael Bohlender Copyright (c) 2018 Christian Mollekopf Copyright (c) 2018 Rémi Nicole This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include "kube_export.h" #include #include #include #include #include #include +#include "eventmodel.h" namespace KCalCore { class MemoryCalendar; class Incidence; } class EntityCacheInterface; /** * Each toplevel index represents a week. * The "events" roles provides a list of lists, where each list represents a visual line, * containing a number of events to display. */ class KUBE_EXPORT MultiDayEventModel : public QAbstractItemModel { Q_OBJECT - /** - * { - * start: QDateTime, - * length: int, - * calendarFilter: QList - * } - */ - Q_PROPERTY(QVariantMap configuration WRITE setConfiguration) - - // Q_PROPERTY(QVariant start READ periodStart WRITE setPeriodStart) - // Q_PROPERTY(int length READ periodLength WRITE setPeriodLength) - - Q_PROPERTY(QSet calendarFilter WRITE setCalendarFilter) + Q_PROPERTY(EventModel* model WRITE setModel) public: MultiDayEventModel(QObject *parent = nullptr); ~MultiDayEventModel() = default; QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override; QModelIndex parent(const QModelIndex &index) const override; int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; QHash roleNames() const override; - void setConfiguration(const QVariantMap &configuration); - void setCalendarFilter(const QSet &filter); + void setModel(EventModel *model); private: - void setupModel(const QDate &start, int length, const QSet &filter); - QSharedPointer mSourceModel; - QTimer mRefreshTimer; + EventModel *mSourceModel; int mPeriodLength{7}; - - QDate mStart; - int mLength; - QSet mFilter; }; diff --git a/framework/src/frameworkplugin.cpp b/framework/src/frameworkplugin.cpp index 2927de7d..63e17b91 100644 --- a/framework/src/frameworkplugin.cpp +++ b/framework/src/frameworkplugin.cpp @@ -1,195 +1,197 @@ /* Copyright (c) 2016 Michael Bohlender Copyright (c) 2016 Christian Mollekopf This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "frameworkplugin.h" #include "domain/maillistmodel.h" #include "domain/folderlistmodel.h" #include "domain/perioddayeventmodel.h" #include "domain/multidayeventmodel.h" +#include "domain/eventmodel.h" #include "domain/composercontroller.h" #include "domain/mime/messageparser.h" #include "domain/retriever.h" #include "domain/outboxmodel.h" #include "domain/mouseproxy.h" #include "domain/contactcontroller.h" #include "domain/peoplemodel.h" #include "domain/textdocumenthandler.h" #include "accounts/accountsmodel.h" #include "accounts/accountfactory.h" #include "settings/settings.h" #include "fabric.h" #include "kubeimage.h" #include "clipboardproxy.h" #include "startupcheck.h" #include "keyring.h" #include "controller.h" #include "domainobjectcontroller.h" #include "extensionmodel.h" #include "viewhighlighter.h" #include "file.h" #include "logmodel.h" #include "entitymodel.h" #include #include #include class KubeImageProvider : public QQuickImageProvider { public: KubeImageProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) { } QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) Q_DECL_OVERRIDE { //The platform theme plugin can overwrite our setting again once it gets loaded, //so we check on every icon load request... if (QIcon::themeName() != "kube") { QIcon::setThemeName("kube"); } const auto icon = QIcon::fromTheme(id); auto expectedSize = requestedSize; //Get the largest size that is still smaller or equal than requested //Except if we only have larger sizes, then just pick the closest one bool first = true; for (const auto s : icon.availableSizes()) { if (first && s.width() > requestedSize.width()) { expectedSize = s; break; } first = false; if (s.width() <= requestedSize.width()) { expectedSize = s; } } const auto pixmap = icon.pixmap(expectedSize); if (size) { *size = pixmap.size(); } return pixmap; } }; static QObject *fabric_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new Kube::Fabric::Fabric; } static QObject *keyring_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) auto instance = Kube::Keyring::instance(); QQmlEngine::setObjectOwnership(instance, QQmlEngine::CppOwnership); return instance; } static QString findFile(const QString file, const QStringList importPathList) { for (const auto &path : importPathList) { const QString f = path + file; if (QFileInfo::exists(f)) { return f; } } return {}; } void FrameworkPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { Q_UNUSED(uri); engine->addImageProvider(QLatin1String("kube"), new KubeImageProvider); QString kubeIcons = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("kube-icons.rcc")); //For windows if (kubeIcons.isEmpty()) { const auto locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation) + QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); kubeIcons = findFile(QStringLiteral("/kube/kube-icons.rcc"), locations); } //For osx if (kubeIcons.isEmpty()) { //On Mac OS we want to include Contents/Resources/ in the bundle, and that path is in AppDataLocations. QStringList iconSearchPaths; for (const auto &p : QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)) { auto iconPath = p; //I'm getting broken paths reported from standardLocations if (iconPath.contains("kube.appContents")) { iconPath.replace("kube.appContents", "kube.app/Contents"); } if (iconPath.contains("kube-kolabnow.appContents")) { iconPath.replace("kube-kolabnow.appContents", "kube-kolabnow.app/Contents"); } iconSearchPaths << iconPath; } kubeIcons = findFile(QStringLiteral("/kube/kube-icons.rcc"), iconSearchPaths); } if (!QResource::registerResource(kubeIcons, "/icons/kube")) { qWarning() << "Failed to register icon resource!" << kubeIcons; qWarning() << "Searched paths: " << QStandardPaths::standardLocations(QStandardPaths::AppDataLocation) + QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); Q_ASSERT(false); } else { QIcon::setThemeSearchPaths(QStringList() << QStringLiteral(":/icons")); QIcon::setThemeName(QStringLiteral("kube")); } } void FrameworkPlugin::registerTypes (const char *uri) { qmlRegisterType(uri, 1, 0, "FolderListModel"); qmlRegisterType(uri, 1, 0, "MailListModel"); qmlRegisterType(uri, 1, 0, "PeriodDayEventModel"); qmlRegisterType(uri, 1, 0, "MultiDayEventModel"); + qmlRegisterType(uri, 1, 0, "EventModel"); qmlRegisterType(uri, 1, 0, "ComposerController"); qmlRegisterType(uri, 1, 0, "ControllerAction"); qmlRegisterType(uri, 1, 0, "MessageParser"); qmlRegisterType(uri, 1, 0, "Retriever"); qmlRegisterType(uri, 1, 0, "OutboxModel"); qmlRegisterType(uri, 1, 0, "MouseProxy"); qmlRegisterType(uri, 1, 0,"ContactController"); qmlRegisterType(uri, 1, 0,"PeopleModel"); qmlRegisterType(uri, 1, 0, "TextDocumentHandler"); qmlRegisterType(uri, 1, 0, "LogModel"); qmlRegisterType(uri, 1, 0, "EntityModel"); qmlRegisterType(uri, 1, 0, "CheckableEntityModel"); qmlRegisterType(uri, 1, 0, "AccountFactory"); qmlRegisterType(uri, 1, 0, "AccountsModel"); qmlRegisterType(uri, 1, 0, "ExtensionModel"); qmlRegisterType(uri, 1, 0, "File"); qmlRegisterType(uri, 1, 0, "Settings"); qmlRegisterType(uri, 1, 0, "Listener"); qmlRegisterType(uri, 1, 0, "DomainObjectController"); qmlRegisterSingletonType(uri, 1, 0, "Fabric", fabric_singletontype_provider); qmlRegisterType(uri, 1, 0, "KubeImage"); qmlRegisterType(uri, 1, 0, "Clipboard"); qmlRegisterType(uri, 1, 0, "StartupCheck"); qmlRegisterType(uri, 1, 0, "ViewHighlighter"); qmlRegisterSingletonType(uri, 1, 0, "Keyring", keyring_singletontype_provider); } diff --git a/views/calendar/qml/MultiDayView.qml b/views/calendar/qml/MultiDayView.qml index 6dd6a2e2..78f65b17 100644 --- a/views/calendar/qml/MultiDayView.qml +++ b/views/calendar/qml/MultiDayView.qml @@ -1,116 +1,119 @@ /* * Copyright (C) 2018 Michael Bohlender, * Copyright (C) 2018 Christian Mollekopf, * * 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. */ import QtQuick 2.4 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.2 import org.kube.framework 1.0 as Kube Rectangle { id: root property int daysToShow property var dayWidth property date currentDate property date startDate property var calendarFilter //Internal property int numberOfLinesShown: 0 width: root.dayWidth * root.daysToShow color: Kube.Colors.viewBackgroundColor border.width: 1 border.color: Kube.Colors.buttonColor //+2 to compensate for borders height: numberOfLinesShown * Kube.Units.gridUnit + 2 visible: numberOfLinesShown //Dimm days in the past Rectangle { anchors { left: parent.left top: parent.top bottom: parent.bottom } //if more than 7 days in past, set to 7, otherwise actual number of days in the past width: (new Date(root.startDate.getFullYear(), root.startDate.getMonth(), root.startDate.getDate() + 7) < roundToDay(root.currentDate) ? 7 : root.currentDate.getDate() - root.startDate.getDate()) * root.dayWidth color: Kube.Colors.buttonColor opacity: 0.2 //Avoid showing at all in the future (the width calculation will not work either) visible: roundToDay(root.currentDate) >= roundToDay(root.startDate) } Column { id: fullDayListView anchors { fill: parent margins: 1 } //Lines Repeater { id: daysRepeater model: Kube.MultiDayEventModel { - configuration: {"start": root.startDate, "length": root.daysToShow, "calendarFilter": root.calendarFilter} - calendarFilter: root.calendarFilter + model: Kube.EventModel { + start: root.startDate + length: root.daysToShow + calendarFilter: root.calendarFilter + } } Repeater { id: linesRepeater model: events onCountChanged: { console.warn("eventcount ", count) root.numberOfLinesShown = count } Item { id: line height: Kube.Units.gridUnit width: parent.width //Events Repeater { id: eventsRepeater model: modelData Rectangle { x: root.dayWidth * modelData.starts y: 0 width: root.dayWidth * modelData.duration height: parent.height color: modelData.color radius: 2 border.width: 1 border.color: Kube.Colors.viewBackgroundColor Kube.Label { anchors { fill: parent leftMargin: Kube.Units.smallSpacing rightMargin: Kube.Units.smallSpacing } color: Kube.Colors.highlightedTextColor text: modelData.text elide: Text.ElideRight } } } } } } } }