Merge "Merge remote-tracking branch 'origin/4.3'"

This commit is contained in:
Eike Ziller
2017-03-22 09:27:56 +00:00
committed by The Qt Project
67 changed files with 560 additions and 703 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1570,36 +1570,54 @@
\list
\li \uicontrol {All Projects} searches files matching the
defined file pattern in all currently open projects.
For example, to search for a string only in \c {.cpp}
and \c {.h} files, enter in \uicontrol {File pattern}
\c {*.cpp,*.h}.
\li \uicontrol {All Projects} searches from all currently open
projects.
\image qtcreator-search-allprojects.png
\li \uicontrol {Current Project} searches files matching the
defined file pattern only in the project you are currently
editing.
\li \uicontrol {Current Project} searches from the project you
are currently editing.
\li \uicontrol {Files in File System} recursively searches files
matching the defined file pattern in the selected directory.
\li \uicontrol {Files in File System} recursively searches from
the selected directory.
\image qtcreator-search-filesystem.png
Select the \uicontrol {Use Git Grep} check box to use Git to
only search tracked files in the Git work tree. To restrict
the search to the HEAD, a tag, a local or remote branch, or
a commit hash, enter a reference in the field. Leave the
field empty to search through the file system.
In the \uicontrol {Search engine} field, select the search
engine to use:
\li \uicontrol {Current File} searches only the current file.
\list
\li Select \uicontrol Internal to use the \QC search
engine.
\li \uicontrol {Open Documents} searches all open files.
\li Select \uicontrol {Git Grep} to use Git to only
search tracked files in the Git work tree. To
restrict the search to the HEAD, a tag, a local or
remote branch, or a commit hash, enter a reference.
Leave the field empty to search through the file
system.
\li Select \uicontrol {Silver Searcher} to use the
experimental Silver Searcher plugin. For more
information, see \l{Enabling Silver Searcher}.
\endlist
\li \uicontrol {Current File} searches only from the current
file.
\li \uicontrol {Open Documents} searches from all open files.
\endlist
\li In the \uicontrol {File pattern} field, specify file patterns to
restrict the search to files that match the pattern. For example, to
search for a string only in \c {.cpp} and \c {.h} files, enter
\c {*.cpp,*.h}.
\li In the \uicontrol {Exclusion pattern} field, specify file patterns
to omit files from the search.
\li Enter the text you are looking for and click \uicontrol Search.
\image qtcreator-searchresults.png
@@ -1628,6 +1646,32 @@
\note You can use \uicontrol {Advanced Find} also to search for symbols. For
more information, see \l{Finding Symbols}.
\section1 Enabling Silver Searcher
You can use Silver Searcher as a search engine in \QC if you install
Silver Searcher on the development PC and enable the experimental plugin.
To use Silver Searcher:
\list 1
\li Download and install Silver Searcher from
\l {https://geoff.greer.fm/ag/}{The Silver Searcher} or
\l {https://github.com/ggreer/the_silver_searcher}{GitHub}.
You might have to build Silver Searcher from sources for some
platforms.
\li Select \uicontrol Help > \uicontrol {About Plugins} >
\uicontrol {Utilities} > \uicontrol {SilverSearcher} to enable the
plugin.
\li Restart \QC to be able to use the plugin.
\li When searching, select \uicontrol {Silver Searcher} in the
\uicontrol {Search engine} field.
\endlist
*/

View File

@@ -85,10 +85,9 @@
\endlist
\QC creates the test in the \c{tests\auto} directory in the project
directory. Edit the .cpp file to add private slots for each test
function in your test. For more information about creating Qt tests, see
\l{Creating a Test}.
\QC creates the test in the specified project directory. Edit the .cpp file
to add private slots for each test function in your test. For more information
about creating Qt tests, see \l{Creating a Test}.
\section2 Creating Google Tests
@@ -133,8 +132,7 @@
\endlist
\QC creates the test in the \c{tests\auto} directory in the project
directory.
\QC creates the test in the specified project directory.
\section1 Setting Up the Google C++ Testing Framework

View File

@@ -318,28 +318,6 @@ class Dumper(DumperBase):
% (self.qtCoreModuleName(), namespace))
return namespace
def couldBeQObjectVTable(self, vtablePtr):
try:
customEventFunc = self.extractPointer(vtablePtr + 8 * self.ptrSize())
except:
self.bump('nostruct-3')
return False
if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
try:
delta = int.from_bytes(self.readRawMemory(customEventFunc + 1, 4), byteorder='little')
if (customEventFunc + 5 + delta) in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
except:
pass
try:
return 'QObject::customEvent' in cdbext.getNameByAddress(customEventFunc)
except:
return False
def qtVersion(self):
qtVersion = self.findValueByExpression('((void**)&%s)[2]' % self.qtHookDataSymbolName())
if qtVersion is None and self.qtCoreModuleName() is not None:

View File

@@ -37,7 +37,7 @@ def extractPointerType(d, value):
postfix = ""
while stripTypeName(value) == "CPlusPlus::PointerType":
postfix += "*"
value = d.downcast(value["_elementType"]["_type"])
value = value["_elementType"]["_type"]
try:
return readLiteral(d, value["_name"]) + postfix
except:
@@ -60,7 +60,7 @@ def readTemplateName(d, value):
for i in range(int(size)):
if i > 0:
name += ", "
name += extractPointerType(d, d.downcast(start[i]["_type"]))
name += extractPointerType(d, start[i]["_type"])
except:
return "<not accessible>"
name += ">"
@@ -69,7 +69,6 @@ def readTemplateName(d, value):
def readLiteral(d, value):
if d.isNull(value):
return "<null>"
value = d.downcast(value)
type = value.type.unqualified()
try:
type = type.target()
@@ -147,7 +146,7 @@ def qdump__CPlusPlus__IntegerType(d, value):
d.putPlainChildren(value)
def qdump__CPlusPlus__FullySpecifiedType(d, value):
type = d.downcast(value["_type"])
type = value["_type"]
typeName = stripTypeName(type)
if typeName == "CPlusPlus::NamedType":
dumpLiteral(d, type["_name"])

View File

@@ -1494,12 +1494,49 @@ class DumperBase:
return self.couldBeQObjectVTable(vtablePtr)
def couldBeQObjectVTable(self, vtablePtr):
def getJumpAddress_x86(dumper, address):
relativeJumpCode = 0xe9
jumpCode = 0xff
data = dumper.readRawMemory(address, 6)
primaryOpcode = data[0]
if primaryOpcode == relativeJumpCode:
# relative jump on 32 and 64 bit with a 32bit offset
offset = int.from_bytes(data[1:5], byteorder='little')
return address + 5 + offset
if primaryOpcode == jumpCode:
if data[1] != 0x25: # check for known extended opcode
return 0
# 0xff25 is a relative jump on 64bit and an absolute jump on 32 bit
if self.ptrSize() == 8:
offset = int.from_bytes(data[2:6], byteorder='little')
return address + 6 + offset
else:
return int.from_bytes(data[2:6], byteorder='little')
return 0
# Do not try to extract a function pointer if there are no values to compare with
if self.qtCustomEventFunc == 0 and self.qtCustomEventPltFunc == 0:
return False
try:
customEventFunc = self.extractPointer(vtablePtr + 9 * self.ptrSize())
customEventOffset = 8 if self.isMsvcTarget() else 9
customEventFunc = self.extractPointer(vtablePtr + customEventOffset * self.ptrSize())
except:
self.bump('nostruct-3')
return False
if self.isWindowsTarget():
if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
# The vtable may point to a function that is just calling the customEvent function
customEventFunc = getJumpAddress_x86(self, customEventFunc)
if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
customEventFunc = self.extractPointer(customEventFunc)
if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
# If the object is defined in another module there may be another level of indirection
customEventFunc = getJumpAddress_x86(self, customEventFunc)
return customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc)
# def extractQObjectProperty(objectPtr):
@@ -3121,10 +3158,6 @@ class DumperBase:
val.type = self.dumper.createType(typish)
return val
def downcast(self):
self.check()
return self
def address(self):
self.check()
return self.laddress

View File

@@ -487,12 +487,20 @@ def qdump__QFile(d, value):
# 9fc0965 and a373ffcd change the layout of the private structure
qtVersion = d.qtVersion()
is32bit = d.ptrSize() == 4
if qtVersion >= 0x050600:
if qtVersion >= 0x050700:
if d.isWindowsTarget():
if d.isMsvcTarget():
offset = 184 if is32bit else 248
else:
offset = 164 if is32bit else 248
offset = 172 if is32bit else 248
else:
offset = 168 if is32bit else 248
elif qtVersion >= 0x050600:
if d.isWindowsTarget():
if d.isMsvcTarget():
offset = 184 if is32bit else 248
else:
offset = 180 if is32bit else 248
else:
offset = 168 if is32bit else 248
elif qtVersion >= 0x050500:

View File

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

View File

@@ -1,26 +0,0 @@
import qbs
@if "%{TestFrameWork}" == "GTest"
import qbs.Environment
@endif
Project {
name: "auto tests"
@if "%{TestFrameWork}" == "GTest"
property string googletestDir: {
if (typeof Environment.getEnv("GOOGLETEST_DIR") === 'undefined') {
console.warn("Using googletest src dir specified at Qt Creator wizard")
console.log("set GOOGLETEST_DIR as environment variable or Qbs property to get rid of this message")
return "%{GTestRepository}"
} else {
return Environment.getEnv("GOOGLETEST_DIR")
}
}
@endif
@if "%{BuildAutoTests}" == "debug"
condition: qbs.buildVariant === "debug"
@endif
references: [
"%{JS: '%{TestCaseName}'.toLowerCase()}/%{JS: '%{TestCaseName}'.toLowerCase()}.qbs"
]
}

View File

