Merge remote-tracking branch 'origin/4.2'

Change-Id: I3a54f679238e6eb4f053608286fc39eae3041561
This commit is contained in:
Eike Ziller
2016-10-17 16:22:04 +02:00
157 changed files with 4676 additions and 5430 deletions

View File

@@ -19,6 +19,9 @@ Prerequisites:
* ActiveState Active Perl
* MinGW with g++ 4.8 or Visual Studio 2015 or later
* jom
The optional Clang code model requires LLVM. A manual build of it requires in addition:
* cmake
* On Mac OS X: latest Xcode
* On Linux: g++ 4.8 or later
* LLVM 3.8.0 or later (optional, needed for the Clang Code Model)
@@ -118,9 +121,32 @@ For detailed information on the supported compilers, see
command...` error. If a `sh.exe` is found, the compile process will fail.
You have to remove it from the path.
10. To enable the Clang-based code model: Install Clang (>= version 3.8.0)
and set the environment variable LLVM_INSTALL_DIR to point to the
10. As of Qt Creator 4.2, a complete build of LLVM and Clang is required
to enable the Clang-based code model (recommmended: 3.9). For 32bit,
a pre-built package can be downloaded from:
https://download.qt.io/development_releases/prebuilt/libclang/.
The environment variable LLVM_INSTALL_DIR needs to be set to point to the
installation location.
It is also possible to build Clang manually, roughly following the
instructions at http://llvm.org/docs/GettingStarted.html#git-mirror .
* Clone LLVM
git clone http://llvm.org/git/llvm.git
* Switch to a suitable branch, for example, release_39
cd llvm
git checkout -b release_39
* Clone Clang under llvm\tools
cd tools
git clone http://llvm.org/git/clang.git
* Switch Clang to a suitable branch
cd clang
git checkout -b release_39
* Create a shadow build directory and build
cd ..\..\..
mkdir build
cd build
cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<installation location> -DLLVM_ENABLE_RTTI=ON ..\llvm
jom install
11. You are now ready to configure and build Qt and Qt Creator.
Please see <https://wiki.qt.io/Building_Qt_5_from_Git> for

72
dist/changes-4.1.1.md vendored Normal file
View File

@@ -0,0 +1,72 @@
Qt Creator version 4.1.1 contains bug fixes.
The most important changes are listed in this document. For a complete
list of changes, see the Git log for the Qt Creator sources that
you can check out from the public Git repository. For example:
git clone git://code.qt.io/qt-creator/qt-creator.git
git log --cherry-pick --pretty=oneline v4.1.0..v4.1.1
General
* Fixed issues with output pane height
(QTCREATORBUG-15986, QTCREATORBUG-16829)
Editing
* Fixed performance of cleaning whitespace (QTCREATORBUG-16420)
* Fixed selection color in help viewer for dark theme (QTCREATORBUG-16375)
Help
* Fixed that no results could be shown in Locator (QTCREATORBUG-16753)
QMake Projects
* Fixed issue with make steps in deploy configurations (QTCREATORBUG-16795)
Qbs Projects
* Fixed handling of generated files (QTCREATORBUG-16976)
QML Support
* Fixed handling of circular dependencies (QTCREATORBUG-16585)
Debugging
* Fixed scrolling in memory editor (QTCREATORBUG-16751)
* Fixed expansion of items in tool tip (QTCREATORBUG-16947)
* GDB
* Fixed handling of built-in pretty printers from new versions of GDB
(QTCREATORBUG-16758)
* Fixed that remote working directory was used for local process
(QTCREATORBUG-16211)
* CDB
* Fixed display order of vectors in vectors (QTCREATORBUG-16813)
* Fixed display of QList contents (QTCREATORBUG-16750)
QML Profiler
* Separated compile events from other QML/JS events in statistics and
flamegraph, since compilation can happen asynchronously
Beautifier
* Fixed that beautifier was not enabled for Objective-C/C++ files
(QTCREATORBUG-16806)
Platform Specific
macOS
* Fixed issue with detecting LLDB through `xcrun`
Android
* Added API level 24 for Android 7
* Fixed debugging on Android 6+ with NDK r11+ (QTCREATORBUG-16721)
iOS
* Fixed QML debugging on device (QTCREATORBUG-15812)

View File

@@ -38,12 +38,14 @@
\title Specifying Build Settings
Different build configurations allow you to quickly switch between
different build settings. By default, \QC creates \b debug
and \b release build configurations. A debug build contains additional
different build settings. By default, \QC creates \e debug, \e release, and
\e profile build configurations. A debug build contains additional
debug symbols that you need for debugging the application but that you
can leave out from the release version. Generally, you use the debug
configuration for testing and the release configuration for creating
the final installation file.
the final installation file. A profile configuration is an optimized release
build that is delivered with separate debug information. It is best suited
for analyzing applications.
You specify build settings in the \uicontrol Projects mode.
To add a new build configuration, click \uicontrol Add and select the type of

111
scripts/createSourcePackages.py Executable file
View File

@@ -0,0 +1,111 @@
#!/usr/bin/env python
############################################################################
#
# Copyright (C) 2016 The Qt Company Ltd.
# Contact: https://www.qt.io/licensing/
#
# 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 The Qt Company. For licensing terms
# and conditions see https://www.qt.io/terms-conditions. For further
# information use the contact form at https://www.qt.io/contact-us.
#
# GNU General Public License Usage
# Alternatively, this file may be used under the terms of the GNU
# General Public License version 3 as published by the Free Software
# Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
# included in the packaging of this file. Please review the following
# information to ensure the GNU General Public License requirements will
# be met: https://www.gnu.org/licenses/gpl-3.0.html.
#
############################################################################
import argparse
import os
import shutil
import subprocess
import tempfile
def archive(repository, target_file, prefix='', crlf=False):
crlf_args = (['-c', 'core.autocrlf=true', '-c', 'core.eol=crlf'] if crlf
else [])
subprocess.check_call(['git'] + crlf_args +
['archive', '--format=tar', '--prefix=' + prefix,
'-o', target_file, 'HEAD'],
cwd=repository)
def extract_combined(archive_list, target_dir):
if not os.path.exists(target_dir):
os.makedirs(target_dir)
for a in archive_list:
subprocess.check_call(['tar', 'xf', a], cwd=target_dir)
def createTarGz(source_dir, target_file):
(cwd, path) = os.path.split(source_dir)
subprocess.check_call(['tar', 'czf', target_file, path], cwd=cwd)
def createTarXz(source_dir, target_file):
(cwd, path) = os.path.split(source_dir)
subprocess.check_call(['tar', 'cJf', target_file, path], cwd=cwd)
def createZip(source_dir, target_file):
(cwd, path) = os.path.split(source_dir)
subprocess.check_call(['zip', '-9qr', target_file, path], cwd=cwd)
def package_repos(repos, combined_prefix, target_file_base):
workdir = tempfile.mkdtemp(suffix="-createQtcSource")
def crlf_postfix(crlf):
return '_win' if crlf else ''
def tar_name(name, crlf):
sanitized_name = name.replace('/', '_').replace('\\', '_')
return os.path.join(workdir, sanitized_name + crlf_postfix(crlf) + '.tar')
def archive_path(crlf=False):
return os.path.join(workdir, 'src' + crlf_postfix(crlf), combined_prefix)
print('Working in "' + workdir + '"')
print('Pre-packaging archives...')
for (name, repo, prefix) in repos:
print(' ' + name + '...')
for crlf in [False, True]:
archive(repo, tar_name(name, crlf), prefix, crlf=crlf)
print('Preparing for packaging...')
for crlf in [False, True]:
archive_list = [tar_name(name, crlf) for (name, _, _) in repos]
extract_combined(archive_list, archive_path(crlf))
print('Creating .tar.gz...')
createTarGz(archive_path(crlf=False), target_file_base + '.tar.gz')
print('Creating .tar.xz...')
createTarGz(archive_path(crlf=False), target_file_base + '.tar.xz')
print('Creating .zip with CRLF...')
createZip(archive_path(crlf=True), target_file_base + '.zip')
print('Removing temporary directory...')
shutil.rmtree(workdir)
def parse_arguments():
script_path = os.path.dirname(os.path.realpath(__file__))
qtcreator_repo = os.path.join(script_path, '..')
parser = argparse.ArgumentParser(description="Create Qt Creator source packages")
parser.add_argument('-p', default=qtcreator_repo, dest='repo', help='path to repository')
parser.add_argument('-n', default='', dest='name', help='name of plugin')
parser.add_argument('-s', action='append', default=[], dest='modules', help='submodule to add')
parser.add_argument('version', help='full version including tag, e.g. 4.2.0-beta1')
parser.add_argument('edition', help='(opensource | enterprise)')
return parser.parse_args()
def main():
args = parse_arguments()
base_repo_name = args.name if args.name else "qtcreator"
if not args.name and not args.modules: # default Qt Creator repository
args.modules = [os.path.join('src', 'shared', 'qbs')]
repos = [(base_repo_name, args.repo, '')]
for module in args.modules:
repos += [(module, os.path.join(args.repo, module), module + os.sep)]
name_part = '-' + args.name if args.name else ''
prefix = 'qt-creator-' + args.edition + name_part + '-src-' + args.version
package_repos(repos, prefix, os.path.join(os.getcwd(), prefix))
if __name__ == "__main__":
main()

View File

@@ -1,55 +0,0 @@
#!/bin/bash
## Command line parameters
if [[ $# != 2 ]]; then
cat <<USAGE
usage:
$0 <version> <edition>
Creates tar and zip source package from HEAD of the main repository and submodules.
Files and directories are named after qt-creator-<edition>-src-<version>.
example:
$0 2.2.0-beta opensource
USAGE
exit 1
fi
VERSION=$1
EDITION=$2
PREFIX=qt-creator-${EDITION}-src-${VERSION}
cd `dirname $0`/..
RESULTDIR=`pwd`
TEMPSOURCES=`mktemp -d -t qtcCreatorSourcePackage.XXXXXX`
echo "Temporary directory: ${TEMPSOURCES}"
echo "Creating tar archive..."
echo " Creating tar sources of repositories..."
git archive --format=tar --prefix=${PREFIX}/ HEAD > ${TEMPSOURCES}/__qtcreator_main.tar || exit 1
echo " qbs..."
cd src/shared/qbs || exit 1
git archive --format=tar --prefix=${PREFIX}/src/shared/qbs/ HEAD > ${TEMPSOURCES}/__qtcreator_qbs.tar || exit 1
echo " Combining tar sources..."
cd ${TEMPSOURCES} || exit 1
tar xf __qtcreator_main.tar || exit 1
tar xf __qtcreator_qbs.tar || exit 1
tar czf "${RESULTDIR}/${PREFIX}.tar.gz" ${PREFIX}/ || exit 1
tar cJf "${RESULTDIR}/${PREFIX}.tar.xz" ${PREFIX}/ || exit 1
echo "Creating zip archive..."
echo " Filtering binary vs text files..."
# write filter for text files (for use with 'file' command)
echo ".*:.*ASCII
.*:.*directory
.*:.*empty
.*:.*POSIX
.*:.*html
.*:.*text" > __txtpattern || exit 1
# list all files
find ${PREFIX} > __packagedfiles || exit 1
# record file types
file -f __packagedfiles > __filetypes || exit 1
echo " Creating archive..."
# zip text files and binary files separately
cat __filetypes | grep -f __txtpattern -v | cut -d: -f1 | zip -9q "${RESULTDIR}/${PREFIX}.zip" -@ || exit 1
cat __filetypes | grep -f __txtpattern | cut -d: -f1 | zip -l9q "${RESULTDIR}/${PREFIX}.zip" -@ || exit 1

View File

@@ -196,3 +196,9 @@ class Dumper(DumperBase):
def nativeDynamicTypeName(self, address, baseType):
return None # FIXME: Seems sufficient, no idea why.
def callHelper(self, rettype, value, function, args):
raise Exception("cdb does not support calling functions")
def putCallItem(self, name, rettype, value, func, *args):
return

View File

@@ -2999,6 +2999,8 @@ class DumperBase:
return self.code in (TypeCodeIntegral, TypeCodeFloat, TypeCodeEnum)
def alignment(self):
if self.code == TypeCodeTypedef:
return self.stripTypedefs().alignment()
if self.isSimpleType():
if self.name == 'double':
return self.dumper.ptrSize() # Crude approximation.
@@ -3371,7 +3373,9 @@ class DumperBase:
builder.addField(ptrSize, 'Q' if ptrSize == 8 else 'I')
elif c == 'P': # Pointer as Value
builder.addField(ptrSize, '%ss' % ptrSize)
elif c in ('q', 'Q', 'd'):
elif c in ('d'):
builder.addField(8, c, fieldType = 'double')
elif c in ('q', 'Q'):
builder.addField(8, c)
elif c in ('i', 'I', 'f'):
builder.addField(4, c)

View File

@@ -353,6 +353,7 @@ def qdump__QDateTime(d, value):
def qdump__QDir(d, value):
if not d.isMsvcTarget():
d.putNumChild(1)
privAddress = d.extractPointer(value)
bit32 = d.ptrSize() == 4
@@ -424,7 +425,7 @@ def qdump__QDir(d, value):
absoluteDirEntryOffset = dirEntryOffset + fileSystemEntrySize
d.putStringValue(privAddress + dirEntryOffset)
if d.isExpanded():
if d.isExpanded() and not d.isMsvcTarget():
with Children(d):
ns = d.qtNamespace()
d.call('int', value, 'count') # Fill cache.
@@ -1042,7 +1043,7 @@ def qdump__QPixmap(d, value):
else:
(dummy, width, height) = d.split('pii', dataPtr)
d.putValue('(%dx%d)' % (width, height))
d.putNumChild(0)
d.putPlainChildren(value)
def qdump__QPoint(d, value):

View File

@@ -213,12 +213,20 @@ def qform__std__map():
def qdump__std__map(d, value):
if d.isQnxTarget():
qdump__std__map__QNX(d, value)
proxy, head, size = value.split('ppI')
d.putItemCount(size)
qdump_std__map__helper(d, size, value)
return
elif d.isMsvcTarget():
proxy, head, size = value.split('ppQ')
d.putItemCount(size)
try:
qdump_std__map__helper(d, size, value['_Mypair']['_Myval2']['_Myval2'])
finally:
return
# stuff is actually (color, pad) with 'I@', but we can save cycles/
(compare, stuff, parent, left, right, size) = value.split('pppppp')
impl = value["_M_t"]["_M_impl"]
d.check(0 <= size and size <= 100*1000*1000)
d.putItemCount(size)
@@ -226,7 +234,7 @@ def qdump__std__map(d, value):
pairType = value.type[3][0]
pairPointer = pairType.pointer()
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
node = impl["_M_header"]["_M_left"]
node = value["_M_t"]["_M_impl"]["_M_header"]["_M_left"]
nodeSize = node.dereference().type.size()
typeCode = "@{%s}@{%s}" % (pairType[0].name, pairType[1].name)
for i in d.childRange():
@@ -248,26 +256,23 @@ def qdump__std__map(d, value):
break
node = node["_M_left"]
def qdump__std__map__QNX(d, value):
size = value['_Mysize']
d.check(0 <= size and size <= 100*1000*1000)
d.putItemCount(size)
def qdump_std__map__helper(d, size, value):
if d.isExpanded():
head = value['_Myhead']
node = head['_Left']
nodeType = head.type
with Children(d, size, maxNumChild=1000):
pairType = head.type[0]
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
for i in d.childRange():
pair = node.cast(nodeType).dereference()['_Myval']
d.putPairItem(i, pair)
if not node['_Right']['_Isnil']:
if node['_Right']['_Isnil'].integer() == 0:
node = node['_Right']
while not node['_Left']['_Isnil']:
while node['_Left']['_Isnil'].integer() == 0:
node = node['_Left']
else:
parent = node['_Parent']
while node == parent['_Right']['_Isnil']:
while node and parent['_Right']['_Isnil'].integer() == 0:
node = parent
parent = parent['_Parent']
if node['_Right'] != parent:
@@ -794,7 +799,7 @@ def qedit__std__vector(d, value, data):
gdb.execute(cmd)
def qdump__std__vector(d, value):
if d.isQnxTarget():
if d.isQnxTarget() or d.isMsvcTarget():
qdumpHelper__std__vector__QNX(d, value)
else:
qdumpHelper__std__vector(d, value, False)
@@ -835,20 +840,26 @@ def qdumpHelper__std__vector(d, value, isLibCpp):
def qdumpHelper__std__vector__QNX(d, value):
innerType = value.type[0]
isBool = str(innerType) == 'bool'
isBool = innerType.name == 'bool'
if isBool:
try:
impl = value['_Myvec']['_Mypair']['_Myval2']
except:
impl = value['_Myvec']
start = impl['_Myfirst']
last = impl['_Mylast']
end = impl['_Myend']
size = value['_Mysize']
start = impl['_Myfirst'].pointer()
last = impl['_Mylast'].pointer()
end = impl['_Myend'].pointer()
size = value['_Mysize'].integer()
storagesize = start.dereference().type.size() * 8
else:
start = value['_Myfirst']
last = value['_Mylast']
end = value['_Myend']
size = (last.integer() - start.integer()) / innerType.size()
alloc = (end.integer() - start.integer()) / innerType.size()
try:
impl = value['_Mypair']['_Myval2']
except:
impl = value
start = impl['_Myfirst'].pointer()
last = impl['_Mylast'].pointer()
end = impl['_Myend'].pointer()
size = (last - start) // innerType.size()
d.check(0 <= size and size <= 1000 * 1000 * 1000)
d.check(last <= end)
@@ -863,11 +874,11 @@ def qdumpHelper__std__vector__QNX(d, value):
for i in d.childRange():
q = start + int(i / storagesize)
with SubItem(d, i):
d.putValue((q.dereference() >> (i % storagesize)) & 1)
d.putValue((q.dereference().pointer() >> (i % storagesize)) & 1)
d.putType("bool")
d.putNumChild(0)
else:
d.putArrayData(start, size, innerType)
d.putPlotData(start, size, innerType)
def qdump__std____1__vector(d, value):
qdumpHelper__std__vector(d, value, True)

View File

@@ -336,6 +336,10 @@ void ObjectNodeInstance::addToNewProperty(QObject *object, QObject *newParent, c
list.append(object);
} else if (isObject(property)) {
property.write(objectToVariant(object));
if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
if (QQuickItem *newParentItem = qobject_cast<QQuickItem *>(newParent))
item->setParentItem(newParentItem);
}
Q_ASSERT(objectToVariant(object).isValid());

View File

@@ -190,8 +190,9 @@ Column {
ButtonRowButton {
iconSource: "images/icon_color_solid.png"
onClicked: {
colorEditor.backendValue.resetValue()
gradientLine.deleteGradient()
textField.text = colorEditor.color
colorEditor.backendValue.resetValue()
}
tooltip: qsTr("Solid Color")
}

View File

@@ -33,6 +33,8 @@ ComboBoxStyle {
}
padding.left: 20
background: Item {
implicitWidth: 120
implicitHeight: 24
@@ -65,18 +67,14 @@ ComboBoxStyle {
}
}
label: Item {
implicitWidth: textitem.implicitWidth + 20
Text {
label: Text {
id: textitem
anchors.left: parent.left
anchors.leftMargin: 14
anchors.verticalCenter: parent.verticalCenter
text: control.currentText
renderType: Text.NativeRendering
color: control.textColor
}
}
__dropDownStyle: MenuStyle {
__maxPopupHeight: 600

View File

@@ -133,6 +133,8 @@ Controls.TextField {
event.accepted = true
if (textField.completionActive) {
listView.model = null
} else {
textField.rejected()
}
}

View File

@@ -40,7 +40,7 @@ Controls.ComboBox {
model: ["Arial", "Times New Roman", "Courier", "Verdana", "Tahoma"]
onModelChanged: {
editText = backendValue.valueToString
editText = comboBox.backendValue.valueToString
}
style: CustomComboBoxStyle {
@@ -50,7 +50,7 @@ Controls.ComboBox {
ColorLogic {
id: colorLogic
backendValue: comboBox.backendValue
property string textValue: backendValue.value
property string textValue: comboBox.backendValue.valueToString
onTextValueChanged: {
comboBox.editText = textValue
}

View File

@@ -60,7 +60,7 @@ Section {
text: qsTr("Font")
}
FontComboBox {
backendValue: fontFamily
backendValue: fontSection.fontFamily
Layout.fillWidth: true
}
@@ -142,6 +142,30 @@ Section {
}
Label {
text: qsTr("Font capitalization")
toolTip: qsTr("Sets the capitalization for the text.")
}
ComboBox {
Layout.fillWidth: true
backendValue: backendValues.font_capitalization
model: ["MixedCase", "AllUppercase", "AllLowercase", "SmallCaps", "Capitalize"]
scope: "Font"
}
Label {
text: qsTr("Font weight")
toolTip: qsTr("Sets the font's weight.")
}
ComboBox {
Layout.fillWidth: true
backendValue: backendValues.font_weight
model: ["Normal", "Light", "ExtraLight", "Thin", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
scope: "Font"
}
Label {
visible: showStyle
text: qsTr("Style")
@@ -154,5 +178,41 @@ Section {
model: ["Normal", "Outline", "Raised", "Sunken"]
scope: "Text"
}
Label {
text: qsTr("Spacing")
}
SecondColumnLayout {
Label {
text: qsTr("Word")
tooltip: qsTr("Sets the word spacing for the font.")
width: 42
}
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.font_wordSpacing
Layout.fillWidth: true
}
Item {
width: 4
height: 4
}
Label {
text: qsTr("Letter")
tooltip: qsTr("Sets the letter spacing for the font.")
width: 42
}
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.font_letterSpacing
Layout.fillWidth: true
}
}
}
}

View File

@@ -108,7 +108,7 @@ Controls.TextField {
selectionColor: creatorTheme.PanelTextColorLight
selectedTextColor: creatorTheme.PanelTextColorMid
textColor: creatorTheme.PanelTextColorLight
textColor: lineEdit.textColor
placeholderTextColor: creatorTheme.PanelTextColorMid
padding.top: 3

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.1
import HelperWidgets 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0 as Controls
Section {
caption: qsTr("Padding")
anchors.left: parent.left
anchors.right: parent.right
SectionLayout {
Label {
text: qsTr("Vertical")
}
SecondColumnLayout {
Label {
text: qsTr("Top")
tooltip: qsTr("Padding between the content and the top edge of the item.")
width: 42
}
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.topPadding
Layout.fillWidth: true
}
Item {
width: 4
height: 4
}
Label {
text: qsTr("Bottom")
tooltip: qsTr("Padding between the content and the bottom edge of the item.")
width: 42
}
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.bottomPadding
Layout.fillWidth: true
}
}
Label {
text: qsTr("Horizontal")
}
SecondColumnLayout {
Label {
text: qsTr("Left")
tooltip: qsTr("Padding between the content and the left edge of the item.")
width: 42
}
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.leftPadding
Layout.fillWidth: true
}
Item {
width: 4
height: 4
}
Label {
text: qsTr("Right")
tooltip: qsTr("Padding between the content and the right edge of the item.")
width: 42
}
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.rightPadding
Layout.fillWidth: true
}
}
Label {
text: qsTr("Padding")
tooltip: qsTr("Padding between the content and the edges of the items.")
}
SecondColumnLayout {
SpinBox {
maximumValue: 9999999
minimumValue: -9999999
decimals: 0
backendValue: backendValues.padding
Layout.fillWidth: true
}
}
}
}

View File

@@ -33,9 +33,11 @@ Section {
caption: qsTr("Text")
property bool showIsWrapping: false
property bool showElide: false
property bool showVerticalAlignment: false
property bool useLineEdit: true
property bool showFormatProperty: false
property bool showFontSizeMode: false
SectionLayout {
columns: 2
@@ -62,6 +64,19 @@ Section {
model: ["NoWrap", "WordWrap", "WrapAnywhere", "WrapAtWordBoundaryOrAnywhere"]
}
Label {
visible: showElide
text: qsTr("Elide")
}
ComboBox {
visible: showElide
Layout.fillWidth: true
backendValue: backendValues.elide
scope: "Text"
model: ["ElideNone", "ElideLeft", "ElideMiddle", "ElideRight"]
}
Label {
text: qsTr("Alignment")
}
@@ -91,5 +106,27 @@ Section {
backendValue: backendValues.textFormat
Layout.fillWidth: true
}
Label {
text: qsTr("Render type")
toolTip: qsTr("Override the default rendering type for this item.")
}
ComboBox {
scope: "Text"
model: ["QtRendering", "NativeRendering"]
backendValue: backendValues.renderType
Layout.fillWidth: true
}
Label {
text: qsTr("Font size mode")
toolTip: qsTr("Specifies how the font size of the displayed text is determined.")
}
ComboBox {
scope: "Text"
model: ["FixedSize", "HorizontalFit", "VerticalFit", "Fit"]
backendValue: backendValues.fontSizeMode
Layout.fillWidth: true
}
}
}

View File

@@ -52,6 +52,13 @@ RowLayout {
Controls.ComboBox {
id: comboBox
ExtendedFunctionButton {
x: 2
anchors.verticalCenter: parent.verticalCenter
backendValue: urlChooser.backendValue
visible: comboBox.enabled
}
property bool isComplete: false
function setCurrentText(text) {

View File

@@ -38,3 +38,4 @@ Tab 2.0 Tab.qml
TabView 2.0 TabView.qml
ToolTipArea 2.0 ToolTipArea.qml
UrlChooser 2.0 UrlChooser.qml
PaddingSection 2.0 PaddingSection.qml

View File

@@ -78,8 +78,8 @@ Rectangle {
// right size after resizing to a wider width
Image {
width: 16
height: 16
Layout.preferredWidth: 16
Layout.preferredHeight: 16
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
ToolTipArea {
anchors.fill: parent

View File

@@ -68,4 +68,8 @@ Column {
TextInputSection {
}
PaddingSection {
visible: minorQtQuickVersion > 5
}
}

View File

@@ -68,4 +68,9 @@ Column {
TextInputSection {
isTextInput: true
}
PaddingSection {
visible: minorQtQuickVersion > 5
}
}

View File

@@ -36,6 +36,8 @@ Column {
showIsWrapping: true
showVerticalAlignment: true
showFormatProperty: true
showElide: true
showFontSizeMode: true
}
Section {
@@ -66,4 +68,8 @@ Column {
FontSection {
showStyle: true
}
PaddingSection {
visible: minorQtQuickVersion > 5
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,8 +28,7 @@
namespace ClangBackEnd {
LinePrefixer::LinePrefixer(const QByteArray &prefix)
: m_prefix(prefix),
m_previousIsEndingWithNewLine(true)
: m_prefix(prefix)
{}
void LinePrefixer::setPrefix(const QByteArray &prefix)

View File

@@ -43,7 +43,7 @@ public:
private:
QByteArray m_prefix;
bool m_previousIsEndingWithNewLine;
bool m_previousIsEndingWithNewLine = true;
};
} // namespace ClangBackEnd

View File

@@ -101,26 +101,23 @@ static inline std::string fixInnerType(const std::string &type,
// Return size from an STL vector (last/first iterators).
static inline int msvcStdVectorSize(const SymbolGroupValue &v)
{
// MSVC2012 has 2 base classes, MSVC2010 1, MSVC2008 none
if (const SymbolGroupValue myFirstPtrV = SymbolGroupValue::findMember(v, "_Myfirst")) {
if (const SymbolGroupValue myLastPtrV = myFirstPtrV.parent()["_Mylast"]) {
const ULONG64 firstPtr = myFirstPtrV.pointerValue();
const ULONG64 lastPtr = myLastPtrV.pointerValue();
const ULONG64 firstPtr = v.readPointerValueFromAncestor("_Myfirst");
const ULONG64 lastPtr = v.readPointerValueFromAncestor("_Mylast");
if (!firstPtr || lastPtr < firstPtr)
return -1;
const std::vector<std::string> innerTypes = v.innerTypes();
if (innerTypes.empty())
return -1;
const std::string innerType = fixInnerType(SymbolGroupValue::stripPointerType(innerTypes[0]), v);
const size_t size = SymbolGroupValue::sizeOf(innerType.c_str());
if (size == 0)
return -1;
if (lastPtr == firstPtr)
return 0;
// Subtract the pointers: We need to do the pointer arithmetics ourselves
// as we get char *pointers.
const std::string innerType = fixInnerType(SymbolGroupValue::stripPointerType(myFirstPtrV.type()), v);
const size_t size = SymbolGroupValue::sizeOf(innerType.c_str());
if (size == 0)
return -1;
return static_cast<int>((lastPtr - firstPtr) / size);
}
}
return -1;
}
// Return size of container or -1
int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx)
@@ -193,10 +190,12 @@ int containerSize(KnownType kt, const SymbolGroupValue &v)
case KT_StdMap:
case KT_StdMultiMap:
case KT_StdValArray:
case KT_StdList:
if (const SymbolGroupValue size = SymbolGroupValue::findMember(v, "_Mysize"))
return size.intValue();
case KT_StdList: {
const int size = v.readIntegerFromAncestor("_Mysize");
if (size >= 0)
return size;
break;
}
case KT_StdStack:
if (const SymbolGroupValue deque = v[unsigned(0)])
return containerSize(KT_StdDeque, deque);

View File

@@ -53,11 +53,30 @@ PyObject *lookupType(const std::string &typeNameIn)
{
std::string typeName = typeNameIn;
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
std::string fullTypeName = typeName;
// GetSymbolTypeId doesn't support pointer types so we need to strip off the '*' first
while (endsWith(typeName, '*'))
typeName.pop_back();
ULONG64 module;
ULONG typeId;
if (FAILED(symbols->GetSymbolTypeId(typeName.c_str(), &typeId, &module)))
Py_RETURN_NONE;
return createType(module, typeId);
if (typeName != fullTypeName) {
if (module == 0) { // found some builtin type like char so we take the first module available to look up the pointer type
ULONG loaded, unloaded;
if (FAILED(symbols->GetNumberModules(&loaded, &unloaded)))
Py_RETURN_NONE;
if ((loaded + unloaded == 0) || FAILED(symbols->GetModuleByIndex(0, &module)))
Py_RETURN_NONE;
}
if (FAILED(symbols->GetTypeId(module, fullTypeName.c_str(), &typeId)))
Py_RETURN_NONE;
}
size_t typeNameLength = fullTypeName.length();
char *cTypeName = new char[typeNameLength + 1];
fullTypeName.copy(cTypeName, fullTypeName.length());
cTypeName[typeNameLength] = 0;
return createType(module, typeId, cTypeName);
}
char *getTypeName(ULONG64 module, ULONG typeId)
@@ -93,7 +112,9 @@ PyObject *type_bitSize(Type *self)
{
ULONG size;
auto extcmd = ExtensionCommandContext::instance();
if (FAILED(extcmd->symbols()->GetTypeSize(self->m_module, self->m_typeId, &size)))
if (endsWith(getTypeName(self), '*'))
size = SUCCEEDED(ExtensionCommandContext::instance()->control()->IsPointer64Bit()) ? 8 : 4;
else if (FAILED(extcmd->symbols()->GetTypeSize(self->m_module, self->m_typeId, &size)))
return NULL;
return Py_BuildValue("k", size * 8);
}
@@ -143,13 +164,8 @@ PyObject *type_Target(Type *self)
Py_XINCREF(self);
return (PyObject *)self;
}
typeName = typeName.substr(0, typeName.length() - 1);
CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols();
ULONG typeId;
if (FAILED(symbols->GetTypeId(self->m_module, typeName.c_str(), &typeId)))
return NULL;
return createType(self->m_module, typeId);
typeName.pop_back();
return lookupType(typeName);
}
PyObject *type_StripTypedef(Type *self)
@@ -241,7 +257,7 @@ PyObject *type_TemplateArgument(Type *self, PyObject *args)
if (innerTypes.size() <= index)
Py_RETURN_NONE;
const std::string &innerType = innerTypes.at(index);
const std::string &innerType = SymbolGroupValue::stripConst(innerTypes.at(index));
if (numeric) {
try {
return Py_BuildValue("i", std::stoi(innerType));
@@ -270,12 +286,12 @@ void type_Dealloc(Type *self)
delete[] self->m_name;
}
PyObject *createType(ULONG64 module, ULONG typeId)
PyObject *createType(ULONG64 module, ULONG typeId, char* name)
{
Type *type = PyObject_New(Type, type_pytype());
type->m_module = module;
type->m_typeId = typeId;
type->m_name = nullptr;
type->m_name = name;
return reinterpret_cast<PyObject *>(type);
}

View File

@@ -44,4 +44,4 @@ PyTypeObject *type_pytype();
char *getTypeName(ULONG64 module, ULONG typeId);
PyObject *lookupType(const std::string &typeName);
PyObject *createType(ULONG64 module, ULONG typeId);
PyObject *createType(ULONG64 module, ULONG typeId, char *name = nullptr);

View File

@@ -154,6 +154,15 @@ int SymbolGroupValue::readIntegerFromAncestor(const std::string &name, int defau
return readPODFromAncestor<int>(name, defaultValue);
}
ULONG64 SymbolGroupValue::offsetOfChild(const SymbolGroupValue &child) const
{
const ULONG64 base = isPointerType(type()) ? pointerValue() : address();
const ULONG64 childAddress = child.address();
if (base == 0 || childAddress == 0)
return 0;
return childAddress - base;
}
LONG64 SymbolGroupValue::offsetOfAncestor(const std::string &name) const
{
return infoOfAncestor(name).offset;
@@ -204,7 +213,7 @@ SymbolAncestorInfo SymbolGroupValue::infoOfAncestor(const std::string &name) con
continue;
info = child.infoOfAncestor(name);
if (info.isValid()) {
info.offset += offsetOfAncestor(child.name());
info.offset += offsetOfChild(child);
break;
}
}

View File

@@ -71,6 +71,7 @@ public:
SymbolGroupValue operator[](const char *name) const;
SymbolGroupValue operator[](unsigned) const;
unsigned childCount() const;
ULONG64 offsetOfChild(const SymbolGroupValue &child) const;
SymbolGroupValue parent() const;
// take address and cast to desired (pointer) type
SymbolGroupValue typeCast(const char *type) const;

View File

@@ -269,7 +269,8 @@ QStringList Environment::appendExeExtensions(const QString &executable) const
}
FileName Environment::searchInPath(const QString &executable,
const QStringList &additionalDirs) const
const QStringList &additionalDirs,
bool (*func)(const QString &name)) const
{
if (executable.isEmpty())
return FileName();
@@ -292,7 +293,7 @@ FileName Environment::searchInPath(const QString &executable,
continue;
alreadyChecked.insert(dir);
FileName tmp = searchInDirectory(execs, dir);
if (!tmp.isEmpty())
if (!tmp.isEmpty() && (!func || func(tmp.toString())))
return tmp;
}
@@ -304,7 +305,7 @@ FileName Environment::searchInPath(const QString &executable,
continue;
alreadyChecked.insert(p);
FileName tmp = searchInDirectory(execs, QDir::fromNativeSeparators(p));
if (!tmp.isEmpty())
if (!tmp.isEmpty() && (!func || func(tmp.toString())))
return tmp;
}
return FileName();

View File

@@ -100,7 +100,9 @@ public:
Environment::const_iterator constFind(const QString &name) const;
FileName searchInPath(const QString &executable,
const QStringList &additionalDirs = QStringList()) const;
const QStringList &additionalDirs = QStringList(),
bool (*func)(const QString &name) = nullptr) const;
QStringList path() const;
QStringList appendExeExtensions(const QString &executable) const;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 977 B

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 211 B

View File

@@ -38,11 +38,16 @@
<file>images/compile_error_taskbar@2x.png</file>
<file>images/dir.png</file>
<file>images/editcopy.png</file>
<file>images/editcopy@2x.png</file>
<file>images/editcut.png</file>
<file>images/editcut@2x.png</file>
<file>images/editpaste.png</file>
<file>images/editpaste@2x.png</file>
<file>images/empty14.png</file>
<file>images/filenew.png</file>
<file>images/filenew@2x.png</file>
<file>images/fileopen.png</file>
<file>images/fileopen@2x.png</file>
<file>images/filesave.png</file>
<file>images/filesave@2x.png</file>
<file>images/inputfield.png</file>

View File

@@ -64,10 +64,10 @@ const Icon BOOKMARK_TOOLBAR({
const Icon BOOKMARK_TEXTEDITOR({
{QLatin1String(":/utils/images/bookmark.png"), Theme::Bookmarks_TextMarkColor}}, Icon::Tint);
const Icon NEWFILE(
QLatin1String(":/utils/images/filenew.png"));
const Icon OPENFILE(
QLatin1String(":/utils/images/fileopen.png"));
const Icon NEWFILE({
{QLatin1String(":/utils/images/filenew.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon OPENFILE({
{QLatin1String(":/utils/images/fileopen.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon SAVEFILE({
{QLatin1String(":/utils/images/filesave.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon SAVEFILE_TOOLBAR({
@@ -76,12 +76,12 @@ const Icon UNDO({
{QLatin1String(":/utils/images/undo.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon REDO({
{QLatin1String(":/utils/images/redo.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon COPY(
QLatin1String(":/utils/images/editcopy.png"));
const Icon PASTE(
QLatin1String(":/utils/images/editpaste.png"));
const Icon CUT(
QLatin1String(":/utils/images/editcut.png"));
const Icon COPY({
{QLatin1String(":/utils/images/editcopy.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon PASTE({
{QLatin1String(":/utils/images/editpaste.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon CUT({
{QLatin1String(":/utils/images/editcut.png"), Theme::PanelTextColorMid}}, Icon::Tint);
const Icon DIR(
QLatin1String(":/utils/images/dir.png"));
const Icon RESET({

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>397</width>
<height>205</height>
<width>449</width>
<height>210</height>
</rect>
</property>
<property name="windowTitle">
@@ -17,16 +17,8 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="runDisabledGTestsCB">
<property name="toolTip">
<string>Executes disabled tests when performing a test run.</string>
</property>
<property name="text">
<string>Run disabled tests</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="breakOnFailureCB">
<property name="toolTip">
<string>Turn failures into debugger breakpoints.</string>
@@ -39,35 +31,30 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="repeatGTestsCB">
<item row="0" column="0">
<widget class="QCheckBox" name="runDisabledGTestsCB">
<property name="toolTip">
<string>Repeats a test run (you might be required to increase the timeout to avoid canceling the tests).</string>
<string>Executes disabled tests when performing a test run.</string>
</property>
<property name="text">
<string>Repeat tests</string>
<string>Run disabled tests</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="4" column="0">
<widget class="QCheckBox" name="throwOnFailureCB">
<property name="toolTip">
<string>Turn assertion failures into C++ exceptions.</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="text">
<string>Throw on failure</string>
</property>
</spacer>
</widget>
</item>
<item>
<item row="2" column="1">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -77,7 +64,27 @@
</property>
</widget>
</item>
<item>
<item row="3" column="0">
<widget class="QCheckBox" name="shuffleGTestsCB">
<property name="toolTip">
<string>Shuffle tests automatically on every iteration by the given seed.</string>
</property>
<property name="text">
<string>Shuffle tests</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="repeatGTestsCB">
<property name="toolTip">
<string>Repeats a test run (you might be required to increase the timeout to avoid canceling the tests).</string>
</property>
<property name="text">
<string>Repeat tests</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="repetitionSpin">
<property name="enabled">
<bool>false</bool>
@@ -90,50 +97,10 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QCheckBox" name="shuffleGTestsCB">
<property name="toolTip">
<string>Shuffle tests automatically on every iteration by the given seed.</string>
</property>
<property name="text">
<string>Shuffle tests</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -143,7 +110,7 @@
</property>
</widget>
</item>
<item>
<item row="3" column="2">
<widget class="QSpinBox" name="seedSpin">
<property name="enabled">
<bool>false</bool>
@@ -159,31 +126,8 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="throwOnFailureCB">
<property name="toolTip">
<string>Turn assertion failures into C++ exceptions.</string>
</property>
<property name="text">
<string>Throw on failure</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@@ -36,9 +36,6 @@
<property name="title">
<string>Benchmark Metrics</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QRadioButton" name="walltimeRB">

View File

@@ -237,7 +237,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getSelectedTestConfigurations() co
int grandChildCount = child->childCount();
for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
const TestTreeItem *grandChild = child->childItem(grandChildRow);
if (grandChild->type() != TestFunctionOrSet)
if (grandChild->checked() != Qt::Checked || grandChild->type() != TestFunctionOrSet)
continue;
testFunctions << child->name() + "::" + grandChild->name();
}

View File

@@ -15,7 +15,6 @@ QtcPlugin {
"bookmark.h",
"bookmarkmanager.cpp",
"bookmarkmanager.h",
"bookmarks.qrc",
"bookmarks_global.h",
"bookmarksplugin.cpp",
"bookmarksplugin.h",

View File

@@ -38,7 +38,6 @@
#include <QDir>
#include <QFile>
#include <QRegularExpression>
#include <QStringList>
using namespace ClangCodeModel;
@@ -100,7 +99,7 @@ public:
optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions();
optionsBuilder.addWrappedQtHeadersIncludePath();
optionsBuilder.addHeaderPathOptions(/*addAsNativePath*/ true);
optionsBuilder.addHeaderPathOptions();
optionsBuilder.addProjectConfigFileInclude();
optionsBuilder.addMsvcCompatibilityVersion();
@@ -118,18 +117,12 @@ private:
bool excludeHeaderPath(const QString &path) const override
{
if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
if (path.contains(QLatin1String("lib/gcc/i686-apple-darwin")))
return true;
}
// We already provide a custom clang include path matching the used libclang version,
// so better ignore the clang include paths from the system as this might lead to an
// unfavorable order with regard to include_next.
static QRegularExpression clangIncludeDir(
QLatin1String("\\A.*/lib/clang/\\d+\\.\\d+(\\.\\d+)?/include\\z"));
if (clangIncludeDir.match(path).hasMatch())
return true;
return false;
return CompilerOptionsBuilder::excludeHeaderPath(path);
}
void addPredefinedMacrosAndHeaderPathsOptions()

View File

@@ -56,18 +56,12 @@ RefactoringCompilerOptionsBuilder::RefactoringCompilerOptionsBuilder(CppTools::P
bool RefactoringCompilerOptionsBuilder::excludeHeaderPath(const QString &path) const
{
if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
if (path.contains(QLatin1String("lib/gcc/i686-apple-darwin")))
return true;
}
// We already provide a custom clang include path matching the used libclang version,
// so better ignore the clang include paths from the system as this might lead to an
// unfavorable order with regard to include_next.
static QRegularExpression clangIncludeDir(
QLatin1String("\\A.*/lib/clang/\\d+\\.\\d+(\\.\\d+)?/include\\z"));
if (clangIncludeDir.match(path).hasMatch())
return true;
return false;
return CompilerOptionsBuilder::excludeHeaderPath(path);
}
void RefactoringCompilerOptionsBuilder::addPredefinedMacrosAndHeaderPathsOptions()

View File

@@ -34,7 +34,6 @@
#include <coreplugin/icore.h>
#include <QDir>
#include <QRegularExpression>
namespace ClangRefactoring {

View File

@@ -107,7 +107,8 @@ void ClangStaticAnalyzerPreconfiguredSessionTests::testPreconfiguredSession()
QSignalSpy waitUntilAnalyzerFinished(&m_analyzerTool, SIGNAL(finished(bool)));
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
const QList<QVariant> arguments = waitUntilAnalyzerFinished.takeFirst();
QVERIFY(arguments.first().toBool());
const bool analyzerFinishedSuccessfully = arguments.first().toBool();
QVERIFY(analyzerFinishedSuccessfully);
QCOMPARE(m_analyzerTool.diagnostics().count(), 0);
}

View File

@@ -182,7 +182,7 @@ public:
const Core::Id type = projectPart.toolchainType;
if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
|| type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID)
optionsBuilder.addDefine("#define _X86INTRIN_H_INCLUDED\n");
optionsBuilder.addDefine("#define _X86INTRIN_H_INCLUDED");
if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
optionsBuilder.addDefines(projectPart.toolchainDefines);

View File

@@ -63,7 +63,7 @@ static QStringList constructCommandLineArguments(const QString &filePath,
arguments
<< QLatin1String("--analyze")
<< QLatin1String("-o")
<< logFile
<< QDir::toNativeSeparators(logFile)
;
arguments += options;
arguments << QDir::toNativeSeparators(filePath);
@@ -80,7 +80,7 @@ ClangStaticAnalyzerRunner::ClangStaticAnalyzerRunner(const QString &clangExecuta
const Utils::Environment &environment,
QObject *parent)
: QObject(parent)
, m_clangExecutable(clangExecutable)
, m_clangExecutable(QDir::toNativeSeparators(clangExecutable))
, m_clangLogFileDir(clangLogFileDir)
{
QTC_CHECK(!m_clangExecutable.isEmpty());

View File

@@ -1970,6 +1970,7 @@ void EditorManagerPrivate::autoSave()
if (!errors.isEmpty())
QMessageBox::critical(ICore::mainWindow(), tr("File Error"),
errors.join(QLatin1Char('\n')));
emit m_instance->autoSaved();
}
void EditorManagerPrivate::handleContextChange(const QList<IContext *> &context)

View File

@@ -185,6 +185,7 @@ signals:
void editorsClosed(QList<Core::IEditor *> editors);
void findOnFileSystemRequest(const QString &path);
void aboutToSave(IDocument *document);
void autoSaved();
public slots:
static void saveDocument();

View File

@@ -68,11 +68,6 @@ void InfoBarEntry::setCancelButtonInfo(const QString &_cancelButtonText, CallBac
m_cancelButtonCallBack = callBack;
}
void InfoBarEntry::setSuppressionButtonInfo(InfoBarEntry::CallBack callback)
{
m_suppressionButtonCallBack = callback;
}
void InfoBarEntry::setShowDefaultCancelButton(bool yesno)
{
m_showDefaultCancelButton = yesno;
@@ -282,9 +277,7 @@ void InfoBarDisplay::update()
if (info.globalSuppression == InfoBarEntry::GlobalSuppressionEnabled) {
infoWidgetSuppressButton = new QToolButton;
infoWidgetSuppressButton->setText(tr("Do Not Show Again"));
connect(infoWidgetSuppressButton, &QAbstractButton::clicked, this, [this, info, id] {
if (info.m_suppressionButtonCallBack)
info.m_suppressionButtonCallBack();
connect(infoWidgetSuppressButton, &QAbstractButton::clicked, this, [this, id] {
m_infoBar->removeInfo(id);
InfoBar::globallySuppressInfo(id);
});

View File

@@ -58,7 +58,6 @@ public:
void setCustomButtonInfo(const QString &_buttonText, CallBack callBack);
void setCancelButtonInfo(CallBack callBack);
void setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack);
void setSuppressionButtonInfo(CallBack callback);
void setShowDefaultCancelButton(bool yesno);
using DetailsWidgetCreator = std::function<QWidget*()>;
@@ -71,7 +70,6 @@ private:
CallBack m_buttonCallBack;
QString cancelButtonText;
CallBack m_cancelButtonCallBack;
CallBack m_suppressionButtonCallBack;
GlobalSuppressionMode globalSuppression;
DetailsWidgetCreator m_detailsWidgetCreator;
bool m_showDefaultCancelButton = true;

View File

@@ -56,6 +56,7 @@
#include <cpptools/cpptoolsconstants.h>
#include <cpptools/cpptoolsplugin.h>
#include <cpptools/cpptoolsreuse.h>
#include <cpptools/cpptoolssettings.h>
#include <cpptools/cppworkingcopy.h>
#include <cpptools/symbolfinder.h>
#include <cpptools/refactoringengineinterface.h>
@@ -130,7 +131,7 @@ public:
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
QToolButton *m_preprocessorButton = nullptr;
QToolButton *m_headerErrorsIndicatorButton = nullptr;
QAction *m_headerErrorsIndicatorAction = nullptr;
CppSelectionChanger m_cppSelectionChanger;
@@ -229,15 +230,20 @@ void CppEditorWidget::finalizeInitialization()
connect(cmd, &Command::keySequenceChanged, this, &CppEditorWidget::updatePreprocessorButtonTooltip);
updatePreprocessorButtonTooltip();
connect(d->m_preprocessorButton, &QAbstractButton::clicked, this, &CppEditorWidget::showPreProcessorWidget);
d->m_headerErrorsIndicatorButton = new QToolButton(this);
d->m_headerErrorsIndicatorButton->setIcon(Utils::Icons::WARNING_TOOLBAR.pixmap());
connect(d->m_headerErrorsIndicatorButton, &QAbstractButton::clicked,
this, &CppEditorWidget::showHeaderErrorInfoBar);
d->m_headerErrorsIndicatorButton->setEnabled(false);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_headerErrorsIndicatorButton);
auto *headerErrorsIndicatorButton = new QToolButton(this);
headerErrorsIndicatorButton->setToolTip(tr("Show First Error in Included Files"));
headerErrorsIndicatorButton->setIcon(Utils::Icons::WARNING_TOOLBAR.pixmap());
connect(headerErrorsIndicatorButton, &QAbstractButton::clicked, []() {
CppToolsSettings::instance()->setShowHeaderErrorInfoBar(true);
});
d->m_headerErrorsIndicatorAction = insertExtraToolBarWidget(TextEditorWidget::Left,
headerErrorsIndicatorButton);
d->m_headerErrorsIndicatorAction->setVisible(false);
connect(CppToolsSettings::instance(), &CppToolsSettings::showHeaderErrorInfoBarChanged,
this, &CppEditorWidget::updateHeaderErrorWidgets);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget());
}
@@ -252,6 +258,10 @@ void CppEditorWidget::finalizeInitializationAfterDuplication(TextEditorWidget *o
d->m_cppEditorOutline->update();
const Id selectionKind = CodeWarningsSelection;
setExtraSelections(selectionKind, cppEditorWidget->extraSelections(selectionKind));
d->m_headerErrorDiagnosticWidgetCreator
= cppEditorWidget->d->m_headerErrorDiagnosticWidgetCreator;
updateHeaderErrorWidgets();
}
CppEditorWidget::~CppEditorWidget()
@@ -329,13 +339,14 @@ void CppEditorWidget::updateHeaderErrorWidgets()
infoBar->removeInfo(id);
if (d->m_headerErrorDiagnosticWidgetCreator) {
if (infoBar->canInfoBeAdded(id)) {
addHeaderErrorInfoBarEntryAndHideIndicator();
if (CppToolsSettings::instance()->showHeaderErrorInfoBar()) {
addHeaderErrorInfoBarEntry();
d->m_headerErrorsIndicatorAction->setVisible(false);
} else {
d->m_headerErrorsIndicatorButton->setEnabled(true);
d->m_headerErrorsIndicatorAction->setVisible(true);
}
} else {
d->m_headerErrorsIndicatorButton->setEnabled(false);
d->m_headerErrorsIndicatorAction->setVisible(false);
}
}
@@ -434,23 +445,20 @@ void CppEditorWidget::renameSymbolUnderCursorBuiltin()
renameUsages(); // Rename non-local symbol or macro
}
void CppEditorWidget::addHeaderErrorInfoBarEntryAndHideIndicator() const
void CppEditorWidget::addHeaderErrorInfoBarEntry() const
{
InfoBarEntry info(Constants::ERRORS_IN_HEADER_FILES,
tr("<b>Warning</b>: The code model could not parse an included file, "
"which might lead to slow or incorrect code completion and "
"highlighting, for example."),
InfoBarEntry::GlobalSuppressionEnabled);
"highlighting, for example."));
info.setDetailsWidgetCreator(d->m_headerErrorDiagnosticWidgetCreator);
info.setShowDefaultCancelButton(false);
info.setSuppressionButtonInfo([this](){
d->m_headerErrorsIndicatorButton->setEnabled(true);
info.setCustomButtonInfo("Minimize", [](){
CppToolsSettings::instance()->setShowHeaderErrorInfoBar(false);
});
InfoBar *infoBar = textDocument()->infoBar();
infoBar->addInfo(info);
d->m_headerErrorsIndicatorButton->setEnabled(false);
}
namespace {
@@ -1024,14 +1032,5 @@ void CppEditorWidget::showPreProcessorWidget()
}
}
void CppEditorWidget::showHeaderErrorInfoBar()
{
const Id id(Constants::ERRORS_IN_HEADER_FILES);
QTC_CHECK(!textDocument()->infoBar()->canInfoBeAdded(id));
InfoBar::globallyUnsuppressInfo(id);
addHeaderErrorInfoBarEntryAndHideIndicator();
}
} // namespace Internal
} // namespace CppEditor

View File

@@ -31,10 +31,6 @@
#include <QScopedPointer>
namespace Core {
class InfoBarEntry;
}
namespace CppTools {
class CppEditorOutline;
class RefactoringEngineInterface;
@@ -91,7 +87,6 @@ public:
void switchDeclarationDefinition(bool inNextSplit);
void showPreProcessorWidget();
void showHeaderErrorInfoBar();
void findUsages();
void renameSymbolUnderCursor();
@@ -150,7 +145,7 @@ private:
void renameSymbolUnderCursorClang();
void renameSymbolUnderCursorBuiltin();
void addHeaderErrorInfoBarEntryAndHideIndicator() const;
void addHeaderErrorInfoBarEntry() const;
CppTools::ProjectPart *projectPart() const;

View File

@@ -28,6 +28,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <QDir>
#include <QRegularExpression>
namespace CppTools {
@@ -100,7 +101,7 @@ void CompilerOptionsBuilder::enableExceptions()
add(QLatin1String("-fexceptions"));
}
void CompilerOptionsBuilder::addHeaderPathOptions(bool addAsNativePath)
void CompilerOptionsBuilder::addHeaderPathOptions()
{
typedef ProjectPartHeaderPath HeaderPath;
const QString defaultPrefix = includeOption();
@@ -126,10 +127,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions(bool addAsNativePath)
break;
}
QString path = prefix + headerPath.path;
path = addAsNativePath ? QDir::toNativeSeparators(path) : path;
result.append(path);
result.append(prefix + QDir::toNativeSeparators(headerPath.path));
}
m_options.append(result);
@@ -393,7 +391,15 @@ bool CompilerOptionsBuilder::excludeDefineLine(const QByteArray &defineLine) con
bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const
{
Q_UNUSED(headerPath);
// A clang tool chain might have another version and passing in the
// intrinsics path from that version will lead to errors (unknown
// intrinsics, unfavorable order with regard to include_next).
if (m_projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
static QRegularExpression clangIncludeDir(
QLatin1String("\\A.*/lib/clang/\\d+\\.\\d+(\\.\\d+)?/include\\z"));
return clangIncludeDir.match(headerPath).hasMatch();
}
return false;
}

View File

@@ -46,7 +46,7 @@ public:
// Add options based on project part
virtual void addTargetTriple();
virtual void enableExceptions();
void addHeaderPathOptions(bool addAsNativePath = false);
void addHeaderPathOptions();
void addToolchainAndProjectDefines();
void addDefines(const QByteArray &defineDirectives);
virtual void addLanguageOption(ProjectFile::Kind fileKind);

View File

@@ -49,6 +49,7 @@ const char CPPTOOLS_SETTINGSGROUP[] = "CppTools";
const char LOWERCASE_CPPFILES_KEY[] = "LowerCaseFiles";
enum { lowerCaseFilesDefault = 1 };
const char CPPTOOLS_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview";
const char CPPTOOLS_SHOW_INFO_BAR_FOR_HEADER_ERRORS[] = "ShowInfoBarForHeaderErrors";
const char CPPTOOLS_MODEL_MANAGER_PCH_USAGE[] = "PCHUsage";
const char CPPTOOLS_SKIP_INDEXING_BIG_FILES[] = "SkipIndexingBigFiles";
const char CPPTOOLS_INDEXER_FILE_SIZE_LIMIT[] = "IndexerFileSizeLimit";

View File

@@ -267,3 +267,21 @@ void CppToolsSettings::setSortedEditorDocumentOutline(bool sorted)
ICore::settings()->setValue(sortEditorDocumentOutlineKey(), sorted);
emit editorDocumentOutlineSortingChanged(sorted);
}
static QString showHeaderErrorInfoBarKey()
{
return QLatin1String(CppTools::Constants::CPPTOOLS_SETTINGSGROUP)
+ QLatin1Char('/')
+ QLatin1String(CppTools::Constants::CPPTOOLS_SHOW_INFO_BAR_FOR_HEADER_ERRORS);
}
bool CppToolsSettings::showHeaderErrorInfoBar() const
{
return ICore::settings()->value(showHeaderErrorInfoBarKey(), true).toBool();
}
void CppToolsSettings::setShowHeaderErrorInfoBar(bool show)
{
ICore::settings()->setValue(showHeaderErrorInfoBarKey(), show);
emit showHeaderErrorInfoBarChanged(show);
}

View File

@@ -63,8 +63,12 @@ public:
bool sortedEditorDocumentOutline() const;
void setSortedEditorDocumentOutline(bool sorted);
bool showHeaderErrorInfoBar() const;
void setShowHeaderErrorInfoBar(bool show);
signals:
void editorDocumentOutlineSortingChanged(bool isSorted);
void showHeaderErrorInfoBarChanged(bool isShown);
private:
Internal::CppToolsSettingsPrivate *d;

View File

@@ -2374,6 +2374,7 @@ void QmlEnginePrivate::insertSubItems(WatchItem *parent, const QVariantList &pro
QTC_ASSERT(parent, return);
LookupItems itemsToLookup;
const QSet<QString> expandedINames = engine->watchHandler()->expandedINames();
foreach (const QVariant &property, properties) {
QmlV8ObjectData propertyData = extractData(property);
auto item = new WatchItem;
@@ -2395,7 +2396,7 @@ void QmlEnginePrivate::insertSubItems(WatchItem *parent, const QVariantList &pro
item->id = propertyData.handle;
item->type = propertyData.type;
item->value = propertyData.value.toString();
if (item->type.isEmpty())
if (item->type.isEmpty() || expandedINames.contains(item->iname))
itemsToLookup.insert(propertyData.handle, {item->iname, item->name, item->exp});
item->setHasChildren(propertyData.properties.count() > 0);
parent->appendChild(item);

View File

@@ -33,7 +33,8 @@ HEADERS += \
iosdeploystep.h \
iosdeploystepfactory.h \
iosdeploystepwidget.h \
iosanalyzesupport.h
iosanalyzesupport.h \
simulatorcontrol.h
SOURCES += \
@@ -61,7 +62,8 @@ SOURCES += \
iosdeploystep.cpp \
iosdeploystepfactory.cpp \
iosdeploystepwidget.cpp \
iosanalyzesupport.cpp
iosanalyzesupport.cpp \
simulatorcontrol.cpp
FORMS += \
iossettingswidget.ui \

View File

@@ -69,6 +69,8 @@ QtcPlugin {
"iossimulatorfactory.cpp",
"iossimulatorfactory.h",
"iostoolhandler.cpp",
"iostoolhandler.h"
"iostoolhandler.h",
"simulatorcontrol.cpp",
"simulatorcontrol.h"
]
}

View File

@@ -27,6 +27,7 @@
#include "iosconstants.h"
#include "iosdevice.h"
#include "iossimulator.h"
#include "simulatorcontrol.h"
#include "iosprobe.h"
#include <coreplugin/icore.h>
@@ -332,7 +333,7 @@ void IosConfigurations::updateSimulators()
dev = IDevice::ConstPtr(new IosSimulator(devId));
devManager->addDevice(dev);
}
IosSimulator::updateAvailableDevices();
SimulatorControl::updateAvailableSimulators();
}
void IosConfigurations::setDeveloperPath(const FileName &devPath)

View File

@@ -169,6 +169,8 @@ IosDebugSupport::IosDebugSupport(IosRunConfiguration *runConfig,
m_runner, &IosRunner::start);
connect(m_runControl, &RunControl::finished,
m_runner, &IosRunner::stop);
connect(m_runControl, &DebuggerRunControl::stateChanged,
m_runner, &IosRunner::debuggerStateChanged);
connect(m_runner, &IosRunner::gotServerPorts,
this, &IosDebugSupport::handleServerPorts);

View File

@@ -101,7 +101,12 @@ bool IosDeployStep::init(QList<const BuildStep *> &earlierSteps)
this->target()->activeRunConfiguration());
QTC_ASSERT(runConfig, return false);
m_bundlePath = runConfig->bundleDirectory().toString();
if (m_device.isNull()) {
if (iosdevice()) {
m_deviceType = IosDeviceType(IosDeviceType::IosDevice, deviceId());
} else if (iossimulator()) {
m_deviceType = runConfig->deviceType();
} else {
emit addOutput(tr("Error: no device available, deploy failed."),
BuildStep::ErrorMessageOutput);
return false;
@@ -113,17 +118,15 @@ void IosDeployStep::run(QFutureInterface<bool> &fi)
{
m_futureInterface = fi;
QTC_CHECK(m_transferStatus == NoTransfer);
if (iosdevice().isNull()) {
if (iossimulator().isNull())
if (device().isNull()) {
TaskHub::addTask(Task::Error, tr("Deployment failed. No iOS device found."),
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
reportRunResult(m_futureInterface, !iossimulator().isNull());
cleanup();
return;
}
m_toolHandler = new IosToolHandler(m_deviceType, this);
m_transferStatus = TransferInProgress;
QTC_CHECK(m_toolHandler == 0);
m_toolHandler = new IosToolHandler(IosDeviceType(IosDeviceType::IosDevice), this);
m_futureInterface.setProgressRange(0, 200);
m_futureInterface.setProgressValueAndText(0, QLatin1String("Transferring application"));
m_futureInterface.reportStarted();
@@ -136,7 +139,7 @@ void IosDeployStep::run(QFutureInterface<bool> &fi)
connect(m_toolHandler, &IosToolHandler::errorMsg,
this, &IosDeployStep::handleErrorMsg);
checkProvisioningProfile();
m_toolHandler->requestTransferApp(appBundle(), deviceId());
m_toolHandler->requestTransferApp(appBundle(), m_deviceType.identifier);
}
void IosDeployStep::cancel()
@@ -150,7 +153,7 @@ void IosDeployStep::cleanup()
QTC_CHECK(m_transferStatus != TransferInProgress);
m_transferStatus = NoTransfer;
m_device.clear();
m_toolHandler = 0;
m_toolHandler = nullptr;
m_expectFail = false;
}

View File

@@ -101,6 +101,7 @@ private:
QFutureInterface<bool> m_futureInterface;
ProjectExplorer::IDevice::ConstPtr m_device;
QString m_bundlePath;
IosDeviceType m_deviceType;
static const Core::Id Id;
bool m_expectFail;
};

View File

@@ -27,6 +27,7 @@
#include "iosconstants.h"
#include "iosmanager.h"
#include "iosdeploystep.h"
#include "simulatorcontrol.h"
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
@@ -346,7 +347,7 @@ IosDeviceType IosRunConfiguration::deviceType() const
{
QList<IosDeviceType> availableSimulators;
if (m_deviceType.type == IosDeviceType::SimulatedDevice)
availableSimulators = IosSimulator::availableDevices();
availableSimulators = SimulatorControl::availableSimulators();
if (!availableSimulators.isEmpty()) {
QList<IosDeviceType> elegibleDevices;
QString devname = m_deviceType.identifier.split(QLatin1Char(',')).value(0);
@@ -417,7 +418,7 @@ void IosRunConfigurationWidget::updateValues()
m_deviceTypeLabel->setVisible(showDeviceSelector);
m_deviceTypeComboBox->setVisible(showDeviceSelector);
if (showDeviceSelector && m_deviceTypeModel.rowCount() == 0) {
foreach (const IosDeviceType &dType, IosSimulator::availableDevices()) {
foreach (const IosDeviceType &dType, SimulatorControl::availableSimulators()) {
QStandardItem *item = new QStandardItem(dType.displayName);
QVariant v;
v.setValue(dType);

View File

@@ -168,6 +168,12 @@ void IosRunner::stop()
}
}
void IosRunner::debuggerStateChanged(Debugger::DebuggerState state)
{
if (m_toolHandler)
m_toolHandler->debuggerStateChanged(state);
}
void IosRunner::handleDidStartApp(IosToolHandler *handler, const QString &bundlePath,
const QString &deviceId, IosToolHandler::OpStatus status)
{

View File

@@ -29,6 +29,7 @@
#include "iostoolhandler.h"
#include "iossimulator.h"
#include <debugger/debuggerconstants.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
@@ -64,6 +65,9 @@ public:
void start();
void stop();
public slots:
void debuggerStateChanged(Debugger::DebuggerState state);
signals:
void didStartApp(Ios::IosToolHandler::OpStatus status);
void gotServerPorts(Utils::Port gdbPort, Utils::Port qmlPort);

View File

@@ -45,9 +45,6 @@ static const QLatin1String iosDeviceTypeDisplayNameKey = QLatin1String("displayN
static const QLatin1String iosDeviceTypeTypeKey = QLatin1String("type");
static const QLatin1String iosDeviceTypeIdentifierKey = QLatin1String("identifier");
QMutex IosSimulator::_mutex;
QList<IosDeviceType> IosSimulator::_availableDevices;
IosSimulator::IosSimulator(Core::Id id)
: IDevice(Core::Id(Constants::IOS_SIMULATOR_TYPE),
IDevice::AutoDetected,
@@ -124,48 +121,6 @@ IDevice::Ptr IosSimulator::clone() const
return IDevice::Ptr(new IosSimulator(*this));
}
QList<IosDeviceType> IosSimulator::availableDevices()
{
QMutexLocker l(&_mutex);
return _availableDevices;
}
void IosSimulator::setAvailableDevices(QList<IosDeviceType> value)
{
QMutexLocker l(&_mutex);
_availableDevices = value;
}
namespace {
void handleDeviceInfo(Ios::IosToolHandler *handler, const QString &deviceId,
const Ios::IosToolHandler::Dict &info)
{
Q_UNUSED(deviceId);
QList<IosDeviceType> res;
QMapIterator<QString, QString> i(info);
while (i.hasNext()) {
i.next();
IosDeviceType simulatorType(IosDeviceType::SimulatedDevice);
simulatorType.displayName = i.value();
simulatorType.identifier = i.key();
QStringList ids = i.key().split(QLatin1Char(','));
if (ids.length() > 1)
simulatorType.displayName += QLatin1String(", iOS ") + ids.last().trimmed();
res.append(simulatorType);
}
handler->deleteLater();
std::stable_sort(res.begin(), res.end());
IosSimulator::setAvailableDevices(res);
}
}
void IosSimulator::updateAvailableDevices()
{
IosToolHandler *toolHandler = new IosToolHandler(IosDeviceType(IosDeviceType::SimulatedDevice));
QObject::connect(toolHandler, &IosToolHandler::deviceInfo, &handleDeviceInfo);
toolHandler->requestDeviceInfo(QString());
}
void IosSimulator::fromMap(const QVariantMap &map)
{
IDevice::fromMap(map);

View File

@@ -67,10 +67,6 @@ public:
typedef QSharedPointer<IosSimulator> Ptr;
ProjectExplorer::IDevice::DeviceInfo deviceInformation() const override;
static QList<IosDeviceType> availableDevices();
static void setAvailableDevices(QList<IosDeviceType> value);
static void updateAvailableDevices();
QString displayType() const override;
ProjectExplorer::IDeviceWidget *createWidget() override;
QList<Core::Id> actionIds() const override;
@@ -91,8 +87,6 @@ protected:
IosSimulator(const IosSimulator &other);
private:
mutable quint16 m_lastPort;
static QMutex _mutex;
static QList<IosDeviceType> _availableDevices;
};
namespace IosKitInformation {

View File

@@ -27,13 +27,18 @@
#include "iosconfigurations.h"
#include "iosconstants.h"
#include "iossimulator.h"
#include "simulatorcontrol.h"
#include "debugger/debuggerconstants.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <utils/fileutils.h>
#include <QCoreApplication>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QList>
#include <QLoggingCategory>
#include <QProcess>
@@ -52,6 +57,8 @@ namespace Ios {
namespace Internal {
using namespace std::placeholders;
struct ParserState {
enum Kind {
Msg,
@@ -132,7 +139,8 @@ public:
virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000) = 0;
bool isRunning();
void start(const QString &exe, const QStringList &args);
void stop(int errorCode);
virtual void stop(int errorCode) = 0;
virtual void debuggerStateChanged(Debugger::DebuggerState state) { Q_UNUSED(state); }
// signals
void isTransferringApp(const QString &bundlePath, const QString &deviceId, int progress,
@@ -148,15 +156,12 @@ public:
void appOutput(const QString &output);
void errorMsg(const QString &msg);
void toolExited(int code);
// slots
void subprocessError(QProcess::ProcessError error);
void subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void subprocessHasData();
void killProcess();
virtual bool expectsFileDescriptor() = 0;
protected:
void processXml();
protected:
void killProcess();
protected:
IosToolHandler *q;
QProcess *process;
QTimer killTimer;
@@ -176,34 +181,56 @@ class IosDeviceToolHandlerPrivate : public IosToolHandlerPrivate
{
public:
explicit IosDeviceToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q);
virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId,
int timeout = 1000);
virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
// IosToolHandlerPrivate overrides
public:
void requestTransferApp(const QString &bundlePath, const QString &deviceId,
int timeout = 1000) override;
void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
IosToolHandler::RunKind runKind,
const QString &deviceId, int timeout = 1000);
virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
virtual bool expectsFileDescriptor();
const QString &deviceId, int timeout = 1000) override;
void requestDeviceInfo(const QString &deviceId, int timeout = 1000) override;
void stop(int errorCode) override;
private:
void subprocessError(QProcess::ProcessError error);
void subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void subprocessHasData();
void processXml();
};
class IosSimulatorToolHandlerPrivate : public IosToolHandlerPrivate
{
public:
explicit IosSimulatorToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q);
virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId,
int timeout = 1000);
virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
// IosToolHandlerPrivate overrides
public:
void requestTransferApp(const QString &bundlePath, const QString &deviceIdentifier,
int timeout = 1000) override;
void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
IosToolHandler::RunKind runKind,
const QString &deviceId, int timeout = 1000);
virtual void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
virtual bool expectsFileDescriptor();
const QString &deviceIdentifier, int timeout = 1000) override;
void requestDeviceInfo(const QString &deviceId, int timeout = 1000) override;
void stop(int errorCode) override;
void debuggerStateChanged(Debugger::DebuggerState state) override;
private:
void addDeviceArguments(QStringList &args) const;
void simAppProcessError(QProcess::ProcessError error);
void simAppProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void simAppProcessHasData();
void simAppProcessHasErrorOutput();
void launchAppOnSimulator();
private:
qint64 appPId = -1;
bool appLaunched = false;
};
IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType,
Ios::IosToolHandler *q) :
q(q),
process(new QProcess),
process(nullptr),
state(NonStarted),
devType(devType),
iBegin(0),
@@ -211,34 +238,6 @@ IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType,
gdbSocket(-1)
{
killTimer.setSingleShot(true);
QProcessEnvironment env(QProcessEnvironment::systemEnvironment());
foreach (const QString &k, env.keys())
if (k.startsWith(QLatin1String("DYLD_")))
env.remove(k);
QStringList frameworkPaths;
Utils::FileName xcPath = IosConfigurations::developerPath();
QString privateFPath = xcPath.appendPath(QLatin1String("Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks")).toFileInfo().canonicalFilePath();
if (!privateFPath.isEmpty())
frameworkPaths << privateFPath;
QString otherFPath = xcPath.appendPath(QLatin1String("../OtherFrameworks")).toFileInfo().canonicalFilePath();
if (!otherFPath.isEmpty())
frameworkPaths << otherFPath;
QString sharedFPath = xcPath.appendPath(QLatin1String("../SharedFrameworks")).toFileInfo().canonicalFilePath();
if (!sharedFPath.isEmpty())
frameworkPaths << sharedFPath;
frameworkPaths << QLatin1String("/System/Library/Frameworks")
<< QLatin1String("/System/Library/PrivateFrameworks");
env.insert(QLatin1String("DYLD_FALLBACK_FRAMEWORK_PATH"), frameworkPaths.join(QLatin1Char(':')));
qCDebug(toolHandlerLog) << "IosToolHandler runEnv:" << env.toStringList();
process->setProcessEnvironment(env);
QObject::connect(process, &QProcess::readyReadStandardOutput,
q, &IosToolHandler::subprocessHasData);
QObject::connect(process,
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
q, &IosToolHandler::subprocessFinished);
QObject::connect(process, &QProcess::errorOccurred, q, &IosToolHandler::subprocessError);
QObject::connect(&killTimer, &QTimer::timeout,
q, &IosToolHandler::killProcess);
}
IosToolHandlerPrivate::~IosToolHandlerPrivate()
@@ -258,6 +257,7 @@ bool IosToolHandlerPrivate::isRunning()
void IosToolHandlerPrivate::start(const QString &exe, const QStringList &args)
{
Q_ASSERT(process);
QTC_CHECK(state == NonStarted);
state = Starting;
qCDebug(toolHandlerLog) << "running " << exe << args;
@@ -265,44 +265,6 @@ void IosToolHandlerPrivate::start(const QString &exe, const QStringList &args)
state = StartedInferior;
}
void IosToolHandlerPrivate::stop(int errorCode)
{
qCDebug(toolHandlerLog) << "IosToolHandlerPrivate::stop";
State oldState = state;
state = Stopped;
switch (oldState) {
case NonStarted:
qCWarning(toolHandlerLog) << "IosToolHandler::stop() when state was NonStarted";
// pass
case Starting:
switch (op){
case OpNone:
qCWarning(toolHandlerLog) << "IosToolHandler::stop() when op was OpNone";
break;
case OpAppTransfer:
didTransferApp(bundlePath, deviceId, IosToolHandler::Failure);
break;
case OpAppRun:
didStartApp(bundlePath, deviceId, IosToolHandler::Failure);
break;
case OpDeviceInfo:
break;
}
// pass
case StartedInferior:
case XmlEndProcessed:
toolExited(errorCode);
break;
case Stopped:
return;
}
if (isRunning()) {
process->write("k\n\r");
process->closeWriteChannel();
killTimer.start(1500);
}
}
// signals
void IosToolHandlerPrivate::isTransferringApp(const QString &bundlePath, const QString &deviceId,
int progress, int maxProgress, const QString &info)
@@ -355,7 +317,7 @@ void IosToolHandlerPrivate::toolExited(int code)
emit q->toolExited(q, code);
}
void IosToolHandlerPrivate::subprocessError(QProcess::ProcessError error)
void IosDeviceToolHandlerPrivate::subprocessError(QProcess::ProcessError error)
{
if (state != Stopped)
errorMsg(IosToolHandler::tr("iOS tool Error %1").arg(error));
@@ -366,7 +328,7 @@ void IosToolHandlerPrivate::subprocessError(QProcess::ProcessError error)
}
}
void IosToolHandlerPrivate::subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
void IosDeviceToolHandlerPrivate::subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
stop((exitStatus == QProcess::NormalExit) ? exitCode : -1 );
qCDebug(toolHandlerLog) << "IosToolHandler::finished(" << this << ")";
@@ -374,7 +336,7 @@ void IosToolHandlerPrivate::subprocessFinished(int exitCode, QProcess::ExitStatu
emit q->finished(q);
}
void IosToolHandlerPrivate::processXml()
void IosDeviceToolHandlerPrivate::processXml()
{
while (!outputParser.atEnd()) {
QXmlStreamReader::TokenType tt = outputParser.readNext();
@@ -556,7 +518,7 @@ void IosToolHandlerPrivate::processXml()
}
}
void IosToolHandlerPrivate::subprocessHasData()
void IosDeviceToolHandlerPrivate::subprocessHasData()
{
qCDebug(toolHandlerLog) << "subprocessHasData, state:" << state;
while (true) {
@@ -596,7 +558,42 @@ void IosToolHandlerPrivate::subprocessHasData()
IosDeviceToolHandlerPrivate::IosDeviceToolHandlerPrivate(const IosDeviceType &devType,
IosToolHandler *q)
: IosToolHandlerPrivate(devType, q)
{ }
{
process = new QProcess;
// Prepare & set process Environment.
QProcessEnvironment env(QProcessEnvironment::systemEnvironment());
foreach (const QString &k, env.keys())
if (k.startsWith(QLatin1String("DYLD_")))
env.remove(k);
QStringList frameworkPaths;
Utils::FileName xcPath = IosConfigurations::developerPath();
QString privateFPath = xcPath.appendPath(QLatin1String("Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks")).toFileInfo().canonicalFilePath();
if (!privateFPath.isEmpty())
frameworkPaths << privateFPath;
QString otherFPath = xcPath.appendPath(QLatin1String("../OtherFrameworks")).toFileInfo().canonicalFilePath();
if (!otherFPath.isEmpty())
frameworkPaths << otherFPath;
QString sharedFPath = xcPath.appendPath(QLatin1String("../SharedFrameworks")).toFileInfo().canonicalFilePath();
if (!sharedFPath.isEmpty())
frameworkPaths << sharedFPath;
frameworkPaths << QLatin1String("/System/Library/Frameworks")
<< QLatin1String("/System/Library/PrivateFrameworks");
env.insert(QLatin1String("DYLD_FALLBACK_FRAMEWORK_PATH"), frameworkPaths.join(QLatin1Char(':')));
qCDebug(toolHandlerLog) << "IosToolHandler runEnv:" << env.toStringList();
process->setProcessEnvironment(env);
QObject::connect(process, &QProcess::readyReadStandardOutput,
std::bind(&IosDeviceToolHandlerPrivate::subprocessHasData,this));
QObject::connect(process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
std::bind(&IosDeviceToolHandlerPrivate::subprocessFinished,this, _1,_2));
QObject::connect(process, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error),
std::bind(&IosDeviceToolHandlerPrivate::subprocessError, this, _1));
QObject::connect(&killTimer, &QTimer::timeout, std::bind(&IosDeviceToolHandlerPrivate::killProcess, this));
}
void IosDeviceToolHandlerPrivate::requestTransferApp(const QString &bundlePath,
const QString &deviceId, int timeout)
@@ -644,10 +641,45 @@ void IosDeviceToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, int
start(IosToolHandler::iosDeviceToolPath(), args);
}
bool IosDeviceToolHandlerPrivate::expectsFileDescriptor()
void IosDeviceToolHandlerPrivate::stop(int errorCode)
{
return op == OpAppRun && runKind == IosToolHandler::DebugRun;
qCDebug(toolHandlerLog) << "IosToolHandlerPrivate::stop";
State oldState = state;
state = Stopped;
switch (oldState) {
case NonStarted:
qCWarning(toolHandlerLog) << "IosToolHandler::stop() when state was NonStarted";
// pass
case Starting:
switch (op){
case OpNone:
qCWarning(toolHandlerLog) << "IosToolHandler::stop() when op was OpNone";
break;
case OpAppTransfer:
didTransferApp(bundlePath, deviceId, IosToolHandler::Failure);
break;
case OpAppRun:
didStartApp(bundlePath, deviceId, IosToolHandler::Failure);
break;
case OpDeviceInfo:
break;
}
// pass
case StartedInferior:
case XmlEndProcessed:
toolExited(errorCode);
break;
case Stopped:
return;
}
if (isRunning()) {
process->write("k\n\r");
process->closeWriteChannel();
killTimer.start(1500);
}
}
// IosSimulatorToolHandlerPrivate
@@ -657,64 +689,159 @@ IosSimulatorToolHandlerPrivate::IosSimulatorToolHandlerPrivate(const IosDeviceTy
{ }
void IosSimulatorToolHandlerPrivate::requestTransferApp(const QString &bundlePath,
const QString &deviceId, int timeout)
const QString &deviceIdentifier, int timeout)
{
Q_UNUSED(timeout);
this->bundlePath = bundlePath;
this->deviceId = deviceId;
emit didTransferApp(bundlePath, deviceId, IosToolHandler::Success);
this->deviceId = deviceIdentifier;
isTransferringApp(bundlePath, deviceId, 0, 100, "");
if (SimulatorControl::startSimulator(deviceId)) {
isTransferringApp(bundlePath, deviceId, 20, 100, "");
QByteArray cmdOutput;
if (SimulatorControl::installApp(deviceId, Utils::FileName::fromString(bundlePath), cmdOutput)) {
isTransferringApp(bundlePath, deviceId, 100, 100, "");
didTransferApp(bundlePath, deviceId, IosToolHandler::Success);
} else {
errorMsg(IosToolHandler::tr("Application install on Simulator failed. %1").arg(QString::fromLocal8Bit(cmdOutput)));
didTransferApp(bundlePath, deviceId, IosToolHandler::Failure);
}
} else {
errorMsg(IosToolHandler::tr("Application install on Simulator failed. Simulator not running."));
didTransferApp(bundlePath, deviceId, IosToolHandler::Failure);
}
emit q->finished(q);
}
void IosSimulatorToolHandlerPrivate::requestRunApp(const QString &bundlePath,
const QStringList &extraArgs,
IosToolHandler::RunKind runType,
const QString &deviceId, int timeout)
const QString &deviceIdentifier, int timeout)
{
Q_UNUSED(timeout);
Q_UNUSED(deviceIdentifier);
this->bundlePath = bundlePath;
this->deviceId = deviceId;
this->deviceId = devType.identifier;
this->runKind = runType;
QStringList args;
args << QLatin1String("launch") << bundlePath;
Utils::FileName devPath = IosConfigurations::developerPath();
if (!devPath.isEmpty())
args << QLatin1String("--developer-path") << devPath.toString();
addDeviceArguments(args);
switch (runType) {
case IosToolHandler::NormalRun:
break;
case IosToolHandler::DebugRun:
args << QLatin1String("--wait-for-debugger");
break;
}
args << QLatin1String("--args") << extraArgs;
op = OpAppRun;
start(IosToolHandler::iosSimulatorToolPath(), args);
Utils::FileName appBundle = Utils::FileName::fromString(bundlePath);
if (!appBundle.exists()) {
errorMsg(IosToolHandler::tr("Application launch on Simulator failed. Invalid Bundle path %1")
.arg(bundlePath));
didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure);
return;
}
if (SimulatorControl::startSimulator(deviceId)) {
qint64 pId = -1;
bool debugRun = runType == IosToolHandler::DebugRun;
QProcess* controlProcess = SimulatorControl::spawnAppProcess(deviceId, appBundle, pId, debugRun, extraArgs);
if (controlProcess) {
Q_ASSERT(!process || !isRunning());
if (process) {
delete process;
process = nullptr;
}
process = controlProcess;
QObject::connect(process, &QProcess::readyReadStandardOutput,
std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasData,this));
QObject::connect(process, &QProcess::readyReadStandardError,
std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessHasErrorOutput,this));
QObject::connect(process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessFinished,this, _1,_2));
QObject::connect(process, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error),
std::bind(&IosSimulatorToolHandlerPrivate::simAppProcessError, this, _1));
appPId = pId;
gotInferiorPid(bundlePath,deviceId,pId);
// For debug run, wait for the debugger to attach and then launch the app.
if (!debugRun) {
launchAppOnSimulator();
}
} else {
errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed."));
didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure);
}
} else {
errorMsg(IosToolHandler::tr("Application launch on Simulator failed. Simulator not running.")
.arg(bundlePath));
didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure);
}
}
void IosSimulatorToolHandlerPrivate::launchAppOnSimulator()
{
// Wait for the app to reach a state when we can launch it on the simulator.
if (appPId != -1 && SimulatorControl::waitForProcessSpawn(appPId)) {
QByteArray commandOutput;
Utils::FileName appBundle = Utils::FileName::fromString(bundlePath);
if (SimulatorControl::launchApp(deviceId, SimulatorControl::bundleIdentifier(appBundle), &commandOutput) != -1) {
appLaunched = true;
didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Success);
} else {
errorMsg(IosToolHandler::tr("Application launch on Simulator failed. %1")
.arg(QString::fromLocal8Bit(commandOutput)));
didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure);
}
} else {
errorMsg(IosToolHandler::tr("Spawning the Application process on Simulator failed. Spawning timed out."));
didStartApp(bundlePath, deviceId, Ios::IosToolHandler::Failure);
}
}
void IosSimulatorToolHandlerPrivate::requestDeviceInfo(const QString &deviceId, int timeout)
{
Q_UNUSED(timeout);
this->deviceId = deviceId;
QStringList args;
args << QLatin1String("showdevicetypes");
op = OpDeviceInfo;
start(IosToolHandler::iosSimulatorToolPath(), args);
Q_UNUSED(deviceId);
}
bool IosSimulatorToolHandlerPrivate::expectsFileDescriptor()
void IosSimulatorToolHandlerPrivate::stop(int errorCode)
{
return false;
if (process) {
if (isRunning()) {
process->terminate();
if (!process->waitForFinished(1000))
process->kill();
}
process->deleteLater();
process = nullptr;
appPId = -1;
appLaunched = false;
}
void IosSimulatorToolHandlerPrivate::addDeviceArguments(QStringList &args) const
{
if (devType.type != IosDeviceType::SimulatedDevice) {
qCWarning(toolHandlerLog) << "IosSimulatorToolHandlerPrivate device type is not SimulatedDevice";
return;
toolExited(errorCode);
}
args << QLatin1String("--devicetypeid") << devType.identifier;
void IosSimulatorToolHandlerPrivate::debuggerStateChanged(Debugger::DebuggerState state)
{
if (!appLaunched && state == Debugger::DebuggerState::InferiorRunOk) {
// Debugger attached. Launch it on the simulator.
launchAppOnSimulator();
}
}
void IosSimulatorToolHandlerPrivate::simAppProcessError(QProcess::ProcessError error)
{
errorMsg(IosToolHandler::tr("Simulator application process error %1").arg(error));
}
void IosSimulatorToolHandlerPrivate::simAppProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
stop((exitStatus == QProcess::NormalExit) ? exitCode : -1 );
qCDebug(toolHandlerLog) << "IosToolHandler::finished(" << this << ")";
q->finished(q);
}
void IosSimulatorToolHandlerPrivate::simAppProcessHasData()
{
appOutput(QString::fromLocal8Bit(process->readAllStandardOutput()));
}
void IosSimulatorToolHandlerPrivate::simAppProcessHasErrorOutput()
{
errorMsg(QString::fromLocal8Bit(process->readAllStandardError()));
}
void IosToolHandlerPrivate::killProcess()
@@ -731,18 +858,6 @@ QString IosToolHandler::iosDeviceToolPath()
return res;
}
QString IosToolHandler::iosSimulatorToolPath()
{
Utils::FileName devPath = Internal::IosConfigurations::developerPath();
bool version182 = devPath.appendPath(QLatin1String(
"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/iPhoneSimulatorRemoteClient.framework"))
.exists();
QString res = Core::ICore::libexecPath() + QLatin1String("/ios/iossim");
if (version182)
res = res.append(QLatin1String("_1_8_2"));
return res;
}
IosToolHandler::IosToolHandler(const Internal::IosDeviceType &devType, QObject *parent) :
QObject(parent)
{
@@ -762,6 +877,11 @@ void IosToolHandler::stop()
d->stop(-1);
}
void IosToolHandler::debuggerStateChanged(int state)
{
d->debuggerStateChanged((Debugger::DebuggerState)state);
}
void IosToolHandler::requestTransferApp(const QString &bundlePath, const QString &deviceId,
int timeout)
{
@@ -784,24 +904,4 @@ bool IosToolHandler::isRunning()
return d->isRunning();
}
void IosToolHandler::subprocessError(QProcess::ProcessError error)
{
d->subprocessError(error);
}
void IosToolHandler::subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
d->subprocessFinished(exitCode, exitStatus);
}
void IosToolHandler::subprocessHasData()
{
d->subprocessHasData();
}
void IosToolHandler::killProcess()
{
d->killProcess();
}
} // namespace Ios

View File

@@ -33,7 +33,6 @@
#include <QStringList>
#include <QProcess>
namespace Ios {
namespace Internal {
class IosToolHandlerPrivate;
@@ -56,7 +55,6 @@ public:
};
static QString iosDeviceToolPath();
static QString iosSimulatorToolPath();
explicit IosToolHandler(const Internal::IosDeviceType &type, QObject *parent = 0);
~IosToolHandler();
@@ -66,6 +64,7 @@ public:
void requestDeviceInfo(const QString &deviceId, int timeout = 1000);
bool isRunning();
void stop();
void debuggerStateChanged(int state);
signals:
void isTransferringApp(Ios::IosToolHandler *handler, const QString &bundlePath,
@@ -85,11 +84,10 @@ signals:
void errorMsg(Ios::IosToolHandler *handler, const QString &msg);
void toolExited(Ios::IosToolHandler *handler, int code);
void finished(Ios::IosToolHandler *handler);
private:
void subprocessError(QProcess::ProcessError error);
void subprocessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void subprocessHasData();
protected:
void killProcess();
private:
friend class Ios::Internal::IosToolHandlerPrivate;
Ios::Internal::IosToolHandlerPrivate *d;

View File

@@ -0,0 +1,422 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "simulatorcontrol.h"
#include "iossimulator.h"
#include "iosconfigurations.h"
#ifdef Q_OS_MAC
#include <CoreFoundation/CoreFoundation.h>
#endif
#include <chrono>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLoggingCategory>
#include <QMap>
#include <QProcess>
#include <QReadLocker>
#include <QReadWriteLock>
#include <QTime>
#include <QUrl>
#include <QWriteLocker>
namespace {
Q_LOGGING_CATEGORY(simulatorLog, "qtc.ios.simulator")
}
namespace Ios {
namespace Internal {
static int COMMAND_TIMEOUT = 10000;
static int SIMULATOR_TIMEOUT = 60000;
static bool checkForTimeout(const std::chrono::time_point< std::chrono::high_resolution_clock, std::chrono::nanoseconds> &start, int msecs = COMMAND_TIMEOUT)
{
bool timedOut = false;
auto end = std::chrono::high_resolution_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() > msecs)
timedOut = true;
return timedOut;
}
class SimulatorControlPrivate :QObject {
Q_OBJECT
private:
struct SimDeviceInfo {
bool isBooted() const { return state.compare(QStringLiteral("Booted")) == 0; }
bool isAvailable() const { return !availability.contains(QStringLiteral("unavailable")); }
QString name;
QString udid;
QString availability;
QString state;
QString sdk;
};
SimulatorControlPrivate(QObject *parent = nullptr);
~SimulatorControlPrivate();
QByteArray runSimCtlCommand(QStringList args) const;
SimDeviceInfo deviceInfo(const QString &simUdid) const;
bool runCommand(QString command, const QStringList &args, QByteArray *output = nullptr);
QHash<QString, QProcess*> simulatorProcesses;
QReadWriteLock processDataLock;
QList<IosDeviceType> availableDevices;
QReadWriteLock deviceDataLock;
friend class SimulatorControl;
};
SimulatorControlPrivate *SimulatorControl::d = new SimulatorControlPrivate;
SimulatorControl::SimulatorControl()
{
}
QList<Ios::Internal::IosDeviceType> SimulatorControl::availableSimulators()
{
QReadLocker locer(&d->deviceDataLock);
return d->availableDevices;
}
void SimulatorControl::updateAvailableSimulators()
{
const QByteArray output = d->runSimCtlCommand({QLatin1String("list"), QLatin1String("-j"), QLatin1String("devices")});
QJsonDocument doc = QJsonDocument::fromJson(output);
if (!doc.isNull()) {
QList<IosDeviceType> availableDevices;
const QJsonObject buildInfo = doc.object().value("devices").toObject();
foreach (const QString &buildVersion, buildInfo.keys()) {
QJsonArray devices = buildInfo.value(buildVersion).toArray();
foreach (const QJsonValue device, devices) {
QJsonObject deviceInfo = device.toObject();
QString deviceName = QString("%1, %2")
.arg(deviceInfo.value("name").toString("Unknown"))
.arg(buildVersion);
QString deviceUdid = deviceInfo.value("udid").toString("Unknown");
if (!deviceInfo.value("availability").toString().contains("unavailable")) {
IosDeviceType iOSDevice(IosDeviceType::SimulatedDevice, deviceUdid, deviceName);
availableDevices.append(iOSDevice);
}
}
}
std::stable_sort(availableDevices.begin(), availableDevices.end());
{
QWriteLocker locker(&d->deviceDataLock);
d->availableDevices = availableDevices;
}
} else {
qCDebug(simulatorLog) << "Error parsing json output from simctl. Output:" << output;
}
}
// Blocks until simulators reaches "Booted" state.
bool SimulatorControl::startSimulator(const QString &simUdid)
{
QWriteLocker locker(&d->processDataLock);
bool simulatorRunning = isSimulatorRunning(simUdid);
if (!simulatorRunning && d->deviceInfo(simUdid).isAvailable()) {
// Simulator is not running but it's available. Start the simulator.
QProcess *p = new QProcess;
QObject::connect(p, static_cast<void(QProcess::*)(int)>(&QProcess::finished), [simUdid]() {
QWriteLocker locker(&d->processDataLock);
d->simulatorProcesses[simUdid]->deleteLater();
d->simulatorProcesses.remove(simUdid);
});
const QString cmd = IosConfigurations::developerPath().appendPath(QStringLiteral("/Applications/Simulator.app")).toString();
const QStringList args({QStringLiteral("--args"), QStringLiteral("-CurrentDeviceUDID"), simUdid});
p->start(cmd, args);
if (p->waitForStarted()) {
d->simulatorProcesses[simUdid] = p;
// At this point the sim device exists, available and was not running.
// So the simulator is started and we'll wait for it to reach to a state
// where we can interact with it.
auto start = std::chrono::high_resolution_clock::now();
SimulatorControlPrivate::SimDeviceInfo info;
do {
info = d->deviceInfo(simUdid);
} while (!info.isBooted()
&& p->state() == QProcess::Running
&& !checkForTimeout(start, SIMULATOR_TIMEOUT));
simulatorRunning = info.isBooted();
} else {
qCDebug(simulatorLog) << "Error starting simulator." << p->errorString();
delete p;
}
}
return simulatorRunning;
}
bool SimulatorControl::isSimulatorRunning(const QString &simUdid)
{
if (simUdid.isEmpty())
return false;
return d->deviceInfo(simUdid).isBooted();
}
bool SimulatorControl::installApp(const QString &simUdid, const Utils::FileName &bundlePath, QByteArray &commandOutput)
{
bool installed = false;
if (isSimulatorRunning(simUdid)) {
commandOutput = d->runSimCtlCommand(QStringList() << QStringLiteral("install") << simUdid << bundlePath.toString());
installed = commandOutput.isEmpty();
} else {
commandOutput = "Simulator device not running.";
}
return installed;
}
qint64 SimulatorControl::launchApp(const QString &simUdid, const QString &bundleIdentifier, QByteArray* commandOutput)
{
qint64 pId = -1;
pId = -1;
if (!bundleIdentifier.isEmpty() && isSimulatorRunning(simUdid)) {
const QStringList args({QStringLiteral("launch"), simUdid , bundleIdentifier});
const QByteArray output = d->runSimCtlCommand(args);
const QByteArray pIdStr = output.trimmed().split(' ').last().trimmed();
bool validInt = false;
pId = pIdStr.toLongLong(&validInt);
if (!validInt) {
// Launch Failed.
qCDebug(simulatorLog) << "Launch app failed. Process id returned is not valid. PID =" << pIdStr;
pId = -1;
if (commandOutput)
*commandOutput = output;
}
}
return pId;
}
QString SimulatorControl::bundleIdentifier(const Utils::FileName &bundlePath)
{
QString bundleID;
#ifdef Q_OS_MAC
if (bundlePath.exists()) {
CFStringRef cFBundlePath = bundlePath.toString().toCFString();
CFURLRef bundle_url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, cFBundlePath, kCFURLPOSIXPathStyle, true);
CFRelease(cFBundlePath);
CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, bundle_url);
CFRelease(bundle_url);
CFStringRef cFBundleID = CFBundleGetIdentifier(bundle);
bundleID = QString::fromCFString(cFBundleID).trimmed();
CFRelease(bundle);
}
#else
Q_UNUSED(bundlePath)
#endif
return bundleID;
}
QString SimulatorControl::bundleExecutable(const Utils::FileName &bundlePath)
{
QString executable;
#ifdef Q_OS_MAC
if (bundlePath.exists()) {
CFStringRef cFBundlePath = bundlePath.toString().toCFString();
CFURLRef bundle_url = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, cFBundlePath, kCFURLPOSIXPathStyle, true);
CFRelease(cFBundlePath);
CFBundleRef bundle = CFBundleCreate (kCFAllocatorDefault, bundle_url);
CFStringRef cFStrExecutableName = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey);
executable = QString::fromCFString(cFStrExecutableName).trimmed();
CFRelease(bundle);
}
#else
Q_UNUSED(bundlePath)
#endif
return executable;
}
SimulatorControlPrivate::SimulatorControlPrivate(QObject *parent):
QObject(parent),
processDataLock(QReadWriteLock::Recursive)
{
}
SimulatorControlPrivate::~SimulatorControlPrivate()
{
}
QByteArray SimulatorControlPrivate::runSimCtlCommand(QStringList args) const
{
QProcess simCtlProcess;
args.prepend(QStringLiteral("simctl"));
simCtlProcess.start(QStringLiteral("xcrun"), args, QProcess::ReadOnly);
if (!simCtlProcess.waitForFinished())
qCDebug(simulatorLog) << "simctl command failed." << simCtlProcess.errorString();
return simCtlProcess.readAll();
}
// The simctl spawns the process and returns the pId but the application process might not have started, at least in a state where you can interrupt it.
// Use SimulatorControl::waitForProcessSpawn to be sure.
QProcess *SimulatorControl::spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, qint64 &pId, bool waitForDebugger, const QStringList &extraArgs)
{
QProcess *simCtlProcess = nullptr;
if (isSimulatorRunning(simUdid)) {
QString bundleId = bundleIdentifier(bundlePath);
QString executableName = bundleExecutable(bundlePath);
QByteArray appPath = d->runSimCtlCommand(QStringList() << QStringLiteral("get_app_container") << simUdid << bundleId).trimmed();
if (!appPath.isEmpty() && !executableName.isEmpty()) {
// Spawn the app. The spawned app is started in suspended mode.
appPath.append('/' + executableName.toLocal8Bit());
simCtlProcess = new QProcess;
QStringList args;
args << QStringLiteral("simctl");
args << QStringLiteral("spawn");
if (waitForDebugger)
args << QStringLiteral("-w");
args << simUdid;
args << QString::fromLocal8Bit(appPath);
args << extraArgs;
simCtlProcess->start(QStringLiteral("xcrun"), args);
if (!simCtlProcess->waitForStarted()){
// Spawn command failed.
qCDebug(simulatorLog) << "Spawning the app failed." << simCtlProcess->errorString();
delete simCtlProcess;
simCtlProcess = nullptr;
}
// Find the process id of the the app process.
if (simCtlProcess) {
qint64 simctlPId = simCtlProcess->processId();
pId = -1;
QByteArray commandOutput;
QStringList pGrepArgs;
pGrepArgs << QStringLiteral("-f") << QString::fromLocal8Bit(appPath);
auto begin = std::chrono::high_resolution_clock::now();
// Find the pid of the spawned app.
while (pId == -1 && d->runCommand(QStringLiteral("pgrep"), pGrepArgs, &commandOutput)) {
foreach (auto pidStr, commandOutput.trimmed().split('\n')) {
qint64 parsedPId = pidStr.toLongLong();
if (parsedPId != simctlPId)
pId = parsedPId;
}
if (checkForTimeout(begin)) {
qCDebug(simulatorLog) << "Spawning the app failed. Process timed out";
break;
}
}
}
if (pId == -1) {
// App process id can't be found.
qCDebug(simulatorLog) << "Spawning the app failed. PID not found.";
delete simCtlProcess;
simCtlProcess = nullptr;
}
} else {
qCDebug(simulatorLog) << "Spawning the app failed. Check installed app." << appPath;
}
} else {
qCDebug(simulatorLog) << "Spawning the app failed. Simulator not running." << simUdid;
}
return simCtlProcess;
}
bool SimulatorControl::waitForProcessSpawn(qint64 processPId)
{
bool success = true;
if (processPId != -1) {
// Wait for app to reach intruptible sleep state.
QByteArray wqStr;
QStringList args;
int wqCount = -1;
args << QStringLiteral("-p") << QString::number(processPId) << QStringLiteral("-o") << QStringLiteral("wq=");
auto begin = std::chrono::high_resolution_clock::now();
do {
if (!d->runCommand(QStringLiteral("ps"), args, &wqStr)) {
success = false;
break;
}
bool validInt = false;
wqCount = wqStr.toInt(&validInt);
if (!validInt) {
wqCount = -1;
}
} while (wqCount < 0 && !checkForTimeout(begin));
success = wqCount >= 0;
} else {
qCDebug(simulatorLog) << "Wait for spawned failed. Invalid Process ID." << processPId;
}
return success;
}
SimulatorControlPrivate::SimDeviceInfo SimulatorControlPrivate::deviceInfo(const QString &simUdid) const
{
SimDeviceInfo info;
bool found = false;
if (!simUdid.isEmpty()) {
// It might happend that the simulator is not started by SimControl.
// Check of intances started externally.
const QByteArray output = runSimCtlCommand({QLatin1String("list"), QLatin1String("-j"), QLatin1String("devices")});
QJsonDocument doc = QJsonDocument::fromJson(output);
if (!doc.isNull()) {
const QJsonObject buildInfo = doc.object().value(QStringLiteral("devices")).toObject();
foreach (const QString &buildVersion, buildInfo.keys()) {
QJsonArray devices = buildInfo.value(buildVersion).toArray();
foreach (const QJsonValue device, devices) {
QJsonObject deviceInfo = device.toObject();
QString deviceUdid = deviceInfo.value(QStringLiteral("udid")).toString();
if (deviceUdid.compare(simUdid) == 0) {
found = true;
info.name = deviceInfo.value(QStringLiteral("name")).toString();
info.udid = deviceUdid;
info.state = deviceInfo.value(QStringLiteral("state")).toString();
info.sdk = buildVersion;
info.availability = deviceInfo.value(QStringLiteral("availability")).toString();
break;
}
}
if (found)
break;
}
} else {
qCDebug(simulatorLog) << "Cannot find device info. Error parsing json output from simctl. Output:" << output;
}
} else {
qCDebug(simulatorLog) << "Cannot find device info. Invalid UDID.";
}
return info;
}
bool SimulatorControlPrivate::runCommand(QString command, const QStringList &args, QByteArray *output)
{
bool success = false;
QProcess process;
process.start(command, args);
success = process.waitForFinished();
if (output)
*output = process.readAll().trimmed();
return success;
}
} // namespace Internal
} // namespace Ios
#include "simulatorcontrol.moc"

View File

@@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#ifndef SIMULATORCONTROL_H
#define SIMULATORCONTROL_H
#include <QHash>
#include "utils/fileutils.h"
class QProcess;
namespace Ios {
namespace Internal {
class IosDeviceType;
class SimulatorControlPrivate;
class SimulatorControl
{
explicit SimulatorControl();
public:
static QList<IosDeviceType> availableSimulators();
static void updateAvailableSimulators();
static bool startSimulator(const QString &simUdid);
static bool isSimulatorRunning(const QString &simUdid);
static bool installApp(const QString &simUdid, const Utils::FileName &bundlePath, QByteArray &commandOutput);
static QProcess* spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, qint64 &pId,
bool waitForDebugger, const QStringList &extraArgs);
static qint64 launchApp(const QString &simUdid, const QString &bundleIdentifier, QByteArray *commandOutput = nullptr);
static QString bundleIdentifier(const Utils::FileName &bundlePath);
static QString bundleExecutable(const Utils::FileName &bundlePath);
static bool waitForProcessSpawn(qint64 processPId);
private:
static SimulatorControlPrivate *d;
};
} // namespace Internal
} // namespace Ios
#endif // SIMULATORCONTROL_H

View File

@@ -77,7 +77,7 @@ exists(../shared/qbs/qbs.pro)|!isEmpty(QBS_INSTALL_DIR): \
isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR)
exists($$LLVM_INSTALL_DIR) {
SUBDIRS += clangcodemodel
SUBDIRS += clangrefactoring
# SUBDIRS += clangrefactoring
} else {
warning("Set LLVM_INSTALL_DIR to build the Clang Code Model. " \
"For details, see doc/src/editors/creator-clang-codemodel.qdoc.")

View File

@@ -208,7 +208,16 @@ Utils::FileName AbstractMsvcToolChain::compilerCommand() const
{
Utils::Environment env = Utils::Environment::systemEnvironment();
addToEnvironment(env);
return env.searchInPath(QLatin1String("cl.exe"));
Utils::FileName clexe = env.searchInPath(QLatin1String("cl.exe"), QStringList(), [](const QString &name) {
QDir dir(QDir::cleanPath(QFileInfo(name).absolutePath() + QStringLiteral("/..")));
do {
if (QFile::exists(dir.absoluteFilePath(QStringLiteral("vcvarsall.bat"))))
return true;
} while (dir.cdUp() && !dir.isRoot());
return false;
});
return clexe;
}
IOutputParser *AbstractMsvcToolChain::outputParser() const

View File

@@ -1061,6 +1061,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(ICore::instance(), &ICore::saveSettingsRequested,
dd, &ProjectExplorerPluginPrivate::savePersistentSettings);
connect(EditorManager::instance(), &EditorManager::autoSaved, this, [this] {
if (!dd->m_shuttingDown && !SessionManager::loadingSession())
SessionManager::save();
});
addAutoReleasedObject(new ProjectTreeWidgetFactory);
addAutoReleasedObject(new FolderNavigationWidgetFactory);
@@ -1518,11 +1522,7 @@ void ProjectExplorerPlugin::openNewProjectDialog()
void ProjectExplorerPluginPrivate::showSessionManager()
{
if (SessionManager::isDefaultVirgin()) {
// do not save new virgin default sessions
} else {
SessionManager::save();
}
SessionDialog sessionDialog(ICore::mainWindow());
sessionDialog.setAutoLoadSession(dd->m_projectExplorerSettings.autorestoreLastSession);
sessionDialog.exec();
@@ -1551,12 +1551,8 @@ void ProjectExplorerPluginPrivate::savePersistentSettings()
foreach (Project *pro, SessionManager::projects())
pro->saveSettings();
if (SessionManager::isDefaultVirgin()) {
// do not save new virgin default sessions
} else {
SessionManager::save();
}
}
QSettings *s = ICore::settings();
s->setValue(QLatin1String("ProjectExplorer/StartupSession"), SessionManager::activeSession());

View File

@@ -50,6 +50,7 @@
#include <QComboBox>
#include <QDockWidget>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QStyledItemDelegate>
#include <QTimer>
@@ -234,6 +235,11 @@ public:
{
Q_UNUSED(column)
if (role == ItemUpdatedFromBelowRole) {
announceChange();
return true;
}
if (role == ItemDeactivatedFromBelowRole) {
announceChange();
return true;
@@ -375,16 +381,13 @@ public:
this, &SelectorModel::openContextMenu);
}
void announceChange()
{
m_changeListener(m_projectsModel.rootItem()->childAt(0)->data(0, PanelWidgetRole).value<QWidget *>());
}
void updatePanel()
{
announceChange();
ProjectItem *projectItem = m_projectsModel.rootItem()->childAt(0);
m_changeListener(projectItem->data(0, PanelWidgetRole).value<QWidget *>());
QModelIndex activeIndex = m_projectsModel.rootItem()->childAt(0)->activeIndex();
QModelIndex activeIndex = projectItem->activeIndex();
m_selectorTree->expandAll();
m_selectorTree->selectionModel()->clear();
m_selectorTree->selectionModel()->select(activeIndex, QItemSelectionModel::Select);
}
@@ -481,9 +484,16 @@ ProjectWindow::ProjectWindow()
selectorView->setWindowTitle(tr("Project Selector"));
selectorView->setAutoFillBackground(true);
auto activeLabel = new QLabel(tr("Active Project"));
QFont font = activeLabel->font();
font.setBold(true);
font.setPointSizeF(font.pointSizeF() * 1.2);
activeLabel->setFont(font);
auto innerLayout = new QVBoxLayout;
innerLayout->setSpacing(10);
innerLayout->setContentsMargins(14, innerLayout->spacing(), 14, 0);
innerLayout->addWidget(activeLabel);
innerLayout->addWidget(selectorModel->m_projectSelection);
innerLayout->addWidget(selectorModel->m_selectorTree);

View File

@@ -42,6 +42,7 @@ enum {
ItemActivatedFromBelowRole, // A subitem gots activated and gives us the opportunity to adjust
ItemActivatedFromAboveRole, // A parent item gots activated and makes us its active child.
ItemDeactivatedFromBelowRole, // A subitem got deactivated and gives us the opportunity to adjust
ItemUpdatedFromBelowRole, // A subitem got updated, re-expansion is necessary.
ActiveItemRole, // The index of the currently selected item in the tree view
PanelWidgetRole // This item's widget to be shown as central widget.
};

View File

@@ -408,6 +408,10 @@ bool SessionManager::loadingSession()
bool SessionManager::save()
{
// do not save new virgin default sessions
if (isDefaultVirgin())
return true;
emit m_instance->aboutToSaveSession();
if (!d->m_writer || d->m_writer->fileName() != sessionNameToFileName(d->m_sessionName)) {
@@ -961,12 +965,10 @@ bool SessionManager::loadSession(const QString &session)
// Allow everyone to set something in the session and before saving
emit m_instance->aboutToUnloadSession(d->m_sessionName);
if (!isDefaultVirgin()) {
if (!save()) {
d->m_loadingSession = false;
return false;
}
}
// Clean up
if (!EditorManager::closeAllEditors()) {

View File

@@ -212,6 +212,7 @@ public:
void handleRemovedKit(Kit *kit);
void handleAddedKit(Kit *kit);
void handleUpdatedKit(Kit *kit);
void handleTargetAdded(Target *target);
void handleTargetRemoved(Target *target);
@@ -755,6 +756,8 @@ TargetGroupItemPrivate::TargetGroupItemPrivate(TargetGroupItem *q, Project *proj
this, &TargetGroupItemPrivate::handleAddedKit);
connect(KitManager::instance(), &KitManager::kitRemoved,
this, &TargetGroupItemPrivate::handleRemovedKit);
connect(KitManager::instance(), &KitManager::kitUpdated,
this, &TargetGroupItemPrivate::handleUpdatedKit);
rebuildContents();
}
@@ -789,7 +792,7 @@ QVariant TargetGroupItem::data(int column, int role) const
bool TargetGroupItem::setData(int column, const QVariant &data, int role)
{
Q_UNUSED(data)
if (role == ItemActivatedFromBelowRole) {
if (role == ItemActivatedFromBelowRole || role == ItemUpdatedFromBelowRole) {
// Bubble up to trigger setting the active project.
parent()->setData(column, QVariant::fromValue(static_cast<TreeItem *>(this)), role);
return true;
@@ -823,8 +826,15 @@ void TargetGroupItemPrivate::handleRemovedKit(Kit *kit)
rebuildContents();
}
void TargetGroupItemPrivate::handleUpdatedKit(Kit *kit)
{
Q_UNUSED(kit);
rebuildContents();
}
void TargetGroupItemPrivate::handleAddedKit(Kit *kit)
{
if (m_project->supportsKit(kit))
q->appendChild(new TargetItem(m_project, kit->id()));
}
@@ -843,8 +853,14 @@ void TargetGroupItemPrivate::rebuildContents()
{
q->removeChildren();
foreach (Kit *kit, KitManager::sortKits(KitManager::kits()))
KitMatcher matcher([this](const Kit *kit) { return m_project->supportsKit(const_cast<Kit *>(kit)); });
const QList<Kit *> kits = KitManager::sortKits(KitManager::matchingKits(matcher));
for (Kit *kit : kits)
q->appendChild(new TargetItem(m_project, kit->id()));
if (q->parent())
q->parent()->setData(0, QVariant::fromValue(static_cast<TreeItem *>(q)),
ItemUpdatedFromBelowRole);
}
void TargetGroupItemPrivate::handleTargetAdded(Target *target)

View File

@@ -1477,7 +1477,9 @@ void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentDa
destDir.append(QLatin1Char('/')).append(ti.target)
.append(QLatin1String(".framework"));
} else {
if (!(isPlugin && config.contains(QLatin1String("no_plugin_name_prefix"))))
targetFileName.prepend(QLatin1String("lib"));
if (!isPlugin) {
targetFileName += QLatin1Char('.');
const QString version = node->singleVariableValue(VersionVar);
@@ -1496,7 +1498,9 @@ void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentDa
case Abi::LinuxOS:
case Abi::BsdOS:
case Abi::UnixOS:
if (!(isPlugin && config.contains(QLatin1String("no_plugin_name_prefix"))))
targetFileName.prepend(QLatin1String("lib"));
targetFileName += QLatin1Char('.');
if (isStatic) {
targetFileName += QLatin1Char('a');

View File

@@ -63,7 +63,7 @@ static CrumbleBarInfo createCrumbleBarInfoFromModelNode(const ModelNode &modelNo
{
CrumbleBarInfo crumbleBarInfo;
crumbleBarInfo.displayName = componentIdForModelNode(modelNode);
crumbleBarInfo.fileName = currentDesignDocument()->textEditor()->document()->filePath().toString();
crumbleBarInfo.fileName = currentDesignDocument()->textEditor()->document()->filePath();
crumbleBarInfo.modelNode = modelNode;
return crumbleBarInfo;
@@ -87,7 +87,7 @@ CrumbleBar::~CrumbleBar()
delete m_crumblePath;
}
void CrumbleBar::pushFile(const QString &fileName)
void CrumbleBar::pushFile(const Utils::FileName &fileName)
{
if (m_isInternalCalled == false) {
crumblePath()->clear();
@@ -102,7 +102,7 @@ void CrumbleBar::pushFile(const QString &fileName)
CrumbleBarInfo crumbleBarInfo;
crumbleBarInfo.fileName = fileName;
crumblePath()->pushElement(fileName.split(QLatin1String("/")).last(), QVariant::fromValue(crumbleBarInfo));
crumblePath()->pushElement(fileName.fileName(), QVariant::fromValue(crumbleBarInfo));
m_isInternalCalled = false;
@@ -171,7 +171,7 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
m_isInternalCalled = true;
if (!clickedCrumbleBarInfo.modelNode.isValid()
&& Utils::FileName::fromString(clickedCrumbleBarInfo.fileName) == currentDesignDocument()->fileName()) {
&& clickedCrumbleBarInfo.fileName == currentDesignDocument()->fileName()) {
nextFileIsCalledInternally();
currentDesignDocument()->changeToDocumentModel();
QmlDesignerPlugin::instance()->viewManager().setComponentViewToMaster();
@@ -179,8 +179,8 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
showSaveDialog();
crumblePath()->popElement();
nextFileIsCalledInternally();
Core::EditorManager::openEditor(clickedCrumbleBarInfo.fileName, Core::Id(),
Core::EditorManager::DoNotMakeVisible);
Core::EditorManager::openEditor(clickedCrumbleBarInfo.fileName.toString(),
Core::Id(), Core::EditorManager::DoNotMakeVisible);
if (clickedCrumbleBarInfo.modelNode.isValid()) {
currentDesignDocument()->changeToSubComponent(clickedCrumbleBarInfo.modelNode);
QmlDesignerPlugin::instance()->viewManager().setComponentNode(clickedCrumbleBarInfo.modelNode);

View File

@@ -27,6 +27,7 @@
#include <QObject>
#include <utils/crumblepath.h>
#include <utils/fileutils.h>
#include <modelnode.h>
namespace QmlDesigner {
@@ -38,7 +39,7 @@ public:
explicit CrumbleBar(QObject *parent = 0);
~CrumbleBar();
void pushFile(const QString &fileName);
void pushFile(const Utils::FileName &fileName);
void pushInFileComponent(const ModelNode &modelNode);
void nextFileIsCalledInternally();
@@ -59,7 +60,7 @@ private:
class CrumbleBarInfo {
public:
QString fileName;
Utils::FileName fileName;
QString displayName;
ModelNode modelNode;
};

View File

@@ -71,10 +71,10 @@ static bool importLess(const Import &firstImport, const Import &secondImport)
return false;
if (firstImport.isLibraryImport() && secondImport.isFileImport())
return true;
return false;
if (firstImport.isFileImport() && secondImport.isLibraryImport())
return false;
return true;
if (firstImport.isFileImport() && secondImport.isFileImport())
return QString::localeAwareCompare(firstImport.file(), secondImport.file()) < 0;

View File

@@ -191,7 +191,9 @@ void ComponentView::searchForComponentAndAddToList(const ModelNode &node)
bool masterNotAdded = true;
foreach (const ModelNode &node, node.allSubModelNodesAndThisNode()) {
if (node.nodeSourceType() == ModelNode::NodeWithComponentSource) {
if (node.nodeSourceType() == ModelNode::NodeWithComponentSource
|| (node.hasParentProperty()
&& !node.parentProperty().isDefaultProperty())) {
if (masterNotAdded) {
masterNotAdded = true;
addMasterDocument();
@@ -200,9 +202,6 @@ void ComponentView::searchForComponentAndAddToList(const ModelNode &node)
if (!hasEntryForNode(node)) {
QString description = descriptionForNode(node);
QStandardItem *item = new QStandardItem(description);
item->setData(QVariant::fromValue(node.internalId()), ModelNodeRole);
item->setEditable(false);

View File

@@ -321,7 +321,7 @@ void DesignDocument::changeToMaster()
if (m_inFileComponentModel)
changeToDocumentModel();
QmlDesignerPlugin::instance()->viewManager().pushFileOnCrumbleBar(fileName().toString());
QmlDesignerPlugin::instance()->viewManager().pushFileOnCrumbleBar(fileName());
QmlDesignerPlugin::instance()->viewManager().setComponentNode(rootModelNode());
}

Some files were not shown because too many files have changed in this diff Show More