1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the tools applications of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "featuretreemodel.h"
46 #include <QApplication>
54 Node(Feature
*f
, Node
*p
= 0) : feature(f
), parent(p
) {}
56 Node
* find(const Feature
*child
) const;
57 bool contains(const Feature
*child
) const { return find(child
) != 0; }
62 QList
<Node
*> children
; // maybe convert to Map to get keys sorted
67 while (!children
.isEmpty())
68 delete children
.takeFirst();
71 Node
* Node::find(const Feature
*f
) const
73 if (this->feature
== f
)
74 return const_cast<Node
*>(this);
76 foreach (Node
*n
, children
)
77 if (Node
*m
= n
->find(f
))
83 static bool nodePtrLessThan(const Node
*n1
, const Node
*n2
)
85 return (n1
->feature
->key() < n2
->feature
->key());
89 Try insert \a n into the tree with this node as root.
90 n is inserted as a child if it has a dependency to this node.
91 Returns true if child is inserted into the tree, false otherwise.
93 bool Node::insert(Node
*n
)
95 Feature
*f
= const_cast<Feature
*>(n
->feature
);
96 if (feature
->supports().contains(f
)) {
98 qSort(children
.begin(), children
.end(), nodePtrLessThan
);
102 foreach (Node
*child
, children
)
103 if (child
->insert(n
))
108 static bool isSection(const QModelIndex
&index
)
110 return index
.isValid() && (index
.internalId() == 0);
113 FeatureTreeModel::FeatureTreeModel(QObject
*parent
)
114 : QAbstractItemModel(parent
)
118 FeatureTreeModel::~FeatureTreeModel()
120 foreach (QString section
, sections
.keys())
121 while (!sections
[section
].isEmpty())
122 delete sections
[section
].takeFirst();
126 Returns true if the model already contains \a in \a section, false otherwise.
128 bool FeatureTreeModel::contains(const QString
§ion
, const Feature
*f
) const
130 return (find(section
, f
) != 0);
133 Node
* FeatureTreeModel::find(const QString
§ion
, const Feature
*f
) const
135 QList
<Node
*> roots
= sections
[section
];
136 foreach (Node
*root
, roots
)
137 if (Node
*n
= root
->find(f
))
143 Add new \a feature to the tree.
144 When all feature is added, buildTree() must be called to build the
147 void FeatureTreeModel::addFeature(Feature
*feature
)
149 const QString section
= feature
->section();
150 Q_ASSERT(!contains(section
, feature
));
152 connect(feature
, SIGNAL(changed()), this, SLOT(featureChanged()));
154 Node
*node
= new Node(feature
, 0);
156 // try insert any toplevel nodes as child of this one
157 foreach (Node
*n
, sections
[section
])
159 sections
[section
].removeAll(n
);
161 // try insert this node as a child of any existing node
162 foreach (Node
*n
, sections
[section
])
163 if (n
->insert(node
)) {
164 emit
layoutChanged();
168 // not a child, insert as a toplevel node
169 sections
[section
].append(node
);
170 qSort(sections
[section
].begin(), sections
[section
].end(), nodePtrLessThan
);
171 emit
layoutChanged();
174 QModelIndex
FeatureTreeModel::createIndex(int row
, int column
,
175 const QModelIndex
&parent
,
176 const Node
*node
) const
178 QModelIndex index
= QAbstractItemModel::createIndex(row
, column
,
180 if (parent
.isValid())
181 parentMap
[index
] = parent
;
183 featureIndexMap
[node
->feature
] = index
;
187 QModelIndex
FeatureTreeModel::index(int row
, int column
,
188 const QModelIndex
&parent
) const
190 if (!parent
.isValid()) { // index is a section
191 if (row
< sections
.size() && column
== 0)
192 return QAbstractItemModel::createIndex(row
, column
, 0);
193 return QModelIndex();
196 if (isSection(parent
)) { // index is a toplevel feature
197 const int parentRow
= parent
.row();
198 if (parentRow
< sections
.size()) {
199 QString section
= sections
.keys().at(parentRow
);
200 QList
<Node
*> nodes
= sections
[section
];
201 if (row
< nodes
.size() && column
< 2)
202 return createIndex(row
, column
, parent
, nodes
.at(row
));
204 return QModelIndex();
207 // parent is a feature
208 Node
*parentNode
= static_cast<Node
*>(parent
.internalPointer());
209 QList
<Node
*> children
= parentNode
->children
;
210 if (row
< children
.size() && column
< 2)
211 return createIndex(row
, column
, parent
, children
.at(row
));
213 return QModelIndex();
216 QModelIndex
FeatureTreeModel::index(const QModelIndex
&parent
,
217 const Feature
*feature
) const
219 const int rows
= rowCount(parent
);
220 for (int i
= 0; i
< rows
; ++i
) {
221 QModelIndex child
= index(i
, 0, parent
);
222 Node
*node
= static_cast<Node
*>(child
.internalPointer());
223 if (node
&& node
->feature
== feature
)
225 QModelIndex childSearch
= index(child
, feature
);
226 if (childSearch
.isValid())
229 return QModelIndex();
232 QModelIndex
FeatureTreeModel::index(const Feature
*feature
) const
234 if (featureIndexMap
.contains(feature
))
235 return featureIndexMap
.value(feature
);
238 int sectionRow
= sections
.keys().indexOf(feature
->section());
239 QModelIndex sectionIndex
= index(sectionRow
, 0, QModelIndex());
241 return index(sectionIndex
, feature
);
244 QModelIndex
FeatureTreeModel::parent(const QModelIndex
&index
) const
246 if (!index
.isValid())
247 return QModelIndex();
249 if (parentMap
.contains(index
))
250 return parentMap
.value(index
);
251 return QModelIndex();
254 int FeatureTreeModel::rowCount(const QModelIndex
&parent
) const
256 if (!parent
.isValid())
257 return sections
.size();
259 if (isSection(parent
)) {
260 const QString section
= sections
.keys().at(parent
.row());
261 return sections
[section
].size();
264 const Node
*node
= static_cast<Node
*>(parent
.internalPointer());
265 return node
->children
.size();
268 int FeatureTreeModel::columnCount(const QModelIndex
&parent
) const
271 if (!parent
.isValid())
274 if (isSection(parent
))
278 return 2; // Feature: [key, name]
281 QVariant
FeatureTreeModel::data(const QModelIndex
&index
, int role
) const
283 if (!index
.isValid())
286 const Node
*node
= static_cast<Node
*>(index
.internalPointer());
289 case Qt::DisplayRole
: {
290 if (node
== 0) // index is a section
291 return sections
.keys().at(index
.row());
292 if (index
.column() == 0)
293 return node
->feature
->key();
294 Q_ASSERT(index
.column() == 1);
295 return node
->feature
->title();
297 case Qt::CheckStateRole
: {
298 if (node
&& index
.column() == 0)
299 return (node
->feature
->enabled() ?
300 Qt::Checked
: Qt::Unchecked
);
303 case Qt::TextColorRole
: {
304 if (node
&& index
.column() == 0) // feature key
305 if (node
->feature
->selectable())
306 return QApplication::palette().color(QPalette::Link
);
309 case Qt::TextAlignmentRole
:
310 case Qt::BackgroundColorRole
:
312 case Qt::ToolTipRole
: // TODO
313 case Qt::StatusTipRole
: // TODO
314 case Qt::WhatsThisRole
: // TODO
315 case Qt::DecorationRole
:
323 bool FeatureTreeModel::setData(const QModelIndex
&index
,
324 const QVariant
&value
, int role
)
326 if (!index
.isValid())
329 Node
*node
= static_cast<Node
*>(index
.internalPointer());
333 if (role
== Qt::CheckStateRole
) {
334 Qt::CheckState state
= static_cast<Qt::CheckState
>(value
.toInt());
335 if (state
== Qt::Checked
)
336 node
->feature
->setEnabled(true);
337 else if (state
== Qt::Unchecked
)
338 node
->feature
->setEnabled(false);
339 emit
dataChanged(index
, index
);
345 Qt::ItemFlags
FeatureTreeModel::flags(const QModelIndex
&index
) const
347 if (!index
.isValid() || index
.internalPointer() == 0)
348 return Qt::ItemIsEnabled
| Qt::ItemIsSelectable
;
350 const Node
*node
= static_cast<Node
*>(index
.internalPointer());
351 const Feature
*feature
= node
->feature
;
352 Qt::ItemFlags flags
= Qt::ItemIsUserCheckable
| Qt::ItemIsSelectable
;
354 if (feature
->selectable())
355 flags
|= Qt::ItemIsEnabled
;
360 QVariant
FeatureTreeModel::headerData(int section
, Qt::Orientation orientation
,
363 if (orientation
== Qt::Horizontal
&& role
== Qt::DisplayRole
) {
365 return QString("Id");
366 else if (section
== 1)
367 return QString("Name");
373 Feature
* FeatureTreeModel::getFeature(const QModelIndex
&index
) const
375 if (!index
.isValid())
377 if (isSection(index
))
379 Node
*node
= static_cast<Node
*>(index
.internalPointer());
380 return const_cast<Feature
*>(node
->feature
);
383 void FeatureTreeModel::featureChanged()
385 Feature
*feature
= qobject_cast
<Feature
*>(sender());
387 QModelIndex featureIndex
= index(feature
);
388 emit
dataChanged(featureIndex
, featureIndex
);
390 emit
layoutChanged();
394 void FeatureTreeModel::readConfig(QTextStream
&stream
)
396 static QRegExp
regexp("\\s*#\\s*define\\s+QT_NO_(\\S+)\\s*");
398 while (!stream
.atEnd()) {
399 QString line
= stream
.readLine();
400 if (regexp
.exactMatch(line
)) {
401 Feature
*f
= Feature::getInstance(regexp
.cap(1));
402 f
->setEnabled(false);
407 Search for all disabled child features of \a parent.
408 Returns a list of feature keys for the disabled items.
410 QStringList
FeatureTreeModel::findDisabled(const QModelIndex
&parent
) const
412 QStringList stringList
;
414 const int rows
= rowCount(parent
);
415 for (int i
= 0; i
< rows
; ++i
) {
416 QModelIndex child
= index(i
, 0, parent
);
417 Node
*node
= static_cast<Node
*>(child
.internalPointer());
418 if (node
&& node
->feature
&& !node
->feature
->enabled())
419 stringList
<< node
->feature
->key();
420 stringList
<< findDisabled(child
);
425 void FeatureTreeModel::writeConfig(QTextStream
&stream
) const
427 const int sectionCount
= rowCount(QModelIndex());
429 for (int i
= 0; i
< sectionCount
; ++i
) {
430 QModelIndex section
= index(i
, 0, QModelIndex());
431 QStringList disabled
= findDisabled(section
);
432 if (disabled
.size() > 0) {
433 stream
<< '\n' << "/* " << sections
.keys().at(i
) << " */" << '\n';
434 foreach (QString feature
, disabled
)
435 stream
<< "#ifndef QT_NO_" << feature
<< '\n'
436 << "# define QT_NO_" << feature
<< '\n'
442 void FeatureTreeModel::clear()
447 featureIndexMap
.clear();
448 emit
layoutChanged();