File indexing completed on 2024-12-22 04:31:09

0001 /*
0002  * <one line to give the program's name and a brief idea of what it does.>
0003  * Copyright (C) 2019  camilo <chiguitar@unal.edu.co>
0004  *
0005  * This program is free software: you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation, either version 3 of the License, or
0008  * (at your option) any later version.
0009  *
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  * GNU General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU General Public License
0016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 #pragma once
0020 
0021 #include <QObject>
0022  #include <QQmlEngine>
0023 #include "fmh.h"
0024 
0025 #include "mauikit_export.h"
0026 
0027 #include <QQmlParserStatus>
0028 
0029 /**
0030  * @brief MauiList class.
0031  * 
0032  * A helper class for easily setting up a list model to be feed into MauiModel::list, and to be used by the browsing views in Mauikit controls.
0033  * 
0034  * @warning This method of setting up a data model is very limited by the lingo supported by the FMH::MODEL_KEY dictionary.
0035  * So only consider using this class if your data model structure is based on only string text and can be represented by the FMH::MODEL_KEY dictionary entries. 
0036  * @see FMH::MODEL_KEY
0037  * 
0038  * This inherits from the QQmlParserStatus class, so t can be aware of its creation status in the QML engine. This is useful to lazy-loading parts when needed, as when the component presenting the data model is ready and loaded.
0039  * 
0040  * The list generated by sub-classing MauiList is meant to be used as the list for the MauiModel class, exposed to QML as the `BaseModel` type. The MauiModel supports features, such as filtering and sorting.
0041  * @see MauiModel
0042  * 
0043  * @image html Misc/listbrowser_data.png
0044  * 
0045  * @section example Example
0046  * This is a simple example of a MauiList based data model.
0047  * 
0048  * First wee need to setup the MauiList data. In the example below the data is manually added. The data must be modeled using the FMH::MODEL_LIST, which is an array list of FMH::MODEL, which is a map of key pairs, where the key must be a FMH::MODEL_KEY enum type, and the value a string text.
0049  * 
0050  * @code 
0051  * #pragma once
0052  * 
0053  * #include <QObject>
0054  * #include <MauiKit4/Core/mauilist.h>
0055  * 
0056  * class PlantsList : public MauiList
0057  * {
0058  *    Q_OBJECT
0059  * public:
0060  *    PlantsList(QObject *parent = nullptr);
0061  * 
0062  *    // QQmlParserStatus interface
0063  *    void componentComplete();
0064  * 
0065  *    // MauiList interface
0066  *    const FMH::MODEL_LIST &items() const;
0067  * 
0068  * private:
0069  *    FMH::MODEL_LIST m_list;
0070  * 
0071  *    //Here we have our own custom raw data and turn it into a FMH::MODEL_LIST
0072  *    FMH::MODEL_LIST getData() const;
0073  * };
0074  * @endcode
0075  * 
0076  * 
0077  * In this example the data is only retrieved once the QML engine has completely loaded the component using the MauiList, for this we override the `componentComplete()` virtual method, and there we inform the MauiModel with the signals that the list data is ready.
0078  * 
0079  * @code
0080  * #include "plantslist.h"
0081  * 
0082  * PlantsList::PlantsList(QObject *parent) : MauiList(parent)
0083  * {
0084  * 
0085  * }
0086  * 
0087  * void PlantsList::componentComplete()
0088  * {
0089  *    Q_EMIT preListChanged();
0090  *    m_list = getData();
0091  *    Q_EMIT postListChanged();
0092  *    Q_EMIT countChanged();
0093  * }
0094  * 
0095  * const FMH::MODEL_LIST &PlantsList::items() const
0096  * {
0097  *    return m_list;
0098  * }
0099  * 
0100  * FMH::MODEL_LIST PlantsList::getData() const
0101  * {
0102  *    FMH::MODEL_LIST data;
0103  * 
0104  *    data << FMH::MODEL {{FMH::MODEL_KEY::TITLE, QStringLiteral("Acanthaceae")}, {FMH::MODEL_KEY::CATEGORY, QStringLiteral("Acanthus")}};
0105  * 
0106  *    data << FMH::MODEL {{FMH::MODEL_KEY::TITLE, QStringLiteral("Agavaceae")}, {FMH::MODEL_KEY::CATEGORY, QStringLiteral("Agave")}};
0107  * 
0108  *    data << FMH::MODEL {{FMH::MODEL_KEY::TITLE, QStringLiteral("Bixaceae")}, {FMH::MODEL_KEY::CATEGORY, QStringLiteral("Annatto")}};
0109  * 
0110  *    data << FMH::MODEL {{FMH::MODEL_KEY::TITLE, QStringLiteral("Asteraceae")}, {FMH::MODEL_KEY::CATEGORY, QStringLiteral("Aster")}};
0111  * 
0112  *    data << FMH::MODEL {{FMH::MODEL_KEY::TITLE, QStringLiteral("Leguminaceae")}, {FMH::MODEL_KEY::CATEGORY, QStringLiteral("Bean")}};
0113  * 
0114  *    return data;
0115  * }
0116  * 
0117  * @endcode
0118  * 
0119  * Now we register our own custom PlanstList class to the QML engine as a type.
0120  * 
0121  * @code
0122  * #include <MauiKit3/Core/mauiapp.h>
0123  * #include "plantslist.h"
0124  * 
0125  * int main(int argc, char *argv[])
0126  * {
0127  *    ...
0128  *    
0129  *    qmlRegisterType<PlantsList>("org.maui.demo", 1, 0, "PlantsList"); //Here we register it.
0130  * 
0131  *    engine.load(url);
0132  * 
0133  *    return app.exec();
0134  * }
0135  * @endcode
0136  * 
0137  * And finally, we can consume the data list by hooking it up to the MauiModel exposed type `BaseModel`.
0138  * 
0139  * @code
0140  * import org.mauikit.controls as Maui
0141  * 
0142  * import org.maui.demo as Demo
0143  * 
0144  * Maui.ApplicationWindow
0145  * {
0146  *    id: root
0147  * 
0148  *    Maui.Page
0149  *    {
0150  *        id: _page
0151  *        anchors.fill: parent
0152  *        Maui.Controls.showCSD: true
0153  *        headBar.forceCenterMiddleContent: true
0154  * 
0155  *        Maui.ListBrowser
0156  *        {
0157  *            anchors.fill: parent
0158  *            model: Maui.BaseModel
0159  *            {
0160  *                list: Demo.PlantsList
0161  *                {
0162  * 
0163  *                }
0164  *            }
0165  * 
0166  *            delegate: Maui.ListBrowserDelegate
0167  *            {
0168  *                width: ListView.view.width
0169  *                label1.text: model.title
0170  *                label2.text: model.category
0171  *            }
0172  *        }
0173  *    }
0174  * }
0175  * @endcode
0176  * 
0177  * <a href="https://invent.kde.org/maui/mauikit/-/blob/qt6-2/examples/mauilist/">You can find a more complete example at this link.</a>
0178  */
0179 class MAUIKIT_EXPORT MauiList : public QObject, public QQmlParserStatus
0180 {
0181     
0182     Q_OBJECT
0183     QML_ANONYMOUS
0184     Q_INTERFACES(QQmlParserStatus)
0185 
0186     Q_DISABLE_COPY(MauiList)
0187     
0188     /**
0189      * The total amount of elements in the list.
0190      * @note This needs to be setup manually, as in emitting the signal when new items are appended or removed, etc.
0191      */
0192     Q_PROPERTY(int count READ getCount NOTIFY countChanged FINAL)
0193     
0194 public:
0195     /**
0196      * @brief Default constructor. The usage of this class is meant to be via inheritance by sub-classing it.
0197      */
0198     explicit MauiList(QObject *parent = nullptr);
0199     
0200     /**
0201      * @brief The modeled data represented by a FMH::MODEL_LIST.
0202      * @note  The data must be modeled using the FMH::MODEL_LIST, which is an array list of FMH::MODEL elements, which is a map of key pairs, where the key must be a FMH::MODEL_KEY enum type, and the value a string text.
0203      * 
0204      * @return The data model.
0205      */
0206     virtual const FMH::MODEL_LIST &items() const = 0;
0207     
0208     /**
0209      * @brief See the Qt documentation on the QQmlParserStatus.
0210      */
0211     virtual void classBegin() override {}
0212     
0213     /**
0214      * @brief See the Qt documentation on the QQmlParserStatus.
0215      */
0216     virtual void componentComplete() override  {}
0217     
0218     /**
0219      * @brief This function is called once the MauiList has been hooked to the MauiModel, using the MauiModel::list property.
0220      */
0221     virtual void modelHooked() {}
0222     
0223     int getCount() const;
0224     
0225     /**
0226      * @brief Request to get an item in the list, the item is represented as a FMH::MODEL key pair value.
0227      * @param index the position of the item to retrieve
0228      * @return The found item/map in the list at the index. If not item is found at the given index, then an empty map is returned.
0229      */
0230     FMH::MODEL getItem(const int &index) const;
0231     
0232 public Q_SLOTS:    
0233     /**
0234      * @brief Request to get an item in the list, the item is represented as a QVariantMap for easy consumption within the QML scope. This function is exposed to be invoked from QML.
0235      * @param index the position of the item to retrieve
0236      * @return The found item/map in the list at the index. If not item is found at the given index, then an empty map is returned.
0237      */
0238     QVariantMap get(const int &index) const;
0239     
0240 protected:    
0241     /**
0242      * @brief Whether an item with a given key-par value exists in the list.
0243      * @param key the FMH::MODEL_KEY to look for
0244      * @param value the value associated with the key to look for
0245      * @return an exact match exists or not
0246      */
0247     bool exists(const FMH::MODEL_KEY &key, const QString &value) const;
0248     
0249     /**
0250      * @brief The index number of an item in the list of a given key-par value.
0251      * @param key the FMH::MODEL_KEY to look for
0252      * @param value the value associated with the key to look for
0253      * @return the found index or `-1` if not found
0254      */
0255     int indexOf(const FMH::MODEL_KEY &key, const QString &value) const;
0256     
0257 Q_SIGNALS:    
0258     /**
0259      * @brief This signal should be emitted by the implementation before appending a new item to the list data model.
0260      */
0261     void preItemAppended();
0262     
0263      /**
0264      * @brief This signal should be emitted by the implementation before appending a multiple new items to the list data model.
0265      * @param count the total amount of new items that will be added
0266      */
0267     void preItemsAppended(uint count);
0268     
0269     /**
0270      * @brief This signal should be emitted by the implementation after one or multiple new items have finished being added into the list data model.
0271      */
0272     void postItemAppended();
0273     
0274     /**
0275      * @brief This signal should be emitted by the implementation before a new item has been inserted at a given index to the list data model.
0276      * @param index the position index where the new item was inserted at
0277      */
0278     void preItemAppendedAt(int index);
0279     
0280     /**
0281      * @brief This signal should be emitted by the implementation before an item has been removed at the given index position.
0282      * @param index the index position of the element that will be removed
0283      */
0284     void preItemRemoved(int index);
0285     
0286     /**
0287      * @brief This signal should be emitted by the implementation after an item has been successfully removed from the list data model. 
0288      */
0289     void postItemRemoved();
0290     
0291     /**
0292      * @brief This signal should be emitted by the implementation when changes have been done in the list data model.
0293      * @param index the index position of the item that was modified in the list data model
0294      * @param roles the keys that were modified, the key values can be FMH::MODEL_KEY
0295      */
0296     void updateModel(int index, QVector<int> roles);
0297     
0298     /**
0299      * @brief This signal should be emitted by the implementation before the list data model has been assigned or populated.
0300      */
0301     void preListChanged();
0302     
0303     /**
0304      * @brief This signal should be emitted by the implementation after the list data model is set and done.
0305      */
0306     void postListChanged();
0307     
0308     /**
0309      * @brief This signal should be emitted by the implementation when an item has been moved from one index position to another.
0310      * @param index the original index position of the item in the list data model
0311      * @param to the new index destination of the item
0312      */
0313     void itemMoved(int index, int to);
0314     
0315     /**
0316      * @brief This signal should be emitted by the implementation when the number of elements in the list data model varies. For example when an item is removed or added.
0317      */
0318     void countChanged();
0319 };