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 \li Some versions of Perf will not start recording unless given a
certain minimum sampling frequency. Try with a certain minimum sampling frequency. Try with a
\uicontrol {Sampling Frequency} of 1000. \uicontrol {Sampling Frequency} of 1000.
\li On some devices, for example Boundary Devices i.MX6 Boards, the \li On some devices, in particular various i.MX6 Boards, the hardware
Perf support is not very stable and the Linux kernel may randomly performance counters are dysfunctional and the Linux kernel may
fail to record data after some time. Perf can use different types randomly fail to record data after some time. Perf can use different
of events to trigger samples. You can get a list of available event types of events to trigger samples. You can get a list of available
types by running \c {perf list} on the device and add event types by running \c {perf list} on the device and add
\c {-e <event type>} to the \uicontrol {Additional arguments} field \c {-e <event type>} to the \uicontrol {Additional arguments} field
to change the event type to be used. The choice of event type to change the event type to be used. The choice of event type
affects the performance and stability of the sampling. 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 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 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} 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 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 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) also move between events by selecting the \uicontrol {Jump to Previous Event}
and \uicontrol {Jump to Next Event} (2) buttons. 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 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, the default zoom level, right-click the timeline to open the context menu,
and select \uicontrol {Reset Zoom}. and select \uicontrol {Reset Zoom}.
Click the time ruler to add vertical orientation lines (5) to the timeline.
\section2 Selecting Event Ranges \section2 Selecting Event Ranges
You can select an event range (7) to view the frame rate of events and to 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 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 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 handle to define the end of the range. The length of the range indicates the
frame rate of the event. frame rate of the event.
@@ -557,14 +559,26 @@
\section2 Visualizing Statistics as Flame Graphs \section2 Visualizing Statistics as Flame Graphs
The \uicontrol {Flame Graph} view shows a more concise statistical overview 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 time all invocations of a certain function took together, relative to the
total runtime of all JavaScript and QML events. The nesting shows which 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 \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 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 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. 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 \title Comparing Files
You can use a diff editor from \QC to compare two text files. They can be You can use a diff editor to display unsaved changed in the current file or
either versions of the same file or arbitrary files. 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 \list 1
\li Select \uicontrol Tools > \uicontrol Diff. \li Select \uicontrol Tools > \uicontrol Diff >
\uicontrol {Diff External Files}.
\li Select two files to compare. \li Select two files to compare.
\endlist \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 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 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 indicates lines that contain added text (painted a darker green) in the
@@ -70,6 +80,26 @@
\inlineimage sidebysidediff.png \inlineimage sidebysidediff.png
(\uicontrol {Switch to Side by Side Diff Editor}). (\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 > To change the default colors, select \uicontrol Tools > \uicontrol Options >
\uicontrol {Text Editor} > \uicontrol {Font & Colors}. Create your own color \uicontrol {Text Editor} > \uicontrol {Font & Colors}. Create your own color
scheme and select new colors for the following options: scheme and select new colors for the following options:
@@ -95,22 +125,4 @@
indicates added characters. indicates added characters.
\endlist \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 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 QML code snippets, which specify QML code constructs
\li Nim code snippets, which specify Nim code constructs \li Nim code snippets, which specify Nim code constructs

View File

@@ -161,6 +161,8 @@
\li Keyword completion \li Keyword completion
\li Code completion
\li Auto-indentation \li Auto-indentation
\li Matching parentheses and quotes \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 you can change the position of an object on the canvas and then add animation
to the change between the states. 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 You can preview the states in the \uicontrol State pane and click them to switch
between states on the canvas. between states on the canvas.

View File

@@ -133,12 +133,23 @@
\image qmldesigner-set-expression.png "Type properties context menu" \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. 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 For more information on the JavaScript environment provided by QML, see
\l{Integrating QML and JavaScript}. \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. performance, so consider setting anchors and margins for items, instead.
For example, instead of setting \c {parent.width} for an item, you could 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. 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...') print('Creating .tar.gz...')
createTarGz(archive_path(crlf=False), target_file_base + '.tar.gz') createTarGz(archive_path(crlf=False), target_file_base + '.tar.gz')
print('Creating .tar.xz...') 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...') print('Creating .zip with CRLF...')
createZip(archive_path(crlf=True), target_file_base + '.zip') createZip(archive_path(crlf=True), target_file_base + '.zip')
print('Removing temporary directory...') print('Removing temporary directory...')

View File

@@ -117,25 +117,25 @@ def qdump__boost__unordered__unordered_set(d, value):
innerType = value.type[0] innerType = value.type[0]
bucketCount = d.extractInt(base + ptrSize) bucketCount = d.extractInt(base + ptrSize)
#warn("A BUCKET COUNT: %s" % bucketCount) #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: try:
# boost 1.58 # boost 1.58
table = value["table_"] table = value["table_"]
bucketsAddr = table["buckets_"].integer() bucketsAddr = table["buckets_"].integer()
#warn("A BUCKETS: 0x%x" % bucketsAddr) #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 lastBucketAddr = bucketsAddr + bucketCount * ptrSize
#warn("A LAST BUCKET: 0x%x" % lastBucketAddr) #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 previousStartAddr = lastBucketAddr
#warn("A PREVIOUS START: 0x%x" % previousStartAddr) #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) item = d.extractPointer(previousStartAddr)
#warn("A KEY ADDR: 0x%x" % item) #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) item = d.extractPointer(previousStartAddr)
#warn("A VALUE: %x" % d.extractInt(item + ptrSize)) #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): with Children(d, size, maxNumChild=10000):
for j in d.childRange(): for j in d.childRange():
d.putSubItem(j, d.createValue(item + 2 * ptrSize, innerType)) 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.output = []
self.setVariableFetchingOptions(args) self.setVariableFetchingOptions(args)
def fromNativeDowncastableValue(self, nativeValue): def fromFrameValue(self, nativeValue):
val = nativeValue
if self.useDynamicType: if self.useDynamicType:
try: try:
return self.fromNativeValue(nativeValue.cast(nativeValue.dynamic_type)) val = nativeValue.cast(nativeValue.dynamic_type)
except: except:
pass pass
return self.fromNativeValue(nativeValue) return self.fromNativeValue(val)
def fromNativeValue(self, nativeValue): 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 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) val = self.Value(self)
if not nativeValue.address is None: if not nativeValue.address is None:
val.laddress = toInteger(nativeValue.address) val.laddress = toInteger(nativeValue.address)
@@ -238,82 +267,131 @@ class Dumper(DumperBase):
val.ldisplay += ' (%s)' % intval val.ldisplay += ' (%s)' % intval
elif code == gdb.TYPE_CODE_COMPLEX: elif code == gdb.TYPE_CODE_COMPLEX:
val.ldisplay = str(nativeValue) val.ldisplay = str(nativeValue)
elif code == gdb.TYPE_CODE_ARRAY: #elif code == gdb.TYPE_CODE_ARRAY:
val.type.ltarget = nativeValue[0].type.unqualified() # val.type.ltarget = nativeValue[0].type.unqualified()
return val return val
def ptrSize(self):
result = gdb.lookup_type('void').pointer().sizeof
self.ptrSize = lambda: result
return result
def fromNativeType(self, nativeType): def fromNativeType(self, nativeType):
self.check(isinstance(nativeType, gdb.Type)) self.check(isinstance(nativeType, gdb.Type))
typeobj = self.Type(self) code = nativeType.code
typeobj.nativeType = nativeType.unqualified() #warn('FROM NATIVE TYPE: %s' % nativeType)
typeobj.name = str(typeobj.nativeType) #nativeType = nativeType.unqualified()
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
def nativeTypeDereference(self, nativeType): if code == gdb.TYPE_CODE_PTR:
return self.fromNativeType(nativeType.strip_typedefs().target()) #warn('PTR')
targetType = self.fromNativeType(nativeType.target().unqualified())
return self.createPointerType(targetType)
def nativeTypeUnqualified(self, nativeType): if code == gdb.TYPE_CODE_REF:
return self.fromNativeType(nativeType.unqualified()) #warn('REF')
targetType = self.fromNativeType(nativeType.target().unqualified())
return self.createReferenceType(targetType)
def nativeTypePointer(self, nativeType): if code == gdb.TYPE_CODE_ARRAY:
return self.fromNativeType(nativeType.pointer()) #warn('ARRAY')
nativeTargetType = nativeType.target().unqualified()
targetType = self.fromNativeType(nativeTargetType)
count = nativeType.sizeof // nativeTargetType.sizeof
return self.createArrayType(targetType, count)
def nativeTypeTarget(self, nativeType): if code == gdb.TYPE_CODE_TYPEDEF:
while nativeType.code == gdb.TYPE_CODE_TYPEDEF: #warn('TYPEDEF')
nativeType = nativeType.strip_typedefs().unqualified() nativeTargetType = nativeType.unqualified()
return self.fromNativeType(nativeType.target()) 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): if code == gdb.TYPE_CODE_ERROR:
nativeFields = nativeType.fields() warn('Type error: %s' % nativeType)
if len(nativeFields) and nativeFields[0].is_base_class: return self.Type(self, '')
return self.fromNativeType(nativeFields[0].type)
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): def nativeTypeEnumDisplay(self, nativeType, intval):
try: try:
val = gdb.parse_and_eval("(%s)%d" % (nativeType, intval)) val = gdb.parse_and_eval('(%s)%d' % (nativeType, intval))
return "%s (%d)" % (val, intval) return '%s (%d)' % (val, intval)
except: except:
return "%d" % intval return '%d' % intval
def nativeTypeFields(self, nativeType): def nativeTypeId(self, nativeType):
if nativeType.code == gdb.TYPE_CODE_TYPEDEF: name = str(nativeType)
return self.nativeTypeFields(nativeType.strip_typedefs()) 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 = [] 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): if not nativeType.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
return fields return fields
@@ -321,18 +399,20 @@ class Dumper(DumperBase):
nativeIndex = 0 nativeIndex = 0
baseIndex = 0 baseIndex = 0
nativeFields = nativeType.fields() nativeFields = nativeType.fields()
#warn("NATIVE FIELDS: %s" % nativeFields) #warn('NATIVE FIELDS: %s' % nativeFields)
anonNumber = 0
for nativeField in nativeFields: for nativeField in nativeFields:
#warn("FIELD: %s" % nativeField) #warn('FIELD: %s' % nativeField)
#warn(" DIR: %s" % dir(nativeField)) #warn(' DIR: %s' % dir(nativeField))
#warn(" BITSIZE: %s" % nativeField.bitsize) #warn(' BITSIZE: %s' % nativeField.bitsize)
#warn(" ARTIFICIAL: %s" % nativeField.artificial) #warn(' ARTIFICIAL: %s' % nativeField.artificial)
#warn("FIELD NAME: %s" % nativeField.name) #warn('FIELD NAME: %s' % nativeField.name)
#warn("FIELD TYPE: %s" % nativeField.type) #warn('FIELD TYPE: %s' % nativeField.type)
#warn('FIELD TYPE ID: %s' % self.nativeTypeId(nativeField.type))
#self.check(isinstance(nativeField, gdb.Field)) #self.check(isinstance(nativeField, gdb.Field))
field = self.Field(self) field = self.Field(self)
field.ltype = self.fromNativeType(nativeField.type) field.ltype = self.fromNativeType(nativeField.type.unqualified())
field.parentType = self.fromNativeType(nativeType) field.parentType = parentType
field.name = nativeField.name field.name = nativeField.name
field.isBaseClass = nativeField.is_base_class field.isBaseClass = nativeField.is_base_class
if hasattr(nativeField, 'bitpos'): if hasattr(nativeField, 'bitpos'):
@@ -356,36 +436,31 @@ class Dumper(DumperBase):
# Something without a name. # Something without a name.
# Anonymous union? We need a dummy name to distinguish # Anonymous union? We need a dummy name to distinguish
# multiple anonymous unions in the struct. # multiple anonymous unions in the struct.
self.anonNumber += 1 anonNumber += 1
field.name = "#%s" % self.anonNumber field.name = '#%s' % anonNumber
else: else:
# Normal named field. # Normal named field.
field.name = nativeField.name field.name = nativeField.name
field.nativeIndex = nativeIndex field.nativeIndex = nativeIndex
#warn('FIELD RESULT: %s' % field)
fields.append(field) fields.append(field)
nativeIndex += 1 nativeIndex += 1
#warn("FIELDS: %s" % fields) #warn('FIELDS: %s' % fields)
return 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): def listOfLocals(self, partialVar):
frame = gdb.selected_frame() frame = gdb.selected_frame()
try: try:
block = frame.block() block = frame.block()
#warn("BLOCK: %s " % block) #warn('BLOCK: %s ' % block)
except RuntimeError as error: except RuntimeError as error:
#warn("BLOCK IN FRAME NOT ACCESSIBLE: %s" % error) #warn('BLOCK IN FRAME NOT ACCESSIBLE: %s' % error)
return [] return []
except: except:
warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS") warn('BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS')
return [] return []
items = [] items = []
@@ -409,10 +484,18 @@ class Dumper(DumperBase):
# "NotImplementedError: Symbol type not yet supported in # "NotImplementedError: Symbol type not yet supported in
# Python scripts." # Python scripts."
#warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name)) #warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name))
try: if False and self.passExceptions:
value = self.fromNativeDowncastableValue(frame.read_var(name, block)) value = self.fromFrameValue(frame.read_var(name, block))
#warn("READ 1: %s" % value)
value.name = name 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) items.append(value)
continue continue
except: except:
@@ -420,7 +503,7 @@ class Dumper(DumperBase):
try: try:
#warn("READ 2: %s" % item.value) #warn("READ 2: %s" % item.value)
value = self.fromNativeDowncastableValue(frame.read_var(name)) value = self.fromFrameValue(frame.read_var(name))
value.name = name value.name = name
items.append(value) items.append(value)
continue continue
@@ -435,7 +518,8 @@ class Dumper(DumperBase):
try: try:
#warn("READ 3: %s %s" % (name, item.value)) #warn("READ 3: %s %s" % (name, item.value))
#warn("ITEM 3: %s" % 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) items.append(value)
except: except:
# Can happen in inlined code (see last line of # 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) exp = "((%s*)0x%x)->%s(%s)" % (typeName, addr, function, arg)
#warn("CALL: %s" % exp) #warn("CALL: %s" % exp)
result = gdb.parse_and_eval(exp) result = gdb.parse_and_eval(exp)
#warn(" -> %s" % result) warn(" -> %s" % result)
res = self.fromNativeValue(result)
if not value.address(): if not value.address():
gdb.parse_and_eval("free((void*)0x%x)" % addr) gdb.parse_and_eval("free((void*)0x%x)" % addr)
return self.fromNativeValue(result) return res
def makeExpression(self, value): def makeExpression(self, value):
typename = "::" + value.type.name typename = "::" + value.type.name
@@ -573,13 +658,6 @@ class Dumper(DumperBase):
#warn(" VALUE: %s" % value) #warn(" VALUE: %s" % value)
return 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): def pokeValue(self, value):
# Allocates inferior memory and copies the contents of value. # Allocates inferior memory and copies the contents of value.
# Returns a pointer to the copy. # Returns a pointer to the copy.
@@ -885,9 +963,6 @@ class Dumper(DumperBase):
def enumExpression(self, enumType, enumValue): def enumExpression(self, enumType, enumValue):
return self.qtNamespace() + "Qt::" + enumValue return self.qtNamespace() + "Qt::" + enumValue
def lookupType(self, typeName):
return self.fromNativeType(self.lookupNativeType(typeName))
def lookupNativeType(self, typeName): def lookupNativeType(self, typeName):
nativeType = self.lookupNativeTypeHelper(typeName) nativeType = self.lookupNativeTypeHelper(typeName)
if not nativeType is None: if not nativeType is None:
@@ -1154,7 +1229,7 @@ class CliDumper(Dumper):
def putNumChild(self, numchild): def putNumChild(self, numchild):
pass pass
def putOriginalAddress(self, value): def putOriginalAddress(self, address):
pass pass
def fetchVariables(self, args): def fetchVariables(self, args):
@@ -1205,4 +1280,4 @@ class InterpreterMessageBreakpoint(gdb.Breakpoint):
print("Interpreter event received.") print("Interpreter event received.")
return theDumper.handleInterpreterMessage() 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'] storage = value['m_storage']
nrows = storage['m_rows'].integer() if argRow == -1 else argRow nrows = storage['m_rows'].integer() if argRow == -1 else argRow
ncols = storage['m_cols'].integer() if argCol == -1 else argCol ncols = storage['m_cols'].integer() if argCol == -1 else argCol
p = storage['m_data'].integer() p = storage['m_data'].pointer()
innerSize = innerType.size() innerSize = innerType.size()
d.putValue('(%s x %s), %s' % (nrows, ncols, ['ColumnMajor', 'RowMajor'][rowMajor])) d.putValue('(%s x %s), %s' % (nrows, ncols, ['ColumnMajor', 'RowMajor'][rowMajor]))
d.putField('keeporder', '1') d.putField('keeporder', '1')

