Merge remote-tracking branch 'origin/4.0'

Change-Id: I80bc3371c6d7cf9f2d46cbcf8e79e4761213d8aa
This commit is contained in:
Eike Ziller
2016-05-27 12:01:36 +02:00
70 changed files with 1243 additions and 339 deletions

53
dist/changes-4.0.1.md vendored Normal file
View File

@@ -0,0 +1,53 @@
Qt Creator version 4.0.1 contains bug fixes.
The most important changes are listed in this document. For a complete
list of changes, see the Git log for the Qt Creator sources that
you can check out from the public Git repository. For example:
git clone git://code.qt.io/qt-creator/qt-creator.git
git log --cherry-pick --pretty=oneline v4.0.0..v4.0.1
CMake Projects
* Added notification when `CMakeCache.txt` changes and introduces a
conflict with the build configuration settings, with the option
to adapt the build configuration settings
* Fixed that build configurations could not override kit settings, and added
a warning to build configurations that override kit settings
* Fixed that `yes` was not considered as boolean `true` value
* Fixed race between persisting and parsing CMake configuration
(QTCREATORBUG-16258)
QML Support
* Added wizard for Qt Quick Controls 2
* Fixed that `pragma` directives were removed when reformatting
Debugging
* Fixed QObject property expansion (QTCREATORBUG-15798)
* Fixed updating evaluated expressions
* Fixed crash on spontaneous debugger exit (QTCREATORBUG-16233)
Valgrind
* Fixed crash when changing filter
Clang Static Analyzer
* Fixed executing Clang with absolute path on Windows (QTCREATORBUG-16234)
Test Integration
* Fixed running tests on Windows with Qbs (QTCREATORBUG-16323)
Beautifier
* Fixed regression with `clang-format` and predefined style set to `File`
(QTCREATORBUG-16239)
Platform Specific
Windows
* Fixed detection of Microsoft Visual C++ Build Tools

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -120,10 +120,12 @@
\li Qt Quick Controls Application \li Qt Quick Controls Application
Create a Qt Quick application using Create a Qt Quick application using
\l{http://doc-snapshots.qt.io/qt5-5.7/qtquickcontrols2-index.html}
{Qt Quick Controls 2} (requires Qt 5.7 or later),
\l{http://doc.qt.io/qt-5/qtquickcontrols-index.html} \l{http://doc.qt.io/qt-5/qtquickcontrols-index.html}
{Qt Quick Controls} or {Qt Quick Controls}, or
\l{http://doc.qt.io/qt-5/qtlabscontrols-index.html} \l{http://doc.qt.io/qt-5/qtlabscontrols-index.html}
{Qt Labs Controls} {Qt Labs Controls} (only for Qt 5.6)
\li Qt Canvas 3D Application \li Qt Canvas 3D Application

View File

@@ -50,13 +50,16 @@
a QQuickView. You can build the application and deploy it to desktop, a QQuickView. You can build the application and deploy it to desktop,
embedded, and mobile target platforms. embedded, and mobile target platforms.
\li \uicontrol {Qt Quick Controls Application} and \li \uicontrol {Qt Quick Controls Application},
\uicontrol {Qt Quick Controls 2 Application}, and
\uicontrol {Qt Labs Controls Application} are like \uicontrol {Qt Labs Controls Application} are like
\uicontrol {Qt Quick Application}, but using \uicontrol {Qt Quick Application}, but using
\l{http://doc-snapshots.qt.io/qt5-5.7/qtquickcontrols2-index.html}
{Qt Quick Controls 2} (requires Qt 5.7 or later),
\l{http://doc.qt.io/qt-5/qtquickcontrols-index.html} \l{http://doc.qt.io/qt-5/qtquickcontrols-index.html}
{Qt Quick Controls} or {Qt Quick Controls}, or
\l{http://doc.qt.io/qt-5/qtlabscontrols-index.html} \l{http://doc.qt.io/qt-5/qtlabscontrols-index.html}
{Qt Labs Controls} {Qt Labs Controls} (only for Qt 5.6)
\li \uicontrol {Qt Canvas 3D Application} creates a Qt Quick application \li \uicontrol {Qt Canvas 3D Application} creates a Qt Quick application
that imports the Qt Canvas 3D module and, optionally, includes that imports the Qt Canvas 3D module and, optionally, includes

View File

@@ -188,7 +188,11 @@ class PlainDumper:
def importPlainDumpers(args): def importPlainDumpers(args):
if args == "off": if args == "off":
try:
gdb.execute("disable pretty-printer .* .*") gdb.execute("disable pretty-printer .* .*")
except:
# Might occur in non-ASCII directories
warn("COULD NOT DISABLE PRETTY PRINTERS")
else: else:
theDumper.importPlainDumpers() theDumper.importPlainDumpers()

View File

@@ -2640,7 +2640,10 @@ def qdumpHelper__QJsonValue(d, data, base, pv):
if t == 2: if t == 2:
d.putType("QJsonValue (Number)") d.putType("QJsonValue (Number)")
if latinOrIntValue: if latinOrIntValue:
d.putValue(v) w = toInteger(v)
if w >= 0x4000000:
w -= 0x8000000
d.putValue(w)
else: else:
data = base + v; data = base + v;
d.putValue(d.extractBlob(data, 8).extractDouble()) d.putValue(d.extractBlob(data, 8).extractDouble())
@@ -2741,10 +2744,12 @@ def qdump__QJsonValue(d, value):
d.putType("QJsonValue (Bool)") d.putType("QJsonValue (Bool)")
v = toInteger(value["b"]) v = toInteger(value["b"])
d.putValue("true" if v else "false") d.putValue("true" if v else "false")
d.putNumChild(0)
return return
if t == 2: if t == 2:
d.putType("QJsonValue (Number)") d.putType("QJsonValue (Number)")
d.putValue(value["dbl"]) d.putValue(value["dbl"])
d.putNumChild(0)
return return
if t == 3: if t == 3:
d.putType("QJsonValue (String)") d.putType("QJsonValue (String)")

View File

@@ -43,7 +43,7 @@ QHash<QObject *, DesignerCustomObjectData*> m_objectToDataHash;
DesignerCustomObjectData::DesignerCustomObjectData(QObject *object) DesignerCustomObjectData::DesignerCustomObjectData(QObject *object)
: m_object(object) : m_object(object)
{ {
if (object) if (object) {
populateResetHashes(); populateResetHashes();
m_objectToDataHash.insert(object, this); m_objectToDataHash.insert(object, this);
QObject::connect(object, &QObject::destroyed, [=] { QObject::connect(object, &QObject::destroyed, [=] {
@@ -51,6 +51,7 @@ DesignerCustomObjectData::DesignerCustomObjectData(QObject *object)
delete this; delete this;
}); });
} }
}
void DesignerCustomObjectData::registerData(QObject *object) void DesignerCustomObjectData::registerData(QObject *object)
{ {

View File

@@ -3,7 +3,7 @@
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ], "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
"id": "W.QtLabsControlsApplication", "id": "W.QtLabsControlsApplication",
"category": "F.Application", "category": "F.Application",
"trDescription": "Creates a deployable Qt Quick 2 application using Qt Labs Controls.", "trDescription": "Creates a deployable Qt Quick 2 application using Qt Labs Controls.<br/><br/><b>Note:</b> Qt Labs Controls are only available with Qt 5.6. Choose <em>Qt Quick Controls 2 Application</em> when targeting Qt 5.7 or later.",
"trDisplayName": "Qt Labs Controls Application", "trDisplayName": "Qt Labs Controls Application",
"trDisplayCategory": "Application", "trDisplayCategory": "Application",
"icon": "../qtquickapplication/qml_wizard.png", "icon": "../qtquickapplication/qml_wizard.png",

View File

@@ -3,6 +3,9 @@ import QtQuick.Window %{QtQuickWindowVersion}
Window { Window {
visible: true visible: true
width: 640
height: 480
title: qsTr("Hello World")
@if %{IsUiFileInUse} @if %{IsUiFileInUse}
MainForm { MainForm {

View File

@@ -0,0 +1,10 @@
import QtQuick %{QtQuickVersion}
Page1Form {
button1.onClicked: {
console.log("Button 1 clicked.");
}
button2.onClicked: {
console.log("Button 2 clicked.");
}
}

View File

@@ -0,0 +1,22 @@
import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickControls2Version}
import QtQuick.Layouts %{QtQuickLayoutsVersion}
Item {
property alias button1: button1
property alias button2: button2
RowLayout {
anchors.centerIn: parent
Button {
id: button1
text: qsTr("Press Me 1")
}
Button {
id: button2
text: qsTr("Press Me 2")
}
}
}

View File

@@ -0,0 +1,13 @@
QT += qml quick
CONFIG += c++11
SOURCES += %{MainCppFileName}
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)

View File

@@ -0,0 +1,12 @@
%{Cpp:LicenseTemplate}\
%{JS: QtSupport.qtIncludes([], ["QtGui/QGuiApplication", "QtQml/QQmlApplicationEngine"])}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}

View File

@@ -0,0 +1,37 @@
import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickControls2Version}
import QtQuick.Layouts %{QtQuickLayoutsVersion}
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
Page1 {
}
Page {
Label {
text: qsTr("Second page")
anchors.centerIn: parent
}
}
}
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
TabButton {
text: qsTr("First")
}
TabButton {
text: qsTr("Second")
}
}
}

View File

@@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>Page1.qml</file>
<file>Page1Form.ui.qml</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,86 @@
{
"version": 1,
"supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
"id": "V.QtQuickControls2Application",
"category": "F.Application",
"trDescription": "Creates a deployable Qt Quick 2 application using Qt Quick Controls 2.<br/><br/><b>Note:</b> Qt Quick Controls 2 are available with Qt 5.7 and later. Choose <em>Qt Labs Controls Application</em> when targeting Qt 5.6.",
"trDisplayName": "Qt Quick Controls 2 Application",
"trDisplayCategory": "Application",
"icon": "../qtquickapplication/qml_wizard.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.2" ],
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
"options":
[
{ "key": "ProFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
{ "key": "MainCppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
{ "key": "QtQuickVersion", "value": "2.7" },
{ "key": "QtQuickControls2Version", "value": "2.0" },
{ "key": "QtQuickDialogsVersion", "value": "1.0" },
{ "key": "QtQuickLayoutsVersion", "value": "1.0" }
],
"pages":
[
{
"trDisplayName": "Project Location",
"trShortTitle": "Location",
"typeId": "Project"
},
{
"trDisplayName": "Kit Selection",
"trShortTitle": "Kits",
"typeId": "Kits",
"enabled": "%{IsTopLevelProject}",
"data": { "projectFilePath": "%{ProFileName}" }
},
{
"trDisplayName": "Project Management",
"trShortTitle": "Summary",
"typeId": "Summary"
}
],
"generators":
[
{
"typeId": "File",
"data":
[
{
"source": "app.pro",
"target": "%{ProFileName}",
"openAsProject": true
},
{
"source": "main.cpp",
"target": "%{MainCppFileName}"
},
{
"source": "main.qml.tpl",
"target": "main.qml",
"openInEditor": true
},
{
"source": "Page1.qml.tpl",
"target": "Page1.qml"
},
{
"source": "Page1Form.ui.qml.tpl",
"target": "Page1Form.ui.qml"
},
{
"source": "qml.qrc"
},
{
"source": "../../../../shared/qrcdeployment.pri",
"target": "%{ProjectDirectory}/deployment.pri"
},
{
"source": "../../git.ignore",
"target": "%{ProjectDirectory}/.gitignore",
"condition": "%{JS: !%{IsSubproject} && '%{VersionControl}' === 'G.Git'}"
}
]
}
]
}

View File

@@ -480,6 +480,13 @@ protected:
} }
} }
virtual bool visit(UiPragma *ast)
{
out("pragma ", ast->pragmaToken);
accept(ast->pragmaType);
return false;
}
virtual bool visit(UiImport *ast) virtual bool visit(UiImport *ast)
{ {
out("import ", ast->importToken); out("import ", ast->importToken);
@@ -1187,6 +1194,12 @@ protected:
return false; return false;
} }
virtual bool visit(UiQualifiedPragmaId *ast)
{
out(ast->identifierToken);
return false;
}
virtual bool visit(Elision *ast) virtual bool visit(Elision *ast)
{ {
for (Elision *it = ast; it; it = it->next) { for (Elision *it = ast; it; it = it->next) {

View File

@@ -447,8 +447,8 @@ static QStringList splitArgsUnix(const QString &args, bool abortOnMeta,
} }
} }
for (int i = 0; i < val.length(); i++) { for (int i = 0; i < val.length(); i++) {
QChar cc = val.unicode()[i]; const QChar cc = val.unicode()[i];
if (cc == 9 || cc == 10 || cc == 32) { if (cc.unicode() == 9 || cc.unicode() == 10 || cc.unicode() == 32) {
if (hadWord) { if (hadWord) {
ret += cret; ret += cret;
cret.clear(); cret.clear();

View File

@@ -48,13 +48,6 @@ ToolTip::ToolTip() : m_tip(0), m_widget(0)
{ {
connect(&m_showTimer, &QTimer::timeout, this, &ToolTip::hideTipImmediately); connect(&m_showTimer, &QTimer::timeout, this, &ToolTip::hideTipImmediately);
connect(&m_hideDelayTimer, &QTimer::timeout, this, &ToolTip::hideTipImmediately); connect(&m_hideDelayTimer, &QTimer::timeout, this, &ToolTip::hideTipImmediately);
connect(static_cast<QGuiApplication *>(QGuiApplication::instance()),
&QGuiApplication::applicationStateChanged,
[this](Qt::ApplicationState state) {
if (state != Qt::ApplicationActive)
hideTipImmediately();
}
);
} }
ToolTip::~ToolTip() ToolTip::~ToolTip()
@@ -290,6 +283,11 @@ void ToolTip::placeTip(const QPoint &pos, QWidget *w)
bool ToolTip::eventFilter(QObject *o, QEvent *event) bool ToolTip::eventFilter(QObject *o, QEvent *event)
{ {
if (m_tip && event->type() == QEvent::ApplicationStateChange
&& qApp->applicationState() != Qt::ApplicationActive) {
hideTipImmediately();
}
if (!o->isWidgetType()) if (!o->isWidgetType())
return false; return false;

View File

@@ -194,9 +194,9 @@ void AutoTestUnitTests::testCodeParserGTest()
if (qgetenv("GOOGLETEST_DIR").isEmpty()) if (qgetenv("GOOGLETEST_DIR").isEmpty())
QSKIP("This test needs googletest - set GOOGLETEST_DIR (point to googletest repository)"); QSKIP("This test needs googletest - set GOOGLETEST_DIR (point to googletest repository)");
QFETCH(QString, projectFilePath);
CppTools::Tests::ProjectOpenerAndCloser projectManager; CppTools::Tests::ProjectOpenerAndCloser projectManager;
CppTools::ProjectInfo projectInfo = projectManager.open( CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
QString(m_tmpDir->path() + QLatin1String("/simple_gt/simple_gt.pro")), true);
QVERIFY(projectInfo.isValid()); QVERIFY(projectInfo.isValid());
QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished()));
@@ -226,5 +226,14 @@ void AutoTestUnitTests::testCodeParserGTest()
QCOMPARE(m_model->dataTagsCount(), 0); QCOMPARE(m_model->dataTagsCount(), 0);
} }
void AutoTestUnitTests::testCodeParserGTest_data()
{
QTest::addColumn<QString>("projectFilePath");
QTest::newRow("simpleGoogletest")
<< QString(m_tmpDir->path() + QLatin1String("/simple_gt/simple_gt.pro"));
QTest::newRow("simpleGoogletestQbs")
<< QString(m_tmpDir->path() + QLatin1String("/simple_gt/simple_gt.qbs"));
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -51,6 +51,7 @@ private slots:
void testCodeParserSwitchStartup(); void testCodeParserSwitchStartup();
void testCodeParserSwitchStartup_data(); void testCodeParserSwitchStartup_data();
void testCodeParserGTest(); void testCodeParserGTest();
void testCodeParserGTest_data();
private: private:
TestTreeModel *m_model; TestTreeModel *m_model;

View File

@@ -41,17 +41,24 @@
<file>unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs</file> <file>unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs</file>
<file>unit_test/simple_gt/src/main.cpp</file> <file>unit_test/simple_gt/src/main.cpp</file>
<file>unit_test/simple_gt/src/src.pro</file> <file>unit_test/simple_gt/src/src.pro</file>
<file>unit_test/simple_gt/src/src.qbs</file>
<file>unit_test/simple_gt/tests/gt1/further.cpp</file> <file>unit_test/simple_gt/tests/gt1/further.cpp</file>
<file>unit_test/simple_gt/tests/gt1/gt1.pro</file> <file>unit_test/simple_gt/tests/gt1/gt1.pro</file>
<file>unit_test/simple_gt/tests/gt1/gt1.qbs</file>
<file>unit_test/simple_gt/tests/gt1/main.cpp</file> <file>unit_test/simple_gt/tests/gt1/main.cpp</file>
<file>unit_test/simple_gt/tests/gt2/gt2.pro</file> <file>unit_test/simple_gt/tests/gt2/gt2.pro</file>
<file>unit_test/simple_gt/tests/gt2/gt2.qbs</file>
<file>unit_test/simple_gt/tests/gt2/main.cpp</file> <file>unit_test/simple_gt/tests/gt2/main.cpp</file>
<file>unit_test/simple_gt/tests/gt2/queuetest.h</file> <file>unit_test/simple_gt/tests/gt2/queuetest.h</file>
<file>unit_test/simple_gt/tests/tests.pro</file> <file>unit_test/simple_gt/tests/tests.pro</file>
<file>unit_test/simple_gt/tests/tests.qbs</file>
<file>unit_test/simple_gt/simple_gt.pro</file> <file>unit_test/simple_gt/simple_gt.pro</file>
<file>unit_test/simple_gt/simple_gt.qbs</file>
<file>unit_test/simple_gt/tests/gtest_dependency.pri</file> <file>unit_test/simple_gt/tests/gtest_dependency.pri</file>
<file>unit_test/simple_gt/tests/gt3/dummytest.h</file> <file>unit_test/simple_gt/tests/gt3/dummytest.h</file>
<file>unit_test/simple_gt/tests/gt3/gt3.pro</file> <file>unit_test/simple_gt/tests/gt3/gt3.pro</file>
<file>unit_test/simple_gt/tests/gt3/gt3.qbs</file>
<file>unit_test/simple_gt/tests/gt3/main.cpp</file> <file>unit_test/simple_gt/tests/gt3/main.cpp</file>
<file>unit_test/simple_gt/tests/common/functions.js</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -115,7 +115,11 @@ void TestConfiguration::completeTestInformation()
foreach (const BuildTargetInfo &bti, appTargets.list) { foreach (const BuildTargetInfo &bti, appTargets.list) {
// some project manager store line/column information as well inside ProjectPart // some project manager store line/column information as well inside ProjectPart
if (bti.isValid() && m_proFile.startsWith(bti.projectFilePath.toString())) { if (bti.isValid() && m_proFile.startsWith(bti.projectFilePath.toString())) {
targetFile = Utils::HostOsInfo::withExecutableSuffix(bti.targetFilePath.toString()); targetFile = bti.targetFilePath.toString();
if (Utils::HostOsInfo::isWindowsHost()
&& !targetFile.toLower().endsWith(QLatin1String(".exe"))) {
targetFile = Utils::HostOsInfo::withExecutableSuffix(targetFile);
}
targetName = bti.targetName; targetName = bti.targetName;
break; break;
} }

View File

@@ -152,6 +152,10 @@ bool TestAstVisitor::visit(CPlusPlus::CallAST *ast)
bool TestAstVisitor::visit(CPlusPlus::CompoundStatementAST *ast) bool TestAstVisitor::visit(CPlusPlus::CompoundStatementAST *ast)
{ {
if (!ast || !ast->symbol) {
m_currentScope = 0;
return false;
}
m_currentScope = ast->symbol->asScope(); m_currentScope = ast->symbol->asScope();
return true; return true;
} }

View File

@@ -75,7 +75,7 @@ public:
private: private:
QString m_className; QString m_className;
CPlusPlus::Scope *m_currentScope; CPlusPlus::Scope *m_currentScope = 0;
CPlusPlus::Document::Ptr m_currentDoc; CPlusPlus::Document::Ptr m_currentDoc;
}; };

View File

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

View File

@@ -0,0 +1,10 @@
import qbs
CppApplication {
type: "application"
name: "Dummy application"
Depends { name: "Qt.core" }
files: [ "main.cpp" ]
}

View File

@@ -0,0 +1,49 @@
var FileInfo = loadExtension("qbs.FileInfo")
function getGTestDir(str) {
if (!str) {
if (qbs.hostOS.contains("linux"))
return "/usr/include/gtest";
} else {
return FileInfo.joinPaths(str, "googletest");
}
return "";
}
function getGMockDir(str) {
if (!str) {
if (qbs.hostOS.contains("linux"))
return "/usr/include/gmock";
} else {
return FileInfo.joinPaths(str, "googlemock");
}
return "";
}
function getGTestAll(str) {
var gtest = getGTestDir(str);
if (!gtest)
return [];
return [FileInfo.joinPaths(gtest, "src/gtest-all.cc")];
}
function getGMockAll(str) {
var gmock = getGMockDir(str);
if (!gmock)
return [];
return [FileInfo.joinPaths(gmock, "src/gmock-all.cc")];
}
function getGTestIncludes(str) {
var gtest = getGTestDir(str);
if (!gtest)
return [];
return [gtest, FileInfo.joinPaths(gtest, "include")];
}
function getGMockIncludes(str) {
var mock = getGMockDir(str);
if (!mock)
return [];
return [mock, FileInfo.joinPaths(mock, "include")];
}

View File

@@ -0,0 +1,35 @@
import qbs
import qbs.File
import qbs.FileInfo
import "../common/functions.js" as googleCommon
CppApplication {
type: "application"
name: "googletest1"
property string gtestDir: googleCommon.getGTestDir(project.googletestDir)
property string gmockDir: googleCommon.getGMockDir(project.googletestDir)
condition: {
if (File.exists(gtestDir) && File.exists(gmockDir))
return true;
console.error("Cannot find Google Test - specify environment variable GOOGLETEST_DIR "
+ "or qbs property " + project.name + ".googletestDir" );
return false;
}
cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
.concat(googleCommon.getGMockIncludes(project.googletestDir))
cpp.cxxLanguageVersion: "c++11"
cpp.defines: ["GTEST_LANG_CXX11"]
cpp.dynamicLibraries: [ "pthread" ]
files: [
// own stuff
"further.cpp",
"main.cpp",
].concat(googleCommon.getGTestAll(project.googletestDir))
.concat(googleCommon.getGMockAll(project.googletestDir))
}

View File

@@ -0,0 +1,36 @@
import qbs
import qbs.File
import qbs.FileInfo
import "../common/functions.js" as googleCommon
CppApplication {
type: "application"
name: "googletest2"
property string gtestDir: googleCommon.getGTestDir(project.googletestDir)
property string gmockDir: googleCommon.getGMockDir(project.googletestDir)
Depends { name: "Qt.core" }
condition: {
if (File.exists(gtestDir) && File.exists(gmockDir))
return true;
console.error("Cannot find Google Test - specify environment variable GOOGLETEST_DIR "
+ "or qbs property " + project.name + ".googletestDir" );
return false;
}
cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
.concat(googleCommon.getGMockIncludes(project.googletestDir))
cpp.cxxLanguageVersion: "c++11"
cpp.defines: ["GTEST_LANG_CXX11"]
files: [
// own stuff
"queuetest.h",
"main.cpp",
].concat(googleCommon.getGTestAll(project.googletestDir))
.concat(googleCommon.getGMockAll(project.googletestDir))
}

View File

@@ -0,0 +1,36 @@
import qbs
import qbs.File
import qbs.FileInfo
import "../common/functions.js" as googleCommon
CppApplication {
type: "application"
name: "googletest3"
property string gtestDir: googleCommon.getGTestDir(project.googletestDir)
property string gmockDir: googleCommon.getGMockDir(project.googletestDir)
Depends { name: "Qt.core" }
condition: {
if (File.exists(gtestDir) && File.exists(gmockDir))
return true;
console.error("Cannot find Google Test - specify environment variable GOOGLETEST_DIR "
+ "or qbs property " + project.name + ".googletestDir" );
return false;
}
cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir))
.concat(googleCommon.getGMockIncludes(project.googletestDir))
cpp.cxxLanguageVersion: "c++11"
cpp.defines: ["GTEST_LANG_CXX11"]
files: [
// own stuff
"dummytest.h",
"main.cpp",
].concat(googleCommon.getGTestAll(project.googletestDir))
.concat(googleCommon.getGMockAll(project.googletestDir))
}

View File

@@ -0,0 +1,14 @@
import qbs
import qbs.Environment
Project {
name: "Tests"
property string googletestDir: Environment.getEnv("GOOGLETEST_DIR")
references: [
"gt1/gt1.qbs",
"gt2/gt2.qbs",
"gt3/gt3.qbs"
]
}

View File

@@ -50,25 +50,29 @@ namespace Internal {
QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid) QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid)
{ {
QString exeFromSettings = ClangStaticAnalyzerSettings::instance()->clangExecutable(); QString executable = ClangStaticAnalyzerSettings::instance()->clangExecutable();
if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
if (exeFromSettings.endsWith(QLatin1String(QTC_HOST_EXE_SUFFIX)))
exeFromSettings.chop(int(qstrlen(QTC_HOST_EXE_SUFFIX)));
if (exeFromSettings.endsWith(QLatin1String("clang")))
exeFromSettings.append(QLatin1String("-cl"));
}
return clangExecutable(exeFromSettings, isValid);
}
QString clangExecutable(const QString &fileNameOrPath, bool *isValid)
{
QString executable = fileNameOrPath;
if (executable.isEmpty()) { if (executable.isEmpty()) {
*isValid = false; *isValid = false;
return executable; return executable;
} }
if (!QFileInfo(executable).isAbsolute()) { const QString hostExeSuffix = QLatin1String(QTC_HOST_EXE_SUFFIX);
const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity();
const bool hasSuffix = executable.endsWith(hostExeSuffix, caseSensitivity);
if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
if (hasSuffix)
executable.chop(hostExeSuffix.length());
executable.append(QLatin1String("-cl"));
if (hasSuffix)
executable.append(hostExeSuffix);
}
const QFileInfo fileInfo = QFileInfo(executable);
if (fileInfo.isAbsolute()) {
if (!hasSuffix)
executable.append(hostExeSuffix);
} else {
const Utils::Environment &environment = Utils::Environment::systemEnvironment(); const Utils::Environment &environment = Utils::Environment::systemEnvironment();
const QString executableFromPath = environment.searchInPath(executable).toString(); const QString executableFromPath = environment.searchInPath(executable).toString();
if (executableFromPath.isEmpty()) { if (executableFromPath.isEmpty()) {

View File

@@ -40,7 +40,6 @@ namespace Internal {
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0); bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0);
QString clangExecutable(const QString &fileNameOrPath, bool *isValid);
QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid); QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid);
QString createFullLocationString(const Debugger::DiagnosticLocation &location); QString createFullLocationString(const Debugger::DiagnosticLocation &location);

View File

@@ -30,6 +30,7 @@
#include "cmakeprojectmanager.h" #include "cmakeprojectmanager.h"
#include "cmaketool.h" #include "cmaketool.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <projectexplorer/kit.h> #include <projectexplorer/kit.h>
@@ -49,6 +50,7 @@
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QFileSystemWatcher> #include <QFileSystemWatcher>
#include <QMessageBox>
#include <QRegularExpression> #include <QRegularExpression>
#include <QSet> #include <QSet>
#include <QTemporaryDir> #include <QTemporaryDir>
@@ -61,20 +63,37 @@ namespace CMakeProjectManager {
namespace Internal { namespace Internal {
static QStringList toArguments(const CMakeConfig &config, const ProjectExplorer::Kit *k) { static QStringList toArguments(const CMakeConfig &config, const ProjectExplorer::Kit *k) {
const QStringList argList return Utils::transform(config, [k](const CMakeConfigItem &i) -> QString {
= Utils::transform(config, [k](const CMakeConfigItem &i) -> QString { QString a = QString::fromLatin1("-D");
const QString tmp = i.toString(); a.append(QString::fromUtf8(i.key));
return tmp.isEmpty() ? QString() switch (i.type) {
: QString::fromLatin1("-D") + k->macroExpander()->expand(tmp); case CMakeConfigItem::FILEPATH:
a.append(QLatin1String(":FILEPATH="));
break;
case CMakeConfigItem::PATH:
a.append(QLatin1String(":PATH="));
break;
case CMakeConfigItem::BOOL:
a.append(QLatin1String(":BOOL="));
break;
case CMakeConfigItem::STRING:
a.append(QLatin1String(":STRING="));
break;
case CMakeConfigItem::INTERNAL:
a.append(QLatin1String(":INTERNAL="));
break;
}
a.append(i.expandedValue(k));
return a;
}); });
return Utils::filtered(argList, [](const QString &s) { return !s.isEmpty(); });
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// BuildDirManager: // BuildDirManager:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
BuildDirManager::BuildDirManager(const CMakeBuildConfiguration *bc) : BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
m_buildConfiguration(bc), m_buildConfiguration(bc),
m_watcher(new QFileSystemWatcher(this)) m_watcher(new QFileSystemWatcher(this))
{ {
@@ -82,7 +101,7 @@ BuildDirManager::BuildDirManager(const CMakeBuildConfiguration *bc) :
m_projectName = sourceDirectory().fileName(); m_projectName = sourceDirectory().fileName();
m_reparseTimer.setSingleShot(true); m_reparseTimer.setSingleShot(true);
m_reparseTimer.setInterval(500); m_reparseTimer.setInterval(5000);
connect(&m_reparseTimer, &QTimer::timeout, this, &BuildDirManager::parse); connect(&m_reparseTimer, &QTimer::timeout, this, &BuildDirManager::parse);
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this]() { connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this]() {
@@ -155,6 +174,7 @@ void BuildDirManager::resetData()
{ {
m_hasData = false; m_hasData = false;
m_cmakeCache.clear();
m_projectName.clear(); m_projectName.clear();
m_buildTargets.clear(); m_buildTargets.clear();
m_watchedFiles.clear(); m_watchedFiles.clear();
@@ -177,22 +197,23 @@ bool BuildDirManager::persistCMakeState()
delete m_tempDir; delete m_tempDir;
m_tempDir = nullptr; m_tempDir = nullptr;
parse(); resetData();
QTimer::singleShot(0, this, &BuildDirManager::parse); // make sure signals only happen afterwards!
return true; return true;
} }
void BuildDirManager::parse() void BuildDirManager::parse()
{ {
checkConfiguration();
CMakeTool *tool = CMakeKitInformation::cmakeTool(kit()); CMakeTool *tool = CMakeKitInformation::cmakeTool(kit());
const QString generator = CMakeGeneratorKitInformation::generator(kit()); const QString generator = CMakeGeneratorKitInformation::generator(kit());
QTC_ASSERT(tool, return); QTC_ASSERT(tool, return);
QTC_ASSERT(!generator.isEmpty(), return); QTC_ASSERT(!generator.isEmpty(), return);
// Pop up a dialog asking the user to rerun cmake const QString cbpFile = CMakeManager::findCbpFile(QDir(workDirectory().toString()));
QString cbpFile = CMakeManager::findCbpFile(QDir(workDirectory().toString())); const QFileInfo cbpFileFi = cbpFile.isEmpty() ? QFileInfo() : QFileInfo(cbpFile);
QFileInfo cbpFileFi(cbpFile);
if (!cbpFileFi.exists()) { if (!cbpFileFi.exists()) {
// Initial create: // Initial create:
startCMake(tool, generator, intendedConfiguration()); startCMake(tool, generator, intendedConfiguration());
@@ -254,21 +275,21 @@ void BuildDirManager::clearFiles()
CMakeConfig BuildDirManager::parsedConfiguration() const CMakeConfig BuildDirManager::parsedConfiguration() const
{ {
if (!m_hasData) if (m_cmakeCache.isEmpty()) {
return CMakeConfig();
Utils::FileName cacheFile = workDirectory(); Utils::FileName cacheFile = workDirectory();
cacheFile.appendPath(QLatin1String("CMakeCache.txt")); cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
if (!cacheFile.exists())
return m_cmakeCache;
QString errorMessage; QString errorMessage;
CMakeConfig result = parseConfiguration(cacheFile, &errorMessage); m_cmakeCache = parseConfiguration(cacheFile, &errorMessage);
if (!errorMessage.isEmpty()) if (!errorMessage.isEmpty())
emit errorOccured(errorMessage); emit errorOccured(errorMessage);
const Utils::FileName sourceOfBuildDir const Utils::FileName sourceOfBuildDir
= Utils::FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", result)); = Utils::FileName::fromUtf8(CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", m_cmakeCache));
if (sourceOfBuildDir != sourceDirectory()) // Use case-insensitive compare where appropriate if (sourceOfBuildDir != sourceDirectory()) // Use case-insensitive compare where appropriate
emit errorOccured(tr("The build directory is not for %1").arg(sourceDirectory().toUserOutput())); emit errorOccured(tr("The build directory is not for %1").arg(sourceDirectory().toUserOutput()));
}
return result; return m_cmakeCache;
} }
void BuildDirManager::stopProcess() void BuildDirManager::stopProcess()
@@ -335,6 +356,7 @@ void BuildDirManager::extractData()
return; return;
m_watcher->addPath(cbpFile); m_watcher->addPath(cbpFile);
m_watcher->addPath(workDirectory().toString() + QLatin1String("/CMakeCache.txt"));
// setFolderName // setFolderName
CMakeCbpParser cbpparser; CMakeCbpParser cbpparser;
@@ -497,6 +519,61 @@ void BuildDirManager::processCMakeError()
}); });
} }
void BuildDirManager::checkConfiguration()
{
if (m_tempDir) // always throw away changes in the tmpdir!
return;
ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit();
const CMakeConfig cache = parsedConfiguration();
if (cache.isEmpty())
return; // No cache file yet.
CMakeConfig newConfig;
QSet<QString> changedKeys;
QSet<QString> removedKeys;
foreach (const CMakeConfigItem &iBc, intendedConfiguration()) {
const CMakeConfigItem &iCache
= Utils::findOrDefault(cache, [&iBc](const CMakeConfigItem &i) { return i.key == iBc.key; });
if (iCache.isNull()) {
removedKeys << QString::fromUtf8(iBc.key);
} else if (QString::fromUtf8(iCache.value) != iBc.expandedValue(k)) {
changedKeys << QString::fromUtf8(iBc.key);
newConfig.append(iCache);
} else {
newConfig.append(iBc);
}
}
if (!changedKeys.isEmpty() || !removedKeys.isEmpty()) {
QSet<QString> total = removedKeys + changedKeys;
QStringList keyList = total.toList();
Utils::sort(keyList);
QString table = QLatin1String("<table>");
foreach (const QString &k, keyList) {
QString change;
if (removedKeys.contains(k))
change = tr("<removed>");
else
change = QString::fromUtf8(CMakeConfigItem::valueOf(k.toUtf8(), cache)).trimmed();
if (change.isEmpty())
change = tr("<empty>");
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td></tr>").arg(k).arg(change.toHtmlEscaped());
}
table += QLatin1String("\n</table>");
QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow());
box->setText(tr("CMake configuration has changed on disk."));
box->setInformativeText(tr("The CMakeCache.txt file has changed: %1").arg(table));
box->setStandardButtons(QMessageBox::Discard | QMessageBox::Apply);
box->setDefaultButton(QMessageBox::Discard);
int ret = box->exec();
if (ret == QMessageBox::Apply)
m_buildConfiguration->setCMakeConfiguration(newConfig);
}
}
static QByteArray trimCMakeCacheLine(const QByteArray &in) { static QByteArray trimCMakeCacheLine(const QByteArray &in) {
int start = 0; int start = 0;
while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t')) while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t'))
@@ -587,6 +664,8 @@ CMakeConfig BuildDirManager::parseConfiguration(const Utils::FileName &cacheFile
void BuildDirManager::maybeForceReparse() void BuildDirManager::maybeForceReparse()
{ {
checkConfiguration();
const QByteArray GENERATOR_KEY = "CMAKE_GENERATOR"; const QByteArray GENERATOR_KEY = "CMAKE_GENERATOR";
const QByteArray EXTRA_GENERATOR_KEY = "CMAKE_EXTRA_GENERATOR"; const QByteArray EXTRA_GENERATOR_KEY = "CMAKE_EXTRA_GENERATOR";
const QByteArray CMAKE_COMMAND_KEY = "CMAKE_COMMAND"; const QByteArray CMAKE_COMMAND_KEY = "CMAKE_COMMAND";

View File

@@ -63,7 +63,7 @@ class BuildDirManager : public QObject
Q_OBJECT Q_OBJECT
public: public:
BuildDirManager(const CMakeBuildConfiguration *bc); BuildDirManager(CMakeBuildConfiguration *bc);
~BuildDirManager() override; ~BuildDirManager() override;
const ProjectExplorer::Kit *kit() const; const ProjectExplorer::Kit *kit() const;
@@ -87,6 +87,8 @@ public:
void clearFiles(); void clearFiles();
CMakeConfig parsedConfiguration() const; CMakeConfig parsedConfiguration() const;
void checkConfiguration();
static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile, static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile,
QString *errorMessage); QString *errorMessage);
@@ -106,12 +108,12 @@ private:
void processCMakeOutput(); void processCMakeOutput();
void processCMakeError(); void processCMakeError();
bool m_hasData = false; bool m_hasData = false;
const CMakeBuildConfiguration *m_buildConfiguration = nullptr; CMakeBuildConfiguration *m_buildConfiguration = nullptr;
Utils::QtcProcess *m_cmakeProcess = nullptr; Utils::QtcProcess *m_cmakeProcess = nullptr;
QTemporaryDir *m_tempDir = nullptr; QTemporaryDir *m_tempDir = nullptr;
mutable CMakeConfig m_cmakeCache;
QSet<Utils::FileName> m_watchedFiles; QSet<Utils::FileName> m_watchedFiles;
QString m_projectName; QString m_projectName;

View File

@@ -156,10 +156,6 @@ void CMakeBuildConfiguration::ctor()
void CMakeBuildConfiguration::maybeForceReparse() void CMakeBuildConfiguration::maybeForceReparse()
{ {
ProjectExplorer::Kit *k = target()->kit();
CMakeConfig config = cmakeConfiguration();
config.append(CMakeConfigurationKitInformation::configuration(k)); // last value wins...
setCMakeConfiguration(config);
m_buildDirManager->maybeForceReparse(); m_buildDirManager->maybeForceReparse();
} }
@@ -206,18 +202,14 @@ QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration
if (m_completeConfigurationCache.isEmpty()) if (m_completeConfigurationCache.isEmpty())
m_completeConfigurationCache = m_buildDirManager->parsedConfiguration(); m_completeConfigurationCache = m_buildDirManager->parsedConfiguration();
CMakeConfig cache = Utils::filtered(m_completeConfigurationCache, return Utils::transform(m_completeConfigurationCache,
[](const CMakeConfigItem &i) { [this](const CMakeConfigItem &i) {
return i.type != CMakeConfigItem::INTERNAL
&& i.type != CMakeConfigItem::STATIC;
});
return Utils::transform(cache, [](const CMakeConfigItem &i) {
ConfigModel::DataItem j; ConfigModel::DataItem j;
j.key = QString::fromUtf8(i.key); j.key = QString::fromUtf8(i.key);
j.value = QString::fromUtf8(i.value); j.value = QString::fromUtf8(i.value);
j.description = QString::fromUtf8(i.documentation); j.description = QString::fromUtf8(i.documentation);
j.isAdvanced = i.isAdvanced; j.isAdvanced = i.isAdvanced || i.type == CMakeConfigItem::INTERNAL;
switch (i.type) { switch (i.type) {
case CMakeConfigItem::FILEPATH: case CMakeConfigItem::FILEPATH:
j.type = ConfigModel::DataItem::FILE; j.type = ConfigModel::DataItem::FILE;
@@ -272,7 +264,6 @@ void CMakeBuildConfiguration::setCurrentCMakeConfiguration(const QList<ConfigMod
return ni; return ni;
}); });
// There is a buildDirManager, so there must also be an active BC:
const CMakeConfig config = cmakeConfiguration() + newConfig; const CMakeConfig config = cmakeConfiguration() + newConfig;
setCMakeConfiguration(config); setCMakeConfiguration(config);
@@ -303,11 +294,28 @@ static CMakeConfig removeDuplicates(const CMakeConfig &config)
void CMakeBuildConfiguration::setCMakeConfiguration(const CMakeConfig &config) void CMakeBuildConfiguration::setCMakeConfiguration(const CMakeConfig &config)
{ {
m_configuration = removeDuplicates(config); m_configuration = removeDuplicates(config);
const Kit *k = target()->kit();
CMakeConfig kitConfig = CMakeConfigurationKitInformation::configuration(k);
bool hasKitOverride = false;
foreach (const CMakeConfigItem &i, m_configuration) {
const QString b = CMakeConfigItem::expandedValueOf(k, i.key, kitConfig);
if (!b.isNull() && i.expandedValue(k) != b) {
hasKitOverride = true;
break;
}
}
if (hasKitOverride)
setWarning(tr("CMake Configuration set by the Kit was overridden in the project."));
else
setWarning(QString());
} }
CMakeConfig CMakeBuildConfiguration::cmakeConfiguration() const CMakeConfig CMakeBuildConfiguration::cmakeConfiguration() const
{ {
return m_configuration; return removeDuplicates(CMakeConfigurationKitInformation::configuration(target()->kit())
+ m_configuration);
} }
void CMakeBuildConfiguration::setError(const QString &message) void CMakeBuildConfiguration::setError(const QString &message)
@@ -319,11 +327,24 @@ void CMakeBuildConfiguration::setError(const QString &message)
emit errorOccured(m_error); emit errorOccured(m_error);
} }
void CMakeBuildConfiguration::setWarning(const QString &message)
{
if (m_warning == message)
return;
m_warning = message;
emit warningOccured(m_warning);
}
QString CMakeBuildConfiguration::error() const QString CMakeBuildConfiguration::error() const
{ {
return m_error; return m_error;
} }
QString CMakeBuildConfiguration::warning() const
{
return m_warning;
}
ProjectExplorer::NamedWidget *CMakeBuildConfiguration::createConfigWidget() ProjectExplorer::NamedWidget *CMakeBuildConfiguration::createConfigWidget()
{ {
return new CMakeBuildSettingsWidget(this); return new CMakeBuildSettingsWidget(this);
@@ -475,7 +496,6 @@ CMakeBuildInfo *CMakeBuildConfigurationFactory::createBuildInfo(const ProjectExp
auto info = new CMakeBuildInfo(this); auto info = new CMakeBuildInfo(this);
info->kitId = k->id(); info->kitId = k->id();
info->sourceDirectory = sourceDir; info->sourceDirectory = sourceDir;
info->configuration = CMakeConfigurationKitInformation::configuration(k);
CMakeConfigItem buildTypeItem; CMakeConfigItem buildTypeItem;
switch (buildType) { switch (buildType) {

View File

@@ -68,6 +68,7 @@ public:
CMakeConfig cmakeConfiguration() const; CMakeConfig cmakeConfiguration() const;
QString error() const; QString error() const;
QString warning() const;
BuildDirManager *buildDirManager() const; BuildDirManager *buildDirManager() const;
@@ -83,6 +84,7 @@ public:
signals: signals:
void errorOccured(const QString &message); void errorOccured(const QString &message);
void warningOccured(const QString &message);
void parsingStarted(); void parsingStarted();
void dataAvailable(); void dataAvailable();
@@ -97,9 +99,11 @@ private:
void setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items); void setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items);
void setError(const QString &message); void setError(const QString &message);
void setWarning(const QString &message);
CMakeConfig m_configuration; CMakeConfig m_configuration;
QString m_error; QString m_error;
QString m_warning;
mutable QList<CMakeConfigItem> m_completeConfigurationCache; mutable QList<CMakeConfigItem> m_completeConfigurationCache;

View File

@@ -48,6 +48,7 @@
#include <QPushButton> #include <QPushButton>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QSpacerItem> #include <QSpacerItem>
#include <QMenu>
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
@@ -108,6 +109,17 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
boxLayout->addWidget(m_errorMessageLabel); boxLayout->addWidget(m_errorMessageLabel);
mainLayout->addLayout(boxLayout, row, 0, 1, 3, Qt::AlignHCenter); mainLayout->addLayout(boxLayout, row, 0, 1, 3, Qt::AlignHCenter);
++row;
m_warningLabel = new QLabel;
m_warningLabel->setPixmap(Core::Icons::WARNING.pixmap());
m_warningLabel->setVisible(false);
m_warningMessageLabel = new QLabel;
m_warningMessageLabel->setVisible(false);
auto boxLayout2 = new QHBoxLayout;
boxLayout2->addWidget(m_warningLabel);
boxLayout2->addWidget(m_warningMessageLabel);
mainLayout->addLayout(boxLayout2, row, 0, 1, 3, Qt::AlignHCenter);
++row; ++row;
mainLayout->addItem(new QSpacerItem(20, 10), row, 0); mainLayout->addItem(new QSpacerItem(20, 10), row, 0);
@@ -142,6 +154,20 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
mainLayout->addWidget(findWrapper, row, 0, 1, 2); mainLayout->addWidget(findWrapper, row, 0, 1, 2);
auto buttonLayout = new QVBoxLayout; auto buttonLayout = new QVBoxLayout;
m_addButton = new QPushButton(tr("&Add"));
buttonLayout->addWidget(m_addButton);
{
m_addButtonMenu = new QMenu;
m_addButtonMenu->addAction(tr("&Boolean"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::BOOLEAN)));
m_addButtonMenu->addAction(tr("&String"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::STRING)));
m_addButtonMenu->addAction(tr("&Directory"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::DIRECTORY)));
m_addButtonMenu->addAction(tr("&File"))->setData(
QVariant::fromValue(static_cast<int>(ConfigModel::DataItem::FILE)));
m_addButton->setMenu(m_addButtonMenu);
}
m_editButton = new QPushButton(tr("&Edit")); m_editButton = new QPushButton(tr("&Edit"));
buttonLayout->addWidget(m_editButton); buttonLayout->addWidget(m_editButton);
m_resetButton = new QPushButton(tr("&Reset")); m_resetButton = new QPushButton(tr("&Reset"));
@@ -161,6 +187,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
updateAdvancedCheckBox(); updateAdvancedCheckBox();
setError(bc->error()); setError(bc->error());
setWarning(bc->warning());
connect(project, &CMakeProject::parsingStarted, this, [this]() { connect(project, &CMakeProject::parsingStarted, this, [this]() {
updateButtonState(); updateButtonState();
@@ -201,24 +228,49 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_configView->setCurrentIndex(idx); m_configView->setCurrentIndex(idx);
m_configView->edit(idx); m_configView->edit(idx);
}); });
connect(m_addButtonMenu, &QMenu::triggered, this, [this](QAction *action) {
ConfigModel::DataItem::Type type =
static_cast<ConfigModel::DataItem::Type>(action->data().value<int>());
QString value = tr("<UNSET>");
if (type == ConfigModel::DataItem::BOOLEAN)
value = QString::fromLatin1("OFF");
m_configModel->appendConfiguration(tr("<UNSET>"), value, type);
QModelIndex idx;
idx = m_configView->model()->index(
m_configView->model()->rowCount(idx) - 1, 0);
m_configView->setCurrentIndex(idx);
m_configView->edit(idx);
});
connect(bc, &CMakeBuildConfiguration::errorOccured, this, &CMakeBuildSettingsWidget::setError); connect(bc, &CMakeBuildConfiguration::errorOccured, this, &CMakeBuildSettingsWidget::setError);
connect(bc, &CMakeBuildConfiguration::warningOccured, this, &CMakeBuildSettingsWidget::setWarning);
} }
void CMakeBuildSettingsWidget::setError(const QString &message) void CMakeBuildSettingsWidget::setError(const QString &message)
{ {
bool showWarning = !message.isEmpty(); bool showError = !message.isEmpty();
m_errorLabel->setVisible(showWarning); m_errorLabel->setVisible(showError);
m_errorLabel->setToolTip(message); m_errorLabel->setToolTip(message);
m_errorMessageLabel->setVisible(showWarning); m_errorMessageLabel->setVisible(showError);
m_errorMessageLabel->setText(message); m_errorMessageLabel->setText(message);
m_errorMessageLabel->setToolTip(message); m_errorMessageLabel->setToolTip(message);
m_configView->setVisible(!showWarning); m_configView->setVisible(!showError);
m_editButton->setVisible(!showWarning); m_editButton->setVisible(!showError);
m_resetButton->setVisible(!showWarning); m_resetButton->setVisible(!showError);
m_showAdvancedCheckBox->setVisible(!showWarning); m_showAdvancedCheckBox->setVisible(!showError);
m_reconfigureButton->setVisible(!showWarning); m_reconfigureButton->setVisible(!showError);
}
void CMakeBuildSettingsWidget::setWarning(const QString &message)
{
bool showWarning = !message.isEmpty();
m_warningLabel->setVisible(showWarning);
m_warningLabel->setToolTip(message);
m_warningMessageLabel->setVisible(showWarning);
m_warningMessageLabel->setText(message);
m_warningMessageLabel->setToolTip(message);
} }
void CMakeBuildSettingsWidget::updateButtonState() void CMakeBuildSettingsWidget::updateButtonState()

View File

@@ -37,6 +37,7 @@ class QLabel;
class QPushButton; class QPushButton;
class QTreeView; class QTreeView;
class QSortFilterProxyModel; class QSortFilterProxyModel;
class QMenu;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace CMakeProjectManager { namespace CMakeProjectManager {
@@ -54,6 +55,7 @@ public:
CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc); CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc);
void setError(const QString &message); void setError(const QString &message);
void setWarning(const QString &message);
private: private:
void updateButtonState(); void updateButtonState();
@@ -64,13 +66,17 @@ private:
ConfigModel *m_configModel; ConfigModel *m_configModel;
QSortFilterProxyModel *m_configFilterModel; QSortFilterProxyModel *m_configFilterModel;
Utils::ProgressIndicator *m_progressIndicator; Utils::ProgressIndicator *m_progressIndicator;
QPushButton *m_addButton;
QMenu *m_addButtonMenu;
QPushButton *m_editButton; QPushButton *m_editButton;
QPushButton *m_resetButton; QPushButton *m_resetButton;
QCheckBox *m_showAdvancedCheckBox; QCheckBox *m_showAdvancedCheckBox;
QPushButton *m_reconfigureButton; QPushButton *m_reconfigureButton;
QTimer m_showProgressTimer; QTimer m_showProgressTimer;
QLabel *m_errorLabel; QLabel *m_errorLabel;
QLabel *m_warningLabel;
QLabel *m_errorMessageLabel; QLabel *m_errorMessageLabel;
QLabel *m_warningMessageLabel;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -25,6 +25,9 @@
#include "cmakeconfigitem.h" #include "cmakeconfigitem.h"
#include <projectexplorer/kit.h>
#include <utils/macroexpander.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QString> #include <QString>
@@ -60,6 +63,21 @@ QByteArray CMakeConfigItem::valueOf(const QByteArray &key, const QList<CMakeConf
return QByteArray(); return QByteArray();
} }
QString CMakeConfigItem::expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key,
const QList<CMakeConfigItem> &input)
{
for (auto it = input.constBegin(); it != input.constEnd(); ++it) {
if (it->key == key)
return it->expandedValue(k);
}
return QString();
}
QString CMakeConfigItem::expandedValue(const ProjectExplorer::Kit *k) const
{
return k->macroExpander()->expand(QString::fromUtf8(value));
}
std::function<bool (const CMakeConfigItem &a, const CMakeConfigItem &b)> CMakeConfigItem::sortOperator() std::function<bool (const CMakeConfigItem &a, const CMakeConfigItem &b)> CMakeConfigItem::sortOperator()
{ {
return [](const CMakeConfigItem &a, const CMakeConfigItem &b) { return a.key < b.key; }; return [](const CMakeConfigItem &a, const CMakeConfigItem &b) { return a.key < b.key; };

View File

@@ -30,6 +30,8 @@
#include <functional> #include <functional>
namespace ProjectExplorer { class Kit; }
namespace CMakeProjectManager { namespace CMakeProjectManager {
class CMakeConfigItem { class CMakeConfigItem {
@@ -41,9 +43,12 @@ public:
CMakeConfigItem(const QByteArray &k, const QByteArray &v); CMakeConfigItem(const QByteArray &k, const QByteArray &v);
static QByteArray valueOf(const QByteArray &key, const QList<CMakeConfigItem> &input); static QByteArray valueOf(const QByteArray &key, const QList<CMakeConfigItem> &input);
static QString expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key,
const QList<CMakeConfigItem> &input);
bool isNull() const { return key.isEmpty(); } bool isNull() const { return key.isEmpty(); }
QString expandedValue(const ProjectExplorer::Kit *k) const;
static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator(); static std::function<bool(const CMakeConfigItem &a, const CMakeConfigItem &b)> sortOperator();
static CMakeConfigItem fromString(const QString &s); static CMakeConfigItem fromString(const QString &s);
QString toString() const; QString toString() const;

View File

@@ -341,9 +341,11 @@ void CMakeProject::runCMake()
return; return;
BuildDirManager *bdm = bc->buildDirManager(); BuildDirManager *bdm = bc->buildDirManager();
if (bdm && !bdm->isParsing()) if (bdm && !bdm->isParsing()) {
bdm->checkConfiguration();
bdm->forceReparse(); bdm->forceReparse();
} }
}
QList<CMakeBuildTarget> CMakeProject::buildTargets() const QList<CMakeBuildTarget> CMakeProject::buildTargets() const
{ {

View File

@@ -35,7 +35,8 @@ namespace CMakeProjectManager {
static bool isTrue(const QString &value) static bool isTrue(const QString &value)
{ {
const QString lower = value.toLower(); const QString lower = value.toLower();
return lower == QStringLiteral("true") || lower == QStringLiteral("on") || lower == QStringLiteral("1"); return lower == QStringLiteral("true") || lower == QStringLiteral("on")
|| lower == QStringLiteral("1") || lower == QStringLiteral("yes");
} }
ConfigModel::ConfigModel(QObject *parent) : QAbstractTableModel(parent) ConfigModel::ConfigModel(QObject *parent) : QAbstractTableModel(parent)
@@ -71,7 +72,10 @@ Qt::ItemFlags ConfigModel::flags(const QModelIndex &index) const
else else
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable; return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
} else { } else {
return Qt::ItemIsEnabled | Qt::ItemIsSelectable; Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (item.isUserNew)
return flags |= Qt::ItemIsEditable;
return flags;
} }
} }
@@ -163,7 +167,7 @@ bool ConfigModel::setData(const QModelIndex &index, const QVariant &value, int r
InternalDataItem &item = itemAtRow(index.row()); InternalDataItem &item = itemAtRow(index.row());
switch (index.column()) { switch (index.column()) {
case 0: case 0:
if (!item.key.isEmpty()) if (!item.key.isEmpty() && !item.isUserNew)
return false; return false;
item.key = newValue; item.key = newValue;
item.isUserNew = true; item.isUserNew = true;
@@ -202,6 +206,25 @@ QVariant ConfigModel::headerData(int section, Qt::Orientation orientation, int r
} }
} }
void ConfigModel::appendConfiguration(const QString &key,
const QString &value,
const ConfigModel::DataItem::Type type,
const QString &description)
{
DataItem item;
item.key = key;
item.type = type;
item.value = value;
item.description = description;
InternalDataItem internalItem(item);
internalItem.isUserNew = true;
beginResetModel();
m_configuration.append(internalItem);
endResetModel();
}
void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config) void ConfigModel::setConfiguration(const QList<ConfigModel::DataItem> &config)
{ {
QList<DataItem> tmp = config; QList<DataItem> tmp = config;

View File

@@ -55,6 +55,10 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
void appendConfiguration(const QString &key,
const QString &value = QString(),
const DataItem::Type type = DataItem::UNKNOWN,
const QString &description = QString());
void setConfiguration(const QList<DataItem> &config); void setConfiguration(const QList<DataItem> &config);
void flush(); void flush();
void resetAllChanges(); void resetAllChanges();

View File

@@ -1221,7 +1221,11 @@ void DebuggerEngine::notifyDebuggerProcessFinished(int exitCode,
notifyEngineSpontaneousShutdown(); notifyEngineSpontaneousShutdown();
break; break;
default: { default: {
notifyEngineIll(); // Initiate shutdown sequence // Initiate shutdown sequence
if (isMasterEngine())
notifyEngineIll();
else
masterEngine()->notifyInferiorIll();
const QString msg = exitStatus == QProcess::CrashExit ? const QString msg = exitStatus == QProcess::CrashExit ?
tr("The %1 process terminated.") : tr("The %1 process terminated.") :
tr("The %2 process terminated unexpectedly (exit code %1).").arg(exitCode); tr("The %2 process terminated unexpectedly (exit code %1).").arg(exitCode);

View File

@@ -1129,9 +1129,16 @@ void QmlEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages
} }
} else if (d->unpausedEvaluate) { } else if (d->unpausedEvaluate) {
d->evaluate(command, CB(d->handleExecuteDebuggerCommand)); d->evaluate(command, CB(d->handleExecuteDebuggerCommand));
} else {
QModelIndex currentIndex = inspectorView()->currentIndex();
quint32 queryId = d->inspectorAgent.queryExpressionResult(
watchHandler()->watchItem(currentIndex)->id, command);
if (queryId) {
d->queryIds.append(queryId);
} else { } else {
d->engine->showMessage(_("The application has to be stopped in a breakpoint in order to" d->engine->showMessage(_("The application has to be stopped in a breakpoint in order to"
"evaluate expressions").arg(command), ConsoleOutput); " evaluate expressions"), ConsoleOutput);
}
} }
} }

View File

@@ -261,13 +261,6 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
data.insert(QLatin1String(CPP_PLATFORMLINKERFLAGS), gcc->platformLinkerFlags()); data.insert(QLatin1String(CPP_PLATFORMLINKERFLAGS), gcc->platformLinkerFlags());
} }
// TODO: Remove this once compiler version properties are set for MSVC
if (targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2013Flavor
|| targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2015Flavor) {
const QLatin1String flags("/FS");
data.insert(QLatin1String(CPP_PLATFORMCFLAGS), flags);
data.insert(QLatin1String(CPP_PLATFORMCXXFLAGS), flags);
}
return data; return data;
} }

View File

@@ -114,8 +114,7 @@ bool QbsBuildStep::init(QList<const BuildStep *> &earlierSteps)
connect(m_parser, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)), connect(m_parser, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)),
this, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat))); this, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)));
connect(m_parser, SIGNAL(addTask(ProjectExplorer::Task)), connect(m_parser, &ProjectExplorer::IOutputParser::addTask, this, &QbsBuildStep::addTask);
this, SIGNAL(addTask(ProjectExplorer::Task)));
return true; return true;
} }

