From ea5aa79dca1fc77ee6d8dc8c26e5362e72503ef8 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Wed, 26 Jun 2013 18:18:25 +0200 Subject: [PATCH 01/48] AndroidPackageCreationStep: Ensure right thread for handleOutput() The ::run method is run in a separate thread, yet the owner of the buildstep is the gui thread. As such we need to use a DirectConnection to ensure that the slot is called in the right thread. Task-number: QTCREATORBUG-9660 Change-Id: Ia206f3256a23f70f50d31c739359ff24b952fe46 Reviewed-by: Paul Olav Tvete Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/android/androidpackagecreationstep.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/android/androidpackagecreationstep.cpp b/src/plugins/android/androidpackagecreationstep.cpp index 5f80db9cd80..c187dc2c007 100644 --- a/src/plugins/android/androidpackagecreationstep.cpp +++ b/src/plugins/android/androidpackagecreationstep.cpp @@ -706,9 +706,9 @@ bool AndroidPackageCreationStep::createPackage() buildProc->setProcessEnvironment(m_environment.toProcessEnvironment()); connect(buildProc, SIGNAL(readyReadStandardOutput()), this, - SLOT(handleBuildStdOutOutput())); + SLOT(handleBuildStdOutOutput()), Qt::DirectConnection); connect(buildProc, SIGNAL(readyReadStandardError()), this, - SLOT(handleBuildStdErrOutput())); + SLOT(handleBuildStdErrOutput()), Qt::DirectConnection); buildProc->setWorkingDirectory(m_androidDir.toString()); From 98d78bed535bc5a2121aaba87a4bf756c9e8cbf7 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 27 Jun 2013 16:27:51 +0200 Subject: [PATCH 02/48] QmlDesigner: export NodeAbstractProperty Change-Id: Ib34a474344d3077096c9775d1c5b99f59ae3e4fa Reviewed-by: Kai Koehne Reviewed-by: Marco Bubke --- .../qmldesigner/designercore/include/nodeabstractproperty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h b/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h index 4d67a2e2aff..4ceb22a8420 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h +++ b/src/plugins/qmldesigner/designercore/include/nodeabstractproperty.h @@ -39,7 +39,7 @@ namespace Internal { typedef QSharedPointer InternalNodeAbstractPropertyPointer; } -class NodeAbstractProperty : public AbstractProperty +class QMLDESIGNERCORE_EXPORT NodeAbstractProperty : public AbstractProperty { friend class QmlDesigner::ModelNode; friend class QmlDesigner::Internal::ModelPrivate; From a86a67d883e0fa23a5c84ea16aa66edad3e1310f Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 27 Jun 2013 16:40:33 +0200 Subject: [PATCH 03/48] Update qbs submodule to version 1.0.1. Change-Id: Ic5f6968736c6d465700baf2afeb388efc90ac1ab Reviewed-by: Joerg Bornemann --- src/shared/qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/qbs b/src/shared/qbs index 6de45d07b83..604aa765a83 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 6de45d07b8382c80dd0ebab993b8e0cadaac4338 +Subproject commit 604aa765a8389bfaf3c97465d4903f709c4e09cd From 7b73029be8bcc541d74c0658f8382981acdf5346 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 27 Jun 2013 16:41:23 +0200 Subject: [PATCH 04/48] Remove workaround for qbs bug. It's been fixed. Change-Id: I49f3dc193752c2796548b5f49eb4e66824125b71 Reviewed-by: Joerg Bornemann --- src/plugins/QtcPlugin.qbs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/QtcPlugin.qbs b/src/plugins/QtcPlugin.qbs index fb839a995ee..d1b52ddf58a 100644 --- a/src/plugins/QtcPlugin.qbs +++ b/src/plugins/QtcPlugin.qbs @@ -19,7 +19,6 @@ Product { } return name; } - moduleSearchPaths: "../../../qbs" // TODO: Should get inherited from project, but doesn't. Depends { name: "ExtensionSystem" } Depends { name: "pluginspec" } From 7cb5e83d73e224480bc29ffe206638752f7d0af9 Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Thu, 27 Jun 2013 20:58:09 +0100 Subject: [PATCH 05/48] Fix building from MSYS shell In debugger.pro, take path that checks and sets QMAKE_CHK_EXISTS_GLUE if QMAKE_SH isn't empty. Change-Id: I7c37acc5867c1ac3ab6da33db3eb2479c1d4213c Reviewed-by: Alexey Pavlov Reviewed-by: hjk --- src/plugins/debugger/debugger.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index e703b8830f6..952586b5372 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -157,7 +157,7 @@ equals(TEST, 1):!isEmpty(copydata) { else: OUTPUT_DIR = $$IDE_BUILD_TREE/$$TEST_DIR testfile.target = $$OUTPUT_DIR/$$basename(INPUT_FILE) testfile.depends = $$INPUT_FILE - win32 { + win32:isEmpty(QMAKE_SH) { INPUT_FILE ~= s,/,\\\\,g OUTPUT_DIR ~= s,/,\\\\,g } else { From 103d0e643fbe828b6d2ff82c4b2e4c06f0745b50 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 27 Jun 2013 10:42:32 +0200 Subject: [PATCH 06/48] Debugger: Add a more generic way to distinguish Qt 4 and 5 in dumpers Change-Id: I1f020032984fb61554b75cc404784d39d9464890 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 17 ++++++++++++++++- share/qtcreator/dumper/lbridge.py | 3 +++ share/qtcreator/dumper/qttypes.py | 3 ++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index 82c5aa96b14..abb55274e3b 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -358,6 +358,9 @@ qqDumpers = {} # This is a cache of all dumpers that support writing. qqEditable = {} +# This is an approximation of the Qt Version found +qqVersion = None + def registerDumper(function): global qqDumpers, qqFormats, qqEditable try: @@ -1134,7 +1137,7 @@ def qtNamespace(): if not qqNs is None: return qqNs try: - str = catchCliOutput("ptype QString::Null")[0] + str = gdb.execute("ptype QString::Null", to_string=True) # The result looks like: # "type = const struct myns::QString::Null {" # " " @@ -1559,6 +1562,18 @@ class Dumper: return xrange(0, self.currentNumChild) return xrange(min(self.currentMaxNumChild, self.currentNumChild)) + def qtVersion(self): + global qqVersion + if not qqVersion is None: + return qqVersion + try: + # This will fail on Qt 5 + gdb.execute("ptype QString::shared_empty", to_string=True) + qqVersion = 0x040800 + except: + qqVersion = 0x050000 + return qqVersion + # Convenience function. def putItemCount(self, count, maximum = 1000000000): # This needs to override the default value, so don't use 'put' directly. diff --git a/share/qtcreator/dumper/lbridge.py b/share/qtcreator/dumper/lbridge.py index 7c0cdfa71c4..8fc10117da4 100644 --- a/share/qtcreator/dumper/lbridge.py +++ b/share/qtcreator/dumper/lbridge.py @@ -609,6 +609,9 @@ class Dumper: inner = self.extractTemplateArgument(typeobj.GetName(), index) return int(inner) + def qtVersion(self): + return 0x050000 + def intType(self): if self.intType_ is None: self.intType_ = self.target.FindFirstType('int') diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index 8cea2413254..a54e6a10903 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -713,7 +713,8 @@ def qform__QImage(): def qdump__QImage(d, value): # This relies on current QImage layout intPtrType = d.lookupType("int").pointer() - base = createReferenceValue(value, d.addressOf(value) + 3 * intPtrType.sizeof, intPtrType) + offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof + base = createReferenceValue(value, d.addressOf(value) + offset, intPtrType) width = int(base[1]) height = int(base[2]) d.putValue("(%dx%d)" % (width, height)) From 58f4516e32d700b0e8dc6ba4432b20a935a352ec Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 27 Jun 2013 11:52:27 +0200 Subject: [PATCH 07/48] Debugger: Make QPixmap dumper work in release builds Change-Id: Ib50d6968fcac38fa59df5c34c578b4a618dc9e06 Reviewed-by: hjk --- share/qtcreator/dumper/qttypes.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index a54e6a10903..ca1a7ba407d 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -1392,14 +1392,10 @@ def qdump__QObject(d, value): # } def qdump__QPixmap(d, value): - painters = int(value["painters"]) - check(0 <= painters and painters < 1000) - d_ptr = value["data"]["d"] - if isNull(d_ptr): - d.putValue("(null)") - else: - checkSimpleRef(d_ptr["ref"]) - d.putValue("(%dx%d)" % (d_ptr["w"], d_ptr["h"])) + intPtrType = d.lookupType("int").pointer() + offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof + base = createReferenceValue(value, d.addressOf(value) + offset, intPtrType) + d.putValue("(%dx%d)" % (base[1], base[2])) d.putNumChild(0) From 61a1ccbfb28c3b8594b1a337314d9d6c3b6eb58a Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 27 Jun 2013 17:18:44 +0200 Subject: [PATCH 08/48] Debugger: Make bytearray dumper work on anonymous data Change-Id: Ibce8030360be161fb8944175afa0ce9119133b39 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 3 ++ share/qtcreator/dumper/qttypes.py | 57 +++++++++++++++++-------------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index abb55274e3b..f55d5758081 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -1542,6 +1542,9 @@ class Dumper: def charPtrType(self): return self.lookupType('char*') + def intPtrType(self): + return self.lookupType('int*') + def voidPtrType(self): return self.lookupType('void*') diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index ca1a7ba407d..d2e3bce1ddb 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -34,18 +34,31 @@ def checkRef(ref): check(count >= minimum) check(count < 1000000) - def qByteArrayDataData(d, value): - checkRef(value['ref']) - size = int(value['size']) - alloc = int(value['alloc']) - try: - # Qt 5. Will fail on Qt 4 due to the missing 'offset' member. - addr = d.addressOf(value) + int(value['offset']) - except: - # Qt 4: - addr = value['data'] - return createPointerValue(value, addr, d.charType()), size, alloc + intType = d.intType() + base = d.addressOf(value) + if d.qtVersion() >= 0x050000: + # QTypedArray: + # - QtPrivate::RefCount ref + # - int size + # - uint alloc : 31, capacityReserved : 1 + # - qptrdiff offset + size = int(createReferenceValue(value, base + intType.sizeof, intType)) + alloc = int(createReferenceValue(value, base + 2 * intType.sizeof, intType)) \ + & 0x7ffffff + data = base + pointerValue(createReferenceValue(value, + base + 2 * intType.sizeof + intType.pointer().sizeof, + d.charPtrType())) + else: + # Data: + # - QBasicAtomicInt ref; + # - int alloc, size; + # - char *data; + # - char array[1]; + alloc = int(createReferenceValue(value, base + intType.sizeof, intType)) + size = int(createReferenceValue(value, base + 2 * intType.sizeof, intType)) + data = pointerCbase + 3 * intType.sizeof + intType.pointer().sizeof + return data, size, alloc def qByteArrayData(d, value): return d.byteArrayDataData(value['d'].dereference()) @@ -1703,22 +1716,16 @@ def qdump__QTextDocument(d, value): def qdump__QUrl(d, value): - try: - # Qt 4 + if d.qtVersion() < 0x050000: data = value["d"].dereference() d.putByteArrayValue(data["encodedOriginal"]) - except: - try: - # Qt 5 - data = value["d"].dereference() - str = d.encodeString(data["scheme"]) - str += "3a002f002f00" - str += d.encodeString(data["host"]) - str += d.encodeString(data["path"]) - d.putValue(str, Hex4EncodedLittleEndian) - except: - d.putPlainChildren(value) - return + else: + data = value["d"].dereference() + str = d.encodeString(data["scheme"]) + str += "3a002f002f00" + str += d.encodeString(data["host"]) + str += d.encodeString(data["path"]) + d.putValue(str, Hex4EncodedLittleEndian) d.putNumChild(1) if d.isExpanded(): with Children(d): From 7724bd467388f6ae3b8a4cbc8609f535a94a03f1 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 26 Jun 2013 16:18:34 +0200 Subject: [PATCH 09/48] Checkout correct branch of the binary-artifacts repository. Change-Id: I66e27b54b59874f5f69958cf9e178a5ce1b2da97 Reviewed-by: Eike Ziller --- qtcreator.pri | 1 + qtcreator.pro | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/qtcreator.pri b/qtcreator.pri index afd46883dca..13e25dca4df 100644 --- a/qtcreator.pri +++ b/qtcreator.pri @@ -2,6 +2,7 @@ QTCREATOR_PRI_INCLUDED = 1 QTCREATOR_VERSION = 2.7.2 +BINARY_ARTIFACTS_BRANCH = 2.7 isEqual(QT_MAJOR_VERSION, 5) { diff --git a/qtcreator.pro b/qtcreator.pro index 0836cf0685e..84d8a9d91b3 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -66,7 +66,7 @@ macx { deployqt.depends = install win32 { deployartifacts.depends = install - deployartifacts.commands = git clone "git://gitorious.org/qt-creator/binary-artifacts.git"&& xcopy /s /q /y /i "binary-artifacts\\win32" \"$(INSTALL_ROOT)$$QTC_PREFIX\"&& rmdir /s /q binary-artifacts + deployartifacts.commands = git clone "git://gitorious.org/qt-creator/binary-artifacts.git" -b $$BINARY_ARTIFACTS_BRANCH&& xcopy /s /q /y /i "binary-artifacts\\win32" \"$(INSTALL_ROOT)$$QTC_PREFIX\"&& rmdir /s /q binary-artifacts QMAKE_EXTRA_TARGETS += deployartifacts } } From c63725ff6645ae9ef9ed992ae504351260fba583 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 27 Jun 2013 13:59:25 +0200 Subject: [PATCH 10/48] Fix sources that are deployed into Qt Creator build for qml(2)puppet When qml(2)puppet is built as part of Qt Creator, we need to generate the Info.plist from Info.plist.in. When it is deployed as source into the Qt Creator build, we need to do that too. Change-Id: I83aa446f19984a51822c46df2ab7f41e78002ad4 Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/qml2puppet/qml2puppet.pri | 15 ++++++++++++--- .../qml/qmlpuppet/qmlpuppet/qmlpuppet.pri | 15 ++++++++++++--- share/qtcreator/static.pro | 7 +++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri index 071a81a1c5d..34157e1e8f1 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri @@ -29,9 +29,18 @@ DEFINES -= QT_NO_CAST_FROM_ASCII OTHER_FILES += Info.plist.in macx { - info.input = $$PWD/Info.plist.in - info.output = $$DESTDIR/$${TARGET}.app/Contents/Info.plist - QMAKE_SUBSTITUTES += info + isEmpty(QTCREATOR_PRI_INCLUDED) { + # So this .pri file is used by + # compiling the sources that were deployed to Qt Creator, + # and the Info.plist was generated by static.pro at build time + QMAKE_INFO_PLIST = $$PWD/Info.plist + } else { + # So this .pri file is used from Qt Creator source tree, + # and we need to generate the Info.plist + info.input = $$PWD/Info.plist.in + info.output = $$DESTDIR/$${TARGET}.app/Contents/Info.plist + QMAKE_SUBSTITUTES += info + } } else { target.path = $$QTC_PREFIX/bin INSTALLS += target diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppet.pri b/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppet.pri index 4ca63d75652..a4332bdc355 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppet.pri +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet/qmlpuppet.pri @@ -23,9 +23,18 @@ DEFINES -= QT_NO_CAST_FROM_ASCII OTHER_FILES += Info.plist.in macx { - info.input = $$PWD/Info.plist.in - info.output = $$DESTDIR/$${TARGET}.app/Contents/Info.plist - QMAKE_SUBSTITUTES += info + isEmpty(QTCREATOR_PRI_INCLUDED) { + # So this .pri file is used by + # compiling the sources that were deployed to Qt Creator, + # and the Info.plist was generated by static.pro at build time + QMAKE_INFO_PLIST = $$PWD/Info.plist + } else { + # So this .pri file is used from Qt Creator source tree, + # and we need to generate the Info.plist + info.input = $$PWD/Info.plist.in + info.output = $$DESTDIR/$${TARGET}.app/Contents/Info.plist + QMAKE_SUBSTITUTES += info + } } else { target.path = $$QTC_PREFIX/bin INSTALLS += target diff --git a/share/qtcreator/static.pro b/share/qtcreator/static.pro index 4ae6ec17549..e9e51c3563b 100644 --- a/share/qtcreator/static.pro +++ b/share/qtcreator/static.pro @@ -44,6 +44,7 @@ macx: DATA_DIRS += scripts for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g + # Info.plist.in are handled below for(file, files):!contains(file, ".*/Info\\.plist\\.in$"):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES @@ -74,6 +75,12 @@ OTHER_FILES += $$FILES observerinfo.input = qml/qmlobserver/Info.plist.in observerinfo.output = $$IDE_DATA_PATH/qml/qmlobserver/Info.plist QMAKE_SUBSTITUTES += observerinfo + puppetinfo.input = qml/qmlpuppet/qmlpuppet/Info.plist.in + puppetinfo.output = $$IDE_DATA_PATH/qml/qmlpuppet/qmlpuppet/Info.plist + QMAKE_SUBSTITUES += puppetinfo + puppet2info.input = qml/qmlpuppet/qml2puppet/Info.plist.in + puppet2info.output = $$IDE_DATA_PATH/qml/qmlpuppet/qml2puppet/Info.plist + QMAKE_SUBSTITUES += puppetinfo } SRCRESOURCEDIR = $$IDE_SOURCE_TREE/src/share/qtcreator/ From 6b0be2d4a4182a6dc35a7448dfcaf90cf665d014 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 27 Jun 2013 14:03:12 +0200 Subject: [PATCH 11/48] Revert "Fixing Info.plist.in for qmlobserver and qmldump" The Info.plist.in files are actually handled by static.pro. The projects should only be compiled from the deployed sources in the build tree. This reverts commit 30c602f458938b9d0c3b5c4602a3764e34e0919a. Change-Id: Ib63fb9e4db1c249817e59239029db7dd220ba5b3 Reviewed-by: Thomas Hartmann Reviewed-by: Kai Koehne --- share/qtcreator/qml/qmldump/qmldump.pro | 10 ++++------ share/qtcreator/qml/qmlobserver/qmlobserver.pro | 9 +++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/share/qtcreator/qml/qmldump/qmldump.pro b/share/qtcreator/qml/qmldump/qmldump.pro index efc179733cc..2b7e3fc8eb5 100644 --- a/share/qtcreator/qml/qmldump/qmldump.pro +++ b/share/qtcreator/qml/qmldump/qmldump.pro @@ -13,12 +13,10 @@ TEMPLATE = app SOURCES += main.cpp \ qmlstreamwriter.cpp -OTHER_FILES += Info.plist.in -macx { - info.input = Info.plist.in - info.output = $$DESTDIR/$${TARGET}.app/Contents/Info.plist - QMAKE_SUBSTITUTES += info -} +# generation of Info.plist from Info.plist.in is handled by static.pro +# compiling this project directly from the Qt Creator source tree does not work +OTHER_FILES += Info.plist +macx:QMAKE_INFO_PLIST = Info.plist HEADERS += \ qmlstreamwriter.h diff --git a/share/qtcreator/qml/qmlobserver/qmlobserver.pro b/share/qtcreator/qml/qmlobserver/qmlobserver.pro index f99ffd278c0..503a375dc5d 100644 --- a/share/qtcreator/qml/qmlobserver/qmlobserver.pro +++ b/share/qtcreator/qml/qmlobserver/qmlobserver.pro @@ -60,12 +60,13 @@ symbian { LIBS += -lavkon -lcone } } -OTHER_FILES+=Info.plist.in + +# generation of Info.plist from Info.plist.in is handled by static.pro +# compiling this project directly from the Qt Creator source tree does not work +OTHER_FILES+=Info.plist mac { + QMAKE_INFO_PLIST=Info.plist TARGET=QMLObserver - info.input = Info.plist.in - info.output = $$DESTDIR/$${TARGET}.app/Contents/Info.plist - QMAKE_SUBSTITUTES += info ICON=qml.icns } else { TARGET=qmlobserver From 5d005078c50ed9174917fd48b19db1d6034ac154 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 28 Jun 2013 14:19:59 +0200 Subject: [PATCH 12/48] Debugger: Re-work QObject detection Change-Id: Id7446d3898d81ac03b32b80cbc7ea22f350d191b Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 17 +++++++- share/qtcreator/dumper/qttypes.py | 69 ++++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index f55d5758081..c137b1840eb 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -1554,6 +1554,20 @@ class Dumper: def addressOf(self, value): return long(value.address) + def isQObject(self, value): + entryType = self.lookupType("int").pointer().pointer() + try: + vtable = createReferenceValue(value, value.address, entryType) + metaObjectEntry = vtable.dereference() # It's the first entry. + return str(metaObjectEntry).find("::metaObject() const") > 0 + except: + return False + # Alternative: Check for specific values, like targeting the + # 'childEvent' member which is typically not overwritten, slot 8. + # entry = pointerValue(vtable) + 8 * ptrType.sizeof + # childEventEntry = createReferenceValue(value, entry, ptrType) + #warn("CHILDEVENT: %s " % childEventEntry) + def put(self, value): self.output.append(value) @@ -2136,7 +2150,8 @@ class Dumper: #warn("INAME: %s " % self.currentIName) #warn("INAMES: %s " % self.expandedINames) #warn("EXPANDED: %s " % (self.currentIName in self.expandedINames)) - self.tryPutObjectNameValue(value) # Is this too expensive? + if self.isQObject(value): + self.putQObjectNameValue(value) # Is this too expensive? self.putType(typeName) self.putEmptyValue() self.putNumChild(fieldCount(type)) diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index d2e3bce1ddb..51ac36de56b 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -125,33 +125,65 @@ Dumper.isMapCompact = \ lambda d, keyType, valueType: qMapCompact(d.currentItemFormat(), keyType, valueType) -# Returns True when it encounters a QObject or derived class. -def tryPutObjectNameValue(d, value): +def putQObjectNameValue(d, value): try: - # Is this derived from QObject? - dd = value["d_ptr"]["d"] - privateType = d.lookupType(d.ns + "QObjectPrivate") - staticMetaObject = value["staticMetaObject"] - d_ptr = dd.cast(privateType.pointer()).dereference() + intType = d.lookupType("int") + ptrType = intType.pointer() + # dd = value["d_ptr"]["d"] is just behind the vtable. + dd = createReferenceValue(value, d.addressOf(value) + ptrType.sizeof, ptrType) + objectName = None - try: - objectName = d_ptr["objectName"] - except: # Qt 5 - p = d_ptr["extraData"] - if not isNull(p): - objectName = p.dereference()["objectName"] + if d.qtVersion() < 0x050000: + # Size of QObjectData: 5 pointer + 2 int + # - vtable + # - QObject *q_ptr; + # - QObject *parent; + # - QObjectList children; + # - uint isWidget : 1; etc.. + # - int postedEvents; + # - QMetaObject *metaObject; + + # Offset of objectName in QObjectPrivate: 5 pointer + 2 int + # - [QObjectData base] + # - QString objectName + objectName = createReferenceValue(value, + pointerValue(dd) + 5 * ptrType.sizeof + 2 * intType.sizeof, + d.lookupType(d.ns + "QString")) + else: + # Size of QObjectData: 5 pointer + 2 int + # - vtable + # - QObject *q_ptr; + # - QObject *parent; + # - QObjectList children; + # - uint isWidget : 1; etc... + # - int postedEvents; + # - QDynamicMetaObjectData *metaObject; + offset = 5 * ptrType.sizeof + 2 * intType.sizeof + extra = createReferenceValue(value, pointerValue(dd) + offset, ptrType) + + # Offset of objectName in ExtraData: 6 pointer + # - QVector userData; only #ifndef QT_NO_USERDATA + # - QList propertyNames; + # - QList propertyValues; + # - QVector runningTimers; + # - QList > eventFilters; + # - QString objectName + if pointerValue(extra): + objectName = createReferenceValue(value, + pointerValue(extra) + 5 * ptrType.sizeof, + d.lookupType(d.ns + "QString")) + if not objectName is None: data, size, alloc = d.stringData(objectName) if size > 0: str = d.readRawMemory(data, 2 * size) d.putValue(str, Hex4EncodedLittleEndian, 1) - return True except: - return False + pass -Dumper.tryPutObjectNameValue = tryPutObjectNameValue +Dumper.putQObjectNameValue = putQObjectNameValue -############################################################################################ +################################################################################### def qdump__QAtomicInt(d, value): @@ -974,8 +1006,7 @@ def extractCString(table, offset): def qdump__QObject(d, value): - #warn("OBJECT: %s " % value) - d.tryPutObjectNameValue(value) + d.putQObjectNameValue(value) try: privateTypeName = d.ns + "QObjectPrivate" From 377078ea27525744bf5e8d934b671dcc0f9fcb1f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 28 Jun 2013 16:36:56 +0200 Subject: [PATCH 13/48] Version bump Change-Id: I7f083350d0e3191e1c2362d6179240b7e7b4c47e Reviewed-by: Eike Ziller --- qtcreator.pri | 2 +- qtcreator.qbs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qtcreator.pri b/qtcreator.pri index 0d677fffaf4..0286cc850dc 100644 --- a/qtcreator.pri +++ b/qtcreator.pri @@ -1,7 +1,7 @@ !isEmpty(QTCREATOR_PRI_INCLUDED):error("qtcreator.pri already included") QTCREATOR_PRI_INCLUDED = 1 -QTCREATOR_VERSION = 2.7.84 +QTCREATOR_VERSION = 2.7.85 BINARY_ARTIFACTS_BRANCH = 2.8 isEqual(QT_MAJOR_VERSION, 5) { diff --git a/qtcreator.qbs b/qtcreator.qbs index 3824ef22eb5..930c9eb0845 100644 --- a/qtcreator.qbs +++ b/qtcreator.qbs @@ -3,7 +3,7 @@ import qbs.base 1.0 Project { property string ide_version_major: '2' property string ide_version_minor: '7' - property string ide_version_release: '84' + property string ide_version_release: '85' property string qtcreator_version: ide_version_major + '.' + ide_version_minor + '.' + ide_version_release property string ide_app_path: qbs.targetOS.contains("osx") ? "" : "bin" property string ide_app_target: qbs.targetOS.contains("osx") ? "Qt Creator" : "qtcreator" From 1fad00f9991b86c3a329410c95f148b6ce3ef0d3 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 28 Jun 2013 11:26:02 +0200 Subject: [PATCH 14/48] CppTools: Fix snapshot in case another project is opened When a second project was opened the snapshot was reset. That resulted in all kinds of problems since from then on the code model effectively was not aware of the files of the first project. The regression was introduced by commit a0d6df7b. Change-Id: I1ccc9de68177205b49a4ba8ead2bc8abe4592b32 Reviewed-by: Fawzi Mohamed --- src/plugins/cpptools/cppmodelmanager.cpp | 28 ++++--- src/plugins/cpptools/cppmodelmanager_test.cpp | 82 +++++++++++++++++++ src/plugins/cpptools/cpptoolsplugin.h | 1 + .../cppmodelmanager/testdata_project1/foo.cpp | 7 ++ tests/cppmodelmanager/testdata_project1/foo.h | 12 +++ .../testdata_project1/main.cpp | 9 ++ .../cppmodelmanager/testdata_project2/bar.cpp | 7 ++ tests/cppmodelmanager/testdata_project2/bar.h | 12 +++ .../testdata_project2/main.cpp | 9 ++ 9 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 tests/cppmodelmanager/testdata_project1/foo.cpp create mode 100644 tests/cppmodelmanager/testdata_project1/foo.h create mode 100644 tests/cppmodelmanager/testdata_project1/main.cpp create mode 100644 tests/cppmodelmanager/testdata_project2/bar.cpp create mode 100644 tests/cppmodelmanager/testdata_project2/bar.h create mode 100644 tests/cppmodelmanager/testdata_project2/main.cpp diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index b26bb706e63..b7abbe2d2dc 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -556,23 +556,31 @@ void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo) return; ProjectExplorer::Project *project = pinfo.project().data(); - m_projects.insert(project, pinfo); - m_dirty = true; - - m_srcToProjectPart.clear(); - - foreach (const ProjectInfo &projectInfo, m_projects) { - foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) { + ProjectInfo oldProjectInfo = m_projects.value(project); + if (oldProjectInfo.isValid()) { + foreach (const ProjectPart::Ptr &projectPart, oldProjectInfo.projectParts()) { foreach (const ProjectFile &cxxFile, projectPart->files) { - m_srcToProjectPart[cxxFile.path].append(projectPart); - foreach (const QString &fileName, m_snapshot.allIncludesForDocument(cxxFile.path)) + foreach (const QString &fileName, + m_snapshot.allIncludesForDocument(cxxFile.path)) { m_snapshot.remove(fileName); + } m_snapshot.remove(cxxFile.path); } } } - m_snapshot.remove(configurationFileName()); + + m_projects.insert(project, pinfo); + m_dirty = true; + + m_srcToProjectPart.clear(); + foreach (const ProjectInfo &projectInfo, m_projects) { + foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) { + foreach (const ProjectFile &cxxFile, projectPart->files) { + m_srcToProjectPart[cxxFile.path].append(projectPart); + } + } + } } if (!qgetenv("QTCREATOR_DUMP_PROJECT_INFO").isEmpty()) diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 3805f157d22..d01c4ff5ab2 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -96,6 +96,42 @@ private: const QString m_testDataDirectory; }; + +// TODO: When possible, use this helper class in all tests +class ProjectCreator +{ +public: + ProjectCreator(ModelManagerTestHelper *modelManagerTestHelper) + : modelManagerTestHelper(modelManagerTestHelper) + {} + + /// 'files' is expected to be a list of file names that reside in 'dir'. + void create(const QString &name, const QString &dir, const QStringList files) + { + const TestDataDirectory projectDir(dir); + foreach (const QString &file, files) + projectFiles << projectDir.file(file); + + Project *project = modelManagerTestHelper->createProject(name); + projectInfo = CppModelManager::instance()->projectInfo(project); + QCOMPARE(projectInfo.project().data(), project); + + ProjectPart::Ptr part(new ProjectPart); + projectInfo.appendProjectPart(part); + part->cxxVersion = ProjectPart::CXX98; + part->qtVersion = ProjectPart::Qt5; + foreach (const QString &file, projectFiles) { + ProjectFile projectFile(file, ProjectFile::classify(file)); + part->files.append(projectFile); + } + } + + ModelManagerTestHelper *modelManagerTestHelper; + ProjectInfo projectInfo; + QStringList projectFiles; +}; + + } // anonymous namespace void CppToolsPlugin::test_modelmanager_paths() @@ -278,3 +314,49 @@ void CppToolsPlugin::test_modelmanager_refresh_2() QVERIFY(document->diagnosticMessages().isEmpty()); } } + +void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects() +{ + QStringList refreshedFiles; + ModelManagerTestHelper helper; + ProjectCreator project1(&helper); + ProjectCreator project2(&helper); + CppModelManager *mm = CppModelManager::instance(); + + // Project 1 + project1.create(QLatin1String("snapshot_after_two_projects.1"), + QLatin1String("testdata_project1"), + QStringList() << QLatin1String("foo.h") + << QLatin1String("foo.cpp") + << QLatin1String("main.cpp")); + + mm->updateProjectInfo(project1.projectInfo); + mm->updateSourceFiles(project1.projectFiles); + refreshedFiles = helper.waitForRefreshedSourceFiles(); + QCOMPARE(refreshedFiles.toSet(), project1.projectFiles.toSet()); + const int snapshotSizeAfterProject1 = mm->snapshot().size(); + + foreach (const QString &file, project1.projectFiles) + QVERIFY(mm->snapshot().contains(file)); + + // Project 2 + project2.create(QLatin1String("snapshot_after_two_projects.2"), + QLatin1String("testdata_project2"), + QStringList() << QLatin1String("bar.h") + << QLatin1String("bar.cpp") + << QLatin1String("main.cpp")); + + mm->updateProjectInfo(project2.projectInfo); + mm->updateSourceFiles(project2.projectFiles); + refreshedFiles = helper.waitForRefreshedSourceFiles(); + QCOMPARE(refreshedFiles.toSet(), project2.projectFiles.toSet()); + + const int snapshotSizeAfterProject2 = mm->snapshot().size(); + QVERIFY(snapshotSizeAfterProject2 > snapshotSizeAfterProject1); + QVERIFY(snapshotSizeAfterProject2 >= snapshotSizeAfterProject1 + project2.projectFiles.size()); + + foreach (const QString &file, project1.projectFiles) + QVERIFY(mm->snapshot().contains(file)); + foreach (const QString &file, project2.projectFiles) + QVERIFY(mm->snapshot().contains(file)); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 4c983bab6ce..d10c6902215 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -163,6 +163,7 @@ private slots: void test_modelmanager_framework_headers(); void test_modelmanager_refresh_1(); void test_modelmanager_refresh_2(); + void test_modelmanager_snapshot_after_two_projects(); private: void test_completion(); diff --git a/tests/cppmodelmanager/testdata_project1/foo.cpp b/tests/cppmodelmanager/testdata_project1/foo.cpp new file mode 100644 index 00000000000..cf92d5c5ccb --- /dev/null +++ b/tests/cppmodelmanager/testdata_project1/foo.cpp @@ -0,0 +1,7 @@ +// Copyright header + +#include "foo.h" + +Foo::Foo() +{ +} diff --git a/tests/cppmodelmanager/testdata_project1/foo.h b/tests/cppmodelmanager/testdata_project1/foo.h new file mode 100644 index 00000000000..b4271076331 --- /dev/null +++ b/tests/cppmodelmanager/testdata_project1/foo.h @@ -0,0 +1,12 @@ +// Copyright header + +#ifndef FOO_H +#define FOO_H + +class Foo +{ +public: + Foo(); +}; + +#endif // FOO_H diff --git a/tests/cppmodelmanager/testdata_project1/main.cpp b/tests/cppmodelmanager/testdata_project1/main.cpp new file mode 100644 index 00000000000..eca708ea3f1 --- /dev/null +++ b/tests/cppmodelmanager/testdata_project1/main.cpp @@ -0,0 +1,9 @@ +// Copyright header + +#include "foo.h" + +int main() +{ + Foo foo; + return 1; +} diff --git a/tests/cppmodelmanager/testdata_project2/bar.cpp b/tests/cppmodelmanager/testdata_project2/bar.cpp new file mode 100644 index 00000000000..30882cdcd9c --- /dev/null +++ b/tests/cppmodelmanager/testdata_project2/bar.cpp @@ -0,0 +1,7 @@ +// Copyright header + +#include "bar.h" + +Bar::Bar() +{ +} diff --git a/tests/cppmodelmanager/testdata_project2/bar.h b/tests/cppmodelmanager/testdata_project2/bar.h new file mode 100644 index 00000000000..abb6e59877f --- /dev/null +++ b/tests/cppmodelmanager/testdata_project2/bar.h @@ -0,0 +1,12 @@ +// Copyright header + +#ifndef BAR_H +#define BAR_H + +class Bar +{ +public: + Bar(); +}; + +#endif // BAR_H diff --git a/tests/cppmodelmanager/testdata_project2/main.cpp b/tests/cppmodelmanager/testdata_project2/main.cpp new file mode 100644 index 00000000000..d6e00511ebb --- /dev/null +++ b/tests/cppmodelmanager/testdata_project2/main.cpp @@ -0,0 +1,9 @@ +// Copyright header + +#include "bar.h" + +int main() +{ + Bar bar; + return 1; +} From 924115d735df538c5c454c1f7d11345e2eb34aaf Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 1 Jul 2013 08:31:09 +0200 Subject: [PATCH 15/48] Cdbext: Fix QMap dumper for Qt5... ... when the symbol was added as an expression. It seems that calling GetSymbolTypeName somehow destroys the red-black tree, so moved the call before creating the tree. Change-Id: Iefb187df4e7f99cfd95195a6ac9a4d8c64fa2365 Reviewed-by: Friedemann Kleint --- src/libs/qtcreatorcdbext/containers.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libs/qtcreatorcdbext/containers.cpp b/src/libs/qtcreatorcdbext/containers.cpp index 58e87b0a2ca..8fbd64f0a50 100644 --- a/src/libs/qtcreatorcdbext/containers.cpp +++ b/src/libs/qtcreatorcdbext/containers.cpp @@ -943,6 +943,12 @@ static inline AbstractSymbolGroupNodePtrVector qMap5Nodes(const SymbolGroupValue SymbolGroupValue root = head["left"]; if (!root) return AbstractSymbolGroupNodePtrVector(); + + const std::string nodeType = qHashNodeType(v, "Node"); + const std::string nodePtrType = nodeType + " *"; + if (SymbolGroupValue::verbose) + DebugPrint() << v.type() << "," << nodeType; + RedBlackTreeNode *nodeTree = RedBlackTreeNode::buildMapRecursion(root, head.address(), 0, "left", "right"); if (!nodeTree) @@ -951,10 +957,6 @@ static inline AbstractSymbolGroupNodePtrVector qMap5Nodes(const SymbolGroupValue nodeTree->debug(DebugPrint(), debugQMap5Node); VectorIndexType i = 0; // Finally convert them into real nodes 'QHashNode (potentially expensive) - const std::string nodeType = qHashNodeType(v, "Node"); - const std::string nodePtrType = nodeType + " *"; - if (SymbolGroupValue::verbose) - DebugPrint() << v.type() << "," << nodeType; AbstractSymbolGroupNodePtrVector result; result.reserve(count); for (const RedBlackTreeNode *n = nodeTree->begin() ; n && i < count; n = RedBlackTreeNode::next(n), i++) { From 11da2fdc247d8960e6bd27b2a80d740a8cb452c7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 24 Jun 2013 14:52:24 -0700 Subject: [PATCH 16/48] Don't accept a column/line number selection just because of ":" If you had typed "filename.cpp:142" in the Locator field, Creator would offer "Column 142" the first option. At the very least, that's confusing because the user intended to select line 142, not column -- for a while I thought someone had typed the wrong word in the source code. But even worse, this selection was the first entry, so instead of jumping to filename.cpp on line 142, the user ended up still on the same file and line, but on a different column. Instead, simply validate that the parts before and after the colon are actually numbers. Change-Id: I1f1fbd33d702ae26c41fd2485aa99fae800e1410 Reviewed-by: Eike Ziller --- src/plugins/texteditor/linenumberfilter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp index b6dd394ceab..a199ea1741a 100644 --- a/src/plugins/texteditor/linenumberfilter.cpp +++ b/src/plugins/texteditor/linenumberfilter.cpp @@ -64,10 +64,13 @@ QList LineNumberFilter::matchesFor(QFutureInterface 0) - line = lineAndColumn.at(0).toInt(); - if (sectionCount > 1) - column = lineAndColumn.at(1).toInt(); + line = lineAndColumn.at(0).toInt(&ok); + if (ok && sectionCount > 1) + column = lineAndColumn.at(1).toInt(&ok); + if (!ok) + return value; if (currentTextEditor() && (line > 0 || column > 0)) { LineColumn data; data.first = line; From e6c85d5ff9e9c199f313a77bc801149859148b81 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 27 Jun 2013 22:36:05 +0300 Subject: [PATCH 17/48] Perforce: Support "+++ filename" for diff Task-number: QTCREATORBUG-7136 Change-Id: I2c163356c06cdc46e39bf93989b9d56f598c0890 Reviewed-by: hjk --- src/plugins/perforce/perforceeditor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/perforce/perforceeditor.cpp b/src/plugins/perforce/perforceeditor.cpp index 7a31f5af42e..d9885e1242f 100644 --- a/src/plugins/perforce/perforceeditor.cpp +++ b/src/plugins/perforce/perforceeditor.cpp @@ -66,7 +66,9 @@ PerforceEditor::PerforceEditor(const VcsBase::VcsBaseEditorParameters *type, // Diff format: // 1) "==== //depot/.../mainwindow.cpp#2 - /depot/.../mainwindow.cpp ====" (created by p4 diff) // 2) "==== //depot/.../mainwindow.cpp#15 (text) ====" (created by p4 describe) - setDiffFilePattern(QRegExp(QLatin1String("^==== (.+)#\\d"))); + // 3) --- //depot/XXX/closingkit/trunk/source/cui/src/cui_core.cpp2012-02-08 13:54:01.000000000 0100 + // +++ P:/XXX\closingkit\trunk\source\cui\src\cui_core.cpp2012-02-08 13:54:01.000000000 0100 + setDiffFilePattern(QRegExp(QLatin1String("^(?:={4}|\\+{3}) (.+)(?:\\t|#\\d)"))); setLogEntryPattern(QRegExp(QLatin1String("^... #\\d change (\\d+) "))); setAnnotateRevisionTextFormat(tr("Annotate change list \"%1\"")); if (Perforce::Constants::debug) From 62554e7647d16e8c916ebd89235f1bafe6cb253e Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 28 Jun 2013 17:28:40 +0300 Subject: [PATCH 18/48] Git: Add a soft assertion If directory is empty, buttons remains NULL, which leads to a crash To reproduce, open Branches dialog then close all editors and projects and click Log for a branch Change-Id: Icf06b76c58585c0dd6062017e94e07dad016c275 Reviewed-by: Eike Ziller Reviewed-by: hjk --- src/plugins/git/gitclient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 83b1e87907d..155769d995f 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -632,6 +632,7 @@ public: m_enableAnnotationContextMenu(enableAnnotationContextMenu), m_fileNames(fileNames) { + QTC_ASSERT(!directory.isEmpty(), return); QToolButton *diffButton = addToggleButton(QLatin1String("--patch"), tr("Show Diff"), tr("Show difference.")); mapSetting(diffButton, m_client->settings()->boolPointer(GitSettings::logDiffKey)); From 338e9a092ba189dc8a75eca49724e1800749a855 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 1 Jul 2013 08:34:39 +0300 Subject: [PATCH 19/48] SettingsAccessor: Fix empty environmentId handling * Empty environment should be ignored when comparing to current one * Fixes superfluous warning when opening a .user file without environmentId Change-Id: Iaf3f71eb2dd2a2a10faa1f6f9fe9e9154fe1ab1f Reviewed-by: Daniel Teske --- src/plugins/projectexplorer/settingsaccessor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/settingsaccessor.cpp b/src/plugins/projectexplorer/settingsaccessor.cpp index a4b774aaa7f..923b1ba3700 100644 --- a/src/plugins/projectexplorer/settingsaccessor.cpp +++ b/src/plugins/projectexplorer/settingsaccessor.cpp @@ -734,7 +734,7 @@ void SettingsAccessor::backupUserFile() const // Do we need to do a backup? const QString origName = oldSettings.fileName().toString(); QString backupName = origName; - if (oldSettings.environmentId() != creatorId()) + if (!oldSettings.environmentId().isEmpty() && oldSettings.environmentId() != creatorId()) backupName += QLatin1String(".") + QString::fromLatin1(oldSettings.environmentId()).mid(1, 7); if (oldSettings.version() != currentVersion()) { if (m_handlers.contains(oldSettings.version())) @@ -774,7 +774,7 @@ SettingsAccessor::SettingsData SettingsAccessor::readUserSettings() const "

All settings files were either too new or too " "old to be read.

"), QMessageBox::Ok); - } else if (result.environmentId() != creatorId()) { + } else if (!result.environmentId().isEmpty() && result.environmentId() != creatorId()) { // Wrong environment! QMessageBox msgBox( QMessageBox::Question, @@ -873,7 +873,7 @@ SettingsAccessor::SettingsData SettingsAccessor::findBestSettings(const QStringL continue; } - if (!tmp.environmentId().isEmpty() && tmp.environmentId() == creatorId()) { + if (tmp.environmentId().isEmpty() || tmp.environmentId() == creatorId()) { if (tmp.version() > newestMatching.version()) newestMatching = tmp; } else { From 893b1e9a16a64ed5444fcc587ee8d97bf373fb6c Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 25 Jun 2013 23:32:39 +0300 Subject: [PATCH 20/48] Git: Support commit.template under ~ Task-number: QTCREATORBUG-9530 Change-Id: I21ee4202aa750a9d4d89f05d51af7c63489eb6c3 Reviewed-by: Eike Ziller --- src/plugins/git/gitclient.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 155769d995f..d8d279ee1d0 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2686,8 +2686,11 @@ bool GitClient::getCommitData(const QString &workingDirectory, QString templateFilename = gitDirectory.absoluteFilePath(QLatin1String("MERGE_MSG")); if (!QFile::exists(templateFilename)) templateFilename = gitDirectory.absoluteFilePath(QLatin1String("SQUASH_MSG")); - if (!QFile::exists(templateFilename)) - templateFilename = readConfigValue(workingDirectory, QLatin1String("commit.template")); + if (!QFile::exists(templateFilename)) { + Utils::FileName templateName = Utils::FileName::fromUserInput( + readConfigValue(workingDirectory, QLatin1String("commit.template"))); + templateFilename = templateName.toString(); + } if (!templateFilename.isEmpty()) { // Make relative to repository const QFileInfo templateFileInfo(templateFilename); From f621ee5bc4aa144e4c907d38762fa7cf72e7a07a Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Wed, 26 Jun 2013 22:26:29 +0300 Subject: [PATCH 21/48] Git: Diff current file against index Task-number: QTCREATORBUG-9663 Change-Id: I18b4ec5577bf0114075141583c938eaa02d5eded Reviewed-by: Jarek Kobus --- src/plugins/git/gitclient.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index d8d279ee1d0..4ffe6021d6e 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -118,8 +118,8 @@ public: // index -> working tree void diffFile(const QString &fileName); - // stagedFileNames - files in index, diff will compare the state in HEAD to the one in the index - // unstagedFileNames - diff will compare the state in the index to the one in the working tree + // stagedFileNames: HEAD -> index + // unstagedFileNames: index -> working tree void diffFiles(const QStringList &stagedFileNames, const QStringList &unstagedFileNames); // index -> working tree void diffProjects(const QStringList &projectPaths); @@ -191,7 +191,7 @@ GitDiffHandler::GitDiffHandler(DiffEditor::DiffEditor *editor, void GitDiffHandler::diffFile(const QString &fileName) { m_requestedRevisionRange = RevisionRange( - Revision(Other, QLatin1String(HEAD)), + Revision(Index), Revision(WorkingTree)); collectFilesList(QStringList() << QLatin1String("--") << fileName); @@ -201,7 +201,7 @@ void GitDiffHandler::diffFiles(const QStringList &stagedFileNames, const QString { RevisionRange stagedRange = RevisionRange( Revision(Other, QLatin1String(HEAD)), - Revision(WorkingTree)); + Revision(Index)); RevisionRange unstagedRange = RevisionRange( Revision(Index), Revision(WorkingTree)); @@ -219,7 +219,7 @@ void GitDiffHandler::diffFiles(const QStringList &stagedFileNames, const QString void GitDiffHandler::diffProjects(const QStringList &projectPaths) { m_requestedRevisionRange = RevisionRange( - Revision(Other, QLatin1String(HEAD)), + Revision(Index), Revision(WorkingTree)); collectFilesList(QStringList() << QLatin1String("--") << projectPaths); @@ -228,7 +228,7 @@ void GitDiffHandler::diffProjects(const QStringList &projectPaths) void GitDiffHandler::diffRepository() { m_requestedRevisionRange = RevisionRange( - Revision(Other, QLatin1String(HEAD)), + Revision(Index), Revision(WorkingTree)); collectFilesList(QStringList()); From 2b3d38b4262f51b55c5fbedc0712913dab731fb1 Mon Sep 17 00:00:00 2001 From: jkobus Date: Mon, 1 Jul 2013 11:38:16 +0200 Subject: [PATCH 22/48] DiffEditor: double click doesn't select the current word Task-number: QTCREATORBUG-9381 Change-Id: Icc96c31b029d978c23a44fca59bcc28891fd92c6 Reviewed-by: Orgad Shaneh --- src/plugins/diffeditor/diffeditorwidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/diffeditor/diffeditorwidget.cpp b/src/plugins/diffeditor/diffeditorwidget.cpp index 98b003a5be7..48c30433fba 100644 --- a/src/plugins/diffeditor/diffeditorwidget.cpp +++ b/src/plugins/diffeditor/diffeditorwidget.cpp @@ -418,6 +418,8 @@ void DiffViewEditorWidget::mouseDoubleClickEvent(QMouseEvent *e) if (e->button() == Qt::LeftButton && !(e->modifiers() & Qt::ShiftModifier)) { QTextCursor cursor = cursorForPosition(e->pos()); jumpToOriginalFile(cursor); + e->accept(); + return; } SnippetEditorWidget::mouseDoubleClickEvent(e); } From 0292600c729886fb20ba79c1efabaf960c67ba4b Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 28 Jun 2013 14:04:05 +0200 Subject: [PATCH 23/48] Debugger: Work on dumper without debug info Change-Id: Iae5f60fe43c28f4cf0254b87530002145dc67e27 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 34 +++++--- share/qtcreator/dumper/lbridge.py | 16 ++-- share/qtcreator/dumper/qttypes.py | 115 +++++++++++++++------------- tests/auto/debugger/tst_dumpers.cpp | 2 +- 4 files changed, 95 insertions(+), 72 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index c137b1840eb..80bbd9e6fb1 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -29,12 +29,6 @@ def directBaseClass(typeobj, index = 0): # FIXME: Check it's really a base. return typeobj.fields()[index] -def createPointerValue(context, address, pointeeType): - return gdb.Value(address).cast(pointeeType.pointer()) - -def createReferenceValue(context, address, referencedType): - return gdb.Value(address).cast(referencedType.pointer()).dereference() - def savePrint(output): try: print(output) @@ -1548,12 +1542,34 @@ class Dumper: def voidPtrType(self): return self.lookupType('void*') - def voidPtrSize(self): - return self.voidPtrType().sizeof - def addressOf(self, value): return long(value.address) + def createPointerValue(self, address, pointeeType): + return gdb.Value(address).cast(pointeeType.pointer()) + + def intSize(self): + return 4 + + def ptrSize(self): + return self.lookupType('void*').sizeof + + def createValue(self, address, referencedType): + return gdb.Value(address).cast(referencedType.pointer()).dereference() + + # Returns the address stored at another address. + def derefAddress(self, addr): + return long(gdb.Value(addr).cast(self.voidPtrType())) + + def dereference(self, addr): + return long(gdb.Value(addr).cast(self.voidPtrType().pointer()).dereference()) + + def extractInt(self, addr): + return long(gdb.Value(addr).cast(self.intPtrType()).dereference()) + + def dereferenceValue(self, value): + return self.dereference(value.address) + def isQObject(self, value): entryType = self.lookupType("int").pointer().pointer() try: diff --git a/share/qtcreator/dumper/lbridge.py b/share/qtcreator/dumper/lbridge.py index 8fc10117da4..222e11cdda9 100644 --- a/share/qtcreator/dumper/lbridge.py +++ b/share/qtcreator/dumper/lbridge.py @@ -252,14 +252,6 @@ Value = lldb.SBValue def pointerValue(value): return value.GetValueAsUnsigned() -def createPointerValue(context, address, pointeeType): - addr = int(address) & 0xFFFFFFFFFFFFFFFF - return context.CreateValueFromAddress(None, addr, pointeeType).AddressOf() - -def createReferenceValue(context, address, referencedType): - addr = int(address) & 0xFFFFFFFFFFFFFFFF - return context.CreateValueFromAddress(None, addr, referencedType) - def impl_SBValue__add__(self, offset): if self.GetType().IsPointerType(): if isinstance(offset, int) or isinstance(offset, long): @@ -751,6 +743,14 @@ class Dumper: def parseAndEvalute(self, expr): return expr + def createPointerValue(self, address, pointeeType): + addr = int(address) & 0xFFFFFFFFFFFFFFFF + return self.context.CreateValueFromAddress(None, addr, pointeeType).AddressOf() + + def createValue(self, address, referencedType): + addr = int(address) & 0xFFFFFFFFFFFFFFFF + return self.context.CreateValueFromAddress(None, addr, referencedType) + def putCallItem(self, name, value, func, *args): result = call2(value, func, args) with SubItem(self, name): diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index 51ac36de56b..df6075d4a6c 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -18,6 +18,7 @@ movableTypes = set([ "QXmlStreamNotationDeclaration", "QXmlStreamEntityDeclaration" ]) + def checkSimpleRef(ref): count = int(ref["_q_value"]) check(count > 0) @@ -34,37 +35,34 @@ def checkRef(ref): check(count >= minimum) check(count < 1000000) -def qByteArrayDataData(d, value): - intType = d.intType() - base = d.addressOf(value) +def qByteArrayDataData(d, addr): + intSize = d.intSize() + ptrSize = d.ptrSize() if d.qtVersion() >= 0x050000: # QTypedArray: # - QtPrivate::RefCount ref # - int size # - uint alloc : 31, capacityReserved : 1 # - qptrdiff offset - size = int(createReferenceValue(value, base + intType.sizeof, intType)) - alloc = int(createReferenceValue(value, base + 2 * intType.sizeof, intType)) \ - & 0x7ffffff - data = base + pointerValue(createReferenceValue(value, - base + 2 * intType.sizeof + intType.pointer().sizeof, - d.charPtrType())) + size = d.extractInt(addr + intSize) + alloc = d.extractInt(addr + 2 * intSize) & 0x7ffffff + data = addr + d.dereference(addr + 2 * intSize + ptrSize) else: # Data: # - QBasicAtomicInt ref; # - int alloc, size; # - char *data; # - char array[1]; - alloc = int(createReferenceValue(value, base + intType.sizeof, intType)) - size = int(createReferenceValue(value, base + 2 * intType.sizeof, intType)) - data = pointerCbase + 3 * intType.sizeof + intType.pointer().sizeof + alloc = d.extractInt(addr + intSize) + size = d.extractInt(addr + 2 * intSize) + data = addr + 3 * intSize + ptrSize return data, size, alloc -def qByteArrayData(d, value): - return d.byteArrayDataData(value['d'].dereference()) +def qByteArrayData(d, addr): + return qByteArrayDataData(d, d.derefAddress(addr)) -def qEncodeByteArray(d, value, limit = None): - data, size, alloc = d.byteArrayData(value) +def qEncodeByteArray(d, addr, limit = None): + data, size, alloc = d.byteArrayData(addr) if alloc != 0: check(0 <= size and size <= alloc and alloc <= 100*1000*1000) limit = d.computeLimit(size, limit) @@ -73,8 +71,8 @@ def qEncodeByteArray(d, value, limit = None): s += "2e2e2e" return s -def qEncodeString(d, value, limit = 0): - data, size, alloc = d.stringData(value) +def qEncodeString(d, addr, limit = 0): + data, size, alloc = qByteArrayData(d, addr) if alloc != 0: check(0 <= size and size <= alloc and alloc <= 100*1000*1000) limit = d.computeLimit(size, limit) @@ -118,21 +116,20 @@ Dumper.putStringValue = \ lambda d, value: d.putValue(d.encodeString(value), Hex4EncodedLittleEndian) Dumper.encodeString = qEncodeString -Dumper.stringData = Dumper.byteArrayData +Dumper.stringData = qByteArrayData Dumper.putMapName = qPutMapName Dumper.isMapCompact = \ lambda d, keyType, valueType: qMapCompact(d.currentItemFormat(), keyType, valueType) -def putQObjectNameValue(d, value): +def qPutQObjectNameValue(d, value): try: - intType = d.lookupType("int") - ptrType = intType.pointer() + intSize = d.intSize() + ptrSize = d.ptrSize() # dd = value["d_ptr"]["d"] is just behind the vtable. - dd = createReferenceValue(value, d.addressOf(value) + ptrType.sizeof, ptrType) + dd = d.dereference(d.addressOf(value) + ptrSize) - objectName = None if d.qtVersion() < 0x050000: # Size of QObjectData: 5 pointer + 2 int # - vtable @@ -146,9 +143,8 @@ def putQObjectNameValue(d, value): # Offset of objectName in QObjectPrivate: 5 pointer + 2 int # - [QObjectData base] # - QString objectName - objectName = createReferenceValue(value, - pointerValue(dd) + 5 * ptrType.sizeof + 2 * intType.sizeof, - d.lookupType(d.ns + "QString")) + objectName = d.dereference(dd + 5 * ptrSize + 2 * intSize) + else: # Size of QObjectData: 5 pointer + 2 int # - vtable @@ -158,8 +154,9 @@ def putQObjectNameValue(d, value): # - uint isWidget : 1; etc... # - int postedEvents; # - QDynamicMetaObjectData *metaObject; - offset = 5 * ptrType.sizeof + 2 * intType.sizeof - extra = createReferenceValue(value, pointerValue(dd) + offset, ptrType) + extra = d.dereference(dd + 5 * ptrSize + 2 * intSize) + if extra == 0: + return # Offset of objectName in ExtraData: 6 pointer # - QVector userData; only #ifndef QT_NO_USERDATA @@ -168,20 +165,17 @@ def putQObjectNameValue(d, value): # - QVector runningTimers; # - QList > eventFilters; # - QString objectName - if pointerValue(extra): - objectName = createReferenceValue(value, - pointerValue(extra) + 5 * ptrType.sizeof, - d.lookupType(d.ns + "QString")) + objectName = d.dereference(extra + 5 * ptrSize) + + data, size, alloc = d.stringData(objectName) + if size > 0: + str = d.readRawMemory(data, 2 * size) + d.putValue(str, Hex4EncodedLittleEndian, 1) - if not objectName is None: - data, size, alloc = d.stringData(objectName) - if size > 0: - str = d.readRawMemory(data, 2 * size) - d.putValue(str, Hex4EncodedLittleEndian, 1) except: pass -Dumper.putQObjectNameValue = putQObjectNameValue +Dumper.putQObjectNameValue = qPutQObjectNameValue ################################################################################### @@ -403,12 +397,10 @@ def qdump__QTime(d, value): # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): - intType = d.lookupType("int") - intPtrType = intType.pointer() - base = pointerValue(value.cast(intPtrType)) - mds = int(createReferenceValue(value, base + intPtrType.sizeof + 8, intType)) + base = d.dereferenceValue(value) + mds = d.extractInt(base + d.ptrSize() + 8) if mds >= 0: - jd = int(createReferenceValue(value, base + intPtrType.sizeof, intType)) + jd = d.extractInt(base + d.ptrSize()) d.putValue("%s/%s" % (jd, mds), JulianDateAndMillisecondsSinceMidnight) d.putNumChild(1) if d.isExpanded(): @@ -737,15 +729,15 @@ def qdump__QList(d, value): addr = d.addressOf(array) + begin * stepSize if isInternal: if innerSize == stepSize: - p = createPointerValue(value, addr, innerType) + p = d.createPointerValue(addr, innerType) d.putArrayData(innerType, p, size) else: with Children(d, size, childType=innerType): for i in d.childRange(): - p = createPointerValue(value, addr + i * stepSize, innerType) - d.putSubItem(i, p.dereference()) + p = d.createValue(addr + i * stepSize, innerType) + d.putSubItem(i, p) else: - p = createPointerValue(value, addr, innerType.pointer()) + p = d.createPointerValue(addr, innerType.pointer()) # about 0.5s / 1000 items with Children(d, size, maxNumChild=2000, childType=innerType): for i in d.childRange(): @@ -759,7 +751,7 @@ def qdump__QImage(d, value): # This relies on current QImage layout intPtrType = d.lookupType("int").pointer() offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = createReferenceValue(value, d.addressOf(value) + offset, intPtrType) + base = d.createValue(d.addressOf(value) + offset, intPtrType) width = int(base[1]) height = int(base[2]) d.putValue("(%dx%d)" % (width, height)) @@ -1438,7 +1430,7 @@ def qdump__QObject(d, value): def qdump__QPixmap(d, value): intPtrType = d.lookupType("int").pointer() offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = createReferenceValue(value, d.addressOf(value) + offset, intPtrType) + base = d.createValue(d.addressOf(value) + offset, intPtrType) d.putValue("(%dx%d)" % (base[1], base[2])) d.putNumChild(0) @@ -1751,12 +1743,27 @@ def qdump__QUrl(d, value): data = value["d"].dereference() d.putByteArrayValue(data["encodedOriginal"]) else: - data = value["d"].dereference() - str = d.encodeString(data["scheme"]) + # QUrlPrivate: + # - QAtomicInt ref; + # - int port; + # - QString scheme; + # - QString userName; + # - QString password; + # - QString host; + # - QString path; + # - QString query; + # - QString fragment; + schemeAddr = d.dereferenceValue(value) + 2 * d.intSize() + scheme = d.dereference(schemeAddr) + host = d.dereference(schemeAddr + 3 * d.ptrSize()) + path = d.dereference(schemeAddr + 4 * d.ptrSize()) + + str = d.encodeString(scheme) str += "3a002f002f00" - str += d.encodeString(data["host"]) - str += d.encodeString(data["path"]) + str += d.encodeString(host) + str += d.encodeString(path) d.putValue(str, Hex4EncodedLittleEndian) + d.putNumChild(1) if d.isExpanded(): with Children(d): diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index c055e5a39dd..9bb97778270 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -776,7 +776,7 @@ void tst_Dumpers::dumper() "run " + nograb + "\n" "up\n" "python print('@%sS@%s@' % ('N', qtNamespace()))\n" - "bb options:fancy,autoderef,dyntype vars: expanded:" + expanded + " typeformats:\n"; + "bb options:fancy,autoderef,dyntype,pe vars: expanded:" + expanded + " typeformats:\n"; } else { cmds += "run\n"; foreach (const Check &check, data.checks) { From abc6e351b8a151926233b86105ddc200b3bd589d Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 1 Jul 2013 11:43:56 +0200 Subject: [PATCH 24/48] Debugger: Make QImage dumper work with release versions This accidentally also allows non-debug Qt users to reproduce the http://blog.qt.digia.com/blog/2010/04/22/peek-and-poke-vol-3/ smiley drawing. Change-Id: Ica436f55494d012d5516ef9d00d6310f2ac2d4ee Reviewed-by: hjk --- share/qtcreator/dumper/qttypes.py | 77 +++++++++++++++------------ src/plugins/debugger/imageviewer.cpp | 1 + src/plugins/debugger/watchhandler.cpp | 21 +++++--- 3 files changed, 58 insertions(+), 41 deletions(-) diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index df6075d4a6c..b7ad03ca533 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -748,50 +748,57 @@ def qform__QImage(): return "Normal,Displayed" def qdump__QImage(d, value): - # This relies on current QImage layout - intPtrType = d.lookupType("int").pointer() - offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = d.createValue(d.addressOf(value) + offset, intPtrType) - width = int(base[1]) - height = int(base[2]) + # This relies on current QImage layout: + # QImageData: + # - QAtomicInt ref + # - int width, height, depth, nbytes + # - qreal devicePixelRatio (+20) # Assume qreal == double, Qt 5 only + # - QVector colortable (+20 + gap) + # - uchar *data (+20 + gap + ptr) + # [- uchar **jumptable jumptable with Qt 3 suppor] + # - enum format (+20 + gap + 2 * ptr) + + ptrSize = d.ptrSize() + isQt5 = d.qtVersion() >= 0x050000 + offset = (3 if isQt5 else 2) * ptrSize + base = d.dereference(d.addressOf(value) + offset) + width = d.extractInt(base + 4) + height = d.extractInt(base + 8) + nbytes = d.extractInt(base + 16) + pixelRatioSize = 8 if isQt5 else 0 + jumpTableSize = ptrSize if not isQt5 else 0 # FIXME: Assumes Qt3 Support + bits = d.dereference(base + 20 + pixelRatioSize + ptrSize) + iformat = d.extractInt(base + 20 + pixelRatioSize + jumpTableSize + 2 * ptrSize) d.putValue("(%dx%d)" % (width, height)) - d.putNumChild(0) - #d.putNumChild(1) + d.putNumChild(1) if d.isExpanded(): with Children(d): + d.putIntItem("width", width) + d.putIntItem("height", height) + d.putIntItem("nbytes", nbytes) + d.putIntItem("format", iformat) with SubItem(d, "data"): - d.putNoType() + d.putValue("0x%x" % bits) d.putNumChild(0) - d.putValue("size: %s bytes" % nbytes); + d.putType("void *") + format = d.currentItemFormat() if format == 1: d.putDisplay(StopDisplay) elif format == 2: - d_ptr = value["d"] - bits = d_ptr["data"] - nbytes = d_ptr["nbytes"] - if False: - # Take four bytes at a time, this is critical for performance. - # In fact, even four at a time is too slow beyond 100x100 or so. - d.putField("editformat", DisplayImageData) - d.put('%s="' % name) - d.put("%08x" % width) - d.put("%08x" % height) - d.put("%08x" % int(d_ptr["format"])) - p = bits.cast(d.intType().pointer()) - for i in xrange(nbytes / 4): - d.put("%08x" % int(p.dereference())) - p += 1 - d.put('",') - else: - # Write to an external file. Much faster ;-( - file = tempfile.mkstemp(prefix="gdbpy_") - filename = file[1].replace("\\", "\\\\") - p = bits.cast(d.charType().pointer()) - gdb.execute("dump binary memory %s %s %s" % - (filename, cleanAddress(p), cleanAddress(p + nbytes))) - d.putDisplay(DisplayImageFile, " %d %d %d %s" - % (width, height, d_ptr["format"], filename)) + # This is critical for performance. Writing to an external + # file using the following is faster when using GDB. + # file = tempfile.mkstemp(prefix="gdbpy_") + # filename = file[1].replace("\\", "\\\\") + # gdb.execute("dump binary memory %s %s %s" % + # (filename, bits, bits + nbytes)) + # d.putDisplay(DisplayImageFile, " %d %d %d %d %s" + # % (width, height, nbytes, iformat, filename)) + d.putField("editformat", DisplayImageData) + d.put('editvalue="') + d.put('%08x%08x%08x%08x' % (width, height, nbytes, iformat)) + d.put(d.readRawMemory(bits, nbytes)) + d.put('",') def qdump__QLinkedList(d, value): diff --git a/src/plugins/debugger/imageviewer.cpp b/src/plugins/debugger/imageviewer.cpp index db7f722e4a8..26d96ad406b 100644 --- a/src/plugins/debugger/imageviewer.cpp +++ b/src/plugins/debugger/imageviewer.cpp @@ -69,6 +69,7 @@ void ImageWidget::setImage(const QImage &image) { setFixedSize(image.size() + QSize(2, 2)); m_image = image; + update(); } void ImageWidget::mousePressEvent(QMouseEvent *ev) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index f400a431296..0616add575f 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1679,28 +1679,37 @@ void WatchHandler::showEditValue(const WatchData &data) showSeparateWidget(l); m_model->m_editHandlers[key] = l; } - int width = 0, height = 0, format = 0; + int width = 0, height = 0, nbytes = 0, format = 0; QByteArray ba; uchar *bits = 0; if (data.editformat == DisplayImageData) { ba = QByteArray::fromHex(data.editvalue); + QTC_ASSERT(ba.size() > 16, return); const int *header = (int *)(ba.data()); if (!ba.at(0) && !ba.at(1)) // Check on 'width' for Python dumpers returning 4-byte swapped-data. - swapEndian(ba.data(), ba.size()); - bits = 12 + (uchar *)(ba.data()); + swapEndian(ba.data(), 16); + bits = 16 + (uchar *)(ba.data()); width = header[0]; height = header[1]; - format = header[2]; + nbytes = header[2]; + format = header[3]; } else if (data.editformat == DisplayImageFile) { QTextStream ts(data.editvalue); QString fileName; - ts >> width >> height >> format >> fileName; + ts >> width >> height >> nbytes >> format >> fileName; QFile f(fileName); f.open(QIODevice::ReadOnly); ba = f.readAll(); bits = (uchar*)ba.data(); + nbytes = width * height; } - l->setImage(QImage(bits, width, height, QImage::Format(format))); + QTC_ASSERT(0 < width && width < 10000, return); + QTC_ASSERT(0 < height && height < 10000, return); + QTC_ASSERT(0 < nbytes && nbytes < 10000 * 10000, return); + QTC_ASSERT(0 < format && format < 32, return); + QImage im(width, height, QImage::Format(format)); + qMemCopy(im.bits(), bits, nbytes); + l->setImage(im); showSeparateWidget(l); } break; From 32217a0c3cf6c469219399771be6485ca3870074 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 1 Jul 2013 16:22:45 +0300 Subject: [PATCH 25/48] Git: Move static strings out of GitClient class They're only used in gitclient.cpp, define them there Change-Id: I601f23a6f2a8e533127d2ed068526815e1b9717d Reviewed-by: hjk --- src/plugins/git/gitclient.cpp | 10 ++++------ src/plugins/git/gitclient.h | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 4ffe6021d6e..0f0041026ff 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -76,7 +76,8 @@ static const char GIT_DIRECTORY[] = ".git"; static const char graphLogFormatC[] = "%h %d %an %s %ci"; static const char HEAD[] = "HEAD"; - +static const char noColorOption[] = "--no-color"; +static const char decorateOption[] = "--decorate"; namespace Git { namespace Internal { @@ -791,9 +792,6 @@ GitClient::~GitClient() { } -const char *GitClient::noColorOption = "--no-color"; -const char *GitClient::decorateOption = "--decorate"; - QString GitClient::findRepositoryForDirectory(const QString &dir) { if (dir.isEmpty() || dir.endsWith(QLatin1String("/.git")) @@ -1308,7 +1306,7 @@ bool GitClient::synchronousLog(const QString &workingDirectory, const QStringLis QByteArray outputText; QByteArray errorText; QStringList allArguments; - allArguments << QLatin1String("log") << QLatin1String(GitClient::noColorOption); + allArguments << QLatin1String("log") << QLatin1String(noColorOption); allArguments.append(arguments); const bool rc = fullySynchronousGit(workingDirectory, allArguments, &outputText, &errorText); if (rc) { @@ -1786,7 +1784,7 @@ QString GitClient::synchronousShortDescription(const QString &workingDirectory, QByteArray outputTextData; QByteArray errorText; QStringList arguments; - arguments << QLatin1String("log") << QLatin1String(GitClient::noColorOption) + arguments << QLatin1String("log") << QLatin1String(noColorOption) << (QLatin1String("--pretty=format:") + format) << QLatin1String("--max-count=1") << revision; const bool rc = fullySynchronousGit(workingDirectory, arguments, &outputTextData, &errorText); diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 6a9d0f6516c..faf39964683 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -313,9 +313,6 @@ public: static QString msgNoChangedFiles(); static QString msgNoCommits(bool includeRemote); - static const char *noColorOption; - static const char *decorateOption; - public slots: void show(const QString &source, const QString &id, const QStringList &args = QStringList(), const QString &name = QString()); From 5f131da1669351a5a1b20b54d2ce65f18d08f39b Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 1 Jul 2013 16:22:54 +0300 Subject: [PATCH 26/48] DiffEditor: Show tags and branches in Show pane Change-Id: I39be7c3fb9b57b133c4da3639813527aa280ae33 Reviewed-by: Jarek Kobus --- src/plugins/git/gitclient.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 0f0041026ff..cccabafd1f1 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -259,7 +259,8 @@ void GitDiffHandler::collectShowDescription(const QString &id) VcsBase::Command *command = new VcsBase::Command(m_gitPath, m_workingDirectory, m_processEnvironment); connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(slotShowDescriptionReceived(QByteArray))); QStringList arguments; - arguments << QLatin1String("show") << QLatin1String("-s") << QLatin1String("--format=fuller") << id; + arguments << QLatin1String("show") << QLatin1String("-s") << QLatin1String("--format=fuller") + << QLatin1String(noColorOption) << QLatin1String(decorateOption) << id; command->addJob(arguments, m_timeout); command->execute(); } From 00337585ab9c8faa0cfae3f6ca480f7832ae5f4a Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 1 Jul 2013 23:20:55 +0300 Subject: [PATCH 27/48] Git: Add some null protections Change-Id: Ia28c70690c6f79499fb8075935ec123b763bcc01 Reviewed-by: Jarek Kobus --- src/plugins/git/gitclient.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index cccabafd1f1..d23b76add44 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -255,6 +255,8 @@ void GitDiffHandler::show(const QString &id) void GitDiffHandler::collectShowDescription(const QString &id) { + if (m_editor.isNull()) + return; m_editor->clear(m_waitMessage); VcsBase::Command *command = new VcsBase::Command(m_gitPath, m_workingDirectory, m_processEnvironment); connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(slotShowDescriptionReceived(QByteArray))); @@ -267,12 +269,13 @@ void GitDiffHandler::collectShowDescription(const QString &id) void GitDiffHandler::slotShowDescriptionReceived(const QByteArray &data) { + if (m_editor.isNull()) + return; const QString description = m_editor->editorWidget()->codec()->toUnicode(data).remove(QLatin1Char('\r')); DiffEditor::DiffShowEditor *editor = qobject_cast(m_editor); - if (editor) { + if (editor) editor->setDescription(description); - } collectFilesList(QStringList() << m_requestedRevisionRange.begin.id @@ -281,6 +284,8 @@ void GitDiffHandler::slotShowDescriptionReceived(const QByteArray &data) void GitDiffHandler::collectFilesList(const QStringList &additionalArguments) { + if (m_editor.isNull()) + return; m_editor->clear(m_waitMessage); VcsBase::Command *command = new VcsBase::Command(m_gitPath, m_workingDirectory, m_processEnvironment); connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(slotFileListReceived(QByteArray))); From ec0fb652c53ad6503a9a9f671fc0f99f6fe6bf7f Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 1 Jul 2013 14:29:00 +0200 Subject: [PATCH 28/48] Debugger: Make more dumper work without debuginfo Change-Id: I2ff23b81dc27be1052c36cffb7ad16dbea6fa339 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 33 ++++++++++++++---- share/qtcreator/dumper/qttypes.py | 38 +++++++++++++-------- tests/auto/debugger/tst_dumpers.cpp | 52 ++++++++++++++++++----------- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index 80bbd9e6fb1..18f3eac73f0 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -1320,6 +1320,7 @@ class Dumper: self.formats = {} self.useDynamicType = True self.expandedINames = {} + self.childEventAddress = None def __init__(self, args): self.defaultInit() @@ -1571,18 +1572,36 @@ class Dumper: return self.dereference(value.address) def isQObject(self, value): - entryType = self.lookupType("int").pointer().pointer() try: - vtable = createReferenceValue(value, value.address, entryType) - metaObjectEntry = vtable.dereference() # It's the first entry. - return str(metaObjectEntry).find("::metaObject() const") > 0 + #if True: + vtable = self.dereference(long(value.address)) # + ptrSize + metaObjectEntry = self.dereference(vtable) # It's the first entry. + warn("MO: 0x%x " % metaObjectEntry) + s = gdb.execute("info symbol 0x%x" % metaObjectEntry, to_string=True) + warn("S: %s " % s) + #return s.find("::metaObject() const") > 0 + return s.find("::metaObject() const") > 0 or s.find("10metaObjectEv") > 0 + #return str(metaObjectEntry).find("::metaObject() const") > 0 except: return False + + def isQObject_B(self, value): # Alternative: Check for specific values, like targeting the # 'childEvent' member which is typically not overwritten, slot 8. - # entry = pointerValue(vtable) + 8 * ptrType.sizeof - # childEventEntry = createReferenceValue(value, entry, ptrType) - #warn("CHILDEVENT: %s " % childEventEntry) + # ~"Symbol \"Myns::QObject::childEvent(Myns::QChildEvent*)\" is a + # function at address 0xb70f691a.\n" + if self.childEventAddress == None: + try: + loc = gdb.execute("info address ::QObject::childEvent", to_string=True) + self.childEventAddress = long(loc[loc.rfind(' '):-2], 16) + except: + self.childEventAddress = 0 + + try: + vtable = self.dereference(long(value.address)) + return self.childEventAddress == self.dereference(vtable + 8 * self.ptrSize()) + except: + return False def put(self, value): self.output.append(value) diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index b7ad03ca533..af2422feb4b 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -51,11 +51,11 @@ def qByteArrayDataData(d, addr): # Data: # - QBasicAtomicInt ref; # - int alloc, size; + # - [padding] # - char *data; - # - char array[1]; alloc = d.extractInt(addr + intSize) size = d.extractInt(addr + 2 * intSize) - data = addr + 3 * intSize + ptrSize + data = d.dereference(addr + 2 * intSize + ptrSize) return data, size, alloc def qByteArrayData(d, addr): @@ -168,6 +168,7 @@ def qPutQObjectNameValue(d, value): objectName = d.dereference(extra + 5 * ptrSize) data, size, alloc = d.stringData(objectName) + if size > 0: str = d.readRawMemory(data, 2 * size) d.putValue(str, Hex4EncodedLittleEndian, 1) @@ -398,9 +399,17 @@ def qdump__QTime(d, value): # {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): base = d.dereferenceValue(value) - mds = d.extractInt(base + d.ptrSize() + 8) + # QDateTimePrivate: + # - QAtomicInt ref; + # - [QDate date;] (+4) + # - - uint jd in Qt 4, qint64 in Qt 5 + # - [QTime time;] (+4 + dateSize) + # - - uint mds; + # - Spec spec; + dateSize = 8 if d.qtVersion() >= 0x050000 else 4 + mds = d.extractInt(base + 4 + dateSize) if mds >= 0: - jd = d.extractInt(base + d.ptrSize()) + jd = d.extractInt(base + 4) d.putValue("%s/%s" % (jd, mds), JulianDateAndMillisecondsSinceMidnight) d.putNumChild(1) if d.isExpanded(): @@ -412,12 +421,12 @@ def qdump__QDateTime(d, value): qtdate += "DateFormat::" # FIXME: Bug?... qttime += "TimeSpec::" # FIXME: Bug?... d.putCallItem("toTime_t", value, "toTime_t") - d.putCallItem("toString", value, "toString", qtdate + "TextDate") - d.putCallItem("(ISO)", value, "toString", qtdate + "ISODate") - d.putCallItem("(SystemLocale)", value, "toString", qtdate + "SystemLocaleDate") - d.putCallItem("(Locale)", value, "toString", qtdate + "LocaleDate") - d.putCallItem("toUTC", value, "toTimeSpec", qttime + "UTC") - d.putCallItem("toLocalTime", value, "toTimeSpec", qttime + "LocalTime") + #d.putCallItem("toString", value, "toString", qtdate + "TextDate") + #d.putCallItem("(ISO)", value, "toString", qtdate + "ISODate") + #d.putCallItem("(SystemLocale)", value, "toString", qtdate + "SystemLocaleDate") + #d.putCallItem("(Locale)", value, "toString", qtdate + "LocaleDate") + #d.putCallItem("toUTC", value, "toTimeSpec", qttime + "UTC") + #d.putCallItem("toLocalTime", value, "toTimeSpec", qttime + "LocalTime") else: d.putValue("(invalid)") d.putNumChild(0) @@ -1435,10 +1444,11 @@ def qdump__QObject(d, value): # } def qdump__QPixmap(d, value): - intPtrType = d.lookupType("int").pointer() - offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = d.createValue(d.addressOf(value) + offset, intPtrType) - d.putValue("(%dx%d)" % (base[1], base[2])) + offset = (3 if d.qtVersion() >= 0x050000 else 2) * d.ptrSize() + base = d.dereference(d.addressOf(value) + offset) + width = d.extractInt(base + 4) + height = d.extractInt(base + 8) + d.putValue("(%dx%d)" % (width, height)) d.putNumChild(0) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 9bb97778270..227aa28c4c8 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -545,9 +545,9 @@ private: void tst_Dumpers::initTestCase() { m_debuggerBinary = qgetenv("QTC_DEBUGGER_PATH_FOR_TEST"); - if (m_debuggerBinary.isEmpty()) m_debuggerBinary = "gdb"; + qDebug() << "Debugger : " << m_debuggerBinary.constData(); m_debuggerEngine = DumpTestGdbEngine; if (m_debuggerBinary.endsWith("cdb.exe")) @@ -559,6 +559,7 @@ void tst_Dumpers::initTestCase() m_qmakeBinary = qgetenv("QTC_QMAKE_PATH_FOR_TEST"); if (m_qmakeBinary.isEmpty()) m_qmakeBinary = "qmake"; + qDebug() << "QMake : " << m_qmakeBinary.constData(); Environment utilsEnv = Environment::systemEnvironment(); utilsEnv.appendOrSet(QLatin1String("QT_HASH_SEED"), QLatin1String("0")); @@ -574,8 +575,8 @@ void tst_Dumpers::initTestCase() QByteArray output = debugger.readAllStandardOutput(); //qDebug() << "stdout: " << output; m_usePython = !output.contains("Python scripting is not supported in this copy of GDB"); - qDebug() << (m_usePython ? "Python is available" : "Python is not available"); - qDebug() << "Dumper dir: " << DUMPERDIR; + qDebug() << "Python : " << (m_usePython ? "ok" : "*** not ok ***"); + qDebug() << "Dumper dir : " << DUMPERDIR; QString version = QString::fromLocal8Bit(output); int pos1 = version.indexOf(QLatin1String("&\"show version\\n")); @@ -587,7 +588,7 @@ void tst_Dumpers::initTestCase() version = version.mid(pos1, pos2 - pos1); extractGdbVersion(version, &m_gdbVersion, &m_gdbBuildVersion, &m_isMacGdb, &m_isQnxGdb); - qDebug() << "Gdb version " << m_gdbVersion; + qDebug() << "Gdb version : " << m_gdbVersion; } else if (m_debuggerEngine == DumpTestCdbEngine) { QByteArray envBat = qgetenv("QTC_MSVC_ENV_BAT"); QMap envPairs; @@ -1116,20 +1117,23 @@ void tst_Dumpers::dumper_data() QTest::newRow("QDateTime0") << Data("#include \n", - "QDateTime date;\n") + "QDateTime date;\n" + "unused(&date);\n") % CoreProfile() % Check("date", "(invalid)", "@QDateTime"); QTest::newRow("QDateTime1") << Data("#include \n", - "QDateTime date(QDate(1980, 1, 1), QTime(13, 15, 32), Qt::UTC);\n") + "QDateTime date(QDate(1980, 1, 1), QTime(13, 15, 32), Qt::UTC);\n" + "unused(&date);\n") % CoreProfile() % Check("date", "Tue Jan 1 13:15:32 1980", "@QDateTime") - % Check("date.(ISO)", "\"1980-01-01T13:15:32Z\"", "@QString") - % CheckType("date.(Locale)", "@QString") - % CheckType("date.(SystemLocale)", "@QString") - % Check("date.toString", "\"Tue Jan 1 13:15:32 1980\"", "@QString") - % Check("date.toUTC", "Tue Jan 1 13:15:32 1980", "@QDateTime"); + //% Check("date.(ISO)", "\"1980-01-01T13:15:32Z\"", "@QString") + //% CheckType("date.(Locale)", "@QString") + //% CheckType("date.(SystemLocale)", "@QString") + //% Check("date.toString", "\"Tue Jan 1 13:15:32 1980\"", "@QString") + //% Check("date.toUTC", "Tue Jan 1 13:15:32 1980", "@QDateTime" + % Check("date.toTime_t", "315580532", "unsigned int"); #ifdef Q_OS_WIN QByteArray tempDir = "\"C:/Program Files\""; @@ -3111,16 +3115,17 @@ void tst_Dumpers::dumper_data() % Check("anc", "1", "int"); QTest::newRow("QThread1") - << Data("#include \n", + << Data("#include \n" "struct Thread : QThread\n" "{\n" + " virtual ~Thread() {}\n" " void run()\n" " {\n" " if (m_id == 3)\n" " breakHere();\n" " }\n" " int m_id;\n" - "};\n" + "};\n", "const int N = 14;\n" "Thread thread[N];\n" "for (int i = 0; i != N; ++i) {\n" @@ -3128,9 +3133,10 @@ void tst_Dumpers::dumper_data() " thread[i].setObjectName(\"This is thread #\" + QString::number(i));\n" " thread[i].start();\n" "}\n") - % CheckType("this", "Thread") - % Check("this.@1", "[@QThread]", "\"This is thread #3\"", "@QThread") - % Check("this.@1.@1", "[@QObject]", "\"This is thread #3\"", "@QObject"); + % CoreProfile() + % CheckType("this", "Thread") + % Check("this.@1", "[@QThread]", "\"This is thread #3\"", "@QThread") + % Check("this.@1.@1", "[@QObject]", "\"This is thread #3\"", "@QObject"); QTest::newRow("QVariant1") << Data("#include \n", @@ -3249,6 +3255,7 @@ void tst_Dumpers::dumper_data() "QVariant var;\n" "var.setValue(my);\n" "breakHere();\n") + % CoreProfile() % Check("my", "<2 items>", "MyType") % Check("my.0", "[0]", "", "@QMapNode") % Check("my.0.key", "1", "unsigned int") @@ -3297,6 +3304,7 @@ void tst_Dumpers::dumper_data() "vl.append(QVariant(21));\n" "vl.append(QVariant(22));\n" "vl.append(QVariant(\"2Some String\"));\n") + % CoreProfile() % Check("vl", "<6 items>", "@QVariantList") % CheckType("vl.0", "[0]", "@QVariant (int)") % CheckType("vl.2", "[2]", "@QVariant (QString)"); @@ -3310,6 +3318,7 @@ void tst_Dumpers::dumper_data() "vm[\"d\"] = QVariant(21);\n" "vm[\"e\"] = QVariant(22);\n" "vm[\"f\"] = QVariant(\"2Some String\");\n") + % CoreProfile() % Check("vm", "<6 items>", "@QVariantMap") % Check("vm.0", "[0]", "", "@QMapNode<@QString, @QVariant>") % Check("vm.0.key", Value4("\"a\""), "@QString") @@ -3318,15 +3327,16 @@ void tst_Dumpers::dumper_data() % Check("vm.0.value", Value5("2"), "@QVariant (int)") % Check("vm.5", "[5]", "", "@QMapNode<@QString, @QVariant>") % Check("vm.5.key", Value4("\"f\""), "@QString") - % Check("vm.5.value", Value4("\"2Some String\""), "@QVariant (@QString)") + % Check("vm.5.value", Value4("\"2Some String\""), "@QVariant (QString)") % Check("vm.5.key", Value5("\"f\""), "@QString") - % Check("vm.5.value", Value5("\"2Some String\""), "@QVariant (@QString)"); + % Check("vm.5.value", Value5("\"2Some String\""), "@QVariant (QString)"); QTest::newRow("QVectorIntBig") << Data("#include \n", "QVector vec(10000);\n" "for (int i = 0; i != vec.size(); ++i)\n" " vec[i] = i * i;\n") + % CoreProfile() % Check("vec", "<10000 items>", "@QVector") % Check("vec.0", "[0]", "0", "int") % Check("vec.1999", "[1999]", "3996001", "int"); @@ -3336,6 +3346,7 @@ void tst_Dumpers::dumper_data() "QVector vec;\n" "vec.append(1);\n" "vec.append(2);\n") + % CoreProfile() % Check("vec", "<2 items>", "@QVector") % Check("vec.0", "[0]", "", "Foo") % Check("vec.0.a", "1", "int") @@ -3348,7 +3359,8 @@ void tst_Dumpers::dumper_data() "FooVector vec;\n" "vec.append(1);\n" "vec.append(2);\n") - % Check("vec", "<2 items>", "@FooVector") + % CoreProfile() + % Check("vec", "<2 items>", "FooVector") % Check("vec.0", "[0]", "", "Foo") % Check("vec.0.a", "1", "int") % Check("vec.1", "[1]", "", "Foo") @@ -4025,7 +4037,7 @@ void tst_Dumpers::dumper_data() "boost::optional sl0, sl;\n" "sl = (QStringList() << \"xxx\" << \"yyy\");\n" "sl.get().append(\"zzz\");\n") - % Check("sl", "<3 items>", "boost::optional"); + % Check("sl", "<3 items>", "boost::optional<@QStringList>"); QTest::newRow("BoostSharedPtr") << Data("#include \n" From dea9672862708e6684319a0ac50b18a4778e1bef Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 2 Jul 2013 09:06:15 +0200 Subject: [PATCH 29/48] Fix translation context of "Attach to process". Task-number: QTCREATORBUG-9712 Change-Id: Ib46e4c91a520044bfa9fb717edecee167b68076e Reviewed-by: hjk --- src/plugins/debugger/debuggerplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index a0a269fcaf3..2495bfca2bf 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1678,7 +1678,7 @@ void DebuggerPluginPrivate::attachToProcess(bool startServerOnly) DebuggerKitChooser::RemoteDebugging : DebuggerKitChooser::LocalDebugging; DebuggerKitChooser *kitChooser = new DebuggerKitChooser(mode); DeviceProcessesDialog *dlg = new DeviceProcessesDialog(kitChooser, mainWindow()); - dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process")); + dlg->addAcceptButton(ProjectExplorer::DeviceProcessesDialog::tr("&Attach to Process")); dlg->showAllDevices(); if (dlg->exec() == QDialog::Rejected) { delete dlg; From cdbbf377432d85f7dba208854d480e0209024d7d Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Mon, 1 Jul 2013 11:35:38 +0200 Subject: [PATCH 30/48] Qt4Project: Do not trigger updateCodeModels on folderChanged This reverts commit 2fdb70bdce77ec0b60847623579af72ddc58da91. Be smarter about what to do on folder changes. Trigger at most one codemodel update per folder change signal. (Thus still fixing the original problem 2fdb70b fixed.) And only trigger one if the actual file list changes. This could be further optimized to only tell the code model about the new files, but that's for another patch. Task-number: QTCREATORBUG-9697 Change-Id: I78d134663f1455254caf812c27c048d4f0828242 Reviewed-by: Fawzi Mohamed Reviewed-by: Nikolai Kosjar Reviewed-by: Eike Ziller --- src/plugins/qt4projectmanager/qt4nodes.cpp | 64 ++++++++++++++++++-- src/plugins/qt4projectmanager/qt4nodes.h | 3 +- src/plugins/qt4projectmanager/qt4project.cpp | 23 +++++-- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 437319ef3d1..8d2efbe0ba8 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -557,7 +557,7 @@ QStringList Qt4PriFileNode::fullVPaths(const QStringList &baseVPaths, QtSupport: return vPaths; } -static QSet recursiveEnumerate(const QString &folder) +QSet Qt4PriFileNode::recursiveEnumerate(const QString &folder) { QSet result; QFileInfo fi(folder); @@ -718,10 +718,66 @@ void Qt4PriFileNode::watchFolders(const QSet &folders) m_watchedFolders = folders; } -void Qt4PriFileNode::folderChanged(const QString &changedFolder) +bool Qt4PriFileNode::folderChanged(const QString &changedFolder, const QSet &newFiles) { - Q_UNUSED(changedFolder); - scheduleUpdate(); + //qDebug()<<"########## Qt4PriFileNode::folderChanged"; + // So, we need to figure out which files changed. + + QSet addedFiles = newFiles; + addedFiles.subtract(m_recursiveEnumerateFiles); + + QSet removedFiles = m_recursiveEnumerateFiles; + removedFiles.subtract(newFiles); + + foreach (const Utils::FileName &file, removedFiles) { + if (!file.isChildOf(Utils::FileName::fromString(changedFolder))) + removedFiles.remove(file); + } + + if (addedFiles.isEmpty() && removedFiles.isEmpty()) + return false; + + m_recursiveEnumerateFiles = newFiles; + + // Apply the differences + // per file type + const QVector &fileTypes = qt4NodeStaticData()->fileTypeData; + for (int i = 0; i < fileTypes.size(); ++i) { + FileType type = fileTypes.at(i).type; + QSet add = filterFilesRecursiveEnumerata(type, addedFiles); + QSet remove = filterFilesRecursiveEnumerata(type, removedFiles); + + if (!add.isEmpty() || !remove.isEmpty()) { + // Scream :) +// qDebug()<<"For type"<type = type; + subfolder->icon = fileTypes.at(i).icon; + subfolder->fullPath = m_projectDir; + subfolder->typeName = fileTypes.at(i).typeName; + subfolder->priority = -i; + subfolder->displayName = fileTypes.at(i).typeName; + contents.virtualfolders.append(subfolder); + // create the hierarchy with subdirectories + subfolder->create(m_projectDir, m_files[type], type); + } + } + + contents.updateSubFolders(this, this); + return true; } bool Qt4PriFileNode::deploysFolder(const QString &folder) const diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index 745b7459667..58ba3bdb89e 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -162,7 +162,7 @@ public: bool renameFile(const FileType fileType, const QString &filePath, const QString &newFilePath); - void folderChanged(const QString &changedFolder); + bool folderChanged(const QString &changedFolder, const QSet &newFiles); bool deploysFolder(const QString &folder) const; QList runConfigurationsFor(Node *node); @@ -172,6 +172,7 @@ public: // Set by parent bool includedInExactParse() const; + static QSet recursiveEnumerate(const QString &folder); protected: void setIncludedInExactParse(bool b); static QStringList varNames(FileType type); diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 4ba2a96919a..a5ba9339268 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -146,7 +146,7 @@ class CentralizedFolderWatcher : public QObject { Q_OBJECT public: - CentralizedFolderWatcher(QObject *parent); + CentralizedFolderWatcher(Qt4Project *parent); ~CentralizedFolderWatcher(); void watchFolders(const QList &folders, Qt4ProjectManager::Qt4PriFileNode *node); void unwatchFolders(const QList &folders, Qt4ProjectManager::Qt4PriFileNode *node); @@ -157,6 +157,7 @@ private slots: void delayedFolderChanged(const QString &folder); private: + Qt4Project *m_project; QSet recursiveDirs(const QString &folder); QFileSystemWatcher m_watcher; QMultiMap m_map; @@ -1215,7 +1216,8 @@ namespace { bool debugCFW = false; } -CentralizedFolderWatcher::CentralizedFolderWatcher(QObject *parent) : QObject(parent) +CentralizedFolderWatcher::CentralizedFolderWatcher(Qt4Project *parent) + : QObject(parent), m_project(parent) { m_compressTimer.setSingleShot(true); m_compressTimer.setInterval(200); @@ -1337,12 +1339,19 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder) QString dir = folder; const QChar slash = QLatin1Char('/'); + bool newOrRemovedFiles = false; while (true) { if (!dir.endsWith(slash)) dir.append(slash); QList nodes = m_map.values(dir); - foreach (Qt4ProjectManager::Qt4PriFileNode *node, nodes) { - node->folderChanged(folder); + if (!nodes.isEmpty()) { + // Collect all the files + QSet newFiles; + newFiles += Qt4PriFileNode::recursiveEnumerate(folder); + foreach (Qt4ProjectManager::Qt4PriFileNode *node, nodes) { + newOrRemovedFiles = newOrRemovedFiles + || node->folderChanged(folder, newFiles); + } } // Chop off last part, and break if there's nothing to chop off @@ -1357,7 +1366,6 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder) dir.truncate(index + 1); } - QString folderWithSlash = folder; if (!folder.endsWith(slash)) folderWithSlash.append(slash); @@ -1374,6 +1382,11 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder) m_watcher.addPaths(tmp.toList()); m_recursiveWatchedFolders += tmp; } + + if (newOrRemovedFiles) { + m_project->updateFileList(); + m_project->updateCodeModels(); + } } bool Qt4Project::needsConfiguration() const From a8a49c985160f5de24922384bc7217cab8ba2348 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 27 Jun 2013 12:17:10 +0200 Subject: [PATCH 31/48] CDB: fix breakpoint location in catch clauses. Task-number: QTCREATORBUG-7336 Change-Id: I926e82499325e4fe38e25cc7a6158050f7fc0e82 Reviewed-by: Friedemann Kleint Reviewed-by: Joerg Bornemann Reviewed-by: Eike Ziller Reviewed-by: Nikolai Kosjar --- src/libs/cplusplus/findcdbbreakpoint.cpp | 1 + tests/auto/cplusplus/misc/tst_misc.cpp | 30 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libs/cplusplus/findcdbbreakpoint.cpp b/src/libs/cplusplus/findcdbbreakpoint.cpp index a5a7b1f37f6..e4f8724efbe 100644 --- a/src/libs/cplusplus/findcdbbreakpoint.cpp +++ b/src/libs/cplusplus/findcdbbreakpoint.cpp @@ -212,6 +212,7 @@ bool FindCdbBreakpoint::visit(SwitchStatementAST *ast) bool FindCdbBreakpoint::visit(TryBlockStatementAST *ast) { accept(ast->statement); + accept(ast->catch_clause_list); return false; } diff --git a/tests/auto/cplusplus/misc/tst_misc.cpp b/tests/auto/cplusplus/misc/tst_misc.cpp index 429a6237807..458431312b3 100644 --- a/tests/auto/cplusplus/misc/tst_misc.cpp +++ b/tests/auto/cplusplus/misc/tst_misc.cpp @@ -46,6 +46,7 @@ private slots: void findBreakpoints(); void findBreakpoints2(); + void findBreakpoints3(); }; void tst_Misc::diagnosticClient_error() @@ -155,7 +156,7 @@ void tst_Misc::findBreakpoints2() " }\n" "}\n" ); - Document::Ptr doc = Document::create("findContstructorBreakpoint"); + Document::Ptr doc = Document::create("findSwitchBreakpoint"); QVERIFY(!doc.isNull()); doc->setUtf8Source(src); bool success = doc->parse(); @@ -173,5 +174,32 @@ void tst_Misc::findBreakpoints2() QCOMPARE(findBreakpoint(7), 7U); } +void tst_Misc::findBreakpoints3() +{ + const QByteArray src("\n" // line 0 + "int foo() {\n" + " try {\n" // line 2 + " bar();\n" // line 3 + " } catch (Mooze &m) {\n" // line 4 + " wooze();\n" // line 5 + " }\n" + " return 0;\n" // line 7 + "}\n" + ); + Document::Ptr doc = Document::create("findCatchBreakpoint"); + QVERIFY(!doc.isNull()); + doc->setUtf8Source(src); + bool success = doc->parse(); + QVERIFY(success); + QCOMPARE(doc->diagnosticMessages().size(), 0); + FindCdbBreakpoint findBreakpoint(doc->translationUnit()); + + QCOMPARE(findBreakpoint(2), 3U); + QCOMPARE(findBreakpoint(3), 3U); + QCOMPARE(findBreakpoint(4), 5U); + QCOMPARE(findBreakpoint(5), 5U); + QCOMPARE(findBreakpoint(7), 7U); +} + QTEST_MAIN(tst_Misc) #include "tst_misc.moc" From 69a00cbabecd6692a07d688db3fd52d540a0aa84 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 2 Jul 2013 09:46:17 +0200 Subject: [PATCH 32/48] QmlDesigner.PropertyEditor: extend lookup rules for extensions If specifics for pane .qml files are located inside the plugin in the designer sudirectory, we still required the path to be fully qualified. e.g. myComponnents/designer/myComponent/MySpecifics.qml This is unconvinient and also a behaivour change for pure directory imports. Pure directory imports were not fully qualified until recently. With this patch we also allow: myComponnents/designer/MySpecifics.qml Change-Id: I9a61016f425caf5d7d15140554c72f4a69a6687a Reviewed-by: Marco Bubke Reviewed-by: Eike Ziller --- .../components/propertyeditor/propertyeditor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp index f4a12681a4e..3b3281fcadb 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp @@ -1096,15 +1096,21 @@ QString PropertyEditor::locateQmlFile(const NodeMetaInfo &info, const QString &r const QString relativePathWithVersion = relativePathWithoutEnding + versionString + QLatin1String(".qml"); //Check for qml files with versions first + const QString withoutDirWithVersion = relativePathWithVersion.split(QLatin1String("/")).last(); if (importDir.exists(relativePathWithVersion)) return importDir.absoluteFilePath(relativePathWithVersion); + if (importDir.exists(withoutDirWithVersion)) //Since we are in a subfolder of the import we do not require the directory + return importDir.absoluteFilePath(withoutDirWithVersion); if (fileSystemDir.exists(relativePathWithVersion)) return fileSystemDir.absoluteFilePath(relativePathWithVersion); if (resourcesDir.exists(relativePathWithVersion)) return resourcesDir.absoluteFilePath(relativePathWithVersion); + const QString withoutDir = relativePath.split(QLatin1String("/")).last(); if (importDir.exists(relativePath)) return importDir.absoluteFilePath(relativePath); + if (importDir.exists(withoutDir)) //Since we are in a subfolder of the import we do not require the directory + return importDir.absoluteFilePath(withoutDir); if (fileSystemDir.exists(relativePath)) return fileSystemDir.absoluteFilePath(relativePath); if (resourcesDir.exists(relativePath)) From c264c0d2137d15ec3746ed0f3bd80f225671b4a6 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 1 Jul 2013 10:25:03 +0200 Subject: [PATCH 33/48] C++: Fix resolving ui_* files in CppPreprocessor The working copy contains the artificial ui_* files and therefore we have to consider it while resolving include files. Task-number: QTCREATORBUG-9683 Change-Id: Icb3387b4cd885b3652bae3f1da465d3e0f633332 Reviewed-by: Christian Stenger Reviewed-by: Eike Ziller Reviewed-by: Daniel Teske Reviewed-by: Robert Loehning Reviewed-by: Erik Verbruggen --- src/plugins/cpptools/cppmodelmanager_test.cpp | 53 +++++++++++++++++++ src/plugins/cpptools/cpppreprocessor.cpp | 2 +- src/plugins/cpptools/cpptoolsplugin.h | 1 + src/plugins/cpptools/modelmanagertesthelper.h | 2 +- .../testdata_guiproject1/main.cpp | 13 +++++ .../testdata_guiproject1/mainwindow.cpp | 16 ++++++ .../testdata_guiproject1/mainwindow.h | 24 +++++++++ .../testdata_guiproject1/mainwindow.ui | 24 +++++++++ .../testdata_guiproject1.pro | 9 ++++ 9 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 tests/cppmodelmanager/testdata_guiproject1/main.cpp create mode 100644 tests/cppmodelmanager/testdata_guiproject1/mainwindow.cpp create mode 100644 tests/cppmodelmanager/testdata_guiproject1/mainwindow.h create mode 100644 tests/cppmodelmanager/testdata_guiproject1/mainwindow.ui create mode 100644 tests/cppmodelmanager/testdata_guiproject1/testdata_guiproject1.pro diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index d01c4ff5ab2..305b16b2c25 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -32,6 +32,9 @@ #include "cpppreprocessor.h" #include "modelmanagertesthelper.h" +#include +#include + #include #include #include @@ -360,3 +363,53 @@ void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects() foreach (const QString &file, project2.projectFiles) QVERIFY(mm->snapshot().contains(file)); } + +void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles() +{ + TestDataDirectory testDataDirectory(QLatin1String("testdata_guiproject1")); + const QString projectFile = testDataDirectory.file(QLatin1String("testdata_guiproject1.pro")); + + // Open project with *.ui file + ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); + QString errorOpeningProject; + Project *project = pe->openProject(projectFile, &errorOpeningProject); + QVERIFY(errorOpeningProject.isEmpty()); + project->configureAsExampleProject(QStringList()); + + // Check working copy. + // An AbstractEditorSupport object should have been added for the ui_* file. + CppModelManagerInterface *mm = CppModelManagerInterface::instance(); + CppModelManagerInterface::WorkingCopy workingCopy = mm->workingCopy(); + + QCOMPARE(workingCopy.size(), 2); // mm->configurationFileName() and "ui_*.h" + + QStringList fileNamesInWorkinCopy; + QHashIterator > it = workingCopy.iterator(); + while (it.hasNext()) { + it.next(); + fileNamesInWorkinCopy << QFileInfo(it.key()).fileName(); + } + fileNamesInWorkinCopy.sort(); + const QString expectedUiHeaderFileName = QLatin1String("ui_mainwindow.h"); + QCOMPARE(fileNamesInWorkinCopy.at(0), mm->configurationFileName()); + QCOMPARE(fileNamesInWorkinCopy.at(1), expectedUiHeaderFileName); + + // Check CppPreprocessor / includes. + // The CppPreprocessor is expected to find the ui_* file in the working copy. + const QString fileIncludingTheUiFile = testDataDirectory.file(QLatin1String("mainwindow.cpp")); + while (!mm->snapshot().document(fileIncludingTheUiFile)) + QCoreApplication::processEvents(); + + const CPlusPlus::Snapshot snapshot = mm->snapshot(); + const Document::Ptr document = snapshot.document(fileIncludingTheUiFile); + QVERIFY(document); + const QStringList includedFiles = document->includedFiles(); + QCOMPARE(includedFiles.size(), 2); + QCOMPARE(QFileInfo(includedFiles.at(0)).fileName(), QLatin1String("mainwindow.h")); + QCOMPARE(QFileInfo(includedFiles.at(1)).fileName(), QLatin1String("ui_mainwindow.h")); + + // Close Project + ProjectExplorer::SessionManager *sm = pe->session(); + sm->removeProject(project); + ModelManagerTestHelper::verifyClean(); +} diff --git a/src/plugins/cpptools/cpppreprocessor.cpp b/src/plugins/cpptools/cpppreprocessor.cpp index 825b29ce8c2..57a3fb4a72b 100644 --- a/src/plugins/cpptools/cpppreprocessor.cpp +++ b/src/plugins/cpptools/cpppreprocessor.cpp @@ -231,7 +231,7 @@ QString CppPreprocessor::resolveFile_helper(const QString &fileName, IncludeType foreach (const QString &includePath, m_includePaths) { QString path = includePath + fileName; - if (checkFile(path)) + if (m_workingCopy.contains(path) || checkFile(path)) return path; } diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index d10c6902215..09bea7fc3ce 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -164,6 +164,7 @@ private slots: void test_modelmanager_refresh_1(); void test_modelmanager_refresh_2(); void test_modelmanager_snapshot_after_two_projects(); + void test_modelmanager_extraeditorsupport_uiFiles(); private: void test_completion(); diff --git a/src/plugins/cpptools/modelmanagertesthelper.h b/src/plugins/cpptools/modelmanagertesthelper.h index 8a228cac42a..b2b042c4452 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.h +++ b/src/plugins/cpptools/modelmanagertesthelper.h @@ -79,7 +79,7 @@ public: ~ModelManagerTestHelper(); void cleanup(); - void verifyClean(); + static void verifyClean(); Project *createProject(const QString &name); diff --git a/tests/cppmodelmanager/testdata_guiproject1/main.cpp b/tests/cppmodelmanager/testdata_guiproject1/main.cpp new file mode 100644 index 00000000000..50ca345343b --- /dev/null +++ b/tests/cppmodelmanager/testdata_guiproject1/main.cpp @@ -0,0 +1,13 @@ +// Copyright license + +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/tests/cppmodelmanager/testdata_guiproject1/mainwindow.cpp b/tests/cppmodelmanager/testdata_guiproject1/mainwindow.cpp new file mode 100644 index 00000000000..495189aa3b0 --- /dev/null +++ b/tests/cppmodelmanager/testdata_guiproject1/mainwindow.cpp @@ -0,0 +1,16 @@ +// Copyright license + +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +MainWindow::~MainWindow() +{ + delete ui; +} diff --git a/tests/cppmodelmanager/testdata_guiproject1/mainwindow.h b/tests/cppmodelmanager/testdata_guiproject1/mainwindow.h new file mode 100644 index 00000000000..6dae9639b63 --- /dev/null +++ b/tests/cppmodelmanager/testdata_guiproject1/mainwindow.h @@ -0,0 +1,24 @@ +// Copyright license + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/tests/cppmodelmanager/testdata_guiproject1/mainwindow.ui b/tests/cppmodelmanager/testdata_guiproject1/mainwindow.ui new file mode 100644 index 00000000000..6050363fa71 --- /dev/null +++ b/tests/cppmodelmanager/testdata_guiproject1/mainwindow.ui @@ -0,0 +1,24 @@ + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + + + + + diff --git a/tests/cppmodelmanager/testdata_guiproject1/testdata_guiproject1.pro b/tests/cppmodelmanager/testdata_guiproject1/testdata_guiproject1.pro new file mode 100644 index 00000000000..0fdc70ad7b4 --- /dev/null +++ b/tests/cppmodelmanager/testdata_guiproject1/testdata_guiproject1.pro @@ -0,0 +1,9 @@ +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = testdata_guiproject1 +TEMPLATE = app + +SOURCES += main.cpp mainwindow.cpp +HEADERS += mainwindow.h +FORMS += mainwindow.ui From eb1d87b30fb5213ae2d7ccda1435bfb1a7761089 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Fri, 28 Jun 2013 18:05:00 +0200 Subject: [PATCH 34/48] qmljs: coalesce resets of code model triggered by cpp files update Use a timer to avoid resetting the model too often. Change-Id: Iadf3ff3f03cfc91df44168243972b1e5a0ee5077 Reviewed-by: Daniel Teske Reviewed-by: Eike Ziller Reviewed-by: Thomas Hartmann --- src/plugins/qmljstools/qmljsmodelmanager.cpp | 12 +++++++++++- src/plugins/qmljstools/qmljsmodelmanager.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index d2c25d49f75..cc615797a8a 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -243,6 +243,11 @@ ModelManager::ModelManager(QObject *parent): m_updateCppQmlTypesTimer->setSingleShot(true); connect(m_updateCppQmlTypesTimer, SIGNAL(timeout()), SLOT(startCppQmlTypeUpdate())); + m_asyncResetTimer = new QTimer(this); + m_asyncResetTimer->setInterval(1000); + m_asyncResetTimer->setSingleShot(true); + connect(m_asyncResetTimer, SIGNAL(timeout()), SLOT(resetCodeModel())); + qRegisterMetaType("QmlJS::Document::Ptr"); qRegisterMetaType("QmlJS::LibraryInfo"); qRegisterMetaType("QmlJSTools::SemanticInfo"); @@ -1056,6 +1061,11 @@ void ModelManager::startCppQmlTypeUpdate() m_queuedCppDocuments.clear(); } +void ModelManager::asyncReset() +{ + m_asyncResetTimer->start(); +} + void ModelManager::updateCppQmlTypes(QFutureInterface &interface, ModelManager *qmlModelManager, CPlusPlus::Snapshot snapshot, @@ -1100,7 +1110,7 @@ void ModelManager::updateCppQmlTypes(QFutureInterface &interface, qmlModelManager->m_cppDataHash = newData; if (hasNewInfo) // one could get away with re-linking the cpp types... - QMetaObject::invokeMethod(qmlModelManager, "resetCodeModel"); + QMetaObject::invokeMethod(qmlModelManager, "asyncReset"); } ModelManager::CppDataHash ModelManager::cppData() const diff --git a/src/plugins/qmljstools/qmljsmodelmanager.h b/src/plugins/qmljstools/qmljsmodelmanager.h index 1c42c038829..9f6d2a35f36 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.h +++ b/src/plugins/qmljstools/qmljsmodelmanager.h @@ -141,6 +141,7 @@ private slots: void maybeQueueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc); void queueCppQmlTypeUpdate(const CPlusPlus::Document::Ptr &doc, bool scan); void startCppQmlTypeUpdate(); + void asyncReset(); private: static bool matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType); @@ -160,6 +161,7 @@ private: QFutureSynchronizer m_synchronizer; QTimer *m_updateCppQmlTypesTimer; + QTimer *m_asyncResetTimer; QHash > m_queuedCppDocuments; QFuture m_cppQmlTypesUpdater; QmlJS::QrcCache m_qrcCache; From f500c4c987b3295a743bbba3a24cf992c6fad6cf Mon Sep 17 00:00:00 2001 From: Lincoln Ramsay Date: Tue, 26 Mar 2013 10:43:16 +1000 Subject: [PATCH 35/48] Call refresh before checking the splitter sizes. If we don't do this, we miss the "current" size when an output pane has just been shown (it comes out as 0) and we resize it to the minimum size. Task-number: QTCREATORBUG-8877 Change-Id: I8b1cc19d116dde6edcf8770bb36d1598dfdce195 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/outputpane.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/coreplugin/outputpane.cpp b/src/plugins/coreplugin/outputpane.cpp index f282a6c5b97..e82d1b255af 100644 --- a/src/plugins/coreplugin/outputpane.cpp +++ b/src/plugins/coreplugin/outputpane.cpp @@ -144,6 +144,7 @@ void OutputPanePlaceHolder::ensureSizeHintAsMinimum() if (idx < 0) return; + d->m_splitter->refresh(); QList sizes = d->m_splitter->sizes(); Internal::OutputPaneManager *om = Internal::OutputPaneManager::instance(); int minimum = (d->m_splitter->orientation() == Qt::Vertical From afa66ab9c7c5ff7baa5826f554463ca48165f198 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 2 Jul 2013 14:52:10 +0200 Subject: [PATCH 36/48] C++: fix potential deadlock when closing an editor When the editor is closed, the CppEditorSupport waits for the highlighting and semantic info futures to finish. These futures might access the CppEditorSupport through the CppModelManager, causing a deadlock on the m_editorSupportMutex. Change-Id: Ifeb3864ed3bc2666d83607ef50d7bfee8f3d118f Reviewed-by: Eike Ziller Reviewed-by: Nikolai Kosjar --- src/plugins/cpptools/cppmodelmanager.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index b7abbe2d2dc..76b8c4e0e50 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -615,9 +615,14 @@ void CppModelManager::deleteEditorSupport(TextEditor::BaseTextEditor *textEditor if (!isCppEditor(textEditor)) return; - QMutexLocker locker(&m_editorSupportMutex); - CppEditorSupport *editorSupport = m_editorSupport.value(textEditor, 0); - m_editorSupport.remove(textEditor); + CppEditorSupport *editorSupport; + + { // only lock the operations on m_editorSupport + QMutexLocker locker(&m_editorSupportMutex); + editorSupport = m_editorSupport.value(textEditor, 0); + m_editorSupport.remove(textEditor); + } + delete editorSupport; } From 964d1212dafe7d458d2b7721971e44c934393571 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 2 Jul 2013 11:42:05 +0200 Subject: [PATCH 37/48] Debugger: Make more dumper work without debug info QRegExp, QHostInfo, QDir, QTextCursor Change-Id: I2a368f8d294a235076491e4c50fc79039a2c9cff Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 7 +- share/qtcreator/dumper/qttypes.py | 140 +++++++++++++++++++--------- tests/auto/debugger/tst_dumpers.cpp | 4 +- 3 files changed, 102 insertions(+), 49 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index 18f3eac73f0..f5ed11b3b80 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -1555,6 +1555,9 @@ class Dumper: def ptrSize(self): return self.lookupType('void*').sizeof + def is32bit(self): + return self.lookupType('void*').sizeof == 4 + def createValue(self, address, referencedType): return gdb.Value(address).cast(referencedType.pointer()).dereference() @@ -1576,9 +1579,9 @@ class Dumper: #if True: vtable = self.dereference(long(value.address)) # + ptrSize metaObjectEntry = self.dereference(vtable) # It's the first entry. - warn("MO: 0x%x " % metaObjectEntry) + #warn("MO: 0x%x " % metaObjectEntry) s = gdb.execute("info symbol 0x%x" % metaObjectEntry, to_string=True) - warn("S: %s " % s) + #warn("S: %s " % s) #return s.find("::metaObject() const") > 0 return s.find("::metaObject() const") > 0 or s.find("10metaObjectEv") > 0 #return str(metaObjectEntry).find("::metaObject() const") > 0 diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index af2422feb4b..28517969ad9 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -398,7 +398,7 @@ def qdump__QTime(d, value): # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): - base = d.dereferenceValue(value) + base = d.dereference(d.addressOf(value)) # QDateTimePrivate: # - QAtomicInt ref; # - [QDate date;] (+4) @@ -434,31 +434,55 @@ def qdump__QDateTime(d, value): def qdump__QDir(d, value): d.putNumChild(1) - data = value["d_ptr"]["d"].dereference() - try: - # Up to Qt 4.7 - d.putStringValue(data["path"]) - except: - # Qt 4.8 and later. - d.putStringValue(data["dirEntry"]["m_filePath"]) + privAddress = d.dereference(d.addressOf(value)) + bit32 = d.is32bit() + qt5 = d.qtVersion() >= 0x050000 + offset = (32 if bit32 else 40) if qt5 else 36 + filePathAddress = privAddress + offset + #try: + # # Up to Qt 4.7 + # d.putStringValue(data["path"]) + #except: + # # Qt 4.8 and later. + # d.putStringValue(data["dirEntry"]["m_filePath"]) + d.putStringValue(d.dereference(filePathAddress)) if d.isExpanded(): with Children(d): - qdir = d.ns + "QDir::" - d.putCallItem("absolutePath", value, "absolutePath") - d.putCallItem("canonicalPath", value, "canonicalPath") - d.putSubItem("entryList", data["files"]) - d.putSubItem("entryInfoList", data["fileInfos"]) + call(value, "count") # Fill cache. + #data = value["d_ptr"]["d"].dereference() + #qdir = d.ns + "QDir::" + #d.putCallItem("absolutePath", value, "absolutePath") + #d.putCallItem("canonicalPath", value, "canonicalPath") + with SubItem(d, "absolutePath"): + # d_ptr.d.priv.absoluteDirEntry.m_filePath + offset = (48 if bit32 else 60) if qt5 else 36 + typ = d.lookupType(d.ns + "QString") + d.putItem(d.createValue(privAddress + offset, typ)) + with SubItem(d, "entryInfoList"): + # d_ptr.d.priv.fileInfos + offset = (28 if bit32 else 32) if qt5 else 32 + typ = d.lookupType(d.ns + "QFileInfoList") + d.putItem(d.createValue(privAddress + offset, typ)) + with SubItem(d, "entryList"): + # d.ptr.d.priv.files + offset = 24 if qt5 else 28 + typ = d.lookupType(d.ns + "QStringList") + d.putItem(d.createValue(privAddress + offset, typ)) + #d.putSubItem("entryList", data["files"]) + #d.putSubItem("entryInfoList", data["fileInfos"]) def qdump__QFile(d, value): try: ptype = d.lookupType(d.ns + "QFilePrivate").pointer() d_ptr = value["d_ptr"]["d"] - d.putStringValue(d_ptr.cast(ptype).dereference()["fileName"]) + fileNameAddress = d.addressOf(d_ptr.cast(ptype).dereference()["fileName"]) + d.putNumChild(1) except: - d.putPlainChildren(value) - return - d.putNumChild(1) + privAddress = d.dereference(d.addressOf(value) + d.ptrSize()) + fileNameAddress = privAddress + 176 # Qt 5, 32 bit + d.putNumChild(0) + d.putStringValue(d.dereference(fileNameAddress)) if d.isExpanded(): with Children(d): base = fieldAt(value.type, 0).type @@ -467,11 +491,16 @@ def qdump__QFile(d, value): def qdump__QFileInfo(d, value): - try: - d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3]) - except: - d.putPlainChildren(value) - return + privAddress = d.dereference(d.addressOf(value)) + #bit32 = d.is32bit() + #qt5 = d.qtVersion() >= 0x050000 + #try: + # d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3]) + #except: + # d.putPlainChildren(value) + # return + filePathAddress = privAddress + d.ptrSize() + d.putStringValue(d.dereference(filePathAddress)) d.putNumChild(1) if d.isExpanded(): with Children(d, childType=d.lookupType(d.ns + "QString")): @@ -696,11 +725,16 @@ def qdump__QHash__iterator(d, value): def qdump__QHostAddress(d, value): - data = value["d"]["d"].dereference() - if int(data["ipString"]["d"]["size"]): - d.putStringValue(data["ipString"]) + privAddress = d.dereference(d.addressOf(value)) + isQt5 = d.qtVersion() >= 0x050000 + ipStringAddress = privAddress + (0 if isQt5 else 24) + # value["d"]["d"].dereference()["ipString"] + ipString = d.encodeString(d.dereference(ipStringAddress)) + if len(ipString) > 0: + d.putValue(ipString, Hex4EncodedLittleEndian) else: - a = int(data["a"]) + # value["d"]["d"].dereference()["a"] + a = d.extractInt(privAddress + (2 * d.ptrSize() if isQt5 else 0)) a, n4 = divmod(a, 256) a, n3 = divmod(a, 256) a, n2 = divmod(a, 256) @@ -709,7 +743,7 @@ def qdump__QHostAddress(d, value): d.putNumChild(1) if d.isExpanded(): with Children(d): - d.putFields(data) + d.putFields(value["d"]["d"].dereference()) def qdump__QList(d, value): dptr = childAt(value, 0)["d"] @@ -1510,16 +1544,35 @@ def qdump__QRectF(d, value): def qdump__QRegExp(d, value): - d.putStringValue(value["priv"]["engineKey"]["pattern"]) + # value["priv"]["engineKey"]["pattern"] + privAddress = d.dereference(d.addressOf(value)) + engineKeyAddress = privAddress + d.ptrSize() + patternAddress = engineKeyAddress + d.putStringValue(d.dereference(patternAddress)) d.putNumChild(1) if d.isExpanded(): with Children(d): - # FIXME: Remove need to call + # QRegExpPrivate: + # - QRegExpEngine *eng (+0) + # - QRegExpEngineKey: (+1ptr) + # - QString pattern; (+1ptr) + # - QRegExp::PatternSyntax patternSyntax; (+2ptr) + # - Qt::CaseSensitivity cs; (+2ptr +1enum +pad?) + # - bool minimal (+2ptr +2enum +2pad?) + # - QString t (+2ptr +2enum +1bool +3pad?) + # - QStringList captures (+3ptr +2enum +1bool +3pad?) + # FIXME: Remove need to call. Needed to warm up cache. call(value, "capturedTexts") # create cache with SubItem(d, "syntax"): - d.putItem(value["priv"]["engineKey"]["patternSyntax"]) + # value["priv"]["engineKey"["capturedCache"] + address = engineKeyAddress + d.ptrSize() + typ = d.lookupType(d.ns + "QRegExp::PatternSyntax") + d.putItem(d.createValue(address, typ)) with SubItem(d, "captures"): - d.putItem(value["priv"]["capturedCache"]) + # value["priv"]["capturedCache"] + address = privAddress + 3 * d.ptrSize() + 12 + typ = d.lookupType(d.ns + "QStringList") + d.putItem(d.createValue(address, typ)) def qdump__QRegion(d, value): @@ -1724,23 +1777,20 @@ def qdump__QTextCodec(d, value): def qdump__QTextCursor(d, value): - dd = value["d"]["d"] - if isNull(dd): + privAddress = d.dereference(d.addressOf(value)) + if privAddress == 0: d.putValue("(invalid)") d.putNumChild(0) else: - try: - p = dd.dereference() - d.putValue(p["position"]) - except: - d.putPlainChildren(value) - return + positionAddress = privAddress + 2 * d.ptrSize() + 8 + d.putValue(d.extractInt(positionAddress)) d.putNumChild(1) - if d.isExpanded(): - with Children(d): - d.putIntItem("position", p["position"]) - d.putIntItem("anchor", p["anchor"]) - d.putCallItem("selected", value, "selectedText") + if d.isExpanded(): + with Children(d): + positionAddress = privAddress + 2 * d.ptrSize() + 8 + d.putIntItem("position", d.extractInt(positionAddress)) + d.putIntItem("anchor", d.extractInt(positionAddress + intSize)) + d.putCallItem("selected", value, "selectedText") def qdump__QTextDocument(d, value): @@ -1770,7 +1820,7 @@ def qdump__QUrl(d, value): # - QString path; # - QString query; # - QString fragment; - schemeAddr = d.dereferenceValue(value) + 2 * d.intSize() + schemeAddr = d.dereference(d.addressOf(value)) + 2 * d.intSize() scheme = d.dereference(schemeAddr) host = d.dereference(schemeAddr + 3 * d.ptrSize()) path = d.dereference(schemeAddr + 4 * d.ptrSize()) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 227aa28c4c8..1eeef1b22d9 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1147,8 +1147,8 @@ void tst_Dumpers::dumper_data() "unused(&dir, &s);\n") % CoreProfile() % Check("dir", tempDir, "@QDir") - % Check("dir.absolutePath", tempDir, "@QString") - % Check("dir.canonicalPath", tempDir, "@QString"); + % Check("dir.absolutePath", tempDir, "@QString"); + // % Check("dir.canonicalPath", tempDir, "@QString"); QTest::newRow("QFileInfo") #ifdef Q_OS_WIN From 2767b77d44f3ea965c68a44dacf506fb22656cea Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 2 Jul 2013 11:41:18 +0200 Subject: [PATCH 38/48] QmlApplicationWizard: translation fix for QML wizards Fixing the generated context and extract from the right element. Change-Id: Ibb454e82d6f197014451399bbb8a9fc0bad04a99 Reviewed-by: Oswald Buddenhagen Reviewed-by: Friedemann Kleint --- share/qtcreator/translations/extract-qmlwizards.xq | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/translations/extract-qmlwizards.xq b/share/qtcreator/translations/extract-qmlwizards.xq index b3daf0c6545..9d6d8c0abe7 100644 --- a/share/qtcreator/translations/extract-qmlwizards.xq +++ b/share/qtcreator/translations/extract-qmlwizards.xq @@ -1,6 +1,6 @@ -let $prefix := string("QT_TRANSLATE_NOOP("QmlProjectManager::QmlApplicationWizardDialog", "") +let $prefix := string("QT_TRANSLATE_NOOP("QmlProjectManager::QmlApplicationWizard", "") let $suffix := concat("")", codepoints-to-string(10)) for $file in tokenize($files, string("\|")) let $doc := doc($file) - for $text in ($doc/*:template/*:description, $doc/*:wizard/*:displayname) + for $text in ($doc/*:template/*:description, $doc/*:template/*:displayname) return fn:concat($prefix, data($text), $suffix) From af9978fd5c7162f16cc4c21d632e0fb09bc0c98f Mon Sep 17 00:00:00 2001 From: Chris Stylianou Date: Fri, 21 Jun 2013 15:02:39 +0100 Subject: [PATCH 39/48] Fix incorrect uname usage. The POSIX function uname() can return any non-negative value for success. - Example: Solaris 10 returns 1 on success. See: http://pubs.opengroup.org/onlinepubs/009695399/functions/uname.html Change-Id: Ic3d51f94a31d8b562b28a2d09df3d31b04c77dc8 Reviewed-by: Oswald Buddenhagen (cherry picked from qtbase/e97c37a37ac27f9ab901e974f0a882e81ffd571d) Reviewed-by: Daniel Teske --- src/shared/proparser/qmakeevaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/proparser/qmakeevaluator.cpp b/src/shared/proparser/qmakeevaluator.cpp index 21a0e3bd31b..0c35a671dca 100644 --- a/src/shared/proparser/qmakeevaluator.cpp +++ b/src/shared/proparser/qmakeevaluator.cpp @@ -1026,7 +1026,7 @@ void QMakeEvaluator::loadDefaults() # endif #elif defined(Q_OS_UNIX) struct utsname name; - if (!uname(&name)) { + if (uname(&name) != -1) { vars[ProKey("QMAKE_HOST.os")] << ProString(name.sysname); vars[ProKey("QMAKE_HOST.name")] << ProString(QString::fromLocal8Bit(name.nodename)); vars[ProKey("QMAKE_HOST.version")] << ProString(name.release); From b403732934c63bb1293b73a0934266634d521cdf Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 2 Jul 2013 16:19:21 +0200 Subject: [PATCH 40/48] QmlJSTools: Fix language detection bug. Due to what looks like a copy/paste error, qbs files were detected as actual QML, resulting in a torrent of parser warnings for projects containing qbs files. Change-Id: I8f4886621641d42bb0b2aa066a0bbdc44b9d8221 Reviewed-by: Fawzi Mohamed Reviewed-by: Eike Ziller --- src/plugins/qmljstools/qmljsmodelmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmljstools/qmljsmodelmanager.cpp b/src/plugins/qmljstools/qmljsmodelmanager.cpp index cc615797a8a..530ca941d51 100644 --- a/src/plugins/qmljstools/qmljsmodelmanager.cpp +++ b/src/plugins/qmljstools/qmljsmodelmanager.cpp @@ -195,7 +195,7 @@ QmlJS::Document::Language QmlJSTools::languageOfFile(const QString &fileName) Core::MimeType qbsSourceTy = db->findByType(QLatin1String(Constants::QBS_MIMETYPE)); mergeSuffixes(qbsSuffixes, qbsSourceTy.suffixes()); Core::MimeType qmlProjectSourceTy = db->findByType(QLatin1String(Constants::QMLPROJECT_MIMETYPE)); - mergeSuffixes(qbsSuffixes, qmlProjectSourceTy.suffixes()); + mergeSuffixes(qmlProjectSuffixes, qmlProjectSourceTy.suffixes()); Core::MimeType jsonSourceTy = db->findByType(QLatin1String(Constants::JSON_MIMETYPE)); mergeSuffixes(jsonSuffixes, jsonSourceTy.suffixes()); } From 1130afde57c0b1c84472f6b556c3e4baece5d608 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 2 Jul 2013 14:00:04 +0200 Subject: [PATCH 41/48] Update German translations for 2.8. Task-number: QTCREATORBUG-9712 Task-number: QTCREATORBUG-8923 Change-Id: I04367cf56be533cc8d078bb232362de9e5cbfe95 Reviewed-by: Thomas Hartmann Reviewed-by: Robert Loehning --- share/qtcreator/translations/qtcreator_de.ts | 80 ++++++++++---------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index 7fb8fbf8f7e..96d024aff8c 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -14439,10 +14439,6 @@ Verwenden Sie die Eigenschaft importPaths, um Importpfade zu qmlproject-basierte Plain C++ Project (CMake Build) C++-Projekt (CMake) - - Creates a C++ plugin to load extensions dynamically into applications using the QDeclarativeEngine class.&lt;br&gt;&lt;br&gt;Requires &lt;b&gt;Qt 4.7.0&lt;/b&gt; or newer. - Erstellt ein C++-Plugin zum dynamischen Laden von Erweiterungen in Anwendungen mittels der Klasse QDeclarativeEngine.&lt;br&gt;&lt;br&gt;Erfordert &lt;b&gt;Qt 4.7.0&lt;/b&gt; oder neuer. - Custom QML Extension Plugin Parameters QML Runtime Plug-in Parameters @@ -14610,18 +14606,22 @@ Verwenden Sie die Eigenschaft importPaths, um Importpfade zu qmlproject-basierte Local user settings Lokale Benutzer-Einstellungen + + Creates a C++ plugin to load extensions dynamically into applications using the QDeclarativeEngine class. Requires Qt 4.7.0 or newer. + Erstellt ein C++-Plugin zum dynamischen Laden von Erweiterungen in Anwendungen mittels der Klasse QDeclarativeEngine. Erfordert Qt 4.7.0 oder neuer. + Object class-name: Klassenname des Objektes: - - Creates a C++ plugin to load extensions dynamically into applications using the QQmlEngine class.&lt;br&gt;&lt;br&gt;Requires &lt;b&gt;Qt 5.0&lt;/b&gt; or newer. - Erstellt ein C++-Plugin zum dynamischen Laden von Erweiterungen in Anwendungen mittels der Klasse QQmlEngine.&lt;br&gt;&lt;br&gt;Erfordert &lt;b&gt;Qt 5.0&lt;/b&gt; oder neuer. - Qt Quick 1 Extension Plugin Plugin zur Erweiterung von QtQuick 1 + + Creates a C++ plugin to load extensions dynamically into applications using the QQmlEngine class. Requires Qt 5.0 or newer. + Erstellt ein C++-Plugin zum dynamischen Laden von Erweiterungen in Anwendungen mittels der Klasse QQmlEngine. Erfordert Qt 5.0 oder neuer. + Qt Quick 2 Extension Plugin Plugin zur Erweiterung von QtQuick 2 @@ -30823,22 +30823,11 @@ Möchten Sie, dass Qt Creator sie für Ihr Projekt anlegt? Qnx::Internal::BlackBerryRunConfiguration - - %1 on BlackBerry device - %1 auf BlackBerry-Gerät - Run on BlackBerry device Ausführung auf BlackBerry-Gerät - - Qnx::Internal::BlackBerryRunConfigurationFactory - - %1 on BlackBerry Device - %1 auf BlackBerry-Gerät - - Qnx::Internal::BlackBerryRunControlFactory @@ -31266,6 +31255,10 @@ Qt Creator know about a likely URI. List of Processes Liste der Prozesse + + &Attach to Process + &An Prozess anhängen + ProjectExplorer::DeviceProcessList @@ -32011,13 +32004,6 @@ Fehlerausgabe: %1 &Letzte: - - DeviceProcessesDialog - - &Attach to Process - &An Prozess anhängen - - Debugger::Internal::DebuggerCore @@ -35711,21 +35697,6 @@ Kurznamen können verwendet werden, sofern sie eindeutig sind. Refaktorisierung konnte nicht angewandt werden. - - QmlProjectManager::QmlApplicationWizardDialog - - Creates a Qt Quick 1 UI project with a single QML file that contains the main view.&lt;br/&gt;You can review Qt Quick 1 UI projects in the QML Viewer and you need not build them. You do not need to have the development environment installed on your computer to create and run this type of projects.&lt;br/&gt;&lt;br/&gt;Requires &lt;b&gt;Qt 4.8&lt;/b&gt; or newer. - Erstellt ein Qt Quick 1-UI-Projekt mit einer einzigen QML-Datei, die die Hauptansicht enthält.&lt;br/&gt;Sie können Qt Quick 1-UI-Projekte mit dem QML-Viewer ohne Erstellung betrachten. Sie benötigen keine Entwicklungsumgebung auf Ihrem Computer, um solche Projekte zu erstellen und auszuführen.&lt;br/&gt;&lt;br/&gt;Erfordert &lt;b&gt;Qt 4.8&lt;/b&gt; oder neuer. - - - Creates a Qt Quick 2 UI project with a single QML file that contains the main view.&lt;br/&gt;You can review Qt Quick 2 UI projects in the QML Scene and you need not build them. You do not need to have the development environment installed on your computer to create and run this type of projects.&lt;br/&gt;&lt;br/&gt;Requires &lt;b&gt;Qt 5.0&lt;/b&gt; or newer. - Erstellt ein Qt Quick 2-UI-Projekt mit einer einzigen QML-Datei, die die Hauptansicht enthält.&lt;br/&gt;Sie können Qt Quick 2-UI-Projekte mit QML-Scene ohne Erstellung betrachten. Sie benötigen keine Entwicklungsumgebung auf Ihrem Computer, um solche Projekte zu erstellen und auszuführen.&lt;br/&gt;&lt;br/&gt;Erfordert &lt;b&gt;Qt 5.0&lt;/b&gt; oder neuer. - - - Creates a Qt Quick 2 UI project with a single QML file that contains the main view and uses Qt Quick Controls.&lt;br/&gt;You can review Qt Quick 2 UI projects in the QML Scene and you need not build them. This project requires that you have installed Qt Quick Controls for your Qt version.&lt;br/&gt;&lt;br/&gt;Requires &lt;b&gt;Qt 5.1&lt;/b&gt; or newer. - Erstellt ein Qt Quick 2-UI-Projekt mit einer einzigen QML-Datei, die die Hauptansicht enthält und Qt Quick Controls verwendet.&lt;br/&gt;Sie können Qt Quick 2-UI-Projekte mit QML-Scene ohne Erstellung betrachten. Dieses Projekt erfordert, dass die Qt Quick Controls für die Qt-Version installiert sind.&lt;br/&gt;&lt;br/&gt;Erfordert &lt;b&gt;Qt 5.1&lt;/b&gt; oder neuer. - - CppEditor::QuickFix @@ -37058,4 +37029,31 @@ Dieser Wizard führt Sie durch die essentiellen Schritte, die zum Deployment ein Beschreibung der Änderung einblenden + + QmlProjectManager::QmlApplicationWizard + + Creates a Qt Quick 1 UI project with a single QML file that contains the main view. You can review Qt Quick 1 UI projects in the QML Viewer and you need not build them. You do not need to have the development environment installed on your computer to create and run this type of projects. Requires Qt 4.8 or newer. + Erstellt ein Qt Quick 1-UI-Projekt mit einer einzigen QML-Datei, die die Hauptansicht enthält. Sie können Qt Quick 1-UI-Projekte mit dem QML-Viewer ohne Erstellung betrachten. Sie benötigen keine Entwicklungsumgebung auf Ihrem Computer, um solche Projekte zu erstellen und auszuführen. Erfordert Qt 4.8 oder neuer. + + + Qt Quick 1 UI + Qt Quick 1-UI + + + Creates a Qt Quick 2 UI project with a single QML file that contains the main view. You can review Qt Quick 2 UI projects in the QML Scene and you need not build them. You do not need to have the development environment installed on your computer to create and run this type of projects. Requires Qt 5.0 or newer. + Erstellt ein Qt Quick 2-UI-Projekt mit einer einzigen QML-Datei, die die Hauptansicht enthält. Sie können Qt Quick 2-UI-Projekte mit QML-Scene ohne Erstellung betrachten. Sie benötigen keine Entwicklungsumgebung auf Ihrem Computer, um solche Projekte zu erstellen und auszuführen. Erfordert Qt 5.0 oder neuer. + + + Qt Quick 2 UI + Qt Quick 2-UI + + + Creates a Qt Quick 2 UI project with a single QML file that contains the main view and uses Qt Quick Controls. You can review Qt Quick 2 UI projects in the QML Scene and you need not build them. This project requires that you have installed Qt Quick Controls for your Qt version. Requires Qt 5.1 or newer. + Erstellt ein Qt Quick 2-UI-Projekt mit einer einzigen QML-Datei, die die Hauptansicht enthält und Qt Quick Controls verwendet. Sie können Qt Quick 2-UI-Projekte mit QML-Scene ohne Erstellung betrachten. Dieses Projekt erfordert, dass die Qt Quick Controls für die Qt-Version installiert sind. Erfordert Qt 5.1 oder neuer. + + + Qt Quick 2 UI with Controls + Qt Quick 2-UI mit Controls + + From 15408b5369b08382c7f62bc076d98eb36a4bca96 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 2 Jul 2013 12:04:10 +0200 Subject: [PATCH 42/48] Bump Linux requirement for binary packages Change-Id: Ia1ac5e2480bc7dbee4ae4a7237a3d0f7427da015 Reviewed-by: Tim Jenssen --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 75c2a09b5ef..c2aa9a0ab55 100644 --- a/README +++ b/README @@ -7,7 +7,7 @@ Supported Platforms The standalone binary packages support the following platforms: Windows XP SP2 or later -(K)Ubuntu Linux 10.04 (32-bit and 64-bit) or later +(K)Ubuntu Linux 11.10 (32-bit and 64-bit) or later Mac OS 10.6 or later Building the sources requires Qt 4.8.0 or later. From e5c394cb26da3dd301443f329057ee1e2e277947 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 2 Jul 2013 17:53:42 +0200 Subject: [PATCH 43/48] Debugger: Distinguish values and addresses properly in dumper interface Change-Id: I1e8874106ecd7376aa9a552977f6827b07d246b1 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 8 ++- share/qtcreator/dumper/qttypes.py | 86 +++++++++++++++---------------- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index f5ed11b3b80..1754af35ef3 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -1561,18 +1561,16 @@ class Dumper: def createValue(self, address, referencedType): return gdb.Value(address).cast(referencedType.pointer()).dereference() - # Returns the address stored at another address. - def derefAddress(self, addr): - return long(gdb.Value(addr).cast(self.voidPtrType())) - def dereference(self, addr): return long(gdb.Value(addr).cast(self.voidPtrType().pointer()).dereference()) def extractInt(self, addr): return long(gdb.Value(addr).cast(self.intPtrType()).dereference()) + # Do not use value.address here as this might not have one, + # i.e. be the result of an inferior call def dereferenceValue(self, value): - return self.dereference(value.address) + return value.cast(self.voidPtrType()) def isQObject(self, value): try: diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index 28517969ad9..f51d4ea74f9 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -35,7 +35,7 @@ def checkRef(ref): check(count >= minimum) check(count < 1000000) -def qByteArrayDataData(d, addr): +def qByteArrayData(d, addr): intSize = d.intSize() ptrSize = d.ptrSize() if d.qtVersion() >= 0x050000: @@ -58,11 +58,9 @@ def qByteArrayDataData(d, addr): data = d.dereference(addr + 2 * intSize + ptrSize) return data, size, alloc -def qByteArrayData(d, addr): - return qByteArrayDataData(d, d.derefAddress(addr)) def qEncodeByteArray(d, addr, limit = None): - data, size, alloc = d.byteArrayData(addr) + data, size, alloc = qByteArrayData(d, addr) if alloc != 0: check(0 <= size and size <= alloc and alloc <= 100*1000*1000) limit = d.computeLimit(size, limit) @@ -71,6 +69,7 @@ def qEncodeByteArray(d, addr, limit = None): s += "2e2e2e" return s +# addr is the begin of a QByteArrayData structure def qEncodeString(d, addr, limit = 0): data, size, alloc = qByteArrayData(d, addr) if alloc != 0: @@ -81,6 +80,24 @@ def qEncodeString(d, addr, limit = 0): s += "2e002e002e00" return s +def qPutStringValueByAddress(d, addr): + d.putValue(qEncodeString(d, d.dereference(addr)), Hex4EncodedLittleEndian) + +Dumper.encodeByteArray = \ + lambda d, value: qEncodeByteArray(d, d.dereferenceValue(value)) +Dumper.byteArrayData = \ + lambda d, value: qByteArrayData(d, d.dereferenceValue(value)) +Dumper.putByteArrayValue = \ + lambda d, value: d.putValue(d.encodeByteArray(value), Hex2EncodedLatin1) + +Dumper.encodeString = \ + lambda d, value: qEncodeString(d, d.dereferenceValue(value)) +Dumper.stringData = \ + lambda d, value: qByteArrayData(d, d.dereferenceValue(value)) +Dumper.putStringValue = \ + lambda d, value: d.putValue(d.encodeString(value), Hex4EncodedLittleEndian) + + def mapForms(): return "Normal,Compact" @@ -107,16 +124,6 @@ def qPutMapName(d, value): else: d.put('name="%s",' % value) -Dumper.encodeByteArray = qEncodeByteArray -Dumper.byteArrayData = qByteArrayData -Dumper.byteArrayDataData = qByteArrayDataData -Dumper.putByteArrayValue = \ - lambda d, value: d.putValue(d.encodeByteArray(value), Hex2EncodedLatin1) -Dumper.putStringValue = \ - lambda d, value: d.putValue(d.encodeString(value), Hex4EncodedLittleEndian) - -Dumper.encodeString = qEncodeString -Dumper.stringData = qByteArrayData Dumper.putMapName = qPutMapName Dumper.isMapCompact = \ @@ -167,7 +174,7 @@ def qPutQObjectNameValue(d, value): # - QString objectName objectName = d.dereference(extra + 5 * ptrSize) - data, size, alloc = d.stringData(objectName) + data, size, alloc = qByteArrayData(d, objectName) if size > 0: str = d.readRawMemory(data, 2 * size) @@ -201,13 +208,6 @@ def qdump__QBasicAtomicPointer(d, value): with Children(d): d.putItem(value["_q_value"]) -def qdump__QByteArrayData(d, value): - data, size, alloc = d.byteArrayDataData(value) - d.putValue(d.readRawMemory(data, size), Hex2EncodedLatin1) - d.putNumChild(size) - if d.isExpanded(): - d.putArrayData(d.charType(), data, size) - def qform__QByteArray(): return "Inline,As Latin1 in Separate Window,As UTF-8 in Separate Window" @@ -398,7 +398,7 @@ def qdump__QTime(d, value): # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): - base = d.dereference(d.addressOf(value)) + base = d.dereferenceValue(value) # QDateTimePrivate: # - QAtomicInt ref; # - [QDate date;] (+4) @@ -434,7 +434,7 @@ def qdump__QDateTime(d, value): def qdump__QDir(d, value): d.putNumChild(1) - privAddress = d.dereference(d.addressOf(value)) + privAddress = d.dereferenceValue(value) bit32 = d.is32bit() qt5 = d.qtVersion() >= 0x050000 offset = (32 if bit32 else 40) if qt5 else 36 @@ -445,12 +445,10 @@ def qdump__QDir(d, value): #except: # # Qt 4.8 and later. # d.putStringValue(data["dirEntry"]["m_filePath"]) - d.putStringValue(d.dereference(filePathAddress)) + qPutStringValueByAddress(d, filePathAddress) if d.isExpanded(): with Children(d): call(value, "count") # Fill cache. - #data = value["d_ptr"]["d"].dereference() - #qdir = d.ns + "QDir::" #d.putCallItem("absolutePath", value, "absolutePath") #d.putCallItem("canonicalPath", value, "canonicalPath") with SubItem(d, "absolutePath"): @@ -468,21 +466,21 @@ def qdump__QDir(d, value): offset = 24 if qt5 else 28 typ = d.lookupType(d.ns + "QStringList") d.putItem(d.createValue(privAddress + offset, typ)) - #d.putSubItem("entryList", data["files"]) - #d.putSubItem("entryInfoList", data["fileInfos"]) def qdump__QFile(d, value): try: + # Try using debug info first. ptype = d.lookupType(d.ns + "QFilePrivate").pointer() d_ptr = value["d_ptr"]["d"] fileNameAddress = d.addressOf(d_ptr.cast(ptype).dereference()["fileName"]) d.putNumChild(1) except: + # 176 is the best guess. privAddress = d.dereference(d.addressOf(value) + d.ptrSize()) fileNameAddress = privAddress + 176 # Qt 5, 32 bit d.putNumChild(0) - d.putStringValue(d.dereference(fileNameAddress)) + qPutStringValueByAddress(d, fileNameAddress) if d.isExpanded(): with Children(d): base = fieldAt(value.type, 0).type @@ -491,7 +489,7 @@ def qdump__QFile(d, value): def qdump__QFileInfo(d, value): - privAddress = d.dereference(d.addressOf(value)) + privAddress = d.dereferenceValue(value) #bit32 = d.is32bit() #qt5 = d.qtVersion() >= 0x050000 #try: @@ -500,7 +498,7 @@ def qdump__QFileInfo(d, value): # d.putPlainChildren(value) # return filePathAddress = privAddress + d.ptrSize() - d.putStringValue(d.dereference(filePathAddress)) + qPutStringValueByAddress(d, filePathAddress) d.putNumChild(1) if d.isExpanded(): with Children(d, childType=d.lookupType(d.ns + "QString")): @@ -725,15 +723,15 @@ def qdump__QHash__iterator(d, value): def qdump__QHostAddress(d, value): - privAddress = d.dereference(d.addressOf(value)) + privAddress = d.dereferenceValue(value) isQt5 = d.qtVersion() >= 0x050000 ipStringAddress = privAddress + (0 if isQt5 else 24) - # value["d"]["d"].dereference()["ipString"] - ipString = d.encodeString(d.dereference(ipStringAddress)) + # value.d.d->ipString + ipString = qEncodeString(d, d.dereference(ipStringAddress)) if len(ipString) > 0: d.putValue(ipString, Hex4EncodedLittleEndian) else: - # value["d"]["d"].dereference()["a"] + # value.d.d->a a = d.extractInt(privAddress + (2 * d.ptrSize() if isQt5 else 0)) a, n4 = divmod(a, 256) a, n3 = divmod(a, 256) @@ -1544,11 +1542,11 @@ def qdump__QRectF(d, value): def qdump__QRegExp(d, value): - # value["priv"]["engineKey"]["pattern"] - privAddress = d.dereference(d.addressOf(value)) + # value.priv.engineKey.pattern + privAddress = d.dereferenceValue(value) engineKeyAddress = privAddress + d.ptrSize() patternAddress = engineKeyAddress - d.putStringValue(d.dereference(patternAddress)) + qPutStringValueByAddress(d, patternAddress) d.putNumChild(1) if d.isExpanded(): with Children(d): @@ -1777,7 +1775,7 @@ def qdump__QTextCodec(d, value): def qdump__QTextCursor(d, value): - privAddress = d.dereference(d.addressOf(value)) + privAddress = d.dereferenceValue(value) if privAddress == 0: d.putValue("(invalid)") d.putNumChild(0) @@ -1820,15 +1818,15 @@ def qdump__QUrl(d, value): # - QString path; # - QString query; # - QString fragment; - schemeAddr = d.dereference(d.addressOf(value)) + 2 * d.intSize() + schemeAddr = d.dereferenceValue(value) + 2 * d.intSize() scheme = d.dereference(schemeAddr) host = d.dereference(schemeAddr + 3 * d.ptrSize()) path = d.dereference(schemeAddr + 4 * d.ptrSize()) - str = d.encodeString(scheme) + str = qEncodeString(d, scheme) str += "3a002f002f00" - str += d.encodeString(host) - str += d.encodeString(path) + str += qEncodeString(d, host) + str += qEncodeString(d, path) d.putValue(str, Hex4EncodedLittleEndian) d.putNumChild(1) From fe20970f12b2d098156ce712ac00e0dbe093b836 Mon Sep 17 00:00:00 2001 From: hluk Date: Tue, 2 Jul 2013 19:32:12 +0200 Subject: [PATCH 44/48] DiffEditor: Fix name for style constant Change-Id: I8fdbcfc702574a0b61f57bb3d92594b66b2171df Reviewed-by: Orgad Shaneh Reviewed-by: hjk --- share/qtcreator/styles/darkvim.xml | 2 +- share/qtcreator/styles/grayscale.xml | 2 +- share/qtcreator/styles/inkpot.xml | 2 +- src/plugins/texteditor/texteditorconstants.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/share/qtcreator/styles/darkvim.xml b/share/qtcreator/styles/darkvim.xml index 9c753067eab..eb6aa8ae5ef 100644 --- a/share/qtcreator/styles/darkvim.xml +++ b/share/qtcreator/styles/darkvim.xml @@ -45,7 +45,7 @@