1 /* === This file is part of Calamares - <https://calamares.io> ===
2  *
3  *   SPDX-FileCopyrightText: 2017 Kyle Robbertze <kyle@aims.ac.za>
4  *   SPDX-FileCopyrightText: 2017 2020, Adriaan de Groot <groot@kde.org>
5  *   SPDX-License-Identifier: GPL-3.0-or-later
6  *
7  *   Calamares is Free Software: see the License-Identifier above.
8  *
9  */
10 
11 #ifndef PACKAGETREEITEM_H
12 #define PACKAGETREEITEM_H
13 
14 #include <QList>
15 #include <QStandardItem>
16 #include <QVariant>
17 
18 class PackageTreeItem : public QStandardItem
19 {
20 public:
21     using List = QList< PackageTreeItem* >;
22 
23     ///@brief A tag class to distinguish package-from-map from group-from-map
24     struct PackageTag
25     {
26         PackageTreeItem* parent;
27     };
28     ///@brief A tag class to distinguish group-from-map from package-from-map
29     struct GroupTag
30     {
31         PackageTreeItem* parent;
32     };
33 
34     ///@brief A package (individual package)
35     explicit PackageTreeItem( const QString& packageName, PackageTreeItem* parent = nullptr );
36     ///@brief A package (individual package with description)
37     explicit PackageTreeItem( const QVariantMap& packageData, PackageTag&& parent );
38     ///@brief A group (sub-items and sub-groups are ignored)
39     explicit PackageTreeItem( const QVariantMap& groupData, GroupTag&& parent );
40     ///@brief A root item, always selected, named "<root>"
41     explicit PackageTreeItem();
42     ~PackageTreeItem() override;
43 
44     void appendChild( PackageTreeItem* child );
45     PackageTreeItem* child( int row );
46     int childCount() const;
47     QVariant data( int column ) const override;
48     int row() const;
49 
50     PackageTreeItem* parentItem();
51     const PackageTreeItem* parentItem() const;
52 
name()53     QString name() const { return m_name; }
packageName()54     QString packageName() const { return m_packageName; }
55 
description()56     QString description() const { return m_description; }
preScript()57     QString preScript() const { return m_preScript; }
postScript()58     QString postScript() const { return m_postScript; }
59 
60     /** @brief Is this item a group-item?
61      *
62      * Groups have a (possibly empty) list of packages, and a
63      * (possibly empty) list of sub-groups, and can be marked
64      * critical, hidden, etc. Packages, on the other hand, only
65      * have a meaningful packageName() and selection status.
66      *
67      * Root is a group.
68      */
isGroup()69     bool isGroup() const { return m_isGroup; }
70 
71     /// @brief Is this item a single package?
isPackage()72     bool isPackage() const { return !isGroup(); }
73 
74     /** @brief Is this item hidden?
75      *
76      * Hidden items (generally only groups) are maintained separately,
77      * not shown to the user, but do enter into the package-installation process.
78      */
isHidden()79     bool isHidden() const { return m_isHidden; }
80 
81     /** @brief Is this hidden item, considered "selected"?
82      *
83      * This asserts when called on a non-hidden item.
84      * A hidden item has its own selected state, but really
85      * falls under the selectedness of the parent item.
86      */
87     bool hiddenSelected() const;
88 
89     /** @brief Is this group critical?
90      *
91      * A critical group must be successfully installed, for the Calamares
92      * installation to continue.
93      */
isCritical()94     bool isCritical() const { return m_isCritical; }
95 
96     /** @brief Is this group expanded on start?
97      *
98      * This does not affect installation, only the UI. A group
99      * that expands on start is shown expanded (not collapsed)
100      * in the treeview when the page is loaded.
101      */
expandOnStart()102     bool expandOnStart() const { return m_startExpanded; }
103 
104     /** @brief Is this an immutable item?
105      *
106      * Groups can be immutable: then you can't toggle the selected
107      * state of any of its items.
108      */
isImmutable()109     bool isImmutable() const { return m_showReadOnly; }
110 
111     /** @brief is this item selected?
112      *
113      * Groups may be partially selected; packages are only on or off.
114      */
isSelected()115     Qt::CheckState isSelected() const { return m_selected; }
116 
117     /** @brief Turns this item into a variant for PackageOperations use
118      *
119      * For "plain" items, this is just the package name; items with
120      * scripts return a map. See the package module for how it's interpreted.
121      */
122     QVariant toOperation() const;
123 
124     void setSelected( Qt::CheckState isSelected );
125     void setChildrenSelected( Qt::CheckState isSelected );
126 
127     /** @brief Update selectedness based on the children's states
128      *
129      * This only makes sense for groups, which might have packages
130      * or subgroups; it checks only direct children.
131      */
132     void updateSelected();
133 
134     // QStandardItem methods
135     int type() const override;
136 
137     /** @brief Are two items equal
138      *
139      * This **disregards** parent-item and the child-items, and compares
140      * only the fields for the items-proper (name, .. expanded). Note
141      * also that *isSelected()* is a run-time state, and is **not**
142      * compared either.
143      */
144     bool operator==( const PackageTreeItem& rhs ) const;
145     bool operator!=( const PackageTreeItem& rhs ) const { return !( *this == rhs ); }
146 
147 private:
148     PackageTreeItem* m_parentItem;
149     List m_childItems;
150 
151     // An entry can be a package, or a group.
152     QString m_name;
153     QString m_packageName;
154     Qt::CheckState m_selected = Qt::Unchecked;
155 
156     // These are only useful for groups
157     QString m_description;
158     QString m_preScript;
159     QString m_postScript;
160     bool m_isGroup = false;
161     bool m_isCritical = false;
162     bool m_isHidden = false;
163     bool m_showReadOnly = false;
164     bool m_startExpanded = false;
165 };
166 
167 #endif  // PACKAGETREEITEM_H
168