@@ -1,31 +0,0 @@
%{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,18 +0,0 @@
@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 c++11
CONFIG -= app_bundle
TEMPLATE = app
TARGET = %{ProjectName}
SOURCES += %{MainCppName}

View File

@@ -1,27 +0,0 @@
import qbs
CppApplication {
type: "application"
consoleApplication: true
name: "%{ProjectName}"
@if "%{TestFrameWork}" == "QtTest"
@if "%{RequireGUI}" == "true"
Depends { name: "Qt.core" }
Depends { name: "Qt.gui" }
Depends {
name: "Qt.widgets"
condition: Qt.core.versionMajor > 4
}
@else
Depends { name: "Qt.core" }
@endif
@endif
cpp.cxxLanguageVersion: "c++11"
files: [
"%{MainCppName}"
]
}

View File

@@ -1,3 +0,0 @@
TEMPLATE = subdirs
SUBDIRS += auto

View File

@@ -1,8 +0,0 @@
import qbs
Project {
name: "%{ProjectName} tests"
references: [
"auto/auto.qbs"
]
}

View File

@@ -1,12 +0,0 @@
TEMPLATE = subdirs
@if "%{BuildAutoTests}" == "always"
SUBDIRS += src \
tests
@else
SUBDIRS += src
CONFIG(debug, debug|release) {
SUBDIRS += tests
}
@endif

View File

@@ -1,8 +0,0 @@
import qbs
Project {
references: [
"src/src.qbs",
"tests/tests.qbs"
]
}

View File

@@ -14,7 +14,7 @@ TEMPLATE = app
SOURCES += %{TestCaseFileWithCppSuffix}
@else
include(../gtest_dependency.pri)
include(gtest_dependency.pri)
TEMPLATE = app
@if "%{GTestCXX11}" == "true"

View File

@@ -1,6 +1,7 @@
import qbs
@if "%{TestFrameWork}" == "GTest"
import "../googlecommon.js" as googleCommon
import qbs.Environment
import "googlecommon.js" as googleCommon
@endif
CppApplication {
@@ -16,6 +17,19 @@ CppApplication {
]
@else
consoleApplication: true
@if "%{TestFrameWork}" == "GTest"
property string googletestDir: {
if (typeof Environment.getEnv("GOOGLETEST_DIR") === 'undefined') {
console.warn("Using googletest src dir specified at Qt Creator wizard")
console.log("set GOOGLETEST_DIR as environment variable or Qbs property to get rid of this message")
return "%{GTestRepository}"
} else {
return Environment.getEnv("GOOGLETEST_DIR")
}
}
@endif
@if "%{GTestCXX11}" == "true"
cpp.cxxLanguageVersion: "c++11"
cpp.defines: [ "GTEST_LANG_CXX11" ]
@@ -23,13 +37,13 @@ CppApplication {
cpp.dynamicLibraries: [ "pthread" ]
cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
.concat(googleCommon.getGMockIncludes(project.googletestDir))
cpp.includePaths: [].concat(googleCommon.getGTestIncludes(googletestDir))
.concat(googleCommon.getGMockIncludes(googletestDir))
files: [
"%{MainCppName}",
"%{TestCaseFileWithHeaderSuffix}",
].concat(googleCommon.getGTestAll(project.googletestDir))
.concat(googleCommon.getGMockAll(project.googletestDir))
].concat(googleCommon.getGTestAll(googletestDir))
.concat(googleCommon.getGMockAll(googletestDir))
@endif
}

View File

@@ -0,0 +1,57 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
PROJECT(%{TestCaseName}
LANGUAGES CXX)
@if "%{TestFrameWork}" == "QtTest"
find_package(Qt5Test REQUIRED)
@if "%{RequireGUI}" == "true"
find_package(Qt5Gui REQUIRED)
@endif
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_CXX_STANDARD 11)
ENABLE_TESTING()
add_executable(${PROJECT_NAME} %{TestCaseFileWithCppSuffix})
add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME})
@if "%{RequireGUI}" == "true"
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui Qt5::Test)
@else
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Test)
@endif
@else
@if "%{GTestCXX11}" == "true"
add_definitions(-DGTEST_LANGUAGE_CXX11)
@endif
find_package(Threads REQUIRED)
if ($ENV{GOOGLETEST_DIR})
SET(GOOGLETEST_DIR $ENV{GOOGLETEST_DIR})
else ()
message(WARNING "Using googletest src dir specified at Qt Creator wizard")
SET(GOOGLETEST_DIR "%{GTestRepository}")
endif ()
if (EXISTS ${GOOGLETEST_DIR})
SET(GTestSrc ${GOOGLETEST_DIR}/googletest)
SET(GMockSrc ${GOOGLETEST_DIR}/googlemock)
else ()
message( FATAL_ERROR "No googletest src dir found - set GOOGLETEST_DIR to enable!")
endif ()
include_directories(${GTestSrc} ${GTestSrc}/include ${GMockSrc} ${GMockSrc}/include)
add_executable(${PROJECT_NAME} %{MainCppName} %{TestCaseFileWithHeaderSuffix}
${GTestSrc}/src/gtest-all.cc
${GMockSrc}/src/gmock-all.cc)
add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
@endif

View File

@@ -3,7 +3,7 @@
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
"id": "R.AutoTest",
"category": "H.Project",
"trDescription": "Creates a new project including an auto test skeleton.",
"trDescription": "Creates a new unit test project. Unit tests allow you to verify that the code is fit for use and that there are no regressions.",
"trDisplayName": "Auto Test Project",
"trDisplayCategory": "Other Project",
"icon": "autotest_24.png",
@@ -13,7 +13,7 @@
"options":
[
{ "key": "ProjectFilePath",
"value": "%{JS: '%{BuildSystem}' == 'qmake' ? '%{ProFileName}' : '%{QbsFileName}' }"
"value": "%{JS: '%{BuildSystem}' == 'qmake' ? '%{ProFileName}' : ('%{BuildSystem}' == 'qbs' ? '%{QbsFileName}' : '%{CMakeFileName}') }"
},
{ "key": "ProFileName",
"value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}"
@@ -22,6 +22,10 @@
"key": "QbsFileName",
"value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}"
},
{
"key": "CMakeFileName",
"value": "%{ProjectDirectory}/CMakeLists.txt"
},
{ "key": "IsTopLevelProject",
"value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }"
},
@@ -46,7 +50,7 @@
"typeId": "Project",
"data":
{
"trDescription": "This wizard creates a simple project with an additional auto test skeleton."
"trDescription": "This wizard creates a simple unit test project."
}
},
{
@@ -133,26 +137,6 @@
"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:",
@@ -179,6 +163,11 @@
"trKey": "Qbs",
"value": "qbs",
"condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}"
},
{
"trKey": "CMake",
"value": "cmake",
"condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}"
}
]
}
@@ -191,7 +180,8 @@
"typeId": "Kits",
"enabled": "%{IsTopLevelProject}",
"data": {
"projectFilePath": "%{ProjectFilePath}"
"projectFilePath": "%{ProjectFilePath}",
"requiredFeatures": [ "%{JS: ('%{BuildSystem}' == 'cmake' && '%{TestFrameWork}' == 'QtTest') ? 'QtSupport.Wizards.FeatureQt.5' : 'QtSupport.Wizards.FeatureQt' }" ]
}
},
{
@@ -206,98 +196,54 @@
"typeId": "File",
"data":
[
{
"source": "files/tmp.pro",
"target": "%{ProFileName}",
"condition": "%{JS: '%{BuildSystem}' == 'qmake'}",
"openAsProject": true
},
{
"source": "files/tmp.qbs",
"target": "%{QbsFileName}",
"condition": "%{JS: '%{BuildSystem}' == 'qbs'}",
"openAsProject": true
},
{
"source": "files/src.pro",
"target": "src/src.pro",
"condition": "%{JS: '%{BuildSystem}' == 'qmake'}",
"openInEditor": false
},
{
"source": "files/src.qbs",
"target": "src/src.qbs",
"condition": "%{JS: '%{BuildSystem}' == 'qbs'}",
"openInEditor": false
},
{
"source": "files/main.cpp",
"target": "src/%{MainCppName}",
"openInEditor": true
},
{
"source": "files/tests.pro",
"target": "tests/tests.pro",
"condition": "%{JS: '%{BuildSystem}' == 'qmake'}",
"openInEditor": false
},
{
"source": "files/tests.qbs",
"target": "tests/tests.qbs",
"condition": "%{JS: '%{BuildSystem}' == 'qbs'}",
"openInEditor": false
},
{
"source": "files/auto.pro",
"target": "tests/auto/auto.pro",
"condition": "%{JS: '%{BuildSystem}' == 'qmake'}",
"openInEditor": false
},
{
"source": "files/auto.qbs",
"target": "tests/auto/auto.qbs",
"condition": "%{JS: '%{BuildSystem}' == 'qbs'}",
"openInEditor": false
},
{
"source": "files/gtest_dependency.pri",
"target": "tests/auto/gtest_dependency.pri",
"target": "gtest_dependency.pri",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest' && '%{BuildSystem}' == 'qmake'}",
"openInEditor": false
},
{
"source": "files/googlecommon.js",
"target": "tests/auto/googlecommon.js",
"target": "googlecommon.js",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest' && '%{BuildSystem}' == 'qbs'}",
"openInEditor": false
},
{
"source": "files/tst.pro",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/%{TestCaseName}'.toLowerCase() + '.pro' }",
"target": "%{ProjectFilePath}",
"condition": "%{JS: '%{BuildSystem}' == 'qmake'}",
"openInEditor": false
"openInEditor": false,
"openAsProject": true
},
{
"source": "files/tst.qbs",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/%{TestCaseName}'.toLowerCase() + '.qbs' }",
"target": "%{ProjectFilePath}",
"condition": "%{JS: '%{BuildSystem}' == 'qbs'}",
"openInEditor": false
"openInEditor": false,
"openAsProject": true
},
{
"source": "files/tst.txt",
"target": "CMakeLists.txt",
"condition": "%{JS: '%{BuildSystem}' == 'cmake'}",
"openInEditor": false,
"openAsProject": true
},
{
"source": "files/tst_src.h",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/'.toLowerCase() + '%{TestCaseFileWithHeaderSuffix}' }",
"target": "%{TestCaseFileWithHeaderSuffix}",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest'}",
"openInEditor": true
},
{
"source": "files/tst_src.cpp",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}/'.toLowerCase() + '%{TestCaseFileWithCppSuffix}' }",
"target": "%{TestCaseFileWithCppSuffix}",
"condition": "%{JS: '%{TestFrameWork}' == 'QtTest'}",
"openInEditor": true
},
{
"source": "files/tst_main.cpp",
"target": "%{JS: 'tests/auto/' + '%{TestCaseName}'.toLowerCase() + '/%{MainCppName}' }",
"target": "%{MainCppName}",
"condition": "%{JS: '%{TestFrameWork}' == 'GTest'}",
"openInEditor": true
},

View File

@@ -62,10 +62,7 @@ QString NameController::convertFileNameToElementName(const QString &fileName)
elementName += baseName.at(i).toTitleCase();
makeTitlecase = false;
} else {
if (insertSpace) {
elementName += QLatin1Char(' ');
insertSpace = false;
}
// insertSpace must be false here
elementName += baseName.at(i);
}
}

