Merge remote-tracking branch 'origin/4.7'
Change-Id: Ifec1f8dc20a18f432ec6ccf68153f31fff3f8b29
13
dist/changes-4.7.0.md
vendored
@@ -31,6 +31,7 @@ Editing
|
|||||||
behavior (QTCREATORBUG-9859, QTCREATORBUG-20061)
|
behavior (QTCREATORBUG-9859, QTCREATORBUG-20061)
|
||||||
* Fixed that extra editor windows were not restored when opening session
|
* Fixed that extra editor windows were not restored when opening session
|
||||||
(QTCREATORBUG-13840)
|
(QTCREATORBUG-13840)
|
||||||
|
* Fixed that editor could stay busy repainting annotations (QTCREATORBUG-20422)
|
||||||
* FakeVim
|
* FakeVim
|
||||||
* Added `:<range>sor[t][!]`
|
* Added `:<range>sor[t][!]`
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ QMake Projects
|
|||||||
* Added support for `-isystem` in `QMAKE_CXXFLAGS`
|
* Added support for `-isystem` in `QMAKE_CXXFLAGS`
|
||||||
* Added deployment rules for devices to widget and console application wizards
|
* Added deployment rules for devices to widget and console application wizards
|
||||||
(QTCREATORBUG-20358)
|
(QTCREATORBUG-20358)
|
||||||
|
* Fixed that arguments for QMake step did not expand variables
|
||||||
|
|
||||||
C++ Support
|
C++ Support
|
||||||
|
|
||||||
@@ -95,6 +97,11 @@ Python Support
|
|||||||
|
|
||||||
* Added stack traces in application output to Issues pane (category `Python`)
|
* Added stack traces in application output to Issues pane (category `Python`)
|
||||||
|
|
||||||
|
Debugging
|
||||||
|
|
||||||
|
* QML
|
||||||
|
* Added support for nested properties (QTBUG-68474)
|
||||||
|
|
||||||
Clang Static Analyzer
|
Clang Static Analyzer
|
||||||
|
|
||||||
* Renamed plugin to `ClangTools`
|
* Renamed plugin to `ClangTools`
|
||||||
@@ -141,9 +148,11 @@ Android
|
|||||||
* Improved behavior when emulator cannot be started (QTCREATORBUG-20160)
|
* Improved behavior when emulator cannot be started (QTCREATORBUG-20160)
|
||||||
|
|
||||||
Credits for these changes go to:
|
Credits for these changes go to:
|
||||||
|
Aaron Barany
|
||||||
Aleix Pol
|
Aleix Pol
|
||||||
Alessandro Portale
|
Alessandro Portale
|
||||||
Alexander Drozdov
|
Alexander Drozdov
|
||||||
|
Alexandru Croitor
|
||||||
Andre Hartmann
|
Andre Hartmann
|
||||||
André Pönitz
|
André Pönitz
|
||||||
Antonio Di Monaco
|
Antonio Di Monaco
|
||||||
@@ -155,13 +164,16 @@ Claus Steuer
|
|||||||
Colin Duquesnoy
|
Colin Duquesnoy
|
||||||
David Schulz
|
David Schulz
|
||||||
Eike Ziller
|
Eike Ziller
|
||||||
|
Filipe Azevedo
|
||||||
Friedemann Kleint
|
Friedemann Kleint
|
||||||
Hugo Holgersson
|
Hugo Holgersson
|
||||||
Ivan Donchevskii
|
Ivan Donchevskii
|
||||||
Jaroslaw Kobus
|
Jaroslaw Kobus
|
||||||
Jay Gupta
|
Jay Gupta
|
||||||
|
José Tomás Tocino
|
||||||
Jörg Bornemann
|
Jörg Bornemann
|
||||||
Kari Oikarinen
|
Kari Oikarinen
|
||||||
|
Kimmo Linnavuo
|
||||||
Leena Miettinen
|
Leena Miettinen
|
||||||
Marco Benelli
|
Marco Benelli
|
||||||
Marco Bubke
|
Marco Bubke
|
||||||
@@ -169,6 +181,7 @@ Mitch Curtis
|
|||||||
Nikita Baryshnikov
|
Nikita Baryshnikov
|
||||||
Nikolai Kosjar
|
Nikolai Kosjar
|
||||||
Orgad Shaneh
|
Orgad Shaneh
|
||||||
|
Oswald Buddenhagen
|
||||||
Pawel Rutka
|
Pawel Rutka
|
||||||
Przemyslaw Gorszkowski
|
Przemyslaw Gorszkowski
|
||||||
Razi Alavizadeh
|
Razi Alavizadeh
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ macro.note = "\\b{Note:}"
|
|||||||
macro.oslash.HTML = "ø"
|
macro.oslash.HTML = "ø"
|
||||||
macro.ouml.HTML = "ö"
|
macro.ouml.HTML = "ö"
|
||||||
macro.QA = "Qt Assistant"
|
macro.QA = "Qt Assistant"
|
||||||
macro.QC = "Qt Creator"
|
macro.QC = "$IDE_DISPLAY_NAME"
|
||||||
macro.QCE = "Qt Creator Enterprise"
|
macro.QCE = "$IDE_DISPLAY_NAME Enterprise"
|
||||||
macro.QD = "Qt Designer"
|
macro.QD = "Qt Designer"
|
||||||
macro.QL = "Qt Linguist"
|
macro.QL = "Qt Linguist"
|
||||||
macro.QMLD = "Qt Quick Designer"
|
macro.QMLD = "Qt Quick Designer"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
project = "QtCreator"
|
project = "$IDE_DISPLAY_NAME"
|
||||||
description = "Qt Creator Manual"
|
description = "$IDE_DISPLAY_NAME Manual"
|
||||||
url = http://doc.qt.io/qtcreator
|
url = http://doc.qt.io/$IDE_ID
|
||||||
|
|
||||||
headerdirs =
|
headerdirs =
|
||||||
sourcedirs = ../src
|
sourcedirs = ../src
|
||||||
@@ -54,17 +54,17 @@ include(qt-defines.qdocconf)
|
|||||||
sources.fileextensions = "*.qdoc"
|
sources.fileextensions = "*.qdoc"
|
||||||
|
|
||||||
qhp.projects = QtCreator
|
qhp.projects = QtCreator
|
||||||
qhp.QtCreator.file = qtcreator.qhp
|
qhp.QtCreator.file = $IDE_ID.qhp
|
||||||
qhp.QtCreator.namespace = org.qt-project.qtcreator.$QTC_VERSION_TAG
|
qhp.QtCreator.namespace = org.qt-project.$IDE_ID.$QTC_VERSION_TAG
|
||||||
qhp.QtCreator.virtualFolder = doc
|
qhp.QtCreator.virtualFolder = doc
|
||||||
qhp.QtCreator.indexTitle = Qt Creator Manual $QTC_VERSION
|
qhp.QtCreator.indexTitle = $IDE_DISPLAY_NAME Manual $QTC_VERSION
|
||||||
qhp.QtCreator.filterAttributes = qtcreator $QTC_VERSION
|
qhp.QtCreator.filterAttributes = $IDE_ID $QTC_VERSION
|
||||||
qhp.QtCreator.customFilters.QtCreator.name = Qt Creator $QTC_VERSION
|
qhp.QtCreator.customFilters.QtCreator.name = $IDE_DISPLAY_NAME $QTC_VERSION
|
||||||
qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator $QTC_VERSION
|
qhp.QtCreator.customFilters.QtCreator.filterAttributes = $IDE_ID $QTC_VERSION
|
||||||
qhp.QtCreator.indexRoot =
|
qhp.QtCreator.indexRoot =
|
||||||
|
|
||||||
qhp.QtCreator.subprojects = manual
|
qhp.QtCreator.subprojects = manual
|
||||||
qhp.QtCreator.subprojects.manual.title = Qt Creator Manual
|
qhp.QtCreator.subprojects.manual.title = $IDE_DISPLAY_NAME Manual
|
||||||
qhp.QtCreator.subprojects.manual.indexTitle = All Topics
|
qhp.QtCreator.subprojects.manual.indexTitle = All Topics
|
||||||
qhp.QtCreator.subprojects.manual.type = manual
|
qhp.QtCreator.subprojects.manual.type = manual
|
||||||
|
|
||||||
@@ -73,5 +73,5 @@ qhp.QtCreator.subprojects.manual.type = manual
|
|||||||
macro.see = "\\sa"
|
macro.see = "\\sa"
|
||||||
macro.function = "\\fn"
|
macro.function = "\\fn"
|
||||||
|
|
||||||
navigation.landingpage = "Qt Creator Manual"
|
navigation.landingpage = "$IDE_DISPLAY_NAME Manual"
|
||||||
buildversion = "Qt Creator Manual $QTC_VERSION"
|
buildversion = "$IDE_DISPLAY_NAME Manual $QTC_VERSION"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 62 KiB |
BIN
doc/images/qtcreator-performance-analyzer-flamegraph.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
doc/images/qtcreator-performance-analyzer-settings.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
doc/images/qtcreator-performance-analyzer-statistics.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
doc/images/qtcreator-performance-analyzer-timeline.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2017 The Qt Company Ltd.
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -40,15 +40,15 @@
|
|||||||
\commercial
|
\commercial
|
||||||
|
|
||||||
\QC is integrated with the Linux Perf tool (commercial only) that can be
|
\QC is integrated with the Linux Perf tool (commercial only) that can be
|
||||||
used to analyze the CPU usage of an application on embedded devices and, to
|
used to analyze the CPU and memory usage of an application on embedded
|
||||||
a limited extent, on Linux desktop platforms. The CPU Usage Analyzer uses
|
devices and, to a limited extent, on Linux desktop platforms. The
|
||||||
the Perf tool bundled with the Linux kernel to take periodic snapshots of
|
Performance Analyzer uses the Perf tool bundled with the Linux kernel to
|
||||||
the call chain of an application and visualizes them in a timeline view or
|
take periodic snapshots of the call chain of an application and visualizes
|
||||||
as a flame graph.
|
them in a timeline view or as a flame graph.
|
||||||
|
|
||||||
\section1 Using the CPU Usage Analyzer
|
\section1 Using the Performance Analyzer
|
||||||
|
|
||||||
The CPU Usage Analyzer usually needs to be able to locate debug symbols for
|
The Performance Analyzer usually needs to be able to locate debug symbols for
|
||||||
the binaries involved.
|
the binaries involved.
|
||||||
|
|
||||||
Profile builds produce optimized binaries with separate debug symbols and
|
Profile builds produce optimized binaries with separate debug symbols and
|
||||||
@@ -69,16 +69,16 @@
|
|||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
You can start the CPU Usage Analyzer in the following ways:
|
You can start the Performance Analyzer in the following ways:
|
||||||
|
|
||||||
\list
|
\list
|
||||||
\li Select \uicontrol Analyze > \uicontrol {CPU Usage Analyzer} to
|
\li Select \uicontrol Analyze > \uicontrol {Performance Analyzer} to
|
||||||
profile the current application.
|
profile the current application.
|
||||||
|
|
||||||
\li Select the
|
\li Select the
|
||||||
\inlineimage qtcreator-analyze-start-button.png
|
\inlineimage qtcreator-analyze-start-button.png
|
||||||
(\uicontrol Start) button to start the application from the
|
(\uicontrol Start) button to start the application from the
|
||||||
CPU Usage Analyzer.
|
Performance Analyzer.
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
(\uicontrol {Collect profile data}) button.
|
(\uicontrol {Collect profile data}) button.
|
||||||
|
|
||||||
When you start analyzing an application, the application is launched, and
|
When you start analyzing an application, the application is launched, and
|
||||||
the CPU Usage Analyzer immediately begins to collect data. This is indicated
|
the Performance Analyzer immediately begins to collect data. This is indicated
|
||||||
by the time running in the \uicontrol Recorded field. However, as the data
|
by the time running in the \uicontrol Recorded field. However, as the data
|
||||||
is passed through the Perf tool and an extra helper program bundled with
|
is passed through the Perf tool and an extra helper program bundled with
|
||||||
\QC, and both buffer and process it on the fly, data may arrive in \QC
|
\QC, and both buffer and process it on the fly, data may arrive in \QC
|
||||||
@@ -103,16 +103,28 @@
|
|||||||
Profile data will still be generated, but \QC will discard it until you
|
Profile data will still be generated, but \QC will discard it until you
|
||||||
select the button again.
|
select the button again.
|
||||||
|
|
||||||
\section1 Specifying CPU Usage Analyzer Settings
|
\section1 Profiling Memory Usage on Devices
|
||||||
|
|
||||||
To specify global settings for the CPU Usage Analyzer, select
|
To create trace points for profiling memory usage on a target device, select
|
||||||
|
\uicontrol Analyze > \uicontrol {Performance Analyzer Options} >
|
||||||
|
\uicontrol {Create Memory Trace Points}.
|
||||||
|
|
||||||
|
To add events for the trace points, see \l{Choosing Event Types}
|
||||||
|
|
||||||
|
You can record a memory trace to view usage graphs in the samples rows of
|
||||||
|
the timeline and to view memory allocations, peaks, and releases in the
|
||||||
|
flame graph.
|
||||||
|
|
||||||
|
\section1 Specifying Performance Analyzer Settings
|
||||||
|
|
||||||
|
To specify global settings for the Performance Analyzer, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
|
\uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
|
||||||
\uicontrol {CPU Usage Analyzer}. For each run configuration, you can also
|
\uicontrol {CPU Usage}. For each run configuration, you can also
|
||||||
use specialized settings. Select \uicontrol Projects > \uicontrol Run, and
|
use specialized settings. Select \uicontrol Projects > \uicontrol Run, and
|
||||||
then select \uicontrol Details next to
|
then select \uicontrol Details next to
|
||||||
\uicontrol {CPU Usage Analyzer Settings}.
|
\uicontrol {Performance Analyzer Settings}.
|
||||||
|
|
||||||
\image qtcreator-cpu-usage-analyzer-settings.png
|
\image qtcreator-performance-analyzer-settings.png
|
||||||
|
|
||||||
To edit the settings for the current run configuration, you can also select
|
To edit the settings for the current run configuration, you can also select
|
||||||
the dropdown menu next to the \uicontrol {Collect profile data} button.
|
the dropdown menu next to the \uicontrol {Collect profile data} button.
|
||||||
@@ -120,12 +132,12 @@
|
|||||||
\section2 Choosing Event Types
|
\section2 Choosing Event Types
|
||||||
|
|
||||||
In the \uicontrol Events table, you can specify which events should trigger
|
In the \uicontrol Events table, you can specify which events should trigger
|
||||||
the CPU Usage Analyzer to take a sample. The most common way of analyzing
|
the Performance Analyzer to take a sample. The most common way of analyzing
|
||||||
CPU usage involves periodic sampling, driven by hardware performance
|
CPU usage involves periodic sampling, driven by hardware performance
|
||||||
counters that react to the number of instructions or CPU cycles executed.
|
counters that react to the number of instructions or CPU cycles executed.
|
||||||
Alternatively, a software counter that uses the CPU clock can be chosen.
|
Alternatively, a software counter that uses the CPU clock can be chosen.
|
||||||
|
|
||||||
Select \uicontrol Add to add events to the table.
|
Select \uicontrol {Add Event} to add events to the table.
|
||||||
In the \uicontrol {Event Type} column, you can choose the general type of
|
In the \uicontrol {Event Type} column, you can choose the general type of
|
||||||
event to be sampled, most commonly \uicontrol {hardware} or
|
event to be sampled, most commonly \uicontrol {hardware} or
|
||||||
\uicontrol {software}. In the \uicontrol {Counter} column, you can choose
|
\uicontrol {software}. In the \uicontrol {Counter} column, you can choose
|
||||||
@@ -141,7 +153,19 @@
|
|||||||
\uicontrol {L1-dcache} on the \uicontrol {load} operation with a result
|
\uicontrol {L1-dcache} on the \uicontrol {load} operation with a result
|
||||||
of \uicontrol {misses}. That would sample L1-dcache misses on reading.
|
of \uicontrol {misses}. That would sample L1-dcache misses on reading.
|
||||||
|
|
||||||
Select \uicontrol Remove to remove the selected event from the table.
|
Select \uicontrol {Remove Event} to remove the selected event from the
|
||||||
|
table.
|
||||||
|
|
||||||
|
Select \uicontrol {Use Trace Points} to replace the current selection of
|
||||||
|
events with trace points defined on the target device and set the
|
||||||
|
\uicontrol {Sample mode} to \uicontrol {event count} and the
|
||||||
|
\uicontrol {Sample period} to \c {1}. If the trace points on the target
|
||||||
|
were defined using the \uicontrol {Create Trace Points} option, the
|
||||||
|
Performance Analyzer will automatically use them to profile memory usage.
|
||||||
|
|
||||||
|
Select \uicontrol {Reset} to revert the selection of events, as well as the
|
||||||
|
\uicontrol {Sample mode} and \uicontrol {Sample period} to the default
|
||||||
|
values.
|
||||||
|
|
||||||
\section2 Choosing a Sampling Mode and Period
|
\section2 Choosing a Sampling Mode and Period
|
||||||
|
|
||||||
@@ -154,7 +178,7 @@
|
|||||||
a sample every \c n times one of the chosen events has occurred,
|
a sample every \c n times one of the chosen events has occurred,
|
||||||
where \c n is specified in the \uicontrol {Sample period} field.
|
where \c n is specified in the \uicontrol {Sample period} field.
|
||||||
|
|
||||||
\li Sampling by \uicontrol {frequency} instructs the kernel to try and
|
\li Sampling by \uicontrol {frequency (Hz)} instructs the kernel to try and
|
||||||
take a sample \c n times per second, by automatically adjusting the
|
take a sample \c n times per second, by automatically adjusting the
|
||||||
sampling period. Specify \c n in the \uicontrol {Sample period}
|
sampling period. Specify \c n in the \uicontrol {Sample period}
|
||||||
field.
|
field.
|
||||||
@@ -168,7 +192,7 @@
|
|||||||
There may be a significant difference between the sampling period you
|
There may be a significant difference between the sampling period you
|
||||||
request and the actual result.
|
request and the actual result.
|
||||||
|
|
||||||
In general, if you configure the CPU Usage Analyzer to collect more data
|
In general, if you configure the Performance Analyzer to collect more data
|
||||||
than it can transmit over the connection between the target and the host
|
than it can transmit over the connection between the target and the host
|
||||||
device, the application may get blocked while Perf is trying to send the
|
device, the application may get blocked while Perf is trying to send the
|
||||||
data, and the processing delay may grow excessively. You should then change
|
data, and the processing delay may grow excessively. You should then change
|
||||||
@@ -176,25 +200,33 @@
|
|||||||
|
|
||||||
\section2 Selecting Call Graph Mode
|
\section2 Selecting Call Graph Mode
|
||||||
|
|
||||||
In the \uicontrol {Call graph mode} field, you can specify how the CPU Usage
|
In the \uicontrol {Call graph mode} field, you can specify how the
|
||||||
Analyzer recovers call chains from your application.
|
Performance Analyzer recovers call chains from your application:
|
||||||
|
|
||||||
The \uicontrol {Frame Pointer}, or \c fp, mode relies on frame pointers
|
\list
|
||||||
|
|
||||||
|
\li The \uicontrol {Frame Pointer}, or \c fp, mode relies on frame pointers
|
||||||
being available in the profiled application and will instruct the kernel on
|
being available in the profiled application and will instruct the kernel on
|
||||||
the target device to walk the chain of frame pointers in order to retrieve
|
the target device to walk the chain of frame pointers in order to retrieve
|
||||||
a call chain for each sample.
|
a call chain for each sample.
|
||||||
|
|
||||||
The \uicontrol {Dwarf} mode works also without frame pointers, but
|
\li The \uicontrol {Dwarf} mode works also without frame pointers, but
|
||||||
generates significantly more data. It takes a snapshot of the current
|
generates significantly more data. It takes a snapshot of the current
|
||||||
application stack each time a sample is triggered and transmits that
|
application stack each time a sample is triggered and transmits that
|
||||||
snapshot to the host computer for analysis.
|
snapshot to the host computer for analysis.
|
||||||
|
|
||||||
|
\li The \uicontrol {Last Branch Record} mode does not use a memory buffer.
|
||||||
|
It automatically decodes the last 16 taken branches every time execution
|
||||||
|
stops. It is supported only on recent Intel CPUs.
|
||||||
|
|
||||||
|
\endlist
|
||||||
|
|
||||||
Qt and most system libraries are compiled without frame pointers by
|
Qt and most system libraries are compiled without frame pointers by
|
||||||
default, so the frame pointer mode is only useful with customized systems.
|
default, so the frame pointer mode is only useful with customized systems.
|
||||||
|
|
||||||
\section2 Setting Stack Snapshot Size
|
\section2 Setting Stack Snapshot Size
|
||||||
|
|
||||||
The CPU Usage Analyzer will analyze and \e unwind the stack snapshots
|
The Performance Analyzer will analyze and \e unwind the stack snapshots
|
||||||
generated by Perf in dwarf mode. Set the size of the stack snapshots in the
|
generated by Perf in dwarf mode. Set the size of the stack snapshots in the
|
||||||
\uicontrol {Stack snapshot size} field. Large stack snapshots result in a
|
\uicontrol {Stack snapshot size} field. Large stack snapshots result in a
|
||||||
larger volume of data to be transferred and processed. Small stack
|
larger volume of data to be transferred and processed. Small stack
|
||||||
@@ -212,7 +244,7 @@
|
|||||||
\section2 Resolving Names for JIT-compiled JavaScript Functions
|
\section2 Resolving Names for JIT-compiled JavaScript Functions
|
||||||
|
|
||||||
Since version 5.6.0, Qt can generate perf.map files with information about
|
Since version 5.6.0, Qt can generate perf.map files with information about
|
||||||
JavaScript functions. The CPU Usage Analyzer will read them and show the
|
JavaScript functions. The Performance Analyzer will read them and show the
|
||||||
function names in the \uicontrol Timeline, \uicontrol Statistics, and
|
function names in the \uicontrol Timeline, \uicontrol Statistics, and
|
||||||
\uicontrol {Flame Graph} views. This only works if the process being
|
\uicontrol {Flame Graph} views. This only works if the process being
|
||||||
profiled is running on the host computer, not on the target device. To
|
profiled is running on the host computer, not on the target device. To
|
||||||
@@ -225,30 +257,30 @@
|
|||||||
The \uicontrol Timeline view displays a graphical representation of CPU
|
The \uicontrol Timeline view displays a graphical representation of CPU
|
||||||
usage per thread and a condensed view of all recorded events.
|
usage per thread and a condensed view of all recorded events.
|
||||||
|
|
||||||
\image cpu-usage-analyzer.png "CPU Usage Analyzer"
|
\image qtcreator-performance-analyzer-timeline.png "Performance Analyzer"
|
||||||
|
|
||||||
Each category in the timeline describes a thread in the application. Move
|
Each category in the timeline describes a thread in the application. Move
|
||||||
the cursor on an event (6) on a row to see how long it takes and which
|
the cursor on an event (5) on a row to see how long it takes and which
|
||||||
function in the source it represents. To display the information only when
|
function in the source it represents. To display the information only when
|
||||||
an event is selected, disable the
|
an event is selected, disable the
|
||||||
\uicontrol {View Event Information on Mouseover} button (5).
|
\uicontrol {View Event Information on Mouseover} button (4).
|
||||||
|
|
||||||
The outline (10) summarizes the period for which data was collected. Drag
|
The outline (9) 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 (7) or click the outline to move on the outline. You can
|
||||||
also move between events by selecting the
|
also move between events by selecting the
|
||||||
\uicontrol {Jump to Previous Event} (1) and \uicontrol {Jump to Next Event}
|
\uicontrol {Jump to Previous Event} and \uicontrol {Jump to Next Event}
|
||||||
(2) buttons.
|
buttons (1).
|
||||||
|
|
||||||
Select the \uicontrol {Show Zoom Slider} button (3) to open a slider that
|
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).
|
you can use to set the zoom level. You can also drag the zoom handles (8).
|
||||||
To reset the default zoom level, right-click the timeline to open the
|
To reset the default zoom level, right-click the timeline to open the
|
||||||
context menu, and select \uicontrol {Reset Zoom}.
|
context menu, and select \uicontrol {Reset Zoom}.
|
||||||
|
|
||||||
\section2 Selecting Event Ranges
|
\section2 Selecting Event Ranges
|
||||||
|
|
||||||
You can select an event range (7) to view the time it represents or to zoom
|
You can select an event range (6) to view the time it represents or to zoom
|
||||||
into a specific region of the trace. Select the \uicontrol {Select Range}
|
into a specific region of the trace. Select the \uicontrol {Select Range}
|
||||||
button (4) to activate the selection tool. Then click in the timeline to
|
button (3) to activate the selection tool. Then click in the timeline to
|
||||||
specify the beginning of the event range. Drag the selection handle to
|
specify the beginning of the event range. Drag the selection handle to
|
||||||
define the end of the range.
|
define the end of the range.
|
||||||
|
|
||||||
@@ -276,10 +308,10 @@
|
|||||||
events to move the cursor in the code editor to the part of the code the
|
events to move the cursor in the code editor to the part of the code the
|
||||||
event is associated with.
|
event is associated with.
|
||||||
|
|
||||||
As the Perf tool only provides periodic samples, the CPU Usage Analyzer
|
As the Perf tool only provides periodic samples, the Performance Analyzer
|
||||||
cannot determine the exact time when a function was called or when it
|
cannot determine the exact time when a function was called or when it
|
||||||
returned. You can, however, see exactly when a sample was taken in the
|
returned. You can, however, see exactly when a sample was taken in the
|
||||||
second row of each thread. The CPU Usage Analyzer assumes that if the same
|
second row of each thread. The Performance Analyzer assumes that if the same
|
||||||
function is present at the same place in the call chain in multiple
|
function is present at the same place in the call chain in multiple
|
||||||
consecutive samples, then this represents a single call to the respective
|
consecutive samples, then this represents a single call to the respective
|
||||||
function. This is, of course, a simplification. Also, there may be other
|
function. This is, of course, a simplification. Also, there may be other
|
||||||
@@ -318,7 +350,7 @@
|
|||||||
|
|
||||||
\section1 Viewing Statistics
|
\section1 Viewing Statistics
|
||||||
|
|
||||||
\image qtcreator-cpu-usage-analyzer-statistics.png
|
\image qtcreator-performance-analyzer-statistics.png
|
||||||
|
|
||||||
The \uicontrol Statistics view displays the number of samples each function
|
The \uicontrol Statistics view displays the number of samples each function
|
||||||
in the timeline was contained in, in total and when on the top of the
|
in the timeline was contained in, in total and when on the top of the
|
||||||
@@ -344,12 +376,39 @@
|
|||||||
|
|
||||||
\section2 Visualizing Statistics as Flame Graphs
|
\section2 Visualizing Statistics as Flame Graphs
|
||||||
|
|
||||||
\image qtcreator-cpu-usage-analyzer-flamegraph.png
|
\image qtcreator-performance-analyzer-flamegraph.png
|
||||||
|
|
||||||
The \uicontrol {Flame Graph} view shows a more concise statistical overview
|
The \uicontrol {Flame Graph} view shows a more concise statistical overview
|
||||||
of the execution. The horizontal bars show the total number of samples
|
of the execution. The horizontal bars show an aspect of the samples
|
||||||
taken for a certain function, relative to the total number of samples. The
|
taken for a certain function, relative to the same aspect of all samples
|
||||||
nesting shows which functions were called by which other ones.
|
together. The nesting shows which functions were called by which other ones.
|
||||||
|
|
||||||
|
The \uicontrol {Visualize} button lets you choose what aspect to show in the
|
||||||
|
\uicontrol {Flame Graph}.
|
||||||
|
|
||||||
|
\list
|
||||||
|
|
||||||
|
\li \uicontrol {Samples} is the default visualization. The size of the
|
||||||
|
horizontal bars represents the number of samples recorded for the given
|
||||||
|
function.
|
||||||
|
|
||||||
|
\li In \uicontrol {Peak Usage} mode, the size of the horizontal bars
|
||||||
|
represents the amount of memory allocated by the respective functions, at
|
||||||
|
the point in time when the allocation's memory usage was at its peak.
|
||||||
|
|
||||||
|
\li In \uicontrol {Allocations} mode, the size of the horizontal bars
|
||||||
|
represents the number of memory allocations triggered by the respective
|
||||||
|
functions.
|
||||||
|
|
||||||
|
\li In \uicontrol {Releases} mode, the size of the horizontal bars
|
||||||
|
represents the number of memory releases triggered by the respective
|
||||||
|
functions.
|
||||||
|
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
The \uicontrol {Peak Usage}, \uicontrol {Allocations}, and
|
||||||
|
\uicontrol {Releases} modes will only show any data if samples from memory
|
||||||
|
trace points have been recorded.
|
||||||
|
|
||||||
\section2 Interaction between the views
|
\section2 Interaction between the views
|
||||||
|
|
||||||
@@ -357,19 +416,20 @@
|
|||||||
\uicontrol {Flame Graph}, or \uicontrol {Statistics} views, information
|
\uicontrol {Flame Graph}, or \uicontrol {Statistics} views, information
|
||||||
about it is displayed in the other two views. To view a time range in the
|
about it is displayed in the other two views. To view a time range in the
|
||||||
\uicontrol {Statistics} and \uicontrol {Flame Graph} views, select
|
\uicontrol {Statistics} and \uicontrol {Flame Graph} views, select
|
||||||
\uicontrol {Limit Statistics to Selected Range} in the context menu in the
|
\uicontrol Analyze > \uicontrol {Performance Analyzer Options} >
|
||||||
\uicontrol {Timeline} view.
|
\uicontrol {Limit to the Range Selected in Timeline}. To show the full
|
||||||
|
stack frame, select \uicontrol {Show Full Range}.
|
||||||
|
|
||||||
\section1 Loading Perf Data Files
|
\section1 Loading Perf Data Files
|
||||||
|
|
||||||
You can load any \c perf.data files generated by recent versions of the
|
You can load any \c perf.data files generated by recent versions of the
|
||||||
Linux Perf tool and view them in \QC. Select \uicontrol Analyze >
|
Linux Perf tool and view them in \QC. Select \uicontrol Analyze >
|
||||||
\uicontrol {CPU Usage Analyzer Options} > \uicontrol {Load perf.data} to
|
\uicontrol {Performance Analyzer Options} > \uicontrol {Load perf.data} to
|
||||||
load a file.
|
load a file.
|
||||||
|
|
||||||
\image qtcreator-cpu-usage-analyzer-load-perf-trace.png
|
\image qtcreator-cpu-usage-analyzer-load-perf-trace.png
|
||||||
|
|
||||||
The CPU Usage Analyzer needs to know the context in which the
|
The Performance Analyzer needs to know the context in which the
|
||||||
data was recorded to find the debug symbols. Therefore, you have to specify
|
data was recorded to find the debug symbols. Therefore, you have to specify
|
||||||
the kit that the application was built with and the folder where the
|
the kit that the application was built with and the folder where the
|
||||||
application executable is located.
|
application executable is located.
|
||||||
@@ -377,11 +437,11 @@
|
|||||||
The Perf data files are generated by calling \c {perf record}. Make sure to
|
The Perf data files are generated by calling \c {perf record}. Make sure to
|
||||||
generate call graphs when recording data by starting Perf with the
|
generate call graphs when recording data by starting Perf with the
|
||||||
\c {--call-graph} option. Also check that the necessary debug symbols are
|
\c {--call-graph} option. Also check that the necessary debug symbols are
|
||||||
available to the CPU Usage Analyzer, either at a standard location
|
available to the Performance Analyzer, either at a standard location
|
||||||
(\c /usr/lib/debug or next to the binaries), or as part of the Qt package
|
(\c /usr/lib/debug or next to the binaries), or as part of the Qt package
|
||||||
you are using.
|
you are using.
|
||||||
|
|
||||||
The CPU Usage Analyzer can read Perf data files generated in either frame
|
The Performance Analyzer can read Perf data files generated in either frame
|
||||||
pointer or dwarf mode. However, to generate the files correctly, numerous
|
pointer or dwarf mode. However, to generate the files correctly, numerous
|
||||||
preconditions have to be met. All system images for the
|
preconditions have to be met. All system images for the
|
||||||
\l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
|
\l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
|
||||||
@@ -394,15 +454,15 @@
|
|||||||
\section1 Loading and Saving Trace Files
|
\section1 Loading and Saving Trace Files
|
||||||
|
|
||||||
You can save and load trace data in a format specific to the
|
You can save and load trace data in a format specific to the
|
||||||
CPU Usage Analyzer with the respective entries in \uicontrol Analyze >
|
Performance Analyzer with the respective entries in \uicontrol Analyze >
|
||||||
\uicontrol {CPU Usage Analyzer Options}. This format is self-contained, and
|
\uicontrol {Performance Analyzer Options}. This format is self-contained, and
|
||||||
therefore loading it does not require you to specify the recording
|
therefore loading it does not require you to specify the recording
|
||||||
environment. You can transfer such trace files to a different computer
|
environment. You can transfer such trace files to a different computer
|
||||||
without any tool chain or debug symbols and analyze them there.
|
without any tool chain or debug symbols and analyze them there.
|
||||||
|
|
||||||
\section1 Troubleshooting
|
\section1 Troubleshooting
|
||||||
|
|
||||||
The CPU Usage Analyzer might fail to record data for the following reasons:
|
The Performance Analyzer might fail to record data for the following reasons:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li Perf events may be globally disabled on your system. The
|
\li Perf events may be globally disabled on your system. The
|
||||||
|
|||||||
@@ -75,10 +75,10 @@
|
|||||||
You can use the Heob heap observer on Windows to detect buffer
|
You can use the Heob heap observer on Windows to detect buffer
|
||||||
overruns and memory leaks.
|
overruns and memory leaks.
|
||||||
|
|
||||||
\li \l{Analyzing CPU Usage}{CPU Usage Analyzer}
|
\li \l{Analyzing CPU Usage}{Performance Analyzer}
|
||||||
|
|
||||||
You can analyze the CPU usage of embedded applications and Linux
|
You can analyze the CPU usage of embedded applications and Linux
|
||||||
desktop applications with the CPU Usage Analyzer (commercial only)
|
desktop applications with the Performance Analyzer (commercial only)
|
||||||
that integrates the Linux Perf tool.
|
that integrates the Linux Perf tool.
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|||||||
@@ -68,14 +68,12 @@
|
|||||||
|
|
||||||
\li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}.
|
\li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}.
|
||||||
|
|
||||||
\image qtcreator-files-to-analyze.png
|
\image qtcreator-files-to-analyze.png "Analyzer Configuration dialog"
|
||||||
|
|
||||||
\li In the \uicontrol {Diagnostic Configuration} group, select
|
\li In the \uicontrol {Diagnostic Configuration} group, select a Clang
|
||||||
\uicontrol {Custom Settings}, and then select \uicontrol Manage to
|
configuration in the list of pre-defined configurations (1). For
|
||||||
specify the Clang-Tidy and Clazy checks to perform.
|
more information about creating a custom configuration, see
|
||||||
|
\l {Configuring Clang Tools}.
|
||||||
\li Select the new custom configuration in the list of configurations
|
|
||||||
(1).
|
|
||||||
|
|
||||||
\li In the \uicontrol {Files to Analyze} group, select the files to
|
\li In the \uicontrol {Files to Analyze} group, select the files to
|
||||||
apply the checks to.
|
apply the checks to.
|
||||||
@@ -90,7 +88,10 @@
|
|||||||
(\uicontrol Start) button to open the \uicontrol {Analyzer Configuration}
|
(\uicontrol Start) button to open the \uicontrol {Analyzer Configuration}
|
||||||
dialog.
|
dialog.
|
||||||
|
|
||||||
\image qtcreator-clang-tools.png
|
The found issues are displayed in the \uicontrol {Clang-Tidy and Clazy}
|
||||||
|
view:
|
||||||
|
|
||||||
|
\image qtcreator-clang-tools.png "Clang-Tidy and Clazy view"
|
||||||
|
|
||||||
Select the link in the \uicontrol Location column to move to the location
|
Select the link in the \uicontrol Location column to move to the location
|
||||||
where the issue appears in the code editor.
|
where the issue appears in the code editor.
|
||||||
@@ -106,14 +107,35 @@
|
|||||||
\list
|
\list
|
||||||
|
|
||||||
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
|
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
|
||||||
\uicontrol {Clang Tools} > \uicontrol Manage.
|
\uicontrol {Clang Tools}.
|
||||||
|
|
||||||
\image qtcreator-clang-tools-options.png
|
\image qtcreator-clang-tools-options.png "Clang Tools options tab"
|
||||||
|
|
||||||
|
\li To build the project before running the Clang tools, select the
|
||||||
|
\uicontrol {Build the project before analysis} check box. The Clang
|
||||||
|
tools do not require the project to be built before analysis, but
|
||||||
|
they might display misleading warnings about files missing that are
|
||||||
|
generated during the build. For big projects, not building the
|
||||||
|
project might save some time.
|
||||||
|
|
||||||
|
\li In the \uicontrol {Simultaneous processes} field, select the number
|
||||||
|
of processes to run simultaneously to make the analysis faster on
|
||||||
|
multi-core processors.
|
||||||
|
|
||||||
|
\li In the \uicontrol {Diagnostic Configuration} group, select
|
||||||
|
\uicontrol Manage to create or edit a custom configuration.
|
||||||
|
|
||||||
|
\li Select \uicontrol Copy to create a custom Clang configuration.
|
||||||
|
|
||||||
|
\image qtcreator-diagnostics-configuration.png "Diagnostics Configuration dialog"
|
||||||
|
|
||||||
|
\li In the \uicontrol {Diagnostic configuration name} field, give the
|
||||||
|
configuration a name, and then select \uicontrol OK.
|
||||||
|
|
||||||
\li In the \uicontrol {Clang-Tidy} tab, select the checks to
|
\li In the \uicontrol {Clang-Tidy} tab, select the checks to
|
||||||
perform.
|
perform.
|
||||||
|
|
||||||
\image qtcreator-clang-tidy.png
|
\image qtcreator-clang-tidy.png "Clang-Tidy tab"
|
||||||
|
|
||||||
\li To edit the selected check as plain text, select
|
\li To edit the selected check as plain text, select
|
||||||
\uicontrol {Edit Checks as String}.
|
\uicontrol {Edit Checks as String}.
|
||||||
@@ -121,7 +143,7 @@
|
|||||||
\li In the \uicontrol Clazy tab, select the level of Clazy
|
\li In the \uicontrol Clazy tab, select the level of Clazy
|
||||||
checks to perform.
|
checks to perform.
|
||||||
|
|
||||||
\image qtcreator-clazy.png
|
\image qtcreator-clazy.png "Clazy tab"
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
\section1 Supported Native Debugger Versions
|
\section1 Supported Native Debugger Versions
|
||||||
|
|
||||||
Qt Creator supports native debuggers when working with compiled code. On
|
\QC supports native debuggers when working with compiled code. On
|
||||||
most supported platforms, the GNU Symbolic Debugger GDB can be used. On
|
most supported platforms, the GNU Symbolic Debugger GDB can be used. On
|
||||||
Microsoft Windows, when using the Microsoft tool chain the Microsoft Console
|
Microsoft Windows, when using the Microsoft tool chain the Microsoft Console
|
||||||
Debugger CDB, is needed. On \macos, the LLDB debugger can be used. Basic
|
Debugger CDB, is needed. On \macos, the LLDB debugger can be used. Basic
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
\note Visual Studio does not include the Debugging tools needed,
|
\note Visual Studio does not include the Debugging tools needed,
|
||||||
and therefore, you must install them separately.
|
and therefore, you must install them separately.
|
||||||
|
|
||||||
In addition, you must select \uicontrol {Qt Creator CDB Debugger Support}
|
In addition, you must select \uicontrol {\QC CDB Debugger Support}
|
||||||
(in \uicontrol Qt > \uicontrol Tools > \uicontrol {\QC}) when you install
|
(in \uicontrol Qt > \uicontrol Tools > \uicontrol {\QC}) when you install
|
||||||
Qt or the stand-alone \QC.
|
Qt or the stand-alone \QC.
|
||||||
|
|
||||||
@@ -328,7 +328,7 @@
|
|||||||
codesign -f -s "fsfgdb" $INSTALL_LOCATION/fsfgdb
|
codesign -f -s "fsfgdb" $INSTALL_LOCATION/fsfgdb
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\li In \QC, select \uicontrol {Qt Creator} > \uicontrol Preferences >
|
\li In \QC, select \uicontrol {\QC} > \uicontrol Preferences >
|
||||||
\uicontrol Kits > \uicontrol Add to
|
\uicontrol Kits > \uicontrol Add to
|
||||||
create a kit that uses FSF GDB.
|
create a kit that uses FSF GDB.
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,7 @@
|
|||||||
The \QC installation program asks you whether you want to register \QC as a
|
The \QC installation program asks you whether you want to register \QC as a
|
||||||
post-mortem debugger. To change the setting, select
|
post-mortem debugger. To change the setting, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
|
\uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
|
||||||
\uicontrol General > \uicontrol {Use Qt Creator for post-mortem debugging}.
|
\uicontrol General > \uicontrol {Use \QC for post-mortem debugging}.
|
||||||
|
|
||||||
You can launch the debugger in the post-mortem mode if an application
|
You can launch the debugger in the post-mortem mode if an application
|
||||||
crashes on Windows. Click the \uicontrol {Debug in \QC} button in the error
|
crashes on Windows. Click the \uicontrol {Debug in \QC} button in the error
|
||||||
@@ -979,7 +979,7 @@
|
|||||||
Unlike GDB's
|
Unlike GDB's
|
||||||
\l{https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing}
|
\l{https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing}
|
||||||
{pretty printers} and LLDB's \l{http://lldb.llvm.org/varformats.html}
|
{pretty printers} and LLDB's \l{http://lldb.llvm.org/varformats.html}
|
||||||
{data formatters}, Qt Creator's debugging helpers are independent of the
|
{data formatters}, \QC's debugging helpers are independent of the
|
||||||
native debugging backend. That is, the same code can be used with GDB on
|
native debugging backend. That is, the same code can be used with GDB on
|
||||||
Linux, LLDB on macOS, and CDB on Windows, or any other platform on which at
|
Linux, LLDB on macOS, and CDB on Windows, or any other platform on which at
|
||||||
least one of the three supported backends is available.
|
least one of the three supported backends is available.
|
||||||
|
|||||||
@@ -138,34 +138,33 @@
|
|||||||
edit the value for the \uicontrol {Do not index files greater than}
|
edit the value for the \uicontrol {Do not index files greater than}
|
||||||
check box. To index all files, deselect the check box.
|
check box. To index all files, deselect the check box.
|
||||||
|
|
||||||
\li Select \uicontrol Manage to specify the level for requesting Clang
|
\li Select \uicontrol Manage to specify the Clang checks to perform.
|
||||||
warnings.
|
|
||||||
|
|
||||||
\image qtcreator-diagnostics-configuration.png
|
\image qtcreator-diagnostics-configuration.png
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\section1 Clang Warnings
|
\section1 Clang Checks
|
||||||
|
|
||||||
The predefined configurations request Clang warnings at the following
|
The predefined configurations perform the following Clang checks:
|
||||||
levels:
|
|
||||||
|
|
||||||
\list
|
\list
|
||||||
|
|
||||||
\li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic option that
|
\li \uicontrol {Clang-only pedantic checks} uses the \c -Wpendantic
|
||||||
requests all the warnings demanded by strict ISO C and ISO C++.
|
option that performs checks as required by strict ISO C and ISO C++.
|
||||||
|
|
||||||
\li \uicontrol {Warnings for Questionable Constructs} combines the
|
\li \uicontrol {Clang-only checks for questionable constructs} combines
|
||||||
\c -Wall and \c -Wextra options to request all warnings about easily
|
the \c -Wall and \c -Wextra checks for easily avoidable questionable
|
||||||
avoidable questionable constructions and some additional warnings.
|
constructions and some additional issues.
|
||||||
|
|
||||||
\li \uicontrol {Warnings for Almost Everything} uses the \c -Weverything
|
\li \uicontrol {Clang-only checks for almost everything} uses the
|
||||||
option with negative options to suppress some warnings.
|
\c -Weverything option with negative options to suppress some
|
||||||
|
warnings.
|
||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
You can edit the predefined configurations to request specific warnings
|
You can edit the predefined configurations to perform particular checks
|
||||||
beginning with \c -W. Each of these warnings also has a negative version
|
beginning with \c -W. Each of these checks also has a negative version
|
||||||
that begins with \c -Wno.
|
that begins with \c -Wno.
|
||||||
|
|
||||||
Keep in mind that some options turn on other options. For more information,
|
Keep in mind that some options turn on other options. For more information,
|
||||||
|
|||||||
@@ -132,7 +132,7 @@
|
|||||||
|
|
||||||
\QC creates the test in the specified project directory.
|
\QC creates the test in the specified project directory.
|
||||||
For more information about creating Google tests, see the
|
For more information about creating Google tests, see the
|
||||||
\l{https://github.com/google/googletest/blob/master/googletest/docs/Primer.md}
|
\l{https://github.com/google/googletest/blob/master/googletest/docs/primer.md}
|
||||||
{Google Test Primer}.
|
{Google Test Primer}.
|
||||||
|
|
||||||
\section1 Setting Up the Google C++ Testing Framework
|
\section1 Setting Up the Google C++ Testing Framework
|
||||||
|
|||||||
@@ -645,13 +645,13 @@
|
|||||||
\li Look In
|
\li Look In
|
||||||
\row
|
\row
|
||||||
\li \uicontrol Tools > \uicontrol Options
|
\li \uicontrol Tools > \uicontrol Options
|
||||||
\li \uicontrol {Qt Creator} > \uicontrol Preferences
|
\li \uicontrol {\QC} > \uicontrol Preferences
|
||||||
\row
|
\row
|
||||||
\li \uicontrol Help > \uicontrol {About Plugins}
|
\li \uicontrol Help > \uicontrol {About Plugins}
|
||||||
\li \uicontrol {Qt Creator} > \uicontrol {About Plugins}
|
\li \uicontrol {\QC} > \uicontrol {About Plugins}
|
||||||
\row
|
\row
|
||||||
\li Keyboard shortcuts
|
\li Keyboard shortcuts
|
||||||
\li \uicontrol {Qt Creator} > \uicontrol Preferences > \uicontrol Environment >
|
\li \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Environment >
|
||||||
\uicontrol Keyboard
|
\uicontrol Keyboard
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
\contentspage {Qt Creator Manual}
|
\contentspage {Qt Creator Manual}
|
||||||
\page creator-commercial-overview.html
|
\page creator-commercial-overview.html
|
||||||
|
|
||||||
\title Qt Creator Commercial Features
|
\title Commercial Features
|
||||||
|
|
||||||
\commercial
|
\commercial
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
\l{http://qt.io/licensing/}{Qt license}:
|
\l{http://qt.io/licensing/}{Qt license}:
|
||||||
|
|
||||||
\list
|
\list
|
||||||
\li \l{Analyzing CPU Usage}{CPU Usage Analyzer}
|
\li \l{Analyzing CPU Usage}{Performance Analyzer}
|
||||||
\li \l{Browsing ISO 7000 Icons} in \QMLD
|
\li \l{Browsing ISO 7000 Icons} in \QMLD
|
||||||
\li \l{http://doc.qt.io/QtForDeviceCreation/index.html}{Developing for
|
\li \l{http://doc.qt.io/QtForDeviceCreation/index.html}{Developing for
|
||||||
embedded devices}
|
embedded devices}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
\image qtcreator-custom-wizard.png
|
\image qtcreator-custom-wizard.png
|
||||||
|
|
||||||
\section1 Integrating Wizards into Qt Creator Builds
|
\section1 Integrating Wizards into Builds
|
||||||
|
|
||||||
To integrate the wizard into \QC and to deliver it as part of the \QC build,
|
To integrate the wizard into \QC and to deliver it as part of the \QC build,
|
||||||
place the wizard files in the \QC sources. Then select \uicontrol Build >
|
place the wizard files in the \QC sources. Then select \uicontrol Build >
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
settings directory to ensure that different \QC instances do not overwrite
|
settings directory to ensure that different \QC instances do not overwrite
|
||||||
each other's profiles. If you only run one \QC instance, you can store the
|
each other's profiles. If you only run one \QC instance, you can store the
|
||||||
profiles in the Qbs settings directory instead, by deselecting the
|
profiles in the Qbs settings directory instead, by deselecting the
|
||||||
\uicontrol {Store profiles in Qt Creator settings directory} check box.
|
\uicontrol {Store profiles in \QC settings directory} check box.
|
||||||
|
|
||||||
In the \uicontrol Kit field, select a build and run kit to view the
|
In the \uicontrol Kit field, select a build and run kit to view the
|
||||||
properties of the associated Qbs profile. To modify the properties of the
|
properties of the associated Qbs profile. To modify the properties of the
|
||||||
|
|||||||
@@ -160,7 +160,7 @@
|
|||||||
|
|
||||||
To generate debug symbols also for applications compiled in release mode,
|
To generate debug symbols also for applications compiled in release mode,
|
||||||
select the \uicontrol {Generate separate debug info} check box. For more
|
select the \uicontrol {Generate separate debug info} check box. For more
|
||||||
information, see \l{Using the CPU Usage Analyzer}.
|
information, see \l{Using the Performance Analyzer}.
|
||||||
|
|
||||||
\section3 Compiling QML
|
\section3 Compiling QML
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
This manual also describes features that are only available if you have the
|
This manual also describes features that are only available if you have the
|
||||||
appropriate \l{http://qt.io/licensing/}{Qt license}. For more information,
|
appropriate \l{http://qt.io/licensing/}{Qt license}. For more information,
|
||||||
see \l{Qt Creator Commercial Features}.
|
see \l{Commercial Features}.
|
||||||
|
|
||||||
\table
|
\table
|
||||||
\row
|
\row
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
\note Kits are listed if they have been specified in \uicontrol
|
\note Kits are listed if they have been specified in \uicontrol
|
||||||
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
|
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
|
||||||
or in \uicontrol {Qt Creator} > \uicontrol Preferences >
|
or in \uicontrol {\QC} > \uicontrol Preferences >
|
||||||
\uicontrol Kits (on \macos).
|
\uicontrol Kits (on \macos).
|
||||||
|
|
||||||
\li Select \uicontrol Next.
|
\li Select \uicontrol Next.
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
\note Kits are listed if they have been specified in \uicontrol
|
\note Kits are listed if they have been specified in \uicontrol
|
||||||
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
|
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
|
||||||
or in \uicontrol {Qt Creator} > \uicontrol Preferences >
|
or in \uicontrol {\QC} > \uicontrol Preferences >
|
||||||
\uicontrol Kits (on \macos).
|
\uicontrol Kits (on \macos).
|
||||||
|
|
||||||
\li Select \uicontrol Next.
|
\li Select \uicontrol Next.
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
\section1 Exporting from Adobe Photoshop to QML
|
\section1 Exporting from Adobe Photoshop to QML
|
||||||
|
|
||||||
You can use a QML Asset Exporter to export designs from Adobe Photoshop
|
You can use a QML Asset Exporter to export designs from Adobe Photoshop
|
||||||
to .ui.qml files. The the QML Asset Exporter provides templates that are
|
to .ui.qml files. The QML Asset Exporter provides templates that are
|
||||||
based on the \l{http://www.pngexpress.com}{PNG EXPRESS} plugin for
|
based on the \l{http://www.pngexpress.com}{PNG EXPRESS} plugin for
|
||||||
Photoshop. They enable you to export PSD files to QML format, so that each
|
Photoshop. They enable you to export PSD files to QML format, so that each
|
||||||
PSD file is converted into an .ui.qml file.
|
PSD file is converted into an .ui.qml file.
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
|
|
||||||
\note If only one kit is specified in \uicontrol Tools >
|
\note If only one kit is specified in \uicontrol Tools >
|
||||||
\uicontrol Options > \uicontrol Kits (on Windows and Linux) or in
|
\uicontrol Options > \uicontrol Kits (on Windows and Linux) or in
|
||||||
\uicontrol {Qt Creator} > \uicontrol Preferences > \uicontrol Kits
|
\uicontrol {\QC} > \uicontrol Preferences > \uicontrol Kits
|
||||||
(on \macos), this dialog is skipped.
|
(on \macos), this dialog is skipped.
|
||||||
|
|
||||||
The \uicontrol{Class Information} dialog opens.
|
The \uicontrol{Class Information} dialog opens.
|
||||||
|
|||||||
8
docs.pri
@@ -5,6 +5,12 @@
|
|||||||
|
|
||||||
isEmpty(VERSION): error("Include qtcreator.pri before including docs.pri!")
|
isEmpty(VERSION): error("Include qtcreator.pri before including docs.pri!")
|
||||||
|
|
||||||
|
qtcname.name = IDE_DISPLAY_NAME
|
||||||
|
qtcname.value = "$$IDE_DISPLAY_NAME"
|
||||||
|
qtcid.name = IDE_ID
|
||||||
|
qtcid.value = $$IDE_ID
|
||||||
|
qtccasedid.name = IDE_CASED_ID
|
||||||
|
qtccasedid.value = $$IDE_CASED_ID
|
||||||
qtcver.name = QTC_VERSION
|
qtcver.name = QTC_VERSION
|
||||||
qtcver.value = $$QTCREATOR_DISPLAY_VERSION
|
qtcver.value = $$QTCREATOR_DISPLAY_VERSION
|
||||||
qtcvertag.name = QTC_VERSION_TAG
|
qtcvertag.name = QTC_VERSION_TAG
|
||||||
@@ -17,7 +23,7 @@ qtcdocsdir.name = QTC_DOCS_DIR
|
|||||||
qtcdocsdir.value = $$IDE_SOURCE_TREE/doc
|
qtcdocsdir.value = $$IDE_SOURCE_TREE/doc
|
||||||
qtccopyrightyear.name = QTCREATOR_COPYRIGHT_YEAR
|
qtccopyrightyear.name = QTCREATOR_COPYRIGHT_YEAR
|
||||||
qtccopyrightyear.value = $$QTCREATOR_COPYRIGHT_YEAR
|
qtccopyrightyear.value = $$QTCREATOR_COPYRIGHT_YEAR
|
||||||
QDOC_ENV += qtcver qtcvertag qtdocs qdocindex qtcdocsdir qtccopyrightyear
|
QDOC_ENV += qtcname qtcid qtccasedid qtcver qtcvertag qtdocs qdocindex qtcdocsdir qtccopyrightyear
|
||||||
|
|
||||||
DOC_INDEX_PATHS += $$IDE_BUILD_TREE/doc
|
DOC_INDEX_PATHS += $$IDE_BUILD_TREE/doc
|
||||||
DOC_HTML_INSTALLDIR = $$INSTALL_DOC_PATH
|
DOC_HTML_INSTALLDIR = $$INSTALL_DOC_PATH
|
||||||
|
|||||||
@@ -26,11 +26,10 @@
|
|||||||
#include "qpacketprotocol.h"
|
#include "qpacketprotocol.h"
|
||||||
|
|
||||||
#include <qelapsedtimer.h>
|
#include <qelapsedtimer.h>
|
||||||
|
#include <qendian.h>
|
||||||
|
|
||||||
namespace QmlDebug {
|
namespace QmlDebug {
|
||||||
|
|
||||||
static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QPacketProtocol
|
\class QPacketProtocol
|
||||||
\internal
|
\internal
|
||||||
@@ -98,15 +97,14 @@ class QPacketProtocolPrivate : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
|
QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
|
||||||
: QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
|
: QObject(parent), inProgressSize(-1), waitingForPacket(false), dev(_dev)
|
||||||
waitingForPacket(false), dev(_dev)
|
|
||||||
{
|
{
|
||||||
Q_ASSERT(4 == sizeof(qint32));
|
Q_ASSERT(4 == sizeof(qint32));
|
||||||
|
|
||||||
QObject::connect(this, &QPacketProtocolPrivate::readyRead,
|
QObject::connect(this, &QPacketProtocolPrivate::readyRead,
|
||||||
parent, &QPacketProtocol::readyRead);
|
parent, &QPacketProtocol::readyRead);
|
||||||
QObject::connect(this, &QPacketProtocolPrivate::invalidPacket,
|
QObject::connect(this, &QPacketProtocolPrivate::protocolError,
|
||||||
parent, &QPacketProtocol::invalidPacket);
|
parent, &QPacketProtocol::protocolError);
|
||||||
QObject::connect(dev, &QIODevice::readyRead,
|
QObject::connect(dev, &QIODevice::readyRead,
|
||||||
this, &QPacketProtocolPrivate::readyToRead);
|
this, &QPacketProtocolPrivate::readyToRead);
|
||||||
QObject::connect(dev, &QIODevice::aboutToClose,
|
QObject::connect(dev, &QIODevice::aboutToClose,
|
||||||
@@ -117,7 +115,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void readyRead();
|
void readyRead();
|
||||||
void invalidPacket();
|
void protocolError();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void aboutToClose()
|
void aboutToClose()
|
||||||
@@ -142,6 +140,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fail()
|
||||||
|
{
|
||||||
|
QObject::disconnect(dev, &QIODevice::readyRead,
|
||||||
|
this, &QPacketProtocolPrivate::readyToRead);
|
||||||
|
QObject::disconnect(dev, &QIODevice::aboutToClose,
|
||||||
|
this, &QPacketProtocolPrivate::aboutToClose);
|
||||||
|
QObject::disconnect(dev, &QIODevice::bytesWritten,
|
||||||
|
this, &QPacketProtocolPrivate::bytesWritten);
|
||||||
|
emit protocolError();
|
||||||
|
}
|
||||||
|
|
||||||
void readyToRead()
|
void readyToRead()
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -152,19 +161,15 @@ public:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Read size header
|
// Read size header
|
||||||
int read = dev->read((char *)&inProgressSize, sizeof(qint32));
|
qint32 inProgressSizeLE;
|
||||||
|
const qint64 read = dev->read((char *)&inProgressSizeLE, sizeof(qint32));
|
||||||
Q_ASSERT(read == sizeof(qint32));
|
Q_ASSERT(read == sizeof(qint32));
|
||||||
Q_UNUSED(read);
|
Q_UNUSED(read);
|
||||||
|
inProgressSize = qFromLittleEndian(inProgressSizeLE);
|
||||||
|
|
||||||
// Check sizing constraints
|
// Check sizing constraints
|
||||||
if (inProgressSize > maxPacketSize) {
|
if (inProgressSize < qint32(sizeof(qint32))) {
|
||||||
QObject::disconnect(dev, &QIODevice::readyRead,
|
fail();
|
||||||
this, &QPacketProtocolPrivate::readyToRead);
|
|
||||||
QObject::disconnect(dev, &QIODevice::aboutToClose,
|
|
||||||
this, &QPacketProtocolPrivate::aboutToClose);
|
|
||||||
QObject::disconnect(dev, &QIODevice::bytesWritten,
|
|
||||||
this, &QPacketProtocolPrivate::bytesWritten);
|
|
||||||
emit invalidPacket();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,11 +192,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QList<qint64> sendingPackets;
|
QList<qint32> sendingPackets;
|
||||||
QList<QByteArray> packets;
|
QList<QByteArray> packets;
|
||||||
QByteArray inProgress;
|
QByteArray inProgress;
|
||||||
qint32 inProgressSize;
|
qint32 inProgressSize;
|
||||||
qint32 maxPacketSize;
|
|
||||||
bool waitingForPacket;
|
bool waitingForPacket;
|
||||||
QIODevice *dev;
|
QIODevice *dev;
|
||||||
};
|
};
|
||||||
@@ -211,18 +215,29 @@ QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
|
|||||||
*/
|
*/
|
||||||
void QPacketProtocol::send(const QByteArray &p)
|
void QPacketProtocol::send(const QByteArray &p)
|
||||||
{
|
{
|
||||||
|
static const qint32 maxSize = std::numeric_limits<qint32>::max() - sizeof(qint32);
|
||||||
|
|
||||||
if (p.isEmpty())
|
if (p.isEmpty())
|
||||||
return; // We don't send empty packets
|
return; // We don't send empty packets
|
||||||
|
|
||||||
qint64 sendSize = p.size() + sizeof(qint32);
|
if (p.size() > maxSize) {
|
||||||
|
d->fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qint32 sendSize = p.size() + sizeof(qint32);
|
||||||
d->sendingPackets.append(sendSize);
|
d->sendingPackets.append(sendSize);
|
||||||
qint32 sendSize32 = sendSize;
|
|
||||||
qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
|
const qint32 sendSizeLE = qToLittleEndian(sendSize);
|
||||||
Q_ASSERT(writeBytes == sizeof(qint32));
|
if (d->dev->write((char *)&sendSizeLE, sizeof(qint32)) != sizeof(qint32)) {
|
||||||
writeBytes = d->dev->write(p);
|
d->fail();
|
||||||
Q_ASSERT(writeBytes == p.size());
|
return;
|
||||||
Q_UNUSED(writeBytes); // For building in release mode.
|
}
|
||||||
|
|
||||||
|
if (d->dev->write(p) != p.size()) {
|
||||||
|
d->fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void readyRead();
|
void readyRead();
|
||||||
void invalidPacket();
|
void protocolError();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPacketProtocolPrivate *d;
|
QPacketProtocolPrivate *d;
|
||||||
|
|||||||
@@ -700,7 +700,8 @@ static std::string dumplocalHelper(ExtensionCommandContext &exc,PCSTR args, int
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
std::wstring value;
|
std::wstring value;
|
||||||
if (!dumpSimpleType(n->asSymbolGroupNode(), SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), &value, &std::string())) {
|
std::string tmp;
|
||||||
|
if (!dumpSimpleType(n->asSymbolGroupNode(), SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), &value, &tmp)) {
|
||||||
*errorMessage = "Cannot dump " + iname;
|
*errorMessage = "Cannot dump " + iname;
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,8 +228,9 @@ SymbolAncestorInfo SymbolGroupValue::infoOfAncestor(const std::string &name) con
|
|||||||
SymbolGroupValue SymbolGroupValue::addSymbol(const ULONG64 address, const std::string &type) const
|
SymbolGroupValue SymbolGroupValue::addSymbol(const ULONG64 address, const std::string &type) const
|
||||||
{
|
{
|
||||||
const std::string &pointerToType = pointedToSymbolName(address, type);
|
const std::string &pointerToType = pointedToSymbolName(address, type);
|
||||||
|
std::string tmp;
|
||||||
if (SymbolGroupNode *ancestorNode =
|
if (SymbolGroupNode *ancestorNode =
|
||||||
node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &std::string())) {
|
node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &tmp)) {
|
||||||
return SymbolGroupValue(ancestorNode, m_context);
|
return SymbolGroupValue(ancestorNode, m_context);
|
||||||
}
|
}
|
||||||
if (isValid() && SymbolGroupValue::verbose) { // Do not report subsequent errors
|
if (isValid() && SymbolGroupValue::verbose) { // Do not report subsequent errors
|
||||||
@@ -2064,8 +2065,9 @@ static inline bool dumpQRegion(const SymbolGroupValue &v, std::wostream &str, vo
|
|||||||
namestr << "(" << info.prependQtGuiModule("QRegionPrivate *") << ")("
|
namestr << "(" << info.prependQtGuiModule("QRegionPrivate *") << ")("
|
||||||
<< std::showbase << std::hex << d.pointerValue() << ')';
|
<< std::showbase << std::hex << d.pointerValue() << ')';
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
SymbolGroupNode *qRegionPrivateNode
|
SymbolGroupNode *qRegionPrivateNode
|
||||||
= v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &std::string());
|
= v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &tmp);
|
||||||
if (!qRegionPrivateNode)
|
if (!qRegionPrivateNode)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -2128,14 +2130,15 @@ static inline bool dumpQHostAddress(const SymbolGroupValue &v, std::wostream &st
|
|||||||
std::ostringstream namestr;
|
std::ostringstream namestr;
|
||||||
namestr << '(' << info.prependQtNetworkModule("QHostAddressPrivate *") << ")("
|
namestr << '(' << info.prependQtNetworkModule("QHostAddressPrivate *") << ")("
|
||||||
<< std::showbase << std::hex << d.pointerValue() << ')';
|
<< std::showbase << std::hex << d.pointerValue() << ')';
|
||||||
|
std::string tmp;
|
||||||
SymbolGroupNode *qHostAddressPrivateNode
|
SymbolGroupNode *qHostAddressPrivateNode
|
||||||
= v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &std::string());
|
= v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &tmp);
|
||||||
if (!qHostAddressPrivateNode)
|
if (!qHostAddressPrivateNode)
|
||||||
return false;
|
return false;
|
||||||
const SymbolGroupValue qHostAddressPrivateValue = SymbolGroupValue(qHostAddressPrivateNode, v.context());
|
const SymbolGroupValue qHostAddressPrivateValue = SymbolGroupValue(qHostAddressPrivateNode, v.context());
|
||||||
const bool parsed = readPODFromMemory<bool>(qHostAddressPrivateValue.context().dataspaces,
|
const bool parsed = readPODFromMemory<bool>(qHostAddressPrivateValue.context().dataspaces,
|
||||||
qHostAddressPrivateValue["isParsed"].address(),
|
qHostAddressPrivateValue["isParsed"].address(),
|
||||||
sizeof(bool), false, &std::string());
|
sizeof(bool), false, &tmp);
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
const int protocol = qHostAddressPrivateValue["protocol"].intValue(-1);
|
const int protocol = qHostAddressPrivateValue["protocol"].intValue(-1);
|
||||||
if (protocol < 0) {
|
if (protocol < 0) {
|
||||||
@@ -2888,7 +2891,8 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str, std::str
|
|||||||
if (const SymbolGroupValue mv = dataV.typeCast(vmType.c_str())) {
|
if (const SymbolGroupValue mv = dataV.typeCast(vmType.c_str())) {
|
||||||
SymbolGroupNode *mapNode = mv.node();
|
SymbolGroupNode *mapNode = mv.node();
|
||||||
std::wstring value;
|
std::wstring value;
|
||||||
if (dumpSimpleType(mapNode, dataV.context(), &value, &std::string())
|
std::string tmp;
|
||||||
|
if (dumpSimpleType(mapNode, dataV.context(), &value, &tmp)
|
||||||
== SymbolGroupNode::SimpleDumperOk) {
|
== SymbolGroupNode::SimpleDumperOk) {
|
||||||
str << value;
|
str << value;
|
||||||
if (specialInfoIn)
|
if (specialInfoIn)
|
||||||
@@ -2903,7 +2907,8 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str, std::str
|
|||||||
if (const SymbolGroupValue vl = dataV.typeCast(vLType.c_str())) {
|
if (const SymbolGroupValue vl = dataV.typeCast(vLType.c_str())) {
|
||||||
SymbolGroupNode *vListNode = vl.node();
|
SymbolGroupNode *vListNode = vl.node();
|
||||||
std::wstring value;
|
std::wstring value;
|
||||||
if (dumpSimpleType(vListNode, dataV.context(), &value, &std::string())
|
std::string tmp;
|
||||||
|
if (dumpSimpleType(vListNode, dataV.context(), &value, &tmp)
|
||||||
== SymbolGroupNode::SimpleDumperOk) {
|
== SymbolGroupNode::SimpleDumperOk) {
|
||||||
str << value;
|
str << value;
|
||||||
if (specialInfoIn)
|
if (specialInfoIn)
|
||||||
@@ -2929,7 +2934,8 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str, std::str
|
|||||||
if (const SymbolGroupValue sl = dataV.typeCast(qtInfo.prependQtCoreModule("QStringList *").c_str())) {
|
if (const SymbolGroupValue sl = dataV.typeCast(qtInfo.prependQtCoreModule("QStringList *").c_str())) {
|
||||||
SymbolGroupNode *listNode = sl.node();
|
SymbolGroupNode *listNode = sl.node();
|
||||||
std::wstring value;
|
std::wstring value;
|
||||||
if (dumpSimpleType(listNode, dataV.context(), &value, &std::string())
|
std::string tmp;
|
||||||
|
if (dumpSimpleType(listNode, dataV.context(), &value, &tmp)
|
||||||
== SymbolGroupNode::SimpleDumperOk) {
|
== SymbolGroupNode::SimpleDumperOk) {
|
||||||
str << value;
|
str << value;
|
||||||
if (specialInfoIn)
|
if (specialInfoIn)
|
||||||
|
|||||||
@@ -58,6 +58,13 @@ Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos
|
|||||||
return optional;
|
return optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int positionInText(QTextDocument *textDocument, int line, int column)
|
||||||
|
{
|
||||||
|
// Deduct 1 from line and column since they are 1-based.
|
||||||
|
// Column should already be converted from UTF-8 byte offset to the TextEditor column.
|
||||||
|
return textDocument->findBlockByNumber(line - 1).position() + column - 1;
|
||||||
|
}
|
||||||
|
|
||||||
QString textAt(QTextCursor tc, int pos, int length)
|
QString textAt(QTextCursor tc, int pos, int length)
|
||||||
{
|
{
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ QTCREATOR_UTILS_EXPORT bool convertPosition(const QTextDocument *document,
|
|||||||
QTCREATOR_UTILS_EXPORT
|
QTCREATOR_UTILS_EXPORT
|
||||||
Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos);
|
Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos);
|
||||||
|
|
||||||
|
// line and column are 1-based
|
||||||
|
QTCREATOR_UTILS_EXPORT int positionInText(QTextDocument *textDocument, int line, int column);
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length);
|
QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length);
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);
|
QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const GTestResult *gtOther = static_cast<const GTestResult *>(other);
|
const GTestResult *gtOther = static_cast<const GTestResult *>(other);
|
||||||
|
if (m_testSetName == gtOther->m_testSetName && other->result() == Result::MessageInternal)
|
||||||
|
return true;
|
||||||
if (m_iteration != gtOther->m_iteration)
|
if (m_iteration != gtOther->m_iteration)
|
||||||
return false;
|
return false;
|
||||||
return isTest() && gtOther->isTestSet();
|
return isTest() && gtOther->isTestSet();
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ static bool isDerivedFromTestCase(QmlJS::AST::UiQualifiedId *id, const QmlJS::Do
|
|||||||
bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
|
bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
|
||||||
{
|
{
|
||||||
const QStringRef name = ast->qualifiedTypeNameId->name;
|
const QStringRef name = ast->qualifiedTypeNameId->name;
|
||||||
|
m_objectStack.push(name.toString());
|
||||||
if (name != "TestCase") {
|
if (name != "TestCase") {
|
||||||
|
m_insideTestCase = false;
|
||||||
if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot))
|
if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot))
|
||||||
return true;
|
return true;
|
||||||
} else if (!documentImportsQtTest(m_currentDoc.data())) {
|
} else if (!documentImportsQtTest(m_currentDoc.data())) {
|
||||||
@@ -92,6 +94,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_typeIsTestCase = true;
|
m_typeIsTestCase = true;
|
||||||
|
m_insideTestCase = true;
|
||||||
m_currentTestCaseName.clear();
|
m_currentTestCaseName.clear();
|
||||||
const auto sourceLocation = ast->firstSourceLocation();
|
const auto sourceLocation = ast->firstSourceLocation();
|
||||||
m_testCaseLocation.m_name = m_currentDoc->fileName();
|
m_testCaseLocation.m_name = m_currentDoc->fileName();
|
||||||
@@ -101,6 +104,11 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQmlVisitor::endVisit(QmlJS::AST::UiObjectDefinition *)
|
||||||
|
{
|
||||||
|
m_insideTestCase = m_objectStack.pop() == "TestCase";
|
||||||
|
}
|
||||||
|
|
||||||
bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
|
bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
|
||||||
{
|
{
|
||||||
const QmlJS::AST::ExpressionNode *expr = ast->expression;
|
const QmlJS::AST::ExpressionNode *expr = ast->expression;
|
||||||
@@ -109,8 +117,15 @@ bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
|
|||||||
|
|
||||||
bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast)
|
bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast)
|
||||||
{
|
{
|
||||||
const QStringRef name = ast->qualifiedId->name;
|
if (m_insideTestCase)
|
||||||
return name == "name";
|
m_expectTestCaseName = ast->qualifiedId->name == "name";
|
||||||
|
return m_expectTestCaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQmlVisitor::endVisit(QmlJS::AST::UiScriptBinding *)
|
||||||
|
{
|
||||||
|
if (m_expectTestCaseName)
|
||||||
|
m_expectTestCaseName = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
|
bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
|
||||||
@@ -139,8 +154,10 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
|
|||||||
|
|
||||||
bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast)
|
bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast)
|
||||||
{
|
{
|
||||||
if (m_typeIsTestCase)
|
if (m_expectTestCaseName && m_currentTestCaseName.isEmpty()) {
|
||||||
m_currentTestCaseName = ast->value.toString();
|
m_currentTestCaseName = ast->value.toString();
|
||||||
|
m_expectTestCaseName = false;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
#include <qmljs/parser/qmljsastvisitor_p.h>
|
#include <qmljs/parser/qmljsastvisitor_p.h>
|
||||||
#include <qmljs/qmljsdocument.h>
|
#include <qmljs/qmljsdocument.h>
|
||||||
|
|
||||||
|
#include <QStack>
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -38,11 +40,13 @@ class TestQmlVisitor : public QmlJS::AST::Visitor
|
|||||||
public:
|
public:
|
||||||
explicit TestQmlVisitor(QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot);
|
explicit TestQmlVisitor(QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot);
|
||||||
|
|
||||||
bool visit(QmlJS::AST::UiObjectDefinition *ast);
|
bool visit(QmlJS::AST::UiObjectDefinition *ast) override;
|
||||||
bool visit(QmlJS::AST::ExpressionStatement *ast);
|
void endVisit(QmlJS::AST::UiObjectDefinition *ast) override;
|
||||||
bool visit(QmlJS::AST::UiScriptBinding *ast);
|
bool visit(QmlJS::AST::ExpressionStatement *ast) override;
|
||||||
bool visit(QmlJS::AST::FunctionDeclaration *ast);
|
bool visit(QmlJS::AST::UiScriptBinding *ast) override;
|
||||||
bool visit(QmlJS::AST::StringLiteral *ast);
|
void endVisit(QmlJS::AST::UiScriptBinding *ast) override;
|
||||||
|
bool visit(QmlJS::AST::FunctionDeclaration *ast) override;
|
||||||
|
bool visit(QmlJS::AST::StringLiteral *ast) override;
|
||||||
|
|
||||||
QString testCaseName() const { return m_currentTestCaseName; }
|
QString testCaseName() const { return m_currentTestCaseName; }
|
||||||
TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; }
|
TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; }
|
||||||
@@ -55,7 +59,10 @@ private:
|
|||||||
QString m_currentTestCaseName;
|
QString m_currentTestCaseName;
|
||||||
TestCodeLocationAndType m_testCaseLocation;
|
TestCodeLocationAndType m_testCaseLocation;
|
||||||
QMap<QString, TestCodeLocationAndType> m_testFunctions;
|
QMap<QString, TestCodeLocationAndType> m_testFunctions;
|
||||||
|
QStack<QString> m_objectStack;
|
||||||
bool m_typeIsTestCase = false;
|
bool m_typeIsTestCase = false;
|
||||||
|
bool m_insideTestCase = false;
|
||||||
|
bool m_expectTestCaseName = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -75,12 +75,14 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
|
|||||||
TestRunMode runMode)
|
TestRunMode runMode)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(rc, return);
|
QTC_ASSERT(rc, return);
|
||||||
|
QTC_ASSERT(m_project, return);
|
||||||
|
|
||||||
if (hasExecutable()) {
|
if (hasExecutable()) {
|
||||||
qCDebug(LOG) << "Executable has been set already - not completing configuration again.";
|
qCDebug(LOG) << "Executable has been set already - not completing configuration again.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Project *project = SessionManager::startupProject();
|
Project *project = SessionManager::startupProject();
|
||||||
if (!project)
|
if (!project || project != m_project)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Target *target = project->activeTarget();
|
Target *target = project->activeTarget();
|
||||||
@@ -94,7 +96,6 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
|
|||||||
|
|
||||||
m_runnable = rc->runnable();
|
m_runnable = rc->runnable();
|
||||||
m_displayName = rc->displayName();
|
m_displayName = rc->displayName();
|
||||||
m_project = rc->project();
|
|
||||||
|
|
||||||
const QString buildKey = rc->buildKey();
|
const QString buildKey = rc->buildKey();
|
||||||
BuildTargetInfo targetInfo = target->applicationTargets().buildTargetInfo(buildKey);
|
BuildTargetInfo targetInfo = target->applicationTargets().buildTargetInfo(buildKey);
|
||||||
@@ -116,6 +117,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(!m_projectFile.isEmpty(), return);
|
QTC_ASSERT(!m_projectFile.isEmpty(), return);
|
||||||
QTC_ASSERT(!m_buildTargets.isEmpty(), return);
|
QTC_ASSERT(!m_buildTargets.isEmpty(), return);
|
||||||
|
QTC_ASSERT(m_project, return);
|
||||||
|
|
||||||
if (m_origRunConfig) {
|
if (m_origRunConfig) {
|
||||||
qCDebug(LOG) << "Using run configuration specified by user or found by first call";
|
qCDebug(LOG) << "Using run configuration specified by user or found by first call";
|
||||||
@@ -129,8 +131,10 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
|
|||||||
qCDebug(LOG) << "Failed to complete - using 'normal' way.";
|
qCDebug(LOG) << "Failed to complete - using 'normal' way.";
|
||||||
}
|
}
|
||||||
Project *project = SessionManager::startupProject();
|
Project *project = SessionManager::startupProject();
|
||||||
if (!project)
|
if (!project || project != m_project) {
|
||||||
|
m_project = nullptr;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Target *target = project->activeTarget();
|
Target *target = project->activeTarget();
|
||||||
if (!target)
|
if (!target)
|
||||||
@@ -204,7 +208,6 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
|
|||||||
m_runnable = runnable;
|
m_runnable = runnable;
|
||||||
m_runnable.executable = currentExecutable;
|
m_runnable.executable = currentExecutable;
|
||||||
m_displayName = runConfig->displayName();
|
m_displayName = runConfig->displayName();
|
||||||
m_project = project;
|
|
||||||
if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
|
if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
|
||||||
m_runConfig = new TestRunConfiguration(runConfig->target(), this);
|
m_runConfig = new TestRunConfiguration(runConfig->target(), this);
|
||||||
break;
|
break;
|
||||||
@@ -224,7 +227,6 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
|
|||||||
if (isLocal(rc)) { // FIXME for now only Desktop support
|
if (isLocal(rc)) { // FIXME for now only Desktop support
|
||||||
const Runnable runnable = rc->runnable();
|
const Runnable runnable = rc->runnable();
|
||||||
m_runnable.environment = runnable.environment;
|
m_runnable.environment = runnable.environment;
|
||||||
m_project = project;
|
|
||||||
m_guessedConfiguration = true;
|
m_guessedConfiguration = true;
|
||||||
m_guessedFrom = rc->displayName();
|
m_guessedFrom = rc->displayName();
|
||||||
if (runMode == TestRunMode::Debug)
|
if (runMode == TestRunMode::Debug)
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ void TestRunner::scheduleNext()
|
|||||||
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
|
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
|
||||||
QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers());
|
QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers());
|
||||||
QTC_ASSERT(m_fakeFutureInterface, onFinished(); return);
|
QTC_ASSERT(m_fakeFutureInterface, onFinished(); return);
|
||||||
|
QTC_ASSERT(!m_canceled, onFinished(); return);
|
||||||
|
|
||||||
m_currentConfig = m_selectedTests.dequeue();
|
m_currentConfig = m_selectedTests.dequeue();
|
||||||
|
|
||||||
@@ -215,9 +216,16 @@ void TestRunner::scheduleNext()
|
|||||||
|
|
||||||
void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
|
void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
|
||||||
{
|
{
|
||||||
|
m_canceled = true;
|
||||||
if (reason == UserCanceled) {
|
if (reason == UserCanceled) {
|
||||||
if (!m_fakeFutureInterface->isCanceled()) // depends on using the button / progress bar
|
// when using the stop button we need to report, for progress bar this happens automatically
|
||||||
|
if (m_fakeFutureInterface && !m_fakeFutureInterface->isCanceled())
|
||||||
m_fakeFutureInterface->reportCanceled();
|
m_fakeFutureInterface->reportCanceled();
|
||||||
|
} else if (reason == KitChanged) {
|
||||||
|
if (m_fakeFutureInterface)
|
||||||
|
m_fakeFutureInterface->reportCanceled();
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
||||||
|
tr("Current kit has changed. Canceling test run."))));
|
||||||
}
|
}
|
||||||
if (m_currentProcess && m_currentProcess->state() != QProcess::NotRunning) {
|
if (m_currentProcess && m_currentProcess->state() != QProcess::NotRunning) {
|
||||||
m_currentProcess->kill();
|
m_currentProcess->kill();
|
||||||
@@ -231,6 +239,7 @@ void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
|
|||||||
|
|
||||||
void TestRunner::onProcessFinished()
|
void TestRunner::onProcessFinished()
|
||||||
{
|
{
|
||||||
|
if (m_currentConfig) {
|
||||||
m_fakeFutureInterface->setProgressValue(m_fakeFutureInterface->progressValue()
|
m_fakeFutureInterface->setProgressValue(m_fakeFutureInterface->progressValue()
|
||||||
+ m_currentConfig->testCaseCount());
|
+ m_currentConfig->testCaseCount());
|
||||||
if (!m_fakeFutureInterface->isCanceled()) {
|
if (!m_fakeFutureInterface->isCanceled()) {
|
||||||
@@ -246,7 +255,7 @@ void TestRunner::onProcessFinished()
|
|||||||
+ rcInfo(m_currentConfig))));
|
+ rcInfo(m_currentConfig))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
resetInternalPointers();
|
resetInternalPointers();
|
||||||
|
|
||||||
if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled())
|
if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled())
|
||||||
@@ -277,6 +286,7 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_executingTests = true;
|
m_executingTests = true;
|
||||||
|
m_canceled = false;
|
||||||
emit testRunStarted();
|
emit testRunStarted();
|
||||||
|
|
||||||
// clear old log and output pane
|
// clear old log and output pane
|
||||||
@@ -299,6 +309,9 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_targetConnect = connect(project, &ProjectExplorer::Project::activeTargetChanged,
|
||||||
|
[this]() { cancelCurrent(KitChanged); });
|
||||||
|
|
||||||
if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy
|
if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy
|
||||||
|| mode == TestRunMode::RunWithoutDeploy) {
|
|| mode == TestRunMode::RunWithoutDeploy) {
|
||||||
runOrDebugTests();
|
runOrDebugTests();
|
||||||
@@ -384,9 +397,13 @@ int TestRunner::precheckTestConfigurations()
|
|||||||
void TestRunner::runTests()
|
void TestRunner::runTests()
|
||||||
{
|
{
|
||||||
QList<TestConfiguration *> toBeRemoved;
|
QList<TestConfiguration *> toBeRemoved;
|
||||||
|
bool projectChanged = false;
|
||||||
for (TestConfiguration *config : m_selectedTests) {
|
for (TestConfiguration *config : m_selectedTests) {
|
||||||
config->completeTestInformation(TestRunMode::Run);
|
config->completeTestInformation(TestRunMode::Run);
|
||||||
if (!config->hasExecutable()) {
|
if (!config->project()) {
|
||||||
|
projectChanged = true;
|
||||||
|
toBeRemoved.append(config);
|
||||||
|
} else if (!config->hasExecutable()) {
|
||||||
if (auto rc = getRunConfiguration(firstTestCaseTarget(config)))
|
if (auto rc = getRunConfiguration(firstTestCaseTarget(config)))
|
||||||
config->setOriginalRunConfiguration(rc);
|
config->setOriginalRunConfiguration(rc);
|
||||||
else
|
else
|
||||||
@@ -398,8 +415,10 @@ void TestRunner::runTests()
|
|||||||
qDeleteAll(toBeRemoved);
|
qDeleteAll(toBeRemoved);
|
||||||
toBeRemoved.clear();
|
toBeRemoved.clear();
|
||||||
if (m_selectedTests.isEmpty()) {
|
if (m_selectedTests.isEmpty()) {
|
||||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
QString mssg = projectChanged ? tr("Startup project has changed. Canceling test run.")
|
||||||
tr("No test cases left for execution. Canceling test run."))));
|
: tr("No test cases left for execution. Canceling test run.");
|
||||||
|
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, mssg)));
|
||||||
onFinished();
|
onFinished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -452,6 +471,12 @@ void TestRunner::debugTests()
|
|||||||
|
|
||||||
TestConfiguration *config = m_selectedTests.first();
|
TestConfiguration *config = m_selectedTests.first();
|
||||||
config->completeTestInformation(TestRunMode::Debug);
|
config->completeTestInformation(TestRunMode::Debug);
|
||||||
|
if (!config->project()) {
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
||||||
|
TestRunner::tr("Startup project has changed. Canceling test run."))));
|
||||||
|
onFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!config->hasExecutable()) {
|
if (!config->hasExecutable()) {
|
||||||
if (auto *rc = getRunConfiguration(firstTestCaseTarget(config)))
|
if (auto *rc = getRunConfiguration(firstTestCaseTarget(config)))
|
||||||
config->completeTestInformation(rc, TestRunMode::Debug);
|
config->completeTestInformation(rc, TestRunMode::Debug);
|
||||||
@@ -571,7 +596,10 @@ void TestRunner::buildFinished(bool success)
|
|||||||
this, &TestRunner::buildFinished);
|
this, &TestRunner::buildFinished);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
if (!m_canceled)
|
||||||
runOrDebugTests();
|
runOrDebugTests();
|
||||||
|
else if (m_executingTests)
|
||||||
|
onFinished();
|
||||||
} else {
|
} else {
|
||||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||||
tr("Build failed. Canceling test run."))));
|
tr("Build failed. Canceling test run."))));
|
||||||
@@ -585,6 +613,7 @@ void TestRunner::onFinished()
|
|||||||
qDeleteAll(m_selectedTests);
|
qDeleteAll(m_selectedTests);
|
||||||
m_selectedTests.clear();
|
m_selectedTests.clear();
|
||||||
|
|
||||||
|
disconnect(m_targetConnect);
|
||||||
m_fakeFutureInterface = nullptr;
|
m_fakeFutureInterface = nullptr;
|
||||||
m_executingTests = false;
|
m_executingTests = false;
|
||||||
emit testRunFinished();
|
emit testRunFinished();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class AUTOTESTSHARED_EXPORT TestRunner : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum CancelReason { UserCanceled, Timeout };
|
enum CancelReason { UserCanceled, Timeout, KitChanged };
|
||||||
|
|
||||||
static TestRunner* instance();
|
static TestRunner* instance();
|
||||||
~TestRunner();
|
~TestRunner();
|
||||||
@@ -91,6 +91,7 @@ private:
|
|||||||
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
|
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
|
||||||
QQueue<TestConfiguration *> m_selectedTests;
|
QQueue<TestConfiguration *> m_selectedTests;
|
||||||
bool m_executingTests = false;
|
bool m_executingTests = false;
|
||||||
|
bool m_canceled = false;
|
||||||
TestConfiguration *m_currentConfig = nullptr;
|
TestConfiguration *m_currentConfig = nullptr;
|
||||||
QProcess *m_currentProcess = nullptr;
|
QProcess *m_currentProcess = nullptr;
|
||||||
TestOutputReader *m_currentOutputReader = nullptr;
|
TestOutputReader *m_currentOutputReader = nullptr;
|
||||||
@@ -98,6 +99,8 @@ private:
|
|||||||
|
|
||||||
// temporarily used if building before running is necessary
|
// temporarily used if building before running is necessary
|
||||||
QMetaObject::Connection m_buildConnect;
|
QMetaObject::Connection m_buildConnect;
|
||||||
|
// temporarily used for handling of switching the current target
|
||||||
|
QMetaObject::Connection m_targetConnect;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RunConfigurationSelectionDialog : public QDialog
|
class RunConfigurationSelectionDialog : public QDialog
|
||||||
|
|||||||
@@ -1673,7 +1673,11 @@ void BinEditorWidget::setNewWindowRequestAllowed(bool c)
|
|||||||
void BinEditorWidget::updateContents()
|
void BinEditorWidget::updateContents()
|
||||||
{
|
{
|
||||||
m_oldData = m_data;
|
m_oldData = m_data;
|
||||||
setSizes(baseAddress() + cursorPosition(), m_size, m_blockSize);
|
m_data.clear();
|
||||||
|
m_modifiedData.clear();
|
||||||
|
m_requests.clear();
|
||||||
|
for (auto it = m_oldData.constBegin(), et = m_oldData.constEnd(); it != et; ++it)
|
||||||
|
d->fetchData(m_baseAddr + it.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint BinEditorWidget::offsetToPos(qint64 offset) const
|
QPoint BinEditorWidget::offsetToPos(qint64 offset) const
|
||||||
|
|||||||
@@ -63,18 +63,6 @@ QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainforma
|
|||||||
return extraSelection;
|
return extraSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
int positionInText(QTextDocument *textDocument,
|
|
||||||
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
|
|
||||||
{
|
|
||||||
auto textBlock = textDocument->findBlockByNumber(
|
|
||||||
static_cast<int>(sourceLocationContainer.line) - 1);
|
|
||||||
// 'sourceLocationContainer' already has the CppEditor column converted from
|
|
||||||
// the utf8 byte offset from the beginning of the line provided by clang.
|
|
||||||
// - 1 is required for 0-based columns.
|
|
||||||
const int column = static_cast<int>(sourceLocationContainer.column) - 1;
|
|
||||||
return textBlock.position() + column;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
||||||
QTextDocument *textDocument,
|
QTextDocument *textDocument,
|
||||||
const QTextCharFormat &contextFormat,
|
const QTextCharFormat &contextFormat,
|
||||||
@@ -82,8 +70,13 @@ void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
|||||||
{
|
{
|
||||||
for (auto &&range : diagnostic.ranges) {
|
for (auto &&range : diagnostic.ranges) {
|
||||||
QTextCursor cursor(textDocument);
|
QTextCursor cursor(textDocument);
|
||||||
cursor.setPosition(positionInText(textDocument, range.start));
|
cursor.setPosition(::Utils::Text::positionInText(textDocument,
|
||||||
cursor.setPosition(positionInText(textDocument, range.end), QTextCursor::KeepAnchor);
|
range.start.line,
|
||||||
|
range.start.column));
|
||||||
|
cursor.setPosition(::Utils::Text::positionInText(textDocument,
|
||||||
|
range.end.line,
|
||||||
|
range.end.column),
|
||||||
|
QTextCursor::KeepAnchor);
|
||||||
|
|
||||||
auto extraSelection = createExtraSelections(contextFormat, cursor);
|
auto extraSelection = createExtraSelections(contextFormat, cursor);
|
||||||
|
|
||||||
@@ -127,11 +120,15 @@ QTextCursor createSelectionCursor(QTextDocument *textDocument,
|
|||||||
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
|
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
|
||||||
{
|
{
|
||||||
QTextCursor cursor(textDocument);
|
QTextCursor cursor(textDocument);
|
||||||
cursor.setPosition(positionInText(textDocument, sourceLocationContainer));
|
cursor.setPosition(::Utils::Text::positionInText(textDocument,
|
||||||
|
sourceLocationContainer.line,
|
||||||
|
sourceLocationContainer.column));
|
||||||
selectToLocationEnd(cursor);
|
selectToLocationEnd(cursor);
|
||||||
|
|
||||||
if (!cursor.hasSelection()) {
|
if (!cursor.hasSelection()) {
|
||||||
cursor.setPosition(positionInText(textDocument, sourceLocationContainer) - 1);
|
cursor.setPosition(::Utils::Text::positionInText(textDocument,
|
||||||
|
sourceLocationContainer.line,
|
||||||
|
sourceLocationContainer.column) - 1);
|
||||||
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2);
|
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -205,20 +205,16 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(
|
|||||||
}
|
}
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
int positionInText(QTextDocument *textDocument,
|
|
||||||
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
|
|
||||||
{
|
|
||||||
auto textBlock = textDocument->findBlockByNumber(int(sourceLocationContainer.line) - 1);
|
|
||||||
|
|
||||||
return textBlock.position() + int(sourceLocationContainer.column) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditor::BlockRange
|
TextEditor::BlockRange
|
||||||
toTextEditorBlock(QTextDocument *textDocument,
|
toTextEditorBlock(QTextDocument *textDocument,
|
||||||
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
|
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
|
||||||
{
|
{
|
||||||
return TextEditor::BlockRange(positionInText(textDocument, sourceRangeContainer.start),
|
return TextEditor::BlockRange(::Utils::Text::positionInText(textDocument,
|
||||||
positionInText(textDocument, sourceRangeContainer.end));
|
sourceRangeContainer.start.line,
|
||||||
|
sourceRangeContainer.start.column),
|
||||||
|
::Utils::Text::positionInText(textDocument,
|
||||||
|
sourceRangeContainer.end.line,
|
||||||
|
sourceRangeContainer.end.column));
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<TextEditor::BlockRange>
|
QList<TextEditor::BlockRange>
|
||||||
|
|||||||
@@ -251,7 +251,10 @@ ClangTidyClazyTool::ClangTidyClazyTool()
|
|||||||
m_applyFixitsButton->setEnabled(false);
|
m_applyFixitsButton->setEnabled(false);
|
||||||
connect(m_diagnosticModel,
|
connect(m_diagnosticModel,
|
||||||
&ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
|
&ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
|
||||||
[this](int c) { m_applyFixitsButton->setEnabled(c); });
|
[this](int c) {
|
||||||
|
m_applyFixitsButton->setEnabled(c);
|
||||||
|
static_cast<DiagnosticView *>(m_diagnosticView)->setSelectedFixItsCount(c);
|
||||||
|
});
|
||||||
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
||||||
QVector<DiagnosticItem *> diagnosticItems;
|
QVector<DiagnosticItem *> diagnosticItems;
|
||||||
m_diagnosticModel->rootItem()->forChildrenAtLevel(1, [&](TreeItem *item){
|
m_diagnosticModel->rootItem()->forChildrenAtLevel(1, [&](TreeItem *item){
|
||||||
|
|||||||
@@ -328,6 +328,9 @@ QVariant DiagnosticItem::data(int column, int role) const
|
|||||||
bool DiagnosticItem::setData(int column, const QVariant &data, int role)
|
bool DiagnosticItem::setData(int column, const QVariant &data, int role)
|
||||||
{
|
{
|
||||||
if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
|
if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
|
||||||
|
if (m_fixitStatus != FixitStatus::Scheduled && m_fixitStatus != FixitStatus::NotScheduled)
|
||||||
|
return false;
|
||||||
|
|
||||||
const FixitStatus newStatus = data.value<Qt::CheckState>() == Qt::Checked
|
const FixitStatus newStatus = data.value<Qt::CheckState>() == Qt::Checked
|
||||||
? FixitStatus::Scheduled
|
? FixitStatus::Scheduled
|
||||||
: FixitStatus::NotScheduled;
|
: FixitStatus::NotScheduled;
|
||||||
|
|||||||
@@ -35,12 +35,60 @@
|
|||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
using namespace Debugger;
|
using namespace Debugger;
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class ClickableFixItHeader : public QHeaderView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClickableFixItHeader(Qt::Orientation orientation, QWidget *parent = 0)
|
||||||
|
: QHeaderView(orientation, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(QFlags<QStyle::StateFlag> newState)
|
||||||
|
{
|
||||||
|
state = newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
|
||||||
|
{
|
||||||
|
painter->save();
|
||||||
|
QHeaderView::paintSection(painter, rect, logicalIndex);
|
||||||
|
painter->restore();
|
||||||
|
if (logicalIndex == DiagnosticView::FixItColumn) {
|
||||||
|
QStyleOptionButton option;
|
||||||
|
const int side = sizeHint().height();
|
||||||
|
option.rect = QRect(rect.left() + 1, 1, side - 3, side - 3);
|
||||||
|
option.state = state;
|
||||||
|
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (event->localPos().x() > sectionPosition(DiagnosticView::FixItColumn)) {
|
||||||
|
state = (state != QStyle::State_On) ? QStyle::State_On : QStyle::State_Off;
|
||||||
|
viewport()->update();
|
||||||
|
emit fixItColumnClicked(state == QStyle::State_On);
|
||||||
|
}
|
||||||
|
QHeaderView::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fixItColumnClicked(bool checked);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFlags<QStyle::StateFlag> state = QStyle::State_Off;
|
||||||
|
};
|
||||||
|
|
||||||
DiagnosticView::DiagnosticView(QWidget *parent)
|
DiagnosticView::DiagnosticView(QWidget *parent)
|
||||||
: Debugger::DetailedErrorView(parent)
|
: Debugger::DetailedErrorView(parent)
|
||||||
{
|
{
|
||||||
@@ -104,12 +152,36 @@ bool DiagnosticView::eventFilter(QObject *watched, QEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiagnosticView::setSelectedFixItsCount(int fixItsCount)
|
||||||
|
{
|
||||||
|
if (m_ignoreSetSelectedFixItsCount)
|
||||||
|
return;
|
||||||
|
auto *clickableFixItHeader = static_cast<ClickableFixItHeader *>(header());
|
||||||
|
clickableFixItHeader->setState(fixItsCount
|
||||||
|
? (QStyle::State_NoChange | QStyle::State_On | QStyle::State_Off)
|
||||||
|
: QStyle::State_Off);
|
||||||
|
clickableFixItHeader->viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
void DiagnosticView::setModel(QAbstractItemModel *model)
|
void DiagnosticView::setModel(QAbstractItemModel *model)
|
||||||
{
|
{
|
||||||
Debugger::DetailedErrorView::setModel(model);
|
Debugger::DetailedErrorView::setModel(model);
|
||||||
|
auto *clickableFixItHeader = new ClickableFixItHeader(Qt::Horizontal, this);
|
||||||
|
connect(clickableFixItHeader, &ClickableFixItHeader::fixItColumnClicked,
|
||||||
|
this, [=](bool checked) {
|
||||||
|
m_ignoreSetSelectedFixItsCount = true;
|
||||||
|
for (int row = 0; row < model->rowCount(); ++row) {
|
||||||
|
QModelIndex index = model->index(row, FixItColumn, QModelIndex());
|
||||||
|
model->setData(index, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
|
||||||
|
}
|
||||||
|
m_ignoreSetSelectedFixItsCount = false;
|
||||||
|
});
|
||||||
|
setHeader(clickableFixItHeader);
|
||||||
header()->setStretchLastSection(false);
|
header()->setStretchLastSection(false);
|
||||||
header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
|
||||||
|
#include "clangtoolsdiagnosticview.moc"
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ public:
|
|||||||
FixItColumn = LocationColumn + 1,
|
FixItColumn = LocationColumn + 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void setSelectedFixItsCount(int fixItsCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void suppressCurrentDiagnostic();
|
void suppressCurrentDiagnostic();
|
||||||
|
|
||||||
@@ -49,6 +51,7 @@ private:
|
|||||||
void setModel(QAbstractItemModel *model) override;
|
void setModel(QAbstractItemModel *model) override;
|
||||||
|
|
||||||
QAction *m_suppressAction;
|
QAction *m_suppressAction;
|
||||||
|
bool m_ignoreSetSelectedFixItsCount = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -118,8 +118,11 @@ void ClangToolsSettings::readSettings()
|
|||||||
|
|
||||||
m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
|
m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
|
||||||
|
|
||||||
m_savedDiagnosticConfigId = m_diagnosticConfigId
|
m_diagnosticConfigId = Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
|
||||||
= Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
|
if (!m_diagnosticConfigId.isValid())
|
||||||
|
m_diagnosticConfigId = "Builtin.TidyAndClazy";
|
||||||
|
|
||||||
|
m_savedDiagnosticConfigId = m_diagnosticConfigId;
|
||||||
|
|
||||||
updateSavedBuildBeforeAnalysiIfRequired();
|
updateSavedBuildBeforeAnalysiIfRequired();
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,13 @@
|
|||||||
\" </magic>\",
|
\" </magic>\",
|
||||||
\" </mime-type>\",
|
\" </mime-type>\",
|
||||||
|
|
||||||
|
\" <mime-type type=\'text/x-dsrc\'>\",
|
||||||
|
\" <comment>D source code</comment>\",
|
||||||
|
\" <sub-class-of type=\'text/plain\'/>\",
|
||||||
|
\" <glob pattern=\'*.d\'/>\",
|
||||||
|
\" <glob pattern=\'*.di\'/>\",
|
||||||
|
\" </mime-type>\",
|
||||||
|
|
||||||
\"</mime-info>\"
|
\"</mime-info>\"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode
|
|||||||
{
|
{
|
||||||
ClangDiagnosticConfig config;
|
ClangDiagnosticConfig config;
|
||||||
config.setId("Builtin.Questionable");
|
config.setId("Builtin.Questionable");
|
||||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
config.setDisplayName(QCoreApplication::translate(
|
||||||
"Warnings for questionable constructs"));
|
"ClangDiagnosticConfigsModel",
|
||||||
|
"Clang-only checks for questionable constructs"));
|
||||||
config.setIsReadOnly(true);
|
config.setIsReadOnly(true);
|
||||||
config.setClangOptions(QStringList{
|
config.setClangOptions(QStringList{
|
||||||
QStringLiteral("-Wall"),
|
QStringLiteral("-Wall"),
|
||||||
@@ -53,19 +54,33 @@ static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model)
|
|||||||
ClangDiagnosticConfig config;
|
ClangDiagnosticConfig config;
|
||||||
config.setId("Builtin.Pedantic");
|
config.setId("Builtin.Pedantic");
|
||||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||||
"Pedantic Warnings"));
|
"Clang-only pedantic checks"));
|
||||||
config.setIsReadOnly(true);
|
config.setIsReadOnly(true);
|
||||||
config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")});
|
config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")});
|
||||||
|
|
||||||
model.appendOrUpdate(config);
|
model.appendOrUpdate(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr const char *DEFAULT_TIDY_CHECKS = "-*,"
|
||||||
|
"bugprone-*,"
|
||||||
|
"cppcoreguidelines-*,"
|
||||||
|
"misc-*,"
|
||||||
|
"modernize-*,"
|
||||||
|
"performance-*,"
|
||||||
|
"readability-*,"
|
||||||
|
"-cppcoreguidelines-owning-memory,"
|
||||||
|
"-readability-braces-around-statements,"
|
||||||
|
"-readability-implicit-bool-conversion,"
|
||||||
|
"-readability-named-parameter";
|
||||||
|
constexpr const char *DEFAULT_CLAZY_CHECKS = "level0";
|
||||||
|
|
||||||
static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
|
static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
|
||||||
{
|
{
|
||||||
ClangDiagnosticConfig config;
|
ClangDiagnosticConfig config;
|
||||||
config.setId(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS);
|
config.setId(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS);
|
||||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
config.setDisplayName(QCoreApplication::translate(
|
||||||
"Warnings for almost everything"));
|
"ClangDiagnosticConfigsModel",
|
||||||
|
"Clang-only checks for almost everything"));
|
||||||
config.setIsReadOnly(true);
|
config.setIsReadOnly(true);
|
||||||
config.setClangOptions(QStringList{
|
config.setClangOptions(QStringList{
|
||||||
QStringLiteral("-Weverything"),
|
QStringLiteral("-Weverything"),
|
||||||
@@ -86,11 +101,75 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
|
|||||||
model.appendOrUpdate(config);
|
model.appendOrUpdate(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void addConfigForTidy(ClangDiagnosticConfigsModel &model)
|
||||||
|
{
|
||||||
|
ClangDiagnosticConfig config;
|
||||||
|
config.setId("Builtin.Tidy");
|
||||||
|
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||||
|
"Clang-Tidy thorough checks"));
|
||||||
|
config.setIsReadOnly(true);
|
||||||
|
config.setClangOptions(QStringList{QStringLiteral("-w")});
|
||||||
|
config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
|
||||||
|
config.setClangTidyChecks(QString::fromUtf8(DEFAULT_TIDY_CHECKS));
|
||||||
|
|
||||||
|
model.appendOrUpdate(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addConfigForClangAnalyze(ClangDiagnosticConfigsModel &model)
|
||||||
|
{
|
||||||
|
ClangDiagnosticConfig config;
|
||||||
|
config.setId("Builtin.TidyClangAnalyze");
|
||||||
|
config.setDisplayName(QCoreApplication::translate(
|
||||||
|
"ClangDiagnosticConfigsModel",
|
||||||
|
"Clang-Tidy static analyzer checks"));
|
||||||
|
config.setIsReadOnly(true);
|
||||||
|
config.setClangOptions(QStringList{
|
||||||
|
QStringLiteral("-w"),
|
||||||
|
});
|
||||||
|
config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
|
||||||
|
config.setClangTidyChecks("-*,clang-analyzer-*");
|
||||||
|
|
||||||
|
model.appendOrUpdate(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addConfigForClazy(ClangDiagnosticConfigsModel &model)
|
||||||
|
{
|
||||||
|
ClangDiagnosticConfig config;
|
||||||
|
config.setId("Builtin.Clazy");
|
||||||
|
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||||
|
"Clazy level0 checks"));
|
||||||
|
config.setIsReadOnly(true);
|
||||||
|
config.setClangOptions(QStringList{QStringLiteral("-w")});
|
||||||
|
config.setClazyChecks(QString::fromUtf8(DEFAULT_CLAZY_CHECKS));
|
||||||
|
|
||||||
|
model.appendOrUpdate(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addConfigForTidyAndClazy(ClangDiagnosticConfigsModel &model)
|
||||||
|
{
|
||||||
|
ClangDiagnosticConfig config;
|
||||||
|
config.setId("Builtin.TidyAndClazy");
|
||||||
|
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||||
|
"Clang-Tidy and Clazy preselected checks"));
|
||||||
|
config.setIsReadOnly(true);
|
||||||
|
config.setClangOptions(QStringList{QStringLiteral("-w")});
|
||||||
|
config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
|
||||||
|
|
||||||
|
config.setClangTidyChecks(QString::fromUtf8(DEFAULT_TIDY_CHECKS));
|
||||||
|
config.setClazyChecks(QString::fromUtf8(DEFAULT_CLAZY_CHECKS));
|
||||||
|
|
||||||
|
model.appendOrUpdate(config);
|
||||||
|
}
|
||||||
|
|
||||||
static void addBuiltinConfigs(ClangDiagnosticConfigsModel &model)
|
static void addBuiltinConfigs(ClangDiagnosticConfigsModel &model)
|
||||||
{
|
{
|
||||||
addConfigForPedanticWarnings(model);
|
addConfigForPedanticWarnings(model);
|
||||||
addConfigForQuestionableConstructs(model);
|
addConfigForQuestionableConstructs(model);
|
||||||
addConfigForAlmostEveryWarning(model);
|
addConfigForAlmostEveryWarning(model);
|
||||||
|
addConfigForTidy(model);
|
||||||
|
addConfigForClangAnalyze(model);
|
||||||
|
addConfigForClazy(model);
|
||||||
|
addConfigForTidyAndClazy(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangDiagnosticConfigsModel::ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs)
|
ClangDiagnosticConfigsModel::ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs)
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public:
|
|||||||
const QModelIndex index = indexForCheck(check);
|
const QModelIndex index = indexForCheck(check);
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
continue;
|
continue;
|
||||||
auto node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
|
auto *node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
|
||||||
node->checked = state;
|
node->checked = state;
|
||||||
propagateUp(index);
|
propagateUp(index);
|
||||||
propagateDown(index);
|
propagateDown(index);
|
||||||
@@ -161,6 +161,18 @@ public:
|
|||||||
return ProjectExplorer::SelectableFilesModel::data(index, role);
|
return ProjectExplorer::SelectableFilesModel::data(index, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
m_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
|
||||||
|
{
|
||||||
|
if (role == Qt::CheckStateRole && !m_enabled)
|
||||||
|
return false;
|
||||||
|
return ProjectExplorer::SelectableFilesModel::setData(index, value, role);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// TODO: Remove/replace this method after base class refactoring is done.
|
// TODO: Remove/replace this method after base class refactoring is done.
|
||||||
@@ -220,6 +232,8 @@ private:
|
|||||||
for (const ProjectExplorer::Tree *t : root->childDirectories)
|
for (const ProjectExplorer::Tree *t : root->childDirectories)
|
||||||
collectChecks(t, checks);
|
collectChecks(t, checks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool m_enabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(const Core::Id &configToSelect,
|
ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(const Core::Id &configToSelect,
|
||||||
@@ -489,7 +503,11 @@ void ClangDiagnosticConfigsWidget::syncClangTidyWidgets(const ClangDiagnosticCon
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tidyChecksWidget->setEnabled(!config.isReadOnly());
|
const bool enabled = !config.isReadOnly();
|
||||||
|
m_tidyChecks->tidyMode->setEnabled(enabled);
|
||||||
|
m_tidyChecks->plainTextEditButton->setText(enabled ? tr("Edit Checks as String...")
|
||||||
|
: tr("View Checks as String..."));
|
||||||
|
m_tidyTreeModel->setEnabled(enabled);
|
||||||
connectClangTidyItemChanged();
|
connectClangTidyItemChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,12 +668,17 @@ void ClangDiagnosticConfigsWidget::setupTabs()
|
|||||||
m_tidyChecks->checksPrefixesTree->header()->setStretchLastSection(false);
|
m_tidyChecks->checksPrefixesTree->header()->setStretchLastSection(false);
|
||||||
m_tidyChecks->checksPrefixesTree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
m_tidyChecks->checksPrefixesTree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||||
connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this]() {
|
connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this]() {
|
||||||
|
const bool readOnly = selectedConfig().isReadOnly();
|
||||||
|
|
||||||
QDialog dialog;
|
QDialog dialog;
|
||||||
dialog.setWindowTitle(tr("Checks"));
|
dialog.setWindowTitle(tr("Checks"));
|
||||||
dialog.setLayout(new QVBoxLayout);
|
dialog.setLayout(new QVBoxLayout);
|
||||||
auto *textEdit = new QTextEdit(&dialog);
|
auto *textEdit = new QTextEdit(&dialog);
|
||||||
|
textEdit->setReadOnly(readOnly);
|
||||||
dialog.layout()->addWidget(textEdit);
|
dialog.layout()->addWidget(textEdit);
|
||||||
auto *buttonsBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
auto *buttonsBox = new QDialogButtonBox(QDialogButtonBox::Ok
|
||||||
|
| (readOnly ? QDialogButtonBox::NoButton
|
||||||
|
: QDialogButtonBox::Cancel));
|
||||||
dialog.layout()->addWidget(buttonsBox);
|
dialog.layout()->addWidget(buttonsBox);
|
||||||
QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||||
QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||||
|
|||||||
@@ -487,10 +487,6 @@ QString CompilerOptionsBuilder::includeOption() const
|
|||||||
|
|
||||||
bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro ¯o) const
|
bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro ¯o) const
|
||||||
{
|
{
|
||||||
// TODO: Remove in QtCreator 4.7
|
|
||||||
if (macro.key == "__cplusplus")
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Ignore for all compiler toolchains since LLVM has it's own implementation for
|
// Ignore for all compiler toolchains since LLVM has it's own implementation for
|
||||||
// __has_include(STR) and __has_include_next(STR)
|
// __has_include(STR) and __has_include_next(STR)
|
||||||
if (macro.key.startsWith("__has_include"))
|
if (macro.key.startsWith("__has_include"))
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ bool isDebuggerWinException(unsigned long code)
|
|||||||
return code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
|
return code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFatalWinException(long code)
|
bool isFatalWinException(unsigned long code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case EXCEPTION_BREAKPOINT:
|
case EXCEPTION_BREAKPOINT:
|
||||||
@@ -217,7 +217,7 @@ bool winResumeThread(unsigned long, QString *) { return false; }
|
|||||||
bool isWinProcessBeingDebugged(unsigned long) { return false; }
|
bool isWinProcessBeingDebugged(unsigned long) { return false; }
|
||||||
void formatWindowsException(unsigned long , quint64, unsigned long,
|
void formatWindowsException(unsigned long , quint64, unsigned long,
|
||||||
quint64, quint64, QTextStream &) { }
|
quint64, quint64, QTextStream &) { }
|
||||||
bool isFatalWinException(long) { return false; }
|
bool isFatalWinException(unsigned long) { return false; }
|
||||||
bool isDebuggerWinException(unsigned long) { return false; }
|
bool isDebuggerWinException(unsigned long) { return false; }
|
||||||
|
|
||||||
#endif // !Q_OS_WIN
|
#endif // !Q_OS_WIN
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ bool winResumeThread(unsigned long dwThreadId, QString *errorMessage);
|
|||||||
bool isWinProcessBeingDebugged(unsigned long pid);
|
bool isWinProcessBeingDebugged(unsigned long pid);
|
||||||
|
|
||||||
// Special exception codes.
|
// Special exception codes.
|
||||||
enum
|
enum : unsigned long
|
||||||
{
|
{
|
||||||
winExceptionCppException = 0xe06d7363,
|
winExceptionCppException = 0xe06d7363,
|
||||||
winExceptionSetThreadName = 0x406d1388,
|
winExceptionSetThreadName = 0x406d1388,
|
||||||
@@ -60,7 +60,7 @@ void formatWindowsException(unsigned long code, quint64 address,
|
|||||||
unsigned long flags, quint64 info1, quint64 info2,
|
unsigned long flags, quint64 info1, quint64 info2,
|
||||||
QTextStream &str);
|
QTextStream &str);
|
||||||
// Check for access violation, etc.
|
// Check for access violation, etc.
|
||||||
bool isFatalWinException(long code);
|
bool isFatalWinException(unsigned long code);
|
||||||
|
|
||||||
// Check for EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP
|
// Check for EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP
|
||||||
bool isDebuggerWinException(unsigned long code);
|
bool isDebuggerWinException(unsigned long code);
|
||||||
|
|||||||
@@ -216,6 +216,23 @@ void GerritDialog::refresh()
|
|||||||
m_ui->treeView->sortByColumn(-1);
|
m_ui->treeView->sortByColumn(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GerritDialog::scheduleUpdateRemotes()
|
||||||
|
{
|
||||||
|
if (isVisible())
|
||||||
|
updateRemotes();
|
||||||
|
else
|
||||||
|
m_shouldUpdateRemotes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GerritDialog::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
QDialog::showEvent(event);
|
||||||
|
if (m_shouldUpdateRemotes) {
|
||||||
|
m_shouldUpdateRemotes = false;
|
||||||
|
updateRemotes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GerritDialog::remoteChanged()
|
void GerritDialog::remoteChanged()
|
||||||
{
|
{
|
||||||
const GerritServer server = m_ui->remoteComboBox->currentServer();
|
const GerritServer server = m_ui->remoteComboBox->currentServer();
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ public:
|
|||||||
void fetchStarted(const QSharedPointer<Gerrit::Internal::GerritChange> &change);
|
void fetchStarted(const QSharedPointer<Gerrit::Internal::GerritChange> &change);
|
||||||
void fetchFinished();
|
void fetchFinished();
|
||||||
void refresh();
|
void refresh();
|
||||||
|
void scheduleUpdateRemotes();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fetchDisplay(const QSharedPointer<Gerrit::Internal::GerritChange> &);
|
void fetchDisplay(const QSharedPointer<Gerrit::Internal::GerritChange> &);
|
||||||
@@ -77,6 +78,7 @@ private:
|
|||||||
void slotFetchCheckout();
|
void slotFetchCheckout();
|
||||||
void remoteChanged();
|
void remoteChanged();
|
||||||
void updateRemotes(bool forceReload = false);
|
void updateRemotes(bool forceReload = false);
|
||||||
|
void showEvent(QShowEvent *event) override;
|
||||||
|
|
||||||
void manageProgressIndicator();
|
void manageProgressIndicator();
|
||||||
|
|
||||||
@@ -101,6 +103,7 @@ private:
|
|||||||
QString m_repository;
|
QString m_repository;
|
||||||
bool m_fetchRunning = false;
|
bool m_fetchRunning = false;
|
||||||
bool m_updatingRemotes = false;
|
bool m_updatingRemotes = false;
|
||||||
|
bool m_shouldUpdateRemotes = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ void GerritOptionsPage::apply()
|
|||||||
newParameters.setPortFlagBySshType();
|
newParameters.setPortFlagBySshType();
|
||||||
*m_parameters = newParameters;
|
*m_parameters = newParameters;
|
||||||
m_parameters->toSettings(Core::ICore::settings());
|
m_parameters->toSettings(Core::ICore::settings());
|
||||||
|
emit settingsChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ public:
|
|||||||
void apply() override;
|
void apply() override;
|
||||||
void finish() override;
|
void finish() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void settingsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QSharedPointer<GerritParameters> &m_parameters;
|
const QSharedPointer<GerritParameters> &m_parameters;
|
||||||
QPointer<GerritOptionsWidget> m_widget;
|
QPointer<GerritOptionsWidget> m_widget;
|
||||||
|
|||||||
@@ -292,7 +292,12 @@ bool GerritPlugin::initialize(ActionContainer *ac)
|
|||||||
connect(pushAction, &QAction::triggered, this, [this]() { push(); });
|
connect(pushAction, &QAction::triggered, this, [this]() { push(); });
|
||||||
ac->addAction(m_pushToGerritCommand);
|
ac->addAction(m_pushToGerritCommand);
|
||||||
|
|
||||||
new GerritOptionsPage(m_parameters, this);
|
auto options = new GerritOptionsPage(m_parameters, this);
|
||||||
|
connect(options, &GerritOptionsPage::settingsChanged,
|
||||||
|
this, [this] {
|
||||||
|
if (m_dialog)
|
||||||
|
m_dialog->scheduleUpdateRemotes();
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +345,7 @@ void GerritPlugin::openView()
|
|||||||
{
|
{
|
||||||
if (m_dialog.isNull()) {
|
if (m_dialog.isNull()) {
|
||||||
while (!m_parameters->isValid()) {
|
while (!m_parameters->isValid()) {
|
||||||
Core::AsynchronousMessageBox::warning(tr("Error"),
|
QMessageBox::warning(Core::ICore::dialogParent(), tr("Error"),
|
||||||
tr("Invalid Gerrit configuration. Host, user and ssh binary are mandatory."));
|
tr("Invalid Gerrit configuration. Host, user and ssh binary are mandatory."));
|
||||||
if (!ICore::showOptionsDialog("Gerrit"))
|
if (!ICore::showOptionsDialog("Gerrit"))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ bool GerritServer::resolveRoot()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // unknown error - fail
|
default: // unknown error - fail
|
||||||
|
authenticated = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1069,7 +1069,6 @@ bool GitPlugin::submitEditorAboutToClose()
|
|||||||
|
|
||||||
// Go ahead!
|
// Go ahead!
|
||||||
SubmitFileModel *model = qobject_cast<SubmitFileModel *>(editor->fileModel());
|
SubmitFileModel *model = qobject_cast<SubmitFileModel *>(editor->fileModel());
|
||||||
bool closeEditor = true;
|
|
||||||
CommitType commitType = editor->commitType();
|
CommitType commitType = editor->commitType();
|
||||||
QString amendSHA1 = editor->amendSHA1();
|
QString amendSHA1 = editor->amendSHA1();
|
||||||
if (model->hasCheckedFiles() || !amendSHA1.isEmpty()) {
|
if (model->hasCheckedFiles() || !amendSHA1.isEmpty()) {
|
||||||
@@ -1077,12 +1076,12 @@ bool GitPlugin::submitEditorAboutToClose()
|
|||||||
if (!DocumentManager::saveDocument(editorDocument))
|
if (!DocumentManager::saveDocument(editorDocument))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
closeEditor = m_gitClient->addAndCommit(m_submitRepository, editor->panelData(),
|
if (!m_gitClient->addAndCommit(m_submitRepository, editor->panelData(), commitType,
|
||||||
commitType, amendSHA1,
|
amendSHA1, m_commitMessageFileName, model)) {
|
||||||
m_commitMessageFileName, model);
|
editor->updateFileModel();
|
||||||
}
|
|
||||||
if (!closeEditor)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
cleanCommitMessageFile();
|
cleanCommitMessageFile();
|
||||||
if (commitType == FixupCommit) {
|
if (commitType == FixupCommit) {
|
||||||
if (!m_gitClient->beginStashScope(m_submitRepository, "Rebase-fixup",
|
if (!m_gitClient->beginStashScope(m_submitRepository, "Rebase-fixup",
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ public:
|
|||||||
GitSubmitEditorPanelData panelData() const;
|
GitSubmitEditorPanelData panelData() const;
|
||||||
CommitType commitType() const { return m_commitType; }
|
CommitType commitType() const { return m_commitType; }
|
||||||
QString amendSHA1() const;
|
QString amendSHA1() const;
|
||||||
|
void updateFileModel() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QByteArray fileContents() const override;
|
QByteArray fileContents() const override;
|
||||||
void updateFileModel() override;
|
|
||||||
void forceUpdateFileModel();
|
void forceUpdateFileModel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "buildconfiguration.h"
|
#include "buildconfiguration.h"
|
||||||
#include "buildstep.h"
|
#include "buildstep.h"
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
#include "target.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
#include <coreplugin/reaper.h>
|
#include <coreplugin/reaper.h>
|
||||||
@@ -306,7 +307,10 @@ void AbstractProcessStep::processReadyReadStdOutput()
|
|||||||
if (!m_process)
|
if (!m_process)
|
||||||
return;
|
return;
|
||||||
m_process->setReadChannel(QProcess::StandardOutput);
|
m_process->setReadChannel(QProcess::StandardOutput);
|
||||||
const bool utf8Output = buildConfiguration()->environment().hasKey("VSLANG");
|
BuildConfiguration *bc = buildConfiguration();
|
||||||
|
if (!bc)
|
||||||
|
bc = target()->activeBuildConfiguration();
|
||||||
|
const bool utf8Output = bc && bc->environment().hasKey("VSLANG");
|
||||||
|
|
||||||
while (m_process->canReadLine()) {
|
while (m_process->canReadLine()) {
|
||||||
QString line = utf8Output ? QString::fromUtf8(m_process->readLine())
|
QString line = utf8Output ? QString::fromUtf8(m_process->readLine())
|
||||||
|
|||||||
@@ -162,20 +162,15 @@ Kit::Kit(const QVariantMap &data) :
|
|||||||
QVariantMap extra = data.value(QLatin1String(DATA_KEY)).toMap();
|
QVariantMap extra = data.value(QLatin1String(DATA_KEY)).toMap();
|
||||||
d->m_data.clear(); // remove default values
|
d->m_data.clear(); // remove default values
|
||||||
const QVariantMap::ConstIterator cend = extra.constEnd();
|
const QVariantMap::ConstIterator cend = extra.constEnd();
|
||||||
for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it) {
|
for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it)
|
||||||
const QString key = it.key();
|
d->m_data.insert(Id::fromString(it.key()), it.value());
|
||||||
if (!key.isEmpty())
|
|
||||||
d->m_data.insert(Id::fromString(key), it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList();
|
QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList();
|
||||||
foreach (const QString &mutableInfo, mutableInfoList)
|
foreach (const QString &mutableInfo, mutableInfoList)
|
||||||
if (!mutableInfo.isEmpty())
|
|
||||||
d->m_mutable.insert(Id::fromString(mutableInfo));
|
d->m_mutable.insert(Id::fromString(mutableInfo));
|
||||||
|
|
||||||
QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList();
|
QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList();
|
||||||
foreach (const QString &stickyInfo, stickyInfoList)
|
foreach (const QString &stickyInfo, stickyInfoList)
|
||||||
if (!stickyInfo.isEmpty())
|
|
||||||
d->m_sticky.insert(Id::fromString(stickyInfo));
|
d->m_sticky.insert(Id::fromString(stickyInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -368,18 +368,21 @@ public:
|
|||||||
const QStyleOptionViewItem &option, const QModelIndex &idx) final
|
const QStyleOptionViewItem &option, const QModelIndex &idx) final
|
||||||
{
|
{
|
||||||
if (ev->type() == QEvent::MouseButtonRelease) {
|
if (ev->type() == QEvent::MouseButtonRelease) {
|
||||||
|
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(ev);
|
||||||
|
const Qt::MouseButtons button = mouseEvent->button();
|
||||||
const QPoint pos = static_cast<QMouseEvent *>(ev)->pos();
|
const QPoint pos = static_cast<QMouseEvent *>(ev)->pos();
|
||||||
const QRect rc(option.rect.right() - 24, option.rect.top(), 24, SESSION_LINE_HEIGHT);
|
const QRect rc(option.rect.right() - 24, option.rect.top(), 24, SESSION_LINE_HEIGHT);
|
||||||
const QString sessionName = idx.data(Qt::DisplayRole).toString();
|
const QString sessionName = idx.data(Qt::DisplayRole).toString();
|
||||||
if (rc.contains(pos)) {
|
if (rc.contains(pos) || button == Qt::RightButton) {
|
||||||
// The expand/collapse "button".
|
// The expand/collapse "button".
|
||||||
if (m_expandedSessions.contains(sessionName))
|
if (m_expandedSessions.contains(sessionName))
|
||||||
m_expandedSessions.removeOne(sessionName);
|
m_expandedSessions.removeOne(sessionName);
|
||||||
else
|
else
|
||||||
m_expandedSessions.append(sessionName);
|
m_expandedSessions.append(sessionName);
|
||||||
model->layoutChanged({QPersistentModelIndex(idx)});
|
model->layoutChanged({QPersistentModelIndex(idx)});
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (button == Qt::LeftButton) {
|
||||||
// One of the action links?
|
// One of the action links?
|
||||||
const auto sessionModel = qobject_cast<SessionModel *>(model);
|
const auto sessionModel = qobject_cast<SessionModel *>(model);
|
||||||
QTC_ASSERT(sessionModel, return false);
|
QTC_ASSERT(sessionModel, return false);
|
||||||
@@ -393,6 +396,7 @@ public:
|
|||||||
sessionModel->deleteSession(sessionName);
|
sessionModel->deleteSession(sessionName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ev->type() == QEvent::MouseMove) {
|
if (ev->type() == QEvent::MouseMove) {
|
||||||
model->layoutChanged({QPersistentModelIndex(idx)}); // Somewhat brutish.
|
model->layoutChanged({QPersistentModelIndex(idx)}); // Somewhat brutish.
|
||||||
//update(option.rect);
|
//update(option.rect);
|
||||||
@@ -473,10 +477,14 @@ public:
|
|||||||
const QStyleOptionViewItem &, const QModelIndex &idx) final
|
const QStyleOptionViewItem &, const QModelIndex &idx) final
|
||||||
{
|
{
|
||||||
if (ev->type() == QEvent::MouseButtonRelease) {
|
if (ev->type() == QEvent::MouseButtonRelease) {
|
||||||
QString projectFile = idx.data(ProjectModel::FilePathRole).toString();
|
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(ev);
|
||||||
|
const Qt::MouseButtons button = mouseEvent->button();
|
||||||
|
if (button == Qt::LeftButton) {
|
||||||
|
const QString projectFile = idx.data(ProjectModel::FilePathRole).toString();
|
||||||
ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
|
ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ private:
|
|||||||
QPushButton * const m_changeButton;
|
QPushButton * const m_changeButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QbsKitInformation::QbsKitInformation()
|
||||||
|
{
|
||||||
|
setObjectName(QLatin1String("QbsKitInformation"));
|
||||||
|
setId(QbsKitInformation::id());
|
||||||
|
setPriority(22000);
|
||||||
|
}
|
||||||
|
|
||||||
QString QbsKitInformation::displayName()
|
QString QbsKitInformation::displayName()
|
||||||
{
|
{
|
||||||
return tr("Additional Qbs Profile Settings");
|
return tr("Additional Qbs Profile Settings");
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class QbsKitInformation final : public ProjectExplorer::KitInformation
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
QbsKitInformation();
|
||||||
|
|
||||||
static QString displayName();
|
static QString displayName();
|
||||||
static QString representation(const ProjectExplorer::Kit *kit);
|
static QString representation(const ProjectExplorer::Kit *kit);
|
||||||
static QVariantMap properties(const ProjectExplorer::Kit *kit);
|
static QVariantMap properties(const ProjectExplorer::Kit *kit);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
@@ -55,6 +56,9 @@ QbsProjectParser::QbsProjectParser(QbsProject *project, QFutureInterface<bool> *
|
|||||||
{
|
{
|
||||||
m_project = project->qbsProject();
|
m_project = project->qbsProject();
|
||||||
m_projectFilePath = project->projectFilePath().toString();
|
m_projectFilePath = project->projectFilePath().toString();
|
||||||
|
auto * const watcher = new QFutureWatcher<bool>(this);
|
||||||
|
connect(watcher, &QFutureWatcher<bool>::canceled, this, &QbsProjectParser::cancel);
|
||||||
|
watcher->setFuture(fi->future());
|
||||||
}
|
}
|
||||||
|
|
||||||
QbsProjectParser::~QbsProjectParser()
|
QbsProjectParser::~QbsProjectParser()
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ GuiAppWizard::GuiAppWizard()
|
|||||||
"Includes a Qt Designer-based main window.\n\n"
|
"Includes a Qt Designer-based main window.\n\n"
|
||||||
"Preselects a desktop Qt for building the application if available."));
|
"Preselects a desktop Qt for building the application if available."));
|
||||||
setIcon(QIcon(QLatin1String(":/wizards/images/gui.png")));
|
setIcon(QIcon(QLatin1String(":/wizards/images/gui.png")));
|
||||||
setRequiredFeatures({QtSupport::Constants::FEATURE_QWIDGETS});
|
auto qt5 = Core::Id::fromString(QString(QtSupport::Constants::FEATURE_QT_PREFIX).append(".5"));
|
||||||
|
setRequiredFeatures({QtSupport::Constants::FEATURE_QWIDGETS, qt5});
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::BaseFileWizard *GuiAppWizard::create(QWidget *parent, const Core::WizardDialogParameters ¶meters) const
|
Core::BaseFileWizard *GuiAppWizard::create(QWidget *parent, const Core::WizardDialogParameters ¶meters) const
|
||||||
@@ -187,6 +188,7 @@ Core::GeneratedFiles GuiAppWizard::generateFiles(const QWizard *w,
|
|||||||
QTextStream proStr(&contents);
|
QTextStream proStr(&contents);
|
||||||
QtProjectParameters::writeProFileHeader(proStr);
|
QtProjectParameters::writeProFileHeader(proStr);
|
||||||
projectParams.writeProFile(proStr);
|
projectParams.writeProFile(proStr);
|
||||||
|
proStr << "\nCONFIG += c++11"; // ensure all Qt5 versions can handle the source
|
||||||
proStr << "\n\nSOURCES +="
|
proStr << "\n\nSOURCES +="
|
||||||
<< " \\\n " << Utils::FileName::fromString(mainSourceFileName).fileName()
|
<< " \\\n " << Utils::FileName::fromString(mainSourceFileName).fileName()
|
||||||
<< " \\\n " << Utils::FileName::fromString(formSource.path()).fileName()
|
<< " \\\n " << Utils::FileName::fromString(formSource.path()).fileName()
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ QtProjectParameters GuiAppWizardDialog::projectParameters() const
|
|||||||
rc.path = path();
|
rc.path = path();
|
||||||
rc.selectedModules = selectedModulesList();
|
rc.selectedModules = selectedModulesList();
|
||||||
rc.deselectedModules = deselectedModulesList();
|
rc.deselectedModules = deselectedModulesList();
|
||||||
|
rc.qtVersionSupport = QtProjectParameters::SupportQt5Only;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,8 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
|
|||||||
RangeType rangeType = MaximumRangeType;
|
RangeType rangeType = MaximumRangeType;
|
||||||
if (!stream.atEnd()) {
|
if (!stream.atEnd()) {
|
||||||
stream >> subtype;
|
stream >> subtype;
|
||||||
|
if (subtype >= 0 && subtype < MaximumRangeType)
|
||||||
rangeType = static_cast<RangeType>(subtype);
|
rangeType = static_cast<RangeType>(subtype);
|
||||||
if (rangeType < 0 || rangeType > MaximumRangeType)
|
|
||||||
rangeType = MaximumRangeType;
|
|
||||||
} else {
|
} else {
|
||||||
subtype = -1;
|
subtype = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -687,7 +687,7 @@ public:
|
|||||||
|
|
||||||
QRegExp m_searchExpr;
|
QRegExp m_searchExpr;
|
||||||
FindFlags m_findFlags;
|
FindFlags m_findFlags;
|
||||||
void highlightSearchResults(const QTextBlock &block, TextEditorOverlay *overlay) const;
|
void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const;
|
||||||
QTimer m_delayedUpdateTimer;
|
QTimer m_delayedUpdateTimer;
|
||||||
|
|
||||||
void setExtraSelections(Core::Id kind, const QList<QTextEdit::ExtraSelection> &selections);
|
void setExtraSelections(Core::Id kind, const QList<QTextEdit::ExtraSelection> &selections);
|
||||||
@@ -3657,8 +3657,7 @@ QTextBlock TextEditorWidgetPrivate::foldedBlockAt(const QPoint &pos, QRect *box)
|
|||||||
return QTextBlock();
|
return QTextBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const
|
||||||
TextEditorOverlay *overlay) const
|
|
||||||
{
|
{
|
||||||
if (m_searchExpr.isEmpty())
|
if (m_searchExpr.isEmpty())
|
||||||
return;
|
return;
|
||||||
@@ -3671,6 +3670,13 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|
|||||||
int idx = -1;
|
int idx = -1;
|
||||||
int l = 1;
|
int l = 1;
|
||||||
|
|
||||||
|
const int left = data.viewportRect.left() - int(data.offset.x());
|
||||||
|
const int right = data.viewportRect.right() - int(data.offset.x());
|
||||||
|
const int top = data.viewportRect.top() - int(data.offset.y());
|
||||||
|
const int bottom = data.viewportRect.bottom() - int(data.offset.y());
|
||||||
|
const QColor &searchResultColor = m_document->fontSettings()
|
||||||
|
.toTextCharFormat(C_SEARCH_RESULT).background().color().darker(120);
|
||||||
|
|
||||||
while (idx < text.length()) {
|
while (idx < text.length()) {
|
||||||
idx = m_searchExpr.indexIn(text, idx + l);
|
idx = m_searchExpr.indexIn(text, idx + l);
|
||||||
if (idx < 0)
|
if (idx < 0)
|
||||||
@@ -3683,19 +3689,44 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|
|||||||
|| (idx + l < text.length() && text.at(idx + l).isLetterOrNumber())))
|
|| (idx + l < text.length() && text.at(idx + l).isLetterOrNumber())))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!q->inFindScope(blockPosition + idx, blockPosition + idx + l))
|
const int start = blockPosition + idx;
|
||||||
|
const int end = start + l;
|
||||||
|
if (!q->inFindScope(start, end))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const QTextCharFormat &searchResultFormat
|
// check if the result is inside the visibale area for long blocks
|
||||||
= m_document->fontSettings().toTextCharFormat(C_SEARCH_RESULT);
|
const QTextLine &startLine = block.layout()->lineForTextPosition(idx);
|
||||||
overlay->addOverlaySelection(blockPosition + idx,
|
const QTextLine &endLine = block.layout()->lineForTextPosition(idx + l);
|
||||||
blockPosition + idx + l,
|
|
||||||
searchResultFormat.background().color().darker(120),
|
|
||||||
QColor(),
|
|
||||||
(idx == cursor.selectionStart() - blockPosition
|
|
||||||
&& idx + l == cursor.selectionEnd() - blockPosition)?
|
|
||||||
TextEditorOverlay::DropShadow : 0);
|
|
||||||
|
|
||||||
|
if (startLine.isValid() && endLine.isValid()
|
||||||
|
&& startLine.lineNumber() == endLine.lineNumber()) {
|
||||||
|
const int lineY = int(endLine.y() + q->blockBoundingGeometry(block).y());
|
||||||
|
if (startLine.cursorToX(idx) > right) { // result is behind the visible area
|
||||||
|
if (endLine.lineNumber() >= block.lineCount() - 1)
|
||||||
|
break; // this is the last line in the block, nothing more to add
|
||||||
|
|
||||||
|
// skip to the start of the next line
|
||||||
|
idx = block.layout()->lineAt(endLine.lineNumber() + 1).textStart();
|
||||||
|
l = 0;
|
||||||
|
continue;
|
||||||
|
} else if (endLine.cursorToX(idx + l, QTextLine::Trailing) < left) { // result is in front of the visible area skip it
|
||||||
|
continue;
|
||||||
|
} else if (lineY + endLine.height() < top) {
|
||||||
|
if (endLine.lineNumber() >= block.lineCount() - 1)
|
||||||
|
break; // this is the last line in the block, nothing more to add
|
||||||
|
// before visible area, skip to the start of the next line
|
||||||
|
idx = block.layout()->lineAt(endLine.lineNumber() + 1).textStart();
|
||||||
|
l = 0;
|
||||||
|
continue;
|
||||||
|
} else if (lineY > bottom) {
|
||||||
|
break; // under the visible area, nothing more to add
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint flag = (idx == cursor.selectionStart() - blockPosition
|
||||||
|
&& idx + l == cursor.selectionEnd() - blockPosition) ?
|
||||||
|
TextEditorOverlay::DropShadow : 0;
|
||||||
|
m_searchResultOverlay->addOverlaySelection(start, end, searchResultColor, QColor(), flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4256,7 +4287,7 @@ void TextEditorWidgetPrivate::paintSearchResultOverlay(const PaintEventData &dat
|
|||||||
|
|
||||||
if (blockBoundingRect.bottom() >= data.eventRect.top() - margin
|
if (blockBoundingRect.bottom() >= data.eventRect.top() - margin
|
||||||
&& blockBoundingRect.top() <= data.eventRect.bottom() + margin) {
|
&& blockBoundingRect.top() <= data.eventRect.bottom() + margin) {
|
||||||
highlightSearchResults(block, m_searchResultOverlay);
|
highlightSearchResults(block, data);
|
||||||
}
|
}
|
||||||
offset.ry() += blockBoundingRect.height();
|
offset.ry() += blockBoundingRect.height();
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,12 @@ FollowSymbolResult FollowSymbol::followSymbol(CXTranslationUnit tu,
|
|||||||
CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
|
CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
|
||||||
const ClangString filename(clang_getFileName(file));
|
const ClangString filename(clang_getFileName(file));
|
||||||
const SourceLocation loc(tu, filename, 1, 1);
|
const SourceLocation loc(tu, filename, 1, 1);
|
||||||
return SourceRangeContainer(SourceRange(loc, loc));
|
FollowSymbolResult result;
|
||||||
|
result.range = SourceRangeContainer(SourceRange(loc, loc));
|
||||||
|
// CLANG-UPGRADE-CHECK: Remove if we don't use empty generated ui_* headers anymore.
|
||||||
|
if (Utf8String(filename).contains("ui_"))
|
||||||
|
result.isResultOnlyForFallBack = true;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For definitions we can always find a declaration in current TU
|
// For definitions we can always find a declaration in current TU
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ def prepareBuildSettings(targetCount, currentTarget, setReleaseBuild=True, disab
|
|||||||
def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings):
|
def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings):
|
||||||
def kitIsActivated(kit):
|
def kitIsActivated(kit):
|
||||||
return not (str(kit.toolTip).startswith("<h3>Click to activate:</h3>")
|
return not (str(kit.toolTip).startswith("<h3>Click to activate:</h3>")
|
||||||
or str(kit.toolTip).startswith("<h3>Kit is unsuited for Project</h3>"))
|
or str(kit.toolTip).startswith("<h3>Kit is unsuited for project</h3>"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
treeView = waitForObject(":Projects.ProjectNavigationTreeView")
|
treeView = waitForObject(":Projects.ProjectNavigationTreeView")
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ def renameFile(projectDir, proFile, branch, oldname, newname):
|
|||||||
menu = ":Qt Creator.Project.Menu.File_QMenu"
|
menu = ":Qt Creator.Project.Menu.File_QMenu"
|
||||||
activateItem(waitForObjectItem(menu, "Rename..."))
|
activateItem(waitForObjectItem(menu, "Rename..."))
|
||||||
replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit")
|
replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit")
|
||||||
if not (oldname.lower().endswith(".qrc") and JIRA.isBugStillOpen(20057)):
|
|
||||||
test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0],
|
test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0],
|
||||||
"Only the filename without the extension is selected?")
|
"Only the filename without the extension is selected?")
|
||||||
replaceEditorContent(replaceEdit, newname)
|
replaceEditorContent(replaceEdit, newname)
|
||||||
|
|||||||