forked from qt-creator/qt-creator
Merge "Merge remote-tracking branch 'origin/4.3'"
This commit is contained in:
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 |
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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"])
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -1,3 +0,0 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += %{JS: '%{TestCaseName}'.toLowerCase()}
|
@@ -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"
|
||||
]
|
||||
}
|
@@ -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
|
@@ -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}
|
@@ -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}"
|
||||
]
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += auto
|
@@ -1,8 +0,0 @@
|
||||
import qbs
|
||||
|
||||
Project {
|
||||
name: "%{ProjectName} tests"
|
||||
references: [
|
||||
"auto/auto.qbs"
|
||||
]
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
@if "%{BuildAutoTests}" == "always"
|
||||
SUBDIRS += src \
|
||||
tests
|
||||
@else
|
||||
SUBDIRS += src
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
SUBDIRS += tests
|
||||
}
|
||||
@endif
|
@@ -1,8 +0,0 @@
|
||||
import qbs
|
||||
|
||||
Project {
|
||||
references: [
|
||||
"src/src.qbs",
|
||||
"tests/tests.qbs"
|
||||
]
|
||||
}
|
@@ -14,7 +14,7 @@ TEMPLATE = app
|
||||
|
||||
SOURCES += %{TestCaseFileWithCppSuffix}
|
||||
@else
|
||||
include(../gtest_dependency.pri)
|
||||
include(gtest_dependency.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
@if "%{GTestCXX11}" == "true"
|
||||
|
@@ -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
|
||||
}
|
||||
|
57
share/qtcreator/templates/wizards/autotest/files/tst.txt
Normal file
57
share/qtcreator/templates/wizards/autotest/files/tst.txt
Normal 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
|
@@ -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
|
||||
},
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
bool QuickTestParser::handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
CPlusPlus::Document::Ptr document,
|
||||
const Core::Id &id)
|
||||
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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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());
|
||||
});
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -1696,11 +1696,17 @@ 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"))
|
||||
objectData.properties = dataMap.value("properties").toList();
|
||||
|
@@ -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();
|
||||
|
@@ -91,6 +91,7 @@ bool FindMacroHandler::executeEvent(const MacroEvent ¯oEvent)
|
||||
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(),
|
||||
|
@@ -198,8 +198,6 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node,
|
||||
menu->popup(QCursor::pos());
|
||||
break;
|
||||
}
|
||||
case ProjectExplorer::NodeType::Session:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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) {
|
||||
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)
|
||||
|
@@ -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;
|
||||
|
@@ -214,10 +214,13 @@ bool Node::isEnabled() const
|
||||
|
||||
QList<ProjectAction> Node::supportedActions(Node *node) const
|
||||
{
|
||||
QList<ProjectAction> list = parentFolderNode()->supportedActions(node);
|
||||
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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
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) {
|
||||
|
@@ -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();
|
||||
|
@@ -275,7 +275,9 @@ Node *ProjectTreeWidget::nodeForFile(const Utils::FileName &fileName)
|
||||
Node *bestNode = nullptr;
|
||||
int bestNodeExpandCount = INT_MAX;
|
||||
|
||||
SessionManager::sessionNode()->forEachGenericNode([&](Node *node) {
|
||||
for (Project *project : SessionManager::projects()) {
|
||||
if (ProjectNode *projectNode = project->rootProjectNode()) {
|
||||
projectNode->forEachGenericNode([&](Node *node) {
|
||||
if (node->filePath() == fileName) {
|
||||
if (!bestNode) {
|
||||
bestNode = node;
|
||||
@@ -292,6 +294,8 @@ Node *ProjectTreeWidget::nodeForFile(const Utils::FileName &fileName)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return bestNode;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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) {
|
||||
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();
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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*/)
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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");
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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 =
|
||||
|
@@ -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;
|
||||
|
@@ -128,7 +128,6 @@ 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")
|
||||
switchViewTo(ViewConstants.PROJECTS)
|
||||
switchToBuildOrRunSettingsFor(kitCount, currentKit, ProjectSettings.RUN)
|
||||
|
Reference in New Issue
Block a user