View File

@@ -41,8 +41,6 @@ const char CPP_COMPILERVERSIONMAJOR[] = "cpp.compilerVersionMajor";
const char CPP_COMPILERVERSIONMINOR[] = "cpp.compilerVersionMinor"; const char CPP_COMPILERVERSIONMINOR[] = "cpp.compilerVersionMinor";
const char CPP_COMPILERVERSIONPATCH[] = "cpp.compilerVersionPatch"; const char CPP_COMPILERVERSIONPATCH[] = "cpp.compilerVersionPatch";
const char CPP_LINKERNAME[] = "cpp.linkerName"; const char CPP_LINKERNAME[] = "cpp.linkerName";
const char CPP_PLATFORMCFLAGS[] = "cpp.platformCFlags";
const char CPP_PLATFORMCXXFLAGS[] = "cpp.platformCxxFlags";
const char CPP_PLATFORMCOMMONCOMPILERFLAGS[] = "cpp.platformCommonCompilerFlags"; const char CPP_PLATFORMCOMMONCOMPILERFLAGS[] = "cpp.platformCommonCompilerFlags";
const char CPP_PLATFORMLINKERFLAGS[] = "cpp.platformLinkerFlags"; const char CPP_PLATFORMLINKERFLAGS[] = "cpp.platformLinkerFlags";
const char CPP_PLATFORMPATH[] = "cpp.platformPath"; const char CPP_PLATFORMPATH[] = "cpp.platformPath";