View File

@@ -152,7 +152,7 @@ def qdump_X_QModelIndex(d, value):
except: except:
p = value['i'] p = value['i']
m = value['m'] 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.putValue('(invalid)')
d.putPlainChildren(value) d.putPlainChildren(value)
return return
@@ -196,7 +196,7 @@ def qdump_X_QModelIndex(d, value):
def qdump__QDate(d, value): def qdump__QDate(d, value):
jd = value.integer() jd = value.pointer()
if jd: if jd:
d.putValue(jd, 'juliandate') d.putValue(jd, 'juliandate')
d.putNumChild(1) d.putNumChild(1)
@@ -332,6 +332,7 @@ def qdump__QDateTime(d, value):
d.putNumChild(0) d.putNumChild(0)
return return
d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
ns = d.qtNamespace() ns = d.qtNamespace()
@@ -1120,7 +1121,7 @@ def qdump__QRegion(d, value):
def qdump__QScopedPointer(d, value): def qdump__QScopedPointer(d, value):
if value.integer() == 0: if value.pointer() == 0:
d.putValue('(null)') d.putValue('(null)')
d.putNumChild(0) d.putNumChild(0)
else: else:
@@ -1187,13 +1188,13 @@ def qdump__QSet(d, value):
def qdump__QSharedData(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) d.putNumChild(0)
def qdump__QSharedDataPointer(d, value): def qdump__QSharedDataPointer(d, value):
d_ptr = value['d'] d_ptr = value['d']
if d_ptr.integer() == 0: if d_ptr.pointer() == 0:
d.putValue('(null)') d.putValue('(null)')
d.putNumChild(0) d.putNumChild(0)
else: else:
@@ -1206,7 +1207,7 @@ def qdump__QSharedDataPointer(d, value):
d.putPlainChildren(value) d.putPlainChildren(value)
return return
d.putBetterType(d.currentType) 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: if displayFormat == SeparateFormat:
d.putDisplay('utf16:separate', url) d.putDisplay('utf16:separate', url)
d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
d.putIntItem('port', port) d.putIntItem('port', port)
@@ -1684,12 +1686,12 @@ def qdump__QVariant(d, value):
ptr = p.pointer() ptr = p.pointer()
(elided, blob) = d.encodeCArray(ptr, 1, 100) (elided, blob) = d.encodeCArray(ptr, 1, 100)
typeName = d.hexdecode(blob) typeName = d.hexdecode(blob)
base = data.extractPointer()
# Prefer namespaced version. # Prefer namespaced version.
if len(ns) > 0: if len(ns) > 0:
if not d.lookupNativeType(ns + typeName) is None: if not d.lookupNativeType(ns + typeName) is None:
typeName = ns + typeName 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: if not typeName is None:
d.putBetterType('%sQVariant (%s)' % (ns, typeName)) d.putBetterType('%sQVariant (%s)' % (ns, typeName))
return None return None
@@ -1706,7 +1708,7 @@ def qedit__QVector(d, value, data):
base = value['d'].address() + offset base = value['d'].address() + offset
except: except:
# Qt 4. # Qt 4.
base = value['p']['array'].integer() base = value['p']['array'].pointer()
d.setValues(base, innerType, values) d.setValues(base, innerType, values)
@@ -1766,6 +1768,7 @@ def qdump_QWeakPointerHelper(d, value, isWeak):
def qdump__QXmlAttributes__Attribute(d, value): def qdump__QXmlAttributes__Attribute(d, value):
d.putEmptyValue() d.putEmptyValue()
d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
(qname, uri, localname, val) = value.split('{QString}' * 4) (qname, uri, localname, val) = value.split('{QString}' * 4)
@@ -2345,7 +2348,7 @@ def qdump__QScriptValue(d, value):
#d.putEmptyValue() #d.putEmptyValue()
dd = value['d_ptr']['d'] dd = value['d_ptr']['d']
ns = d.qtNamespace() ns = d.qtNamespace()
if dd.integer() == 0: if dd.pointer() == 0:
d.putValue('(invalid)') d.putValue('(invalid)')
d.putNumChild(0) d.putNumChild(0)
return return
@@ -2621,9 +2624,9 @@ def qdump__QJsonValue(d, value):
def qdump__QJsonArray(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): 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"] impl = value["_M_impl"]
start = impl["_M_start"] start = impl["_M_start"]
finish = impl["_M_finish"] finish = impl["_M_finish"]
size = bufsize * int((finish["_M_node"].integer() - start["_M_node"].integer()) / d.ptrSize() - 1) size = bufsize * ((finish["_M_node"].pointer() - start["_M_node"].pointer()) // d.ptrSize() - 1)
size += int((finish["_M_cur"].integer() - finish["_M_first"].integer()) / innerSize) size += ((finish["_M_cur"].pointer() - finish["_M_first"].pointer()) // innerSize)
size += int((start["_M_last"].integer() - start["_M_cur"].integer()) / innerSize) size += ((start["_M_last"].pointer() - start["_M_cur"].pointer()) // innerSize)
d.check(0 <= size and size <= 1000 * 1000 * 1000) d.check(0 <= size and size <= 1000 * 1000 * 1000)
d.putItemCount(size) d.putItemCount(size)
if d.isExpanded(): if d.isExpanded():
with Children(d, size, maxNumChild=2000, childType=innerType): with Children(d, size, maxNumChild=2000, childType=innerType):
pcur = start["_M_cur"].integer() pcur = start["_M_cur"].pointer()
pfirst = start["_M_first"] pfirst = start["_M_first"]
plast = start["_M_last"].integer() plast = start["_M_last"].pointer()
pnode = start["_M_node"] pnode = start["_M_node"]
for i in d.childRange(): for i in d.childRange():
d.putSubItem(i, d.createValue(pcur, innerType)) 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)) #warn("NEWNODE: 0x%x %s" % (newnode.pointer(), newnode))
pnode = newnode pnode = newnode
#warn("PNODE 2: 0x%x %s" % (pnode.pointer(), pnode)) #warn("PNODE 2: 0x%x %s" % (pnode.pointer(), pnode))
pfirst = newnode.dereference().integer() pfirst = newnode.dereference().pointer()
plast = pfirst + bufsize * d.ptrSize() plast = pfirst + bufsize * d.ptrSize()
pcur = pfirst pcur = pfirst
@@ -237,7 +237,6 @@ def qdump__std__map(d, value):
if d.isExpanded(): if d.isExpanded():
pairType = value.type[3][0] pairType = value.type[3][0]
pairPointer = pairType.pointer()
with PairedChildren(d, size, pairType=pairType, maxNumChild=1000): with PairedChildren(d, size, pairType=pairType, maxNumChild=1000):
node = value["_M_t"]["_M_impl"]["_M_header"]["_M_left"] node = value["_M_t"]["_M_impl"]["_M_header"]["_M_left"]
nodeSize = node.dereference().type.size() nodeSize = node.dereference().type.size()
@@ -245,10 +244,10 @@ def qdump__std__map(d, value):
for i in d.childRange(): for i in d.childRange():
(pad1, key, pad2, value) = d.split(typeCode, node.pointer() + nodeSize) (pad1, key, pad2, value) = d.split(typeCode, node.pointer() + nodeSize)
d.putPairItem(i, (key, value)) d.putPairItem(i, (key, value))
if node["_M_right"].integer() == 0: if node["_M_right"].pointer() == 0:
parent = node["_M_parent"] parent = node["_M_parent"]
while True: while True:
if node.integer() != parent["_M_right"].integer(): if node.pointer() != parent["_M_right"].pointer():
break break
node = parent node = parent
parent = parent["_M_parent"] parent = parent["_M_parent"]
@@ -257,7 +256,7 @@ def qdump__std__map(d, value):
else: else:
node = node["_M_right"] node = node["_M_right"]
while True: while True:
if node["_M_left"].integer() == 0: if node["_M_left"].pointer() == 0:
break break
node = node["_M_left"] node = node["_M_left"]
@@ -271,13 +270,13 @@ def qdump_std__map__helper(d, size, value):
for i in d.childRange(): for i in d.childRange():
pair = node.cast(nodeType).dereference()['_Myval'] pair = node.cast(nodeType).dereference()['_Myval']
d.putPairItem(i, pair) d.putPairItem(i, pair)
if node['_Right']['_Isnil'].integer() == 0: if node['_Right']['_Isnil'].pointer() == 0:
node = node['_Right'] node = node['_Right']
while node['_Left']['_Isnil'].integer() == 0: while node['_Left']['_Isnil'].pointer() == 0:
node = node['_Left'] node = node['_Left']
else: else:
parent = node['_Parent'] parent = node['_Parent']
while node and parent['_Right']['_Isnil'].integer() == 0: while node and parent['_Right']['_Isnil'].pointer() == 0:
node = parent node = parent
parent = parent['_Parent'] parent = parent['_Parent']
if node['_Right'] != parent: if node['_Right'] != parent:
@@ -377,7 +376,7 @@ def qdump__std__set(d, value):
for i in d.childRange(): for i in d.childRange():
(pad, val) = d.split(typeCode, node.pointer() + nodeSize) (pad, val) = d.split(typeCode, node.pointer() + nodeSize)
d.putSubItem(i, val) d.putSubItem(i, val)
if node["_M_right"].integer() == 0: if node["_M_right"].pointer() == 0:
parent = node["_M_parent"] parent = node["_M_parent"]
while node == parent["_M_right"]: while node == parent["_M_right"]:
node = parent node = parent
@@ -386,7 +385,7 @@ def qdump__std__set(d, value):
node = parent node = parent
else: else:
node = node["_M_right"] node = node["_M_right"]
while node["_M_left"].integer() != 0: while node["_M_left"].pointer() != 0:
node = node["_M_left"] node = node["_M_left"]
def qdump__std__set__QNX(d, value): def qdump__std__set__QNX(d, value):
@@ -419,7 +418,7 @@ def std1TreeMin(d, node):
# return __x; # return __x;
# #
left = node['__left_'] left = node['__left_']
if left.integer(): if left.pointer():
node = left node = left
return node return node
@@ -428,7 +427,7 @@ def std1TreeIsLeftChild(d, node):
# return __x == __x->__parent_->__left_; # return __x == __x->__parent_->__left_;
# #
other = node['__parent_']['__left_'] other = node['__parent_']['__left_']
return node.integer() == other.integer() return node.pointer() == other.pointer()
def std1TreeNext(d, node): def std1TreeNext(d, node):
@@ -440,7 +439,7 @@ def std1TreeNext(d, node):
# return __x->__parent_; # return __x->__parent_;
# #
right = node['__right_'] right = node['__right_']
if right.integer(): if right.pointer():
return std1TreeMin(d, right) return std1TreeMin(d, right)
while not std1TreeIsLeftChild(d, node): while not std1TreeIsLeftChild(d, node):
node = node['__parent_'] node = node['__parent_']
@@ -612,18 +611,18 @@ def qdump__std____1__wstring(d, value):
def qdump__std__shared_ptr(d, value): def qdump__std__shared_ptr(d, value):
if d.isMsvcTarget: if d.isMsvcTarget():
i = value["_Ptr"] i = value["_Ptr"]
else: else:
i = value["_M_ptr"] i = value["_M_ptr"]
if i.integer() == 0: if i.pointer() == 0:
d.putValue("(null)") d.putValue("(null)")
d.putNumChild(0) d.putNumChild(0)
return return
with Children(d): with Children(d):
short = d.putSubItem("data", i) short = d.putSubItem("data", i.dereference())
if d.isMsvcTarget: if d.isMsvcTarget():
refcount = value["_Rep"] refcount = value["_Rep"]
d.putIntItem("usecount", refcount["_Uses"]) d.putIntItem("usecount", refcount["_Uses"])
d.putIntItem("weakcount", refcount["_Weaks"]) d.putIntItem("weakcount", refcount["_Weaks"])
@@ -635,7 +634,7 @@ def qdump__std__shared_ptr(d, value):
def qdump__std____1__shared_ptr(d, value): def qdump__std____1__shared_ptr(d, value):
i = value["__ptr_"] i = value["__ptr_"]
if i.integer() == 0: if i.pointer() == 0:
d.putValue("(null)") d.putValue("(null)")
d.putNumChild(0) d.putNumChild(0)
return return
@@ -660,6 +659,17 @@ def qdump__std____1__unique_ptr(d, value):
qdump__std__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(): def qform__std__unordered_map():
return mapForms() return mapForms()
@@ -733,7 +743,7 @@ def qdump__std__unordered_set(d, value):
d.putItemCount(size) d.putItemCount(size)
if d.isExpanded(): if d.isExpanded():
p = start.integer() p = start.pointer()
valueType = value.type[0] valueType = value.type[0]
with Children(d, size, childType=valueType): with Children(d, size, childType=valueType):
ptrSize = d.ptrSize() ptrSize = d.ptrSize()
@@ -974,10 +984,10 @@ def qdump____gnu_cxx__hash_set(d, value):
bucketFinish = buckets["_M_finish"] bucketFinish = buckets["_M_finish"]
p = bucketStart p = bucketStart
itemCount = 0 itemCount = 0
for i in xrange(int((bucketFinish.integer() - bucketStart.integer()) / d.ptrSize())): for i in xrange((bucketFinish.pointer() - bucketStart.pointer()) // d.ptrSize()):
if p.dereference().integer(): if p.dereference().pointer():
cur = p.dereference() cur = p.dereference()
while cur.integer(): while cur.pointer():
d.putSubItem(itemCount, cur["_M_val"]) d.putSubItem(itemCount, cur["_M_val"])
cur = cur["_M_next"] cur = cur["_M_next"]
itemCount += 1 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) 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) QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, const QByteArray &importCode, QQmlContext *context)

