aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/app/app.pro4
-rw-r--r--src/app/config-ui/config-ui.pro11
-rw-r--r--src/app/config-ui/main.cpp60
-rw-r--r--src/app/config-ui/mainwindow.cpp97
-rw-r--r--src/app/config-ui/mainwindow.h59
-rw-r--r--src/app/config-ui/mainwindow.ui37
-rw-r--r--src/app/config-ui/settingsmodel.cpp165
-rw-r--r--src/app/config-ui/settingsmodel.h51
-rw-r--r--src/app/qbs/qbstool.cpp5
-rw-r--r--src/app/qbs/qbstool.h2
-rw-r--r--src/lib/tools/settings.cpp11
-rw-r--r--src/lib/tools/settings.h1
12 files changed, 496 insertions, 7 deletions
diff --git a/src/app/app.pro b/src/app/app.pro
index 839898686..4725a9a3b 100644
--- a/src/app/app.pro
+++ b/src/app/app.pro
@@ -5,4 +5,6 @@ SUBDIRS =\
setupmaddeplatforms \
qbs-setup-qt \
config \
- qbs-qmltypes \
+ qbs-qmltypes
+
+lessThan(QT_MAJOR_VERSION, 5)|!isEmpty(QT.widgets.name):SUBDIRS += config-ui
diff --git a/src/app/config-ui/config-ui.pro b/src/app/config-ui/config-ui.pro
new file mode 100644
index 000000000..1a587587e
--- /dev/null
+++ b/src/app/config-ui/config-ui.pro
@@ -0,0 +1,11 @@
+QT = core gui
+greaterThan(QT_MAJOR_VERSION, 4):QT += widgets
+
+TARGET = qbs-config-ui
+DESTDIR = ../../../bin
+
+HEADERS = settingsmodel.h mainwindow.h
+SOURCES = settingsmodel.cpp mainwindow.cpp main.cpp
+FORMS = mainwindow.ui
+
+include(../../lib/use.pri)
diff --git a/src/app/config-ui/main.cpp b/src/app/config-ui/main.cpp
new file mode 100644
index 000000000..43f6b300e
--- /dev/null
+++ b/src/app/config-ui/main.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "mainwindow.h"
+
+#include "../shared/qbssettings.h"
+
+#include <logging/consolelogger.h>
+#include <logging/translator.h>
+
+#include <QApplication>
+#include <cstdlib>
+
+using namespace qbs;
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ SettingsPtr settings = qbsSettings();
+ ConsoleLogger cl(settings.data());
+
+ const QStringList args = app.arguments().mid(1);
+ if (args.count() == 1 &&
+ (args.first() == QLatin1String("--help") || args.first() == QLatin1String("-h"))) {
+ qbsInfo() << DontPrintLogLevel << LogOutputStdOut
+ << Tr::tr("This tool displays qbs settings in a GUI.\n"
+ "If you have more than a few settings, this might be preferable to "
+ "plain \"qbs config\", as it presents a hierarchical view.");
+ return EXIT_SUCCESS;
+ }
+
+ MainWindow mw;
+ mw.show();
+ return app.exec();
+}
diff --git a/src/app/config-ui/mainwindow.cpp b/src/app/config-ui/mainwindow.cpp
new file mode 100644
index 000000000..1ea3729b5
--- /dev/null
+++ b/src/app/config-ui/mainwindow.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#include "settingsmodel.h"
+
+#include <QAction>
+#include <QKeySequence>
+#include <QMenu>
+#include <QMenuBar>
+
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+ m_model = new SettingsModel(this);
+ ui->treeView->setModel(m_model);
+ connect(ui->treeView, SIGNAL(expanded(QModelIndex)), SLOT(adjustColumns()));
+ adjustColumns();
+
+ QMenu * const fileMenu = menuBar()->addMenu(tr("&File"));
+ QMenu * const viewMenu = menuBar()->addMenu(tr("&View"));
+
+ QAction * const reloadAction = new QAction(tr("&Reload"), this);
+ reloadAction->setShortcut(Qt::CTRL | Qt::Key_R);
+ connect(reloadAction, SIGNAL(triggered()), SLOT(reloadSettings()));
+ QAction * const expandAllAction = new QAction(tr("&Expand All"), this);
+ expandAllAction->setShortcut(Qt::CTRL | Qt::Key_E);
+ connect(expandAllAction, SIGNAL(triggered()), SLOT(expandAll()));
+ QAction * const collapseAllAction = new QAction(tr("C&ollapse All"), this);
+ collapseAllAction->setShortcut(Qt::CTRL | Qt::Key_O);
+ connect(collapseAllAction, SIGNAL(triggered()), SLOT(collapseAll()));
+ QAction * const exitAction = new QAction(tr("E&xit"), this);
+ exitAction->setShortcut(Qt::CTRL | Qt::Key_Q);
+ connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+
+ fileMenu->addAction(reloadAction);
+ fileMenu->addSeparator();
+ fileMenu->addAction(exitAction);
+
+ viewMenu->addAction(expandAllAction);
+ viewMenu->addAction(collapseAllAction);
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::adjustColumns()
+{
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ ui->treeView->resizeColumnToContents(column);
+}
+
+void MainWindow::expandAll()
+{
+ ui->treeView->expandAll();
+ adjustColumns();
+}
+
+void MainWindow::collapseAll()
+{
+ ui->treeView->collapseAll();
+ adjustColumns();
+}
+
+void MainWindow::reloadSettings()
+{
+ m_model->reload();
+}
diff --git a/src/app/config-ui/mainwindow.h b/src/app/config-ui/mainwindow.h
new file mode 100644
index 000000000..e793f69dd
--- /dev/null
+++ b/src/app/config-ui/mainwindow.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class MainWindow; }
+QT_END_NAMESPACE
+
+class SettingsModel;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+private slots:
+ void adjustColumns();
+ void expandAll();
+ void collapseAll();
+ void reloadSettings();
+
+private:
+ Ui::MainWindow *ui;
+ SettingsModel *m_model;
+};
+
+#endif // MAINWINDOW_H
diff --git a/src/app/config-ui/mainwindow.ui b/src/app/config-ui/mainwindow.ui
new file mode 100644
index 000000000..7a3416ce4
--- /dev/null
+++ b/src/app/config-ui/mainwindow.ui
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qbs Settings</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeView" name="treeView"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>27</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/app/config-ui/settingsmodel.cpp b/src/app/config-ui/settingsmodel.cpp
new file mode 100644
index 000000000..f54ef5ac0
--- /dev/null
+++ b/src/app/config-ui/settingsmodel.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "settingsmodel.h"
+
+#include "../shared/qbssettings.h"
+
+#include <QList>
+#include <QString>
+
+struct Node
+{
+ Node() : parent(0) {}
+ ~Node() { qDeleteAll(children); }
+
+ QString name;
+ QString value;
+ Node *parent;
+ QList<Node *> children;
+};
+
+class SettingsModel::SettingsModelPrivate
+{
+public:
+ void readSettings();
+ void addNode(qbs::Settings *settings, Node *parentNode, const QString &fullyQualifiedName);
+ Node *indexToNode(const QModelIndex &index);
+
+ Node rootNode;
+};
+
+SettingsModel::SettingsModel(QObject *parent)
+ : QAbstractItemModel(parent), d(new SettingsModelPrivate)
+{
+ d->readSettings();
+}
+
+SettingsModel::~SettingsModel()
+{
+ delete d;
+}
+
+void SettingsModel::reload()
+{
+ beginResetModel();
+ d->readSettings();
+ endResetModel();
+}
+
+Qt::ItemFlags SettingsModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::ItemFlags();
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+}
+
+QVariant SettingsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation != Qt::Horizontal)
+ return QVariant();
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (section == 0)
+ return tr("Key");
+ return tr("Value");
+}
+
+int SettingsModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return 2;
+}
+
+int SettingsModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.column() > 0)
+ return 0;
+ const Node * const node = d->indexToNode(parent);
+ Q_ASSERT(node);
+ return node->children.count();
+}
+
+QVariant SettingsModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ const Node * const node = static_cast<Node *>(index.internalPointer());
+ Q_ASSERT(node);
+ if (index.column() == 0)
+ return node->name;
+ return node->value;
+}
+
+QModelIndex SettingsModel::index(int row, int column, const QModelIndex &parent) const
+{
+ const Node * const parentNode = d->indexToNode(parent);
+ Q_ASSERT(parentNode);
+ if (parentNode->children.count() <= row)
+ return QModelIndex();
+ return createIndex(row, column, parentNode->children.at(row));
+}
+
+QModelIndex SettingsModel::parent(const QModelIndex &child) const
+{
+ Node * const childNode = static_cast<Node *>(child.internalPointer());
+ Q_ASSERT(childNode);
+ Node * const parentNode = childNode->parent;
+ if (parentNode == &d->rootNode)
+ return QModelIndex();
+ const Node * const grandParentNode = parentNode->parent;
+ Q_ASSERT(grandParentNode);
+ return createIndex(grandParentNode->children.indexOf(parentNode), 0, parentNode);
+}
+
+
+void SettingsModel::SettingsModelPrivate::readSettings()
+{
+ qDeleteAll(rootNode.children);
+ rootNode.children.clear();
+ SettingsPtr settings = qbsSettings();
+ foreach (const QString &topLevelKey, settings->directChildren(QString()))
+ addNode(settings.data(), &rootNode, topLevelKey);
+}
+
+void SettingsModel::SettingsModelPrivate::addNode(qbs::Settings *settings, Node *parentNode,
+ const QString &fullyQualifiedName)
+{
+ Node * const node = new Node;
+ node->name = fullyQualifiedName.mid(fullyQualifiedName.lastIndexOf(QLatin1Char('.')) + 1);
+ node->value = settings->value(fullyQualifiedName).toString();
+ node->parent = parentNode;
+ parentNode->children << node;
+ foreach (const QString &childKey, settings->directChildren(fullyQualifiedName))
+ addNode(settings, node, fullyQualifiedName + QLatin1Char('.') + childKey);
+}
+
+Node *SettingsModel::SettingsModelPrivate::indexToNode(const QModelIndex &index)
+{
+ return index.isValid() ? static_cast<Node *>(index.internalPointer()) : &rootNode;
+}
diff --git a/src/app/config-ui/settingsmodel.h b/src/app/config-ui/settingsmodel.h
new file mode 100644
index 000000000..1052196e2
--- /dev/null
+++ b/src/app/config-ui/settingsmodel.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include <QAbstractItemModel>
+
+class SettingsModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ SettingsModel(QObject *parent = 0);
+ ~SettingsModel();
+
+ void reload();
+
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+
+private:
+ class SettingsModelPrivate;
+ SettingsModelPrivate * const d;
+};
diff --git a/src/app/qbs/qbstool.cpp b/src/app/qbs/qbstool.cpp
index 512e2ed9b..3ed7e4950 100644
--- a/src/app/qbs/qbstool.cpp
+++ b/src/app/qbs/qbstool.cpp
@@ -44,14 +44,13 @@ static QString qbsToolFilePath(const QString &toolName)
void QbsTool::runTool(const QString &toolName, const QStringList &arguments)
{
- m_failedToStart = m_failedToFinish = false;
+ m_failedToStart = false;
m_exitCode = -1;
QProcess toolProc;
toolProc.start(qbsToolFilePath(toolName), arguments);
if (!toolProc.waitForStarted())
m_failedToStart = true;
- if (!toolProc.waitForFinished())
- m_failedToFinish = true;
+ toolProc.waitForFinished(-1);
m_exitCode = toolProc.exitCode();
m_stdout = QString::fromLocal8Bit(toolProc.readAllStandardOutput());
m_stderr = QString::fromLocal8Bit(toolProc.readAllStandardError());
diff --git a/src/app/qbs/qbstool.h b/src/app/qbs/qbstool.h
index 4e7b5e3f7..92520af6b 100644
--- a/src/app/qbs/qbstool.h
+++ b/src/app/qbs/qbstool.h
@@ -35,7 +35,6 @@ public:
void runTool(const QString &toolName, const QStringList &arguments);
bool failedToStart() const { return m_failedToStart; }
- bool failedToFinish() const { return m_failedToFinish; }
int exitCode() const { return m_exitCode; }
QString stdOut() const { return m_stdout; }
QString stdErr() const { return m_stderr; }
@@ -46,7 +45,6 @@ public:
private:
bool m_failedToStart;
- bool m_failedToFinish;
int m_exitCode;
QString m_stdout;
QString m_stderr;
diff --git a/src/lib/tools/settings.cpp b/src/lib/tools/settings.cpp
index 255a78c98..147ec0693 100644
--- a/src/lib/tools/settings.cpp
+++ b/src/lib/tools/settings.cpp
@@ -69,6 +69,16 @@ QStringList Settings::allKeys() const
return keys;
}
+QStringList Settings::directChildren(const QString &parentGroup)
+{
+ m_settings->beginGroup(internalRepresentation(parentGroup));
+ QStringList children = m_settings->childGroups();
+ children << m_settings->childKeys();
+ m_settings->endGroup();
+ fixupKeys(children);
+ return children;
+}
+
QStringList Settings::allKeysWithPrefix(const QString &group)
{
m_settings->beginGroup(internalRepresentation(group));
@@ -118,7 +128,6 @@ QString Settings::externalRepresentation(const QString &internalKey) const
void Settings::fixupKeys(QStringList &keys) const
{
keys.sort();
- std::unique(keys.begin(), keys.end());
keys.removeDuplicates();
for (QStringList::Iterator it = keys.begin(); it != keys.end(); ++it)
*it = externalRepresentation(*it);
diff --git a/src/lib/tools/settings.h b/src/lib/tools/settings.h
index 2a6c93129..25e7bc0d6 100644
--- a/src/lib/tools/settings.h
+++ b/src/lib/tools/settings.h
@@ -47,6 +47,7 @@ public:
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
QStringList allKeys() const;
+ QStringList directChildren(const QString &parentGroup); // Keys and groups.
QStringList allKeysWithPrefix(const QString &group);
void setValue(const QString &key, const QVariant &value);
void remove(const QString &key);