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