Merge remote-tracking branch 'origin/4.2'

Conflicts:
	qbs/modules/qtc/qtc.qbs
	qtcreator.pri

Change-Id: I245212bd45104636b1c9737b36d3db3e4af23092
This commit is contained in:
Eike Ziller
2016-11-01 09:30:49 +01:00
78 changed files with 1925 additions and 1132 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -346,11 +346,11 @@
\li Some versions of Perf will not start recording unless given a
certain minimum sampling frequency. Try with a
\uicontrol {Sampling Frequency} of 1000.
\li On some devices, for example Boundary Devices i.MX6 Boards, the
Perf support is not very stable and the Linux kernel may randomly
fail to record data after some time. Perf can use different types
of events to trigger samples. You can get a list of available event
types by running \c {perf list} on the device and add
\li On some devices, in particular various i.MX6 Boards, the hardware
performance counters are dysfunctional and the Linux kernel may
randomly fail to record data after some time. Perf can use different
types of events to trigger samples. You can get a list of available
event types by running \c {perf list} on the device and add
\c {-e <event type>} to the \uicontrol {Additional arguments} field
to change the event type to be used. The choice of event type
affects the performance and stability of the sampling.

View File

@@ -171,23 +171,25 @@
recorded. Move the cursor on an event on a row to see how long it takes and
where in the source it is being called. To display the information only when
an event is selected, disable the \uicontrol {View Event Information on Mouseover}
button (5).
button (4).
The outline (10) summarizes the period for which data was collected. Drag
the zoom range (8) or click the outline to move on the outline. You can
also move between events by selecting the \uicontrol {Jump to Previous Event} (1)
and \uicontrol {Jump to Next Event} (2) buttons.
also move between events by selecting the \uicontrol {Jump to Previous Event}
and \uicontrol {Jump to Next Event} buttons (1).
Select the \uicontrol {Show Zoom Slider} button (3) to open a slider that you can
Select the \uicontrol {Show Zoom Slider} button (2) to open a slider that you can
use to set the zoom level. You can also drag the zoom handles (9). To reset
the default zoom level, right-click the timeline to open the context menu,
and select \uicontrol {Reset Zoom}.
Click the time ruler to add vertical orientation lines (5) to the timeline.
\section2 Selecting Event Ranges
You can select an event range (7) to view the frame rate of events and to
compare it with the frame rate of similar events. Select the
\uicontrol {Select Range} button (4) to activate the selection tool. Then click in
\uicontrol {Select Range} button (3) to activate the selection tool. Then click in
the timeline to specify the beginning of the event range. Drag the selection
handle to define the end of the range. The length of the range indicates the
frame rate of the event.
@@ -557,14 +559,26 @@
\section2 Visualizing Statistics as Flame Graphs
The \uicontrol {Flame Graph} view shows a more concise statistical overview
of QML and JavaScript execution. The horizontal bars show the amount of
of QML and JavaScript execution. In the \uicontrol {Visualize Total Time}
view, the horizontal bars show the amount of
time all invocations of a certain function took together, relative to the
total runtime of all JavaScript and QML events. The nesting shows which
functions were called by which other ones. Mind that, unlike the
functions were called by which other ones.
\image qml-profiler-flamegraph.png "Flame Graph View"
To view the total amount of memory allocated by the functions in the
\uicontrol {Visualize Memory} view, select \uicontrol Memory in the
drop-down menu (1).
To view the the number of memory allocations performed by the functions in
the \uicontrol {Visualize Allocations} view, select \uicontrol Allocations
in the drop-down menu.
Unlike the
\uicontrol Timeline view, the \uicontrol {Flame Graph} view does not show the
time spans when no QML or JavaScript is running at all. Thus, it is not
suitable for analyzing per frame execution times. However, it is very easy
to see the total impact of the various QML and JavaScript events there.
\image qml-profiler-flamegraph.png "Flame Graph View"
*/

View File

@@ -37,22 +37,32 @@
\title Comparing Files
You can use a diff editor from \QC to compare two text files. They can be
either versions of the same file or arbitrary files.
You can use a diff editor to display unsaved changed in the current file or
all open files or to compare any two text files that can be either versions
of the same file or arbitrary files.
\image creator-diff-editor.png "Diff editor output in the Edit mode"
To view unsaved changes in the current file, select \uicontrol Tools >
\uicontrol Diff > \uicontrol {Diff Current File}.
To compare files:
To view unsaved changes in all open files, select \uicontrol Tools >
\uicontrol Diff > \uicontrol {Diff Open Files}.
To compare two files:
\list 1
\li Select \uicontrol Tools > \uicontrol Diff.
\li Select \uicontrol Tools > \uicontrol Diff >
\uicontrol {Diff External Files}.
\li Select two files to compare.
\endlist
The differences are output in the \uicontrol Edit mode. Color coding is used
\section1 Viewing the Changes
\image creator-diff-editor.png "Diff editor output in the Edit mode"
The changes are displayed in the \uicontrol Edit mode. Color coding is used
to mark changed lines. By default, light red indicates lines that contain
removed text (painted a darker red) in the left pane and light green
indicates lines that contain added text (painted a darker green) in the
@@ -70,6 +80,26 @@
\inlineimage sidebysidediff.png
(\uicontrol {Switch to Side by Side Diff Editor}).
To only show text changes, select \uicontrol {Ignore Whitespace}.
To expand the context for the changes, set the number of unchanged lines to
show in \uicontrol {Context lines}. Set the value to -1 to show the whole
file.
By default, the horizontal scroll bars in the left and right pane are
synchronized. To use them independently of each other, select the
\inlineimage linkicon.png
(\uicontrol {Synchronize Horizontal Scroll Bars}) button.
If the files change outside \QC, select \inlineimage reload_gray.png
(\uicontrol {Reload Editor}) to compare them again and to show the results.
To send a chunk of changes to a \l{Pasting and Fetching Code Snippets}
{code pasting service}, select \uicontrol {Send Chunk to CodePaster} in the
context menu.
\section1 Changing the Colors
To change the default colors, select \uicontrol Tools > \uicontrol Options >
\uicontrol {Text Editor} > \uicontrol {Font & Colors}. Create your own color
scheme and select new colors for the following options:
@@ -95,22 +125,4 @@
indicates added characters.
\endlist
To only show text changes, select \uicontrol {Ignore Whitespace}.
To expand the context for the changes, set the number of unchanged lines to
show in \uicontrol {Context lines}. Set the value to -1 to show the whole
file.
By default, the horizontal scroll bars in the left and right pane are
synchronized. To use them independently of each other, select the
\inlineimage linkicon.png
(\uicontrol {Synchronize Horizontal Scroll Bars}) button.
If the files change outside \QC, select \inlineimage reload_gray.png
(\uicontrol {Reload Editor}) to compare them again and to show the results.
To send a chunk of changes to a \l{Pasting and Fetching Code Snippets}
{code pasting service}, select \uicontrol {Send Chunk to CodePaster} in the
context menu.
*/

View File

@@ -915,6 +915,9 @@
\li C++ code snippets, which specify C++ code constructs
\li CMake code snippets that you can use when editing \c CMakeLists.txt
files in the CMake editor
\li QML code snippets, which specify QML code constructs
\li Nim code snippets, which specify Nim code constructs

View File

@@ -161,6 +161,8 @@
\li Keyword completion
\li Code completion
\li Auto-indentation
\li Matching parentheses and quotes

View File

@@ -428,6 +428,10 @@
you can change the position of an object on the canvas and then add animation
to the change between the states.
To determine when the state should be applied, select
\uicontrol {Set when Condition} in the context menu and specify a
\l [QtQuick]{State::when}{when} property for the state.
You can preview the states in the \uicontrol State pane and click them to switch
between states on the canvas.

View File

@@ -133,12 +133,23 @@
\image qmldesigner-set-expression.png "Type properties context menu"
The \uicontrol {Binding Editor} supports code completion. Start typing a
string and press \key Ctrl+Space to display a list of properties, IDs, and
code snippets. When you enter a period (.) after a property name, a list of
available values is displayed. Press \key Enter to accept the first
suggestion in the list and to complete the code.
\image qmldesigner-binding-editor.png "Binding Editor"
To remove bindings, select \uicontrol Reset in the context menu.
You can set bindings also in the \uicontrol Connections view. For more
information, see \l {Adding Bindings Between Properties}.
For more information on the JavaScript environment provided by QML, see
\l{Integrating QML and JavaScript}.
\QMLD cannot show bindings and using them might have a negative impact on
Bindings are a black box for \QMLD and using them might have a negative impact on
performance, so consider setting anchors and margins for items, instead.
For example, instead of setting \c {parent.width} for an item, you could
anchor the item to its sibling items on the left and the right.

View File