View File

@@ -589,7 +589,7 @@ void ClassItem::updateMembers(const Style *style)
bool addSpace = false;
if (currentVisibility)
*currentVisibility = member.visibility();
if (member.group() != currentGroup) {
if (currentGroup && member.group() != *currentGroup) {
*text += QString(QStringLiteral("[%1]")).arg(member.group());
addNewline = true;
*currentGroup = member.group();

View File

@@ -26,6 +26,7 @@
#include "basetreeview.h"
#include "progressindicator.h"
#include "treemodel.h"
#include <utils/qtcassert.h>
@@ -271,35 +272,14 @@ BaseTreeView::~BaseTreeView()
void BaseTreeView::setModel(QAbstractItemModel *m)
{
struct ExtraConnection {
const char *signature;
const char *qsignal;
QObject *receiver;
const char *qslot;
};
#define DESC(sign, receiver, slot) { #sign, SIGNAL(sign), receiver, SLOT(slot) }
const ExtraConnection c[] = {
DESC(requestExpansion(QModelIndex), this, expand(QModelIndex))
};
#undef DESC
QAbstractItemModel *oldModel = model();
if (oldModel) {
for (unsigned i = 0; i < sizeof(c) / sizeof(c[0]); ++i) {
int index = model()->metaObject()->indexOfSignal(c[i].signature);
if (index != -1)
disconnect(model(), c[i].qsignal, c[i].receiver, c[i].qslot);
}
}
if (BaseTreeModel *oldModel = qobject_cast<BaseTreeModel *>(model()))
disconnect(oldModel, &BaseTreeModel::requestExpansion, this, &BaseTreeView::expand);
TreeView::setModel(m);
if (m) {
for (unsigned i = 0; i < sizeof(c) / sizeof(c[0]); ++i) {
int index = m->metaObject()->indexOfSignal(c[i].signature);
if (index != -1)
connect(model(), c[i].qsignal, c[i].receiver, c[i].qslot);
}
if (BaseTreeModel *newModel = qobject_cast<BaseTreeModel *>(m))
connect(newModel, &BaseTreeModel::requestExpansion, this, &BaseTreeView::expand);
d->restoreState();
QVariant delegateBlob = m->data(QModelIndex(), ItemDelegateRole);

View File

@@ -183,7 +183,7 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt
if (!expandNestedMacros(str, &i, ret))
return false;
varName.chop(1);
varName += ret;
varName += *ret;
} else if (currArg == &varName && c == '-' && prev == ':' && validateVarName(varName)) {
varName.chop(1);
currArg = &defaultValue;

View File

@@ -37,13 +37,9 @@
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QFileSystemWatcher>
namespace Autotest {
namespace Internal {
static QFileSystemWatcher s_directoryWatcher;
TestTreeItem *QuickTestParseResult::createTestTreeItem() const
{
if (itemType == TestTreeItem::Root || itemType == TestTreeItem::TestDataTag)
@@ -126,7 +122,7 @@ static QString quickTestName(const CPlusPlus::Document::Ptr &doc)
return QString();
}
static QList<QmlJS::Document::Ptr> scanDirectoryForQuickTestQmlFiles(const QString &srcDir)
QList<QmlJS::Document::Ptr> QuickTestParser::scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const
{
QStringList dirs(srcDir);
QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance();
@@ -142,9 +138,9 @@ static QList<QmlJS::Document::Ptr> scanDirectoryForQuickTestQmlFiles(const QStri
while (it.hasNext()) {
it.next();
QFileInfo fi(it.fileInfo().canonicalFilePath());
dirs << fi.filePath();
dirs.append(fi.filePath());
}
s_directoryWatcher.addPaths(dirs);
emit updateWatchPaths(dirs);
QList<QmlJS::Document::Ptr> foundDocs;
@@ -211,9 +207,9 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface<TestParseResultPtr
return true;
}
static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document,
const Core::Id &id)
bool QuickTestParser::handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document,
const Core::Id &id) const
{
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
if (quickTestName(document).isEmpty())
@@ -229,32 +225,35 @@ static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterfa
if (srcDir.isEmpty())
return false;
if (futureInterface.isCanceled())
return false;
const QList<QmlJS::Document::Ptr> qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir);
bool result = false;
for (const QmlJS::Document::Ptr &qmlJSDoc : qmlDocs)
for (const QmlJS::Document::Ptr &qmlJSDoc : qmlDocs) {
if (futureInterface.isCanceled())
break;
result |= checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id, proFile);
}
return result;
}
QuickTestParser::QuickTestParser()
: CppParser()
{
QObject::connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged, [] {
const QStringList &dirs = s_directoryWatcher.directories();
connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged, [this] {
const QStringList &dirs = m_directoryWatcher.directories();
if (!dirs.isEmpty())
s_directoryWatcher.removePaths(dirs);
m_directoryWatcher.removePaths(dirs);
});
QObject::connect(&s_directoryWatcher, &QFileSystemWatcher::directoryChanged,
connect(&m_directoryWatcher, &QFileSystemWatcher::directoryChanged,
[this] { TestTreeModel::instance()->parser()->emitUpdateTestTree(this); });
connect(this, &QuickTestParser::updateWatchPaths,
&m_directoryWatcher, &QFileSystemWatcher::addPaths, Qt::QueuedConnection);
}
QuickTestParser::~QuickTestParser()
{
QObject::disconnect(&s_directoryWatcher, 0, 0, 0);
const QStringList &dirs = s_directoryWatcher.directories();
if (!dirs.isEmpty())
s_directoryWatcher.removePaths(dirs);
}
void QuickTestParser::init(const QStringList &filesToParse)

View File

@@ -29,6 +29,8 @@
#include <qmljs/qmljsdocument.h>
#include <QFileSystemWatcher>
namespace Autotest {
namespace Internal {
@@ -39,8 +41,9 @@ public:
TestTreeItem *createTestTreeItem() const override;
};
class QuickTestParser : public CppParser
class QuickTestParser : public QObject, public CppParser
{
Q_OBJECT
public:
QuickTestParser();
virtual ~QuickTestParser();
@@ -48,9 +51,15 @@ public:
void release() override;
bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
const QString &fileName) override;
signals:
void updateWatchPaths(const QStringList &directories) const;
private:
bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
CPlusPlus::Document::Ptr document, const Core::Id &id) const;
QList<QmlJS::Document::Ptr> scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const;
QmlJS::Snapshot m_qmlSnapshot;
QHash<QString, QString> m_proFilesForQmlFiles;
QFileSystemWatcher m_directoryWatcher;
};
} // namespace Internal

View File

@@ -645,7 +645,7 @@ int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, boo
int block = from / m_blockSize;
const int lowerBound = qMax(qint64(0), from - SearchStride);
while (from > lowerBound) {
if (!requestDataAt(block * m_blockSize))
if (!requestDataAt(qint64(block) * m_blockSize))
return -1;
QByteArray data = blockData(block);
::memcpy(b + m_blockSize, b, trailing);
@@ -658,7 +658,7 @@ int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, boo
if (pos >= 0)
return pos + block * m_blockSize;
--block;
from = block * m_blockSize + (m_blockSize-1) + trailing;
from = qint64(block) * m_blockSize + (m_blockSize-1) + trailing;
}
return lowerBound == 0 ? -1 : -2;
}

View File

@@ -313,9 +313,9 @@ QStringList CMakeProject::files(FilesMode fileMode) const
if (ProjectNode *rpn = rootProjectNode()) {
rpn->forEachNode([&](const FileNode *fn) {
const bool isGenerated = fn->isGenerated();
if (fileMode == Project::SourceFiles && !isGenerated)
if ((fileMode & Project::SourceFiles) && !isGenerated)
result.append(fn->filePath().toString());
if (fileMode == Project::GeneratedFiles && isGenerated)
if ((fileMode & Project::GeneratedFiles) && isGenerated)
result.append(fn->filePath().toString());
});
}

View File

@@ -1033,6 +1033,12 @@ void EditorManagerPrivate::readSettings()
d->m_autoSaveEnabled = qs->value(autoSaveEnabledKey).toBool();
d->m_autoSaveInterval = qs->value(autoSaveIntervalKey).toInt();
}
if (qs->contains(autoSuspendEnabledKey)) {
d->m_autoSuspendEnabled = qs->value(autoSuspendEnabledKey).toBool();
d->m_autoSuspendMinDocumentCount = qs->value(autoSuspendMinDocumentCountKey).toInt();
}
updateAutoSave();
}

View File

