aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2017-07-28 15:24:14 +0200
committerEike Ziller <eike.ziller@qt.io>2017-07-28 15:24:14 +0200
commitc01ddc4660c10e8ddc605602fd623135fb607de0 (patch)
treefdf50dee801ce09d2a6d671d558b73d8769870d9 /src/libs
parent712297cbf0b73d8af8db3921c646ed252b0c41d7 (diff)
parent36968528805d99a746d27f2632cabc1a132e535f (diff)
Merge remote-tracking branch 'origin/4.4'
Conflicts: qbs/modules/qtc/qtc.qbs qtcreator.pri src/plugins/qbsprojectmanager/qbsproject.h Change-Id: I6b9cdf704be95ade02488c8b19582b6621282fb8
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/3rdparty/cplusplus/ASTPatternBuilder.cpp2
-rw-r--r--src/libs/3rdparty/cplusplus/ObjectiveCAtKeywords.cpp19
-rw-r--r--src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.cpp19
-rw-r--r--src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.h27
-rw-r--r--src/libs/3rdparty/cplusplus/QtContextKeywords.cpp19
-rw-r--r--src/libs/3rdparty/cplusplus/QtContextKeywords.h19
-rw-r--r--src/libs/3rdparty/cplusplus/SafeMatcher.h5
-rw-r--r--src/libs/3rdparty/cplusplus/cplusplus.pri1
-rw-r--r--src/libs/cplusplus/cplusplus.qbs1
-rw-r--r--src/libs/extensionsystem/pluginspec.cpp27
-rw-r--r--src/libs/extensionsystem/pluginspec.h2
-rw-r--r--src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp7
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbext.qbs109
-rw-r--r--src/libs/utils/highlightingitemdelegate.cpp305
-rw-r--r--src/libs/utils/highlightingitemdelegate.h61
-rw-r--r--src/libs/utils/icon.cpp8
-rw-r--r--src/libs/utils/stringutils.cpp23
-rw-r--r--src/libs/utils/stringutils.h3
-rw-r--r--src/libs/utils/utils-lib.pri6
-rw-r--r--src/libs/utils/utils.qbs2
20 files changed, 618 insertions, 47 deletions
diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.cpp b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.cpp
deleted file mode 100644
index 0c1549e51b8..00000000000
--- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-
-#include "ASTPatternBuilder.h"
diff --git a/src/libs/3rdparty/cplusplus/ObjectiveCAtKeywords.cpp b/src/libs/3rdparty/cplusplus/ObjectiveCAtKeywords.cpp
index d05222c681a..8177368d7f1 100644
--- a/src/libs/3rdparty/cplusplus/ObjectiveCAtKeywords.cpp
+++ b/src/libs/3rdparty/cplusplus/ObjectiveCAtKeywords.cpp
@@ -1,3 +1,22 @@
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
#include "Lexer.h"
#include "Token.h"
diff --git a/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.cpp b/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.cpp
index 6b85bf4a1b1..6005fe574fc 100644
--- a/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.cpp
+++ b/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.cpp
@@ -1,3 +1,22 @@
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
#include "ObjectiveCTypeQualifiers.h"
diff --git a/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.h b/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.h
index ac46bd6070f..3f920e5bfc2 100644
--- a/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.h
+++ b/src/libs/3rdparty/cplusplus/ObjectiveCTypeQualifiers.h
@@ -1,9 +1,27 @@
-#ifndef CPLUSPLUS_OBJC_TYPEQUALIFIERS_H
-#define CPLUSPLUS_OBJC_TYPEQUALIFIERS_H
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#pragma once
#include "CPlusPlusForwardDeclarations.h"
-
namespace CPlusPlus {
enum {
@@ -27,6 +45,3 @@ enum {
CPLUSPLUS_EXPORT int classifyObjectiveCContextKeyword(const char *s, int n);
} // namespace CPlusPlus
-
-
-#endif // CPLUSPLUS_OBJC_TYPEQUALIFIERS_H
diff --git a/src/libs/3rdparty/cplusplus/QtContextKeywords.cpp b/src/libs/3rdparty/cplusplus/QtContextKeywords.cpp
index 87403aed14f..ce7bd0a1dde 100644
--- a/src/libs/3rdparty/cplusplus/QtContextKeywords.cpp
+++ b/src/libs/3rdparty/cplusplus/QtContextKeywords.cpp
@@ -1,3 +1,22 @@
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
#include "QtContextKeywords.h"
diff --git a/src/libs/3rdparty/cplusplus/QtContextKeywords.h b/src/libs/3rdparty/cplusplus/QtContextKeywords.h
index edef73a7ee8..42dce9b917d 100644
--- a/src/libs/3rdparty/cplusplus/QtContextKeywords.h
+++ b/src/libs/3rdparty/cplusplus/QtContextKeywords.h
@@ -1,3 +1,22 @@
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
#pragma once
diff --git a/src/libs/3rdparty/cplusplus/SafeMatcher.h b/src/libs/3rdparty/cplusplus/SafeMatcher.h
index 98219eeffdc..98fbbae2aa2 100644
--- a/src/libs/3rdparty/cplusplus/SafeMatcher.h
+++ b/src/libs/3rdparty/cplusplus/SafeMatcher.h
@@ -23,8 +23,7 @@
**
****************************************************************************/
-#ifndef CPLUSPLUS_SAFETYPEMATCHER_H
-#define CPLUSPLUS_SAFETYPEMATCHER_H
+#pragma once
#include "Matcher.h"
@@ -56,5 +55,3 @@ private:
};
} // CPlusPlus namespace
-
-#endif // CPLUSPLUS_SAFETYPEMATCHER_H
diff --git a/src/libs/3rdparty/cplusplus/cplusplus.pri b/src/libs/3rdparty/cplusplus/cplusplus.pri
index 025519ef89c..2a4f71a7122 100644
--- a/src/libs/3rdparty/cplusplus/cplusplus.pri
+++ b/src/libs/3rdparty/cplusplus/cplusplus.pri
@@ -40,7 +40,6 @@ SOURCES += \
$$PWD/ASTMatch0.cpp \
$$PWD/ASTVisitor.cpp \
$$PWD/ASTClone.cpp \
- $$PWD/ASTPatternBuilder.cpp \
$$PWD/ASTMatcher.cpp \
$$PWD/Matcher.cpp \
$$PWD/Control.cpp \
diff --git a/src/libs/cplusplus/cplusplus.qbs b/src/libs/cplusplus/cplusplus.qbs
index c9aae72b3e3..a0e0d66178c 100644
--- a/src/libs/cplusplus/cplusplus.qbs
+++ b/src/libs/cplusplus/cplusplus.qbs
@@ -30,7 +30,6 @@ Project {
"ASTMatch0.cpp",
"ASTMatcher.cpp",
"ASTMatcher.h",
- "ASTPatternBuilder.cpp",
"ASTPatternBuilder.h",
"ASTVisit.cpp",
"ASTVisitor.cpp",
diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp
index cde1903099f..8fd64007a29 100644
--- a/src/libs/extensionsystem/pluginspec.cpp
+++ b/src/libs/extensionsystem/pluginspec.cpp
@@ -32,6 +32,7 @@
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
+#include <utils/stringutils.h>
#include <QCoreApplication>
#include <QDebug>
@@ -631,26 +632,6 @@ static inline QString msgInvalidFormat(const char *key, const QString &content)
.arg(QLatin1String(key), content);
}
-bool PluginSpec::readMultiLineString(const QJsonValue &value, QString *out)
-{
- QTC_ASSERT(out, return false);
- if (value.isString()) {
- *out = value.toString();
- } else if (value.isArray()) {
- QJsonArray array = value.toArray();
- QStringList lines;
- foreach (const QJsonValue &v, array) {
- if (!v.isString())
- return false;
- lines.append(v.toString());
- }
- *out = lines.join(QLatin1Char('\n'));
- } else {
- return false;
- }
- return true;
-}
-
/*!
\internal
*/
@@ -735,7 +716,7 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
copyright = value.toString();
value = metaData.value(QLatin1String(DESCRIPTION));
- if (!value.isUndefined() && !PluginSpec::readMultiLineString(value, &description))
+ if (!value.isUndefined() && !Utils::readMultiLineString(value, &description))
return reportError(msgValueIsNotAString(DESCRIPTION));
value = metaData.value(QLatin1String(URL));
@@ -749,7 +730,7 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
category = value.toString();
value = metaData.value(QLatin1String(LICENSE));
- if (!value.isUndefined() && !PluginSpec::readMultiLineString(value, &license))
+ if (!value.isUndefined() && !Utils::readMultiLineString(value, &license))
return reportError(msgValueIsNotAMultilineString(LICENSE));
value = metaData.value(QLatin1String(PLATFORM));
@@ -799,7 +780,7 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
} else if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_TEST)) {
dep.type = PluginDependency::Test;
} else {
- return reportError(tr("Dependency: \"%1\" must be \"%2\" or \"%3\" (is \"%4\")")
+ return reportError(tr("Dependency: \"%1\" must be \"%2\" or \"%3\" (is \"%4\").")
.arg(QLatin1String(DEPENDENCY_TYPE),
QLatin1String(DEPENDENCY_TYPE_HARD),
QLatin1String(DEPENDENCY_TYPE_SOFT),
diff --git a/src/libs/extensionsystem/pluginspec.h b/src/libs/extensionsystem/pluginspec.h
index da89ff6029f..0462acddefe 100644
--- a/src/libs/extensionsystem/pluginspec.h
+++ b/src/libs/extensionsystem/pluginspec.h
@@ -131,8 +131,6 @@ public:
bool hasError() const;
QString errorString() const;
- static bool readMultiLineString(const QJsonValue &value, QString *out);
-
private:
PluginSpec();
diff --git a/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp b/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp
index ddaeafc29f1..614069e0b37 100644
--- a/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp
+++ b/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp
@@ -758,6 +758,13 @@ void ModelController::moveObject(MPackage *newOwner, MObject *object)
QMT_ASSERT(object, return);
QMT_ASSERT(object != m_rootPackage, return);
+ // verify that newOwner is not a child of object
+ MObject *newOwnerObject = newOwner;
+ while (newOwnerObject && newOwnerObject != object)
+ newOwnerObject = newOwnerObject->owner();
+ if (newOwnerObject == object)
+ return;
+
if (newOwner != object->owner()) {
int formerRow = 0;
MObject *formerOwner = object->owner();
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.qbs b/src/libs/qtcreatorcdbext/qtcreatorcdbext.qbs
index 1e1edbefb32..2243c217586 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.qbs
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.qbs
@@ -2,6 +2,8 @@ import qbs
import qbs.Environment
import qbs.File
import qbs.FileInfo
+import qbs.Process
+import qbs.Utilities
QtcLibrary {
condition: qbs.toolchain.contains("msvc") && cdbPath
@@ -45,11 +47,98 @@ QtcLibrary {
}
return undefined;
}
- cpp.includePaths: [FileInfo.joinPaths(cdbPath, "inc")]
- cpp.dynamicLibraries: [
- "user32.lib",
- FileInfo.joinPaths(cdbLibPath, "dbgeng.lib")
- ]
+
+ property string pythonInstallDir: Environment.getEnv("PYTHON_INSTALL_DIR")
+
+ Probe {
+ id: pythonDllProbe
+ condition: product.condition
+ property string pythonDir: pythonInstallDir // Input
+ property string buildVariant: qbs.buildVariant // Input
+ property string fileNamePrefix // Output
+ configure: {
+ function printWarning(msg) {
+ console.warn(msg + " The python dumpers for cdb will not be available.");
+ }
+
+ if (!pythonDir) {
+ printWarning("PYTHON_INSTALL_DIR not set.");
+ return;
+ }
+ if (!File.exists(pythonDir)) {
+ printWarning("The provided python installation directory '" + pythonDir
+ + "' does not exist.");
+ return;
+ }
+ var p = new Process();
+ try {
+ var pythonFilePath = FileInfo.joinPaths(pythonDir, "python.exe");
+ p.exec(pythonFilePath, ["--version"], true);
+ var output = p.readStdOut().trim();
+ var magicPrefix = "Python ";
+ if (!output.startsWith(magicPrefix)) {
+ printWarning("Unexpected python output when checking for version: '"
+ + output + "'");
+ return;
+ }
+ var versionNumberString = output.slice(magicPrefix.length);
+ var versionNumbers = versionNumberString.split('.');
+ if (versionNumbers.length < 2) {
+ printWarning("Unexpected python output when checking for version: '"
+ + output + "'");
+ return;
+ }
+ if (Utilities.versionCompare(versionNumberString, "3.5") < 0) {
+ printWarning("The python installation at '" + pythonDir
+ + "' has version " + versionNumberString + ", but 3.5 or higher "
+ + "is required.");
+ return;
+ }
+ found = true;
+ fileNamePrefix = "python" + versionNumbers[0] + versionNumbers[1];
+ if (buildVariant === "debug")
+ fileNamePrefix += "_d"
+ } finally {
+ p.close();
+ }
+
+ }
+ }
+
+ Group {
+ name: "pythonDumper"
+ condition: pythonDllProbe.found
+ files: [
+ "pycdbextmodule.cpp",
+ "pycdbextmodule.h",
+ "pyfield.cpp",
+ "pyfield.h",
+ "pystdoutredirect.cpp",
+ "pystdoutredirect.h",
+ "pytype.cpp",
+ "pytype.h",
+ "pyvalue.cpp",
+ "pyvalue.h",
+ ]
+ }
+
+ Properties {
+ condition: pythonDllProbe.found
+ cpp.defines: ["WITH_PYTHON=1"]
+ }
+ cpp.includePaths: {
+ var paths = [FileInfo.joinPaths(cdbPath, "inc")];
+ if (pythonDllProbe.found)
+ paths.push(FileInfo.joinPaths(pythonInstallDir, "include"));
+ return paths;
+ }
+ cpp.dynamicLibraries: {
+ var libs = [ "user32.lib", FileInfo.joinPaths(cdbLibPath, "dbgeng.lib") ];
+ if (pythonDllProbe.found)
+ libs.push(FileInfo.joinPaths(pythonInstallDir, "libs",
+ pythonDllProbe.fileNamePrefix + ".lib"));
+ return libs;
+ }
cpp.linkerFlags: ["/DEF:" + FileInfo.toWindowsSeparators(
FileInfo.joinPaths(product.sourceDirectory,
"qtcreatorcdbext.def"))]
@@ -61,6 +150,16 @@ QtcLibrary {
dirName += "32";
return FileInfo.joinPaths(qtc.libDirName, dirName);
}
+
+ Group {
+ condition: pythonDllProbe.found
+ files: [FileInfo.joinPaths(pythonInstallDir, pythonDllProbe.fileNamePrefix + ".dll")]
+ qbs.install: true
+ qbs.installDir: installDir
+ }
+
+ useNonGuiPchFile: false
+
files: [
"common.cpp",
"common.h",
diff --git a/src/libs/utils/highlightingitemdelegate.cpp b/src/libs/utils/highlightingitemdelegate.cpp
new file mode 100644
index 00000000000..fe2525122c8
--- /dev/null
+++ b/src/libs/utils/highlightingitemdelegate.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "highlightingitemdelegate.h"
+
+#include <QApplication>
+#include <QModelIndex>
+#include <QPainter>
+
+const int kMinimumLineNumberDigits = 6;
+
+namespace Utils {
+
+HighlightingItemDelegate::HighlightingItemDelegate(int tabWidth, QObject *parent)
+ : QItemDelegate(parent)
+{
+ setTabWidth(tabWidth);
+}
+
+void HighlightingItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ static const int iconSize = 16;
+
+ painter->save();
+
+ const QStyleOptionViewItem opt = setOptions(index, option);
+ painter->setFont(opt.font);
+
+ QItemDelegate::drawBackground(painter, opt, index);
+
+ // ---- do the layout
+ QRect checkRect;
+ QRect pixmapRect;
+ QRect textRect;
+
+ // check mark
+ const bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable);
+ Qt::CheckState checkState = Qt::Unchecked;
+ if (checkable) {
+ QVariant checkStateData = index.data(Qt::CheckStateRole);
+ checkState = static_cast<Qt::CheckState>(checkStateData.toInt());
+ checkRect = doCheck(opt, opt.rect, checkStateData);
+ }
+
+ // icon
+ const QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>();
+ if (!icon.isNull()) {
+ const QSize size = icon.actualSize(QSize(iconSize, iconSize));
+ pixmapRect = QRect(0, 0, size.width(), size.height());
+ }
+
+ // text
+ textRect = opt.rect.adjusted(0, 0, checkRect.width() + pixmapRect.width(), 0);
+
+ // do layout
+ doLayout(opt, &checkRect, &pixmapRect, &textRect, false);
+ // ---- draw the items
+ // icon
+ if (!icon.isNull())
+ icon.paint(painter, pixmapRect, option.decorationAlignment);
+
+ // line numbers
+ const int lineNumberAreaWidth = drawLineNumber(painter, opt, textRect, index);
+ textRect.adjust(lineNumberAreaWidth, 0, 0, 0);
+
+ // text and focus/selection
+ drawText(painter, opt, textRect, index);
+ QItemDelegate::drawFocus(painter, opt, opt.rect);
+
+ // check mark
+ if (checkable)
+ QItemDelegate::drawCheck(painter, opt, checkRect, checkState);
+
+ painter->restore();
+}
+
+void HighlightingItemDelegate::setTabWidth(int width)
+{
+ m_tabString = QString(width, ' ');
+}
+
+// returns the width of the line number area
+int HighlightingItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option,
+ const QRect &rect,
+ const QModelIndex &index) const
+{
+ static const int lineNumberAreaHorizontalPadding = 4;
+ const int lineNumber = index.model()->data(index, int(HighlightingItemRole::LineNumber)).toInt();
+ if (lineNumber < 1)
+ return 0;
+ const bool isSelected = option.state & QStyle::State_Selected;
+ const QString lineText = QString::number(lineNumber);
+ const int minimumLineNumberDigits = qMax(kMinimumLineNumberDigits, lineText.count());
+ const int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, '0'));
+ const int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth
+ + lineNumberAreaHorizontalPadding;
+ QRect lineNumberAreaRect(rect);
+ lineNumberAreaRect.setWidth(lineNumberAreaWidth);
+
+ QPalette::ColorGroup cg = QPalette::Normal;
+ if (!(option.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ else if (!(option.state & QStyle::State_Enabled))
+ cg = QPalette::Disabled;
+
+ painter->fillRect(lineNumberAreaRect, QBrush(isSelected ?
+ option.palette.brush(cg, QPalette::Highlight) :
+ option.palette.color(cg, QPalette::Base).darker(111)));
+
+ QStyleOptionViewItem opt = option;
+ opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
+ opt.palette.setColor(cg, QPalette::Text, Qt::darkGray);
+
+ const QStyle *style = QApplication::style();
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1;
+
+ const QRect rowRect
+ = lineNumberAreaRect.adjusted(-textMargin, 0,
+ textMargin - lineNumberAreaHorizontalPadding, 0);
+ QItemDelegate::drawDisplay(painter, opt, rowRect, lineText);
+
+ return lineNumberAreaWidth;
+}
+
+void HighlightingItemDelegate::drawText(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QRect &rect,
+ const QModelIndex &index) const
+{
+ QString text = index.model()->data(index, Qt::DisplayRole).toString();
+ // show number of subresults in displayString
+ if (index.model()->hasChildren(index))
+ text += " (" + QString::number(index.model()->rowCount(index)) + ')';
+
+ int searchTermStart = index.model()->data(index, int(HighlightingItemRole::StartColumn)).toInt();
+ int searchTermLength = index.model()->data(index, int(HighlightingItemRole::Length)).toInt();
+ if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
+ drawDisplay(painter, option, rect, text.replace('\t', m_tabString), {});
+ return;
+ }
+
+ // replace tabs with searchTerm bookkeeping
+ int searchTermEnd = searchTermStart + searchTermLength;
+ const int tabDiff = m_tabString.size() - 1;
+ for (int i = 0; i < text.length(); i++) {
+ if (text.at(i) == '\t') {
+ text.replace(i, 1, m_tabString);
+ if (i < searchTermStart) {
+ searchTermStart += tabDiff;
+ searchTermEnd += tabDiff;
+ } else if (i < searchTermEnd) {
+ searchTermEnd += tabDiff;
+ searchTermLength += tabDiff;
+ }
+ i += tabDiff;
+ }
+ }
+
+ const QColor highlightForeground =
+ index.model()->data(index, int(HighlightingItemRole::Foreground)).value<QColor>();
+ const QColor highlightBackground =
+ index.model()->data(index, int(HighlightingItemRole::Background)).value<QColor>();
+ QTextCharFormat highlightFormat;
+ highlightFormat.setForeground(highlightForeground);
+ highlightFormat.setBackground(highlightBackground);
+
+ drawDisplay(painter, option, rect, text, {{searchTermStart, searchTermLength, highlightFormat}});
+}
+
+// copied from QItemDelegate for drawDisplay
+static QString replaceNewLine(QString text)
+{
+ static const QChar nl = '\n';
+ for (int i = 0; i < text.count(); ++i)
+ if (text.at(i) == nl)
+ text[i] = QChar::LineSeparator;
+ return text;
+}
+
+// copied from QItemDelegate for drawDisplay
+QSizeF doTextLayout(QTextLayout *textLayout, int lineWidth)
+{
+ qreal height = 0;
+ qreal widthUsed = 0;
+ textLayout->beginLayout();
+ while (true) {
+ QTextLine line = textLayout->createLine();
+ if (!line.isValid())
+ break;
+ line.setLineWidth(lineWidth);
+ line.setPosition(QPointF(0, height));
+ height += line.height();
+ widthUsed = qMax(widthUsed, line.naturalTextWidth());
+ }
+ textLayout->endLayout();
+ return QSizeF(widthUsed, height);
+}
+
+// copied from QItemDelegate to be able to add the 'format' parameter
+void HighlightingItemDelegate::drawDisplay(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QRect &rect, const QString &text,
+ const QVector<QTextLayout::FormatRange> &format) const
+{
+ QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
+ ? QPalette::Normal : QPalette::Disabled;
+ if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ if (option.state & QStyle::State_Selected) {
+ painter->fillRect(rect, option.palette.brush(cg, QPalette::Highlight));
+ painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
+ } else {
+ painter->setPen(option.palette.color(cg, QPalette::Text));
+ }
+
+ if (text.isEmpty())
+ return;
+
+ if (option.state & QStyle::State_Editing) {
+ painter->save();
+ painter->setPen(option.palette.color(cg, QPalette::Text));
+ painter->drawRect(rect.adjusted(0, 0, -1, -1));
+ painter->restore();
+ }
+
+ const QStyleOptionViewItem opt = option;
+
+ const QWidget *widget = option.widget;
+ QStyle *style = widget ? widget->style() : QApplication::style();
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
+ QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
+ const bool wrapText = opt.features & QStyleOptionViewItem::WrapText;
+ QTextOption textOption;
+ textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
+ textOption.setTextDirection(option.direction);
+ textOption.setAlignment(QStyle::visualAlignment(option.direction, option.displayAlignment));
+ QTextLayout textLayout;
+ textLayout.setTextOption(textOption);
+ textLayout.setFont(option.font);
+ textLayout.setText(replaceNewLine(text));
+
+ QSizeF textLayoutSize = doTextLayout(&textLayout, textRect.width());
+
+ if (textRect.width() < textLayoutSize.width()
+ || textRect.height() < textLayoutSize.height()) {
+ QString elided;
+ int start = 0;
+ int end = text.indexOf(QChar::LineSeparator, start);
+ if (end == -1) {
+ elided += option.fontMetrics.elidedText(text, option.textElideMode, textRect.width());
+ } else {
+ while (end != -1) {
+ elided += option.fontMetrics.elidedText(text.mid(start, end - start),
+ option.textElideMode, textRect.width());
+ elided += QChar::LineSeparator;
+ start = end + 1;
+ end = text.indexOf(QChar::LineSeparator, start);
+ }
+ // let's add the last line (after the last QChar::LineSeparator)
+ elided += option.fontMetrics.elidedText(text.mid(start),
+ option.textElideMode, textRect.width());
+ }
+ textLayout.setText(elided);
+ textLayoutSize = doTextLayout(&textLayout, textRect.width());
+ }
+
+ const QSize layoutSize(textRect.width(), int(textLayoutSize.height()));
+ const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment,
+ layoutSize, textRect);
+ // if we still overflow even after eliding the text, enable clipping
+ if (!hasClipping() && (textRect.width() < textLayoutSize.width()
+ || textRect.height() < textLayoutSize.height())) {
+ painter->save();
+ painter->setClipRect(layoutRect);
+ textLayout.draw(painter, layoutRect.topLeft(), format, layoutRect);
+ painter->restore();
+ } else {
+ textLayout.draw(painter, layoutRect.topLeft(), format, layoutRect);
+ }
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/highlightingitemdelegate.h b/src/libs/utils/highlightingitemdelegate.h
new file mode 100644
index 00000000000..b9cfb617ddf
--- /dev/null
+++ b/src/libs/utils/highlightingitemdelegate.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "utils_global.h"
+
+#include <QItemDelegate>
+#include <QTextLayout>
+
+namespace Utils {
+
+enum class HighlightingItemRole {
+ LineNumber = Qt::UserRole,
+ StartColumn,
+ Length,
+ Foreground,
+ Background,
+ User
+};
+
+class QTCREATOR_UTILS_EXPORT HighlightingItemDelegate : public QItemDelegate
+{
+public:
+ HighlightingItemDelegate(int tabWidth, QObject *parent = 0);
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ void setTabWidth(int width);
+
+private:
+ int drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const;
+ void drawText(QPainter *painter, const QStyleOptionViewItem &option,
+ const QRect &rect, const QModelIndex &index) const;
+ using QItemDelegate::drawDisplay;
+ void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect,
+ const QString &text, const QVector<QTextLayout::FormatRange> &format) const;
+ QString m_tabString;
+};
+
+} // namespace Utils
diff --git a/src/libs/utils/icon.cpp b/src/libs/utils/icon.cpp
index e3a9a92ee89..f451d9697e2 100644
--- a/src/libs/utils/icon.cpp
+++ b/src/libs/utils/icon.cpp
@@ -36,6 +36,7 @@
#include <QPainter>
#include <QPaintEngine>
#include <QWidget>
+#include <QDebug>
namespace Utils {
@@ -67,7 +68,12 @@ static MasksAndColors masksAndColors(const Icon &icon, int dpr)
const QColor color = creatorTheme()->color(i.second);
const QString dprFileName = StyleHelper::availableImageResolutions(i.first).contains(dpr) ?
StyleHelper::imageFileWithResolution(fileName, dpr) : fileName;
- result.append(qMakePair(QPixmap(dprFileName), color));
+ QPixmap pixmap;
+ if (!pixmap.load(dprFileName)) {
+ pixmap = QPixmap(1, 1);
+ qWarning() << "Could not load image: " << dprFileName;
+ }
+ result.append({pixmap, color});
}
return result;
}
diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp
index b69bfe6f971..f2a13991cb2 100644
--- a/src/libs/utils/stringutils.cpp
+++ b/src/libs/utils/stringutils.cpp
@@ -28,8 +28,11 @@
#include "hostosinfo.h"
#include <utils/algorithm.h>
+#include <utils/qtcassert.h>
#include <QDir>
+#include <QJsonArray>
+#include <QJsonValue>
#include <QRegularExpression>
#include <QSet>
@@ -246,4 +249,24 @@ QTCREATOR_UTILS_EXPORT QString stripAccelerator(const QString &text)
return res;
}
+QTCREATOR_UTILS_EXPORT bool readMultiLineString(const QJsonValue &value, QString *out)
+{
+ QTC_ASSERT(out, return false);
+ if (value.isString()) {
+ *out = value.toString();
+ } else if (value.isArray()) {
+ QJsonArray array = value.toArray();
+ QStringList lines;
+ foreach (const QJsonValue &v, array) {
+ if (!v.isString())
+ return false;
+ lines.append(v.toString());
+ }
+ *out = lines.join(QLatin1Char('\n'));
+ } else {
+ return false;
+ }
+ return true;
+}
+
} // namespace Utils
diff --git a/src/libs/utils/stringutils.h b/src/libs/utils/stringutils.h
index 8ff42bac6a4..0723e76656f 100644
--- a/src/libs/utils/stringutils.h
+++ b/src/libs/utils/stringutils.h
@@ -28,6 +28,7 @@
#include "utils_global.h"
QT_BEGIN_NAMESPACE
+class QJsonValue;
class QStringList;
QT_END_NAMESPACE
@@ -53,6 +54,8 @@ QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path);
// Removes first unescaped ampersand in text
QTCREATOR_UTILS_EXPORT QString stripAccelerator(const QString &text);
+QTCREATOR_UTILS_EXPORT bool readMultiLineString(const QJsonValue &value, QString *out);
+
class QTCREATOR_UTILS_EXPORT AbstractMacroExpander
{
public:
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 3a6aa0a09af..578e0a8d5e4 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -113,7 +113,8 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/port.cpp \
$$PWD/runextensions.cpp \
$$PWD/utilsicons.cpp \
- $$PWD/guard.cpp
+ $$PWD/guard.cpp \
+ $$PWD/highlightingitemdelegate.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
@@ -239,8 +240,9 @@ HEADERS += \
$$PWD/asconst.h \
$$PWD/smallstringfwd.h \
$$PWD/optional.h \
+ $$PWD/../3rdparty/optional/optional.hpp \
$$PWD/qtcfallthrough.h \
- $$PWD/../3rdparty/optional/optional.hpp
+ $$PWD/highlightingitemdelegate.cpp
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index 6d68683fdd5..0c0562acaf7 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -117,6 +117,8 @@ Project {
"functiontraits.h",
"guard.cpp",
"guard.h",
+ "highlightingitemdelegate.cpp",
+ "highlightingitemdelegate.h",
"historycompleter.cpp",
"historycompleter.h",
"hostosinfo.h",