summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLorenz Haas <lykurg@gmail.com>2013-12-11 21:55:45 +0100
committerDavid Schulz <david.schulz@digia.com>2014-02-18 07:36:12 +0100
commit4988b41b3f419dff3c6bf4fcf22d484fbc5384f4 (patch)
treeb25004f51d29003e85a75275fe95953aeeffd62a /src
parentf2ae69b1bf7f7ade6c01b42ed8444cd7e1b3ab94 (diff)
downloadqt-creator-4988b41b3f419dff3c6bf4fcf22d484fbc5384f4.tar.gz
Introduce new Beautifier plug-in
Beautifier is a plug-in for source code beautifiers. Currently Artistic Style, Clang-format and Uncrustify are supported. Task-number: QTCREATORBUG-7489 Change-Id: I8dde9a8ba6a6a55537bfd450ec82ef966ed283c0 Reviewed-by: David Schulz <david.schulz@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/beautifier/Beautifier.pluginspec.in18
-rw-r--r--src/plugins/beautifier/abstractsettings.cpp317
-rw-r--r--src/plugins/beautifier/abstractsettings.h94
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.cpp146
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.h68
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyleconstants.h46
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.cpp143
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.h85
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.ui104
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp186
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstylesettings.h66
-rw-r--r--src/plugins/beautifier/beautifier.pro51
-rw-r--r--src/plugins/beautifier/beautifier.qbs79
-rw-r--r--src/plugins/beautifier/beautifier.qrc5
-rw-r--r--src/plugins/beautifier/beautifier_dependencies.pri7
-rw-r--r--src/plugins/beautifier/beautifierabstracttool.h57
-rw-r--r--src/plugins/beautifier/beautifierconstants.h56
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp296
-rw-r--r--src/plugins/beautifier/beautifierplugin.h70
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.cpp149
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.h71
-rw-r--r--src/plugins/beautifier/clangformat/clangformatconstants.h47
-rw-r--r--src/plugins/beautifier/clangformat/clangformatoptionspage.cpp150
-rw-r--r--src/plugins/beautifier/clangformat/clangformatoptionspage.h84
-rw-r--r--src/plugins/beautifier/clangformat/clangformatoptionspage.ui132
-rw-r--r--src/plugins/beautifier/clangformat/clangformatsettings.cpp236
-rw-r--r--src/plugins/beautifier/clangformat/clangformatsettings.h71
-rw-r--r--src/plugins/beautifier/configurationdialog.cpp155
-rw-r--r--src/plugins/beautifier/configurationdialog.h71
-rw-r--r--src/plugins/beautifier/configurationdialog.ui118
-rw-r--r--src/plugins/beautifier/configurationeditor.cpp267
-rw-r--r--src/plugins/beautifier/configurationeditor.h106
-rw-r--r--src/plugins/beautifier/configurationpanel.cpp131
-rw-r--r--src/plugins/beautifier/configurationpanel.h70
-rw-r--r--src/plugins/beautifier/configurationpanel.ui57
-rw-r--r--src/plugins/beautifier/images/beautifier.pngbin0 -> 3424 bytes
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.cpp146
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.h68
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifyconstants.h46
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp143
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifyoptionspage.h85
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui104
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.cpp172
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustifysettings.h66
-rw-r--r--src/plugins/plugins.pro3
-rw-r--r--src/plugins/plugins.qbs1
46 files changed, 4642 insertions, 1 deletions
diff --git a/src/plugins/beautifier/Beautifier.pluginspec.in b/src/plugins/beautifier/Beautifier.pluginspec.in
new file mode 100644
index 0000000000..df85d373eb
--- /dev/null
+++ b/src/plugins/beautifier/Beautifier.pluginspec.in
@@ -0,0 +1,18 @@
+<plugin name=\"Beautifier\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\" experimental=\"true\">
+ <vendor>Lorenz Haas</vendor>
+ <copyright>(C) 2014 Lorenz Haas</copyright>
+ <license>
+Commercial Usage
+
+Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.
+
+GNU Lesser General Public License Usage
+
+Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 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.
+ </license>
+ <description>Format source files with the help of beautifiers like AStyle, uncrustify or clang-format.</description>
+ <category>C++</category>
+ <url>http://www.qt-project.org</url>
+ $$dependencyList
+</plugin>
+
diff --git a/src/plugins/beautifier/abstractsettings.cpp b/src/plugins/beautifier/abstractsettings.cpp
new file mode 100644
index 0000000000..75d2bc049d
--- /dev/null
+++ b/src/plugins/beautifier/abstractsettings.cpp
@@ -0,0 +1,317 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "abstractsettings.h"
+
+#include "beautifierconstants.h"
+#include "beautifierplugin.h"
+
+#include <coreplugin/icore.h>
+#include <utils/fileutils.h>
+
+#include <QDomDocument>
+#include <QDir>
+#include <QDomElement>
+#include <QFile>
+#include <QFileInfo>
+
+namespace Beautifier {
+namespace Internal {
+
+AbstractSettings::AbstractSettings(const QString &name, const QString &ending)
+ : m_name(name)
+ , m_ending(ending)
+ , m_styleDir(Core::ICore::userResourcePath() + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::SETTINGS_DIRNAME) + QLatin1Char('/')
+ + m_name)
+{
+}
+
+AbstractSettings::~AbstractSettings()
+{
+}
+
+QStringList AbstractSettings::completerWords()
+{
+ return QStringList();
+}
+
+QStringList AbstractSettings::styles() const
+{
+ QStringList list = m_styles.keys();
+ list.sort(Qt::CaseInsensitive);
+ return list;
+}
+
+QString AbstractSettings::style(const QString &key) const
+{
+ return m_styles.value(key);
+}
+
+bool AbstractSettings::styleExists(const QString &key) const
+{
+ return m_styles.contains(key);
+}
+
+bool AbstractSettings::styleIsReadOnly(const QString &key)
+{
+ QFileInfo fi(m_styleDir.absoluteFilePath(key + m_ending));
+ if (!fi.exists()) {
+ // newly added style which was not saved yet., thus it is not read only.
+ //TODO In a later version when we have predefined styles in Core::ICore::resourcePath()
+ // we need to check if it is a read only global config file...
+ return false;
+ }
+
+ return !fi.isWritable();
+}
+
+void AbstractSettings::setStyle(const QString &key, const QString &value)
+{
+ m_styles.insert(key, value);
+ m_changedStyles.insert(key);
+}
+
+void AbstractSettings::removeStyle(const QString &key)
+{
+ m_styles.remove(key);
+ m_stylesToRemove << key + m_ending;
+}
+
+void AbstractSettings::replaceStyle(const QString &oldKey, const QString &newKey,
+ const QString &value)
+{
+ // Set value regardles if keys are equal
+ m_styles.insert(newKey, value);
+
+ if (oldKey != newKey)
+ removeStyle(oldKey);
+
+ m_changedStyles.insert(newKey);
+}
+
+QString AbstractSettings::styleFileName(const QString &key) const
+{
+ return m_styleDir.absoluteFilePath(key + m_ending);
+}
+
+QString AbstractSettings::command() const
+{
+ return m_command;
+}
+
+void AbstractSettings::setCommand(const QString &command)
+{
+ if (command == m_command)
+ return;
+
+ m_command = command;
+}
+
+QStringList AbstractSettings::options()
+{
+ if (m_options.isEmpty())
+ readDocumentation();
+
+ return m_options.keys();
+}
+
+QString AbstractSettings::documentation(const QString &option) const
+{
+ const int index = m_options.value(option, -1);
+ if (index != -1)
+ return m_docu.at(index);
+ else
+ return QString();
+}
+
+void AbstractSettings::save()
+{
+ // Save settings, except styles
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(QLatin1String(Constants::SETTINGS_GROUP));
+ s->beginGroup(m_name);
+ QMap<QString, QVariant>::const_iterator iSettings = m_settings.constBegin();
+ while (iSettings != m_settings.constEnd()) {
+ s->setValue(iSettings.key(), iSettings.value());
+ ++iSettings;
+ }
+ s->setValue(QLatin1String("command"), m_command);
+ s->endGroup();
+ s->endGroup();
+
+ // Save styles
+ if (m_stylesToRemove.isEmpty() && m_styles.isEmpty())
+ return;
+
+ if (!m_styleDir.exists()) {
+ const QString path = m_styleDir.absolutePath();
+ if (!(m_styleDir.mkpath(path)
+ && m_styleDir.cd(path))) {
+ BeautifierPlugin::showError(tr("Failed to save styles. %1 does not exist.").arg(path));
+ return;
+ }
+ }
+
+ // remove old files
+ foreach (const QString file, m_stylesToRemove)
+ m_styleDir.remove(file);
+ m_stylesToRemove.clear();
+
+ QMap<QString, QString>::const_iterator iStyles = m_styles.constBegin();
+ while (iStyles != m_styles.constEnd()) {
+ // Only save changed styles.
+ if (!m_changedStyles.contains(iStyles.key())) {
+ ++iStyles;
+ continue;
+ }
+
+ Utils::FileSaver saver(styleFileName(iStyles.key()));
+ if (saver.hasError()) {
+ BeautifierPlugin::showError(tr("Could not open file \"%1\": %2.")
+ .arg(saver.fileName())
+ .arg(saver.errorString()));
+ } else {
+ saver.write(iStyles.value().toLocal8Bit());
+ if (!saver.finalize()) {
+ BeautifierPlugin::showError(tr("Error while saving file \"%1\": %2.")
+ .arg(saver.fileName())
+ .arg(saver.errorString()));
+ }
+ }
+ ++iStyles;
+ }
+
+ m_changedStyles.clear();
+}
+
+void AbstractSettings::createDocumentationFile() const
+{
+ // Could be reimplemented to create a documentation file.
+}
+
+void AbstractSettings::read()
+{
+ // Read settings, except styles
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(QLatin1String(Constants::SETTINGS_GROUP));
+ s->beginGroup(m_name);
+ const QStringList keys = s->allKeys();
+ foreach (const QString key, keys) {
+ if (key == QLatin1String("command"))
+ setCommand(s->value(key).toString());
+ else if (m_settings.contains(key))
+ m_settings[key] = s->value(key);
+ else
+ s->remove(key);
+ }
+ s->endGroup();
+ s->endGroup();
+
+ // Read styles
+ if (!m_styleDir.exists())
+ return;
+
+ m_stylesToRemove.clear();
+ m_styles.clear();
+ const QStringList files
+ = m_styleDir.entryList(QStringList() << QLatin1Char('*') + m_ending,
+ QDir::Files | QDir::Readable | QDir::NoDotAndDotDot);
+ foreach (const QString filename, files) {
+ // do not allow empty file names
+ if (filename == m_ending)
+ continue;
+
+ QFile file(m_styleDir.absoluteFilePath(filename));
+ if (file.open(QIODevice::ReadOnly)) {
+ m_styles.insert(filename.left(filename.length() - m_ending.length()),
+ QString::fromLocal8Bit(file.readAll()));
+ }
+ }
+
+ m_changedStyles.clear();
+ m_stylesToRemove.clear();
+}
+
+void AbstractSettings::readDocumentation()
+{
+ const QString filename = documentationFilePath();
+ if (filename.isEmpty()) {
+ BeautifierPlugin::showError(tr("No documentation file specified."));
+ return;
+ }
+
+ QFile file(filename);
+ if (!file.exists())
+ createDocumentationFile();
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ BeautifierPlugin::showError(tr("Could not open documentation file \"%1\".").arg(filename));
+ return;
+ }
+
+ QDomDocument xml;
+ xml.setContent(&file);
+ file.close();
+
+ QDomElement docElem = xml.documentElement();
+ if (docElem.tagName() != QLatin1String(Constants::DOCUMENTATION_XMLROOT)) {
+ BeautifierPlugin::showError(tr("The file \"%1\" is not a valid documentation file.")
+ .arg(filename));
+ return;
+ }
+
+ // We do not use QHash<QString, QString> since e.g. in Artistic Style there are many different
+ // keys with the same (long) documentation text. By splitting the keys from the documentation
+ // text we save a huge amount of memory.
+ m_options.clear();
+ m_docu.clear();
+ QDomElement e = docElem.firstChildElement(QLatin1String(Constants::DOCUMENTATION_XMLENTRY));
+ while (!e.isNull()) {
+ QDomElement keys = e.firstChildElement(QLatin1String(Constants::DOCUMENTATION_XMLKEYS));
+ if (keys.isNull()) {
+ m_docu << e.firstChildElement(QLatin1String(Constants::DOCUMENTATION_XMLDOC)).text();
+ m_options.insert(
+ e.firstChildElement(QLatin1String(Constants::DOCUMENTATION_XMLKEY)).text(),
+ m_docu.size() - 1);
+ } else {
+ m_docu << e.firstChildElement(QLatin1String(Constants::DOCUMENTATION_XMLDOC)).text();
+ const int index = m_docu.size() - 1;
+ QDomElement key = keys.firstChildElement(QLatin1String(Constants::DOCUMENTATION_XMLKEY));
+ while (!key.isNull()) {
+ m_options.insert(key.text(), index);
+ key = key.nextSiblingElement(QLatin1String(Constants::DOCUMENTATION_XMLKEY));
+ }
+ }
+ e = e.nextSiblingElement(QLatin1String(Constants::DOCUMENTATION_XMLENTRY));
+ }
+}
+
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/abstractsettings.h b/src/plugins/beautifier/abstractsettings.h
new file mode 100644
index 0000000000..031ccd26f3
--- /dev/null
+++ b/src/plugins/beautifier/abstractsettings.h
@@ -0,0 +1,94 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_ABSTRACTSETTINGS_H
+#define BEAUTIFIER_ABSTRACTSETTINGS_H
+
+#include <QCoreApplication>
+#include <QDir>
+#include <QHash>
+#include <QMap>
+#include <QSet>
+#include <QString>
+#include <QStringList>
+
+namespace Beautifier {
+namespace Internal {
+
+class AbstractSettings
+{
+ Q_DECLARE_TR_FUNCTIONS(AbstractSettings)
+
+public:
+ explicit AbstractSettings(const QString &name, const QString &ending);
+ virtual ~AbstractSettings();
+
+ void read();
+ void save();
+
+ virtual QString documentationFilePath() const = 0;
+ virtual void createDocumentationFile() const;
+ virtual QStringList completerWords();
+
+ QStringList styles() const;
+ QString style(const QString &key) const;
+ bool styleExists(const QString &key) const;
+ bool styleIsReadOnly(const QString &key);
+ void setStyle(const QString &key, const QString &value);
+ void removeStyle(const QString &key);
+ void replaceStyle(const QString &oldKey, const QString &newKey, const QString &value);
+ QString styleFileName(const QString &key) const;
+
+ QString command() const;
+ void setCommand(const QString &command);
+
+ QStringList options();
+ QString documentation(const QString &option) const;
+
+protected:
+ QMap<QString, QString> m_styles;
+ QMap<QString, QVariant> m_settings;
+
+ void readDocumentation();
+
+private:
+ QString m_name;
+ QString m_ending;
+ QDir m_styleDir;
+ QStringList m_stylesToRemove;
+ QSet<QString> m_changedStyles;
+ QString m_command;
+ QHash<QString, int> m_options;
+ QStringList m_docu;
+};
+
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_ABSTRACTSETTINGS_H
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
new file mode 100644
index 0000000000..b104e8d38a
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
@@ -0,0 +1,146 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "artisticstyle.h"
+
+#include "artisticstyleconstants.h"
+#include "artisticstyleoptionspage.h"
+#include "artisticstylesettings.h"
+
+#include "../beautifierconstants.h"
+#include "../beautifierplugin.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <cppeditor/cppeditorconstants.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/project.h>
+#include <utils/fileutils.h>
+
+#include <QAction>
+#include <QMenu>
+
+namespace Beautifier {
+namespace Internal {
+namespace ArtisticStyle {
+
+ArtisticStyle::ArtisticStyle(QObject *parent) :
+ BeautifierAbstractTool(parent),
+ m_settings(new ArtisticStyleSettings)
+{
+}
+
+ArtisticStyle::~ArtisticStyle()
+{
+ delete m_settings;
+}
+
+bool ArtisticStyle::initialize()
+{
+ Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::ArtisticStyle::MENU_ID);
+ menu->menu()->setTitle(QLatin1String("Artistic Style"));
+
+ m_formatFile = new QAction(tr("Format Current File"), this);
+ Core::Command *cmd
+ = Core::ActionManager::registerAction(m_formatFile,
+ Constants::ArtisticStyle::ACTION_FORMATFILE,
+ Core::Context(Core::Constants::C_GLOBAL));
+ menu->addAction(cmd);
+ connect(m_formatFile, SIGNAL(triggered()), this, SLOT(formatFile()));
+
+ Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
+
+ return true;
+}
+
+void ArtisticStyle::updateActions(Core::IEditor *editor)
+{
+ m_formatFile->setEnabled(editor && editor->id() == CppEditor::Constants::CPPEDITOR_ID);
+}
+
+QList<QObject *> ArtisticStyle::autoReleaseObjects()
+{
+ ArtisticStyleOptionsPage *optionsPage = new ArtisticStyleOptionsPage(m_settings, this);
+ return QList<QObject *>() << optionsPage;
+}
+
+void ArtisticStyle::formatFile()
+{
+ QString cfgFileName;
+
+ if (m_settings->useOtherFiles()) {
+ if (const ProjectExplorer::Project *project
+ = ProjectExplorer::ProjectExplorerPlugin::currentProject()) {
+ const QStringList files = project->files(ProjectExplorer::Project::AllFiles);
+ for (int i = 0, total = files.size(); i < total; ++i) {
+ const QString &file = files.at(i);
+ if (!file.endsWith(QLatin1String(".astylerc")))
+ continue;
+ const QFileInfo fi(file);
+ if (fi.isReadable()) {
+ cfgFileName = file;
+ break;
+ }
+ }
+ }
+ }
+
+ if (cfgFileName.isEmpty() && m_settings->useHomeFile()) {
+ QString file = QDir::home().filePath(QLatin1String(".astylerc"));
+ if (QFile::exists(file)) {
+ cfgFileName = file;
+ } else {
+ file = QDir::home().filePath(QLatin1String("astylerc"));
+ if (QFile::exists(file))
+ cfgFileName = file;
+ }
+ }
+
+ if (m_settings->useCustomStyle())
+ cfgFileName = m_settings->styleFileName(m_settings->customStyle());
+
+ if (cfgFileName.isEmpty()) {
+ BeautifierPlugin::showError(tr("Could not get configuration file for Artistic Style."));
+ } else {
+ BeautifierPlugin::formatCurrentFile(QStringList()
+ << m_settings->command()
+ << QLatin1String("-q")
+ << QLatin1String("--options=") + cfgFileName
+ << QLatin1String("%file"));
+ }
+}
+
+} // namespace ArtisticStyle
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.h b/src/plugins/beautifier/artisticstyle/artisticstyle.h
new file mode 100644
index 0000000000..630d4f376a
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_ARTISTICSTYLE_H
+#define BEAUTIFIER_ARTISTICSTYLE_H
+
+#include "../beautifierabstracttool.h"
+
+#include <utils/qtcoverride.h>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+namespace Beautifier {
+namespace Internal {
+namespace ArtisticStyle {
+
+class ArtisticStyleSettings;
+
+class ArtisticStyle : public BeautifierAbstractTool
+{
+ Q_OBJECT
+
+public:
+ explicit ArtisticStyle(QObject *parent = 0);
+ virtual ~ArtisticStyle();
+ bool initialize() QTC_OVERRIDE;
+ void updateActions(Core::IEditor *editor) QTC_OVERRIDE;
+ QList<QObject *> autoReleaseObjects() QTC_OVERRIDE;
+
+private slots:
+ void formatFile();
+
+private:
+ QAction *m_formatFile;
+ ArtisticStyleSettings *m_settings;
+};
+
+} // namespace ArtisticStyle
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_ARTISTICSTYLE_H
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyleconstants.h b/src/plugins/beautifier/artisticstyle/artisticstyleconstants.h
new file mode 100644
index 0000000000..433271f3fb
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstyleconstants.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_ARTISTICSTYLECONSTANTS_H
+#define BEAUTIFIER_ARTISTICSTYLECONSTANTS_H
+
+namespace Beautifier {
+namespace Constants {
+namespace ArtisticStyle {
+
+const char ACTION_FORMATFILE[] = "ArtisticStyle.FormatFile";
+const char MENU_ID[] = "ArtisticStyle.Menu";
+const char OPTION_ID[] = "ArtisticStyle";
+const char SETTINGS_NAME[] = "artisticstyle";
+
+} // namespace ArtisticStyle
+} // namespace Constants
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_ARTISTICSTYLECONSTANTS_H
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.cpp b/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.cpp
new file mode 100644
index 0000000000..457a9e4b8a
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.cpp
@@ -0,0 +1,143 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "artisticstyleoptionspage.h"
+#include "ui_artisticstyleoptionspage.h"
+
+#include "artisticstyleconstants.h"
+#include "artisticstylesettings.h"
+
+#include "../beautifierconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QTextStream>
+
+namespace Beautifier {
+namespace Internal {
+namespace ArtisticStyle {
+
+ArtisticStyleOptionsPageWidget::ArtisticStyleOptionsPageWidget(ArtisticStyleSettings *settings,
+ QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::ArtisticStyleOptionsPage)
+ , m_settings(settings)
+{
+ ui->setupUi(this);
+ ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ ui->command->setPromptDialogTitle(tr("Artistic Style Command"));
+ connect(ui->command, SIGNAL(validChanged(bool)), ui->options, SLOT(setEnabled(bool)));
+ ui->configurations->setSettings(m_settings);
+}
+
+ArtisticStyleOptionsPageWidget::~ArtisticStyleOptionsPageWidget()
+{
+ delete ui;
+}
+
+QString ArtisticStyleOptionsPageWidget::searchKeywords() const
+{
+ QString keywords;
+ const QLatin1Char sep(' ');
+ QTextStream(&keywords) << sep << ui->configuration->title()
+ << sep << ui->commandLabel->text()
+ << sep << ui->options->title()
+ << sep << ui->useOtherFiles->text()
+ << sep << ui->useHomeFile->text()
+ << sep << ui->useCustomStyle->text();
+ keywords.remove(QLatin1Char('&'));
+ return keywords;
+}
+
+void ArtisticStyleOptionsPageWidget::restore()
+{
+ ui->command->setPath(m_settings->command());
+ ui->useOtherFiles->setChecked(m_settings->useOtherFiles());
+ ui->useHomeFile->setChecked(m_settings->useHomeFile());
+ ui->useCustomStyle->setChecked(m_settings->useCustomStyle());
+ ui->configurations->setCurrentConfiguration(m_settings->customStyle());
+}
+
+void ArtisticStyleOptionsPageWidget::apply()
+{
+ m_settings->setCommand(ui->command->path());
+ m_settings->setUseOtherFiles(ui->useOtherFiles->isChecked());
+ m_settings->setUseHomeFile(ui->useHomeFile->isChecked());
+ m_settings->setUseCustomStyle(ui->useCustomStyle->isChecked());
+ m_settings->setCustomStyle(ui->configurations->currentConfiguration());
+ m_settings->save();
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+ArtisticStyleOptionsPage::ArtisticStyleOptionsPage(ArtisticStyleSettings *settings, QObject *parent) :
+ IOptionsPage(parent),
+ m_widget(0),
+ m_settings(settings),
+ m_searchKeywords()
+{
+ setId(Constants::ArtisticStyle::OPTION_ID);
+ setDisplayName(tr("Artistic Style"));
+ setCategory(Constants::OPTION_CATEGORY);
+ setDisplayCategory(QCoreApplication::translate("Beautifier", Constants::OPTION_TR_CATEGORY));
+ setCategoryIcon(QLatin1String(Constants::OPTION_CATEGORY_ICON));
+}
+
+QWidget *ArtisticStyleOptionsPage::widget()
+{
+ m_settings->read();
+
+ if (!m_widget) {
+ m_widget = new ArtisticStyleOptionsPageWidget(m_settings);
+ if (m_searchKeywords.isEmpty())
+ m_searchKeywords = m_widget->searchKeywords();
+ }
+ m_widget->restore();
+
+ return m_widget;
+}
+
+void ArtisticStyleOptionsPage::apply()
+{
+ if (m_widget)
+ m_widget->apply();
+}
+
+void ArtisticStyleOptionsPage::finish()
+{
+}
+
+bool ArtisticStyleOptionsPage::matches(const QString &searchKeyWord) const
+{
+ return m_searchKeywords.contains(searchKeyWord, Qt::CaseInsensitive);
+}
+
+} // namespace ArtisticStyle
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.h b/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.h
new file mode 100644
index 0000000000..1ac90ad369
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_ARTISTICSTYLEOPTIONSPAGE_H
+#define BEAUTIFIER_ARTISTICSTYLEOPTIONSPAGE_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+#include <utils/qtcoverride.h>
+
+#include <QPointer>
+#include <QWidget>
+
+namespace Beautifier {
+namespace Internal {
+namespace ArtisticStyle {
+
+class ArtisticStyleSettings;
+
+namespace Ui { class ArtisticStyleOptionsPage; }
+
+class ArtisticStyleOptionsPageWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ArtisticStyleOptionsPageWidget(ArtisticStyleSettings *settings, QWidget *parent = 0);
+ virtual ~ArtisticStyleOptionsPageWidget();
+ QString searchKeywords() const;
+ void restore();
+ void apply();
+
+private:
+ Ui::ArtisticStyleOptionsPage *ui;
+ ArtisticStyleSettings *m_settings;
+};
+
+class ArtisticStyleOptionsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ explicit ArtisticStyleOptionsPage(ArtisticStyleSettings *settings, QObject *parent = 0);
+ QWidget *widget() QTC_OVERRIDE;
+ void apply() QTC_OVERRIDE;
+ void finish() QTC_OVERRIDE;
+ bool matches(const QString &searchKeywords) const QTC_OVERRIDE;
+
+private:
+ QPointer<ArtisticStyleOptionsPageWidget> m_widget;
+ ArtisticStyleSettings *m_settings;
+ QString m_searchKeywords;
+};
+
+} // namespace ArtisticStyle
+} // namespace Internal
+} // namespace Beautifier
+
+
+#endif // BEAUTIFIER_ARTISTICSTYLEOPTIONSPAGE_H
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.ui b/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.ui
new file mode 100644
index 0000000000..030e0bac1a
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstyleoptionspage.ui
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Beautifier::Internal::ArtisticStyle::ArtisticStyleOptionsPage</class>
+ <widget class="QWidget" name="Beautifier::Internal::ArtisticStyle::ArtisticStyleOptionsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>817</width>
+ <height>631</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0">
+ <item>
+ <widget class="QGroupBox" name="configuration">
+ <property name="title">
+ <string>Configuration</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="commandLabel">
+ <property name="text">
+ <string>Artistic Style command:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Utils::PathChooser" name="command" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="options">
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="useOtherFiles">
+ <property name="text">
+ <string>Use file *.astylerc defined in project files</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="useHomeFile">
+ <property name="text">
+ <string>Use $HOME/.astylerc or $HOME/astylerc</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,9999">
+ <item>
+ <widget class="QCheckBox" name="useCustomStyle">
+ <property name="text">
+ <string>Use selfdefined style:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Beautifier::Internal::ConfigurationPanel</class>
+ <extends>QWidget</extends>
+ <header location="global">beautifier/configurationpanel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
new file mode 100644
index 0000000000..7ee6c50d85
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp
@@ -0,0 +1,186 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "artisticstylesettings.h"
+
+#include "artisticstyleconstants.h"
+
+#include "../beautifierconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QDateTime>
+#include <QFile>
+#include <QFileInfo>
+#include <QProcess>
+#include <QXmlStreamWriter>
+
+namespace Beautifier {
+namespace Internal {
+namespace ArtisticStyle {
+
+namespace {
+const char kUseOtherFiles[] = "useOtherFiles";
+const char kUseHomeFile[] = "useHomeFile";
+const char kUseCustomStyle[] = "useCustomStyle";
+const char kCustomStyle[] = "customStyle";
+}
+
+ArtisticStyleSettings::ArtisticStyleSettings() :
+ AbstractSettings(QLatin1String(Constants::ArtisticStyle::SETTINGS_NAME),
+ QLatin1String(".astyle"))
+{
+ setCommand(QLatin1String("astyle"));
+ m_settings.insert(QLatin1String(kUseOtherFiles), QVariant(true));
+ m_settings.insert(QLatin1String(kUseHomeFile), QVariant(false));
+ m_settings.insert(QLatin1String(kUseCustomStyle), QVariant(false));
+ m_settings.insert(QLatin1String(kCustomStyle), QVariant());
+ read();
+}
+
+bool ArtisticStyleSettings::useOtherFiles() const
+{
+ return m_settings.value(QLatin1String(kUseOtherFiles)).toBool();
+}
+
+void ArtisticStyleSettings::setUseOtherFiles(bool useOtherFiles)
+{
+ m_settings.insert(QLatin1String(kUseOtherFiles), QVariant(useOtherFiles));
+}
+
+bool ArtisticStyleSettings::useHomeFile() const
+{
+ return m_settings.value(QLatin1String(kUseHomeFile)).toBool();
+}
+
+void ArtisticStyleSettings::setUseHomeFile(bool useHomeFile)
+{
+ m_settings.insert(QLatin1String(kUseHomeFile), QVariant(useHomeFile));
+}
+
+bool ArtisticStyleSettings::useCustomStyle() const
+{
+ return m_settings.value(QLatin1String(kUseCustomStyle)).toBool();
+}
+
+void ArtisticStyleSettings::setUseCustomStyle(bool useCustomStyle)
+{
+ m_settings.insert(QLatin1String(kUseCustomStyle), QVariant(useCustomStyle));
+}
+
+QString ArtisticStyleSettings::customStyle() const
+{
+ return m_settings.value(QLatin1String(kCustomStyle)).toString();
+}
+
+void ArtisticStyleSettings::setCustomStyle(const QString &customStyle)
+{
+ m_settings.insert(QLatin1String(kCustomStyle), QVariant(customStyle));
+}
+
+QString ArtisticStyleSettings::documentationFilePath() const
+{
+ return Core::ICore::userResourcePath() + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::SETTINGS_DIRNAME) + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::DOCUMENTATION_DIRNAME) + QLatin1Char('/')
+ + QLatin1String(Constants::ArtisticStyle::SETTINGS_NAME) + QLatin1String(".xml");
+}
+
+void ArtisticStyleSettings::createDocumentationFile() const
+{
+ QFile file(documentationFilePath());
+ const QFileInfo fi(file);
+ if (!fi.exists())
+ fi.dir().mkpath(fi.absolutePath());
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
+ return;
+
+ QProcess process;
+ process.start(command(), QStringList() << QLatin1String("-h"));
+ process.waitForFinished(2000); // show help should be really fast.
+ if (process.error() != QProcess::UnknownError)
+ return;
+
+ QXmlStreamWriter stream(&file);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument(QLatin1String("1.0"), true);
+ stream.writeComment(QLatin1String("Created ")
+ + QDateTime::currentDateTime().toString(Qt::ISODate));
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLROOT));
+
+ // astyle writes its output to 'error'...
+ const QStringList lines = QString::fromUtf8(process.readAllStandardError())
+ .split(QLatin1Char('\n'));
+ const int totalLines = lines.count();
+ QStringList keys;
+ QStringList docu;
+ for (int i = 0; i < totalLines; ++i) {
+ const QString &line = lines.at(i).trimmed();
+ if ((line.startsWith(QLatin1String("--")) && !line.startsWith(QLatin1String("---")))
+ || line.startsWith(QLatin1String("OR "))) {
+ QStringList rawKeys = line.split(QLatin1String(" OR "), QString::SkipEmptyParts);
+ foreach (QString k, rawKeys) {
+ k = k.trimmed();
+ k.remove(QLatin1Char('#'));
+ keys << k;
+ if (k.startsWith(QLatin1String("--")))
+ keys << k.right(k.size() - 2);
+ }
+ } else {
+ if (line.isEmpty()) {
+ if (!keys.isEmpty()) {
+ // Write entry
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLENTRY));
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLKEYS));
+ foreach (const QString &key, keys)
+ stream.writeTextElement(QLatin1String(Constants::DOCUMENTATION_XMLKEY), key);
+ stream.writeEndElement();
+ const QString text = QLatin1String("<p><span class=\"option\">")
+ + keys.filter(QRegExp(QLatin1String("^\\-"))).join(QLatin1String(", "))
+ + QLatin1String("</span></p><p>")
+ + Qt::escape(docu.join(QLatin1Char(' ')))
+ + QLatin1String("</p>");
+ stream.writeTextElement(QLatin1String(Constants::DOCUMENTATION_XMLDOC), text);
+ stream.writeEndElement();
+ }
+ keys.clear();
+ docu.clear();
+ } else if (!keys.isEmpty()) {
+ docu << line;
+ }
+ }
+ }
+
+ stream.writeEndElement();
+ stream.writeEndDocument();
+}
+
+} // namespace ArtisticStyle
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.h b/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
new file mode 100644
index 0000000000..412570c9e4
--- /dev/null
+++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_ARTISTICSTYLESETTINGS_H
+#define BEAUTIFIER_ARTISTICSTYLESETTINGS_H
+
+#include "../abstractsettings.h"
+
+#include <utils/qtcoverride.h>
+
+namespace Beautifier {
+namespace Internal {
+namespace ArtisticStyle {
+
+class ArtisticStyleSettings : public AbstractSettings
+{
+public:
+ ArtisticStyleSettings();
+
+ bool useOtherFiles() const;
+ void setUseOtherFiles(bool useOtherFiles);
+
+ bool useHomeFile() const;
+ void setUseHomeFile(bool useHomeFile);
+
+ bool useCustomStyle() const;
+ void setUseCustomStyle(bool useCustomStyle);
+
+ QString customStyle() const;
+ void setCustomStyle(const QString &customStyle);
+
+ QString documentationFilePath() const QTC_OVERRIDE;
+ void createDocumentationFile() const QTC_OVERRIDE;
+};
+
+} // namespace ArtisticStyle
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_ARTISTICSTYLESETTINGS_H
diff --git a/src/plugins/beautifier/beautifier.pro b/src/plugins/beautifier/beautifier.pro
new file mode 100644
index 0000000000..4e0891dc25
--- /dev/null
+++ b/src/plugins/beautifier/beautifier.pro
@@ -0,0 +1,51 @@
+include(../../qtcreatorplugin.pri)
+
+QT += xml
+
+HEADERS += \
+ abstractsettings.h \
+ beautifierabstracttool.h \
+ beautifierconstants.h \
+ beautifierplugin.h \
+ configurationdialog.h \
+ configurationeditor.h \
+ configurationpanel.h \
+ artisticstyle/artisticstyleconstants.h \
+ artisticstyle/artisticstyle.h \
+ artisticstyle/artisticstyleoptionspage.h \
+ artisticstyle/artisticstylesettings.h \
+ clangformat/clangformatconstants.h \
+ clangformat/clangformat.h \
+ clangformat/clangformatoptionspage.h \
+ clangformat/clangformatsettings.h \
+ uncrustify/uncrustifyconstants.h \
+ uncrustify/uncrustify.h \
+ uncrustify/uncrustifyoptionspage.h \
+ uncrustify/uncrustifysettings.h
+
+SOURCES += \
+ abstractsettings.cpp \
+ beautifierplugin.cpp \
+ configurationdialog.cpp \
+ configurationeditor.cpp \
+ configurationpanel.cpp \
+ artisticstyle/artisticstyle.cpp \
+ artisticstyle/artisticstyleoptionspage.cpp \
+ artisticstyle/artisticstylesettings.cpp \
+ clangformat/clangformat.cpp \
+ clangformat/clangformatoptionspage.cpp \
+ clangformat/clangformatsettings.cpp \
+ uncrustify/uncrustify.cpp \
+ uncrustify/uncrustifyoptionspage.cpp \
+ uncrustify/uncrustifysettings.cpp
+
+FORMS += \
+ configurationdialog.ui \
+ configurationpanel.ui \
+ artisticstyle/artisticstyleoptionspage.ui \
+ clangformat/clangformatoptionspage.ui \
+ uncrustify/uncrustifyoptionspage.ui \
+
+RESOURCES += \
+ beautifier.qrc
+
diff --git a/src/plugins/beautifier/beautifier.qbs b/src/plugins/beautifier/beautifier.qbs
new file mode 100644
index 0000000000..78ef3327ee
--- /dev/null
+++ b/src/plugins/beautifier/beautifier.qbs
@@ -0,0 +1,79 @@
+import qbs.base 1.0
+
+import QtcPlugin
+
+QtcPlugin {
+ name: "Beautifier"
+
+ Depends { name: "Qt.widgets" }
+ Depends { name: "Qt.xml" }
+ Depends { name: "Utils" }
+ Depends { name: "Core" }
+ Depends { name: "CppEditor" }
+ Depends { name: "DiffEditor" }
+ Depends { name: "TextEditor" }
+ Depends { name: "ProjectExplorer" }
+
+ files: [
+ "abstractsettings.h",
+ "abstractsettings.cpp",
+ "beautifier.qrc",
+ "beautifierabstracttool.h",
+ "beautifierconstants.h",
+ "beautifierplugin.cpp",
+ "beautifierplugin.h",
+ "configurationdialog.cpp",
+ "configurationdialog.h",
+ "configurationdialog.ui",
+ "configurationeditor.cpp",
+ "configurationeditor.h",
+ "configurationpanel.cpp",
+ "configurationpanel.h",
+ "configurationpanel.ui"
+ ]
+
+ Group {
+ name: "ArtisticStyle"
+ prefix: "artisticstyle/"
+ files: [
+ "artisticstyle.cpp",
+ "artisticstyle.h",
+ "artisticstyleconstants.h",
+ "artisticstyleoptionspage.cpp",
+ "artisticstyleoptionspage.h",
+ "artisticstyleoptionspage.ui",
+ "artisticstylesettings.cpp",
+ "artisticstylesettings.h"
+ ]
+ }
+
+ Group {
+ name: "ClangFormat"
+ prefix: "clangformat/"
+ files: [
+ "clangformat.cpp",
+ "clangformat.h",
+ "clangformatconstants.h",
+ "clangformatoptionspage.cpp",
+ "clangformatoptionspage.h",
+ "clangformatoptionspage.ui",
+ "clangformatsettings.cpp",
+ "clangformatsettings.h"
+ ]
+ }
+
+ Group {
+ name: "Uncrustify"
+ prefix: "uncrustify/"
+ files: [
+ "uncrustify.cpp",
+ "uncrustify.h",
+ "uncrustifyconstants.h",
+ "uncrustifyoptionspage.cpp",
+ "uncrustifyoptionspage.h",
+ "uncrustifyoptionspage.ui",
+ "uncrustifysettings.cpp",
+ "uncrustifysettings.h"
+ ]
+ }
+}
diff --git a/src/plugins/beautifier/beautifier.qrc b/src/plugins/beautifier/beautifier.qrc
new file mode 100644
index 0000000000..db98b065bc
--- /dev/null
+++ b/src/plugins/beautifier/beautifier.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="categoryicon">images/beautifier.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/beautifier/beautifier_dependencies.pri b/src/plugins/beautifier/beautifier_dependencies.pri
new file mode 100644
index 0000000000..a759c36322
--- /dev/null
+++ b/src/plugins/beautifier/beautifier_dependencies.pri
@@ -0,0 +1,7 @@
+QTC_PLUGIN_NAME = Beautifier
+QTC_LIB_DEPENDS += utils
+QTC_PLUGIN_DEPENDS += coreplugin \
+ cppeditor \
+ diffeditor \
+ projectexplorer \
+ texteditor
diff --git a/src/plugins/beautifier/beautifierabstracttool.h b/src/plugins/beautifier/beautifierabstracttool.h
new file mode 100644
index 0000000000..0dbd6296cf
--- /dev/null
+++ b/src/plugins/beautifier/beautifierabstracttool.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_BEAUTIFIERABSTRACTTOOL_H
+#define BEAUTIFIER_BEAUTIFIERABSTRACTTOOL_H
+
+#include <QList>
+#include <QObject>
+
+namespace Core { class IEditor; }
+
+namespace Beautifier {
+namespace Internal {
+
+class BeautifierAbstractTool : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit BeautifierAbstractTool(QObject *parent = 0) : QObject(parent) {}
+ virtual ~BeautifierAbstractTool() {}
+
+ virtual bool initialize() = 0;
+ virtual void updateActions(Core::IEditor *editor) = 0;
+ virtual QList<QObject *> autoReleaseObjects() = 0;
+};
+
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_BEAUTIFIERABSTRACTTOOL_H
diff --git a/src/plugins/beautifier/beautifierconstants.h b/src/plugins/beautifier/beautifierconstants.h
new file mode 100644
index 0000000000..f317a14ddf
--- /dev/null
+++ b/src/plugins/beautifier/beautifierconstants.h
@@ -0,0 +1,56 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_BEAUTIFIERCONSTANTS_H
+#define BEAUTIFIER_BEAUTIFIERCONSTANTS_H
+
+#include <QtGlobal>
+
+namespace Beautifier {
+namespace Constants {
+
+const char ACTION_ID[] = "Beautifier.Action";
+const char MENU_ID[] = "Beautifier.Menu";
+const char OPTION_CATEGORY[] = "II.Beautifier";
+const char OPTION_TR_CATEGORY[] = QT_TRANSLATE_NOOP("Beautifier", "Beautifier");
+const char OPTION_CATEGORY_ICON[] = ":/categoryicon";
+const char SETTINGS_GROUP[] = "Beautifier";
+const char SETTINGS_DIRNAME[] = "beautifier";
+const char DOCUMENTATION_DIRNAME[] = "documentation";
+const char DOCUMENTATION_XMLROOT[] = "beautifier_documentation";
+const char DOCUMENTATION_XMLENTRY[] = "entry";
+const char DOCUMENTATION_XMLKEYS[] = "keys";
+const char DOCUMENTATION_XMLKEY[] = "key";
+const char DOCUMENTATION_XMLDOC[] = "doc";
+
+} // namespace Constants
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_BEAUTIFIERCONSTANTS_H
+
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
new file mode 100644
index 0000000000..abf8e16b38
--- /dev/null
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -0,0 +1,296 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "beautifierplugin.h"
+
+#include "beautifierconstants.h"
+#include "artisticstyle/artisticstyle.h"
+#include "clangformat/clangformat.h"
+#include "uncrustify/uncrustify.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/messagemanager.h>
+#include <diffeditor/differ.h>
+#include <texteditor/basetextdocument.h>
+#include <texteditor/basetextdocumentlayout.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/texteditorconstants.h>
+#include <utils/fileutils.h>
+
+#include <QAction>
+#include <QFileInfo>
+#include <QPlainTextEdit>
+#include <QProcess>
+#include <QScrollBar>
+#include <QTextBlock>
+#include <QTimer>
+#include <QtPlugin>
+
+namespace Beautifier {
+namespace Internal {
+
+BeautifierPlugin::BeautifierPlugin()
+{
+}
+
+BeautifierPlugin::~BeautifierPlugin()
+{
+}
+
+bool BeautifierPlugin::initialize(const QStringList &arguments, QString *errorString)
+{
+ Q_UNUSED(arguments)
+ Q_UNUSED(errorString)
+
+ m_tools << new ArtisticStyle::ArtisticStyle(this);
+ m_tools << new ClangFormat::ClangFormat(this);
+ m_tools << new Uncrustify::Uncrustify(this);
+
+ Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
+ menu->menu()->setTitle(QLatin1String("Beautifier"));
+ Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
+
+ for (int i = 0, total = m_tools.count(); i < total; ++i) {
+ BeautifierAbstractTool *tool = m_tools.at(i);
+ tool->initialize();
+ const QList<QObject *> autoReleasedObjects = tool->autoReleaseObjects();
+ for (int j = 0, total = autoReleasedObjects.count(); j < total; ++j)
+ addAutoReleasedObject(autoReleasedObjects.at(j));
+ }
+
+ // The single shot is needed, otherwise the menu will stay disabled even
+ // when the submenu's actions get enabled later on.
+ QTimer::singleShot(0, this, SLOT(updateActions()));
+ return true;
+}
+
+void BeautifierPlugin::extensionsInitialized()
+{
+ if (const Core::EditorManager *editorManager = Core::EditorManager::instance()) {
+ connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor *)),
+ this, SLOT(updateActions(Core::IEditor *)));
+ }
+}
+
+ExtensionSystem::IPlugin::ShutdownFlag BeautifierPlugin::aboutToShutdown()
+{
+ return SynchronousShutdown;
+}
+
+void BeautifierPlugin::updateActions(Core::IEditor *editor)
+{
+ for (int i = 0, total = m_tools.count(); i < total; ++i)
+ m_tools.at(i)->updateActions(editor);
+}
+
+QString BeautifierPlugin::format(const QString &text, QStringList command, const QString &fileName)
+{
+ if (command.isEmpty())
+ return QString();
+
+ // Save text to temporary file
+ QFileInfo fi(fileName);
+ Utils::TempFileSaver sourceFile(QLatin1String("qtc_beautifier_XXXXXXXX.") + fi.suffix());
+ sourceFile.setAutoRemove(true);
+ sourceFile.write(text.toUtf8());
+ if (!sourceFile.finalize()) {
+ showError(tr("Couldn't create temporary file %1: %2.")
+ .arg(sourceFile.fileName()).arg(sourceFile.errorString()));
+ return QString();
+ }
+
+ // Format temporary file
+ QProcess process;
+ command.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
+ process.start(command.takeFirst(), command);
+ if (!process.waitForFinished()) {
+ showError(tr("Failed to call %1 or an error occurred.").arg(process.program()));
+ return QString();
+ }
+ const QByteArray output = process.readAllStandardError();
+ if (!output.isEmpty())
+ showError(process.program() + QLatin1String(": ") + QString::fromLocal8Bit(output));
+
+ // Read text back
+ Utils::FileReader reader;
+ if (!reader.fetch(sourceFile.fileName(), QIODevice::Text)) {
+ showError(tr("Couldn't read file %1: %2.")
+ .arg(sourceFile.fileName()).arg(reader.errorString()));
+ return QString();
+ }
+ return QString::fromUtf8(reader.data());
+}
+
+void BeautifierPlugin::formatCurrentFile(QStringList command)
+{
+ QPlainTextEdit *textEditor = 0;
+ if (TextEditor::BaseTextEditor *editor
+ = qobject_cast<TextEditor::BaseTextEditor *>(Core::EditorManager::currentEditor()))
+ textEditor = qobject_cast<QPlainTextEdit *>(editor->editorWidget());
+ if (!textEditor)
+ return;
+
+ const QString sourceData = textEditor->toPlainText();
+ if (sourceData.isEmpty())
+ return;
+
+ const QString formattedData = format(sourceData, command,
+ Core::EditorManager::currentDocument()->filePath());
+ if ((sourceData == formattedData) || formattedData.isEmpty())
+ return;
+
+ // Since QTextCursor does not work properly with folded blocks, all blocks must be unfolded.
+ // To restore the current state at the end, keep track of which block is folded.
+ QList<int> foldedBlocks;
+ QTextBlock block = textEditor->document()->firstBlock();
+ while (block.isValid()) {
+ if (const TextEditor::TextBlockUserData *userdata
+ = static_cast<TextEditor::TextBlockUserData *>(block.userData())) {
+ if (userdata->folded()) {
+ foldedBlocks << block.blockNumber();
+ TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(block, true);
+ }
+ }
+ block = block.next();
+ }
+ textEditor->update();
+
+ // Save the current viewport position of the cursor to ensure the same vertical position after
+ // the formatted text has set to the editor.
+ int absoluteVerticalCursorOffset = textEditor->cursorRect().y();
+
+ // Calculate diff
+ DiffEditor::Differ differ;
+ const QList<DiffEditor::Diff> diff = differ.diff(sourceData, formattedData);
+
+ // Update changed lines and keep track of the cursor position
+ QTextCursor cursor = textEditor->textCursor();
+ int charactersInfrontOfCursor = cursor.position();
+ int newCursorPos = charactersInfrontOfCursor;
+ cursor.beginEditBlock();
+ cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
+ const int diffSize = diff.size();
+ for (int i = 0; i < diffSize; ++i) {
+ const DiffEditor::Diff d = diff.at(i);
+ switch (d.command) {
+ case DiffEditor::Diff::Insert:
+ {
+ // Adjust cursor position if we do work in front of the cursor.
+ if (charactersInfrontOfCursor > 0) {
+ const int size = d.text.size();
+ charactersInfrontOfCursor += size;
+ newCursorPos += size;
+ }
+ // Adjust folded blocks, if a new block is added.
+ if (d.text.contains(QLatin1Char('\n'))) {
+ const int newLineCount = d.text.count(QLatin1Char('\n'));
+ const int number = cursor.blockNumber();
+ const int total = foldedBlocks.size();
+ for (int i = 0; i < total; ++i) {
+ if (foldedBlocks.at(i) > number)
+ foldedBlocks[i] += newLineCount;
+ }
+ }
+ cursor.insertText(d.text);
+ }
+ break;
+ case DiffEditor::Diff::Delete:
+ {
+ // Adjust cursor position if we do work in front of the cursor.
+ if (charactersInfrontOfCursor > 0) {
+ const int size = d.text.size();
+ charactersInfrontOfCursor -= size;
+ newCursorPos -= size;
+ // Cursor was inside the deleted text, so adjust the new cursor position
+ if (charactersInfrontOfCursor < 0)
+ newCursorPos -= charactersInfrontOfCursor;
+ }
+ // Adjust folded blocks, if at least one block is being deleted.
+ if (d.text.contains(QLatin1Char('\n'))) {
+ const int newLineCount = d.text.count(QLatin1Char('\n'));
+ const int number = cursor.blockNumber();
+ for (int i = 0, total = foldedBlocks.size(); i < total; ++i) {
+ if (foldedBlocks.at(i) > number) {
+ foldedBlocks[i] -= newLineCount;
+ if (foldedBlocks[i] < number) {
+ foldedBlocks.removeAt(i);
+ --i;
+ --total;
+ }
+ }
+ }
+ }
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, d.text.size());
+ cursor.removeSelectedText();
+ }
+ break;
+ case DiffEditor::Diff::Equal:
+ // Adjust cursor position
+ charactersInfrontOfCursor -= d.text.size();
+ cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, d.text.size());
+ break;
+ }
+ }
+ cursor.endEditBlock();
+ cursor.setPosition(newCursorPos);
+ textEditor->setTextCursor(cursor);
+
+ // Adjust vertical scrollbar
+ absoluteVerticalCursorOffset = textEditor->cursorRect().y() - absoluteVerticalCursorOffset;
+ const double fontHeight = QFontMetrics(textEditor->document()->defaultFont()).height();
+ textEditor->verticalScrollBar()->setValue(textEditor->verticalScrollBar()->value()
+ + absoluteVerticalCursorOffset / fontHeight);
+ // Restore folded blocks
+ const QTextDocument *doc = textEditor->document();
+ const int total = foldedBlocks.size();
+ for (int i = 0; i < total; ++i) {
+ QTextBlock block = doc->findBlockByNumber(qMax(0, foldedBlocks.at(i)));
+ if (block.isValid())
+ TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(block, false);
+ }
+
+ textEditor->document()->setModified(true);
+}
+
+void BeautifierPlugin::showError(const QString &error)
+{
+ Core::MessageManager::write(tr("ERROR in Beautifier: %1").arg(error.trimmed()));
+}
+
+} // namespace Internal
+} // namespace Beautifier
+
+Q_EXPORT_PLUGIN(Beautifier::Internal::BeautifierPlugin)
diff --git a/src/plugins/beautifier/beautifierplugin.h b/src/plugins/beautifier/beautifierplugin.h
new file mode 100644
index 0000000000..2e4910e042
--- /dev/null
+++ b/src/plugins/beautifier/beautifierplugin.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_BEAUTIFIER_H
+#define BEAUTIFIER_BEAUTIFIER_H
+
+#include <extensionsystem/iplugin.h>
+#include <utils/qtcoverride.h>
+
+namespace Core { class IEditor; }
+
+namespace Beautifier {
+namespace Internal {
+
+class BeautifierAbstractTool;
+
+class BeautifierPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Beautifier.json")
+
+public:
+ BeautifierPlugin();
+ ~BeautifierPlugin();
+ bool initialize(const QStringList &arguments, QString *errorString) QTC_OVERRIDE;
+ void extensionsInitialized() QTC_OVERRIDE;
+ ShutdownFlag aboutToShutdown() QTC_OVERRIDE;
+
+ static QString format(const QString &text, QStringList command, const QString &fileName);
+ static void formatCurrentFile(QStringList command);
+ static void showError(const QString &error);
+
+private slots:
+ void updateActions(Core::IEditor *editor = 0);
+
+private:
+ QList<BeautifierAbstractTool *> m_tools;
+};
+
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_BEAUTIFIER_H
+
diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp
new file mode 100644
index 0000000000..5c6f929cbb
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformat.cpp
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "clangformat.h"
+
+#include "clangformatconstants.h"
+#include "clangformatoptionspage.h"
+#include "clangformatsettings.h"
+
+#include "../beautifierconstants.h"
+#include "../beautifierplugin.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <cppeditor/cppeditorconstants.h>
+#include <texteditor/basetexteditor.h>
+
+#include <QAction>
+#include <QMenu>
+
+namespace Beautifier {
+namespace Internal {
+namespace ClangFormat {
+
+ClangFormat::ClangFormat(QObject *parent) :
+ BeautifierAbstractTool(parent),
+ m_settings(new ClangFormatSettings)
+{
+}
+
+ClangFormat::~ClangFormat()
+{
+ delete m_settings;
+}
+
+bool ClangFormat::initialize()
+{
+ Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::ClangFormat::MENU_ID);
+ menu->menu()->setTitle(QLatin1String("ClangFormat"));
+
+ m_formatFile = new QAction(tr("Format Current File"), this);
+ Core::Command *cmd
+ = Core::ActionManager::registerAction(m_formatFile,
+ Constants::ClangFormat::ACTION_FORMATFILE,
+ Core::Context(Core::Constants::C_GLOBAL));
+ menu->addAction(cmd);
+ connect(m_formatFile, SIGNAL(triggered()), this, SLOT(formatFile()));
+
+ m_formatRange = new QAction(tr("Format Selected Text"), this);
+ cmd = Core::ActionManager::registerAction(m_formatRange,
+ Constants::ClangFormat::ACTION_FORMATSELECTED,
+ Core::Context(Core::Constants::C_GLOBAL));
+ menu->addAction(cmd);
+ connect(m_formatRange, SIGNAL(triggered()), this, SLOT(formatSelectedText()));
+
+ Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
+
+ return true;
+}
+
+void ClangFormat::updateActions(Core::IEditor *editor)
+{
+ const bool enabled = (editor && editor->id() == CppEditor::Constants::CPPEDITOR_ID);
+ m_formatFile->setEnabled(enabled);
+ m_formatRange->setEnabled(enabled);
+}
+
+QList<QObject *> ClangFormat::autoReleaseObjects()
+{
+ ClangFormatOptionsPage *optionsPage = new ClangFormatOptionsPage(m_settings, this);
+ return QList<QObject *>() << optionsPage;
+}
+
+void ClangFormat::formatFile()
+{
+ BeautifierPlugin::formatCurrentFile(command());
+}
+
+void ClangFormat::formatSelectedText()
+{
+ TextEditor::BaseTextEditor *editor
+ = qobject_cast<TextEditor::BaseTextEditor *>(Core::EditorManager::currentEditor());
+ if (!editor)
+ return;
+
+ QTextCursor tc = editor->editorWidget()->textCursor();
+ if (tc.hasSelection()) {
+ const int offset = tc.selectionStart();
+ const int length = tc.selectionEnd() - offset;
+ BeautifierPlugin::formatCurrentFile(command(offset, length));
+ } else if (m_settings->formatEntireFileFallback()) {
+ formatFile();
+ }
+}
+
+QStringList ClangFormat::command(int offset, int length) const
+{
+ QStringList command;
+ command << m_settings->command();
+ command << QLatin1String("-i");
+ if (m_settings->usePredefinedStyle()) {
+ command << QLatin1String("-style=") + m_settings->predefinedStyle();
+ } else {
+ command << QLatin1String("-style={") + m_settings->style(
+ m_settings->customStyle()).remove(QLatin1Char('\n')) + QLatin1String("}");
+ }
+ if (offset != -1) {
+ command << QLatin1String("-offset=") + QString::number(offset);
+ command << QLatin1String("-length=") + QString::number(length);
+ }
+ command << QLatin1String("%file");
+
+ return command;
+}
+
+} // namespace ClangFormat
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/clangformat/clangformat.h b/src/plugins/beautifier/clangformat/clangformat.h
new file mode 100644
index 0000000000..6424f0aa38
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformat.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CLANGFORMAT_H
+#define BEAUTIFIER_CLANGFORMAT_H
+
+#include "../beautifierabstracttool.h"
+
+#include <utils/qtcoverride.h>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+namespace Beautifier {
+namespace Internal {
+namespace ClangFormat {
+
+class ClangFormatSettings;
+
+class ClangFormat : public BeautifierAbstractTool
+{
+ Q_OBJECT
+
+public:
+ explicit ClangFormat(QObject *parent = 0);
+ virtual ~ClangFormat();
+ bool initialize() QTC_OVERRIDE;
+ void updateActions(Core::IEditor *editor) QTC_OVERRIDE;
+ QList<QObject *> autoReleaseObjects() QTC_OVERRIDE;
+
+private slots:
+ void formatFile();
+ void formatSelectedText();
+
+private:
+ QAction *m_formatFile;
+ QAction *m_formatRange;
+ ClangFormatSettings *m_settings;
+ QStringList command(int offset = -1, int length = -1) const;
+};
+
+} // namespace ClangFormat
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CLANGFORMAT_H
diff --git a/src/plugins/beautifier/clangformat/clangformatconstants.h b/src/plugins/beautifier/clangformat/clangformatconstants.h
new file mode 100644
index 0000000000..844da37b78
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformatconstants.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CLANGFORMATCONSTANTS_H
+#define BEAUTIFIER_CLANGFORMATCONSTANTS_H
+
+namespace Beautifier {
+namespace Constants {
+namespace ClangFormat {
+
+const char ACTION_FORMATFILE[] = "ClangFormat.FormatFile";
+const char ACTION_FORMATSELECTED[] = "ClangFormat.FormatSelectedText";
+const char MENU_ID[] = "ClangFormat.Menu";
+const char OPTION_ID[] = "ClangFormat";
+const char SETTINGS_NAME[] = "clangformat";
+
+} // namespace ClangFormat
+} // namespace Constants
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CLANGFORMATCONSTANTS_H
diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp b/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp
new file mode 100644
index 0000000000..b8ea14477b
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.cpp
@@ -0,0 +1,150 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "clangformatoptionspage.h"
+#include "ui_clangformatoptionspage.h"
+
+#include "clangformatconstants.h"
+#include "clangformatsettings.h"
+
+#include "../beautifierconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QTextStream>
+
+namespace Beautifier {
+namespace Internal {
+namespace ClangFormat {
+
+ClangFormatOptionsPageWidget::ClangFormatOptionsPageWidget(ClangFormatSettings *settings,
+ QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::ClangFormatOptionsPage)
+ , m_settings(settings)
+{
+ ui->setupUi(this);
+ ui->options->setEnabled(false);
+ ui->predefinedStyle->addItems(m_settings->predefinedStyles());
+ ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ ui->command->setPromptDialogTitle(tr("ClangFormat Command"));
+ connect(ui->command, SIGNAL(validChanged(bool)), ui->options, SLOT(setEnabled(bool)));
+ ui->configurations->setSettings(m_settings);
+}
+
+ClangFormatOptionsPageWidget::~ClangFormatOptionsPageWidget()
+{
+ delete ui;
+}
+
+QString ClangFormatOptionsPageWidget::searchKeywords() const
+{
+ QString keywords;
+ const QLatin1Char sep(' ');
+ QTextStream(&keywords) << sep << ui->configuration->title()
+ << sep << ui->commandLabel->text()
+ << sep << ui->options->title()
+ << sep << ui->usePredefinedStyle->text()
+ << sep << ui->useCustomizedStyle->text()
+ << sep << ui->formatEntireFileFallback->text();
+ keywords.remove(QLatin1Char('&'));
+ return keywords;
+}
+
+void ClangFormatOptionsPageWidget::restore()
+{
+ ui->command->setPath(m_settings->command());
+ ui->predefinedStyle->setCurrentText(m_settings->predefinedStyle());
+ ui->formatEntireFileFallback->setChecked(m_settings->formatEntireFileFallback());
+ ui->configurations->setSettings(m_settings);
+ ui->configurations->setCurrentConfiguration(m_settings->customStyle());
+
+ if (m_settings->usePredefinedStyle())
+ ui->usePredefinedStyle->setChecked(true);
+ else
+ ui->useCustomizedStyle->setChecked(true);
+}
+
+void ClangFormatOptionsPageWidget::apply()
+{
+ m_settings->setCommand(ui->command->path());
+ m_settings->setUsePredefinedStyle(ui->usePredefinedStyle->isChecked());
+ m_settings->setPredefinedStyle(ui->predefinedStyle->currentText());
+ m_settings->setCustomStyle(ui->configurations->currentConfiguration());
+ m_settings->setFormatEntireFileFallback(ui->formatEntireFileFallback->isChecked());
+ m_settings->save();
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+ClangFormatOptionsPage::ClangFormatOptionsPage(ClangFormatSettings *settings, QObject *parent) :
+ IOptionsPage(parent),
+ m_widget(0),
+ m_settings(settings),
+ m_searchKeywords()
+{
+ setId(Constants::ClangFormat::OPTION_ID);
+ setDisplayName(tr("ClangFormat"));
+ setCategory(Constants::OPTION_CATEGORY);
+ setDisplayCategory(QCoreApplication::translate("Beautifier", Constants::OPTION_TR_CATEGORY));
+ setCategoryIcon(QLatin1String(Constants::OPTION_CATEGORY_ICON));
+}
+
+QWidget *ClangFormatOptionsPage::widget()
+{
+ m_settings->read();
+
+ if (!m_widget) {
+ m_widget = new ClangFormatOptionsPageWidget(m_settings);
+ if (m_searchKeywords.isEmpty())
+ m_searchKeywords = m_widget->searchKeywords();
+ }
+ m_widget->restore();
+
+ return m_widget;
+}
+
+void ClangFormatOptionsPage::apply()
+{
+ if (m_widget)
+ m_widget->apply();
+}
+
+void ClangFormatOptionsPage::finish()
+{
+}
+
+bool ClangFormatOptionsPage::matches(const QString &searchKeyWord) const
+{
+ return m_searchKeywords.contains(searchKeyWord, Qt::CaseInsensitive);
+}
+
+} // namespace ClangFormat
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.h b/src/plugins/beautifier/clangformat/clangformatoptionspage.h
new file mode 100644
index 0000000000..777037a14a
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.h
@@ -0,0 +1,84 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CLANGFORMATOPTIONSPAGE_H
+#define BEAUTIFIER_CLANGFORMATOPTIONSPAGE_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+#include <utils/qtcoverride.h>
+
+#include <QPointer>
+#include <QWidget>
+
+namespace Beautifier {
+namespace Internal {
+namespace ClangFormat {
+
+class ClangFormatSettings;
+
+namespace Ui { class ClangFormatOptionsPage; }
+
+class ClangFormatOptionsPageWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ClangFormatOptionsPageWidget(ClangFormatSettings *settings, QWidget *parent = 0);
+ virtual ~ClangFormatOptionsPageWidget();
+ QString searchKeywords() const;
+ void restore();
+ void apply();
+
+private:
+ Ui::ClangFormatOptionsPage *ui;
+ ClangFormatSettings *m_settings;
+};
+
+class ClangFormatOptionsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ explicit ClangFormatOptionsPage(ClangFormatSettings *settings, QObject *parent = 0);
+ QWidget *widget() QTC_OVERRIDE;
+ void apply() QTC_OVERRIDE;
+ void finish() QTC_OVERRIDE;
+ bool matches(const QString &searchKeywords) const QTC_OVERRIDE;
+
+private:
+ QPointer<ClangFormatOptionsPageWidget> m_widget;
+ ClangFormatSettings *m_settings;
+ QString m_searchKeywords;
+};
+
+} // namespace ClangFormat
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CLANGFORMATOPTIONSPAGE_H
diff --git a/src/plugins/beautifier/clangformat/clangformatoptionspage.ui b/src/plugins/beautifier/clangformat/clangformatoptionspage.ui
new file mode 100644
index 0000000000..7a06b29e30
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformatoptionspage.ui
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Beautifier::Internal::ClangFormat::ClangFormatOptionsPage</class>
+ <widget class="QWidget" name="Beautifier::Internal::ClangFormat::ClangFormatOptionsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>817</width>
+ <height>631</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="configuration">
+ <property name="title">
+ <string>Configuration</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="commandLabel">
+ <property name="text">
+ <string>ClangFormat command:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Utils::PathChooser" name="command" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="options">
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="usePredefinedStyle">
+ <property name="text">
+ <string>Use Predefined Style:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="predefinedStyle"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QRadioButton" name="useCustomizedStyle">
+ <property name="text">
+ <string>Use Customized Style:</string>
+ </property>
+ <property name="autoExclusive">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="formatEntireFileFallback">
+ <property name="text">
+ <string>Format entire file if no text was selected. (For action &quot;Format Selected Text&quot;)</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Beautifier::Internal::ConfigurationPanel</class>
+ <extends>QWidget</extends>
+ <header location="global">beautifier/configurationpanel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>usePredefinedStyle</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>predefinedStyle</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>67</x>
+ <y>108</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>240</x>
+ <y>113</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.cpp b/src/plugins/beautifier/clangformat/clangformatsettings.cpp
new file mode 100644
index 0000000000..795411a5b2
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformatsettings.cpp
@@ -0,0 +1,236 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "clangformatsettings.h"
+
+#include "clangformatconstants.h"
+
+#include "../beautifierconstants.h"
+
+#include <QDateTime>
+#include <QXmlStreamWriter>
+
+#include <coreplugin/icore.h>
+
+namespace Beautifier {
+namespace Internal {
+namespace ClangFormat {
+
+namespace {
+const char kUsePredefinedStyle[] = "usePredefinedStyle";
+const char kPredefinedStyle[] = "predefinedStyle";
+const char kCustomStyle[] = "customStyle";
+const char kFormatEntireFileFallback[] = "formatEntireFileFallback";
+}
+
+ClangFormatSettings::ClangFormatSettings() :
+ AbstractSettings(QLatin1String(Constants::ClangFormat::SETTINGS_NAME),
+ QLatin1String(".clang-format"))
+
+{
+ setCommand(QLatin1String("clang-format"));
+ m_settings.insert(QLatin1String(kUsePredefinedStyle), QVariant(true));
+ m_settings.insert(QLatin1String(kPredefinedStyle), QLatin1String("LLVM"));
+ m_settings.insert(QLatin1String(kCustomStyle), QVariant());
+ m_settings.insert(QLatin1String(kFormatEntireFileFallback), QVariant(true));
+ read();
+}
+
+QString ClangFormatSettings::documentationFilePath() const
+{
+ return Core::ICore::userResourcePath() + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::SETTINGS_DIRNAME) + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::DOCUMENTATION_DIRNAME) + QLatin1Char('/')
+ + QLatin1String(Constants::ClangFormat::SETTINGS_NAME) + QLatin1String(".xml");
+}
+
+void ClangFormatSettings::createDocumentationFile() const
+{
+ QFile file(documentationFilePath());
+ const QFileInfo fi(file);
+ if (!fi.exists())
+ fi.dir().mkpath(fi.absolutePath());
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
+ return;
+
+ QXmlStreamWriter stream(&file);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument(QLatin1String("1.0"), true);
+ stream.writeComment(QLatin1String("Created ")
+ + QDateTime::currentDateTime().toString(Qt::ISODate));
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLROOT));
+
+ const QStringList lines = QStringList()
+ << QLatin1String("BasedOnStyle {string: LLVM, Google, Chromium, Mozilla, WebKit}")
+ << QLatin1String("AccessModifierOffset {int}")
+ << QLatin1String("AlignEscapedNewlinesLeft {bool}")
+ << QLatin1String("AlignTrailingComments {bool}")
+ << QLatin1String("AllowAllParametersOfDeclarationOnNextLine {bool}")
+ << QLatin1String("AllowShortFunctionsOnASingleLine {bool}")
+ << QLatin1String("AllowShortIfStatementsOnASingleLine {bool}")
+ << QLatin1String("AllowShortLoopsOnASingleLine {bool}")
+ << QLatin1String("AlwaysBreakBeforeMultilineStrings {bool}")
+ << QLatin1String("AlwaysBreakTemplateDeclarations {bool}")
+ << QLatin1String("BinPackParameters {bool}")
+ << QLatin1String("BreakBeforeBinaryOperators {bool}")
+ << QLatin1String("BreakBeforeBraces {BraceBreakingStyle: BS_Attach, BS_Linux, BS_Stroustrup, BS_Allman, BS_GNU}")
+ << QLatin1String("BreakBeforeTernaryOperators {bool}")
+ << QLatin1String("BreakConstructorInitializersBeforeComma {bool}")
+ << QLatin1String("ColumnLimit {unsigned}")
+ << QLatin1String("CommentPragmas {string}")
+ << QLatin1String("ConstructorInitializerAllOnOneLineOrOnePerLine {bool}")
+ << QLatin1String("ConstructorInitializerIndentWidth {unsigned}")
+ << QLatin1String("ContinuationIndentWidth {unsigned}")
+ << QLatin1String("Cpp11BracedListStyle {bool}")
+ << QLatin1String("IndentCaseLabels {bool}")
+ << QLatin1String("IndentFunctionDeclarationAfterType {bool}")
+ << QLatin1String("IndentWidth {unsigned}")
+ << QLatin1String("Language {LanguageKind: LK_None, LK_Cpp, LK_JavaScript, LK_Proto}")
+ << QLatin1String("MaxEmptyLinesToKeep {unsigned}")
+ << QLatin1String("NamespaceIndentation {NamespaceIndentationKind: NI_None, NI_Inner, NI_All}")
+ << QLatin1String("ObjCSpaceAfterProperty {bool}")
+ << QLatin1String("ObjCSpaceBeforeProtocolList {bool}")
+ << QLatin1String("PenaltyBreakBeforeFirstCallParameter {unsigned}")
+ << QLatin1String("PenaltyBreakComment {unsigned}")
+ << QLatin1String("PenaltyBreakFirstLessLess {unsigned}")
+ << QLatin1String("PenaltyBreakString {unsigned}")
+ << QLatin1String("PenaltyExcessCharacter {unsigned}")
+ << QLatin1String("PenaltyReturnTypeOnItsOwnLine {unsigned}")
+ << QLatin1String("PointerBindsToType {bool}")
+ << QLatin1String("SpaceBeforeAssignmentOperators {bool}")
+ << QLatin1String("SpaceBeforeParens {SpaceBeforeParensOptions: SBPO_Never, SBPO_ControlStatements, SBPO_Always}")
+ << QLatin1String("SpaceInEmptyParentheses {bool}")
+ << QLatin1String("SpacesBeforeTrailingComments {unsigned}")
+ << QLatin1String("SpacesInAngles {bool}")
+ << QLatin1String("SpacesInCStyleCastParentheses {bool}")
+ << QLatin1String("SpacesInContainerLiterals {bool}")
+ << QLatin1String("SpacesInParentheses {bool}")
+ << QLatin1String("Standard {LanguageStandard: LS_Cpp03, LS_Cpp11, LS_Auto}")
+ << QLatin1String("TabWidth {unsigned}")
+ << QLatin1String("UseTab {UseTabStyle: UT_Never, UT_ForIndentation, UT_Always}");
+
+ const int totalLines = lines.count();
+ for (int i = 0; i < totalLines; ++i) {
+ const QString& line = lines.at(i);
+ const int firstSpace = line.indexOf(QLatin1Char(' '));
+ const QString keyword = line.left(firstSpace);
+ const QString options = line.right(line.size() - firstSpace).trimmed();
+ const QString text = QLatin1String("<p><span class=\"option\">") + keyword
+ + QLatin1String("</span> <span class=\"param\">") + options
+ + QLatin1String("</span></p><p>") + tr("Yet no description available.")
+ + QLatin1String("</p>");
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLENTRY));
+ stream.writeTextElement(QLatin1String(Constants::DOCUMENTATION_XMLKEY), keyword);
+ stream.writeTextElement(QLatin1String(Constants::DOCUMENTATION_XMLDOC), text);
+ stream.writeEndElement();
+ }
+
+ stream.writeEndElement();
+ stream.writeEndDocument();
+}
+
+QStringList ClangFormatSettings::completerWords()
+{
+ QStringList words;
+ words << QLatin1String("LLVM")
+ << QLatin1String("Google")
+ << QLatin1String("Chromium")
+ << QLatin1String("Mozilla")
+ << QLatin1String("WebKit")
+ << QLatin1String("BS_Attach")
+ << QLatin1String("BS_Linux")
+ << QLatin1String("BS_Stroustrup")
+ << QLatin1String("BS_Allman")
+ << QLatin1String("NI_None")
+ << QLatin1String("NI_Inner")
+ << QLatin1String("NI_All")
+ << QLatin1String("LS_Cpp03")
+ << QLatin1String("LS_Cpp11")
+ << QLatin1String("LS_Auto")
+ << QLatin1String("UT_Never")
+ << QLatin1String("UT_ForIndentation")
+ << QLatin1String("UT_Always");
+ return words;
+}
+
+bool ClangFormatSettings::usePredefinedStyle() const
+{
+ return m_settings.value(QLatin1String(kUsePredefinedStyle)).toBool();
+}
+
+void ClangFormatSettings::setUsePredefinedStyle(bool usePredefinedStyle)
+{
+ m_settings.insert(QLatin1String(kUsePredefinedStyle), QVariant(usePredefinedStyle));
+}
+
+QString ClangFormatSettings::predefinedStyle() const
+{
+ return m_settings.value(QLatin1String(kPredefinedStyle)).toString();
+}
+
+void ClangFormatSettings::setPredefinedStyle(const QString &predefinedStyle)
+{
+ const QStringList test = predefinedStyles();
+ if (test.contains(predefinedStyle))
+ m_settings.insert(QLatin1String(kPredefinedStyle), QVariant(predefinedStyle));
+}
+
+QString ClangFormatSettings::customStyle() const
+{
+ return m_settings.value(QLatin1String(kCustomStyle)).toString();
+}
+
+void ClangFormatSettings::setCustomStyle(const QString &customStyle)
+{
+ m_settings.insert(QLatin1String(kCustomStyle), QVariant(customStyle));
+}
+
+bool ClangFormatSettings::formatEntireFileFallback() const
+{
+ return m_settings.value(QLatin1String(kFormatEntireFileFallback)).toBool();
+}
+
+void ClangFormatSettings::setFormatEntireFileFallback(bool formatEntireFileFallback)
+{
+ m_settings.insert(QLatin1String(kFormatEntireFileFallback), QVariant(formatEntireFileFallback));
+}
+
+QStringList ClangFormatSettings::predefinedStyles() const
+{
+ return QStringList() << QLatin1String("LLVM")
+ << QLatin1String("Google")
+ << QLatin1String("Chromium")
+ << QLatin1String("Mozilla")
+ << QLatin1String("WebKit")
+ << QLatin1String("File");
+}
+
+} // namespace ClangFormat
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/clangformat/clangformatsettings.h b/src/plugins/beautifier/clangformat/clangformatsettings.h
new file mode 100644
index 0000000000..39931d131c
--- /dev/null
+++ b/src/plugins/beautifier/clangformat/clangformatsettings.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CLANGFORMATSETTINGS_H
+#define BEAUTIFIER_CLANGFORMATSETTINGS_H
+
+#include "../abstractsettings.h"
+
+#include <utils/qtcoverride.h>
+
+namespace Beautifier {
+namespace Internal {
+namespace ClangFormat {
+
+class ClangFormatSettings : public AbstractSettings
+{
+ Q_DECLARE_TR_FUNCTIONS(ClangFormatSettings)
+
+public:
+ explicit ClangFormatSettings();
+
+ QString documentationFilePath() const QTC_OVERRIDE;
+ void createDocumentationFile() const QTC_OVERRIDE;
+ QStringList completerWords() QTC_OVERRIDE;
+
+ bool usePredefinedStyle() const;
+ void setUsePredefinedStyle(bool usePredefinedStyle);
+
+ QString predefinedStyle() const;
+ void setPredefinedStyle(const QString &predefinedStyle);
+
+ QString customStyle() const;
+ void setCustomStyle(const QString &customStyle);
+
+ bool formatEntireFileFallback() const;
+ void setFormatEntireFileFallback(bool formatEntireFileFallback);
+
+ QStringList predefinedStyles() const;
+};
+
+} // namespace ClangFormat
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CLANGFORMATSETTINGS_H
diff --git a/src/plugins/beautifier/configurationdialog.cpp b/src/plugins/beautifier/configurationdialog.cpp
new file mode 100644
index 0000000000..e0e9e538f6
--- /dev/null
+++ b/src/plugins/beautifier/configurationdialog.cpp
@@ -0,0 +1,155 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "configurationdialog.h"
+#include "ui_configurationdialog.h"
+
+#include "abstractsettings.h"
+
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
+
+#include <QPushButton>
+#include <QRegExpValidator>
+
+namespace Beautifier {
+namespace Internal {
+
+ConfigurationDialog::ConfigurationDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::ConfigurationDialog),
+ m_settings(0)
+{
+ ui->setupUi(this);
+
+ // Filter out characters which are not allowed in a file name
+ QRegExpValidator *fileNameValidator = new QRegExpValidator(ui->name);
+ fileNameValidator->setRegExp(QRegExp(QLatin1String("^[^\\/\\\\\\?\\>\\<\\*\\%\\:\\\"\\']*$")));
+ ui->name->setValidator(fileNameValidator);
+
+ updateDocumentation();
+ connect(ui->name, SIGNAL(textChanged(QString)), this, SLOT(updateOkButton()));
+ updateOkButton(); // force initial test.
+ connect(ui->editor, SIGNAL(documentationChanged(QString,QString)),
+ this, SLOT(updateDocumentation(QString,QString)));
+
+ // Set palette and font according to settings
+ const TextEditor::FontSettings fs = TextEditor::TextEditorSettings::instance()->fontSettings();
+ const QTextCharFormat tf = fs.toTextCharFormat(TextEditor::C_TEXT);
+ const QTextCharFormat selectionFormat = fs.toTextCharFormat(TextEditor::C_SELECTION);
+
+ QPalette pal;
+ pal.setColor(QPalette::Base, tf.background().color());
+ pal.setColor(QPalette::Text, tf.foreground().color());
+ pal.setColor(QPalette::Foreground, tf.foreground().color());
+ if (selectionFormat.background().style() != Qt::NoBrush)
+ pal.setColor(QPalette::Highlight, selectionFormat.background().color());
+ pal.setBrush(QPalette::HighlightedText, selectionFormat.foreground());
+ ui->documentation->setPalette(pal);
+ ui->editor->setPalette(pal);
+
+ ui->documentation->setFont(tf.font());
+ ui->editor->setFont(tf.font());
+
+ // Set style sheet for documentation browser
+ const QTextCharFormat tfOption = fs.toTextCharFormat(TextEditor::C_FIELD);
+ const QTextCharFormat tfParam = fs.toTextCharFormat(TextEditor::C_STRING);
+
+ const QString css = QString::fromLatin1("span.param {color: %1; background-color: %2;} "
+ "span.option {color: %3; background-color: %4;} "
+ "p { text-align: justify; } ")
+ .arg(tfParam.foreground().color().name())
+ .arg(tfParam.background().style() == Qt::NoBrush
+ ? QString() : tfParam.background().color().name())
+ .arg(tfOption.foreground().color().name())
+ .arg(tfOption.background().style() == Qt::NoBrush
+ ? QString() : tfOption.background().color().name())
+ ;
+ ui->documentation->document()->setDefaultStyleSheet(css);
+}
+
+ConfigurationDialog::~ConfigurationDialog()
+{
+ delete ui;
+}
+
+void ConfigurationDialog::setSettings(AbstractSettings *settings)
+{
+ m_settings = settings;
+ ui->editor->setSettings(m_settings);
+}
+
+void ConfigurationDialog::clear()
+{
+ ui->name->clear();
+ ui->editor->clear();
+ m_currentKey.clear();
+ updateOkButton();
+}
+
+QString ConfigurationDialog::key() const
+{
+ return ui->name->text().simplified();
+}
+
+void ConfigurationDialog::setKey(const QString &key)
+{
+ m_currentKey = key;
+ ui->name->setText(m_currentKey);
+ if (m_settings)
+ ui->editor->setPlainText(m_settings->style(m_currentKey));
+ else
+ ui->editor->clear();
+}
+
+QString ConfigurationDialog::value() const
+{
+ return ui->editor->toPlainText();
+}
+
+void ConfigurationDialog::updateOkButton()
+{
+ const QString key = ui->name->text().simplified();
+ bool exists = false;
+ if (m_settings && key != m_currentKey)
+ exists = m_settings->styleExists(key);
+ ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!(key.isEmpty() || exists));
+}
+
+void ConfigurationDialog::updateDocumentation(const QString &word, const QString &docu)
+{
+ if (word.isEmpty())
+ ui->documentationHeader->setText(tr("Documentation"));
+ else
+ ui->documentationHeader->setText(tr("Documentation for '%1'").arg(word));
+ ui->documentation->setHtml(docu);
+}
+
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/configurationdialog.h b/src/plugins/beautifier/configurationdialog.h
new file mode 100644
index 0000000000..6a924689f5
--- /dev/null
+++ b/src/plugins/beautifier/configurationdialog.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CONFIGURATIONDIALOG_H
+#define BEAUTIFIER_CONFIGURATIONDIALOG_H
+
+#include <QDialog>
+#include <QString>
+
+namespace Beautifier {
+namespace Internal {
+
+class AbstractSettings;
+
+namespace Ui { class ConfigurationDialog; }
+
+class ConfigurationDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigurationDialog(QWidget *parent = 0);
+ ~ConfigurationDialog();
+ void setSettings(AbstractSettings *settings);
+
+ void clear();
+ QString key() const;
+ void setKey(const QString &key);
+ QString value() const;
+
+private slots:
+ void updateOkButton();
+ void updateDocumentation(const QString &word = QString(), const QString &docu = QString());
+
+private:
+ Ui::ConfigurationDialog *ui;
+ AbstractSettings *m_settings;
+ QString m_currentKey;
+};
+
+
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CONFIGURATIONDIALOG_H
diff --git a/src/plugins/beautifier/configurationdialog.ui b/src/plugins/beautifier/configurationdialog.ui
new file mode 100644
index 0000000000..58df158f83
--- /dev/null
+++ b/src/plugins/beautifier/configurationdialog.ui
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Beautifier::Internal::ConfigurationDialog</class>
+ <widget class="QDialog" name="Beautifier::Internal::ConfigurationDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>640</width>
+ <height>512</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Name</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="name"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Value</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QSplitter" name="splitter">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="childrenCollapsible">
+ <bool>false</bool>
+ </property>
+ <widget class="Beautifier::Internal::ConfigurationEditor" name="editor"/>
+ <widget class="QWidget" name="layoutWidget">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QLabel" name="documentationHeader">
+ <property name="text">
+ <string>Documentation</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="documentation">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Beautifier::Internal::ConfigurationEditor</class>
+ <extends>QPlainTextEdit</extends>
+ <header>configurationeditor.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Beautifier::Internal::ConfigurationDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Beautifier::Internal::ConfigurationDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/plugins/beautifier/configurationeditor.cpp b/src/plugins/beautifier/configurationeditor.cpp
new file mode 100644
index 0000000000..0fdbeaa388
--- /dev/null
+++ b/src/plugins/beautifier/configurationeditor.cpp
@@ -0,0 +1,267 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "configurationeditor.h"
+
+#include "abstractsettings.h"
+
+#include <texteditor/fontsettings.h>
+#include <texteditor/texteditorsettings.h>
+#include <utils/qtcassert.h>
+
+#include <QAbstractItemView>
+#include <QCompleter>
+#include <QScrollBar>
+#include <QStringListModel>
+
+namespace Beautifier {
+namespace Internal {
+
+ConfigurationSyntaxHighlighter::ConfigurationSyntaxHighlighter(QTextDocument *parent) :
+ QSyntaxHighlighter(parent)
+{
+ const TextEditor::FontSettings fs = TextEditor::TextEditorSettings::instance()->fontSettings();
+ m_formatKeyword = fs.toTextCharFormat(TextEditor::C_FIELD);
+ m_formatComment = fs.toTextCharFormat(TextEditor::C_COMMENT);
+
+ m_expressionComment.setPattern(QLatin1String("#[^\\n]*"));
+ m_expressionComment.setMinimal(false);
+}
+
+void ConfigurationSyntaxHighlighter::setKeywords(const QStringList &keywords)
+{
+ if (keywords.isEmpty())
+ return;
+
+ QStringList pattern;
+ for (int i = 0, total = keywords.count(); i < total; ++i)
+ pattern << QRegExp::escape(keywords.at(i));
+
+ m_expressionKeyword.setPattern(QLatin1String("(?:\\s|^)(") + pattern.join(QLatin1Char('|'))
+ + QLatin1String(")(?=\\s|\\:|\\=|\\,|$)"));
+}
+
+void ConfigurationSyntaxHighlighter::setCommentExpression(const QRegExp &rx)
+{
+ m_expressionComment = rx;
+}
+
+void ConfigurationSyntaxHighlighter::highlightBlock(const QString &text)
+{
+ int pos = 0;
+ if (!m_expressionKeyword.isEmpty()) {
+ while ((pos = m_expressionKeyword.indexIn(text, pos)) != -1) {
+ const int length = m_expressionKeyword.matchedLength();
+ setFormat(pos, length, m_formatKeyword);
+ pos += length;
+ }
+ }
+
+ if (!m_expressionComment.isEmpty()) {
+ pos = 0;
+ while ((pos = m_expressionComment.indexIn(text, pos)) != -1) {
+ const int length = m_expressionComment.matchedLength();
+ setFormat(pos, length, m_formatComment);
+ pos += length;
+ }
+ }
+}
+
+ConfigurationEditor::ConfigurationEditor(QWidget *parent)
+ : QPlainTextEdit(parent)
+ , m_settings(0)
+ , m_completer(new QCompleter(this))
+ , m_model(new QStringListModel(QStringList(), m_completer))
+ , m_highlighter(new ConfigurationSyntaxHighlighter(document()))
+{
+ m_completer->setModel(m_model);
+ m_completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ m_completer->setWrapAround(false);
+ m_completer->setWidget(this);
+ m_completer->setCompletionMode(QCompleter::PopupCompletion);
+ m_completer->setCaseSensitivity(Qt::CaseInsensitive);
+ m_completer->popup()->installEventFilter(this);
+
+ connect(m_completer, SIGNAL(activated(QString)), this, SLOT(insertCompleterText(QString)));
+ connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateDocumentation()));
+}
+
+void ConfigurationEditor::setSettings(AbstractSettings *settings)
+{
+ QTC_CHECK(settings);
+ m_settings = settings;
+
+ QStringList keywords = m_settings->options();
+ m_highlighter->setKeywords(keywords);
+ keywords << m_settings->completerWords();
+ keywords.sort(Qt::CaseInsensitive);
+ m_model->setStringList(keywords);
+}
+
+void ConfigurationEditor::setCommentExpression(const QRegExp &rx)
+{
+ m_highlighter->setCommentExpression(rx);
+}
+
+// Workaround for handling "ESC" right when popup is shown.
+bool ConfigurationEditor::eventFilter(QObject *object, QEvent *event)
+{
+ if (event->type() == QEvent::ShortcutOverride) {
+ QKeyEvent *key = static_cast<QKeyEvent *>(event);
+ if (key->key() == Qt::Key_Escape) {
+ event->accept();
+ m_completer->popup()->hide();
+ return true;
+ }
+ }
+ return QObject::eventFilter(object, event);
+}
+
+void ConfigurationEditor::keyPressEvent(QKeyEvent *event)
+{
+ const int key = event->key();
+
+ if (key == Qt::Key_Escape) {
+ event->ignore();
+ return;
+ }
+
+ if (m_completer->popup()->isVisible()) {
+ switch (key) {
+ case Qt::Key_Backtab:
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_Tab:
+ event->ignore();
+ return;
+ default:
+ break;
+ }
+ }
+
+ const bool isShortcut = ((event->modifiers() & Qt::ControlModifier) && key == Qt::Key_Space);
+ if (!isShortcut)
+ QPlainTextEdit::keyPressEvent(event);
+
+ const int cursorPosition = textCursor().position();
+ QTextCursor cursor = cursorForTextUnderCursor();
+ const QString prefix = cursor.selectedText();
+
+ if (!isShortcut && (prefix.length() < 2 || cursorPosition != cursor.position())) {
+ m_completer->popup()->hide();
+ return;
+ }
+
+ if (prefix != m_completer->completionPrefix()) {
+ m_completer->setCompletionPrefix(prefix);
+ m_completer->popup()->setCurrentIndex(m_completer->completionModel()->index(0, 0));
+ }
+
+ if (m_completer->completionCount() == 1 && prefix == m_completer->currentCompletion()) {
+ m_completer->popup()->hide();
+ return;
+ }
+
+ QRect popupRect = cursorRect();
+ popupRect.setWidth(m_completer->popup()->sizeHintForColumn(0)
+ + m_completer->popup()->verticalScrollBar()->sizeHint().width());
+ m_completer->complete(popupRect);
+}
+
+// Hack because '-' and '=' are treated as End/StartOfWord
+QTextCursor ConfigurationEditor::cursorForTextUnderCursor(QTextCursor tc) const
+{
+ if (tc.isNull())
+ tc = textCursor();
+
+ tc.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
+ QChar ch = document()->characterAt(tc.position() - 1);
+ while (!(ch.isNull() || ch.isSpace() || ch == QLatin1Char(':') || ch == QLatin1Char(','))) {
+ tc.movePosition(QTextCursor::PreviousCharacter, QTextCursor::MoveAnchor);
+ ch = document()->characterAt(tc.position() - 1);
+ }
+ tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
+ ch = document()->characterAt(tc.position());
+ while (!(ch.isNull() || ch.isSpace() || ch == QLatin1Char(':') || ch == QLatin1Char(','))) {
+ tc.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
+ ch = document()->characterAt(tc.position());
+ }
+ return tc;
+}
+
+void ConfigurationEditor::insertCompleterText(const QString &text)
+{
+ QTextCursor tc = textCursor();
+ // Replace entire word to get case sensitivity right.
+ tc.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor,
+ m_completer->completionPrefix().length());
+ tc.insertText(text);
+ setTextCursor(tc);
+}
+
+void ConfigurationEditor::updateDocumentation()
+{
+ QTC_CHECK(m_settings);
+ QTextCursor cursor = textCursor();
+
+ QString word = cursorForTextUnderCursor(cursor).selectedText();
+ if (word == m_lastDocumentation)
+ return;
+
+ QString doc = m_settings->documentation(word);
+ if (!doc.isEmpty()) {
+ m_lastDocumentation = word;
+ emit documentationChanged(word, doc);
+ return;
+ }
+
+ // If the documentation was empty, then try to use the line's first word or the first word
+ // in front of a colon for providing a documentation.
+ cursor.movePosition(QTextCursor::PreviousWord);
+ cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
+ const int pos = cursor.selectedText().lastIndexOf(QLatin1Char(','));
+ if (-1 != pos) {
+ cursor.setPosition(cursor.position() + pos);
+ cursor.movePosition(QTextCursor::NextWord);
+ }
+ word = cursorForTextUnderCursor(cursor).selectedText();
+
+ if (word == m_lastDocumentation)
+ return;
+
+ doc = m_settings->documentation(word);
+ if (doc.isEmpty())
+ return;
+
+ m_lastDocumentation = word;
+ emit documentationChanged(word, doc);
+}
+
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/configurationeditor.h b/src/plugins/beautifier/configurationeditor.h
new file mode 100644
index 0000000000..4319fd6653
--- /dev/null
+++ b/src/plugins/beautifier/configurationeditor.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CONFIGURATIONEDITOR_H
+#define BEAUTIFIER_CONFIGURATIONEDITOR_H
+
+#include <utils/qtcoverride.h>
+
+#include <QPlainTextEdit>
+#include <QRegExp>
+#include <QString>
+#include <QStringList>
+#include <QSyntaxHighlighter>
+#include <QTextCharFormat>
+
+QT_BEGIN_NAMESPACE
+class QCompleter;
+class QRegExp;
+class QStringListModel;
+class QTextDocument;
+QT_END_NAMESPACE
+
+namespace Beautifier {
+namespace Internal {
+
+class AbstractSettings;
+
+class ConfigurationSyntaxHighlighter : public QSyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigurationSyntaxHighlighter(QTextDocument *parent);
+ void setKeywords(const QStringList &keywords);
+ void setCommentExpression(const QRegExp &rx);
+
+protected:
+ void highlightBlock(const QString &text) QTC_OVERRIDE;
+
+private:
+ QRegExp m_expressionKeyword;
+ QRegExp m_expressionComment;
+ QTextCharFormat m_formatKeyword;
+ QTextCharFormat m_formatComment;
+};
+
+class ConfigurationEditor : public QPlainTextEdit
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigurationEditor(QWidget *parent = 0);
+ void setSettings(AbstractSettings *settings);
+ void setCommentExpression(const QRegExp &rx);
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event) QTC_OVERRIDE;
+ void keyPressEvent(QKeyEvent *event) QTC_OVERRIDE;
+
+private slots:
+ void insertCompleterText(const QString &text);
+ void updateDocumentation();
+
+signals:
+ void documentationChanged(const QString &word, const QString &documentation);
+
+private:
+ QTextCursor cursorForTextUnderCursor(QTextCursor tc = QTextCursor()) const;
+
+ AbstractSettings *m_settings;
+ QCompleter *m_completer;
+ QStringListModel *m_model;
+ ConfigurationSyntaxHighlighter *m_highlighter;
+ QString m_lastDocumentation;
+};
+
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CONFIGURATIONEDITOR_H
diff --git a/src/plugins/beautifier/configurationpanel.cpp b/src/plugins/beautifier/configurationpanel.cpp
new file mode 100644
index 0000000000..01d246d9f9
--- /dev/null
+++ b/src/plugins/beautifier/configurationpanel.cpp
@@ -0,0 +1,131 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "configurationpanel.h"
+#include "ui_configurationpanel.h"
+
+#include "abstractsettings.h"
+#include "configurationdialog.h"
+
+#include <QPointer>
+
+namespace Beautifier {
+namespace Internal {
+
+ConfigurationPanel::ConfigurationPanel(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::ConfigurationPanel),
+ m_settings(0)
+{
+ ui->setupUi(this);
+ connect(ui->add, SIGNAL(clicked()), this, SLOT(add()));
+ connect(ui->edit, SIGNAL(clicked()), this, SLOT(edit()));
+ connect(ui->remove, SIGNAL(clicked()), this, SLOT(remove()));
+ connect(ui->configurations, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
+}
+
+ConfigurationPanel::~ConfigurationPanel()
+{
+ delete ui;
+}
+
+void ConfigurationPanel::setSettings(AbstractSettings *settings)
+{
+ m_settings = settings;
+ populateConfigurations();
+}
+
+void ConfigurationPanel::setCurrentConfiguration(const QString &text)
+{
+ ui->configurations->setCurrentText(text);
+}
+
+QString ConfigurationPanel::currentConfiguration() const
+{
+ return ui->configurations->currentText();
+}
+
+void ConfigurationPanel::remove()
+{
+ m_settings->removeStyle(ui->configurations->currentText());
+ populateConfigurations();
+}
+
+void ConfigurationPanel::add()
+{
+ ConfigurationDialog dialog;
+ dialog.setWindowTitle(tr("Add Configuration"));
+ dialog.setSettings(m_settings);
+ if (QDialog::Accepted == dialog.exec()) {
+ const QString key = dialog.key();
+ m_settings->setStyle(key, dialog.value());
+ populateConfigurations(key);
+ }
+}
+
+void ConfigurationPanel::edit()
+{
+ const QString key = ui->configurations->currentText();
+ ConfigurationDialog dialog;
+ dialog.setWindowTitle(tr("Edit Configuration"));
+ dialog.setSettings(m_settings);
+ dialog.setKey(key);
+ if (QDialog::Accepted == dialog.exec()) {
+ const QString newKey = dialog.key();
+ if (newKey == key) {
+ m_settings->setStyle(key, dialog.value());
+ } else {
+ m_settings->replaceStyle(key, newKey, dialog.value());
+ ui->configurations->setItemText(ui->configurations->currentIndex(), newKey);
+ }
+ }
+}
+
+void ConfigurationPanel::populateConfigurations(const QString &key)
+{
+ ui->configurations->blockSignals(true);
+ const QString currentText = (!key.isEmpty()) ? key : ui->configurations->currentText();
+ ui->configurations->clear();
+ ui->configurations->addItems(m_settings->styles());
+ ui->configurations->setCurrentText(currentText);
+ updateButtons();
+ ui->configurations->blockSignals(false);
+}
+
+void ConfigurationPanel::updateButtons()
+{
+ const bool enabled
+ = ((ui->configurations->count() > 0)
+ && !m_settings->styleIsReadOnly(ui->configurations->currentText()));
+ ui->remove->setEnabled(enabled);
+ ui->edit->setEnabled(enabled);
+}
+
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/configurationpanel.h b/src/plugins/beautifier/configurationpanel.h
new file mode 100644
index 0000000000..dd9625640b
--- /dev/null
+++ b/src/plugins/beautifier/configurationpanel.h
@@ -0,0 +1,70 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_CONFIGURATIONPANEL_H
+#define BEAUTIFIER_CONFIGURATIONPANEL_H
+
+#include <QWidget>
+
+namespace Beautifier {
+namespace Internal {
+
+class AbstractSettings;
+class ConfigurationDialog;
+
+namespace Ui { class ConfigurationPanel; }
+
+class ConfigurationPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ConfigurationPanel(QWidget *parent = 0);
+ ~ConfigurationPanel();
+
+ void setSettings(AbstractSettings *settings);
+ void setCurrentConfiguration(const QString &text);
+ QString currentConfiguration() const;
+
+private slots:
+ void remove();
+ void add();
+ void edit();
+ void updateButtons();
+
+private:
+ Ui::ConfigurationPanel *ui;
+ AbstractSettings *m_settings;
+ void populateConfigurations(const QString &key = QString());
+};
+
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_CONFIGURATIONPANEL_H
diff --git a/src/plugins/beautifier/configurationpanel.ui b/src/plugins/beautifier/configurationpanel.ui
new file mode 100644
index 0000000000..73d35bc09f
--- /dev/null
+++ b/src/plugins/beautifier/configurationpanel.ui
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Beautifier::Internal::ConfigurationPanel</class>
+ <widget class="QWidget" name="Beautifier::Internal::ConfigurationPanel">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>595</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="9999,0,0,0">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QComboBox" name="configurations"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="edit">
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="remove">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="add">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/beautifier/images/beautifier.png b/src/plugins/beautifier/images/beautifier.png
new file mode 100644
index 0000000000..65cf56ae8e
--- /dev/null
+++ b/src/plugins/beautifier/images/beautifier.png
Binary files differ
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.cpp b/src/plugins/beautifier/uncrustify/uncrustify.cpp
new file mode 100644
index 0000000000..02774261c7
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustify.cpp
@@ -0,0 +1,146 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "uncrustify.h"
+
+#include "uncrustifyconstants.h"
+#include "uncrustifyoptionspage.h"
+#include "uncrustifysettings.h"
+
+#include "../beautifierconstants.h"
+#include "../beautifierplugin.h"
+
+#include <coreplugin/actionmanager/actioncontainer.h>
+#include <coreplugin/actionmanager/actionmanager.h>
+#include <coreplugin/actionmanager/command.h>
+#include <coreplugin/coreconstants.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icontext.h>
+#include <coreplugin/icore.h>
+#include <cppeditor/cppeditorconstants.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/project.h>
+#include <utils/fileutils.h>
+
+#include <QAction>
+#include <QMenu>
+
+namespace Beautifier {
+namespace Internal {
+namespace Uncrustify {
+
+Uncrustify::Uncrustify(QObject *parent) :
+ BeautifierAbstractTool(parent),
+ m_settings(new UncrustifySettings)
+{
+}
+
+Uncrustify::~Uncrustify()
+{
+ delete m_settings;
+}
+
+bool Uncrustify::initialize()
+{
+ Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::Uncrustify::MENU_ID);
+ menu->menu()->setTitle(QLatin1String("Uncrustify"));
+
+ m_formatFile = new QAction(tr("Format Current File"), this);
+ Core::Command *cmd
+ = Core::ActionManager::registerAction(m_formatFile,
+ Constants::Uncrustify::ACTION_FORMATFILE,
+ Core::Context(Core::Constants::C_GLOBAL));
+ menu->addAction(cmd);
+ connect(m_formatFile, SIGNAL(triggered()), this, SLOT(formatFile()));
+
+ Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
+
+ return true;
+}
+
+void Uncrustify::updateActions(Core::IEditor *editor)
+{
+ m_formatFile->setEnabled(editor && editor->id() == CppEditor::Constants::CPPEDITOR_ID);
+}
+
+QList<QObject *> Uncrustify::autoReleaseObjects()
+{
+ UncrustifyOptionsPage *optionsPage = new UncrustifyOptionsPage(m_settings, this);
+ return QList<QObject *>() << optionsPage;
+}
+
+void Uncrustify::formatFile()
+{
+ QString cfgFileName;
+
+ if (m_settings->useOtherFiles()) {
+ if (const ProjectExplorer::Project *project
+ = ProjectExplorer::ProjectExplorerPlugin::currentProject()) {
+ const QStringList files = project->files(ProjectExplorer::Project::AllFiles);
+ for (int i = 0, total = files.size(); i < total; ++i) {
+ const QString &file = files.at(i);
+ if (!file.endsWith(QLatin1String("cfg")))
+ continue;
+ const QFileInfo fi(file);
+ if (fi.isReadable() && fi.fileName() == QLatin1String("uncrustify.cfg")) {
+ cfgFileName = file;
+ break;
+ }
+ }
+ }
+ }
+
+ if (cfgFileName.isEmpty() && m_settings->useHomeFile()) {
+ const QString file = QDir::home().filePath(QLatin1String("uncrustify.cfg"));
+ if (QFile::exists(file))
+ cfgFileName = file;
+ }
+
+ if (m_settings->useCustomStyle())
+ cfgFileName = m_settings->styleFileName(m_settings->customStyle());
+
+ if (cfgFileName.isEmpty()) {
+ BeautifierPlugin::showError(tr("Could not get configuration file for uncrustify."));
+ } else {
+ BeautifierPlugin::formatCurrentFile(QStringList()
+ << m_settings->command()
+ << QLatin1String("-l")
+ << QLatin1String("cpp")
+ << QLatin1String("-L")
+ << QLatin1String("1-2")
+ << QLatin1String("--no-backup")
+ << QLatin1String("-c")
+ << cfgFileName
+ << QLatin1String("%file"));
+ }
+}
+
+} // namespace Uncrustify
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.h b/src/plugins/beautifier/uncrustify/uncrustify.h
new file mode 100644
index 0000000000..7397380d0b
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustify.h
@@ -0,0 +1,68 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_UNCRUSTIFY_H
+#define BEAUTIFIER_UNCRUSTIFY_H
+
+#include "../beautifierabstracttool.h"
+
+#include <utils/qtcoverride.h>
+
+QT_FORWARD_DECLARE_CLASS(QAction)
+
+namespace Beautifier {
+namespace Internal {
+namespace Uncrustify {
+
+class UncrustifySettings;
+
+class Uncrustify : public BeautifierAbstractTool
+{
+ Q_OBJECT
+
+public:
+ explicit Uncrustify(QObject *parent = 0);
+ virtual ~Uncrustify();
+ bool initialize() QTC_OVERRIDE;
+ void updateActions(Core::IEditor *editor) QTC_OVERRIDE;
+ QList<QObject *> autoReleaseObjects() QTC_OVERRIDE;
+
+private slots:
+ void formatFile();
+
+private:
+ QAction *m_formatFile;
+ UncrustifySettings *m_settings;
+};
+
+} // namespace Uncrustify
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_UNCRUSTIFY_H
diff --git a/src/plugins/beautifier/uncrustify/uncrustifyconstants.h b/src/plugins/beautifier/uncrustify/uncrustifyconstants.h
new file mode 100644
index 0000000000..6a09f2138f
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustifyconstants.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_UNCRUSTIFYCONSTANTS_H
+#define BEAUTIFIER_UNCRUSTIFYCONSTANTS_H
+
+namespace Beautifier {
+namespace Constants {
+namespace Uncrustify {
+
+const char ACTION_FORMATFILE[] = "Uncrustify.FormatFile";
+const char MENU_ID[] = "Uncrustify.Menu";
+const char OPTION_ID[] = "Uncrustify";
+const char SETTINGS_NAME[] = "uncrustify";
+
+} // namespace Uncrustify
+} // namespace Constants
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_UNCRUSTIFYCONSTANTS_H
diff --git a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp
new file mode 100644
index 0000000000..77e2590298
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.cpp
@@ -0,0 +1,143 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "uncrustifyoptionspage.h"
+#include "ui_uncrustifyoptionspage.h"
+
+#include "uncrustifyconstants.h"
+#include "uncrustifysettings.h"
+
+#include "../beautifierconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QTextStream>
+
+namespace Beautifier {
+namespace Internal {
+namespace Uncrustify {
+
+UncrustifyOptionsPageWidget::UncrustifyOptionsPageWidget(UncrustifySettings *settings,
+ QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::UncrustifyOptionsPage)
+ , m_settings(settings)
+{
+ ui->setupUi(this);
+ ui->command->setExpectedKind(Utils::PathChooser::ExistingCommand);
+ ui->command->setPromptDialogTitle(tr("Uncrustify Command"));
+ connect(ui->command, SIGNAL(validChanged(bool)), ui->options, SLOT(setEnabled(bool)));
+ ui->configurations->setSettings(m_settings);
+}
+
+UncrustifyOptionsPageWidget::~UncrustifyOptionsPageWidget()
+{
+ delete ui;
+}
+
+QString UncrustifyOptionsPageWidget::searchKeywords() const
+{
+ QString keywords;
+ const QLatin1Char sep(' ');
+ QTextStream(&keywords) << sep << ui->configuration->title()
+ << sep << ui->commandLabel->text()
+ << sep << ui->options->title()
+ << sep << ui->useOtherFiles->text()
+ << sep << ui->useHomeFile->text()
+ << sep << ui->useCustomStyle->text();
+ keywords.remove(QLatin1Char('&'));
+ return keywords;
+}
+
+void UncrustifyOptionsPageWidget::restore()
+{
+ ui->command->setPath(m_settings->command());
+ ui->useOtherFiles->setChecked(m_settings->useOtherFiles());
+ ui->useHomeFile->setChecked(m_settings->useHomeFile());
+ ui->useCustomStyle->setChecked(m_settings->useCustomStyle());
+ ui->configurations->setCurrentConfiguration(m_settings->customStyle());
+}
+
+void UncrustifyOptionsPageWidget::apply()
+{
+ m_settings->setCommand(ui->command->path());
+ m_settings->setUseOtherFiles(ui->useOtherFiles->isChecked());
+ m_settings->setUseHomeFile(ui->useHomeFile->isChecked());
+ m_settings->setUseCustomStyle(ui->useCustomStyle->isChecked());
+ m_settings->setCustomStyle(ui->configurations->currentConfiguration());
+ m_settings->save();
+}
+
+/* ---------------------------------------------------------------------------------------------- */
+
+UncrustifyOptionsPage::UncrustifyOptionsPage(UncrustifySettings *settings, QObject *parent) :
+ IOptionsPage(parent),
+ m_widget(0),
+ m_settings(settings),
+ m_searchKeywords()
+{
+ setId(Constants::Uncrustify::OPTION_ID);
+ setDisplayName(tr("Uncrustify"));
+ setCategory(Constants::OPTION_CATEGORY);
+ setDisplayCategory(QCoreApplication::translate("Beautifier", Constants::OPTION_TR_CATEGORY));
+ setCategoryIcon(QLatin1String(Constants::OPTION_CATEGORY_ICON));
+}
+
+QWidget *UncrustifyOptionsPage::widget()
+{
+ m_settings->read();
+
+ if (!m_widget) {
+ m_widget = new UncrustifyOptionsPageWidget(m_settings);
+ if (m_searchKeywords.isEmpty())
+ m_searchKeywords = m_widget->searchKeywords();
+ }
+ m_widget->restore();
+
+ return m_widget;
+}
+
+void UncrustifyOptionsPage::apply()
+{
+ if (m_widget)
+ m_widget->apply();
+}
+
+void UncrustifyOptionsPage::finish()
+{
+}
+
+bool UncrustifyOptionsPage::matches(const QString &searchKeyWord) const
+{
+ return m_searchKeywords.contains(searchKeyWord, Qt::CaseInsensitive);
+}
+
+} // namespace Uncrustify
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.h b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.h
new file mode 100644
index 0000000000..125862c0e9
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_UNCRUSTIFYOPTIONSPAGE_H
+#define BEAUTIFIER_UNCRUSTIFYOPTIONSPAGE_H
+
+#include <coreplugin/dialogs/ioptionspage.h>
+#include <utils/qtcoverride.h>
+
+#include <QPointer>
+#include <QWidget>
+
+namespace Beautifier {
+namespace Internal {
+namespace Uncrustify {
+
+class UncrustifySettings;
+
+namespace Ui { class UncrustifyOptionsPage; }
+
+class UncrustifyOptionsPageWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit UncrustifyOptionsPageWidget(UncrustifySettings *settings, QWidget *parent = 0);
+ virtual ~UncrustifyOptionsPageWidget();
+ QString searchKeywords() const;
+ void restore();
+ void apply();
+
+private:
+ Ui::UncrustifyOptionsPage *ui;
+ UncrustifySettings *m_settings;
+};
+
+class UncrustifyOptionsPage : public Core::IOptionsPage
+{
+ Q_OBJECT
+
+public:
+ explicit UncrustifyOptionsPage(UncrustifySettings *settings, QObject *parent = 0);
+ QWidget *widget() QTC_OVERRIDE;
+ void apply() QTC_OVERRIDE;
+ void finish() QTC_OVERRIDE;
+ bool matches(const QString &searchKeywords) const QTC_OVERRIDE;
+
+private:
+ QPointer<UncrustifyOptionsPageWidget> m_widget;
+ UncrustifySettings *m_settings;
+ QString m_searchKeywords;
+};
+
+} // namespace Uncrustify
+} // namespace Internal
+} // namespace Beautifier
+
+
+#endif // BEAUTIFIER_UNCRUSTIFYOPTIONSPAGE_H
diff --git a/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui
new file mode 100644
index 0000000000..6dbc77a710
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustifyoptionspage.ui
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Beautifier::Internal::Uncrustify::UncrustifyOptionsPage</class>
+ <widget class="QWidget" name="Beautifier::Internal::Uncrustify::UncrustifyOptionsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>817</width>
+ <height>631</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0">
+ <item>
+ <widget class="QGroupBox" name="configuration">
+ <property name="title">
+ <string>Configuration</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="commandLabel">
+ <property name="text">
+ <string>Uncrustify command:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Utils::PathChooser" name="command" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="options">
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="useOtherFiles">
+ <property name="text">
+ <string>Use file uncrustify.cfg defined in project files</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="useHomeFile">
+ <property name="text">
+ <string>Use $HOME/uncrustify.cfg</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,9999">
+ <item>
+ <widget class="QCheckBox" name="useCustomStyle">
+ <property name="text">
+ <string>Use selfdefined style:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Utils::PathChooser</class>
+ <extends>QWidget</extends>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Beautifier::Internal::ConfigurationPanel</class>
+ <extends>QWidget</extends>
+ <header location="global">beautifier/configurationpanel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
new file mode 100644
index 0000000000..705c0c922f
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp
@@ -0,0 +1,172 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 "uncrustifysettings.h"
+
+#include "uncrustifyconstants.h"
+
+#include "../beautifierconstants.h"
+
+#include <coreplugin/icore.h>
+
+#include <QDateTime>
+#include <QFile>
+#include <QFileInfo>
+#include <QProcess>
+#include <QXmlStreamWriter>
+
+namespace Beautifier {
+namespace Internal {
+namespace Uncrustify {
+
+namespace {
+const QString kUseOtherFiles = QLatin1String("useOtherFiles");
+const QString kUseHomeFile = QLatin1String("useHomeFile");
+const QString kUseCustomStyle = QLatin1String("useCustomStyle");
+const QString kCustomStyle = QLatin1String("customStyle");
+}
+
+UncrustifySettings::UncrustifySettings() :
+ AbstractSettings(QLatin1String(Constants::Uncrustify::SETTINGS_NAME), QLatin1String(".cfg"))
+{
+ setCommand(QLatin1String("uncrustify"));
+ m_settings.insert(kUseOtherFiles, QVariant(true));
+ m_settings.insert(kUseHomeFile, QVariant(false));
+ m_settings.insert(kUseCustomStyle, QVariant(false));
+ m_settings.insert(kCustomStyle, QVariant());
+ read();
+}
+
+bool UncrustifySettings::useOtherFiles() const
+{
+ return m_settings.value(kUseOtherFiles).toBool();
+}
+
+void UncrustifySettings::setUseOtherFiles(bool useOtherFiles)
+{
+ m_settings.insert(kUseOtherFiles, QVariant(useOtherFiles));
+}
+
+bool UncrustifySettings::useHomeFile() const
+{
+ return m_settings.value(kUseHomeFile).toBool();
+}
+
+void UncrustifySettings::setUseHomeFile(bool useHomeFile)
+{
+ m_settings.insert(kUseHomeFile, QVariant(useHomeFile));
+}
+
+bool UncrustifySettings::useCustomStyle() const
+{
+ return m_settings.value(kUseCustomStyle).toBool();
+}
+
+void UncrustifySettings::setUseCustomStyle(bool useCustomStyle)
+{
+ m_settings.insert(kUseCustomStyle, QVariant(useCustomStyle));
+}
+
+QString UncrustifySettings::customStyle() const
+{
+ return m_settings.value(kCustomStyle).toString();
+}
+
+void UncrustifySettings::setCustomStyle(const QString &customStyle)
+{
+ m_settings.insert(kCustomStyle, QVariant(customStyle));
+}
+
+QString UncrustifySettings::documentationFilePath() const
+{
+ return Core::ICore::userResourcePath() + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::SETTINGS_DIRNAME) + QLatin1Char('/')
+ + QLatin1String(Beautifier::Constants::DOCUMENTATION_DIRNAME) + QLatin1Char('/')
+ + QLatin1String(Constants::Uncrustify::SETTINGS_NAME) + QLatin1String(".xml");
+}
+
+void UncrustifySettings::createDocumentationFile() const
+{
+ QFile file(documentationFilePath());
+ const QFileInfo fi(file);
+ if (!fi.exists())
+ fi.dir().mkpath(fi.absolutePath());
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
+ return;
+
+ QProcess process;
+ process.start(command(), QStringList() << QLatin1String("--show-config"));
+ process.waitForFinished(2000); // show config should be really fast.
+ if (process.error() != QProcess::UnknownError)
+ return;
+
+ QXmlStreamWriter stream(&file);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument(QLatin1String("1.0"), true);
+ stream.writeComment(QLatin1String("Created ")
+ + QDateTime::currentDateTime().toString(Qt::ISODate));
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLROOT));
+
+ const QStringList lines = QString::fromUtf8(process.readAll()).split(QLatin1Char('\n'));
+ const int totalLines = lines.count();
+ for (int i = 0; i < totalLines; ++i) {
+ const QString &line = lines.at(i);
+ if (line.startsWith(QLatin1Char('#')) || line.trimmed().isEmpty())
+ continue;
+
+ const int firstSpace = line.indexOf(QLatin1Char(' '));
+ const QString keyword = line.left(firstSpace);
+ const QString options = line.right(line.size() - firstSpace).trimmed();
+ QStringList docu;
+ while (++i < totalLines) {
+ const QString &subline = lines.at(i);
+ if (line.startsWith(QLatin1Char('#')) || subline.trimmed().isEmpty()) {
+ //TODO As soon as Qt 4 support is dropped, use toHtmlEscaped().
+ const QString text = QLatin1String("<p><span class=\"option\">") + keyword
+ + QLatin1String("</span> <span class=\"param\">") + options
+ + QLatin1String("</span></p><p>") + Qt::escape(docu.join(QLatin1Char(' ')))
+ + QLatin1String("</p>");
+ stream.writeStartElement(QLatin1String(Constants::DOCUMENTATION_XMLENTRY));
+ stream.writeTextElement(QLatin1String(Constants::DOCUMENTATION_XMLKEY), keyword);
+ stream.writeTextElement(QLatin1String(Constants::DOCUMENTATION_XMLDOC), text);
+ stream.writeEndElement();
+ break;
+ } else {
+ docu << subline;
+ }
+ }
+ }
+
+ stream.writeEndElement();
+ stream.writeEndDocument();
+}
+
+} // namespace Uncrustify
+} // namespace Internal
+} // namespace Beautifier
diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.h b/src/plugins/beautifier/uncrustify/uncrustifysettings.h
new file mode 100644
index 0000000000..3398a64e1a
--- /dev/null
+++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.h
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 Lorenz Haas
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** 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 BEAUTIFIER_UNCRUSTIFYSETTINGS_H
+#define BEAUTIFIER_UNCRUSTIFYSETTINGS_H
+
+#include "../abstractsettings.h"
+
+#include <utils/qtcoverride.h>
+
+namespace Beautifier {
+namespace Internal {
+namespace Uncrustify {
+
+class UncrustifySettings : public AbstractSettings
+{
+public:
+ UncrustifySettings();
+
+ bool useOtherFiles() const;
+ void setUseOtherFiles(bool useOtherFiles);
+
+ bool useHomeFile() const;
+ void setUseHomeFile(bool useHomeFile);
+
+ bool useCustomStyle() const;
+ void setUseCustomStyle(bool useCustomStyle);
+
+ QString customStyle() const;
+ void setCustomStyle(const QString &customStyle);
+
+ QString documentationFilePath() const QTC_OVERRIDE;
+ void createDocumentationFile() const QTC_OVERRIDE;
+};
+
+} // namespace Uncrustify
+} // namespace Internal
+} // namespace Beautifier
+
+#endif // BEAUTIFIER_UNCRUSTIFYSETTINGS_H
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 4b4587e272..987cb24b3a 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -48,7 +48,8 @@ SUBDIRS = \
qnx \
clearcase \
baremetal \
- ios
+ ios \
+ beautifier
# prefer qmake variable set on command line over env var
isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR)
diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs
index 757ec3200f..7f621efd7a 100644
--- a/src/plugins/plugins.qbs
+++ b/src/plugins/plugins.qbs
@@ -9,6 +9,7 @@ Project {
"autotoolsprojectmanager/autotoolsprojectmanager.qbs",
"baremetal/baremetal.qbs",
"bazaar/bazaar.qbs",
+ "beautifier/beautifier.qbs",
"bineditor/bineditor.qbs",
"bookmarks/bookmarks.qbs",
"clangcodemodel/clangcodemodel.qbs",