Merge remote-tracking branch 'origin/4.2'
Conflicts: qbs/modules/qtc/qtc.qbs qtcreator.pri src/shared/qbs Change-Id: I5050baa31f4a892d00cd6f7e088d1b597921474d
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
BIN
doc/images/navigator.png
Normal file
|
After Width: | Height: | Size: 434 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 36 KiB |
BIN
doc/images/statistics.png
Normal file
|
After Width: | Height: | Size: 258 B |
@@ -236,7 +236,7 @@
|
||||
|
||||
To enable the debugger to step into the code and display the source code
|
||||
when using a copy of the source tree at a location different from the one
|
||||
at which the libraries where built, map the source paths to target paths:
|
||||
at which the libraries were built, map the source paths to target paths:
|
||||
|
||||
\list 1
|
||||
|
||||
|
||||
@@ -160,9 +160,15 @@
|
||||
{Options to Request or Suppress Warnings} or the GCC or Clang
|
||||
manual pages.
|
||||
|
||||
\li To have Clang process pre-compiled headers, deselect the
|
||||
\li To process pre-compiled headers, deselect the
|
||||
\uicontrol {Ignore pre-compiled headers} check box.
|
||||
|
||||
\li To avoid out-of-memory crashes caused by indexing huge source files
|
||||
that are typically auto-generated by scripts or code, the size of
|
||||
files to index is limited to 5MB by default. To adjust the limit,
|
||||
edit the value for the \uicontrol {Do not index files greater than}
|
||||
check box. To index all files, deselect the check box.
|
||||
|
||||
\endlist
|
||||
|
||||
*/
|
||||
|
||||
@@ -83,8 +83,7 @@
|
||||
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.
|
||||
show in \uicontrol {Context lines}.
|
||||
|
||||
By default, the horizontal scroll bars in the left and right pane are
|
||||
synchronized. To use them independently of each other, select the
|
||||
|
||||
@@ -91,10 +91,13 @@
|
||||
To keep the selections in the diagram and the \uicontrol Structure view
|
||||
synchronized, select \uicontrol {Keep Synchronized}.
|
||||
|
||||
To zoom into diagrams, press \key Ctrl++ or press \key Ctrl and roll the
|
||||
mouse wheel up. To zoom out of diagrams, press \key Ctrl+- or press
|
||||
\key Ctrl and roll the mouse wheel down. To reset the diagram size to 100%,
|
||||
select \key Ctrl+0.
|
||||
To zoom into diagrams, select \uicontrol Tools > \uicontrol {Model Editor} >
|
||||
\uicontrol {Zoom In}, press \key Ctrl++, or press \key Ctrl and roll the
|
||||
mouse wheel up. To zoom out of diagrams, select \uicontrol Tools >
|
||||
\uicontrol {Model Editor} > \uicontrol {Zoom Out}, press \key Ctrl+-, or
|
||||
press \key Ctrl and roll the mouse wheel down. To reset the diagram size to
|
||||
100%, select \uicontrol Tools > \uicontrol {Model Editor} > \uicontrol
|
||||
{Reset Zoom} or press \key Ctrl+0.
|
||||
|
||||
To print diagrams, press \key Ctrl+C when no elements are selected in
|
||||
the editor to copy all elements to the clipboard by using 300 dpi. Then
|
||||
|
||||
@@ -128,6 +128,9 @@
|
||||
\li Select \uicontrol {Show command lines} to print actual command lines
|
||||
to the compile output pane instead of high-level descriptions.
|
||||
|
||||
\li Select \uicontrol {Force probes} to force re-execution of the
|
||||
configure scripts of \l{https://doc.qt.io/qbs/probe-item.html}{Probes}.
|
||||
|
||||
\li Select \uicontrol {Install} to copy artifacts to their install location
|
||||
after building them. This option is enabled by default.
|
||||
|
||||
|
||||
@@ -41,23 +41,29 @@
|
||||
build and run settings for the development targets might be set up
|
||||
automatically in \QC.
|
||||
|
||||
To view and modify the settings for currently open projects, switch to the
|
||||
\uicontrol Projects mode by pressing \key Ctrl+5.
|
||||
When you open a project for the first time, the
|
||||
\uicontrol {Configure Projects} view is displayed to let you select a set of
|
||||
\l{glossary-buildandrun-kit}{kits} that you want to use to build and run
|
||||
your project. At least one kit must be active for you to be able to build
|
||||
and run the project. For more information about selecting the initial kit,
|
||||
see \l{Opening Projects}.
|
||||
|
||||
You can select build and run \l{glossary-buildandrun-kit}{kits} for the
|
||||
open projects and use the \uicontrol Build menu commands to build, deploy, and
|
||||
run projects.
|
||||
To maintain the list of active kits for a currently open project, switch to
|
||||
the \uicontrol Projects mode by pressing \key Ctrl+5.
|
||||
|
||||
\section1 Selecting Kits
|
||||
\section1 Activating Kits for a Project
|
||||
|
||||
All kits compatible with your project are listed in the
|
||||
\uicontrol {Build & Run} section of the sidebar. To activate one or more
|
||||
disabled kits, click them.
|
||||
|
||||
\image qtcreator-project-kits.png
|
||||
|
||||
To enable kits for the project, click them in \uicontrol {Build & Run}. The
|
||||
list displays kits that are configured in \uicontrol Tools >
|
||||
The list displays kits that are configured in \uicontrol Tools >
|
||||
\uicontrol Options > \uicontrol {Build & Run} > \uicontrol Kits. To modify
|
||||
kit configuration or to add kits to the list, select
|
||||
\uicontrol {Manage Kits} in the context menu. For more information about
|
||||
managing kits, see \l{Adding Kits}.
|
||||
kit configuration or to add kits to the list, right-click the sidebar to
|
||||
open a context-menu, and then select \uicontrol {Manage Kits}. For more
|
||||
information about managing kits, see \l{Adding Kits}.
|
||||
|
||||
Each kit consists of a set of values that define one environment, such as a
|
||||
device, compiler, and Qt version. For more information, see
|
||||
@@ -66,33 +72,22 @@
|
||||
To copy the build and run settings for a kit to another kit, select
|
||||
\uicontrol {Copy Steps from Other Kit} in the context menu.
|
||||
|
||||
To disable a kit for the project, select \uicontrol {Disable Kit for Project}
|
||||
in the context menu.
|
||||
To deactivate a kit, select \uicontrol {Disable Kit for Project} in the
|
||||
context menu.
|
||||
|
||||
\note Deactivating a kit removes all custom build and run settings for the
|
||||
kit.
|
||||
|
||||
To import an existing build for the project, select
|
||||
\uicontrol {Import Existing Build} in the context menu.
|
||||
|
||||
\section1 Specifying Settings
|
||||
|
||||
The \uicontrol Projects mode displays one of the following views:
|
||||
To specify build or run settings for a kit, select \uicontrol Build or
|
||||
\uicontrol Run below the kit. For more information, see
|
||||
\l{Specifying Build Settings} and \l{Specifying Run Settings}.
|
||||
|
||||
\list
|
||||
|
||||
\li \uicontrol {Build & Run} settings for each configured kit:
|
||||
|
||||
\list
|
||||
|
||||
\li \l{Specifying Build Settings}{Build}
|
||||
|
||||
\li \l{Specifying Run Settings}{Run}
|
||||
|
||||
\endlist
|
||||
|
||||
\note If you have not configured the project for building, the
|
||||
\uicontrol {Build & Run} view is replaced by the
|
||||
\l{Opening Projects}{Configure Projects} view.
|
||||
|
||||
\li \uicontrol {Project Settings} for each project:
|
||||
In addition, you can modify the following global settings for each project:
|
||||
|
||||
\list
|
||||
|
||||
@@ -102,14 +97,14 @@
|
||||
|
||||
\li \l{Specifying Dependencies}{Dependencies}
|
||||
|
||||
\li \l{Parsing C++ Files with the Clang Code Model} (experimental)
|
||||
\li \l{Parsing C++ Files with the Clang Code Model}
|
||||
{Clang Code Model} (experimental)
|
||||
|
||||
\li \l{Using Clang Static Analyzer}{Clang Static Analyzer}
|
||||
|
||||
\li \l{To-Do Entries}{To-Do} (experimental)
|
||||
|
||||
\endlist
|
||||
\endlist
|
||||
|
||||
If you have multiple projects open in \QC, select the project to configure
|
||||
in the list of projects.
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
\li \l{Using Layouts}
|
||||
|
||||
\li \l{Using Split Views}
|
||||
\li \l{Organizing Items}
|
||||
|
||||
\endlist
|
||||
|
||||
@@ -269,12 +269,29 @@
|
||||
\uicontrol Layout > \uicontrol {Fill Width} in the context menu. To make the item as
|
||||
high as possible, select \uicontrol {Fill Height}.
|
||||
|
||||
\section2 Using Split Views
|
||||
\section2 Organizing Items
|
||||
|
||||
From Qt 5.1, you can use the SplitView Qt Quick Control to arrange items
|
||||
horizontally or vertically
|
||||
with a draggable splitter between each item.
|
||||
From Qt 5.7, you can use the following \l{Qt Quick Controls 2} types to
|
||||
organize items on screens:
|
||||
|
||||
\list
|
||||
|
||||
\li \l [QtQuickControls2]{Frame} places a logical group of controls
|
||||
within a visual frame.
|
||||
|
||||
\li \l [QtQuickControls2]{GroupBox}{Group Box} is used to lay out a
|
||||
logical group of controls together, within a titled visual frame.
|
||||
|
||||
\li \l [QtQuickControls2]{Label} is a text label with inherited styling
|
||||
and font.
|
||||
|
||||
\li \l [QtQuickControls2]{PageIndicator}{Page Indicator} indicates the
|
||||
currently active page.
|
||||
|
||||
\li \l [QtQuickControls2]{Pane} provides a background matching with the
|
||||
application style and theme.
|
||||
|
||||
\endlist
|
||||
|
||||
\section1 Using States
|
||||
|
||||
@@ -382,62 +399,68 @@
|
||||
|
||||
\endlist
|
||||
|
||||
From Qt 5.1, you can also use the following
|
||||
\l{Qt Quick Controls} to present or receive input from the user:
|
||||
Since Qt 5.7, you can also use the following \l{Qt Quick Controls 2} types
|
||||
to inform users about the progress of the application or to gather input
|
||||
from the user:
|
||||
|
||||
\list
|
||||
|
||||
\li \l{Button} provides a push button that you can associate with an
|
||||
action.
|
||||
\li \l [QtQuickControls2]{BusyIndicator}{Busy Indicator} indicates
|
||||
activity while content is being loaded.
|
||||
|
||||
\li CheckBox provides an option button that can be toggled on
|
||||
(checked) or off (unchecked).
|
||||
\li \l [QtQuickControls2]{Button} provides a push button that you can
|
||||
associate with an action.
|
||||
|
||||
\li ComboBox provides a drop-down list. Add items to the combo box by
|
||||
assigning it a ListModel, or a list of strings to the model
|
||||
property.
|
||||
\li \l [QtQuickControls2]{CheckBox}{Check Box} provides an option button
|
||||
that can be toggled on (checked) or off (unchecked).
|
||||
|
||||
\li GroupBox provides a frame, a title on top, and place for various
|
||||
other controls inside the frame.
|
||||
\li \l [QtQuickControls2]{CheckDelegate}{Check Delegate} presents an
|
||||
item delegate that can be toggled on (checked) or off (unchecked).
|
||||
|
||||
\li \l{Label} provides a text label that follows the font and color scheme
|
||||
of the system.
|
||||
\li \l [QtQuickControls2]{ComboBox}{Combo Box} is a combined button and
|
||||
popup list that is populated by using a data model.
|
||||
|
||||
\li ProgressBar indicates the progress of an operation.
|
||||
\li \l [QtQuickControls2]{Dial} is a circular dial that is rotated to
|
||||
set a value.
|
||||
|
||||
\li RadioButton provides an option button that can be switched on
|
||||
(checked) or off (unchecked).
|
||||
\li \l [QtQuickControls2]{ItemDelegate}{Item Delegate} is a standard
|
||||
view item that can be used in various views and controls.
|
||||
|
||||
\li \l{Slider}
|
||||
{Slider (Horizontal) and Slider (Vertical)} enable the user to move
|
||||
a slider handle along a horizontal or vertical groove and translate
|
||||
the handle's position into a value within the specified range.
|
||||
\li \l [QtQuickControls2]{ProgressBar}{Progress Bar} indicates the
|
||||
progress of an operation.
|
||||
|
||||
\li SpinBox enables the user to specify a value by clicking the up or
|
||||
down buttons, by pressing up or down on the keyboard, or by entering
|
||||
a value in the box.
|
||||
\li \l [QtQuickControls2]{RadioButton}{Radio Button} provides an option
|
||||
button that can be switched on (checked) or off (unchecked).
|
||||
|
||||
\omit
|
||||
Not visible in the item library in 3.2.
|
||||
\li StatusBar contains status information in your application. It
|
||||
does not provide a layout of its own, but requires you to position
|
||||
its contents, for instance by creating a \uicontrol {Row Layout}.
|
||||
\endomit
|
||||
\li \l [QtQuickControls2]{RadioDelegate}{Radio Delegate} presents an
|
||||
item delegate that can be toggled on (checked) or off (unchecked).
|
||||
|
||||
\li TextArea displays multiple lines of editable formatted text.
|
||||
\li \l [QtQuickControls2]{Slider} selects a value by sliding a handle
|
||||
along a track.
|
||||
|
||||
\li TextField displays a single line of editable plain text.
|
||||
\li \l [QtQuickControls2]{SpinBox}{Spin Box} enables the user to specify
|
||||
a value by clicking the up or down buttons, by pressing up or down
|
||||
on the keyboard, or by entering a value in the box.
|
||||
|
||||
\omit
|
||||
Not visible in the item library in 3.2.
|
||||
\li ToolBar provides styling for ToolButton as well as other controls
|
||||
that it can contain. However, it does not provide a layout of its
|
||||
own, but requires you to position its contents, for instance by
|
||||
creating a \uicontrol {Row Layout}.
|
||||
\endomit
|
||||
\li \l [QtQuickControls2]{Switch} is an option button that can be
|
||||
toggled on or off.
|
||||
|
||||
\li ToolButton provides a button that is functionally similar to
|
||||
\uicontrol Button, but that looks more suitable on a \uicontrol {Tool Bar}.
|
||||
\li \l [QtQuickControls2]{TextArea}{Text Area} displays multiple lines
|
||||
of editable formatted text.
|
||||
|
||||
\li \l [QtQuickControls2]{TextField}{Text Field} displays a single line
|
||||
of editable plain text.
|
||||
|
||||
\li \l [QtQuickControls2]{ToolBar}{Tool Bar} is a container of
|
||||
application-wide and context sensitive actions and controls, such as
|
||||
navigation buttons and search fields.
|
||||
|
||||
\li \l [QtQuickControls2]{ToolButton}{Tool Button} is a button
|
||||
that is functionally similar to \uicontrol Button, but provides a
|
||||
look that is more suitable for a \uicontrol {Tool Bar}.
|
||||
|
||||
\li \l [QtQuickControls2]{Tumbler} is a spinnable wheel of items that
|
||||
can be selected.
|
||||
|
||||
\endlist
|
||||
|
||||
|
||||
@@ -65,12 +65,8 @@ def qdump__boost__shared_ptr(d, value):
|
||||
d.check(weakcount >= 0)
|
||||
d.check(weakcount <= usecount)
|
||||
d.check(usecount <= 10*1000*1000)
|
||||
|
||||
with Children(d):
|
||||
short = d.putSubItem("data", d.createValue(px, value.type[0]))
|
||||
d.putIntItem("weakcount", weakcount)
|
||||
d.putIntItem("usecount", usecount)
|
||||
d.putValue(short.value, short.encoding)
|
||||
d.putItem(d.createValue(px, value.type[0]))
|
||||
d.putBetterType(value.type)
|
||||
|
||||
|
||||
def qdump__boost__container__list(d, value):
|
||||
|
||||
@@ -253,6 +253,9 @@ class DumperBase:
|
||||
self.typesReported = {}
|
||||
self.typesToReport = {}
|
||||
self.qtNamespaceToReport = None
|
||||
self.qtCustomEventFunc = 0
|
||||
self.qtCustomEventPltFunc = 0
|
||||
self.qtPropertyFunc = 0
|
||||
self.passExceptions = False
|
||||
self.isTesting = False
|
||||
|
||||
@@ -303,7 +306,7 @@ class DumperBase:
|
||||
self.forceQtNamespace = int(args.get('forcens', '0'))
|
||||
self.passExceptions = int(args.get('passexceptions', '0'))
|
||||
self.isTesting = int(args.get('testing', '0'))
|
||||
self.showQObjectNames = int(args.get('qobjectnames', '0'))
|
||||
self.showQObjectNames = int(args.get('qobjectnames', '1'))
|
||||
self.nativeMixed = int(args.get('nativemixed', '0'))
|
||||
self.autoDerefPointers = int(args.get('autoderef', '0'))
|
||||
self.partialVariable = args.get('partialvar', '')
|
||||
@@ -790,6 +793,13 @@ class DumperBase:
|
||||
self.putField('keyencoded', key.encoding)
|
||||
self.putValue(value.value, value.encoding)
|
||||
|
||||
def putEnumValue(self, value, vals):
|
||||
ival = value.integer()
|
||||
nice = vals.get(ival, None)
|
||||
display = ('%d' % ival) if nice is None else ('%s (%d)' % (nice, ival))
|
||||
self.putValue(display)
|
||||
self.putNumChild(0)
|
||||
|
||||
def putCallItem(self, name, rettype, value, func, *args):
|
||||
with SubItem(self, name):
|
||||
try:
|
||||
@@ -1366,11 +1376,13 @@ class DumperBase:
|
||||
|
||||
def putQObjectNameValue(self, value):
|
||||
try:
|
||||
intSize = 4
|
||||
ptrSize = self.ptrSize()
|
||||
# dd = value['d_ptr']['d'] is just behind the vtable.
|
||||
(vtable, dd) = self.split('pp', value)
|
||||
if not self.couldBeQObjectVTable(vtable):
|
||||
return False
|
||||
|
||||
intSize = 4
|
||||
ptrSize = self.ptrSize()
|
||||
if self.qtVersion() < 0x050000:
|
||||
# Size of QObjectData: 5 pointer + 2 int
|
||||
# - vtable
|
||||
@@ -1421,97 +1433,62 @@ class DumperBase:
|
||||
|
||||
except:
|
||||
# warn('NO QOBJECT: %s' % value.type)
|
||||
pass
|
||||
return False
|
||||
|
||||
def canBePointer(self, p):
|
||||
def couldBePointer(self, p):
|
||||
if self.ptrSize() == 4:
|
||||
return p > 100000 and (p & 0x3 == 0)
|
||||
else:
|
||||
return p > 100000 and (p & 0x7 == 0) and (p < 0x7fffffffffff)
|
||||
|
||||
def canBeVTableEntry(self, p):
|
||||
def couldBeVTableEntry(self, p):
|
||||
if self.ptrSize() == 4:
|
||||
return p > 100000 and (p & 0x1 == 0)
|
||||
else:
|
||||
return p > 100000 and (p & 0x1 == 0) and (p < 0x7fffffffffff)
|
||||
|
||||
def couldBeQObject(self, objectPtr):
|
||||
def couldBeQObjectPointer(self, objectPtr):
|
||||
try:
|
||||
(vtablePtr, dd) = self.split('pp', objectPtr)
|
||||
vtablePtr, dd = self.split('pp', objectPtr)
|
||||
except:
|
||||
self.bump('nostruct-1')
|
||||
return False
|
||||
|
||||
if not self.canBePointer(vtablePtr):
|
||||
self.bump('vtable')
|
||||
return False
|
||||
if not self.canBePointer(dd):
|
||||
self.bump('d_d_ptr')
|
||||
return False
|
||||
|
||||
try:
|
||||
metaObjectFunc, metaCastFunc, metaCallFunc = self.split('ppp', vtablePtr)
|
||||
except:
|
||||
return False
|
||||
|
||||
# The first three entries are in a fairly rigid relationship defined
|
||||
# by the Q_OBJECT macro.
|
||||
if not self.canBeVTableEntry(metaObjectFunc):
|
||||
return False
|
||||
if not self.canBeVTableEntry(metaCastFunc):
|
||||
return False
|
||||
if not self.canBeVTableEntry(metaCallFunc):
|
||||
return False
|
||||
if metaCastFunc < metaObjectFunc or metaCastFunc > metaObjectFunc + 200:
|
||||
# The metaObject implementation is just that:
|
||||
# QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject()
|
||||
# : &staticMetaObject;
|
||||
# That should not exceed 200 bytes. Observed on x86_64 debug 72.
|
||||
return False
|
||||
if metaCallFunc < metaCastFunc or metaCallFunc > metaCastFunc + 200:
|
||||
# if (!_clname) return nullptr;
|
||||
# if (!strcmp(_clname, qt_meta_stringdata_Bar__TestObject.stringdata0))
|
||||
# return static_cast<void*>(const_cast< TestObject*>(this));
|
||||
# return QWidget::qt_metacast(_clname);
|
||||
# That should not exceed 200 bytes. Observed on x86_64 debug 80.
|
||||
return False
|
||||
|
||||
try:
|
||||
(dvtablePtr, qptr, parentPtr, childrenDPtr, flags) \
|
||||
= self.split('ppppI', dd)
|
||||
dvtablePtr, qptr, parentPtr = self.split('ppp', dd)
|
||||
except:
|
||||
self.bump('nostruct-2')
|
||||
return False
|
||||
#warn('STRUCT DD: %s 0x%x' % (self.currentIName, qptr))
|
||||
if not self.canBePointer(dvtablePtr):
|
||||
self.bump('dvtable')
|
||||
#warn('DVT: 0x%x' % dvtablePtr)
|
||||
return False
|
||||
# Check d_ptr.d.q_ptr == objectPtr
|
||||
if qptr != objectPtr:
|
||||
#warn('QPTR: 0x%x 0x%x' % (qptr, objectPtr))
|
||||
self.bump('q_ptr')
|
||||
return False
|
||||
if parentPtr and not self.canBePointer(parentPtr):
|
||||
#warn('PAREN')
|
||||
self.bump('parent')
|
||||
return False
|
||||
if not self.canBePointer(childrenDPtr):
|
||||
#warn('CHILD')
|
||||
self.bump('children')
|
||||
return False
|
||||
#if flags >= 0x80: # Only 7 flags are defined
|
||||
# warn('FLAGS: 0x%x %s' % (flags, self.currentIName))
|
||||
# self.bump('flags')
|
||||
# return False
|
||||
#warn('OK')
|
||||
#if dynMetaObjectPtr and not self.canBePointer(dynMetaObjectPtr):
|
||||
# self.bump('dynmo')
|
||||
# return False
|
||||
|
||||
self.bump('couldBeQObject')
|
||||
return True
|
||||
return self.couldBeQObjectVTable(vtablePtr)
|
||||
|
||||
def couldBeQObjectVTable(self, vtablePtr):
|
||||
try:
|
||||
customEventFunc = self.extractPointer(vtablePtr + 9 * self.ptrSize())
|
||||
except:
|
||||
self.bump('nostruct-3')
|
||||
return False
|
||||
|
||||
return customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc)
|
||||
|
||||
def extractQObjectProperty(objectPtr):
|
||||
vtablePtr = self.extractPointer(objectPtr)
|
||||
metaObjectFunc = self.extractPointer(vtablePtr)
|
||||
cmd = '((void*(*)(void*))0x%x)((void*)0x%x)' % (metaObjectFunc, objectPtr)
|
||||
try:
|
||||
#warn('MO CMD: %s' % cmd)
|
||||
res = self.parseAndEvaluate(cmd)
|
||||
#warn('MO RES: %s' % res)
|
||||
self.bump('successfulMetaObjectCall')
|
||||
return res.pointer()
|
||||
except:
|
||||
self.bump('failedMetaObjectCall')
|
||||
#warn('COULD NOT EXECUTE: %s' % cmd)
|
||||
return 0
|
||||
|
||||
def extractMetaObjectPtr(self, objectPtr, typeobj):
|
||||
""" objectPtr - address of *potential* instance of QObject derived class
|
||||
@@ -1521,7 +1498,7 @@ class DumperBase:
|
||||
self.checkIntType(objectPtr)
|
||||
|
||||
def extractMetaObjectPtrFromAddress():
|
||||
return 0
|
||||
#return 0
|
||||
# FIXME: Calling 'works' but seems to impact memory contents(!)
|
||||
# in relevant places. One symptom is that object name
|
||||
# contents 'vanishes' as the reported size of the string
|
||||
@@ -1535,7 +1512,7 @@ class DumperBase:
|
||||
res = self.parseAndEvaluate(cmd)
|
||||
#warn('MO RES: %s' % res)
|
||||
self.bump('successfulMetaObjectCall')
|
||||
return toInteger(res)
|
||||
return res.pointer()
|
||||
except:
|
||||
self.bump('failedMetaObjectCall')
|
||||
#warn('COULD NOT EXECUTE: %s' % cmd)
|
||||
@@ -1587,7 +1564,8 @@ class DumperBase:
|
||||
# if base is not None and base != someTypeObj: # sanity check
|
||||
# result = extractStaticMetaObjectPtrFromType(base)
|
||||
|
||||
self.knownStaticMetaObjects[someTypeName] = result
|
||||
if result:
|
||||
self.knownStaticMetaObjects[someTypeName] = result
|
||||
return result
|
||||
|
||||
|
||||
@@ -1603,7 +1581,7 @@ class DumperBase:
|
||||
#warn('CACHED RESULT: %s %s 0x%x' % (self.currentIName, typeName, result))
|
||||
return result
|
||||
|
||||
if not self.couldBeQObject(objectPtr):
|
||||
if not self.couldBeQObjectPointer(objectPtr):
|
||||
self.bump('cannotBeQObject')
|
||||
#warn('DOES NOT LOOK LIKE A QOBJECT: %s' % self.currentIName)
|
||||
return 0
|
||||
@@ -1683,8 +1661,11 @@ class DumperBase:
|
||||
self.putNumChild(0)
|
||||
|
||||
# This is called is when a QObject derived class is expanded
|
||||
def putQObjectGuts(self, qobject, metaObjectPtr):
|
||||
self.putQObjectGutsHelper(qobject, qobject.address(), -1, metaObjectPtr, 'QObject')
|
||||
def tryPutQObjectGuts(self, value):
|
||||
metaObjectPtr = self.extractMetaObjectPtr(value.address(), value.type)
|
||||
if metaObjectPtr:
|
||||
self.putQObjectGutsHelper(value, value.address(),
|
||||
-1, metaObjectPtr, 'QObject')
|
||||
|
||||
def metaString(self, metaObjectPtr, index, revision):
|
||||
ptrSize = self.ptrSize()
|
||||
@@ -1787,7 +1768,7 @@ class DumperBase:
|
||||
qobjectPtrType = self.createType('QObject') # FIXME.
|
||||
with SubItem(self, '[parent]'):
|
||||
self.putField('sortgroup', 9)
|
||||
self.putItem(self.createValue(dd + 2 * ptrSize, qobjectPtrType))
|
||||
self.putItem(self.createValue(parentPtr, qobjectPtrType))
|
||||
with SubItem(self, '[children]'):
|
||||
self.putField('sortgroup', 8)
|
||||
base = self.extractPointer(dd + 3 * ptrSize) # It's a QList<QObject *>
|
||||
@@ -1881,8 +1862,21 @@ class DumperBase:
|
||||
if qobject:
|
||||
# LLDB doesn't like calling it on a derived class, possibly
|
||||
# due to type information living in a different shared object.
|
||||
base = self.createValue(qobjectPtr, '@QObject')
|
||||
self.putCallItem(name, '@QVariant', base, 'property', '"' + name + '"')
|
||||
#base = self.createValue(qobjectPtr, '@QObject')
|
||||
#warn("CALL FUNC: 0x%x" % self.qtPropertyFunc)
|
||||
cmd = '((QVariant(*)(void*,char*))0x%x)((void*)0x%x,"%s")' \
|
||||
% (self.qtPropertyFunc, qobjectPtr, name)
|
||||
try:
|
||||
#warn('PROP CMD: %s' % cmd)
|
||||
res = self.parseAndEvaluate(cmd)
|
||||
#warn('PROP RES: %s' % res)
|
||||
except:
|
||||
self.bump('failedMetaObjectCall')
|
||||
putt(name, ' ')
|
||||
continue
|
||||
#warn('COULD NOT EXECUTE: %s' % cmd)
|
||||
#self.putCallItem(name, '@QVariant', base, 'property', '"' + name + '"')
|
||||
self.putSubItem(name, res)
|
||||
else:
|
||||
putt(name, ' ')
|
||||
|
||||
@@ -2679,23 +2673,16 @@ class DumperBase:
|
||||
self.putNumChild(1)
|
||||
self.putEmptyValue()
|
||||
#warn('STRUCT GUTS: %s ADDRESS: 0x%x ' % (value.name, value.address()))
|
||||
metaObjectPtr = self.extractMetaObjectPtr(value.address(), value.type)
|
||||
if self.showQObjectNames:
|
||||
self.preping(self.currentIName)
|
||||
metaObjectPtr = self.extractMetaObjectPtr(value.address(), value.type)
|
||||
self.ping(self.currentIName)
|
||||
if metaObjectPtr:
|
||||
self.context = value
|
||||
self.putQObjectNameValue(value)
|
||||
#warn('STRUCT GUTS: %s MO: 0x%x ' % (self.currentIName, metaObjectPtr))
|
||||
self.ping(self.currentIName)
|
||||
if self.isExpanded():
|
||||
self.putField('sortable', 1)
|
||||
with Children(self, 1, childType=None):
|
||||
self.putFields(value)
|
||||
if not self.showQObjectNames:
|
||||
metaObjectPtr = self.extractMetaObjectPtr(value.address(), value.type)
|
||||
if metaObjectPtr:
|
||||
self.putQObjectGuts(value, metaObjectPtr)
|
||||
if self.showQObjectNames:
|
||||
self.tryPutQObjectGuts(value)
|
||||
|
||||
def symbolAddress(self, symbolName):
|
||||
res = self.parseAndEvaluate('(size_t)&' + symbolName)
|
||||
@@ -3275,7 +3262,7 @@ class DumperBase:
|
||||
except:
|
||||
return None
|
||||
#warn('VTBL: 0x%x' % vtbl)
|
||||
if not self.dumper.canBePointer(vtbl):
|
||||
if not self.dumper.couldBePointer(vtbl):
|
||||
return None
|
||||
return self.dumper.nativeDynamicTypeName(address, self)
|
||||
|
||||
|
||||
@@ -1010,6 +1010,12 @@ class Dumper(DumperBase):
|
||||
self.ping('qtNamespace')
|
||||
return res
|
||||
|
||||
def findSymbol(self, symbolName):
|
||||
try:
|
||||
return toInteger(gdb.parse_and_eval("(size_t)&'%s'" % symbolName))
|
||||
except:
|
||||
return 0
|
||||
|
||||
def qtNamespaceX(self):
|
||||
if not self.currentQtNamespaceGuess is None:
|
||||
return self.currentQtNamespaceGuess
|
||||
@@ -1039,6 +1045,24 @@ class Dumper(DumperBase):
|
||||
except:
|
||||
pass
|
||||
|
||||
lenns = len(ns)
|
||||
strns = ('%d%s' % (lenns - 2, ns[:lenns - 2])) if lenns else ''
|
||||
|
||||
if lenns:
|
||||
sym = '_ZN%s7QObject11customEventEPNS_6QEventE' % strns
|
||||
else:
|
||||
sym = '_ZN7QObject11customEventEP6QEvent'
|
||||
self.qtCustomEventFunc = self.findSymbol(sym)
|
||||
|
||||
if lenns:
|
||||
sym = '_ZN%s7QObject11customEventEPNS_6QEventE@plt' % strns
|
||||
else:
|
||||
sym = '_ZN7QObject11customEventEP6QEvent@plt'
|
||||
self.qtCustomEventPltFunc = self.findSymbol(sym)
|
||||
|
||||
sym = '_ZNK7%sQObject8propertyEPKc' % strns
|
||||
self.qtPropertyFunc = self.findSymbol(sym)
|
||||
|
||||
# This might be wrong, but we can't do better: We found
|
||||
# a libQt5Core and could not extract a namespace.
|
||||
# The best guess is that there isn't any.
|
||||
|
||||
@@ -679,6 +679,15 @@ class Dumper(DumperBase):
|
||||
qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch)
|
||||
self.qtVersion = lambda: qtVersion
|
||||
|
||||
funcs = self.target.FindFunctions('QObject::customEvent')
|
||||
if len(funcs):
|
||||
symbol = funcs[0].GetSymbol()
|
||||
self.qtCustomEventFunc = symbol.GetStartAddress().GetLoadAddress(self.target)
|
||||
|
||||
funcs = self.target.FindFunctions('QObject::property')
|
||||
if len(funcs):
|
||||
symbol = funcs[0].GetSymbol()
|
||||
self.qtPropertyFunc = symbol.GetStartAddress().GetLoadAddress(self.target)
|
||||
return (qtNamespace, qtVersion)
|
||||
|
||||
return ('', 0x50200)
|
||||
|
||||
@@ -190,6 +190,34 @@ def qdump_X_QModelIndex(d, value):
|
||||
d.putCallItem('parent', '@QModelIndex', value, 'parent')
|
||||
#gdb.execute('call free($mi)')
|
||||
|
||||
def qdump__Qt__ItemDataRole(d, value):
|
||||
d.putEnumValue(value, {
|
||||
0 : "Qt::DisplayRole",
|
||||
1 : "Qt::DecorationRole",
|
||||
2 : "Qt::EditRole",
|
||||
3 : "Qt::ToolTipRole",
|
||||
4 : "Qt::StatusTipRole",
|
||||
5 : "Qt::WhatsThisRole",
|
||||
6 : "Qt::FontRole",
|
||||
7 : "Qt::TextAlignmentRole",
|
||||
# obsolete: 8 : "Qt::BackgroundColorRole",
|
||||
8 : "Qt::BackgroundRole",
|
||||
# obsolete: 9 : "Qt::TextColorRole",
|
||||
9 : "Qt::ForegroundRole",
|
||||
10 : "Qt::CheckStateRole",
|
||||
11 : "Qt::AccessibleTextRole",
|
||||
12 : "Qt::AccessibleDescriptionRole",
|
||||
13 : "Qt::SizeHintRole",
|
||||
14 : "Qt::InitialSortOrderRole",
|
||||
# 27-31 Qt4 ItemDataRoles
|
||||
27 : "Qt::DisplayPropertyRole",
|
||||
28 : "Qt::DecorationPropertyRole",
|
||||
29 : "Qt::ToolTipPropertyRole",
|
||||
30 : "Qt::StatusTipPropertyRole",
|
||||
31 : "Qt::WhatsThisPropertyRole",
|
||||
0x100 : "Qt::UserRole"
|
||||
})
|
||||
|
||||
def qdump__QStandardItemData(d, value):
|
||||
role, pad, val = value.split('{@Qt::ItemDataRole}@{QVariant}')
|
||||
d.putPairContents(role.value(), (role, val), 'role', 'value')
|
||||
@@ -202,8 +230,9 @@ def qdump__QStandardItem(d, value):
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
d.putSubItem('[model]', d.createValue(model, '@QStandardItemModel'))
|
||||
d.putSubItem('[values]', d.createVectorItem(values, 'QStandardItemData'))
|
||||
d.putSubItem('[children]', d.createVectorItem(children, '@QStandardItem*'))
|
||||
d.putSubItem('[values]', d.createVectorItem(values, '@QStandardItemData'))
|
||||
d.putSubItem('[children]', d.createVectorItem(children,
|
||||
d.createPointerType(value.type)))
|
||||
|
||||
|
||||
def qdump__QDate(d, value):
|
||||
|
||||
@@ -657,6 +657,9 @@ def qdump__std____weak_ptr(d, value):
|
||||
def qdump__std__weak_ptr(d, value):
|
||||
return qdump__std__shared_ptr(d, value)
|
||||
|
||||
def qdump__std____1__weak_ptr(d, value):
|
||||
return qdump__std____1__shared_ptr(d, value)
|
||||
|
||||
|
||||
def qdump__std__shared_ptr(d, value):
|
||||
if d.isMsvcTarget():
|
||||
@@ -667,41 +670,27 @@ def qdump__std__shared_ptr(d, value):
|
||||
if i.pointer() == 0:
|
||||
d.putValue("(null)")
|
||||
d.putNumChild(0)
|
||||
return
|
||||
with Children(d):
|
||||
short = d.putSubItem("data", i.dereference())
|
||||
if d.isMsvcTarget():
|
||||
refcount = value["_Rep"]
|
||||
d.putIntItem("usecount", refcount["_Uses"])
|
||||
d.putIntItem("weakcount", refcount["_Weaks"])
|
||||
else:
|
||||
refcount = value["_M_refcount"]["_M_pi"]
|
||||
d.putIntItem("usecount", refcount["_M_use_count"])
|
||||
d.putIntItem("weakcount", refcount["_M_weak_count"])
|
||||
d.putValue(short.value, short.encoding)
|
||||
else:
|
||||
d.putItem(i.dereference())
|
||||
d.putBetterType(value.type)
|
||||
|
||||
def qdump__std____1__shared_ptr(d, value):
|
||||
i = value["__ptr_"]
|
||||
if i.pointer() == 0:
|
||||
d.putValue("(null)")
|
||||
d.putNumChild(0)
|
||||
return
|
||||
with Children(d):
|
||||
short = d.putSubItem("data", i.dereference())
|
||||
d.putFields(value["__cntrl_"].dereference())
|
||||
#d.putIntItem("usecount", refcount["_M_use_count"])
|
||||
#d.putIntItem("weakcount", refcount["_M_weak_count"])
|
||||
d.putValue(short.value, short.encoding)
|
||||
else:
|
||||
d.putItem(i.dereference())
|
||||
d.putBetterType(value.type)
|
||||
|
||||
def qdump__std__unique_ptr(d, value):
|
||||
p = d.extractPointer(value)
|
||||
if p == 0:
|
||||
d.putValue("(null)")
|
||||
d.putNumChild(0)
|
||||
return
|
||||
with Children(d):
|
||||
short = d.putSubItem("data", d.createValue(p, value.type[0]))
|
||||
d.putValue(short.value, short.encoding)
|
||||
else:
|
||||
d.putItem(d.createValue(p, value.type[0]))
|
||||
d.putBetterType(value.type)
|
||||
|
||||
def qdump__std____1__unique_ptr(d, value):
|
||||
qdump__std__unique_ptr(d, value)
|
||||
@@ -1002,6 +991,14 @@ def qdump__std____1__basic_string(d, value):
|
||||
def qdump__wstring(d, value):
|
||||
qdump__std__wstring(d, value)
|
||||
|
||||
def qdump__std____1__once_flag(d, value):
|
||||
qdump__std__once_flag(d, value)
|
||||
|
||||
def qdump__std__once_flag(d, value):
|
||||
d.putItem(value[0])
|
||||
d.putBetterType(value.type)
|
||||
d.putPlainChildren(value)
|
||||
|
||||
|
||||
def qdump____gnu_cxx__hash_set(d, value):
|
||||
ht = value["_M_ht"]
|
||||
|
||||
@@ -32,9 +32,14 @@
|
||||
#include "stringutils.h"
|
||||
#include "symbolgroupvalue.h"
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
constexpr bool debugPyValue = false;
|
||||
constexpr bool debuggingValueEnabled() { return debugPyValue || debugPyCdbextModule; }
|
||||
|
||||
static std::map<CIDebugSymbolGroup *, std::list<Value *>> valuesForSymbolGroup;
|
||||
|
||||
std::string getSymbolName(CIDebugSymbolGroup *sg, ULONG index)
|
||||
{
|
||||
ULONG size = 0;
|
||||
@@ -147,6 +152,21 @@ PyObject *value_Address(Value *self)
|
||||
return Py_BuildValue("K", address);
|
||||
}
|
||||
|
||||
void indicesMoved(CIDebugSymbolGroup *symbolGroup, ULONG start, ULONG delta)
|
||||
{
|
||||
if (delta == 0)
|
||||
return;
|
||||
ULONG count;
|
||||
if (FAILED(symbolGroup->GetNumberSymbols(&count)))
|
||||
return;
|
||||
if (count <= start)
|
||||
return;
|
||||
for (Value *val : valuesForSymbolGroup[symbolGroup]) {
|
||||
if (val->m_index >= start && val->m_index + delta < count)
|
||||
val->m_index += delta;
|
||||
}
|
||||
}
|
||||
|
||||
bool expandValue(Value *v)
|
||||
{
|
||||
DEBUG_SYMBOL_PARAMETERS params;
|
||||
@@ -154,7 +174,15 @@ bool expandValue(Value *v)
|
||||
return false;
|
||||
if (params.Flags & DEBUG_SYMBOL_EXPANDED)
|
||||
return true;
|
||||
return SUCCEEDED(v->m_symbolGroup->ExpandSymbol(v->m_index, TRUE));
|
||||
if (FAILED(v->m_symbolGroup->ExpandSymbol(v->m_index, TRUE)))
|
||||
return false;
|
||||
if (FAILED(v->m_symbolGroup->GetSymbolParameters(v->m_index, 1, ¶ms)))
|
||||
return false;
|
||||
if (params.Flags & DEBUG_SYMBOL_EXPANDED) {
|
||||
indicesMoved(v->m_symbolGroup, v->m_index + 1, params.SubElements);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ULONG numberOfChildren(Value *v)
|
||||
@@ -310,8 +338,11 @@ PyObject *value_ChildFromIndex(Value *self, PyObject *args)
|
||||
return createValue(self->m_index + index + 1, self->m_symbolGroup);
|
||||
}
|
||||
|
||||
void value_Dealloc(Value *)
|
||||
{ }
|
||||
void value_Dealloc(Value *v)
|
||||
{
|
||||
auto values = valuesForSymbolGroup[v->m_symbolGroup];
|
||||
std::remove(values.begin(), values.end(), v);
|
||||
}
|
||||
|
||||
PyObject *value_New(PyTypeObject *type, PyObject *, PyObject *)
|
||||
{
|
||||
@@ -339,6 +370,7 @@ PyObject *createValue(ULONG index, CIDebugSymbolGroup *symbolGroup)
|
||||
if (value != NULL) {
|
||||
value->m_index = index;
|
||||
value->m_symbolGroup = symbolGroup;
|
||||
valuesForSymbolGroup[symbolGroup].push_back(value);
|
||||
}
|
||||
return reinterpret_cast<PyObject*>(value);
|
||||
}
|
||||
|
||||
@@ -214,78 +214,112 @@ using decay_t = typename std::decay<T>::type;
|
||||
template<typename T>
|
||||
using result_of_t = typename std::result_of<T>::type;
|
||||
|
||||
// Result type of transform operation
|
||||
// abstraction to treat Container<T> and QStringList similarly
|
||||
template<typename T>
|
||||
struct ContainerType
|
||||
{
|
||||
|
||||
template<template<typename> class Container, template<typename> class InputContainer, typename IT, typename Function>
|
||||
using ResultContainer = Container<decay_t<result_of_t<Function(IT)>>>;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
// specialization for qt container T_Container<T_Type>
|
||||
template<template<typename> class T_Container, typename T_Type>
|
||||
struct ContainerType<T_Container<T_Type>>
|
||||
{
|
||||
template<class F, template<typename> class C = T_Container>
|
||||
using ResultOfTransform = C<decay_t<result_of_t<F (T_Type)>>>;
|
||||
|
||||
template<class R>
|
||||
using ResultOfTransformPMF = T_Container<decay_t<R>>;
|
||||
};
|
||||
|
||||
// specialization for QStringList
|
||||
template<>
|
||||
struct ContainerType<QStringList> : ContainerType<QList<QString>>
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// actual implementation of transform
|
||||
template<typename C, // result container type
|
||||
typename SC> // input container type
|
||||
struct TransformImpl {
|
||||
template <typename F>
|
||||
Q_REQUIRED_RESULT
|
||||
static C call(const SC &container, F function)
|
||||
{
|
||||
C result;
|
||||
std::transform(container.begin(), container.end(),
|
||||
inserter(result),
|
||||
function);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename R, typename S>
|
||||
Q_REQUIRED_RESULT
|
||||
static C call(const SC &container, R (S::*p)() const)
|
||||
{
|
||||
return call(container, std::mem_fn(p));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// same container type for input and output, e.g. transforming a QList<QString> into QList<int>
|
||||
// or QStringList -> QList<>
|
||||
template<typename C, // container
|
||||
typename F>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const C &container, F function)
|
||||
-> typename ContainerType<C>::template ResultOfTransform<F>
|
||||
{
|
||||
return TransformImpl<
|
||||
typename ContainerType<C>::template ResultOfTransform<F>,
|
||||
C
|
||||
>::call(container, function);
|
||||
}
|
||||
|
||||
// same container type for member function pointer
|
||||
template<typename C,
|
||||
typename R,
|
||||
typename S>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const C &container, R (S::*p)() const)
|
||||
->typename ContainerType<C>::template ResultOfTransformPMF<R>
|
||||
{
|
||||
return TransformImpl<
|
||||
typename ContainerType<C>::template ResultOfTransformPMF<R>,
|
||||
C
|
||||
>::call(container, p);
|
||||
}
|
||||
|
||||
// different container types for input and output, e.g. transforming a QList into a QSet
|
||||
template<template<typename> class C, // result container type
|
||||
template<typename> class SC, // input container type
|
||||
typename T, // input value type
|
||||
typename SC, // input container type
|
||||
typename F> // function type
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const SC<T> &container, F function) -> ResultContainer<C, SC, T, F>
|
||||
auto transform(const SC &container, F function)
|
||||
-> typename ContainerType<SC>::template ResultOfTransform<F, C>
|
||||
{
|
||||
ResultContainer<C, SC, T, F> result;
|
||||
std::transform(container.begin(), container.end(),
|
||||
inserter(result),
|
||||
function);
|
||||
return result;
|
||||
return TransformImpl<
|
||||
typename ContainerType<SC>::template ResultOfTransform<F, C>,
|
||||
SC
|
||||
>::call(container, function);
|
||||
}
|
||||
|
||||
// different container types for input and output, e.g. transforming a QList into a QSet
|
||||
// for member function pointers
|
||||
template<template<typename> class C, // result container type
|
||||
template<typename> class SC, // input container type
|
||||
typename T, // input value type
|
||||
typename SC, // input container type
|
||||
typename R,
|
||||
typename S>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const SC<T> &container, R (S::*p)() const) -> ResultContainer<C, SC, T, R(S::*)() const>
|
||||
auto transform(const SC &container, R (S::*p)() const)
|
||||
-> C<decay_t<R>>
|
||||
{
|
||||
return Utils::transform<C, SC, T>(container, std::mem_fn(p));
|
||||
}
|
||||
|
||||
// same container type for input and output, e.g. transforming a QList<QString> into QList<int>
|
||||
// or QStringList -> QList<>
|
||||
template<template<typename> class C, // container
|
||||
typename T, // container value type
|
||||
typename F>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const C<T> &container, F function) -> ResultContainer<C, C, T, F>
|
||||
{
|
||||
return Utils::transform<C, C, T>(container, function);
|
||||
}
|
||||
|
||||
// same container type for member function pointer
|
||||
template<template<typename> class C, // container
|
||||
typename T, // container value type
|
||||
typename R,
|
||||
typename S>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const C<T> &container, R (S::*p)() const) -> ResultContainer<C, C, T, R(S::*)() const>
|
||||
{
|
||||
return Utils::transform<C, C, T>(container, std::mem_fn(p));
|
||||
}
|
||||
|
||||
// QStringList different containers
|
||||
template<template<typename> class C, // result container type
|
||||
typename F>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const QStringList &container, F function) -> ResultContainer<C, QList, QString, F>
|
||||
{
|
||||
return Utils::transform<C, QList, QString>(container, function);
|
||||
}
|
||||
|
||||
// QStringList -> QList
|
||||
template<typename F>
|
||||
Q_REQUIRED_RESULT
|
||||
auto transform(const QStringList &container, F function) -> ResultContainer<QList, QList, QString, F>
|
||||
{
|
||||
return Utils::transform<QList, QList, QString>(container, function);
|
||||
return TransformImpl<
|
||||
C<decay_t<R>>,
|
||||
SC
|
||||
>::call(container, p);
|
||||
}
|
||||
|
||||
//////////////////
|
||||
|
||||
@@ -155,8 +155,6 @@ void TestCodeParser::updateTestTree()
|
||||
return;
|
||||
|
||||
m_fullUpdatePostponed = false;
|
||||
|
||||
emit aboutToPerformFullParse();
|
||||
qCDebug(LOG) << "calling scanForTests (updateTestTree)";
|
||||
scanForTests();
|
||||
}
|
||||
@@ -199,6 +197,7 @@ void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *project)
|
||||
qCDebug(LOG) << "Canceling scanForTest (startup project changed)";
|
||||
Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE);
|
||||
}
|
||||
emit aboutToPerformFullParse();
|
||||
if (project)
|
||||
emitUpdateTestTree();
|
||||
}
|
||||
|
||||
@@ -59,9 +59,14 @@ using namespace ProjectExplorer::Constants;
|
||||
AutotoolsBuildConfiguration::AutotoolsBuildConfiguration(Target *parent) :
|
||||
BuildConfiguration(parent, Core::Id(AUTOTOOLS_BC_ID))
|
||||
{
|
||||
// /<foobar> is used so the un-changed check in setBuildDirectory() works correctly.
|
||||
// The leading / is to avoid the relative the path expansion in BuildConfiguration::buildDirectory.
|
||||
BuildConfiguration::setBuildDirectory(Utils::FileName::fromString(QString::fromLatin1("/<foobar>")));
|
||||
// /<foobar> is used so the un-changed check in setBuildDirectory() works correctly.
|
||||
// The leading / is to avoid the relative the path expansion in BuildConfiguration::buildDirectory.
|
||||
BuildConfiguration::setBuildDirectory(Utils::FileName::fromString(QString::fromLatin1("/<foobar>")));
|
||||
|
||||
connect(this, &BuildConfiguration::buildDirectoryChanged, this, [this] {
|
||||
foreach (auto bs, stepList(BUILDSTEPS_BUILD)->allOfType<ConfigureStep>())
|
||||
bs->notifyBuildDirectoryChanged();
|
||||
});
|
||||
}
|
||||
|
||||
NamedWidget *AutotoolsBuildConfiguration::createConfigWidget()
|
||||
@@ -222,12 +227,3 @@ BuildConfiguration::BuildType AutotoolsBuildConfiguration::buildType() const
|
||||
// TODO: Should I return something different from Unknown?
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
void AutotoolsBuildConfiguration::setBuildDirectory(const Utils::FileName &directory)
|
||||
{
|
||||
if (directory == buildDirectory())
|
||||
return;
|
||||
BuildConfiguration::setBuildDirectory(directory);
|
||||
foreach (auto bs, stepList(BUILDSTEPS_BUILD)->allOfType<ConfigureStep>())
|
||||
bs->notifyBuildDirectoryChanged();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace Internal {
|
||||
|
||||
class AutotoolsTarget;
|
||||
class AutotoolsBuildConfigurationFactory;
|
||||
class AutotoolsBuildSettingsWidget;
|
||||
|
||||
class AutotoolsBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
{
|
||||
@@ -53,11 +52,6 @@ public:
|
||||
protected:
|
||||
AutotoolsBuildConfiguration(ProjectExplorer::Target *parent, Core::Id id);
|
||||
AutotoolsBuildConfiguration(ProjectExplorer::Target *parent, AutotoolsBuildConfiguration *source);
|
||||
|
||||
friend class AutotoolsBuildSettingsWidget;
|
||||
|
||||
private:
|
||||
void setBuildDirectory(const Utils::FileName &directory) override;
|
||||
};
|
||||
|
||||
class AutotoolsBuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
|
||||
|
||||
@@ -411,8 +411,8 @@ void CMakeGeneratorKitInformation::fix(Kit *k)
|
||||
void CMakeGeneratorKitInformation::upgrade(Kit *k)
|
||||
{
|
||||
const QVariant value = k->value(GENERATOR_ID);
|
||||
GeneratorInfo info;
|
||||
if (value.type() != QVariant::Map) {
|
||||
GeneratorInfo info;
|
||||
const QString fullName = value.toString();
|
||||
const int pos = fullName.indexOf(" - ");
|
||||
if (pos >= 0) {
|
||||
|
||||
@@ -102,12 +102,14 @@ void Find::destroy()
|
||||
{
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
delete d->m_currentDocumentFind;
|
||||
delete d->m_findToolBar;
|
||||
delete d->m_findDialog;
|
||||
ExtensionSystem::PluginManager::removeObject(d->m_searchResultWindow);
|
||||
delete d->m_searchResultWindow;
|
||||
delete d;
|
||||
if (d) {
|
||||
delete d->m_currentDocumentFind;
|
||||
delete d->m_findToolBar;
|
||||
delete d->m_findDialog;
|
||||
ExtensionSystem::PluginManager::removeObject(d->m_searchResultWindow);
|
||||
delete d->m_searchResultWindow;
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
||||
Find *Find::instance()
|
||||
|
||||
@@ -257,15 +257,15 @@ DebuggerSettings::DebuggerSettings()
|
||||
insertItem(ShowQtNamespace, item);
|
||||
|
||||
item = new SavedAction(this);
|
||||
item->setSettingsKey(debugModeGroup, QLatin1String("ShowQObjectNames"));
|
||||
item->setSettingsKey(debugModeGroup, QLatin1String("ShowQObjectNames2"));
|
||||
item->setText(tr("Show QObject names if available"));
|
||||
item->setDialogText(tr("Show QObject names if available"));
|
||||
item->setToolTip(tr("<p>Displays the objectName property of QObject based items. "
|
||||
"Note that this can negatively impact debugger performance "
|
||||
"even if no QObjects are present."));
|
||||
item->setCheckable(true);
|
||||
item->setDefaultValue(false);
|
||||
item->setValue(false);
|
||||
item->setDefaultValue(true);
|
||||
item->setValue(true);
|
||||
insertItem(ShowQObjectNames, item);
|
||||
|
||||
item = new SavedAction(this);
|
||||
|
||||
@@ -54,13 +54,6 @@ BuildConfiguration::BuildType NimBuildConfiguration::buildType() const
|
||||
return BuildConfiguration::Unknown;
|
||||
}
|
||||
|
||||
void NimBuildConfiguration::setBuildDirectory(const FileName &dir)
|
||||
{
|
||||
if (dir == buildDirectory())
|
||||
return;
|
||||
BuildConfiguration::setBuildDirectory(dir);
|
||||
}
|
||||
|
||||
bool NimBuildConfiguration::fromMap(const QVariantMap &map)
|
||||
{
|
||||
if (!BuildConfiguration::fromMap(map))
|
||||
|
||||
@@ -46,8 +46,6 @@ public:
|
||||
|
||||
ProjectExplorer::BuildConfiguration::BuildType buildType() const override;
|
||||
|
||||
void setBuildDirectory(const Utils::FileName &dir) override;
|
||||
|
||||
bool fromMap(const QVariantMap &map) override;
|
||||
QVariantMap toMap() const override;
|
||||
|
||||
|
||||
@@ -122,6 +122,8 @@ Utils::FileName BuildConfiguration::rawBuildDirectory() const
|
||||
|
||||
void BuildConfiguration::setBuildDirectory(const Utils::FileName &dir)
|
||||
{
|
||||
if (dir == m_buildDirectory)
|
||||
return;
|
||||
m_buildDirectory = dir;
|
||||
emitBuildDirectoryChanged();
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
|
||||
Utils::FileName buildDirectory() const;
|
||||
Utils::FileName rawBuildDirectory() const;
|
||||
void setBuildDirectory(const Utils::FileName &dir);
|
||||
|
||||
virtual NamedWidget *createConfigWidget() = 0;
|
||||
virtual QList<NamedWidget *> createSubConfigWidgets();
|
||||
@@ -96,7 +97,6 @@ protected:
|
||||
BuildConfiguration(Target *target, Core::Id id);
|
||||
BuildConfiguration(Target *target, BuildConfiguration *source);
|
||||
|
||||
virtual void setBuildDirectory(const Utils::FileName &dir);
|
||||
void cloneSteps(BuildConfiguration *source);
|
||||
void emitEnvironmentChanged();
|
||||
|
||||
|
||||
@@ -333,11 +333,11 @@ public:
|
||||
QAction *m_projectSelectorActionQuick;
|
||||
QAction *m_runSubProject;
|
||||
|
||||
ProjectWindow *m_proWindow;
|
||||
ProjectWindow *m_proWindow = nullptr;
|
||||
QString m_sessionToRestoreAtStartup;
|
||||
|
||||
QStringList m_profileMimeTypes;
|
||||
AppOutputPane *m_outputPane;
|
||||
AppOutputPane *m_outputPane = nullptr;
|
||||
|
||||
QList<QPair<QString, QString> > m_recentProjects; // pair of filename, displayname
|
||||
static const int m_maxRecentProjects = 25;
|
||||
|
||||
@@ -102,6 +102,8 @@ enum { debug = 0 };
|
||||
QmakeBuildConfiguration::QmakeBuildConfiguration(Target *target)
|
||||
: QmakeBuildConfiguration(target, Core::Id(QMAKE_BC_ID))
|
||||
{
|
||||
connect(this, &BuildConfiguration::buildDirectoryChanged,
|
||||
this, &QmakeBuildConfiguration::emitProFileEvaluateNeeded);
|
||||
}
|
||||
|
||||
QmakeBuildConfiguration::QmakeBuildConfiguration(Target *target, Core::Id id) :
|
||||
@@ -223,14 +225,6 @@ bool QmakeBuildConfiguration::isShadowBuild() const
|
||||
return buildDirectory() != target()->project()->projectDirectory();
|
||||
}
|
||||
|
||||
void QmakeBuildConfiguration::setBuildDirectory(const FileName &directory)
|
||||
{
|
||||
if (directory == buildDirectory())
|
||||
return;
|
||||
BuildConfiguration::setBuildDirectory(directory);
|
||||
emitProFileEvaluateNeeded();
|
||||
}
|
||||
|
||||
QString QmakeBuildConfiguration::makefile() const
|
||||
{
|
||||
return static_cast<QmakeProject *>(target()->project())->rootProjectNode()->makefile();
|
||||
|
||||
@@ -116,7 +116,6 @@ protected:
|
||||
QmakeBuildConfiguration(ProjectExplorer::Target *target, QmakeBuildConfiguration *source);
|
||||
QmakeBuildConfiguration(ProjectExplorer::Target *target, Core::Id id);
|
||||
bool fromMap(const QVariantMap &map) override;
|
||||
void setBuildDirectory(const Utils::FileName &directory) override;
|
||||
|
||||
private:
|
||||
void ctor();
|
||||
|
||||
@@ -3398,6 +3398,14 @@ void tst_Dumpers::dumper_data()
|
||||
"{\n"
|
||||
" void run()\n"
|
||||
" {\n"
|
||||
" auto mo = &QThread::metaObject;\n"
|
||||
" auto mc = &QThread::qt_metacast;\n"
|
||||
" auto p0 = (*(void***)this)[0]; unused(&p0);\n"
|
||||
" auto p1 = (*(void***)this)[1]; unused(&p1);\n"
|
||||
" auto p2 = (*(void***)this)[2]; unused(&p2);\n"
|
||||
" auto p3 = (*(void***)this)[3]; unused(&p3);\n"
|
||||
" auto p4 = (*(void***)this)[4]; unused(&p4);\n"
|
||||
" auto p5 = (*(void***)this)[5]; unused(&p5);\n"
|
||||
" if (m_id == 3) {\n"
|
||||
" BREAK;\n"
|
||||
" }\n"
|
||||
@@ -4375,15 +4383,16 @@ void tst_Dumpers::dumper_data()
|
||||
+ MacLibCppProfile()
|
||||
|
||||
+ Check("p0", "(null)", "std::unique_ptr<int, std::default_delete<int> >")
|
||||
|
||||
+ Check("p1", "32", "std::unique_ptr<int, std::default_delete<int> >")
|
||||
+ Check("p1.data", "32", "int")
|
||||
|
||||
+ Check("p2", Pointer(), "std::unique_ptr<Foo, std::default_delete<Foo> >")
|
||||
+ CheckType("p2.data", "Foo")
|
||||
+ Check("p3", "\"ABC\"", "std::unique_ptr<std::string, std::default_delete<std::string> >");
|
||||
|
||||
+ Check("p3", "\"ABC\"", "std::unique_ptr<std::string, std::default_delete<std::string> >")
|
||||
+ Check("p3.data", "\"ABC\"", "std::string");
|
||||
|
||||
QTest::newRow("StdOnce")
|
||||
<< Data("#include <mutex>\n",
|
||||
"std::once_flag x; unused(&x);\n")
|
||||
+ Cxx11Profile()
|
||||
+ Check("x", "0", "std::once_flag");
|
||||
|
||||
|
||||
QTest::newRow("StdSharedPtr")
|
||||
@@ -4401,17 +4410,12 @@ void tst_Dumpers::dumper_data()
|
||||
+ MacLibCppProfile()
|
||||
|
||||
+ Check("pi", "32", "std::shared_ptr<int>")
|
||||
+ Check("pi.data", "32", "int")
|
||||
+ Check("pf", Pointer(), "std::shared_ptr<Foo>")
|
||||
+ CheckType("pf.data", "Foo")
|
||||
+ Check("ps", "\"ABC\"", "std::shared_ptr<std::string>")
|
||||
+ Check("ps.data", "\"ABC\"", "std::string")
|
||||
+ Check("wi", "32", "std::weak_ptr<int>")
|
||||
+ Check("wi.data", "32", "int")
|
||||
+ Check("wf", Pointer(), "std::weak_ptr<Foo>")
|
||||
+ CheckType("wf.data", "Foo")
|
||||
+ Check("ws", "\"ABC\"", "std::weak_ptr<std::string>")
|
||||
+ Check("ws.data", "\"ABC\"", "std::string");
|
||||
+ Check("ps", "\"ABC\"", "std::shared_ptr<std::string>");
|
||||
|
||||
QTest::newRow("StdSharedPtr2")
|
||||
<< Data("#include <memory>\n"
|
||||
@@ -4429,10 +4433,10 @@ void tst_Dumpers::dumper_data()
|
||||
+ Check("inner.m_1", "0x1", "int *")
|
||||
+ Check("inner.m_2", "0x2", "int *")
|
||||
+ Check("inner.x", "3", "int")
|
||||
+ Check("a.data.m_0", "0x0", "int *")
|
||||
+ Check("a.data.m_1", "0x1", "int *")
|
||||
+ Check("a.data.m_2", "0x2", "int *")
|
||||
+ Check("a.data.x", "3", "int");
|
||||
+ Check("a.m_0", "0x0", "int *")
|
||||
+ Check("a.m_1", "0x1", "int *")
|
||||
+ Check("a.m_2", "0x2", "int *")
|
||||
+ Check("a.x", "3", "int");
|
||||
|
||||
QTest::newRow("StdSet")
|
||||
<< Data("#include <set>\n",
|
||||
@@ -5587,13 +5591,9 @@ void tst_Dumpers::dumper_data()
|
||||
|
||||
+ Check("s", "(null)", "boost::shared_ptr<int>")
|
||||
+ Check("i", "43", "boost::shared_ptr<int>")
|
||||
+ Check("i.weakcount", "1", "int")
|
||||
+ Check("i.usecount", "2", "int")
|
||||
+ Check("i.data", "43", "int")
|
||||
+ Check("j", "43", "boost::shared_ptr<int>")
|
||||
+ Check("sl", "<1 items>", " boost::shared_ptr<@QStringList>")
|
||||
+ Check("sl.data", "<1 items>", "@QStringList")
|
||||
+ Check("sl.data.0", "[0]", "\"HUH!\"", "@QString");
|
||||
+ Check("sl.0", "[0]", "\"HUH!\"", "@QString");
|
||||
|
||||
|
||||
QTest::newRow("BoostGregorianDate")
|
||||
@@ -6389,7 +6389,8 @@ void tst_Dumpers::dumper_data()
|
||||
" root->appendRow(item);\n"
|
||||
"}\n")
|
||||
+ GuiProfile()
|
||||
+ Check("root.[children].0.[values].0.value", "\"item 0\"", "@QVariant (@QString)");
|
||||
+ Check("root.[children].0.[values].0.role", "Qt::DisplayRole (0)", "@Qt::ItemDataRole")
|
||||
+ Check("root.[children].0.[values].0.value", "\"item 0\"", "@QVariant (QString)");
|
||||
|
||||
|
||||
QTest::newRow("Internal1")
|
||||
|
||||
@@ -8,5 +8,5 @@ QtcAutotest {
|
||||
targetName: testName // Test runner hardcodes the names of the executables
|
||||
destinationDirectory: project.buildDirectory + '/'
|
||||
+ qtc.ide_bin_path + '/testapps/' + testName
|
||||
files: "main.cpp"
|
||||
files: sourceDirectory + "/main.cpp"
|
||||
}
|
||||
|
||||