diff --git a/qtcreator.pro b/qtcreator.pro index f2b368b8ce6..7271ab940c4 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -74,7 +74,7 @@ macx { } else { BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX" BINDIST_INSTALLER_SOURCE = "$$BINDIST_SOURCE/*" - deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX\" + deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX\" \"$(QMAKE)\" deployqt.depends = install win32 { deployartifacts.depends = install diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index cf37f4f965f..a0b1028ff47 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -261,6 +261,9 @@ class DumperBase: self.isGdb = False self.isLldb = False + def is32bit(self): + return self.ptrSize() == 4 + def computeLimit(self, size, limit): if limit is None: return size diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 914cba7b160..ae096c907bb 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1215,7 +1215,14 @@ class Dumper(DumperBase): return toInteger(value.address) def createPointerValue(self, address, pointeeType): - return gdb.Value(address).cast(pointeeType.pointer()) + # This might not always work: + # a Python 3 based GDB due to the bug addressed in + # https://sourceware.org/ml/gdb-patches/2013-09/msg00571.html + try: + return gdb.Value(address).cast(pointeeType.pointer()) + except: + # Try _some_ fallback (good enough for the std::complex dumper) + return gdb.parse_and_eval("(%s*)%s" % (pointeeType, address)) def intSize(self): return 4 @@ -1223,11 +1230,12 @@ class Dumper(DumperBase): 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() + try: + return gdb.Value(address).cast(referencedType.pointer()).dereference() + except: + # Try _some_ fallback (good enough for the std::complex dumper) + return gdb.parse_and_eval("{%s}%s" % (referencedType, address)) def readRawMemory(self, addr, size): mem = gdb.selected_inferior().read_memory(addr, size) @@ -1362,6 +1370,9 @@ class Dumper(DumperBase): self.currentValuePriority = priority self.currentValueEncoding = None + def putSimpleValue(self, value, encoding = None, priority = 0): + self.putValue(value, encoding, priority) + def putValue(self, value, encoding = None, priority = 0): # Higher priority values override lower ones. if priority >= self.currentValuePriority: diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index b6474089823..c347c4ea096 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -53,17 +53,17 @@ proc = subprocess.Popen(args=[sys.argv[1], '-P'], stdout=subprocess.PIPE, stderr (path, error) = proc.communicate() if error.startswith('lldb: invalid option -- P'): - sys.stdout.write('msg=\'Could not run "%s -P". Trying to find lldb.so from Xcode.\'@\n' % sys.argv[1]) + sys.stdout.write('msg=\'Could not run "%s -P". Trying to find lldb.so from Xcode.\'\n' % sys.argv[1]) proc = subprocess.Popen(args=['xcode-select', '--print-path'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (path, error) = proc.communicate() if len(error): path = '/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/' - sys.stdout.write('msg=\'Could not run "xcode-select --print-path"@\n') - sys.stdout.write('msg=\'Using hardcoded fallback at %s\'@\n' % path) + sys.stdout.write('msg=\'Could not run "xcode-select --print-path"\n') + sys.stdout.write('msg=\'Using hardcoded fallback at %s\'\n' % path) else: path = path.strip() + '/../SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/' - sys.stdout.write('msg=\'Using fallback at %s\'@\n' % path) + sys.stdout.write('msg=\'Using fallback at %s\'\n' % path) #sys.path.append(path) sys.path.insert(1, path.strip()) @@ -142,7 +142,7 @@ stateNames = ["invalid", "unloaded", "connected", "attaching", "launching", "sto def loggingCallback(args): s = args.strip() s = s.replace('"', "'") - sys.stdout.write('log="%s"@\n' % s) + sys.stdout.write('log="%s"\n' % s) def check(exp): if not exp: @@ -494,9 +494,6 @@ class Dumper(DumperBase): break return qqVersion - def is32bit(self): - return False - def intSize(self): return 4 @@ -607,6 +604,9 @@ class Dumper(DumperBase): self.currentValuePriority = priority self.currentValueEncoding = None + def putSimpleValue(self, value, encoding = None, priority = 0): + self.putValue(value.GetValue(), encoding, priority) + def putValue(self, value, encoding = None, priority = 0): # Higher priority values override lower ones. if priority >= self.currentValuePriority: @@ -959,6 +959,11 @@ class Dumper(DumperBase): qdump____c_style_array__(self, value) return + # Vectors like char __attribute__ ((vector_size (8))) + if typeClass == lldb.eTypeClassVector: + qdump____c_style_array__(self, value) + return + # References if value.GetType().IsReferenceType(): origType = value.GetTypeName(); @@ -1215,13 +1220,22 @@ class Dumper(DumperBase): self.currentIName = 'local' self.put('data=[') self.anonNumber = 0 - for value in frame.GetVariables(True, True, False, False): + shadowed = {} + values = [v for v in frame.GetVariables(True, True, False, False) if v.IsValid()] + values.reverse() # To get shadowed vars numbered backwards. + for value in values: if self.dummyValue is None: self.dummyValue = value - with SubItem(self, value): - if value.IsValid(): - self.put('iname="%s",' % self.currentIName) - self.putItem(value) + name = value.name + if value.name in shadowed: + level = shadowed[name] + shadowed[name] = level + 1 + name += "@%s" % level + else: + shadowed[name] = 1 + with SubItem(self, name): + self.put('iname="%s",' % self.currentIName) + self.putItem(value) # 'watchers':[{'id':'watch.0','exp':'23'},...] if not self.dummyValue is None: @@ -1275,8 +1289,7 @@ class Dumper(DumperBase): self.report(result) def report(self, stuff): - sys.stdout.write(stuff) - sys.stdout.write("@\n") + sys.stdout.write(stuff + "\n") def interruptInferior(self, _ = None): if self.process is None: @@ -1699,32 +1712,11 @@ def doit(): for reader in readable: if reader == sys.stdin: line = sys.stdin.readline() - #warn("READING LINE '%s'" % line) - if line.startswith("db "): - line = line.replace("'", '"')[3:] + try: db.execute(convertHash(json.loads(line))) - - -def testit1(): - - db = Dumper() - - db.setupInferior({'cmd':'setupInferior','executable':sys.argv[2],'token':1}) - db.handleBreakpoints({'cmd':'handleBreakpoints','bkpts':[{'operation':'add', - 'modelid':'1','type':2,'ignorecount':0,'condition':'','function':'main', - 'oneshot':0,'enabled':1,'file':'','line':0}]}) - db.runEngine({'cmd':'runEngine','token':4}) - - while True: - readable, _, _ = select.select([sys.stdin], [], []) - for reader in readable: - if reader == sys.stdin: - line = sys.stdin.readline().strip() - #warn("READING LINE '%s'" % line) - if line.startswith("db "): - db.execute(eval(line[3:])) - else: - db.executeDebuggerCommand({'command':line}) + except: + warn("EXCEPTION CAUGHT: %s" % sys.exc_info()[1]) + pass # Used in dumper auto test. diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index a80986ef744..e28df11ea31 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -235,8 +235,8 @@ def qdump__QDateTime(d, value): # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), ... base = d.dereferenceValue(value) - dateBase = base + d.ptrSize() # Only QAtomicInt, but will be padded. if qtVersion >= 0x050200: + dateBase = base + d.ptrSize() # Only QAtomicInt, but will be padded. ms = d.extractInt64(dateBase) offset = d.extractInt(dateBase + 12) isValid = ms > 0 @@ -248,11 +248,14 @@ def qdump__QDateTime(d, value): # QDateTimePrivate: # - QAtomicInt ref; (padded on 64 bit) # - [QDate date;] - # - - uint jd in Qt 4, qint64 in Qt 5.0 and Qt 5.2; padded on 64 bit + # - - uint jd in Qt 4, qint64 in Qt 5.0 and Qt 5.1; padded on 64 bit # - [QTime time;] # - - uint mds; # - Spec spec; - dateSize = 4 if qtVersion < 0x050000 and d.is32bit() else 8 + dateSize = 8 if qtVersion >= 0x050000 else 4 # Qt5: qint64, Qt4 uint + # 4 byte padding after 4 byte QAtomicInt if we are on 64 bit and QDate is 64 bit + refPlusPadding = 8 if qtVersion >= 0x050000 and not d.is32bit() else 4 + dateBase = base + refPlusPadding timeBase = dateBase + dateSize mds = d.extractInt(timeBase) isValid = mds > 0 @@ -286,36 +289,49 @@ def qdump__QDir(d, value): privAddress = d.dereferenceValue(value) bit32 = d.is32bit() qt5 = d.qtVersion() >= 0x050000 - # value.d_ptr.d.dirEntry.m_filePath - value.d_ptr.d - offset = (32 if bit32 else 56) 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.putStringValueByAddress(filePathAddress) + # QDirPrivate: + # QAtomicInt ref + # QStringList nameFilters; + # QDir::SortFlags sort; + # QDir::Filters filters; + # // qt3support: + # QChar filterSepChar; + # bool matchAllDirs; + # // end qt3support + # QScopedPointer fileEngine; + # bool fileListsInitialized; + # QStringList files; + # QFileInfoList fileInfos; + # QFileSystemEntry dirEntry; + # QFileSystemEntry absoluteDirEntry; + qt3SupportAddition = 0 if qt5 else d.ptrSize() # qt5 doesn't have qt3support + filesOffset = (24 if bit32 else 40) + qt3SupportAddition + fileInfosOffset = filesOffset + d.ptrSize() + dirEntryOffset = fileInfosOffset + d.ptrSize() + # QFileSystemEntry: + # QString m_filePath + # QByteArray m_nativeFilePath + # qint16 m_lastSeparator + # qint16 m_firstDotInFileName + # qint16 m_lastDotInFileName + # + 2 byte padding + fileSystemEntrySize = 2 * d.ptrSize() + 8 + absoluteDirEntryOffset = dirEntryOffset + fileSystemEntrySize + d.putStringValueByAddress(privAddress + dirEntryOffset) if d.isExpanded(): with Children(d): d.call(value, "count") # Fill cache. #d.putCallItem("absolutePath", value, "absolutePath") #d.putCallItem("canonicalPath", value, "canonicalPath") with SubItem(d, "absolutePath"): - # value.d_ptr.d.absoluteDirEntry.m_filePath - value.d_ptr.d - offset = (48 if bit32 else 80) if qt5 else 36 typ = d.lookupType(d.ns + "QString") - d.putItem(d.createValue(privAddress + offset, typ)) + d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, typ)) with SubItem(d, "entryInfoList"): - # value.d_ptr.d.fileInfos - value.d_ptr.d - offset = (28 if bit32 else 48) if qt5 else 32 typ = d.lookupType(d.ns + "QList<" + d.ns + "QFileInfo>") - d.putItem(d.createValue(privAddress + offset, typ)) + d.putItem(d.createValue(privAddress + fileInfosOffset, typ)) with SubItem(d, "entryList"): - # d.ptr.d.files - value.d_ptr.d - offset = (24 if bit32 else 40) if qt5 else 28 typ = d.lookupType(d.ns + "QStringList") - d.putItem(d.createValue(privAddress + offset, typ)) + d.putItem(d.createValue(privAddress + filesOffset, typ)) def qdump__QFile(d, value): @@ -326,9 +342,10 @@ def qdump__QFile(d, value): fileNameAddress = d.addressOf(d_ptr.cast(ptype).dereference()["fileName"]) d.putNumChild(1) except: - # 176 and 280 are best guesses for Qt 5 - offset = 176 if d.is32bit() else 280 - #qt5 = d.qtVersion() >= 0x050000 + if d.qtVersion() >= 0x050000: + offset = 176 if d.is32bit() else 280 + else: + offset = 140 if d.is32bit() else 232 privAddress = d.dereference(d.addressOf(value) + d.ptrSize()) fileNameAddress = privAddress + offset d.putNumChild(0) @@ -524,7 +541,10 @@ def qdump__QHash(d, value): it = nodePtr.dereference().cast(innerType) with SubItem(d, i): if isCompact: - d.putMapName(it["key"]) + # cannot reference "key" directly because it is inside + # anonymous union for (u)int key in Qt4 + keyAddress = d.addressOf(it) + d.ptrSize() # addr + QHashNode* + d.putMapName(d.createValue(keyAddress, keyType)) d.putItem(it["value"]) d.putType(valueType) else: @@ -1482,6 +1502,7 @@ def qdump__QRegion(d, value): d.putIntItem("numRects", n) d.putSubItem("extents", d.createValue(pp + 2 * v, rectType)) d.putSubItem("innerRect", d.createValue(pp + 2 * v + rectType.sizeof, rectType)) + d.putIntItem("innerArea", d.extractInt(pp + 2 * v + 2 * rectType.sizeof)) # FIXME try: # Can fail if QVector debuginfo is missing. @@ -1894,8 +1915,12 @@ def qdump__QVariant(d, value): # User types. d_ptr = value["d"] typeCode = int(d_ptr["type"]) - exp = "((const char *(*)(int))%sQMetaType::typeName)(%d)" % (d.ns, typeCode) - type = str(d.parseAndEvaluate(exp)) + try: + exp = "((const char *(*)(int))%sQMetaType::typeName)(%d)" % (d.ns, typeCode) + type = str(d.parseAndEvaluate(exp)) + except: + exp = "%sQMetaType::typeName(%d)" % (d.ns, typeCode) + type = str(d.parseAndEvaluate(exp)) type = type[type.find('"') + 1 : type.rfind('"')] type = type.replace("Q", d.ns + "Q") # HACK! type = type.replace("uint", "unsigned int") # HACK! @@ -1969,16 +1994,15 @@ def qdump__QWeakPointer(d, value): d.check(strongref <= weakref) d.check(weakref <= 10*1000*1000) - if d.isSimpleType(val.dereference().type): - d.putNumChild(3) - d.putItem(val.dereference()) + innerType = d.templateArgument(value.type, 0) + if d.isSimpleType(innerType): + d.putSimpleValue(val.dereference()) else: d.putEmptyValue() d.putNumChild(3) if d.isExpanded(): with Children(d): - innerType = d.templateArgument(value.type, 0) d.putSubItem("data", val.dereference().cast(innerType)) d.putIntItem("weakref", weakref) d.putIntItem("strongref", strongref) diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index d0fac283c0b..c29cbfed11a 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -79,9 +79,8 @@ def qdump__std____1__array(d, value): def qdump__std__complex(d, value): innerType = d.templateArgument(value.type, 0) - base = value.address.cast(innerType.pointer()) - real = base.dereference() - imag = (base + 1).dereference() + real = value.cast(innerType) + imag = d.createValue(d.addressOf(value) + innerType.sizeof, innerType) d.putValue("(%f, %f)" % (real, imag)); d.putNumChild(2) if d.isExpanded(): @@ -116,7 +115,7 @@ def qdump__std__deque(d, value): for i in d.childRange(): d.putSubItem(i, pcur.dereference()) pcur += 1 - if pcur == plast: + if toInteger(pcur) == toInteger(plast): newnode = pnode + 1 pnode = newnode pfirst = newnode.dereference() @@ -221,14 +220,14 @@ def qdump__std____cxx1998__map(d, value): qdump__std__map(d, value) def stdTreeIteratorHelper(d, value): - pnode = value["_M_node"] - node = pnode.dereference() + node = value["_M_node"].dereference() d.putNumChild(1) d.putEmptyValue() if d.isExpanded(): - dataType = d.templateArgument(value.type, 0) - nodeType = d.lookupType("std::_Rb_tree_node<%s>" % dataType) - data = pnode.cast(nodeType.pointer()).dereference()["_M_value_field"] + nodeTypeName = str(value.type).replace("_Rb_tree_iterator", "_Rb_tree_node", 1) + nodeTypeName = nodeTypeName.replace("_Rb_tree_const_iterator", "_Rb_tree_node", 1) + nodeType = d.lookupType(nodeTypeName) + data = node.cast(nodeType)["_M_value_field"] with Children(d): try: d.putSubItem("first", data["first"]) @@ -443,21 +442,36 @@ def qform__std____debug__unordered_map(): return mapForms() def qdump__std__unordered_map(d, value): + keyType = d.templateArgument(value.type, 0) + valueType = d.templateArgument(value.type, 1) + allocatorType = d.templateArgument(value.type, 4) + pairType = d.templateArgument(allocatorType, 0) + ptrSize = d.ptrSize() try: + # gcc >= 4.7 size = value["_M_element_count"] start = value["_M_before_begin"]["_M_nxt"] + offset = 0 except: - size = value["_M_h"]["_M_element_count"] - start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"] + try: + # libc++ (Mac) + size = value["_M_h"]["_M_element_count"] + start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"] + offset = 0 + except: + # gcc 4.6.2 + size = value["_M_element_count"] + start = value["_M_buckets"].dereference() + # FIXME: Pointer-aligned? + offset = pairType.sizeof + d.putItemCount(size) + # We don't know where the data is + d.putNumChild(0) + return d.putItemCount(size) d.putNumChild(size) if d.isExpanded(): p = d.pointerValue(start) - keyType = d.templateArgument(value.type, 0) - valueType = d.templateArgument(value.type, 1) - allocatorType = d.templateArgument(value.type, 4) - pairType = d.templateArgument(allocatorType, 0) - ptrSize = d.ptrSize() if d.isMapCompact(keyType, valueType): with Children(d, size, childType=valueType): for i in d.childRange(): @@ -470,19 +484,29 @@ def qdump__std__unordered_map(d, value): else: with Children(d, size, childType=pairType): for i in d.childRange(): - d.putSubItem(i, d.createValue(p + ptrSize, pairType)) - p = d.dereference(p) + d.putSubItem(i, d.createValue(p + ptrSize - offset, pairType)) + p = d.dereference(p + offset) def qdump__std____debug__unordered_map(d, value): qdump__std__unordered_map(d, value) def qdump__std__unordered_set(d, value): try: + # gcc >= 4.7 size = value["_M_element_count"] start = value["_M_before_begin"]["_M_nxt"] + offset = 0 except: - size = value["_M_h"]["_M_element_count"] - start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"] + try: + # libc++ (Mac) + size = value["_M_h"]["_M_element_count"] + start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"] + offset = 0 + except: + # gcc 4.6.2 + size = value["_M_element_count"] + start = value["_M_buckets"].dereference() + offset = d.ptrSize() d.putItemCount(size) d.putNumChild(size) if d.isExpanded(): @@ -491,8 +515,18 @@ def qdump__std__unordered_set(d, value): with Children(d, size, childType=valueType): ptrSize = d.ptrSize() for i in d.childRange(): - d.putSubItem(i, d.createValue(p + ptrSize, valueType)) - p = d.dereference(p) + d.putSubItem(i, d.createValue(p + ptrSize - offset, valueType)) + p = d.dereference(p + offset) + +def qform__std____1__unordered_map(): + return mapForms() + +def qdump__std____1__unordered_map(d, value): + n = toInteger(value["__table_"]["__p2_"]["__first_"]) + d.putItemCount(n) + if d.isExpanded(): + with Children(d, 1): + d.putFields(value) def qdump__std____debug__unordered_set(d, value): qdump__std__unordered_set(d, value) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp index cf1455a9db4..9cb611272ae 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp @@ -1015,6 +1015,10 @@ QObject *ObjectNodeInstance::createCustomParserObject(const QString &nodeSource, QObject *ObjectNodeInstance::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context) { + ComponentCompleteDisabler disableComponentComplete; + + Q_UNUSED(disableComponentComplete) + QObject *object = 0; QQmlType *type = QQmlMetaType::qmlType(typeName.toUtf8(), majorNumber, minorNumber); if (type) { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/CustomComboBoxStyle.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/CustomComboBoxStyle.qml index 185ac8b7ce7..29f03abdcb5 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/CustomComboBoxStyle.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/CustomComboBoxStyle.qml @@ -67,12 +67,24 @@ ComboBoxStyle { opacity: 0.3 visible: control.activeFocus } + + Rectangle { + color: "#333" + width: 1 + anchors.right: imageItem.left + anchors.topMargin: 4 + anchors.bottomMargin: 4 + anchors.rightMargin: 6 + anchors.top: parent.top + anchors.bottom: parent.bottom + } + Image { id: imageItem source: "images/down-arrow.png" anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - anchors.rightMargin: 8 + anchors.rightMargin: 10 opacity: control.enabled ? 0.7 : 0.5 } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/Section.qml index c59fe14ad98..9380e844ce2 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/Section.qml @@ -52,6 +52,9 @@ Item { anchors.verticalCenter: parent.verticalCenter color: "white" x: 22 + style: Text.Sunken + styleColor: "#292929" + font.bold: true } Image { @@ -103,9 +106,10 @@ Item { x: 8 y: header.height + 4 id: row + Behavior on opacity { NumberAnimation{easing.type: Easing.Linear ; duration: 80} } } - Behavior on height { NumberAnimation{easing.type: Easing.OutCubic ; duration: 60} } + Behavior on height { NumberAnimation{easing.type: Easing.OutCubic ; duration: 140} } states: [ State { @@ -114,6 +118,11 @@ Item { target: section height: header.height } + PropertyChanges { + target: row + opacity: 0 + + } } ] diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/TabView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/TabView.qml index 9a5bdbdb9cd..2f46721e2a8 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/TabView.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/HelperWidgets/TabView.qml @@ -40,26 +40,28 @@ Controls.TabView { frameOverlap: 0 frame: Item { } tab: Rectangle { - color: styleData.selected ? "#eee" : "#444" + color: styleData.selected ? "#eee" : "#414141" implicitWidth: root.width/root.count + 2 - implicitHeight: 21 + implicitHeight: 28 Text { id: text + font.bold: true anchors.centerIn: parent + anchors.verticalCenterOffset: -1 text: styleData.title renderType: Text.NativeRendering - color: styleData.selected ? "#000" : "#fff" + color: styleData.selected ? "#333" : "#fff" } + Rectangle { - anchors.fill: parent - opacity: 0.10 - gradient: Gradient { - GradientStop {color: '#fff' ; position: 0} - GradientStop {color: '#000' ; position: 1} - } + color: "#eee" + width: parent.width + height: 4 + anchors.bottom: parent.bottom } + Rectangle { - color: "#666" + color: "#333" width: parent.width height: 1 } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml index 4090bb48146..c6193a4deda 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ItemPane.qml @@ -35,12 +35,13 @@ Rectangle { id: itemPane width: 320 height: 400 - color: "#404040" + color: "#4f4f4f" ScrollView { anchors.fill: parent Column { + y: -1 width: itemPane.width Section { caption: qsTr("Type") @@ -95,12 +96,12 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right - caption: qsTr("Visibilty") + caption: qsTr("Visibility") SectionLayout { rows: 2 Label { - text: qsTr("Visibilty") + text: qsTr("Visibility") } SecondColumnLayout { @@ -146,6 +147,11 @@ Rectangle { } } + Item { + height: 4 + width: 4 + } + TabView { anchors.left: parent.left anchors.right: parent.right diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml index 15f6a80781e..dd0b2834c58 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/emptyPane.qml @@ -34,9 +34,10 @@ Rectangle { id: itemPane width: 320 height: 400 - color: "#404040" + color: "#4f4f4f" Section { + y: -1 anchors.left: parent.left anchors.right: parent.right diff --git a/share/qtcreator/templates/qtquickapp/app.pro b/share/qtcreator/templates/qtquick1app/app.pro similarity index 88% rename from share/qtcreator/templates/qtquickapp/app.pro rename to share/qtcreator/templates/qtquick1app/app.pro index e96d5e0c4be..19aef272818 100644 --- a/share/qtcreator/templates/qtquickapp/app.pro +++ b/share/qtcreator/templates/qtquick1app/app.pro @@ -25,7 +25,7 @@ SOURCES += main.cpp # target.path = # Please do not modify the following two lines. Required for deployment. -include(qmlapplicationviewer/qmlapplicationviewer.pri) -# REMOVE_NEXT_LINE (wizard will remove the include and append deployment.pri to qmlapplicationviewer.pri, instead) # +include(qtquick1applicationviewer/qtquick1applicationviewer.pri) +# REMOVE_NEXT_LINE (wizard will remove the include and append deployment.pri to qtquick1applicationviewer.pri, instead) # include(../shared/deployment.pri) qtcAddDeployment() diff --git a/share/qtcreator/templates/qtquickapp/main.cpp b/share/qtcreator/templates/qtquick1app/main.cpp similarity index 63% rename from share/qtcreator/templates/qtquickapp/main.cpp rename to share/qtcreator/templates/qtquick1app/main.cpp index 3cd4a57edc3..70b2e9ea7eb 100644 --- a/share/qtcreator/templates/qtquickapp/main.cpp +++ b/share/qtcreator/templates/qtquick1app/main.cpp @@ -1,13 +1,13 @@ -#include "qmlapplicationviewer.h" +#include "qtquick1applicationviewer.h" #include int main(int argc, char *argv[]) { QApplication app(argc, argv); - QmlApplicationViewer viewer; + QtQuick1ApplicationViewer viewer; viewer.addImportPath(QLatin1String("modules")); // ADDIMPORTPATH - viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); // ORIENTATION + viewer.setOrientation(QtQuick1ApplicationViewer::ScreenOrientationAuto); // ORIENTATION viewer.setMainQmlFile(QLatin1String("qml/app/qtquick10/main.qml")); // MAINQML viewer.showExpanded(); diff --git a/share/qtcreator/templates/qtquickapp/qml/app/meego10/MainPage.qml b/share/qtcreator/templates/qtquick1app/qml/app/meego10/MainPage.qml similarity index 100% rename from share/qtcreator/templates/qtquickapp/qml/app/meego10/MainPage.qml rename to share/qtcreator/templates/qtquick1app/qml/app/meego10/MainPage.qml diff --git a/share/qtcreator/templates/qtquickapp/qml/app/meego10/main.qml b/share/qtcreator/templates/qtquick1app/qml/app/meego10/main.qml similarity index 100% rename from share/qtcreator/templates/qtquickapp/qml/app/meego10/main.qml rename to share/qtcreator/templates/qtquick1app/qml/app/meego10/main.qml diff --git a/share/qtcreator/templates/qtquickapp/qml/app/qtquick10/main.qml b/share/qtcreator/templates/qtquick1app/qml/app/qtquick10/main.qml similarity index 100% rename from share/qtcreator/templates/qtquickapp/qml/app/qtquick10/main.qml rename to share/qtcreator/templates/qtquick1app/qml/app/qtquick10/main.qml diff --git a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp b/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.cpp similarity index 59% rename from share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp rename to share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.cpp index b29054eb0d1..d487e109f9c 100644 --- a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.cpp +++ b/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.cpp @@ -1,13 +1,13 @@ /* - This file was generated by the Qt Quick Application wizard of Qt Creator. - QmlApplicationViewer is a convenience class containing mobile device specific - code such as screen orientation handling. Also QML paths and debugging are + This file was generated by the Qt Quick 1 Application wizard of Qt Creator. + QtQuick1ApplicationViewer is a convenience class containing mobile device + specific code such as screen orientation handling. Also QML paths are handled here. It is recommended not to modify this file, since newer versions of Qt Creator may offer an updated version of it. */ -#include "qmlapplicationviewer.h" +#include "qtquick1applicationviewer.h" #include #include @@ -18,14 +18,14 @@ #include // MEEGO_EDITION_HARMATTAN -class QmlApplicationViewerPrivate +class QtQuick1ApplicationViewerPrivate { QString mainQmlFile; - friend class QmlApplicationViewer; + friend class QtQuick1ApplicationViewer; static QString adjustPath(const QString &path); }; -QString QmlApplicationViewerPrivate::adjustPath(const QString &path) +QString QtQuick1ApplicationViewerPrivate::adjustPath(const QString &path) { #ifdef Q_OS_MAC if (!QDir::isAbsolutePath(path)) @@ -36,38 +36,40 @@ QString QmlApplicationViewerPrivate::adjustPath(const QString &path) return QString::fromLatin1("app/native/%1").arg(path); #elif !defined(Q_OS_ANDROID) QString pathInInstallDir = - QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path); + QString::fromLatin1("%1/../%2").arg( + QCoreApplication::applicationDirPath(), path); if (QFileInfo(pathInInstallDir).exists()) return pathInInstallDir; pathInInstallDir = - QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path); + QString::fromLatin1("%1/%2").arg( + QCoreApplication::applicationDirPath(), path); if (QFileInfo(pathInInstallDir).exists()) return pathInInstallDir; #endif return path; } -QmlApplicationViewer::QmlApplicationViewer(QWidget *parent) +QtQuick1ApplicationViewer::QtQuick1ApplicationViewer(QWidget *parent) : QDeclarativeView(parent) - , d(new QmlApplicationViewerPrivate()) + , d(new QtQuick1ApplicationViewerPrivate()) { connect(engine(), SIGNAL(quit()), SLOT(close())); setResizeMode(QDeclarativeView::SizeRootObjectToView); } -QmlApplicationViewer::~QmlApplicationViewer() +QtQuick1ApplicationViewer::~QtQuick1ApplicationViewer() { delete d; } -QmlApplicationViewer *QmlApplicationViewer::create() +QtQuick1ApplicationViewer *QtQuick1ApplicationViewer::create() { - return new QmlApplicationViewer(); + return new QtQuick1ApplicationViewer(); } -void QmlApplicationViewer::setMainQmlFile(const QString &file) +void QtQuick1ApplicationViewer::setMainQmlFile(const QString &file) { - d->mainQmlFile = QmlApplicationViewerPrivate::adjustPath(file); + d->mainQmlFile = QtQuick1ApplicationViewerPrivate::adjustPath(file); #ifdef Q_OS_ANDROID setSource(QUrl(QLatin1String("assets:/")+d->mainQmlFile)); #else @@ -75,12 +77,12 @@ void QmlApplicationViewer::setMainQmlFile(const QString &file) #endif } -void QmlApplicationViewer::addImportPath(const QString &path) +void QtQuick1ApplicationViewer::addImportPath(const QString &path) { - engine()->addImportPath(QmlApplicationViewerPrivate::adjustPath(path)); + engine()->addImportPath(QtQuick1ApplicationViewerPrivate::adjustPath(path)); } -void QmlApplicationViewer::setOrientation(ScreenOrientation orientation) +void QtQuick1ApplicationViewer::setOrientation(ScreenOrientation orientation) { #if QT_VERSION < 0x050000 Qt::WidgetAttribute attribute; @@ -102,7 +104,7 @@ void QmlApplicationViewer::setOrientation(ScreenOrientation orientation) #endif // QT_VERSION < 0x050000 } -void QmlApplicationViewer::showExpanded() +void QtQuick1ApplicationViewer::showExpanded() { #if defined(Q_WS_SIMULATOR) || defined(Q_OS_QNX) showFullScreen(); diff --git a/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.h b/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.h new file mode 100644 index 00000000000..b9dc3a9fee4 --- /dev/null +++ b/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.h @@ -0,0 +1,43 @@ +/* + This file was generated by the Qt Quick 1 Application wizard of Qt Creator. + QtQuick1ApplicationViewer is a convenience class containing mobile device + specific code such as screen orientation handling. Also QML paths are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QTQUICK1APPLICATIONVIEWER_H +#define QTQUICK1APPLICATIONVIEWER_H + +#include + +class QtQuick1ApplicationViewer : public QDeclarativeView +{ + Q_OBJECT + +public: + enum ScreenOrientation { + ScreenOrientationLockPortrait, + ScreenOrientationLockLandscape, + ScreenOrientationAuto + }; + + explicit QtQuick1ApplicationViewer(QWidget *parent = 0); + virtual ~QtQuick1ApplicationViewer(); + + static QtQuick1ApplicationViewer *create(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + + // Note that this will only have an effect on Fremantle. + void setOrientation(ScreenOrientation orientation); + + void showExpanded(); + +private: + class QtQuick1ApplicationViewerPrivate *d; +}; + +#endif // QTQUICK1APPLICATIONVIEWER_H diff --git a/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.pri b/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.pri new file mode 100644 index 00000000000..030edc1d018 --- /dev/null +++ b/share/qtcreator/templates/qtquick1app/qtquick1applicationviewer/qtquick1applicationviewer.pri @@ -0,0 +1,11 @@ +# This file was generated by the Qt Quick 1 Application wizard of Qt Creator. +# The code below adds the QtQuick1ApplicationViewer to the project. +# +# It is recommended not to modify this file, since newer versions of Qt Creator +# may offer an updated version of it. + +QT += declarative + +SOURCES += $$PWD/qtquick1applicationviewer.cpp +HEADERS += $$PWD/qtquick1applicationviewer.h +INCLUDEPATH += $$PWD diff --git a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.h b/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.h deleted file mode 100644 index 183ff8bea63..00000000000 --- a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file was generated by the Qt Quick Application wizard of Qt Creator. - QmlApplicationViewer is a convenience class containing mobile device specific - code such as screen orientation handling. Also QML paths and debugging are - handled here. - It is recommended not to modify this file, since newer versions of Qt Creator - may offer an updated version of it. -*/ - -#ifndef QMLAPPLICATIONVIEWER_H -#define QMLAPPLICATIONVIEWER_H - -#include - -class QmlApplicationViewer : public QDeclarativeView -{ - Q_OBJECT - -public: - enum ScreenOrientation { - ScreenOrientationLockPortrait, - ScreenOrientationLockLandscape, - ScreenOrientationAuto - }; - - explicit QmlApplicationViewer(QWidget *parent = 0); - virtual ~QmlApplicationViewer(); - - static QmlApplicationViewer *create(); - - void setMainQmlFile(const QString &file); - void addImportPath(const QString &path); - - // Note that this will only have an effect on Fremantle. - void setOrientation(ScreenOrientation orientation); - - void showExpanded(); - -private: - class QmlApplicationViewerPrivate *d; -}; - -QApplication *createApplication(int &argc, char **argv); - -#endif // QMLAPPLICATIONVIEWER_H diff --git a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.pri b/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.pri deleted file mode 100644 index bac43a6d800..00000000000 --- a/share/qtcreator/templates/qtquickapp/qmlapplicationviewer/qmlapplicationviewer.pri +++ /dev/null @@ -1,11 +0,0 @@ -# This file was generated by the Qt Quick Application wizard of Qt Creator. -# The code below adds the QmlApplicationViewer to the project and handles the -# activation of QML debugging. -# It is recommended not to modify this file, since newer versions of Qt Creator -# may offer an updated version of it. - -QT += declarative - -SOURCES += $$PWD/qmlapplicationviewer.cpp -HEADERS += $$PWD/qmlapplicationviewer.h -INCLUDEPATH += $$PWD diff --git a/share/qtcreator/templates/wizards/qtquick1-extension/wizard.xml b/share/qtcreator/templates/wizards/qtquick1-extension/wizard.xml index ce311f620e3..5f305c04417 100644 --- a/share/qtcreator/templates/wizards/qtquick1-extension/wizard.xml +++ b/share/qtcreator/templates/wizards/qtquick1-extension/wizard.xml @@ -51,7 +51,7 @@ leave room for the Qt 4 target page. - Custom QML Extension Plugin Parameters + Custom QML Extension Plugin Parameters diff --git a/share/qtcreator/templates/wizards/qtquick2-extension/wizard.xml b/share/qtcreator/templates/wizards/qtquick2-extension/wizard.xml index 16c624d21ab..8de803a7231 100644 --- a/share/qtcreator/templates/wizards/qtquick2-extension/wizard.xml +++ b/share/qtcreator/templates/wizards/qtquick2-extension/wizard.xml @@ -51,7 +51,7 @@ leave room for the Qt 4 target page. - Custom QML Extension Plugin Parameters + Custom QML Extension Plugin Parameters diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 80ef5bc5ff3..ef3b5c5e778 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -38,6 +38,10 @@ #include #include +#ifdef Q_OS_WIN +#include +#endif + namespace Utils { /*! \class Utils::FileUtils @@ -237,6 +241,60 @@ bool FileUtils::makeWritable(const FileName &path) return QFile::setPermissions(fileName, QFile::permissions(fileName) | QFile::WriteUser); } +#ifdef Q_OS_WIN +static QString getShortPathName(const QString &name) +{ + if (name.isEmpty()) + return name; + + // Determine length, then convert. + const LPCTSTR nameC = reinterpret_cast(name.utf16()); // MinGW + const DWORD length = GetShortPathNameW(nameC, NULL, 0); + if (length == 0) + return name; + QScopedArrayPointer buffer(new TCHAR[length]); + GetShortPathNameW(nameC, buffer.data(), length); + const QString rc = QString::fromUtf16(reinterpret_cast(buffer.data()), length - 1); + return rc; +} + +static QString getLongPathName(const QString &name) +{ + if (name.isEmpty()) + return name; + + // Determine length, then convert. + const LPCTSTR nameC = reinterpret_cast(name.utf16()); // MinGW + const DWORD length = GetLongPathNameW(nameC, NULL, 0); + if (length == 0) + return name; + QScopedArrayPointer buffer(new TCHAR[length]); + GetLongPathNameW(nameC, buffer.data(), length); + const QString rc = QString::fromUtf16(reinterpret_cast(buffer.data()), length - 1); + return rc; +} +#endif // Q_OS_WIN + +// makes sure that capitalization of directories is canonical on Windows. +// This mimics the logic in QDeclarative_isFileCaseCorrect +QString FileUtils::normalizePathName(const QString &name) +{ +#ifdef Q_OS_WIN + QString canonicalName = getShortPathName(name); + if (canonicalName.isEmpty()) + return name; + canonicalName = getLongPathName(canonicalName); + if (canonicalName.isEmpty()) + return name; + // Upper case drive letter + if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':')) + canonicalName[0] = canonicalName.at(0).toUpper(); + return canonicalName; +#else // Filesystem is case-insensitive only on Windows + return name; +#endif +} + QByteArray FileReader::fetchQrc(const QString &fileName) { QTC_ASSERT(fileName.startsWith(QLatin1Char(':')), return QByteArray()); diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index 0cf1db64b18..0b19a913fbd 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -98,6 +98,7 @@ public: static QString shortNativePath(const FileName &path); static QString fileSystemFriendlyName(const QString &name); static bool makeWritable(const FileName &path); + static QString normalizePathName(const QString &name); }; class QTCREATOR_UTILS_EXPORT FileReader diff --git a/src/libs/utils/function.cpp b/src/libs/utils/function.cpp index 68370976d87..45f02f776df 100644 --- a/src/libs/utils/function.cpp +++ b/src/libs/utils/function.cpp @@ -41,7 +41,7 @@ void functionUser(Utils::function generator, Utils::function c struct GenFunctor { - int operator()() { return 29; } + int operator()() const { return 29; } }; struct ConsumerFunctor @@ -49,6 +49,13 @@ struct ConsumerFunctor void operator()(int) {} }; +struct ConsumerFunctor2 +{ + ConsumerFunctor2() : i(0) { } + int i; + void operator()(int j) { i = j; } +}; + int generatorF() { return 42; @@ -64,6 +71,9 @@ void test() { functionUser(GenFunctor(), ConsumerFunctor()); functionUser(&generatorF, &consumerF); + ConsumerFunctor2 f2; + GenFunctor g2; + functionUser(Utils::cref(g2), Utils::ref(f2)); } } // end namespace diff --git a/src/libs/utils/function.h b/src/libs/utils/function.h index d6dbc2f9999..52938f385e4 100644 --- a/src/libs/utils/function.h +++ b/src/libs/utils/function.h @@ -39,9 +39,9 @@ # ifdef __GNUC__ # include # endif -namespace Utils { using std::tr1::function; } +namespace Utils { using std::tr1::function; using std::tr1::ref; using std::tr1::cref; } #else -namespace Utils { using std::function; } +namespace Utils { using std::function; using std::ref; using std::cref; } #endif #endif // QTC_FUNCTION_H diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 9305680ad58..d6e3a59301b 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -654,6 +654,11 @@ void PathChooser::installLineEditVersionToolTip(QLineEdit *le, const QStringList ef->setArguments(arguments); } +void PathChooser::setHistoryCompleter(const QString &historyKey) +{ + d->m_lineEdit->setHistoryCompleter(historyKey); +} + QStringList PathChooser::commandVersionArguments() const { return d->m_binaryVersionToolTipEventFilter ? diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index 2dc33c0c9d0..483c94e576f 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -128,6 +128,9 @@ public: // Install a tooltip on lineedits used for binaries showing the version. static void installLineEditVersionToolTip(QLineEdit *le, const QStringList &arguments); + // Enable a history completer with a history of entries. + void setHistoryCompleter(const QString &historyKey); + bool isReadOnly() const; void setReadOnly(bool b); diff --git a/src/libs/utils/winutils.cpp b/src/libs/utils/winutils.cpp index cf54a24d4f3..59daad82df9 100644 --- a/src/libs/utils/winutils.cpp +++ b/src/libs/utils/winutils.cpp @@ -129,54 +129,6 @@ QTCREATOR_UTILS_EXPORT QString winGetDLLVersion(WinDLLVersionType t, return rc; } -QTCREATOR_UTILS_EXPORT QString getShortPathName(const QString &name) -{ - if (name.isEmpty()) - return name; - - // Determine length, then convert. - const LPCTSTR nameC = reinterpret_cast(name.utf16()); // MinGW - const DWORD length = GetShortPathNameW(nameC, NULL, 0); - if (length == 0) - return name; - QScopedArrayPointer buffer(new TCHAR[length]); - GetShortPathNameW(nameC, buffer.data(), length); - const QString rc = QString::fromUtf16(reinterpret_cast(buffer.data()), length - 1); - return rc; -} - -QTCREATOR_UTILS_EXPORT QString getLongPathName(const QString &name) -{ - if (name.isEmpty()) - return name; - - // Determine length, then convert. - const LPCTSTR nameC = reinterpret_cast(name.utf16()); // MinGW - const DWORD length = GetLongPathNameW(nameC, NULL, 0); - if (length == 0) - return name; - QScopedArrayPointer buffer(new TCHAR[length]); - GetLongPathNameW(nameC, buffer.data(), length); - const QString rc = QString::fromUtf16(reinterpret_cast(buffer.data()), length - 1); - return rc; -} - -// makes sure that capitalization of directories is canonical. -// This mimics the logic in QDeclarative_isFileCaseCorrect -QTCREATOR_UTILS_EXPORT QString normalizePathName(const QString &name) -{ - QString canonicalName = getShortPathName(name); - if (canonicalName.isEmpty()) - return name; - canonicalName = getLongPathName(canonicalName); - if (canonicalName.isEmpty()) - return name; - // Upper case drive letter - if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':')) - canonicalName[0] = canonicalName.at(0).toUpper(); - return canonicalName; -} - QTCREATOR_UTILS_EXPORT bool winIs64BitSystem() { SYSTEM_INFO systemInfo; diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 80d1c9451ab..ee39135f5d6 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index 405f317ef50..75e39a6f9ec 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -336,7 +336,7 @@ void AndroidDeployQtStep::runCommand(const QString &program, const QStringList & QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.") .arg(program).arg(arguments.join(QLatin1String(" "))); if (buildProc.error() != QProcess::UnknownError) - mainMessage += tr(" Reason: %1").arg(buildProc.errorString()); + mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc.errorString()); else mainMessage += tr("Exit code: %1").arg(buildProc.exitCode()); emit addOutput(mainMessage, BuildStep::ErrorMessageOutput); diff --git a/src/plugins/android/androiddeploystep.cpp b/src/plugins/android/androiddeploystep.cpp index d8264898d87..dcdb8968ffc 100644 --- a/src/plugins/android/androiddeploystep.cpp +++ b/src/plugins/android/androiddeploystep.cpp @@ -239,7 +239,7 @@ bool AndroidDeployStep::runCommand(QProcess *buildProc, QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.") .arg(program).arg(arguments.join(QLatin1String(" "))); if (buildProc->error() != QProcess::UnknownError) - mainMessage += tr(" Reason: %1").arg(buildProc->errorString()); + mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc->errorString()); else mainMessage += tr("Exit code: %1").arg(buildProc->exitCode()); writeOutput(mainMessage, BuildStep::ErrorMessageOutput); diff --git a/src/plugins/android/androidpackagecreationstep.cpp b/src/plugins/android/androidpackagecreationstep.cpp index 285f7b3ee56..a72b9ac6951 100644 --- a/src/plugins/android/androidpackagecreationstep.cpp +++ b/src/plugins/android/androidpackagecreationstep.cpp @@ -613,7 +613,7 @@ bool AndroidPackageCreationStep::createPackage() emit addOutput(tr("Copy Qt app & libs to Android package ..."), MessageOutput); QStringList build; - build << QLatin1String("-silent"); + // build << QLatin1String("-silent"); //TODO depends on ant 1.9.0, enabled, not *now* build << QLatin1String("clean"); QFile::remove(m_gdbServerDestination.toString()); if (m_signPackageForRun) { @@ -803,7 +803,7 @@ bool AndroidPackageCreationStep::runCommand(QProcess *buildProc QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.") .arg(program).arg(arguments.join(QLatin1String(" "))); if (buildProc->error() != QProcess::UnknownError) - mainMessage += tr(" Reason: %1").arg(buildProc->errorString()); + mainMessage += QLatin1Char(' ') + tr("Reason: %1").arg(buildProc->errorString()); else mainMessage += tr("Exit code: %1").arg(buildProc->exitCode()); raiseError(mainMessage); diff --git a/src/plugins/clearcase/settingspage.cpp b/src/plugins/clearcase/settingspage.cpp index 983dac4845f..2dc0ad0019b 100644 --- a/src/plugins/clearcase/settingspage.cpp +++ b/src/plugins/clearcase/settingspage.cpp @@ -86,7 +86,8 @@ void SettingsPageWidget::setSettings(const ClearCaseSettings &s) } else { QString diffWarning = tr("In order to use External diff, 'diff' command needs to be accessible."); if (HostOsInfo::isWindowsHost()) { - diffWarning.append(tr(" DiffUtils is available for free download " + diffWarning += QLatin1Char(' '); + diffWarning.append(tr("DiffUtils is available for free download " "here. " "Please extract it to a directory in your PATH.")); } diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp index a68a919c1d3..f3a49624e9d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp @@ -455,7 +455,7 @@ ShadowBuildPage::ShadowBuildPage(CMakeOpenProjectWizard *cmakeWizard, bool chang QLabel *label = new QLabel(this); label->setWordWrap(true); if (change) - label->setText(tr("Please enter the directory in which you want to build your project. ")); + label->setText(tr("Please enter the directory in which you want to build your project.") + QLatin1Char(' ')); else label->setText(tr("Please enter the directory in which you want to build your project. " "Qt Creator recommends to not use the source directory for building. " @@ -507,13 +507,14 @@ void ChooseCMakePage::updateErrorText() } else { QString text = tr("Specify the path to the CMake executable. No CMake executable was found in the path."); if (!cmakeExecutable.isEmpty()) { + text += QLatin1Char(' '); QFileInfo fi(cmakeExecutable); if (!fi.exists()) - text += tr(" The CMake executable (%1) does not exist.").arg(cmakeExecutable); + text += tr("The CMake executable (%1) does not exist.").arg(cmakeExecutable); else if (!fi.isExecutable()) - text += tr(" The path %1 is not an executable.").arg(cmakeExecutable); + text += tr("The path %1 is not an executable.").arg(cmakeExecutable); else - text += tr(" The path %1 is not a valid CMake executable.").arg(cmakeExecutable); + text += tr("The path %1 is not a valid CMake executable.").arg(cmakeExecutable); } m_cmakeLabel->setText(text); } diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index e256fbe4f0c..50e5a4d6afe 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -193,7 +193,12 @@ QString CMakeRunConfiguration::defaultDisplayName() const { if (m_title.isEmpty()) return tr("Run CMake kit"); - return m_title + (m_enabled ? QString() : tr(" (disabled)")); + QString result = m_title; + if (!m_enabled) { + result += QLatin1Char(' '); + result += tr("(disabled)"); + } + return result; } QWidget *CMakeRunConfiguration::createConfigurationWidget() diff --git a/src/plugins/coreplugin/basefilewizard.cpp b/src/plugins/coreplugin/basefilewizard.cpp index bb26839348f..9ba83657a57 100644 --- a/src/plugins/coreplugin/basefilewizard.cpp +++ b/src/plugins/coreplugin/basefilewizard.cpp @@ -407,9 +407,9 @@ BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(GeneratedFiles * QStringList existingFiles; bool oddStuffFound = false; - static const QString readOnlyMsg = tr(" [read only]"); - static const QString directoryMsg = tr(" [folder]"); - static const QString symLinkMsg = tr(" [symbolic link]"); + static const QString readOnlyMsg = tr("[read only]"); + static const QString directoryMsg = tr("[folder]"); + static const QString symLinkMsg = tr("[symbolic link]"); foreach (const GeneratedFile &file, *files) { const QFileInfo fi(file.path()); @@ -432,17 +432,17 @@ BaseFileWizard::OverwriteResult BaseFileWizard::promptOverwrite(GeneratedFiles * do { if (fi.isDir()) { oddStuffFound = true; - fileNamesMsgPart += directoryMsg; + fileNamesMsgPart += QLatin1Char(' ') + directoryMsg; break; } if (fi.isSymLink()) { oddStuffFound = true; - fileNamesMsgPart += symLinkMsg; + fileNamesMsgPart += QLatin1Char(' ') + symLinkMsg; break; } if (!fi.isWritable()) { oddStuffFound = true; - fileNamesMsgPart += readOnlyMsg; + fileNamesMsgPart += QLatin1Char(' ') + readOnlyMsg; } } while (false); } diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp index bb6783bcda1..4593488c1b5 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -400,6 +400,8 @@ void SettingsDialog::createGui() mainGridLayout->setColumnStretch(1, 4); setLayout(mainGridLayout); setMinimumSize(1000, 550); + if (Utils::HostOsInfo::isMacHost()) + setMinimumHeight(minimumHeight() * 1.1); } SettingsDialog::~SettingsDialog() diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 93a7c3c739d..073b89dc5b9 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -854,10 +854,13 @@ static void setFocusToEditorViewAndUnmaximizePanes(EditorView *view) void EditorManager::doEscapeKeyFocusMoveMagic() { // use cases to cover: - // 1. if app focus is in mode or external window without editor view (e.g. Projects, ext. Help) - // activate & raise the current editor view (can be external) - // if that is in edit mode - // activate edit mode and unmaximize output pane + // 1. if app focus is in mode or external window without editor view (e.g. Design, Projects, ext. Help) + // if there are extra views (e.g. output) + // hide them + // otherwise + // activate & raise the current editor view (can be external) + // if that is in edit mode + // activate edit mode and unmaximize output pane // 2. if app focus is in external window with editor view // hide find if necessary // 2. if app focus is in mode with editor view @@ -874,13 +877,40 @@ void EditorManager::doEscapeKeyFocusMoveMagic() // otherwise (i.e. mode is edit mode) // hide extra views (find, help, output) + QWidget *activeWindow = qApp->activeWindow(); + if (!activeWindow) + return; + QWidget *focus = qApp->focusWidget(); EditorView *editorView = currentEditorView(); - bool editorViewActive = (qApp->focusWidget() == editorView->focusWidget()); + bool editorViewActive = (focus && focus == editorView->focusWidget()); bool editorViewVisible = editorView->isVisible(); + + if (!( editorViewVisible && !editorViewActive && editorView->window() == activeWindow )) { + bool stuffHidden = false; + QWidget *findPane = FindToolBarPlaceHolder::getCurrent(); + if (findPane && findPane->isVisible() && findPane->window() == activeWindow) { + findPane->hide(); + stuffHidden = true; + } + QWidget *outputPane = OutputPanePlaceHolder::getCurrent(); + if (outputPane && outputPane->isVisible() && outputPane->window() == activeWindow) { + OutputPaneManager::instance()->slotHide(); + stuffHidden = true; + } + QWidget *rightPane = RightPanePlaceHolder::current(); + if (rightPane && rightPane->isVisible() && rightPane->window() == activeWindow) { + RightPaneWidget::instance()->setShown(false); + stuffHidden = true; + } + if (stuffHidden) + return; + } + if (!editorViewActive && editorViewVisible) { setFocusToEditorViewAndUnmaximizePanes(editorView); return; } + if (!editorViewActive && !editorViewVisible) { // assumption is that editorView is in main window then ModeManager::activateMode(Id(Constants::MODE_EDIT)); @@ -888,30 +918,13 @@ void EditorManager::doEscapeKeyFocusMoveMagic() setFocusToEditorViewAndUnmaximizePanes(editorView); return; } - if (editorViewActive) { - QTC_CHECK(editorViewVisible); - bool stuffHidden = false; - QWidget *findPane = FindToolBarPlaceHolder::getCurrent(); - if (findPane && findPane->isVisibleTo(editorView)) { - findPane->hide(); - stuffHidden = true; - } - QWidget *outputPane = OutputPanePlaceHolder::getCurrent(); - if (outputPane && outputPane->isVisibleTo(editorView)) { - OutputPaneManager::instance()->slotHide(); - stuffHidden = true; - } - QWidget *rightPane = RightPanePlaceHolder::current(); - if (rightPane && rightPane->isVisibleTo(editorView)) { - RightPaneWidget::instance()->setShown(false); - stuffHidden = true; - } - if (!stuffHidden && editorView->window() == ICore::mainWindow()) { - // we are in a editor view and there's nothing to hide, switch to edit - ModeManager::activateMode(Id(Constants::MODE_EDIT)); - // next call works only because editor views in main window are shared between modes - setFocusToEditorViewAndUnmaximizePanes(editorView); - } + + if (editorView->window() == ICore::mainWindow()) { + // we are in a editor view and there's nothing to hide, switch to edit + ModeManager::activateMode(Id(Constants::MODE_EDIT)); + QTC_CHECK(editorView->isVisible()); + // next call works only because editor views in main window are shared between modes + setFocusToEditorViewAndUnmaximizePanes(editorView); } } diff --git a/src/plugins/coreplugin/icore.cpp b/src/plugins/coreplugin/icore.cpp index 7564a59f027..a226c2b6094 100644 --- a/src/plugins/coreplugin/icore.cpp +++ b/src/plugins/coreplugin/icore.cpp @@ -415,7 +415,9 @@ static QString compilerString() #elif defined(Q_CC_GNU) return QLatin1String("GCC " ) + QLatin1String(__VERSION__); #elif defined(Q_CC_MSVC) - if (_MSC_VER >= 1500) // 1500: MSVC 2008, 1600: MSVC 2010, ... + if (_MSC_VER >= 1800) // 1800: MSVC 2013 (yearly release cycle) + return QLatin1String("MSVC ") + QString::number(2008 + ((_MSC_VER / 100) - 13)); + if (_MSC_VER >= 1500) // 1500: MSVC 2008, 1600: MSVC 2010, ... (2-year release cycle) return QLatin1String("MSVC ") + QString::number(2008 + 2 * ((_MSC_VER / 100) - 15)); #endif return QLatin1String(""); diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 0604edde96e..fe072bde82a 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -518,6 +518,7 @@ CPPEditorWidget::CPPEditorWidget(QWidget *parent) , m_objcEnabled(false) , m_commentsSettings(CppTools::CppToolsSettings::instance()->commentsSettings()) , m_followSymbolUnderCursor(new FollowSymbolUnderCursor(this)) + , m_preprocessorButton(0) { qRegisterMetaType("CppTools::SemanticInfo"); @@ -647,10 +648,13 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor) connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateUses())); connect(this, SIGNAL(textChanged()), this, SLOT(updateUses())); - QToolButton *hashButton = new QToolButton(this); - hashButton->setText(QLatin1String("#")); - connect(hashButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget())); - editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, hashButton); + m_preprocessorButton = new QToolButton(this); + m_preprocessorButton->setText(QLatin1String("#")); + Core::Command *cmd = Core::ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); + connect(cmd, SIGNAL(keySequenceChanged()), this, SLOT(updatePreprocessorButtonTooltip())); + updatePreprocessorButtonTooltip(); + connect(m_preprocessorButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget())); + editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_preprocessorButton); editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_outlineCombo); } @@ -1012,6 +1016,14 @@ void CPPEditorWidget::onContentsChanged(int position, int charsRemoved, int char updateUses(); } +void CPPEditorWidget::updatePreprocessorButtonTooltip() +{ + QTC_ASSERT(m_preprocessorButton, return); + Core::Command *cmd = Core::ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); + QTC_ASSERT(cmd, return); + m_preprocessorButton->setToolTip(cmd->action()->toolTip()); +} + void CPPEditorWidget::jumpToOutlineElement(int index) { QModelIndex modelIndex = m_outlineCombo->view()->currentIndex(); diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index ae1f57e31b2..ba3b58cceef 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE class QComboBox; class QSortFilterProxyModel; +class QToolButton; QT_END_NAMESPACE namespace CPlusPlus { @@ -175,6 +176,7 @@ private Q_SLOTS: void onFunctionDeclDefLinkFound(QSharedPointer link); void onDocumentUpdated(); void onContentsChanged(int position, int charsRemoved, int charsAdded); + void updatePreprocessorButtonTooltip(); void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo); void highlightSymbolUsages(int from, int to); @@ -258,7 +260,7 @@ private: CppTools::CommentsSettings m_commentsSettings; QScopedPointer m_followSymbolUnderCursor; - QString m_preProcessorAdditions; + QToolButton *m_preprocessorButton; }; } // namespace Internal diff --git a/src/plugins/cppeditor/cppeditorplugin.cpp b/src/plugins/cppeditor/cppeditorplugin.cpp index b9c66de4a1c..d7dd630a431 100644 --- a/src/plugins/cppeditor/cppeditorplugin.cpp +++ b/src/plugins/cppeditor/cppeditorplugin.cpp @@ -210,7 +210,7 @@ bool CppEditorPlugin::initialize(const QStringList & /*arguments*/, QString *err contextMenu->addAction(cmd); cppToolsMenu->addAction(cmd); - QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives"), this); + QAction *openPreprocessorDialog = new QAction(tr("Additional Preprocessor Directives..."), this); cmd = ActionManager::registerAction(openPreprocessorDialog, Constants::OPEN_PREPROCESSOR_DIALOG, context); cmd->setDefaultKeySequence(QKeySequence()); diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 33e32593f4c..c9e6f5e873d 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -138,6 +138,10 @@ private slots: void test_FollowSymbolUnderCursor_virtualFunctionCall_allOverrides(); void test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides1(); void test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides2(); + void test_FollowSymbolUnderCursor_virtualFunctionCall_fallbackToDeclaration(); + void test_FollowSymbolUnderCursor_virtualFunctionCall_itemOrder(); + void test_FollowSymbolUnderCursor_virtualFunctionCall_onDotMemberAccessOfReferenceTypes(); + void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDotMemberAccessOfNonReferenceType(); void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQualified(); void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDeclaration(); void test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefinition(); diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index ad4a8c30121..0b6cd23a6db 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -55,35 +55,57 @@ typedef BaseTextEditorWidget::Link Link; namespace { -bool lookupVirtualFunctionOverrides(const QString &expression, Function *function, Scope *scope, +bool lookupVirtualFunctionOverrides(TypeOfExpression &typeOfExpression, + const Document::Ptr &document, + const Function *function, + Scope *scope, const Snapshot &snapshot) { - if (expression.isEmpty() || !function || !scope || scope->isClass() || snapshot.isEmpty()) + if (!document || !function || !scope || scope->isClass() || snapshot.isEmpty()) + return false; + + ExpressionAST *expressionAST = typeOfExpression.expressionAST(); + if (!expressionAST) + return false; + CallAST *callAST = expressionAST->asCall(); + if (!callAST) + return false; + ExpressionAST *baseExpressionAST = callAST->base_expression; + if (!baseExpressionAST) return false; bool result = false; - Document::Ptr expressionDocument = documentForExpression(expression.toUtf8()); - if (ExpressionAST *expressionAST = extractExpressionAST(expressionDocument)) { - if (CallAST *callAST = expressionAST->asCall()) { - if (ExpressionAST *baseExpressionAST = callAST->base_expression) { - if (IdExpressionAST *idExpressionAST = baseExpressionAST->asIdExpression()) { - NameAST *name = idExpressionAST->name; - result = name && !name->asQualifiedName(); - } else if (MemberAccessAST *memberAccessAST = baseExpressionAST->asMemberAccess()) { - NameAST *name = memberAccessAST->member_name; - const bool nameIsQualified = name && name->asQualifiedName(); + if (IdExpressionAST *idExpressionAST = baseExpressionAST->asIdExpression()) { + NameAST *name = idExpressionAST->name; + const bool nameIsQualified = name && name->asQualifiedName(); + result = !nameIsQualified && FunctionHelper::isVirtualFunction(function, snapshot); + } else if (MemberAccessAST *memberAccessAST = baseExpressionAST->asMemberAccess()) { + NameAST *name = memberAccessAST->member_name; + const bool nameIsQualified = name && name->asQualifiedName(); + if (!nameIsQualified && FunctionHelper::isVirtualFunction(function, snapshot)) { + const Document::Ptr expressionDocument + = typeOfExpression.context().expressionDocument(); + QTC_ASSERT(expressionDocument, return false); + TranslationUnit *unit = expressionDocument->translationUnit(); + QTC_ASSERT(unit, return false); + const int accessTokenKind = unit->tokenKind(memberAccessAST->access_token); - TranslationUnit *unit = expressionDocument->translationUnit(); - QTC_ASSERT(unit, return false); - const int tokenKind = unit->tokenKind(memberAccessAST->access_token); - result = tokenKind == T_ARROW && !nameIsQualified; + if (accessTokenKind == T_ARROW) { + result = true; + } else if (accessTokenKind == T_DOT) { + const QList items = typeOfExpression.reference( + memberAccessAST->base_expression, document, scope); + if (!items.isEmpty()) { + const LookupItem item = items.first(); + if (Symbol *declaration = item.declaration()) + result = declaration->type()->isReferenceType(); } } } } - return result && FunctionHelper::isVirtualFunction(function, snapshot); + return result; } Link findMacroLink_helper(const QByteArray &name, Document::Ptr doc, const Snapshot &snapshot, @@ -530,16 +552,27 @@ BaseTextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor & // Consider to show a pop-up displaying overrides for the function Function *function = symbol->type()->asFunctionType(); - if (lookupVirtualFunctionOverrides(expression, function, scope, snapshot)) { + if (lookupVirtualFunctionOverrides(typeOfExpression, doc, function, scope, snapshot)) { Class *klass = symbolFinder->findMatchingClassDeclaration(function, snapshot); QTC_CHECK(klass); - if (m_virtualFunctionAssistProvider->configure(klass, function, snapshot, - inNextSplit)) { + VirtualFunctionAssistProvider::Parameters params; + params.startClass = klass; + params.function = function; + params.snapshot = snapshot; + params.cursorPosition = cursor.position(); + params.openInNextSplit = inNextSplit; + + if (m_virtualFunctionAssistProvider->configure(params)) { m_widget->invokeAssist(TextEditor::FollowSymbol, m_virtualFunctionAssistProvider); } - return Link(); + + // Ensure a valid link text, so the symbol name will be underlined on Ctrl+Hover. + Link link; + link.linkTextStart = beginOfToken; + link.linkTextEnd = endOfToken; + return link; } if (resolveTarget) { diff --git a/src/plugins/cppeditor/cppincludehierarchymodel.cpp b/src/plugins/cppeditor/cppincludehierarchymodel.cpp index 7b6909f6179..7709bed2d57 100644 --- a/src/plugins/cppeditor/cppincludehierarchymodel.cpp +++ b/src/plugins/cppeditor/cppincludehierarchymodel.cpp @@ -117,11 +117,11 @@ QVariant CppIncludeHierarchyModel::data(const QModelIndex &index, int role) cons if (role == Qt::DisplayRole) { if ((item == m_includesItem && m_includesItem->childCount() == 0) || (item == m_includedByItem && m_includedByItem->childCount() == 0)) { - return QString(item->fileName() + tr(" (none)")); + return QString(item->fileName() + QLatin1Char(' ') + tr("(none)")); } if (item->isCyclic()) - return QString(item->fileName() + tr(" (cyclic)")); + return QString(item->fileName() + QLatin1Char(' ') + tr("(cyclic)")); return item->fileName(); } diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index 5f445898855..76d6cc0d172 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -40,6 +40,8 @@ #include #include +#include + #include #include #include @@ -107,16 +109,13 @@ private: class VirtualFunctionsAssistProcessor : public IAssistProcessor { public: - VirtualFunctionsAssistProcessor(const VirtualFunctionAssistProvider *provider) - : m_startClass(provider->startClass()) - , m_function(provider->function()) - , m_snapshot(provider->snapshot()) - , m_openInNextSplit(provider->openInNextSplit()) + VirtualFunctionsAssistProcessor(const VirtualFunctionAssistProvider::Parameters ¶ms) + : m_params(params) {} - IAssistProposal *immediateProposal(const TextEditor::IAssistInterface *interface) + IAssistProposal *immediateProposal(const TextEditor::IAssistInterface *) { - QTC_ASSERT(m_function, return 0); + QTC_ASSERT(m_params.function, return 0); BasicProposalItem *hintItem = new VirtualFunctionProposalItem(CPPEditorWidget::Link()); hintItem->setText(QCoreApplication::translate("VirtualFunctionsAssistProcessor", @@ -124,69 +123,67 @@ public: hintItem->setOrder(-1000); QList items; - items << itemFromSymbol(m_function, m_function); + items << itemFromSymbol(maybeDefinitionFor(m_params.function)); items << hintItem; - return new VirtualFunctionProposal(interface->position(), + return new VirtualFunctionProposal(m_params.cursorPosition, new BasicProposalItemListModel(items), - m_openInNextSplit); + m_params.openInNextSplit); } - IAssistProposal *perform(const IAssistInterface *interface) + IAssistProposal *perform(const IAssistInterface *) { - if (!interface) + QTC_ASSERT(m_params.startClass, return 0); + QTC_ASSERT(m_params.function, return 0); + QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0); + + const QList overrides + = FunctionHelper::overrides(m_params.startClass, m_params.function, m_params.snapshot); + if (overrides.isEmpty()) return 0; - QTC_ASSERT(m_startClass, return 0); - QTC_ASSERT(m_function, return 0); - QTC_ASSERT(!m_snapshot.isEmpty(), return 0); - - const QList overrides = FunctionHelper::overrides(m_startClass, m_function, - m_snapshot); QList items; foreach (Symbol *symbol, overrides) - items << itemFromSymbol(symbol, m_function); + items << itemFromSymbol(maybeDefinitionFor(symbol)); + items.first()->setOrder(1000); // Ensure top position for function of static type - return new VirtualFunctionProposal(interface->position(), + return new VirtualFunctionProposal(m_params.cursorPosition, new BasicProposalItemListModel(items), - m_openInNextSplit); + m_params.openInNextSplit); } - BasicProposalItem *itemFromSymbol(Symbol *symbol, Symbol *firstSymbol) const +private: + Symbol *maybeDefinitionFor(Symbol *symbol) + { + if (Function *definition = m_finder.findMatchingDefinition(symbol, m_params.snapshot)) + return definition; + return symbol; + } + + BasicProposalItem *itemFromSymbol(Symbol *symbol) const { const QString text = m_overview.prettyName(LookupContext::fullyQualifiedName(symbol)); const CPPEditorWidget::Link link = CPPEditorWidget::linkToSymbol(symbol); - BasicProposalItem *item = new VirtualFunctionProposalItem(link, m_openInNextSplit); + BasicProposalItem *item = new VirtualFunctionProposalItem(link, m_params.openInNextSplit); item->setText(text); item->setIcon(m_icons.iconForSymbol(symbol)); - if (symbol == firstSymbol) - item->setOrder(1000); // Ensure top position for function of static type return item; } -private: - Class *m_startClass; - Function *m_function; - Snapshot m_snapshot; - bool m_openInNextSplit; + VirtualFunctionAssistProvider::Parameters m_params; Overview m_overview; Icons m_icons; + CppTools::SymbolFinder m_finder; }; VirtualFunctionAssistProvider::VirtualFunctionAssistProvider() - : m_function(0) - , m_openInNextSplit(false) { } -bool VirtualFunctionAssistProvider::configure(Class *startClass, Function *function, - const Snapshot &snapshot, bool openInNextSplit) +bool VirtualFunctionAssistProvider::configure(const Parameters ¶meters) { - m_startClass = startClass; - m_function = function; - m_snapshot = snapshot; - m_openInNextSplit = openInNextSplit; + m_params = parameters; return true; } @@ -202,7 +199,7 @@ bool VirtualFunctionAssistProvider::supportsEditor(const Core::Id &editorId) con IAssistProcessor *VirtualFunctionAssistProvider::createProcessor() const { - return new VirtualFunctionsAssistProcessor(this); + return new VirtualFunctionsAssistProcessor(m_params); } enum VirtualType { Virtual, PureVirtual }; @@ -263,9 +260,6 @@ QList FunctionHelper::overrides(Class *startClass, Function *function, const Name *referenceName = function->name(); QTC_ASSERT(referenceName && referenceType.isValid(), return result); - // Add itself - result << function; - // Find overrides CppEditor::Internal::CppClass cppClass = CppClass(startClass); cppClass.lookupDerived(startClass, snapshot); diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h index c634b4ed44f..b5ff42d846b 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.h @@ -35,6 +35,8 @@ #include #include +#include + namespace CppEditor { namespace Internal { @@ -43,22 +45,25 @@ class VirtualFunctionAssistProvider : public TextEditor::IAssistProvider public: VirtualFunctionAssistProvider(); - virtual bool configure(CPlusPlus::Class *startClass, CPlusPlus::Function *function, - const CPlusPlus::Snapshot &snapshot, bool openInNextSplit); - CPlusPlus::Class *startClass() const { return m_startClass; } - CPlusPlus::Function *function() const { return m_function; } - CPlusPlus::Snapshot snapshot() const { return m_snapshot; } - bool openInNextSplit() const { return m_openInNextSplit; } + struct Parameters { + Parameters() : startClass(0), function(0), cursorPosition(-1), openInNextSplit(false) {} + + CPlusPlus::Class *startClass; + CPlusPlus::Function *function; + CPlusPlus::Snapshot snapshot; + int cursorPosition; + bool openInNextSplit; + }; + + virtual bool configure(const Parameters ¶meters); + Parameters params() const { return m_params; } bool isAsynchronous() const; bool supportsEditor(const Core::Id &editorId) const; TextEditor::IAssistProcessor *createProcessor() const; private: - CPlusPlus::Class *m_startClass; - CPlusPlus::Function *m_function; - CPlusPlus::Snapshot m_snapshot; - bool m_openInNextSplit; + Parameters m_params; }; class FunctionHelper diff --git a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h index 7d09c9db2cd..44cf50dcc91 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h +++ b/src/plugins/cppeditor/cppvirtualfunctionproposalitem.h @@ -41,6 +41,7 @@ public: VirtualFunctionProposalItem(const TextEditor::BaseTextEditorWidget::Link &link, bool openInSplit = true); void apply(TextEditor::BaseTextEditor * /* editor */, int /* basePosition */) const; + TextEditor::BaseTextEditorWidget::Link link() const { return m_link; } // Exposed for tests private: TextEditor::BaseTextEditorWidget::Link m_link; diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 19f33336ae2..2a2c754e639 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -31,6 +31,7 @@ #include "cppeditorplugin.h" #include "cppelementevaluator.h" #include "cppvirtualfunctionassistprovider.h" +#include "cppvirtualfunctionproposalitem.h" #include #include @@ -59,6 +60,35 @@ using namespace CppTools; using namespace TextEditor; using namespace Core; +class OverrideItem { +public: + OverrideItem() : line(0) {} + OverrideItem(const QString &text, int line = 0) : text(text), line(line) {} + bool isValid() { return line != 0; } + + QString text; + int line; +}; +typedef QList OverrideItemList; +Q_DECLARE_METATYPE(OverrideItem) + +inline bool operator==(const OverrideItem &lhs, const OverrideItem &rhs) +{ + return lhs.text == rhs.text && lhs.line == rhs.line; +} + +QT_BEGIN_NAMESPACE +namespace QTest { +template<> char *toString(const OverrideItem &data) +{ + QByteArray ba = "OverrideItem("; + ba += data.text.toLatin1() + ", " + QByteArray::number(data.line); + ba += ")"; + return qstrdup(ba.data()); +} +} +QT_END_NAMESPACE + namespace { /// A fake virtual functions assist provider that runs processor->perform() already in configure() @@ -72,14 +102,13 @@ public: // Invoke the processor already here to calculate the proposals. Return false in order to // indicate that configure failed, so the actual code assist invocation leading to a pop-up // will not happen. - bool configure(CPlusPlus::Class *startClass, CPlusPlus::Function *function, - const CPlusPlus::Snapshot &snapshot, bool openInNextSplit) + bool configure(const VirtualFunctionAssistProvider::Parameters ¶ms) { - VirtualFunctionAssistProvider::configure(startClass, function, snapshot, openInNextSplit); + VirtualFunctionAssistProvider::configure(params); IAssistProcessor *processor = createProcessor(); - IAssistInterface *assistInterface = m_editorWidget->createAssistInterface(FollowSymbol, - ExplicitlyInvoked); + IAssistInterface *assistInterface + = m_editorWidget->createAssistInterface(FollowSymbol, ExplicitlyInvoked); IAssistProposal *immediateProposal = processor->immediateProposal(assistInterface); IAssistProposal *finalProposal = processor->perform(assistInterface); @@ -89,27 +118,36 @@ public: return false; } - static QStringList itemList(IAssistProposalModel *imodel) + static OverrideItemList itemList(IAssistProposalModel *imodel) { - QStringList immediateItems; + OverrideItemList result; BasicProposalItemListModel *model = dynamic_cast(imodel); if (!model) - return immediateItems; + return result; + + // Mimic relevant GenericProposalWidget::showProposal() calls + model->removeDuplicates(); + model->reset(); if (model->isSortable(QString())) model->sort(QString()); - model->removeDuplicates(); for (int i = 0, size = model->size(); i < size; ++i) { + VirtualFunctionProposalItem *item + = dynamic_cast(model->proposalItem(i)); + const QString text = model->text(i); - immediateItems.append(text); + const int line = item->link().targetLine; +// Uncomment for updating/generating reference data: +// qDebug("<< OverrideItem(QLatin1String(\"%s\"), %d)", qPrintable(text), line); + result << OverrideItem(text, line); } - return immediateItems; + return result; } public: - QStringList m_immediateItems; - QStringList m_finalItems; + OverrideItemList m_immediateItems; + OverrideItemList m_finalItems; private: CPPEditorWidget *m_editorWidget; @@ -199,11 +237,11 @@ public: }; TestCase(CppEditorAction action, const QByteArray &source, - const QStringList &expectedVirtualFunctionImmediateProposal = QStringList(), - const QStringList &expectedVirtualFunctionFinalProposal = QStringList()); + const OverrideItemList &expectedVirtualFunctionImmediateProposal = OverrideItemList(), + const OverrideItemList &expectedVirtualFunctionFinalProposal = OverrideItemList()); TestCase(CppEditorAction action, const QList theTestFiles, - const QStringList &expectedVirtualSymbolsImmediateProposal = QStringList(), - const QStringList &expectedVirtualSymbolsFinalProposal = QStringList()); + const OverrideItemList &expectedVirtualFunctionImmediateProposal = OverrideItemList(), + const OverrideItemList &expectedVirtualFunctionFinalProposal = OverrideItemList()); ~TestCase(); void run(bool expectedFail = false); @@ -220,18 +258,18 @@ private: private: CppEditorAction m_action; QList m_testFiles; - QStringList m_expectedVirtualSymbolsImmediateProposal; // for virtual functions - QStringList m_expectedVirtualSymbolsFinalProposals; // for virtual functions + OverrideItemList m_expectedVirtualFunctionImmediateProposal; + OverrideItemList m_expectedVirtualFunctionFinalProposals; }; /// Convenience function for creating a TestDocument. /// See TestDocument. TestCase::TestCase(CppEditorAction action, const QByteArray &source, - const QStringList &expectedVirtualFunctionImmediateProposal, - const QStringList &expectedVirtualFunctionFinalProposal) + const OverrideItemList &expectedVirtualFunctionImmediateProposal, + const OverrideItemList &expectedVirtualFunctionFinalProposal) : m_action(action) - , m_expectedVirtualSymbolsImmediateProposal(expectedVirtualFunctionImmediateProposal) - , m_expectedVirtualSymbolsFinalProposals(expectedVirtualFunctionFinalProposal) + , m_expectedVirtualFunctionImmediateProposal(expectedVirtualFunctionImmediateProposal) + , m_expectedVirtualFunctionFinalProposals(expectedVirtualFunctionFinalProposal) { m_testFiles << TestDocument::create(source, QLatin1String("file.cpp")); init(); @@ -242,12 +280,12 @@ TestCase::TestCase(CppEditorAction action, const QByteArray &source, /// Exactly one test document must be provided that contains '$', the target position marker. /// It can be the same document. TestCase::TestCase(CppEditorAction action, const QList theTestFiles, - const QStringList &expectedVirtualSymbolsImmediateProposal, - const QStringList &expectedVirtualSymbolsFinalProposal) + const OverrideItemList &expectedVirtualFunctionImmediateProposal, + const OverrideItemList &expectedVirtualFunctionFinalProposal) : m_action(action) , m_testFiles(theTestFiles) - , m_expectedVirtualSymbolsImmediateProposal(expectedVirtualSymbolsImmediateProposal) - , m_expectedVirtualSymbolsFinalProposals(expectedVirtualSymbolsFinalProposal) + , m_expectedVirtualFunctionImmediateProposal(expectedVirtualFunctionImmediateProposal) + , m_expectedVirtualFunctionFinalProposals(expectedVirtualFunctionFinalProposal) { init(); } @@ -365,8 +403,8 @@ void TestCase::run(bool expectedFail) // qDebug() << "Initial line:" << initialTestFile->editor->currentLine(); // qDebug() << "Initial column:" << initialTestFile->editor->currentColumn() - 1; - QStringList immediateVirtualSymbolResults; - QStringList finalVirtualSymbolResults; + OverrideItemList immediateVirtualSymbolResults; + OverrideItemList finalVirtualSymbolResults; // Trigger the action switch (m_action) { @@ -416,8 +454,8 @@ void TestCase::run(bool expectedFail) // qDebug() << immediateVirtualSymbolResults; // qDebug() << finalVirtualSymbolResults; - QCOMPARE(immediateVirtualSymbolResults, m_expectedVirtualSymbolsImmediateProposal); - QCOMPARE(finalVirtualSymbolResults, m_expectedVirtualSymbolsFinalProposals); + QCOMPARE(immediateVirtualSymbolResults, m_expectedVirtualFunctionImmediateProposal); + QCOMPARE(finalVirtualSymbolResults, m_expectedVirtualFunctionFinalProposals); } } // anonymous namespace @@ -1232,22 +1270,19 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_allOverri "struct CD2 : C { void virt(); };\n" "void CD2::virt() {}\n" "\n" - "int f(A *o)\n" - "{\n" - " o->$@virt();\n" + "int f(A *o) { o->$@virt(); }\n" "}\n" ; - const QStringList immediateResults = QStringList() - << QLatin1String("A::virt") - << QLatin1String("...searching overrides"); - const QStringList finalResults = QStringList() - << QLatin1String("A::virt") - << QLatin1String("A::virt") // TODO: Double entry - << QLatin1String("B::virt") - << QLatin1String("C::virt") - << QLatin1String("CD1::virt") - << QLatin1String("CD2::virt"); + const OverrideItemList immediateResults = OverrideItemList() + << OverrideItem(QLatin1String("A::virt"), 2) + << OverrideItem(QLatin1String("...searching overrides")); + const OverrideItemList finalResults = OverrideItemList() + << OverrideItem(QLatin1String("A::virt"), 2) + << OverrideItem(QLatin1String("B::virt"), 5) + << OverrideItem(QLatin1String("C::virt"), 8) + << OverrideItem(QLatin1String("CD1::virt"), 11) + << OverrideItem(QLatin1String("CD2::virt"), 14); TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults); test.run(); @@ -1272,21 +1307,18 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleO "struct CD2 : C { void virt(); };\n" "void CD2::virt() {}\n" "\n" - "int f(B *o)\n" - "{\n" - " o->$@virt();\n" + "int f(B *o) { o->$@virt(); }\n" "}\n" ; - const QStringList immediateResults = QStringList() - << QLatin1String("B::virt") - << QLatin1String("...searching overrides"); - const QStringList finalResults = QStringList() - << QLatin1String("B::virt") - << QLatin1String("B::virt") // Double entry - << QLatin1String("C::virt") - << QLatin1String("CD1::virt") - << QLatin1String("CD2::virt"); + const OverrideItemList immediateResults = OverrideItemList() + << OverrideItem(QLatin1String("B::virt"), 5) + << OverrideItem(QLatin1String("...searching overrides")); + const OverrideItemList finalResults = OverrideItemList() + << OverrideItem(QLatin1String("B::virt"), 5) + << OverrideItem(QLatin1String("C::virt"), 8) + << OverrideItem(QLatin1String("CD1::virt"), 11) + << OverrideItem(QLatin1String("CD2::virt"), 14); TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults); test.run(); @@ -1296,40 +1328,121 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleO void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_possibleOverrides2() { const QByteArray source = - "struct A { virtual void f(); };\n" - "void A::f() {}\n" + "struct A { virtual void virt(); };\n" + "void A::virt() {}\n" "\n" - "struct B : public A { void f(); };\n" - "void B::f() {}\n" + "struct B : public A { void virt(); };\n" + "void B::virt() {}\n" "\n" - "struct C : public B { void g() { f$@(); } }; \n" + "struct C : public B { void g() { virt$@(); } }; \n" "\n" - "struct D : public C { void f(); };\n" - "void D::f() {}\n" + "struct D : public C { void virt(); };\n" + "void D::virt() {}\n" ; - const QStringList immediateResults = QStringList() - << QLatin1String("B::f") - << QLatin1String("...searching overrides"); - const QStringList finalResults = QStringList() - << QLatin1String("B::f") - << QLatin1String("B::f") - << QLatin1String("D::f"); + const OverrideItemList immediateResults = OverrideItemList() + << OverrideItem(QLatin1String("B::virt"), 5) + << OverrideItem(QLatin1String("...searching overrides")); + const OverrideItemList finalResults = OverrideItemList() + << OverrideItem(QLatin1String("B::virt"), 5) + << OverrideItem(QLatin1String("D::virt"), 10); TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults); test.run(); } +/// Check: If no definition is found, fallback to the declaration. +void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_fallbackToDeclaration() +{ + const QByteArray source = + "struct A { virtual void virt(); };\n" + "\n" + "int f(A *o) { o->$@virt(); }\n" + ; + + const OverrideItemList immediateResults = OverrideItemList() + << OverrideItem(QLatin1String("A::virt"), 1) + << OverrideItem(QLatin1String("...searching overrides")); + const OverrideItemList finalResults = OverrideItemList() + << OverrideItem(QLatin1String("A::virt"), 1); + + TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults); + test.run(); +} + +/// Check: Ensure that the first entry in the final results is the same as the first in the +/// immediate results. +void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_itemOrder() +{ + const QByteArray source = + "struct C { virtual void virt() = 0; };\n" + "void C::virt() {}\n" + "\n" + "struct B : C { void virt(); };\n" + "void B::virt() {}\n" + "\n" + "struct A : B { void virt(); };\n" + "void A::virt() {}\n" + "\n" + "int f(C *o) { o->$@virt(); }\n" + ; + + const OverrideItemList immediateResults = OverrideItemList() + << OverrideItem(QLatin1String("C::virt"), 2) + << OverrideItem(QLatin1String("...searching overrides")); + const OverrideItemList finalResults = OverrideItemList() + << OverrideItem(QLatin1String("C::virt"), 2) + << OverrideItem(QLatin1String("A::virt"), 8) + << OverrideItem(QLatin1String("B::virt"), 5); + + TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults); + test.run(); +} + +/// Check: Trigger on a.virt() if a is of type &A. +void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_onDotMemberAccessOfReferenceTypes() +{ + const QByteArray source = + "struct A { virtual void virt() = 0; };\n" + "void A::virt() {}\n" + "\n" + "void client(A &o) { o.$@virt(); }\n" + ; + + const OverrideItemList immediateResults = OverrideItemList() + << OverrideItem(QLatin1String("A::virt"), 2) + << OverrideItem(QLatin1String("...searching overrides")); + const OverrideItemList finalResults = OverrideItemList() + << OverrideItem(QLatin1String("A::virt"), 2); + + TestCase test(TestCase::FollowSymbolUnderCursorAction, source, immediateResults, finalResults); + test.run(); +} + +/// Check: Do not trigger on a.virt() if a is of type A. +void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDotMemberAccessOfNonReferenceType() +{ + const QByteArray source = + "struct A { virtual void virt(); };\n" + "void A::$virt() {}\n" + "\n" + "void client(A o) { o.@virt(); }\n" + ; + + TestCase test(TestCase::FollowSymbolUnderCursorAction, source); + test.run(); +} + /// Check: Do not trigger on qualified function calls. void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQualified() { const QByteArray source = - "struct A { virtual void f(); };\n" - "void A::$f() {}\n" + "struct A { virtual void virt(); };\n" + "void A::$virt() {}\n" "\n" "struct B : public A {\n" - " void f();\n" - " void g() { A::@f(); }\n" + " void virt();\n" + " void g() { A::@virt(); }\n" "};\n" ; @@ -1341,11 +1454,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnQual void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDeclaration() { const QByteArray source = - "struct A { virtual void f(); };\n" - "void A::f() {}\n" + "struct A { virtual void virt(); };\n" + "void A::virt() {}\n" "\n" - "struct B : public A { void f@(); };\n" - "void B::$f() {}\n" + "struct B : public A { void virt@(); };\n" + "void B::$virt() {}\n" ; TestCase test(TestCase::FollowSymbolUnderCursorAction, source); @@ -1356,11 +1469,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDecl void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefinition() { const QByteArray source = - "struct A { virtual void f(); };\n" - "void A::f() {}\n" + "struct A { virtual void virt(); };\n" + "void A::virt() {}\n" "\n" - "struct B : public A { void $f(); };\n" - "void B::@f() {}\n" + "struct B : public A { void $virt(); };\n" + "void B::@virt() {}\n" ; TestCase test(TestCase::FollowSymbolUnderCursorAction, source); @@ -1370,13 +1483,13 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnDefi void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_notOnNonPointerNonReference() { const QByteArray source = - "struct A { virtual void f(); };\n" - "void A::f() {}\n" + "struct A { virtual void virt(); };\n" + "void A::virt() {}\n" "\n" - "struct B : public A { void f(); };\n" - "void B::$f() {}\n" + "struct B : public A { void virt(); };\n" + "void B::$virt() {}\n" "\n" - "void client(B b) { b.@f(); }\n" + "void client(B b) { b.@virt(); }\n" ; TestCase test(TestCase::FollowSymbolUnderCursorAction, source); diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index ff69f7746ae..b7206450326 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -51,11 +51,9 @@ #include #include +#include #include #include -#ifdef Q_OS_WIN -#include -#endif #include #include @@ -352,11 +350,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader) foreach (const QString &candidateDir, candidateDirs) { foreach (const QString &candidateFileName, candidateFileNames) { const QString candidateFilePath = candidateDir + QLatin1Char('/') + candidateFileName; -#ifdef Q_OS_WIN - const QString normalized = Utils::normalizePathName(candidateFilePath); -#else - const QString normalized = candidateFilePath; -#endif + const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath); const QFileInfo candidateFi(normalized); if (candidateFi.isFile()) { m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath(); diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 52331b4e185..5376b4c9143 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -2879,11 +2879,7 @@ CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDeb const QString fileName = cdbSourcePathMapping(QDir::toNativeSeparators(f), m_sourcePathMappings, DebuggerToSource); // Up/lower case normalization according to Windows. -#ifdef Q_OS_WIN - QString normalized = Utils::normalizePathName(fileName); -#else - QString normalized = fileName; -#endif + const QString normalized = Utils::FileUtils::normalizePathName(fileName); if (debugSourceMapping) qDebug(" sourceMapNormalizeFileNameFromDebugger %s->%s", qPrintable(fileName), qPrintable(normalized)); // Check if it really exists, that is normalize worked and QFileInfo confirms it. diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index ce31216535b..7798cf0bfe1 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -24,9 +24,13 @@ HEADERS += \ debuggercore.h \ debuggerconstants.h \ debuggerinternalconstants.h \ + debuggeritem.h \ + debuggeritemmanager.h \ + debuggeritemmodel.h \ debuggerdialogs.h \ debuggerengine.h \ debuggermainwindow.h \ + debuggeroptionspage.h \ debuggerplugin.h \ debuggerprotocol.h \ debuggerrunconfigurationaspect.h \ @@ -80,12 +84,16 @@ SOURCES += \ debuggeractions.cpp \ debuggerdialogs.cpp \ debuggerengine.cpp \ + debuggeritem.cpp \ + debuggeritemmanager.cpp \ + debuggeritemmodel.cpp \ debuggermainwindow.cpp \ debuggerplugin.cpp \ debuggerprotocol.cpp \ debuggerrunconfigurationaspect.cpp \ debuggerrunner.cpp \ debuggerstreamops.cpp \ + debuggeroptionspage.cpp \ debuggerkitconfigwidget.cpp \ debuggerkitinformation.cpp \ disassembleragent.cpp \ diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs index 9032e846608..709dc128c3c 100644 --- a/src/plugins/debugger/debugger.qbs +++ b/src/plugins/debugger/debugger.qbs @@ -40,9 +40,13 @@ QtcPlugin { "debuggerdialogs.cpp", "debuggerdialogs.h", "debuggerengine.cpp", "debuggerengine.h", "debuggerinternalconstants.h", + "debuggeritem.cpp", "debuggeritem.h", + "debuggeritemmanager.cpp", "debuggeritemmanager.h", + "debuggeritemmodel.cpp", "debuggeritemmodel.h", "debuggerkitconfigwidget.cpp", "debuggerkitconfigwidget.h", "debuggerkitinformation.cpp", "debuggerkitinformation.h", "debuggermainwindow.cpp", "debuggermainwindow.h", + "debuggeroptionspage.cpp", "debuggeroptionspage.h", "debuggerplugin.cpp", "debuggerplugin.h", "debuggerprotocol.cpp", "debuggerprotocol.h", "debuggerruncontrolfactory.h", diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index 13f292de991..b1db49211d9 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -248,7 +248,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) d->localExecutablePathChooser = new PathChooser(this); d->localExecutablePathChooser->setExpectedKind(PathChooser::File); d->localExecutablePathChooser->setPromptDialogTitle(tr("Select Executable")); - d->localExecutablePathChooser->lineEdit()->setHistoryCompleter(QLatin1String("LocalExecutable")); + d->localExecutablePathChooser->setHistoryCompleter(QLatin1String("LocalExecutable")); d->arguments = new FancyLineEdit(this); d->arguments->setHistoryCompleter(QLatin1String("CommandlineArguments")); @@ -256,7 +256,7 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) d->workingDirectory = new PathChooser(this); d->workingDirectory->setExpectedKind(PathChooser::ExistingDirectory); d->workingDirectory->setPromptDialogTitle(tr("Select Working Directory")); - d->workingDirectory->lineEdit()->setHistoryCompleter(QLatin1String("WorkingDirectory")); + d->workingDirectory->setHistoryCompleter(QLatin1String("WorkingDirectory")); d->runInTerminalCheckBox = new QCheckBox(this); @@ -633,7 +633,7 @@ AddressDialog::AddressDialog(QWidget *parent) : setWindowTitle(tr("Select Start Address")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); QHBoxLayout *hLayout = new QHBoxLayout; - hLayout->addWidget(new QLabel(tr("Enter an address: "))); + hLayout->addWidget(new QLabel(tr("Enter an address:") + QLatin1Char(' '))); hLayout->addWidget(m_lineEdit); QVBoxLayout *vLayout = new QVBoxLayout; vLayout->addLayout(hLayout); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 71b196a7102..2bbea66f5b9 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1676,9 +1676,9 @@ QString DebuggerEngine::msgInterrupted() void DebuggerEngine::showStoppedBySignalMessageBox(QString meaning, QString name) { if (name.isEmpty()) - name = tr(" ", "name"); + name = QLatin1Char(' ') + tr("", "name") + QLatin1Char(' '); if (meaning.isEmpty()) - meaning = tr(" ", "meaning"); + meaning = QLatin1Char(' ') + tr("", "meaning") + QLatin1Char(' '); const QString msg = tr("

The inferior stopped because it received a " "signal from the Operating System.

" "" diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp new file mode 100644 index 00000000000..0768d2ecdd6 --- /dev/null +++ b/src/plugins/debugger/debuggeritem.cpp @@ -0,0 +1,352 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "debuggerkitinformation.h" +#include "debuggerkitconfigwidget.h" +#include "debuggeroptionspage.h" + +#include +#include + +#include +#include + +using namespace Debugger::Internal; +using namespace ProjectExplorer; +using namespace Utils; + +static const char DEBUGGER_INFORMATION_COMMAND[] = "Binary"; +static const char DEBUGGER_INFORMATION_DISPLAYNAME[] = "DisplayName"; +static const char DEBUGGER_INFORMATION_ID[] = "Id"; +static const char DEBUGGER_INFORMATION_ENGINETYPE[] = "EngineType"; +static const char DEBUGGER_INFORMATION_AUTODETECTED[] = "AutoDetected"; +static const char DEBUGGER_INFORMATION_ABIS[] = "Abis"; + +namespace Debugger { + +// -------------------------------------------------------------------------- +// DebuggerItem +// -------------------------------------------------------------------------- + +DebuggerItem::DebuggerItem() +{ + m_id = QUuid::createUuid().toString(); + m_engineType = NoEngineType; + m_isAutoDetected = false; +} + +DebuggerItem::DebuggerItem(const QVariant &id) +{ + m_id = id; + m_engineType = NoEngineType; + m_isAutoDetected = false; +} + +DebuggerItem::DebuggerItem(const QVariantMap &data) +{ + m_command = FileName::fromUserInput(data.value(QLatin1String(DEBUGGER_INFORMATION_COMMAND)).toString()); + m_id = data.value(QLatin1String(DEBUGGER_INFORMATION_ID)).toString(); + m_displayName = data.value(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME)).toString(); + m_isAutoDetected = data.value(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), false).toBool(); + m_engineType = DebuggerEngineType(data.value(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), + static_cast(NoEngineType)).toInt()); + + foreach (const QString &a, data.value(QLatin1String(DEBUGGER_INFORMATION_ABIS)).toStringList()) { + Abi abi(a); + if (abi.isValid()) + m_abis.append(abi); + } +} + +void DebuggerItem::reinitializeFromFile() +{ + QProcess proc; + proc.start(m_command.toString(), QStringList() << QLatin1String("--version")); + proc.waitForStarted(); + proc.waitForFinished(); + QByteArray ba = proc.readAll(); + if (ba.contains("gdb")) { + m_engineType = GdbEngineType; + const char needle[] = "This GDB was configured as \""; + // E.g. "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0". + // or "i686-linux-gnu" + int pos1 = ba.indexOf(needle); + if (pos1 != -1) { + pos1 += int(sizeof(needle)); + int pos2 = ba.indexOf('"', pos1 + 1); + QByteArray target = ba.mid(pos1, pos2 - pos1); + int pos3 = target.indexOf("--target="); + if (pos3 >= 0) + target = target.mid(pos3 + 9); + m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target))); + } else { + // Fallback. + m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong. + } + return; + } + if (ba.contains("lldb") || ba.startsWith("LLDB")) { + m_engineType = LldbEngineType; + m_abis = Abi::abisOfBinary(m_command); + return; + } + if (ba.startsWith("Python")) { + m_engineType = PdbEngineType; + return; + } + m_engineType = NoEngineType; +} + +QString DebuggerItem::engineTypeName() const +{ + switch (m_engineType) { + case Debugger::NoEngineType: + return DebuggerOptionsPage::tr("Not recognized"); + case Debugger::GdbEngineType: + return QLatin1String("GDB"); + case Debugger::CdbEngineType: + return QLatin1String("CDB"); + case Debugger::LldbEngineType: + return QLatin1String("LLDB"); + default: + return QString(); + } +} + +QStringList DebuggerItem::abiNames() const +{ + QStringList list; + foreach (const Abi &abi, m_abis) + list.append(abi.toString()); + return list; +} + +bool DebuggerItem::operator==(const DebuggerItem &other) const +{ + return m_id == other.m_id + && m_displayName == other.m_displayName + && m_isAutoDetected == other.m_isAutoDetected + && m_command == other.m_command; +} + +QVariantMap DebuggerItem::toMap() const +{ + QVariantMap data; + data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName); + data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id); + data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput()); + data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType)); + data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected); + data.insert(QLatin1String(DEBUGGER_INFORMATION_ABIS), abiNames()); + return data; +} + +void DebuggerItem::setDisplayName(const QString &displayName) +{ + m_displayName = displayName; +} + +void DebuggerItem::setEngineType(const DebuggerEngineType &engineType) +{ + m_engineType = engineType; +} + +void DebuggerItem::setCommand(const Utils::FileName &command) +{ + m_command = command; +} + +void DebuggerItem::setAutoDetected(bool isAutoDetected) +{ + m_isAutoDetected = isAutoDetected; +} + +void DebuggerItem::setAbis(const QList &abis) +{ + m_abis = abis; +} + +void DebuggerItem::setAbi(const Abi &abi) +{ + m_abis.clear(); + m_abis.append(abi); +} + +static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi) +{ + if (debuggerAbi.architecture() != Abi::UnknownArchitecture + && debuggerAbi.architecture() != targetAbi.architecture()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.os() != Abi::UnknownOS + && debuggerAbi.os() != targetAbi.os()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.binaryFormat() != Abi::UnknownFormat + && debuggerAbi.binaryFormat() != targetAbi.binaryFormat()) + return DebuggerItem::DoesNotMatch; + + if (debuggerAbi.os() == Abi::WindowsOS) { + if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor) + return DebuggerItem::DoesNotMatch; + if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor) + return DebuggerItem::DoesNotMatch; + } + + if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32) + return DebuggerItem::MatchesSomewhat; + if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth()) + return DebuggerItem::DoesNotMatch; + + return DebuggerItem::MatchesPerfectly; +} + +DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const +{ + MatchLevel bestMatch = DoesNotMatch; + foreach (const Abi &debuggerAbi, m_abis) { + MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi); + if (currentMatch > bestMatch) + bestMatch = currentMatch; + } + return bestMatch; +} + +bool Debugger::DebuggerItem::isValid() const +{ + return !m_id.isNull(); +} + +} // namespace Debugger; + +#ifdef WITH_TESTS + +# include +# include "debuggerplugin.h" + +void Debugger::DebuggerPlugin::testDebuggerMatching_data() +{ + QTest::addColumn("debugger"); + QTest::addColumn("target"); + QTest::addColumn("result"); + + QTest::newRow("Invalid data") + << QStringList() + << QString() + << int(DebuggerItem::DoesNotMatch); + QTest::newRow("Invalid debugger") + << QStringList() + << QString::fromLatin1("x86-linux-generic-elf-32bit") + << int(DebuggerItem::DoesNotMatch); + QTest::newRow("Invalid target") + << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) + << QString() + << int(DebuggerItem::DoesNotMatch); + + QTest::newRow("Fuzzy match 1") + << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit")) + << QString::fromLatin1("x86-linux-generic-elf-32bit") + << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior? + QTest::newRow("Fuzzy match 2") + << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit")) + << QString::fromLatin1("arm-windows-msys-pe-64bit") + << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior? + + QTest::newRow("Architecture mismatch") + << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) + << QString::fromLatin1("arm-linux-generic-elf-32bit") + << int(DebuggerItem::DoesNotMatch); + QTest::newRow("OS mismatch") + << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) + << QString::fromLatin1("x86-macosx-generic-elf-32bit") + << int(DebuggerItem::DoesNotMatch); + QTest::newRow("Format mismatch") + << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) + << QString::fromLatin1("x86-linux-generic-pe-32bit") + << int(DebuggerItem::DoesNotMatch); + + QTest::newRow("Linux perfect match") + << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) + << QString::fromLatin1("x86-linux-generic-elf-32bit") + << int(DebuggerItem::MatchesPerfectly); + QTest::newRow("Linux match") + << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")) + << QString::fromLatin1("x86-linux-generic-elf-32bit") + << int(DebuggerItem::MatchesSomewhat); + + QTest::newRow("Windows perfect match 1") + << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) + << QString::fromLatin1("x86-windows-msvc2013-pe-64bit") + << int(DebuggerItem::MatchesPerfectly); + QTest::newRow("Windows perfect match 2") + << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) + << QString::fromLatin1("x86-windows-msvc2012-pe-64bit") + << int(DebuggerItem::MatchesPerfectly); + QTest::newRow("Windows match 1") + << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) + << QString::fromLatin1("x86-windows-msvc2013-pe-32bit") + << int(DebuggerItem::MatchesSomewhat); + QTest::newRow("Windows match 2") + << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) + << QString::fromLatin1("x86-windows-msvc2012-pe-32bit") + << int(DebuggerItem::MatchesSomewhat); + QTest::newRow("Windows mismatch on word size") + << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit")) + << QString::fromLatin1("x86-windows-msvc2013-pe-64bit") + << int(DebuggerItem::DoesNotMatch); + QTest::newRow("Windows mismatch on osflavor 1") + << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit")) + << QString::fromLatin1("x86-windows-msys-pe-64bit") + << int(DebuggerItem::DoesNotMatch); + QTest::newRow("Windows mismatch on osflavor 2") + << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit")) + << QString::fromLatin1("x86-windows-msvc2010-pe-64bit") + << int(DebuggerItem::DoesNotMatch); +} + +void Debugger::DebuggerPlugin::testDebuggerMatching() +{ + QFETCH(QStringList, debugger); + QFETCH(QString, target); + QFETCH(int, result); + + DebuggerItem::MatchLevel expectedLevel = static_cast(result); + + QList debuggerAbis; + foreach (const QString &abi, debugger) + debuggerAbis << Abi(abi); + + DebuggerItem item; + item.setAbis(debuggerAbis); + + DebuggerItem::MatchLevel level = item.matchTarget(Abi(target)); + + QCOMPARE(expectedLevel, level); +} +#endif diff --git a/src/plugins/debugger/debuggeritem.h b/src/plugins/debugger/debuggeritem.h new file mode 100644 index 00000000000..14219471e9f --- /dev/null +++ b/src/plugins/debugger/debuggeritem.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_DEBUGGERITEM_H +#define DEBUGGER_DEBUGGERITEM_H + +#include "debugger_global.h" +#include "debuggerconstants.h" + +#include + +#include + +#include +#include + +namespace Debugger { + +namespace Internal { class DebuggerItemModel; } + +// ----------------------------------------------------------------------- +// DebuggerItem +// ----------------------------------------------------------------------- + +class DEBUGGER_EXPORT DebuggerItem +{ +public: + DebuggerItem(); + DebuggerItem(const QVariantMap &data); + + bool canClone() const { return true; } + bool isValid() const; + QString engineTypeName() const; + + QVariantMap toMap() const; + void reinitializeFromFile(); + + QVariant id() const { return m_id; } + + QString displayName() const { return m_displayName; } + void setDisplayName(const QString &displayName); + + DebuggerEngineType engineType() const { return m_engineType; } + void setEngineType(const DebuggerEngineType &engineType); + + Utils::FileName command() const { return m_command; } + void setCommand(const Utils::FileName &command); + + bool isAutoDetected() const { return m_isAutoDetected; } + void setAutoDetected(bool isAutoDetected); + + QList abis() const { return m_abis; } + void setAbis(const QList &abis); + void setAbi(const ProjectExplorer::Abi &abi); + + enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly }; + MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const; + + QStringList abiNames() const; + + bool operator==(const DebuggerItem &other) const; + +private: + DebuggerItem(const QVariant &id); + + QVariant m_id; + QString m_displayName; + DebuggerEngineType m_engineType; + Utils::FileName m_command; + bool m_isAutoDetected; + QList m_abis; + + friend class Internal::DebuggerItemModel; +}; + +} // namespace Debugger + +#endif // DEBUGGER_DEBUGGERITEM_H diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp new file mode 100644 index 00000000000..fcca5d8eac0 --- /dev/null +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "debuggeritemmanager.h" + +#include "debuggeritemmodel.h" +#include "debuggerkitinformation.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include + +using namespace ProjectExplorer; +using namespace Utils; + +namespace Debugger { + +static const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count"; +static const char DEBUGGER_DATA_KEY[] = "DebuggerItem."; +static const char DEBUGGER_LEGACY_FILENAME[] = "/qtcreator/profiles.xml"; +static const char DEBUGGER_FILE_VERSION_KEY[] = "Version"; +static const char DEBUGGER_FILENAME[] = "/qtcreator/debuggers.xml"; + +// -------------------------------------------------------------------------- +// DebuggerItemManager +// -------------------------------------------------------------------------- + +static DebuggerItemManager *m_instance = 0; + +static FileName userSettingsFileName() +{ + QFileInfo settingsLocation(Core::ICore::settings()->fileName()); + return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME)); +} + +static void readDebuggers(const FileName &fileName, bool isSystem) +{ + PersistentSettingsReader reader; + if (!reader.load(fileName)) + return; + QVariantMap data = reader.restoreValues(); + + // Check version + int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt(); + if (version < 1) + return; + + int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt(); + for (int i = 0; i < count; ++i) { + const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i); + if (!data.contains(key)) + continue; + const QVariantMap dbMap = data.value(key).toMap(); + DebuggerItem item(dbMap); + if (isSystem) { + item.setAutoDetected(true); + // SDK debuggers are always considered to be up-to-date, so no need to recheck them. + } else { + // User settings. + if (item.isAutoDetected() && (!item.isValid() || item.engineType() == NoEngineType)) { + qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid") + .arg(item.command().toString()).arg(item.id().toString()); + continue; + } + } + DebuggerItemManager::registerDebugger(item); + } +} + +QList DebuggerItemManager::m_debuggers; +PersistentSettingsWriter * DebuggerItemManager::m_writer = 0; + +DebuggerItemManager::DebuggerItemManager(QObject *parent) + : QObject(parent) +{ + m_instance = this; + m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger")); + connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), + this, SLOT(saveDebuggers())); +} + +QObject *DebuggerItemManager::instance() +{ + return m_instance; +} + +DebuggerItemManager::~DebuggerItemManager() +{ + disconnect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), + this, SLOT(saveDebuggers())); + delete m_writer; +} + +QList DebuggerItemManager::debuggers() +{ + return m_debuggers; +} + +void DebuggerItemManager::autoDetectCdbDebuggers() +{ + QList cdbs; + + QStringList programDirs; + programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles"))); + programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)"))); + programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432"))); + + foreach (const QString &dirName, programDirs) { + if (dirName.isEmpty()) + continue; + QDir dir(dirName); + // Windows SDK's starting from version 8 live in + // "ProgramDir\Windows Kits\" + const QString windowsKitsFolderName = QLatin1String("Windows Kits"); + if (dir.exists(windowsKitsFolderName)) { + QDir windowKitsFolder = dir; + if (windowKitsFolder.cd(windowsKitsFolderName)) { + // Check in reverse order (latest first) + const QFileInfoList kitFolders = + windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, + QDir::Time | QDir::Reversed); + foreach (const QFileInfo &kitFolderFi, kitFolders) { + const QString path = kitFolderFi.absoluteFilePath(); + const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe")); + if (cdb32.isExecutable()) + cdbs.append(FileName::fromString(cdb32.absoluteFilePath())); + const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe")); + if (cdb64.isExecutable()) + cdbs.append(FileName::fromString(cdb64.absoluteFilePath())); + } + } + } + + // Pre Windows SDK 8: Check 'Debugging Tools for Windows' + foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")), + QDir::Dirs | QDir::NoDotAndDotDot)) { + FileName filePath(fi); + filePath.appendPath(QLatin1String("cdb.exe")); + if (!cdbs.contains(filePath)) + cdbs.append(filePath); + } + } + + foreach (const FileName &cdb, cdbs) { + if (findByCommand(cdb)) + continue; + DebuggerItem item; + item.setAutoDetected(true); + item.setAbis(Abi::abisOfBinary(cdb)); + item.setCommand(cdb); + item.setEngineType(CdbEngineType); + item.setDisplayName(uniqueDisplayName(tr("Auto-detected CDB at %1").arg(cdb.toUserOutput()))); + addDebugger(item); + } +} + +void DebuggerItemManager::autoDetectGdbOrLldbDebuggers() +{ + QStringList filters; + filters.append(QLatin1String("gdb-i686-pc-mingw32")); + filters.append(QLatin1String("gdb")); + filters.append(QLatin1String("lldb")); + filters.append(QLatin1String("lldb-*")); + +// DebuggerItem result; +// result.setAutoDetected(true); +// result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName())); + /* + // Check suggestions from the SDK. + Environment env = Environment::systemEnvironment(); + if (tc) { + tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment. + QString path = tc->suggestedDebugger().toString(); + if (!path.isEmpty()) { + const QFileInfo fi(path); + if (!fi.isAbsolute()) + path = env.searchInPath(path); + result.command = FileName::fromString(path); + result.engineType = engineTypeFromBinary(path); + return maybeAddDebugger(result, false); + } + } + */ + + QFileInfoList suspects; + + QStringList path = Environment::systemEnvironment().path(); + foreach (const QString &base, path) { + QDir dir(base); + dir.setNameFilters(filters); + suspects += dir.entryInfoList(); + } + + foreach (const QFileInfo &fi, suspects) { + if (fi.exists()) { + FileName command = FileName::fromString(fi.absoluteFilePath()); + if (findByCommand(command)) + continue; + DebuggerItem item; + item.setCommand(command); + item.reinitializeFromFile(); + //: %1: Debugger engine type (GDB, LLDB, CDB...), %2: Path + item.setDisplayName(tr("System %1 at %2") + .arg(item.engineTypeName()).arg(QDir::toNativeSeparators(fi.absoluteFilePath()))); + item.setAutoDetected(true); + addDebugger(item); + } + } +} + +void DebuggerItemManager::readLegacyDebuggers() +{ + QFileInfo settingsLocation(Core::ICore::settings()->fileName()); + FileName legacyKits = FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_LEGACY_FILENAME)); + + PersistentSettingsReader reader; + if (!reader.load(legacyKits)) + return; + + foreach (const QVariant &v, reader.restoreValues()) { + QVariantMap data1 = v.toMap(); + QString kitName = data1.value(QLatin1String("PE.Profile.Name")).toString(); + QVariantMap data2 = data1.value(QLatin1String("PE.Profile.Data")).toMap(); + QVariant v3 = data2.value(DebuggerKitInformation::id().toString()); + QString fn; + if (v3.type() == QVariant::String) + fn = v3.toString(); + else + fn = v3.toMap().value(QLatin1String("Binary")).toString(); + if (fn.isEmpty()) + continue; + if (fn.startsWith(QLatin1Char('{'))) + continue; + if (fn == QLatin1String("auto")) + continue; + FileName command = FileName::fromUserInput(fn); + if (findByCommand(command)) + continue; + DebuggerItem item; + item.setCommand(command); + item.setAutoDetected(true); + item.reinitializeFromFile(); + item.setDisplayName(tr("Extracted from Kit %1").arg(kitName)); + addDebugger(item); + } +} + +const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command) +{ + foreach (const DebuggerItem &item, m_debuggers) + if (item.command() == command) + return &item; + + return 0; +} + +const DebuggerItem *DebuggerItemManager::findById(const QVariant &id) +{ + foreach (const DebuggerItem &item, m_debuggers) + if (item.id() == id) + return &item; + + return 0; +} + +void DebuggerItemManager::restoreDebuggers() +{ + // Read debuggers from SDK + QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName()); + readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true); + + // Read all debuggers from user file. + readDebuggers(userSettingsFileName(), false); + + // Auto detect current. + autoDetectCdbDebuggers(); + autoDetectGdbOrLldbDebuggers(); + + // Add debuggers from pre-3.x profiles.xml + readLegacyDebuggers(); +} + +void DebuggerItemManager::saveDebuggers() +{ + QTC_ASSERT(m_writer, return); + QVariantMap data; + data.insert(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 1); + + int count = 0; + foreach (const DebuggerItem &item, m_debuggers) { + if (item.isValid() && item.engineType() != NoEngineType) { + QVariantMap tmp = item.toMap(); + if (tmp.isEmpty()) + continue; + data.insert(QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(count), tmp); + ++count; + } + } + data.insert(QLatin1String(DEBUGGER_COUNT_KEY), count); + m_writer->save(data, Core::ICore::mainWindow()); + + // Do not save default debuggers as they are set by the SDK. +} + +QVariant DebuggerItemManager::registerDebugger(const DebuggerItem &item) +{ + QTC_ASSERT(!findById(item.id()), return item.id()); + + return addDebugger(item); +} + +void DebuggerItemManager::deregisterDebugger(const DebuggerItem &item) +{ + QTC_ASSERT(!item.command().isEmpty(), return); + QTC_ASSERT(!item.displayName().isEmpty(), return); + QTC_ASSERT(item.engineType() != NoEngineType, return); + + if (findById(item.id())) + removeDebugger(item.id()); +} + +QVariant DebuggerItemManager::addDebugger(const DebuggerItem &item) +{ + QTC_ASSERT(item.id().isValid(), return QVariant()); + m_debuggers.append(item); + QVariant id = item.id(); + emit m_instance->debuggerAdded(id); + return id; +} + +void DebuggerItemManager::removeDebugger(const QVariant &id) +{ + bool ok = false; + for (int i = 0, n = m_debuggers.size(); i != n; ++i) { + if (m_debuggers.at(i).id() == id) { + emit m_instance->aboutToRemoveDebugger(id); + m_debuggers.removeAt(i); + emit m_instance->debuggerRemoved(id); + ok = true; + break; + } + } + + QTC_ASSERT(ok, return); +} + +QString DebuggerItemManager::uniqueDisplayName(const QString &base) +{ + foreach (const DebuggerItem &item, m_debuggers) + if (item.displayName() == base) + return uniqueDisplayName(base + QLatin1String(" (1)")); + + return base; +} + +void DebuggerItemManager::setItemData(const QVariant &id, const QString &displayName, const FileName &fileName) +{ + for (int i = 0, n = m_debuggers.size(); i != n; ++i) { + DebuggerItem &item = m_debuggers[i]; + if (item.id() == id) { + item.setDisplayName(displayName); + item.setCommand(fileName); + item.reinitializeFromFile(); + emit m_instance->debuggerUpdated(id); + break; + } + } +} + +} // namespace Debugger; diff --git a/src/plugins/debugger/debuggeritemmanager.h b/src/plugins/debugger/debuggeritemmanager.h new file mode 100644 index 00000000000..27ad45614bb --- /dev/null +++ b/src/plugins/debugger/debuggeritemmanager.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_DEBUGGERITEMMANAGER_H +#define DEBUGGER_DEBUGGERITEMMANAGER_H + +#include "debugger_global.h" +#include "debuggeritem.h" +#include "debuggeritemmodel.h" + +#include +#include +#include + +namespace Utils { class PersistentSettingsWriter; } + +namespace Debugger { + +// ----------------------------------------------------------------------- +// DebuggerItemManager +// ----------------------------------------------------------------------- + +class DEBUGGER_EXPORT DebuggerItemManager : public QObject +{ + Q_OBJECT + +public: + static QObject *instance(); + ~DebuggerItemManager(); + + static QList debuggers(); + + static QVariant registerDebugger(const DebuggerItem &item); + static void deregisterDebugger(const DebuggerItem &item); + static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName); + + static const DebuggerItem *findByCommand(const Utils::FileName &command); + static const DebuggerItem *findById(const QVariant &id); + + static void restoreDebuggers(); + static QString uniqueDisplayName(const QString &base); + + static void removeDebugger(const QVariant &id); + static QVariant addDebugger(const DebuggerItem &item); + +signals: + void debuggerAdded(const QVariant &id); + void aboutToRemoveDebugger(const QVariant &id); + void debuggerRemoved(const QVariant &id); + void debuggerUpdated(const QVariant &id); + +public slots: + void saveDebuggers(); + +private: + explicit DebuggerItemManager(QObject *parent = 0); + static void autoDetectGdbOrLldbDebuggers(); + static void autoDetectCdbDebuggers(); + static void readLegacyDebuggers(); + + static Utils::PersistentSettingsWriter *m_writer; + static QList m_debuggers; + + friend class Internal::DebuggerItemModel; + friend class DebuggerPlugin; // Enable constrcutor for DebuggerPlugin +}; + +} // namespace Debugger + +#endif // DEBUGGER_DEBUGGERITEMMANAGER_H diff --git a/src/plugins/debugger/debuggeritemmodel.cpp b/src/plugins/debugger/debuggeritemmodel.cpp new file mode 100644 index 00000000000..2adb8d75d4e --- /dev/null +++ b/src/plugins/debugger/debuggeritemmodel.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "debuggeritemmodel.h" + +#include "debuggeritem.h" +#include "debuggeritemmanager.h" + +#include + +namespace Debugger { +namespace Internal { + +static QList describeItem(const DebuggerItem &item) +{ + QList row; + row.append(new QStandardItem(item.displayName())); + row.append(new QStandardItem(item.command().toUserOutput())); + row.append(new QStandardItem(item.engineTypeName())); + row.at(0)->setData(item.id()); + row.at(0)->setData(item.abiNames(), Qt::UserRole + 2); + row.at(0)->setEditable(false); + row.at(1)->setEditable(false); + row.at(1)->setData(item.toMap()); + row.at(2)->setEditable(false); + row.at(2)->setData(static_cast(item.engineType())); + row.at(0)->setSelectable(true); + row.at(1)->setSelectable(true); + row.at(2)->setSelectable(true); + return row; +} + +static QList createRow(const QString &display) +{ + QList row; + row.append(new QStandardItem(display)); + row.append(new QStandardItem()); + row.append(new QStandardItem()); + row.at(0)->setEditable(false); + row.at(1)->setEditable(false); + row.at(2)->setEditable(false); + row.at(0)->setSelectable(false); + row.at(1)->setSelectable(false); + row.at(2)->setSelectable(false); + return row; +} + +// -------------------------------------------------------------------------- +// DebuggerItemModel +// -------------------------------------------------------------------------- + +DebuggerItemModel::DebuggerItemModel(QObject *parent) + : QStandardItemModel(parent) +{ + setColumnCount(3); + + QList row = createRow(tr("Auto-detected")); + m_autoRoot = row.at(0); + appendRow(row); + + row = createRow(tr("Manual")); + m_manualRoot = row.at(0); + appendRow(row); + + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) + addDebuggerStandardItem(item, false); + + QObject *manager = DebuggerItemManager::instance(); + connect(manager, SIGNAL(debuggerAdded(QVariant)), + this, SLOT(onDebuggerAdded(QVariant))); + connect(manager, SIGNAL(debuggerUpdated(QVariant)), + this, SLOT(onDebuggerUpdate(QVariant))); + connect(manager, SIGNAL(debuggerRemoved(QVariant)), + this, SLOT(onDebuggerRemoval(QVariant))); +} + +QVariant DebuggerItemModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + switch (section) { + case 0: + return tr("Name"); + case 1: + return tr("Path"); + case 2: + return tr("Type"); + } + } + return QVariant(); +} + +bool DebuggerItemModel::addDebuggerStandardItem(const DebuggerItem &item, bool changed) +{ + if (findStandardItemById(item.id())) + return false; + + QList row = describeItem(item); + foreach (QStandardItem *cell, row) { + QFont font = cell->font(); + font.setBold(changed); + cell->setFont(font); + } + (item.isAutoDetected() ? m_autoRoot : m_manualRoot)->appendRow(row); + return true; +} + +bool DebuggerItemModel::removeDebuggerStandardItem(const QVariant &id) +{ + QStandardItem *sitem = findStandardItemById(id); + QTC_ASSERT(sitem, return false); + QStandardItem *parent = sitem->parent(); + QTC_ASSERT(parent, return false); + // This will trigger a change of m_currentDebugger via changing the + // view selection. + parent->removeRow(sitem->row()); + return true; +} + +bool DebuggerItemModel::updateDebuggerStandardItem(const DebuggerItem &item, bool changed) +{ + QStandardItem *sitem = findStandardItemById(item.id()); + QTC_ASSERT(sitem, return false); + QStandardItem *parent = sitem->parent(); + QTC_ASSERT(parent, return false); + int row = sitem->row(); + QFont font = sitem->font(); + font.setBold(changed); + parent->child(row, 0)->setData(item.displayName(), Qt::DisplayRole); + parent->child(row, 0)->setFont(font); + parent->child(row, 1)->setData(item.command().toUserOutput(), Qt::DisplayRole); + parent->child(row, 1)->setFont(font); + parent->child(row, 2)->setData(item.engineTypeName(), Qt::DisplayRole); + parent->child(row, 2)->setData(static_cast(item.engineType())); + parent->child(row, 2)->setFont(font); + return true; +} + +DebuggerItem DebuggerItemModel::debuggerItem(QStandardItem *sitem) const +{ + DebuggerItem item = DebuggerItem(QVariant()); + if (sitem && sitem->parent()) { + item.setAutoDetected(sitem->parent() == m_autoRoot); + + QStandardItem *i = sitem->parent()->child(sitem->row(), 0); + item.m_id = i->data(); + item.setDisplayName(i->data(Qt::DisplayRole).toString()); + + QStringList abis = i->data(Qt::UserRole + 2).toStringList(); + QList abiList; + foreach (const QString &abi, abis) + abiList << ProjectExplorer::Abi(abi); + item.setAbis(abiList); + + i = sitem->parent()->child(sitem->row(), 1); + item.setCommand(Utils::FileName::fromUserInput(i->data(Qt::DisplayRole).toString())); + + i = sitem->parent()->child(sitem->row(), 2); + item.setEngineType(static_cast(i->data().toInt())); + } + return item; +} + +QList DebuggerItemModel::debuggerItems() const +{ + QList result; + for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) + result << debuggerItem(m_autoRoot->child(i)); + for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) + result << debuggerItem(m_manualRoot->child(i)); + return result; +} + +QStandardItem *DebuggerItemModel::currentStandardItem() const +{ + return findStandardItemById(m_currentDebugger); +} + +QStandardItem *DebuggerItemModel::findStandardItemById(const QVariant &id) const +{ + for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) { + QStandardItem *sitem = m_autoRoot->child(i); + if (sitem->data() == id) + return sitem; + } + for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) { + QStandardItem *sitem = m_manualRoot->child(i); + if (sitem->data() == id) + return sitem; + } + return 0; +} + +QModelIndex DebuggerItemModel::currentIndex() const +{ + QStandardItem *current = currentStandardItem(); + return current ? current->index() : QModelIndex(); +} + +QModelIndex DebuggerItemModel::lastIndex() const +{ + int n = m_manualRoot->rowCount(); + QStandardItem *current = m_manualRoot->child(n - 1); + return current ? current->index() : QModelIndex(); +} + +void DebuggerItemModel::onDebuggerAdded(const QVariant &id) +{ + const DebuggerItem *item = DebuggerItemManager::findById(id); + QTC_ASSERT(item, return); + if (!addDebuggerStandardItem(*item, false)) + updateDebuggerStandardItem(*item, false); // already had it added, so just update it. +} + +void DebuggerItemModel::onDebuggerUpdate(const QVariant &id) +{ + const DebuggerItem *item = DebuggerItemManager::findById(id); + QTC_ASSERT(item, return); + updateDebuggerStandardItem(*item, false); +} + +void DebuggerItemModel::onDebuggerRemoval(const QVariant &id) +{ + removeDebuggerStandardItem(id); +} + +void DebuggerItemModel::addDebugger(const DebuggerItem &item) +{ + addDebuggerStandardItem(item, true); +} + +void DebuggerItemModel::removeDebugger(const QVariant &id) +{ + if (!removeDebuggerStandardItem(id)) // Nothing there! + return; + + if (DebuggerItemManager::findById(id)) + m_removedItems.append(id); +} + +void DebuggerItemModel::updateDebugger(const DebuggerItem &item) +{ + updateDebuggerStandardItem(item, true); +} + +void DebuggerItemModel::apply() +{ + foreach (const QVariant &id, m_removedItems) { + const DebuggerItem *item = DebuggerItemManager::findById(id); + QTC_CHECK(item); + DebuggerItemManager::deregisterDebugger(*item); + } + + foreach (const DebuggerItem &item, debuggerItems()) { + const DebuggerItem *managed = DebuggerItemManager::findById(item.id()); + if (managed) { + if (*managed == item) + continue; + else + DebuggerItemManager::setItemData(item.id(), item.displayName(), item.command()); + } else { + DebuggerItemManager::registerDebugger(item); + } + } +} + +void DebuggerItemModel::setCurrentIndex(const QModelIndex &index) +{ + QStandardItem *sit = itemFromIndex(index); + m_currentDebugger = sit ? sit->data() : QVariant(); +} + +DebuggerItem DebuggerItemModel::currentDebugger() const +{ + return debuggerItem(currentStandardItem()); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/debuggeritemmodel.h b/src/plugins/debugger/debuggeritemmodel.h new file mode 100644 index 00000000000..1f261696250 --- /dev/null +++ b/src/plugins/debugger/debuggeritemmodel.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_DEBUGGERITEMMODEL_H +#define DEBUGGER_DEBUGGERITEMMODEL_H + +#include "debuggeritem.h" + +#include +#include + +namespace Debugger { +namespace Internal { + +// ----------------------------------------------------------------------- +// DebuggerItemModel +//------------------------------------------------------------------------ + +class DebuggerItemModel : public QStandardItemModel +{ + Q_OBJECT + +public: + DebuggerItemModel(QObject *parent = 0); + + QModelIndex currentIndex() const; + QModelIndex lastIndex() const; + void setCurrentIndex(const QModelIndex &index); + QVariant currentDebuggerId() const { return m_currentDebugger; } + DebuggerItem currentDebugger() const; + void addDebugger(const DebuggerItem &item); + void removeDebugger(const QVariant &id); + void updateDebugger(const DebuggerItem &item); + + void apply(); + +private slots: + void onDebuggerAdded(const QVariant &id); + void onDebuggerUpdate(const QVariant &id); + void onDebuggerRemoval(const QVariant &id); + +private: + QStandardItem *currentStandardItem() const; + QStandardItem *findStandardItemById(const QVariant &id) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + + bool addDebuggerStandardItem(const DebuggerItem &item, bool changed); + bool removeDebuggerStandardItem(const QVariant &id); + bool updateDebuggerStandardItem(const DebuggerItem &item, bool changed); + + DebuggerItem debuggerItem(QStandardItem *sitem) const; + QList debuggerItems() const; + + QVariant m_currentDebugger; + + QStandardItem *m_autoRoot; + QStandardItem *m_manualRoot; + QStringList removed; + + QList m_removedItems; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_DEBUGGERITEMMODEL_H diff --git a/src/plugins/debugger/debuggerkitconfigwidget.cpp b/src/plugins/debugger/debuggerkitconfigwidget.cpp index 9d9f0b23a9a..9ced9edf691 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.cpp +++ b/src/plugins/debugger/debuggerkitconfigwidget.cpp @@ -29,6 +29,10 @@ #include "debuggerkitconfigwidget.h" +#include "debuggeritemmanager.h" +#include "debuggeritemmodel.h" +#include "debuggerkitinformation.h" + #include #include @@ -64,816 +68,10 @@ using namespace Utils; using namespace Debugger::Internal; namespace Debugger { - -static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging"; - -static const char DEBUGGER_DATA_KEY[] = "DebuggerItem."; -static const char DEBUGGER_COUNT_KEY[] = "DebuggerItem.Count"; -static const char DEBUGGER_FILE_VERSION_KEY[] = "Version"; -static const char DEBUGGER_FILENAME[] = "/qtcreator/debuggers.xml"; -static const char DEBUGGER_LEGACY_FILENAME[] = "/qtcreator/profiles.xml"; - -// -------------------------------------------------------------------------- -// DebuggerKitInformation -// -------------------------------------------------------------------------- - -DebuggerKitInformation::DebuggerKitInformation() -{ - setObjectName(QLatin1String("DebuggerKitInformation")); - setId(DebuggerKitInformation::id()); - setPriority(28000); -} - -QVariant DebuggerKitInformation::defaultValue(Kit *k) const -{ - ToolChain *tc = ToolChainKitInformation::toolChain(k); - QTC_ASSERT(tc, return QVariant()); - - const Abi toolChainAbi = tc->targetAbi(); - foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) - foreach (const Abi targetAbi, item.abis()) - if (targetAbi.isCompatibleWith(toolChainAbi)) - return item.id(); - - return QVariant(); -} - -void DebuggerKitInformation::setup(Kit *k) -{ - // Get one of the available debugger matching the kit's toolchain. - const ToolChain *tc = ToolChainKitInformation::toolChain(k); - const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi(); - - // This can be anything (Id, binary path, "auto") - const QVariant rawId = k->value(DebuggerKitInformation::id()); - - enum { - NotDetected, DetectedAutomatically, DetectedByFile, DetectedById - } detection = NotDetected; - DebuggerEngineType autoEngine = NoEngineType; - FileName fileName; - - // With 3.0 we have: - // {75ecf347-f221-44c3-b613-ea1d29929cd4} - // Before we had: - // - // /data/dev/debugger/gdb-git/gdb/gdb - // 1 - // - // Or for force auto-detected CDB - // - // auto - // 4 - // - - if (rawId.isNull()) { - // Initial setup of a kit - detection = NotDetected; - } else if (rawId.type() == QVariant::String) { - detection = DetectedById; - } else { - QMap map = rawId.toMap(); - QString binary = map.value(QLatin1String("Binary")).toString(); - if (binary == QLatin1String("auto")) { - detection = DetectedAutomatically; - autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt()); - } else { - detection = DetectedByFile; - fileName = FileName::fromUserInput(binary); - } - } - - const DebuggerItem *bestItem = 0; - DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch; - foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { - const DebuggerItem *goodItem = 0; - if (detection == DetectedById && item.id() == rawId) - goodItem = &item; - if (detection == DetectedByFile && item.command() == fileName) - goodItem = &item; - if (detection == DetectedAutomatically && item.engineType() == autoEngine) - goodItem = &item; - - if (goodItem) { - DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi); - if (level > bestLevel) { - bestLevel = level; - bestItem = goodItem; - } - } - } - - // If we have an existing debugger with matching id _and_ - // matching target ABI we are fine. - if (bestItem) { - k->setValue(DebuggerKitInformation::id(), bestItem->id()); - return; - } - - // We didn't find an existing debugger that matched by whatever - // data we found in the kit (i.e. no id, filename, "auto") - // (or what we found did not match ABI-wise) - // Let's try to pick one with matching ABI. - QVariant bestId; - bestLevel = DebuggerItem::DoesNotMatch; - foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { - DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi); - if (level > bestLevel) { - bestLevel = level; - bestId = item.id(); - } - } - - k->setValue(DebuggerKitInformation::id(), bestId); -} - - -// This handles the upgrade path from 2.8 to 3.0 -void DebuggerKitInformation::fix(Kit *k) -{ - // This can be Id, binary path, but not "auto" anymore. - const QVariant rawId = k->value(DebuggerKitInformation::id()); - - if (rawId.isNull()) // No debugger set, that is fine. - return; - - if (rawId.type() == QVariant::String) { - if (!DebuggerItemManager::findById(rawId)) { - qWarning("Unknown debugger id %s in kit %s", - qPrintable(rawId.toString()), qPrintable(k->displayName())); - k->setValue(DebuggerKitInformation::id(), QVariant()); - } - return; // All fine (now). - } - - QMap map = rawId.toMap(); - QString binary = map.value(QLatin1String("Binary")).toString(); - if (binary == QLatin1String("auto")) { - // This should not happen as "auto" is handled by setup() already. - QTC_CHECK(false); - k->setValue(DebuggerKitInformation::id(), QVariant()); - return; - } - - FileName fileName = FileName::fromUserInput(binary); - const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName); - if (!item) { - qWarning("Debugger command %s invalid in kit %s", - qPrintable(binary), qPrintable(k->displayName())); - k->setValue(DebuggerKitInformation::id(), QVariant()); - return; - } - - k->setValue(DebuggerKitInformation::id(), item->id()); -} - -// Check the configuration errors and return a flag mask. Provide a quick check and -// a verbose one with a list of errors. - -enum DebuggerConfigurationErrors { - NoDebugger = 0x1, - DebuggerNotFound = 0x2, - DebuggerNotExecutable = 0x4, - DebuggerNeedsAbsolutePath = 0x8 -}; - -static unsigned debuggerConfigurationErrors(const Kit *k) -{ - QTC_ASSERT(k, return NoDebugger); - - const DebuggerItem *item = DebuggerKitInformation::debugger(k); - if (!item) - return NoDebugger; - - if (item->command().isEmpty()) - return NoDebugger; - - unsigned result = 0; - const QFileInfo fi = item->command().toFileInfo(); - if (!fi.exists() || fi.isDir()) - result |= DebuggerNotFound; - else if (!fi.isExecutable()) - result |= DebuggerNotExecutable; - - if (!fi.exists() || fi.isDir()) { - if (item->engineType() == NoEngineType) - return NoDebugger; - - // We need an absolute path to be able to locate Python on Windows. - if (item->engineType() == GdbEngineType) - if (const ToolChain *tc = ToolChainKitInformation::toolChain(k)) - if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute()) - result |= DebuggerNeedsAbsolutePath; - } - return result; -} - -const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit) -{ - QTC_ASSERT(kit, return 0); - const QVariant id = kit->value(DebuggerKitInformation::id()); - return DebuggerItemManager::findById(id); -} - -bool DebuggerKitInformation::isValidDebugger(const Kit *k) -{ - return debuggerConfigurationErrors(k) == 0; -} - -QList DebuggerKitInformation::validateDebugger(const Kit *k) -{ - QList result; - - const unsigned errors = debuggerConfigurationErrors(k); - if (!errors) - return result; - - QString path; - if (const DebuggerItem *item = debugger(k)) - path = item->command().toUserOutput(); - - const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM; - if (errors & NoDebugger) - result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id); - - if (errors & DebuggerNotFound) - result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path), - FileName(), -1, id); - if (errors & DebuggerNotExecutable) - result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id); - - if (errors & DebuggerNeedsAbsolutePath) { - const QString message = - tr("The debugger location must be given as an " - "absolute path (%1).").arg(path); - result << Task(Task::Error, message, FileName(), -1, id); - } - return result; -} - -KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const -{ - return new Internal::DebuggerKitConfigWidget(k, this); -} - -KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const -{ - return ItemList() << qMakePair(tr("Debugger"), displayString(k)); -} - -FileName DebuggerKitInformation::debuggerCommand(const ProjectExplorer::Kit *k) -{ - const DebuggerItem *item = debugger(k); - QTC_ASSERT(item, return FileName()); - return item->command(); -} - -DebuggerEngineType DebuggerKitInformation::engineType(const ProjectExplorer::Kit *k) -{ - const DebuggerItem *item = debugger(k); - QTC_ASSERT(item, return NoEngineType); - return item->engineType(); -} - -QString DebuggerKitInformation::displayString(const Kit *k) -{ - const DebuggerItem *item = debugger(k); - if (!item) - return tr("No Debugger"); - QString binary = item->command().toUserOutput(); - QString name = tr("%1 Engine").arg(item->engineTypeName()); - return binary.isEmpty() ? tr("%1 ").arg(name) : tr("%1 using \"%2\"").arg(name, binary); -} - -void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id) -{ - // Only register reasonably complete debuggers. - QTC_ASSERT(DebuggerItemManager::findById(id), return); - k->setValue(DebuggerKitInformation::id(), id); -} - -Core::Id DebuggerKitInformation::id() -{ - return "Debugger.Information"; -} - -// -------------------------------------------------------------------------- -// DebuggerItemManager -// -------------------------------------------------------------------------- - -static DebuggerItemManager *m_instance = 0; - -static FileName userSettingsFileName() -{ - QFileInfo settingsLocation(Core::ICore::settings()->fileName()); - return FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_FILENAME)); -} - -static void readDebuggers(const FileName &fileName, bool isSystem) -{ - PersistentSettingsReader reader; - if (!reader.load(fileName)) - return; - QVariantMap data = reader.restoreValues(); - - // Check version - int version = data.value(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 0).toInt(); - if (version < 1) - return; - - int count = data.value(QLatin1String(DEBUGGER_COUNT_KEY), 0).toInt(); - for (int i = 0; i < count; ++i) { - const QString key = QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(i); - if (!data.contains(key)) - continue; - const QVariantMap dbMap = data.value(key).toMap(); - DebuggerItem item; - item.fromMap(dbMap); - if (isSystem) { - item.setAutoDetected(true); - // SDK debuggers are always considered to be up-to-date, so no need to recheck them. - } else { - // User settings. - if (item.isAutoDetected() && !item.isValid()) { - qWarning() << QString::fromLatin1("DebuggerItem \"%1\" (%2) dropped since it is not valid") - .arg(item.command().toString()).arg(item.id().toString()); - continue; - } - } - DebuggerItemManager::registerDebugger(item); - } -} - -QList DebuggerItemManager::m_debuggers; -DebuggerItemModel* DebuggerItemManager::m_model = 0; -PersistentSettingsWriter * DebuggerItemManager::m_writer = 0; - -DebuggerItemManager::DebuggerItemManager(QObject *parent) - : QObject(parent) -{ - m_instance = this; - m_writer = new PersistentSettingsWriter(userSettingsFileName(), QLatin1String("QtCreatorDebugger")); - m_model = new Debugger::Internal::DebuggerItemModel(this); - connect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), - this, SLOT(saveDebuggers())); -} - -QObject *DebuggerItemManager::instance() -{ - return m_instance; -} - -DebuggerItemManager::~DebuggerItemManager() -{ - disconnect(Core::ICore::instance(), SIGNAL(saveSettingsRequested()), - this, SLOT(saveDebuggers())); - delete m_writer; -} - -QList DebuggerItemManager::debuggers() -{ - return m_debuggers; -} - -DebuggerItemModel *DebuggerItemManager::model() -{ - return m_model; -} - -void DebuggerItemManager::autoDetectCdbDebuggers() -{ - QList cdbs; - - QStringList programDirs; - programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles"))); - programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramFiles(x86)"))); - programDirs.append(QString::fromLocal8Bit(qgetenv("ProgramW6432"))); - - foreach (const QString &dirName, programDirs) { - if (dirName.isEmpty()) - continue; - QDir dir(dirName); - // Windows SDK's starting from version 8 live in - // "ProgramDir\Windows Kits\" - const QString windowsKitsFolderName = QLatin1String("Windows Kits"); - if (dir.exists(windowsKitsFolderName)) { - QDir windowKitsFolder = dir; - if (windowKitsFolder.cd(windowsKitsFolderName)) { - // Check in reverse order (latest first) - const QFileInfoList kitFolders = - windowKitsFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, - QDir::Time | QDir::Reversed); - foreach (const QFileInfo &kitFolderFi, kitFolders) { - const QString path = kitFolderFi.absoluteFilePath(); - const QFileInfo cdb32(path + QLatin1String("/Debuggers/x86/cdb.exe")); - if (cdb32.isExecutable()) - cdbs.append(FileName::fromString(cdb32.absoluteFilePath())); - const QFileInfo cdb64(path + QLatin1String("/Debuggers/x64/cdb.exe")); - if (cdb64.isExecutable()) - cdbs.append(FileName::fromString(cdb64.absoluteFilePath())); - } - } - } - - // Pre Windows SDK 8: Check 'Debugging Tools for Windows' - foreach (const QFileInfo &fi, dir.entryInfoList(QStringList(QLatin1String("Debugging Tools for Windows*")), - QDir::Dirs | QDir::NoDotAndDotDot)) { - FileName filePath(fi); - filePath.appendPath(QLatin1String("cdb.exe")); - if (!cdbs.contains(filePath)) - cdbs.append(filePath); - } - } - - foreach (const FileName &cdb, cdbs) { - if (findByCommand(cdb)) - continue; - DebuggerItem item; - item.setAutoDetected(true); - item.setAbis(Abi::abisOfBinary(cdb)); - item.setCommand(cdb); - item.setEngineType(CdbEngineType); - item.setDisplayName(uniqueDisplayName(tr("Auto-detected CDB at %1").arg(cdb.toUserOutput()))); - addDebugger(item); - } -} - -void DebuggerItemManager::autoDetectGdbOrLldbDebuggers() -{ - QStringList filters; - filters.append(QLatin1String("gdb-i686-pc-mingw32")); - filters.append(QLatin1String("gdb")); - filters.append(QLatin1String("lldb")); - filters.append(QLatin1String("lldb-*")); - -// DebuggerItem result; -// result.setAutoDetected(true); -// result.setDisplayName(tr("Auto-detected for Tool Chain %1").arg(tc->displayName())); - /* - // Check suggestions from the SDK. - Environment env = Environment::systemEnvironment(); - if (tc) { - tc->addToEnvironment(env); // Find MinGW gdb in toolchain environment. - QString path = tc->suggestedDebugger().toString(); - if (!path.isEmpty()) { - const QFileInfo fi(path); - if (!fi.isAbsolute()) - path = env.searchInPath(path); - result.command = FileName::fromString(path); - result.engineType = engineTypeFromBinary(path); - return maybeAddDebugger(result, false); - } - } - */ - - QFileInfoList suspects; - - QStringList path = Environment::systemEnvironment().path(); - foreach (const QString &base, path) { - QDir dir(base); - dir.setNameFilters(filters); - suspects += dir.entryInfoList(); - } - - foreach (const QFileInfo &fi, suspects) { - if (fi.exists()) { - FileName command = FileName::fromString(fi.absoluteFilePath()); - if (findByCommand(command)) - continue; - DebuggerItem item; - item.setCommand(command); - item.reinitializeFromFile(); - //: %1: Debugger engine type (GDB, LLDB, CDB...), %2: Path - item.setDisplayName(tr("System %1 at %2") - .arg(item.engineTypeName()).arg(QDir::toNativeSeparators(fi.absoluteFilePath()))); - item.setAutoDetected(true); - addDebugger(item); - } - } -} - -void DebuggerItemManager::readLegacyDebuggers() -{ - QFileInfo settingsLocation(Core::ICore::settings()->fileName()); - FileName legacyKits = FileName::fromString(settingsLocation.absolutePath() + QLatin1String(DEBUGGER_LEGACY_FILENAME)); - - PersistentSettingsReader reader; - if (!reader.load(legacyKits)) - return; - - foreach (const QVariant &v, reader.restoreValues()) { - QVariantMap data1 = v.toMap(); - QString kitName = data1.value(QLatin1String("PE.Profile.Name")).toString(); - QVariantMap data2 = data1.value(QLatin1String("PE.Profile.Data")).toMap(); - QVariant v3 = data2.value(DebuggerKitInformation::id().toString()); - QString fn; - if (v3.type() == QVariant::String) - fn = v3.toString(); - else - fn = v3.toMap().value(QLatin1String("Binary")).toString(); - if (fn.isEmpty()) - continue; - if (fn.startsWith(QLatin1Char('{'))) - continue; - if (fn == QLatin1String("auto")) - continue; - FileName command = FileName::fromUserInput(fn); - if (findByCommand(command)) - continue; - DebuggerItem item; - item.setCommand(command); - item.setAutoDetected(true); - item.reinitializeFromFile(); - item.setDisplayName(tr("Extracted from Kit %1").arg(kitName)); - addDebugger(item); - } -} - -const DebuggerItem *DebuggerItemManager::findByCommand(const FileName &command) -{ - foreach (const DebuggerItem &item, m_debuggers) - if (item.command() == command) - return &item; - - return 0; -} - -const DebuggerItem *DebuggerItemManager::findById(const QVariant &id) -{ - foreach (const DebuggerItem &item, m_debuggers) - if (item.id() == id) - return &item; - - return 0; -} - -void DebuggerItemManager::restoreDebuggers() -{ - // Read debuggers from SDK - QFileInfo systemSettingsFile(Core::ICore::settings(QSettings::SystemScope)->fileName()); - readDebuggers(FileName::fromString(systemSettingsFile.absolutePath() + QLatin1String(DEBUGGER_FILENAME)), true); - - // Read all debuggers from user file. - readDebuggers(userSettingsFileName(), false); - - // Auto detect current. - autoDetectCdbDebuggers(); - autoDetectGdbOrLldbDebuggers(); - - // Add debuggers from pre-3.x profiles.xml - readLegacyDebuggers(); -} - -void DebuggerItemManager::saveDebuggers() -{ - QTC_ASSERT(m_writer, return); - QVariantMap data; - data.insert(QLatin1String(DEBUGGER_FILE_VERSION_KEY), 1); - - int count = 0; - foreach (const DebuggerItem &item, m_debuggers) { - if (item.isValid()) { - QVariantMap tmp = item.toMap(); - if (tmp.isEmpty()) - continue; - data.insert(QString::fromLatin1(DEBUGGER_DATA_KEY) + QString::number(count), tmp); - ++count; - } - } - data.insert(QLatin1String(DEBUGGER_COUNT_KEY), count); - m_writer->save(data, Core::ICore::mainWindow()); - - // Do not save default debuggers as they are set by the SDK. -} - -QVariant DebuggerItemManager::registerDebugger(const DebuggerItem &item) -{ - if (findByCommand(item.command())) - return item.id(); - - return addDebugger(item); -} - -void DebuggerItemManager::deregisterDebugger(const DebuggerItem &item) -{ - if (findByCommand(item.command())) - removeDebugger(item.id()); -} - -QVariant DebuggerItemManager::addDebugger(const DebuggerItem& item0) -{ - DebuggerItem item = item0; - QTC_ASSERT(!item.command().isEmpty(), return QVariant()); - QTC_ASSERT(!item.displayName().isEmpty(), return QVariant()); - QTC_ASSERT(item.engineType() != NoEngineType, return QVariant()); - if (item.id().isNull()) - item.setId(QUuid::createUuid().toString()); - m_debuggers.append(item); - m_model->addDebugger(item); - return item.id(); -} - -void DebuggerItemManager::removeDebugger(const QVariant &id) -{ - bool ok = false; - for (int i = 0, n = m_debuggers.size(); i != n; ++i) { - if (m_debuggers.at(i).id() == id) { - m_debuggers.removeAt(i); - ok = true; - break; - } - } - - QTC_ASSERT(ok, return); - m_model->removeDebugger(id); -} - -QString DebuggerItemManager::uniqueDisplayName(const QString &base) -{ - foreach (const DebuggerItem &item, m_debuggers) - if (item.displayName() == base) - return uniqueDisplayName(base + QLatin1String(" (1)")); - - return base; -} - -void DebuggerItemManager::setItemData(const QVariant &id, const QString &displayName, const FileName &fileName) -{ - for (int i = 0, n = m_debuggers.size(); i != n; ++i) { - DebuggerItem &item = m_debuggers[i]; - if (item.id() == id) { - item.setDisplayName(displayName); - item.setCommand(fileName); - item.reinitializeFromFile(); - emit m_model->updateDebugger(item.id()); - break; - } - } -} - namespace Internal { -static QList describeItem(const DebuggerItem &item) -{ - QList row; - row.append(new QStandardItem(item.displayName())); - row.append(new QStandardItem(item.command().toUserOutput())); - row.append(new QStandardItem(item.engineTypeName())); - row.at(0)->setData(item.id()); - row.at(0)->setEditable(false); - row.at(1)->setEditable(false); - row.at(2)->setEditable(false); - row.at(0)->setSelectable(true); - row.at(1)->setSelectable(true); - row.at(2)->setSelectable(true); - return row; -} - -static QList createRow(const QString &display) -{ - QList row; - row.append(new QStandardItem(display)); - row.append(new QStandardItem()); - row.append(new QStandardItem()); - row.at(0)->setEditable(false); - row.at(1)->setEditable(false); - row.at(2)->setEditable(false); - row.at(0)->setSelectable(false); - row.at(1)->setSelectable(false); - row.at(2)->setSelectable(false); - return row; -} - class DebuggerItemConfigWidget; -// -------------------------------------------------------------------------- -// DebuggerItemModel -// -------------------------------------------------------------------------- - -DebuggerItemModel::DebuggerItemModel(QObject *parent) - : QStandardItemModel(parent) -{ - setColumnCount(3); - - QList row = createRow(tr("Auto-detected")); - m_autoRoot = row.at(0); - appendRow(row); - - row = createRow(tr("Manual")); - m_manualRoot = row.at(0); - appendRow(row); -} - -QVariant DebuggerItemModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { - switch (section) { - case 0: - return tr("Name"); - case 1: - return tr("Path"); - case 2: - return tr("Type"); - } - } - return QVariant(); -} - -QStandardItem *DebuggerItemModel::currentStandardItem() const -{ - return findStandardItemById(m_currentDebugger); -} - -QStandardItem *DebuggerItemModel::findStandardItemById(const QVariant &id) const -{ - for (int i = 0, n = m_autoRoot->rowCount(); i != n; ++i) { - QStandardItem *sitem = m_autoRoot->child(i); - if (sitem->data() == id) - return sitem; - } - for (int i = 0, n = m_manualRoot->rowCount(); i != n; ++i) { - QStandardItem *sitem = m_manualRoot->child(i); - if (sitem->data() == id) - return sitem; - } - return 0; -} - -QModelIndex DebuggerItemModel::currentIndex() const -{ - QStandardItem *current = currentStandardItem(); - return current ? current->index() : QModelIndex(); -} - -QModelIndex DebuggerItemModel::lastIndex() const -{ - int n = m_manualRoot->rowCount(); - QStandardItem *current = m_manualRoot->child(n - 1); - return current ? current->index() : QModelIndex(); -} - -void DebuggerItemModel::markCurrentDirty() -{ - QStandardItem *sitem = currentStandardItem(); - QTC_ASSERT(sitem, return); - QFont font = sitem->font(); - font.setBold(true); - sitem->setFont(font); -} - -void DebuggerItemModel::addDebugger(const DebuggerItem &item0) -{ - DebuggerItem item = item0; - if (item.id().isNull()) - item.setId(QUuid::createUuid().toString()); - QList row = describeItem(item); - (item.isAutoDetected() ? m_autoRoot : m_manualRoot)->appendRow(row); - emit debuggerAdded(item.id(), item.displayName()); -} - -void DebuggerItemModel::removeDebugger(const QVariant &id) -{ - QStandardItem *sitem = findStandardItemById(id); - QTC_ASSERT(sitem, return); - QStandardItem *parent = sitem->parent(); - QTC_ASSERT(parent, return); - // This will trigger a change of m_currentDebugger via changing the - // view selection. - parent->removeRow(sitem->row()); - emit debuggerRemoved(id); -} - -void DebuggerItemModel::updateDebugger(const QVariant &id) -{ - QList debuggers = DebuggerItemManager::debuggers(); - for (int i = 0, n = debuggers.size(); i != n; ++i) { - DebuggerItem &item = debuggers[i]; - if (item.id() == id) { - QStandardItem *sitem = findStandardItemById(id); - QTC_ASSERT(sitem, return); - QStandardItem *parent = sitem->parent(); - QTC_ASSERT(parent, return); - int row = sitem->row(); - QFont font = sitem->font(); - font.setBold(false); - parent->child(row, 0)->setData(item.displayName(), Qt::DisplayRole); - parent->child(row, 0)->setFont(font); - parent->child(row, 1)->setData(item.command().toUserOutput(), Qt::DisplayRole); - parent->child(row, 1)->setFont(font); - parent->child(row, 2)->setData(item.engineTypeName(), Qt::DisplayRole); - parent->child(row, 2)->setFont(font); - emit debuggerUpdated(id, item.displayName()); - return; - } - } -} - -void DebuggerItemModel::setCurrentIndex(const QModelIndex &index) -{ - QStandardItem *sit = itemFromIndex(index); - m_currentDebugger = sit ? sit->data() : QVariant(); -} - // ----------------------------------------------------------------------- // DebuggerKitConfigWidget // ----------------------------------------------------------------------- @@ -881,9 +79,6 @@ void DebuggerItemModel::setCurrentIndex(const QModelIndex &index) DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInformation *ki) : KitConfigWidget(workingCopy, ki) { - DebuggerItemModel *model = DebuggerItemManager::model(); - QTC_CHECK(model); - m_comboBox = new QComboBox; m_comboBox->setEnabled(true); m_comboBox->setToolTip(toolTip()); @@ -898,11 +93,12 @@ DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInfo m_manageButton->setContentsMargins(0, 0, 0, 0); connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageDebuggers())); - connect(model, SIGNAL(debuggerAdded(QVariant,QString)), - this, SLOT(onDebuggerAdded(QVariant,QString))); - connect(model, SIGNAL(debuggerUpdated(QVariant,QString)), - this, SLOT(onDebuggerUpdated(QVariant,QString))); - connect(model, SIGNAL(debuggerRemoved(QVariant)), + QObject *manager = DebuggerItemManager::instance(); + connect(manager, SIGNAL(debuggerAdded(QVariant)), + this, SLOT(onDebuggerAdded(QVariant))); + connect(manager, SIGNAL(debuggerUpdated(QVariant)), + this, SLOT(onDebuggerUpdated(QVariant))); + connect(manager, SIGNAL(debuggerRemoved(QVariant)), this, SLOT(onDebuggerRemoved(QVariant))); } @@ -957,20 +153,22 @@ void DebuggerKitConfigWidget::currentDebuggerChanged(int) m_kit->setValue(DebuggerKitInformation::id(), id); } -void DebuggerKitConfigWidget::onDebuggerAdded(const QVariant &id, const QString &displayName) +void DebuggerKitConfigWidget::onDebuggerAdded(const QVariant &id) { - m_comboBox->setEnabled(true); - m_comboBox->addItem(displayName, id); + const DebuggerItem *item = DebuggerItemManager::findById(id); + QTC_ASSERT(item, return); + m_comboBox->addItem(item->displayName(), id); updateComboBox(id); } -void DebuggerKitConfigWidget::onDebuggerUpdated(const QVariant &id, const QString &displayName) +void DebuggerKitConfigWidget::onDebuggerUpdated(const QVariant &id) { - m_comboBox->setEnabled(true); + const DebuggerItem *item = DebuggerItemManager::findById(id); + QTC_ASSERT(item, return); const int pos = indexOf(id); if (pos < 0) return; - m_comboBox->setItemText(pos, displayName); + m_comboBox->setItemText(pos, item->displayName()); } void DebuggerKitConfigWidget::onDebuggerRemoved(const QVariant &id) @@ -1007,296 +205,5 @@ void DebuggerKitConfigWidget::updateComboBox(const QVariant &id) m_comboBox->setCurrentIndex(0); } -// ----------------------------------------------------------------------- -// DebuggerItemConfigWidget -// ----------------------------------------------------------------------- - -class DebuggerItemConfigWidget : public QWidget -{ - Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::DebuggerItemConfigWidget) -public: - explicit DebuggerItemConfigWidget(); - void loadItem(); - void saveItem(); - void connectDirty(); - void disconnectDirty(); - -private: - QLineEdit *m_displayNameLineEdit; - QLabel *m_cdbLabel; - PathChooser *m_binaryChooser; - QLineEdit *m_abis; -}; - -DebuggerItemConfigWidget::DebuggerItemConfigWidget() -{ - m_displayNameLineEdit = new QLineEdit(this); - - m_binaryChooser = new PathChooser(this); - m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand); - m_binaryChooser->setMinimumWidth(400); - - m_cdbLabel = new QLabel(this); - m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - m_cdbLabel->setOpenExternalLinks(true); - - m_abis = new QLineEdit(this); - m_abis->setEnabled(false); - - QFormLayout *formLayout = new QFormLayout(this); - formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); -// formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox); - formLayout->addRow(m_cdbLabel); - formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); - formLayout->addRow(new QLabel(tr("ABIs:")), m_abis); - - connectDirty(); -} - -void DebuggerItemConfigWidget::connectDirty() -{ - DebuggerItemModel *model = DebuggerItemManager::model(); - connect(m_displayNameLineEdit, SIGNAL(textChanged(QString)), - model, SLOT(markCurrentDirty())); - connect(m_binaryChooser, SIGNAL(changed(QString)), - model, SLOT(markCurrentDirty())); -} - -void DebuggerItemConfigWidget::disconnectDirty() -{ - DebuggerItemModel *model = DebuggerItemManager::model(); - disconnect(m_displayNameLineEdit, SIGNAL(textChanged(QString)), - model, SLOT(markCurrentDirty())); - disconnect(m_binaryChooser, SIGNAL(changed(QString)), - model, SLOT(markCurrentDirty())); -} - -void DebuggerItemConfigWidget::loadItem() -{ - DebuggerItemModel *model = DebuggerItemManager::model(); - const DebuggerItem *item = DebuggerItemManager::findById(model->m_currentDebugger); - if (!item) - return; - - disconnectDirty(); - m_displayNameLineEdit->setEnabled(!item->isAutoDetected()); - m_displayNameLineEdit->setText(item->displayName()); - - m_binaryChooser->setEnabled(!item->isAutoDetected()); - m_binaryChooser->setFileName(item->command()); - connectDirty(); - - QString text; - QString versionCommand; - if (item->engineType() == CdbEngineType) { -#ifdef Q_OS_WIN - const bool is64bit = winIs64BitSystem(); -#else - const bool is64bit = false; -#endif - const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version"); - //: Label text for path configuration. %2 is "x-bit version". - text = tr("

Specify the path to the " - "Windows Console Debugger executable" - " (%2) here.

"""). - arg(QLatin1String(debuggingToolsWikiLinkC), versionString); - versionCommand = QLatin1String("-version"); - } else { - versionCommand = QLatin1String("--version"); - } - - m_cdbLabel->setText(text); - m_cdbLabel->setVisible(!text.isEmpty()); - m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand)); - - m_abis->setText(item->abiNames().join(QLatin1String(", "))); -} - -void DebuggerItemConfigWidget::saveItem() -{ - DebuggerItemModel *model = DebuggerItemManager::model(); - const DebuggerItem *item = DebuggerItemManager::findById(model->m_currentDebugger); - QTC_ASSERT(item, return); - DebuggerItemManager::setItemData(item->id(), m_displayNameLineEdit->text(), - m_binaryChooser->fileName()); -} - -// -------------------------------------------------------------------------- -// DebuggerOptionsPage -// -------------------------------------------------------------------------- - -DebuggerOptionsPage::DebuggerOptionsPage() -{ - m_model = 0; - m_debuggerView = 0; - m_container = 0; - m_addButton = 0; - m_cloneButton = 0; - m_delButton = 0; - - setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID); - setDisplayName(tr("Debuggers")); - setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY); - setDisplayCategory(QCoreApplication::translate("ProjectExplorer", - ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY)); - setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON)); -} - -QWidget *DebuggerOptionsPage::createPage(QWidget *parent) -{ - m_configWidget = new QWidget(parent); - - m_addButton = new QPushButton(tr("Add"), m_configWidget); - m_cloneButton = new QPushButton(tr("Clone"), m_configWidget); - m_delButton = new QPushButton(tr("Remove"), m_configWidget); - - m_container = new DetailsWidget(m_configWidget); - m_container->setState(DetailsWidget::NoSummary); - m_container->setVisible(false); - - m_model = DebuggerItemManager::model(); - - m_debuggerView = new QTreeView(m_configWidget); - m_debuggerView->setModel(m_model); - m_debuggerView->setUniformRowHeights(true); - m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection); - m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows); - m_debuggerView->expandAll(); - - QHeaderView *header = m_debuggerView->header(); - header->setStretchLastSection(false); - header->setResizeMode(0, QHeaderView::ResizeToContents); - header->setResizeMode(1, QHeaderView::ResizeToContents); - header->setResizeMode(2, QHeaderView::Stretch); - - QVBoxLayout *buttonLayout = new QVBoxLayout(); - buttonLayout->setSpacing(6); - buttonLayout->setContentsMargins(0, 0, 0, 0); - buttonLayout->addWidget(m_addButton); - buttonLayout->addWidget(m_cloneButton); - buttonLayout->addWidget(m_delButton); - buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); - - QVBoxLayout *verticalLayout = new QVBoxLayout(); - verticalLayout->addWidget(m_debuggerView); - verticalLayout->addWidget(m_container); - - QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget); - horizontalLayout->addLayout(verticalLayout); - horizontalLayout->addLayout(buttonLayout); - - connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - this, SLOT(debuggerSelectionChanged())); - - connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection); - connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection); - connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection); - - m_searchKeywords = tr("Debuggers"); - - m_itemConfigWidget = new DebuggerItemConfigWidget; - m_container->setWidget(m_itemConfigWidget); - - updateState(); - - return m_configWidget; -} - -void DebuggerOptionsPage::apply() -{ - m_itemConfigWidget->saveItem(); - debuggerModelChanged(); -} - -void DebuggerOptionsPage::cloneDebugger() -{ - const DebuggerItem *item = DebuggerItemManager::findById(m_model->currentDebugger()); - QTC_ASSERT(item, return); - DebuggerItem newItem; - newItem.setCommand(item->command()); - newItem.setEngineType(item->engineType()); - newItem.setAbis(item->abis()); - newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item->displayName()))); - newItem.setAutoDetected(false); - DebuggerItemManager::addDebugger(newItem); - m_debuggerView->setCurrentIndex(m_model->lastIndex()); -} - -void DebuggerOptionsPage::addDebugger() -{ - DebuggerItem item; - item.setEngineType(NoEngineType); - item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger"))); - item.setAutoDetected(false); - DebuggerItemManager::addDebugger(item); - m_debuggerView->setCurrentIndex(m_model->lastIndex()); -} - -void DebuggerOptionsPage::removeDebugger() -{ - QVariant id = m_model->currentDebugger(); - DebuggerItemManager::removeDebugger(id); - m_debuggerView->setCurrentIndex(m_model->lastIndex()); -} - -void DebuggerOptionsPage::finish() -{ - // Deleted by settingsdialog. - m_configWidget = 0; - - // Children of m_configWidget. - m_container = 0; - m_debuggerView = 0; - m_addButton = 0; - m_cloneButton = 0; - m_delButton = 0; -} - -bool DebuggerOptionsPage::matches(const QString &s) const -{ - return m_searchKeywords.contains(s, Qt::CaseInsensitive); -} - -void DebuggerOptionsPage::debuggerSelectionChanged() -{ - QTC_ASSERT(m_container, return); - - QModelIndex mi = m_debuggerView->currentIndex(); - mi = mi.sibling(mi.row(), 0); - m_model->setCurrentIndex(mi); - - m_itemConfigWidget->loadItem(); - m_container->setVisible(m_model->m_currentDebugger.isValid()); - updateState(); -} - -void DebuggerOptionsPage::debuggerModelChanged() -{ - QTC_ASSERT(m_container, return); - - m_itemConfigWidget->loadItem(); - m_container->setVisible(m_model->m_currentDebugger.isValid()); - m_debuggerView->setCurrentIndex(m_model->currentIndex()); - updateState(); -} - -void DebuggerOptionsPage::updateState() -{ - if (!m_cloneButton) - return; - - bool canCopy = false; - bool canDelete = false; - - if (const DebuggerItem *item = DebuggerItemManager::findById(m_model->m_currentDebugger)) { - canCopy = item->isValid() && item->canClone(); - canDelete = !item->isAutoDetected(); - canDelete = true; // Do we want to remove auto-detected items? - } - m_cloneButton->setEnabled(canCopy); - m_delButton->setEnabled(canDelete); -} - } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggerkitconfigwidget.h b/src/plugins/debugger/debuggerkitconfigwidget.h index f2ab06695f5..e126f513f96 100644 --- a/src/plugins/debugger/debuggerkitconfigwidget.h +++ b/src/plugins/debugger/debuggerkitconfigwidget.h @@ -30,7 +30,7 @@ #ifndef DEBUGGER_DEBUGGERKITCONFIGWIDGET_H #define DEBUGGER_DEBUGGERKITCONFIGWIDGET_H -#include "debuggerkitinformation.h" +#include "debuggeritemmodel.h" #include #include @@ -52,52 +52,6 @@ QT_END_NAMESPACE namespace Debugger { namespace Internal { -class DebuggerItemConfigWidget; -class DebuggerKitConfigWidget; - -// ----------------------------------------------------------------------- -// DebuggerItemModel -//------------------------------------------------------------------------ -class DebuggerItemModel : public QStandardItemModel -{ - Q_OBJECT - -public: - DebuggerItemModel(QObject *parent); - - QModelIndex currentIndex() const; - QModelIndex lastIndex() const; - void setCurrentIndex(const QModelIndex &index); - QVariant currentDebugger() const { return m_currentDebugger; } - void addDebugger(const DebuggerItem &item); - void removeDebugger(const QVariant &id); - void updateDebugger(const QVariant &id); - -public slots: - void markCurrentDirty(); - -signals: - void debuggerAdded(const QVariant &id, const QString &display); - void debuggerUpdated(const QVariant &id, const QString &display); - void debuggerRemoved(const QVariant &id); - -private: - friend class Debugger::DebuggerKitInformation; - friend class DebuggerKitConfigWidget; - friend class DebuggerItemConfigWidget; - friend class DebuggerOptionsPage; - - QStandardItem *currentStandardItem() const; - QStandardItem *findStandardItemById(const QVariant &id) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - - QVariant m_currentDebugger; - - QStandardItem *m_autoRoot; - QStandardItem *m_manualRoot; - QStringList removed; -}; - // ----------------------------------------------------------------------- // DebuggerKitConfigWidget // ----------------------------------------------------------------------- @@ -121,8 +75,8 @@ public: private slots: void manageDebuggers(); void currentDebuggerChanged(int idx); - void onDebuggerAdded(const QVariant &id, const QString &displayName); - void onDebuggerUpdated(const QVariant &id, const QString &displayName); + void onDebuggerAdded(const QVariant &id); + void onDebuggerUpdated(const QVariant &id); void onDebuggerRemoved(const QVariant &id); private: @@ -135,44 +89,7 @@ private: QPushButton *m_manageButton; }; -// -------------------------------------------------------------------------- -// DebuggerOptionsPage -// -------------------------------------------------------------------------- - -class DebuggerOptionsPage : public Core::IOptionsPage -{ - Q_OBJECT - -public: - DebuggerOptionsPage(); - - QWidget *createPage(QWidget *parent); - void apply(); - void finish(); - bool matches(const QString &) const; - -private slots: - void debuggerSelectionChanged(); - void debuggerModelChanged(); - void updateState(); - void cloneDebugger(); - void addDebugger(); - void removeDebugger(); - -private: - QWidget *m_configWidget; - QString m_searchKeywords; - - DebuggerItemModel *m_model; - DebuggerItemConfigWidget *m_itemConfigWidget; - QTreeView *m_debuggerView; - Utils::DetailsWidget *m_container; - QPushButton *m_addButton; - QPushButton *m_cloneButton; - QPushButton *m_delButton; -}; - } // namespace Internal } // namespace Debugger -#endif // DEBUGGER_DEBUGGERKITINFORMATION_H +#endif // DEBUGGER_DEBUGGERKITCONFIGWIDGET_H diff --git a/src/plugins/debugger/debuggerkitinformation.cpp b/src/plugins/debugger/debuggerkitinformation.cpp index 30ca4f2c230..7ee98c619db 100644 --- a/src/plugins/debugger/debuggerkitinformation.cpp +++ b/src/plugins/debugger/debuggerkitinformation.cpp @@ -28,312 +28,305 @@ ****************************************************************************/ #include "debuggerkitinformation.h" + +#include "debuggeritemmanager.h" #include "debuggerkitconfigwidget.h" -#include +#include "projectexplorer/toolchain.h" +#include "projectexplorer/projectexplorerconstants.h" + #include +#include -#include +#include -using namespace Debugger::Internal; using namespace ProjectExplorer; using namespace Utils; -static const char DEBUGGER_INFORMATION_COMMAND[] = "Binary"; -static const char DEBUGGER_INFORMATION_DISPLAYNAME[] = "DisplayName"; -static const char DEBUGGER_INFORMATION_ID[] = "Id"; -static const char DEBUGGER_INFORMATION_ENGINETYPE[] = "EngineType"; -static const char DEBUGGER_INFORMATION_AUTODETECTED[] = "AutoDetected"; -static const char DEBUGGER_INFORMATION_ABIS[] = "Abis"; - namespace Debugger { // -------------------------------------------------------------------------- -// DebuggerItem +// DebuggerKitInformation // -------------------------------------------------------------------------- -DebuggerItem::DebuggerItem() +DebuggerKitInformation::DebuggerKitInformation() { - m_engineType = NoEngineType; - m_isAutoDetected = false; + setObjectName(QLatin1String("DebuggerKitInformation")); + setId(DebuggerKitInformation::id()); + setPriority(28000); } -void DebuggerItem::reinitializeFromFile() +QVariant DebuggerKitInformation::defaultValue(Kit *k) const { - QProcess proc; - proc.start(m_command.toString(), QStringList() << QLatin1String("--version")); - proc.waitForStarted(); - proc.waitForFinished(); - QByteArray ba = proc.readAll(); - if (ba.contains("gdb")) { - m_engineType = GdbEngineType; - const char needle[] = "This GDB was configured as \""; - // E.g. "--host=i686-pc-linux-gnu --target=arm-unknown-nto-qnx6.5.0". - // or "i686-linux-gnu" - int pos1 = ba.indexOf(needle); - if (pos1 != -1) { - pos1 += int(sizeof(needle)); - int pos2 = ba.indexOf('"', pos1 + 1); - QByteArray target = ba.mid(pos1, pos2 - pos1); - int pos3 = target.indexOf("--target="); - if (pos3 >= 0) - target = target.mid(pos3 + 9); - m_abis.append(Abi::abiFromTargetTriplet(QString::fromLatin1(target))); + ToolChain *tc = ToolChainKitInformation::toolChain(k); + QTC_ASSERT(tc, return QVariant()); + + const Abi toolChainAbi = tc->targetAbi(); + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) + foreach (const Abi targetAbi, item.abis()) + if (targetAbi.isCompatibleWith(toolChainAbi)) + return item.id(); + + return QVariant(); +} + +void DebuggerKitInformation::setup(Kit *k) +{ + // Get one of the available debugger matching the kit's toolchain. + const ToolChain *tc = ToolChainKitInformation::toolChain(k); + const Abi toolChainAbi = tc ? tc->targetAbi() : Abi::hostAbi(); + + // This can be anything (Id, binary path, "auto") + const QVariant rawId = k->value(DebuggerKitInformation::id()); + + enum { + NotDetected, DetectedAutomatically, DetectedByFile, DetectedById + } detection = NotDetected; + DebuggerEngineType autoEngine = NoEngineType; + FileName fileName; + + // With 3.0 we have: + // {75ecf347-f221-44c3-b613-ea1d29929cd4} + // Before we had: + // + // /data/dev/debugger/gdb-git/gdb/gdb + // 1 + // + // Or for force auto-detected CDB + // + // auto + // 4 + // + + if (rawId.isNull()) { + // Initial setup of a kit + detection = NotDetected; + } else if (rawId.type() == QVariant::String) { + detection = DetectedById; + } else { + QMap map = rawId.toMap(); + QString binary = map.value(QLatin1String("Binary")).toString(); + if (binary == QLatin1String("auto")) { + detection = DetectedAutomatically; + autoEngine = DebuggerEngineType(map.value(QLatin1String("EngineType")).toInt()); } else { - // Fallback. - m_abis = Abi::abisOfBinary(m_command); // FIXME: Wrong. + detection = DetectedByFile; + fileName = FileName::fromUserInput(binary); } + } + + const DebuggerItem *bestItem = 0; + DebuggerItem::MatchLevel bestLevel = DebuggerItem::DoesNotMatch; + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { + const DebuggerItem *goodItem = 0; + if (detection == DetectedById && item.id() == rawId) + goodItem = &item; + if (detection == DetectedByFile && item.command() == fileName) + goodItem = &item; + if (detection == DetectedAutomatically && item.engineType() == autoEngine) + goodItem = &item; + + if (goodItem) { + DebuggerItem::MatchLevel level = goodItem->matchTarget(toolChainAbi); + if (level > bestLevel) { + bestLevel = level; + bestItem = goodItem; + } + } + } + + // If we have an existing debugger with matching id _and_ + // matching target ABI we are fine. + if (bestItem) { + k->setValue(DebuggerKitInformation::id(), bestItem->id()); return; } - if (ba.contains("lldb") || ba.startsWith("LLDB")) { - m_engineType = LldbEngineType; - m_abis = Abi::abisOfBinary(m_command); + + // We didn't find an existing debugger that matched by whatever + // data we found in the kit (i.e. no id, filename, "auto") + // (or what we found did not match ABI-wise) + // Let's try to pick one with matching ABI. + QVariant bestId; + bestLevel = DebuggerItem::DoesNotMatch; + foreach (const DebuggerItem &item, DebuggerItemManager::debuggers()) { + DebuggerItem::MatchLevel level = item.matchTarget(toolChainAbi); + if (level > bestLevel) { + bestLevel = level; + bestId = item.id(); + } + } + + k->setValue(DebuggerKitInformation::id(), bestId); +} + + +// This handles the upgrade path from 2.8 to 3.0 +void DebuggerKitInformation::fix(Kit *k) +{ + // This can be Id, binary path, but not "auto" anymore. + const QVariant rawId = k->value(DebuggerKitInformation::id()); + + if (rawId.isNull()) // No debugger set, that is fine. + return; + + if (rawId.type() == QVariant::String) { + if (!DebuggerItemManager::findById(rawId)) { + qWarning("Unknown debugger id %s in kit %s", + qPrintable(rawId.toString()), qPrintable(k->displayName())); + k->setValue(DebuggerKitInformation::id(), QVariant()); + } + return; // All fine (now). + } + + QMap map = rawId.toMap(); + QString binary = map.value(QLatin1String("Binary")).toString(); + if (binary == QLatin1String("auto")) { + // This should not happen as "auto" is handled by setup() already. + QTC_CHECK(false); + k->setValue(DebuggerKitInformation::id(), QVariant()); return; } - if (ba.startsWith("Python")) { - m_engineType = PdbEngineType; + + FileName fileName = FileName::fromUserInput(binary); + const DebuggerItem *item = DebuggerItemManager::findByCommand(fileName); + if (!item) { + qWarning("Debugger command %s invalid in kit %s", + qPrintable(binary), qPrintable(k->displayName())); + k->setValue(DebuggerKitInformation::id(), QVariant()); return; } - m_engineType = NoEngineType; + + k->setValue(DebuggerKitInformation::id(), item->id()); } -QString DebuggerItem::engineTypeName() const +// Check the configuration errors and return a flag mask. Provide a quick check and +// a verbose one with a list of errors. + +enum DebuggerConfigurationErrors { + NoDebugger = 0x1, + DebuggerNotFound = 0x2, + DebuggerNotExecutable = 0x4, + DebuggerNeedsAbsolutePath = 0x8 +}; + +static unsigned debuggerConfigurationErrors(const Kit *k) { - switch (m_engineType) { - case Debugger::NoEngineType: - return DebuggerOptionsPage::tr("Not recognized"); - case Debugger::GdbEngineType: - return QLatin1String("GDB"); - case Debugger::CdbEngineType: - return QLatin1String("CDB"); - case Debugger::LldbEngineType: - return QLatin1String("LLDB"); - default: - return QString(); + QTC_ASSERT(k, return NoDebugger); + + const DebuggerItem *item = DebuggerKitInformation::debugger(k); + if (!item) + return NoDebugger; + + if (item->command().isEmpty()) + return NoDebugger; + + unsigned result = 0; + const QFileInfo fi = item->command().toFileInfo(); + if (!fi.exists() || fi.isDir()) + result |= DebuggerNotFound; + else if (!fi.isExecutable()) + result |= DebuggerNotExecutable; + + if (!fi.exists() || fi.isDir()) { + if (item->engineType() == NoEngineType) + return NoDebugger; + + // We need an absolute path to be able to locate Python on Windows. + if (item->engineType() == GdbEngineType) + if (const ToolChain *tc = ToolChainKitInformation::toolChain(k)) + if (tc->targetAbi().os() == Abi::WindowsOS && !fi.isAbsolute()) + result |= DebuggerNeedsAbsolutePath; } + return result; } -QStringList DebuggerItem::abiNames() const +const DebuggerItem *DebuggerKitInformation::debugger(const Kit *kit) { - QStringList list; - foreach (const Abi &abi, m_abis) - list.append(abi.toString()); - return list; + QTC_ASSERT(kit, return 0); + const QVariant id = kit->value(DebuggerKitInformation::id()); + return DebuggerItemManager::findById(id); } -QVariantMap DebuggerItem::toMap() const +bool DebuggerKitInformation::isValidDebugger(const Kit *k) { - QVariantMap data; - data.insert(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME), m_displayName); - data.insert(QLatin1String(DEBUGGER_INFORMATION_ID), m_id); - data.insert(QLatin1String(DEBUGGER_INFORMATION_COMMAND), m_command.toUserOutput()); - data.insert(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE), int(m_engineType)); - data.insert(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED), m_isAutoDetected); - data.insert(QLatin1String(DEBUGGER_INFORMATION_ABIS), abiNames()); - return data; + return debuggerConfigurationErrors(k) == 0; } -void DebuggerItem::fromMap(const QVariantMap &data) +QList DebuggerKitInformation::validateDebugger(const Kit *k) { - m_command = FileName::fromUserInput(data.value(QLatin1String(DEBUGGER_INFORMATION_COMMAND)).toString()); - m_id = data.value(QLatin1String(DEBUGGER_INFORMATION_ID)).toString(); - m_displayName = data.value(QLatin1String(DEBUGGER_INFORMATION_DISPLAYNAME)).toString(); - m_isAutoDetected = data.value(QLatin1String(DEBUGGER_INFORMATION_AUTODETECTED)).toBool(); - m_engineType = DebuggerEngineType(data.value(QLatin1String(DEBUGGER_INFORMATION_ENGINETYPE)).toInt()); + QList result; - m_abis.clear(); - foreach (const QString &a, data.value(QLatin1String(DEBUGGER_INFORMATION_ABIS)).toStringList()) { - Abi abi(a); - if (abi.isValid()) - m_abis.append(abi); + const unsigned errors = debuggerConfigurationErrors(k); + if (!errors) + return result; + + QString path; + if (const DebuggerItem *item = debugger(k)) + path = item->command().toUserOutput(); + + const Core::Id id = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM; + if (errors & NoDebugger) + result << Task(Task::Warning, tr("No debugger set up."), FileName(), -1, id); + + if (errors & DebuggerNotFound) + result << Task(Task::Error, tr("Debugger '%1' not found.").arg(path), + FileName(), -1, id); + if (errors & DebuggerNotExecutable) + result << Task(Task::Error, tr("Debugger '%1' not executable.").arg(path), FileName(), -1, id); + + if (errors & DebuggerNeedsAbsolutePath) { + const QString message = + tr("The debugger location must be given as an " + "absolute path (%1).").arg(path); + result << Task(Task::Error, message, FileName(), -1, id); } + return result; } -void DebuggerItem::setId(const QVariant &id) +KitConfigWidget *DebuggerKitInformation::createConfigWidget(Kit *k) const { - m_id = id; + return new Internal::DebuggerKitConfigWidget(k, this); } -void DebuggerItem::setDisplayName(const QString &displayName) +KitInformation::ItemList DebuggerKitInformation::toUserOutput(const Kit *k) const { - m_displayName = displayName; + return ItemList() << qMakePair(tr("Debugger"), displayString(k)); } -void DebuggerItem::setEngineType(const DebuggerEngineType &engineType) +FileName DebuggerKitInformation::debuggerCommand(const ProjectExplorer::Kit *k) { - m_engineType = engineType; + const DebuggerItem *item = debugger(k); + QTC_ASSERT(item, return FileName()); + return item->command(); } -void DebuggerItem::setCommand(const Utils::FileName &command) +DebuggerEngineType DebuggerKitInformation::engineType(const ProjectExplorer::Kit *k) { - m_command = command; + const DebuggerItem *item = debugger(k); + QTC_ASSERT(item, return NoEngineType); + return item->engineType(); } -void DebuggerItem::setAutoDetected(bool isAutoDetected) +QString DebuggerKitInformation::displayString(const Kit *k) { - m_isAutoDetected = isAutoDetected; + const DebuggerItem *item = debugger(k); + if (!item) + return tr("No Debugger"); + QString binary = item->command().toUserOutput(); + QString name = tr("%1 Engine").arg(item->engineTypeName()); + return binary.isEmpty() ? tr("%1 ").arg(name) : tr("%1 using \"%2\"").arg(name, binary); } -void DebuggerItem::setAbis(const QList &abis) +void DebuggerKitInformation::setDebugger(Kit *k, const QVariant &id) { - m_abis = abis; + // Only register reasonably complete debuggers. + QTC_ASSERT(DebuggerItemManager::findById(id), return); + k->setValue(DebuggerKitInformation::id(), id); } -void DebuggerItem::setAbi(const Abi &abi) +Core::Id DebuggerKitInformation::id() { - m_abis.clear(); - m_abis.append(abi); + return "Debugger.Information"; } -static DebuggerItem::MatchLevel matchSingle(const Abi &debuggerAbi, const Abi &targetAbi) -{ - if (debuggerAbi.architecture() != Abi::UnknownArchitecture - && debuggerAbi.architecture() != targetAbi.architecture()) - return DebuggerItem::DoesNotMatch; - - if (debuggerAbi.os() != Abi::UnknownOS - && debuggerAbi.os() != targetAbi.os()) - return DebuggerItem::DoesNotMatch; - - if (debuggerAbi.binaryFormat() != Abi::UnknownFormat - && debuggerAbi.binaryFormat() != targetAbi.binaryFormat()) - return DebuggerItem::DoesNotMatch; - - if (debuggerAbi.os() == Abi::WindowsOS) { - if (debuggerAbi.osFlavor() == Abi::WindowsMSysFlavor && targetAbi.osFlavor() != Abi::WindowsMSysFlavor) - return DebuggerItem::DoesNotMatch; - if (debuggerAbi.osFlavor() != Abi::WindowsMSysFlavor && targetAbi.osFlavor() == Abi::WindowsMSysFlavor) - return DebuggerItem::DoesNotMatch; - } - - if (debuggerAbi.wordWidth() == 64 && targetAbi.wordWidth() == 32) - return DebuggerItem::MatchesSomewhat; - if (debuggerAbi.wordWidth() != 0 && debuggerAbi.wordWidth() != targetAbi.wordWidth()) - return DebuggerItem::DoesNotMatch; - - return DebuggerItem::MatchesPerfectly; -} - -DebuggerItem::MatchLevel DebuggerItem::matchTarget(const Abi &targetAbi) const -{ - MatchLevel bestMatch = DoesNotMatch; - foreach (const Abi &debuggerAbi, m_abis) { - MatchLevel currentMatch = matchSingle(debuggerAbi, targetAbi); - if (currentMatch > bestMatch) - bestMatch = currentMatch; - } - return bestMatch; -} - -bool Debugger::DebuggerItem::isValid() const -{ - return m_engineType != NoEngineType; -} - -} // namespace Debugger; - -#ifdef WITH_TESTS - -# include -# include "debuggerplugin.h" - -void Debugger::DebuggerPlugin::testDebuggerMatching_data() -{ - QTest::addColumn("debugger"); - QTest::addColumn("target"); - QTest::addColumn("result"); - - QTest::newRow("Invalid data") - << QStringList() - << QString() - << int(DebuggerItem::DoesNotMatch); - QTest::newRow("Invalid debugger") - << QStringList() - << QString::fromLatin1("x86-linux-generic-elf-32bit") - << int(DebuggerItem::DoesNotMatch); - QTest::newRow("Invalid target") - << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) - << QString() - << int(DebuggerItem::DoesNotMatch); - - QTest::newRow("Fuzzy match 1") - << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit")) - << QString::fromLatin1("x86-linux-generic-elf-32bit") - << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior? - QTest::newRow("Fuzzy match 2") - << (QStringList() << QLatin1String("unknown-unknown-unknown-unknown-0bit")) - << QString::fromLatin1("arm-windows-msys-pe-64bit") - << int(DebuggerItem::MatchesPerfectly); // Is this the expected behavior? - - QTest::newRow("Architecture mismatch") - << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) - << QString::fromLatin1("arm-linux-generic-elf-32bit") - << int(DebuggerItem::DoesNotMatch); - QTest::newRow("OS mismatch") - << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) - << QString::fromLatin1("x86-macosx-generic-elf-32bit") - << int(DebuggerItem::DoesNotMatch); - QTest::newRow("Format mismatch") - << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) - << QString::fromLatin1("x86-linux-generic-pe-32bit") - << int(DebuggerItem::DoesNotMatch); - - QTest::newRow("Linux perfect match") - << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit")) - << QString::fromLatin1("x86-linux-generic-elf-32bit") - << int(DebuggerItem::MatchesPerfectly); - QTest::newRow("Linux match") - << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")) - << QString::fromLatin1("x86-linux-generic-elf-32bit") - << int(DebuggerItem::MatchesSomewhat); - - QTest::newRow("Windows perfect match 1") - << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) - << QString::fromLatin1("x86-windows-msvc2013-pe-64bit") - << int(DebuggerItem::MatchesPerfectly); - QTest::newRow("Windows perfect match 2") - << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) - << QString::fromLatin1("x86-windows-msvc2012-pe-64bit") - << int(DebuggerItem::MatchesPerfectly); - QTest::newRow("Windows match 1") - << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) - << QString::fromLatin1("x86-windows-msvc2013-pe-32bit") - << int(DebuggerItem::MatchesSomewhat); - QTest::newRow("Windows match 2") - << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-64bit")) - << QString::fromLatin1("x86-windows-msvc2012-pe-32bit") - << int(DebuggerItem::MatchesSomewhat); - QTest::newRow("Windows mismatch on word size") - << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit")) - << QString::fromLatin1("x86-windows-msvc2013-pe-64bit") - << int(DebuggerItem::DoesNotMatch); - QTest::newRow("Windows mismatch on osflavor 1") - << (QStringList() << QLatin1String("x86-windows-msvc2013-pe-32bit")) - << QString::fromLatin1("x86-windows-msys-pe-64bit") - << int(DebuggerItem::DoesNotMatch); - QTest::newRow("Windows mismatch on osflavor 2") - << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit")) - << QString::fromLatin1("x86-windows-msvc2010-pe-64bit") - << int(DebuggerItem::DoesNotMatch); -} - -void Debugger::DebuggerPlugin::testDebuggerMatching() -{ - QFETCH(QStringList, debugger); - QFETCH(QString, target); - QFETCH(int, result); - - DebuggerItem::MatchLevel expectedLevel = static_cast(result); - - QList debuggerAbis; - foreach (const QString &abi, debugger) - debuggerAbis << Abi(abi); - - DebuggerItem item; - item.setAbis(debuggerAbis); - - DebuggerItem::MatchLevel level = item.matchTarget(Abi(target)); - - QCOMPARE(expectedLevel, level); -} -#endif +} // namespace Debugger diff --git a/src/plugins/debugger/debuggerkitinformation.h b/src/plugins/debugger/debuggerkitinformation.h index dfdf6350a4e..3e03e19d2e7 100644 --- a/src/plugins/debugger/debuggerkitinformation.h +++ b/src/plugins/debugger/debuggerkitinformation.h @@ -32,6 +32,7 @@ #include "debugger_global.h" #include "debuggerconstants.h" +#include "debuggeritem.h" #include #include @@ -40,106 +41,6 @@ namespace Debugger { -namespace Internal { class DebuggerItemModel; } - -// ----------------------------------------------------------------------- -// DebuggerItem -// ----------------------------------------------------------------------- - -class DEBUGGER_EXPORT DebuggerItem -{ -public: - DebuggerItem(); - - bool canClone() const { return true; } - bool isValid() const; - QString engineTypeName() const; - - QVariantMap toMap() const; - void fromMap(const QVariantMap &data); - void reinitializeFromFile(); - - QVariant id() const { return m_id; } - - QString displayName() const { return m_displayName; } - void setDisplayName(const QString &displayName); - - DebuggerEngineType engineType() const { return m_engineType; } - void setEngineType(const DebuggerEngineType &engineType); - - Utils::FileName command() const { return m_command; } - void setCommand(const Utils::FileName &command); - - bool isAutoDetected() const { return m_isAutoDetected; } - void setAutoDetected(bool isAutoDetected); - - QList abis() const { return m_abis; } - void setAbis(const QList &abis); - void setAbi(const ProjectExplorer::Abi &abi); - - enum MatchLevel { DoesNotMatch, MatchesSomewhat, MatchesPerfectly }; - MatchLevel matchTarget(const ProjectExplorer::Abi &targetAbi) const; - - QStringList abiNames() const; - -private: - friend class Debugger::Internal::DebuggerItemModel; - friend class DebuggerItemManager; - void setId(const QVariant &id); - - QVariant m_id; - QString m_displayName; - DebuggerEngineType m_engineType; - Utils::FileName m_command; - bool m_isAutoDetected; - QList m_abis; -}; - -// ----------------------------------------------------------------------- -// DebuggerItemManager -// ----------------------------------------------------------------------- - -class DEBUGGER_EXPORT DebuggerItemManager : public QObject -{ - Q_OBJECT - -public: - static QObject *instance(); - ~DebuggerItemManager(); - - static QList debuggers(); - static Debugger::Internal::DebuggerItemModel *model(); - - static QVariant registerDebugger(const DebuggerItem &item); - static void deregisterDebugger(const DebuggerItem &item); - - static const DebuggerItem *findByCommand(const Utils::FileName &command); - static const DebuggerItem *findById(const QVariant &id); - - static void restoreDebuggers(); - static QString uniqueDisplayName(const QString &base); - static void setItemData(const QVariant &id, const QString& displayName, const Utils::FileName &fileName); - - static void removeDebugger(const QVariant &id); - static QVariant addDebugger(const DebuggerItem &item); - -public slots: - void saveDebuggers(); - -private: - explicit DebuggerItemManager(QObject *parent = 0); - static void autoDetectGdbOrLldbDebuggers(); - static void autoDetectCdbDebuggers(); - static void readLegacyDebuggers(); - - static Utils::PersistentSettingsWriter *m_writer; - static QList m_debuggers; - static Debugger::Internal::DebuggerItemModel *m_model; - - friend class Internal::DebuggerItemModel; - friend class DebuggerPlugin; // Enable constrcutor for DebuggerPlugin -}; - class DEBUGGER_EXPORT DebuggerKitInformation : public ProjectExplorer::KitInformation { Q_OBJECT diff --git a/src/plugins/debugger/debuggeroptionspage.cpp b/src/plugins/debugger/debuggeroptionspage.cpp new file mode 100644 index 00000000000..884edf439fd --- /dev/null +++ b/src/plugins/debugger/debuggeroptionspage.cpp @@ -0,0 +1,337 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "debuggeroptionspage.h" + +#include "debuggeritemmanager.h" +#include "debuggeritemmodel.h" + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Utils; + +namespace Debugger { +namespace Internal { + +static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging"; + +// ----------------------------------------------------------------------- +// DebuggerItemConfigWidget +// ----------------------------------------------------------------------- + +class DebuggerItemConfigWidget : public QWidget +{ + Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::DebuggerItemConfigWidget) + +public: + explicit DebuggerItemConfigWidget(DebuggerItemModel *model); + void setItem(const DebuggerItem &item); + void apply(); + +private: + QLineEdit *m_displayNameLineEdit; + QLabel *m_cdbLabel; + PathChooser *m_binaryChooser; + QLineEdit *m_abis; + DebuggerItemModel *m_model; +}; + +DebuggerItemConfigWidget::DebuggerItemConfigWidget(DebuggerItemModel *model) : + m_model(model) +{ + QTC_CHECK(model); + + m_displayNameLineEdit = new QLineEdit(this); + + m_binaryChooser = new PathChooser(this); + m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand); + m_binaryChooser->setMinimumWidth(400); + m_binaryChooser->setHistoryCompleter(QLatin1String("DebuggerPaths")); + + m_cdbLabel = new QLabel(this); + m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + m_cdbLabel->setOpenExternalLinks(true); + + m_abis = new QLineEdit(this); + m_abis->setEnabled(false); + + QFormLayout *formLayout = new QFormLayout(this); + formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); +// formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox); + formLayout->addRow(m_cdbLabel); + formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); + formLayout->addRow(new QLabel(tr("ABIs:")), m_abis); +} + +void DebuggerItemConfigWidget::setItem(const DebuggerItem &item) +{ + m_displayNameLineEdit->setEnabled(!item.isAutoDetected()); + m_displayNameLineEdit->setText(item.displayName()); + + m_binaryChooser->setEnabled(!item.isAutoDetected()); + m_binaryChooser->setFileName(item.command()); + + QString text; + QString versionCommand; + if (item.engineType() == CdbEngineType) { +#ifdef Q_OS_WIN + const bool is64bit = winIs64BitSystem(); +#else + const bool is64bit = false; +#endif + const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version"); + //: Label text for path configuration. %2 is "x-bit version". + text = tr("

Specify the path to the " + "Windows Console Debugger executable" + " (%2) here.

"""). + arg(QLatin1String(debuggingToolsWikiLinkC), versionString); + versionCommand = QLatin1String("-version"); + } else { + versionCommand = QLatin1String("--version"); + } + + m_cdbLabel->setText(text); + m_cdbLabel->setVisible(!text.isEmpty()); + m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand)); + + m_abis->setText(item.abiNames().join(QLatin1String(", "))); +} + +void DebuggerItemConfigWidget::apply() +{ + DebuggerItem item = m_model->currentDebugger(); + QTC_ASSERT(item.isValid(), return); + + item.setDisplayName(m_displayNameLineEdit->text()); + item.setCommand(m_binaryChooser->fileName()); + item.reinitializeFromFile(); + m_model->updateDebugger(item); +} + +// -------------------------------------------------------------------------- +// DebuggerOptionsPage +// -------------------------------------------------------------------------- + +DebuggerOptionsPage::DebuggerOptionsPage() +{ + m_model = 0; + m_debuggerView = 0; + m_container = 0; + m_addButton = 0; + m_cloneButton = 0; + m_delButton = 0; + + setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID); + setDisplayName(tr("Debuggers")); + setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY); + setDisplayCategory(QCoreApplication::translate("ProjectExplorer", + ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY)); + setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON)); +} + +QWidget *DebuggerOptionsPage::createPage(QWidget *parent) +{ + m_configWidget = new QWidget(parent); + + m_addButton = new QPushButton(tr("Add"), m_configWidget); + m_cloneButton = new QPushButton(tr("Clone"), m_configWidget); + m_delButton = new QPushButton(tr("Remove"), m_configWidget); + + m_container = new DetailsWidget(m_configWidget); + m_container->setState(DetailsWidget::NoSummary); + m_container->setVisible(false); + + m_model = new DebuggerItemModel(parent); + + m_debuggerView = new QTreeView(m_configWidget); + m_debuggerView->setModel(m_model); + m_debuggerView->setUniformRowHeights(true); + m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection); + m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_debuggerView->expandAll(); + + QHeaderView *header = m_debuggerView->header(); + header->setStretchLastSection(false); + header->setResizeMode(0, QHeaderView::ResizeToContents); + header->setResizeMode(1, QHeaderView::ResizeToContents); + header->setResizeMode(2, QHeaderView::Stretch); + + QVBoxLayout *buttonLayout = new QVBoxLayout(); + buttonLayout->setSpacing(6); + buttonLayout->setContentsMargins(0, 0, 0, 0); + buttonLayout->addWidget(m_addButton); + buttonLayout->addWidget(m_cloneButton); + buttonLayout->addWidget(m_delButton); + buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + QVBoxLayout *verticalLayout = new QVBoxLayout(); + verticalLayout->addWidget(m_debuggerView); + verticalLayout->addWidget(m_container); + + QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget); + horizontalLayout->addLayout(verticalLayout); + horizontalLayout->addLayout(buttonLayout); + + connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(debuggerSelectionChanged())); + + connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection); + connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection); + connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection); + + m_searchKeywords = tr("Debuggers"); + + m_itemConfigWidget = new DebuggerItemConfigWidget(m_model); + m_container->setWidget(m_itemConfigWidget); + + updateState(); + + return m_configWidget; +} + +void DebuggerOptionsPage::apply() +{ + m_itemConfigWidget->apply(); + m_model->apply(); +} + +void DebuggerOptionsPage::cloneDebugger() +{ + DebuggerItem item = m_model->currentDebugger(); + if (!item.isValid()) + return; + + DebuggerItem newItem; + newItem.setCommand(item.command()); + newItem.setEngineType(item.engineType()); + newItem.setAbis(item.abis()); + newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item.displayName()))); + newItem.setAutoDetected(false); + m_model->addDebugger(newItem); + m_debuggerView->setCurrentIndex(m_model->lastIndex()); +} + +void DebuggerOptionsPage::addDebugger() +{ + DebuggerItem item; + item.setEngineType(NoEngineType); + item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger"))); + item.setAutoDetected(false); + m_model->addDebugger(item); + m_debuggerView->setCurrentIndex(m_model->lastIndex()); +} + +void DebuggerOptionsPage::removeDebugger() +{ + QVariant id = m_model->currentDebuggerId(); + m_model->removeDebugger(id); + m_debuggerView->setCurrentIndex(m_model->lastIndex()); +} + +void DebuggerOptionsPage::finish() +{ + // Deleted by settingsdialog. + m_configWidget = 0; + + // Children of m_configWidget. + m_container = 0; + m_debuggerView = 0; + m_addButton = 0; + m_cloneButton = 0; + m_delButton = 0; +} + +bool DebuggerOptionsPage::matches(const QString &s) const +{ + return m_searchKeywords.contains(s, Qt::CaseInsensitive); +} + +void DebuggerOptionsPage::debuggerSelectionChanged() +{ + QTC_ASSERT(m_container, return); + + QModelIndex mi = m_debuggerView->currentIndex(); + mi = mi.sibling(mi.row(), 0); + m_model->setCurrentIndex(mi); + + DebuggerItem item = m_model->currentDebugger(); + + m_itemConfigWidget->setItem(item); + m_container->setVisible(item.isValid()); + updateState(); +} + +void DebuggerOptionsPage::debuggerModelChanged() +{ + QTC_ASSERT(m_container, return); + + QVariant id = m_model->currentDebuggerId(); + const DebuggerItem *item = DebuggerItemManager::findById(id); + if (!item) + return; + + m_itemConfigWidget->setItem(*item); + m_container->setVisible(m_model->currentDebuggerId().isValid()); + m_debuggerView->setCurrentIndex(m_model->currentIndex()); + updateState(); +} + +void DebuggerOptionsPage::updateState() +{ + if (!m_cloneButton) + return; + + bool canCopy = false; + bool canDelete = false; + + DebuggerItem item = m_model->currentDebugger(); + + canCopy = item.isValid() && item.canClone(); + canDelete = !item.isAutoDetected(); + + m_cloneButton->setEnabled(canCopy); + m_delButton->setEnabled(canDelete); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/debuggeroptionspage.h b/src/plugins/debugger/debuggeroptionspage.h new file mode 100644 index 00000000000..fd1782f4b47 --- /dev/null +++ b/src/plugins/debugger/debuggeroptionspage.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_DEBUGGEROPTIONSPAGE_H +#define DEBUGGER_DEBUGGEROPTIONSPAGE_H + +#include + +QT_BEGIN_NAMESPACE +class QPushButton; +class QTreeView; +class QWidget; +QT_END_NAMESPACE + +namespace Utils { class DetailsWidget; } + +namespace Debugger { +namespace Internal { + +class DebuggerItemModel; +class DebuggerItemConfigWidget; +class DebuggerKitConfigWidget; + +// -------------------------------------------------------------------------- +// DebuggerOptionsPage +// -------------------------------------------------------------------------- + +class DebuggerOptionsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + DebuggerOptionsPage(); + + QWidget *createPage(QWidget *parent); + void apply(); + void finish(); + bool matches(const QString &) const; + +private slots: + void debuggerSelectionChanged(); + void debuggerModelChanged(); + void updateState(); + void cloneDebugger(); + void addDebugger(); + void removeDebugger(); + +private: + QWidget *m_configWidget; + QString m_searchKeywords; + + DebuggerItemModel *m_model; + DebuggerItemConfigWidget *m_itemConfigWidget; + QTreeView *m_debuggerView; + Utils::DetailsWidget *m_container; + QPushButton *m_addButton; + QPushButton *m_cloneButton; + QPushButton *m_delButton; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_DEBUGGEROPTIONSPAGE_H diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index a01bdc9b636..67953afcfca 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -36,11 +36,13 @@ #include "debuggerkitconfigwidget.h" #include "debuggerdialogs.h" #include "debuggerengine.h" +#include "debuggeritemmanager.h" #include "debuggermainwindow.h" #include "debuggerrunner.h" #include "debuggerrunconfigurationaspect.h" #include "debuggerruncontrolfactory.h" #include "debuggerstringutils.h" +#include "debuggeroptionspage.h" #include "debuggerkitinformation.h" #include "memoryagent.h" #include "breakhandler.h" diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index a7d33fdb5ec..59c2158dcff 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -43,7 +43,6 @@ #ifdef Q_OS_WIN # include "shared/peutils.h" -# include #endif #include // For LocalApplication* @@ -55,6 +54,7 @@ #include #include +#include #include #include #include @@ -344,12 +344,9 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu if (!fillParameters(&sp, kit, errorMessage)) return sp; sp.environment = environment->environment(); - sp.workingDirectory = rc->workingDirectory(); -#if defined(Q_OS_WIN) - // Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...) - sp.workingDirectory = normalizePathName(sp.workingDirectory); -#endif + // Normalize to work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch'...) + sp.workingDirectory = FileUtils::normalizePathName(rc->workingDirectory()); sp.executable = rc->executable(); if (sp.executable.isEmpty()) @@ -385,7 +382,7 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu || server.listen(QHostAddress::LocalHostIPv6); if (!canListen) { if (errorMessage) - *errorMessage = DebuggerPlugin::tr("Not enough free ports for QML debugging. "); + *errorMessage = DebuggerPlugin::tr("Not enough free ports for QML debugging.") + QLatin1Char(' '); return sp; } sp.qmlServerAddress = server.serverAddress().toString(); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 7e8febf779c..9341d1d74e2 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -277,7 +277,7 @@ QString GdbEngine::errorMessage(QProcess::ProcessError error) return tr("The gdb process failed to start. Either the " "invoked program \"%1\" is missing, or you may have insufficient " "permissions to invoke the program.\n%2") - .arg(m_gdb, gdbProc()->errorString()); + .arg(m_gdb, m_gdbProc->errorString()); case QProcess::Crashed: if (targetState() == DebuggerFinished) return tr("The gdb process crashed some time after starting " @@ -296,15 +296,10 @@ QString GdbEngine::errorMessage(QProcess::ProcessError error) return tr("An error occurred when attempting to read from " "the gdb process. For example, the process may not be running."); default: - return tr("An unknown error in the gdb process occurred. "); + return tr("An unknown error in the gdb process occurred."); } } -GdbProcess *GdbEngine::gdbProc() const -{ - return m_gdbProc; -} - #if 0 static void dump(const char *first, const char *middle, const QString & to) { @@ -338,7 +333,7 @@ static inline QString msgWinException(const QByteArray &data, unsigned *exCodeIn const quint64 address = data.mid(addressPos).trimmed().toULongLong(0, 0); QString rc; QTextStream str(&rc); - str << GdbEngine::tr("An exception was triggered: "); + str << GdbEngine::tr("An exception was triggered:") << ' '; formatWindowsException(exCode, address, 0, 0, 0, str); str << '.'; return rc; @@ -794,7 +789,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) void GdbEngine::readGdbStandardError() { - QByteArray err = gdbProc()->readAllStandardError(); + QByteArray err = m_gdbProc->readAllStandardError(); showMessage(_("UNEXPECTED GDB STDERR: " + err)); if (err == "Undefined command: \"bb\". Try \"help\".\n") return; @@ -810,7 +805,7 @@ void GdbEngine::readGdbStandardOutput() int newstart = 0; int scan = m_inbuffer.size(); - QByteArray out = gdbProc()->readAllStandardOutput(); + QByteArray out = m_gdbProc->readAllStandardOutput(); m_inbuffer.append(out); // This can trigger when a dialog starts a nested event loop. @@ -974,7 +969,7 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0) return; } - QTC_ASSERT(gdbProc()->state() == QProcess::Running, return); + QTC_ASSERT(m_gdbProc->state() == QProcess::Running, return); const int token = ++currentToken(); @@ -1055,7 +1050,7 @@ void GdbEngine::commandTimeout() if (mb->exec() == QMessageBox::Ok) { showMessage(_("KILLING DEBUGGER AS REQUESTED BY USER")); // This is an undefined state, so we just pull the emergency brake. - gdbProc()->kill(); + m_gdbProc->kill(); } else { showMessage(_("CONTINUE DEBUGGER AS REQUESTED BY USER")); } @@ -2044,9 +2039,9 @@ void GdbEngine::notifyAdapterShutdownOk() { QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state()); showMessage(_("INITIATE GDBENGINE SHUTDOWN IN STATE %1, PROC: %2") - .arg(lastGoodState()).arg(gdbProc()->state())); + .arg(lastGoodState()).arg(m_gdbProc->state())); m_commandsDoneCallback = 0; - switch (gdbProc()->state()) { + switch (m_gdbProc->state()) { case QProcess::Running: postCommand("-gdb-exit", GdbEngine::ExitRequest, CB(handleGdbExit)); break; @@ -2056,7 +2051,7 @@ void GdbEngine::notifyAdapterShutdownOk() break; case QProcess::Starting: showMessage(_("GDB NOT REALLY RUNNING; KILLING IT")); - gdbProc()->kill(); + m_gdbProc->kill(); notifyEngineShutdownFailed(); break; } @@ -2073,7 +2068,7 @@ void GdbEngine::handleGdbExit(const GdbResponse &response) QString::fromLocal8Bit(response.data["msg"].data())); qDebug() << (_("GDB WON'T EXIT (%1); KILLING IT").arg(msg)); showMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg)); - gdbProc()->kill(); + m_gdbProc->kill(); } } @@ -4758,7 +4753,7 @@ void GdbEngine::startGdb(const QStringList &args) foreach (int test, m_testCases) showMessage(_("ENABLING TEST CASE: " + QByteArray::number(test))); - gdbProc()->disconnect(); // From any previous runs + m_gdbProc->disconnect(); // From any previous runs const DebuggerStartParameters &sp = startParameters(); m_gdb = gdbBinary(sp); @@ -4783,19 +4778,19 @@ void GdbEngine::startGdb(const QStringList &args) } gdbArgs += args; - connect(gdbProc(), SIGNAL(error(QProcess::ProcessError)), + connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)), SLOT(handleGdbError(QProcess::ProcessError))); - connect(gdbProc(), SIGNAL(finished(int,QProcess::ExitStatus)), + connect(m_gdbProc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(handleGdbFinished(int,QProcess::ExitStatus))); - connect(gdbProc(), SIGNAL(readyReadStandardOutput()), + connect(m_gdbProc, SIGNAL(readyReadStandardOutput()), SLOT(readGdbStandardOutput())); - connect(gdbProc(), SIGNAL(readyReadStandardError()), + connect(m_gdbProc, SIGNAL(readyReadStandardError()), SLOT(readGdbStandardError())); showMessage(_("STARTING ") + m_gdb + _(" ") + gdbArgs.join(_(" "))); - gdbProc()->start(m_gdb, gdbArgs); + m_gdbProc->start(m_gdb, gdbArgs); - if (!gdbProc()->waitForStarted()) { + if (!m_gdbProc->waitForStarted()) { handleGdbStartFailed(); const QString msg = errorMessage(QProcess::FailedToStart); handleAdapterStartFailed(msg); @@ -5009,7 +5004,7 @@ void GdbEngine::handleGdbError(QProcess::ProcessError error) case QProcess::WriteError: case QProcess::Timedout: default: - //gdbProc()->kill(); + //m_gdbProc->kill(); //notifyEngineIll(); showMessageBox(QMessageBox::Critical, tr("GDB I/O Error"), msg); break; @@ -5050,8 +5045,8 @@ void GdbEngine::abortDebugger() if (targetState() == DebuggerFinished) { // We already tried. Try harder. showMessage(_("ABORTING DEBUGGER. SECOND TIME.")); - QTC_ASSERT(gdbProc(), return); - gdbProc()->kill(); + QTC_ASSERT(m_gdbProc, return); + m_gdbProc->kill(); } else { // Be friendly the first time. This will change targetState(). showMessage(_("ABORTING DEBUGGER. FIRST TIME.")); @@ -5215,7 +5210,7 @@ void GdbEngine::handleBreakOnQFatal(const GdbResponse &response) void GdbEngine::notifyInferiorSetupFailed(const QString &msg) { - showStatusMessage(tr("Failed to start application: ") + msg); + showStatusMessage(tr("Failed to start application:") + QLatin1Char(' ') + msg); if (state() == EngineSetupFailed) { showMessage(_("INFERIOR START FAILED, BUT ADAPTER DIED ALREADY")); return; // Adapter crashed meanwhile, so this notification is meaningless. @@ -5240,7 +5235,7 @@ void GdbEngine::handleAdapterCrashed(const QString &msg) notifyEngineIll(); // No point in being friendly here ... - gdbProc()->kill(); + m_gdbProc->kill(); if (!msg.isEmpty()) showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg); @@ -5385,7 +5380,7 @@ bool GdbEngine::attemptQuickStart() const void GdbEngine::write(const QByteArray &data) { - gdbProc()->write(data); + m_gdbProc->write(data); } bool GdbEngine::prepareCommand() diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index fd278d51ae9..592be2b0a98 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -649,7 +649,6 @@ protected: // Convenience Functions // QString errorMessage(QProcess::ProcessError error); - GdbProcess *gdbProc() const; void showExecutionError(const QString &message); static QByteArray tooltipIName(const QString &exp); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 9526e5e6081..46dfd62aef8 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -110,8 +110,8 @@ void LldbEngine::runCommand(const Command &command) QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll()); ++m_lastToken; QByteArray token = QByteArray::number(m_lastToken); - QByteArray cmd = "db {'cmd':'" + command.function + "'," - + command.args + "'token':" + token + "}\n"; + QByteArray cmd = "{\"cmd\":\"" + command.function + "\"," + + command.args + "\"token\":" + token + "}\n"; showMessage(_(token + cmd), LogInput); m_lldbProc.write(cmd); } @@ -156,7 +156,7 @@ void LldbEngine::setupEngine() m_lldbProc.start(_("python"), args); if (!m_lldbProc.waitForStarted()) { - const QString msg = tr("Unable to start LLDB '%1': %2") + const QString msg = tr("Unable to start LLDB \"%1\": %2") .arg(m_lldbCmd, m_lldbProc.errorString()); notifyEngineSetupFailed(); showMessage(_("ADAPTER START FAILED")); @@ -645,7 +645,7 @@ bool LldbEngine::setToolTipExpression(const QPoint &mousePos, } if (!hasLetterOrNumber(exp)) { - QToolTip::showText(m_toolTipPos, tr("'%1' contains no identifier.").arg(exp)); + QToolTip::showText(m_toolTipPos, tr("\"%1\" contains no identifier.").arg(exp)); return true; } @@ -665,7 +665,7 @@ bool LldbEngine::setToolTipExpression(const QPoint &mousePos, if (hasSideEffects(exp)) { QToolTip::showText(m_toolTipPos, - tr("Cowardly refusing to evaluate expression '%1' " + tr("Cowardly refusing to evaluate expression \"%1\" " "with potential side effects.").arg(exp)); return true; } @@ -794,7 +794,7 @@ QString LldbEngine::errorMessage(QProcess::ProcessError error) const switch (error) { case QProcess::FailedToStart: return tr("The LLDB process failed to start. Either the " - "invoked program '%1' is missing, or you may have insufficient " + "invoked program \"%1\" is missing, or you may have insufficient " "permissions to invoke the program.") .arg(m_lldbCmd); case QProcess::Crashed: @@ -812,7 +812,7 @@ QString LldbEngine::errorMessage(QProcess::ProcessError error) const return tr("An error occurred when attempting to read from " "the Lldb process. For example, the process may not be running."); default: - return tr("An unknown error in the Lldb process occurred. "); + return tr("An unknown error in the Lldb process occurred.") + QLatin1Char(' '); } } @@ -836,15 +836,14 @@ void LldbEngine::readLldbStandardError() void LldbEngine::readLldbStandardOutput() { QByteArray out = m_lldbProc.readAllStandardOutput(); - //showMessage(_("Lldb stdout: " + out)); - showMessage(_(out), LogDebug); + showMessage(_("Lldb stdout: " + out)); m_inbuffer.append(out); while (true) { - int pos = m_inbuffer.indexOf("@\n"); + int pos = m_inbuffer.indexOf('\n'); if (pos == -1) break; QByteArray response = m_inbuffer.left(pos).trimmed(); - m_inbuffer = m_inbuffer.mid(pos + 2); + m_inbuffer = m_inbuffer.mid(pos + 1); emit outputReady(response); } } @@ -856,12 +855,12 @@ void LldbEngine::requestUpdateWatchers() while (it.hasNext()) { it.next(); QHash hash; - hash["iname"] = "'watch." + QByteArray::number(it.value()) + '\''; - hash["exp"] = '\'' + it.key().toHex() + '\''; + hash["iname"] = "\"watch." + QByteArray::number(it.value()) + '"'; + hash["exp"] = '"' + it.key().toHex() + '"'; watcherData.append(Command::toData(hash)); } Command cmd("setWatchers"); - cmd.args.append("'watchers':" + Command::toData(watcherData) + ','); + cmd.args.append("\"watchers\":" + Command::toData(watcherData) + ','); runCommand(cmd); } @@ -1117,9 +1116,9 @@ DebuggerEngine *createLldbEngine(const DebuggerStartParameters &startParameters) const LldbEngine::Command &LldbEngine::Command::argHelper(const char *name, const QByteArray &data) const { - args.append('\''); + args.append('"'); args.append(name); - args.append("':"); + args.append("\":"); args.append(data); args.append(","); return *this; @@ -1144,7 +1143,7 @@ QByteArray LldbEngine::Command::toData(const QHash &valu it.next(); if (!res.isEmpty()) res.append(','); - res += '\'' + it.key() + "':" + it.value(); + res += '"' + it.key() + "\":" + it.value(); } return '{' + res + '}'; } @@ -1176,20 +1175,20 @@ const LldbEngine::Command &LldbEngine::Command::arg(const char *name, const QByt const LldbEngine::Command &LldbEngine::Command::arg(const char *name, const char *value) const { - args.append('\''); + args.append('"'); args.append(name); - args.append("':'"); + args.append("\":\""); args.append(value); - args.append("',"); + args.append("\","); return *this; } const LldbEngine::Command &LldbEngine::Command::beginList(const char *name) const { if (name) { - args += '\''; + args += '"'; args += name; - args += "':"; + args += "\":"; } args += '['; return *this; @@ -1205,9 +1204,9 @@ void LldbEngine::Command::endList() const const LldbEngine::Command &LldbEngine::Command::beginGroup(const char *name) const { if (name) { - args += '\''; + args += '"'; args += name; - args += "':"; + args += "\":"; } args += '{'; return *this; diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 702bd1cefa9..71453f46f05 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -596,7 +596,7 @@ QString PdbEngine::errorMessage(QProcess::ProcessError error) const return tr("An error occurred when attempting to read from " "the Pdb process. For example, the process may not be running."); default: - return tr("An unknown error in the Pdb process occurred. "); + return tr("An unknown error in the Pdb process occurred.") + QLatin1Char(' '); } } diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 89929350c73..4308c42c48c 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -1167,7 +1167,7 @@ void QmlEngine::updateCurrentContext() QmlJS::ConsoleManagerInterface *consoleManager = qmlConsoleManager(); if (consoleManager) - consoleManager->setContext(tr("Context: ").append(context)); + consoleManager->setContext(tr("Context:") + QLatin1Char(' ') + context); } void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message, diff --git a/src/plugins/debugger/qml/qmlinspectoragent.cpp b/src/plugins/debugger/qml/qmlinspectoragent.cpp index 68974bf9d46..c1e4f41b4f4 100644 --- a/src/plugins/debugger/qml/qmlinspectoragent.cpp +++ b/src/plugins/debugger/qml/qmlinspectoragent.cpp @@ -454,7 +454,8 @@ void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value, } else if (type == "SET_BINDING_R" || type == "RESET_BINDING_R" || type == "SET_METHOD_BODY_R") { - QString msg = QLatin1String(type) + tr("Success: "); + QString msg = QLatin1String(type) + tr("Success:"); + msg += QLatin1Char(' '); msg += value.toBool() ? QLatin1Char('1') : QLatin1Char('0'); if (!value.toBool()) emit automaticUpdateFailed(); diff --git a/src/plugins/debugger/watchdata.cpp b/src/plugins/debugger/watchdata.cpp index 8cad1a3c13c..cead6220a3d 100644 --- a/src/plugins/debugger/watchdata.cpp +++ b/src/plugins/debugger/watchdata.cpp @@ -392,7 +392,8 @@ QString WatchData::toToolTip() const } if (val.size() > 1000) { val.truncate(1000); - val += tr(" ... "); + val += QLatin1Char(' '); + val += tr("... "); } formatToolTipRow(str, tr("Value"), val); if (address) diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 1619cfeb2fc..7539387542f 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -649,7 +649,7 @@ void WatchTreeView::contextMenuEvent(QContextMenuEvent *ev) QString msg = (individualFormat == -1 && typeFormat != -1) ? tr("Use Format for Type (Currently %1)") .arg(alternativeFormats.at(typeFormat)) - : tr("Use Display Format Based on Type "); + : tr("Use Display Format Based on Type") + QLatin1Char(' '); clearIndividualFormatAction = formatMenu.addAction(spacer + msg); clearIndividualFormatAction->setCheckable(true); clearIndividualFormatAction->setChecked(individualFormat == -1); diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 59a65c0ac2c..5c3050f81d4 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1576,7 +1576,6 @@ public: QTextBlock previousLine(const QTextBlock &block) const; // previous line (respects wrapped parts) int linesOnScreen() const; - int columnsOnScreen() const; int linesInDocument() const; // The following use all zero-based counting. @@ -3673,9 +3672,12 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) setCursorPosition(&m_cursor, pos); handleStartOfLine(); } else if (g.gflag && input.is('m')) { - moveToStartOfLine(); - moveRight(qMin(columnsOnScreen() / 2, rightDist()) - 1); - setTargetColumn(); + const QPoint pos(EDITOR(viewport()->width()) / 2, EDITOR(cursorRect(m_cursor)).y()); + QTextCursor tc = EDITOR(cursorForPosition(pos)); + if (!tc.isNull()) { + m_cursor = tc; + setTargetColumn(); + } } else if (input.is('M')) { m_cursor = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2))); handleStartOfLine(); @@ -5397,7 +5399,7 @@ bool FakeVimHandler::Private::handleExSetCommand(const ExCommand &cmd) if (!error.isEmpty()) showMessage(MessageError, error); } else { - showMessage(MessageError, FakeVimHandler::tr("Unknown option: ") + cmd.args); + showMessage(MessageError, FakeVimHandler::tr("Unknown option:") + QLatin1Char(' ') + cmd.args); } updateMiniBuffer(); updateEditor(); @@ -6370,25 +6372,16 @@ int FakeVimHandler::Private::cursorLineOnScreen() const { if (!editor()) return 0; - QRect rect = EDITOR(cursorRect()); - return rect.y() / rect.height(); + const QRect rect = EDITOR(cursorRect(m_cursor)); + return rect.height() > 0 ? rect.y() / rect.height() : 0; } int FakeVimHandler::Private::linesOnScreen() const { if (!editor()) return 1; - QRect rect = EDITOR(cursorRect()); - return EDITOR(viewport()->height()) / rect.height(); -} - -int FakeVimHandler::Private::columnsOnScreen() const -{ - if (!editor()) - return 1; - QRect rect = EDITOR(cursorRect()); - // qDebug() << "WID: " << EDITOR(width()) << "RECT: " << rect; - return EDITOR(viewport()->width()) / rect.width(); + const int h = EDITOR(cursorRect(m_cursor)).height(); + return h > 0 ? EDITOR(viewport()->height()) / h : 1; } int FakeVimHandler::Private::cursorLine() const diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp index 27f84d55beb..8859af24e7c 100644 --- a/src/plugins/git/gerrit/gerritdialog.cpp +++ b/src/plugins/git/gerrit/gerritdialog.cpp @@ -101,7 +101,7 @@ GerritDialog::GerritDialog(const QSharedPointer &p, , m_filterLineEdit(new Utils::FilterLineEdit) , m_repositoryChooser(new Utils::PathChooser) , m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Close)) - , m_repositoryChooserLabel(new QLabel(tr("Apply in: "), this)) + , m_repositoryChooserLabel(new QLabel(tr("Apply in:") + QLatin1Char(' '), this)) , m_fetchRunning(false) { setWindowTitle(tr("Gerrit %1@%2").arg(p->user, p->host)); diff --git a/src/plugins/git/gerrit/gerritpushdialog.cpp b/src/plugins/git/gerrit/gerritpushdialog.cpp index 4cba7599952..c8b0537a22d 100644 --- a/src/plugins/git/gerrit/gerritpushdialog.cpp +++ b/src/plugins/git/gerrit/gerritpushdialog.cpp @@ -37,6 +37,7 @@ #include #include +#include namespace Gerrit { namespace Internal { @@ -156,6 +157,9 @@ GerritPushDialog::GerritPushDialog(const QString &workingDir, const QString &rev connect(m_ui->branchComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setChangeRange())); setRemoteBranches(); m_ui->reviewersLineEdit->setText(reviewerList); + + m_ui->topicLineEdit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("^\\S+$")), this)); + m_valid = true; } diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 764ba726b07..416c29e5d3a 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2767,7 +2767,7 @@ void GitClient::continuePreviousGitCommand(const QString &workingDirectory, == GitClient::StatusChanged; } if (!hasChanges) - msgBoxText.prepend(tr("No changes found. ")); + msgBoxText.prepend(tr("No changes found.") + QLatin1Char(' ')); QMessageBox msgBox(QMessageBox::Question, msgBoxTitle, msgBoxText, QMessageBox::NoButton, Core::ICore::mainWindow()); if (hasChanges || isRebase) @@ -2808,7 +2808,7 @@ QString GitClient::extendedShowDescription(const QString &workingDirectory, cons if (branchCount > 20) { const int leave = 10; //: Displayed after the untranslated message "Branches: branch1, branch2 'and %n more'" in git show. - moreBranches = tr(" and %n more", 0, branchCount - leave); + moreBranches = QLatin1Char(' ') + tr("and %n more", 0, branchCount - leave); branches.erase(branches.begin() + leave, branches.end()); } if (!branches.isEmpty()) { diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index ebfca0293fc..1eaa690bc99 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp index d258d34991d..524eff47281 100644 --- a/src/plugins/ios/iosdevice.cpp +++ b/src/plugins/ios/iosdevice.cpp @@ -33,6 +33,7 @@ #include "iostoolhandler.h" #include #include +#include #include #include @@ -318,11 +319,12 @@ void IosDeviceManager::deviceInfo(IosToolHandler *, const QString &uid, mBox.setText(tr("An iOS device in user mode has been detected.")); mBox.setInformativeText(tr("Do you want to see how to set it up for development?")); mBox.setStandardButtons(QMessageBox::NoAll | QMessageBox::No | QMessageBox::Yes); - mBox.setDefaultButton(QMessageBox::No); + mBox.setDefaultButton(QMessageBox::Yes); int ret = mBox.exec(); switch (ret) { case QMessageBox::Yes: - // open doc + Core::HelpManager::handleHelpRequest( + QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-developing-ios.html")); break; case QMessageBox::No: newDev->m_ignoreDevice = true; diff --git a/src/plugins/locator/executefilter.cpp b/src/plugins/locator/executefilter.cpp index 4b4ef46b0b6..20e940a1d78 100644 --- a/src/plugins/locator/executefilter.cpp +++ b/src/plugins/locator/executefilter.cpp @@ -168,6 +168,11 @@ void ExecuteFilter::runHeadCommand() m_process->setCommand(fullPath, d.arguments); m_process->start(); m_process->closeWriteChannel(); + if (!m_process->waitForStarted(1000)) { + MessageManager::write(tr("Could not start process: %1").arg(m_process->errorString())); + m_taskQueue.dequeue(); + runHeadCommand(); + } } } diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp index b0c45aa001a..aafe96ccd95 100644 --- a/src/plugins/projectexplorer/abi.cpp +++ b/src/plugins/projectexplorer/abi.cpp @@ -311,18 +311,19 @@ Abi::Abi(const Architecture &a, const OS &o, m_osFlavor = UnknownFlavor; break; case ProjectExplorer::Abi::LinuxOS: - if (m_osFlavor < GenericLinuxFlavor || m_osFlavor > MaemoLinuxFlavor) + if (m_osFlavor < GenericLinuxFlavor || m_osFlavor > AndroidLinuxFlavor) m_osFlavor = UnknownFlavor; break; case ProjectExplorer::Abi::BsdOS: - m_osFlavor = FreeBsdFlavor; + if (m_osFlavor < FreeBsdFlavor || m_osFlavor > OpenBsdFlavor) + m_osFlavor = UnknownFlavor; break; case ProjectExplorer::Abi::MacOS: if (m_osFlavor < GenericMacFlavor || m_osFlavor > GenericMacFlavor) m_osFlavor = UnknownFlavor; break; case ProjectExplorer::Abi::UnixOS: - if (m_osFlavor < GenericUnixFlavor || m_osFlavor > GenericUnixFlavor) + if (m_osFlavor < GenericUnixFlavor || m_osFlavor > SolarisUnixFlavor) m_osFlavor = UnknownFlavor; break; case ProjectExplorer::Abi::WindowsOS: @@ -387,10 +388,6 @@ Abi::Abi(const QString &abiString) : m_osFlavor = NetBsdFlavor; else if (abiParts.at(2) == QLatin1String("openbsd") && m_os == BsdOS) m_osFlavor = OpenBsdFlavor; - else if (abiParts.at(2) == QLatin1String("maemo") && m_os == LinuxOS) - m_osFlavor = MaemoLinuxFlavor; - else if (abiParts.at(2) == QLatin1String("harmattan") && m_os == LinuxOS) - m_osFlavor = HarmattanLinuxFlavor; else if (abiParts.at(2) == QLatin1String("generic") && m_os == MacOS) m_osFlavor = GenericMacFlavor; else if (abiParts.at(2) == QLatin1String("generic") && m_os == UnixOS) @@ -637,10 +634,6 @@ QString Abi::toString(const OSFlavor &of) return QLatin1String("netbsd"); case ProjectExplorer::Abi::OpenBsdFlavor: return QLatin1String("openbsd"); - case ProjectExplorer::Abi::MaemoLinuxFlavor: - return QLatin1String("maemo"); - case ProjectExplorer::Abi::HarmattanLinuxFlavor: - return QLatin1String("harmattan"); case ProjectExplorer::Abi::GenericMacFlavor: return QLatin1String("generic"); case ProjectExplorer::Abi::GenericUnixFlavor: @@ -698,8 +691,7 @@ QList Abi::flavorsForOs(const Abi::OS &o) case BsdOS: return result << FreeBsdFlavor << OpenBsdFlavor << NetBsdFlavor << UnknownFlavor; case LinuxOS: - return result << GenericLinuxFlavor << HarmattanLinuxFlavor << MaemoLinuxFlavor - << AndroidLinuxFlavor << UnknownFlavor; + return result << GenericLinuxFlavor << AndroidLinuxFlavor << UnknownFlavor; case MacOS: return result << GenericMacFlavor << UnknownFlavor; case UnixOS: diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h index 473918b9185..e7e7a9669ea 100644 --- a/src/plugins/projectexplorer/abi.h +++ b/src/plugins/projectexplorer/abi.h @@ -73,8 +73,6 @@ public: // Linux GenericLinuxFlavor, AndroidLinuxFlavor, - HarmattanLinuxFlavor, - MaemoLinuxFlavor, // Mac GenericMacFlavor, diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp index a3667fbeceb..e04b94731d8 100644 --- a/src/plugins/projectexplorer/applicationlauncher.cpp +++ b/src/plugins/projectexplorer/applicationlauncher.cpp @@ -35,10 +35,8 @@ #include #include +#include #include -#ifdef Q_OS_WIN -#include -#endif #include @@ -131,19 +129,10 @@ ApplicationLauncher::~ApplicationLauncher() void ApplicationLauncher::setWorkingDirectory(const QString &dir) { -#ifdef Q_OS_WIN // Work around QTBUG-17529 (QtDeclarative fails with 'File name case mismatch' ...) - const QString fixedPath = Utils::normalizePathName(dir); -#else -# define fixedPath dir -#endif - + const QString fixedPath = Utils::FileUtils::normalizePathName(dir); d->m_guiProcess.setWorkingDirectory(fixedPath); d->m_consoleProcess.setWorkingDirectory(fixedPath); - -#ifndef Q_OS_WIN -# undef fixedPath -#endif } void ApplicationLauncher::setEnvironment(const Utils::Environment &env) diff --git a/src/plugins/projectexplorer/copytaskhandler.cpp b/src/plugins/projectexplorer/copytaskhandler.cpp index 58c3f691ad2..1b641a7ce17 100644 --- a/src/plugins/projectexplorer/copytaskhandler.cpp +++ b/src/plugins/projectexplorer/copytaskhandler.cpp @@ -45,11 +45,11 @@ void CopyTaskHandler::handle(const ProjectExplorer::Task &task) switch (task.type) { case Task::Error: //: Task is of type: error - type = tr("error: "); + type = tr("error:") + QLatin1Char(' '); break; case Task::Warning: //: Task is of type: warning - type = tr("warning: "); + type = tr("warning:") + QLatin1Char(' '); break; default: break; diff --git a/src/plugins/projectexplorer/customparserconfigdialog.cpp b/src/plugins/projectexplorer/customparserconfigdialog.cpp index b45c745c8f9..2a6c0f72024 100644 --- a/src/plugins/projectexplorer/customparserconfigdialog.cpp +++ b/src/plugins/projectexplorer/customparserconfigdialog.cpp @@ -147,7 +147,7 @@ void CustomParserConfigDialog::changed() int pos = rx.indexIn(ui->errorMessage->text()); if (rx.isEmpty() || !rx.isValid() || pos < 0) { - QString error = QLatin1String("") + tr("Not applicable: "); + QString error = QLatin1String("") + tr("Not applicable:") + QLatin1Char(' '); if (rx.isEmpty()) error += tr("Pattern is empty."); else if (!rx.isValid()) diff --git a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp index c2d736b3f51..719739bce28 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopprocesssignaloperation.cpp @@ -85,14 +85,16 @@ void DesktopProcessSignalOperation::appendMsgCannotKill(int pid, const QString & { if (!m_errorMessage.isEmpty()) m_errorMessage += QChar::fromLatin1('\n'); - m_errorMessage += tr("Cannot kill process with pid %1: %3 ").arg(pid).arg(why); + m_errorMessage += tr("Cannot kill process with pid %1: %3").arg(pid).arg(why); + m_errorMessage += QLatin1Char(' '); } void DesktopProcessSignalOperation::appendMsgCannotInterrupt(int pid, const QString &why) { if (!m_errorMessage.isEmpty()) m_errorMessage += QChar::fromLatin1('\n'); - m_errorMessage += tr("Cannot interrupt process with pid %1: %3 ").arg(pid).arg(why); + m_errorMessage += tr("Cannot interrupt process with pid %1: %3").arg(pid).arg(why); + m_errorMessage += QLatin1Char(' '); } void DesktopProcessSignalOperation::killProcessSilently(int pid) @@ -165,8 +167,8 @@ GDB 32bit | Api | Api | N/A | Win32 m_specialInterrupt == Win64Interrupt && creatorIs64Bit || m_specialInterrupt == Win32Interrupt && !creatorIs64Bit) { if (!DebugBreakProcess(inferior)) { - appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed: ") - + Utils::winErrorMessage(GetLastError())); + appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:") + + QLatin1Char(' ') + Utils::winErrorMessage(GetLastError())); } } else if (m_specialInterrupt == Win32Interrupt || m_specialInterrupt == Win64Interrupt) { QString executable = QCoreApplication::applicationDirPath(); @@ -189,7 +191,7 @@ GDB 32bit | Api | Api | N/A | Win32 break; default: appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable) - + tr(" could not break the process.")); + + QLatin1Char(' ') + tr("could not break the process.")); break; } } diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 6aad3a6b208..4e26ef1101b 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -158,6 +158,8 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) this, SLOT(slotOpenItem(QModelIndex))); connect(m_filterHiddenFilesAction, SIGNAL(toggled(bool)), this, SLOT(setHiddenFilesFilter(bool))); connect(m_toggleSync, SIGNAL(clicked(bool)), this, SLOT(toggleAutoSynchronization())); + connect(m_filterModel, SIGNAL(layoutChanged()), + this, SLOT(ensureCurrentIndex())); } void FolderNavigationWidget::toggleAutoSynchronization() @@ -225,10 +227,17 @@ bool FolderNavigationWidget::setCurrentDirectory(const QString &directory) setCurrentTitle(QString(), QString()); return false; } - m_listView->setRootIndex(m_filterModel->mapFromSource(index)); + QModelIndex oldRootIndex = m_listView->rootIndex(); + QModelIndex newRootIndex = m_filterModel->mapFromSource(index); + m_listView->setRootIndex(newRootIndex); const QDir current(QDir::cleanPath(newDirectory)); setCurrentTitle(current.dirName(), QDir::toNativeSeparators(current.absolutePath())); + if (oldRootIndex.parent() == newRootIndex) { // cdUp, so select the old directory + m_listView->setCurrentIndex(oldRootIndex); + m_listView->scrollTo(oldRootIndex, QAbstractItemView::EnsureVisible); + } + return !directory.isEmpty(); } @@ -365,6 +374,17 @@ bool FolderNavigationWidget::hiddenFilesFilter() const return m_filterHiddenFilesAction->isChecked(); } +void FolderNavigationWidget::ensureCurrentIndex() +{ + QModelIndex index = m_listView->currentIndex(); + if (!index.isValid() + || index.parent() != m_listView->rootIndex()) { + index = m_listView->rootIndex().child(0, 0); + m_listView->setCurrentIndex(index); + } + m_listView->scrollTo(index); +} + // --------------------FolderNavigationWidgetFactory FolderNavigationWidgetFactory::FolderNavigationWidgetFactory() { diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index 6b6aaed266e..f99a9262e8e 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -70,6 +70,7 @@ private slots: void setCurrentFile(const QString &filePath); void slotOpenItem(const QModelIndex &viewIndex); void setHiddenFilesFilter(bool filter); + void ensureCurrentIndex(); protected: virtual void contextMenuEvent(QContextMenuEvent *ev); diff --git a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp index d3a43ba0967..7c5ac9bcad1 100644 --- a/src/plugins/projectexplorer/kitinformationconfigwidget.cpp +++ b/src/plugins/projectexplorer/kitinformationconfigwidget.cpp @@ -89,7 +89,7 @@ void SysRootInformationConfigWidget::refresh() void SysRootInformationConfigWidget::makeReadOnly() { - m_chooser->setReadOnly(true); + m_chooser->setEnabled(false); } QWidget *SysRootInformationConfigWidget::mainWidget() const diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp index 0bc41b7b842..653d9e30f7c 100644 --- a/src/plugins/projectexplorer/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -31,9 +31,7 @@ #include "projectexplorerconstants.h" #include -#ifdef Q_OS_WIN -#include -#endif +#include static const char FILE_POS_PATTERN[] = "(cl|LINK|.+) : "; static const char ERROR_PATTERN[] = "[A-Z]+\\d\\d\\d\\d ?:"; @@ -58,11 +56,7 @@ static QPair parseFileName(const QString &input) } } } -#ifdef Q_OS_WIN - const QString normalized = Utils::normalizePathName(fileName); -#else - const QString normalized = fileName; -#endif + const QString normalized = Utils::FileUtils::normalizePathName(fileName); return qMakePair(Utils::FileName::fromUserInput(normalized), linenumber); } diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index db71fccfa86..fa2b24a9959 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -29,8 +29,6 @@ #include "projectwelcomepage.h" -#include - #include #include #include @@ -42,9 +40,8 @@ #include #include -#ifdef Q_OS_WIN -#include -#endif +#include +#include namespace ProjectExplorer { namespace Internal { @@ -225,12 +222,9 @@ void ProjectWelcomePage::facilitateQml(QQmlEngine *engine) QUrl ProjectWelcomePage::pageLocation() const { - QString resourcePath = Core::ICore::resourcePath(); -#ifdef Q_OS_WIN // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows - resourcePath = Utils::normalizePathName(resourcePath); -#endif - return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/develop.qml")); + const QString resourcePath = Utils::FileUtils::normalizePathName(Core::ICore::resourcePath()); + return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/develop.qml")); } ProjectWelcomePage::Id ProjectWelcomePage::id() const diff --git a/src/plugins/projectexplorer/targetsettingspanel.cpp b/src/plugins/projectexplorer/targetsettingspanel.cpp index 504871cb5b6..95a99377a0e 100644 --- a/src/plugins/projectexplorer/targetsettingspanel.cpp +++ b/src/plugins/projectexplorer/targetsettingspanel.cpp @@ -418,7 +418,7 @@ Target *TargetSettingsPanelWidget::cloneTarget(Target *sourceTarget, Kit *k) if (!runconfigurationError.isEmpty()) { if (!error.isEmpty()) error.append(QLatin1Char('\n')); - error += tr("Run configurations ") + error += tr("Run configurations") + QLatin1Char(' ') + runconfigurationError.join(QLatin1String("\n")); } diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp index ce094aeff8e..34ab0c6d011 100644 --- a/src/plugins/projectexplorer/taskwindow.cpp +++ b/src/plugins/projectexplorer/taskwindow.cpp @@ -48,6 +48,7 @@ #include #include #include +#include namespace { const int ELLIPSIS_GRADIENT_WIDTH = 16; @@ -74,6 +75,8 @@ class TaskDelegate : public QStyledItemDelegate { Q_OBJECT + friend class TaskView; // for using Positions::minimumSize() + public: TaskDelegate(QObject * parent = 0); ~TaskDelegate(); @@ -126,11 +129,11 @@ private: int right() const { return m_totalWidth - ITEM_MARGIN; } int bottom() const { return m_bottom; } int firstLineHeight() const { return m_fontHeight + 1; } - int minimumHeight() const { return taskIconHeight() + 2 * ITEM_MARGIN; } + static int minimumHeight() { return taskIconHeight() + 2 * ITEM_MARGIN; } int taskIconLeft() const { return left(); } - int taskIconWidth() const { return TASK_ICON_SIZE; } - int taskIconHeight() const { return TASK_ICON_SIZE; } + static int taskIconWidth() { return TASK_ICON_SIZE; } + static int taskIconHeight() { return TASK_ICON_SIZE; } int taskIconRight() const { return taskIconLeft() + taskIconWidth(); } QRect taskIcon() const { return QRect(taskIconLeft(), top(), taskIconWidth(), taskIconHeight()); } @@ -169,6 +172,13 @@ TaskView::TaskView(QWidget *parent) { setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + + QFontMetrics fm(font()); + int vStepSize = fm.height() + 3; + if (vStepSize < TaskDelegate::Positions::minimumHeight()) + vStepSize = TaskDelegate::Positions::minimumHeight(); + + verticalScrollBar()->setSingleStep(vStepSize); } TaskView::~TaskView() diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 03f5c72654c..970626a241e 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -412,7 +412,14 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const QTC_ASSERT(!dir.isNull(), return); qbs::SetupProjectParameters params; - params.setBuildConfiguration(config); + QVariantMap baseConfig; + QVariantMap userConfig = config; + QString specialKey = QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY); + baseConfig.insert(specialKey, userConfig.take(specialKey)); + specialKey = QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY); + baseConfig.insert(specialKey, userConfig.take(specialKey)); + params.setBuildConfiguration(baseConfig); + params.setOverriddenValues(userConfig); qbs::ErrorInfo err = params.expandBuildConfiguration(m_manager->settings()); if (err.hasError()) { generateErrors(err); @@ -423,7 +430,7 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const const qbs::Project ¤tProject = qbsProject(); if (!m_forceParsing && currentProject.isValid() - && currentProject.projectConfiguration() == params.buildConfiguration()) { + && currentProject.projectConfiguration() == params.finalBuildConfigurationTree()) { QHash usedEnv = currentProject.usedEnvironment(); bool canSkip = true; for (QHash::const_iterator i = usedEnv.constBegin(); diff --git a/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp b/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp index 9a04a2cec3e..82411e6b989 100644 --- a/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp +++ b/src/plugins/qmldesigner/components/componentcore/tabviewdesigneraction.cpp @@ -151,7 +151,7 @@ void TabViewDesignerAction::addNewTab() QString newFilePath = directoryPath +QLatin1String("/") + tabName + QLatin1String(".qml"); if (QFileInfo(newFilePath).exists()) { - QMessageBox::warning(Core::ICore::mainWindow(), tr("Name Error"), tr("Component already exists.")); + QMessageBox::warning(Core::ICore::mainWindow(), tr("Naming Error"), tr("Component already exists.")); } else { bool fileCreated = createFile(newFilePath); diff --git a/src/plugins/qmldesigner/components/debugview/debugview.cpp b/src/plugins/qmldesigner/components/debugview/debugview.cpp index 2b7823ccbe2..013b4a2f567 100644 --- a/src/plugins/qmldesigner/components/debugview/debugview.cpp +++ b/src/plugins/qmldesigner/components/debugview/debugview.cpp @@ -147,8 +147,8 @@ void DebugView::nodeIdChanged(const ModelNode &node, const QString &newId, const QString string; message.setString(&string); message << node; - message << tr("New Id: ") << newId << lineBreak; - message << tr("Old Id: ") << oldId << lineBreak; + message << tr("New Id:") << ' ' << newId << lineBreak; + message << tr("Old Id:") << ' ' << oldId << lineBreak; log(tr("Node id changed:"), string); } } diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml index 793d7ea7f01..697d3a95a8c 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml +++ b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsView.qml @@ -223,6 +223,7 @@ content position out of scope regarding the scrollbar. */ anchors.bottom: parent.bottom anchors.bottomMargin: 1 anchors.right: parent.right + anchors.rightMargin: 2 width: (itemsFlickable.contentHeight > itemsFlickable.height)? 11:0 Scrollbar { diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml index e5f29de94ce..c112ffa50fb 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml +++ b/src/plugins/qmldesigner/components/itemlibrary/qml/ItemsViewStyle.qml @@ -61,7 +61,7 @@ Item { property int textWidth: 95 property int textHeight: 15 - property int cellHorizontalMargin: 5 + property int cellHorizontalMargin: 4 property int cellVerticalSpacing: 7 property int cellVerticalMargin: 10 diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml index 33bc50fc800..23adc86abb2 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml +++ b/src/plugins/qmldesigner/components/itemlibrary/qml/Scrollbar.qml @@ -39,11 +39,11 @@ Item { property variant flickable function scroll(delta) { - handle.y = Math.max(0, Math.min(scrollHeight, handle.y + delta)) + handle.y = Math.max(2, Math.min(scrollHeight, handle.y + delta)) } function reset() { - handle.y = 0 + handle.y = 2 } // internal @@ -62,8 +62,7 @@ Item { anchors.bottom: parent.bottom anchors.bottomMargin: 3 anchors.horizontalCenter: parent.horizontalCenter - width: 6 - radius: 3 + width: 10 color: style.scrollbarColor border.width: 1 border.color: style.scrollbarBorderColor @@ -77,7 +76,7 @@ Item { flickable.contentY / (flickable.contentHeight - flickable.height), 1) else - handle.y = 0 + handle.y = 2 handle.updateFlickable = true } @@ -109,6 +108,7 @@ Item { Item { id: handle + y: 2 anchors.left: parent.left anchors.right: parent.right @@ -125,27 +125,20 @@ Item { width: parent.height height: parent.width y: -height - 2 - x: -2 rotation: 90 transformOrigin: Item.BottomLeft border.color: style.scrollbarBorderColor border.width: 1 - radius: 3 - - gradient: Gradient { - GradientStop { position: 0.15; color: style.scrollbarGradientStartColor } - GradientStop { position: 0.78; color: style.scrollbarGradientMiddleColor } - GradientStop { position: 0.80; color: style.scrollbarGradientEndColor } - } + color: style.sectionTitleBackgroundColor } MouseArea { anchors.fill: parent drag.target: parent drag.axis: "YAxis" - drag.minimumY: 0 + drag.minimumY: 2 drag.maximumY: scrollHeight } } diff --git a/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml b/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml index 5a43d7de750..bfc324ebe46 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml +++ b/src/plugins/qmldesigner/components/itemlibrary/qml/SectionView.qml @@ -28,6 +28,7 @@ ****************************************************************************/ import QtQuick 2.1 +import QtQuick.Controls 1.0 as Controls // view displaying one item library section including its grid @@ -114,12 +115,27 @@ Column { width: parent.width height: style.sectionTitleHeight - color: style.sectionTitleBackgroundColor + gradient: Gradient { + GradientStop {color: '#555' ; position: 0} + GradientStop {color: '#444' ; position: 1} + } + + Rectangle { + color:"#333" + width: parent.width + height: 1 + } + + Rectangle { + color: "#333" + anchors.bottom: parent.bottom + width: parent.width + height: 1 + } Item { id: arrow - Rectangle { y: 0; x: 0; height: 1; width: 11; color: style.sectionArrowColor } Rectangle { y: 1; x: 1; height: 1; width: 9; color: style.sectionArrowColor } Rectangle { y: 2; x: 2; height: 1; width: 7; color: style.sectionArrowColor } Rectangle { y: 3; x: 3; height: 1; width: 5; color: style.sectionArrowColor } @@ -127,25 +143,26 @@ Column { Rectangle { y: 5; x: 5; height: 1; width: 1; color: style.sectionArrowColor } anchors.left: parent.left - anchors.leftMargin: 10 + anchors.leftMargin: 4 anchors.verticalCenter: parent.verticalCenter width: 11 height: 6 transformOrigin: Item.Center } - Text { + Controls.Label { id: text anchors.verticalCenter: parent.verticalCenter anchors.left: arrow.right - anchors.leftMargin: 12 + anchors.leftMargin: 4 text: sectionName // to be set by model color: style.sectionTitleTextColor elide: Text.ElideMiddle font.bold: true - renderType: Text.NativeRendering + style: Text.Sunken + styleColor: "#292929" } MouseArea { id: mouseArea @@ -161,6 +178,9 @@ Column { Item { id: gridFrame + Behavior on opacity { NumberAnimation{easing.type: Easing.Linear ; duration: 80} } + Behavior on height { NumberAnimation{easing.type: Easing.OutCubic ; duration: 140} } + function toggleExpanded() { state = ((state == "")? "shrunk":"") diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 05b2511778b..67376a966b9 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -44,9 +44,7 @@ #include -#ifdef Q_OS_WIN -#include -#endif +#include enum { debug = false @@ -95,12 +93,8 @@ static QObject *variantToQObject(const QVariant &value) static QString applicationDirPath() { -#ifdef Q_OS_WIN // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows - return Utils::normalizePathName(QCoreApplication::applicationDirPath()); -#else - return QCoreApplication::applicationDirPath(); -#endif + return Utils::FileUtils::normalizePathName(QCoreApplication::applicationDirPath()); } #ifdef Q_OS_MAC diff --git a/src/plugins/qmldesigner/components/resources/scrollbar.css b/src/plugins/qmldesigner/components/resources/scrollbar.css index 34e8af8acbd..661c987cb93 100644 --- a/src/plugins/qmldesigner/components/resources/scrollbar.css +++ b/src/plugins/qmldesigner/components/resources/scrollbar.css @@ -1,26 +1,21 @@ QScrollBar:vertical { - border-image: url(:/qmldesigner/images/scrollbar-borderimage-vertical.png); - border-left: 0; - border-right: 0; - border-top: 3; - border-bottom: 3; + background-color: #444444; + border: 1px solid #333333; margin-top: 3; margin-bottom: 3; width: 10; } QScrollBar::handle:vertical { - background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, - stop: 0.20 #888888, - stop: 0.23 #656565, - stop: 0.85 #393939); + background-color: #656565; margin-top: -5; margin-bottom: -5; min-height: 18px; width: 8px; border: 1px solid #313131; - border-radius: 4px; border-width: 1; + margin-left: -1; + margin-right: -1; } QScrollBar::add-line:vertical { @@ -49,28 +44,24 @@ } QScrollBar:horizontal { - border-image: url(:/qmldesigner/images/scrollbar-borderimage-horizontal.png); - border-left: 3; - border-right: 3; - border-top: 0; - border-bottom: 0; + background-color: #444444; + border: 1px solid #333333; margin-left: 3; margin-right: 3; height: 10; } QScrollBar::handle:horizontal { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0.20 #888888, - stop: 0.23 #656565, - stop: 0.85 #393939); + background-color: #656565; + margin-left: -5; margin-right: -5; min-width: 18px; height: 8px; border: 1px solid #313131; - border-radius: 4px; border-width: 1; + margin-top: -1; + margin-bottom: -1; } QScrollBar::add-line:horizontal { diff --git a/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml b/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml index a1077e7ead8..08479b6a70a 100644 --- a/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml +++ b/src/plugins/qmldesigner/components/stateseditor/HorizontalScrollBar.qml @@ -55,9 +55,8 @@ Item { Rectangle { id: groove width: parent.width - 4 - height: 6 + height: 10 color: "#444444" - radius: 3 border.width: 1 border.color: "#333333" anchors.right: parent.right @@ -95,13 +94,8 @@ Item { y:0 border.color: "#333333" border.width: 1 - radius: 3 - gradient: Gradient { - GradientStop { position: 0.20; color: "#888888" } - GradientStop { position: 0.23; color: "#656565" } - GradientStop { position: 0.85; color: "#393939" } - } + color: "#656565" MouseArea { property int dragging:0; diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml index 4633c06fc34..f02154a92a9 100644 --- a/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml +++ b/src/plugins/qmldesigner/componentsplugin/Controls/ButtonSpecifics.qml @@ -135,7 +135,7 @@ Column { Label { text: qsTr("Focus on press") - toolTip: "Determines whether the check box gets focus if pressed." + toolTip: "Determines whether the button gets focus if pressed." } SecondColumnLayout { diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml index 7ec2cfd91df..6384c65e012 100644 --- a/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml +++ b/src/plugins/qmldesigner/componentsplugin/Controls/CheckBoxSpecifics.qml @@ -44,7 +44,7 @@ Column { Label { text: qsTr("Text") - toolTip: qsTr("The text shown on the check button") + toolTip: qsTr("The text shown on the check box") } SecondColumnLayout { @@ -59,7 +59,7 @@ Column { Label { text: qsTr("Checked") - toolTip: qsTr("The state of the check button") + toolTip: qsTr("The state of the check box") } SecondColumnLayout { @@ -75,7 +75,7 @@ Column { Label { text: qsTr("Focus on press") - toolTip: "Determines whether the check box gets focus if pressed." + toolTip: qsTr("Determines whether the check box gets focus if pressed.") } SecondColumnLayout { diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml index 9bd9a5c56cf..7c031333ee6 100644 --- a/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml +++ b/src/plugins/qmldesigner/componentsplugin/Controls/TextAreaSpecifics.qml @@ -58,7 +58,7 @@ Column { Label { text: qsTr("Text") - toolTip: qsTr("The text shown on the button") + toolTip: qsTr("The text shown on the text area") } SecondColumnLayout { @@ -73,7 +73,7 @@ Column { Label { text: qsTr("Read only") - toolTip: qsTr("Determines whether the text field is read only.") + toolTip: qsTr("Determines whether the text area is read only.") } SecondColumnLayout { diff --git a/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml b/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml index 7bad9156255..4967a340210 100644 --- a/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml +++ b/src/plugins/qmldesigner/componentsplugin/Controls/TextFieldSpecifics.qml @@ -44,7 +44,7 @@ Column { Label { text: qsTr("Text") - toolTip: qsTr("The text shown on the button") + toolTip: qsTr("The text shown on the text field") } SecondColumnLayout { diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp index 01d8504510a..6790478a52a 100644 --- a/src/plugins/qmlprofiler/qmlprofilereventview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -524,7 +524,7 @@ void QmlProfilerEventsMainView::parseModelProxy() QString toolTipText; if (event.eventType == Binding) { if (event.bindingType == (int)OptimizedBinding) { - typeString = typeString + tr(" (Opt)"); + typeString = typeString + QLatin1Char(' ') + tr("(Opt)"); toolTipText = tr("Binding is evaluated by the optimized engine."); } else if (event.bindingType == (int)V8Binding) { toolTipText = tr("Binding not optimized (e.g. has side effects or assignments,\n" diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index f133d802b9d..2d17f24d5b0 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -37,11 +37,13 @@ #include #include #include -#include #include #include #include +#include +#include + #ifdef Q_OS_WIN #include #endif @@ -159,13 +161,7 @@ QString QmlProjectRunConfiguration::workingDirectory() const is exactly like the capitalization on disk.*/ QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName) { - QString canonicalPath = QFileInfo(fileName).canonicalFilePath(); - -#if defined(Q_OS_WIN) - canonicalPath = Utils::normalizePathName(canonicalPath); -#endif - - return canonicalPath; + return Utils::FileUtils::normalizePathName(QFileInfo(fileName).canonicalFilePath()); } diff --git a/src/plugins/qnx/blackberryapplicationrunner.cpp b/src/plugins/qnx/blackberryapplicationrunner.cpp index 7e2ed840255..8178f2b3afc 100644 --- a/src/plugins/qnx/blackberryapplicationrunner.cpp +++ b/src/plugins/qnx/blackberryapplicationrunner.cpp @@ -32,6 +32,7 @@ #include "blackberryapplicationrunner.h" #include "blackberrydeployconfiguration.h" +#include "blackberrydeviceconnectionmanager.h" #include "blackberryrunconfiguration.h" #include "blackberrylogprocessrunner.h" #include "qnxconstants.h" @@ -94,28 +95,17 @@ BlackBerryApplicationRunner::BlackBerryApplicationRunner(bool debugMode, BlackBe void BlackBerryApplicationRunner::start() { - QStringList args; - args << QLatin1String("-launchApp"); - if (m_debugMode) - args << QLatin1String("-debugNative"); - args << QLatin1String("-device") << m_sshParams.host; - if (!m_sshParams.password.isEmpty()) - args << QLatin1String("-password") << m_sshParams.password; - args << QDir::toNativeSeparators(m_barPackage); - - if (!m_launchProcess) { - m_launchProcess = new QProcess(this); - connect(m_launchProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError())); - connect(m_launchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput())); - connect(m_launchProcess, SIGNAL(finished(int,QProcess::ExitStatus)), - this, SLOT(startFinished(int,QProcess::ExitStatus))); - - m_launchProcess->setEnvironment(m_environment.toStringList()); + if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id())) { + connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()), + this, SLOT(launchApplication())); + connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceDisconnected(Core::Id)), + this, SLOT(disconnectFromDeviceSignals(Core::Id))); + connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)), + this, SLOT(displayConnectionOutput(Core::Id,QString))); + BlackBerryDeviceConnectionManager::instance()->connectDevice(m_device->id()); + } else { + launchApplication(); } - - m_launchProcess->start(m_deployCmd, args); - m_runningStateTimer->start(); - m_running = true; } void BlackBerryApplicationRunner::startLogProcessRunner() @@ -130,6 +120,17 @@ void BlackBerryApplicationRunner::startLogProcessRunner() m_logProcessRunner->start(); } +void BlackBerryApplicationRunner::displayConnectionOutput(Core::Id deviceId, const QString &msg) +{ + if (deviceId != m_device->id()) + return; + + if (msg.contains(QLatin1String("Info:"))) + emit output(msg, Utils::StdOutFormat); + else if (msg.contains(QLatin1String("Error:"))) + emit output(msg, Utils::StdErrFormat); +} + void BlackBerryApplicationRunner::startFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitCode == 0 && exitStatus == QProcess::NormalExit && m_pid > -1) { @@ -214,6 +215,18 @@ void BlackBerryApplicationRunner::readStandardError() } } +void BlackBerryApplicationRunner::disconnectFromDeviceSignals(Core::Id deviceId) +{ + if (m_device->id() == deviceId) { + disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()), + this, SLOT(launchApplication())); + disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceDisconnected(Core::Id)), + this, SLOT(disconnectFromDeviceSignals(Core::Id))); + disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)), + this, SLOT(displayConnectionOutput(Core::Id,QString))); + } +} + void BlackBerryApplicationRunner::setPid(qint64 pid) { m_pid = pid; @@ -224,6 +237,37 @@ void BlackBerryApplicationRunner::setApplicationId(const QString &applicationId) m_appId = applicationId; } +void BlackBerryApplicationRunner::launchApplication() +{ + // If original device connection fails before launching, this method maybe triggered + // if any other device is connected(?) + if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id())) + return; + + QStringList args; + args << QLatin1String("-launchApp"); + if (m_debugMode) + args << QLatin1String("-debugNative"); + args << QLatin1String("-device") << m_sshParams.host; + if (!m_sshParams.password.isEmpty()) + args << QLatin1String("-password") << m_sshParams.password; + args << QDir::toNativeSeparators(m_barPackage); + + if (!m_launchProcess) { + m_launchProcess = new QProcess(this); + connect(m_launchProcess, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError())); + connect(m_launchProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput())); + connect(m_launchProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(startFinished(int,QProcess::ExitStatus))); + + m_launchProcess->setEnvironment(m_environment.toStringList()); + } + + m_launchProcess->start(m_deployCmd, args); + m_runningStateTimer->start(); + m_running = true; +} + void BlackBerryApplicationRunner::startRunningStateTimer() { if (m_running) diff --git a/src/plugins/qnx/blackberryapplicationrunner.h b/src/plugins/qnx/blackberryapplicationrunner.h index 9f257066d4f..3ba06a4785c 100644 --- a/src/plugins/qnx/blackberryapplicationrunner.h +++ b/src/plugins/qnx/blackberryapplicationrunner.h @@ -82,6 +82,7 @@ private slots: void readStandardOutput(); void readStandardError(); + void disconnectFromDeviceSignals(Core::Id deviceId); void startRunningStateTimer(); void determineRunningState(); void readRunningStateStandardOutput(); @@ -89,8 +90,11 @@ private slots: void setPid(qint64 pid); void setApplicationId(const QString &applicationId); + void launchApplication(); void startLogProcessRunner(); + void displayConnectionOutput(Core::Id deviceId, const QString &output); + private: void reset(); diff --git a/src/plugins/qnx/blackberryconfiguration.cpp b/src/plugins/qnx/blackberryconfiguration.cpp index 78b01a30d88..cc45468e539 100644 --- a/src/plugins/qnx/blackberryconfiguration.cpp +++ b/src/plugins/qnx/blackberryconfiguration.cpp @@ -45,6 +45,7 @@ #include +#include #include #include diff --git a/src/plugins/qnx/blackberrydebugsupport.cpp b/src/plugins/qnx/blackberrydebugsupport.cpp index e0ae83c181e..cbd48c5b4f2 100644 --- a/src/plugins/qnx/blackberrydebugsupport.cpp +++ b/src/plugins/qnx/blackberrydebugsupport.cpp @@ -51,8 +51,8 @@ BlackBerryDebugSupport::BlackBerryDebugSupport(BlackBerryRunConfiguration *runCo this, SLOT(handleDebuggerStateChanged(Debugger::DebuggerState))); connect(m_runner, SIGNAL(started()), this, SLOT(handleStarted())); - connect(m_runner, SIGNAL(started()), m_runner, SLOT(checkSlog2Info())); connect(m_runner, SIGNAL(startFailed(QString)), this, SLOT(handleStartFailed(QString))); + connect(m_runner, SIGNAL(started()), m_runner, SLOT(checkSlog2Info())); connect(m_runner, SIGNAL(output(QString,Utils::OutputFormat)), this, SLOT(handleApplicationOutput(QString,Utils::OutputFormat))); diff --git a/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp b/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp index d4011d246b6..37d8a199e26 100644 --- a/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp +++ b/src/plugins/qnx/blackberrydebugtokenrequestdialog.cpp @@ -191,7 +191,7 @@ void BlackBerryDebugTokenRequestDialog::expandPath() void BlackBerryDebugTokenRequestDialog::debugTokenArrived(int status) { - QString errorString = tr("Failed to request debug token: "); + QString errorString = tr("Failed to request debug token:") + QLatin1Char(' '); switch (status) { case BlackBerryDebugTokenRequester::Success: diff --git a/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp b/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp index 76c02a33031..cb762f41de0 100644 --- a/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp +++ b/src/plugins/qnx/blackberrydeviceconfigurationwidget.cpp @@ -165,7 +165,7 @@ void BlackBerryDeviceConfigurationWidget::uploadFinished(int status) { progressDialog->hide(); - QString errorString = tr("Failed to upload debug token: "); + QString errorString = tr("Failed to upload debug token:") + QLatin1Char(' '); switch (status) { case BlackBerryDebugTokenUploader::Success: diff --git a/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp b/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp index 342a2bd93f3..96b4c48687c 100644 --- a/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp +++ b/src/plugins/qnx/blackberrydeviceconfigurationwizardpages.cpp @@ -290,7 +290,8 @@ void BlackBerryDeviceConfigurationWizardQueryPage::sshKeysGenerationFailed(const if (m_state != GeneratingSshKey) return; - QString message = tr("Failed generating SSH key needed for securing connection to a device. Error: "); + QString message = tr("Failed generating SSH key needed for securing connection to a device. Error:"); + message += QLatin1Char(' '); message.append(error); setState(Done, message); } @@ -310,7 +311,8 @@ void BlackBerryDeviceConfigurationWizardQueryPage::processSshKeys(const QByteArr if (! BlackBerryDeviceConnectionManager::instance()->hasValidSSHKeys()) { QString error; if (!BlackBerryDeviceConnectionManager::instance()->setSSHKeys(privateKey, publicKey, &error)) { - QString message = tr("Failed saving SSH key needed for securing connection to a device. Error: "); + QString message = tr("Failed saving SSH key needed for securing connection to a device. Error:"); + message += QLatin1Char(' '); message.append(error); setState(Done, message); return; diff --git a/src/plugins/qnx/blackberrydeviceconnection.cpp b/src/plugins/qnx/blackberrydeviceconnection.cpp index 9b809863706..3db96567a5e 100644 --- a/src/plugins/qnx/blackberrydeviceconnection.cpp +++ b/src/plugins/qnx/blackberrydeviceconnection.cpp @@ -62,8 +62,7 @@ BlackBerryDeviceConnection::BlackBerryDeviceConnection() : void BlackBerryDeviceConnection::connectDevice(const ProjectExplorer::IDevice::ConstPtr &device) { Utils::Environment env = Utils::Environment::systemEnvironment(); - foreach (const Utils::EnvironmentItem &item, BlackBerryConfigurationManager::instance().defaultQnxEnv()) - env.appendOrSet(item.name, item.value); + env.modify(BlackBerryConfigurationManager::instance().defaultQnxEnv()); m_process->setEnvironment(env.toStringList()); diff --git a/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp b/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp index fa549d70db1..ad0c308295b 100644 --- a/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp +++ b/src/plugins/qnx/blackberrydeviceconnectionmanager.cpp @@ -278,9 +278,11 @@ void BlackBerryDeviceConnectionManager::handleDeviceDisconnected() QTC_ASSERT(connection, return); QList disconnectedDevices = m_connections.values(connection); - foreach (Core::Id id, disconnectedDevices) + foreach (Core::Id id, disconnectedDevices) { ProjectExplorer::DeviceManager::instance()->setDeviceState(id, ProjectExplorer::IDevice::DeviceDisconnected); + emit deviceDisconnected(id); + } } void BlackBerryDeviceConnectionManager::handleDeviceAboutToConnect() diff --git a/src/plugins/qnx/blackberrydeviceconnectionmanager.h b/src/plugins/qnx/blackberrydeviceconnectionmanager.h index a211f505e98..b9a5e10909d 100644 --- a/src/plugins/qnx/blackberrydeviceconnectionmanager.h +++ b/src/plugins/qnx/blackberrydeviceconnectionmanager.h @@ -69,6 +69,7 @@ signals: void connectionOutput(Core::Id deviceId, const QString &output); void deviceAboutToConnect(Core::Id deviceId); void deviceConnected(); + void deviceDisconnected(Core::Id deviceId); public slots: void connectDevice(Core::Id deviceId); diff --git a/src/plugins/qnx/blackberryruncontrol.cpp b/src/plugins/qnx/blackberryruncontrol.cpp index f372452bc70..564329fa573 100644 --- a/src/plugins/qnx/blackberryruncontrol.cpp +++ b/src/plugins/qnx/blackberryruncontrol.cpp @@ -34,8 +34,6 @@ #include "blackberryrunconfiguration.h" #include "blackberrydeviceconnectionmanager.h" -#include - #include #include @@ -45,7 +43,6 @@ using namespace Qnx::Internal; BlackBerryRunControl::BlackBerryRunControl(BlackBerryRunConfiguration *runConfiguration) : ProjectExplorer::RunControl(runConfiguration, ProjectExplorer::NormalRunMode) { - m_device = BlackBerryDeviceConfiguration::device(runConfiguration->target()->kit()); m_runner = new BlackBerryApplicationRunner(false, runConfiguration, this); connect(m_runner, SIGNAL(started()), this, SIGNAL(started())); @@ -57,7 +54,7 @@ BlackBerryRunControl::BlackBerryRunControl(BlackBerryRunConfiguration *runConfig void BlackBerryRunControl::start() { - checkDeviceConnection(); + m_runner->start(); } ProjectExplorer::RunControl::StopResult BlackBerryRunControl::stop() @@ -79,32 +76,3 @@ void BlackBerryRunControl::handleStartFailed(const QString &message) { appendMessage(message, Utils::StdErrFormat); } - -void BlackBerryRunControl::handleDeviceConnected() -{ - m_runner->start(); -} - -void BlackBerryRunControl::displayConnectionOutput(Core::Id deviceId, const QString &output) -{ - if (deviceId != m_device->id()) - return; - - if (output.contains(QLatin1String("Info:"))) - appendMessage(output, Utils::StdOutFormat); - else if (output.contains(QLatin1String("Error:"))) - appendMessage(output, Utils::StdErrFormat); -} - -void BlackBerryRunControl::checkDeviceConnection() -{ - if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id())) { - connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()), - this, SLOT(handleDeviceConnected())); - connect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)), - this, SLOT(displayConnectionOutput(Core::Id,QString))); - BlackBerryDeviceConnectionManager::instance()->connectDevice(m_device->id()); - } else { - m_runner->start(); - } -} diff --git a/src/plugins/qnx/blackberryruncontrol.h b/src/plugins/qnx/blackberryruncontrol.h index 787add054b1..ab061407d00 100644 --- a/src/plugins/qnx/blackberryruncontrol.h +++ b/src/plugins/qnx/blackberryruncontrol.h @@ -32,8 +32,6 @@ #ifndef QNX_INTERNAL_BLACKBERRYRUNCONTROL_H #define QNX_INTERNAL_BLACKBERRYRUNCONTROL_H -#include "blackberrydeviceconfiguration.h" - #include namespace QmakeProjectManager { @@ -60,13 +58,9 @@ public: private slots: void handleStartFailed(const QString &message); - void handleDeviceConnected(); - void displayConnectionOutput(Core::Id deviceId, const QString &output); - void checkDeviceConnection(); private: BlackBerryApplicationRunner *m_runner; - BlackBerryDeviceConfiguration::ConstPtr m_device; }; } // namespace Internal diff --git a/src/plugins/qnx/blackberrysetupwizard.cpp b/src/plugins/qnx/blackberrysetupwizard.cpp index 43cc73a7c04..e5214b0a0f3 100644 --- a/src/plugins/qnx/blackberrysetupwizard.cpp +++ b/src/plugins/qnx/blackberrysetupwizard.cpp @@ -176,7 +176,7 @@ void BlackBerrySetupWizard::certificateCreated(int status) void BlackBerrySetupWizard::debugTokenArrived(int status) { - QString errorString = tr("Failed to request debug token: "); + QString errorString = tr("Failed to request debug token:") + QLatin1Char(' '); switch (status) { case BlackBerryDebugTokenRequester::Success: @@ -222,7 +222,7 @@ void BlackBerrySetupWizard::debugTokenArrived(int status) void BlackBerrySetupWizard::uploaderFinished(int status) { - QString errorString = tr("Failed to upload debug token: "); + QString errorString = tr("Failed to upload debug token:") + QLatin1Char(' '); switch (status) { case BlackBerryDebugTokenUploader::Success: diff --git a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp index 72536849664..3f79461f3cd 100644 --- a/src/plugins/qt4projectmanager/librarydetailscontroller.cpp +++ b/src/plugins/qt4projectmanager/librarydetailscontroller.cpp @@ -103,7 +103,6 @@ LibraryDetailsController::LibraryDetailsController( } } } - setPlatformsVisible(true); setLinkageGroupVisible(true); setMacLibraryGroupVisible(true); diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index 5331ece9729..0980c48982a 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -166,11 +166,6 @@ QStringList QMakeStep::deducedArguments() ProjectExplorer::Abi targetAbi; if (tc) targetAbi = tc->targetAbi(); - if ((HostOsInfo::isWindowsHost() || HostOsInfo::isMacHost()) - && (targetAbi.osFlavor() == ProjectExplorer::Abi::HarmattanLinuxFlavor - || targetAbi.osFlavor() == ProjectExplorer::Abi::MaemoLinuxFlavor)) { - arguments << QLatin1String("-unix"); - } // explicitly add architecture to CONFIG if ((targetAbi.os() == ProjectExplorer::Abi::MacOS) diff --git a/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp b/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp index b252083f895..5965088f250 100644 --- a/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp +++ b/src/plugins/qt4projectmanager/wizards/qtquickapp.cpp @@ -29,6 +29,9 @@ #include "qtquickapp.h" +#include + +#include #include #include #include @@ -113,15 +116,25 @@ QString QtQuickApp::originsRoot() const switch (m_componentSet) { case QtQuickControls10: return templatesRoot() + QLatin1String("qtquick2controls/"); case QtQuick20Components: return templatesRoot() + QLatin1String("qtquick2app/"); - default: break; + case QtQuick10Components: return templatesRoot() + QLatin1String("qtquick1app/"); } - return templatesRoot() + QLatin1String("qtquickapp/"); + qWarning() << "QtQuickApp::originsRoot() - unhandled component set" + << m_componentSet; + return QString(); } QString QtQuickApp::mainWindowClassName() const { - return QLatin1String("QmlApplicationViewer"); + switch (m_componentSet) { + case QtQuickControls10: return QLatin1String("QtQuick2ControlsApplicationViewer"); + case QtQuick20Components: return QLatin1String("QtQuick2ApplicationViewer"); + case QtQuick10Components: return QLatin1String("QtQuick1ApplicationViewer"); + } + + qWarning() << "QtQuickApp::mainWindowClassName() - unhandled component set" + << m_componentSet; + return QString(); } bool QtQuickApp::adaptCurrentMainCppTemplateLine(QString &line) const @@ -174,12 +187,15 @@ bool QtQuickApp::useExistingMainQml() const QString QtQuickApp::appViewerBaseName() const { - if (m_componentSet == QtQuick20Components) { - return QLatin1String("qtquick2applicationviewer"); - } else if (m_componentSet == QtQuickControls10) { - return QLatin1String("qtquick2controlsapplicationviewer"); + switch (m_componentSet) { + case QtQuickControls10: return QLatin1String("qtquick2controlsapplicationviewer"); + case QtQuick20Components: return QLatin1String("qtquick2applicationviewer"); + case QtQuick10Components: return QLatin1String("qtquick1applicationviewer"); } - return QLatin1String("qmlapplicationviewer"); + + qWarning() << "QtQuickApp::appViewerBaseName() - unhandled component set" + << m_componentSet; + return QString(); } QString QtQuickApp::fileName(QtQuickApp::ExtendedFileType type) const diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index ced6d1defed..7e08dc3493f 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -1475,16 +1475,6 @@ bool BaseQtVersion::isQmlDebuggingSupported(QString *reason) const if (!needsQmlDebuggingLibrary() || hasQmlDebuggingLibrary()) return true; - if (!qtAbis().isEmpty()) { - Abi abi = qtAbis().first(); - if (abi.osFlavor() == Abi::MaemoLinuxFlavor) { - if (reason) - reason->clear(); - // *reason = QCoreApplication::translate("BaseQtVersion", "Qml debugging on device not yet supported."); - return false; - } - } - if (!isValid()) { if (reason) *reason = QCoreApplication::translate("BaseQtVersion", "Invalid Qt version."); diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index a514b0d3b0b..54d4ea1123d 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -241,11 +241,8 @@ QString ExamplesWelcomePage::title() const QUrl ExamplesWelcomePage::pageLocation() const { - QString resourcePath = Core::ICore::resourcePath(); -#ifdef Q_OS_WIN // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows - resourcePath = Utils::normalizePathName(resourcePath); -#endif + const QString resourcePath = Utils::FileUtils::normalizePathName(Core::ICore::resourcePath()); if (m_showExamples) return QUrl::fromLocalFile(resourcePath + QLatin1String("/welcomescreen/examples.qml")); else diff --git a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp index 015a2ea6d05..a4b26fef313 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfigurationfactory.cpp @@ -102,7 +102,7 @@ QList RemoteLinuxRunConfigurationFactory::availableCreationIds(Target QString RemoteLinuxRunConfigurationFactory::displayNameForId(const Core::Id id) const { return QFileInfo(pathFromId(id)).completeBaseName() - + tr(" (on Remote Generic Linux Host)"); + + QLatin1Char(' ') + tr("(on Remote Generic Linux Host)"); } RunConfiguration *RemoteLinuxRunConfigurationFactory::doCreate(Target *parent, const Core::Id id) diff --git a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp index bdfb67a787e..e3f96e27131 100644 --- a/src/plugins/remotelinux/remotelinuxsignaloperation.cpp +++ b/src/plugins/remotelinux/remotelinuxsignaloperation.cpp @@ -120,7 +120,8 @@ void RemoteLinuxSignalOperation::runnerProcessFinished() if (m_runner->processExitStatus() != QSsh::SshRemoteProcess::NormalExit) { m_errorMessage = m_runner->processErrorString(); } else if (m_runner->processExitCode() != 0) { - m_errorMessage = tr("Exit code is %1. stderr: ").arg(m_runner->processExitCode()) + m_errorMessage = tr("Exit code is %1. stderr:").arg(m_runner->processExitCode()) + + QLatin1Char(' ') + QString::fromLatin1(m_runner->readAllStandardError()); } finish(); diff --git a/src/plugins/texteditor/behaviorsettingswidget.cpp b/src/plugins/texteditor/behaviorsettingswidget.cpp index b21c709c219..044b2a328db 100644 --- a/src/plugins/texteditor/behaviorsettingswidget.cpp +++ b/src/plugins/texteditor/behaviorsettingswidget.cpp @@ -77,6 +77,13 @@ BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent) d->m_codecs.append(codec); } + // Qt5 doesn't list the system locale (QTBUG-34283), so add it manually + const QString system(QLatin1String("System")); + if (d->m_ui.encodingBox->findText(system) == -1) { + d->m_ui.encodingBox->insertItem(0, system); + d->m_codecs.prepend(QTextCodec::codecForLocale()); + } + connect(d->m_ui.autoIndent, SIGNAL(toggled(bool)), this, SLOT(slotTypingSettingsChanged())); connect(d->m_ui.smartBackspaceBehavior, SIGNAL(currentIndexChanged(int)), diff --git a/src/plugins/valgrind/memcheck/memcheckrunner.cpp b/src/plugins/valgrind/memcheck/memcheckrunner.cpp index 6827f6b47d7..91033203f6d 100644 --- a/src/plugins/valgrind/memcheck/memcheckrunner.cpp +++ b/src/plugins/valgrind/memcheck/memcheckrunner.cpp @@ -168,14 +168,14 @@ bool MemcheckRunner::start() } bool check = d->xmlServer.listen(hostAddr); - if (!check) emit processErrorReceived( tr("XmlServer on %1: ").arg(ip) + d->xmlServer.errorString(), QProcess::FailedToStart ); + if (!check) emit processErrorReceived( tr("XmlServer on %1:").arg(ip) + QLatin1Char(' ') + d->xmlServer.errorString(), QProcess::FailedToStart ); QTC_ASSERT(check, return false); d->xmlServer.setMaxPendingConnections(1); const quint16 xmlPortNumber = d->xmlServer.serverPort(); connect(&d->xmlServer, SIGNAL(newConnection()), SLOT(xmlSocketConnected())); check = d->logServer.listen(hostAddr); - if (!check) emit processErrorReceived( tr("LogServer on %1: ").arg(ip) + d->logServer.errorString(), QProcess::FailedToStart ); + if (!check) emit processErrorReceived( tr("LogServer on %1:").arg(ip) + QLatin1Char(' ') + d->logServer.errorString(), QProcess::FailedToStart ); QTC_ASSERT(check, return false); d->logServer.setMaxPendingConnections(1); const quint16 logPortNumber = d->logServer.serverPort(); diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index 202645a5d43..da1aa21fb38 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -40,6 +40,7 @@ #include +#include #include #include #include @@ -208,22 +209,14 @@ void WelcomeMode::facilitateQml(QQmlEngine * /*engine*/) static QString applicationDirPath() { -#ifdef Q_OS_WIN // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows - return Utils::normalizePathName(QCoreApplication::applicationDirPath()); -#else - return QCoreApplication::applicationDirPath(); -#endif + return Utils::FileUtils::normalizePathName(QCoreApplication::applicationDirPath()); } static QString resourcePath() { -#ifdef Q_OS_WIN // normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows - return Utils::normalizePathName(Core::ICore::resourcePath()); -#else - return Core::ICore::resourcePath(); -#endif + return Utils::FileUtils::normalizePathName(Core::ICore::resourcePath()); } void WelcomeMode::initPlugins() diff --git a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp index 90b131f3139..f95755bbdd2 100644 --- a/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp +++ b/src/tools/qtcreatorcrashhandler/crashhandlerdialog.cpp @@ -134,7 +134,7 @@ void CrashHandlerDialog::setApplicationInfo(const QString &signalName) QString revision; #ifdef IDE_REVISION - revision = tr(" from revision %1").arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10)); + revision = QLatin1Char(' ') + tr("from revision %1").arg(QString::fromLatin1(Core::Constants::IDE_REVISION_STR).left(10)); #endif const QString versionInformation = tr( "%1 %2%3, built on %4 at %5, based on Qt %6 (%7 bit)\n") diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 0bcb04d4975..2e6e1b3ed25 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -157,6 +157,9 @@ static QString toHex(const QString &str) } +struct GdbOnly {}; +struct LldbOnly {}; + struct Context { Context() : qtVersion(0) {} @@ -305,7 +308,22 @@ struct Type QByteArray type; }; -struct Check +enum DebuggerEngine +{ + DumpTestGdbEngine, + DumpTestCdbEngine, + DumpTestLldbEngine +}; + +struct CheckBase +{ + CheckBase() : useLldb(true), useGdb(true) {} + + mutable bool useLldb; + mutable bool useGdb; +}; + +struct Check : CheckBase { Check() {} @@ -320,6 +338,30 @@ struct Check expectedValue(value), expectedType(type) {} + bool matchesEngine(DebuggerEngine engine) const + { + return (engine == DumpTestLldbEngine && useLldb) + || (engine == DumpTestGdbEngine && useGdb); + } + + const Check &setForLldbOnly() const + { + clearUsed(); + useLldb = true; + return *this; + } + + const Check &setForGdbOnly() const + { + clearUsed(); + useGdb = true; + return *this; + } + + void clearUsed() const + { + useLldb = useGdb = false; + } QByteArray iname; Name expectedName; Value expectedValue; @@ -381,9 +423,6 @@ struct MacLibCppProfile : public Profile {} }; -struct GdbOnly {}; -struct LldbOnly {}; - struct GdbVersion { // Minimum and maximum are inclusive. @@ -454,7 +493,7 @@ public: const Data &operator%(const Check &check) const { - checks.insert("local." + check.iname, check); + checks.append(check); return *this; } @@ -532,7 +571,7 @@ public: mutable QByteArray profileExtra; mutable QByteArray includes; mutable QByteArray code; - mutable QMap checks; // IName -> Action + mutable QList checks; }; struct TempStuff @@ -549,13 +588,6 @@ struct TempStuff QString buildPath; }; -enum DebuggerEngine -{ - DumpTestGdbEngine, - DumpTestCdbEngine, - DumpTestLldbEngine -}; - Q_DECLARE_METATYPE(Data) class tst_Dumpers : public QObject @@ -997,26 +1029,36 @@ void tst_Dumpers::dumper() bool ok = true; foreach (const WatchData &item, list) { seenINames.insert(item.iname); - if (data.checks.contains(item.iname)) { - Check check = data.checks.take(item.iname); - if (!check.expectedName.matches(item.name.toLatin1(), context)) { - qDebug() << "INAME : " << item.iname; - qDebug() << "NAME ACTUAL : " << item.name.toLatin1(); - qDebug() << "NAME EXPECTED: " << check.expectedName.name; - ok = false; - } - if (!check.expectedValue.matches(item.value, context)) { - qDebug() << "INAME : " << item.iname; - qDebug() << "VALUE ACTUAL : " << item.value << toHex(item.value); - qDebug() << "VALUE EXPECTED: " - << check.expectedValue.value << toHex(check.expectedValue.value); - ok = false; - } - if (!check.expectedType.matches(item.type, context)) { - qDebug() << "INAME : " << item.iname; - qDebug() << "TYPE ACTUAL : " << item.type; - qDebug() << "TYPE EXPECTED: " << check.expectedType.type; - ok = false; + //qDebug() << "NUM CHECKS" << data.checks.size(); + for (int i = data.checks.size(); --i >= 0; ) { + Check check = data.checks.at(i); + //qDebug() << "CHECKS" << i << check.iname; + if ("local." + check.iname == item.iname) { + data.checks.removeAt(i); + if (check.matchesEngine(m_debuggerEngine)) { + //qDebug() << "USING MATCHING TEST FOR " << item.iname; + if (!check.expectedName.matches(item.name.toLatin1(), context)) { + qDebug() << "INAME : " << item.iname; + qDebug() << "NAME ACTUAL : " << item.name.toLatin1(); + qDebug() << "NAME EXPECTED: " << check.expectedName.name; + ok = false; + } + if (!check.expectedValue.matches(item.value, context)) { + qDebug() << "INAME : " << item.iname; + qDebug() << "VALUE ACTUAL : " << item.value << toHex(item.value); + qDebug() << "VALUE EXPECTED: " + << check.expectedValue.value << toHex(check.expectedValue.value); + ok = false; + } + if (!check.expectedType.matches(item.type, context)) { + qDebug() << "INAME : " << item.iname; + qDebug() << "TYPE ACTUAL : " << item.type; + qDebug() << "TYPE EXPECTED: " << check.expectedType.type; + ok = false; + } + } else { + qDebug() << "SKIPPING NON-MATCHING TEST FOR " << item.iname; + } } } } @@ -2190,7 +2232,7 @@ void tst_Dumpers::dumper_data() "QString dummy;\n" "QPoint s0, s;\n" "s = QPoint(100, 200);\n" - "unused(&s0, &s);\n") + "unused(&s0, &s, &dummy);\n") % CoreProfile() % Check("s0", "(0, 0)", "@QPoint") % Check("s", "(100, 200)", "@QPoint"); @@ -2200,7 +2242,8 @@ void tst_Dumpers::dumper_data() "#include // Dummy for namespace\n", "QString dummy;\n" "QPointF s0, s;\n" - "s = QPointF(100.5, 200.5);\n") + "s = QPointF(100.5, 200.5);\n" + "unused(&s0, &s, &dummy);\n") % CoreProfile() % Check("s0", "(0.0, 0.0)", "@QPointF") % Check("s", "(100.5, 200.5)", "@QPointF"); @@ -2210,8 +2253,9 @@ void tst_Dumpers::dumper_data() "#include // Dummy for namespace\n", "QString dummy;\n" "QRect rect0, rect;\n" - "rect = QRect(100, 100, 200, 200);\n") - % Check("rect", "0x0+0+0", "@QRect") + "rect = QRect(100, 100, 200, 200);\n" + "unused(&rect0, &rect, &dummy);\n") + % Check("rect0", "0x0+0+0", "@QRect") % Check("rect", "200x200+100+100", "@QRect"); QTest::newRow("QRectF") @@ -2219,8 +2263,9 @@ void tst_Dumpers::dumper_data() "#include // Dummy for namespace\n", "QString dummy;\n" "QRectF rect0, rect;\n" - "rect = QRectF(100.25, 100.25, 200.5, 200.5);\n") - % Check("rect", "0x0+0+0", "@QRectF") + "rect = QRectF(100.25, 100.25, 200.5, 200.5);\n" + "unused(&rect0, &rect, &dummy);\n") + % Check("rect0", "0.0x0.0+0.0+0.0", "@QRectF") % Check("rect", "200.5x200.5+100.25+100.25", "@QRectF"); QTest::newRow("QSize") @@ -2228,7 +2273,8 @@ void tst_Dumpers::dumper_data() "#include // Dummy for namespace\n", "QString dummy;\n" "QSize s0, s;\n" - "s = QSize(100, 200);\n") + "s = QSize(100, 200);\n" + "unused(&s0, &s, &dummy);\n") % CoreProfile() % Check("s0", "(-1, -1)", "@QSize") % Check("s", "(100, 200)", "@QSize"); @@ -2238,7 +2284,8 @@ void tst_Dumpers::dumper_data() "#include // Dummy for namespace\n", "QString dummy;\n" "QSizeF s0, s;\n" - "s = QSizeF(100.5, 200.5);\n") + "s = QSizeF(100.5, 200.5);\n" + "unused(&s0, &s, &dummy);\n") % CoreProfile() % Check("s0", "(-1.0, -1.0)", "@QSizeF") % Check("s", "(100.5, 200.5)", "@QSizeF"); @@ -2260,7 +2307,8 @@ void tst_Dumpers::dumper_data() % Check("region1.innerArea", "40000", "int") % Check("region1.innerRect", "200x200+100+100", "@QRect") % Check("region1.numRects", "1", "int") - % Check("region1.rects", "<1 items>", "@QVector<@QRect>") + // This seems to be 0(!) items on Linux, 1 on Mac + // % Check("region1.rects", "<1 items>", "@QVector<@QRect>") % Check("region2", "<2 items>", "@QRegion") % Check("region2.extents", "600x700+100+100", "@QRect") % Check("region2.innerArea", "200000", "int") @@ -2394,11 +2442,11 @@ void tst_Dumpers::dumper_data() "QWeakPointer ptr3 = ptr;\n" "unused(&ptr, &ptr2, &ptr3);\n") % CoreProfile() - % Check("iptr", "", "@QSharedPointer") + % Check("iptr", "43", "@QSharedPointer") % Check("iptr.data", "43", "int") % Check("iptr.weakref", "4", "int") % Check("iptr.strongref", "1", "int") - % Check("ptr3", "43", "int") + % Check("ptr3", "43", "@QWeakPointer") % Check("ptr3.data", "43", "int"); QTest::newRow("QSharedPointer4") @@ -2468,30 +2516,22 @@ void tst_Dumpers::dumper_data() QTest::newRow("StdComplex") << Data("#include \n", - "std::complex c(1, 2);\n") - % Check("c", "(1.000000, 2.000000)", "std::complex"); + "std::complex c(1, 2);\n" + "unused(&c);\n") + % Check("c", "(1.000000, 2.000000)", "std::complex") + % CheckType("c.real", "double"); - QTest::newRow("CComplexGdb") + QTest::newRow("CComplex") << Data("#include \n", "// Doesn't work when compiled as C++.\n" "double complex a = 0;\n" "double _Complex b = 0;\n" "unused(&a, &b);\n") % ForceC() - % GdbOnly() - % Check("a", "0 + 0 * I", "complex double") - % Check("b", "0 + 0 * I", "complex double"); - - QTest::newRow("CComplexLldb") - << Data("#include \n", - "// Doesn't work when compiled as C++.\n" - "double complex a = 0;\n" - "double _Complex b = 0;\n" - "unused(&a, &b);\n") - % ForceC() - % LldbOnly() - % Check("a", "0 + 0i", "_Complex double") - % Check("b", "0 + 0i", "_Complex double"); + % Check("a", "0 + 0 * I", "complex double").setForGdbOnly() + % Check("b", "0 + 0 * I", "complex double").setForGdbOnly() + % Check("a", "0 + 0i", "_Complex double").setForLldbOnly() + % Check("b", "0 + 0i", "_Complex double").setForLldbOnly(); QTest::newRow("StdDequeInt") << Data("#include \n", @@ -3393,8 +3433,6 @@ void tst_Dumpers::dumper_data() "value = QVariant(t, (void*)0);\n" "*(QString*)value.data() = QString(\"Some string\");\n") % CoreProfile() - % GdbOnly() - % Check("t", "@QVariant::String (10)", "@QVariant::Type") % Check("value", "\"Some string\"", "@QVariant (QString)"); QTest::newRow("QVariant1") @@ -3602,7 +3640,6 @@ void tst_Dumpers::dumper_data() "QVariant v = h;\n" "unused(&v);\n") % CoreProfile() - % GdbOnly() % Check("v", "<1 items>", "@QVariant (QVariantHash)") % Check("v.0", "[0]", "", "@QHashNode<@QString, @QVariant>") % Check("v.0.key", "\"one\"", "@QString") @@ -3615,7 +3652,6 @@ void tst_Dumpers::dumper_data() "QVariant v = h;\n" "unused(&v);\n") % CoreProfile() - % GdbOnly() % Check("v", "<1 items>", "@QVariant (QVariantMap)") % Check("v.0", "[0]", "", "@QMapNode<@QString, @QVariant>") % Check("v.0.key", "\"one\"", "@QString") @@ -3628,7 +3664,6 @@ void tst_Dumpers::dumper_data() "QVariant v = h;\n" "unused(&v);\n") % CoreProfile() - % GdbOnly() % Check("v", "<1 items>", "@QVariant (QVariantList)") % Check("v.0", "[0]", "\"one\"", "@QVariant (QString)"); @@ -3971,7 +4006,7 @@ void tst_Dumpers::dumper_data() % Check("foo.9", "[9]", "", "Foo"); - QTest::newRow("BitfieldsGdb") + QTest::newRow("Bitfields") << Data("struct S\n" "{\n" " S() : x(0), y(0), c(0), b(0), f(0), d(0), i(0) {}\n" @@ -3984,38 +4019,17 @@ void tst_Dumpers::dumper_data() " int i;\n" "} s;\n" "unused(&s);\n") - % GdbOnly() % Check("s", "", "S") % Check("s.b", "false", "bool") - % Check("s.c", "false", "bool") + % Check("s.c", "false", "bool:1").setForLldbOnly() + % Check("s.c", "false", "bool").setForGdbOnly() % Check("s.d", "0", "double") % Check("s.f", "0", "float") % Check("s.i", "0", "int") - % Check("s.x", "0", "unsigned int") - % Check("s.y", "0", "unsigned int"); - - QTest::newRow("BitfieldsLldb") - << Data("struct S\n" - "{\n" - " S() : x(0), y(0), c(0), b(0), f(0), d(0), i(0) {}\n" - " unsigned int x : 1;\n" - " unsigned int y : 1;\n" - " bool c : 1;\n" - " bool b;\n" - " float f;\n" - " double d;\n" - " int i;\n" - "} s;\n" - "unused(&s);\n") - % LldbOnly() - % Check("s", "", "S") - % Check("s.b", "false", "bool") - % Check("s.c", "false", "bool:1") - % Check("s.d", "0", "double") - % Check("s.f", "0", "float") - % Check("s.i", "0", "int") - % Check("s.x", "0", "unsigned int:1") - % Check("s.y", "0", "unsigned int:1"); + % Check("s.x", "0", "unsigned int:1").setForLldbOnly() + % Check("s.x", "0", "unsigned int").setForGdbOnly() + % Check("s.y", "0", "unsigned int:1").setForLldbOnly() + % Check("s.y", "0", "unsigned int").setForGdbOnly(); QTest::newRow("Function") @@ -4033,14 +4047,9 @@ void tst_Dumpers::dumper_data() "Function func(\"x\", \"sin(x)\", 0, 1);\n" "func.max = 10;\n" "func.f = \"cos(x)\";\n" - "func.max = 4;\n" - "func.max = 5;\n" - "func.max = 6;\n" "func.max = 7;\n") % CoreProfile() % Check("func", "", "Function") - % Check("func.f", "sin(x)", "@QByteArray") - % Check("func.max", "1", "double") % Check("func.min", "0", "double") % Check("func.var", "\"x\"", "@QByteArray") % Check("func", "", "Function") @@ -4322,19 +4331,14 @@ void tst_Dumpers::dumper_data() % Check("y2", "", "X") % Check("y3", "", "X"); - QTest::newRow("RValueReferenceGdb") + QTest::newRow("RValueReference") << Data(rvalueData) - % GdbOnly() - % Check("x1", "", "X &") - % Check("x2", "", "X &") - % Check("x3", "", "X &"); - - QTest::newRow("RValueReferenceLldb") - << Data(rvalueData) - % LldbOnly() - % Check("x1", "", "X &&") - % Check("x2", "", "X &&") - % Check("x3", "", "X &&"); + % Check("x1", "", "X &").setForGdbOnly() + % Check("x2", "", "X &").setForGdbOnly() + % Check("x3", "", "X &").setForGdbOnly() + % Check("x1", "", "X &&").setForLldbOnly() + % Check("x2", "", "X &&").setForLldbOnly() + % Check("x3", "", "X &&").setForLldbOnly(); QTest::newRow("SSE") << Data("#include \n" @@ -4888,6 +4892,7 @@ void tst_Dumpers::dumper_data() "int sharedPtr = 1;\n" "#endif\n" "unused(&ptrConst, &ref, &refConst, &ptrToPtr, &sharedPtr);\n") + % GdbOnly() % GdbVersion(70500) % BoostProfile() % Check("d", "", "Derived") @@ -4920,19 +4925,31 @@ void tst_Dumpers::dumper_data() // on -var-list-children on an anonymous union. mac/MI was fixed in 2006"); // The proposed fix has been reported to crash gdb steered from eclipse"); // http://sourceware.org/ml/gdb-patches/2011-12/msg00420.html - QTest::newRow("gdb10586mi") + QTest::newRow("gdb10586miGdb") << Data("struct Test {\n" " struct { int a; float b; };\n" " struct { int c; float d; };\n" "} v = {{1, 2}, {3, 4}};\n" "unused(&v);\n") + % GdbOnly() % Check("v", "", "Test") % Check("v.a", "1", "int"); - QTest::newRow("gdb10586eclipse") + QTest::newRow("gdb10586miLldb") + << Data("struct Test {\n" + " struct { int a; float b; };\n" + " struct { int c; float d; };\n" + "} v = {{1, 2}, {3, 4}};\n" + "unused(&v);\n") + % LldbOnly() + % Check("v", "", "Test") + % Check("v.#1.a", "1", "int"); + + QTest::newRow("gdb10586eclipseGdb") << Data("struct { int x; struct { int a; }; struct { int b; }; } v = {1, {2}, {3}};\n" "struct S { int x, y; } n = {10, 20};\n" "unused(&v, &n);\n") + % GdbOnly() % Check("v", "", "{...}") % Check("n", "", "S") % Check("v.a", "2", "int") @@ -4941,6 +4958,18 @@ void tst_Dumpers::dumper_data() % Check("n.x", "10", "int") % Check("n.y", "20", "int"); + QTest::newRow("gdb10586eclipseLldb") + << Data("struct { int x; struct { int a; }; struct { int b; }; } v = {1, {2}, {3}};\n" + "struct S { int x, y; } n = {10, 20};\n" + "unused(&v, &n);\n") + % LldbOnly() + % Check("v", "", "") + % Check("n", "", "S") + % Check("v.#1.a", "2", "int") + % Check("v.#2.b", "3", "int") + % Check("v.x", "1", "int") + % Check("n.x", "10", "int") + % Check("n.y", "20", "int"); QTest::newRow("stdint") << Data("#include \n", diff --git a/tests/auto/qml/codemodel/check/tst_check.cpp b/tests/auto/qml/codemodel/check/tst_check.cpp index a2bdefba585..f4da84c6524 100644 --- a/tests/auto/qml/codemodel/check/tst_check.cpp +++ b/tests/auto/qml/codemodel/check/tst_check.cpp @@ -111,7 +111,7 @@ void tst_Check::test() QFETCH(QString, path); Snapshot snapshot; - Document::MutablePtr doc = Document::create(path, Document::QmlLanguage); + Document::MutablePtr doc = Document::create(path, Language::Qml); QFile file(doc->fileName()); file.open(QFile::ReadOnly | QFile::Text); doc->setSource(file.readAll()); diff --git a/tests/auto/valgrind/memcheck/parsertests.h b/tests/auto/valgrind/memcheck/parsertests.h index 0059564cae5..91e74c8a53e 100644 --- a/tests/auto/valgrind/memcheck/parsertests.h +++ b/tests/auto/valgrind/memcheck/parsertests.h @@ -103,10 +103,8 @@ public: this, SLOT(internalError(QString))); connect(parser, SIGNAL(status(Valgrind::XmlProtocol::Status)), this, SLOT(status(Valgrind::XmlProtocol::Status))); - connect(runner, SIGNAL(standardErrorReceived(QByteArray)), - this, SLOT(standardErrorReceived(QByteArray))); - connect(runner, SIGNAL(standardOutputReceived(QByteArray)), - this, SLOT(standardOutputReceived(QByteArray))); + connect(runner, SIGNAL(processOutputReceived(QByteArray,Utils::OutputFormat)), + this, SLOT(handleProcessOutput(QByteArray,Utils::OutputFormat))); connect(runner, SIGNAL(logMessageReceived(QByteArray)), this, SLOT(logMessageReceived(QByteArray))); connect(runner, SIGNAL(processErrorReceived(QString, QProcess::ProcessError)), @@ -123,14 +121,9 @@ public slots: { qDebug() << "internal error received:" << error; } - void standardErrorReceived(const QByteArray &err) + void handleProcessOutput(const QByteArray &out, Utils::OutputFormat format) { - Q_UNUSED(err); - // qDebug() << "STDERR received:" << err; // this can be a lot of text - } - void standardOutputReceived(const QByteArray &out) - { - qDebug() << "STDOUT received:" << out; + qDebug() << "Output received:" << format << out; } void status(const Valgrind::XmlProtocol::Status &status) { diff --git a/tests/system/objects.map b/tests/system/objects.map index 92afa970b02..5eff1a358e2 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -152,7 +152,7 @@ :Qt Creator_Help::Internal::HelpViewer {type='Help::Internal::HelpViewer' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_HelpSelector_QComboBox {occurrence='3' type='QComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Issues_Core::Internal::OutputPaneToggleButton {occurrence='1' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} -:Qt Creator_ProFileEditorWidget {type='Qt4ProjectManager::Internal::ProFileEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} +:Qt Creator_ProFileEditorWidget {type='QmakeProjectManager::Internal::ProFileEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_PythonEditor::EditorWidget {type='PythonEditor::Internal::EditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_QDeclarativeView {type='QDeclarativeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_QHelpContentWidget {type='QHelpContentWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} @@ -163,10 +163,10 @@ :Qt Creator_SystemSettings.Details_Utils::DetailsButton {occurrence='4' text='Details' type='Utils::DetailsButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Utils::NavigationTreeView {type='Utils::NavigationTreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit {container=':Qt Creator_Utils::NavigationTreeView' type='QExpandingLineEdit' unnamed='1' visible='1'} -:Qt Gui Application.Form file:_QLabel {name='formLabel' text='Form file:' type='QLabel' visible='1' window=':Qt Gui Application_Qt4ProjectManager::Internal::GuiAppWizardDialog'} -:Qt Gui Application.Header file:_QLabel {name='headerLabel' text='Header file:' type='QLabel' visible='1' window=':Qt Gui Application_Qt4ProjectManager::Internal::GuiAppWizardDialog'} -:Qt Gui Application.Source file:_QLabel {name='sourceLabel' text='Source file:' type='QLabel' visible='1' window=':Qt Gui Application_Qt4ProjectManager::Internal::GuiAppWizardDialog'} -:Qt Gui Application_Qt4ProjectManager::Internal::GuiAppWizardDialog {type='Qt4ProjectManager::Internal::GuiAppWizardDialog' unnamed='1' visible='1' windowTitle='Qt Gui Application'} +:Qt Gui Application.Form file:_QLabel {name='formLabel' text='Form file:' type='QLabel' visible='1' window=':Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog'} +:Qt Gui Application.Header file:_QLabel {name='headerLabel' text='Header file:' type='QLabel' visible='1' window=':Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog'} +:Qt Gui Application.Source file:_QLabel {name='sourceLabel' text='Source file:' type='QLabel' visible='1' window=':Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog'} +:Qt Gui Application_QmakeProjectManager::Internal::GuiAppWizardDialog {type='QmakeProjectManager::Internal::GuiAppWizardDialog' unnamed='1' visible='1' windowTitle='Qt Widgets Application'} :QtSupport__Internal__QtVersionManager.QLabel {container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' type='QLabel' unnamed='1' visible='1'} :QtSupport__Internal__QtVersionManager.errorLabel.QLabel {container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' name='errorLabel' type='QLabel' visible='1'} :QtSupport__Internal__QtVersionManager.qmake_QLabel {container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' name='qmakePath' type='QLabel' visible='1'} diff --git a/tests/system/settings/unix/QtProject/qtcreator/debuggers.xml b/tests/system/settings/unix/QtProject/qtcreator/debuggers.xml new file mode 100644 index 00000000000..0f31f081d68 --- /dev/null +++ b/tests/system/settings/unix/QtProject/qtcreator/debuggers.xml @@ -0,0 +1,26 @@ + + + + + + DebuggerItem.0 + + + unknown-linux-generic-elf-unknown + + true + /usr/bin/gdb + System GDB at /usr/bin/gdb + 1 + {70e26273-2c0b-4534-bbc0-eb6ca670821a} + + + + DebuggerItem.Count + 1 + + + Version + 1 + + diff --git a/tests/system/settings/unix/QtProject/qtcreator/profiles.xml b/tests/system/settings/unix/QtProject/qtcreator/profiles.xml index 7eac69d2dfe..9c9cadcee98 100644 --- a/tests/system/settings/unix/QtProject/qtcreator/profiles.xml +++ b/tests/system/settings/unix/QtProject/qtcreator/profiles.xml @@ -1,6 +1,6 @@ - + Profile.0 @@ -8,7 +8,7 @@ false - /usr/bin/gdb + {70e26273-2c0b-4534-bbc0-eb6ca670821a} Desktop Device Desktop @@ -18,6 +18,7 @@ :///DESKTOP/// {4d9ea3ed-a7f0-4b0e-885f-da3b82931988} + Desktop 474 GCC false @@ -28,7 +29,7 @@ false - /usr/bin/gdb + {70e26273-2c0b-4534-bbc0-eb6ca670821a} Desktop Device Desktop @@ -38,6 +39,7 @@ :///DESKTOP/// {68d379f6-357c-42a6-83c6-7743840db4ea} + Qt Simulator false @@ -48,7 +50,7 @@ false - /usr/bin/gdb + {70e26273-2c0b-4534-bbc0-eb6ca670821a} {68a75dff-5ec6-40cb-884f-8f383ed2ebb2} Maemo5OsType @@ -58,6 +60,7 @@ :///DESKTOP/// {f559999e-8f5d-4246-9321-ea9d1c444c85} + Fremantle false @@ -68,10 +71,7 @@ false - - /usr/bin/gdb - 1 - + {70e26273-2c0b-4534-bbc0-eb6ca670821a} {1a0985cf-ad32-487c-8af8-85ee532ac19c} HarmattanOsType @@ -81,6 +81,7 @@ :///DESKTOP/// {744799ff-3430-41e1-ad7d-d76c50c1c621} + Harmattan false @@ -91,10 +92,7 @@ false - - /usr/bin/gdb - 1 - + {70e26273-2c0b-4534-bbc0-eb6ca670821a} {7c5a3673-e300-4286-9666-0f86d3e3dc38} GenericLinuxOsType @@ -104,6 +102,7 @@ :///DESKTOP/// {f16848fc-b615-43b5-b0cc-16a9f57fb573} + Embedded Linux false @@ -114,7 +113,7 @@ false - /usr/bin/gdb + {70e26273-2c0b-4534-bbc0-eb6ca670821a} Desktop Device Desktop @@ -124,6 +123,7 @@ :///DESKTOP/// {9c58fcfd-9e49-4a08-971f-a677dc9ce185} + Desktop 501 default false @@ -134,7 +134,7 @@ false - /usr/bin/gdb + {70e26273-2c0b-4534-bbc0-eb6ca670821a} Desktop Device Desktop @@ -144,6 +144,7 @@ :///DESKTOP/// {1dcb5509-1670-470d-80a5-8a988f36e4e2} + Desktop 480 GCC false diff --git a/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml b/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml new file mode 100644 index 00000000000..f9bac448c4a --- /dev/null +++ b/tests/system/settings/windows/QtProject/qtcreator/debuggers.xml @@ -0,0 +1,50 @@ + + + + + + DebuggerItem.0 + + + x86-windows-msvc2010-pe-64bit + + true + C:\Program Files\Debugging Tools for Windows (x64)\cdb.exe + Auto-detected CDB at C:\Program Files\Debugging Tools for Windows (x64)\cdb.exe + 4 + {811977c9-ea95-4616-bc28-c66d1935ff65} + + + + DebuggerItem.1 + + + true + C:\QtSDK\pythongdb\python_2.7based\gdb-i686-pc-mingw32.exe + Extracted from Kit Desktop 474 GCC + 1 + {44aee0bd-999d-4abe-82c6-5c7979e7cf01} + + + + DebuggerItem.2 + + + arm-linux-generic-elf-32bit + + true + C:\QtSDK\pythongdb\python_2.7based\gdb-arm-none-linux-gnueabi.exe + Extracted from Kit Fremantle + 1 + {5ad1d623-7300-41b4-ba32-99e11bfcb988} + + + + DebuggerItem.Count + 3 + + + Version + 1 + + diff --git a/tests/system/settings/windows/QtProject/qtcreator/profiles.xml b/tests/system/settings/windows/QtProject/qtcreator/profiles.xml index faa3216ef03..09cf47de68e 100644 --- a/tests/system/settings/windows/QtProject/qtcreator/profiles.xml +++ b/tests/system/settings/windows/QtProject/qtcreator/profiles.xml @@ -1,6 +1,6 @@ - + Profile.0 @@ -8,7 +8,7 @@ false - C:/QtSDK/pythongdb/python_2.7based/gdb-i686-pc-mingw32.exe + {44aee0bd-999d-4abe-82c6-5c7979e7cf01} Desktop Device Desktop @@ -18,6 +18,7 @@ :///DESKTOP/// {897290fe-c35a-4e5e-b5e2-d8e448e2aed1} + Desktop 474 GCC false @@ -28,7 +29,7 @@ false - C:/QtSDK/pythongdb/python_2.7based/gdb-i686-pc-mingw32.exe + {44aee0bd-999d-4abe-82c6-5c7979e7cf01} Desktop Device Desktop @@ -38,6 +39,7 @@ :///DESKTOP/// {0ce9f69f-0f60-4b04-8691-c328ee5bfe14} + Qt Simulator false @@ -48,7 +50,7 @@ false - C:/QtSDK/pythongdb/python_2.7based/gdb-arm-none-linux-gnueabi.exe + {5ad1d623-7300-41b4-ba32-99e11bfcb988} {0d112162-56a5-40cb-a911-e0545489da5c} Maemo5OsType @@ -58,6 +60,7 @@ :///DESKTOP/// {618722a5-c008-4869-9404-07f755973496} + Fremantle false @@ -68,10 +71,7 @@ false - - C:\QtSDK\pythongdb\python_2.7based\gdb-arm-none-linux-gnueabi.exe - 1 - + {5ad1d623-7300-41b4-ba32-99e11bfcb988} {3260da4e-2949-43b8-b464-1f34d0a47c04} HarmattanOsType @@ -81,6 +81,7 @@ :///DESKTOP/// {3800d54f-6c86-4cd1-88a9-7456bbef6dce} + Harmattan false @@ -91,10 +92,7 @@ false - - C:\Program Files\Debugging Tools for Windows (x64)\cdb.exe - 4 - + {811977c9-ea95-4616-bc28-c66d1935ff65} Desktop Device Desktop @@ -104,6 +102,7 @@ :///DESKTOP/// {9b35bbe6-25a7-4cce-ba07-487c795f5265} + Desktop 480 MSVC2010 false @@ -114,10 +113,7 @@ false - - C:\Program Files\Debugging Tools for Windows (x64)\cdb.exe - 4 - + {811977c9-ea95-4616-bc28-c66d1935ff65} Desktop Device Desktop @@ -127,6 +123,7 @@ :///DESKTOP/// {175f6238-a585-4e62-b2d3-d15e90296bb6} + Desktop 501 default false @@ -137,7 +134,7 @@ false - C:/QtSDK/pythongdb/python_2.7based/gdb-i686-pc-mingw32.exe + {44aee0bd-999d-4abe-82c6-5c7979e7cf01} Desktop Device Desktop @@ -147,6 +144,7 @@ :///DESKTOP/// {9dc9de67-fdc0-4ba6-877a-1463aacd3b3e} + Desktop 480 GCC false diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py index 9a883915792..d4fbfbd9c0f 100644 --- a/tests/system/shared/debugger.py +++ b/tests/system/shared/debugger.py @@ -49,11 +49,12 @@ def handleDebuggerWarnings(config, isMsvcBuild=False): except LookupError: pass # No warning. Fine. if "Release" in config and (isMsvcBuild or platform.system() == "Linux"): - message = waitForObject("{container=':Qt Creator.DebugModeWidget_QSplitter' name='qt_msgbox_label' type='QLabel' visible='1'}") + msgBox = "{type='QMessageBox' unnamed='1' visible='1' windowTitle='Warning'}" + message = waitForObject("{name='qt_msgbox_label' type='QLabel' visible='1' window=%s}" % msgBox) messageText = str(message.text) test.verify(messageText.startswith('This does not seem to be a "Debug" build.\nSetting breakpoints by file name and line number may fail.'), "Got warning: %s" % messageText) - clickButton("{container=':Qt Creator.DebugModeWidget_QSplitter' text='OK' type='QPushButton' unnamed='1' visible='1'}") + clickButton("{text='OK' type='QPushButton' unnamed='1' visible='1' window=%s}" % msgBox) def takeDebuggerLog(): invokeMenuItem("Window", "Views", "Debugger Log") diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index f5aa4d3298d..16243564e8d 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -175,7 +175,7 @@ def __verifyFileCreation__(path, expectedFiles): # param projectName is the name for the new project # param checks turns tests in the function on if set to True def createProject_Qt_GUI(path, projectName, checks = True): - template = "Qt Gui Application" + template = "Qt Widgets Application" available = __createProjectOrFileSelectType__(" Applications", template) __createProjectSetNameAndPath__(path, projectName, checks) checkedTargets = __selectQtVersionDesktop__(checks, available) @@ -322,8 +322,7 @@ def createNewNonQtProject(workingDir=None, projectName=None, target=Targets.DESK # parameter target can be an OR'd value of Targets # parameter availableTargets should be the result of __createProjectOrFileSelectType__() # or use None as a fallback -def __chooseTargets__(targets=Targets.DESKTOP_474_GCC, availableTargets=None, - isMaddeDisabled=True): +def __chooseTargets__(targets=Targets.DESKTOP_474_GCC, availableTargets=None): if availableTargets != None: available = availableTargets else: @@ -333,10 +332,9 @@ def __chooseTargets__(targets=Targets.DESKTOP_474_GCC, availableTargets=None, if platform.system() in ('Windows', 'Microsoft'): available.remove(Targets.EMBEDDED_LINUX) available.append(Targets.DESKTOP_480_MSVC2010) - if isMaddeDisabled: - for target in filter(lambda x: x in available, - (Targets.MAEMO5, Targets.HARMATTAN)): - available.remove(target) + for target in filter(lambda x: x in available, + (Targets.MAEMO5, Targets.HARMATTAN)): + available.remove(target) checkedTargets = [] for current in available: mustCheck = targets & current == current diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py index 335f6ce1873..3279980aab7 100644 --- a/tests/system/shared/utils.py +++ b/tests/system/shared/utils.py @@ -373,7 +373,7 @@ def __checkParentAccess__(filePath): # this function checks for all configured Qt versions inside # options dialog and returns a dict holding the kits as keys # and a list of information of its configured Qt -def getConfiguredKits(isMaddeDisabled=True): +def getConfiguredKits(): def __retrieveQtVersionName__(target, version): treeWidget = waitForObject(":QtSupport__Internal__QtVersionManager.qtdirList_QTreeWidget") return treeWidget.currentItem().text(0) @@ -393,8 +393,8 @@ def getConfiguredKits(isMaddeDisabled=True): iterateKits(True, True, __setQtVersionForKit__, kitsWithQtVersionName) # merge defined target names with their configured Qt versions and devices for kit, qtVersion in kitsWithQtVersionName.iteritems(): - if isMaddeDisabled and kit in ('Fremantle', 'Harmattan') and qtVersion == 'None': - test.log("Found Kit '%s' with unassigned Qt version (disabled Madde plugin)" % kit) + if kit in ('Fremantle', 'Harmattan') and qtVersion == 'None': + test.log("Found Kit '%s' with unassigned Qt version (disabled Madde plugin)" % kit) elif qtVersion in qtVersionNames: result[kit] = targetsQtVersions[qtVersionNames.index(qtVersion)].items()[0] else: diff --git a/tests/system/suite_debugger/tst_cli_output_console/test.py b/tests/system/suite_debugger/tst_cli_output_console/test.py index 826049cf7b0..ee5302ad33d 100644 --- a/tests/system/suite_debugger/tst_cli_output_console/test.py +++ b/tests/system/suite_debugger/tst_cli_output_console/test.py @@ -73,6 +73,7 @@ def main(): test.log("Testing build configuration: " + config) test.log("Running application") + progressBarWait(15000) setRunInTerminal(len(checkedTargets), kit, False) runControlFinished = False clickButton(waitForObject(":*Qt Creator.Run_Core::Internal::FancyToolButton")) diff --git a/tests/system/suite_debugger/tst_debug_empty_main/test.py b/tests/system/suite_debugger/tst_debug_empty_main/test.py index a055bcd0a91..ab62d7dc87d 100644 --- a/tests/system/suite_debugger/tst_debug_empty_main/test.py +++ b/tests/system/suite_debugger/tst_debug_empty_main/test.py @@ -78,6 +78,7 @@ def main(): replaceEditorContent(editor, "") typeLines(editor, ["int main() {"]) invokeMenuItem("File", "Save All") + progressBarWait(15000) setRunInTerminal(1, 0, False) performDebugging(workingDir, projectName, [singleTarget]) invokeMenuItem("File", "Close All Projects and Editors") diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py index 21a8d29525a..77fee043a24 100644 --- a/tests/system/suite_general/tst_create_proj_wizard/test.py +++ b/tests/system/suite_general/tst_create_proj_wizard/test.py @@ -33,6 +33,7 @@ import re def main(): global tmpSettingsDir + global textChanged sourceExample = os.path.abspath(sdkPath + "/Examples/4.7/declarative/text/textselection") qmlFile = os.path.join("qml", "textselection.qml") if not neededFilePresent(os.path.join(sourceExample, qmlFile)): @@ -44,19 +45,7 @@ def main(): overrideInstallLazySignalHandler() installLazySignalHandler(":frame.templateDescription_QTextBrowser", "textChanged()","__handleTextChanged__") - performTest(templateDir, qmlFile, True) - enableMaddePlugin() - invokeMenuItem("File", "Exit") - waitForCleanShutdown() - copySettingsToTmpDir(tmpSettingsDir, ['QtCreator.ini']) - overrideStartApplication() - startApplication("qtcreator" + SettingsPath) - performTest(templateDir, qmlFile, False) - invokeMenuItem("File", "Exit") - -def performTest(templateDir, qmlFile, isMaddeDisabled): - global textChanged - kits = getConfiguredKits(isMaddeDisabled) + kits = getConfiguredKits() test.log("Collecting potential project types...") availableProjectTypes = [] invokeMenuItem("File", "New File or Project...") @@ -69,7 +58,7 @@ def performTest(templateDir, qmlFile, isMaddeDisabled): maddeTargets = Targets.getTargetsAsStrings([Targets.MAEMO5, Targets.HARMATTAN]) maddeInTargets = len(set(targets) & set(maddeTargets)) > 0 test.verify(comboBox.enabled, "Verifying whether combobox is enabled.") - test.compare(maddeInTargets, not isMaddeDisabled, "Verifying if kits are configured.") + test.verify(not maddeInTargets, "Verify there are no leftovers of Madde") test.compare(comboBox.currentText, "Desktop Templates") selectFromCombo(comboBox, "All Templates") for category in [item.replace(".", "\\.") for item in dumpItems(catModel, projects)]: @@ -133,17 +122,7 @@ def performTest(templateDir, qmlFile, isMaddeDisabled): test.fail("Found unexpected additional kit(s) %s on 'Kit Selection' page." % str(availableCheckboxes)) clickButton(waitForObject("{text='Cancel' type='QPushButton' unnamed='1' visible='1'}")) - -def enableMaddePlugin(): - invokeMenuItem("Help", "About Plugins...") - pluginsTW = waitForObject(":Installed Plugins.categoryWidget_QTreeWidget") - devSupport = ("{container=':Installed Plugins.categoryWidget_QTreeWidget' " - "column='0' text='Device Support' type='QModelIndex'}") - # children position + 1 because children will be counted beginning with 0 - maddePos = dumpItems(pluginsTW.model(), waitForObject(devSupport)).index('Madde') + 1 - mouseClick(waitForObject("{column='1' container=%s text='' type='QModelIndex' " - "occurrence='%d'}" % (devSupport, maddePos)), 5, 5, 0, Qt.LeftButton) - clickButton(":Installed Plugins.Close_QPushButton") + invokeMenuItem("File", "Exit") def __handleTextChanged__(*args): global textChanged diff --git a/tests/system/suite_tools/tst_git_clone/test.py b/tests/system/suite_tools/tst_git_clone/test.py index 0bc5400bc09..6ccbfb760b4 100644 --- a/tests/system/suite_tools/tst_git_clone/test.py +++ b/tests/system/suite_tools/tst_git_clone/test.py @@ -79,7 +79,7 @@ def main(): replaceEditorContent(cloneDirEdit, cloneDir) clickButton(waitForObject(":Next_QPushButton")) test.compare(waitForObject(":Git Repository Clone.Result._QLabel").text, - "Checkout started...") + "Cloning started...") if button == "Cancel immediately": clickButton(":Git Repository Clone.Cancel_QPushButton") verifyCloneLog(targetDir, True)
Signal name : %1