@@ -1696,10 +1696,16 @@ QmlV8ObjectData QmlEnginePrivate::extractData(const QVariant &data) const
if (dataMap.contains("value")) {
QVariant value = dataMap.value("value");
if (value.isNull())
// The QVariant representation of null has changed across various Qt versions
// 5.6, 5.7: QVariant::Invalid
// 5.8: isValid(), !isNull(), type() == 51; only typeName() is unique: "std::nullptr_t"
// 5.9: isValid(), isNull(); We can then use isNull()
if (!value.isValid() || value.isNull()
|| strcmp(value.typeName(), "std::nullptr_t") == 0) {
objectData.value = "null"; // Yes, null is an object.
else if (value.isValid())
} else if (value.isValid()) {
objectData.expectedProperties = value.toInt();
}
}
if (dataMap.contains("properties"))

View File

@@ -737,10 +737,15 @@ static GerritChangePtr parseSshOutput(const QJsonObject &object)
}
*/
static int restNumberValue(const QJsonObject &object)
{
return object.value("_number").toInt();
}
static GerritChangePtr parseRestOutput(const QJsonObject &object, const GerritServer &server)
{
GerritChangePtr change(new GerritChange);
change->number = object.value("_number").toInt();
change->number = restNumberValue(object);
change->url = QString("%1/%2").arg(server.url()).arg(change->number);
change->title = object.value("subject").toString();
change->owner = parseGerritUser(object.value("owner").toObject());
@@ -751,10 +756,11 @@ static GerritChangePtr parseRestOutput(const QJsonObject &object, const GerritSe
Qt::DateFormat::ISODate).toLocalTime();
// Read current patch set.
const QJsonObject patchSet = object.value("revisions").toObject().begin().value().toObject();
change->currentPatchSet.patchSetNumber = qMax(1, patchSet.value("number").toString().toInt());
change->currentPatchSet.ref = patchSet.value("ref").toString();
change->currentPatchSet.patchSetNumber = qMax(1, restNumberValue(patchSet));
const QJsonObject fetchInfo = patchSet.value("fetch").toObject().value("http").toObject();
change->currentPatchSet.ref = fetchInfo.value("ref").toString();
// Replace * in ssh://*:29418/qt-creator/qt-creator with the hostname
change->currentPatchSet.url = patchSet.value("url").toString().replace('*', server.host);
change->currentPatchSet.url = fetchInfo.value("url").toString().replace('*', server.host);
const QJsonObject labels = object.value("labels").toObject();
for (auto it = labels.constBegin(), end = labels.constEnd(); it != end; ++it) {
const QJsonArray all = it.value().toObject().value("all").toArray();

View File

@@ -91,6 +91,7 @@ bool FindMacroHandler::executeEvent(const MacroEvent &macroEvent)
currentFind->replace(macroEvent.value(BEFORE).toString(),
macroEvent.value(AFTER).toString(),
(Core::FindFlags)macroEvent.value(FLAGS).toInt());
break;
case REPLACESTEP:
currentFind->replaceStep(macroEvent.value(BEFORE).toString(),
macroEvent.value(AFTER).toString(),

View File

@@ -198,8 +198,6 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node,
menu->popup(QCursor::pos());
break;
}
case ProjectExplorer::NodeType::Session:
break;
}
}

View File

@@ -80,9 +80,6 @@ QString PxNodeUtilities::calcRelativePath(const ProjectExplorer::Node *node,
case ProjectExplorer::NodeType::Project:
nodePath = node->filePath().toString();
break;
case ProjectExplorer::NodeType::Session:
QTC_ASSERT(false, return QString());
break;
}
return qmt::NameController::calcRelativePath(nodePath, anchorFolder);

View File