@@ -78,7 +78,7 @@ def package_repos(repos, combined_prefix, target_file_base):
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')
createTarXz(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...')

View File

@@ -117,25 +117,25 @@ def qdump__boost__unordered__unordered_set(d, value):
innerType = value.type[0]
bucketCount = d.extractInt(base + ptrSize)
#warn("A BUCKET COUNT: %s" % bucketCount)
#warn("X BUCKET COUNT: %s" % d.parseAndEvaluate("s1.table_.bucket_count_"))
#warn("X BUCKET COUNT: %s" % d.parseAndEvaluate("s1.table_.bucket_count_").value())
try:
# boost 1.58
table = value["table_"]
bucketsAddr = table["buckets_"].integer()
#warn("A BUCKETS: 0x%x" % bucketsAddr)
#warn("X BUCKETS: %s" % d.parseAndEvaluate("s1.table_.buckets_"))
#warn("X BUCKETS: 0x%x" % d.parseAndEvaluate("s1.table_.buckets_").pointer())
lastBucketAddr = bucketsAddr + bucketCount * ptrSize
#warn("A LAST BUCKET: 0x%x" % lastBucketAddr)
#warn("X LAST BUCKET: %s" % d.parseAndEvaluate("s1.table_.get_bucket(s1.table_.bucket_count_)"))
#warn("X LAST BUCKET: 0x%x" % d.parseAndEvaluate("s1.table_.get_bucket(s1.table_.bucket_count_)").pointer())
previousStartAddr = lastBucketAddr
#warn("A PREVIOUS START: 0x%x" % previousStartAddr)
#warn("X PREVIOUS START: %s" % d.parseAndEvaluate("s1.table_.get_previous_start()"))
#warn("X PREVIOUS START: 0x%x" % d.parseAndEvaluate("s1.table_.get_previous_start()").pointer())
item = d.extractPointer(previousStartAddr)
#warn("A KEY ADDR: 0x%x" % item)
#warn("X KEY ADDR: %s" % d.parseAndEvaluate("s1.table_.get_previous_start()->next_"))
#warn("X KEY ADDR: 0x%x" % d.parseAndEvaluate("s1.table_.get_previous_start()->next_").pointer())
item = d.extractPointer(previousStartAddr)
#warn("A VALUE: %x" % d.extractInt(item + ptrSize))
#warn("X VALUE: %s" % d.parseAndEvaluate("*(int*)(s1.table_.get_previous_start()->next_ + 1)"))
#warn("X VALUE: %x" % d.parseAndEvaluate("*(int*)(s1.table_.get_previous_start()->next_ + 1)").integer())
with Children(d, size, maxNumChild=10000):
for j in d.childRange():
d.putSubItem(j, d.createValue(item + 2 * ptrSize, innerType))

File diff suppressed because it is too large Load Diff

View File

@@ -205,17 +205,46 @@ class Dumper(DumperBase):
self.output = []
self.setVariableFetchingOptions(args)
def fromNativeDowncastableValue(self, nativeValue):
def fromFrameValue(self, nativeValue):
val = nativeValue
if self.useDynamicType:
try:
return self.fromNativeValue(nativeValue.cast(nativeValue.dynamic_type))
val = nativeValue.cast(nativeValue.dynamic_type)
except:
pass
return self.fromNativeValue(nativeValue)
return self.fromNativeValue(val)
def fromNativeValue(self, nativeValue):
#self.check(isinstance(nativeValue, gdb.Value))
#warn("FROM NATIVE VALUE: %s" % nativeValue)
self.check(isinstance(nativeValue, gdb.Value))
nativeType = nativeValue.type
code = nativeType.code
if code == gdb.TYPE_CODE_REF:
targetType = self.fromNativeType(nativeType.target().unqualified())
val = self.createReferenceValue(toInteger(nativeValue.address), targetType)
#warn("CREATED REF: %s" % val)
return val
if code == gdb.TYPE_CODE_PTR:
targetType = self.fromNativeType(nativeType.target().unqualified())
val = self.createPointerValue(toInteger(nativeValue), targetType)
#warn("CREATED PTR 1: %s" % val)
if not nativeValue.address is None:
val.laddress = toInteger(nativeValue.address)
#warn("CREATED PTR 2: %s" % val)
return val
if code == gdb.TYPE_CODE_TYPEDEF:
targetType = nativeType.strip_typedefs().unqualified()
#warn("TARGET TYPE: %s" % targetType)
if targetType.code == gdb.TYPE_CODE_ARRAY:
val = self.Value(self)
val.laddress = toInteger(nativeValue.address)
else:
# Cast may fail (e.g for arrays, see test for Bug5799)
val = self.fromNativeValue(nativeValue.cast(targetType))
val.type = self.fromNativeType(nativeType)
#warn("CREATED TYPEDEF: %s" % val)
return val
val = self.Value(self)
if not nativeValue.address is None:
val.laddress = toInteger(nativeValue.address)
@@ -238,82 +267,131 @@ class Dumper(DumperBase):
val.ldisplay += ' (%s)' % intval
elif code == gdb.TYPE_CODE_COMPLEX:
val.ldisplay = str(nativeValue)
elif code == gdb.TYPE_CODE_ARRAY:
val.type.ltarget = nativeValue[0].type.unqualified()
#elif code == gdb.TYPE_CODE_ARRAY:
# val.type.ltarget = nativeValue[0].type.unqualified()
return val
def ptrSize(self):
result = gdb.lookup_type('void').pointer().sizeof
self.ptrSize = lambda: result
return result
def fromNativeType(self, nativeType):
self.check(isinstance(nativeType, gdb.Type))
typeobj = self.Type(self)
typeobj.nativeType = nativeType.unqualified()
typeobj.name = str(typeobj.nativeType)
typeobj.lbitsize = nativeType.sizeof * 8
typeobj.code = {
gdb.TYPE_CODE_TYPEDEF : TypeCodeTypedef,
gdb.TYPE_CODE_METHOD : TypeCodeFunction,
gdb.TYPE_CODE_VOID : TypeCodeVoid,
gdb.TYPE_CODE_FUNC : TypeCodeFunction,
gdb.TYPE_CODE_METHODPTR : TypeCodeFunction,
gdb.TYPE_CODE_MEMBERPTR : TypeCodeFunction,
gdb.TYPE_CODE_PTR : TypeCodePointer,
gdb.TYPE_CODE_REF : TypeCodeReference,
gdb.TYPE_CODE_BOOL : TypeCodeIntegral,
gdb.TYPE_CODE_CHAR : TypeCodeIntegral,
gdb.TYPE_CODE_INT : TypeCodeIntegral,
gdb.TYPE_CODE_FLT : TypeCodeFloat,
gdb.TYPE_CODE_ENUM : TypeCodeEnum,
gdb.TYPE_CODE_ARRAY : TypeCodeArray,
gdb.TYPE_CODE_STRUCT : TypeCodeStruct,
gdb.TYPE_CODE_UNION : TypeCodeStruct,
gdb.TYPE_CODE_COMPLEX : TypeCodeComplex,
gdb.TYPE_CODE_STRING : TypeCodeFortranString,
}[nativeType.code]
return typeobj
code = nativeType.code
#warn('FROM NATIVE TYPE: %s' % nativeType)
#nativeType = nativeType.unqualified()
def nativeTypeDereference(self, nativeType):
return self.fromNativeType(nativeType.strip_typedefs().target())
if code == gdb.TYPE_CODE_PTR:
#warn('PTR')
targetType = self.fromNativeType(nativeType.target().unqualified())
return self.createPointerType(targetType)
def nativeTypeUnqualified(self, nativeType):
return self.fromNativeType(nativeType.unqualified())
if code == gdb.TYPE_CODE_REF:
#warn('REF')
targetType = self.fromNativeType(nativeType.target().unqualified())
return self.createReferenceType(targetType)
def nativeTypePointer(self, nativeType):
return self.fromNativeType(nativeType.pointer())
if code == gdb.TYPE_CODE_ARRAY:
#warn('ARRAY')
nativeTargetType = nativeType.target().unqualified()
targetType = self.fromNativeType(nativeTargetType)
count = nativeType.sizeof // nativeTargetType.sizeof
return self.createArrayType(targetType, count)
def nativeTypeTarget(self, nativeType):
while nativeType.code == gdb.TYPE_CODE_TYPEDEF:
nativeType = nativeType.strip_typedefs().unqualified()
return self.fromNativeType(nativeType.target())
if code == gdb.TYPE_CODE_TYPEDEF:
#warn('TYPEDEF')
nativeTargetType = nativeType.unqualified()
while nativeTargetType.code == gdb.TYPE_CODE_TYPEDEF:
nativeTargetType = nativeTargetType.strip_typedefs().unqualified()
targetType = self.fromNativeType(nativeTargetType)
return self.createTypedefedType(targetType, str(nativeType))
def nativeTypeFirstBase(self, nativeType):
nativeFields = nativeType.fields()
if len(nativeFields) and nativeFields[0].is_base_class:
return self.fromNativeType(nativeFields[0].type)
if code == gdb.TYPE_CODE_ERROR:
warn('Type error: %s' % nativeType)
return self.Type(self, '')
typeId = self.nativeTypeId(nativeType)
res = self.typeData.get(typeId, None)
if res is None:
tdata = self.TypeData(self)
tdata.name = str(nativeType)
tdata.typeId = typeId
tdata.lbitsize = nativeType.sizeof * 8
tdata.code = {
#gdb.TYPE_CODE_TYPEDEF : TypeCodeTypedef, # Handled above.
gdb.TYPE_CODE_METHOD : TypeCodeFunction,
gdb.TYPE_CODE_VOID : TypeCodeVoid,
gdb.TYPE_CODE_FUNC : TypeCodeFunction,
gdb.TYPE_CODE_METHODPTR : TypeCodeFunction,
gdb.TYPE_CODE_MEMBERPTR : TypeCodeFunction,
#gdb.TYPE_CODE_PTR : TypeCodePointer, # Handled above.
#gdb.TYPE_CODE_REF : TypeCodeReference, # Handled above.
gdb.TYPE_CODE_BOOL : TypeCodeIntegral,
gdb.TYPE_CODE_CHAR : TypeCodeIntegral,
gdb.TYPE_CODE_INT : TypeCodeIntegral,
gdb.TYPE_CODE_FLT : TypeCodeFloat,
gdb.TYPE_CODE_ENUM : TypeCodeEnum,
#gdb.TYPE_CODE_ARRAY : TypeCodeArray,
gdb.TYPE_CODE_STRUCT : TypeCodeStruct,
gdb.TYPE_CODE_UNION : TypeCodeStruct,
gdb.TYPE_CODE_COMPLEX : TypeCodeComplex,
gdb.TYPE_CODE_STRING : TypeCodeFortranString,
}[code]
if tdata.code == TypeCodeEnum:
tdata.enumDisplay = lambda intval: self.nativeTypeEnumDisplay(nativeType, intval)
self.registerType(typeId, tdata) # Prevent recursion in fields.
tdata.lfields = self.listFields(nativeType, self.Type(self, typeId))
tdata.templateArguments = self.listTemplateParameters(nativeType)
self.registerType(typeId, tdata) # Fix up fields and template args
# warn('CREATE TYPE: %s' % typeId)
#else:
# warn('REUSE TYPE: %s' % typeId)
return self.Type(self, typeId)
def listTemplateParameters(self, nativeType):
targs = []
pos = 0
while True:
try:
targ = nativeType.template_argument(pos)
except:
break
if isinstance(targ, gdb.Type):
targs.append(self.fromNativeType(targ.unqualified()))
elif isinstance(targ, gdb.Value):
#targs.append(self.fromNativeValue(targ))
targs.append(self.fromNativeValue(targ).value())
else:
error('CRAP')
pos += 1
return targs
def nativeTypeEnumDisplay(self, nativeType, intval):
try:
val = gdb.parse_and_eval("(%s)%d" % (nativeType, intval))
return "%s (%d)" % (val, intval)
val = gdb.parse_and_eval('(%s)%d' % (nativeType, intval))
return '%s (%d)' % (val, intval)
except:
return "%d" % intval
return '%d' % intval
def nativeTypeFields(self, nativeType):
if nativeType.code == gdb.TYPE_CODE_TYPEDEF:
return self.nativeTypeFields(nativeType.strip_typedefs())
def nativeTypeId(self, nativeType):
name = str(nativeType)
if len(name) == 0:
c = '0'
elif name == 'struct {...}':
c = 's'
elif name == 'union {...}':
c = 'u'
else:
return name
typeId = c + ''.join(['{%s:%s}' % (f.name, self.nativeTypeId(f.type)) for f in nativeType.fields()])
return typeId
def listFields(self, nativeType, parentType):
#if nativeType.code == gdb.TYPE_CODE_TYPEDEF:
# return self.listFields(nativeType.strip_typedefs(), parentType)
fields = []
if nativeType.code == gdb.TYPE_CODE_ARRAY:
# An array.
typeobj = nativeType.strip_typedefs()
innerType = typeobj.target()
for i in xrange(int(typeobj.sizeof / innerType.sizeof)):
field = self.Field(self)
field.ltype = self.fromNativeType(innerType)
field.parentType = self.fromNativeType(nativeType)
field.isBaseClass = False
field.lbitsize = innerType.sizeof
field.lbitpos = i * innerType.sizeof * 8
fields.append(field)
return fields
if not nativeType.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
return fields
@@ -321,18 +399,20 @@ class Dumper(DumperBase):
nativeIndex = 0
baseIndex = 0
nativeFields = nativeType.fields()
#warn("NATIVE FIELDS: %s" % nativeFields)
#warn('NATIVE FIELDS: %s' % nativeFields)
anonNumber = 0
for nativeField in nativeFields:
#warn("FIELD: %s" % nativeField)
#warn(" DIR: %s" % dir(nativeField))
#warn(" BITSIZE: %s" % nativeField.bitsize)
#warn(" ARTIFICIAL: %s" % nativeField.artificial)
#warn("FIELD NAME: %s" % nativeField.name)
#warn("FIELD TYPE: %s" % nativeField.type)
#warn('FIELD: %s' % nativeField)
#warn(' DIR: %s' % dir(nativeField))
#warn(' BITSIZE: %s' % nativeField.bitsize)
#warn(' ARTIFICIAL: %s' % nativeField.artificial)
#warn('FIELD NAME: %s' % nativeField.name)
#warn('FIELD TYPE: %s' % nativeField.type)
#warn('FIELD TYPE ID: %s' % self.nativeTypeId(nativeField.type))
#self.check(isinstance(nativeField, gdb.Field))
field = self.Field(self)
field.ltype = self.fromNativeType(nativeField.type)
field.parentType = self.fromNativeType(nativeType)
field.ltype = self.fromNativeType(nativeField.type.unqualified())
field.parentType = parentType
field.name = nativeField.name
field.isBaseClass = nativeField.is_base_class
if hasattr(nativeField, 'bitpos'):
@@ -356,36 +436,31 @@ class Dumper(DumperBase):
# Something without a name.
# Anonymous union? We need a dummy name to distinguish
# multiple anonymous unions in the struct.
self.anonNumber += 1
field.name = "#%s" % self.anonNumber
anonNumber += 1
field.name = '#%s' % anonNumber
else:
# Normal named field.
field.name = nativeField.name
field.nativeIndex = nativeIndex
#warn('FIELD RESULT: %s' % field)
fields.append(field)
nativeIndex += 1
#warn("FIELDS: %s" % fields)
#warn('FIELDS: %s' % fields)
return fields
def nativeTypeStripTypedefs(self, typeobj):
typeobj = typeobj.unqualified()
while typeobj.code == gdb.TYPE_CODE_TYPEDEF:
typeobj = typeobj.strip_typedefs().unqualified()
return self.fromNativeType(typeobj)
def listOfLocals(self, partialVar):
frame = gdb.selected_frame()
try:
block = frame.block()
#warn("BLOCK: %s " % block)
#warn('BLOCK: %s ' % block)
except RuntimeError as error:
#warn("BLOCK IN FRAME NOT ACCESSIBLE: %s" % error)
#warn('BLOCK IN FRAME NOT ACCESSIBLE: %s' % error)
return []
except:
warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS")
warn('BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS')
return []
items = []
@@ -409,10 +484,18 @@ class Dumper(DumperBase):
# "NotImplementedError: Symbol type not yet supported in
# Python scripts."
#warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name))
try:
value = self.fromNativeDowncastableValue(frame.read_var(name, block))
#warn("READ 1: %s" % value)
if False and self.passExceptions:
value = self.fromFrameValue(frame.read_var(name, block))
value.name = name
#warn("READ 1: %s" % value.stringify())
items.append(value)
continue
try:
# Same as above, but for production.
value = self.fromFrameValue(frame.read_var(name, block))
value.name = name
#warn("READ 1: %s" % value.stringify())
items.append(value)
continue
except:
@@ -420,7 +503,7 @@ class Dumper(DumperBase):
try:
#warn("READ 2: %s" % item.value)
value = self.fromNativeDowncastableValue(frame.read_var(name))
value = self.fromFrameValue(frame.read_var(name))
value.name = name
items.append(value)
continue
@@ -435,7 +518,8 @@ class Dumper(DumperBase):
try:
#warn("READ 3: %s %s" % (name, item.value))
#warn("ITEM 3: %s" % item.value)
value = self.fromNativeDowncastableValue(gdb.parse_and_eval(name))
value = self.fromFrameValue(gdb.parse_and_eval(name))
value.name = name
items.append(value)
except:
# Can happen in inlined code (see last line of
@@ -550,10 +634,11 @@ class Dumper(DumperBase):
exp = "((%s*)0x%x)->%s(%s)" % (typeName, addr, function, arg)
#warn("CALL: %s" % exp)
result = gdb.parse_and_eval(exp)
#warn(" -> %s" % result)
warn(" -> %s" % result)
res = self.fromNativeValue(result)
if not value.address():
gdb.parse_and_eval("free((void*)0x%x)" % addr)
return self.fromNativeValue(result)
return res
def makeExpression(self, value):
typename = "::" + value.type.name
@@ -573,13 +658,6 @@ class Dumper(DumperBase):
#warn(" VALUE: %s" % value)
return value
def nativeTypeTemplateArgument(self, nativeType, position, numeric):
#warn("NATIVE TYPE: %s" % dir(nativeType))
arg = nativeType.template_argument(position)
if numeric:
return int(str(arg))
return self.fromNativeType(arg)
def pokeValue(self, value):
# Allocates inferior memory and copies the contents of value.
# Returns a pointer to the copy.
@@ -885,9 +963,6 @@ class Dumper(DumperBase):
def enumExpression(self, enumType, enumValue):
return self.qtNamespace() + "Qt::" + enumValue
def lookupType(self, typeName):
return self.fromNativeType(self.lookupNativeType(typeName))
def lookupNativeType(self, typeName):
nativeType = self.lookupNativeTypeHelper(typeName)
if not nativeType is None:
@@ -1154,7 +1229,7 @@ class CliDumper(Dumper):
def putNumChild(self, numchild):
pass
def putOriginalAddress(self, value):
def putOriginalAddress(self, address):
pass
def fetchVariables(self, args):
@@ -1205,4 +1280,4 @@ class InterpreterMessageBreakpoint(gdb.Breakpoint):
print("Interpreter event received.")
return theDumper.handleInterpreterMessage()
InterpreterMessageBreakpoint()
#InterpreterMessageBreakpoint()

File diff suppressed because it is too large Load Diff

View File

@@ -121,7 +121,7 @@ def qdump__Eigen__Matrix(d, value):
storage = value['m_storage']
nrows = storage['m_rows'].integer() if argRow == -1 else argRow
ncols = storage['m_cols'].integer() if argCol == -1 else argCol
p = storage['m_data'].integer()
p = storage['m_data'].pointer()
innerSize = innerType.size()
d.putValue('(%s x %s), %s' % (nrows, ncols, ['ColumnMajor', 'RowMajor'][rowMajor]))
d.putField('keeporder', '1')

View File

@@ -152,7 +152,7 @@ def qdump_X_QModelIndex(d, value):
except:
p = value['i']
m = value['m']
if m.integer() == 0 or r < 0 or c < 0:
if m.pointer() == 0 or r < 0 or c < 0:
d.putValue('(invalid)')
d.putPlainChildren(value)
return
@@ -196,7 +196,7 @@ def qdump_X_QModelIndex(d, value):
def qdump__QDate(d, value):
jd = value.integer()
jd = value.pointer()
if jd:
d.putValue(jd, 'juliandate')
d.putNumChild(1)
@@ -332,6 +332,7 @@ def qdump__QDateTime(d, value):
d.putNumChild(0)
return
d.putNumChild(1)
if d.isExpanded():
with Children(d):
ns = d.qtNamespace()
@@ -1120,7 +1121,7 @@ def qdump__QRegion(d, value):
def qdump__QScopedPointer(d, value):
if value.integer() == 0:
if value.pointer() == 0:
d.putValue('(null)')
d.putNumChild(0)
else:
@@ -1187,13 +1188,13 @@ def qdump__QSet(d, value):
def qdump__QSharedData(d, value):
d.putValue('ref: %s' % d.extractInt(value['ref'].address))
d.putValue('ref: %s' % value.to('i'))
d.putNumChild(0)
def qdump__QSharedDataPointer(d, value):
d_ptr = value['d']
if d_ptr.integer() == 0:
if d_ptr.pointer() == 0:
d.putValue('(null)')
d.putNumChild(0)
else:
@@ -1206,7 +1207,7 @@ def qdump__QSharedDataPointer(d, value):
d.putPlainChildren(value)
return
d.putBetterType(d.currentType)
d.putItem(d_ptr.cast(innerType.pointer()).dereference())
d.putItem(d_ptr.dereference())
@@ -1404,6 +1405,7 @@ def qdump__QUrl(d, value):
if displayFormat == SeparateFormat:
d.putDisplay('utf16:separate', url)
d.putNumChild(1)
if d.isExpanded():
with Children(d):
d.putIntItem('port', port)
@@ -1684,12 +1686,12 @@ def qdump__QVariant(d, value):
ptr = p.pointer()
(elided, blob) = d.encodeCArray(ptr, 1, 100)
typeName = d.hexdecode(blob)
base = data.extractPointer()
# Prefer namespaced version.
if len(ns) > 0:
if not d.lookupNativeType(ns + typeName) is None:
typeName = ns + typeName
d.putSubItem('data', d.createValue(base, d.createType(typeName)))
data.type = d.createType(typeName + ' *')
d.putSubItem('data', data)
if not typeName is None:
d.putBetterType('%sQVariant (%s)' % (ns, typeName))
return None
@@ -1706,7 +1708,7 @@ def qedit__QVector(d, value, data):
base = value['d'].address() + offset
except:
# Qt 4.
base = value['p']['array'].integer()
base = value['p']['array'].pointer()
d.setValues(base, innerType, values)
@@ -1766,6 +1768,7 @@ def qdump_QWeakPointerHelper(d, value, isWeak):
def qdump__QXmlAttributes__Attribute(d, value):
d.putEmptyValue()
d.putNumChild(1)
if d.isExpanded():
with Children(d):
(qname, uri, localname, val) = value.split('{QString}' * 4)
@@ -2345,7 +2348,7 @@ def qdump__QScriptValue(d, value):
#d.putEmptyValue()
dd = value['d_ptr']['d']
ns = d.qtNamespace()
if dd.integer() == 0:
if dd.pointer() == 0:
d.putValue('(invalid)')
d.putNumChild(0)
return
@@ -2621,9 +2624,9 @@ def qdump__QJsonValue(d, value):
def qdump__QJsonArray(d, value):
qdumpHelper_QJsonArray(d, value['d'].integer(), value['a'].integer())
qdumpHelper_QJsonArray(d, value['d'].pointer(), value['a'].pointer())
def qdump__QJsonObject(d, value):
qdumpHelper_QJsonObject(d, value['d'].integer(), value['o'].integer())
qdumpHelper_QJsonObject(d, value['d'].pointer(), value['o'].pointer())

View File

@@ -76,17 +76,17 @@ def qdump__std__deque(d, value):
impl = value["_M_impl"]
start = impl["_M_start"]
finish = impl["_M_finish"]
size = bufsize * int((finish["_M_node"].integer() - start["_M_node"].integer()) / d.ptrSize() - 1)
size += int((finish["_M_cur"].integer() - finish["_M_first"].integer()) / innerSize)
size += int((start["_M_last"].integer() - start["_M_cur"].integer()) / innerSize)
size = bufsize * ((finish["_M_node"].pointer() - start["_M_node"].pointer()) // d.ptrSize() - 1)
size += ((finish["_M_cur"].pointer() - finish["_M_first"].pointer()) // innerSize)
size += ((start["_M_last"].pointer() - start["_M_cur"].pointer()) // innerSize)
d.check(0 <= size and size <= 1000 * 1000 * 1000)
d.putItemCount(size)
if d.isExpanded():
with Children(d, size, maxNumChild=2000, childType=innerType):
pcur = start["_M_cur"].integer()
pcur = start["_M_cur"].pointer()
pfirst = start["_M_first"]
plast = start["_M_last"].integer()
plast = start["_M_last"].pointer()
pnode = start["_M_node"]
for i in d.childRange():
d.putSubItem(i, d.createValue(pcur, innerType))
@@ -99,7 +99,7 @@ def qdump__std__deque(d, value):
#warn("NEWNODE: 0x%x %s" % (newnode.pointer(), newnode))
pnode = newnode
#warn("PNODE 2: 0x%x %s" % (pnode.pointer(), pnode))
pfirst = newnode.dereference().integer()
pfirst = newnode.dereference().pointer()
plast = pfirst + bufsize * d.ptrSize()
pcur = pfirst
@@ -237,7 +237,6 @@ def qdump__std__map(d, value):
if d.isExpanded():
pairType = value.type[3][0]
pairPointer = pairType.pointer()
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
node = value["_M_t"]["_M_impl"]["_M_header"]["_M_left"]
nodeSize = node.dereference().type.size()
@@ -245,10 +244,10 @@ def qdump__std__map(d, value):
for i in d.childRange():
(pad1, key, pad2, value) = d.split(typeCode, node.pointer() + nodeSize)
d.putPairItem(i, (key, value))
if node["_M_right"].integer() == 0:
if node["_M_right"].pointer() == 0:
parent = node["_M_parent"]
while True:
if node.integer() != parent["_M_right"].integer():
if node.pointer() != parent["_M_right"].pointer():
break
node = parent
parent = parent["_M_parent"]
@@ -257,7 +256,7 @@ def qdump__std__map(d, value):
else:
node = node["_M_right"]
while True:
if node["_M_left"].integer() == 0:
if node["_M_left"].pointer() == 0:
break
node = node["_M_left"]
@@ -271,13 +270,13 @@ def qdump_std__map__helper(d, size, value):
for i in d.childRange():
pair = node.cast(nodeType).dereference()['_Myval']
d.putPairItem(i, pair)
if node['_Right']['_Isnil'].integer() == 0:
if node['_Right']['_Isnil'].pointer() == 0:
node = node['_Right']
while node['_Left']['_Isnil'].integer() == 0:
while node['_Left']['_Isnil'].pointer() == 0:
node = node['_Left']
else:
parent = node['_Parent']
while node and parent['_Right']['_Isnil'].integer() == 0:
while node and parent['_Right']['_Isnil'].pointer() == 0:
node = parent
parent = parent['_Parent']
if node['_Right'] != parent:
@@ -377,7 +376,7 @@ def qdump__std__set(d, value):
for i in d.childRange():
(pad, val) = d.split(typeCode, node.pointer() + nodeSize)
d.putSubItem(i, val)
if node["_M_right"].integer() == 0:
if node["_M_right"].pointer() == 0:
parent = node["_M_parent"]
while node == parent["_M_right"]:
node = parent
@@ -386,7 +385,7 @@ def qdump__std__set(d, value):
node = parent
else:
node = node["_M_right"]
while node["_M_left"].integer() != 0:
while node["_M_left"].pointer() != 0:
node = node["_M_left"]
def qdump__std__set__QNX(d, value):
@@ -419,7 +418,7 @@ def std1TreeMin(d, node):
# return __x;
#
left = node['__left_']
if left.integer():
if left.pointer():
node = left
return node
@@ -428,7 +427,7 @@ def std1TreeIsLeftChild(d, node):
# return __x == __x->__parent_->__left_;
#
other = node['__parent_']['__left_']
return node.integer() == other.integer()
return node.pointer() == other.pointer()
def std1TreeNext(d, node):
@@ -440,7 +439,7 @@ def std1TreeNext(d, node):
# return __x->__parent_;
#
right = node['__right_']
if right.integer():
if right.pointer():
return std1TreeMin(d, right)
while not std1TreeIsLeftChild(d, node):
node = node['__parent_']
@@ -612,18 +611,18 @@ def qdump__std____1__wstring(d, value):
def qdump__std__shared_ptr(d, value):
if d.isMsvcTarget:
if d.isMsvcTarget():
i = value["_Ptr"]
else:
i = value["_M_ptr"]
if i.integer() == 0:
if i.pointer() == 0:
d.putValue("(null)")
d.putNumChild(0)
return
with Children(d):
short = d.putSubItem("data", i)
if d.isMsvcTarget:
short = d.putSubItem("data", i.dereference())
if d.isMsvcTarget():
refcount = value["_Rep"]
d.putIntItem("usecount", refcount["_Uses"])
d.putIntItem("weakcount", refcount["_Weaks"])
@@ -635,7 +634,7 @@ def qdump__std__shared_ptr(d, value):
def qdump__std____1__shared_ptr(d, value):
i = value["__ptr_"]
if i.integer() == 0:
if i.pointer() == 0:
d.putValue("(null)")
d.putNumChild(0)
return
@@ -660,6 +659,17 @@ def qdump__std____1__unique_ptr(d, value):
qdump__std__unique_ptr(d, value)
def qdump__std__pair(d, value):
typeCode = '{%s}@{%s}' % (value.type[0].name, value.type[1].name)
first, pad, second = value.split(typeCode)
with Children(d):
key = d.putSubItem('first', first)
value = d.putSubItem('second', second)
d.putField('key', key.value)
if key.encoding is not None:
d.putField('keyencoded', key.encoding)
d.putValue(value.value, value.encoding)
def qform__std__unordered_map():
return mapForms()
@@ -733,7 +743,7 @@ def qdump__std__unordered_set(d, value):
d.putItemCount(size)
if d.isExpanded():
p = start.integer()
p = start.pointer()
valueType = value.type[0]
with Children(d, size, childType=valueType):
ptrSize = d.ptrSize()
@@ -974,10 +984,10 @@ def qdump____gnu_cxx__hash_set(d, value):
bucketFinish = buckets["_M_finish"]
p = bucketStart
itemCount = 0
for i in xrange(int((bucketFinish.integer() - bucketStart.integer()) / d.ptrSize())):
if p.dereference().integer():
for i in xrange((bucketFinish.pointer() - bucketStart.pointer()) // d.ptrSize()):
if p.dereference().pointer():
cur = p.dereference()
while cur.integer():
while cur.pointer():
d.putSubItem(itemCount, cur["_M_val"])
cur = cur["_M_next"]
itemCount += 1

View File

@@ -605,7 +605,33 @@ ObjectNodeInstance::Pointer ObjectNodeInstance::create(QObject *object)
QObject *ObjectNodeInstance::createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
{
return QmlPrivateGate::createPrimitive(typeName, majorNumber, minorNumber, context);
QObject *object = QmlPrivateGate::createPrimitive(typeName, majorNumber, minorNumber, context);
/* Let's try to create the primitive from source, since with incomplete meta info this might be a pure
* QML type. This is the case for example if a C++ type is mocked up with a QML file.
*/
if (!object)
object = createPrimitiveFromSource(typeName, majorNumber, minorNumber, context);
return object;
}
QObject *ObjectNodeInstance::createPrimitiveFromSource(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
{
if (typeName.isEmpty())
return 0;
QStringList parts = typeName.split("/");
const QString unqualifiedTypeName = parts.last();
parts.removeLast();
if (parts.isEmpty())
return 0;
const QString importString = parts.join(".") + " " + QString::number(majorNumber) + "." + QString::number(minorNumber);
QString source = "import " + importString + "\n" + unqualifiedTypeName + " {\n" + "}\n";
return createCustomParserObject(source, "", context);
}
QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context)

View File

@@ -67,6 +67,7 @@ public:
static Pointer create(QObject *objectToBeWrapped);
static QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context);
static QObject *createPrimitiveFromSource(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context);
static QObject *createCustomParserObject(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context);
static QObject *createComponent(const QString &componentPath, QQmlContext *context);
static QObject *createComponent(const QUrl &componentUrl, QQmlContext *context);

View File

@@ -1,4 +1,4 @@
project(%{ProjectName})
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
project(%{ProjectName})
add_executable(${PROJECT_NAME} "%{CFileName}")

View File

@@ -1,4 +1,4 @@
project(%{ProjectName})
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
project(%{ProjectName})
add_executable(${PROJECT_NAME} "%{CppFileName}")

View File

@@ -1,7 +1,7 @@
TEMPLATE = lib
TARGET = %ProjectName%
QT += qml quick
CONFIG += qt plugin c++11
CONFIG += plugin c++11
TARGET = $$qtLibraryTarget($$TARGET)
uri = %Uri%

View File

@@ -242,5 +242,5 @@ IconOverlayCppSource=:/cppeditor/images/dark_qt_cpp.png
IconOverlayPrf=:/qtsupport/images/dark_qt_project.png
IconOverlayPri=:/qtsupport/images/dark_qt_project.png
IconOverlayPro=:/qtsupport/images/dark_qt_project.png
StandardPixmapFileIcon=:/core/images/dark_fileicon.png
StandardPixmapDirIcon=:/core/images/dark_foldericon.png
StandardPixmapFileIcon=:/utils/images/dark_fileicon.png
StandardPixmapDirIcon=:/utils/images/dark_foldericon.png

View File

@@ -19865,6 +19865,38 @@ Ids must begin with a lowercase letter.</source>
<source>iOS tool Error %1</source>
<translation>Ошибка %1 утилиты iOS</translation>
</message>
<message>
<source>Application install on Simulator failed. %1</source>
<translation>Не удалось установить приложение на эмулятор. %1</translation>
</message>
<message>
<source>Application install on Simulator failed. Simulator not running.</source>
<translation>Не удалось установить приложение на эмулятор. Он не запущен.</translation>
</message>
<message>
<source>Application launch on Simulator failed. Invalid Bundle path %1</source>
<translation>Запуск приложения на эмуляторе не удался. Неверный путь пакета %1</translation>
</message>
<message>
<source>Spawning the Application process on Simulator failed.</source>
<translation>Не удалось породить процесс приложения на эмуляторе.</translation>
</message>
<message>
<source>Application launch on Simulator failed. Simulator not running.</source>
<translation>Не удалось запустить приложение на эмуляторе. Он не запущен.</translation>
</message>
<message>
<source>Application launch on Simulator failed. %1</source>
<translation>Запуск приложения на эмуляторе не удался. %1</translation>
</message>
<message>
<source>Spawning the Application process on Simulator failed. Spawning timed out.</source>
<translation>Не удалось породить процесс приложения на эмуляторе. Время порождения истекло.</translation>
</message>
<message>
<source>Simulator application process error %1</source>
<translation>Приложение из эмулятора вернуло ошибку %1</translation>
</message>
</context>
<context>
<name>IosDeployStepWidget</name>
@@ -21336,14 +21368,14 @@ Ids must begin with a lowercase letter.</source>
<name>Nim::NimCompilerBuildStepFactory</name>
<message>
<source>Nim Compiler Build Step</source>
<translation type="unfinished">Этап сборки компилятора Nim</translation>
<translation>Этап сборки компилятора Nim</translation>
</message>
</context>
<context>
<name>Nim::NimCompilerCleanStep</name>
<message>
<source>Nim Clean Step</source>
<translation type="unfinished">Этап очистки компилятора Nim</translation>
<translation>Этап очистки компилятора Nim</translation>
</message>
<message>
<source>Build directory &quot;%1&quot; does not exist.</source>
@@ -21432,28 +21464,28 @@ Ids must begin with a lowercase letter.</source>
<name>NimCompilerBuildStep</name>
<message>
<source>Nim Compiler Build Step</source>
<translation type="unfinished">Этап сборки компилятора Nim</translation>
<translation>Этап сборки компилятора Nim</translation>
</message>
</context>
<context>
<name>NimCompilerBuildStepConfigWidget</name>
<message>
<source>Nim build step</source>
<translation type="unfinished">Этап сборки Nim</translation>
<translation>Этап сборки Nim</translation>
</message>
</context>
<context>
<name>NimCompilerCleanStepFactory</name>
<message>
<source>Nim Compiler Clean Step</source>
<translation type="unfinished">Этап очистки компилятора Nim</translation>
<translation>Этап очистки компилятора Nim</translation>
</message>
</context>
<context>
<name>NimCompilerCleanStepWidget</name>
<message>
<source>Nim clean step</source>
<translation type="unfinished">Этап очистки Nim</translation>
<translation>Этап очистки Nim</translation>
</message>
</context>
<context>
@@ -36642,11 +36674,11 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
</message>
<message>
<source>Remove the automatically inserted character if the trigger is deleted by backspace after the completion.</source>
<translation type="unfinished">Удалять автоматически вставленный символ, если флаг удалён бекспейсом после дополнения.</translation>
<translation>Удалять автоматически вставленный символ, если флаг удалён бекспейсом после дополнения.</translation>
</message>
<message>
<source>Remove automatically inserted text on backspace</source>
<translation type="unfinished">Удалять автоматически вставленный текст по бекспейсу</translation>
<translation>Удалять автоматически вставленный текст по бекспейсу</translation>
</message>
<message>
<source>Documentation Comments</source>

View File

@@ -66,9 +66,9 @@ Item {
anchors.leftMargin: 18
anchors.rightMargin: 20
anchors.right: parent.right
text: examplesModel.searchString
placeholderText: qsTr("Search in Examples...")
onTextChanged: examplesModel.parseSearchString(text)
onTextChanged: examplesModel.setSearchString(text)
}
CustomizedGridView {

View File

@@ -39,9 +39,9 @@ Item {
anchors.rightMargin: 20
anchors.left: parent.left
anchors.leftMargin: 30
text: tutorialsModel.searchString
placeholderText: qsTr("Search in Tutorials...")
onTextChanged: tutorialsModel.parseSearchString(text)
onTextChanged: tutorialsModel.setSearchString(text)
}
CustomizedGridView {

View File

@@ -1252,7 +1252,12 @@ bool Check::visit(BinaryExpression *ast)
bool Check::visit(Block *ast)
{
addMessage(ErrBlocksNotSupportedInQmlUi, locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()));
bool isDirectInConnectionsScope =
(!m_typeStack.isEmpty() && m_typeStack.last() == QLatin1String("Connections"));
if (!isDirectInConnectionsScope)
addMessage(ErrBlocksNotSupportedInQmlUi, locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()));
if (Node *p = parent()) {
if (!cast<UiScriptBinding *>(p)

View File

@@ -1300,7 +1300,7 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface,
interface.setProgressValue(0);
CppDataHash newData;
QHash<QString, QStringList> newDeclarations;
QHash<QString, QList<CPlusPlus::Document::Ptr> > newDeclarations;
{
QMutexLocker locker(&qmlModelManager->m_cppDataMutex);
newData = qmlModelManager->m_cppDataHash;
@@ -1321,33 +1321,36 @@ void ModelManagerInterface::updateCppQmlTypes(QFutureInterface<void> &interface,
const QString fileName = doc->fileName();
if (!scan) {
hasNewInfo = newData.remove(fileName) > 0 || hasNewInfo;
foreach (const QString &file, newDeclarations[fileName]) {
CPlusPlus::Document::Ptr doc = snapshot.document(file);
if (doc.isNull())
continue;
finder(doc);
hasNewInfo = rescanExports(file, finder, newData) || hasNewInfo;
foreach (const CPlusPlus::Document::Ptr &savedDoc, newDeclarations.value(fileName)) {
finder(savedDoc);
hasNewInfo = rescanExports(savedDoc->fileName(), finder, newData) || hasNewInfo;
}
continue;
}
for (auto it = newDeclarations.begin(), end = newDeclarations.end(); it != end;) {
if (it->removeOne(fileName)) {
doc->releaseSourceAndAST();
if (it->isEmpty()) {
it = newDeclarations.erase(it);
continue;
for (auto docIt = it->begin(), endDocIt = it->end(); docIt != endDocIt;) {
CPlusPlus::Document::Ptr &savedDoc = *docIt;
if (savedDoc->fileName() == fileName) {
savedDoc->releaseSourceAndAST();
it->erase(docIt);
break;
} else {
++docIt;
}
}
++it;
if (it->isEmpty())
it = newDeclarations.erase(it);
else
++it;
}
foreach (const QString &declarationFile, finder(doc)) {
newDeclarations[declarationFile].append(fileName);
newDeclarations[declarationFile].append(doc);
doc->keepSourceAndAST(); // keep for later reparsing when dependent doc changes
}
hasNewInfo = rescanExports(doc->fileName(), finder, newData) || hasNewInfo;
hasNewInfo = rescanExports(fileName, finder, newData) || hasNewInfo;
doc->releaseSourceAndAST();
}

View File

@@ -275,7 +275,7 @@ private:
QrcCache m_qrcCache;
CppDataHash m_cppDataHash;
QHash<QString, QStringList> m_cppDeclarationFiles;
QHash<QString, QList<CPlusPlus::Document::Ptr> > m_cppDeclarationFiles;
mutable QMutex m_cppDataMutex;
// project integration

View File

@@ -14,9 +14,9 @@ msvc {
# Starting from Windows SDK 8, the headers and libs are under 'ProgramFiles (x86)'.
# The libraries are under 'ProgramFiles'as well, so, check for existence of 'inc'.
# 32bit qmake:
!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.0/Debuggers"
!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.1/Debuggers"
!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Windows Kits/10/Debuggers"
!exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.0/Debuggers"
!exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.1/Debuggers"
!exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles)/Windows Kits/10/Debuggers"
# 64bit qmake:
!exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles) (x86)/Windows Kits/8.0/Debuggers"
!exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles) (x86)/Windows Kits/8.1/Debuggers"

View File

@@ -166,11 +166,11 @@ QVariant SftpFileSystemModel::data(const QModelIndex &index, int role) const
switch (node->fileInfo.type) {
case FileTypeRegular:
case FileTypeOther:
return QIcon(QLatin1String(":/core/images/unknownfile.png"));
return QIcon(":/utils/images/unknownfile.png");
case FileTypeDirectory:
return QIcon(QLatin1String(":/core/images/dir.png"));
return QIcon(":/utils/images/dir.png");
case FileTypeUnknown:
return QIcon(QLatin1String(":/core/images/help.png")); // Shows a question mark.
return QIcon(":/utils/images/help.png"); // Shows a question mark.
}
}
if (index.column() == 1) {

View File

@@ -31,6 +31,7 @@
#include <QCoreApplication>
#include <QFuture>
#include <QFutureInterface>
#include <QFutureWatcher>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
@@ -493,4 +494,58 @@ runAsync(QThreadPool *pool, Function &&function, Args&&... args)
std::forward<Args>(args)...);
}
/*!
Adds a handler for when a result is ready.
This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
or create a QFutureWatcher already for other reasons.
*/
template <typename R, typename T>
const QFuture<T> &onResultReady(const QFuture<T> &future, R *receiver, void(R::*member)(const T &))
{
auto watcher = new QFutureWatcher<T>();
watcher->setFuture(future);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, receiver,
[receiver, member, watcher](int index) {
(receiver->*member)(watcher->future().resultAt(index));
});
return future;
}
/*!
Adds a handler for when a result is ready. The guard object determines the lifetime of
the connection.
This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
or create a QFutureWatcher already for other reasons.
*/
template <typename T, typename Function>
const QFuture<T> &onResultReady(const QFuture<T> &future, QObject *guard, Function f)
{
auto watcher = new QFutureWatcher<T>();
watcher->setFuture(future);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, guard, [f, watcher](int index) {
f(watcher->future().resultAt(index));
});
return future;
}
/*!
Adds a handler for when a result is ready.
This creates a new QFutureWatcher. Do not use if you intend to react on multiple conditions
or create a QFutureWatcher already for other reasons.
*/
template <typename T, typename Function>
const QFuture<T> &onResultReady(const QFuture<T> &future, Function f)
{
auto watcher = new QFutureWatcher<T>();
watcher->setFuture(future);
QObject::connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
QObject::connect(watcher, &QFutureWatcherBase::resultReadyAt, [f, watcher](int index) {
f(watcher->future().resultAt(index));
});
return future;
}
} // Utils

View File

@@ -149,9 +149,7 @@ public:
PaletteShadow,
PaletteWindowDisabled,
PaletteBackgroundDisabled,
PaletteWindowTextDisabled,
PaletteForegroundDisabled,
PaletteBaseDisabled,
PaletteAlternateBaseDisabled,
PaletteToolTipBaseDisabled,
@@ -299,18 +297,9 @@ public:
enum Gradient {
DetailsWidgetHeaderGradient,
Welcome_Button_GradientNormal,
Welcome_Button_GradientPressed
};
enum ImageFile {
ProjectExplorerHeader,
ProjectExplorerSource,
ProjectExplorerForm,
ProjectExplorerResource,
ProjectExplorerQML,
ProjectExplorerOtherFiles,
ProjectFileIcon,
IconOverlayCSource,
IconOverlayCppHeader,
IconOverlayCppSource,

View File

@@ -507,9 +507,12 @@ FileName AndroidConfig::toolPath(const Abi &abi, const QString &ndkToolChainVers
.arg(toolsPrefix(abi)));
}
FileName AndroidConfig::gccPath(const Abi &abi, const QString &ndkToolChainVersion) const
FileName AndroidConfig::gccPath(const Abi &abi, ToolChain::Language lang,
const QString &ndkToolChainVersion) const
{
return toolPath(abi, ndkToolChainVersion).appendString(QLatin1String("-gcc" QTC_HOST_EXE_SUFFIX));
const QString tool
= HostOsInfo::withExecutableSuffix(QString::fromLatin1(lang == ToolChain::Language::C ? "-gcc" : "-g++"));
return toolPath(abi, ndkToolChainVersion).appendString(tool);
}
FileName AndroidConfig::gdbPath(const Abi &abi, const QString &ndkToolChainVersion) const
@@ -1198,24 +1201,32 @@ QString AndroidConfigurations::defaultDevice(Project *project, const QString &ab
return map.value(abi);
}
static bool equalKits(Kit *a, Kit *b)
static bool matchToolChain(const ToolChain *atc, const ToolChain *btc)
{
if (atc == btc)
return true;
if (!atc || !btc)
return false;
if (atc->typeId() != Constants::ANDROID_TOOLCHAIN_ID || btc->typeId() != Constants::ANDROID_TOOLCHAIN_ID)
return false;
auto aatc = static_cast<const AndroidToolChain *>(atc);
auto abtc = static_cast<const AndroidToolChain *>(btc);
return aatc->ndkToolChainVersion() == abtc->ndkToolChainVersion()
&& aatc->targetAbi() == abtc->targetAbi();
}
static bool matchKits(const Kit *a, const Kit *b)
{
if (QtSupport::QtKitInformation::qtVersion(a) != QtSupport::QtKitInformation::qtVersion(b))
return false;
ToolChain *atc = ToolChainKitInformation::toolChain(a, ToolChain::Language::Cxx);
ToolChain *btc = ToolChainKitInformation::toolChain(b, ToolChain::Language::Cxx);
if (atc == btc)
return true;
if (!atc || atc->typeId() != Constants::ANDROID_TOOLCHAIN_ID)
return false;
if (!btc || btc->typeId() != Constants::ANDROID_TOOLCHAIN_ID)
return false;
AndroidToolChain *aatc = static_cast<AndroidToolChain *>(atc);
AndroidToolChain *bbtc = static_cast<AndroidToolChain *>(btc);
if (aatc->ndkToolChainVersion() == bbtc->ndkToolChainVersion()
&& aatc->targetAbi() == bbtc->targetAbi())
return true;
return false;
return matchToolChain(ToolChainKitInformation::toolChain(a, ToolChain::Language::Cxx),
ToolChainKitInformation::toolChain(b, ToolChain::Language::Cxx))
&& matchToolChain(ToolChainKitInformation::toolChain(a, ToolChain::Language::C),
ToolChainKitInformation::toolChain(b, ToolChain::Language::C));
}
void AndroidConfigurations::registerNewToolChains()
@@ -1243,32 +1254,13 @@ void AndroidConfigurations::removeOldToolChains()
void AndroidConfigurations::updateAutomaticKitList()
{
QList<AndroidToolChain *> toolchains;
if (AndroidConfigurations::currentConfig().automaticKitCreation()) {
// having a empty toolchains list will remove all autodetected kits for android
// exactly what we want in that case
foreach (ToolChain *tc, ToolChainManager::toolChains()) {
if (!tc->isAutoDetected())
continue;
if (tc->typeId() != Constants::ANDROID_TOOLCHAIN_ID)
continue;
if (!tc->isValid()) // going to be deleted
continue;
toolchains << static_cast<AndroidToolChain *>(tc);
}
}
const QList<Kit *> existingKits = Utils::filtered(KitManager::kits(), [](const Kit *k) {
return k->isAutoDetected() && !k->isSdkProvided()
&& DeviceTypeKitInformation::deviceTypeId(k) == Core::Id(Constants::ANDROID_DEVICE_TYPE);
});
QList<Kit *> existingKits;
foreach (Kit *k, KitManager::kits()) {
if (DeviceTypeKitInformation::deviceTypeId(k) != Core::Id(Constants::ANDROID_DEVICE_TYPE))
continue;
if (!k->isAutoDetected())
continue;
if (k->isSdkProvided())
continue;
// Update code for 3.0 beta, which shipped with a bug for the debugger settings
// Update code for 3.0 beta, which shipped with a bug for the debugger settings
for (Kit *k : existingKits) {
ToolChain *tc = ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx);
if (tc && Debugger::DebuggerKitInformation::runnable(k).executable != tc->suggestedDebugger().toString()) {
Debugger::DebuggerItem debugger;
@@ -1281,14 +1273,15 @@ void AndroidConfigurations::updateAutomaticKitList()
QVariant id = Debugger::DebuggerItemManager::registerDebugger(debugger);
Debugger::DebuggerKitInformation::setDebugger(k, id);
}
existingKits << k;
}
QHash<Abi, QList<QtSupport::BaseQtVersion *> > qtVersionsForArch;
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) {
if (qtVersion->type() != QLatin1String(Constants::ANDROIDQT))
continue;
QList<Abi> qtAbis = qtVersion->qtAbis();
QHash<Abi, QList<const QtSupport::BaseQtVersion *> > qtVersionsForArch;
const QList<QtSupport::BaseQtVersion *> qtVersions
= Utils::filtered(QtSupport::QtVersionManager::unsortedVersions(), [](const QtSupport::BaseQtVersion *v) {
return v->type() == Constants::ANDROIDQT;
});
for (const QtSupport::BaseQtVersion *qtVersion : qtVersions) {
const QList<Abi> qtAbis = qtVersion->qtAbis();
if (qtAbis.empty())
continue;
qtVersionsForArch[qtAbis.first()].append(qtVersion);
@@ -1298,22 +1291,36 @@ void AndroidConfigurations::updateAutomaticKitList()
IDevice::ConstPtr device = dm->find(Core::Id(Constants::ANDROID_DEVICE_ID));
if (device.isNull()) {
// no device, means no sdk path
foreach (Kit *k, existingKits)
for (Kit *k : existingKits)
KitManager::deregisterKit(k);
return;
}
// register new kits
QList<Kit *> newKits;
foreach (AndroidToolChain *tc, toolchains) {
if (tc->isSecondaryToolChain())
const QList<ToolChain *> tmp = Utils::filtered(ToolChainManager::toolChains(), [](ToolChain *tc) {
return tc->isAutoDetected()
&& tc->isValid()
&& tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
&& !static_cast<AndroidToolChain *>(tc)->isSecondaryToolChain();
});
const QList<AndroidToolChain *> toolchains = Utils::transform(tmp, [](ToolChain *tc) {
return static_cast<AndroidToolChain *>(tc);
});
for (AndroidToolChain *tc : toolchains) {
if (tc->isSecondaryToolChain() || tc->language() != ToolChain::Language::Cxx)
continue;
QList<QtSupport::BaseQtVersion *> qtVersions = qtVersionsForArch.value(tc->targetAbi());
foreach (QtSupport::BaseQtVersion *qt, qtVersions) {
const QList<AndroidToolChain *> allLanguages = Utils::filtered(toolchains,
[tc](AndroidToolChain *otherTc) {
return tc->targetAbi() == otherTc->targetAbi();
});
for (const QtSupport::BaseQtVersion *qt : qtVersionsForArch.value(tc->targetAbi())) {
Kit *newKit = new Kit;
newKit->setAutoDetected(true);
newKit->setAutoDetectionSource("AndroidConfiguration");
DeviceTypeKitInformation::setDeviceTypeId(newKit, Core::Id(Constants::ANDROID_DEVICE_TYPE));
ToolChainKitInformation::setToolChain(newKit, tc);
for (AndroidToolChain *tc : allLanguages)
ToolChainKitInformation::setToolChain(newKit, tc);
QtSupport::QtKitInformation::setQtVersion(newKit, qt);
DeviceKitInformation::setDevice(newKit, device);
@@ -1329,48 +1336,25 @@ void AndroidConfigurations::updateAutomaticKitList()
AndroidGdbServerKitInformation::setGdbSever(newKit, tc->suggestedGdbServer());
newKit->makeSticky();
newKit->setUnexpandedDisplayName(tr("Android for %1 (GCC %2, Qt %3)")
.arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
.arg(tc->ndkToolChainVersion())
.arg(qt->qtVersionString()));
newKits << newKit;
}
}
for (int i = existingKits.count() - 1; i >= 0; --i) {
Kit *existingKit = existingKits.at(i);
for (int j = 0; j < newKits.count(); ++j) {
Kit *newKit = newKits.at(j);
if (equalKits(existingKit, newKit)) {
// Kit is already registered, nothing to do
newKits.removeAt(j);
existingKits.at(i)->makeSticky();
existingKits.removeAt(i);
ToolChainKitInformation::setToolChain(existingKit, ToolChainKitInformation::toolChain(newKit, ToolChain::Language::Cxx));
KitManager::deleteKit(newKit);
j = newKits.count();
}
}
}
foreach (Kit *k, existingKits) {
ToolChain *tc = ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx);
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
if (tc && tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
&& tc->isValid()
&& qtVersion && qtVersion->type() == QLatin1String(Constants::ANDROIDQT)) {
k->makeUnSticky();
k->setAutoDetected(false);
QSet<const Kit *> rediscoveredExistingKits;
for (Kit *newKit : newKits) {
Kit *existingKit = Utils::findOrDefault(existingKits, [newKit](const Kit *k) { return matchKits(newKit, k); });
if (existingKit) {
existingKit->copyFrom(newKit);
KitManager::deleteKit(newKit);
rediscoveredExistingKits.insert(existingKit);
} else {
KitManager::deregisterKit(k);
KitManager::registerKit(newKit);
}
}
foreach (Kit *kit, newKits) {
AndroidToolChain *tc = static_cast<AndroidToolChain *>(ToolChainKitInformation::toolChain(kit, ToolChain::Language::Cxx));
AndroidQtVersion *qt = static_cast<AndroidQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit));
kit->setUnexpandedDisplayName(tr("Android for %1 (GCC %2, Qt %3)")
.arg(qt->targetArch())
.arg(tc->ndkToolChainVersion())
.arg(qt->qtVersionString()));
KitManager::registerKit(kit);
}
}
bool AndroidConfigurations::force32bitEmulator()

View File

@@ -27,6 +27,8 @@
#include "android_global.h"
#include <projectexplorer/toolchain.h>
#include <QObject>
#include <QString>
#include <QStringList>
@@ -126,7 +128,9 @@ public:
Utils::FileName emulatorToolPath() const;
Utils::FileName gccPath(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion) const;
Utils::FileName gccPath(const ProjectExplorer::Abi &abi,
ProjectExplorer::ToolChain::Language lang,
const QString &ndkToolChainVersion) const;
Utils::FileName gdbPath(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion) const;
Utils::FileName keytoolPath() const;

View File

@@ -314,6 +314,8 @@ void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
// Check for a gdb with a broken python
QStringList gdbPaths;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
if (ati.language == ProjectExplorer::ToolChain::Language::C)
continue;
// we only check the arm gdbs, that's indicative enough
if (ati.abi.architecture() != ProjectExplorer::Abi::ArmArchitecture)
continue;
@@ -329,8 +331,10 @@ void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
// See if we have qt versions for those toolchains
QSet<ProjectExplorer::Abi> toolchainsForAbi;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths)
toolchainsForAbi.insert(ati.abi);
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
if (ati.language == ProjectExplorer::ToolChain::Language::Cxx)
toolchainsForAbi.insert(ati.abi);
}
QSet<ProjectExplorer::Abi> qtVersionsForAbi;
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) {
@@ -496,16 +500,6 @@ void AndroidSettingsWidget::saveSettings()
AndroidConfigurations::setConfig(m_androidConfig);
}
int indexOf(const QList<AndroidToolChainFactory::AndroidToolChainInformation> &list, const Utils::FileName &f)
{
int end = list.count();
for (int i = 0; i < end; ++i) {
if (list.at(i).compilerCommand == f)
return i;
}
return -1;
}
void AndroidSettingsWidget::sdkLocationEditingFinished()
{
m_androidConfig.setSdkLocation(Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath()));

View File

@@ -302,16 +302,17 @@ QList<AndroidToolChainFactory::AndroidToolChainInformation> AndroidToolChainFact
int idx = versionRegExp.indexIn(fileName);
if (idx == -1)
continue;
AndroidToolChainInformation ati;
ati.version = fileName.mid(idx + 1);
QString platform = fileName.left(idx);
ati.abi = AndroidConfig::abiForToolChainPrefix(platform);
if (ati.abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
continue;
// AndroidToolChain *tc = new AndroidToolChain(arch, version, true);
ati.compilerCommand = AndroidConfigurations::currentConfig().gccPath(ati.abi, ati.version);
// tc->setCompilerCommand(compilerPath);
result.append(ati);
for (const ToolChain::Language lang : { ToolChain::Language::Cxx, ToolChain::Language::C }) {
AndroidToolChainInformation ati;
ati.language = lang;
ati.version = fileName.mid(idx + 1);
QString platform = fileName.left(idx);
ati.abi = AndroidConfig::abiForToolChainPrefix(platform);
if (ati.abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
continue;
ati.compilerCommand = AndroidConfigurations::currentConfig().gccPath(ati.abi, lang, ati.version);
result.append(ati);
}
}
return result;
}
@@ -353,19 +354,22 @@ bool AndroidToolChainFactory::versionCompareLess(const QList<int> &a, const QLis
return false;
}
bool AndroidToolChainFactory::versionCompareLess(AndroidToolChain *atc, AndroidToolChain *btc)
bool AndroidToolChainFactory::versionCompareLess(QList<AndroidToolChain *> atc,
QList<AndroidToolChain *> btc)
{
QList<int> a = versionNumberFromString(atc->ndkToolChainVersion());
QList<int> b = versionNumberFromString(btc->ndkToolChainVersion());
const QList<int> a = versionNumberFromString(atc.at(0)->ndkToolChainVersion());
const QList<int> b = versionNumberFromString(btc.at(0)->ndkToolChainVersion());
return versionCompareLess(a, b);
}
static AndroidToolChain *findToolChain(Utils::FileName &compilerPath, const QList<ToolChain *> &alreadyKnown)
static AndroidToolChain *findToolChain(Utils::FileName &compilerPath, ToolChain::Language lang,
const QList<ToolChain *> &alreadyKnown)
{
return static_cast<AndroidToolChain *>(
Utils::findOrDefault(alreadyKnown, [compilerPath](ToolChain *tc) {
Utils::findOrDefault(alreadyKnown, [compilerPath, lang](ToolChain *tc) {
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
&& tc->language() == lang
&& tc->compilerCommand() == compilerPath;
}));
}
@@ -382,7 +386,7 @@ AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
FileName path = ndkPath;
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
QStringList() << QLatin1String("*"), QDir::Dirs);
QHash<Abi, AndroidToolChain *> newestToolChainForArch;
QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;
while (it.hasNext()) {
const QString &fileName = FileName::fromString(it.next()).fileName();
@@ -394,26 +398,30 @@ AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
continue;
FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, version);
QList<AndroidToolChain *> toolChainBundle;
for (ToolChain::Language lang : { ToolChain::Language::Cxx, ToolChain::Language::C }) {
FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, lang, version);
AndroidToolChain *tc = findToolChain(compilerPath, alreadyKnown);
if (!tc) {
tc = new AndroidToolChain(abi, version, ToolChain::Language::Cxx,
ToolChain::AutoDetection);
tc->resetToolChain(compilerPath);
AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
if (!tc) {
tc = new AndroidToolChain(abi, version, lang,
ToolChain::AutoDetection);
tc->resetToolChain(compilerPath);
}
result.append(tc);
toolChainBundle.append(tc);
}
result.append(tc);
auto it = newestToolChainForArch.constFind(abi);
if (it == newestToolChainForArch.constEnd())
newestToolChainForArch.insert(abi, tc);
else if (versionCompareLess(it.value(), tc))
newestToolChainForArch[abi] = tc;
newestToolChainForArch.insert(abi, toolChainBundle);
else if (versionCompareLess(it.value(), toolChainBundle))
newestToolChainForArch[abi] = toolChainBundle;
}
foreach (ToolChain *tc, result) {
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
atc->setSecondaryToolChain(newestToolChainForArch.value(atc->targetAbi()) != atc);
atc->setSecondaryToolChain(!newestToolChainForArch.value(atc->targetAbi()).contains(atc));
}
return result;

View File

@@ -104,6 +104,7 @@ public:
class AndroidToolChainInformation
{
public:
ProjectExplorer::ToolChain::Language language;
Utils::FileName compilerCommand;
ProjectExplorer::Abi abi;
QString version;
@@ -116,7 +117,8 @@ public:
static QList<int> versionNumberFromString(const QString &version);
static bool versionCompareLess(const QList<int> &a, const QList<int> &b);
static bool versionCompareLess(AndroidToolChain *atc, AndroidToolChain *btc);
static bool versionCompareLess(QList<AndroidToolChain *> atc,
QList<AndroidToolChain *> btc);
static QList<int> newestToolChainVersionForArch(const ProjectExplorer::Abi &abi);
private:
static QHash<ProjectExplorer::Abi, QList<int> > m_newestVersionForAbi;

View File

@@ -129,6 +129,8 @@ void AppManagerProject::populateProject()
foreach (ProjectExplorer::Target *target, targets())
targetUpdateDeployableFiles(target, files);
}
emit parsingFinished();
}
void AppManagerProject::recursiveScanDirectory(const QDir &dir, QSet<QString> &container)

View File

@@ -231,6 +231,8 @@ void AutotoolsProject::makefileParsingFinished()
m_makefileParserThread->deleteLater();
m_makefileParserThread = 0;
emit parsingFinished();
}
void AutotoolsProject::onFileChanged(const QString &file)

View File

@@ -29,7 +29,6 @@
#include "clangstaticanalyzertool.h"
#include "clangstaticanalyzerutils.h"
#include <cpptools/cppmodelmanager.h>
#include <cpptools/projectinfo.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/kitmanager.h>
@@ -44,6 +43,7 @@
#include <QSignalSpy>
#include <QTimer>
#include <QtTest>
#include <QVariant>
#include <functional>
@@ -66,6 +66,35 @@ static bool processEventsUntil(const std::function<bool()> condition, int timeOu
}
}
class WaitForParsedProjects : public QObject
{
public:
WaitForParsedProjects(ProjectExplorer::SessionManager &sessionManager,
const QStringList &projects)
: m_sessionManager(sessionManager)
, m_projectsToWaitFor(projects)
{
connect(&m_sessionManager, &ProjectExplorer::SessionManager::projectFinishedParsing,
this, &WaitForParsedProjects::onProjectFinishedParsing);
}
void onProjectFinishedParsing(ProjectExplorer::Project *project)
{
m_projectsToWaitFor.removeOne(project->projectFilePath().toString());
}
bool wait()
{
return processEventsUntil([this]() {
return m_projectsToWaitFor.isEmpty();
});
}
private:
ProjectExplorer::SessionManager &m_sessionManager;
QStringList m_projectsToWaitFor;
};
namespace ClangStaticAnalyzer {
namespace Internal {
@@ -84,16 +113,14 @@ void ClangStaticAnalyzerPreconfiguredSessionTests::initTestCase()
if (!m_sessionManager.sessions().contains(preconfiguredSessionName))
QSKIP("Manually preconfigured session 'ClangStaticAnalyzerPreconfiguredSession' needed.");
// Load session
if (m_sessionManager.activeSession() != preconfiguredSessionName)
QVERIFY(m_sessionManager.loadSession(preconfiguredSessionName));
if (m_sessionManager.activeSession() == preconfiguredSessionName)
QSKIP("Session must not be already active.");
// Wait until all projects are loaded.
const int sessionManagerProjects = m_sessionManager.projects().size();
const auto allProjectsLoaded = [sessionManagerProjects]() {
return CppModelManager::instance()->projectInfos().size() == sessionManagerProjects;
};
QVERIFY(processEventsUntil(allProjectsLoaded));
// Load session
const QStringList projects = m_sessionManager.projectsForSessionName(preconfiguredSessionName);
WaitForParsedProjects waitForParsedProjects(m_sessionManager, projects);
QVERIFY(m_sessionManager.loadSession(preconfiguredSessionName));
QVERIFY(waitForParsedProjects.wait());
}
void ClangStaticAnalyzerPreconfiguredSessionTests::testPreconfiguredSession()
@@ -201,15 +228,15 @@ bool ClangStaticAnalyzerPreconfiguredSessionTests::switchToProjectAndTarget(Proj
m_sessionManager.setStartupProject(project);
if (target != project->activeTarget()) {
QSignalSpy waitUntilProjectUpdated(CppModelManager::instance(),
&CppModelManager::projectPartsUpdated);
QSignalSpy spyFinishedParsing(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::projectFinishedParsing);
m_sessionManager.setActiveTarget(project, target, ProjectExplorer::SetActive::NoCascade);
QTC_ASSERT(spyFinishedParsing.wait(30000), return false);
const bool waitResult = waitUntilProjectUpdated.wait(30000);
if (!waitResult) {
qWarning() << "waitUntilProjectUpdated() failed";
return false;
}
const QVariant projectArgument = spyFinishedParsing.takeFirst().takeFirst();
QTC_ASSERT(projectArgument.canConvert<ProjectExplorer::Project *>(), return false);
return projectArgument.value<ProjectExplorer::Project *>() == project;
}
return true;

View File

@@ -145,6 +145,8 @@ void CMakeProject::updateProjectData()
emit fileListChanged();
emit cmakeBc->emitBuildTypeChanged();
emit parsingFinished();
}
void CMakeProject::updateQmlJSCodeModel()

View File

@@ -44,17 +44,12 @@ ConfigModel::ConfigModel(QObject *parent) : QAbstractTableModel(parent)
int ConfigModel::rowCount(const QModelIndex &parent) const
{
QTC_ASSERT(parent.model() == nullptr || parent.model() == this, return 0);
if (parent.isValid())
return 0;
return m_configuration.count();
return parent.isValid() ? 0 : m_configuration.count();
}
int ConfigModel::columnCount(const QModelIndex &parent) const
{
QTC_ASSERT(!parent.isValid(), return 0);
QTC_ASSERT(parent.model() == nullptr, return 0);
return 3;
return parent.isValid() ? 0 : 3;
}
Qt::ItemFlags ConfigModel::flags(const QModelIndex &index) const

View File

@@ -340,9 +340,8 @@ QIcon ManhattanStyle::standardIcon(StandardPixmap standardIcon, const QStyleOpti
if (standardIcon == QStyle::SP_ComputerIcon) {
// Ubuntu has in some versions a 16x16 icon, see QTCREATORBUG-12832
const QList<QSize> &sizes = icon.availableSizes();
if (Utils::allOf(sizes, [](const QSize &size) { return size.width() < 32;})) {
icon = QIcon(QLatin1String(":/core/images/Desktop.png"));
}
if (Utils::allOf(sizes, [](const QSize &size) { return size.width() < 32;}))
icon = QIcon(":/utils/images/Desktop.png");
}
return icon;
}

View File

@@ -23,8 +23,8 @@
<string>?</string>
</property>
<property name="icon">
<iconset resource="core.qrc">
<normaloff>:/core/images/help.png</normaloff>:/core/images/help.png</iconset>
<iconset resource="../../libs/utils/utils.qrc">
<normaloff>:/utils/images/help.png</normaloff>:/utils/images/help.png</iconset>
</property>
</widget>
</item>
@@ -390,7 +390,7 @@
<tabstop>bigFilesLimitSpinBox</tabstop>
</tabstops>
<resources>
<include location="core.qrc"/>
<include location="../../libs/utils/utils.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -771,6 +771,66 @@ void CppEditorPlugin::test_quickfix_data()
"}\n"
);
// Checks: No special treatment for reference to non const.
QTest::newRow("GenerateGetterSetter_referenceToNonConst")
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
"\n"
"class Something\n"
"{\n"
" int &it@;\n"
"};\n"
) << _(
"\n"
"class Something\n"
"{\n"
" int &it;\n"
"\n"
"public:\n"
" int &getIt() const;\n"
" void setIt(const int &value);\n"
"};\n"
"\n"
"int &Something::getIt() const\n"
"{\n"
" return it;\n"
"}\n"
"\n"
"void Something::setIt(const int &value)\n"
"{\n"
" it = value;\n"
"}\n"
);
// Checks: No special treatment for reference to const.
QTest::newRow("GenerateGetterSetter_referenceToConst")
<< CppQuickFixFactoryPtr(new GenerateGetterSetter) << _(
"\n"
"class Something\n"
"{\n"
" const int &it@;\n"
"};\n"
) << _(
"\n"
"class Something\n"
"{\n"
" const int &it;\n"
"\n"
"public:\n"
" const int &getIt() const;\n"
" void setIt(const int &value);\n"
"};\n"
"\n"
"const int &Something::getIt() const\n"
"{\n"
" return it;\n"
"}\n"
"\n"
"void Something::setIt(const int &value)\n"
"{\n"
" it = value;\n"
"}\n"
);
// Checks:
// 1. Setter: Setter is a static function.
// 2. Getter: Getter is a static, non const function.

