File indexing completed on 2025-01-19 04:51:58

0001 /*
0002     Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
0003 
0004     This library is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to the
0016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301, USA.
0018 */
0019 #include "controller.h"
0020 
0021 #include <QQmlEngine>
0022 #include <QMetaProperty>
0023 #include <QStandardItemModel>
0024 #include <QStandardItem>
0025 #include <QUuid>
0026 #include <sink/log.h>
0027 
0028 using namespace Kube;
0029 
0030 ControllerState::ControllerState()
0031     : QObject()
0032 {
0033     QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
0034 }
0035 
0036 ControllerAction::ControllerAction()
0037     : ControllerState()
0038 {
0039 }
0040 
0041 void ControllerAction::execute()
0042 {
0043     emit triggered();
0044 }
0045 
0046 void Controller::classBegin()
0047 {
0048 }
0049 
0050 void Controller::componentComplete()
0051 {
0052     init();
0053 }
0054 
0055 void Controller::init()
0056 {
0057 }
0058 
0059 void Controller::clear()
0060 {
0061     auto meta = metaObject();
0062     //We want to get the offset for this class, but clear the properties of all subclasses (thus staticMetaObject for the offset)
0063     for (auto i = staticMetaObject.propertyOffset(); i < meta->propertyCount(); i++) {
0064         auto property = meta->property(i);
0065         setProperty(property.name(), QVariant());
0066     }
0067     for (const auto &p : dynamicPropertyNames()) {
0068         setProperty(p, QVariant());
0069     }
0070     emit cleared();
0071 }
0072 
0073 void Controller::run(const KAsync::Job<void> &job)
0074 {
0075     auto jobToExec = job.onError([] (const KAsync::Error &error) {
0076         SinkWarningCtx(Sink::Log::Context{"controller"}) << "Error while executing job: " << error.errorMessage;
0077     });
0078     //TODO handle error
0079     //TODO attach a log context to the execution that we can gather from the job?
0080     jobToExec.exec();
0081 }
0082 
0083 void Controller::propertyChanged(const QByteArray &property)
0084 {
0085     mModified = true;
0086     emit modifiedChanged();
0087 }
0088 
0089 bool Controller::modified() const
0090 {
0091     return mModified;
0092 }
0093 
0094 void Controller::setModified(bool modified)
0095 {
0096     mModified = modified;
0097     emit modifiedChanged();
0098 }
0099 
0100 static void traverse(const QStandardItemModel *model, const std::function<bool(QStandardItem *item)> &f)
0101 {
0102     auto root = model->invisibleRootItem();
0103     for (int row = 0; row < root->rowCount(); row++) {
0104         if (!f(root->child(row, 0))) {
0105             return;
0106         }
0107     }
0108 }
0109 
0110 ListPropertyController::ListPropertyController(const QStringList &roles)
0111     : QObject(),
0112     mModel(new QStandardItemModel)
0113 {
0114     //Generate a set of roles for the names. We're not using any enum, so the actual role value doesn't matter.
0115     int role = Qt::UserRole + 1;
0116     mRoles.insert("id", role);
0117     role++;
0118     for (const auto &r : roles) {
0119         mRoles.insert(r, role);
0120         role++;
0121     }
0122 
0123     QHash<int, QByteArray> roleNames;
0124     for (const auto &r : mRoles.keys()) {
0125         roleNames.insert(mRoles[r], r.toLatin1());
0126     }
0127     mModel->setItemRoleNames(roleNames);
0128 }
0129 
0130 void ListPropertyController::add(const QVariantMap &value)
0131 {
0132     auto item = new QStandardItem;
0133     auto id = QUuid::createUuid().toByteArray();
0134     item->setData(id, mRoles["id"]);
0135     for (const auto &k : value.keys()) {
0136         item->setData(value.value(k), mRoles[k]);
0137     }
0138     mModel->appendRow(QList<QStandardItem*>() << item);
0139     if (mModel->rowCount() <= 1) {
0140         emit emptyChanged();
0141     }
0142     emit added(id, value);
0143 }
0144 
0145 void ListPropertyController::remove(const QByteArray &id)
0146 {
0147     auto root = mModel->invisibleRootItem();
0148     const auto idRole = mRoles["id"];
0149     for (int row = 0; row < root->rowCount(); row++) {
0150         if (root->child(row, 0)->data(idRole).toByteArray() == id) {
0151             root->removeRow(row);
0152             break;
0153         }
0154     }
0155     emit removed(id);
0156     if (mModel->rowCount() <= 0) {
0157         emit emptyChanged();
0158     }
0159 }
0160 
0161 bool ListPropertyController::empty() const
0162 {
0163     return mModel->rowCount() == 0;
0164 }
0165 
0166 void ListPropertyController::clear()
0167 {
0168     mModel->clear();
0169 }
0170 
0171 QAbstractItemModel *ListPropertyController::model()
0172 {
0173     QQmlEngine::setObjectOwnership(mModel.data(), QQmlEngine::CppOwnership);
0174     return mModel.data();
0175 }
0176 
0177 void ListPropertyController::setValue(const QByteArray &id, const QString &key, const QVariant &value)
0178 {
0179     setValues(id, {{key, value}});
0180 }
0181 
0182 QVariant ListPropertyController::value(const QByteArray &id, const QString &key)
0183 {
0184     QVariant result;
0185     const auto idRole = mRoles["id"];
0186     ::traverse(mModel.data(), [&] (QStandardItem *item) {
0187         if (item->data(idRole).toByteArray() == id) {
0188             result = item->data(mRoles[key]);
0189             return false;
0190         }
0191         return true;
0192     });
0193     return result;
0194 }
0195 
0196 QByteArray ListPropertyController::findByProperty(const QByteArray &key, const QVariant &value) const
0197 {
0198     QByteArray id;
0199     const auto idRole = mRoles["id"];
0200     ::traverse(mModel.data(), [&] (QStandardItem *item) {
0201         if (item->data(mRoles[key]) == value) {
0202             id = item->data(idRole).toByteArray();
0203             return false;
0204         }
0205         return true;
0206     });
0207     return id;
0208 }
0209 
0210 void ListPropertyController::setValues(const QByteArray &id, const QVariantMap &values)
0211 {
0212     const auto idRole = mRoles["id"];
0213     ::traverse(mModel.data(), [&] (QStandardItem *item) {
0214         if (item->data(idRole).toByteArray() == id) {
0215             for (const auto &key : values.keys()) {
0216                 item->setData(values.value(key), mRoles[key]);
0217             }
0218             return false;
0219         }
0220         return true;
0221     });
0222 }
0223 
0224 void ListPropertyController::traverse(const std::function<void(const QVariantMap &)> &f)
0225 {
0226     ::traverse(mModel.data(), [&] (QStandardItem *item) {
0227         QVariantMap map;
0228         for (const auto &key : mRoles.keys()) {
0229             map.insert(key, item->data(mRoles[key]));
0230         }
0231         f(map);
0232         return true;
0233     });
0234 }
0235