Merge remote-tracking branch 'origin/4.1'

Change-Id: Ic8d82172a97bdf1dbf3d047157cc2c8d853f35cc
This commit is contained in:
Eike Ziller
2016-06-28 12:13:33 +02:00
186 changed files with 1784 additions and 1045 deletions

View File

@@ -5,6 +5,7 @@ QtcProduct {
type: ["dynamiclibrary", "dynamiclibrary_symlink", "qtc.dev-module"]
installDir: qtc.ide_library_path
installTags: ["dynamiclibrary", "dynamiclibrary_symlink"]
useNonGuiPchFile: true
Depends {
condition: qtc.testsEnabled
name: "Qt.test"

View File

@@ -6,6 +6,7 @@ QtcProduct {
type: ["dynamiclibrary", "pluginSpec", "qtc.dev-module"]
installDir: qtc.ide_plugin_path
installTags: ["dynamiclibrary"]
useGuiPchFile: true
property var pluginJsonReplacements
property var pluginRecommends: []

View File

@@ -9,6 +9,11 @@ Product {
property string installDir
property stringList installTags: type
property string fileName: FileInfo.fileName(sourceDirectory) + ".qbs"
property bool useNonGuiPchFile: false
property bool useGuiPchFile: false
property string pathToSharedSources: FileInfo.joinPaths(path,
FileInfo.relativePath(FileInfo.joinPaths('/', qtc.ide_qbs_imports_path),
FileInfo.joinPaths('/', qtc.ide_shared_sources_path)))
Depends { name: "cpp" }
Depends { name: "qtc" }
@@ -24,6 +29,7 @@ Product {
}
cpp.minimumOsxVersion: "10.7"
cpp.minimumWindowsVersion: qbs.architecture === "x86" ? "5.1" : "5.2"
cpp.useCxxPrecompiledHeader: useNonGuiPchFile || useGuiPchFile
cpp.visibility: "minimal"
Depends { name: "Qt.core" }
@@ -39,4 +45,20 @@ Product {
qbs.install: true
qbs.installDir: qtc.ide_qbs_modules_path + '/' + product.name
}
Group {
name: "standard pch file (non-gui)"
condition: useNonGuiPchFile
prefix: pathToSharedSources + '/'
files: ["qtcreator_pch.h"]
fileTags: ["cpp_pch_src"]
}
Group {
name: "standard pch file (gui)"
condition: useGuiPchFile
prefix: pathToSharedSources + '/'
files: ["qtcreator_gui_pch.h"]
fileTags: ["cpp_pch_src"]
}
}

View File

@@ -5,6 +5,7 @@ QtcProduct {
type: ["application"]
consoleApplication: true
installDir: qtc.ide_libexec_path
useNonGuiPchFile: true
cpp.rpaths: {
var relativePathToLibs = FileInfo.relativePath('/' + qtc.ide_libexec_path,

0
qbs/imports/src Normal file
View File

View File

@@ -51,6 +51,7 @@ Module {
property string ide_qbs_resources_path: "qbs-resources"
property string ide_qbs_modules_path: ide_qbs_resources_path + "/modules"
property string ide_qbs_imports_path: ide_qbs_resources_path + "/imports"
property string ide_shared_sources_path: "src/shared"
property bool make_dev_package: false

View File

@@ -65,7 +65,7 @@ void BehaviorNodeInstance::resetProperty(const PropertyName &name)
PropertyNameList BehaviorNodeInstance::ignoredProperties() const
{
return PropertyNameList() << "enabled";
return PropertyNameList({"enabled"});
}

View File

@@ -70,7 +70,8 @@ void LayoutNodeInstance::refreshLayoutable()
PropertyNameList LayoutNodeInstance::ignoredProperties() const
{
return PropertyNameList() << "move" << "add" << "populate";
static const PropertyNameList properties({"move", "add", "populate"});
return properties;
}
}

View File

@@ -76,8 +76,8 @@ void PositionerNodeInstance::refreshLayoutable()
PropertyNameList PositionerNodeInstance::ignoredProperties() const
{
return PropertyNameList() << "move" << "add" << "populate";
}
static const PropertyNameList properties({"move", "add", "populate"});
return properties;
}
} // namespace Internal
} // namespace QmlDesigner

View File

@@ -52,7 +52,8 @@ bool QmlTransitionNodeInstance::isTransition() const
PropertyNameList QmlTransitionNodeInstance::ignoredProperties() const
{
return PropertyNameList() << "from" << "to";
static const PropertyNameList properties({"from", "to"});
return properties;
}
}

View File

@@ -734,15 +734,15 @@ bool QuickItemNodeInstance::hasAnchor(const PropertyName &name) const
static bool isValidAnchorName(const PropertyName &name)
{
static PropertyNameList anchorNameList(PropertyNameList() << "anchors.top"
<< "anchors.left"
<< "anchors.right"
<< "anchors.bottom"
<< "anchors.verticalCenter"
<< "anchors.horizontalCenter"
<< "anchors.fill"
<< "anchors.centerIn"
<< "anchors.baseline");
static PropertyNameList anchorNameList({"anchors.top",
"anchors.left",
"anchors.right",
"anchors.bottom",
"anchors.verticalCenter",
"anchors.horizontalCenter",
"anchors.fill",
"anchors.centerIn",
"anchors.baseline"});
return anchorNameList.contains(name);
}

View File

@@ -392,7 +392,7 @@ QVariant fixResourcePaths(const QVariant &value)
if (QFileInfo(fixedPath).exists()) {
fixedPath.replace(QLatin1String("//"), QLatin1String("/"));
fixedPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
return QUrl(fixedPath);
return QUrl::fromLocalFile(fixedPath);
}
}
}

View File

@@ -105,7 +105,7 @@ QVariant fixResourcePaths(const QVariant &value)
if (QFileInfo(fixedPath).exists()) {
fixedPath.replace(QLatin1String("//"), QLatin1String("/"));
fixedPath.replace(QLatin1Char('\\'), QLatin1Char('/'));
return QUrl(fixedPath);
return QUrl::fromLocalFile(fixedPath);
}
}
}

View File

