diff --git a/framework/qml/StatusBar.qml b/framework/qml/StatusBar.qml index 062acb2a..d638d2a0 100644 --- a/framework/qml/StatusBar.qml +++ b/framework/qml/StatusBar.qml @@ -1,135 +1,136 @@ /* * Copyright (C) 2017 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.7 import org.kube.framework 1.0 as Kube Item { id: root property string accountId: "" - property string currentFolderName: "" + property string currentFolderName: entityLoader.name property string currentFolderId: "" property string errorText: "" visible: false - onCurrentFolderIdChanged: root.currentFolderName = "" - Kube.FolderListModel { - id: folderModel - folderId: root.currentFolderId - onRowsInserted: root.currentFolderName = folderModel.data(folderModel.index(0, 0), Kube.FolderListModel.Name) - onRowsRemoved: root.currentFolderName = "" + Kube.EntityLoader { + id: entityLoader + type: "folder" + roles: ["name"] + accountId: root.accountId + entityId: root.currentFolderId + property variant name } Repeater { model: Kube.AccountsModel { accountId: root.accountId } Item { anchors.fill: root anchors.leftMargin: Kube.Units.smallSpacing anchors.rightMargin: Kube.Units.smallSpacing Column { anchors.fill: parent Kube.Label { id: statusText anchors.horizontalCenter: parent.horizontalCenter color: Kube.Colors.highlightedTextColor states: [ State { name: "disconnected"; when: model.status == Kube.AccountsModel.OfflineStatus PropertyChanges { target: root; visible: true } PropertyChanges { target: statusText; text: qsTr("Disconnected"); visible: true } PropertyChanges { target: descriptionText; visible: root.errorText != "" } }, State { name: "busy"; when: model.status == Kube.AccountsModel.BusyStatus PropertyChanges { target: root; visible: true } PropertyChanges { target: statusText; text: root.currentFolderName.length > 0 ? "Synchronizing " + root.currentFolderName: "Synchronizing..."; visible: true } PropertyChanges { target: progressBar; visible: true } }, State { name: "error"; when: model.status == Kube.AccountsModel.ErrorStatus PropertyChanges { target: root; visible: true } PropertyChanges { target: statusText; text: root.errorText; visible: true } PropertyChanges { target: descriptionText; visible: true } } ] } Kube.Label { id: descriptionText anchors.horizontalCenter: parent.horizontalCenter width: parent.width visible: false color: Kube.Colors.disabledTextColor text: root.errorText elide: Text.ElideRight maximumLineCount: 1 } Kube.ProgressBar { id: progressBar anchors { horizontalCenter: parent.horizontalCenter topMargin: Kube.Units.smallSpacing } height: 2 width: parent.width indeterminate: true visible: false Kube.Listener { filter: Kube.Messages.progressNotification onMessageReceived: { progressBar.indeterminate = false progressBar.from = 0 progressBar.to = message.total progressBar.value = message.progress if (message.folderId) { root.currentFolderId = message.folderId } else { root.currentFolderId = "" } } } Kube.Listener { filter: Kube.Messages.errorNotification onMessageReceived: { root.errorText = message.message } } } } MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true } Kube.IconButton { anchors { right: parent.right verticalCenter: parent.verticalCenter } visible: progressBar.visible && (hovered || mouseArea.containsMouse) iconName: Kube.Icons.remove onClicked: Kube.Fabric.postMessage(Kube.Messages.abortSynchronization, {}) tooltip: qsTr("Abort") } } } } diff --git a/framework/src/entitymodel.cpp b/framework/src/entitymodel.cpp index b38ec1d6..0f9f4bb3 100644 --- a/framework/src/entitymodel.cpp +++ b/framework/src/entitymodel.cpp @@ -1,270 +1,331 @@ /* Copyright (c) 2018 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 "entitymodel.h" #include #include using namespace Sink; using namespace Sink::ApplicationDomain; enum Roles { IdRole = Qt::UserRole + 1, ObjectRole, LastRole }; EntityModel::EntityModel(QObject *parent) : QSortFilterProxyModel(parent) { setDynamicSortFilter(true); setFilterCaseSensitivity(Qt::CaseInsensitive); setSortCaseSensitivity(Qt::CaseInsensitive); } EntityModel::~EntityModel() { } QHash EntityModel::roleNames() const { return mRoleNames; } QVariant EntityModel::data(const QModelIndex &idx, int role) const { auto srcIdx = mapToSource(idx); auto entity = srcIdx.data(Sink::Store::DomainObjectBaseRole).value(); const auto roleName = mRoleNames.value(role); if (roleName == "identifier") { return entity->identifier(); } else if (roleName == "object") { return QVariant::fromValue(entity); } else { return entity->getProperty(roleName); } } bool EntityModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const { auto left = sourceLeft.data(Sink::Store::DomainObjectBaseRole).value(); auto right = sourceRight.data(Sink::Store::DomainObjectBaseRole).value(); const auto leftProperty = left->getProperty(mSortRole.toUtf8()).toString(); const auto rightProperty = right->getProperty(mSortRole.toUtf8()).toString(); return leftProperty < rightProperty; } void EntityModel::runQuery(const Query &query) { if (mType == "calendar") { mModel = Store::loadModel(query); } else if (mType == "addressbook") { mModel = Store::loadModel(query); + } else if (mType == "folder") { + mModel = Store::loadModel(query); } else { qWarning() << "Type not supported " << mType; Q_ASSERT(false); } setSourceModel(mModel.data()); } void EntityModel::updateQuery() { if (mType.isEmpty() || mRoles.isEmpty()) { return; } Query query; if (!mAccountId.isEmpty()) { query.resourceFilter(mAccountId.toUtf8()); } + if (!mResourceId.isEmpty()) { + query.resourceFilter(mResourceId.toUtf8()); + } + if (!mEntityId.isEmpty()) { + query.filter(mEntityId.toUtf8()); + } query.setFlags(Sink::Query::LiveQuery | Sink::Query::UpdateStatus); for (const auto &property: mRoles.keys()) { query.requestedProperties << property; } runQuery(query); } -void EntityModel::setAccountId(const QString &accountId) +void EntityModel::setAccountId(const QString &id) { - - //Get all folders of an account - mAccountId = accountId; - updateQuery(); + if (mAccountId != id) { + mAccountId = id; + updateQuery(); + } } QString EntityModel::accountId() const { - return {}; + return mAccountId; +} + +void EntityModel::setResourceId(const QString &id) +{ + if (mResourceId != id) { + mResourceId = id; + updateQuery(); + } +} + +QString EntityModel::resourceId() const +{ + return mResourceId; +} + +void EntityModel::setEntityId(const QString &id) +{ + if (mEntityId != id) { + mEntityId = id; + updateQuery(); + } +} + +QString EntityModel::entityId() const +{ + return mEntityId; } void EntityModel::setType(const QString &type) { mType = type; updateQuery(); } QString EntityModel::type() const { return {}; } void EntityModel::setRoles(const QStringList &roles) { mRoleNames.clear(); mRoleNames.insert(IdRole, "identifier"); mRoleNames.insert(ObjectRole, "object"); int role = LastRole; for (int i = 0; i < roles.size(); i++) { mRoleNames.insert(role++, roles.at(i).toLatin1()); } mRoles.clear(); for (const auto &r : mRoleNames.keys()) { mRoles.insert(mRoleNames.value(r), r); } updateQuery(); } QStringList EntityModel::roles() const { // return mRoleNames.values(); return {}; } void EntityModel::setFilter(const QVariantMap &) { //TODO } QVariantMap EntityModel::filter() const { return {}; } void EntityModel::setSortRole(const QString &sortRole) { mSortRole = sortRole; sort(0, Qt::AscendingOrder); } QString EntityModel::sortRole() const { return mSortRole; } QVariantMap EntityModel::data(int row) const { QVariantMap map; for (const auto &r : mRoleNames.keys()) { map.insert(mRoleNames.value(r), data(index(row, 0), r)); } return map; } bool EntityModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!mRoleNames.contains(role)) { return false; } const auto entity = EntityModel::data(index, ObjectRole).value(); //FIXME hardcoding calendar is not a great idea here. Sink::ApplicationDomain::Calendar modifiedEntity{*entity}; const auto propertyName = mRoleNames.value(role); modifiedEntity.setProperty(propertyName, value.toBool()); //Ignore if we didn't modify anything. if (!modifiedEntity.changedProperties().isEmpty()) { Sink::Store::modify(modifiedEntity).exec(); } return true; } +EntityLoader::EntityLoader(QObject *parent) : EntityModel(parent) +{ + QObject::connect(this, &QAbstractItemModel::rowsInserted, this, [this] (const QModelIndex &parent, int first, int last) { + for (int row = first; row <= last; row++) { + auto idx = index(row, 0, parent); + for (const auto &r : mRoleNames.keys()) { + setProperty(mRoleNames.value(r), data(idx, r)); + } + //We only ever use the first index (we're not expecting any more either) + break; + } + }); +} + +EntityLoader::~EntityLoader() +{ + +} + +void EntityLoader::updateQuery() +{ + if (entityId().isEmpty()) { + return; + } + EntityModel::updateQuery(); +} + CheckableEntityModel::CheckableEntityModel(QObject *parent) : EntityModel(parent) { } CheckableEntityModel::~CheckableEntityModel() { } QHash CheckableEntityModel::roleNames() const { auto roleNames = EntityModel::roleNames(); roleNames.insert(Qt::CheckStateRole, "checked"); return roleNames; } QVariant CheckableEntityModel::data(const QModelIndex &index, int role) const { if (mCheckedEntities && role == Qt::CheckStateRole) { return mCheckedEntities->contains(EntityModel::data(index, IdRole).toByteArray()); } return EntityModel::data(index, role); } bool CheckableEntityModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (mCheckedEntities && role == Qt::CheckStateRole) { auto identifier = EntityModel::data(index, IdRole).toByteArray(); if (value.toBool()) { mCheckedEntities->insert(identifier); } else { mCheckedEntities->remove(identifier); } return true; } return EntityModel::setData(index, value, role); } CheckedEntities *CheckableEntityModel::checkedEntities() const { return mCheckedEntities; } void CheckableEntityModel::setCheckedEntities(CheckedEntities *checkedEntities) { mCheckedEntities = checkedEntities; } void CheckedEntities::insert(const QByteArray &id) { mCheckedEntities.insert(id); emit checkedEntitiesChanged(); } void CheckedEntities::remove(const QByteArray &id) { mCheckedEntities.remove(id); emit checkedEntitiesChanged(); } bool CheckedEntities::contains(const QByteArray &id) const { return mCheckedEntities.contains(id); } QSet CheckedEntities::checkedEntities() const { return mCheckedEntities; } diff --git a/framework/src/entitymodel.h b/framework/src/entitymodel.h index 080e22bf..6592843c 100644 --- a/framework/src/entitymodel.h +++ b/framework/src/entitymodel.h @@ -1,121 +1,141 @@ /* Copyright (c) 2018 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. */ #pragma once #include "kube_export.h" #include #include #include #include namespace Sink { class Query; } class KUBE_EXPORT EntityModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY (QString accountId READ accountId WRITE setAccountId) + Q_PROPERTY (QString resourceId READ resourceId WRITE setResourceId) + Q_PROPERTY (QString entityId READ entityId WRITE setEntityId) Q_PROPERTY (QString type READ type WRITE setType) Q_PROPERTY (QStringList roles READ roles WRITE setRoles) Q_PROPERTY (QString sortRole READ sortRole WRITE setSortRole) Q_PROPERTY (QVariantMap filter READ filter WRITE setFilter) public: enum Status { NoStatus, InProgressStatus, ErrorStatus, SuccessStatus, }; Q_ENUMS(Status) EntityModel(QObject *parent = Q_NULLPTR); virtual ~EntityModel(); virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; virtual QHash roleNames() const override; void setAccountId(const QString &); QString accountId() const; + void setResourceId(const QString &); + QString resourceId() const; + + void setEntityId(const QString &); + QString entityId() const; + void setType(const QString &); QString type() const; void setRoles(const QStringList &); QStringList roles() const; void setFilter(const QVariantMap &); QVariantMap filter() const; void setSortRole(const QString &); QString sortRole() const; Q_INVOKABLE QVariantMap data(int row) const; protected: bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; + virtual void updateQuery(); + QHash mRoleNames; + private: void runQuery(const Sink::Query &query); - void updateQuery(); QSharedPointer mModel; - QHash mRoleNames; QHash mRoles; QString mAccountId; + QString mResourceId; + QString mEntityId; QString mType; QString mSortRole; }; +class KUBE_EXPORT EntityLoader : public EntityModel { + Q_OBJECT +public: + EntityLoader(QObject *parent = Q_NULLPTR); + virtual ~EntityLoader(); +protected: + void updateQuery() override; +}; + class KUBE_EXPORT CheckedEntities : public QObject { Q_OBJECT Q_PROPERTY (QSet checkedEntities READ checkedEntities NOTIFY checkedEntitiesChanged) public: bool contains(const QByteArray &) const; void insert(const QByteArray &); void remove(const QByteArray &); QSet checkedEntities() const; signals: void checkedEntitiesChanged(); private: QSet mCheckedEntities; }; class KUBE_EXPORT CheckableEntityModel : public EntityModel { Q_OBJECT Q_PROPERTY (CheckedEntities* checkedEntities READ checkedEntities WRITE setCheckedEntities CONSTANT) public: CheckableEntityModel(QObject *parent = Q_NULLPTR); virtual ~CheckableEntityModel(); QHash roleNames() const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; CheckedEntities *checkedEntities() const; void setCheckedEntities(CheckedEntities *); private: CheckedEntities *mCheckedEntities = nullptr; }; diff --git a/framework/src/frameworkplugin.cpp b/framework/src/frameworkplugin.cpp index 0748b2dc..3885f05a 100644 --- a/framework/src/frameworkplugin.cpp +++ b/framework/src/frameworkplugin.cpp @@ -1,200 +1,201 @@ /* 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/eventcontroller.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, "EventController"); 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, "EntityLoader"); qmlRegisterType(uri, 1, 0, "CheckedEntities"); 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/framework/src/tests/CMakeLists.txt b/framework/src/tests/CMakeLists.txt index b7ba3c54..984b1da4 100644 --- a/framework/src/tests/CMakeLists.txt +++ b/framework/src/tests/CMakeLists.txt @@ -1,33 +1,42 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. ) find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Core Test Gui) add_executable(folderlistmodeltest folderlistmodeltest.cpp) add_test(folderlistmodeltest folderlistmodeltest) target_link_libraries(folderlistmodeltest Qt5::Core Qt5::Test Qt5::Gui kubeframework ) add_executable(maillistmodeltest maillistmodeltest.cpp) add_test(maillistmodeltest maillistmodeltest) target_link_libraries(maillistmodeltest Qt5::Core Qt5::Test Qt5::Gui kubeframework ) add_executable(eventmodeltest eventmodeltest.cpp) add_test(eventmodeltest eventmodeltest) target_link_libraries(eventmodeltest Qt5::Core Qt5::Test Qt5::Gui kubeframework ) + +add_executable(entitymodeltest entitymodeltest.cpp) +add_test(entitymodeltest entitymodeltest) +target_link_libraries(entitymodeltest + Qt5::Core + Qt5::Test + Qt5::Gui + kubeframework +) diff --git a/framework/src/tests/entitymodeltest.cpp b/framework/src/tests/entitymodeltest.cpp new file mode 100644 index 00000000..0543dee9 --- /dev/null +++ b/framework/src/tests/entitymodeltest.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + +#include "entitymodel.h" + +class EntityModelTest : public QObject +{ + Q_OBJECT +private slots: + + void initTestCase() + { + Sink::Test::initTest(); + } + + void testModel() + { + Sink::ApplicationDomain::DummyResource::create("account1"); + + using namespace Sink::ApplicationDomain; + auto account = ApplicationDomainType::createEntity(); + Sink::Store::create(account).exec().waitForFinished(); + + auto resource = Sink::ApplicationDomain::DummyResource::create(account.identifier()); + Sink::Store::create(resource).exec().waitForFinished(); + + auto calendar1 = ApplicationDomainType::createEntity(resource.identifier()); + calendar1.setName("name1"); + Sink::Store::create(calendar1).exec().waitForFinished(); + + auto calendar2 = ApplicationDomainType::createEntity(resource.identifier()); + calendar2.setName("name2"); + Sink::Store::create(calendar2).exec().waitForFinished(); + + + Sink::ResourceControl::flushMessageQueue(resource.identifier()).exec().waitForFinished(); + + { + EntityModel model; + model.setType("calendar"); + model.setRoles({"name"}); + model.setAccountId(account.identifier()); + QTRY_COMPARE(model.rowCount({}), 2); + } + + { + EntityModel model; + model.setType("calendar"); + model.setRoles({"name"}); + model.setAccountId(account.identifier()); + model.setEntityId(calendar2.identifier()); + QTRY_COMPARE(model.rowCount({}), 1); + QCOMPARE(model.data(0).value("name").toString(), {"name2"}); + } + + { + EntityLoader model; + model.setType("calendar"); + model.setRoles({"name"}); + model.setAccountId(account.identifier()); + model.setEntityId(calendar2.identifier()); + QTRY_COMPARE(model.rowCount({}), 1); + QCOMPARE(model.property("name").toString(), {"name2"}); + } + } +}; + +QTEST_MAIN(EntityModelTest) +#include "entitymodeltest.moc"