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 };