@@ -34,6 +34,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-top.png"
tooltip: qsTr("Anchor item to the top.")
property bool topAnchored: anchorBackend.topAnchored
onTopAnchoredChanged: {
@@ -53,6 +54,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-bottom.png"
tooltip: qsTr("Anchor item to the bottom.")
property bool bottomAnchored: anchorBackend.bottomAnchored
onBottomAnchoredChanged: {
@@ -73,6 +75,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-left.png"
tooltip: qsTr("Anchor item to the left.")
property bool leftAnchored: anchorBackend.leftAnchored
onLeftAnchoredChanged: {
@@ -92,6 +95,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-right.png"
tooltip: qsTr("Anchor item to the right.")
property bool rightAnchored: anchorBackend.rightAnchored
onRightAnchoredChanged: {
@@ -116,6 +120,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-fill.png"
tooltip: qsTr("Fill parent item.")
property bool isFilled: anchorBackend.isFilled
onIsFilledChanged: {
@@ -137,6 +142,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-vertical.png"
tooltip: qsTr("Anchor item vertically.")
property bool verticalCentered: anchorBackend.verticalCentered;
onVerticalCenteredChanged: {
@@ -158,6 +164,7 @@ ButtonRow {
ButtonRowButton {
iconSource: "images/anchor-horizontal.png"
tooltip: qsTr("Anchor item horizontally.")
property bool horizontalCentered: anchorBackend.horizontalCentered;
onHorizontalCenteredChanged: {

View File

@@ -32,6 +32,8 @@ Controls.Label {
id: label
property alias tooltip: toolTipArea.tooltip
// workaround because PictureSpecifics.qml still use this
property alias toolTip: toolTipArea.tooltip
width: Math.max(Math.min(240, parent.width - 220), 80)
color: "#eee"

View File

@@ -126,6 +126,7 @@ RowLayout {
exclusive: true
ButtonRowButton {
iconSource: verticalAnchor ? "../HelperWidgets/images/anchor-top.png" : "../HelperWidgets/images/anchor-left.png"
tooltip: verticalAnchor ? qsTr("Anchor to the top of the target.") : qsTr("Anchor to the left of the target.")
onClicked: {
if (!invertRelativeTargets)
sameEdgeButtonClicked();
@@ -136,12 +137,14 @@ RowLayout {
ButtonRowButton {
iconSource: verticalAnchor ? "../HelperWidgets/images/anchor-vertical.png" : "../HelperWidgets/images/anchor-horizontal.png"
tooltip: verticalAnchor ? qsTr("Anchor to the vertical center of the target.") : qsTr("Anchor to the horizontal center of the target.")
onClicked: centerButtonClicked();
}
ButtonRowButton {
iconSource: verticalAnchor ? "../HelperWidgets/images/anchor-bottom.png" : "../HelperWidgets/images/anchor-right.png"
tooltip: verticalAnchor ? qsTr("Anchor to the bottom of the target.") : qsTr("Anchor to the right of the target.")
onClicked: {
if (!invertRelativeTargets)
oppositeEdgeButtonClicked();

View File

@@ -1,3 +0,0 @@
TEMPLATE = subdirs
SUBDIRS += %TestCaseName:l%

View File

@@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS += %{JS: '%{TestCaseName}'.toLowerCase()}

View File

@@ -0,0 +1,31 @@
isEmpty(GOOGLETEST_DIR):GOOGLETEST_DIR=$$(GOOGLETEST_DIR)
isEmpty(GOOGLETEST_DIR) {
warning("Using googletest src dir specified at Qt Creator wizard")
message("set GOOGLETEST_DIR as environment variable or qmake variable to get rid of this message")
GOOGLETEST_DIR = %{GTestRepository}
}
!isEmpty(GOOGLETEST_DIR): {
GTEST_SRCDIR = $$GOOGLETEST_DIR/googletest
GMOCK_SRCDIR = $$GOOGLETEST_DIR/googlemock
}
requires(exists($$GTEST_SRCDIR):exists($$GMOCK_SRCDIR))
!exists($$GOOGLETEST_DIR):message("No googletest src dir found - set GOOGLETEST_DIR to enable.")
@if "%{GTestCXX11}" == "true"
DEFINES += \\
GTEST_LANG_CXX11
@endif
INCLUDEPATH *= \\
$$GTEST_SRCDIR \\
$$GTEST_SRCDIR/include \\
$$GMOCK_SRCDIR \\
$$GMOCK_SRCDIR/include
SOURCES += \\
$$GTEST_SRCDIR/src/gtest-all.cc \\
$$GMOCK_SRCDIR/src/gmock-all.cc

View File

@@ -0,0 +1,31 @@
%{Cpp:LicenseTemplate}\
@if "%{TestFrameWork}" == "QtTest"
@if "%{RequireGUI}" == "true"
%{JS: QtSupport.qtIncludes([ 'QtGui/QApplication' ],
[ 'QtWidgets/QApplication' ]) }\
@else
%{JS: QtSupport.qtIncludes([ 'QtCore/QCoreApplication' ],
[ 'QtCore/QCoreApplication' ]) }\
@endif
// add necessary includes here
int main(int argc, char *argv[])
{
@if "%{RequireGUI}" == "true"
QApplication a(argc, argv);
@else
QCoreApplication a(argc, argv);
@endif
return a.exec();
}
@else
#include <iostream>
int main(int , char **)
{
std::cout << "Hello World!\\n";
return 0;
}
@endif

View File

@@ -1,13 +1,18 @@
@if "%RequireGUI%" == "true"
@if "%{TestFrameWork}" == "QtTest"
@if "%{RequireGUI}" == "true"
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
@else
QT -= gui
@endif
@else
CONFIG -= qt
@endif
CONFIG += console
CONFIG -= app_bundle
@endif
TEMPLATE = app
TARGET = %ProjectName%
SOURCES += main.%CppSourceSuffix%
TARGET = %{ProjectName}
SOURCES += %{MainCppName}

View File

@@ -1,6 +1,6 @@
TEMPLATE = subdirs
@if "%BuildTests%" == "always"
@if "%{BuildTests}" == "always"
SUBDIRS += src \
tests
@else

View File

@@ -0,0 +1,34 @@
@if "%{TestFrameWork}" == "QtTest"
QT += testlib
@if "%{RequireGUI}" == "false"
QT -= gui
CONFIG += qt console warn_on depend_includepath testcase
CONFIG -= app_bundle
@else
QT += gui
CONFIG += qt warn_on depend_includepath testcase
@endif
TEMPLATE = app
SOURCES += %{TestCaseFileWithCppSuffix}
@else
include(../gtest_dependency.pri)
TEMPLATE = app
@if "%{GTestCXX11}" == "true"
CONFIG += console c++11
@else
CONFIG += console
@endif
CONFIG -= app_bundle
CONFIG += thread
CONFIG -= qt
HEADERS += \
%{TestCaseFileWithHeaderSuffix}
SOURCES += \
%{MainCppName}
@endif

View File

@@ -0,0 +1,10 @@
%{Cpp:LicenseTemplate}\
#include "%{TestCaseFileWithHeaderSuffix}"
#include <gtest/gtest.h>
int main(int argc, char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,60 @@
%{Cpp:LicenseTemplate}\
#include <QtTest>
@if "%{RequireApplication}" == "true"
%{JS: QtSupport.qtIncludes([ 'QtCore/QCoreApplication' ],
[ 'QtCore/QCoreApplication' ]) }\
@endif
// add necessary includes here
class %{TestCaseName} : public QObject
{
Q_OBJECT
public:
%{TestCaseName}();
~%{TestCaseName}();
private slots:
@if "%{GenerateInitAndCleanup}" == "true"
void initTestCase();
void cleanupTestCase();
@endif
void test_case1();
};
%{TestCaseName}::%{TestCaseName}()
{
}
%{TestCaseName}::~%{TestCaseName}()
{
}
@if "%{GenerateInitAndCleanup}" == "true"
void %{TestCaseName}::initTestCase()
{
}
void %{TestCaseName}::cleanupTestCase()
{
}
@endif
void %{TestCaseName}::test_case1()
{
}
@if "%{RequireApplication}" == "true"
QTEST_MAIN(%{TestCaseName})
@else
QTEST_APPLESS_MAIN(%{TestCaseName})
@endif
#include "%{JS: 'tst_%{TestCaseName}.moc'.toLowerCase() }"

View File

@@ -0,0 +1,11 @@
%{Cpp:LicenseTemplate}\
#include <gtest/gtest.h>
#include <gmock/gmock-matchers.h>
using namespace testing;
TEST(%{TestCaseName}, %{TestSetName})
{
EXPECT_EQ(1, 1);
ASSERT_THAT(0, Eq(0));
}

View File

@@ -1,18 +0,0 @@
@if "%RequireGUI%" == "true"
#include <QApplication>
@else
#include <QCoreApplication>
@endif
// add necessary includes here
int main(int argc, char *argv[])
{
@if "%RequireGUI%" == "true"
QApplication a(argc, argv);
@else
QCoreApplication a(argc, argv);
@endif
return a.exec();
}

View File

@@ -1,14 +0,0 @@
QT += testlib
@if "%RequireGUI%" == "false"
QT -= gui
CONFIG += qt console warn_on depend_includepath testcase
CONFIG -= app_bundle
@else
QT += gui
CONFIG += qt warn_on depend_includepath testcase
@endif
TEMPLATE = app
SOURCES += tst_%TestCaseName:l%.%CppSourceSuffix%

View File

@@ -1,58 +0,0 @@
#include <QtTest>
@if "%RequireApplication%" == "true"
#include <QCoreApplication>
@endif
// add necessary includes here
class %TestCaseName% : public QObject
{
Q_OBJECT
public:
%TestCaseName%();
~%TestCaseName%();
private slots:
@if "%GenerateInitAndCleanup%" == "true"
void initTestCase();
void cleanupTestCase();
@endif
void test_case1();
};
%TestCaseName%::%TestCaseName%()
{
}
%TestCaseName%::~%TestCaseName%()
{
}
@if "%GenerateInitAndCleanup%" == "true"
void %TestCaseName%::initTestCase()
{
}
void %TestCaseName%::cleanupTestCase()
{
}
@endif
void %TestCaseName%::test_case1()
{
}
@if "%RequireApplication%" == "true"
QTEST_MAIN(%TestCaseName%)
@else
QTEST_APPLESS_MAIN(%TestCaseName%)
@endif
#include "tst_%TestCaseName:l%.moc"

View File

@@ -0,0 +1,241 @@
{
"version": 1,
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
"id": "R.AutoTest",
"category": "H.Project",
"trDescription": "Creates a new project including auto test skeleton.",
"trDisplayName": "Auto Test Project",
"trDisplayCategory": "Other Project",
"icon": "autotest_24.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt", "QtSupport.Wizards.FeatureDesktop" ],
"enabled": "%{JS: [ %{Plugins} ].indexOf('AutoTest') >= 0}",
"options":
[
{ "key": "ProFileName",
"value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}"
},
{ "key": "IsTopLevelProject",
"value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }"
},
{ "key": "MainCppName",
"value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }"
},
{
"key": "TestCaseFileWithHeaderSuffix",
"value": "%{JS: 'tst_%{TestCaseName}.'.toLowerCase() + Util.preferredSuffix('text/x-c++hdr') }"
},
{
"key": "TestCaseFileWithCppSuffix",
"value": "%{JS: 'tst_%{TestCaseName}.'.toLowerCase() + Util.preferredSuffix('text/x-c++src') }"
}
],
"pages":
[
{
"trDisplayName": "Project Location",
"trShortTitle": "Location",
"typeId": "Project",
"data":
{
"trDescription": "This wizard creates a simple Qmake based project with additional auto test skeleton."
}
},
{
"trDisplayName": "Project and Test Information",
"trShortTitle": "Details",
"typeId": "Fields",
"data":
[
{
"name": "TestFrameWork",
"trDisplayName": "Test Framework:",
"type": "ComboBox",
"data":
{
"index": 0,
"items":
[
{
"trKey": "Qt Test",
"value": "QtTest"
},
{
"trKey": "Googletest",
"value": "GTest"
}
]
}
},
{
"name": "RequireGUI",
"trDisplayName": "GUI Application",
"visible": "%{JS: '%{TestFrameWork}' === 'QtTest'}",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": "true",
"uncheckedValue": "false"
}
},
{
"name": "TestCaseName",
"trDisplayName": "Test Case Name:",
"mandatory": true,
"type": "LineEdit",
"data": { "validator": "^[a-zA-Z_0-9]+$" }
},
{
"name": "RequireApplication",
"trDisplayName": "Requires QApplication",
"visible": "%{JS: '%{TestFrameWork}' === 'QtTest'}",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": "true",
"uncheckedValue": "false"
}
},
{
"name": "GenerateInitAndCleanup",
"trDisplayName": "Generate initialization and cleanup code",
"visible": "%{JS: '%{TestFrameWork}' === 'QtTest'}",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": "true",
"uncheckedValue": "false"
}
},
{
"name": "TestSetName",
"trDisplayName": "Test Set Name:",
"visible": "%{JS: '%{TestFrameWork}' === 'GTest'}",
"type": "LineEdit",
"data": { "validator": "^[a-zA-Z0-9]+$" }
},
{
"name": "GTestCXX11",
"trDisplayName": "Enable C++11",
"visible": "%{JS: '%{TestFrameWork}' === 'GTest'}",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": "true",
"uncheckedValue": "false"
}
},
{
"name": "BuildAutoTests",
"trDisplayName": "Build auto tests",
"type": "ComboBox",
"data":
{
"index": 0,
"items":
[
{
"trKey": "always",
"value": "always"
},
{
"trKey": "debug only",
"value": "debug"
}
]
}
},
{
"name": "GTestRepository",
"trDisplayName": "Googletest repository:",
"visible": "%{JS: '%{TestFrameWork}' === 'GTest'}",
"type": "PathChooser",
"data": {
"kind": "existingDirectory"
}
}
]
},
{
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
"enabled": "%{IsTopLevelProject}",
"data": { "projectFilePath": "%{ProFileName}" }
},
{
"trDisplayName": "Project Management",
"trShortTitle": "Summary",
"typeId": "Summary"
}
],
"generators":
[
{
"typeId": "File",
"data":
[
{
"source": "files/tmp.pro",
"target": "%{ProFileName}",
"openAsProject": true
},
{
"source": "files/src.pro",
"target": "src/src.pro",
"openInEditor": false
},
{
"source": "files/main.cpp",
"target": "src/%{MainCppName}",
"openInEditor": true
},
{
"source": "files/tests.pro",
"target": "tests/tests.pro",
"openInEditor": false
},
{
"source": "files/auto.pro",
"target": "tests/auto/auto.pro",
"openInEditor": false
},
{
"source": "files/gtest_dependency.pri",
"target": "tests/auto/gtest_dependency.pri",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest'}",
"openInEditor": false
},
{
"source": "files/tst.pro",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/%{TestCaseName}'.toLowerCase() + '.pro' }",
"openInEditor": false
},
{
"source": "files/tst_src.h",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/'.toLowerCase() + '%{TestCaseFileWithHeaderSuffix}' }",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest'}",
"openInEditor": true
},
{
"source": "files/tst_src.cpp",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/'.toLowerCase() + '%{TestCaseFileWithCppSuffix}' }",
"condition": "%{JS: '%{TestFrameWork}' == 'QtTest'}",
"openInEditor": true
},
{
"source": "files/tst_main.cpp",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}'.toLowerCase() + '/%{MainCppName}' }",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest'}",
"openInEditor": true
},
{
"source": "../projects/git.ignore",
"target": ".gitignore",
"condition": "%{JS: ( %{IsTopLevelProject} && '%{VersionControl}' === 'G.Git' )}"
}
]
}
]
}

View File

@@ -1,83 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/****************************************************************************
**
** Copyright (C) 2016 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.
**
****************************************************************************/
-->
<wizard version="1" kind="project"
class="qmakeproject" firstpage="10"
id="R.AutoTest" category="H.Project"
featuresRequired="QtSupport.Wizards.FeatureQt,QtSupport.Wizards.FeatureDesktop">
<!-- "Plugin.AutotestGenerator" as required feature would disable the template if the
plugin is disabled, but it fails on the kit selection page for having no valid kit -->
<icon>autotest_24.png</icon>
<description>Creates a new project including auto test skeleton.</description>
<displayname>Auto Test</displayname>;
<displaycategory>Other Project</displaycategory>
<files>
<file source="src.pro" target="src/src.pro" />
<file source="tests.pro" target="tests/tests.pro" />
<file source="auto.pro" target="tests/auto/auto.pro"/>
<file source="tst.pro" target="tests/auto/%TestCaseName:l%/%TestCaseName:l%.pro" />
<file source="tst_src.cpp"
target="tests/auto/%TestCaseName:l%/tst_%TestCaseName:l%.%CppSourceSuffix%"
openeditor="true"/>
<file source="main.cpp" target="src/main.%CppSourceSuffix%" openeditor="true" />
<file source="tmp.pro" target="%ProjectName:l%.pro" openproject="true" />
</files>
<!-- Create a 2nd wizard page with parameters -->
<fieldpagetitle>Project and Test Information</fieldpagetitle>
<fields>
<field name="RequireGUI">
<fieldcontrol class="QCheckBox" />
<fielddescription>GUI Application</fielddescription>
</field>
<field mandatory="true" name="TestCaseName">
<fieldcontrol class="QLineEdit" validator="^[a-zA-Z_0-9]+$"
/><!-- defaulttext="" /> -->
<fielddescription>Test Case Name:</fielddescription>
</field>
<field name="RequireApplication">
<fieldcontrol class="QCheckBox" />
<fielddescription>Requires QApplication</fielddescription>
</field>
<field name="GenerateInitAndCleanup">
<fieldcontrol class="QCheckBox" />
<fielddescription>Generate initialization and cleanup code</fielddescription>
</field>
<field name="BuildAutoTests">
<fieldcontrol class="QComboBox" defaultindex="0" >
<comboentries>
<comboentry value="always" >
<comboentrytext>always</comboentrytext>
</comboentry>
<comboentry value="debug" >
<comboentrytext>debug only</comboentrytext>
</comboentry>
</comboentries>
</fieldcontrol>
<fielddescription>Build auto tests</fielddescription>
</field>
</fields>
</wizard>

View File

@@ -112,10 +112,10 @@ bool OptionsParser::checkForTestOptions()
if (m_currentArg == QLatin1String(TEST_OPTION)) {
if (nextToken(RequiredToken)) {
if (m_currentArg == QLatin1String("all")) {
foreach (PluginSpec *spec, m_pmPrivate->pluginSpecs) {
if (spec && !m_pmPrivate->containsTestSpec(spec))
m_pmPrivate->testSpecs.append(PluginManagerPrivate::TestSpec(spec));
}
m_pmPrivate->testSpecs =
Utils::transform(m_pmPrivate->loadQueue(), [](PluginSpec *spec) {
return PluginManagerPrivate::TestSpec(spec);
});
} else {
QStringList args = m_currentArg.split(QLatin1Char(','));
const QString pluginName = args.takeFirst();

View File

@@ -29,6 +29,8 @@
#include "pluginmanager.h"
#include "pluginspec.h"
#include <utils/algorithm.h>
#include <QDir>
#include <QRegExp>
@@ -88,23 +90,6 @@ void PluginDetailsView::update(PluginSpec *spec)
const QString platformString = tr("%1 (current: \"%2\")").arg(pluginPlatformString,
PluginManager::platformName());
m_ui->platforms->setText(platformString);
QStringList depStrings;
foreach (const PluginDependency &dep, spec->dependencies()) {
QString depString = dep.name;
depString += QLatin1String(" (");
depString += dep.version;
switch (dep.type) {
case PluginDependency::Required:
break;
case PluginDependency::Optional:
depString += QLatin1String(", optional");
break;
case PluginDependency::Test:
depString += QLatin1String(", test");
break;
}
depString += QLatin1Char(')');
depStrings.append(depString);
}
const QStringList depStrings = Utils::transform<QList>(spec->dependencies(), &PluginDependency::toString);
m_ui->dependencies->addItems(depStrings);
}

View File

@@ -369,12 +369,10 @@ void PluginManager::loadPlugins()
*/
bool PluginManager::hasError()
{
foreach (PluginSpec *spec, plugins()) {
return Utils::anyOf(plugins(), [](PluginSpec *spec) {
// only show errors on startup if plugin is enabled.
if (spec->hasError() && spec->isEffectivelyEnabled())
return true;
}
return false;
return spec->hasError() && spec->isEffectivelyEnabled();
});
}
/*!
@@ -382,19 +380,11 @@ bool PluginManager::hasError()
*/
QSet<PluginSpec *> PluginManager::pluginsRequiringPlugin(PluginSpec *spec)
{
QSet<PluginSpec *> dependingPlugins;
QSet<PluginSpec *> dependingPlugins({spec});
// recursively add plugins that depend on plugins that.... that depend on spec
foreach (PluginSpec *spec, d->loadQueue()) {
if (spec->requiresAny(dependingPlugins))
dependingPlugins.insert(spec);
foreach (PluginSpec *checkSpec, d->loadQueue()) {
QHashIterator<PluginDependency, PluginSpec *> depIt(checkSpec->dependencySpecs());
while (depIt.hasNext()) {
depIt.next();
if (depIt.key().type != PluginDependency::Required)
continue;
if (dependingPlugins.contains(depIt.value())) {
dependingPlugins.insert(checkSpec);
break; // no use to check other dependencies, continue with load queue
}
}
}
dependingPlugins.remove(spec);
return dependingPlugins;
@@ -665,9 +655,7 @@ bool PluginManager::parseOptions(const QStringList &args,
static inline void indent(QTextStream &str, int indent)
{
const QChar blank = QLatin1Char(' ');
for (int i = 0 ; i < indent; i++)
str << blank;
str << QString(indent, ' ');
}
static inline void formatOption(QTextStream &str,
@@ -927,12 +915,9 @@ void PluginManagerPrivate::stopAll()
*/
void PluginManagerPrivate::deleteAll()
{
QList<PluginSpec *> queue = loadQueue();
QListIterator<PluginSpec *> it(queue);
it.toBack();
while (it.hasPrevious()) {
loadPlugin(it.previous(), PluginSpec::Deleted);
}
Utils::reverseForeach(loadQueue(), [this](PluginSpec *spec) {
loadPlugin(spec, PluginSpec::Deleted);
});
}
#ifdef WITH_TESTS
@@ -1225,10 +1210,7 @@ void PluginManagerPrivate::loadPlugins()
foreach (PluginSpec *spec, queue) {
loadPlugin(spec, PluginSpec::Initialized);
}
QListIterator<PluginSpec *> it(queue);
it.toBack();
while (it.hasPrevious()) {
PluginSpec *spec = it.previous();
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
loadPlugin(spec, PluginSpec::Running);
if (spec->state() == PluginSpec::Running) {
delayedInitializeQueue.append(spec);
@@ -1236,7 +1218,7 @@ void PluginManagerPrivate::loadPlugins()
// Plugin initialization failed, so cleanup after it
spec->d->kill();
}
}
});
emit q->pluginsChanged();
delayedInitializeTimer = new QTimer;
@@ -1420,6 +1402,21 @@ void PluginManagerPrivate::setPluginPaths(const QStringList &paths)
readPluginPaths();
}
static QStringList pluginFiles(const QStringList &pluginPaths)
{
QStringList pluginFiles;
QStringList searchPaths = pluginPaths;
while (!searchPaths.isEmpty()) {
const QDir dir(searchPaths.takeFirst());
const QFileInfoList files = dir.entryInfoList(QDir::Files | QDir::NoSymLinks);
const QStringList absoluteFilePaths = Utils::transform(files, &QFileInfo::absoluteFilePath);
pluginFiles += Utils::filtered(absoluteFilePaths, [](const QString &path) { return QLibrary::isLibrary(path); });
const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
searchPaths += Utils::transform(dirs, &QFileInfo::absoluteFilePath);
}
return pluginFiles;
}
/*!
\internal
*/
@@ -1430,24 +1427,10 @@ void PluginManagerPrivate::readPluginPaths()
pluginSpecs.clear();
pluginCategories.clear();
QStringList pluginFiles;
QStringList searchPaths = pluginPaths;
while (!searchPaths.isEmpty()) {
const QDir dir(searchPaths.takeFirst());
const QFileInfoList files = dir.entryInfoList(QDir::Files | QDir::NoSymLinks);
foreach (const QFileInfo &file, files) {
const QString filePath = file.absoluteFilePath();
if (QLibrary::isLibrary(filePath))
pluginFiles.append(filePath);
}
const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
foreach (const QFileInfo &subdir, dirs)
searchPaths << subdir.absoluteFilePath();
}
defaultCollection = new PluginCollection(QString());
auto defaultCollection = new PluginCollection(QString());
pluginCategories.insert(QString(), defaultCollection);
foreach (const QString &pluginFile, pluginFiles) {
foreach (const QString &pluginFile, pluginFiles(pluginPaths)) {
PluginSpec *spec = new PluginSpec;
if (!spec->d->read(pluginFile)) { // not a Qt Creator plugin
delete spec;
@@ -1492,12 +1475,9 @@ void PluginManagerPrivate::resolveDependencies()
spec->d->resolveDependencies(pluginSpecs);
}
QListIterator<PluginSpec *> it(loadQueue());
it.toBack();
while (it.hasPrevious()) {
PluginSpec *spec = it.previous();
Utils::reverseForeach(loadQueue(), [](PluginSpec *spec) {
spec->d->enableDependenciesIndirectly();
}
});
}
void PluginManagerPrivate::enableOnlyTestedSpecs()
@@ -1534,15 +1514,14 @@ PluginSpec *PluginManagerPrivate::pluginForOption(const QString &option, bool *r
{
// Look in the plugins for an option
*requiresArgument = false;
foreach (PluginSpec *ps, pluginSpecs) {
const PluginSpec::PluginArgumentDescriptions pargs = ps->argumentDescriptions();
if (!pargs.empty()) {
foreach (PluginArgumentDescription pad, pargs) {
if (pad.name == option) {
*requiresArgument = !pad.parameter.isEmpty();
return ps;
}
}
foreach (PluginSpec *spec, pluginSpecs) {
PluginArgumentDescription match = Utils::findOrDefault(spec->argumentDescriptions(),
[option](PluginArgumentDescription pad) {
return pad.name == option;
});
if (!match.name.isEmpty()) {
*requiresArgument = !match.parameter.isEmpty();
return spec;
}
}
return 0;
@@ -1550,10 +1529,7 @@ PluginSpec *PluginManagerPrivate::pluginForOption(const QString &option, bool *r
PluginSpec *PluginManagerPrivate::pluginByName(const QString &name) const
{
foreach (PluginSpec *spec, pluginSpecs)
if (spec->name() == name)
return spec;
return 0;
return Utils::findOrDefault(pluginSpecs, [name](PluginSpec *spec) { return spec->name() == name; });
}
void PluginManagerPrivate::initProfiling()
@@ -1586,22 +1562,19 @@ void PluginManagerPrivate::profilingReport(const char *what, const PluginSpec *s
void PluginManagerPrivate::profilingSummary() const
{
if (!m_profileTimer.isNull()) {
typedef QMultiMap<int, const PluginSpec *> Sorter;
Sorter sorter;
QMultiMap<int, const PluginSpec *> sorter;
int total = 0;
QHash<const PluginSpec *, int>::ConstIterator it1 = m_profileTotal.constBegin();
QHash<const PluginSpec *, int>::ConstIterator et1 = m_profileTotal.constEnd();
for (; it1 != et1; ++it1) {
sorter.insert(it1.value(), it1.key());
total += it1.value();
auto totalEnd = m_profileTotal.constEnd();
for (auto it = m_profileTotal.constBegin(); it != totalEnd; ++it) {
sorter.insert(it.value(), it.key());
total += it.value();
}
Sorter::ConstIterator it2 = sorter.constBegin();
Sorter::ConstIterator et2 = sorter.constEnd();
for (; it2 != et2; ++it2)
qDebug("%-22s %8dms ( %5.2f%% )", qPrintable(it2.value()->name()),
it2.key(), 100.0 * it2.key() / total);
auto sorterEnd = sorter.constEnd();
for (auto it = sorter.constBegin(); it != sorterEnd; ++it)
qDebug("%-22s %8dms ( %5.2f%% )", qPrintable(it.value()->name()),
it.key(), 100.0 * it.key() / total);
qDebug("Total: %8dms", total);
}
}
@@ -1693,12 +1666,9 @@ bool PluginManager::isInitializationDone()
QObject *PluginManager::getObjectByName(const QString &name)
{
QReadLocker lock(&d->m_lock);
QList<QObject *> all = allObjects();
foreach (QObject *obj, all) {
if (obj->objectName() == name)
return obj;
}
return 0;
return Utils::findOrDefault(allObjects(), [&name](const QObject *obj) {
return obj->objectName() == name;
});
}
/*!
@@ -1711,10 +1681,7 @@ QObject *PluginManager::getObjectByClassName(const QString &className)
{
const QByteArray ba = className.toUtf8();
QReadLocker lock(&d->m_lock);
QList<QObject *> all = allObjects();
foreach (QObject *obj, all) {
if (obj->inherits(ba.constData()))
return obj;
}
return 0;
return Utils::findOrDefault(allObjects(), [&ba](const QObject *obj) {
return obj->inherits(ba.constData());
});
}

View File

@@ -134,7 +134,6 @@ public:
bool m_isInitializationDone = false;
private:
PluginCollection *defaultCollection;
PluginManager *q;
void nextDelayedInitialize();

View File

@@ -30,6 +30,8 @@
#include "iplugin_p.h"
#include "pluginmanager.h"
#include <utils/algorithm.h>
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
@@ -146,6 +148,24 @@ bool PluginDependency::operator==(const PluginDependency &other) const
return name == other.name && version == other.version && type == other.type;
}
static QString typeString(PluginDependency::Type type)
{
switch (type) {
case PluginDependency::Optional:
return QString(", optional");
case PluginDependency::Test:
return QString(", test");
case PluginDependency::Required:
default:
return QString();
}
}
QString PluginDependency::toString() const
{
return name + " (" + version + typeString(type) + ")";
}
/*!
\internal
*/
@@ -446,6 +466,14 @@ QHash<PluginDependency, PluginSpec *> PluginSpec::dependencySpecs() const
return d->dependencySpecs;
}
bool PluginSpec::requiresAny(const QSet<PluginSpec *> &plugins) const
{
return Utils::anyOf(d->dependencySpecs.keys(), [this, &plugins](const PluginDependency &dep) {
return dep.type == PluginDependency::Required
&& plugins.contains(d->dependencySpecs.value(dep));
});
}
//==========PluginSpecPrivate==================
namespace {
@@ -877,14 +905,9 @@ bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
}
QHash<PluginDependency, PluginSpec *> resolvedDependencies;
foreach (const PluginDependency &dependency, dependencies) {
PluginSpec *found = 0;
foreach (PluginSpec *spec, specs) {
if (spec->provides(dependency.name, dependency.version)) {
found = spec;
break;
}
}
PluginSpec * const found = Utils::findOrDefault(specs, [&dependency](PluginSpec *spec) {
return spec->provides(dependency.name, dependency.version);
});
if (!found) {
if (dependency.type == PluginDependency::Required) {
hasError = true;

View File

@@ -63,6 +63,7 @@ struct EXTENSIONSYSTEM_EXPORT PluginDependency
QString version;
Type type;
bool operator==(const PluginDependency &other) const;
QString toString() const;
};
uint qHash(const ExtensionSystem::PluginDependency &value);
@@ -118,6 +119,7 @@ public:
// dependency specs, valid after 'Resolved' state is reached
QHash<PluginDependency, PluginSpec *> dependencySpecs() const;
bool requiresAny(const QSet<PluginSpec *> &plugins) const;
// linked plugin instance, valid after 'Loaded' state is reached
IPlugin *plugin() const;

View File

@@ -820,6 +820,9 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
const QString typeName = getRightMostIdentifier(typeId)->name.toString();
if (!m_typeStack.isEmpty() && m_typeStack.last() == QLatin1String("State"))
addMessage(StateCannotHaveChildItem, typeErrorLocation, typeName);
if (checkTypeForDesignerSupport(typeId))
addMessage(WarnUnsupportedTypeInVisualDesigner, typeErrorLocation, typeName);

View File

@@ -104,12 +104,13 @@ ModelManagerInterface::ModelManagerInterface(QObject *parent)
m_updateCppQmlTypesTimer = new QTimer(this);
m_updateCppQmlTypesTimer->setInterval(1000);
m_updateCppQmlTypesTimer->setSingleShot(true);
connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(startCppQmlTypeUpdate()));
connect(m_updateCppQmlTypesTimer, &QTimer::timeout,
this, &ModelManagerInterface::startCppQmlTypeUpdate);
m_asyncResetTimer = new QTimer(this);
m_asyncResetTimer->setInterval(15000);
m_asyncResetTimer->setSingleShot(true);
connect(m_asyncResetTimer, SIGNAL(timeout()), SLOT(resetCodeModel()));
connect(m_asyncResetTimer, &QTimer::timeout, this, &ModelManagerInterface::resetCodeModel);
qRegisterMetaType<QmlJS::Document::Ptr>("QmlJS::Document::Ptr");
qRegisterMetaType<QmlJS::LibraryInfo>("QmlJS::LibraryInfo");

View File

@@ -205,9 +205,11 @@ public:
PathsAndLanguages paths,
ModelManagerInterface *modelManager,
bool emitDocChangedOnDisk, bool libOnly = true);
public slots:
virtual void resetCodeModel();
void removeProjectInfo(ProjectExplorer::Project *project);
void maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc);
signals:
void documentUpdated(QmlJS::Document::Ptr doc);
void documentChangedOnDisk(QmlJS::Document::Ptr doc);
@@ -215,12 +217,11 @@ signals:
void libraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info);
void projectInfoUpdated(const ProjectInfo &pinfo);
void projectPathChanged(const QString &projectPath);
protected slots:
void maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc);
void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan);
void asyncReset();
virtual void startCppQmlTypeUpdate();
protected:
Q_INVOKABLE void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan);
Q_INVOKABLE void asyncReset();
virtual void startCppQmlTypeUpdate();
QMutex *mutex() const;
virtual QHash<QString,Dialect> languageForSuffix() const;
virtual void writeMessageInternal(const QString &msg) const;

View File

@@ -51,8 +51,8 @@ Utils::FileSystemWatcher *PluginDumper::pluginWatcher()
if (!m_pluginWatcher) {
m_pluginWatcher = new Utils::FileSystemWatcher(this);
m_pluginWatcher->setObjectName(QLatin1String("PluginDumperWatcher"));
connect(m_pluginWatcher, SIGNAL(fileChanged(QString)),
this, SLOT(pluginChanged(QString)));
connect(m_pluginWatcher, &Utils::FileSystemWatcher::fileChanged,
this, &PluginDumper::pluginChanged);
}
return m_pluginWatcher;
}
@@ -509,8 +509,10 @@ void PluginDumper::runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &i
{
QProcess *process = new QProcess(this);
process->setEnvironment(info.qmlDumpEnvironment.toStringList());
connect(process, SIGNAL(finished(int)), SLOT(qmlPluginTypeDumpDone(int)));
connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(qmlPluginTypeDumpError(QProcess::ProcessError)));
connect(process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
this, &PluginDumper::qmlPluginTypeDumpDone);
connect(process, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error),
this, &PluginDumper::qmlPluginTypeDumpError);
process->start(info.qmlDumpPath, arguments);
m_runningQmldumps.insert(process, importPath);
}

View File

@@ -52,13 +52,13 @@ public:
void scheduleRedumpPlugins();
void scheduleMaybeRedumpBuiltins(const QmlJS::ModelManagerInterface::ProjectInfo &info);
private slots:
void onLoadBuiltinTypes(const QmlJS::ModelManagerInterface::ProjectInfo &info,
private:
Q_INVOKABLE void onLoadBuiltinTypes(const QmlJS::ModelManagerInterface::ProjectInfo &info,
bool force = false);
void onLoadPluginTypes(const QString &libraryPath, const QString &importPath,
Q_INVOKABLE void onLoadPluginTypes(const QString &libraryPath, const QString &importPath,
const QString &importUri, const QString &importVersion);
void dumpBuiltins(const QmlJS::ModelManagerInterface::ProjectInfo &info);
void dumpAllPlugins();
Q_INVOKABLE void dumpBuiltins(const QmlJS::ModelManagerInterface::ProjectInfo &info);
Q_INVOKABLE void dumpAllPlugins();
void qmlPluginTypeDumpDone(int exitCode);
void qmlPluginTypeDumpError(QProcess::ProcessError error);
void pluginChanged(const QString &pluginLibrary);

View File

@@ -235,6 +235,8 @@ StaticAnalysisMessages::StaticAnalysisMessages()
tr("States are only supported in the root item in a Qt Quick UI form."));
newMsg(ErrReferenceToParentItemNotSupportedInQmlUi, Error,
tr("Referencing the parent of the root item is not supported in a Qt Quick UI form."));
newMsg(StateCannotHaveChildItem, Error,
tr("A State cannot have a child item (%1)."), 1);
}
} // anonymous namespace

View File

@@ -88,6 +88,7 @@ enum Type
HintExtraParentheses = 123,
MaybeWarnEqualityTypeCoercion = 126,
WarnConfusingExpressionStatement = 127,
StateCannotHaveChildItem = 128,
HintDeclarationsShouldBeAtStartOfFunction = 201,
HintOneStatementPerLine = 202,
WarnImperativeCodeNotEditableInVisualDesigner = 203,

View File

@@ -418,4 +418,24 @@ inline void sort(Container &c, Predicate p)
std::sort(c.begin(), c.end(), p);
}
//////////////////
// reverseForeach
/////////////////
template <typename Container, typename Op>
inline void reverseForeach(const Container &c, const Op &operation)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
auto rend = c.begin();
auto it = c.end();
while (it != rend) {
--it;
operation(*it);
}
#else
auto rend = c.rend();
for (auto it = c.rbegin(); it != rend; ++it)
operation(*it);
#endif
}
}

View File

@@ -153,13 +153,16 @@ public:
m_floatButton = new DockWidgetTitleButton(this);
m_floatButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));
m_floatButton->setAccessibleName(QDockWidget::tr("Float"));
m_floatButton->setAccessibleDescription(QDockWidget::tr("Undocks and re-attaches the dock widget"));
m_closeButton = new DockWidgetTitleButton(this);
m_closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));
#ifndef QT_NO_ACCESSIBILITY
m_floatButton->setAccessibleName(QDockWidget::tr("Float"));
m_floatButton->setAccessibleDescription(QDockWidget::tr("Undocks and re-attaches the dock widget"));
m_closeButton->setAccessibleName(QDockWidget::tr("Close"));
m_closeButton->setAccessibleDescription(QDockWidget::tr("Closes the dock widget"));
#endif
setActive(false);

View File

@@ -306,24 +306,24 @@ void PathChooser::setEnvironment(const Environment &env)
}
}
QString PathChooser::path() const
{
return d->expandedPath(rawPath());
}
QString PathChooser::rawPath() const
{
return rawFileName().toString();
}
QString PathChooser::path() const
{
return fileName().toString();
}
FileName PathChooser::rawFileName() const
{
return FileName::fromUserInput(d->m_lineEdit->text());
return FileName::fromString(QDir::fromNativeSeparators(d->m_lineEdit->text()));
}
FileName PathChooser::fileName() const
{
return FileName::fromString(path());
return FileName::fromUserInput(d->expandedPath(rawFileName().toString()));
}
// FIXME: try to remove again

View File

@@ -377,7 +377,7 @@ Utils::SynchronousProcessResponse ShellCommand::runCommand(const Utils::FileName
process.setTimeOutMessageBoxEnabled(true);
// Run!
response = process.run(binary.toString(), arguments);
response = process.runBlocking(binary.toString(), arguments);
}
if (!d->m_aborted) {

View File

@@ -297,12 +297,12 @@ void SynchronousProcess::setTimeoutS(int timeoutS)
if (timeoutS > 0)
d->m_maxHangTimerCount = qMax(2, timeoutS);
else
d->m_maxHangTimerCount = INT_MAX;
d->m_maxHangTimerCount = INT_MAX / 1000;
}
int SynchronousProcess::timeoutS() const
{
return d->m_maxHangTimerCount == INT_MAX ? -1 : d->m_maxHangTimerCount;
return d->m_maxHangTimerCount == (INT_MAX / 1000) ? -1 : d->m_maxHangTimerCount;
}
void SynchronousProcess::setCodec(QTextCodec *c)
@@ -476,7 +476,7 @@ SynchronousProcessResponse SynchronousProcess::runBlocking(const QString &binary
QTC_ASSERT(d->m_process.state() == QProcess::NotRunning, return d->m_result);
d->m_result.exitCode = d->m_process.exitCode();
if (d->m_result.result != SynchronousProcessResponse::StartFailed) {
if (d->m_result.result == SynchronousProcessResponse::StartFailed) {
if (d->m_process.exitStatus() != QProcess::NormalExit)
d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
else

View File

@@ -41,7 +41,7 @@ public:
TreeItem();
virtual ~TreeItem();
virtual TreeItem *parent() const { return m_parent; }
TreeItem *parent() const { return m_parent; }
virtual TreeItem *child(int pos) const;
virtual int rowCount() const;
@@ -148,7 +148,7 @@ private:
};
// A TreeItem with children all of the same type.
template <class ChildType>
template <class ChildType, class ParentType = TreeItem>
class TypedTreeItem : public TreeItem
{
public:
@@ -175,6 +175,10 @@ public:
ChildType *findFirstLevelChild(Predicate pred) const {
return TreeItem::findFirstLevelChild<ChildType *, Predicate>(pred);
}
ParentType *parent() const {
return static_cast<ParentType *>(TreeItem::parent());
}
};
class QTCREATOR_UTILS_EXPORT StaticTreeItem : public TreeItem
@@ -241,9 +245,9 @@ protected:
// A multi-level model with uniform types per level.
// All items below second level have to have identitical types.
template <class FirstLevelItem,
class SecondLevelItem = FirstLevelItem,
class RootItem = TreeItem>
template <class RootItem,
class FirstLevelItem,
class SecondLevelItem = FirstLevelItem>
class LeveledTreeModel : public TreeModel
{
public:

View File

@@ -1,10 +1,13 @@
include(../../qtcreatorplugin.pri)
DEFINES += BINEDITOR_LIBRARY
HEADERS += bineditorplugin.h \
bineditor.h \
bineditorwidget.h \
bineditorconstants.h \
bineditor_global.h \
markup.h
SOURCES += bineditorplugin.cpp \
bineditor.cpp \
bineditorwidget.cpp \
markup.cpp

View File

@@ -11,9 +11,10 @@ QtcPlugin {
Depends { name: "TextEditor" }
files: [
"bineditor.cpp",
"bineditor.h",
"bineditorwidget.cpp",
"bineditorwidget.h",
"bineditorconstants.h",
"bineditor_global.h",
"bineditorplugin.cpp",
"bineditorplugin.h",
"markup.cpp",

View File

@@ -0,0 +1,34 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <QtGlobal>
#if defined(BINEDITOR_LIBRARY)
# define BINEDITOR_EXPORT Q_DECL_EXPORT
#else
# define BINEDITOR_EXPORT Q_DECL_IMPORT
#endif

View File

@@ -24,7 +24,7 @@
****************************************************************************/
#include "bineditorplugin.h"
#include "bineditor.h"
#include "bineditorwidget.h"
#include "bineditorconstants.h"
#include <coreplugin/icore.h>

View File

@@ -23,7 +23,7 @@
**
****************************************************************************/
#include "bineditor.h"
#include "bineditorwidget.h"
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorconstants.h>

View File

@@ -25,6 +25,7 @@
#pragma once
#include "bineditor_global.h"
#include "markup.h"
#include <QBasicTimer>
@@ -46,7 +47,7 @@ namespace TextEditor { class FontSettings; }
namespace BinEditor {
class BinEditorWidget : public QAbstractScrollArea
class BINEDITOR_EXPORT BinEditorWidget : public QAbstractScrollArea
{
Q_OBJECT
Q_PROPERTY(bool modified READ isModified WRITE setModified DESIGNABLE false)

View File

@@ -71,9 +71,11 @@ bool BookmarksPlugin::initialize(const QStringList & /*arguments*/, QString *)
mbm->menu()->setTitle(tr("&Bookmarks"));
mtools->addMenu(mbm);
const Context editorManagerContext(Core::Constants::C_EDITORMANAGER);
//Toggle
m_toggleAction = new QAction(tr("Toggle Bookmark"), this);
Command *cmd = ActionManager::registerAction(m_toggleAction, BOOKMARKS_TOGGLE_ACTION);
Command *cmd = ActionManager::registerAction(m_toggleAction, BOOKMARKS_TOGGLE_ACTION, editorManagerContext);
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+M") : tr("Ctrl+M")));
mbm->addAction(cmd);
@@ -81,13 +83,13 @@ bool BookmarksPlugin::initialize(const QStringList & /*arguments*/, QString *)
//Previous
m_prevAction = new QAction(tr("Previous Bookmark"), this);
cmd = ActionManager::registerAction(m_prevAction, BOOKMARKS_PREV_ACTION);
cmd = ActionManager::registerAction(m_prevAction, BOOKMARKS_PREV_ACTION, editorManagerContext);
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+,") : tr("Ctrl+,")));
mbm->addAction(cmd);
//Next
m_nextAction = new QAction(tr("Next Bookmark"), this);
cmd = ActionManager::registerAction(m_nextAction, BOOKMARKS_NEXT_ACTION);
cmd = ActionManager::registerAction(m_nextAction, BOOKMARKS_NEXT_ACTION, editorManagerContext);
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Meta+.") : tr("Ctrl+.")));
mbm->addAction(cmd);
@@ -95,12 +97,12 @@ bool BookmarksPlugin::initialize(const QStringList & /*arguments*/, QString *)
//Previous Doc
m_docPrevAction = new QAction(tr("Previous Bookmark in Document"), this);
cmd = ActionManager::registerAction(m_docPrevAction, BOOKMARKS_PREVDOC_ACTION);
cmd = ActionManager::registerAction(m_docPrevAction, BOOKMARKS_PREVDOC_ACTION, editorManagerContext);
mbm->addAction(cmd);
//Next Doc
m_docNextAction = new QAction(tr("Next Bookmark in Document"), this);
cmd = ActionManager::registerAction(m_docNextAction, BOOKMARKS_NEXTDOC_ACTION);
cmd = ActionManager::registerAction(m_docNextAction, BOOKMARKS_NEXTDOC_ACTION, editorManagerContext);
mbm->addAction(cmd);
m_editBookmarkAction = new QAction(tr("Edit Bookmark"), this);

View File

@@ -613,7 +613,7 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(
QTC_CHECK(m_completions.isEmpty());
m_completions = toAssistProposalItems(completions);
if (m_addSnippets)
if (m_addSnippets && !m_completions.isEmpty())
addSnippets();
setAsyncProposalAvailable(createProposal(neededCorrection));

View File

@@ -932,18 +932,28 @@ void ClangCodeCompletionTest::testCompleteConstructorAndFallbackToGlobalCompleti
QVERIFY(!hasSnippet(t.proposal, "class"));
}
void ClangCodeCompletionTest::testCompleteWithDotToArrowCorrection()
{
// Inserting the dot for this test is important since it will send the editor
// Explicitly Inserting The Dot
// ----------------------------
// Inserting the dot for is important since it will send the editor
// content to the backend and thus generate an unsaved file on the backend
// side. The unsaved file enables us to do the dot to arrow correction.
void ClangCodeCompletionTest::testCompleteWithDotToArrowCorrection()
{
ProjectLessCompletionTest t("dotToArrowCorrection.cpp",
QStringLiteral("."));
QStringLiteral(".")); // See above "Explicitly Inserting The Dot"
QVERIFY(hasItem(t.proposal, "member"));
}
void ClangCodeCompletionTest::testDontCompleteWithDotToArrowCorrectionForFloats()
{
ProjectLessCompletionTest t("noDotToArrowCorrectionForFloats.cpp",
QStringLiteral(".")); // See above "Explicitly Inserting The Dot"
QCOMPARE(t.proposal->size(), 0);
}
void ClangCodeCompletionTest::testCompleteProjectDependingCode()
{
const TestDocument testDocument("completionWithProject.cpp");

View File

@@ -48,6 +48,7 @@ private slots:
void testCompleteConstructorAndFallbackToGlobalCompletion();
void testCompleteWithDotToArrowCorrection();
void testDontCompleteWithDotToArrowCorrectionForFloats();
void testCompleteProjectDependingCode();
void testCompleteProjectDependingCodeAfterChangingProject();

View File

@@ -22,5 +22,6 @@
<file>objc_messages_3.mm</file>
<file>preprocessorKeywordsCompletion.cpp</file>
<file>dotToArrowCorrection.cpp</file>
<file>noDotToArrowCorrectionForFloats.cpp</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,4 @@
void f()
{
0 /* COMPLETE HERE */
}

View File

@@ -49,7 +49,6 @@
#include <QDateTime>
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QMessageBox>
#include <QRegularExpression>
#include <QSet>
@@ -97,20 +96,14 @@ static QStringList toArguments(const CMakeConfig &config, const ProjectExplorer:
// --------------------------------------------------------------------
BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
m_buildConfiguration(bc),
m_watcher(new QFileSystemWatcher(this))
m_buildConfiguration(bc)
{
QTC_ASSERT(bc, return);
m_projectName = sourceDirectory().fileName();
m_reparseTimer.setSingleShot(true);
m_reparseTimer.setInterval(5000);
m_reparseTimer.setInterval(2000);
connect(&m_reparseTimer, &QTimer::timeout, this, &BuildDirManager::parse);
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this]() {
if (!isParsing())
m_reparseTimer.start();
});
}
BuildDirManager::~BuildDirManager()
@@ -157,6 +150,18 @@ bool BuildDirManager::isParsing() const
return false;
}
void BuildDirManager::cmakeFilesChanged()
{
if (isParsing())
return;
const CMakeTool *tool = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
if (!tool->isAutoRun())
return;
m_reparseTimer.start();
}
void BuildDirManager::forceReparse()
{
if (m_buildConfiguration->target()->activeBuildConfiguration() != m_buildConfiguration)
@@ -180,13 +185,8 @@ void BuildDirManager::resetData()
m_cmakeCache.clear();
m_projectName.clear();
m_buildTargets.clear();
m_watchedFiles.clear();
qDeleteAll(m_files);
m_files.clear();
const QStringList watchedFiles = m_watcher->files();
if (!watchedFiles.isEmpty())
m_watcher->removePaths(watchedFiles);
}
bool BuildDirManager::persistCMakeState()
@@ -223,8 +223,8 @@ void BuildDirManager::parse()
return;
}
const bool mustUpdate = m_watchedFiles.isEmpty()
|| Utils::anyOf(m_watchedFiles, [&cbpFileFi](const Utils::FileName &f) {
const bool mustUpdate = m_cmakeFiles.isEmpty()
|| Utils::anyOf(m_cmakeFiles, [&cbpFileFi](const Utils::FileName &f) {
return f.toFileInfo().lastModified() > cbpFileFi.lastModified();
});
if (mustUpdate) {
@@ -251,11 +251,6 @@ void BuildDirManager::clearCache()
forceReparse();
}
bool BuildDirManager::isProjectFile(const Utils::FileName &fileName) const
{
return m_watchedFiles.contains(fileName);
}
QString BuildDirManager::projectName() const
{
return m_projectName;
@@ -271,6 +266,11 @@ QList<ProjectExplorer::FileNode *> BuildDirManager::files()
return m_files;
}
QSet<Utils::FileName> BuildDirManager::cmakeFiles()
{
return m_cmakeFiles;
}
void BuildDirManager::clearFiles()
{
m_files.clear();
@@ -355,15 +355,19 @@ void BuildDirManager::extractData()
m_projectName = sourceDirectory().fileName();
m_files.append(new ProjectExplorer::FileNode(topCMake, ProjectExplorer::ProjectFileType, false));
m_watchedFiles.insert(topCMake);
// Do not insert topCMake into m_cmakeFiles: The project already watches that!
// Find cbp file
QString cbpFile = CMakeManager::findCbpFile(workDirectory().toString());
if (cbpFile.isEmpty())
return;
m_cmakeFiles.insert(Utils::FileName::fromString(cbpFile));
m_watcher->addPath(cbpFile);
m_watcher->addPath(workDirectory().toString() + QLatin1String("/CMakeCache.txt"));
// Add CMakeCache.txt file:
Utils::FileName cacheFile = workDirectory();
cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
if (cacheFile.toFileInfo().exists())
m_cmakeFiles.insert(cacheFile);
// setFolderName
CMakeCbpParser cbpparser;
@@ -374,21 +378,14 @@ void BuildDirManager::extractData()
m_projectName = cbpparser.projectName();
m_files = cbpparser.fileList();
QSet<Utils::FileName> projectFiles;
if (cbpparser.hasCMakeFiles()) {
m_files.append(cbpparser.cmakeFileList());
foreach (const ProjectExplorer::FileNode *node, cbpparser.cmakeFileList())
projectFiles.insert(node->filePath());
m_cmakeFiles.insert(node->filePath());
} else {
m_files.append(new ProjectExplorer::FileNode(topCMake, ProjectExplorer::ProjectFileType, false));
projectFiles.insert(topCMake);
}
m_watchedFiles = projectFiles;
const QStringList toWatch
= Utils::transform(m_watchedFiles.toList(), [](const Utils::FileName &fn) { return fn.toString(); });
m_watcher->addPaths(toWatch);
m_buildTargets = cbpparser.buildTargets();
}

View File

@@ -73,6 +73,8 @@ public:
const CMakeConfig intendedConfiguration() const;
bool isParsing() const;
void cmakeFilesChanged();
void parse();
void clearCache();
void forceReparse();
@@ -80,10 +82,10 @@ public:
void resetData();
bool persistCMakeState();
bool isProjectFile(const Utils::FileName &fileName) const;
QString projectName() const;
QList<CMakeBuildTarget> buildTargets() const;
QList<ProjectExplorer::FileNode *> files();
QSet<Utils::FileName> cmakeFiles();
void clearFiles();
CMakeConfig parsedConfiguration() const;
@@ -115,10 +117,9 @@ private:
QTemporaryDir *m_tempDir = nullptr;
mutable CMakeConfig m_cmakeCache;
QSet<Utils::FileName> m_watchedFiles;
QSet<Utils::FileName> m_cmakeFiles;
QString m_projectName;
QList<CMakeBuildTarget> m_buildTargets;
QFileSystemWatcher *m_watcher;
QList<ProjectExplorer::FileNode *> m_files;
// For error reporting:

View File

@@ -71,6 +71,11 @@ CMakeBuildConfiguration::~CMakeBuildConfiguration()
m_buildDirManager->deleteLater(); // Do not block while waiting for cmake...
}
void CMakeBuildConfiguration::cmakeFilesChanged()
{
m_buildDirManager->cmakeFilesChanged();
}
bool CMakeBuildConfiguration::isEnabled() const
{
return m_error.isEmpty();

View File

@@ -52,6 +52,8 @@ public:
CMakeBuildConfiguration(ProjectExplorer::Target *parent);
~CMakeBuildConfiguration();
void cmakeFilesChanged();
bool isEnabled() const override;
QString disabledReason() const override;

View File

@@ -27,6 +27,8 @@
#include "cmakeproject.h"
#include "cmakeprojectconstants.h"
#include <projectexplorer/target.h>
#include <utils/fileutils.h>
using namespace Utils;
@@ -34,7 +36,7 @@ using namespace Utils;
namespace CMakeProjectManager {
namespace Internal {
CMakeFile::CMakeFile(const FileName &fileName)
CMakeFile::CMakeFile(CMakeProject *project, const FileName &fileName) : m_project(project)
{
setId("Cmake.ProjectFile");
setMimeType(QLatin1String(Constants::CMAKEPROJECTMIMETYPE));
@@ -48,5 +50,15 @@ Core::IDocument::ReloadBehavior CMakeFile::reloadBehavior(ChangeTrigger state, C
return BehaviorSilent;
}
bool CMakeFile::reload(QString *errorString, Core::IDocument::ReloadFlag flag, Core::IDocument::ChangeType type)
{
Q_UNUSED(errorString);
Q_UNUSED(flag);
if (type != TypePermissions)
m_project->handleCmakeFileChanged();
return true;
}
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -35,9 +35,13 @@ namespace Internal {
class CMakeFile : public Core::IDocument
{
public:
CMakeFile(const Utils::FileName &fileName);
CMakeFile(CMakeProject *project, const Utils::FileName &fileName);
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override;
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
private:
CMakeProject *m_project;
};
} // namespace Internal

View File

@@ -36,6 +36,7 @@
#include "cmakeprojectmanager.h"
#include <coreplugin/icore.h>
#include <coreplugin/documentmanager.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/projectinfo.h>
#include <cpptools/projectpartbuilder.h>
@@ -88,11 +89,13 @@ CMakeProject::CMakeProject(CMakeManager *manager, const FileName &fileName)
{
setId(Constants::CMAKEPROJECT_ID);
setProjectManager(manager);
setDocument(new CMakeFile(fileName));
setDocument(new Internal::CMakeFile(this, fileName));
setRootProjectNode(new CMakeProjectNode(fileName));
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
Core::DocumentManager::addDocument(document());
rootProjectNode()->setDisplayName(fileName.parentDir().fileName());
connect(this, &CMakeProject::activeTargetChanged, this, &CMakeProject::handleActiveTargetChanged);
@@ -217,6 +220,29 @@ void CMakeProject::parseCMakeOutput()
rootProjectNode()->setDisplayName(bdm->projectName());
// Delete no longer necessary file watcher:
const QSet<Utils::FileName> currentWatched
= Utils::transform(m_watchedFiles, [](CMakeFile *cmf) { return cmf->filePath(); });
const QSet<Utils::FileName> toWatch = bdm->cmakeFiles();
QSet<Utils::FileName> toDelete = currentWatched;
toDelete.subtract(toWatch);
m_watchedFiles = Utils::filtered(m_watchedFiles, [&toDelete](Internal::CMakeFile *cmf) {
if (toDelete.contains(cmf->filePath())) {
delete cmf;
return false;
}
return true;
});
// Add new file watchers:
QSet<Utils::FileName> toAdd = toWatch;
toAdd.subtract(currentWatched);
foreach (const Utils::FileName &fn, toAdd) {
CMakeFile *cm = new CMakeFile(this, fn);
Core::DocumentManager::addDocument(cm);
m_watchedFiles.insert(cm);
}
buildTree(static_cast<CMakeProjectNode *>(rootProjectNode()), bdm->files());
bdm->clearFiles(); // Some of the FileNodes in files() were deleted!
@@ -512,6 +538,15 @@ bool CMakeProject::setupTarget(Target *t)
return true;
}
void CMakeProject::handleCmakeFileChanged()
{
if (Target *t = activeTarget()) {
if (auto bc = qobject_cast<CMakeBuildConfiguration *>(t->activeBuildConfiguration())) {
bc->cmakeFilesChanged();
}
}
}
void CMakeProject::handleActiveTargetChanged()
{
if (m_connectedTarget) {

View File

@@ -120,6 +120,8 @@ protected:
bool setupTarget(ProjectExplorer::Target *t) override;
private:
void handleCmakeFileChanged();
void handleActiveTargetChanged();
void handleActiveBuildConfigurationChanged();
void handleParsingStarted();
@@ -144,7 +146,10 @@ private:
QFuture<void> m_codeModelFuture;
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
QSet<Internal::CMakeFile *> m_watchedFiles;
friend class Internal::CMakeBuildConfiguration;
friend class Internal::CMakeFile;
};
} // namespace CMakeProjectManager

View File

@@ -36,6 +36,7 @@
#include <utils/qtcassert.h>
#include <utils/treemodel.h>
#include <QCheckBox>
#include <QFormLayout>
#include <QHeaderView>
#include <QLabel>
@@ -56,7 +57,7 @@ class CMakeToolTreeItem;
// CMakeToolItemModel
// --------------------------------------------------------------------------
class CMakeToolItemModel : public LeveledTreeModel<TreeItem, CMakeToolTreeItem>
class CMakeToolItemModel : public LeveledTreeModel<TreeItem, TreeItem, CMakeToolTreeItem>
{
Q_DECLARE_TR_FUNCTIONS(CMakeProjectManager::CMakeSettingsPage)
@@ -65,12 +66,13 @@ public:
CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const;
CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const;
QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool isAutoDetected);
QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool isAutoDetected);
void addCMakeTool(const CMakeTool *item, bool changed);
TreeItem *autoGroupItem() const;
TreeItem *manualGroupItem() const;
void reevaluateChangedFlag(CMakeToolTreeItem *item) const;
void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable);
void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable,
bool autoRun);
void removeCMakeTool(const Core::Id &id);
void apply();
@@ -92,19 +94,22 @@ public:
m_id(item->id()),
m_name(item->displayName()),
m_executable(item->cmakeExecutable()),
m_isAutoRun(item->isAutoRun()),
m_autodetected(item->isAutoDetected()),
m_changed(changed)
{}
CMakeToolTreeItem(const QString &name, const Utils::FileName &executable, bool autodetected) :
CMakeToolTreeItem(const QString &name, const Utils::FileName &executable,
bool autoRun, bool autodetected) :
m_id(Core::Id::fromString(QUuid::createUuid().toString())),
m_name(name),
m_executable(executable),
m_isAutoRun(autoRun),
m_autodetected(autodetected),
m_changed(true)
{}
CMakeToolTreeItem() : m_autodetected(false), m_changed(true) {}
CMakeToolTreeItem() = default;
CMakeToolItemModel *model() const { return static_cast<CMakeToolItemModel *>(TreeItem::model()); }
@@ -135,8 +140,9 @@ public:
Core::Id m_id;
QString m_name;
FileName m_executable;
bool m_autodetected;
bool m_changed;
bool m_isAutoRun = true;
bool m_autodetected = false;
bool m_changed = true;
};
CMakeToolItemModel::CMakeToolItemModel()
@@ -157,9 +163,10 @@ CMakeToolItemModel::CMakeToolItemModel()
}
QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable, const bool isAutoDetected)
QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable,
const bool autoRun, const bool isAutoDetected)
{
CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, isAutoDetected);
CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, isAutoDetected);
if (isAutoDetected)
autoGroupItem()->appendChild(item);
else
@@ -208,13 +215,14 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const
}
void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName,
const FileName &executable)
const FileName &executable, bool autoRun)
{
CMakeToolTreeItem *treeItem = cmakeToolItem(id);
QTC_ASSERT(treeItem, return);
treeItem->m_name = displayName;
treeItem->m_executable = executable;
treeItem->m_isAutoRun = autoRun;
reevaluateChangedFlag(treeItem);
}
@@ -249,6 +257,7 @@ void CMakeToolItemModel::apply()
if (CMakeTool *cmake = CMakeToolManager::findById(item->m_id)) {
cmake->setDisplayName(item->m_name);
cmake->setCMakeExecutable(item->m_executable);
cmake->setAutorun(item->m_isAutoRun);
} else {
toRegister.append(item);
}
@@ -315,6 +324,7 @@ public:
private:
CMakeToolItemModel *m_model;
QLineEdit *m_displayNameLineEdit;
QCheckBox *m_autoRunCheckBox;
PathChooser *m_binaryChooser;
Core::Id m_id;
bool m_loadingItem;
@@ -330,21 +340,28 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
m_binaryChooser->setMinimumWidth(400);
m_binaryChooser->setHistoryCompleter(QLatin1String("Cmake.Command.History"));
m_autoRunCheckBox = new QCheckBox;
m_autoRunCheckBox->setText("Autorun CMake");
QFormLayout *formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
formLayout->addRow(m_autoRunCheckBox);
connect(m_binaryChooser, &PathChooser::rawPathChanged,
this, &CMakeToolItemConfigWidget::store);
connect(m_displayNameLineEdit, &QLineEdit::textChanged,
this, &CMakeToolItemConfigWidget::store);
connect(m_autoRunCheckBox, &QCheckBox::toggled,
this, &CMakeToolItemConfigWidget::store);
}
void CMakeToolItemConfigWidget::store() const
{
if (!m_loadingItem && m_id.isValid())
m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName());
m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(),
m_autoRunCheckBox->checkState() == Qt::Checked);
}
void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
@@ -363,6 +380,8 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
m_binaryChooser->setReadOnly(item->m_autodetected);
m_binaryChooser->setFileName(item->m_executable);
m_autoRunCheckBox->setChecked(item->m_isAutoRun);
m_id = item->m_id;
m_loadingItem = false;
}
@@ -375,7 +394,7 @@ class CMakeToolConfigWidget : public QWidget
{
Q_OBJECT
public:
CMakeToolConfigWidget() : m_currentItem(0)
CMakeToolConfigWidget()
{
m_addButton = new QPushButton(tr("Add"), this);
@@ -452,7 +471,7 @@ public:
QPushButton *m_makeDefButton;
DetailsWidget *m_container;
CMakeToolItemConfigWidget *m_itemConfigWidget;
CMakeToolTreeItem *m_currentItem;
CMakeToolTreeItem *m_currentItem = nullptr;
};
void CMakeToolConfigWidget::apply()
@@ -467,7 +486,7 @@ void CMakeToolConfigWidget::cloneCMakeTool()
QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name),
m_currentItem->m_executable,
false);
m_currentItem->m_isAutoRun, false);
m_cmakeToolsView->setCurrentIndex(newItem);
}
@@ -475,7 +494,7 @@ void CMakeToolConfigWidget::cloneCMakeTool()
void CMakeToolConfigWidget::addCMakeTool()
{
QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")),
FileName(), false);
FileName(), true, false);
m_cmakeToolsView->setCurrentIndex(newItem);
}

