File indexing completed on 2024-06-02 06:03:17

0001 /*
0002     This file is part of the Kasten Framework, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2008 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #ifndef KASTEN_ABSTRACTMODEL_HPP
0010 #define KASTEN_ABSTRACTMODEL_HPP
0011 
0012 // lib
0013 #include "kastencore_export.hpp"
0014 // Qt
0015 #include <QObject>
0016 // Std
0017 #include <memory>
0018 
0019 class QString;
0020 
0021 namespace Kasten {
0022 class AbstractModelPrivate;
0023 
0024 // TODO: reasons not to name it AbstractObjectModel, but just as it is
0025 class KASTENCORE_EXPORT AbstractModel : public QObject
0026 {
0027     Q_OBJECT
0028 
0029 protected:
0030     explicit AbstractModel(AbstractModel* baseModel = nullptr);
0031     KASTENCORE_NO_EXPORT explicit AbstractModel(AbstractModelPrivate* d);
0032 
0033 public:
0034     ~AbstractModel() override;
0035 
0036 public:
0037 // TODO: just one baseModel, or can there be multiple? Better name?
0038     AbstractModel* baseModel() const;
0039     /**
0040      * returns the first baseModel which is of type T, or null if none is found.
0041      * The search is started with the model itself
0042      */
0043     template <typename T>
0044     T findBaseModel() const;
0045     /**
0046      * returns the first baseModel which is of type T, or null if none is found.
0047      * The search is started with the model itself
0048      */
0049     template <typename T>
0050     AbstractModel* findBaseModelWithInterface() const;
0051 
0052 public: // API to be implemented
0053     virtual QString title() const = 0;
0054 
0055     /** Default returns false */
0056     virtual bool isModifiable() const;
0057     /** default returns true */
0058     virtual bool isReadOnly() const;
0059     /** default does nothing */
0060     virtual void setReadOnly(bool isReadOnly);
0061 
0062 Q_SIGNALS:
0063     // TODO: readonly and modifiable should be turned into flags, also get/set methods
0064     void readOnlyChanged(bool isReadOnly);
0065     void modifiableChanged(bool isModifiable);
0066     void titleChanged(const QString& newTitle);
0067 
0068 protected:
0069     void setBaseModel(AbstractModel* baseModel);
0070 
0071 protected:
0072     const std::unique_ptr<AbstractModelPrivate> d_ptr;
0073 
0074 private:
0075     Q_DECLARE_PRIVATE(AbstractModel)
0076 };
0077 
0078 template <typename T>
0079 T AbstractModel::findBaseModel() const
0080 {
0081     auto* model = const_cast<AbstractModel*>(this);
0082     do {
0083         T castedModel = qobject_cast<T>(model);
0084         if (castedModel) {
0085             return castedModel;
0086         }
0087         model = model->baseModel();
0088     } while (model);
0089 
0090     return nullptr;
0091 }
0092 
0093 template <typename T>
0094 AbstractModel* AbstractModel::findBaseModelWithInterface() const
0095 {
0096     auto* model = const_cast<AbstractModel*>(this);
0097     do {
0098         T interface = qobject_cast<T>(model);
0099         if (interface) {
0100             return model;
0101         }
0102         model = model->baseModel();
0103     } while (model);
0104 
0105     return nullptr;
0106 }
0107 
0108 }
0109 
0110 #endif