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)
|
||||
* Fixed that extra editor windows were not restored when opening session
|
||||
(QTCREATORBUG-13840)
|
||||
* Fixed that editor could stay busy repainting annotations (QTCREATORBUG-20422)
|
||||
* FakeVim
|
||||
* Added `:<range>sor[t][!]`
|
||||
|
||||
@@ -55,6 +56,7 @@ QMake Projects
|
||||
* Added support for `-isystem` in `QMAKE_CXXFLAGS`
|
||||
* Added deployment rules for devices to widget and console application wizards
|
||||
(QTCREATORBUG-20358)
|
||||
* Fixed that arguments for QMake step did not expand variables
|
||||
|
||||
C++ Support
|
||||
|
||||
@@ -95,6 +97,11 @@ Python Support
|
||||
|
||||
* Added stack traces in application output to Issues pane (category `Python`)
|
||||
|
||||
Debugging
|
||||
|
||||
* QML
|
||||
* Added support for nested properties (QTBUG-68474)
|
||||
|
||||
Clang Static Analyzer
|
||||
|
||||
* Renamed plugin to `ClangTools`
|
||||
@@ -141,9 +148,11 @@ Android
|
||||
* Improved behavior when emulator cannot be started (QTCREATORBUG-20160)
|
||||
|
||||
Credits for these changes go to:
|
||||
Aaron Barany
|
||||
Aleix Pol
|
||||
Alessandro Portale
|
||||
Alexander Drozdov
|
||||
Alexandru Croitor
|
||||
Andre Hartmann
|
||||
André Pönitz
|
||||
Antonio Di Monaco
|
||||
@@ -155,13 +164,16 @@ Claus Steuer
|
||||
Colin Duquesnoy
|
||||
David Schulz
|
||||
Eike Ziller
|
||||
Filipe Azevedo
|
||||
Friedemann Kleint
|
||||
Hugo Holgersson
|
||||
Ivan Donchevskii
|
||||
Jaroslaw Kobus
|
||||
Jay Gupta
|
||||
José Tomás Tocino
|
||||
Jörg Bornemann
|
||||
Kari Oikarinen
|
||||
Kimmo Linnavuo
|
||||
Leena Miettinen
|
||||
Marco Benelli
|
||||
Marco Bubke
|
||||
@@ -169,6 +181,7 @@ Mitch Curtis
|
||||
Nikita Baryshnikov
|
||||
Nikolai Kosjar
|
||||
Orgad Shaneh
|
||||
Oswald Buddenhagen
|
||||
Pawel Rutka
|
||||
Przemyslaw Gorszkowski
|
||||
Razi Alavizadeh
|
||||
|
||||
@@ -17,8 +17,8 @@ macro.note = "\\b{Note:}"
|
||||
macro.oslash.HTML = "ø"
|
||||
macro.ouml.HTML = "ö"
|
||||
macro.QA = "Qt Assistant"
|
||||
macro.QC = "Qt Creator"
|
||||
macro.QCE = "Qt Creator Enterprise"
|
||||
macro.QC = "$IDE_DISPLAY_NAME"
|
||||
macro.QCE = "$IDE_DISPLAY_NAME Enterprise"
|
||||
macro.QD = "Qt Designer"
|
||||
macro.QL = "Qt Linguist"
|
||||
macro.QMLD = "Qt Quick Designer"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
project = "QtCreator"
|
||||
description = "Qt Creator Manual"
|
||||
url = http://doc.qt.io/qtcreator
|
||||
project = "$IDE_DISPLAY_NAME"
|
||||
description = "$IDE_DISPLAY_NAME Manual"
|
||||
url = http://doc.qt.io/$IDE_ID
|
||||
|
||||
headerdirs =
|
||||
sourcedirs = ../src
|
||||
@@ -54,17 +54,17 @@ include(qt-defines.qdocconf)
|
||||
sources.fileextensions = "*.qdoc"
|
||||
|
||||
qhp.projects = QtCreator
|
||||
qhp.QtCreator.file = qtcreator.qhp
|
||||
qhp.QtCreator.namespace = org.qt-project.qtcreator.$QTC_VERSION_TAG
|
||||
qhp.QtCreator.file = $IDE_ID.qhp
|
||||
qhp.QtCreator.namespace = org.qt-project.$IDE_ID.$QTC_VERSION_TAG
|
||||
qhp.QtCreator.virtualFolder = doc
|
||||
qhp.QtCreator.indexTitle = Qt Creator Manual $QTC_VERSION
|
||||
qhp.QtCreator.filterAttributes = qtcreator $QTC_VERSION
|
||||
qhp.QtCreator.customFilters.QtCreator.name = Qt Creator $QTC_VERSION
|
||||
qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator $QTC_VERSION
|
||||
qhp.QtCreator.indexTitle = $IDE_DISPLAY_NAME Manual $QTC_VERSION
|
||||
qhp.QtCreator.filterAttributes = $IDE_ID $QTC_VERSION
|
||||
qhp.QtCreator.customFilters.QtCreator.name = $IDE_DISPLAY_NAME $QTC_VERSION
|
||||
qhp.QtCreator.customFilters.QtCreator.filterAttributes = $IDE_ID $QTC_VERSION
|
||||
qhp.QtCreator.indexRoot =
|
||||
|
||||
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.type = manual
|
||||
|
||||
@@ -73,5 +73,5 @@ qhp.QtCreator.subprojects.manual.type = manual
|
||||
macro.see = "\\sa"
|
||||
macro.function = "\\fn"
|
||||
|
||||
navigation.landingpage = "Qt Creator Manual"
|
||||
buildversion = "Qt Creator Manual $QTC_VERSION"
|
||||
navigation.landingpage = "$IDE_DISPLAY_NAME Manual"
|
||||
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/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -40,15 +40,15 @@
|
||||
\commercial
|
||||
|
||||
\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
|
||||
a limited extent, on Linux desktop platforms. The CPU Usage Analyzer uses
|
||||
the Perf tool bundled with the Linux kernel to take periodic snapshots of
|
||||
the call chain of an application and visualizes them in a timeline view or
|
||||
as a flame graph.
|
||||
used to analyze the CPU and memory usage of an application on embedded
|
||||
devices and, to a limited extent, on Linux desktop platforms. The
|
||||
Performance Analyzer uses the Perf tool bundled with the Linux kernel to
|
||||
take periodic snapshots of the call chain of an application and visualizes
|
||||
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.
|
||||
|
||||
Profile builds produce optimized binaries with separate debug symbols and
|
||||
@@ -69,16 +69,16 @@
|
||||
|
||||
\endlist
|
||||
|
||||
You can start the CPU Usage Analyzer in the following ways:
|
||||
You can start the Performance Analyzer in the following ways:
|
||||
|
||||
\list
|
||||
\li Select \uicontrol Analyze > \uicontrol {CPU Usage Analyzer} to
|
||||
\li Select \uicontrol Analyze > \uicontrol {Performance Analyzer} to
|
||||
profile the current application.
|
||||
|
||||
\li Select the
|
||||
\inlineimage qtcreator-analyze-start-button.png
|
||||
(\uicontrol Start) button to start the application from the
|
||||
CPU Usage Analyzer.
|
||||
Performance Analyzer.
|
||||
|
||||
\endlist
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
(\uicontrol {Collect profile data}) button.
|
||||
|
||||
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
|
||||
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
|
||||
@@ -103,16 +103,28 @@
|
||||
Profile data will still be generated, but \QC will discard it until you
|
||||
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 {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
|
||||
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
|
||||
the dropdown menu next to the \uicontrol {Collect profile data} button.
|
||||
@@ -120,12 +132,12 @@
|
||||
\section2 Choosing Event Types
|
||||
|
||||
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
|
||||
counters that react to the number of instructions or CPU cycles executed.
|
||||
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
|
||||
event to be sampled, most commonly \uicontrol {hardware} or
|
||||
\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
|
||||
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
|
||||
|
||||
@@ -154,7 +178,7 @@
|
||||
a sample every \c n times one of the chosen events has occurred,
|
||||
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
|
||||
sampling period. Specify \c n in the \uicontrol {Sample period}
|
||||
field.
|
||||
@@ -168,7 +192,7 @@
|
||||
There may be a significant difference between the sampling period you
|
||||
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
|
||||
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
|
||||
@@ -176,25 +200,33 @@
|
||||
|
||||
\section2 Selecting Call Graph Mode
|
||||
|
||||
In the \uicontrol {Call graph mode} field, you can specify how the CPU Usage
|
||||
Analyzer recovers call chains from your application.
|
||||
In the \uicontrol {Call graph mode} field, you can specify how the
|
||||
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
|
||||
the target device to walk the chain of frame pointers in order to retrieve
|
||||
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
|
||||
application stack each time a sample is triggered and transmits that
|
||||
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
|
||||
default, so the frame pointer mode is only useful with customized systems.
|
||||
|
||||
\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
|
||||
\uicontrol {Stack snapshot size} field. Large stack snapshots result in a
|
||||
larger volume of data to be transferred and processed. Small stack
|
||||
@@ -212,7 +244,7 @@
|
||||
\section2 Resolving Names for JIT-compiled JavaScript Functions
|
||||
|
||||
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
|
||||
\uicontrol {Flame Graph} views. This only works if the process being
|
||||
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
|
||||
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
|
||||
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
|
||||
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 zoom range (8) or click the outline to move on the outline. You can
|
||||
The outline (9) summarizes the period for which data was collected. Drag
|
||||
the zoom range (7) or click the outline to move on the outline. You can
|
||||
also move between events by selecting the
|
||||
\uicontrol {Jump to Previous Event} (1) and \uicontrol {Jump to Next Event}
|
||||
(2) buttons.
|
||||
\uicontrol {Jump to Previous Event} and \uicontrol {Jump to Next Event}
|
||||
buttons (1).
|
||||
|
||||
Select the \uicontrol {Show Zoom Slider} button (3) to open a slider that
|
||||
you can use to set the zoom level. You can also drag the zoom handles (9).
|
||||
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 (8).
|
||||
To reset the default zoom level, right-click the timeline to open the
|
||||
context menu, and select \uicontrol {Reset Zoom}.
|
||||
|
||||
\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}
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
consecutive samples, then this represents a single call to the respective
|
||||
function. This is, of course, a simplification. Also, there may be other
|
||||
@@ -318,7 +350,7 @@
|
||||
|
||||
\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
|
||||
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
|
||||
|
||||
\image qtcreator-cpu-usage-analyzer-flamegraph.png
|
||||
\image qtcreator-performance-analyzer-flamegraph.png
|
||||
|
||||
The \uicontrol {Flame Graph} view shows a more concise statistical overview
|
||||
of the execution. The horizontal bars show the total number of samples
|
||||
taken for a certain function, relative to the total number of samples. The
|
||||
nesting shows which functions were called by which other ones.
|
||||
of the execution. The horizontal bars show an aspect of the samples
|
||||
taken for a certain function, relative to the same aspect of all samples
|
||||
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
|
||||
|
||||
@@ -357,19 +416,20 @@
|
||||
\uicontrol {Flame Graph}, or \uicontrol {Statistics} views, information
|
||||
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 {Limit Statistics to Selected Range} in the context menu in the
|
||||
\uicontrol {Timeline} view.
|
||||
\uicontrol Analyze > \uicontrol {Performance Analyzer Options} >
|
||||
\uicontrol {Limit to the Range Selected in Timeline}. To show the full
|
||||
stack frame, select \uicontrol {Show Full Range}.
|
||||
|
||||
\section1 Loading Perf Data Files
|
||||
|
||||
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 >
|
||||
\uicontrol {CPU Usage Analyzer Options} > \uicontrol {Load perf.data} to
|
||||
\uicontrol {Performance Analyzer Options} > \uicontrol {Load perf.data} to
|
||||
load a file.
|
||||
|
||||
\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
|
||||
the kit that the application was built with and the folder where the
|
||||
application executable is located.
|
||||
@@ -377,11 +437,11 @@
|
||||
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
|
||||
\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
|
||||
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
|
||||
preconditions have to be met. All system images for the
|
||||
\l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
|
||||
@@ -394,15 +454,15 @@
|
||||
\section1 Loading and Saving Trace Files
|
||||
|
||||
You can save and load trace data in a format specific to the
|
||||
CPU Usage Analyzer with the respective entries in \uicontrol Analyze >
|
||||
\uicontrol {CPU Usage Analyzer Options}. This format is self-contained, and
|
||||
Performance Analyzer with the respective entries in \uicontrol Analyze >
|
||||
\uicontrol {Performance Analyzer Options}. This format is self-contained, and
|
||||
therefore loading it does not require you to specify the recording
|
||||
environment. You can transfer such trace files to a different computer
|
||||
without any tool chain or debug symbols and analyze them there.
|
||||
|
||||
\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
|
||||
\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
|
||||
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
|
||||
desktop applications with the CPU Usage Analyzer (commercial only)
|
||||
desktop applications with the Performance Analyzer (commercial only)
|
||||
that integrates the Linux Perf tool.
|
||||
|
||||
\endlist
|
||||
|
||||
@@ -68,14 +68,12 @@
|
||||
|
||||
\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
|
||||
\uicontrol {Custom Settings}, and then select \uicontrol Manage to
|
||||
specify the Clang-Tidy and Clazy checks to perform.
|
||||
|
||||
\li Select the new custom configuration in the list of configurations
|
||||
(1).
|
||||
\li In the \uicontrol {Diagnostic Configuration} group, select a Clang
|
||||
configuration in the list of pre-defined configurations (1). For
|
||||
more information about creating a custom configuration, see
|
||||
\l {Configuring Clang Tools}.
|
||||
|
||||
\li In the \uicontrol {Files to Analyze} group, select the files to
|
||||
apply the checks to.
|
||||
@@ -90,7 +88,10 @@
|
||||
(\uicontrol Start) button to open the \uicontrol {Analyzer Configuration}
|
||||
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
|
||||
where the issue appears in the code editor.
|
||||
@@ -106,14 +107,35 @@
|
||||
\list
|
||||
|
||||
\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
|
||||
perform.
|
||||
|
||||
\image qtcreator-clang-tidy.png
|
||||
\image qtcreator-clang-tidy.png "Clang-Tidy tab"
|
||||
|
||||
\li To edit the selected check as plain text, select
|
||||
\uicontrol {Edit Checks as String}.
|
||||
@@ -121,7 +143,7 @@
|
||||
\li In the \uicontrol Clazy tab, select the level of Clazy
|
||||
checks to perform.
|
||||
|
||||
\image qtcreator-clazy.png
|
||||
\image qtcreator-clazy.png "Clazy tab"
|
||||
|
||||
\endlist
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
\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
|
||||
Microsoft Windows, when using the Microsoft tool chain the Microsoft Console
|
||||
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,
|
||||
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
|
||||
Qt or the stand-alone \QC.
|
||||
|
||||
@@ -328,7 +328,7 @@
|
||||
codesign -f -s "fsfgdb" $INSTALL_LOCATION/fsfgdb
|
||||
\endcode
|
||||
|
||||
\li In \QC, select \uicontrol {Qt Creator} > \uicontrol Preferences >
|
||||
\li In \QC, select \uicontrol {\QC} > \uicontrol Preferences >
|
||||
\uicontrol Kits > \uicontrol Add to
|
||||
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
|
||||
post-mortem debugger. To change the setting, select
|
||||
\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
|
||||
crashes on Windows. Click the \uicontrol {Debug in \QC} button in the error
|
||||
@@ -979,7 +979,7 @@
|
||||
Unlike GDB's
|
||||
\l{https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing}
|
||||
{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
|
||||
Linux, LLDB on macOS, and CDB on Windows, or any other platform on which at
|
||||
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}
|
||||
check box. To index all files, deselect the check box.
|
||||
|
||||
\li Select \uicontrol Manage to specify the level for requesting Clang
|
||||
warnings.
|
||||
\li Select \uicontrol Manage to specify the Clang checks to perform.
|
||||
|
||||
\image qtcreator-diagnostics-configuration.png
|
||||
|
||||
\endlist
|
||||
|
||||
\section1 Clang Warnings
|
||||
\section1 Clang Checks
|
||||
|
||||
The predefined configurations request Clang warnings at the following
|
||||
levels:
|
||||
The predefined configurations perform the following Clang checks:
|
||||
|
||||
\list
|
||||
|
||||
\li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic option that
|
||||
requests all the warnings demanded by strict ISO C and ISO C++.
|
||||
\li \uicontrol {Clang-only pedantic checks} uses the \c -Wpendantic
|
||||
option that performs checks as required by strict ISO C and ISO C++.
|
||||
|
||||
\li \uicontrol {Warnings for Questionable Constructs} combines the
|
||||
\c -Wall and \c -Wextra options to request all warnings about easily
|
||||
avoidable questionable constructions and some additional warnings.
|
||||
\li \uicontrol {Clang-only checks for questionable constructs} combines
|
||||
the \c -Wall and \c -Wextra checks for easily avoidable questionable
|
||||
constructions and some additional issues.
|
||||
|
||||
\li \uicontrol {Warnings for Almost Everything} uses the \c -Weverything
|
||||
option with negative options to suppress some warnings.
|
||||
\li \uicontrol {Clang-only checks for almost everything} uses the
|
||||
\c -Weverything option with negative options to suppress some
|
||||
warnings.
|
||||
|
||||
\endlist
|
||||
|
||||
You can edit the predefined configurations to request specific warnings
|
||||
beginning with \c -W. Each of these warnings also has a negative version
|
||||
You can edit the predefined configurations to perform particular checks
|
||||
beginning with \c -W. Each of these checks also has a negative version
|
||||
that begins with \c -Wno.
|
||||
|
||||
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.
|
||||
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}.
|
||||
|
||||
\section1 Setting Up the Google C++ Testing Framework
|
||||
|
||||
@@ -645,13 +645,13 @@
|
||||
\li Look In
|
||||
\row
|
||||
\li \uicontrol Tools > \uicontrol Options
|
||||
\li \uicontrol {Qt Creator} > \uicontrol Preferences
|
||||
\li \uicontrol {\QC} > \uicontrol Preferences
|
||||
\row
|
||||
\li \uicontrol Help > \uicontrol {About Plugins}
|
||||
\li \uicontrol {Qt Creator} > \uicontrol {About Plugins}
|
||||
\li \uicontrol {\QC} > \uicontrol {About Plugins}
|
||||
\row
|
||||
\li Keyboard shortcuts
|
||||
\li \uicontrol {Qt Creator} > \uicontrol Preferences > \uicontrol Environment >
|
||||
\li \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Environment >
|
||||
\uicontrol Keyboard
|
||||
\endtable
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
\contentspage {Qt Creator Manual}
|
||||
\page creator-commercial-overview.html
|
||||
|
||||
\title Qt Creator Commercial Features
|
||||
\title Commercial Features
|
||||
|
||||
\commercial
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
\l{http://qt.io/licensing/}{Qt license}:
|
||||
|
||||
\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{http://doc.qt.io/QtForDeviceCreation/index.html}{Developing for
|
||||
embedded devices}
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
\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,
|
||||
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
|
||||
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
|
||||
\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
|
||||
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,
|
||||
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
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
This manual also describes features that are only available if you have the
|
||||
appropriate \l{http://qt.io/licensing/}{Qt license}. For more information,
|
||||
see \l{Qt Creator Commercial Features}.
|
||||
see \l{Commercial Features}.
|
||||
|
||||
\table
|
||||
\row
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
\note Kits are listed if they have been specified in \uicontrol
|
||||
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).
|
||||
|
||||
\li Select \uicontrol Next.
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
|
||||
\note Kits are listed if they have been specified in \uicontrol
|
||||
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).
|
||||
|
||||
\li Select \uicontrol Next.
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
\section1 Exporting from Adobe Photoshop to QML
|
||||
|
||||
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
|
||||
Photoshop. They enable you to export PSD files to QML format, so that each
|
||||
PSD file is converted into an .ui.qml file.
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
\note If only one kit is specified in \uicontrol Tools >
|
||||
\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.
|
||||
|
||||
The \uicontrol{Class Information} dialog opens.
|
||||
|
||||
8
docs.pri
@@ -5,6 +5,12 @@
|
||||
|
||||
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.value = $$QTCREATOR_DISPLAY_VERSION
|
||||
qtcvertag.name = QTC_VERSION_TAG
|
||||
@@ -17,7 +23,7 @@ qtcdocsdir.name = QTC_DOCS_DIR
|
||||
qtcdocsdir.value = $$IDE_SOURCE_TREE/doc
|
||||
qtccopyrightyear.name = 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_HTML_INSTALLDIR = $$INSTALL_DOC_PATH
|
||||
|
||||
@@ -26,11 +26,10 @@
|
||||
#include "qpacketprotocol.h"
|
||||
|
||||
#include <qelapsedtimer.h>
|
||||
#include <qendian.h>
|
||||
|
||||
namespace QmlDebug {
|
||||
|
||||
static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
|
||||
|
||||
/*!
|
||||
\class QPacketProtocol
|
||||
\internal
|
||||
@@ -98,15 +97,14 @@ class QPacketProtocolPrivate : public QObject
|
||||
|
||||
public:
|
||||
QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
|
||||
: QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
|
||||
waitingForPacket(false), dev(_dev)
|
||||
: QObject(parent), inProgressSize(-1), waitingForPacket(false), dev(_dev)
|
||||
{
|
||||
Q_ASSERT(4 == sizeof(qint32));
|
||||
|
||||
QObject::connect(this, &QPacketProtocolPrivate::readyRead,
|
||||
parent, &QPacketProtocol::readyRead);
|
||||
QObject::connect(this, &QPacketProtocolPrivate::invalidPacket,
|
||||
parent, &QPacketProtocol::invalidPacket);
|
||||
QObject::connect(this, &QPacketProtocolPrivate::protocolError,
|
||||
parent, &QPacketProtocol::protocolError);
|
||||
QObject::connect(dev, &QIODevice::readyRead,
|
||||
this, &QPacketProtocolPrivate::readyToRead);
|
||||
QObject::connect(dev, &QIODevice::aboutToClose,
|
||||
@@ -117,7 +115,7 @@ public:
|
||||
|
||||
signals:
|
||||
void readyRead();
|
||||
void invalidPacket();
|
||||
void protocolError();
|
||||
|
||||
public:
|
||||
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()
|
||||
{
|
||||
while (true) {
|
||||
@@ -152,19 +161,15 @@ public:
|
||||
return;
|
||||
|
||||
// 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_UNUSED(read);
|
||||
inProgressSize = qFromLittleEndian(inProgressSizeLE);
|
||||
|
||||
// Check sizing constraints
|
||||
if (inProgressSize > maxPacketSize) {
|
||||
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 invalidPacket();
|
||||
if (inProgressSize < qint32(sizeof(qint32))) {
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -187,11 +192,10 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
QList<qint64> sendingPackets;
|
||||
QList<qint32> sendingPackets;
|
||||
QList<QByteArray> packets;
|
||||
QByteArray inProgress;
|
||||
qint32 inProgressSize;
|
||||
qint32 maxPacketSize;
|
||||
bool waitingForPacket;
|
||||
QIODevice *dev;
|
||||
};
|
||||
@@ -211,18 +215,29 @@ QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
|
||||
*/
|
||||
void QPacketProtocol::send(const QByteArray &p)
|
||||
{
|
||||
static const qint32 maxSize = std::numeric_limits<qint32>::max() - sizeof(qint32);
|
||||
|
||||
if (p.isEmpty())
|
||||
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);
|
||||
qint32 sendSize32 = sendSize;
|
||||
qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
|
||||
Q_ASSERT(writeBytes == sizeof(qint32));
|
||||
writeBytes = d->dev->write(p);
|
||||
Q_ASSERT(writeBytes == p.size());
|
||||
Q_UNUSED(writeBytes); // For building in release mode.
|
||||
|
||||
const qint32 sendSizeLE = qToLittleEndian(sendSize);
|
||||
if (d->dev->write((char *)&sendSizeLE, sizeof(qint32)) != sizeof(qint32)) {
|
||||
d->fail();
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->dev->write(p) != p.size()) {
|
||||
d->fail();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
signals:
|
||||
void readyRead();
|
||||
void invalidPacket();
|
||||
void protocolError();
|
||||
|
||||
private:
|
||||
QPacketProtocolPrivate *d;
|
||||
|
||||
@@ -700,7 +700,8 @@ static std::string dumplocalHelper(ExtensionCommandContext &exc,PCSTR args, int
|
||||
return std::string();
|
||||
}
|
||||
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;
|
||||
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
|
||||
{
|
||||
const std::string &pointerToType = pointedToSymbolName(address, type);
|
||||
std::string tmp;
|
||||
if (SymbolGroupNode *ancestorNode =
|
||||
node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &std::string())) {
|
||||
node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &tmp)) {
|
||||
return SymbolGroupValue(ancestorNode, m_context);
|
||||
}
|
||||
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 *") << ")("
|
||||
<< std::showbase << std::hex << d.pointerValue() << ')';
|
||||
|
||||
std::string tmp;
|
||||
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)
|
||||
return false;
|
||||
|
||||
@@ -2128,14 +2130,15 @@ static inline bool dumpQHostAddress(const SymbolGroupValue &v, std::wostream &st
|
||||
std::ostringstream namestr;
|
||||
namestr << '(' << info.prependQtNetworkModule("QHostAddressPrivate *") << ")("
|
||||
<< std::showbase << std::hex << d.pointerValue() << ')';
|
||||
std::string tmp;
|
||||
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)
|
||||
return false;
|
||||
const SymbolGroupValue qHostAddressPrivateValue = SymbolGroupValue(qHostAddressPrivateNode, v.context());
|
||||
const bool parsed = readPODFromMemory<bool>(qHostAddressPrivateValue.context().dataspaces,
|
||||
qHostAddressPrivateValue["isParsed"].address(),
|
||||
sizeof(bool), false, &std::string());
|
||||
sizeof(bool), false, &tmp);
|
||||
if (parsed) {
|
||||
const int protocol = qHostAddressPrivateValue["protocol"].intValue(-1);
|
||||
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())) {
|
||||
SymbolGroupNode *mapNode = mv.node();
|
||||
std::wstring value;
|
||||
if (dumpSimpleType(mapNode, dataV.context(), &value, &std::string())
|
||||
std::string tmp;
|
||||
if (dumpSimpleType(mapNode, dataV.context(), &value, &tmp)
|
||||
== SymbolGroupNode::SimpleDumperOk) {
|
||||
str << value;
|
||||
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())) {
|
||||
SymbolGroupNode *vListNode = vl.node();
|
||||
std::wstring value;
|
||||
if (dumpSimpleType(vListNode, dataV.context(), &value, &std::string())
|
||||
std::string tmp;
|
||||
if (dumpSimpleType(vListNode, dataV.context(), &value, &tmp)
|
||||
== SymbolGroupNode::SimpleDumperOk) {
|
||||
str << value;
|
||||
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())) {
|
||||
SymbolGroupNode *listNode = sl.node();
|
||||
std::wstring value;
|
||||
if (dumpSimpleType(listNode, dataV.context(), &value, &std::string())
|
||||
std::string tmp;
|
||||
if (dumpSimpleType(listNode, dataV.context(), &value, &tmp)
|
||||
== SymbolGroupNode::SimpleDumperOk) {
|
||||
str << value;
|
||||
if (specialInfoIn)
|
||||
|
||||
@@ -58,6 +58,13 @@ Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos
|
||||
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)
|
||||
{
|
||||
if (pos < 0)
|
||||
|
||||
@@ -43,6 +43,9 @@ QTCREATOR_UTILS_EXPORT bool convertPosition(const QTextDocument *document,
|
||||
QTCREATOR_UTILS_EXPORT
|
||||
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 QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);
|
||||
|
||||
@@ -69,6 +69,8 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
|
||||
return false;
|
||||
|
||||
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)
|
||||
return false;
|
||||
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)
|
||||
{
|
||||
const QStringRef name = ast->qualifiedTypeNameId->name;
|
||||
m_objectStack.push(name.toString());
|
||||
if (name != "TestCase") {
|
||||
m_insideTestCase = false;
|
||||
if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot))
|
||||
return true;
|
||||
} else if (!documentImportsQtTest(m_currentDoc.data())) {
|
||||
@@ -92,6 +94,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
|
||||
}
|
||||
|
||||
m_typeIsTestCase = true;
|
||||
m_insideTestCase = true;
|
||||
m_currentTestCaseName.clear();
|
||||
const auto sourceLocation = ast->firstSourceLocation();
|
||||
m_testCaseLocation.m_name = m_currentDoc->fileName();
|
||||
@@ -101,6 +104,11 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TestQmlVisitor::endVisit(QmlJS::AST::UiObjectDefinition *)
|
||||
{
|
||||
m_insideTestCase = m_objectStack.pop() == "TestCase";
|
||||
}
|
||||
|
||||
bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
|
||||
{
|
||||
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)
|
||||
{
|
||||
const QStringRef name = ast->qualifiedId->name;
|
||||
return name == "name";
|
||||
if (m_insideTestCase)
|
||||
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)
|
||||
@@ -139,8 +154,10 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
|
||||
|
||||
bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast)
|
||||
{
|
||||
if (m_typeIsTestCase)
|
||||
if (m_expectTestCaseName && m_currentTestCaseName.isEmpty()) {
|
||||
m_currentTestCaseName = ast->value.toString();
|
||||
m_expectTestCaseName = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <qmljs/parser/qmljsastvisitor_p.h>
|
||||
#include <qmljs/qmljsdocument.h>
|
||||
|
||||
#include <QStack>
|
||||
|
||||
namespace Autotest {
|
||||
namespace Internal {
|
||||
|
||||
@@ -38,11 +40,13 @@ class TestQmlVisitor : public QmlJS::AST::Visitor
|
||||
public:
|
||||
explicit TestQmlVisitor(QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot);
|
||||
|
||||
bool visit(QmlJS::AST::UiObjectDefinition *ast);
|
||||
bool visit(QmlJS::AST::ExpressionStatement *ast);
|
||||
bool visit(QmlJS::AST::UiScriptBinding *ast);
|
||||
bool visit(QmlJS::AST::FunctionDeclaration *ast);
|
||||
bool visit(QmlJS::AST::StringLiteral *ast);
|
||||
bool visit(QmlJS::AST::UiObjectDefinition *ast) override;
|
||||
void endVisit(QmlJS::AST::UiObjectDefinition *ast) override;
|
||||
bool visit(QmlJS::AST::ExpressionStatement *ast) override;
|
||||
bool visit(QmlJS::AST::UiScriptBinding *ast) override;
|
||||
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; }
|
||||
TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; }
|
||||
@@ -55,7 +59,10 @@ private:
|
||||
QString m_currentTestCaseName;
|
||||
TestCodeLocationAndType m_testCaseLocation;
|
||||
QMap<QString, TestCodeLocationAndType> m_testFunctions;
|
||||
QStack<QString> m_objectStack;
|
||||
bool m_typeIsTestCase = false;
|
||||
bool m_insideTestCase = false;
|
||||
bool m_expectTestCaseName = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -75,12 +75,14 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
|
||||
TestRunMode runMode)
|
||||
{
|
||||
QTC_ASSERT(rc, return);
|
||||
QTC_ASSERT(m_project, return);
|
||||
|
||||
if (hasExecutable()) {
|
||||
qCDebug(LOG) << "Executable has been set already - not completing configuration again.";
|
||||
return;
|
||||
}
|
||||
Project *project = SessionManager::startupProject();
|
||||
if (!project)
|
||||
if (!project || project != m_project)
|
||||
return;
|
||||
|
||||
Target *target = project->activeTarget();
|
||||
@@ -94,7 +96,6 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
|
||||
|
||||
m_runnable = rc->runnable();
|
||||
m_displayName = rc->displayName();
|
||||
m_project = rc->project();
|
||||
|
||||
const QString buildKey = rc->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_buildTargets.isEmpty(), return);
|
||||
QTC_ASSERT(m_project, return);
|
||||
|
||||
if (m_origRunConfig) {
|
||||
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.";
|
||||
}
|
||||
Project *project = SessionManager::startupProject();
|
||||
if (!project)
|
||||
if (!project || project != m_project) {
|
||||
m_project = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
Target *target = project->activeTarget();
|
||||
if (!target)
|
||||
@@ -204,7 +208,6 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
|
||||
m_runnable = runnable;
|
||||
m_runnable.executable = currentExecutable;
|
||||
m_displayName = runConfig->displayName();
|
||||
m_project = project;
|
||||
if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
|
||||
m_runConfig = new TestRunConfiguration(runConfig->target(), this);
|
||||
break;
|
||||
@@ -224,7 +227,6 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
|
||||
if (isLocal(rc)) { // FIXME for now only Desktop support
|
||||
const Runnable runnable = rc->runnable();
|
||||
m_runnable.environment = runnable.environment;
|
||||
m_project = project;
|
||||
m_guessedConfiguration = true;
|
||||
m_guessedFrom = rc->displayName();
|
||||
if (runMode == TestRunMode::Debug)
|
||||
|
||||
@@ -154,6 +154,7 @@ void TestRunner::scheduleNext()
|
||||
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
|
||||
QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers());
|
||||
QTC_ASSERT(m_fakeFutureInterface, onFinished(); return);
|
||||
QTC_ASSERT(!m_canceled, onFinished(); return);
|
||||
|
||||
m_currentConfig = m_selectedTests.dequeue();
|
||||
|
||||
@@ -215,9 +216,16 @@ void TestRunner::scheduleNext()
|
||||
|
||||
void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
|
||||
{
|
||||
m_canceled = true;
|
||||
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();
|
||||
} 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) {
|
||||
m_currentProcess->kill();
|
||||
@@ -231,6 +239,7 @@ void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
|
||||
|
||||
void TestRunner::onProcessFinished()
|
||||
{
|
||||
if (m_currentConfig) {
|
||||
m_fakeFutureInterface->setProgressValue(m_fakeFutureInterface->progressValue()
|
||||
+ m_currentConfig->testCaseCount());
|
||||
if (!m_fakeFutureInterface->isCanceled()) {
|
||||
@@ -246,7 +255,7 @@ void TestRunner::onProcessFinished()
|
||||
+ rcInfo(m_currentConfig))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
resetInternalPointers();
|
||||
|
||||
if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled())
|
||||
@@ -277,6 +286,7 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
|
||||
}
|
||||
|
||||
m_executingTests = true;
|
||||
m_canceled = false;
|
||||
emit testRunStarted();
|
||||
|
||||
// clear old log and output pane
|
||||
@@ -299,6 +309,9 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
|
||||
return;
|
||||
}
|
||||
|
||||
m_targetConnect = connect(project, &ProjectExplorer::Project::activeTargetChanged,
|
||||
[this]() { cancelCurrent(KitChanged); });
|
||||
|
||||
if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy
|
||||
|| mode == TestRunMode::RunWithoutDeploy) {
|
||||
runOrDebugTests();
|
||||
@@ -384,9 +397,13 @@ int TestRunner::precheckTestConfigurations()
|
||||
void TestRunner::runTests()
|
||||
{
|
||||
QList<TestConfiguration *> toBeRemoved;
|
||||
bool projectChanged = false;
|
||||
for (TestConfiguration *config : m_selectedTests) {
|
||||
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)))
|
||||
config->setOriginalRunConfiguration(rc);
|
||||
else
|
||||
@@ -398,8 +415,10 @@ void TestRunner::runTests()
|
||||
qDeleteAll(toBeRemoved);
|
||||
toBeRemoved.clear();
|
||||
if (m_selectedTests.isEmpty()) {
|
||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
||||
tr("No test cases left for execution. Canceling test run."))));
|
||||
QString mssg = projectChanged ? tr("Startup project has changed. Canceling test run.")
|
||||
: tr("No test cases left for execution. Canceling test run.");
|
||||
|
||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, mssg)));
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
@@ -452,6 +471,12 @@ void TestRunner::debugTests()
|
||||
|
||||
TestConfiguration *config = m_selectedTests.first();
|
||||
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 (auto *rc = getRunConfiguration(firstTestCaseTarget(config)))
|
||||
config->completeTestInformation(rc, TestRunMode::Debug);
|
||||
@@ -571,7 +596,10 @@ void TestRunner::buildFinished(bool success)
|
||||
this, &TestRunner::buildFinished);
|
||||
|
||||
if (success) {
|
||||
if (!m_canceled)
|
||||
runOrDebugTests();
|
||||
else if (m_executingTests)
|
||||
onFinished();
|
||||
} else {
|
||||
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||
tr("Build failed. Canceling test run."))));
|
||||
@@ -585,6 +613,7 @@ void TestRunner::onFinished()
|
||||
qDeleteAll(m_selectedTests);
|
||||
m_selectedTests.clear();
|
||||
|
||||
disconnect(m_targetConnect);
|
||||
m_fakeFutureInterface = nullptr;
|
||||
m_executingTests = false;
|
||||
emit testRunFinished();
|
||||
|
||||
@@ -54,7 +54,7 @@ class AUTOTESTSHARED_EXPORT TestRunner : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum CancelReason { UserCanceled, Timeout };
|
||||
enum CancelReason { UserCanceled, Timeout, KitChanged };
|
||||
|
||||
static TestRunner* instance();
|
||||
~TestRunner();
|
||||
@@ -91,6 +91,7 @@ private:
|
||||
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
|
||||
QQueue<TestConfiguration *> m_selectedTests;
|
||||
bool m_executingTests = false;
|
||||
bool m_canceled = false;
|
||||
TestConfiguration *m_currentConfig = nullptr;
|
||||
QProcess *m_currentProcess = nullptr;
|
||||
TestOutputReader *m_currentOutputReader = nullptr;
|
||||
@@ -98,6 +99,8 @@ private:
|
||||
|
||||
// temporarily used if building before running is necessary
|
||||
QMetaObject::Connection m_buildConnect;
|
||||
// temporarily used for handling of switching the current target
|
||||
QMetaObject::Connection m_targetConnect;
|
||||
};
|
||||
|
||||
class RunConfigurationSelectionDialog : public QDialog
|
||||
|
||||
@@ -1673,7 +1673,11 @@ void BinEditorWidget::setNewWindowRequestAllowed(bool c)
|
||||
void BinEditorWidget::updateContents()
|
||||
{
|
||||
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
|
||||
|
||||
@@ -63,18 +63,6 @@ QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainforma
|
||||
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,
|
||||
QTextDocument *textDocument,
|
||||
const QTextCharFormat &contextFormat,
|
||||
@@ -82,8 +70,13 @@ void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
||||
{
|
||||
for (auto &&range : diagnostic.ranges) {
|
||||
QTextCursor cursor(textDocument);
|
||||
cursor.setPosition(positionInText(textDocument, range.start));
|
||||
cursor.setPosition(positionInText(textDocument, range.end), QTextCursor::KeepAnchor);
|
||||
cursor.setPosition(::Utils::Text::positionInText(textDocument,
|
||||
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);
|
||||
|
||||
@@ -127,11 +120,15 @@ QTextCursor createSelectionCursor(QTextDocument *textDocument,
|
||||
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
|
||||
{
|
||||
QTextCursor cursor(textDocument);
|
||||
cursor.setPosition(positionInText(textDocument, sourceLocationContainer));
|
||||
cursor.setPosition(::Utils::Text::positionInText(textDocument,
|
||||
sourceLocationContainer.line,
|
||||
sourceLocationContainer.column));
|
||||
selectToLocationEnd(cursor);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -205,20 +205,16 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(
|
||||
}
|
||||
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
|
||||
toTextEditorBlock(QTextDocument *textDocument,
|
||||
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
|
||||
{
|
||||
return TextEditor::BlockRange(positionInText(textDocument, sourceRangeContainer.start),
|
||||
positionInText(textDocument, sourceRangeContainer.end));
|
||||
return TextEditor::BlockRange(::Utils::Text::positionInText(textDocument,
|
||||
sourceRangeContainer.start.line,
|
||||
sourceRangeContainer.start.column),
|
||||
::Utils::Text::positionInText(textDocument,
|
||||
sourceRangeContainer.end.line,
|
||||
sourceRangeContainer.end.column));
|
||||
}
|
||||
|
||||
QList<TextEditor::BlockRange>
|
||||
|
||||
@@ -251,7 +251,10 @@ ClangTidyClazyTool::ClangTidyClazyTool()
|
||||
m_applyFixitsButton->setEnabled(false);
|
||||
connect(m_diagnosticModel,
|
||||
&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]() {
|
||||
QVector<DiagnosticItem *> diagnosticItems;
|
||||
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)
|
||||
{
|
||||
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
|
||||
? FixitStatus::Scheduled
|
||||
: FixitStatus::NotScheduled;
|
||||
|
||||
@@ -35,12 +35,60 @@
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QPainter>
|
||||
|
||||
using namespace Debugger;
|
||||
|
||||
namespace ClangTools {
|
||||
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)
|
||||
: 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)
|
||||
{
|
||||
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()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangTools
|
||||
|
||||
#include "clangtoolsdiagnosticview.moc"
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
FixItColumn = LocationColumn + 1,
|
||||
};
|
||||
|
||||
void setSelectedFixItsCount(int fixItsCount);
|
||||
|
||||
private:
|
||||
void suppressCurrentDiagnostic();
|
||||
|
||||
@@ -49,6 +51,7 @@ private:
|
||||
void setModel(QAbstractItemModel *model) override;
|
||||
|
||||
QAction *m_suppressAction;
|
||||
bool m_ignoreSetSelectedFixItsCount = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -118,8 +118,11 @@ void ClangToolsSettings::readSettings()
|
||||
|
||||
m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
|
||||
|
||||
m_savedDiagnosticConfigId = m_diagnosticConfigId
|
||||
= Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
|
||||
m_diagnosticConfigId = Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
|
||||
if (!m_diagnosticConfigId.isValid())
|
||||
m_diagnosticConfigId = "Builtin.TidyAndClazy";
|
||||
|
||||
m_savedDiagnosticConfigId = m_diagnosticConfigId;
|
||||
|
||||
updateSavedBuildBeforeAnalysiIfRequired();
|
||||
|
||||
|
||||
@@ -113,6 +113,13 @@
|
||||
\" </magic>\",
|
||||
\" </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>\"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -37,8 +37,9 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode
|
||||
{
|
||||
ClangDiagnosticConfig config;
|
||||
config.setId("Builtin.Questionable");
|
||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||
"Warnings for questionable constructs"));
|
||||
config.setDisplayName(QCoreApplication::translate(
|
||||
"ClangDiagnosticConfigsModel",
|
||||
"Clang-only checks for questionable constructs"));
|
||||
config.setIsReadOnly(true);
|
||||
config.setClangOptions(QStringList{
|
||||
QStringLiteral("-Wall"),
|
||||
@@ -53,19 +54,33 @@ static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model)
|
||||
ClangDiagnosticConfig config;
|
||||
config.setId("Builtin.Pedantic");
|
||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||
"Pedantic Warnings"));
|
||||
"Clang-only pedantic checks"));
|
||||
config.setIsReadOnly(true);
|
||||
config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")});
|
||||
|
||||
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)
|
||||
{
|
||||
ClangDiagnosticConfig config;
|
||||
config.setId(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS);
|
||||
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
|
||||
"Warnings for almost everything"));
|
||||
config.setDisplayName(QCoreApplication::translate(
|
||||
"ClangDiagnosticConfigsModel",
|
||||
"Clang-only checks for almost everything"));
|
||||
config.setIsReadOnly(true);
|
||||
config.setClangOptions(QStringList{
|
||||
QStringLiteral("-Weverything"),
|
||||
@@ -86,11 +101,75 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
|
||||
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)
|
||||
{
|
||||
addConfigForPedanticWarnings(model);
|
||||
addConfigForQuestionableConstructs(model);
|
||||
addConfigForAlmostEveryWarning(model);
|
||||
addConfigForTidy(model);
|
||||
addConfigForClangAnalyze(model);
|
||||
addConfigForClazy(model);
|
||||
addConfigForTidyAndClazy(model);
|
||||
}
|
||||
|
||||
ClangDiagnosticConfigsModel::ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs)
|
||||
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
const QModelIndex index = indexForCheck(check);
|
||||
if (!index.isValid())
|
||||
continue;
|
||||
auto node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
|
||||
auto *node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
|
||||
node->checked = state;
|
||||
propagateUp(index);
|
||||
propagateDown(index);
|
||||
@@ -161,6 +161,18 @@ public:
|
||||
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:
|
||||
|
||||
// TODO: Remove/replace this method after base class refactoring is done.
|
||||
@@ -220,6 +232,8 @@ private:
|
||||
for (const ProjectExplorer::Tree *t : root->childDirectories)
|
||||
collectChecks(t, checks);
|
||||
}
|
||||
|
||||
bool m_enabled = true;
|
||||
};
|
||||
|
||||
ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(const Core::Id &configToSelect,
|
||||
@@ -489,7 +503,11 @@ void ClangDiagnosticConfigsWidget::syncClangTidyWidgets(const ClangDiagnosticCon
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -650,12 +668,17 @@ void ClangDiagnosticConfigsWidget::setupTabs()
|
||||
m_tidyChecks->checksPrefixesTree->header()->setStretchLastSection(false);
|
||||
m_tidyChecks->checksPrefixesTree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this]() {
|
||||
const bool readOnly = selectedConfig().isReadOnly();
|
||||
|
||||
QDialog dialog;
|
||||
dialog.setWindowTitle(tr("Checks"));
|
||||
dialog.setLayout(new QVBoxLayout);
|
||||
auto *textEdit = new QTextEdit(&dialog);
|
||||
textEdit->setReadOnly(readOnly);
|
||||
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);
|
||||
QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||
QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||
|
||||
@@ -487,10 +487,6 @@ QString CompilerOptionsBuilder::includeOption() 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
|
||||
// __has_include(STR) and __has_include_next(STR)
|
||||
if (macro.key.startsWith("__has_include"))
|
||||
|
||||
@@ -193,7 +193,7 @@ bool isDebuggerWinException(unsigned long code)
|
||||
return code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
|
||||
}
|
||||
|
||||
bool isFatalWinException(long code)
|
||||
bool isFatalWinException(unsigned long code)
|
||||
{
|
||||
switch (code) {
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
@@ -217,7 +217,7 @@ bool winResumeThread(unsigned long, QString *) { return false; }
|
||||
bool isWinProcessBeingDebugged(unsigned long) { return false; }
|
||||
void formatWindowsException(unsigned long , quint64, unsigned long,
|
||||
quint64, quint64, QTextStream &) { }
|
||||
bool isFatalWinException(long) { return false; }
|
||||
bool isFatalWinException(unsigned long) { return false; }
|
||||
bool isDebuggerWinException(unsigned long) { return false; }
|
||||
|
||||
#endif // !Q_OS_WIN
|
||||
|
||||
@@ -40,7 +40,7 @@ bool winResumeThread(unsigned long dwThreadId, QString *errorMessage);
|
||||
bool isWinProcessBeingDebugged(unsigned long pid);
|
||||
|
||||
// Special exception codes.
|
||||
enum
|
||||
enum : unsigned long
|
||||
{
|
||||
winExceptionCppException = 0xe06d7363,
|
||||
winExceptionSetThreadName = 0x406d1388,
|
||||
@@ -60,7 +60,7 @@ void formatWindowsException(unsigned long code, quint64 address,
|
||||
unsigned long flags, quint64 info1, quint64 info2,
|
||||
QTextStream &str);
|
||||
// Check for access violation, etc.
|
||||
bool isFatalWinException(long code);
|
||||
bool isFatalWinException(unsigned long code);
|
||||
|
||||
// Check for EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP
|
||||
bool isDebuggerWinException(unsigned long code);
|
||||
|
||||
@@ -216,6 +216,23 @@ void GerritDialog::refresh()
|
||||
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()
|
||||
{
|
||||
const GerritServer server = m_ui->remoteComboBox->currentServer();
|
||||
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
void fetchStarted(const QSharedPointer<Gerrit::Internal::GerritChange> &change);
|
||||
void fetchFinished();
|
||||
void refresh();
|
||||
void scheduleUpdateRemotes();
|
||||
|
||||
signals:
|
||||
void fetchDisplay(const QSharedPointer<Gerrit::Internal::GerritChange> &);
|
||||
@@ -77,6 +78,7 @@ private:
|
||||
void slotFetchCheckout();
|
||||
void remoteChanged();
|
||||
void updateRemotes(bool forceReload = false);
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
void manageProgressIndicator();
|
||||
|
||||
@@ -101,6 +103,7 @@ private:
|
||||
QString m_repository;
|
||||
bool m_fetchRunning = false;
|
||||
bool m_updatingRemotes = false;
|
||||
bool m_shouldUpdateRemotes = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -72,6 +72,7 @@ void GerritOptionsPage::apply()
|
||||
newParameters.setPortFlagBySshType();
|
||||
*m_parameters = newParameters;
|
||||
m_parameters->toSettings(Core::ICore::settings());
|
||||
emit settingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,9 @@ public:
|
||||
void apply() override;
|
||||
void finish() override;
|
||||
|
||||
signals:
|
||||
void settingsChanged();
|
||||
|
||||
private:
|
||||
const QSharedPointer<GerritParameters> &m_parameters;
|
||||
QPointer<GerritOptionsWidget> m_widget;
|
||||
|
||||
@@ -292,7 +292,12 @@ bool GerritPlugin::initialize(ActionContainer *ac)
|
||||
connect(pushAction, &QAction::triggered, this, [this]() { push(); });
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -340,7 +345,7 @@ void GerritPlugin::openView()
|
||||
{
|
||||
if (m_dialog.isNull()) {
|
||||
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."));
|
||||
if (!ICore::showOptionsDialog("Gerrit"))
|
||||
return;
|
||||
|
||||
@@ -323,6 +323,7 @@ bool GerritServer::resolveRoot()
|
||||
}
|
||||
break;
|
||||
default: // unknown error - fail
|
||||
authenticated = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1069,7 +1069,6 @@ bool GitPlugin::submitEditorAboutToClose()
|
||||
|
||||
// Go ahead!
|
||||
SubmitFileModel *model = qobject_cast<SubmitFileModel *>(editor->fileModel());
|
||||
bool closeEditor = true;
|
||||
CommitType commitType = editor->commitType();
|
||||
QString amendSHA1 = editor->amendSHA1();
|
||||
if (model->hasCheckedFiles() || !amendSHA1.isEmpty()) {
|
||||
@@ -1077,12 +1076,12 @@ bool GitPlugin::submitEditorAboutToClose()
|
||||
if (!DocumentManager::saveDocument(editorDocument))
|
||||
return false;
|
||||
|
||||
closeEditor = m_gitClient->addAndCommit(m_submitRepository, editor->panelData(),
|
||||
commitType, amendSHA1,
|
||||
m_commitMessageFileName, model);
|
||||
}
|
||||
if (!closeEditor)
|
||||
if (!m_gitClient->addAndCommit(m_submitRepository, editor->panelData(), commitType,
|
||||
amendSHA1, m_commitMessageFileName, model)) {
|
||||
editor->updateFileModel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cleanCommitMessageFile();
|
||||
if (commitType == FixupCommit) {
|
||||
if (!m_gitClient->beginStashScope(m_submitRepository, "Rebase-fixup",
|
||||
|
||||
@@ -62,10 +62,10 @@ public:
|
||||
GitSubmitEditorPanelData panelData() const;
|
||||
CommitType commitType() const { return m_commitType; }
|
||||
QString amendSHA1() const;
|
||||
void updateFileModel() override;
|
||||
|
||||
protected:
|
||||
QByteArray fileContents() const override;
|
||||
void updateFileModel() override;
|
||||
void forceUpdateFileModel();
|
||||
|
||||
private:
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "buildconfiguration.h"
|
||||
#include "buildstep.h"
|
||||
#include "project.h"
|
||||
#include "target.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <coreplugin/reaper.h>
|
||||
@@ -306,7 +307,10 @@ void AbstractProcessStep::processReadyReadStdOutput()
|
||||
if (!m_process)
|
||||
return;
|
||||
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()) {
|
||||
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();
|
||||
d->m_data.clear(); // remove default values
|
||||
const QVariantMap::ConstIterator cend = extra.constEnd();
|
||||
for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it) {
|
||||
const QString key = it.key();
|
||||
if (!key.isEmpty())
|
||||
d->m_data.insert(Id::fromString(key), it.value());
|
||||
}
|
||||
for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it)
|
||||
d->m_data.insert(Id::fromString(it.key()), it.value());
|
||||
|
||||
QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList();
|
||||
foreach (const QString &mutableInfo, mutableInfoList)
|
||||
if (!mutableInfo.isEmpty())
|
||||
d->m_mutable.insert(Id::fromString(mutableInfo));
|
||||
|
||||
QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList();
|
||||
foreach (const QString &stickyInfo, stickyInfoList)
|
||||
if (!stickyInfo.isEmpty())
|
||||
d->m_sticky.insert(Id::fromString(stickyInfo));
|
||||
}
|
||||
|
||||
|
||||
@@ -368,18 +368,21 @@ public:
|
||||
const QStyleOptionViewItem &option, const QModelIndex &idx) final
|
||||
{
|
||||
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 QRect rc(option.rect.right() - 24, option.rect.top(), 24, SESSION_LINE_HEIGHT);
|
||||
const QString sessionName = idx.data(Qt::DisplayRole).toString();
|
||||
if (rc.contains(pos)) {
|
||||
if (rc.contains(pos) || button == Qt::RightButton) {
|
||||
// The expand/collapse "button".
|
||||
if (m_expandedSessions.contains(sessionName))
|
||||
m_expandedSessions.removeOne(sessionName);
|
||||
else
|
||||
m_expandedSessions.append(sessionName);
|
||||
model->layoutChanged({QPersistentModelIndex(idx)});
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (button == Qt::LeftButton) {
|
||||
// One of the action links?
|
||||
const auto sessionModel = qobject_cast<SessionModel *>(model);
|
||||
QTC_ASSERT(sessionModel, return false);
|
||||
@@ -393,6 +396,7 @@ public:
|
||||
sessionModel->deleteSession(sessionName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ev->type() == QEvent::MouseMove) {
|
||||
model->layoutChanged({QPersistentModelIndex(idx)}); // Somewhat brutish.
|
||||
//update(option.rect);
|
||||
@@ -473,10 +477,14 @@ public:
|
||||
const QStyleOptionViewItem &, const QModelIndex &idx) final
|
||||
{
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,6 +72,13 @@ private:
|
||||
QPushButton * const m_changeButton;
|
||||
};
|
||||
|
||||
QbsKitInformation::QbsKitInformation()
|
||||
{
|
||||
setObjectName(QLatin1String("QbsKitInformation"));
|
||||
setId(QbsKitInformation::id());
|
||||
setPriority(22000);
|
||||
}
|
||||
|
||||
QString QbsKitInformation::displayName()
|
||||
{
|
||||
return tr("Additional Qbs Profile Settings");
|
||||
|
||||
@@ -35,6 +35,8 @@ class QbsKitInformation final : public ProjectExplorer::KitInformation
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QbsKitInformation();
|
||||
|
||||
static QString displayName();
|
||||
static QString representation(const ProjectExplorer::Kit *kit);
|
||||
static QVariantMap properties(const ProjectExplorer::Kit *kit);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
@@ -55,6 +56,9 @@ QbsProjectParser::QbsProjectParser(QbsProject *project, QFutureInterface<bool> *
|
||||
{
|
||||
m_project = project->qbsProject();
|
||||
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()
|
||||
|
||||
@@ -78,7 +78,8 @@ GuiAppWizard::GuiAppWizard()
|
||||
"Includes a Qt Designer-based main window.\n\n"
|
||||
"Preselects a desktop Qt for building the application if available."));
|
||||
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
|
||||
@@ -187,6 +188,7 @@ Core::GeneratedFiles GuiAppWizard::generateFiles(const QWizard *w,
|
||||
QTextStream proStr(&contents);
|
||||
QtProjectParameters::writeProFileHeader(proStr);
|
||||
projectParams.writeProFile(proStr);
|
||||
proStr << "\nCONFIG += c++11"; // ensure all Qt5 versions can handle the source
|
||||
proStr << "\n\nSOURCES +="
|
||||
<< " \\\n " << Utils::FileName::fromString(mainSourceFileName).fileName()
|
||||
<< " \\\n " << Utils::FileName::fromString(formSource.path()).fileName()
|
||||
|
||||
@@ -84,6 +84,7 @@ QtProjectParameters GuiAppWizardDialog::projectParameters() const
|
||||
rc.path = path();
|
||||
rc.selectedModules = selectedModulesList();
|
||||
rc.deselectedModules = deselectedModulesList();
|
||||
rc.qtVersionSupport = QtProjectParameters::SupportQt5Only;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,8 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
|
||||
RangeType rangeType = MaximumRangeType;
|
||||
if (!stream.atEnd()) {
|
||||
stream >> subtype;
|
||||
if (subtype >= 0 && subtype < MaximumRangeType)
|
||||
rangeType = static_cast<RangeType>(subtype);
|
||||
if (rangeType < 0 || rangeType > MaximumRangeType)
|
||||
rangeType = MaximumRangeType;
|
||||
} else {
|
||||
subtype = -1;
|
||||
}
|
||||
|
||||
@@ -687,7 +687,7 @@ public:
|
||||
|
||||
QRegExp m_searchExpr;
|
||||
FindFlags m_findFlags;
|
||||
void highlightSearchResults(const QTextBlock &block, TextEditorOverlay *overlay) const;
|
||||
void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const;
|
||||
QTimer m_delayedUpdateTimer;
|
||||
|
||||
void setExtraSelections(Core::Id kind, const QList<QTextEdit::ExtraSelection> &selections);
|
||||
@@ -3657,8 +3657,7 @@ QTextBlock TextEditorWidgetPrivate::foldedBlockAt(const QPoint &pos, QRect *box)
|
||||
return QTextBlock();
|
||||
}
|
||||
|
||||
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|
||||
TextEditorOverlay *overlay) const
|
||||
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const
|
||||
{
|
||||
if (m_searchExpr.isEmpty())
|
||||
return;
|
||||
@@ -3671,6 +3670,13 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|
||||
int idx = -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()) {
|
||||
idx = m_searchExpr.indexIn(text, idx + l);
|
||||
if (idx < 0)
|
||||
@@ -3683,19 +3689,44 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|
||||
|| (idx + l < text.length() && text.at(idx + l).isLetterOrNumber())))
|
||||
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;
|
||||
|
||||
const QTextCharFormat &searchResultFormat
|
||||
= m_document->fontSettings().toTextCharFormat(C_SEARCH_RESULT);
|
||||
overlay->addOverlaySelection(blockPosition + idx,
|
||||
blockPosition + idx + l,
|
||||
searchResultFormat.background().color().darker(120),
|
||||
QColor(),
|
||||
(idx == cursor.selectionStart() - blockPosition
|
||||
&& idx + l == cursor.selectionEnd() - blockPosition)?
|
||||
TextEditorOverlay::DropShadow : 0);
|
||||
// check if the result is inside the visibale area for long blocks
|
||||
const QTextLine &startLine = block.layout()->lineForTextPosition(idx);
|
||||
const QTextLine &endLine = block.layout()->lineForTextPosition(idx + l);
|
||||
|
||||
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
|
||||
&& blockBoundingRect.top() <= data.eventRect.bottom() + margin) {
|
||||
highlightSearchResults(block, m_searchResultOverlay);
|
||||
highlightSearchResults(block, data);
|
||||
}
|
||||
offset.ry() += blockBoundingRect.height();
|
||||
|
||||
|
||||
@@ -142,7 +142,12 @@ FollowSymbolResult FollowSymbol::followSymbol(CXTranslationUnit tu,
|
||||
CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
|
||||
const ClangString filename(clang_getFileName(file));
|
||||
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
|
||||
|
||||
@@ -85,7 +85,7 @@ def prepareBuildSettings(targetCount, currentTarget, setReleaseBuild=True, disab
|
||||
def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings):
|
||||
def kitIsActivated(kit):
|
||||
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:
|
||||
treeView = waitForObject(":Projects.ProjectNavigationTreeView")
|
||||
|
||||
@@ -104,7 +104,6 @@ def renameFile(projectDir, proFile, branch, oldname, newname):
|
||||
menu = ":Qt Creator.Project.Menu.File_QMenu"
|
||||
activateItem(waitForObjectItem(menu, "Rename..."))
|
||||
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],
|
||||
"Only the filename without the extension is selected?")
|
||||
replaceEditorContent(replaceEdit, newname)
|
||||
|
||||