View File

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

View File

@@ -1,4 +1,4 @@
project(%{ProjectName})
cmake_minimum_required(VERSION 2.8) 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) 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 TEMPLATE = lib
TARGET = %ProjectName% TARGET = %ProjectName%
QT += qml quick QT += qml quick
CONFIG += qt plugin c++11 CONFIG += plugin c++11
TARGET = $$qtLibraryTarget($$TARGET) TARGET = $$qtLibraryTarget($$TARGET)
uri = %Uri% uri = %Uri%

View File

@@ -242,5 +242,5 @@ IconOverlayCppSource=:/cppeditor/images/dark_qt_cpp.png
IconOverlayPrf=:/qtsupport/images/dark_qt_project.png IconOverlayPrf=:/qtsupport/images/dark_qt_project.png
IconOverlayPri=:/qtsupport/images/dark_qt_project.png IconOverlayPri=:/qtsupport/images/dark_qt_project.png
IconOverlayPro=:/qtsupport/images/dark_qt_project.png IconOverlayPro=:/qtsupport/images/dark_qt_project.png
StandardPixmapFileIcon=:/core/images/dark_fileicon.png StandardPixmapFileIcon=:/utils/images/dark_fileicon.png
StandardPixmapDirIcon=:/core/images/dark_foldericon.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> <source>iOS tool Error %1</source>
<translation>Ошибка %1 утилиты iOS</translation> <translation>Ошибка %1 утилиты iOS</translation>
</message> </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>
<context> <context>
<name>IosDeployStepWidget</name> <name>IosDeployStepWidget</name>
@@ -21336,14 +21368,14 @@ Ids must begin with a lowercase letter.</source>
<name>Nim::NimCompilerBuildStepFactory</name> <name>Nim::NimCompilerBuildStepFactory</name>
<message> <message>
<source>Nim Compiler Build Step</source> <source>Nim Compiler Build Step</source>
<translation type="unfinished">Этап сборки компилятора Nim</translation> <translation>Этап сборки компилятора Nim</translation>
</message> </message>
</context> </context>
<context> <context>
<name>Nim::NimCompilerCleanStep</name> <name>Nim::NimCompilerCleanStep</name>
<message> <message>
<source>Nim Clean Step</source> <source>Nim Clean Step</source>
<translation type="unfinished">Этап очистки компилятора Nim</translation> <translation>Этап очистки компилятора Nim</translation>
</message> </message>
<message> <message>
<source>Build directory &quot;%1&quot; does not exist.</source> <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> <name>NimCompilerBuildStep</name>
<message> <message>
<source>Nim Compiler Build Step</source> <source>Nim Compiler Build Step</source>
<translation type="unfinished">Этап сборки компилятора Nim</translation> <translation>Этап сборки компилятора Nim</translation>
</message> </message>
</context> </context>
<context> <context>
<name>NimCompilerBuildStepConfigWidget</name> <name>NimCompilerBuildStepConfigWidget</name>
<message> <message>
<source>Nim build step</source> <source>Nim build step</source>
<translation type="unfinished">Этап сборки Nim</translation> <translation>Этап сборки Nim</translation>
</message> </message>
</context> </context>
<context> <context>
<name>NimCompilerCleanStepFactory</name> <name>NimCompilerCleanStepFactory</name>
<message> <message>
<source>Nim Compiler Clean Step</source> <source>Nim Compiler Clean Step</source>
<translation type="unfinished">Этап очистки компилятора Nim</translation> <translation>Этап очистки компилятора Nim</translation>
</message> </message>
</context> </context>
<context> <context>
<name>NimCompilerCleanStepWidget</name> <name>NimCompilerCleanStepWidget</name>
<message> <message>
<source>Nim clean step</source> <source>Nim clean step</source>
<translation type="unfinished">Этап очистки Nim</translation> <translation>Этап очистки Nim</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -36642,11 +36674,11 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
</message> </message>
<message> <message>
<source>Remove the automatically inserted character if the trigger is deleted by backspace after the completion.</source> <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>
<message> <message>
<source>Remove automatically inserted text on backspace</source> <source>Remove automatically inserted text on backspace</source>
<translation type="unfinished">Удалять автоматически вставленный текст по бекспейсу</translation> <translation>Удалять автоматически вставленный текст по бекспейсу</translation>
</message> </message>
<message> <message>
<source>Documentation Comments</source> <source>Documentation Comments</source>

