Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #ifndef TREEVIEWMODEL_H
10 : #define TREEVIEWMODEL_H
11 :
12 : #include <QAbstractListModel>
13 : #include <QDebug>
14 : #include <QList>
15 : #include <QtQml>
16 : #include <backend.hpp>
17 : #include <kdb.hpp>
18 : #include <keyio.hpp>
19 :
20 : #include <merging/automergeconfiguration.hpp>
21 : #include <merging/mergingkdb.hpp>
22 :
23 : #include "confignode.hpp"
24 : #include "findvisitor.hpp"
25 : #include "keysetvisitor.hpp"
26 : #include "printvisitor.hpp"
27 :
28 : class Visitor;
29 :
30 : /**
31 : * @brief The TreeViewModel class. It holds ConfigNodes.
32 : */
33 :
34 0 : class TreeViewModel : public QAbstractListModel
35 : {
36 :
37 0 : Q_OBJECT
38 :
39 : public:
40 : /**
41 : * @brief The TreeViewModelRoles enum
42 : */
43 : enum TreeViewModelRoles
44 : {
45 : NameRole = Qt::UserRole + 1, ///< The role QML can access the name of a ConfigNode at a specified index.
46 : PathRole, ///< The role QML can access the path of a ConfigNode at a specified index.
47 : ValueRole, ///< The role QML can access the value of a ConfigNode at a specified index.
48 : ChildCountRole, ///< The role QML can access the number of children of a ConfigNode at a specified index.
49 : ChildrenRole, ///< The role QML can access the children model of a ConfigNode at a specified index.
50 : ChildrenHaveNoChildrenRole, ///< The role QML can access if children of a ConfigNode at a specified index do have children
51 : /// on their own.
52 : MetaValueRole, ///< The role QML can access the meta model of a ConfigNode at a specified index.
53 : NodeRole, ///< The role QML can retrieve the ConfigNode at a specified index.
54 : ParentModelRole, ///< The role QML can retrieve a pointer to the ParentModel of a ConfigNode.
55 : IndexRole, ///< The role QML can retrieve the index of a ConfigNode.
56 : IsNullRole, ///< The role QML can retrieve if the key of this node is null.
57 : IsExpandedRole ///< The role QML can retrieve if a ConfigNode is expanded.
58 : };
59 :
60 : /**
61 : * @brief The default constructor.
62 : * @param parentModel An optional parent.
63 : */
64 : explicit TreeViewModel (QObject * parentModel = nullptr);
65 :
66 : /**
67 : * @brief Constructor for root node.
68 : * @param parentModel An optional parent.
69 : */
70 : explicit TreeViewModel (kdb::tools::merging::MergingKDB * kdb, QObject * parentModel = nullptr);
71 :
72 : /**
73 : * @brief The mandatory copy constructor.
74 : * @param The TreeViewModel that is copied.
75 : */
76 : TreeViewModel (TreeViewModel const & other);
77 :
78 : /**
79 : * @brief Returns the QList that holds the ConfigNodes.
80 : * @return The QList that holds the ConfigNodes.
81 : */
82 : QList<ConfigNodePtr> & model ()
83 : {
84 0 : return m_model;
85 : }
86 :
87 : // mandatory methods inherited from QAbstractItemModel
88 :
89 : /**
90 : * @copydoc QAbstractListModel::rowCount()
91 : */
92 : Q_INVOKABLE int rowCount (const QModelIndex & parentIndex = QModelIndex ()) const override;
93 :
94 : /**
95 : * @copydoc QAbstractListModel::data()
96 : */
97 : QVariant data (const QModelIndex & idx, int role = Qt::DisplayRole) const override;
98 :
99 : /**
100 : * @copydoc QAbstractListModel::setData()
101 : */
102 : bool setData (const QModelIndex & idx, const QVariant & modelData, int role = Qt::EditRole) override;
103 :
104 : /**
105 : * \copydoc QAbstractListModel::insertRow()
106 : */
107 : Q_INVOKABLE bool insertRow (int row, const QModelIndex & parentIndex = QModelIndex ());
108 :
109 : /**
110 : * @copydoc QAbstractListModel::removeRow()
111 : */
112 : Q_INVOKABLE bool removeRow (int row, const QModelIndex & parentIndex = QModelIndex ());
113 :
114 : /**
115 : * @copydoc QAbstractListModel::flags()
116 : */
117 : Qt::ItemFlags flags (const QModelIndex & idx) const override;
118 :
119 : /**
120 : * @brief Populates this TreeViewModel with a keyset. The root keys (system, user and spec) will be recreated.
121 : */
122 : Q_INVOKABLE void populateModel ();
123 :
124 : /**
125 : * @brief Populates this TreeViewModel with a keyset. The root keys (system, user and spec) will be recreated.
126 : * @param keySet The KeySet that holds the Key objects.
127 : */
128 : void populateModel (kdb::KeySet const & keySet);
129 :
130 : /**
131 : * @brief Populates this TreeViewModel with a keyset. The root keys (system, user and spec) will not be recreated.
132 : * @param keySet The KeySet that holds the Key objects.
133 : */
134 : void createNewNodes (kdb::KeySet keySet);
135 :
136 : /**
137 : * @brief The recursive method that actually populates this TreeViewModel.
138 : *
139 : * @param node The ConfigNode that is supposed to find its place in the hierarchy.
140 : * @param keys The path of the ConfigNode that is supposed to find its place in the hierarchy, splitted up into a QStringList.
141 : * @param key The Key that the ConfigNode holds. If it is no leaf node, the Key is NULL.
142 : */
143 : void sink (ConfigNodePtr node, QStringList keys, const kdb::Key & key);
144 :
145 : /**
146 : * @brief The method thats accepts a Visitor object to support the Vistor Pattern.
147 : * @param visitor The visitor that visits this TreeViewModel.
148 : */
149 : void accept (Visitor & visitor);
150 :
151 : /**
152 : * @brief Get the roles of a ConfigNode at the specifies index. Needed to access roles from outside a delegate in QML.
153 : *
154 : * @param idx The index of the ConfigNode.
155 : *
156 : * @return A map of the roles of the ConfigNode at the specified index.
157 : */
158 : Q_INVOKABLE QVariantMap get (const int & idx) const;
159 :
160 : /**
161 : * @brief Find a search term in the model.
162 : *
163 : * @param term The search term of interest.
164 : *
165 : * @return A model which includes all ConfigNodes that have the search term in their name, value or metakeys.
166 : */
167 : Q_INVOKABLE QVariant find (const QString & term);
168 :
169 : /**
170 : * @brief Inserts a new ConfigNode at a specified index into this TreeViewModel. This method is used if this TreeViewModel is
171 : * holding metakeys.
172 : * @param row The index the new ConfigNode is supposed to be inserted at.
173 : * @param key The key that holds the metadata.
174 : * @param name The name of the parent ConfigNode that holds the metadata.
175 : */
176 : void insertMetaRow (int row, kdb::Key key, const QString & name);
177 :
178 : /**
179 : * @brief Inserts a new ConfigNode at a specified index into this TreeViewModel. This method is used if this TreeViewModel is
180 : * holding non metakey ConfigNodes.
181 : * @param row The index the new ConfigNode is supposed to be inserted at.
182 : * @param node The ConfigNode that is supposed to be inserted.
183 : * @param addParent Determines if the parentModel of the ConfigNode should be set with this TreeViewModel.
184 : */
185 : void insertRow (int row, ConfigNodePtr node, bool addParent = true);
186 :
187 : /**
188 : * @brief Collects all current ConfigNodes, adds them to a KeySet, threewaymerges the KeySet with the permanent database
189 : * and populates this TreeViewModel with the result.
190 : */
191 : Q_INVOKABLE void synchronize ();
192 :
193 : /**
194 : * @brief Creates a new ConfigNode and puts it into its place in the hierarchy.
195 : *
196 : * @param path The path (full keyname) of the ConfigNode.
197 : * @param value The value of the ConfigNode.
198 : * @param metaData The metada of the ConfigNode.
199 : */
200 : Q_INVOKABLE kdb::Key createNewKey (const QString & path, const QString & value, const QVariantMap metaData);
201 :
202 : /**
203 : * @brief Appends a ConfigNode to this TreeViewModel. At the time of insertion the index of the ConfigNode will be the largest in
204 : * this model.
205 : *
206 : * @param node The ConfigNode that is appended to this TreeViewModel.
207 : */
208 : void append (ConfigNodePtr node);
209 :
210 : /**
211 : * @brief Returns the index of a ConfigNode in this TreeViewModel based in the ConfigNode's name.
212 : *
213 : * @param name The name of the ConfigNode.
214 : *
215 : * @return The index of the ConfigNode, -1 if a ConfigNode with this name is not present in this TreeViewModel.
216 : */
217 : Q_INVOKABLE int getIndexByName (const QString & name) const;
218 :
219 : /**
220 : * @brief Export the configuration below a ConfigNode to a file on the harddisk.
221 : * @param parentModel The TreeViewModel that holds the ConfigNode.
222 : * @param idx The index of the ConfigNode in the TreeViewModel.
223 : * @param format Specifies the file format of the exported file.
224 : * @param file The path on the harddisk where the exported file is written to.
225 : */
226 : Q_INVOKABLE void exportConfiguration (TreeViewModel * parentModel, int idx, QString format, QString file);
227 :
228 : /**
229 : * @brief Import a configuration from a file on the harddrive into the current configuration.
230 : *
231 : * @param name The name of the ConfigNode the configuration is imported to.
232 : * @param file The path of the file on the harddisk.
233 : * @param format The format of the file on the harddisk.
234 : * @param mergeStrategies The mergeStrategies in case of conflict.
235 : */
236 : Q_INVOKABLE void importConfiguration (const QString & name, const QString & file, QString & format,
237 : const QVariantList & mergeStrategies);
238 :
239 : /**
240 : * @brief Stores the current state of the configuration in the KeySet.
241 : */
242 : kdb::KeySet collectCurrentKeySet ();
243 :
244 : /**
245 : * @brief Clears this model if it holds metakeys.
246 : */
247 : void clearMetaModel ();
248 :
249 : /**
250 : * @brief Unmounts a backend.
251 : *
252 : * @param backendName The name of the backend that is unmounted.
253 : */
254 : Q_INVOKABLE void unMountBackend (QString backendName);
255 :
256 : /**
257 : * @brief Needed to update the QML view.
258 : */
259 : Q_INVOKABLE void refresh ();
260 :
261 : /**
262 : * @brief Returns the correct name for a new Array Entry.
263 : *
264 : * @return The correct name for a new Array Entry.
265 : */
266 : Q_INVOKABLE QString getCurrentArrayNo () const;
267 :
268 : /**
269 : * @brief Renames all Array Entries in this model to prevent holes.
270 : */
271 : void refreshArrayNumbers ();
272 :
273 : /**
274 : * @brief Returns a list of the currently mounted backends.
275 : *
276 : * @return A list of the current mounted backends.
277 : */
278 : Q_INVOKABLE QStringList mountedBackends ();
279 :
280 : /**
281 : * @brief getSplittedKeyname Splits a keyname into pieces. Delimiter is an unescaped slash ("/").
282 : * @param key The key with the keyname of interest.
283 : * @return A QStringList that holds the splitted keyname.
284 : */
285 : QStringList getSplittedKeyname (const kdb::Key & key);
286 :
287 : /**
288 : * @brief discardModel Allow the QML side to destroy this model, even if this model is owned by C++.
289 : */
290 : Q_INVOKABLE void discardModel ();
291 :
292 : private:
293 : QList<ConfigNodePtr> m_model;
294 : kdb::Key m_root;
295 : kdb::Key m_metaModelParent;
296 : kdb::tools::merging::MergingKDB * m_kdb;
297 : /**
298 : * @brief Returns a MergeConflictStrategy object based on the name of the MergeConflictStrategy.
299 : * @param mergeStrategy The name of the MergeConflictStrategy.
300 : * @return The MergeConflictStrategy object based on the name of the MergeConflictStrategy.
301 : */
302 : kdb::tools::merging::MergeConflictStrategy * getMergeStrategy (const QString & mergeStrategy);
303 :
304 : /**
305 : * @brief Connect to system D-Bus
306 : */
307 : void connectDBus ();
308 :
309 : /**
310 : * @brief Extract the contents of an KDBException::what() function for usage in a TreeViewModel::showMessage() function.
311 : * @param e The KDBException.
312 : * @return A QMap with the contents of the KDBException.
313 : */
314 : QMap<QString, QString> getErrorMessage (kdb::KDBException const & e);
315 :
316 : protected:
317 : QHash<int, QByteArray> roleNames () const override;
318 :
319 : signals: // Use "Error", "Warning" and "Information" as title to display the according icon
320 : /**
321 : * @brief Triggers a messagedialog in the GUI.
322 : * @param title The title of the messagedialog in the GUI.
323 : * @param text The text of the messagedialog in the GUI.This is the text that will be initially shown to the user.
324 : * @param detailedText The detailed text of the messagedialog in the GUI.The user will have to click on a button to access this
325 : * text.
326 : */
327 : void showMessage (QString title, QString text, QString detailedText) const;
328 : /**
329 : * @brief Triggers the expanded property of a ConfigNode.
330 : */
331 : void expandNode (bool);
332 : /**
333 : * @brief Triggers the update of the treeview in the GUI.
334 : */
335 : void updateIndicator () const;
336 :
337 : public slots:
338 :
339 : /**
340 : * @brief Displays a pop up window to the user
341 : * @param title The title of the pop up window
342 : * @param text The message of the pop up window
343 : * @param detailedText A more detailed message to display
344 : */
345 : void showConfigNodeMessage (QString title, QString text, QString detailedText);
346 :
347 : /**
348 : * @brief Writes a change of the system config to std::out if in debug mode
349 : *
350 : * @param msg
351 : */
352 : void configChanged (QString msg);
353 : };
354 :
355 0 : Q_DECLARE_METATYPE (TreeViewModel)
356 :
357 : #endif // TREEVIEWMODEL_H
|