Fix breakage introduced in 21e0423a5c9ecd9da8e141dcfba25e60b55f7fe5
[qt-netbsd.git] / tools / qconfig / featuretreemodel.cpp
blobff4f9d9ab56f87091aabdd52f2e7b86d29bc64c9
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the tools applications of the Qt Toolkit.
8 **
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
14 ** this package.
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.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
42 #include "featuretreemodel.h"
43 #include "feature.h"
44 #include <QPalette>
45 #include <QColor>
46 #include <QApplication>
47 #include <QtDebug>
49 QT_BEGIN_NAMESPACE
51 class Node
53 public:
54 Node(Feature *f, Node *p = 0) : feature(f), parent(p) {}
55 ~Node();
56 Node* find(const Feature *child) const;
57 bool contains(const Feature *child) const { return find(child) != 0; }
58 bool insert(Node *n);
60 Feature *feature;
61 Node *parent;
62 QList<Node*> children; // maybe convert to Map to get keys sorted
65 Node::~Node()
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))
78 return m;
80 return 0;
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)) {
97 children.append(n);
98 qSort(children.begin(), children.end(), nodePtrLessThan);
99 n->parent = this;
100 return true;
102 foreach (Node *child, children)
103 if (child->insert(n))
104 return true;
105 return false;
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 &section, const Feature *f) const
130 return (find(section, f) != 0);
133 Node* FeatureTreeModel::find(const QString &section, const Feature *f) const
135 QList<Node*> roots = sections[section];
136 foreach (Node *root, roots)
137 if (Node *n = root->find(f))
138 return n;
139 return 0;
143 Add new \a feature to the tree.
144 When all feature is added, buildTree() must be called to build the
145 dependency tree.
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])
158 if (node->insert(n))
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();
165 return;
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,
179 (void*)node);
180 if (parent.isValid())
181 parentMap[index] = parent;
182 if (node)
183 featureIndexMap[node->feature] = index;
184 return 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)
224 return child;
225 QModelIndex childSearch = index(child, feature);
226 if (childSearch.isValid())
227 return childSearch;
229 return QModelIndex();
232 QModelIndex FeatureTreeModel::index(const Feature *feature) const
234 if (featureIndexMap.contains(feature))
235 return featureIndexMap.value(feature);
237 // exhaustive search
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
270 #if 0
271 if (!parent.isValid())
272 return 0;
274 if (isSection(parent))
275 return 1;
276 #endif
277 Q_UNUSED(parent);
278 return 2; // Feature: [key, name]
281 QVariant FeatureTreeModel::data(const QModelIndex &index, int role) const
283 if (!index.isValid())
284 return QVariant();
286 const Node *node = static_cast<Node*>(index.internalPointer());
288 switch (role) {
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);
301 break;
303 case Qt::TextColorRole: {
304 if (node && index.column() == 0) // feature key
305 if (node->feature->selectable())
306 return QApplication::palette().color(QPalette::Link);
307 break;
309 case Qt::TextAlignmentRole:
310 case Qt::BackgroundColorRole:
311 case Qt::FontRole:
312 case Qt::ToolTipRole: // TODO
313 case Qt::StatusTipRole: // TODO
314 case Qt::WhatsThisRole: // TODO
315 case Qt::DecorationRole:
316 case Qt::EditRole:
317 default:
318 break;
320 return QVariant();
323 bool FeatureTreeModel::setData(const QModelIndex &index,
324 const QVariant &value, int role)
326 if (!index.isValid())
327 return false;
329 Node *node = static_cast<Node*>(index.internalPointer());
330 if (!node)
331 return false;
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);
340 return true;
342 return false;
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;
357 return flags;
360 QVariant FeatureTreeModel::headerData(int section, Qt::Orientation orientation,
361 int role) const
363 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
364 if (section == 0)
365 return QString("Id");
366 else if (section == 1)
367 return QString("Name");
370 return QVariant();
373 Feature* FeatureTreeModel::getFeature(const QModelIndex &index) const
375 if (!index.isValid())
376 return 0;
377 if (isSection(index))
378 return 0;
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());
386 if (feature) {
387 QModelIndex featureIndex = index(feature);
388 emit dataChanged(featureIndex, featureIndex);
389 } else {
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);
422 return stringList;
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'
437 << "#endif" << '\n';
442 void FeatureTreeModel::clear()
444 Feature::clear();
445 sections.clear();
446 parentMap.clear();
447 featureIndexMap.clear();
448 emit layoutChanged();
451 QT_END_NAMESPACE