View File

@@ -42,6 +42,7 @@ namespace CMakeProjectManager {
const char CMAKE_INFORMATION_ID[] = "Id";
const char CMAKE_INFORMATION_COMMAND[] = "Binary";
const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName";
const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun";
const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
///////////////////////////
@@ -57,6 +58,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fr
{
m_id = Core::Id::fromSetting(map.value(QLatin1String(CMAKE_INFORMATION_ID)));
m_displayName = map.value(QLatin1String(CMAKE_INFORMATION_DISPLAYNAME)).toString();
m_isAutoRun = map.value(QLatin1String(CMAKE_INFORMATION_AUTORUN), true).toBool();
//loading a CMakeTool from SDK is always autodetection
if (!fromSdk)
@@ -82,6 +84,15 @@ void CMakeTool::setCMakeExecutable(const Utils::FileName &executable)
CMakeToolManager::notifyAboutUpdate(this);
}
void CMakeTool::setAutorun(bool autoRun)
{
if (m_isAutoRun == autoRun)
return;
m_isAutoRun = autoRun;
CMakeToolManager::notifyAboutUpdate(this);
}
bool CMakeTool::isValid() const
{
if (!m_id.isValid())
@@ -121,6 +132,7 @@ QVariantMap CMakeTool::toMap() const
data.insert(QLatin1String(CMAKE_INFORMATION_DISPLAYNAME), m_displayName);
data.insert(QLatin1String(CMAKE_INFORMATION_ID), m_id.toSetting());
data.insert(QLatin1String(CMAKE_INFORMATION_COMMAND), m_executable.toString());
data.insert(QLatin1String(CMAKE_INFORMATION_AUTORUN), m_isAutoRun);
data.insert(QLatin1String(CMAKE_INFORMATION_AUTODETECTED), m_isAutoDetected);
return data;
}
@@ -130,6 +142,11 @@ Utils::FileName CMakeTool::cmakeExecutable() const
return m_executable;
}
bool CMakeTool::isAutoRun() const
{
return m_isAutoRun;
}
QStringList CMakeTool::supportedGenerators() const
{
if (m_generators.isEmpty()) {

View File

@@ -66,8 +66,10 @@ public:
QVariantMap toMap () const;
void setCMakeExecutable(const Utils::FileName &executable);
void setAutorun(bool autoRun);
Utils::FileName cmakeExecutable() const;
bool isAutoRun() const;
QStringList supportedGenerators() const;
TextEditor::Keywords keywords();
@@ -87,6 +89,8 @@ private:
QString m_displayName;
Utils::FileName m_executable;
bool m_isAutoRun;
bool m_isAutoDetected;
mutable bool m_didAttemptToRun;

View File

@@ -56,6 +56,9 @@ SystemSettings::SystemSettings()
setCategory(Constants::SETTINGS_CATEGORY_CORE);
setDisplayCategory(QCoreApplication::translate("Core", Constants::SETTINGS_TR_CATEGORY_CORE));
setCategoryIcon(QLatin1String(Constants::SETTINGS_CATEGORY_CORE_ICON));
connect(VcsManager::instance(), &VcsManager::configurationChanged,
this, &SystemSettings::updatePath);
}
QWidget *SystemSettings::widget()
@@ -138,9 +141,6 @@ QWidget *SystemSettings::widget()
}
updatePath();
connect(VcsManager::instance(), &VcsManager::configurationChanged,
this, &SystemSettings::updatePath);
}
return m_widget;
}
@@ -200,6 +200,9 @@ void SystemSettings::resetFileBrowser()
void SystemSettings::updatePath()
{
if (!m_page)
return;
Environment env = Environment::systemEnvironment();
QStringList toAdd = VcsManager::additionalToolsPath();
env.appendOrSetPath(toAdd.join(HostOsInfo::pathListSeparator()));

View File

@@ -996,34 +996,34 @@ void CppModelManager::delayedGC()
d->m_delayedGcTimer.start(500);
}
static QStringList idsOfAllProjectParts(const ProjectInfo &projectInfo)
static QStringList removedProjectParts(const QStringList &before, const QStringList &after)
{
QStringList projectPaths;
foreach (const ProjectPart::Ptr &part, projectInfo.projectParts())
projectPaths << part->id();
return projectPaths;
QSet<QString> b = before.toSet();
b.subtract(after.toSet());
return b.toList();
}
void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
{
QStringList projectPartIds;
QStringList idsOfRemovedProjectParts;
d->m_projectToIndexerCanceled.remove(project);
{
QMutexLocker locker(&d->m_projectMutex);
d->m_dirty = true;
// Save paths
const ProjectInfo projectInfo = d->m_projectToProjectsInfo.value(project, ProjectInfo());
projectPartIds = idsOfAllProjectParts(projectInfo);
const QStringList projectPartsIdsBefore = d->m_projectPartIdToProjectProjectPart.keys();
d->m_projectToProjectsInfo.remove(project);
recalculateProjectPartMappings();
const QStringList projectPartsIdsAfter = d->m_projectPartIdToProjectProjectPart.keys();
idsOfRemovedProjectParts = removedProjectParts(projectPartsIdsBefore, projectPartsIdsAfter);
}
if (!projectPartIds.isEmpty())
emit projectPartsRemoved(projectPartIds);
if (!idsOfRemovedProjectParts.isEmpty())
emit projectPartsRemoved(idsOfRemovedProjectParts);
delayedGC();
}