View File

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

View File

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

View File

@@ -1252,7 +1252,12 @@ bool Check::visit(BinaryExpression *ast)
bool Check::visit(Block *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 (Node *p = parent()) {
if (!cast<UiScriptBinding *>(p) if (!cast<UiScriptBinding *>(p)

View File

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

View File

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

View File

@@ -14,9 +14,9 @@ msvc {
# Starting from Windows SDK 8, the headers and libs are under 'ProgramFiles (x86)'. # 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'. # The libraries are under 'ProgramFiles'as well, so, check for existence of 'inc'.
# 32bit qmake: # 32bit qmake:
!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.0/Debuggers" !exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.0/Debuggers"
!exists($$CDB_PATH):CDB_PATH="$$(ProgramFiles)/Windows Kits/8.1/Debuggers" !exists($$CDB_PATH/inc):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/10/Debuggers"
# 64bit qmake: # 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.0/Debuggers"
!exists($$CDB_PATH/inc):CDB_PATH="$$(ProgramFiles) (x86)/Windows Kits/8.1/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) { switch (node->fileInfo.type) {
case FileTypeRegular: case FileTypeRegular:
case FileTypeOther: case FileTypeOther:
return QIcon(QLatin1String(":/core/images/unknownfile.png")); return QIcon(":/utils/images/unknownfile.png");
case FileTypeDirectory: case FileTypeDirectory:
return QIcon(QLatin1String(":/core/images/dir.png")); return QIcon(":/utils/images/dir.png");
case FileTypeUnknown: 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) { if (index.column() == 1) {

View File

@@ -31,6 +31,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QFuture> #include <QFuture>
#include <QFutureInterface> #include <QFutureInterface>
#include <QFutureWatcher>
#include <QRunnable> #include <QRunnable>
#include <QThread> #include <QThread>
#include <QThreadPool> #include <QThreadPool>
@@ -493,4 +494,58 @@ runAsync(QThreadPool *pool, Function &&function, Args&&... args)
std::forward<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 } // Utils

View File

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

View File

@@ -507,9 +507,12 @@ FileName AndroidConfig::toolPath(const Abi &abi, const QString &ndkToolChainVers
.arg(toolsPrefix(abi))); .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 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); 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)) if (QtSupport::QtKitInformation::qtVersion(a) != QtSupport::QtKitInformation::qtVersion(b))
return false; return false;
ToolChain *atc = ToolChainKitInformation::toolChain(a, ToolChain::Language::Cxx);
ToolChain *btc = ToolChainKitInformation::toolChain(b, ToolChain::Language::Cxx); return matchToolChain(ToolChainKitInformation::toolChain(a, ToolChain::Language::Cxx),
if (atc == btc) ToolChainKitInformation::toolChain(b, ToolChain::Language::Cxx))
return true; && matchToolChain(ToolChainKitInformation::toolChain(a, ToolChain::Language::C),
if (!atc || atc->typeId() != Constants::ANDROID_TOOLCHAIN_ID) ToolChainKitInformation::toolChain(b, ToolChain::Language::C));
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;
} }
void AndroidConfigurations::registerNewToolChains() void AndroidConfigurations::registerNewToolChains()
@@ -1243,32 +1254,13 @@ void AndroidConfigurations::removeOldToolChains()
void AndroidConfigurations::updateAutomaticKitList() void AndroidConfigurations::updateAutomaticKitList()
{ {
QList<AndroidToolChain *> toolchains; const QList<Kit *> existingKits = Utils::filtered(KitManager::kits(), [](const Kit *k) {
if (AndroidConfigurations::currentConfig().automaticKitCreation()) { return k->isAutoDetected() && !k->isSdkProvided()
// having a empty toolchains list will remove all autodetected kits for android && DeviceTypeKitInformation::deviceTypeId(k) == Core::Id(Constants::ANDROID_DEVICE_TYPE);
// 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);
}
}
QList<Kit *> existingKits; // Update code for 3.0 beta, which shipped with a bug for the debugger settings
for (Kit *k : 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
ToolChain *tc = ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx); ToolChain *tc = ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx);
if (tc && Debugger::DebuggerKitInformation::runnable(k).executable != tc->suggestedDebugger().toString()) { if (tc && Debugger::DebuggerKitInformation::runnable(k).executable != tc->suggestedDebugger().toString()) {
Debugger::DebuggerItem debugger; Debugger::DebuggerItem debugger;
@@ -1281,14 +1273,15 @@ void AndroidConfigurations::updateAutomaticKitList()
QVariant id = Debugger::DebuggerItemManager::registerDebugger(debugger); QVariant id = Debugger::DebuggerItemManager::registerDebugger(debugger);
Debugger::DebuggerKitInformation::setDebugger(k, id); Debugger::DebuggerKitInformation::setDebugger(k, id);
} }
existingKits << k;
} }
QHash<Abi, QList<QtSupport::BaseQtVersion *> > qtVersionsForArch; QHash<Abi, QList<const QtSupport::BaseQtVersion *> > qtVersionsForArch;
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) { const QList<QtSupport::BaseQtVersion *> qtVersions
if (qtVersion->type() != QLatin1String(Constants::ANDROIDQT)) = Utils::filtered(QtSupport::QtVersionManager::unsortedVersions(), [](const QtSupport::BaseQtVersion *v) {
continue; return v->type() == Constants::ANDROIDQT;
QList<Abi> qtAbis = qtVersion->qtAbis(); });
for (const QtSupport::BaseQtVersion *qtVersion : qtVersions) {
const QList<Abi> qtAbis = qtVersion->qtAbis();
if (qtAbis.empty()) if (qtAbis.empty())
continue; continue;
qtVersionsForArch[qtAbis.first()].append(qtVersion); qtVersionsForArch[qtAbis.first()].append(qtVersion);
@@ -1298,22 +1291,36 @@ void AndroidConfigurations::updateAutomaticKitList()
IDevice::ConstPtr device = dm->find(Core::Id(Constants::ANDROID_DEVICE_ID)); IDevice::ConstPtr device = dm->find(Core::Id(Constants::ANDROID_DEVICE_ID));
if (device.isNull()) { if (device.isNull()) {
// no device, means no sdk path // no device, means no sdk path
foreach (Kit *k, existingKits) for (Kit *k : existingKits)
KitManager::deregisterKit(k); KitManager::deregisterKit(k);
return; return;
} }
// register new kits // register new kits
QList<Kit *> newKits; QList<Kit *> newKits;
foreach (AndroidToolChain *tc, toolchains) { const QList<ToolChain *> tmp = Utils::filtered(ToolChainManager::toolChains(), [](ToolChain *tc) {
if (tc->isSecondaryToolChain()) 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; continue;
QList<QtSupport::BaseQtVersion *> qtVersions = qtVersionsForArch.value(tc->targetAbi()); const QList<AndroidToolChain *> allLanguages = Utils::filtered(toolchains,
foreach (QtSupport::BaseQtVersion *qt, qtVersions) { [tc](AndroidToolChain *otherTc) {
return tc->targetAbi() == otherTc->targetAbi();
});
for (const QtSupport::BaseQtVersion *qt : qtVersionsForArch.value(tc->targetAbi())) {
Kit *newKit = new Kit; Kit *newKit = new Kit;
newKit->setAutoDetected(true); newKit->setAutoDetected(true);
newKit->setAutoDetectionSource("AndroidConfiguration");
DeviceTypeKitInformation::setDeviceTypeId(newKit, Core::Id(Constants::ANDROID_DEVICE_TYPE)); 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); QtSupport::QtKitInformation::setQtVersion(newKit, qt);
DeviceKitInformation::setDevice(newKit, device); DeviceKitInformation::setDevice(newKit, device);
@@ -1329,48 +1336,25 @@ void AndroidConfigurations::updateAutomaticKitList()
AndroidGdbServerKitInformation::setGdbSever(newKit, tc->suggestedGdbServer()); AndroidGdbServerKitInformation::setGdbSever(newKit, tc->suggestedGdbServer());
newKit->makeSticky(); 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; newKits << newKit;
} }
} }
for (int i = existingKits.count() - 1; i >= 0; --i) { QSet<const Kit *> rediscoveredExistingKits;
Kit *existingKit = existingKits.at(i); for (Kit *newKit : newKits) {
for (int j = 0; j < newKits.count(); ++j) { Kit *existingKit = Utils::findOrDefault(existingKits, [newKit](const Kit *k) { return matchKits(newKit, k); });
Kit *newKit = newKits.at(j); if (existingKit) {
if (equalKits(existingKit, newKit)) { existingKit->copyFrom(newKit);
// Kit is already registered, nothing to do KitManager::deleteKit(newKit);
newKits.removeAt(j); rediscoveredExistingKits.insert(existingKit);
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);
} else { } 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() bool AndroidConfigurations::force32bitEmulator()

View File

@@ -27,6 +27,8 @@
#include "android_global.h" #include "android_global.h"
#include <projectexplorer/toolchain.h>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
@@ -126,7 +128,9 @@ public:
Utils::FileName emulatorToolPath() const; 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 gdbPath(const ProjectExplorer::Abi &abi, const QString &ndkToolChainVersion) const;
Utils::FileName keytoolPath() 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 // Check for a gdb with a broken python
QStringList gdbPaths; QStringList gdbPaths;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) { foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
if (ati.language == ProjectExplorer::ToolChain::Language::C)
continue;
// we only check the arm gdbs, that's indicative enough // we only check the arm gdbs, that's indicative enough
if (ati.abi.architecture() != ProjectExplorer::Abi::ArmArchitecture) if (ati.abi.architecture() != ProjectExplorer::Abi::ArmArchitecture)
continue; continue;
@@ -329,8 +331,10 @@ void AndroidSettingsWidget::check(AndroidSettingsWidget::Mode mode)
// See if we have qt versions for those toolchains // See if we have qt versions for those toolchains
QSet<ProjectExplorer::Abi> toolchainsForAbi; QSet<ProjectExplorer::Abi> toolchainsForAbi;
foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) foreach (const AndroidToolChainFactory::AndroidToolChainInformation &ati, compilerPaths) {
toolchainsForAbi.insert(ati.abi); if (ati.language == ProjectExplorer::ToolChain::Language::Cxx)
toolchainsForAbi.insert(ati.abi);
}
QSet<ProjectExplorer::Abi> qtVersionsForAbi; QSet<ProjectExplorer::Abi> qtVersionsForAbi;
foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) { foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::unsortedVersions()) {
@@ -496,16 +500,6 @@ void AndroidSettingsWidget::saveSettings()
AndroidConfigurations::setConfig(m_androidConfig); 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() void AndroidSettingsWidget::sdkLocationEditingFinished()
{ {
m_androidConfig.setSdkLocation(Utils::FileName::fromUserInput(m_ui->SDKLocationPathChooser->rawPath())); 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); int idx = versionRegExp.indexIn(fileName);
if (idx == -1) if (idx == -1)
continue; continue;
AndroidToolChainInformation ati; for (const ToolChain::Language lang : { ToolChain::Language::Cxx, ToolChain::Language::C }) {
ati.version = fileName.mid(idx + 1); AndroidToolChainInformation ati;
QString platform = fileName.left(idx); ati.language = lang;
ati.abi = AndroidConfig::abiForToolChainPrefix(platform); ati.version = fileName.mid(idx + 1);
if (ati.abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported QString platform = fileName.left(idx);
continue; ati.abi = AndroidConfig::abiForToolChainPrefix(platform);
// AndroidToolChain *tc = new AndroidToolChain(arch, version, true); if (ati.abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
ati.compilerCommand = AndroidConfigurations::currentConfig().gccPath(ati.abi, ati.version); continue;
// tc->setCompilerCommand(compilerPath); ati.compilerCommand = AndroidConfigurations::currentConfig().gccPath(ati.abi, lang, ati.version);
result.append(ati); result.append(ati);
}
} }
return result; return result;
} }
@@ -353,19 +354,22 @@ bool AndroidToolChainFactory::versionCompareLess(const QList<int> &a, const QLis
return false; return false;
} }
bool AndroidToolChainFactory::versionCompareLess(AndroidToolChain *atc, AndroidToolChain *btc) bool AndroidToolChainFactory::versionCompareLess(QList<AndroidToolChain *> atc,
QList<AndroidToolChain *> btc)
{ {
QList<int> a = versionNumberFromString(atc->ndkToolChainVersion()); const QList<int> a = versionNumberFromString(atc.at(0)->ndkToolChainVersion());
QList<int> b = versionNumberFromString(btc->ndkToolChainVersion()); const QList<int> b = versionNumberFromString(btc.at(0)->ndkToolChainVersion());
return versionCompareLess(a, b); 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 *>( return static_cast<AndroidToolChain *>(
Utils::findOrDefault(alreadyKnown, [compilerPath](ToolChain *tc) { Utils::findOrDefault(alreadyKnown, [compilerPath, lang](ToolChain *tc) {
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
&& tc->language() == lang
&& tc->compilerCommand() == compilerPath; && tc->compilerCommand() == compilerPath;
})); }));
} }
@@ -382,7 +386,7 @@ AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
FileName path = ndkPath; FileName path = ndkPath;
QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(), QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
QStringList() << QLatin1String("*"), QDir::Dirs); QStringList() << QLatin1String("*"), QDir::Dirs);
QHash<Abi, AndroidToolChain *> newestToolChainForArch; QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;
while (it.hasNext()) { while (it.hasNext()) {
const QString &fileName = FileName::fromString(it.next()).fileName(); const QString &fileName = FileName::fromString(it.next()).fileName();
@@ -394,26 +398,30 @@ AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
Abi abi = AndroidConfig::abiForToolChainPrefix(platform); Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
continue; 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); AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
if (!tc) { if (!tc) {
tc = new AndroidToolChain(abi, version, ToolChain::Language::Cxx, tc = new AndroidToolChain(abi, version, lang,
ToolChain::AutoDetection); ToolChain::AutoDetection);
tc->resetToolChain(compilerPath); tc->resetToolChain(compilerPath);
}
result.append(tc);
toolChainBundle.append(tc);
} }
result.append(tc);
auto it = newestToolChainForArch.constFind(abi); auto it = newestToolChainForArch.constFind(abi);
if (it == newestToolChainForArch.constEnd()) if (it == newestToolChainForArch.constEnd())
newestToolChainForArch.insert(abi, tc); newestToolChainForArch.insert(abi, toolChainBundle);
else if (versionCompareLess(it.value(), tc)) else if (versionCompareLess(it.value(), toolChainBundle))
newestToolChainForArch[abi] = tc; newestToolChainForArch[abi] = toolChainBundle;
} }
foreach (ToolChain *tc, result) { foreach (ToolChain *tc, result) {
AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc); AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
atc->setSecondaryToolChain(newestToolChainForArch.value(atc->targetAbi()) != atc); atc->setSecondaryToolChain(!newestToolChainForArch.value(atc->targetAbi()).contains(atc));
} }
return result; return result;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,17 +44,12 @@ ConfigModel::ConfigModel(QObject *parent) : QAbstractTableModel(parent)
int ConfigModel::rowCount(const QModelIndex &parent) const int ConfigModel::rowCount(const QModelIndex &parent) const
{ {
QTC_ASSERT(parent.model() == nullptr || parent.model() == this, return 0); return parent.isValid() ? 0 : m_configuration.count();
if (parent.isValid())
return 0;
return m_configuration.count();
} }
int ConfigModel::columnCount(const QModelIndex &parent) const int ConfigModel::columnCount(const QModelIndex &parent) const
{ {
QTC_ASSERT(!parent.isValid(), return 0); return parent.isValid() ? 0 : 3;
QTC_ASSERT(parent.model() == nullptr, return 0);
return 3;
} }
Qt::ItemFlags ConfigModel::flags(const QModelIndex &index) const 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) { if (standardIcon == QStyle::SP_ComputerIcon) {
// Ubuntu has in some versions a 16x16 icon, see QTCREATORBUG-12832 // Ubuntu has in some versions a 16x16 icon, see QTCREATORBUG-12832
const QList<QSize> &sizes = icon.availableSizes(); const QList<QSize> &sizes = icon.availableSizes();
if (Utils::allOf(sizes, [](const QSize &size) { return size.width() < 32;})) { if (Utils::allOf(sizes, [](const QSize &size) { return size.width() < 32;}))
icon = QIcon(QLatin1String(":/core/images/Desktop.png")); icon = QIcon(":/utils/images/Desktop.png");
}
} }
return icon; return icon;
} }

