diff --git a/README.md b/README.md index 649620b74bf..08d253afc8e 100644 --- a/README.md +++ b/README.md @@ -333,3 +333,15 @@ SQLite (https://www.sqlite.org) is in the Public Domain. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + +### Source Code Pro font + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a + trademark of Adobe Systems Incorporated in the United States + and/or other countries. + + This Font Software is licensed under the SIL Open Font License, Version 1.1. + + The font and license files can be found in QtCreator/src/libs/3rdparty/fonts. + diff --git a/dist/changes-4.1.0.md b/dist/changes-4.1.0.md index f9160eb7b4f..044ba33cdd2 100644 --- a/dist/changes-4.1.0.md +++ b/dist/changes-4.1.0.md @@ -10,23 +10,23 @@ you can check out from the public Git repository. For example: General * Added `Flat Dark` and `Flat Light` themes -* Added `Ctrl+N` and `Ctrl+P` shortcuts for navigating in Locator -* Added experimental support for the `Nim` programming language +* Added `Ctrl+N` and `Ctrl+P` shortcuts for navigating in locator +* Added experimental support for `Nim` programming language Editing * Added automatic release of resources for unmodified documents that have - not been visible a long time (QTCREATORBUG-10016) + not been visible recently (QTCREATORBUG-10016) * Added separate options for automatically inserted characters * Added highlighting of automatically inserted characters * Added option for skipping automatically inserted character, and changed - it to do this only as long as the cursor stays before it -* Fixed that replacing could change the selection (QTCREATORBUG-15623) + it to be done only if the cursor stays before the character +* Fixed that replacing could change selection (QTCREATORBUG-15623) All Projects -* Improved feedback when build results in errors and there - are issues with the kit (QTCREATORBUG-16079) +* Improved feedback when building results in errors, because of issues with + kits (QTCREATORBUG-16079) * Fixed issue with building in paths with non-ASCII characters (QTCREATORBUG-15855) * Fixed that `%{buildDir}` and `%{sourceDir}` stopped working in @@ -44,12 +44,12 @@ CMake Projects * Improved parsing of errors * Added workaround for CMake issue that include paths are in random order (QTCREATORBUG-16432) -* Added option for disabling automatic running of CMake to Build & Run > CMake - (QTCREATORBUG-15934) -* Fixed that CMake was automatically run even if the Qt Creator application - is not in the foreground (QTCREATORBUG-16354) +* Added option for disabling automatic running of CMake to `Build & Run` > + `CMake` (QTCREATORBUG-15934) +* Fixed that CMake was automatically run even if Qt Creator application + is not in foreground (QTCREATORBUG-16354) * QML_IMPORT_PATH can now be set in CMakeLists.txt files. This information - will be passed on to the QmlJS code model (QTCREATORBUG-11328) + will be passed on to QmlJS code model (QTCREATORBUG-11328) Example CMakeLists.txt code: `set(QML_IMPORT_PATH ${CMAKE_SOURCE_DIR}/qml ${CMAKE_BINARY_DIR}/imports CACHE string "" FORCE)` @@ -69,7 +69,7 @@ C++ Support QML Support -* Added formal parameters of JavaScript functions to outline and Locator +* Added formal parameters of JavaScript functions to outline and locator Debugging @@ -89,7 +89,7 @@ Qt Quick Designer * Added support for Qt Quick Controls 2 styles * Added `Move to Component` action -* Added `Add new Signal Handler` action +* Added `Add New Signal Handler` action * Improved performance * Improved error dialog (QTCREATORBUG-15772) * Fixed crumble bar for component navigation @@ -144,9 +144,9 @@ Remote Linux iOS +* Added human readable error messages (QTCREATORBUG-16328) * Fixed that deployment could fail if device and host are in same WiFi network (QTCREATORBUG-16061) -* Fixed missing human readable error messages (QTCREATORBUG-16328) Credits for these changes go to: Albert Astals Cid diff --git a/doc/src/qtquick/qtquick-buttons.qdoc b/doc/src/qtquick/qtquick-buttons.qdoc index f468ca3c0a8..71c3cb2f3d1 100644 --- a/doc/src/qtquick/qtquick-buttons.qdoc +++ b/doc/src/qtquick/qtquick-buttons.qdoc @@ -159,10 +159,10 @@ width (\uicontrol W) and height (\uicontrol H) of the button in the \uicontrol Properties pane. - \li Select \uicontrol Connections > \uicontrol {Dynamic Properties} > + \li Select \uicontrol Connections > \uicontrol {Properties} > \uicontrol Add to add properties for the item: - \image qmldesigner-borderimage-properties.png "Dynamic properties" + \image qmldesigner-borderimage-properties.png "Properties" \list a diff --git a/doc/src/qtquick/qtquick-connection-editor.qdoc b/doc/src/qtquick/qtquick-connection-editor.qdoc index 6e3f2c26bfa..236d3f9bbc6 100644 --- a/doc/src/qtquick/qtquick-connection-editor.qdoc +++ b/doc/src/qtquick/qtquick-connection-editor.qdoc @@ -80,7 +80,7 @@ \list 1 - \li Select the \uicontrol {Dynamic Properties} tab. + \li Select the \uicontrol {Properties} tab. \li Select \uicontrol Item to select the object to specify the property for. diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 99db06848cf..959c81ab5e4 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -344,6 +344,7 @@ class DumperBase: self.displayStringLimit = 100 self.resetCaches() + self.resetStats() self.childrenPrefix = 'children=[' self.childrenSuffix = '],' @@ -376,6 +377,35 @@ class DumperBase: # to not be QObject derived, it contains a 0 value. self.knownStaticMetaObjects = {} + self.counts = {} + self.pretimings = {} + self.timings = [] + + def resetStats(self): + # Timing collection + self.pretimings = {} + self.timings = [] + pass + + def dumpStats(self): + msg = [self.counts, self.timings] + self.resetStats() + return msg + + def bump(self, key): + if key in self.counts: + self.counts[key] += 1 + else: + self.counts[key] = 1 + + def preping(self, key): + import time + self.pretimings[key] = time.time() + + def ping(self, key): + import time + elapsed = int(1000000 * (time.time() - self.pretimings[key])) + self.timings.append([key, elapsed]) def putNewline(self): pass @@ -1260,67 +1290,171 @@ class DumperBase: pass - def extractStaticMetaObjectHelper(self, typeobj): - """ - Checks whether type has a Q_OBJECT macro. - Returns the staticMetaObject, or 0. - """ + def extractMetaObjectPtr(self, objectPtr, typeobj): + """ objectPtr - address of *potential* instance of QObject derived class + typeobj - type of *objectPtr if known, None otherwise. """ - if self.isSimpleType(typeobj): + def canBePointer(p): + if ptrSize == 4: + return p > 100000 and (p & 0x3 == 0) + else: + return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff) + + def couldBeQObject(): + (vtablePtr, dd) \ + = self.extractStruct('PP', objectPtr, 2 * ptrSize) + if not canBePointer(vtablePtr): + self.bump("vtable") + return False + if not canBePointer(dd): + self.bump("d_d_ptr") + return False + + (dvtablePtr, qptr, parentPtr, childrenDPtr, flags) \ + = self.extractStruct('PPPPI', dd, 4 * ptrSize + 4) + #warn("STRUCT DD: %s %s" % (self.currentIName, x)) + if not canBePointer(dvtablePtr): + self.bump("dvtable") + #warn("DVT: 0x%x" % dvtablePtr) + return False + # Check d_ptr.d.q_ptr == objectPtr + if qptr != objectPtr: + #warn("QPTR: 0x%x 0x%x" % (qptr, objectPtr)) + self.bump("q_ptr") + return False + if parentPtr and not canBePointer(parentPtr): + #warn("PAREN") + self.bump("parent") + return False + if not canBePointer(childrenDPtr): + #warn("CHILD") + self.bump("children") + return False + #if flags >= 0x80: # Only 7 flags are defined + # warn("FLAGS: 0x%x %s" % (flags, self.currentIName)) + # self.bump("flags") + # return False + #warn("OK") + #if dynMetaObjectPtr and not canBePointer(dynMetaObjectPtr): + # self.bump("dynmo") + # return False + + self.bump("couldBeQObject") + return True + + def extractMetaObjectPtrFromAddress(): + # Try vtable, metaObject() is the first entry. + vtablePtr = self.extractPointer(objectPtr) + metaObjectFunc = self.extractPointer(vtablePtr) + cmd = "((void*(*)(void *))0x%x)(0x%x)" % (metaObjectFunc, objectPtr) + try: + #warn("MO CMD: %s" % cmd) + res = self.parseAndEvaluate(cmd) + #warn("MO RES: %s" % res) + self.bump("successfulMetaObjectCall") + return toInteger(res) + except: + self.bump("failedMetaObjectCall") + #warn("COULD NOT EXECUTE: %s" % cmd) return 0 - typeName = str(typeobj) - isQObjectProper = typeName == self.qtNamespace() + "QObject" - - if not isQObjectProper: - if self.directBaseClass(typeobj, 0) is None: + def extractStaticMetaObjectFromTypeHelper(typeobj): + if self.isSimpleType(typeobj): return 0 - # No templates for now. - if typeName.find('<') >= 0: + typeName = str(typeobj) + isQObjectProper = typeName == self.qtNamespace() + "QObject" + + if not isQObjectProper: + if self.directBaseClass(typeobj, 0) is None: + return 0 + + # No templates for now. + if typeName.find('<') >= 0: + return 0 + + result = self.findStaticMetaObject(typeName) + + # We need to distinguish Q_OBJECT from Q_GADGET: + # a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself), + # a Q_GADGET SMO has a null superdata (hopefully) + if result and not isQObjectProper: + superdata = self.extractPointer(result) + if superdata == 0: + # This looks like a Q_GADGET + return 0 + + return result + + def extractStaticMetaObjectPtrFromType(someTypeObj): + if someTypeObj is None: return 0 + someTypeName = str(someTypeObj) + self.bump('metaObjectFromType') + known = self.knownStaticMetaObjects.get(someTypeName, None) + if known is not None: # Is 0 or the static metaobject. + return known - result = self.findStaticMetaObject(typeName) + result = 0 + #try: + result = extractStaticMetaObjectFromTypeHelper(someTypeObj) + #except RuntimeError as error: + # warn("METAOBJECT EXTRACTION FAILED: %s" % error) + #except: + # warn("METAOBJECT EXTRACTION FAILED FOR UNKNOWN REASON") - # We need to distinguish Q_OBJECT from Q_GADGET: - # a Q_OBJECT SMO has a non-null superdata (unless it's QObject itself), - # a Q_GADGET SMO has a null superdata (hopefully) - if result and not isQObjectProper: - superdata = self.extractPointer(result) - if toInteger(superdata) == 0: - # This looks like a Q_GADGET - return 0 + if not result: + base = self.directBaseClass(typeobj, 0) + if base != someTypeObj: # sanity check + result = extractStaticMetaObjectPtrFromType(base) + + self.knownStaticMetaObjects[someTypeName] = result + return result - return result - def extractStaticMetaObject(self, typeobj): - """ - Checks recursively whether a type derives from QObject. - """ if not self.useFancy: return 0 + ptrSize = self.ptrSize() + typeName = str(typeobj) result = self.knownStaticMetaObjects.get(typeName, None) if result is not None: # Is 0 or the static metaobject. + self.bump("typecached") + #warn("CACHED RESULT: %s %s 0x%x" % (self.currentIName, typeName, result)) return result - try: - result = self.extractStaticMetaObjectHelper(typeobj) - except RuntimeError as error: - warn("METAOBJECT EXTRACTION FAILED: %s" % error) - result = 0 - except: - warn("METAOBJECT EXTRACTION FAILED FOR UNKNOWN REASON") - result = 0 + if not couldBeQObject(): + self.bump('cannotBeQObject') + #warn("DOES NOT LOOK LIKE A QOBJECT: %s" % self.currentIName) + return 0 - if not result: - base = self.directBaseClass(typeobj, 0) - if base: - result = self.extractStaticMetaObject(base) + metaObjectPtr = 0 + if not metaObjectPtr: + # measured: 3 ms (example had one level of inheritance) + self.preping("metaObjectType-" + self.currentIName) + metaObjectPtr = extractStaticMetaObjectPtrFromType(typeobj) + self.ping("metaObjectType-" + self.currentIName) - self.knownStaticMetaObjects[typeName] = result - return result + if not metaObjectPtr: + # measured: 200 ms (example had one level of inheritance) + self.preping("metaObjectCall-" + self.currentIName) + metaObjectPtr = extractMetaObjectPtrFromAddress() + self.ping("metaObjectCall-" + self.currentIName) + + #if metaObjectPtr: + # self.bump('foundMetaObject') + # self.knownStaticMetaObjects[typeName] = metaObjectPtr + + return metaObjectPtr + + def extractStruct(self, pattern, base, size): + #warn("PATTERN: '%s'" % pattern) + pointerReplacement = 'Q' if self.ptrSize() == 8 else 'I' + pattern = pattern.replace('P', pointerReplacement) + mem = self.readRawMemory(base, size) + #warn("OUT: '%s'" % str(struct.unpack_from(pattern, mem))) + return struct.unpack_from(pattern, mem) def extractCString(self, addr): result = bytearray() @@ -1361,88 +1495,74 @@ class DumperBase: def putStructGuts(self, value): self.putEmptyValue() + #metaObjectPtr = self.extractMetaObjectPtr(self.addressOf(value), value.type) if self.showQObjectNames: - staticMetaObject = self.extractStaticMetaObject(value.type) - if staticMetaObject: + self.preping(self.currentIName) + metaObjectPtr = self.extractMetaObjectPtr(self.addressOf(value), value.type) + self.ping(self.currentIName) + if metaObjectPtr: self.context = value self.putQObjectNameValue(value) + #warn("STRUCT GUTS: %s MO: 0x%x " % (self.currentIName, metaObjectPtr)) if self.isExpanded(): self.put('sortable="1"') with Children(self, 1, childType=None): self.putFields(value) if not self.showQObjectNames: - staticMetaObject = self.extractStaticMetaObject(value.type) - if staticMetaObject: - self.putQObjectGuts(value, staticMetaObject) + metaObjectPtr = self.extractMetaObjectPtr(self.addressOf(value), value.type) + if metaObjectPtr: + self.putQObjectGuts(value, metaObjectPtr) # This is called is when a QObject derived class is expanded - def putQObjectGuts(self, qobject, smo): + def putQObjectGuts(self, qobject, metaObjectPtr): + self.putQObjectGutsHelper(qobject, self.addressOf(qobject), -1, metaObjectPtr, "QObject") + + + def metaString(self, metaObjectPtr, index, revision = 7): + #stringData = self.extractPointer(metaObjectPtr["d"]["stringdata"]) ptrSize = self.ptrSize() - dd = self.extractPointer(qobject, offset=ptrSize) - - # Parent and children. - try: - if qobject: - d_ptr = qobject["d_ptr"]["d"] - with SubItem(self, "[parent]"): - self.putItem(d_ptr["parent"]) - self.put('sortgroup="9"') - with SubItem(self, "[children]"): - self.putItem(d_ptr["children"]) - self.put('sortgroup="1"') - except: - pass - - # dd = value["d_ptr"]["d"] is just behind the vtable. - isQt5 = self.qtVersion() >= 0x50000 - extraDataOffset = 5 * ptrSize + 8 if isQt5 else 6 * ptrSize + 8 - extraData = self.extractPointer(dd + extraDataOffset) - self.putQObjectGutsHelper(qobject, extraData, -1, smo, "QObject") - - - def metaString(self, metaObject, index, revision = 7): - sd = self.extractPointer(metaObject["d"]["stringdata"]) + stringdata = self.extractPointer(toInteger(metaObjectPtr) + ptrSize) if revision >= 7: # Qt 5. - byteArrayDataType = self.lookupQtType("QByteArrayData") - byteArrayDataSize = byteArrayDataType.sizeof - literal = toInteger(sd) + toInteger(index) * byteArrayDataSize + #byteArrayDataType = self.lookupQtType("QByteArrayData") + #byteArrayDataSize = byteArrayDataType.sizeof + byteArrayDataSize = 24 if ptrSize == 8 else 16 + literal = stringdata + toInteger(index) * byteArrayDataSize ldata, lsize, lalloc = self.byteArrayDataHelper(literal) try: return self.extractBlob(ldata, lsize).toString() except: - return "" + return "" else: # Qt 4. - ldata = sd + index + ldata = stringdata + index return self.extractCString(ldata).decode("utf8") def putQMetaStuff(self, value, origType): - metaObject = value["mobj"] - if not metaObject: - self.putEmptyValue() - if self.isExpanded(): - with Children(self): - self.putFields(value) - else: + metaObjectPtr = value["mobj"] + if toInteger(metaObjectPtr): handle = toInteger(value["handle"]) - index = toInteger(metaObject["d"]["data"][handle]) - name = self.metaString(metaObject.dereference(), index) + index = toInteger(metaObjectPtr["d"]["data"][handle]) + name = self.metaString(metaObjectPtr, index) self.putValue(name) self.putNumChild(1) if self.isExpanded(): with Children(self): self.putFields(value) - self.putQObjectGutsHelper(0, 0, handle, metaObject, origType) + self.putQObjectGutsHelper(0, 0, handle, toInteger(metaObjectPtr), origType) + else: + self.putEmptyValue() + if self.isExpanded(): + with Children(self): + self.putFields(value) - def putQObjectGutsHelper(self, qobject, extraData, handle, metaObject, origType): + # basically all meta things go through this here. + # qobject and qobjectPtr are non-null if coming from a real structure display + # qobject == 0, qobjectPtr != 0 is possible for builds without QObject debug info + # if qobject == 0, properties and d-ptr cannot be shown. + # handle is what's store in QMetaMethod etc, pass -1 for QObject/QMetaObject itself + # metaObjectPtr needs to point to a valid QMetaObject. + def putQObjectGutsHelper(self, qobject, qobjectPtr, handle, metaObjectPtr, origType): intSize = self.intSize() ptrSize = self.ptrSize() - data = metaObject["d"]["data"] - - def walker(base): - ptr = toInteger(base) - while True: - yield self.extractInt(ptr) - ptr += intSize def putt(name, value, typeName = ' '): with SubItem(self, name): @@ -1450,63 +1570,103 @@ class DumperBase: self.putType(typeName) self.putNumChild(0) - def superData(mo): - return mo['d']['superdata'] + def extractSuperDataPtr(someMetaObjectPtr): + #return someMetaObjectPtr['d']['superdata'] + return self.extractPointer(someMetaObjectPtr) + + def extractDataPtr(someMetaObjectPtr): + # dataPtr = metaObjectPtr["d"]["data"] + return self.extractPointer(someMetaObjectPtr + 2 * ptrSize) isQMetaObject = origType == "QMetaObject" isQObject = origType == "QObject" - p = walker(data) - revision = p.next() - classname = p.next() - classinfo = p.next() - classinfo2 = p.next() - methodCount = p.next() - methods = p.next() - propertyCount = p.next() - properties = p.next() - enumCount = p.next() - enums = p.next() - constructorCount = p.next() - constructors = p.next() - flags = p.next() - signalCount = p.next() - - globalOffset = 0 - superdata = superData(metaObject) - while toInteger(superdata): - sdata = superdata["d"]["data"] - p = walker(sdata) - revision = p.next() - classname = p.next() - classinfo = p.next() - classinfo2 = p.next() - methodCount = p.next() - globalOffset += methodCount - superdata = superData(superdata) + #warn("OBJECT GUTS: %s 0x%x " % (self.currentIName, metaObjectPtr)) + dataPtr = extractDataPtr(metaObjectPtr) + #warn("DATA PTRS: %s 0x%x " % (self.currentIName, dataPtr)) + (revision, classname, + classinfo, classinfo2, + methodCount, methods, + propertyCount, properties, + enumCount, enums, + constructorCount, constructors, + flags, signalCount) = self.extractStruct('IIIIIIIIIIIIII', dataPtr, 56) largestStringIndex = -1 for i in range(methodCount): - t = (p.next(), p.next(), p.next(), p.next(), p.next()) + t = self.extractStruct('IIIII', dataPtr + 56 + i * 20, 20) if largestStringIndex < t[0]: largestStringIndex = t[0] + extraData = 0 + if qobjectPtr: + isQt5 = self.qtVersion() >= 0x50000 + extraDataOffset = 5 * ptrSize + 8 if isQt5 else 6 * ptrSize + 8 + # dd = value["d_ptr"]["d"] is just behind the vtable. + dd = self.extractPointer(qobjectPtr + ptrSize) + extraData = self.extractPointer(dd + extraDataOffset) + + if qobjectPtr: + qobjectType = self.lookupQtType("QObject") + badType = qobjectType is None + with SubItem(self, "[parent]"): + self.put('sortgroup="9"') + parentPtrType = self.voidPtrType() if badType else qobjectType.pointer() + self.putItem(self.createValue(dd + 2 * ptrSize, parentPtrType)) + with SubItem(self, "[children]"): + self.put('sortgroup="8"') + base = self.extractPointer(dd + 3 * ptrSize) # It's a QList + begin = self.extractInt(base + 8) + end = self.extractInt(base + 12) + array = base + 16 + if self.qtVersion() < 0x50000: + array += ptrSize + self.check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000) + size = end - begin + self.check(size >= 0) + self.putItemCount(size) + if self.isExpanded(): + addrBase = array + begin * ptrSize + with Children(self, size): + for i in self.childRange(): + with SubItem(self, i): + childPtr = self.extractPointer(addrBase + i * ptrSize) + if badType: + # release build + childMetaObjectPtr = self.extractMetaObjectPtr(childPtr, None) + if childMetaObjectPtr: + # release build + live process + self.putNumChild(1) + self.putAddress(childPtr) + if self.isExpanded(): + with Children(self): + self.putQObjectGutsHelper(0, childPtr, -1, childMetaObjectPtr, "QObject") + else: + # release build + core dump + self.putItem(self.createValue(addrBase + i * ptrSize, self.voidPtrType())) + else: + # debug info + self.putItem(self.createValue(childPtr, qobjectType)) + if isQMetaObject: with SubItem(self, "[strings]"): self.put('sortgroup="2"') - self.putSpecialValue("minimumitemcount", largestStringIndex + 1) - self.putNumChild(1) - if self.isExpanded(): - with Children(self, largestStringIndex + 1): - for i in self.childRange(): - with SubItem(self, i): - self.putValue(self.hexencode(self.metaString(metaObject, i)), "latin1") - self.putNumChild(0) + if largestStringIndex > 0: + self.putSpecialValue("minimumitemcount", largestStringIndex) + self.putNumChild(1) + if self.isExpanded(): + with Children(self, largestStringIndex + 1): + for i in self.childRange(): + with SubItem(self, i): + self.putValue(self.hexencode(self.metaString(metaObjectPtr, i)), "latin1") + self.putNumChild(0) + else: + self.putValue(" ") + self.putNumChild(0) if isQMetaObject: with SubItem(self, "[raw]"): self.put('sortgroup="1"') - p = walker(data) self.putEmptyValue() self.putNumChild(1) if self.isExpanded(): @@ -1520,9 +1680,8 @@ class DumperBase: putt("constructors", "%d %d" % (constructorCount, constructors)) putt("flags", flags) putt("signalCount", signalCount) - p = walker(toInteger(data) + 14 * 4) for i in range(methodCount): - t = (p.next(), p.next(), p.next(), p.next(), p.next()) + t = self.extractStruct('IIIII', dataPtr + 56 + i * 20, 20) putt("method %d" % i, "%s %s %s %s %s" % t) putt("[extraData]", "0x%x" % toInteger(extraData), "void *") @@ -1535,10 +1694,9 @@ class DumperBase: usesVector = self.qtVersion() >= 0x50700 with Children(self): # Static properties. - p = walker(toInteger(data) + properties * 4) for i in range(propertyCount): - t = (p.next(), p.next(), p.next()) - name = self.metaString(metaObject, t[0]) + t = self.extractStruct("III", dataPtr + properties * 4 + 12 * i, 12) + name = self.metaString(metaObjectPtr, t[0]) if qobject: self.putCallItem(name, qobject, "property", '"' + name + '"') else: @@ -1563,8 +1721,17 @@ class DumperBase: # We need a handle to [x] for the user to expand the item # before we know whether there are actual children. Counting # them is too expensive. - self.putNumChild(1) self.putSpecialValue("minimumitemcount", propertyCount) + self.putNumChild(1) + + superDataPtr = extractSuperDataPtr(metaObjectPtr) + + globalOffset = 0 + superDataIterator = superDataPtr + while superDataIterator: + sdata = extractDataPtr(superDataIterator) + globalOffset += self.extractInt(sdata + 16) # methodCount member + superDataIterator = extractSuperDataPtr(superDataIterator) if isQMetaObject or isQObject: with SubItem(self, "[methods]"): @@ -1572,10 +1739,9 @@ class DumperBase: self.putItemCount(methodCount) if self.isExpanded(): with Children(self): - p = walker(toInteger(data) + 14 * 4) for i in range(methodCount): - t = (p.next(), p.next(), p.next(), p.next(), p.next()) - name = self.metaString(metaObject, t[0]) + t = self.extractStruct("IIIII", dataPtr + 56 + 20 * i, 20) + name = self.metaString(metaObjectPtr, t[0]) with SubItem(self, i): self.putValue(name) self.putType(" ") @@ -1602,29 +1768,39 @@ class DumperBase: putt("[globalindex]", str(globalOffset + i)) if isQObject: - self.putSubItem("[metaObject]", metaObject) + with SubItem(self, "[metaObject]"): + self.putAddress(metaObjectPtr) + self.putNumChild(1) + if self.isExpanded(): + with Children(self): + self.putQObjectGutsHelper(0, 0, -1, metaObjectPtr, "QMetaObject") if isQObject: with SubItem(self, "d"): self.put('sortgroup="15"') - self.putItem(qobject["d_ptr"]["d"]) + try: + self.putItem(qobject["d_ptr"]["d"]) + except: + self.putNumChild(0) + self.putSpecialValue("notaccessible") if isQMetaObject: with SubItem(self, "[superdata]"): self.put('sortgroup="12"') - superdata = superData(metaObject) - self.putValue("0x%x" % superdata) - if toInteger(superdata): + if superDataPtr: + self.putType(self.qtNamespace() + "QMetaObject") + self.putAddress(superDataPtr) self.putNumChild(1) if self.isExpanded(): with Children(self): - self.putSubItem('*', superdata) + self.putQObjectGutsHelper(0, 0, -1, superDataPtr, "QMetaObject") else: + self.putType(self.qtNamespace() + "QMetaObject *") + self.putValue("0x0") self.putNumChild(0) - self.putType(superdata.type) if handle >= 0: - localIndex = (handle - methods) / 5 + localIndex = int((handle - methods) / 5) with SubItem(self, "[localindex]"): self.put('sortgroup="12"') self.putValue(localIndex) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 24abf794d0e..3e6c6f15aaf 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -383,13 +383,9 @@ class Dumper(DumperBase): def canCallLocale(self): return False if self.is32bit() else True - def reportTime(self, hint): - #from datetime import datetime - #warn("%s: %s" % (hint, datetime.now().time().isoformat())) - pass - def fetchVariables(self, args): - self.reportTime("begin fetch") + self.resetStats() + self.preping("locals") self.prepare(args) partialVariable = args.get("partialvar", "") isPartial = len(partialVariable) > 0 @@ -425,7 +421,7 @@ class Dumper(DumperBase): else: locals = self.listOfLocals() - self.reportTime("locals") + self.ping("locals") # Take care of the return value of the last function call. if len(self.resultVarName) > 0: @@ -449,12 +445,16 @@ class Dumper(DumperBase): else: # A "normal" local variable or parameter. with TopLevelItem(self, item.iname): + self.preping("all-" + item.iname) self.put('iname="%s",' % item.iname) self.put('name="%s",' % item.name) self.putItem(value) + self.ping("all-" + item.iname) + self.preping("watches") with OutputSafer(self): self.handleWatches(args) + self.ping("watches") self.output.append('],typeinfo=[') for name in self.typesToReport.keys(): @@ -475,9 +475,10 @@ class Dumper(DumperBase): self.output.append(',partial="%d"' % isPartial) - self.reportTime("before print: %s" % len(self.output)) + self.preping('safePrint') safePrint(''.join(self.output)) - self.reportTime("after print") + self.ping('safePrint') + safePrint('"%s"' % str(self.dumpStats())) def enterSubItem(self, item): if not item.iname: @@ -800,10 +801,12 @@ class Dumper(DumperBase): return struct.unpack("b", self.readRawMemory(address, 1))[0] def findStaticMetaObject(self, typename): - return self.findSymbol(typename + "::staticMetaObject") + symbol = gdb.lookup_global_symbol(typename + "::staticMetaObject") + return toInteger(symbol.value().address) if symbol else 0 def findSymbol(self, symbolName): try: + self.bump('findSymbol1') result = gdb.lookup_global_symbol(symbolName) return result.value() if result else 0 except: @@ -812,9 +815,11 @@ class Dumper(DumperBase): try: address = gdb.parse_and_eval("&'%s'" % symbolName) typeobj = gdb.lookup_type(self.qtNamespace() + "QMetaObject") + self.bump('findSymbol2') return self.createPointerValue(address, typeobj) except: - return 0 + self.bump('findSymbol3') + return 0 def put(self, value): self.output.append(value) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 5402db229fe..8e4cb83ef10 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -900,6 +900,10 @@ class Dumper(DumperBase): # logview pane feature. self.report('token(\"%s\")' % args["token"]) + def readRawMemory(self, address, size): + error = lldb.SBError() + return self.process.ReadMemory(address, size, error) + def extractBlob(self, base, size): if size == 0: return Blob("") @@ -923,7 +927,8 @@ class Dumper(DumperBase): def findStaticMetaObject(self, typeName): symbolName = self.mangleName(typeName + '::staticMetaObject') - return self.target.FindFirstGlobalVariable(symbolName) + symbol = self.target.FindFirstGlobalVariable(symbolName) + return int(symbol.AddressOf()) if symbol.IsValid() else 0 def findSymbol(self, symbolName): return self.target.FindFirstGlobalVariable(symbolName) @@ -1205,6 +1210,13 @@ class Dumper(DumperBase): else: shadowed[name] = 1 + if not value.IsInScope(): + with SubItem(self, name): + self.put('iname="%s",' % self.currentIName) + self.putSpecialValue('outofscope') + self.putNumChild(0) + continue + if name == "argv" and value.GetType().GetName() == "char **": self.putSpecialArgv(value) else: diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 095f30a8ff2..f0bc8ccc37d 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1106,7 +1106,7 @@ def qdump__QMetaObject(d, value): d.putNumChild(1) if d.isExpanded(): with Children(d): - d.putQObjectGutsHelper(0, 0, -1, value, "QMetaObject") + d.putQObjectGutsHelper(0, 0, -1, d.addressOf(value), "QMetaObject") d.putMembersItem(value) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml index a606fc97f7e..80272e25c34 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/ColorButton.qml @@ -298,13 +298,9 @@ Item { elide: Text.ElideRight anchors.verticalCenter: parent.verticalCenter } - SliderSpinBox { + DoubleSpinBox { id: hueSlider2 //value: colorButton.hue - decimals: 2 - stepSize: 0.1 - minimumValue: 0 - maximumValue: 1 onValueChanged: { if (colorButton.hue !== value && !colorButton.block) { colorButton.hue = value @@ -325,13 +321,9 @@ Item { anchors.verticalCenter: parent.verticalCenter } - SliderSpinBox { + DoubleSpinBox { id: saturationSlider //value: colorButton.saturation - decimals: 2 - stepSize: 0.1 - minimumValue: 0 - maximumValue: 1 onValueChanged: { if (colorButton.saturation !== value && !colorButton.block) { colorButton.saturation = value @@ -351,13 +343,9 @@ Item { elide: Text.ElideRight anchors.verticalCenter: parent.verticalCenter } - SliderSpinBox { + DoubleSpinBox { id: lightnessSlider //value: colorButton.lightness - decimals: 2 - stepSize: 0.1 - minimumValue: 0 - maximumValue: 1 onValueChanged: { if (colorButton.lightness !== value && !colorButton.block) { colorButton.lightness = value @@ -378,13 +366,9 @@ Item { anchors.verticalCenter: parent.verticalCenter } - SliderSpinBox { + DoubleSpinBox { id: alphaSlider - decimals: 2 - stepSize: 0.1 //value: colorButton.alpha - minimumValue: 0 - maximumValue: 1 onValueChanged: { if (colorButton.alpha !== value && !colorButton.block) { colorButton.alpha = value diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/SliderSpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/DoubleSpinBox.qml similarity index 90% rename from share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/SliderSpinBox.qml rename to share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/DoubleSpinBox.qml index 9bd286769e4..c80054b14ff 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/SliderSpinBox.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/DoubleSpinBox.qml @@ -29,8 +29,12 @@ import QtQuick.Controls 1.0 SpinBox { id: spinBox width: 76 + decimals: 2 + stepSize: 0.1 + minimumValue: 0 + maximumValue: 1 - property color textColor: colorLogic.textColor + property color textColor: creatorTheme.PanelTextColorLight style: CustomSpinBoxStyle { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/GradientLine.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/GradientLine.qml index 2bd1f6d631e..dd00c9d0a1d 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/GradientLine.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/GradientLine.qml @@ -25,6 +25,7 @@ import QtQuick 2.1 import HelperWidgets 2.0 +import QtQuick.Controls.Private 1.0 // showing a ToolTip Item { width: 300 @@ -100,7 +101,9 @@ Item { var gradientObject = Qt.createQmlObject(gradientString, gradientRectangle, "test"); for (i = 0; i < gradientModel.count; i++) { - repeater.itemAt(i).item.y = 20 //fixes corner case for dragging overlapped items + if (repeater.itemAt(i) !== null) + repeater.itemAt(i).item.y = 20 //fixes corner case for dragging overlapped items + gradientObject.stops[i].color = gradientModel.getColor(i) gradientObject.stops[i].position = gradientModel.getPosition(i) } @@ -199,6 +202,7 @@ Item { Component { id: component Item { + id: gradientStopHandle y: 20 width: 10 height: 20 @@ -206,6 +210,26 @@ Item { property alias color: rectangle.color property alias highlighted: canvas.highlighted + property bool toolTipVisible: false + + function refreshToolTip(showToolTip) { + toolTipVisible = showToolTip; + if (showToolTip) { + var currentPoint = Qt.point(gradientStopHandleMouseArea.mouseX, gradientStopHandleMouseArea.mouseY); + var fixedGradiantStopPosition = currentGradiantStopPosition(); + Tooltip.showText(gradientStopHandleMouseArea, currentPoint, fixedGradiantStopPosition.toFixed(3)); + } else { + Tooltip.hideText() + } + } + function currentGradiantStopPosition() { + return x / colorLine.effectiveWidth; + } + + onXChanged: { + refreshToolTip(toolTipVisible) + } + Rectangle { id: rectangle width: 10 @@ -272,21 +296,41 @@ Item { duration: 100 } } - MouseArea { + id: gradientStopHandleMouseArea anchors.fill: parent drag.target: parent drag.minimumX: 0 drag.maximumX: colorLine.effectiveWidth drag.minimumY: !readOnly ? 0 : 20 drag.maximumY: 20 + + // using pressed property instead of drag.active which was not working + onExited: { + gradientStopHandle.refreshToolTip(pressed); + } + onCanceled: { + gradientStopHandle.refreshToolTip(pressed); + } + hoverEnabled: true + + Timer { + interval: 1000 + running: gradientStopHandleMouseArea.containsMouse + onTriggered: { + gradientStopHandle.refreshToolTip(true); + } + } + onPressed: { colorLine.select(index); + gradientStopHandle.refreshToolTip(true); } onReleased: { if (drag.active) { - gradientModel.setPosition(colorLine.selectedIndex, parent.x / colorLine.effectiveWidth) + gradientModel.setPosition(colorLine.selectedIndex, gradientStopHandle.currentGradiantStopPosition()) + gradientStopHandle.refreshToolTip(false); if (parent.y < 10) { if (!readOnly) { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/images/checkers.png b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/images/checkers.png new file mode 100644 index 00000000000..72cb9f03506 Binary files /dev/null and b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/images/checkers.png differ diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/qmldir index 5aa64e7d68e..b4ee6dda7fc 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/qmldir +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/qmldir @@ -31,7 +31,7 @@ ScrollView 2.0 ScrollView.qml SecondColumnLayout 2.0 SecondColumnLayout.qml Section 2.0 Section.qml SectionLayout 2.0 SectionLayout.qml -SliderSpinBox 2.0 SliderSpinBox.qml +DoubleSpinBox 2.0 DoubleSpinBox.qml SpinBox 2.0 SpinBox.qml StandardTextSection 2.0 StandardTextSection.qml Tab 2.0 Tab.qml diff --git a/share/qtcreator/styles/creator-dark.xml b/share/qtcreator/styles/creator-dark.xml new file mode 100644 index 00000000000..2b9a333b38d --- /dev/null +++ b/share/qtcreator/styles/creator-dark.xml @@ -0,0 +1,63 @@ + + +