@@ -39,6 +39,9 @@
#include <coreplugin/idocument.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/projecttree.h>
@@ -80,18 +83,52 @@ const char PLUGIN_SETTINGS_KEY[] = "ProjectExplorer.Project.PluginSettings";
} // namespace
namespace ProjectExplorer {
class ContainerNode : public ProjectNode
{
public:
ContainerNode(Project *project)
: ProjectNode(Utils::FileName()),
m_project(project)
{}
QString displayName() const final
{
QString name = m_project->displayName();
const QFileInfo fi = m_project->projectFilePath().toFileInfo();
const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath();
if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir)) {
QString vcsTopic = vc->vcsTopic(dir);
if (!vcsTopic.isEmpty())
name += " [" + vcsTopic + ']';
}
return name;
}
QList<ProjectAction> supportedActions(Node *) const final
{
return {};
}
private:
Project *m_project;
};
// -------------------------------------------------------------------------
// Project
// -------------------------------------------------------------------------
class ProjectPrivate
{
public:
ProjectPrivate(Project *owner) : m_containerNode(owner) {}
~ProjectPrivate();
Core::Id m_id;
Core::IDocument *m_document = nullptr;
ProjectNode *m_rootProjectNode = nullptr;
ContainerNode m_containerNode;
QList<Target *> m_targets;
Target *m_activeTarget = nullptr;
EditorConfiguration m_editorConfiguration;
@@ -117,7 +154,7 @@ ProjectPrivate::~ProjectPrivate()
delete m_accessor;
}
Project::Project() : d(new ProjectPrivate)
Project::Project() : d(new ProjectPrivate(this))
{
d->m_macroExpander.setDisplayName(tr("Project"));
d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"),
@@ -426,9 +463,13 @@ void Project::setRootProjectNode(ProjectNode *root)
ProjectTree::applyTreeManager(root);
ProjectNode *oldNode = d->m_rootProjectNode;
d->m_rootProjectNode = root;
emit projectTreeChanged(this, QPrivateSignal());
// Do not delete oldNode! The ProjectTree owns that!
if (root)
root->setParentFolderNode(&d->m_containerNode);
ProjectTree::emitSubtreeChanged(root);
delete oldNode;
}
Target *Project::restoreTarget(const QVariantMap &data)
@@ -532,6 +573,11 @@ ProjectNode *Project::rootProjectNode() const
return d->m_rootProjectNode;
}
ProjectNode *Project::containerNode() const
{
return &d->m_containerNode;
}
Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMessage)
{
Q_UNUSED(errorMessage);

View File

@@ -81,6 +81,7 @@ public:
static Utils::FileName projectDirectory(const Utils::FileName &top);
virtual ProjectNode *rootProjectNode() const;
ProjectNode *containerNode() const;
bool hasActiveBuildSettings() const;
@@ -142,7 +143,6 @@ public:
Utils::MacroExpander *macroExpander() const;
signals:
void projectTreeChanged(Project *project, QPrivateSignal);
void displayNameChanged();
void fileListChanged();

View File

@@ -71,7 +71,7 @@ static bool sortWrapperNodes(const WrapperNode *w1, const WrapperNode *w2)
}
FlatModel::FlatModel(QObject *parent)
: TreeModel<WrapperNode, WrapperNode>(new WrapperNode(SessionManager::sessionNode()), parent)
: TreeModel<WrapperNode, WrapperNode>(new WrapperNode(nullptr), parent)
{
ProjectTree *tree = ProjectTree::instance();
connect(tree, &ProjectTree::subtreeChanged, this, &FlatModel::update);
@@ -93,17 +93,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
FolderNode *folderNode = node->asFolderNode();
switch (role) {
case Qt::DisplayRole: {
QString name = node->displayName();
if (node->nodeType() == NodeType::Project
&& node->parentFolderNode()
&& node->parentFolderNode()->nodeType() == NodeType::Session) {
const QString vcsTopic = static_cast<ProjectNode *>(node)->vcsTopic();
if (!vcsTopic.isEmpty())
name += QLatin1String(" [") + vcsTopic + QLatin1Char(']');
}
result = name;
result = node->displayName();
break;
}
case Qt::EditRole: {
@@ -124,7 +114,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
case Qt::FontRole: {
QFont font;
if (Project *project = SessionManager::startupProject()) {
if (node == SessionManager::nodeForProject(project))
if (node == project->containerNode())
font.setBold(true);
}
result = font;
@@ -187,23 +177,44 @@ void FlatModel::update()
void FlatModel::rebuildModel()
{
QList<Project *> projects = SessionManager::projects();
Utils::sort(projects, [](Project *p1, Project *p2) {
const int displayNameResult = caseFriendlyCompare(p1->displayName(), p2->displayName());
if (displayNameResult != 0)
return displayNameResult < 0;
return p1 < p2; // sort by pointer value
});
QSet<Node *> seen;
rootItem()->removeChildren();
for (Node *node : SessionManager::sessionNode()->nodes()) {
if (ProjectNode *projectNode = node->asProjectNode()) {
if (!seen.contains(projectNode))
addProjectNode(rootItem(), projectNode, &seen);
for (Project *project : projects) {
WrapperNode *container = new WrapperNode(project->containerNode());
ProjectNode *projectNode = project->rootProjectNode();
if (projectNode) {
addFolderNode(container, projectNode, &seen);
} else {
FileNode *projectFileNode = new FileNode(project->projectFilePath(), FileType::Project, false);
seen.insert(projectFileNode);
container->appendChild(new WrapperNode(projectFileNode));
}
container->sortChildren(&sortWrapperNodes);
rootItem()->appendChild(container);
}
rootItem()->sortChildren(&sortWrapperNodes);
forAllItems([this](WrapperNode *node) {
const QString path = node->m_node->filePath().toString();
const QString displayName = node->m_node->displayName();
ExpandData ed(path, displayName);
if (m_toExpand.contains(ed))
if (node->m_node) {
const QString path = node->m_node->filePath().toString();
const QString displayName = node->m_node->displayName();
ExpandData ed(path, displayName);
if (m_toExpand.contains(ed))
emit requestExpansion(node->index());
} else {
emit requestExpansion(node->index());
}
});
}
@@ -227,7 +238,7 @@ ExpandData FlatModel::expandDataForNode(const Node *node) const
void FlatModel::handleProjectAdded(Project *project)
{
Node *node = SessionManager::nodeForProject(project);
Node *node = project->rootProjectNode();
m_toExpand.insert(expandDataForNode(node));
if (WrapperNode *wrapper = wrapperForNode(node)) {
wrapper->forFirstLevelChildren([this](WrapperNode *child) {
@@ -251,21 +262,6 @@ void FlatModel::saveExpandData()
SessionManager::setValue(QLatin1String("ProjectTree.ExpandData"), data);
}
void FlatModel::addProjectNode(WrapperNode *parent, ProjectNode *projectNode, QSet<Node *> *seen)
{
seen->insert(projectNode);
auto node = new WrapperNode(projectNode);
parent->appendChild(node);
addFolderNode(node, projectNode, seen);
for (Node *subNode : projectNode->nodes()) {
if (ProjectNode *subProjectNode = subNode->asProjectNode()) {
if (!seen->contains(subProjectNode))
addProjectNode(node, subProjectNode, seen);
}
}
node->sortChildren(&sortWrapperNodes);
}
void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen)
{
const QList<FolderNode *> subFolderNodes = folderNode->folderNodes();
@@ -374,16 +370,6 @@ const QLoggingCategory &FlatModel::logger()
return logger;
}
bool isSorted(const QList<Node *> &nodes)
{
int size = nodes.size();
for (int i = 0; i < size -1; ++i) {
if (!sortNodes(nodes.at(i), nodes.at(i+1)))
return false;
}
return true;
}
namespace Internal {
int caseFriendlyCompare(const QString &a, const QString &b)

View File

@@ -94,7 +94,6 @@ private:
void update();
void rebuildModel();
void addProjectNode(WrapperNode *parent, ProjectNode *projectNode, QSet<Node *> *seen);
void addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet<Node *> *seen);
ExpandData expandDataForNode(const Node *node) const;

View File

@@ -214,9 +214,12 @@ bool Node::isEnabled() const
QList<ProjectAction> Node::supportedActions(Node *node) const
{
QList<ProjectAction> list = parentFolderNode()->supportedActions(node);
list.append(InheritedFromParent);
return list;
if (FolderNode *folder = parentFolderNode()) {
QList<ProjectAction> list = folder->supportedActions(node);
list.append(InheritedFromParent);
return list;
}
return {};
}
void Node::setEnabled(bool enabled)
@@ -702,18 +705,6 @@ ProjectNode::ProjectNode(const Utils::FileName &projectFilePath) :
setDisplayName(projectFilePath.fileName());
}
QString ProjectNode::vcsTopic() const
{
const QFileInfo fi = filePath().toFileInfo();
const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath();
if (Core::IVersionControl *const vc =
Core::VcsManager::findVersionControlForDirectory(dir))
return vc->vcsTopic(dir);
return QString();
}
bool ProjectNode::canAddSubProject(const QString &proFilePath) const
{
Q_UNUSED(proFilePath)
@@ -797,28 +788,4 @@ bool FolderNode::isEmpty() const
return m_nodes.isEmpty();
}
/*!
\class ProjectExplorer::SessionNode
*/
SessionNode::SessionNode() :
FolderNode(Utils::FileName::fromString("session"), NodeType::Session)
{ }
QList<ProjectAction> SessionNode::supportedActions(Node *node) const
{
Q_UNUSED(node)
return QList<ProjectAction>();
}
bool SessionNode::showInSimpleTree() const
{
return true;
}
QString SessionNode::addFileFilter() const
{
return QString::fromLatin1("*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;");
}
} // namespace ProjectExplorer

View File

@@ -40,14 +40,12 @@ namespace Utils { class MimeType; }
namespace ProjectExplorer {
class RunConfiguration;
class SessionManager;
enum class NodeType : quint16 {
File = 1,
Folder,
VirtualFolder,
Project,
Session
Project
};
// File types common for qt projects
@@ -275,8 +273,6 @@ private:
class PROJECTEXPLORER_EXPORT ProjectNode : public FolderNode
{
public:
QString vcsTopic() const;
virtual bool canAddSubProject(const QString &proFilePath) const;
virtual bool addSubProject(const QString &proFile);
virtual bool removeSubProject(const QString &proFilePath);
@@ -298,24 +294,7 @@ public:
const ProjectNode *asProjectNode() const final { return this; }
protected:
// this is just the in-memory representation, a subclass
// will add the persistent stuff
explicit ProjectNode(const Utils::FileName &projectFilePath);
friend class SessionManager;
};
// Documentation inside.
class PROJECTEXPLORER_EXPORT SessionNode : public FolderNode
{
public:
SessionNode();
private:
QList<ProjectAction> supportedActions(Node *node) const final;
QString addFileFilter() const final;
bool showInSimpleTree() const final;
};
} // namespace ProjectExplorer

View File

@@ -261,9 +261,6 @@ void ProjectTree::updateContext()
void ProjectTree::emitSubtreeChanged(FolderNode *node)
{
if (!SessionManager::sessionNode()->isAncesterOf(node))
return;
emit s_instance->subtreeChanged(node);
}
@@ -318,16 +315,15 @@ bool ProjectTree::hasFocus(ProjectTreeWidget *widget)
void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &globalPos, Node *node)
{
QMenu *contextMenu = nullptr;
Project *project = SessionManager::projectForNode(node);
emit s_instance->aboutToShowContextMenu(project, node);
if (!node)
node = SessionManager::sessionNode();
if (node->nodeType() != NodeType::Session) {
Project *project = SessionManager::projectForNode(node);
emit s_instance->aboutToShowContextMenu(project, node);
if (!node) {
contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu();
} else {
switch (node->nodeType()) {
case NodeType::Project:
if (node->parentFolderNode() == SessionManager::sessionNode())
if (node->parentFolderNode())
contextMenu = Core::ActionManager::actionContainer(Constants::M_PROJECTCONTEXT)->menu();
else
contextMenu = Core::ActionManager::actionContainer(Constants::M_SUBPROJECTCONTEXT)->menu();
@@ -342,10 +338,6 @@ void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &global
default:
qWarning("ProjectExplorerPlugin::showContextMenu - Missing handler for node type");
}
} else { // session item
emit s_instance->aboutToShowContextMenu(nullptr, node);
contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu();
}
if (contextMenu && contextMenu->actions().count() > 0) {

View File

@@ -70,6 +70,9 @@ public:
void collapseAll();
// for nodes to emit signals, do not call unless you are a node
static void emitSubtreeChanged(FolderNode *node);
signals:
void currentProjectChanged(ProjectExplorer::Project *project);
void currentNodeChanged();
@@ -80,9 +83,6 @@ signals:
void aboutToShowContextMenu(ProjectExplorer::Project *project,
ProjectExplorer::Node *node);
public: // for nodes to emit signals, do not call unless you are a node
static void emitSubtreeChanged(FolderNode *node);
private:
void sessionChanged();
void focusChanged();

View File

@@ -275,23 +275,27 @@ Node *ProjectTreeWidget::nodeForFile(const Utils::FileName &fileName)
Node *bestNode = nullptr;
int bestNodeExpandCount = INT_MAX;
SessionManager::sessionNode()->forEachGenericNode([&](Node *node) {
if (node->filePath() == fileName) {
if (!bestNode) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} else if (node->nodeType() < bestNode->nodeType()) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} else if (node->nodeType() == bestNode->nodeType()) {
int nodeExpandCount = ProjectTreeWidget::expandedCount(node);
if (nodeExpandCount < bestNodeExpandCount) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
for (Project *project : SessionManager::projects()) {
if (ProjectNode *projectNode = project->rootProjectNode()) {
projectNode->forEachGenericNode([&](Node *node) {
if (node->filePath() == fileName) {
if (!bestNode) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} else if (node->nodeType() < bestNode->nodeType()) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
} else if (node->nodeType() == bestNode->nodeType()) {
int nodeExpandCount = ProjectTreeWidget::expandedCount(node);
if (nodeExpandCount < bestNodeExpandCount) {
bestNode = node;
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
}
}
}
}
});
}
});
}
return bestNode;
}

View File

@@ -55,6 +55,8 @@
using namespace Core;
using namespace Utils;
const int LINK_HEIGHT = 35;
namespace ProjectExplorer {
namespace Internal {
@@ -154,13 +156,18 @@ class BaseDelegate : public QAbstractItemDelegate
{
protected:
virtual QString entryType() = 0;
virtual QRect toolTipArea(const QRect &itemRect, const QModelIndex &) const
{
return itemRect;
}
bool helpEvent(QHelpEvent *ev, QAbstractItemView *view,
const QStyleOptionViewItem &option, const QModelIndex &idx) final
{
const int y = ev->pos().y();
if (y > option.rect.bottom() - 20)
if (!toolTipArea(option.rect, idx).contains(ev->pos())) {
QToolTip::hideText();
return false;
}
QString shortcut;
if (idx.row() < m_shortcuts.size())
@@ -188,6 +195,13 @@ class SessionDelegate : public BaseDelegate
{
protected:
QString entryType() override { return tr("session", "Appears in \"Open session <name>\""); }
QRect toolTipArea(const QRect &itemRect, const QModelIndex &idx) const override
{
// in expanded state bottom contains 'Clone', 'Rename', etc links, where the tool tip
// would be confusing
const bool expanded = m_expandedSessions.contains(idx.data(Qt::DisplayRole).toString());
return expanded ? itemRect.adjusted(0, 0, 0, -LINK_HEIGHT) : itemRect;
}
public:
SessionDelegate() {
@@ -312,7 +326,7 @@ public:
QString sessionName = idx.data(Qt::DisplayRole).toString();
if (m_expandedSessions.contains(sessionName)) {
QStringList projects = SessionManager::projectsForSessionName(sessionName);
h += projects.size() * 40 + 35;
h += projects.size() * 40 + LINK_HEIGHT;
}
return QSize(380, h);
}
@@ -408,7 +422,7 @@ public:
painter->drawPixmap(x + 11, y + 3, pixmap("project", Theme::Welcome_ForegroundSecondaryColor));
QString projectName = idx.data(Qt::DisplayRole).toString();
QString projectPath = idx.data(Qt::UserRole + 1).toString();
QString projectPath = idx.data(ProjectModel::FilePathRole).toString();
painter->setPen(themeColor(Theme::Welcome_ForegroundSecondaryColor));
painter->setFont(sizedFont(10, option.widget));
@@ -429,7 +443,7 @@ public:
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &idx) const final
{
QString projectName = idx.data(Qt::DisplayRole).toString();
QString projectPath = idx.data(Qt::UserRole + 1).toString();
QString projectPath = idx.data(ProjectModel::FilePathRole).toString();
QFontMetrics fm(sizedFont(13, option.widget));
int width = std::max(fm.width(projectName), fm.width(projectPath)) + 36;
return QSize(width, 48);
@@ -439,7 +453,7 @@ public:
const QStyleOptionViewItem &, const QModelIndex &idx) final
{
if (ev->type() == QEvent::MouseButtonRelease) {
QString projectFile = idx.data(Qt::UserRole + 1).toString();
QString projectFile = idx.data(ProjectModel::FilePathRole).toString();
ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
return true;
}

View File

@@ -26,6 +26,7 @@
#include "projectwizardpage.h"
#include "ui_projectwizardpage.h"
#include "project.h"
#include "projectexplorer.h"
#include "session.h"
@@ -300,18 +301,14 @@ ProjectWizardPage::~ProjectWizardPage()
{
disconnect(m_ui->projectComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &ProjectWizardPage::projectChanged);
delete m_model;
delete m_ui;
}
void ProjectWizardPage::setModel(Utils::TreeModel<> *model)
{
delete m_model;
m_model = model;
// TODO see OverViewCombo and OverView for click event filter
m_ui->projectComboBox->setModel(model);
bool enabled = m_model->rowCount(QModelIndex()) > 1;
bool enabled = m_model.rowCount(QModelIndex()) > 1;
m_ui->projectComboBox->setEnabled(enabled);
expandTree(QModelIndex());
@@ -324,9 +321,9 @@ bool ProjectWizardPage::expandTree(const QModelIndex &root)
expand = true;
// Check children
int count = m_model->rowCount(root);
int count = m_model.rowCount(root);
for (int i = 0; i < count; ++i) {
if (expandTree(m_model->index(i, 0, root)))
if (expandTree(m_model.index(i, 0, root)))
expand = true;
}
@@ -346,7 +343,7 @@ bool ProjectWizardPage::expandTree(const QModelIndex &root)
void ProjectWizardPage::setBestNode(AddNewTree *tree)
{
QModelIndex index = tree ? m_model->indexForItem(tree) : QModelIndex();
QModelIndex index = tree ? m_model.indexForItem(tree) : QModelIndex();
m_ui->projectComboBox->setCurrentIndex(index);
while (index.isValid()) {
@@ -454,28 +451,22 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const QStringList &
{
BestNodeSelector selector(m_commonDirectory, paths);
AddNewTree *tree;
SessionNode *root = SessionManager::sessionNode();
QList<AddNewTree *> children;
for (Node *node : root->nodes()) {
if (ProjectNode *pn = node->asProjectNode()) {
TreeItem *root = m_model.rootItem();
root->removeChildren();
for (Project *project : SessionManager::projects()) {
if (ProjectNode *pn = project->rootProjectNode()) {
if (kind == IWizardFactory::ProjectWizard) {
if (AddNewTree *child = buildAddProjectTree(pn, paths.first(), context, &selector))
children.append(child);
root->appendChild(child);
} else {
if (AddNewTree *child = buildAddFilesTree(pn, paths, context, &selector))
children.append(child);
root->appendChild(child);
}
}
}
children.prepend(createNoneNode(&selector));
tree = new AddNewTree(root, children, root->displayName());
root->prependChild(createNoneNode(&selector));
setAdditionalInfo(selector.deployingProjects());
setModel(new TreeModel<>(tree));
setBestNode(selector.bestChoice());
setAddingSubProject(action == AddSubProject);
}

View File

@@ -95,7 +95,7 @@ private:
Ui::WizardPage *m_ui;
QStringList m_projectToolTips;
Utils::TreeModel<> *m_model = nullptr;
Utils::TreeModel<> m_model;
QList<Core::IVersionControl*> m_activeVersionControls;
QString m_commonDirectory;

View File

@@ -92,13 +92,7 @@ public:
static QString sessionTitle(const QString &filePath);
bool hasProjects() const { return !m_projects.isEmpty(); }
bool hasProject(Project *p) const
{
return Utils::contains(m_projects,
[p](const QPair<Project *, ProjectNode *> &pair) { return pair.first == p; });
}
SessionNode m_sessionNode;
QString m_sessionName = QLatin1String("default");
bool m_virginSession = true;
bool m_loadingSession = false;
@@ -110,7 +104,7 @@ public:
mutable QHash<Project *, QStringList> m_projectFileCache;
Project *m_startupProject = nullptr;
QList<QPair<Project *,ProjectNode*>> m_projects;
QList<Project *> m_projects;
QStringList m_failedProjects;
QMap<QString, QStringList> m_depMap;
QMap<QString, QVariant> m_values;
@@ -188,36 +182,6 @@ void SessionManager::clearProjectFileCache()
d->m_projectFileCache.clear();
}
void SessionManager::updateProjectTree(Project *pro)
{
if (!pro)
return;
QPair<Project *, ProjectNode *> *currentPair = nullptr;
for (QPair<Project *, ProjectNode *> &pair : d->m_projects) {
if (pair.first == pro) {
currentPair = &pair;
break;
}
}
if (!currentPair)
return; // Project was already de-registered and is shutting down
ProjectNode *const oldNode = currentPair->second;
ProjectNode *newNode = pro->rootProjectNode();
if (!newNode) {
// Set up generic project structure if the project does not provide any!
newNode = new ProjectNode(pro->projectDirectory());
newNode->setDisplayName(pro->displayName());
newNode->addNode(new FileNode(pro->projectFilePath(), FileType::Project, false));
}
d->m_sessionNode.replaceSubtree(oldNode, newNode);
currentPair->second = newNode;
}
bool SessionManagerPrivate::recursiveDependencyCheck(const QString &newDep, const QString &checkDep) const
{
if (newDep == checkDep)
@@ -393,8 +357,8 @@ void SessionManager::setActiveDeployConfiguration(Target *target, DeployConfigur
void SessionManager::setStartupProject(Project *startupProject)
{
QTC_ASSERT((!startupProject)
|| (startupProject && hasProject(startupProject)), return);
QTC_ASSERT(!startupProject
|| (startupProject && d->m_projects.contains(startupProject)), return);
if (d->m_startupProject == startupProject)
return;
@@ -413,13 +377,11 @@ void SessionManager::addProject(Project *pro)
QTC_ASSERT(pro, return);
d->m_virginSession = false;
QTC_ASSERT(!hasProject(pro), return);
QTC_ASSERT(!d->m_projects.contains(pro), return);
d->m_projects.append(qMakePair(pro, nullptr));
m_instance->updateProjectTree(pro);
d->m_projects.append(pro);
connect(pro, &Project::fileListChanged, m_instance, &SessionManager::clearProjectFileCache);
connect(pro, &Project::projectTreeChanged, m_instance, &SessionManager::updateProjectTree);
emit m_instance->projectAdded(pro);
configureEditors(pro);
@@ -522,8 +484,7 @@ void SessionManager::closeAllProjects()
const QList<Project *> SessionManager::projects()
{
return Utils::transform(d->m_projects,
[](const QPair<Project *, ProjectNode *> &pair) { return pair.first; });
return d->m_projects;
}
bool SessionManager::hasProjects()
@@ -533,7 +494,7 @@ bool SessionManager::hasProjects()
bool SessionManager::hasProject(Project *p)
{
return d->hasProject(p);
return d->m_projects.contains(p);
}
QStringList SessionManagerPrivate::dependencies(const QString &proName) const
@@ -604,8 +565,8 @@ QStringList SessionManagerPrivate::dependenciesOrder() const
QStringList ordered;
// copy the map to a temporary list
for (const QPair<Project *, ProjectNode *> &pro : m_projects) {
const QString proName = pro.first->projectFilePath().toString();
for (const Project *pro : m_projects) {
const QString proName = pro->projectFilePath().toString();
unordered << QPair<QString, QStringList>(proName, m_depMap.value(proName));
}
@@ -658,13 +619,17 @@ QList<Project *> SessionManager::projectOrder(const Project *project)
Node *SessionManager::nodeForFile(const Utils::FileName &fileName)
{
Node *node = nullptr;
sessionNode()->forEachGenericNode([&](Node *n) {
if (n->filePath() == fileName) {
// prefer file nodes
if (!node || (node->nodeType() != NodeType::File && n->nodeType() == NodeType::File))
node = n;
for (Project *project : d->m_projects) {
if (ProjectNode *projectNode = project->rootProjectNode()) {
projectNode->forEachGenericNode([&](Node *n) {
if (n->filePath() == fileName) {
// prefer file nodes
if (!node || (node->nodeType() != NodeType::File && n->nodeType() == NodeType::File))
node = n;
}
});
}
});
}
return node;
}
@@ -673,25 +638,16 @@ Project *SessionManager::projectForNode(Node *node)
if (!node)
return nullptr;
FolderNode *rootProjectNode = node->asFolderNode();
if (!rootProjectNode)
rootProjectNode = node->parentFolderNode();
FolderNode *folder = node->asFolderNode();
if (!folder)
folder = node->parentFolderNode();
while (rootProjectNode && rootProjectNode->parentFolderNode() != &d->m_sessionNode)
rootProjectNode = rootProjectNode->parentFolderNode();
while (folder && folder->parentFolderNode())
folder = folder->parentFolderNode();
for (const QPair<Project *, ProjectNode *> &pair : d->m_projects) {
if (pair.second == rootProjectNode)
return pair.first;
}
return nullptr;
}
Node *SessionManager::nodeForProject(Project *project)
{
for (const QPair<Project *,ProjectNode*> &pair : d->m_projects) {
if (pair.first == project)
return pair.second;
for (Project *pro : d->m_projects) {
if (pro->containerNode() == folder)
return pro;
}
return nullptr;
}
@@ -771,17 +727,9 @@ void SessionManager::removeProjects(QList<Project *> remove)
// Delete projects
foreach (Project *pro, remove) {
pro->saveSettings();
pro->setRootProjectNode(nullptr); // Deregister project with sessionnode!
// Remove the project node:
Node *projectNode = nodeForProject(pro);
d->m_sessionNode.removeNode(projectNode);
d->m_projects
= Utils::filtered(d->m_projects, [pro](const QPair<Project *, ProjectNode *> &pair)
{
return pair.first != pro;
});
d->m_projects.removeOne(pro);
if (pro == d->m_startupProject)
setStartupProject(nullptr);
@@ -965,9 +913,9 @@ void SessionManagerPrivate::restoreStartupProject(const PersistentSettingsReader
{
const QString startupProject = reader.restoreValue(QLatin1String("StartupProject")).toString();
if (!startupProject.isEmpty()) {
for (const QPair<Project *, ProjectNode *> &pro : m_projects) {
if (pro.first->projectFilePath().toString() == startupProject) {
m_instance->setStartupProject(pro.first);
for (Project *pro : m_projects) {
if (pro->projectFilePath().toString() == startupProject) {
m_instance->setStartupProject(pro);
break;
}
}
@@ -976,7 +924,7 @@ void SessionManagerPrivate::restoreStartupProject(const PersistentSettingsReader
if (!startupProject.isEmpty())
qWarning() << "Could not find startup project" << startupProject;
if (hasProjects())
m_instance->setStartupProject(m_projects.first().first);
m_instance->setStartupProject(m_projects.first());
}
}
@@ -1140,11 +1088,6 @@ QString SessionManager::lastSession()
return ICore::settings()->value(QLatin1String("ProjectExplorer/StartupSession")).toString();
}
SessionNode *SessionManager::sessionNode()
{
return &d->m_sessionNode;
}
void SessionManager::reportProjectLoadingProgress()
{
d->sessionLoadingProgress();

View File

@@ -44,7 +44,6 @@ class Target;
class BuildConfiguration;
class DeployConfiguration;
class Node;
class SessionNode;
enum class SetActive { Cascade, NoCascade };
@@ -113,10 +112,7 @@ public:
// NBS rewrite projectOrder (dependency management)
static QList<Project *> projectOrder(const Project *project = 0);
static SessionNode *sessionNode();
static Project *projectForNode(Node *node);
static Node *nodeForProject(Project *project);
static Node *nodeForFile(const Utils::FileName &fileName);
static Project *projectForFile(const Utils::FileName &fileName);
@@ -126,8 +122,7 @@ public:
static bool loadingSession();
signals:
void projectAdded(ProjectExplorer::Project *project);
void aboutToRemoveProject(ProjectExplorer::Project *project);
void projectAdded(ProjectExplorer::Project *project); void aboutToRemoveProject(ProjectExplorer::Project *project);
void projectDisplayNameChanged(ProjectExplorer::Project *project);
void projectRemoved(ProjectExplorer::Project *project);
@@ -145,7 +140,6 @@ signals: // for tests only
private:
static void saveActiveMode(Core::Id mode);
void clearProjectFileCache();
void updateProjectTree(Project *pro);
static void configureEditor(Core::IEditor *editor, const QString &fileName);
static void markSessionFileDirty(bool makeDefaultVirginDirty = true);
static void configureEditors(Project *project);

View File

@@ -42,6 +42,7 @@
#include <QtDebug>
#include <QDir>
#include <QIcon>
#include <QStyle>
// ----------------------------------------------------------------------
@@ -64,10 +65,6 @@ static QIcon generateIcon(const QString &overlay)
namespace QbsProjectManager {
namespace Internal {
QIcon QbsGroupNode::m_groupIcon;
QIcon QbsProjectNode::m_projectIcon;
QIcon QbsProductNode::m_productIcon;
static QbsProjectNode *parentQbsProjectNode(ProjectExplorer::Node *node)
{
for (ProjectExplorer::FolderNode *pn = node->managingProject(); pn; pn = pn->parentProjectNode()) {
@@ -263,9 +260,8 @@ QString QbsFileNode::displayName() const
QbsFolderNode::QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer::NodeType nodeType,
const QString &displayName, bool isGeneratedFilesFolder)
: ProjectExplorer::FolderNode(folderPath, nodeType, displayName),
m_isGeneratedFilesFolder(isGeneratedFilesFolder)
const QString &displayName)
: ProjectExplorer::FolderNode(folderPath, nodeType, displayName)
{
}
@@ -300,10 +296,8 @@ QList<ProjectExplorer::ProjectAction> QbsBaseProjectNode::supportedActions(Proje
QbsGroupNode::QbsGroupNode(const qbs::GroupData &grp, const QString &productPath) :
QbsBaseProjectNode(Utils::FileName())
{
if (m_groupIcon.isNull())
m_groupIcon = QIcon(QString::fromLatin1(Constants::QBS_GROUP_ICON));
setIcon(m_groupIcon);
static QIcon groupIcon = QIcon(QString(Constants::QBS_GROUP_ICON));
setIcon(groupIcon);
m_productPath = productPath;
m_qbsGroupData = grp;
@@ -379,10 +373,8 @@ QbsProductNode::QbsProductNode(const qbs::ProductData &prd) :
QbsBaseProjectNode(Utils::FileName::fromString(prd.location().filePath())),
m_qbsProductData(prd)
{
if (m_productIcon.isNull())
m_productIcon = generateIcon(QString::fromLatin1(Constants::QBS_PRODUCT_OVERLAY_ICON));
setIcon(m_productIcon);
static QIcon productIcon = generateIcon(QString(Constants::QBS_PRODUCT_OVERLAY_ICON));
setIcon(productIcon);
}
bool QbsProductNode::showInSimpleTree() const
@@ -464,16 +456,6 @@ QList<ProjectExplorer::RunConfiguration *> QbsProductNode::runConfigurations() c
return result;
}
QbsGroupNode *QbsProductNode::findGroupNode(const QString &name)
{
for (ProjectExplorer::Node *n : nodes()) {
if (QbsGroupNode *qn = dynamic_cast<QbsGroupNode *>(n))
if (qn->qbsGroupData().name() == name)
return qn;
}
return 0;
}
// --------------------------------------------------------------------
// QbsProjectNode:
// --------------------------------------------------------------------
@@ -481,15 +463,8 @@ QbsGroupNode *QbsProductNode::findGroupNode(const QString &name)
QbsProjectNode::QbsProjectNode(const Utils::FileName &projectDirectory) :
QbsBaseProjectNode(projectDirectory)
{
if (m_projectIcon.isNull())
m_projectIcon = generateIcon(QString::fromLatin1(ProjectExplorer::Constants::FILEOVERLAY_QT));
setIcon(m_projectIcon);
}
QbsProjectNode::~QbsProjectNode()
{
// do not delete m_project
static QIcon projectIcon = generateIcon(QString(ProjectExplorer::Constants::FILEOVERLAY_QT));
setIcon(projectIcon);
}
QbsProject *QbsProjectNode::project() const

View File

@@ -29,15 +29,11 @@
#include <qbs.h>
#include <QIcon>
namespace QbsProjectManager {
namespace Internal {
class FileTreeNode;
class QbsNodeTreeBuilder;
class QbsProject;
class QbsProjectFile;
// ----------------------------------------------------------------------
// QbsFileNode:
@@ -56,14 +52,10 @@ class QbsFolderNode : public ProjectExplorer::FolderNode
{
public:
QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer::NodeType nodeType,
const QString &displayName, bool isGeneratedFilesFolder);
bool isGeneratedFilesFolder() const { return m_isGeneratedFilesFolder; }
const QString &displayName);
private:
QList<ProjectExplorer::ProjectAction> supportedActions(ProjectExplorer::Node *node) const override;
const bool m_isGeneratedFilesFolder;
};
// ---------------------------------------------------------------------------
@@ -100,13 +92,9 @@ public:
qbs::GroupData qbsGroupData() const { return m_qbsGroupData; }
QString productPath() const;
private:
qbs::GroupData m_qbsGroupData;
QString m_productPath;
static QIcon m_groupIcon;
};
// --------------------------------------------------------------------
@@ -129,10 +117,7 @@ public:
QList<ProjectExplorer::RunConfiguration *> runConfigurations() const override;
private:
QbsGroupNode *findGroupNode(const QString &name);
const qbs::ProductData m_qbsProductData;
static QIcon m_productIcon;
};
// ---------------------------------------------------------------------------
@@ -143,18 +128,15 @@ class QbsProjectNode : public QbsBaseProjectNode
{
public:
explicit QbsProjectNode(const Utils::FileName &projectDirectory);
~QbsProjectNode() override;
virtual QbsProject *project() const;
const qbs::Project qbsProject() const;
const qbs::ProjectData qbsProjectData() const { return m_projectData; }
bool showInSimpleTree() const override;
void setProjectData(const qbs::ProjectData &data);
void setProjectData(const qbs::ProjectData &data); // FIXME: Needed?
private:
static QIcon m_projectIcon;
qbs::ProjectData m_projectData;
friend class QbsNodeTreeBuilder;

View File

@@ -148,6 +148,8 @@ void setupProjectNode(QbsProjectManager::Internal::QbsProjectNode *node, const q
node->setDisplayName(prjData.name());
else
node->setDisplayName(node->project()->displayName());
node->setProjectData(prjData);
}
QSet<QString> referencedBuildSystemFiles(const qbs::ProjectData &data)

View File

@@ -325,8 +325,9 @@ void resetSize(const SelectionContext &selectionState)
try {
RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetSize"));
foreach (ModelNode node, selectionState.selectedModelNodes()) {
node.removeProperty("width");
node.removeProperty("height");
QmlItemNode itemNode(node);
itemNode.removeProperty("width");
itemNode.removeProperty("height");
}
} catch (const RewritingException &e) { //better save then sorry
e.showException();
@@ -341,8 +342,9 @@ void resetPosition(const SelectionContext &selectionState)
try {
RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetPosition"));
foreach (ModelNode node, selectionState.selectedModelNodes()) {
node.removeProperty("x");
node.removeProperty("y");
QmlItemNode itemNode(node);
itemNode.removeProperty("x");
itemNode.removeProperty("y");
}
transaction.commit();
} catch (const RewritingException &e) { //better save then sorry
@@ -366,7 +368,8 @@ void resetZ(const SelectionContext &selectionState)
RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetZ"));
foreach (ModelNode node, selectionState.selectedModelNodes()) {
node.removeProperty("z");
QmlItemNode itemNode(node);
itemNode.removeProperty("z");
}
}

View File

@@ -301,15 +301,12 @@ void FormEditorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
m_scene->update();
}
void FormEditorView::documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings)
void FormEditorView::documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &)
{
if (!errors.isEmpty())
formEditorWidget()->showErrorMessageBox(errors);
else
formEditorWidget()->hideErrorMessageBox();
if (!warnings.isEmpty())
formEditorWidget()->showWarningMessageBox(warnings);
}
void FormEditorView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList<ModelNode> &/*nodeList*/, const QList<QVariant> &/*data*/)

View File

@@ -286,8 +286,6 @@ void FormEditorWidget::showWarningMessageBox(const QList<DocumentMessage> &warni
errorWidget()->setWarnings(warnings);
errorWidget()->setVisible(true);
m_graphicsView->setDisabled(true);
m_toolBox->setDisabled(true);
}
ZoomAction *FormEditorWidget::zoomAction() const

View File

@@ -82,10 +82,10 @@ public:
void setResourcePath(const QString &resourcePath);
void startDragAndDrop(QVariant itemLibId);
void setModel(Model *model);
Q_INVOKABLE void startDragAndDrop(QVariant itemLibId);
protected:
void removeImport(const QString &name);
void addImport(const QString &name, const QString &version);

View File

@@ -66,6 +66,25 @@ static Q_LOGGING_CATEGORY(puppetBuild, "qtc.puppet.build")
namespace QmlDesigner {
class EventFilter : public QObject {
public:
EventFilter()
{}
bool eventFilter(QObject *o, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress
|| event->type() == QEvent::MouseButtonRelease
|| event->type() == QEvent::KeyPress
|| event->type() == QEvent::KeyRelease) {
return true;
}
return QObject::eventFilter(o, event);
}
};
QHash<Core::Id, PuppetCreator::PuppetType> PuppetCreator::m_qml2PuppetForKitPuppetHash;
QByteArray PuppetCreator::qtHash() const
@@ -241,6 +260,7 @@ static QString idealProcessCount()
bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const
{
PuppetBuildProgressDialog progressDialog;
progressDialog.setParent(Core::ICore::mainWindow());
m_compileLog.clear();
@@ -248,6 +268,16 @@ bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const
bool buildSucceeded = false;
/* Ensure the model dialog is shown and no events are delivered to the rest of Qt Creator. */
EventFilter eventFilter;
QCoreApplication::instance()->installEventFilter(&eventFilter);
progressDialog.show();
QCoreApplication::processEvents();
QCoreApplication::instance()->removeEventFilter(&eventFilter);
/* Now the modal dialog will block input to the rest of Qt Creator.
We can call process events without risking a mode change. */
if (qtIsSupported()) {
if (buildDirectory.isValid()) {
QStringList qmakeArguments;

View File

@@ -188,7 +188,6 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
bool QmlDesignerPlugin::delayedInitialize()
{
integrateIntoQtCreator(d->mainWidget);
// adding default path to item library plugins
const QString pluginPath = Utils::HostOsInfo::isMacHost()
? QString(QCoreApplication::applicationDirPath() + "/../PlugIns/QmlDesigner")
@@ -210,6 +209,7 @@ bool QmlDesignerPlugin::delayedInitialize()
void QmlDesignerPlugin::extensionsInitialized()
{
integrateIntoQtCreator(d->mainWidget);
}
static QStringList allUiQmlFilesforCurrentProject(const Utils::FileName &fileName)

View File

@@ -84,6 +84,7 @@ QVariantMap InputEventsModel::details(int index) const
switch (event.type) {
case InputKeyPress:
type = tr("Key Press");
// fallthrough
case InputKeyRelease:
if (type.isEmpty())
type = tr("Key Release");
@@ -97,9 +98,11 @@ QVariantMap InputEventsModel::details(int index) const
break;
case InputMouseDoubleClick:
type = tr("Double Click");
// fallthrough
case InputMousePress:
if (type.isEmpty())
type = tr("Mouse Press");
// fallthrough
case InputMouseRelease:
if (type.isEmpty())
type = tr("Mouse Release");

View File

@@ -208,9 +208,10 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type
PixmapState &state = pixmap.sizes[newEvent.sizeIndex];
if (state.cacheState == ToBeCached) {
m_lastCacheSizeEvent = updateCacheCount(m_lastCacheSizeEvent, pixmapStartTime,
state.size.width() * state.size.height(), newEvent,
event.typeIndex());
m_lastCacheSizeEvent = updateCacheCount(
m_lastCacheSizeEvent, pixmapStartTime,
(qint64) state.size.width() * (qint64) state.size.height(),
newEvent, event.typeIndex());
state.cacheState = Cached;
}
break;
@@ -230,7 +231,7 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type
} else if (!uncache && i->cacheState == Uncached) {
newEvent.sizeIndex = i - pixmap.sizes.begin();
if (i->size.isValid()) {
pixSize = i->size.width() * i->size.height();
pixSize = (qint64) i->size.width() * i->size.height();
i->cacheState = Cached;
} else {
i->cacheState = ToBeCached;
@@ -247,7 +248,7 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type
if (uncache && (i->cacheState == Cached || i->cacheState == ToBeCached)) {
newEvent.sizeIndex = i - pixmap.sizes.begin();
if (i->size.isValid())
pixSize = -i->size.width() * i->size.height();
pixSize = (qint64) -i->size.width() * i->size.height();
i->cacheState = Uncached;
break;
} else if (!uncache && i->cacheState == Uncacheable) {

View File

@@ -638,7 +638,7 @@ void QmlProfilerStatisticsMainView::parseModel()
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
if (d->m_fieldShown[TimePerCall]) {
const qint64 timePerCall = stats.duration / stats.calls;
const qint64 timePerCall = stats.calls > 0 ? stats.duration / stats.calls : 0;
newRow << new StatisticsViewItem(Timeline::formatTime(timePerCall),
timePerCall);
}

View File

@@ -243,6 +243,7 @@ Kit *TestQtProjectImporter::createKit(void *directoryData) const
QList<BuildInfo *> TestQtProjectImporter::buildInfoListForKit(const Kit *k, void *directoryData) const
{
Q_UNUSED(directoryData);
assert(m_testData.contains(directoryData));
assert(!m_deletedTestData.contains(directoryData));
assert(static_cast<const DirectoryData *>(directoryData)->importPath == m_path);

View File

@@ -192,7 +192,7 @@ IEditor *FindInFilesSilverSearcher::openEditor(const SearchResultItem & /*item*/
return 0;
}
void FindInFilesSilverSearcher::readSettings(QSettings */*settings*/)
void FindInFilesSilverSearcher::readSettings(QSettings * /*settings*/)
{
}

View File

@@ -2724,7 +2724,8 @@ void tst_Dumpers::dumper_data()
+ Check("ob", "\"An Object\"", "@QWidget")
+ Check("ob1", "\"Another Object\"", "@QObject")
+ Check("ob2", "\"A Subobject\"", "@QObject")
+ Check("ob.[extra].[connections].0.0.receiver", "\"Another Object\"", "@QObject");
+ Check("ob.[extra].[connections].0.0.receiver", "\"Another Object\"",
"@QObject") % NoCdbEngine;
QString senderData =

View File

@@ -146,12 +146,22 @@ void tst_offsets::offsets_data()
const int qtVersion = QT_VERSION;
if (qtVersion >= 0x50600)
if (qtVersion >= 0x50700)
#ifdef Q_OS_WIN
# ifdef Q_CC_MSVC
OFFSET_TEST(QFilePrivate, fileName) << 184 << 248;
# else // MinGW
OFFSET_TEST(QFilePrivate, fileName) << 164 << 248;
OFFSET_TEST(QFilePrivate, fileName) << 172 << 248;
# endif
#else
OFFSET_TEST(QFilePrivate, fileName) << 168 << 248;
#endif
else if (qtVersion >= 0x50600)
#ifdef Q_OS_WIN
# ifdef Q_CC_MSVC
OFFSET_TEST(QFilePrivate, fileName) << 184 << 248;
# else // MinGW
OFFSET_TEST(QFilePrivate, fileName) << 180 << 248;
# endif
#else
OFFSET_TEST(QFilePrivate, fileName) << 168 << 248;

View File

@@ -128,8 +128,7 @@ def doSimpleDebugging(kitCount, currentKit, currentConfigName, pressContinueCoun
expectedLabelTexts = ['Stopped\.', 'Stopped at breakpoint \d+ \(\d+\) in thread \d+\.']
if len(expectedBPOrder) == 0:
expectedLabelTexts.append("Running\.")
if JIRA.isBugStillOpen(17492):
expectedLabelTexts.append("QML Debugger: Error: Unknown socket error 0")
expectedLabelTexts.append("QML Debugger: Error: Unknown socket error 0")
switchViewTo(ViewConstants.PROJECTS)
switchToBuildOrRunSettingsFor(kitCount, currentKit, ProjectSettings.RUN)
ensureChecked(waitForObject("{container=':Qt Creator.scrollArea_QScrollArea' text='Enable QML' "