View File

@@ -48,11 +48,10 @@ public:
QString displayName() const;
private slots:
private:
void chooseSettings(int setting);
void restoreGlobal();
private:
QWidget *m_configWidget;
ProjectExplorer::IRunConfigurationAspect *m_aspect;
ProjectExplorer::ISettingsAspect *m_config;

View File

@@ -157,7 +157,7 @@ inline uint qHash(const Debugger::Internal::Breakpoint &b) { return b.hash(); }
typedef QList<Breakpoint> Breakpoints;
class BreakHandler : public Utils::LeveledTreeModel<BreakpointItem, LocationItem>
class BreakHandler : public Utils::LeveledTreeModel<Utils::TreeItem, BreakpointItem, LocationItem>
{
Q_OBJECT

View File

@@ -96,7 +96,6 @@ public:
void setParameters(const BreakpointParameters &data);
BreakpointParameters parameters() const;
public slots:
void typeChanged(int index);
private:

View File

@@ -116,7 +116,7 @@ public:
static QString extensionLibraryName(bool is64Bit);
private slots:
private:
void readyReadStandardOut();
void readyReadStandardError();
void processError();
@@ -132,7 +132,6 @@ private slots:
void handleDoInterruptInferior(const QString &errorMessage);
private:
typedef QHash<BreakpointModelId, BreakpointResponse> PendingBreakPointMap;
typedef QPair<QString, QString> SourcePathMapping;
struct NormalizedSourceFileName // Struct for caching mapped/normalized source files.

View File

@@ -44,8 +44,6 @@ public:
void emitSizeHintChanged(const QModelIndex &index);
QColor drawBackground(QPainter *painter, const QRect &rect, const QModelIndex &index,
bool selected) const;
public slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
protected:

View File

@@ -51,7 +51,6 @@ public:
int sizeOfFile(const QFont &font);
int sizeOfLineNumber(const QFont &font);
public slots:
void clear();
signals:

View File

@@ -39,7 +39,6 @@ class ConsoleProxyModel : public QSortFilterProxyModel
public:
explicit ConsoleProxyModel(QObject *parent);
public slots:
void setShowLogs(bool show);
void setShowWarnings(bool show);
void setShowErrors(bool show);

View File

@@ -39,7 +39,6 @@ class ConsoleView : public Utils::TreeView
public:
ConsoleView(ConsoleItemModel *model, QWidget *parent);
public slots:
void onScrollToBottom();
protected:

View File

@@ -99,7 +99,7 @@ public:
// DebuggerItemModel
// --------------------------------------------------------------------------
class DebuggerItemModel : public LeveledTreeModel<StaticTreeItem, DebuggerTreeItem>
class DebuggerItemModel : public LeveledTreeModel<TreeItem, StaticTreeItem, DebuggerTreeItem>
{
Q_DECLARE_TR_FUNCTIONS(Debugger::DebuggerOptionsPage)

View File

@@ -3076,9 +3076,7 @@ void showModuleSections(const QString &moduleName, const Sections &sections)
void DebuggerPluginPrivate::aboutToShutdown()
{
disconnect(SessionManager::instance(),
SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
this, 0);
disconnect(SessionManager::instance(), &SessionManager::startupProjectChanged, this, nullptr);
m_mainWindow->saveCurrentPerspective();
delete m_mainWindow;

View File

@@ -62,7 +62,7 @@ public:
static SourcePathMap mergePlatformQtPath(const DebuggerRunParameters &sp,
const SourcePathMap &in);
private slots:
private:
void slotAdd();
void slotAddQt();
void slotRemove();
@@ -70,7 +70,6 @@ private slots:
void slotEditSourceFieldChanged();
void slotEditTargetFieldChanged();
private:
void resizeColumns();
void updateEnabled();
QString editSourceField() const;

View File

@@ -122,7 +122,7 @@ protected: ////////// Gdb Process Management //////////
// Make sure to clean up everything before emitting this signal.
void handleAdapterCrashed(const QString &msg);
private slots:
private:
friend class GdbPlainEngine;
friend class GdbCoreEngine;
void handleInterruptDeviceInferior(const QString &error);
@@ -132,7 +132,6 @@ private slots:
void readGdbStandardError();
void readDebuggeeOutput(const QByteArray &ba);
private:
QTextCodec *m_gdbOutputCodec;
QTextCodec::ConverterState m_gdbOutputCodecState;
QTextCodec *m_inferiorOutputCodec;
@@ -204,7 +203,7 @@ private:
private: ////////// Gdb Output, State & Capability Handling //////////
protected:
void handleResponse(const QString &buff);
Q_INVOKABLE void handleResponse(const QString &buff);
void handleAsyncOutput(const QString &asyncClass, const GdbMi &result);
void handleStopResponse(const GdbMi &data);
void handleResultRecord(DebuggerResponse *response);

View File

@@ -45,7 +45,7 @@ public:
void run();
private slots:
private:
void handleRemoteError(const QString &errorMessage);
void portGathererError(const QString &errorMessage);
void portListReady();
@@ -56,7 +56,6 @@ private slots:
void handleProcessStarted();
void handleConnectionError();
private:
void attach(int port);
void logMessage(const QString &line);
StartGdbServerDialogPrivate *d;

View File

@@ -310,7 +310,6 @@ public:
(void) new OutputHighlighter(this);
}
public slots:
void gotoResult(int i)
{
QString needle = QString::number(i) + QLatin1Char('^');

View File

@@ -64,7 +64,6 @@ public:
static QChar charForChannel(int channel);
static LogChannel channelForChar(QChar c);
public slots:
void clearContents();
void sendCommand();
void executeLine();

View File

@@ -55,7 +55,7 @@ public:
void expressionEvaluated(quint32 queryId, const QVariant &result);
private slots:
private:
void disconnected();
void errorMessageBoxFinished(int result);
void updateCurrentContext();
@@ -67,7 +67,6 @@ private slots:
void appStartupFailed(const QString &errorMessage);
void appendMessage(const QString &msg, Utils::OutputFormat);
private:
void notifyEngineRemoteServerRunning(const QString &, int pid) override;
void notifyEngineRemoteSetupFinished(const RemoteSetupResult &result) override;

View File

@@ -30,6 +30,8 @@
#include <utils/qtcassert.h>
using namespace Utils;
namespace Debugger {
namespace Internal {
@@ -286,9 +288,10 @@ void RegisterValue::shiftOneDigit(uint digit, RegisterFormat format)
//
//////////////////////////////////////////////////////////////////
class RegisterItem;
class RegisterSubItem;
class RegisterEditItem : public Utils::TreeItem
class RegisterEditItem : public TypedTreeItem<TreeItem, RegisterSubItem>
{
public:
RegisterEditItem(int pos, RegisterKind subKind, int subSize, RegisterFormat format)
@@ -306,7 +309,7 @@ public:
};
class RegisterSubItem : public Utils::TreeItem
class RegisterSubItem : public TypedTreeItem<RegisterEditItem, RegisterItem>
{
public:
RegisterSubItem(RegisterKind subKind, int subSize, int count, RegisterFormat format)
@@ -333,7 +336,7 @@ public:
bool m_changed;
};
class RegisterItem : public Utils::TreeItem
class RegisterItem : public TypedTreeItem<RegisterSubItem>
{
public:
explicit RegisterItem(const Register &reg);
@@ -460,10 +463,8 @@ QVariant RegisterSubItem::data(int column, int role) const
case RegisterChangedRole:
return m_changed;
case RegisterFormatRole: {
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
return int(registerItem->m_format);
}
case RegisterFormatRole:
return int(parent()->m_format);
case RegisterAsAddressRole:
return 0;
@@ -474,8 +475,7 @@ QVariant RegisterSubItem::data(int column, int role) const
return subTypeName(m_subKind, m_subSize, m_subFormat);
case RegisterValueColumn: {
QTC_ASSERT(parent(), return QVariant());
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
RegisterValue value = registerItem->m_reg.value;
RegisterValue value = parent()->m_reg.value;
QString ba;
for (int i = 0; i != m_count; ++i) {
int tab = 5 * (i + 1) * m_subSize;
@@ -582,14 +582,13 @@ QVariant RegisterEditItem::data(int column, int role) const
return QString("[%1]").arg(m_index);
}
case RegisterValueColumn: {
RegisterItem *registerItem = static_cast<RegisterItem *>(parent()->parent());
RegisterValue value = registerItem->m_reg.value;
RegisterValue value = parent()->parent()->m_reg.value;
return value.subValue(m_subSize, m_index)
.toString(m_subKind, m_subSize, m_subFormat, role == Qt::EditRole);
}
}
case Qt::ToolTipRole: {
RegisterItem *registerItem = static_cast<RegisterItem *>(parent()->parent());
RegisterItem *registerItem = parent()->parent();
return RegisterHandler::tr("Edit bits %1...%2 of register %3")
.arg(m_index * 8).arg(m_index * 8 + 7).arg(registerItem->m_reg.name);
}
@@ -604,7 +603,7 @@ bool RegisterEditItem::setData(int column, const QVariant &value, int role)
if (column == RegisterValueColumn && role == Qt::EditRole) {
QTC_ASSERT(parent(), return false);
QTC_ASSERT(parent()->parent(), return false);
RegisterItem *registerItem = static_cast<RegisterItem *>(parent()->parent());
RegisterItem *registerItem = parent()->parent();
Register &reg = registerItem->m_reg;
RegisterValue vv;
vv.fromString(value.toString(), m_subFormat);
@@ -618,8 +617,7 @@ bool RegisterEditItem::setData(int column, const QVariant &value, int role)
Qt::ItemFlags RegisterEditItem::flags(int column) const
{
QTC_ASSERT(parent(), return Qt::ItemFlags());
RegisterSubItem *registerSubItem = static_cast<RegisterSubItem *>(parent());
Qt::ItemFlags f = registerSubItem->flags(column);
Qt::ItemFlags f = parent()->flags(column);
if (column == RegisterValueColumn)
f |= Qt::ItemIsEditable;
return f;

View File

@@ -37,7 +37,6 @@ class RegisterTreeView : public Utils::BaseTreeView
public:
RegisterTreeView();
public slots:
void reloadRegisters();
private:

View File

@@ -41,7 +41,7 @@ namespace Internal {
class GdbMi;
class ThreadItem;
class ThreadsHandler : public Utils::LeveledTreeModel<ThreadItem>
class ThreadsHandler : public Utils::LeveledTreeModel<Utils::TreeItem, ThreadItem>
{
Q_OBJECT

View File

@@ -36,7 +36,6 @@
#include "simplifytype.h"
#include "imageviewer.h"
#include "watchutils.h"
#include "cdb/cdbengine.h" // Remove after string freeze
#include <coreplugin/icore.h>
@@ -1185,9 +1184,9 @@ QString WatchModel::nameForFormat(int format)
case AutomaticFormat: return tr("Automatic");
case RawFormat: return tr("Raw Data");
case SimpleFormat: return CdbEngine::tr("Normal"); // FIXME: String
case SimpleFormat: return tr("Normal");
case EnhancedFormat: return tr("Enhanced");
case SeparateFormat: return CdbEngine::tr("Separate Window"); // FIXME: String
case SeparateFormat: return tr("Separate Window");
case Latin1StringFormat: return tr("Latin1 String");
case SeparateLatin1StringFormat: return tr("Latin1 String in Separate Window");

View File

@@ -88,6 +88,9 @@ BranchDialog::BranchDialog(QWidget *parent) :
connect(m_ui->branchView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &BranchDialog::enableButtons);
connect(m_model, &QAbstractItemModel::dataChanged, this, &BranchDialog::resizeColumns);
connect(m_model, &QAbstractItemModel::rowsInserted, this, &BranchDialog::resizeColumns);
connect(m_model, &QAbstractItemModel::rowsRemoved, this, &BranchDialog::resizeColumns);
enableButtons();
}
@@ -109,8 +112,7 @@ void BranchDialog::refresh(const QString &repository, bool force)
VcsOutputWindow::appendError(errorMessage);
m_ui->branchView->expandAll();
m_ui->branchView->resizeColumnToContents(0);
m_ui->branchView->resizeColumnToContents(1);
resizeColumns();
}
void BranchDialog::refreshIfSame(const QString &repository)
@@ -119,6 +121,12 @@ void BranchDialog::refreshIfSame(const QString &repository)
refreshCurrentRepository();
}
void BranchDialog::resizeColumns()
{
m_ui->branchView->resizeColumnToContents(0);
m_ui->branchView->resizeColumnToContents(1);
}
void BranchDialog::enableButtons()
{
QModelIndex idx = selectedIndex();

View File

@@ -52,11 +52,11 @@ public:
explicit BranchDialog(QWidget *parent = 0);
~BranchDialog() override;
public slots:
void refresh(const QString &repository, bool force);
void refreshIfSame(const QString &repository);
private:
void resizeColumns();
void enableButtons();
void refreshCurrentRepository();
void add();

View File

@@ -470,6 +470,14 @@ QString BranchModel::sha(const QModelIndex &idx) const
return node->sha;
}
QDateTime BranchModel::dateTime(const QModelIndex &idx) const
{
if (!idx.isValid())
return QDateTime();
BranchNode *node = indexToNode(idx);
return node->dateTime;
}
bool BranchModel::hasTags() const
{
return m_rootNode->children.count() > Tags;
@@ -590,6 +598,7 @@ QModelIndex BranchModel::addBranch(const QString &name, bool track, const QModel
QString startSha;
QString output;
QString errorMessage;
QDateTime branchDateTime;
QStringList args;
args << (track ? QLatin1String("--track") : QLatin1String("--no-track"));
@@ -597,8 +606,17 @@ QModelIndex BranchModel::addBranch(const QString &name, bool track, const QModel
if (!fullTrackedBranch.isEmpty()) {
args << fullTrackedBranch;
startSha = sha(startPoint);
branchDateTime = dateTime(startPoint);
} else {
startSha = m_client->synchronousTopRevision(m_workingDirectory);
QString output;
QString errorMessage;
const QStringList arguments({"-n1", "--format=%H %ct"});
if (m_client->synchronousLog(m_workingDirectory, arguments, &output, &errorMessage,
VcsCommand::SuppressCommandLogging)) {
const QStringList values = output.split(' ');
startSha = values[0];
branchDateTime = QDateTime::fromTime_t(values[1].toInt());
}
}
if (!m_client->synchronousBranchCmd(m_workingDirectory, args, &output, &errorMessage)) {
@@ -624,7 +642,8 @@ QModelIndex BranchModel::addBranch(const QString &name, bool track, const QModel
local = child;
}
int pos = positionForName(local, leafName);
auto newNode = new BranchNode(leafName, startSha, track ? trackedBranch : QString());
auto newNode = new BranchNode(leafName, startSha, track ? trackedBranch : QString(),
branchDateTime);
if (!added)
beginInsertRows(nodeToIndex(local, 0), pos, pos);
newNode->parent = local;

View File

@@ -68,6 +68,7 @@ public:
QString fullName(const QModelIndex &idx, bool includePrefix = false) const;
QStringList localBranchNames() const;
QString sha(const QModelIndex &idx) const;
QDateTime dateTime(const QModelIndex &idx) const;
bool hasTags() const;
bool isLocal(const QModelIndex &idx) const;
bool isLeaf(const QModelIndex &idx) const;

Some files were not shown because too many files have changed in this diff Show More