File indexing completed on 2025-01-05 04:54: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 #pragma once
0020 #include "kube_export.h"
0021 #include <QObject>
0022 #include <QVariant>
0023 #include <QAbstractItemModel>
0024 #include <QStandardItemModel>
0025 #include <QQmlParserStatus>
0026 #include <KAsync/Async>
0027 
0028 #define KUBE_CONTROLLER_PROPERTY(TYPE, NAME, LOWERCASENAME) \
0029     public: Q_PROPERTY(TYPE LOWERCASENAME READ get##NAME WRITE setInternal##NAME NOTIFY LOWERCASENAME##Changed) \
0030     Q_SIGNALS: void LOWERCASENAME##Changed(); \
0031     private: TYPE m##NAME; \
0032     public: \
0033     struct NAME { \
0034         static constexpr const char *name = #LOWERCASENAME; \
0035         typedef TYPE Type; \
0036     }; \
0037     void set##NAME(const TYPE &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \
0038     void setInternal##NAME(const TYPE &value) { if (m##NAME != value) {m##NAME = value; emit LOWERCASENAME##Changed(); propertyChanged(NAME::name);} } \
0039     void clear##NAME() { setProperty(NAME::name, QVariant{}); } \
0040     TYPE get##NAME() const { return m##NAME; } \
0041 
0042 
0043 #define KUBE_CONTROLLER_ACTION(NAME) \
0044     Q_PROPERTY (Kube::ControllerAction* NAME##Action READ NAME##Action CONSTANT) \
0045     private: QScopedPointer<Kube::ControllerAction> action_##NAME; \
0046     public: Kube::ControllerAction* NAME##Action() const { Q_ASSERT(action_##NAME); return action_##NAME.data(); } \
0047     private slots: void NAME(); \
0048 
0049 #define KUBE_CONTROLLER_LISTCONTROLLER(NAME) \
0050     Q_PROPERTY (Kube::ListPropertyController* NAME READ NAME##Controller CONSTANT) \
0051     private: QScopedPointer<Kube::ListPropertyController> controller_##NAME; \
0052     public: Kube::ListPropertyController* NAME##Controller() const { Q_ASSERT(controller_##NAME); return controller_##NAME.data(); } \
0053 
0054 
0055 namespace Kube {
0056 
0057 class ControllerState : public QObject {
0058     Q_OBJECT
0059     Q_PROPERTY(bool enabled MEMBER mEnabled NOTIFY enabledChanged)
0060 public:
0061     ControllerState();
0062     ~ControllerState() = default;
0063 
0064     void setEnabled(bool enabled) { setProperty("enabled", enabled); }
0065 
0066 signals:
0067     void enabledChanged();
0068 
0069 private:
0070     bool mEnabled = false;
0071 };
0072 
0073 class KUBE_EXPORT ControllerAction : public ControllerState {
0074     Q_OBJECT
0075 public:
0076     ControllerAction();
0077     template <typename Func>
0078     ControllerAction(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func slot)
0079     : ControllerAction()
0080     {
0081         QObject::connect(this, &ControllerAction::triggered, obj, slot);
0082     }
0083 
0084     ~ControllerAction() = default;
0085 
0086     Q_INVOKABLE void execute();
0087 
0088 signals:
0089     void triggered();
0090 };
0091 
0092 class Controller : public QObject, public QQmlParserStatus {
0093     Q_OBJECT
0094     Q_INTERFACES(QQmlParserStatus)
0095     Q_PROPERTY(bool modified READ modified WRITE setModified NOTIFY modifiedChanged)
0096 
0097 public:
0098     Controller() = default;
0099     virtual ~Controller() = default;
0100 
0101     virtual void init();
0102 
0103     void classBegin() override;
0104     void componentComplete() override;
0105     bool modified() const;
0106     void setModified(bool);
0107     void propertyChanged(const QByteArray &);
0108 
0109 public slots:
0110     virtual void clear();
0111 
0112 signals:
0113     void done();
0114     void error();
0115     void cleared();
0116     void modifiedChanged();
0117 
0118 protected:
0119     void run(const KAsync::Job<void> &job);
0120 
0121 private:
0122     bool mModified{false};
0123 };
0124 
0125 class KUBE_EXPORT ListPropertyController : public QObject
0126 {
0127     Q_OBJECT
0128     Q_PROPERTY(QAbstractItemModel* model READ model CONSTANT)
0129     Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged)
0130 
0131 public:
0132     ListPropertyController(const QStringList &roles);
0133     Q_INVOKABLE virtual void add(const QVariantMap &value);
0134     Q_INVOKABLE virtual void remove(const QByteArray &id);
0135     Q_INVOKABLE void clear();
0136 
0137     QAbstractItemModel *model();
0138 
0139     void setValue(const QByteArray &id, const QString &key, const QVariant &);
0140     void setValues(const QByteArray &id, const QVariantMap &values);
0141     QVariant value(const QByteArray &id, const QString &key);
0142     void traverse(const std::function<void(const QVariantMap &)> &f);
0143 
0144     QByteArray findByProperty(const QByteArray &key, const QVariant &) const;
0145 
0146     template<typename T>
0147     QList<T> getList(const QString &property)
0148     {
0149         QList<T> list;
0150         traverse([&] (const QVariantMap &map) {
0151             list << map[property].value<T>();
0152         });
0153         return list;
0154     }
0155 
0156     bool empty() const;
0157 
0158 Q_SIGNALS:
0159     void added(QByteArray, QVariantMap);
0160     void removed(QByteArray);
0161     void emptyChanged();
0162 
0163 protected:
0164     QScopedPointer<QStandardItemModel> mModel;
0165 
0166 private:
0167     QHash<QString, int> mRoles;
0168 };
0169 
0170 
0171 }