View File

@@ -3018,10 +3018,12 @@ public:
if (passByValue) {
paramString = oo.prettyType(fullySpecifiedType, paramName);
} else {
FullySpecifiedType constParamType(fullySpecifiedType);
const ReferenceType *refType = type->asReferenceType();
FullySpecifiedType constParamType(refType ? refType->elementType()
: fullySpecifiedType);
constParamType.setConst(true);
QScopedPointer<ReferenceType> referenceType(new ReferenceType(constParamType, false));
FullySpecifiedType referenceToConstParamType(referenceType.data());
const FullySpecifiedType referenceToConstParamType(referenceType.data());
paramString = oo.prettyType(referenceToConstParamType, paramName);
}

View File

@@ -286,6 +286,7 @@ void GenericProject::refresh(RefreshOptions options)
}
refreshCppCodeModel();
emit parsingFinished();
}
/**

View File

@@ -102,8 +102,10 @@ void IosAnalyzeSupport::handleRemoteOutput(const QString &output)
void IosAnalyzeSupport::handleRemoteErrorOutput(const QString &output)
{
if (m_runControl)
if (m_runControl) {
m_runControl->appendMessage(output, Utils::StdErrFormat);
m_outputParser.processOutput(output);
}
}
} // namespace Internal

View File

@@ -64,6 +64,16 @@ static bool checkForTimeout(const std::chrono::time_point< std::chrono::high_res
return timedOut;
}
static QByteArray runSimCtlCommand(QStringList args)
{
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();
}
class SimulatorControlPrivate :QObject {
Q_OBJECT
private:
@@ -79,7 +89,6 @@ private:
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);
@@ -105,7 +114,7 @@ QList<Ios::Internal::IosDeviceType> SimulatorControl::availableSimulators()
void SimulatorControl::updateAvailableSimulators()
{
const QByteArray output = d->runSimCtlCommand({QLatin1String("list"), QLatin1String("-j"), QLatin1String("devices")});
const QByteArray output = runSimCtlCommand({QLatin1String("list"), QLatin1String("-j"), QLatin1String("devices")});
QJsonDocument doc = QJsonDocument::fromJson(output);
if (!doc.isNull()) {
QList<IosDeviceType> availableDevices;
@@ -185,7 +194,7 @@ bool SimulatorControl::installApp(const QString &simUdid, const Utils::FileName
{
bool installed = false;
if (isSimulatorRunning(simUdid)) {
commandOutput = d->runSimCtlCommand(QStringList() << QStringLiteral("install") << simUdid << bundlePath.toString());
commandOutput = runSimCtlCommand(QStringList() << QStringLiteral("install") << simUdid << bundlePath.toString());
installed = commandOutput.isEmpty();
} else {
commandOutput = "Simulator device not running.";
@@ -199,7 +208,7 @@ qint64 SimulatorControl::launchApp(const QString &simUdid, const QString &bundle
pId = -1;
if (!bundleIdentifier.isEmpty() && isSimulatorRunning(simUdid)) {
const QStringList args({QStringLiteral("launch"), simUdid , bundleIdentifier});
const QByteArray output = d->runSimCtlCommand(args);
const QByteArray output = runSimCtlCommand(args);
const QByteArray pIdStr = output.trimmed().split(' ').last().trimmed();
bool validInt = false;
pId = pIdStr.toLongLong(&validInt);
@@ -264,16 +273,6 @@ 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)
@@ -282,7 +281,7 @@ QProcess *SimulatorControl::spawnAppProcess(const QString &simUdid, const Utils:
if (isSimulatorRunning(simUdid)) {
QString bundleId = bundleIdentifier(bundlePath);
QString executableName = bundleExecutable(bundlePath);
QByteArray appPath = d->runSimCtlCommand(QStringList() << QStringLiteral("get_app_container") << simUdid << bundleId).trimmed();
QByteArray appPath = 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());

View File

@@ -140,6 +140,8 @@ void NimProject::updateProject()
rootProjectNode()->buildTree(fileNodes);
emit fileListChanged();
emit parsingFinished();
}
bool NimProject::supportsKit(Kit *k, QString *) const

View File

@@ -304,9 +304,6 @@ void JsonFieldPage::Field::setIsCompleteExpando(const QVariant &v, const QString
// LabelFieldData:
// --------------------------------------------------------------------
LabelField::LabelField() : m_wordWrap(false)
{ }
bool LabelField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.type() != QVariant::Map) {
@@ -343,9 +340,6 @@ QWidget *LabelField::createWidget(const QString &displayName, JsonFieldPage *pag
// SpacerFieldData:
// --------------------------------------------------------------------
SpacerField::SpacerField() : m_factor(1)
{ }
bool SpacerField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.isNull())
@@ -388,9 +382,6 @@ QWidget *SpacerField::createWidget(const QString &displayName, JsonFieldPage *pa
// LineEditFieldData:
// --------------------------------------------------------------------
LineEditField::LineEditField() : m_isModified(false), m_isValidating(false)
{ }
bool LineEditField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.isNull())
@@ -502,9 +493,6 @@ void LineEditField::initializeData(MacroExpander *expander)
// --------------------------------------------------------------------
TextEditField::TextEditField() : m_acceptRichText(false)
{ }
bool TextEditField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.isNull())
@@ -570,9 +558,6 @@ void TextEditField::initializeData(MacroExpander *expander)
// PathChooserFieldData:
// --------------------------------------------------------------------
PathChooserField::PathChooserField() : m_kind(PathChooser::ExistingDirectory)
{ }
bool PathChooserField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.isNull())
@@ -668,11 +653,6 @@ void PathChooserField::initializeData(MacroExpander *expander)
// CheckBoxFieldData:
// --------------------------------------------------------------------
CheckBoxField::CheckBoxField() :
m_checkedValue(QLatin1String("0")),
m_uncheckedValue(QLatin1String("1"))
{ }
bool CheckBoxField::parseData(const QVariant &data, QString *errorMessage)
{
if (data.isNull())

View File

@@ -63,36 +63,28 @@ public:
class LabelField : public JsonFieldPage::Field
{
public:
LabelField();
private:
QWidget *createWidget(const QString &displayName, JsonFieldPage *page) override;
bool parseData(const QVariant &data, QString *errorMessage) override;
bool m_wordWrap;
bool m_wordWrap = false;
QString m_text;
};
class SpacerField : public JsonFieldPage::Field
{
public:
SpacerField();
bool suppressName() const override { return true; }
private:
bool parseData(const QVariant &data, QString *errorMessage) override;
QWidget *createWidget(const QString &displayName, JsonFieldPage *page) override;
int m_factor;
int m_factor = 1;
};
class LineEditField : public JsonFieldPage::Field
{
public:
LineEditField();
private:
bool parseData(const QVariant &data, QString *errorMessage) override;
QWidget *createWidget(const QString &displayName, JsonFieldPage *page) override;
@@ -102,10 +94,10 @@ private:
bool validate(Utils::MacroExpander *expander, QString *message) override;
void initializeData(Utils::MacroExpander *expander) override;
bool m_isModified;
bool m_isValidating;
bool m_restoreLastHistoryItem;
bool m_isPassword;
bool m_isModified = false;
bool m_isValidating = false;
bool m_restoreLastHistoryItem = false;
bool m_isPassword = false;
QString m_placeholderText;
QString m_defaultText;
QString m_disabledText;
@@ -117,9 +109,6 @@ private:
class TextEditField : public JsonFieldPage::Field
{
public:
TextEditField();
private:
bool parseData(const QVariant &data, QString *errorMessage) override;
QWidget *createWidget(const QString &displayName, JsonFieldPage *page) override;
@@ -130,7 +119,7 @@ private:
void initializeData(Utils::MacroExpander *expander) override;
QString m_defaultText;
bool m_acceptRichText;
bool m_acceptRichText = false;
QString m_disabledText;
mutable QString m_currentText;
@@ -138,9 +127,6 @@ private:
class PathChooserField : public JsonFieldPage::Field
{
public:
PathChooserField();
private:
bool parseData(const QVariant &data, QString *errorMessage) override;
@@ -155,7 +141,7 @@ private:
QString m_path;
QString m_basePath;
QString m_historyId;
Utils::PathChooser::Kind m_kind;
Utils::PathChooser::Kind m_kind = Utils::PathChooser::ExistingDirectory;
QString m_currentPath;
};
@@ -163,8 +149,6 @@ private:
class CheckBoxField : public JsonFieldPage::Field
{
public:
CheckBoxField();
bool suppressName() const override { return true; }
private:
@@ -177,8 +161,8 @@ private:
bool validate(Utils::MacroExpander *expander, QString *message) override;
void initializeData(Utils::MacroExpander *expander) override;
QString m_checkedValue;
QString m_uncheckedValue;
QString m_checkedValue = QString("0");
QString m_uncheckedValue = QString("1");
QVariant m_checkedExpression;
bool m_isModified = false;
@@ -186,9 +170,6 @@ private:
class ComboBoxField : public JsonFieldPage::Field
{
public:
ComboBoxField() = default;
private:
bool parseData(const QVariant &data, QString *errorMessage) override;

View File

@@ -573,7 +573,7 @@ MsvcToolChainFactory::MsvcToolChainFactory()
QSet<ToolChain::Language> MsvcToolChainFactory::supportedLanguages() const
{
return { ProjectExplorer::ToolChain::Language::Cxx };
return { ToolChain::Language::C, ToolChain::Language::Cxx };
}
bool MsvcToolChainFactory::checkForVisualStudioInstallation(const QString &vsName)
@@ -617,24 +617,32 @@ QString MsvcToolChainFactory::vcVarsBatFor(const QString &basePath, MsvcToolChai
return QString();
}
static ToolChain *findOrCreateToolChain(const QList<ToolChain *> &alreadyKnown,
const QString &name, const Abi &abi,
const QString &varsBat, const QString &varsBatArg,
ToolChain::Detection d = ToolChain::ManualDetection)
static QList<ToolChain *> findOrCreateToolChain(
const QList<ToolChain *> &alreadyKnown,
const QString &name, const Abi &abi,
const QString &varsBat, const QString &varsBatArg,
ToolChain::Detection d = ToolChain::ManualDetection)
{
ToolChain *tc = Utils::findOrDefault(alreadyKnown,
[&varsBat, &varsBatArg, &abi](ToolChain *tc) -> bool {
if (tc->typeId() != Constants::MSVC_TOOLCHAIN_TYPEID)
return false;
if (tc->targetAbi() != abi)
return false;
auto mtc = static_cast<MsvcToolChain *>(tc);
return mtc->varsBat() == varsBat
&& mtc->varsBatArg() == varsBatArg;
});
if (!tc)
tc = new MsvcToolChain(name, abi, varsBat, varsBatArg, ToolChain::Language::Cxx, d);
return tc;
QList<ToolChain *> res;
for (auto language: {ToolChain::Language::C, ToolChain::Language::Cxx}) {
ToolChain *tc = Utils::findOrDefault(
alreadyKnown,
[&varsBat, &varsBatArg, &abi, &language](ToolChain *tc) -> bool {
if (tc->typeId() != Constants::MSVC_TOOLCHAIN_TYPEID)
return false;
if (tc->targetAbi() != abi)
return false;
if (tc->language() != language)
return false;
auto mtc = static_cast<MsvcToolChain *>(tc);
return mtc->varsBat() == varsBat
&& mtc->varsBatArg() == varsBatArg;
});
if (!tc)
tc = new MsvcToolChain(name, abi, varsBat, varsBatArg, language, d);
res << tc;
}
return res;
}
// Detect build tools introduced with MSVC2015
@@ -670,10 +678,11 @@ static void detectCppBuildTools(QList<ToolChain *> *list)
const Entry &e = entries[i];
const Abi abi(e.architecture, Abi::WindowsOS, Abi::WindowsMsvc2015Flavor,
e.format, e.wordSize);
list->append(new MsvcToolChain(name + QLatin1String(e.postFix), abi,
vcVarsBat, QLatin1String(e.varsBatArg),
ToolChain::Language::Cxx,
ToolChain::AutoDetection));
for (auto language: {ToolChain::Language::C, ToolChain::Language::Cxx}) {
list->append(new MsvcToolChain(name + QLatin1String(e.postFix), abi,
vcVarsBat, QLatin1String(e.varsBatArg),
language, ToolChain::AutoDetection));
}
}
}
@@ -743,19 +752,18 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
continue;
QList<ToolChain *> tmp;
tmp.append(findOrCreateToolChain(alreadyKnown,
generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::x86),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::x86, sdkKey),
fi.absoluteFilePath(), QLatin1String("/x86"), ToolChain::AutoDetection));
// Add all platforms, cross-compiler is automatically selected by SetEnv.cmd if needed
tmp.append(findOrCreateToolChain(alreadyKnown,
generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::amd64),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::amd64, sdkKey),
fi.absoluteFilePath(), QLatin1String("/x64"), ToolChain::AutoDetection));
tmp.append(findOrCreateToolChain(alreadyKnown,
generateDisplayName(name, MsvcToolChain::WindowsSDK, MsvcToolChain::ia64),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, MsvcToolChain::ia64, sdkKey),
fi.absoluteFilePath(), QLatin1String("/ia64"), ToolChain::AutoDetection));
const QVector<QPair<MsvcToolChain::Platform, QString> > platforms = {
{MsvcToolChain::x86, "x86"},
{MsvcToolChain::amd64, "x64"},
{MsvcToolChain::ia64, "ia64"},
};
for (auto platform: platforms) {
tmp.append(findOrCreateToolChain(
alreadyKnown,
generateDisplayName(name, MsvcToolChain::WindowsSDK, platform.first),
findAbiOfMsvc(MsvcToolChain::WindowsSDK, platform.first, sdkKey),
fi.absoluteFilePath(), "/" + platform.second, ToolChain::AutoDetection));
}
// Make sure the default is front.
if (folder == defaultSdkPath)
results = tmp + results;
@@ -786,14 +794,16 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
const int version = vsName.leftRef(dotPos).toInt();
const QString vcvarsAllbat = path + QLatin1String("/vcvarsall.bat");
if (QFileInfo(vcvarsAllbat).isFile()) {
QList<MsvcToolChain::Platform> platforms; // prioritized list
// prioritized list.
// x86_arm was put before amd64_arm as a workaround for auto detected windows phone
// toolchains. As soon as windows phone builds support x64 cross builds, this change
// can be reverted.
platforms << MsvcToolChain::x86 << MsvcToolChain::amd64_x86
<< MsvcToolChain::amd64 << MsvcToolChain::x86_amd64
<< MsvcToolChain::arm << MsvcToolChain::x86_arm << MsvcToolChain::amd64_arm
<< MsvcToolChain::ia64 << MsvcToolChain::x86_ia64;
const QVector<MsvcToolChain::Platform> platforms = {
MsvcToolChain::x86, MsvcToolChain::amd64_x86,
MsvcToolChain::amd64, MsvcToolChain::x86_amd64,
MsvcToolChain::arm, MsvcToolChain::x86_arm, MsvcToolChain::amd64_arm,
MsvcToolChain::ia64, MsvcToolChain::x86_ia64
};
foreach (const MsvcToolChain::Platform &platform, platforms) {
const bool toolchainInstalled = QFileInfo(vcVarsBatFor(path, platform)).isFile();
if (hostSupportsPlatform(platform) && toolchainInstalled) {

View File

@@ -168,6 +168,9 @@ signals:
void projectContextUpdated();
void projectLanguagesUpdated();
signals: // for tests only
void parsingFinished();
protected:
virtual RestoreResult fromMap(const QVariantMap &map, QString *errorMessage);
virtual bool setupTarget(Target *t);

View File

@@ -1689,6 +1689,9 @@ ProjectExplorerPlugin::OpenProjectResult ProjectExplorerPlugin::openProjects(con
foundProjectManager = true;
QString tmp;
if (Project *pro = manager->openProject(filePath, &tmp)) {
QObject::connect(pro, &Project::parsingFinished, [pro]() {
emit SessionManager::instance()->projectFinishedParsing(pro);
});
QString restoreError;
Project::RestoreResult restoreResult = pro->restoreSettings(&restoreError);
if (restoreResult == Project::RestoreResult::Ok) {

View File

@@ -138,6 +138,9 @@ signals:
void aboutToSaveSession();
void dependencyChanged(ProjectExplorer::Project *a, ProjectExplorer::Project *b);
signals: // for tests only
void projectFinishedParsing(ProjectExplorer::Project *project);
private:
static void saveActiveMode(Core::Id mode);
void clearProjectFileCache();

View File

@@ -202,7 +202,9 @@ bool ToolChain::operator == (const ToolChain &tc) const
return true;
// We ignore displayname
return typeId() == tc.typeId() && isAutoDetected() == tc.isAutoDetected();
return typeId() == tc.typeId()
&& isAutoDetected() == tc.isAutoDetected()
&& language() == tc.language();
}
/*!

View File

@@ -619,6 +619,8 @@ void PythonProject::refresh()
return new PythonFileNode(FileName::fromString(f), displayName);
});
rootProjectNode()->buildTree(fileNodes);
emit parsingFinished();
}
/**

View File

@@ -503,6 +503,7 @@ void QbsProject::handleQbsParsingDone(bool success)
if (dataChanged)
updateAfterParse();
emit projectParsingDone(success);
emit parsingFinished();
}
void QbsProject::handleRuleExecutionDone()

View File

@@ -87,7 +87,8 @@ void QmakeKitInformation::setup(Kit *k)
break;
}
}
ToolChainKitInformation::setToolChain(k, possibleTc);
if (possibleTc)
ToolChainKitInformation::setToolChain(k, possibleTc);
}
}

View File

@@ -87,26 +87,25 @@ using namespace Utils;
struct FileTypeDataStorage {
FileType type;
Theme::ImageFile themeImage;
const char *typeName;
const char *icon;
const char *addFileFilter;
};
static const FileTypeDataStorage fileTypeDataStorage[] = {
{ HeaderType, Theme::ProjectExplorerHeader, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Headers"),
{ HeaderType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Headers"),
ProjectExplorer::Constants::FILEOVERLAY_H, "*.h; *.hh; *.hpp; *.hxx;"},
{ SourceType, Theme::ProjectExplorerSource, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Sources"),
{ SourceType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Sources"),
ProjectExplorer::Constants::FILEOVERLAY_CPP, "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++;" },
{ FormType, Theme::ProjectExplorerForm, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Forms"),
{ FormType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Forms"),
Constants::FILEOVERLAY_UI, "*.ui;" },
{ StateChartType, Theme::ProjectExplorerForm, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "State charts"),
{ StateChartType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "State charts"),
ProjectExplorer::Constants::FILEOVERLAY_SCXML, "*.scxml;" },
{ ResourceType, Theme::ProjectExplorerResource, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Resources"),
{ ResourceType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Resources"),
ProjectExplorer::Constants::FILEOVERLAY_QRC, "*.qrc;" },
{ QMLType, Theme::ProjectExplorerQML, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "QML"),
{ QMLType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "QML"),
ProjectExplorer::Constants::FILEOVERLAY_QML, "*.qml;" },
{ UnknownFileType, Theme::ProjectExplorerOtherFiles, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Other files"),
{ UnknownFileType, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Other files"),
ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN, "*;" }
};
@@ -159,10 +158,7 @@ QmakeNodeStaticData::QmakeNodeStaticData()
const QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
for (unsigned i = 0 ; i < count; ++i) {
QIcon overlayIcon;
const QString iconFile = creatorTheme()->imageFile(fileTypeDataStorage[i].themeImage,
QString::fromLatin1(fileTypeDataStorage[i].icon));
overlayIcon = QIcon(iconFile);
const QIcon overlayIcon(QLatin1String(fileTypeDataStorage[i].icon));
QIcon folderIcon;
folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFileNode", fileTypeDataStorage[i].typeName);
@@ -171,9 +167,7 @@ QmakeNodeStaticData::QmakeNodeStaticData()
desc, filter, folderIcon));
}
// Project icon
const QString fileName = creatorTheme()->imageFile(Theme::ProjectFileIcon,
QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QT));
const QIcon projectBaseIcon(fileName);
const QIcon projectBaseIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon);
projectIcon.addPixmap(projectPixmap);
@@ -205,7 +199,6 @@ public:
QtSupport::ProFileReader *readerCumulative;
ProFileGlobals *qmakeGlobals;
QMakeVfs *qmakeVfs;
bool isQt5;
};
class PriFileEvalResult
@@ -244,7 +237,6 @@ public:
TargetInformation targetInformation;
InstallsList installsList;
QHash<QmakeVariable, QStringList> newVarValues;
bool isDeployable;
QStringList errors;
};
@@ -645,7 +637,7 @@ PriFileEvalResult QmakePriFileNode::extractValues(const EvalInput &input,
// all the files from those folders and add watchers for them. That's too
// dangerous if we get the folders wrong and enumerate the whole project
// tree multiple times.
QStringList dynamicVariables = dynamicVarNames(input.readerExact, input.isQt5);
QStringList dynamicVariables = dynamicVarNames(input.readerExact);
foreach (ProFile *includeFileExact, includeFilesExact)
foreach (const QString &dynamicVar, dynamicVariables)
result.folders += input.readerExact->values(dynamicVar, includeFileExact);
@@ -1467,25 +1459,15 @@ QStringList QmakePriFileNode::varNamesForRemoving()
return vars;
}
QStringList QmakePriFileNode::dynamicVarNames(QtSupport::ProFileReader *readerExact,
bool isQt5)
QStringList QmakePriFileNode::dynamicVarNames(QtSupport::ProFileReader *reader)
{
QStringList result;
// Figure out DEPLOYMENT and INSTALLS
const QString deployment = QLatin1String("DEPLOYMENT");
const QString sources = QLatin1String(isQt5 ? ".files" : ".sources");
QStringList listOfVars = readerExact->values(deployment);
foreach (const QString &var, listOfVars) {
result << (var + sources);
}
// Figure out INSTALLS (and DEPLOYMENT, as it's aliased)
const QString installs = QLatin1String("INSTALLS");
const QString files = QLatin1String(".files");
listOfVars = readerExact->values(installs);
foreach (const QString &var, listOfVars) {
foreach (const QString &var, reader->values(installs))
result << (var + files);
}
result.removeDuplicates();
return result;
}
@@ -1631,11 +1613,6 @@ QByteArray QmakeProFileNode::cxxDefines() const
return result;
}
bool QmakeProFileNode::isDeployable() const
{
return m_isDeployable;
}
/*!
\class QmakeProFileNode
Implements abstract ProjectNode class
@@ -1798,10 +1775,6 @@ EvalInput QmakeProFileNode::evalInput() const
input.buildDirectory = buildDir();
input.readerExact = m_readerExact;
input.readerCumulative = m_readerCumulative;
Target *t = m_project->activeTarget();
Kit *k = t ? t->kit() : KitManager::defaultKit();
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
input.isQt5 = !qtVersion || qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5,0,0);
input.qmakeGlobals = m_project->qmakeGlobals();
input.qmakeVfs = m_project->qmakeVfs();
return input;
@@ -2012,19 +1985,6 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
result->newVarValues[QmakeCc] = input.readerExact->values("QMAKE_CC");
result->newVarValues[QmakeCxx] = input.readerExact->values("QMAKE_CXX");
result->isDeployable = false;
if (result->projectType == ApplicationTemplate) {
result->isDeployable = true;
} else {
foreach (const QString &item, input.readerExact->values(QLatin1String("DEPLOYMENT"))) {
if (!input.readerExact->values(item + QLatin1String(".sources")).isEmpty()) {
result->isDeployable = true;
break;
}
}
}
if (readerBuildPass && readerBuildPass != input.readerExact)
delete readerBuildPass;
}
@@ -2274,7 +2234,6 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
m_subProjectsNotToDeploy = result->subProjectsNotToDeploy;
m_installsList = result->installsList;
m_isDeployable = result->isDeployable;
if (m_varValues != result->newVarValues)
m_varValues = result->newVarValues;

View File

@@ -180,7 +180,7 @@ protected:
static QStringList varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact);
static QStringList varNamesForRemoving();
static QString varNameForAdding(const QString &mimeType);
static QStringList dynamicVarNames(QtSupport::ProFileReader *readerExact, bool isQt5);
static QStringList dynamicVarNames(QtSupport::ProFileReader *readerExact);
static QSet<Utils::FileName> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);
static QSet<Utils::FileName> filterFilesRecursiveEnumerata(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);
@@ -354,7 +354,6 @@ public:
QString objectExtension() const;
QString objectsDirectory() const;
QByteArray cxxDefines() const;
bool isDeployable() const;
enum AsyncUpdateDelay { ParseNow, ParseLater };
void scheduleUpdate(AsyncUpdateDelay delay);
@@ -401,8 +400,6 @@ private:
static TargetInformation targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const QString &buildDir, const QString &projectFilePath);
static InstallsList installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir);
bool m_isDeployable = false;
bool m_validParse = false;
bool m_parseInProgress = true;

View File

@@ -753,6 +753,7 @@ void QmakeProject::decrementPendingEvaluateFutures()
activeTarget()->updateDefaultDeployConfigurations();
updateRunConfigurations();
emit proFilesEvaluated();
emit parsingFinished();
if (debug)
qDebug()<<" Setting state to Base";
}

View File

@@ -25,6 +25,9 @@
#include "componentview.h"
#include "componentaction.h"
#include <nodemetainfo.h>
#include <QDebug>
#include <nodeabstractproperty.h>
@@ -193,7 +196,9 @@ void ComponentView::searchForComponentAndAddToList(const ModelNode &node)
foreach (const ModelNode &node, node.allSubModelNodesAndThisNode()) {
if (node.nodeSourceType() == ModelNode::NodeWithComponentSource
|| (node.hasParentProperty()
&& !node.parentProperty().isDefaultProperty())) {
&& !node.parentProperty().isDefaultProperty()
&& node.metaInfo().isValid()
&& node.metaInfo().isGraphicalItem())) {
if (masterNotAdded) {
masterNotAdded = true;
addMasterDocument();

View File

@@ -223,7 +223,7 @@ static bool idContainsWrongLetter(const QString& id)
bool ModelNode::isValidId(const QString &id)
{
return id.isEmpty() || (!idContainsWrongLetter(id) && !idIsQmlKeyWord(id)) && !isIdToAvoid(id);
return id.isEmpty() || (!idContainsWrongLetter(id) && !idIsQmlKeyWord(id) && !isIdToAvoid(id));
}
bool ModelNode::hasId() const

View File

@@ -198,6 +198,8 @@ void QmlProject::refresh(RefreshOptions options)
QmlJS::Dialect::Qml);
modelManager()->updateProjectInfo(projectInfo, this);
emit parsingFinished();
}
QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const

View File

@@ -760,6 +760,14 @@ void ExamplesListModelFilter::updateFilter()
}
}
void ExamplesListModelFilter::setFilterStrings(const QStringList &arg)
{
if (m_filterStrings != arg) {
m_filterStrings = arg;
delayedUpdateFilter();
}
}
bool containsSubString(const QStringList &list, const QString &substr, Qt::CaseSensitivity cs)
{
return Utils::contains(list, [&substr, &cs](const QString &elem) {
@@ -789,11 +797,11 @@ bool ExamplesListModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex
});
}
if (!m_searchString.isEmpty()) {
if (!m_filterStrings.isEmpty()) {
const QString description = sourceModel()->index(sourceRow, 0, sourceParent).data(Description).toString();
const QString name = sourceModel()->index(sourceRow, 0, sourceParent).data(Name).toString();
foreach (const QString &subString, m_searchString) {
foreach (const QString &subString, m_filterStrings) {
bool wordMatch = false;
wordMatch |= (bool)name.contains(subString, Qt::CaseInsensitive);
if (wordMatch)
@@ -835,6 +843,14 @@ void ExamplesListModelFilter::filterForExampleSet(int index)
m_sourceModel->selectExampleSet(index);
}
void ExamplesListModelFilter::setFilterTags(const QStringList &arg)
{
if (m_filterTags != arg) {
m_filterTags = arg;
emit filterTagsChanged(arg);
}
}
void ExamplesListModelFilter::setShowTutorialsOnly(bool showTutorialsOnly)
{
m_showTutorialsOnly = showTutorialsOnly;
@@ -984,8 +1000,13 @@ struct SearchStringLexer
}
};
void ExamplesListModelFilter::parseSearchString(const QString &arg)
void ExamplesListModelFilter::setSearchString(const QString &arg)
{
if (m_searchString == arg)
return;
m_searchString = arg;
emit searchStringChanged(m_searchString);
// parse and update
QStringList tags;
QStringList searchTerms;
SearchStringLexer lex(arg);
@@ -1007,10 +1028,15 @@ void ExamplesListModelFilter::parseSearchString(const QString &arg)
}
}
setSearchStrings(searchTerms);
setFilterStrings(searchTerms);
setFilterTags(tags);
delayedUpdateFilter();
}
QString ExamplesListModelFilter::searchString() const
{
return m_searchString;
}
} // namespace Internal
} // namespace QtSupport

View File

@@ -163,7 +163,7 @@ class ExamplesListModelFilter : public QSortFilterProxyModel
public:
Q_PROPERTY(bool showTutorialsOnly READ showTutorialsOnly WRITE setShowTutorialsOnly NOTIFY showTutorialsOnlyChanged)
Q_PROPERTY(QStringList filterTags READ filterTags WRITE setFilterTags NOTIFY filterTagsChanged)
Q_PROPERTY(QStringList searchStrings READ searchStrings WRITE setSearchStrings NOTIFY searchStrings)
Q_PROPERTY(QString searchString READ searchString WRITE setSearchString NOTIFY searchStringChanged)
Q_PROPERTY(int exampleSetIndex READ exampleSetIndex NOTIFY exampleSetIndexChanged)
@@ -171,9 +171,11 @@ public:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
Q_INVOKABLE void setSearchString(const QString &arg);
QString searchString() const;
bool showTutorialsOnly() { return m_showTutorialsOnly; }
QStringList filterTags() const { return m_filterTags; }
QStringList searchStrings() const { return m_searchString; }
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
@@ -182,35 +184,21 @@ public:
Q_INVOKABLE void filterForExampleSet(int index);
public slots:
void setFilterTags(const QStringList &arg)
{
if (m_filterTags != arg) {
m_filterTags = arg;
emit filterTagsChanged(arg);
}
}
void setFilterTags(const QStringList &arg);
void updateFilter();
void setSearchStrings(const QStringList &arg)
{
if (m_searchString != arg) {
m_searchString = arg;
emit searchStrings(arg);
delayedUpdateFilter();
}
}
void parseSearchString(const QString &arg);
void setShowTutorialsOnly(bool showTutorialsOnly);
void handleQtVersionsChanged();
signals:
void showTutorialsOnlyChanged();
void filterTagsChanged(const QStringList &arg);
void searchStrings(const QStringList &arg);
void searchStringChanged(const QString &arg);
void exampleSetIndexChanged();
private:
void setFilterStrings(const QStringList &arg);
void qtVersionManagerLoaded();
void helpManagerInitialized();
@@ -221,8 +209,9 @@ private:
int exampleSetIndex() const;
bool m_showTutorialsOnly;
QString m_searchString;
QStringList m_filterTags;
QStringList m_searchString;
QStringList m_filterStrings;
ExamplesListModel *m_sourceModel;
int m_timerId;
bool m_blockIndexUpdate;

View File

@@ -685,11 +685,6 @@ void QtOptionsPageWidget::userChangedCurrentVersion()
updateDescriptionLabel();
}
void QtOptionsPageWidget::qtVersionChanged()
{
updateDescriptionLabel();
}
void QtOptionsPageWidget::updateDescriptionLabel()
{
QtVersionItem *item = currentItem();
@@ -736,7 +731,7 @@ void QtOptionsPageWidget::updateWidgets()
m_versionUi->formLayout->addRow(m_configurationWidget);
m_configurationWidget->setEnabled(!version->isAutodetected());
connect(m_configurationWidget, &QtConfigWidget::changed,
this, &QtOptionsPageWidget::qtVersionChanged);
this, &QtOptionsPageWidget::updateDescriptionLabel);
}
} else {
m_versionUi->nameEdit->clear();

View File

@@ -85,7 +85,6 @@ private:
private:
void updateQtVersions(const QList<int> &, const QList<int> &, const QList<int> &);
void qtVersionChanged();
void versionChanged(const QModelIndex &current, const QModelIndex &previous);
void addQtDir();
void removeQtDir();

View File

@@ -103,7 +103,7 @@ class RelayServer: public QObject
public:
RelayServer(IosTool *parent);
~RelayServer();
bool startServer(int port, bool ipv6);
bool startServer(int port);
void stopServer();
quint16 serverPort();
IosTool *iosTool();
@@ -113,7 +113,8 @@ public:
protected:
virtual void newRelayConnection() = 0;
QTcpServer m_server;
QTcpServer m_ipv4Server;
QTcpServer m_ipv6Server;
QList<Relayer *> m_connections;
};
@@ -188,7 +189,6 @@ private:
int maxProgress;
int opLeft;
bool debug;
bool ipv6;
bool inAppOutput;
bool splitAppOutput; // as QXmlStreamReader reports the text attributes atomically it is better to split
Ios::IosDeviceManager::AppOp appOp;
@@ -404,31 +404,39 @@ RelayServer::~RelayServer()
stopServer();
}
bool RelayServer::startServer(int port, bool ipv6)
bool RelayServer::startServer(int port)
{
QTC_CHECK(!m_server.isListening());
m_server.setMaxPendingConnections(1);
connect(&m_server, &QTcpServer::newConnection, this, &RelayServer::handleNewRelayConnection);
QTC_CHECK(!m_ipv4Server.isListening());
QTC_CHECK(!m_ipv6Server.isListening());
connect(&m_ipv4Server, &QTcpServer::newConnection,
this, &RelayServer::handleNewRelayConnection);
connect(&m_ipv6Server, &QTcpServer::newConnection,
this, &RelayServer::handleNewRelayConnection);
quint16 portValue = static_cast<quint16>(port);
if (port < 0 || port > 0xFFFF)
return false;
if (ipv6)
return m_server.listen(QHostAddress(QHostAddress::LocalHostIPv6), portValue);
else
return m_server.listen(QHostAddress(QHostAddress::LocalHost), portValue);
m_ipv4Server.listen(QHostAddress(QHostAddress::LocalHostIPv6), portValue);
m_ipv6Server.listen(QHostAddress(QHostAddress::LocalHost), portValue);
return m_ipv4Server.isListening() || m_ipv6Server.isListening();
}
void RelayServer::stopServer()
{
foreach (Relayer *connection, m_connections)
delete connection;
if (m_server.isListening())
m_server.close();
if (m_ipv4Server.isListening())
m_ipv4Server.close();
if (m_ipv6Server.isListening())
m_ipv6Server.close();
}
quint16 RelayServer::serverPort()
{
return m_server.serverPort();
if (m_ipv4Server.isListening())
return m_ipv4Server.serverPort();
if (m_ipv6Server.isListening())
return m_ipv6Server.serverPort();
return 0;
}
IosTool *RelayServer::iosTool()
@@ -459,11 +467,12 @@ SingleRelayServer::SingleRelayServer(IosTool *parent,
void SingleRelayServer::newRelayConnection()
{
QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections()
? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection();
if (m_connections.size() > 0) {
delete m_server.nextPendingConnection();
delete clientSocket;
return;
}
QTcpSocket *clientSocket = m_server.nextPendingConnection();
if (clientSocket) {
Relayer *newConnection = new Relayer(this, clientSocket);
m_connections.append(newConnection);
@@ -483,7 +492,8 @@ GenericRelayServer::GenericRelayServer(IosTool *parent, int remotePort,
void GenericRelayServer::newRelayConnection()
{
QTcpSocket *clientSocket = m_server.nextPendingConnection();
QTcpSocket *clientSocket = m_ipv4Server.hasPendingConnections()
? m_ipv4Server.nextPendingConnection() : m_ipv6Server.nextPendingConnection();
if (clientSocket) {
iosTool()->errorMsg(QString::fromLatin1("setting up relayer for new connection"));
RemotePortRelayer *newConnection = new RemotePortRelayer(this, clientSocket);
@@ -498,7 +508,6 @@ IosTool::IosTool(QObject *parent):
maxProgress(0),
opLeft(0),
debug(false),
ipv6(false),
inAppOutput(false),
splitAppOutput(true),
appOp(Ios::IosDeviceManager::None),
@@ -548,8 +557,6 @@ void IosTool::run(const QStringList &args)
appOp = Ios::IosDeviceManager::AppOp(appOp | Ios::IosDeviceManager::Run);
} else if (arg == QLatin1String("--noninteractive")) {
// ignored for compatibility
} else if (arg == QLatin1String("--ipv6")) {
ipv6 = true;
} else if (arg == QLatin1String("-v") || arg == QLatin1String("--verbose")) {
echoRelays = true;
} else if (arg == QLatin1String("-d") || arg == QLatin1String("--debug")) {
@@ -721,12 +728,12 @@ void IosTool::didStartApp(const QString &bundlePath, const QString &deviceId,
int qmlPort = deviceSession->qmljsDebugPort();
if (qmlPort) {
qmlServer = new GenericRelayServer(this, qmlPort, deviceSession);
qmlServer->startServer(0, ipv6);
qmlServer->startServer(0);
}
}
if (debug) {
gdbServer = new SingleRelayServer(this, gdbFd);
if (!gdbServer->startServer(0, ipv6)) {
if (!gdbServer->startServer(0)) {
doExit(-4);
return;
}

View File

@@ -1903,9 +1903,9 @@ void tst_Dumpers::dumper_data()
+ Check("h1.2.value.1", "[1]", "2", "int")
+ Check("h2", "<3 items>", "@QHash<int, float>")
+ Check("h2.0", "[0] 0", FloatValue("33"), "float")
+ Check("h2.1", "[1] 22", FloatValue("22"), "float")
+ Check("h2.2", "[2] 11", FloatValue("11"), "float")
+ Check("h2.0", "[0] 0", FloatValue("33"), "")
+ Check("h2.1", "[1] 22", FloatValue("22"), "")
+ Check("h2.2", "[2] 11", FloatValue("11"), "")
+ Check("h3", "<1 items>", "@QHash<@QString, int>")
+ Check("h3.0.key", "key", "\"22.0\"", "@QString")
@@ -1934,7 +1934,7 @@ void tst_Dumpers::dumper_data()
+ CheckType("h7.2.value", "@QPointer<@QObject>")
+ Check("h8", "<3 items>", "Hash")
+ Check("h8.0", "[0] 22", FloatValue("22"), "float")
+ Check("h8.0", "[0] 22", FloatValue("22"), "")
+ Check("it1.key", "22", "int")
+ Check("it1.value", FloatValue("22"), "float")
+ Check("it3.key", "33", "int")
@@ -2347,8 +2347,8 @@ void tst_Dumpers::dumper_data()
+ Check("m1.1.value.0", "[0]", "\"22\"", "@QString")
+ Check("m2", "<2 items>", "@QMap<unsigned int, float>")
+ Check("m2.0", "[0] 11", FloatValue("31.0"), "float")
+ Check("m2.1", "[1] 22", FloatValue("32.0"), "float")
+ Check("m2.0", "[0] 11", FloatValue("31.0"), "")
+ Check("m2.1", "[1] 22", FloatValue("32.0"), "")
+ Check("m3", "<2 items>", "T")
@@ -2432,8 +2432,8 @@ void tst_Dumpers::dumper_data()
+ Check("m0", "<0 items>", "@QMultiMap<int, int>")
+ Check("m1", "<6 items>", "@QMultiMap<unsigned int, float>")
+ Check("m1.0", "[0] 11", FloatValue("11"), "float")
+ Check("m1.5", "[5] 22", FloatValue("22"), "float")
+ Check("m1.0", "[0] 11", FloatValue("11"), "")
+ Check("m1.5", "[5] 22", FloatValue("22"), "")
+ Check("m2", "<1 items>", "@QMultiMap<@QString, float>")
+ Check("m2.0.key", "\"22.0\"", "@QString")
@@ -4120,23 +4120,23 @@ void tst_Dumpers::dumper_data()
"map4.insert(std::pair<unsigned int, float>(22, 25.0));\n")
+ Check("map1", "<2 items>", "std::map<unsigned int, unsigned int>")
+ Check("map1.0", "[0] 11", "1", "unsigned int")
+ Check("map1.1", "[1] 22", "2", "unsigned int")
+ Check("map1.0", "[0] 11", "1", "")
+ Check("map1.1", "[1] 22", "2", "")
+ Check("map2", "<2 items>", "std::map<unsigned int, float>")
+ Check("map2.0", "[0] 11", FloatValue("11"), "float")
+ Check("map2.1", "[1] 22", FloatValue("22"), "float")
+ Check("map2.0", "[0] 11", FloatValue("11"), "")
+ Check("map2.1", "[1] 22", FloatValue("22"), "")
+ Check("map3", "<6 items>", "Map")
+ Check("map3.0", "[0] 11", FloatValue("11"), "float")
+ Check("map3.0", "[0] 11", FloatValue("11"), "")
+ Check("it1.first", "11", "int")
+ Check("it1.second", FloatValue("11"), "float")
+ Check("it6.first", "66", "int")
+ Check("it6.second", FloatValue("66"), "float")
+ Check("map4", "<5 items>", "std::multimap<unsigned int, float>")
+ Check("map4.0", "[0] 11", FloatValue("11"), "float")
+ Check("map4.4", "[4] 22", FloatValue("25"), "float");
+ Check("map4.0", "[0] 11", FloatValue("11"), "")
+ Check("map4.4", "[4] 22", FloatValue("25"), "");
QTest::newRow("StdMapQt")
@@ -4188,33 +4188,33 @@ void tst_Dumpers::dumper_data()
+ CoreProfile()
+ Check("map1", "<3 items>", "std::map<@QString, Foo>")
+ Check("map1.0", "[0] \"22.0\"", "", "std::pair<@QString const, Foo>")
+ Check("map1.0", "[0] \"22.0\"", "", "")
+ Check("map1.0.first", "\"22.0\"", "@QString")
+ Check("map1.0.second", "", "Foo")
+ Check("map1.0.second.a", "22", "int")
+ Check("map1.1", "[1] \"33.0\"", "", "std::pair<@QString const, Foo>")
+ Check("map1.1", "[1] \"33.0\"", "", "")
+ Check("map1.2.first", "\"44.0\"", "@QString")
+ Check("map1.2.second", "", "Foo")
+ Check("map1.2.second.a", "44", "int")
+ Check("map2", "<2 items>", "std::map<char const*, Foo>")
+ Check("map2.0", "[0] \"22.0\"", "", "std::pair<char const* const, Foo>")
+ Check("map2.0", "[0] \"22.0\"", "", "")
+ Check("map2.0.first", "\"22.0\"", "char *")
+ Check("map2.0.first.0", "[0]", "50", "char")
+ Check("map2.0.second", "", "Foo")
+ Check("map2.0.second.a", "22", "int")
+ Check("map2.1", "[1] \"33.0\"", "", "std::pair<char const* const, Foo>")
+ Check("map2.1", "[1] \"33.0\"", "", "")
+ Check("map2.1.first", "\"33.0\"", "char *")
+ Check("map2.1.first.0", "[0]", "51", "char")
+ Check("map2.1.second", "", "Foo")
+ Check("map2.1.second.a", "33", "int")
+ Check("map3", "<2 items>", "std::map<unsigned int, @QStringList>")
+ Check("map3.0", "[0] 11", "<1 items>", "std::pair<unsigned int const, @QStringList>")
+ Check("map3.0", "[0] 11", "<1 items>", "")
+ Check("map3.0.first", "11", "unsigned int")
+ Check("map3.0.second", "<1 items>", "@QStringList")
+ Check("map3.0.second.0", "[0]", "\"11\"", "@QString")
+ Check("map3.1", "[1] 22", "<1 items>", "std::pair<unsigned int const, @QStringList>")
+ Check("map3.1", "[1] 22", "<1 items>", "")
+ Check("map3.1.first", "22", "unsigned int")
+ Check("map3.1.second", "<1 items>", "@QStringList")
+ Check("map3.1.second.0", "[0]", "\"22\"", "@QString")
@@ -4222,26 +4222,25 @@ void tst_Dumpers::dumper_data()
+ Check("map4.1.second.0", "[0]", "\"22\"", "@QString")
+ Check("map5", "<2 items>", "std::map<@QString, float>")
+ Check("map5.0", "[0] \"11.0\"", FloatValue("11"), "std::pair<@QString const, float>")
+ Check("map5.0", "[0] \"11.0\"", FloatValue("11"), "")
+ Check("map5.0.first", "\"11.0\"", "@QString")
+ Check("map5.0.second", FloatValue("11"), "float")
+ Check("map5.1", "[1] \"22.0\"", FloatValue("22"), "std::pair<@QString const, float>")
+ Check("map5.1", "[1] \"22.0\"", FloatValue("22"), "")
+ Check("map5.1.first", "\"22.0\"", "@QString")
+ Check("map5.1.second", FloatValue("22"), "float")
+ Check("map6", "<2 items>", "std::map<int, @QString>")
+ Check("map6.0", "[0] 11", "\"11.0\"", "std::pair<int const, @QString>")
+ Check("map6.0", "[0] 11", "\"11.0\"", "")
+ Check("map6.0.first", "11", "int")
+ Check("map6.0.second", "\"11.0\"", "@QString")
+ Check("map6.1", "[1] 22", "\"22.0\"", "std::pair<int const, @QString>")
+ Check("map6.1", "[1] 22", "\"22.0\"", "")
+ Check("map6.1.first", "22", "int")
+ Check("map6.1.second", "\"22.0\"", "@QString")
+ Check("map7", "<3 items>", "std::map<@QString, @QPointer<@QObject>>")
+ Check("map7.0", "[0] \".\"", "", "std::pair<@QString const, @QPointer<@QObject>>")
+ Check("map7.0", "[0] \".\"", "", "")
+ Check("map7.0.first", "\".\"", "@QString")
+ Check("map7.0.second", "", "@QPointer<@QObject>")
+ Check("map7.2", "[2] \"Welt\"", "", "std::pair<@QString const, @QPointer<@QObject>>")
+ Check("map7.2.first", "\"Welt\"", "@QString");
@@ -4672,8 +4671,8 @@ void tst_Dumpers::dumper_data()
+ Cxx11Profile()
+ Check("map1", "<2 items>", "std::unordered_map<unsigned int, unsigned int>")
+ Check("map1.0", "[0] 22", "2", "unsigned int")
+ Check("map1.1", "[1] 11", "1", "unsigned int")
+ Check("map1.0", "[0] 22", "2", "")
+ Check("map1.1", "[1] 11", "1", "")
+ Check("map2", "<2 items>", "std::unordered_map<std::string, float>")
+ Check("map2.0", "[0] \"22.0\"", FloatValue("22.0"), "")
@@ -5382,17 +5381,8 @@ void tst_Dumpers::dumper_data()
+ Check("y2", "", "X")
+ Check("y3", "", "X");
QTest::newRow("RValueReferenceLldb")
QTest::newRow("RValueReference")
<< Data(rvalueData)
+ LldbEngine
+ Check("x1", "", "X &&")
+ Check("x2", "", "X &&")
+ Check("x3", "", "X &&");
QTest::newRow("RValueReferenceGdb")
<< Data(rvalueData)
+ GdbEngine
+ GccVersion(0, 40704)
+ Check("x1", "", "X &")
+ Check("x2", "", "X &")
+ Check("x3", "", "X &");
@@ -6231,6 +6221,7 @@ void tst_Dumpers::dumper_data()
+ Check("v15", "\"utf16\"", "@QJSValue (QString)")
+ Check("v15.1", "[1]", "116", "@QChar");
#if 0
#ifdef Q_OS_LINUX
// Hint: To open a failing test in Creator, do:
// touch qt_tst_dumpers_Nim_.../dummy.nimproject
@@ -6239,6 +6230,7 @@ void tst_Dumpers::dumper_data()
nimData.configTest = "which nim";
nimData.allProfile =
"CONFIG -= qt\n"
"SOURCES += main.nim\n"
"# Prevents linking\n"
"TARGET=\n"
"# Overwrites qmake-generated 'all' target.\n"
@@ -6253,8 +6245,10 @@ void tst_Dumpers::dumper_data()
"proc mainProc =\n"
" var name: string = \"Hello World\"\n"
" var i: int = 43\n"
" var j: int\n"
" var x: seq[int]\n"
" x = @[1, 2, 3, 4, 5, 6]\n\n"
" j = i + name.len()\n"
" # Crash it.\n"
" var m1 = Mirror(tag:1)\n"
" var m2 = Mirror(tag:2)\n"
@@ -6278,6 +6272,7 @@ void tst_Dumpers::dumper_data()
+ Check("x", "<6 items>", Pattern("TY.*NI.6..")) // Something like "TY95019 (NI[6])"
+ Check("x.2", "[2]", "3", "NI");
#endif
#endif
}
int main(int argc, char *argv[])

View File

@@ -44,6 +44,7 @@ private slots:
void threadPriority();
void runAsyncNoFutureInterface();
void crefFunction();
void onResultReady();
};
void report3(QFutureInterface<int> &fi)
@@ -557,6 +558,64 @@ void tst_RunExtensions::crefFunction()
QCOMPARE(value, true);
}
class ObjWithProperty : public QObject
{
Q_OBJECT
public slots:
void setValue(const QString &s)
{
value = s;
}
public:
QString value;
};
void tst_RunExtensions::onResultReady()
{
{ // lambda
QFuture<QString> f = Utils::runAsync([](QFutureInterface<QString> &fi) {
fi.reportResult("Hi");
fi.reportResult("there");
});
int count = 0;
QString res;
Utils::onResultReady(f, [&count, &res](const QString &s) {
++count;
res = s;
});
f.waitForFinished();
QCoreApplication::processEvents();
QCOMPARE(count, 2);
QCOMPARE(res, QString("there"));
}
{ // lambda with guard
QFuture<QString> f = Utils::runAsync([](QFutureInterface<QString> &fi) {
fi.reportResult("Hi");
fi.reportResult("there");
});
int count = 0;
ObjWithProperty obj;
Utils::onResultReady(f, &obj, [&count, &obj](const QString &s) {
++count;
obj.setValue(s);
});
f.waitForFinished();
QCoreApplication::processEvents();
QCOMPARE(count, 2);
QCOMPARE(obj.value, QString("there"));
}
{ // member
QFuture<QString> f = Utils::runAsync([]() { return QString("Hi"); });
ObjWithProperty obj;
Utils::onResultReady(f, &obj, &ObjWithProperty::setValue);
f.waitForFinished();
QCoreApplication::processEvents();
QCOMPARE(obj.value, QString("Hi"));
}
}
QTEST_MAIN(tst_RunExtensions)
#include "tst_runextensions.moc"