1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Designer of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "promotionmodel_p.h"
30#include "widgetdatabase_p.h"
31
32#include <QtDesigner/abstractwidgetdatabase.h>
33#include <QtDesigner/abstractpromotioninterface.h>
34#include <QtDesigner/abstractformeditor.h>
35
36#include <QtGui/qstandarditemmodel.h>
37#include <QtCore/qcoreapplication.h>
38
39QT_BEGIN_NAMESPACE
40
41namespace {
42 using StandardItemList = QList<QStandardItem *>;
43
44 // Model columns.
45 enum { ClassNameColumn, IncludeFileColumn, IncludeTypeColumn, ReferencedColumn, NumColumns };
46
47 // Create a model row.
48 StandardItemList modelRow() {
49 StandardItemList rc;
50 for (int i = 0; i < NumColumns; i++) {
51 rc.push_back(t: new QStandardItem());
52 }
53 return rc;
54 }
55
56 // Create a model row for a base class (read-only, cannot be selected).
57 StandardItemList baseModelRow(const QDesignerWidgetDataBaseItemInterface *dbItem) {
58 StandardItemList rc = modelRow();
59
60 rc[ClassNameColumn]->setText(dbItem->name());
61 for (int i = 0; i < NumColumns; i++) {
62 rc[i]->setFlags(Qt::ItemIsEnabled);
63 }
64 return rc;
65 }
66
67 // Create an editable model row for a promoted class.
68 StandardItemList promotedModelRow(QDesignerWidgetDataBaseItemInterface *baseItem,
69 QDesignerWidgetDataBaseItemInterface *dbItem,
70 bool referenced)
71 {
72 qdesigner_internal::PromotionModel::ModelData data;
73 data.baseItem = baseItem;
74 data.promotedItem = dbItem;
75 data.referenced = referenced;
76
77 const QVariant userData = QVariant::fromValue(value: data);
78
79 StandardItemList rc = modelRow();
80 // name
81 rc[ClassNameColumn]->setText(dbItem->name());
82 rc[ClassNameColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable);
83 rc[ClassNameColumn]->setData(value: userData);
84 // header
85 const qdesigner_internal::IncludeSpecification spec = qdesigner_internal::includeSpecification(includeFile: dbItem->includeFile());
86 rc[IncludeFileColumn]->setText(spec.first);
87 rc[IncludeFileColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable);
88 rc[IncludeFileColumn]->setData(value: userData);
89 // global include
90 rc[IncludeTypeColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable|Qt::ItemIsUserCheckable);
91 rc[IncludeTypeColumn]->setData(value: userData);
92 rc[IncludeTypeColumn]->setCheckState(spec.second == qdesigner_internal::IncludeGlobal ? Qt::Checked : Qt::Unchecked);
93 // referenced
94 rc[ReferencedColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
95 rc[ClassNameColumn]->setData(value: userData);
96 if (!referenced) {
97 //: Usage of promoted widgets
98 static const QString notUsed = QCoreApplication::translate(context: "PromotionModel", key: "Not used");
99 rc[ReferencedColumn]->setText(notUsed);
100 }
101 return rc;
102 }
103}
104
105namespace qdesigner_internal {
106
107 PromotionModel::PromotionModel(QDesignerFormEditorInterface *core) :
108 m_core(core)
109 {
110 connect(sender: this, signal: &QStandardItemModel::itemChanged, receiver: this, slot: &PromotionModel::slotItemChanged);
111 }
112
113 void PromotionModel::initializeHeaders() {
114 setColumnCount(NumColumns);
115 QStringList horizontalLabels(tr(s: "Name"));
116 horizontalLabels += tr(s: "Header file");
117 horizontalLabels += tr(s: "Global include");
118 horizontalLabels += tr(s: "Usage");
119 setHorizontalHeaderLabels (horizontalLabels);
120 }
121
122 void PromotionModel::updateFromWidgetDatabase() {
123 using PromotedClasses = QDesignerPromotionInterface::PromotedClasses;
124
125 clear();
126 initializeHeaders();
127
128 // retrieve list of pairs from DB and convert into a tree structure.
129 // Set the item index as user data on the item.
130 const PromotedClasses promotedClasses = m_core->promotion()->promotedClasses();
131
132 if (promotedClasses.isEmpty())
133 return;
134
135 const QSet<QString> usedPromotedClasses = m_core->promotion()->referencedPromotedClassNames();
136
137 QDesignerWidgetDataBaseItemInterface *baseClass = nullptr;
138 QStandardItem *baseItem = nullptr;
139
140 const PromotedClasses::const_iterator bcend = promotedClasses.constEnd();
141 for (PromotedClasses::const_iterator it = promotedClasses.constBegin(); it != bcend; ++it) {
142 // Start a new base class?
143 if (baseClass != it->baseItem) {
144 baseClass = it->baseItem;
145 const StandardItemList baseRow = baseModelRow(dbItem: it->baseItem);
146 baseItem = baseRow.constFirst();
147 appendRow(items: baseRow);
148 }
149 Q_ASSERT(baseItem);
150 // Append derived
151 baseItem->appendRow(aitems: promotedModelRow(baseItem: it->baseItem, dbItem: it->promotedItem, referenced: usedPromotedClasses.contains(value: it->promotedItem->name())));
152 }
153 }
154
155 void PromotionModel::slotItemChanged(QStandardItem * changedItem) {
156 // Retrieve DB item
157 const ModelData data = modelData(item: changedItem);
158 Q_ASSERT(data.isValid());
159 QDesignerWidgetDataBaseItemInterface *dbItem = data.promotedItem;
160 // Change header or type
161 switch (changedItem->column()) {
162 case ClassNameColumn:
163 emit classNameChanged(dbItem, newName: changedItem->text());
164 break;
165 case IncludeTypeColumn:
166 case IncludeFileColumn: {
167 // Get both file and type items via parent.
168 const QStandardItem *baseClassItem = changedItem->parent();
169 const QStandardItem *fileItem = baseClassItem->child(row: changedItem->row(), column: IncludeFileColumn);
170 const QStandardItem *typeItem = baseClassItem->child(row: changedItem->row(), column: IncludeTypeColumn);
171 emit includeFileChanged(dbItem, includeFile: buildIncludeFile(includeFile: fileItem->text(), includeType: typeItem->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal));
172 }
173 break;
174 }
175 }
176
177 PromotionModel::ModelData PromotionModel::modelData(const QStandardItem *item) const
178 {
179 const QVariant userData = item->data();
180 return userData.canConvert<ModelData>() ? userData.value<ModelData>() : ModelData();
181 }
182
183 PromotionModel::ModelData PromotionModel::modelData(const QModelIndex &index) const
184 {
185 return index.isValid() ? modelData(item: itemFromIndex(index)) : ModelData();
186 }
187
188 QModelIndex PromotionModel::indexOfClass(const QString &className) const {
189 const StandardItemList matches = findItems (text: className, flags: Qt::MatchFixedString|Qt::MatchCaseSensitive|Qt::MatchRecursive);
190 return matches.isEmpty() ? QModelIndex() : indexFromItem (item: matches.constFirst());
191 }
192} // namespace qdesigner_internal
193
194QT_END_NAMESPACE
195

source code of qttools/src/designer/src/lib/shared/promotionmodel.cpp