View File

@@ -149,197 +149,273 @@ typedef int (MDEV_API *AMDeviceSecureInstallApplicationPtr)(int, AMDeviceRef, CF
static QString mobileDeviceErrorString(am_res_t code) static QString mobileDeviceErrorString(am_res_t code)
{ {
static const char *errorStrings[] = { static const char *errorStrings[] = {
"kAMDSuccess", // 0x0 "kAMDSuccess", // 0x00000000
"kAMDUndefinedError", // 0xe8000001 "kAMDUndefinedError", // 0xe8000001
"kAMDBadHeaderError", "kAMDBadHeaderError", // 0xe8000002
"kAMDNoResourcesError", "kAMDNoResourcesError", // 0xe8000003
"kAMDReadError", "kAMDReadError", // 0xe8000004
"kAMDWriteError", "kAMDWriteError", // 0xe8000005
"kAMDUnknownPacketError", "kAMDUnknownPacketError", // 0xe8000006
"kAMDInvalidArgumentError", "kAMDInvalidArgumentError", // 0xe8000007
"kAMDNotFoundError", "kAMDNotFoundError", // 0xe8000008
"kAMDIsDirectoryError", "kAMDIsDirectoryError", // 0xe8000009
"kAMDPermissionError", "kAMDPermissionError", // 0xe800000a
"kAMDNotConnectedError", "kAMDNotConnectedError", // 0xe800000b
"kAMDTimeOutError", "kAMDTimeOutError", // 0xe800000c
"kAMDOverrunError", "kAMDOverrunError", // 0xe800000d
"kAMDEOFError", "kAMDEOFError", // 0xe800000e
"kAMDUnsupportedError", "kAMDUnsupportedError", // 0xe800000f
"kAMDFileExistsError", "kAMDFileExistsError", // 0xe8000010
"kAMDBusyError", "kAMDBusyError", // 0xe8000011
"kAMDCryptoError", "kAMDCryptoError", // 0xe8000012
"kAMDInvalidResponseError", "kAMDInvalidResponseError", // 0xe8000013
"kAMDMissingKeyError", "kAMDMissingKeyError", // 0xe8000014
"kAMDMissingValueError", "kAMDMissingValueError", // 0xe8000015
"kAMDGetProhibitedError", "kAMDGetProhibitedError", // 0xe8000016
"kAMDSetProhibitedError", "kAMDSetProhibitedError", // 0xe8000017
"kAMDRemoveProhibitedError", "kAMDRemoveProhibitedError", // 0xe8000018
"kAMDImmutableValueError", "kAMDImmutableValueError", // 0xe8000019
"kAMDPasswordProtectedError", "kAMDPasswordProtectedError", // 0xe800001a
"kAMDMissingHostIDError", "kAMDMissingHostIDError", // 0xe800001b
"kAMDInvalidHostIDError", "kAMDInvalidHostIDError", // 0xe800001c
"kAMDSessionActiveError", "kAMDSessionActiveError", // 0xe800001d
"kAMDSessionInactiveError", "kAMDSessionInactiveError", // 0xe800001e
"kAMDMissingSessionIDError", "kAMDMissingSessionIDError", // 0xe800001f
"kAMDInvalidSessionIDError", "kAMDInvalidSessionIDError", // 0xe8000020
"kAMDMissingServiceError", "kAMDMissingServiceError", // 0xe8000021
"kAMDInvalidServiceError", "kAMDInvalidServiceError", // 0xe8000022
"kAMDInvalidCheckinError", "kAMDInvalidCheckinError", // 0xe8000023
"kAMDCheckinTimeoutError", "kAMDCheckinTimeoutError", // 0xe8000024
"kAMDMissingPairRecordError", "kAMDMissingPairRecordError", // 0xe8000025
"kAMDInvalidActivationRecordError", "kAMDInvalidActivationRecordError", // 0xe8000026
"kAMDMissingActivationRecordError", "kAMDMissingActivationRecordError", // 0xe8000027
"kAMDWrongDroidError", "kAMDWrongDroidError", // 0xe8000028
"kAMDSUVerificationError", "kAMDSUVerificationError", // 0xe8000029
"kAMDSUPatchError", "kAMDSUPatchError", // 0xe800002a
"kAMDSUFirmwareError", "kAMDSUFirmwareError", // 0xe800002b
"kAMDProvisioningProfileNotValid", "kAMDProvisioningProfileNotValid", // 0xe800002c
"kAMDSendMessageError", "kAMDSendMessageError", // 0xe800002d
"kAMDReceiveMessageError", "kAMDReceiveMessageError", // 0xe800002e
"kAMDMissingOptionsError", "kAMDMissingOptionsError", // 0xe800002f
"kAMDMissingImageTypeError", "kAMDMissingImageTypeError", // 0xe8000030
"kAMDDigestFailedError", "kAMDDigestFailedError", // 0xe8000031
"kAMDStartServiceError", "kAMDStartServiceError", // 0xe8000032
"kAMDInvalidDiskImageError", "kAMDInvalidDiskImageError", // 0xe8000033
"kAMDMissingDigestError", "kAMDMissingDigestError", // 0xe8000034
"kAMDMuxError", "kAMDMuxError", // 0xe8000035
"kAMDApplicationAlreadyInstalledError", "kAMDApplicationAlreadyInstalledError", // 0xe8000036
"kAMDApplicationMoveFailedError", "kAMDApplicationMoveFailedError", // 0xe8000037
"kAMDApplicationSINFCaptureFailedError", "kAMDApplicationSINFCaptureFailedError", // 0xe8000038
"kAMDApplicationSandboxFailedError", "kAMDApplicationSandboxFailedError", // 0xe8000039
"kAMDApplicationVerificationFailedError", "kAMDApplicationVerificationFailedError", // 0xe800003a
"kAMDArchiveDestructionFailedError", "kAMDArchiveDestructionFailedError", // 0xe800003b
"kAMDBundleVerificationFailedError", "kAMDBundleVerificationFailedError", // 0xe800003c
"kAMDCarrierBundleCopyFailedError", "kAMDCarrierBundleCopyFailedError", // 0xe800003d
"kAMDCarrierBundleDirectoryCreationFailedError", "kAMDCarrierBundleDirectoryCreationFailedError", // 0xe800003e
"kAMDCarrierBundleMissingSupportedSIMsError", "kAMDCarrierBundleMissingSupportedSIMsError", // 0xe800003f
"kAMDCommCenterNotificationFailedError", "kAMDCommCenterNotificationFailedError", // 0xe8000040
"kAMDContainerCreationFailedError", "kAMDContainerCreationFailedError", // 0xe8000041
"kAMDContainerP0wnFailedError", "kAMDContainerP0wnFailedError", // 0xe8000042
"kAMDContainerRemovalFailedError", "kAMDContainerRemovalFailedError", // 0xe8000043
"kAMDEmbeddedProfileInstallFailedError", "kAMDEmbeddedProfileInstallFailedError", // 0xe8000044
"kAMDErrorError", "kAMDErrorError", // 0xe8000045
"kAMDExecutableTwiddleFailedError", "kAMDExecutableTwiddleFailedError", // 0xe8000046
"kAMDExistenceCheckFailedError", "kAMDExistenceCheckFailedError", // 0xe8000047
"kAMDInstallMapUpdateFailedError", "kAMDInstallMapUpdateFailedError", // 0xe8000048
"kAMDManifestCaptureFailedError", "kAMDManifestCaptureFailedError", // 0xe8000049
"kAMDMapGenerationFailedError", "kAMDMapGenerationFailedError", // 0xe800004a
"kAMDMissingBundleExecutableError", "kAMDMissingBundleExecutableError", // 0xe800004b
"kAMDMissingBundleIdentifierError", "kAMDMissingBundleIdentifierError", // 0xe800004c
"kAMDMissingBundlePathError", "kAMDMissingBundlePathError", // 0xe800004d
"kAMDMissingContainerError", "kAMDMissingContainerError", // 0xe800004e
"kAMDNotificationFailedError", "kAMDNotificationFailedError", // 0xe800004f
"kAMDPackageExtractionFailedError", "kAMDPackageExtractionFailedError", // 0xe8000050
"kAMDPackageInspectionFailedError", "kAMDPackageInspectionFailedError", // 0xe8000051
"kAMDPackageMoveFailedError", "kAMDPackageMoveFailedError", // 0xe8000052
"kAMDPathConversionFailedError", "kAMDPathConversionFailedError", // 0xe8000053
"kAMDRestoreContainerFailedError", "kAMDRestoreContainerFailedError", // 0xe8000054
"kAMDSeatbeltProfileRemovalFailedError", "kAMDSeatbeltProfileRemovalFailedError", // 0xe8000055
"kAMDStageCreationFailedError", "kAMDStageCreationFailedError", // 0xe8000056
"kAMDSymlinkFailedError", "kAMDSymlinkFailedError", // 0xe8000057
"kAMDiTunesArtworkCaptureFailedError", "kAMDiTunesArtworkCaptureFailedError", // 0xe8000058
"kAMDiTunesMetadataCaptureFailedError", "kAMDiTunesMetadataCaptureFailedError", // 0xe8000059
"kAMDAlreadyArchivedError", "kAMDAlreadyArchivedError", // 0xe800005a
"kAMDServiceLimitError", "kAMDServiceLimitError", // 0xe800005b
"kAMDInvalidPairRecordError", "kAMDInvalidPairRecordError", // 0xe800005c
"kAMDServiceProhibitedError", "kAMDServiceProhibitedError", // 0xe800005d
"kAMDCheckinSetupFailedError", "kAMDCheckinSetupFailedError", // 0xe800005e
"kAMDCheckinConnectionFailedError", "kAMDCheckinConnectionFailedError", // 0xe800005f
"kAMDCheckinReceiveFailedError", "kAMDCheckinReceiveFailedError", // 0xe8000060
"kAMDCheckinResponseFailedError", "kAMDCheckinResponseFailedError", // 0xe8000061
"kAMDCheckinSendFailedError", "kAMDCheckinSendFailedError", // 0xe8000062
"kAMDMuxCreateListenerError", "kAMDMuxCreateListenerError", // 0xe8000063
"kAMDMuxGetListenerError", "kAMDMuxGetListenerError", // 0xe8000064
"kAMDMuxConnectError", "kAMDMuxConnectError", // 0xe8000065
"kAMDUnknownCommandError", "kAMDUnknownCommandError", // 0xe8000066
"kAMDAPIInternalError", "kAMDAPIInternalError", // 0xe8000067
"kAMDSavePairRecordFailedError", "kAMDSavePairRecordFailedError", // 0xe8000068
"kAMDCheckinOutOfMemoryError", "kAMDCheckinOutOfMemoryError", // 0xe8000069
"kAMDDeviceTooNewError", "kAMDDeviceTooNewError", // 0xe800006a
"kAMDDeviceRefNoGood", "kAMDDeviceRefNoGood", // 0xe800006b
"kAMDCannotTranslateError", "kAMDCannotTranslateError", // 0xe800006c
"kAMDMobileImageMounterMissingImageSignature", "kAMDMobileImageMounterMissingImageSignature", // 0xe800006d
"kAMDMobileImageMounterResponseCreationFailed", "kAMDMobileImageMounterResponseCreationFailed", // 0xe800006e
"kAMDMobileImageMounterMissingImageType", "kAMDMobileImageMounterMissingImageType", // 0xe800006f
"kAMDMobileImageMounterMissingImagePath", "kAMDMobileImageMounterMissingImagePath", // 0xe8000070
"kAMDMobileImageMounterImageMapLoadFailed", "kAMDMobileImageMounterImageMapLoadFailed", // 0xe8000071
"kAMDMobileImageMounterAlreadyMounted", "kAMDMobileImageMounterAlreadyMounted", // 0xe8000072
"kAMDMobileImageMounterImageMoveFailed", "kAMDMobileImageMounterImageMoveFailed", // 0xe8000073
"kAMDMobileImageMounterMountPathMissing", "kAMDMobileImageMounterMountPathMissing", // 0xe8000074
"kAMDMobileImageMounterMountPathNotEmpty", "kAMDMobileImageMounterMountPathNotEmpty", // 0xe8000075
"kAMDMobileImageMounterImageMountFailed", "kAMDMobileImageMounterImageMountFailed", // 0xe8000076
"kAMDMobileImageMounterTrustCacheLoadFailed", "kAMDMobileImageMounterTrustCacheLoadFailed", // 0xe8000077
"kAMDMobileImageMounterDigestFailed", "kAMDMobileImageMounterDigestFailed", // 0xe8000078
"kAMDMobileImageMounterDigestCreationFailed", "kAMDMobileImageMounterDigestCreationFailed", // 0xe8000079
"kAMDMobileImageMounterImageVerificationFailed", "kAMDMobileImageMounterImageVerificationFailed", // 0xe800007a
"kAMDMobileImageMounterImageInfoCreationFailed", "kAMDMobileImageMounterImageInfoCreationFailed", // 0xe800007b
"kAMDMobileImageMounterImageMapStoreFailed", "kAMDMobileImageMounterImageMapStoreFailed", // 0xe800007c
"kAMDBonjourSetupError", "kAMDBonjourSetupError", // 0xe800007d
"kAMDDeviceOSVersionTooLow", "kAMDDeviceOSVersionTooLow", // 0xe800007e
"kAMDNoWifiSyncSupportError", "kAMDNoWifiSyncSupportError", // 0xe800007f
"kAMDDeviceFamilyNotSupported", "kAMDDeviceFamilyNotSupported", // 0xe8000080
"kAMDEscrowLockedError", "kAMDEscrowLockedError", // 0xe8000081
"kAMDPairingProhibitedError", "kAMDPairingProhibitedError", // 0xe8000082
"kAMDProhibitedBySupervision", "kAMDProhibitedBySupervision", // 0xe8000083
"kAMDDeviceDisconnectedError", "kAMDDeviceDisconnectedError", // 0xe8000084
"kAMDTooBigError", "kAMDTooBigError", // 0xe8000085
"kAMDPackagePatchFailedError", "kAMDPackagePatchFailedError", // 0xe8000086
"kAMDIncorrectArchitectureError", "kAMDIncorrectArchitectureError", // 0xe8000087
"kAMDPluginCopyFailedError", "kAMDPluginCopyFailedError", // 0xe8000088
"kAMDBreadcrumbFailedError", "kAMDBreadcrumbFailedError", // 0xe8000089
"kAMDBreadcrumbUnlockError", "kAMDBreadcrumbUnlockError", // 0xe800008a
"kAMDGeoJSONCaptureFailedError", "kAMDGeoJSONCaptureFailedError", // 0xe800008b
"kAMDNewsstandArtworkCaptureFailedError", "kAMDNewsstandArtworkCaptureFailedError", // 0xe800008c
"kAMDMissingCommandError", "kAMDMissingCommandError", // 0xe800008d
"kAMDNotEntitledError", "kAMDNotEntitledError", // 0xe800008e
"kAMDMissingPackagePathError", "kAMDMissingPackagePathError", // 0xe800008f
"kAMDMissingContainerPathError", "kAMDMissingContainerPathError", // 0xe8000090
"kAMDMissingApplicationIdentifierError", "kAMDMissingApplicationIdentifierError", // 0xe8000091
"kAMDMissingAttributeValueError", "kAMDMissingAttributeValueError", // 0xe8000092
"kAMDLookupFailedError", "kAMDLookupFailedError", // 0xe8000093
"kAMDDictCreationFailedError", "kAMDDictCreationFailedError", // 0xe8000094
"kAMDUserDeniedPairingError", "kAMDUserDeniedPairingError", // 0xe8000095
"kAMDPairingDialogResponsePendingError", "kAMDPairingDialogResponsePendingError", // 0xe8000096
"kAMDInstallProhibitedError", "kAMDInstallProhibitedError", // 0xe8000097
"kAMDUninstallProhibitedError", "kAMDUninstallProhibitedError", // 0xe8000098
"kAMDFMiPProtectedError", "kAMDFMiPProtectedError", // 0xe8000099
"kAMDMCProtected", "kAMDMCProtected", // 0xe800009a
"kAMDMCChallengeRequired", "kAMDMCChallengeRequired", // 0xe800009b
"kAMDMissingBundleVersionError" // 0xe800009c "kAMDMissingBundleVersionError", // 0xe800009c
"kAMDAppBlacklistedError", // 0xe800009d
"This app contains an app extension with an illegal bundle identifier. App extension bundle identifiers must have a prefix consisting of their containing application's bundle identifier followed by a '.'.", // 0xe800009e
"If an app extension defines the XPCService key in its Info.plist, it must have a dictionary value.", // 0xe800009f
"App extensions must define the NSExtension key with a dictionary value in their Info.plist.", // 0xe80000a0
"If an app extension defines the CFBundlePackageType key in its Info.plist, it must have the value \"XPC!\".", // 0xe80000a1
"App extensions must define either NSExtensionMainStoryboard or NSExtensionPrincipalClass keys in the NSExtension dictionary in their Info.plist.", // 0xe80000a2
"If an app extension defines the NSExtensionContextClass key in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters.", // 0xe80000a3
"If an app extension defines the NSExtensionContextHostClass key in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters.", // 0xe80000a4
"If an app extension defines the NSExtensionViewControllerHostClass key in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters.", // 0xe80000a5
"This app contains an app extension that does not define the NSExtensionPointIdentifier key in its Info.plist. This key must have a reverse-DNS format string value.", // 0xe80000a6
"This app contains an app extension that does not define the NSExtensionPointIdentifier key in its Info.plist with a valid reverse-DNS format string value.", // 0xe80000a7
"If an app extension defines the NSExtensionAttributes key in the NSExtension dictionary in its Info.plist, it must have a dictionary value.", // 0xe80000a8
"If an app extension defines the NSExtensionPointName key in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters.", // 0xe80000a9
"If an app extension defines the NSExtensionPointVersion key in the NSExtensionAttributes dictionary in the NSExtension dictionary in its Info.plist, it must have a string value containing one or more characters.", // 0xe80000aa
"This app or a bundle it contains does not define the CFBundleName key in its Info.plist with a string value containing one or more characters.", // 0xe80000ab
"This app or a bundle it contains does not define the CFBundleDisplayName key in its Info.plist with a string value containing one or more characters.", // 0xe80000ac
"This app or a bundle it contains defines the CFBundleShortVersionStringKey key in its Info.plist with a non-string value or a zero-length string value.", // 0xe80000ad
"This app or a bundle it contains defines the RunLoopType key in the XPCService dictionary in its Info.plist with a non-string value or a zero-length string value.", // 0xe80000ae
"This app or a bundle it contains defines the ServiceType key in the XPCService dictionary in its Info.plist with a non-string value or a zero-length string value.", // 0xe80000af
"This application or a bundle it contains has the same bundle identifier as this application or another bundle that it contains. Bundle identifiers must be unique.", // 0xe80000b0
"This app contains an app extension that specifies an extension point identifier that is not supported on this version of iOS for the value of the NSExtensionPointIdentifier key in its Info.plist.", // 0xe80000b1
"This app contains multiple app extensions that are file providers. Apps are only allowed to contain at most a single file provider app extension.", // 0xe80000b2
"kMobileHouseArrestMissingCommand", // 0xe80000b3
"kMobileHouseArrestUnknownCommand", // 0xe80000b4
"kMobileHouseArrestMissingIdentifier", // 0xe80000b5
"kMobileHouseArrestDictionaryFailed", // 0xe80000b6
"kMobileHouseArrestInstallationLookupFailed", // 0xe80000b7
"kMobileHouseArrestApplicationLookupFailed", // 0xe80000b8
"kMobileHouseArrestMissingContainer", // 0xe80000b9
0, // 0xe80000ba
"kMobileHouseArrestPathConversionFailed", // 0xe80000bb
"kMobileHouseArrestPathMissing", // 0xe80000bc
"kMobileHouseArrestInvalidPath", // 0xe80000bd
"kAMDMismatchedApplicationIdentifierEntitlementError", // 0xe80000be
"kAMDInvalidSymlinkError", // 0xe80000bf
"kAMDNoSpaceError", // 0xe80000c0
"The WatchKit app extension must have, in its Info.plist's NSExtension dictionary's NSExtensionAttributes dictionary, the key WKAppBundleIdentifier with a value equal to the associated WatchKit app's bundle identifier.", // 0xe80000c1
"This app is not a valid AppleTV Stub App", // 0xe80000c2
"kAMDBundleiTunesMetadataVersionMismatchError", // 0xe80000c3
"kAMDInvalidiTunesMetadataPlistError", // 0xe80000c4
"kAMDMismatchedBundleIDSigningIdentifierError", // 0xe80000c5
"This app contains multiple WatchKit app extensions. Only a single WatchKit extension is allowed.", // 0xe80000c6
"A WatchKit app within this app is not a valid bundle.", // 0xe80000c7
"kAMDDeviceNotSupportedByThinningError", // 0xe80000c8
"The UISupportedDevices key in this app's Info.plist does not specify a valid set of supported devices.", // 0xe80000c9
"This app contains an app extension with an illegal bundle identifier. App extension bundle identifiers must have a prefix consisting of their containing application's bundle identifier followed by a '.', with no further '.' characters after the prefix.", // 0xe80000ca
"kAMDAppexBundleIDConflictWithOtherIdentifierError", // 0xe80000cb
"kAMDBundleIDConflictWithOtherIdentifierError", // 0xe80000cc
"This app contains multiple WatchKit 1.0 apps. Only a single WatchKit 1.0 app is allowed.", // 0xe80000cd
"This app contains multiple WatchKit 2.0 apps. Only a single WatchKit 2.0 app is allowed.", // 0xe80000ce
"The WatchKit app has an invalid stub executable.", // 0xe80000cf
"The WatchKit app has multiple app extensions. Only a single WatchKit extension is allowed in a WatchKit app, and only if this is a WatchKit 2.0 app.", // 0xe80000d0
"The WatchKit 2.0 app contains non-WatchKit app extensions. Only WatchKit app extensions are allowed in WatchKit apps.", // 0xe80000d1
"The WatchKit app has one or more embedded frameworks. Frameworks are only allowed in WatchKit app extensions in WatchKit 2.0 apps.", // 0xe80000d2
"This app contains a WatchKit 1.0 app with app extensions. This is not allowed.", // 0xe80000d3
"This app contains a WatchKit 2.0 app without an app extension. WatchKit 2.0 apps must contain a WatchKit app extension.", // 0xe80000d4
"The WatchKit app's Info.plist must have a WKCompanionAppBundleIdentifier key set to the bundle identifier of the companion app.", // 0xe80000d5
"The WatchKit app's Info.plist contains a non-string key.", // 0xe80000d6
"The WatchKit app's Info.plist contains a key that is not in the whitelist of allowed keys for a WatchKit app.", // 0xe80000d7
"The WatchKit 1.0 and a WatchKit 2.0 apps within this app must have have the same bundle identifier.", // 0xe80000d8
"This app contains a WatchKit app with an invalid bundle identifier. The bundle identifier of a WatchKit app must have a prefix consisting of the companion app's bundle identifier, followed by a '.'.", // 0xe80000d9
"This app contains a WatchKit app where the UIDeviceFamily key in its Info.plist does not specify the value 4 to indicate that it's compatible with the Apple Watch device type.", // 0xe80000da
"The device is out of storage for apps. Please remove some apps from the device and try again.", // 0xe80000db
}; };
static const size_t errorStringMask = 0xe8000000;
static const size_t errorStringLast = ((sizeof(errorStrings) / sizeof(char *)) - 1) | errorStringMask;
static const char *errorStrings2[] = {
0,
"An unknown error has occurred.", // 0xe8008001
"Attempted to modify an immutable provisioning profile.", // 0xe8008002
"This provisioning profile is malformed.", // 0xe8008003
"This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature).", // 0xe8008004
"This provisioning profile is malformed.", // 0xe8008005
"This provisioning profile is malformed.", // 0xe8008006
"This provisioning profile is malformed.", // 0xe8008007
"This provisioning profile is malformed.", // 0xe8008008
"The signature was not valid.", // 0xe8008009
"Unable to allocate memory.", // 0xe800800a
"A file operation failed.", // 0xe800800b
"There was an error communicating with your device.", // 0xe800800c
"There was an error communicating with your device.", // 0xe800800d
"This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature).", // 0xe800800e
"The application's signature is valid but it does not match the expected hash.", // 0xe800800f
"This provisioning profile is unsupported.", // 0xe8008010
"This provisioning profile has expired.", // 0xe8008011
"This provisioning profile cannot be installed on this device.", // 0xe8008012
"This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature).", // 0xe8008013
"The executable contains an invalid signature.", // 0xe8008014
"A valid provisioning profile for this executable was not found.", // 0xe8008015
"The executable was signed with invalid entitlements.", // 0xe8008016
"A signed resource has been added, modified, or deleted.", // 0xe8008017
"The identity used to sign the executable is no longer valid.", // 0xe8008018
"The application does not have a valid signature.", // 0xe8008019
"This provisioning profile does not have a valid signature (or it has a valid, but untrusted signature).", // 0xe800801a
"There was an error communicating with your device.", // 0xe800801b
"No code signature found.", // 0xe800801c
"Rejected by policy.", // 0xe800801d
"The requested profile does not exist (it may have been removed).", // 0xe800801e
};
static const size_t errorString2Mask = 0xe8008000;
static const size_t errorString2Last = ((sizeof(errorStrings2) / sizeof(char *)) - 1) | errorString2Mask;
CFStringRef key = NULL; CFStringRef key = NULL;
static const size_t errorStringLast = ((sizeof(errorStrings) / sizeof(char *)) - 1) | 0xe8000000; if (code <= errorStringLast && code != 0xe80000ba)
if (code <= errorStringLast) { key = QString::fromLatin1(errorStrings[code & ~errorStringMask]).toCFString();
// Mask off some bits to get an index into the known error names array else if (code > errorString2Mask && code <= errorString2Last)
key = QString::fromLatin1(errorStrings[code & ~0xe8000000]).toCFString(); key = QString::fromLatin1(errorStrings2[code & ~errorString2Mask]).toCFString();
} else { else
// Some errors don't have constant names; check a few other known error codes
switch (code) {
case 0xe8008015:
key = CFSTR("A valid provisioning profile for this executable was not found.");
break;
case 0xe8008016:
key = CFSTR("The executable was signed with invalid entitlements.");
break;
case 0xe8008017:
key = CFSTR("A signed resource has been added, modified, or deleted.");
break;
case 0xe8008018:
key = CFSTR("The identity used to sign the executable is no longer valid.");
break;
case 0xe8008019:
key = CFSTR("The application does not have a valid signature.");
break;
case 0xe800801c:
key = CFSTR("The signature was not valid.");
break;
default:
return QString(); return QString();
}
CFRetain(key);
}
CFURLRef url = QUrl::fromLocalFile( CFURLRef url = QUrl::fromLocalFile(
QStringLiteral("/System/Library/PrivateFrameworks/MobileDevice.framework")).toCFURL(); QStringLiteral("/System/Library/PrivateFrameworks/MobileDevice.framework")).toCFURL();

View File

@@ -5989,6 +5989,18 @@ void tst_Dumpers::dumper_data()
"b.append(a);\n" "b.append(a);\n"
"b.append(QJsonValue(2));\n" "b.append(QJsonValue(2));\n"
"\n" "\n"
"QJsonArray c;\n"
"for (unsigned int i = 0; i < 32; ++i) {\n"
" c.append(QJsonValue(qint64(1u << i) - 1));\n"
" c.append(QJsonValue(qint64(1u << i)));\n"
" c.append(QJsonValue(qint64(1u << i) + 1));\n"
"}\n"
"for (unsigned int i = 0; i < 32; ++i) {\n"
" c.append(QJsonValue(-qint64(1u << i) + 1));\n"
" c.append(QJsonValue(-qint64(1u << i)));\n"
" c.append(QJsonValue(-qint64(1u << i) - 1));\n"
"}\n"
"\n"
"unused(&ob,&b,&a);\n") "unused(&ob,&b,&a);\n")
+ Cxx11Profile() + Cxx11Profile()
+ Check("a", "<6 items>", "@QJsonArray") + Check("a", "<6 items>", "@QJsonArray")
@@ -6013,6 +6025,17 @@ void tst_Dumpers::dumper_data()
+ Check("b.1.4", "[4]", "true", "QJsonValue (Bool)") + Check("b.1.4", "[4]", "true", "QJsonValue (Bool)")
+ Check("b.1.5", "[5]", "<5 items>", "QJsonValue (Object)") + Check("b.1.5", "[5]", "<5 items>", "QJsonValue (Object)")
+ Check("b.2", "[2]", "2", "QJsonValue (Number)") + Check("b.2", "[2]", "2", "QJsonValue (Number)")
+ Check("c", "c", "<192 items>", "@QJsonArray")
+ Check("c.0", "[0]", "0.0", "QJsonValue (Number)")
+ Check("c.1", "[1]", "1", "QJsonValue (Number)")
+ Check("c.78", "[78]", "67108863", "QJsonValue (Number)")
+ Check("c.79", "[79]", "67108864.0", "QJsonValue (Number)")
+ Check("c.94", "[94]", "2147483648.0", "QJsonValue (Number)")
+ Check("c.95", "[95]", "2147483649.0", "QJsonValue (Number)")
+ Check("c.96", "[96]", "0.0", "QJsonValue (Number)")
+ Check("c.97", "[97]", "-1", "QJsonValue (Number)")
+ Check("c.174", "[174]", "-67108863", "QJsonValue (Number)")
+ Check("c.175", "[175]", "-67108864.0", "QJsonValue (Number)")
+ Check("ob", "ob", "<5 items>", "@QJsonObject") + Check("ob", "ob", "<5 items>", "@QJsonObject")
+ Check("ob.0", "\"a\"", "1", "QJsonValue (Number)") + Check("ob.0", "\"a\"", "1", "QJsonValue (Number)")
+ Check("ob.1", "\"bb\"", "2", "QJsonValue (Number)") + Check("ob.1", "\"bb\"", "2", "QJsonValue (Number)")

View File

@@ -0,0 +1,6 @@
pragma Singleton
import QtQuick 2.0
Item {
}

View File

@@ -185,6 +185,9 @@ void dummyStatement(...) {}
#include <QXmlAttributes> #include <QXmlAttributes>
#include <QHostAddress> #include <QHostAddress>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <array> #include <array>
@@ -6014,6 +6017,41 @@ namespace qscript {
} // namespace script } // namespace script
namespace qjson {
void testQJson()
{
QJsonObject obj {
{"-1", -1},
{"3", 3},
{"0x3fffff (4194303)", 4194303},
{"0x400000 (4194304)", 4194304},
{"0x800000 (8388608)", 8388608},
{"0x1000000 (16777216)", 16777216},
{"-0x3fffff (-4194303)", -4194303},
{"-0x400000 (-4194304)", -4194304},
{"-0x800000 (-8388608)", -8388608}
};
QJsonArray arr;
for (unsigned int i = 0; i < 32; ++i) {
arr.append(QJsonValue(qint64(1u << i) - 1));
arr.append(QJsonValue(qint64(1u << i)));
arr.append(QJsonValue(qint64(1u << i) + 1));
}
for (unsigned int i = 0; i < 32; ++i) {
arr.append(QJsonValue(-qint64(1u << i) + 1));
arr.append(QJsonValue(-qint64(1u << i)));
arr.append(QJsonValue(-qint64(1u << i) - 1));
}
BREAK_HERE;
// Check v -1 QJsonValue.
// Check obj "foo" -1 QJsonValue.
// Continue.
}
} // namespace json
namespace webkit { namespace webkit {
void testWTFString() void testWTFString()
@@ -7187,6 +7225,7 @@ int main(int argc, char *argv[])
qregexp::testQRegExp(); qregexp::testQRegExp();
qregion::testQRegion(); qregion::testQRegion();
qscript::testQScript(); qscript::testQScript();
qjson::testQJson();
qset::testQSet(); qset::testQSet();
qsharedpointer::testQSharedPointer(); qsharedpointer::testQSharedPointer();
qstack::testQStack(); qstack::testQStack();

View File

@@ -1,5 +1,5 @@
:*Qt Creator.Add Kit_QPushButton {text='Add Kit' type='QPushButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Add Kit_QPushButton {text='Add Kit' type='QPushButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Build Project_Core::Internal::FancyToolButton {text='Build Project' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Build Project_Core::Internal::FancyToolButton {text?='Build Project*' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Cancel Build_QToolButton {text='Cancel Build' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Cancel Build_QToolButton {text='Cancel Build' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Cancel_QPushButton {text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Cancel_QPushButton {text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Clear_QToolButton {text='Clear' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :*Qt Creator.Clear_QToolButton {text='Clear' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}

View File

@@ -24,8 +24,17 @@
############################################################################ ############################################################################
def startCreatorTryingClang(): def startCreatorTryingClang():
try:
# start Qt Creator with enabled ClangCodeModel plugin (without modifying settings) # start Qt Creator with enabled ClangCodeModel plugin (without modifying settings)
startApplication("qtcreator -load ClangCodeModel" + SettingsPath) startApplication("qtcreator -load ClangCodeModel" + SettingsPath)
except RuntimeError:
t, v = sys.exc_info()[:2]
strv = str(v)
if strv == "startApplication() failed":
test.fatal("%s. Creator built without ClangCodeModel?" % strv)
else:
test.fatal("Exception caught", "%s(%s)" % (str(t), strv))
return False
errorMsg = "{type='QMessageBox' unnamed='1' visible='1' windowTitle='Qt Creator'}" errorMsg = "{type='QMessageBox' unnamed='1' visible='1' windowTitle='Qt Creator'}"
errorOK = "{text='OK' type='QPushButton' unnamed='1' visible='1' window=%s}" % errorMsg errorOK = "{text='OK' type='QPushButton' unnamed='1' visible='1' window=%s}" % errorMsg
if not waitFor("object.exists(errorOK)", 5000): if not waitFor("object.exists(errorOK)", 5000):

View File

@@ -345,17 +345,17 @@ def invokeContextMenuItem(editorArea, command1, command2 = None):
ctxtMenu = openContextMenuOnTextCursorPosition(editorArea) ctxtMenu = openContextMenuOnTextCursorPosition(editorArea)
snooze(1) snooze(1)
if platform.system() == 'Darwin': if platform.system() == 'Darwin':
activateItem(ctxtMenu, command1) item1 = waitForObjectItem(ctxtMenu, command1)
subMenu = item1.menu()
activateItem(item1)
# subMenu could have been triggered by hovering, but closed again by clicking
if subMenu and not subMenu.visible:
activateItem(item1)
if command2:
activateItem(subMenu, command2)
else: else:
activateItem(waitForObjectItem(objectMap.realName(ctxtMenu), command1, 2000)) activateItem(waitForObjectItem(objectMap.realName(ctxtMenu), command1, 2000))
if command2: if command2:
# Hack for Squish 5.0.1 handling menus of Qt5.2 on Mac (avoids crash) - remove asap
if platform.system() == 'Darwin':
for obj in object.topLevelObjects():
if className(obj) == 'QMenu' and obj.visible and not obj == ctxtMenu:
activateItem(obj, command2)
break
else:
activateItem(waitForObjectItem("{title='%s' type='QMenu' visible='1' window=%s}" activateItem(waitForObjectItem("{title='%s' type='QMenu' visible='1' window=%s}"
% (command1, objectMap.realName(ctxtMenu)), command2, 2000)) % (command1, objectMap.realName(ctxtMenu)), command2, 2000))

View File

@@ -689,7 +689,7 @@ def copyFilesToDir(files, targetDir):
return result return result
def __sortFilenamesOSDependent__(filenames): def __sortFilenamesOSDependent__(filenames):
if platform.system() in ('Windows', 'Microsoft'): if platform.system() in ('Windows', 'Microsoft', 'Darwin'):
filenames.sort(key=str.lower) filenames.sort(key=str.lower)
else: else:
filenames.sort() filenames.sort()

View File

@@ -58,13 +58,13 @@ def ensureChecked(objectName, shouldBeChecked = True, timeout=20000):
try: try:
# needed for transition Qt::PartiallyChecked -> Qt::Checked -> Qt::Unchecked # needed for transition Qt::PartiallyChecked -> Qt::Checked -> Qt::Unchecked
clicked = 0 clicked = 0
while not waitFor('widget.checkState() == targetState', 1000) and clicked < 2: while not waitFor('widget.checkState() == targetState', 1500) and clicked < 2:
clickButton(widget) clickButton(widget)
clicked += 1 clicked += 1
test.verify(waitFor("widget.checkState() == targetState", 1000)) test.verify(waitFor("widget.checkState() == targetState", 1000))
except: except:
# widgets not derived from QCheckbox don't have checkState() # widgets not derived from QCheckbox don't have checkState()
if not waitFor('widget.checked == shouldBeChecked', 1000): if not waitFor('widget.checked == shouldBeChecked', 1500):
mouseClick(widget, 10, 6, 0, Qt.LeftButton) mouseClick(widget, 10, 6, 0, Qt.LeftButton)
test.verify(waitFor("widget.checked == shouldBeChecked", 1000)) test.verify(waitFor("widget.checked == shouldBeChecked", 1000))
test.log("New state for QCheckBox: %s" % state, test.log("New state for QCheckBox: %s" % state,
@@ -217,10 +217,11 @@ def logApplicationOutput():
# get the output from a given cmdline call # get the output from a given cmdline call
def getOutputFromCmdline(cmdline): def getOutputFromCmdline(cmdline):
versCall = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True) try:
result = versCall.communicate()[0] return subprocess.check_output(cmdline, shell=True) # TODO: do not use shell=True
versCall.stdout.close() except subprocess.CalledProcessError as e:
return result test.warning("Command '%s' returned %d" % (e.cmd, e.returncode))
return e.output
def selectFromFileDialog(fileName, waitForFile=False): def selectFromFileDialog(fileName, waitForFile=False):
if platform.system() == "Darwin": if platform.system() == "Darwin":
@@ -228,7 +229,7 @@ def selectFromFileDialog(fileName, waitForFile=False):
nativeType("<Command+Shift+g>") nativeType("<Command+Shift+g>")
snooze(1) snooze(1)
nativeType(fileName) nativeType(fileName)
snooze(1) snooze(2)
nativeType("<Return>") nativeType("<Return>")
snooze(3) snooze(3)
nativeType("<Return>") nativeType("<Return>")
@@ -600,6 +601,7 @@ def clickOnTab(tabBarStr, tabText, timeout=5000):
if platform.system() == 'Darwin' and not tabBar.visible: if platform.system() == 'Darwin' and not tabBar.visible:
test.log("Using workaround for Mac.") test.log("Using workaround for Mac.")
setWindowState(tabBar, WindowState.Normal) setWindowState(tabBar, WindowState.Normal)
tabBar = waitForObject(tabBarStr, 2000)
clickTab(tabBar, tabText) clickTab(tabBar, tabText)
waitFor("str(tabBar.tabText(tabBar.currentIndex)) == '%s'" % tabText, timeout) waitFor("str(tabBar.tabText(tabBar.currentIndex)) == '%s'" % tabText, timeout)

View File

@@ -78,6 +78,19 @@ def main():
type(waitForObject(":popupFrame_Proposal_QListView"), "<Tab>") type(waitForObject(":popupFrame_Proposal_QListView"), "<Tab>")
test.compare(str(lineUnderCursor(editorWidget)).strip(), "void", test.compare(str(lineUnderCursor(editorWidget)).strip(), "void",
"Step 4: Verifying if: Word 'void' is completed because only one option is available.") "Step 4: Verifying if: Word 'void' is completed because only one option is available.")
# Step 4.5: Insert text "2." to new line and verify that code completion is not triggered (QTCREATORBUG-16188)
resetLine(editorWidget)
lineWithFloat = "float fl = 2."
type(editorWidget, lineWithFloat)
try:
waitForObject(":popupFrame_Proposal_QListView", 5000)
if useClang and JIRA.isBugStillOpen(16188):
test.xfail("Typing a float value triggered code completion")
else:
test.fail("Typing a float value triggered code completion")
except:
test.compare(str(lineUnderCursor(editorWidget)), " " + lineWithFloat,
"Typing a float value does not trigger code completion")
# Step 5: From "Tools -> Options -> Text Editor -> Completion" select Activate completion Manually, # Step 5: From "Tools -> Options -> Text Editor -> Completion" select Activate completion Manually,
# uncheck Autocomplete common prefix and press Apply and then Ok . Return to Edit mode. # uncheck Autocomplete common prefix and press Apply and then Ok . Return to Edit mode.
test.log("Step 5: Change Code Completion settings") test.log("Step 5: Change Code Completion settings")

View File

@@ -31,7 +31,8 @@ def main():
# expected error texts - for different compilers # expected error texts - for different compilers
expectedErrorAlternatives = ["'SyntaxError' was not declared in this scope", expectedErrorAlternatives = ["'SyntaxError' was not declared in this scope",
"'SyntaxError' : undeclared identifier", "'SyntaxError' : undeclared identifier",
"use of undeclared identifier 'SyntaxError'"] "use of undeclared identifier 'SyntaxError'",
"unknown type name 'SyntaxError'"]
startApplication("qtcreator" + SettingsPath) startApplication("qtcreator" + SettingsPath)
if not startedWithoutPluginError(): if not startedWithoutPluginError():
return return

View File

@@ -49,6 +49,10 @@ def main():
waitFor("object.exists(':popupFrame_TextEditor::GenericProposalWidget')", 1500) waitFor("object.exists(':popupFrame_TextEditor::GenericProposalWidget')", 1500)
found = str(lineUnderCursor(cppwindow)).strip() found = str(lineUnderCursor(cppwindow)).strip()
exp = testData.field(record, "expected") exp = testData.field(record, "expected")
if (useClang and exp.endswith("->") and JIRA.isBugStillOpen(16336)
and platform.system() in ('Windows', 'Microsoft')):
test.xcompare(found, exp)
else:
test.compare(found, exp) test.compare(found, exp)
invokeMenuItem("File", 'Revert "main.cpp" to Saved') invokeMenuItem("File", 'Revert "main.cpp" to Saved')
clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton"))

View File

@@ -2,6 +2,8 @@
"" "" "syntaxError" "." "syntaxError." "" "" "syntaxError" "." "syntaxError."
"" "" "argc" "." "argc." "" "" "argc" "." "argc."
"" "" "argv[0]" "." "argv[0]." "" "" "argv[0]" "." "argv[0]."
"" "" "2" "." "2."
"" "" "float fl = 2" "." "float fl = 2."
"" "QCoreApplication qa;" "qa" "." "qa." "" "QCoreApplication qa;" "qa" "." "qa."
"" "QCoreApplication *p;" "p" "." "p->" "" "QCoreApplication *p;" "p" "." "p->"
"" "QCoreApplication &ref = a;" "ref" "." "ref." "" "QCoreApplication &ref = a;" "ref" "." "ref."
1 include declaration usage operator expected
2 syntaxError . syntaxError.
3 argc . argc.
4 argv[0] . argv[0].
5 2 . 2.
6 float fl = 2 . float fl = 2.
7 QCoreApplication qa; qa . qa.
8 QCoreApplication *p; p . p->
9 QCoreApplication &ref = a; ref . ref.

View File

@@ -117,7 +117,7 @@ def __compFunc__(it, foundComp, foundCompNames):
foundCompNames.append(it) foundCompNames.append(it)
def __dbgFunc__(it, foundDbg): def __dbgFunc__(it, foundDbg):
waitFor("object.exists(':Path.Utils_BaseValidatingLineEdit')", 1000) waitFor("object.exists(':Path.Utils_BaseValidatingLineEdit')", 2000)
pathLineEdit = findObject(":Path.Utils_BaseValidatingLineEdit") pathLineEdit = findObject(":Path.Utils_BaseValidatingLineEdit")
foundDbg.append(str(pathLineEdit.text)) foundDbg.append(str(pathLineEdit.text))

View File

@@ -42,6 +42,8 @@ def main():
selectFromCombo(":User Interface.languageBox_QComboBox", languageName) selectFromCombo(":User Interface.languageBox_QComboBox", languageName)
clickButton(waitForObject(":Options.OK_QPushButton")) clickButton(waitForObject(":Options.OK_QPushButton"))
clickButton(waitForObject(":Restart required.OK_QPushButton")) clickButton(waitForObject(":Restart required.OK_QPushButton"))
test.verify(waitFor("not object.exists(':Options_Core::Internal::SettingsDialog')", 5000),
"Options dialog disappeared")
invokeMenuItem("File", "Exit") invokeMenuItem("File", "Exit")
waitForCleanShutdown() waitForCleanShutdown()
snooze(4) # wait for complete unloading of Creator snooze(4) # wait for complete unloading of Creator
@@ -49,12 +51,16 @@ def main():
startApplication("qtcreator" + SettingsPath) startApplication("qtcreator" + SettingsPath)
try: try:
if platform.system() == 'Darwin': if platform.system() == 'Darwin':
# temporary hack for handling wrong menus when using Squish 5.0.1 with Qt5.2 try:
fileMenu = waitForObjectItem(":Qt Creator.QtCreator.MenuBar_QMenuBar", fileMenu = waitForObjectItem(":Qt Creator.QtCreator.MenuBar_QMenuBar",
testData.field(lang, "File")) testData.field(lang, "File"))
activateItem(fileMenu) activateItem(fileMenu)
waitForObject("{type='QMenu' visible='1'}") obj = waitForObject("{type='QMenu' visible='1'}")
test.compare(str(obj.objectName), 'QtCreator.Menu.File',
"Creator was running in %s translation" % languageName)
activateItem(fileMenu) activateItem(fileMenu)
except:
test.fail("Creator seems to be missing %s translation" % languageName)
nativeType("<Command+q>") nativeType("<Command+q>")
else: else:
invokeMenuItem(testData.field(lang, "File"), testData.field(lang, "Exit")) invokeMenuItem(testData.field(lang, "File"), testData.field(lang, "Exit"))

View File

@@ -52,7 +52,7 @@ def main():
type(editor, "<Return>") type(editor, "<Return>")
invokeMenuItem("File", "Save All") invokeMenuItem("File", "Save All")
clickButton(waitForObject(":Qt Creator.CloseDoc_QToolButton")) clickButton(waitForObject(":Qt Creator.CloseDoc_QToolButton"))
if test.verify(waitFor("headerFileName in str(mainWindow.windowTitle)", 1000), if test.verify(waitFor("headerFileName in str(mainWindow.windowTitle)", 2000),
"Header file was shown after closing source?"): "Header file was shown after closing source?"):
editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
editorText = str(editor.plainText) editorText = str(editor.plainText)
@@ -80,7 +80,7 @@ def main():
addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", False, newBasePath=basePath, addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", False, newBasePath=basePath,
expectedSourceName=sourceFileName, expectedSourceName=sourceFileName,
expectedHeaderName=headerFileName) expectedHeaderName=headerFileName)
test.verify(not waitFor("overwritten(sourceFileName)", 500), test.verify(not waitFor("overwritten(sourceFileName)", 2000),
"Source file should not be overwritten.") "Source file should not be overwritten.")
test.verify(not waitFor("overwritten(headerFileName)", 500), test.verify(not waitFor("overwritten(headerFileName)", 500),
"Header file should not be overwritten.") "Header file should not be overwritten.")
@@ -88,7 +88,7 @@ def main():
addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", True, newBasePath=basePath, addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", True, newBasePath=basePath,
expectedSourceName=sourceFileName, expectedSourceName=sourceFileName,
expectedHeaderName=headerFileName) expectedHeaderName=headerFileName)
test.verify(waitFor("overwritten(sourceFileName)", 500), test.verify(waitFor("overwritten(sourceFileName)", 2000),
"Source file should be overwritten.") "Source file should be overwritten.")
test.verify(waitFor("overwritten(headerFileName)", 500), test.verify(waitFor("overwritten(headerFileName)", 500),
"Header file should be overwritten.") "Header file should be overwritten.")

View File

@@ -33,12 +33,25 @@ def performEditMenu():
passiveLineEdit = waitForObject(":FormEditorStack.__qt__passive_editor_QLineEdit") passiveLineEdit = waitForObject(":FormEditorStack.__qt__passive_editor_QLineEdit")
replaceEditorContent(passiveLineEdit, "SquishTestFile") replaceEditorContent(passiveLineEdit, "SquishTestFile")
type(passiveLineEdit, "<Return>") type(passiveLineEdit, "<Return>")
menu = waitForObject("{name='menuSquishTestFile' title='SquishTestFile' type='QDesignerMenu' " # this "special" QDesignerMenu will be hidden and unusable on OSX
"visible='1' window=':Qt Creator_Core::Internal::MainWindow'}") menuStr = ("{name='menuSquishTestFile' title='SquishTestFile' type='QDesignerMenu' "
"window=':Qt Creator_Core::Internal::MainWindow'}")
try:
menu = waitForObject(menuStr, 5000)
except:
if platform.system() == 'Darwin':
# we need some information of the menu, so find at least the 'hidden' one
menu = findObject(menuStr)
else:
raise
menuHeight = menu.height menuHeight = menu.height
itemHeight = menuHeight / 2 # actually only 'Type Here' and 'Add Separator' are shown itemHeight = menuHeight / 2 # actually only 'Type Here' and 'Add Separator' are shown
itemHalf = itemHeight / 2 itemHalf = itemHeight / 2
# add Open menu item # add Open menu item
if platform.system() == 'Darwin':
# double clicking is not possible on hidden objects
nativeType("<Return>")
else:
doubleClick(menu, 15, itemHalf, 0, Qt.LeftButton) doubleClick(menu, 15, itemHalf, 0, Qt.LeftButton)
passiveLineEdit = waitForObject(":FormEditorStack.__qt__passive_editor_QLineEdit") passiveLineEdit = waitForObject(":FormEditorStack.__qt__passive_editor_QLineEdit")
replaceEditorContent(passiveLineEdit, "Open") replaceEditorContent(passiveLineEdit, "Open")
@@ -46,11 +59,18 @@ def performEditMenu():
waitFor("menu.height > menuHeight", 2000) waitFor("menu.height > menuHeight", 2000)
menuHeight = menu.height menuHeight = menu.height
# add a separator # add a separator
if platform.system() == 'Darwin':
nativeType("<Down>")
nativeType("<Return>")
else:
doubleClick(menu, 15, menu.height - itemHalf, 0, Qt.LeftButton) doubleClick(menu, 15, menu.height - itemHalf, 0, Qt.LeftButton)
waitFor("menu.height > menuHeight", 2000) waitFor("menu.height > menuHeight", 2000)
separatorHeight = menu.height - menuHeight separatorHeight = menu.height - menuHeight
menuHeight = menu.height menuHeight = menu.height
# add Shutdown menu item (Quit/Exit do not work because Squish/Qt5 problems with menus) # add Shutdown menu item (Quit/Exit do not work because Squish/Qt5 problems with menus)
if platform.system() == 'Darwin':
nativeType("<Return>")
else:
doubleClick(menu, 30, itemHeight + separatorHeight + itemHalf, 0, Qt.LeftButton) doubleClick(menu, 30, itemHeight + separatorHeight + itemHalf, 0, Qt.LeftButton)
passiveLineEdit = waitForObject(":FormEditorStack.__qt__passive_editor_QLineEdit") passiveLineEdit = waitForObject(":FormEditorStack.__qt__passive_editor_QLineEdit")
replaceEditorContent(passiveLineEdit, "Shutdown") replaceEditorContent(passiveLineEdit, "Shutdown")