View File

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

View File

@@ -771,6 +771,66 @@ void CppEditorPlugin::test_quickfix_data()
"}\n" "}\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: // Checks:
// 1. Setter: Setter is a static function. // 1. Setter: Setter is a static function.
// 2. Getter: Getter is a static, non const function. // 2. Getter: Getter is a static, non const function.

View File

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

View File

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

View File

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

View File

@@ -64,6 +64,16 @@ static bool checkForTimeout(const std::chrono::time_point< std::chrono::high_res
return timedOut; 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 { class SimulatorControlPrivate :QObject {
Q_OBJECT Q_OBJECT
private: private:
@@ -79,7 +89,6 @@ private:
SimulatorControlPrivate(QObject *parent = nullptr); SimulatorControlPrivate(QObject *parent = nullptr);
~SimulatorControlPrivate(); ~SimulatorControlPrivate();
QByteArray runSimCtlCommand(QStringList args) const;
SimDeviceInfo deviceInfo(const QString &simUdid) const; SimDeviceInfo deviceInfo(const QString &simUdid) const;
bool runCommand(QString command, const QStringList &args, QByteArray *output = nullptr); bool runCommand(QString command, const QStringList &args, QByteArray *output = nullptr);
@@ -105,7 +114,7 @@ QList<Ios::Internal::IosDeviceType> SimulatorControl::availableSimulators()
void SimulatorControl::updateAvailableSimulators() 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); QJsonDocument doc = QJsonDocument::fromJson(output);
if (!doc.isNull()) { if (!doc.isNull()) {
QList<IosDeviceType> availableDevices; QList<IosDeviceType> availableDevices;
@@ -185,7 +194,7 @@ bool SimulatorControl::installApp(const QString &simUdid, const Utils::FileName
{ {
bool installed = false; bool installed = false;
if (isSimulatorRunning(simUdid)) { if (isSimulatorRunning(simUdid)) {
commandOutput = d->runSimCtlCommand(QStringList() << QStringLiteral("install") << simUdid << bundlePath.toString()); commandOutput = runSimCtlCommand(QStringList() << QStringLiteral("install") << simUdid << bundlePath.toString());
installed = commandOutput.isEmpty(); installed = commandOutput.isEmpty();
} else { } else {
commandOutput = "Simulator device not running."; commandOutput = "Simulator device not running.";
@@ -199,7 +208,7 @@ qint64 SimulatorControl::launchApp(const QString &simUdid, const QString &bundle
pId = -1; pId = -1;
if (!bundleIdentifier.isEmpty() && isSimulatorRunning(simUdid)) { if (!bundleIdentifier.isEmpty() && isSimulatorRunning(simUdid)) {
const QStringList args({QStringLiteral("launch"), simUdid , bundleIdentifier}); 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(); const QByteArray pIdStr = output.trimmed().split(' ').last().trimmed();
bool validInt = false; bool validInt = false;
pId = pIdStr.toLongLong(&validInt); 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. // 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. // Use SimulatorControl::waitForProcessSpawn to be sure.
QProcess *SimulatorControl::spawnAppProcess(const QString &simUdid, const Utils::FileName &bundlePath, qint64 &pId, bool waitForDebugger, const QStringList &extraArgs) 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)) { if (isSimulatorRunning(simUdid)) {
QString bundleId = bundleIdentifier(bundlePath); QString bundleId = bundleIdentifier(bundlePath);
QString executableName = bundleExecutable(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()) { if (!appPath.isEmpty() && !executableName.isEmpty()) {
// Spawn the app. The spawned app is started in suspended mode. // Spawn the app. The spawned app is started in suspended mode.
appPath.append('/' + executableName.toLocal8Bit()); appPath.append('/' + executableName.toLocal8Bit());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -202,7 +202,9 @@ bool ToolChain::operator == (const ToolChain &tc) const
return true; return true;
// We ignore displayname // 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); return new PythonFileNode(FileName::fromString(f), displayName);
}); });
rootProjectNode()->buildTree(fileNodes); rootProjectNode()->buildTree(fileNodes);
emit parsingFinished();
} }
/** /**

View File

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

View File

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

View File

@@ -87,26 +87,25 @@ using namespace Utils;
struct FileTypeDataStorage { struct FileTypeDataStorage {
FileType type; FileType type;
Theme::ImageFile themeImage;
const char *typeName; const char *typeName;
const char *icon; const char *icon;
const char *addFileFilter; const char *addFileFilter;
}; };
static const FileTypeDataStorage fileTypeDataStorage[] = { 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;"}, 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++;" }, 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;" }, 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;" }, 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;" }, 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;" }, 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, "*;" } ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN, "*;" }
}; };
@@ -159,10 +158,7 @@ QmakeNodeStaticData::QmakeNodeStaticData()
const QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize); const QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize);
for (unsigned i = 0 ; i < count; ++i) { for (unsigned i = 0 ; i < count; ++i) {
QIcon overlayIcon; const QIcon overlayIcon(QLatin1String(fileTypeDataStorage[i].icon));
const QString iconFile = creatorTheme()->imageFile(fileTypeDataStorage[i].themeImage,
QString::fromLatin1(fileTypeDataStorage[i].icon));
overlayIcon = QIcon(iconFile);
QIcon folderIcon; QIcon folderIcon;
folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon)); folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFileNode", fileTypeDataStorage[i].typeName); const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFileNode", fileTypeDataStorage[i].typeName);
@@ -171,9 +167,7 @@ QmakeNodeStaticData::QmakeNodeStaticData()
desc, filter, folderIcon)); desc, filter, folderIcon));
} }
// Project icon // Project icon
const QString fileName = creatorTheme()->imageFile(Theme::ProjectFileIcon, const QIcon projectBaseIcon(ProjectExplorer::Constants::FILEOVERLAY_QT);
QLatin1String(ProjectExplorer::Constants::FILEOVERLAY_QT));
const QIcon projectBaseIcon(fileName);
const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon); const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon);
projectIcon.addPixmap(projectPixmap); projectIcon.addPixmap(projectPixmap);
@@ -205,7 +199,6 @@ public:
QtSupport::ProFileReader *readerCumulative; QtSupport::ProFileReader *readerCumulative;
ProFileGlobals *qmakeGlobals; ProFileGlobals *qmakeGlobals;
QMakeVfs *qmakeVfs; QMakeVfs *qmakeVfs;
bool isQt5;
}; };
class PriFileEvalResult class PriFileEvalResult
@@ -244,7 +237,6 @@ public:
TargetInformation targetInformation; TargetInformation targetInformation;
InstallsList installsList; InstallsList installsList;
QHash<QmakeVariable, QStringList> newVarValues; QHash<QmakeVariable, QStringList> newVarValues;
bool isDeployable;
QStringList errors; 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 // 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 // dangerous if we get the folders wrong and enumerate the whole project
// tree multiple times. // tree multiple times.
QStringList dynamicVariables = dynamicVarNames(input.readerExact, input.isQt5); QStringList dynamicVariables = dynamicVarNames(input.readerExact);
foreach (ProFile *includeFileExact, includeFilesExact) foreach (ProFile *includeFileExact, includeFilesExact)
foreach (const QString &dynamicVar, dynamicVariables) foreach (const QString &dynamicVar, dynamicVariables)
result.folders += input.readerExact->values(dynamicVar, includeFileExact); result.folders += input.readerExact->values(dynamicVar, includeFileExact);
@@ -1467,25 +1459,15 @@ QStringList QmakePriFileNode::varNamesForRemoving()
return vars; return vars;
} }
QStringList QmakePriFileNode::dynamicVarNames(QtSupport::ProFileReader *readerExact, QStringList QmakePriFileNode::dynamicVarNames(QtSupport::ProFileReader *reader)
bool isQt5)
{ {
QStringList result; QStringList result;
// Figure out DEPLOYMENT and INSTALLS // Figure out INSTALLS (and DEPLOYMENT, as it's aliased)
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);
}
const QString installs = QLatin1String("INSTALLS"); const QString installs = QLatin1String("INSTALLS");
const QString files = QLatin1String(".files"); const QString files = QLatin1String(".files");
listOfVars = readerExact->values(installs); foreach (const QString &var, reader->values(installs))
foreach (const QString &var, listOfVars) {
result << (var + files); result << (var + files);
}
result.removeDuplicates(); result.removeDuplicates();
return result; return result;
} }
@@ -1631,11 +1613,6 @@ QByteArray QmakeProFileNode::cxxDefines() const
return result; return result;
} }
bool QmakeProFileNode::isDeployable() const
{
return m_isDeployable;
}
/*! /*!
\class QmakeProFileNode \class QmakeProFileNode
Implements abstract ProjectNode class Implements abstract ProjectNode class
@@ -1798,10 +1775,6 @@ EvalInput QmakeProFileNode::evalInput() const
input.buildDirectory = buildDir(); input.buildDirectory = buildDir();
input.readerExact = m_readerExact; input.readerExact = m_readerExact;
input.readerCumulative = m_readerCumulative; 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.qmakeGlobals = m_project->qmakeGlobals();
input.qmakeVfs = m_project->qmakeVfs(); input.qmakeVfs = m_project->qmakeVfs();
return input; return input;
@@ -2012,19 +1985,6 @@ EvalResult *QmakeProFileNode::evaluate(const EvalInput &input)
result->newVarValues[QmakeCc] = input.readerExact->values("QMAKE_CC"); result->newVarValues[QmakeCc] = input.readerExact->values("QMAKE_CC");
result->newVarValues[QmakeCxx] = input.readerExact->values("QMAKE_CXX"); 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) if (readerBuildPass && readerBuildPass != input.readerExact)
delete readerBuildPass; delete readerBuildPass;
} }
@@ -2274,7 +2234,6 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
m_subProjectsNotToDeploy = result->subProjectsNotToDeploy; m_subProjectsNotToDeploy = result->subProjectsNotToDeploy;
m_installsList = result->installsList; m_installsList = result->installsList;
m_isDeployable = result->isDeployable;
if (m_varValues != result->newVarValues) if (m_varValues != result->newVarValues)
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 varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact);
static QStringList varNamesForRemoving(); static QStringList varNamesForRemoving();
static QString varNameForAdding(const QString &mimeType); 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> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files);
static QSet<Utils::FileName> filterFilesRecursiveEnumerata(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 objectExtension() const;
QString objectsDirectory() const; QString objectsDirectory() const;
QByteArray cxxDefines() const; QByteArray cxxDefines() const;
bool isDeployable() const;
enum AsyncUpdateDelay { ParseNow, ParseLater }; enum AsyncUpdateDelay { ParseNow, ParseLater };
void scheduleUpdate(AsyncUpdateDelay delay); 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 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); static InstallsList installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir);
bool m_isDeployable = false;
bool m_validParse = false; bool m_validParse = false;
bool m_parseInProgress = true; bool m_parseInProgress = true;

View File

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

View File

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

View File

@@ -223,7 +223,7 @@ static bool idContainsWrongLetter(const QString& id)
bool ModelNode::isValidId(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 bool ModelNode::hasId() const

View File

@@ -198,6 +198,8 @@ void QmlProject::refresh(RefreshOptions options)
QmlJS::Dialect::Qml); QmlJS::Dialect::Qml);
modelManager()->updateProjectInfo(projectInfo, this); modelManager()->updateProjectInfo(projectInfo, this);
emit parsingFinished();
} }
QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const 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) bool containsSubString(const QStringList &list, const QString &substr, Qt::CaseSensitivity cs)
{ {
return Utils::contains(list, [&substr, &cs](const QString &elem) { 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 description = sourceModel()->index(sourceRow, 0, sourceParent).data(Description).toString();
const QString name = sourceModel()->index(sourceRow, 0, sourceParent).data(Name).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; bool wordMatch = false;
wordMatch |= (bool)name.contains(subString, Qt::CaseInsensitive); wordMatch |= (bool)name.contains(subString, Qt::CaseInsensitive);
if (wordMatch) if (wordMatch)
@@ -835,6 +843,14 @@ void ExamplesListModelFilter::filterForExampleSet(int index)
m_sourceModel->selectExampleSet(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) void ExamplesListModelFilter::setShowTutorialsOnly(bool showTutorialsOnly)
{ {
m_showTutorialsOnly = 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 tags;
QStringList searchTerms; QStringList searchTerms;
SearchStringLexer lex(arg); SearchStringLexer lex(arg);
@@ -1007,10 +1028,15 @@ void ExamplesListModelFilter::parseSearchString(const QString &arg)
} }
} }
setSearchStrings(searchTerms); setFilterStrings(searchTerms);
setFilterTags(tags); setFilterTags(tags);
delayedUpdateFilter(); delayedUpdateFilter();
} }
QString ExamplesListModelFilter::searchString() const
{
return m_searchString;
}
} // namespace Internal } // namespace Internal
} // namespace QtSupport } // namespace QtSupport

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -44,6 +44,7 @@ private slots:
void threadPriority(); void threadPriority();
void runAsyncNoFutureInterface(); void runAsyncNoFutureInterface();
void crefFunction(); void crefFunction();
void onResultReady();
}; };
void report3(QFutureInterface<int> &fi) void report3(QFutureInterface<int> &fi)
@@ -557,6 +558,64 @@ void tst_RunExtensions::crefFunction()
QCOMPARE(value, true); 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) QTEST_MAIN(tst_RunExtensions)
#include "tst_runextensions.moc" #include "tst_runextensions.moc"