Merge remote-tracking branch 'origin/4.7'

Change-Id: Ifec1f8dc20a18f432ec6ccf68153f31fff3f8b29
This commit is contained in:
Eike Ziller
2018-06-25 11:07:03 +02:00
78 changed files with 754 additions and 290 deletions

13
dist/changes-4.7.0.md vendored
View File

@@ -31,6 +31,7 @@ Editing
behavior (QTCREATORBUG-9859, QTCREATORBUG-20061) behavior (QTCREATORBUG-9859, QTCREATORBUG-20061)
* Fixed that extra editor windows were not restored when opening session * Fixed that extra editor windows were not restored when opening session
(QTCREATORBUG-13840) (QTCREATORBUG-13840)
* Fixed that editor could stay busy repainting annotations (QTCREATORBUG-20422)
* FakeVim * FakeVim
* Added `:<range>sor[t][!]` * Added `:<range>sor[t][!]`
@@ -55,6 +56,7 @@ QMake Projects
* Added support for `-isystem` in `QMAKE_CXXFLAGS` * Added support for `-isystem` in `QMAKE_CXXFLAGS`
* Added deployment rules for devices to widget and console application wizards * Added deployment rules for devices to widget and console application wizards
(QTCREATORBUG-20358) (QTCREATORBUG-20358)
* Fixed that arguments for QMake step did not expand variables
C++ Support C++ Support
@@ -95,6 +97,11 @@ Python Support
* Added stack traces in application output to Issues pane (category `Python`) * Added stack traces in application output to Issues pane (category `Python`)
Debugging
* QML
* Added support for nested properties (QTBUG-68474)
Clang Static Analyzer Clang Static Analyzer
* Renamed plugin to `ClangTools` * Renamed plugin to `ClangTools`
@@ -141,9 +148,11 @@ Android
* Improved behavior when emulator cannot be started (QTCREATORBUG-20160) * Improved behavior when emulator cannot be started (QTCREATORBUG-20160)
Credits for these changes go to: Credits for these changes go to:
Aaron Barany
Aleix Pol Aleix Pol
Alessandro Portale Alessandro Portale
Alexander Drozdov Alexander Drozdov
Alexandru Croitor
Andre Hartmann Andre Hartmann
André Pönitz André Pönitz
Antonio Di Monaco Antonio Di Monaco
@@ -155,13 +164,16 @@ Claus Steuer
Colin Duquesnoy Colin Duquesnoy
David Schulz David Schulz
Eike Ziller Eike Ziller
Filipe Azevedo
Friedemann Kleint Friedemann Kleint
Hugo Holgersson Hugo Holgersson
Ivan Donchevskii Ivan Donchevskii
Jaroslaw Kobus Jaroslaw Kobus
Jay Gupta Jay Gupta
José Tomás Tocino
Jörg Bornemann Jörg Bornemann
Kari Oikarinen Kari Oikarinen
Kimmo Linnavuo
Leena Miettinen Leena Miettinen
Marco Benelli Marco Benelli
Marco Bubke Marco Bubke
@@ -169,6 +181,7 @@ Mitch Curtis
Nikita Baryshnikov Nikita Baryshnikov
Nikolai Kosjar Nikolai Kosjar
Orgad Shaneh Orgad Shaneh
Oswald Buddenhagen
Pawel Rutka Pawel Rutka
Przemyslaw Gorszkowski Przemyslaw Gorszkowski
Razi Alavizadeh Razi Alavizadeh

View File

@@ -17,8 +17,8 @@ macro.note = "\\b{Note:}"
macro.oslash.HTML = "&oslash;" macro.oslash.HTML = "&oslash;"
macro.ouml.HTML = "&ouml;" macro.ouml.HTML = "&ouml;"
macro.QA = "Qt Assistant" macro.QA = "Qt Assistant"
macro.QC = "Qt Creator" macro.QC = "$IDE_DISPLAY_NAME"
macro.QCE = "Qt Creator Enterprise" macro.QCE = "$IDE_DISPLAY_NAME Enterprise"
macro.QD = "Qt Designer" macro.QD = "Qt Designer"
macro.QL = "Qt Linguist" macro.QL = "Qt Linguist"
macro.QMLD = "Qt Quick Designer" macro.QMLD = "Qt Quick Designer"

View File

@@ -1,6 +1,6 @@
project = "QtCreator" project = "$IDE_DISPLAY_NAME"
description = "Qt Creator Manual" description = "$IDE_DISPLAY_NAME Manual"
url = http://doc.qt.io/qtcreator url = http://doc.qt.io/$IDE_ID
headerdirs = headerdirs =
sourcedirs = ../src sourcedirs = ../src
@@ -54,17 +54,17 @@ include(qt-defines.qdocconf)
sources.fileextensions = "*.qdoc" sources.fileextensions = "*.qdoc"
qhp.projects = QtCreator qhp.projects = QtCreator
qhp.QtCreator.file = qtcreator.qhp qhp.QtCreator.file = $IDE_ID.qhp
qhp.QtCreator.namespace = org.qt-project.qtcreator.$QTC_VERSION_TAG qhp.QtCreator.namespace = org.qt-project.$IDE_ID.$QTC_VERSION_TAG
qhp.QtCreator.virtualFolder = doc qhp.QtCreator.virtualFolder = doc
qhp.QtCreator.indexTitle = Qt Creator Manual $QTC_VERSION qhp.QtCreator.indexTitle = $IDE_DISPLAY_NAME Manual $QTC_VERSION
qhp.QtCreator.filterAttributes = qtcreator $QTC_VERSION qhp.QtCreator.filterAttributes = $IDE_ID $QTC_VERSION
qhp.QtCreator.customFilters.QtCreator.name = Qt Creator $QTC_VERSION qhp.QtCreator.customFilters.QtCreator.name = $IDE_DISPLAY_NAME $QTC_VERSION
qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator $QTC_VERSION qhp.QtCreator.customFilters.QtCreator.filterAttributes = $IDE_ID $QTC_VERSION
qhp.QtCreator.indexRoot = qhp.QtCreator.indexRoot =
qhp.QtCreator.subprojects = manual qhp.QtCreator.subprojects = manual
qhp.QtCreator.subprojects.manual.title = Qt Creator Manual qhp.QtCreator.subprojects.manual.title = $IDE_DISPLAY_NAME Manual
qhp.QtCreator.subprojects.manual.indexTitle = All Topics qhp.QtCreator.subprojects.manual.indexTitle = All Topics
qhp.QtCreator.subprojects.manual.type = manual qhp.QtCreator.subprojects.manual.type = manual
@@ -73,5 +73,5 @@ qhp.QtCreator.subprojects.manual.type = manual
macro.see = "\\sa" macro.see = "\\sa"
macro.function = "\\fn" macro.function = "\\fn"
navigation.landingpage = "Qt Creator Manual" navigation.landingpage = "$IDE_DISPLAY_NAME Manual"
buildversion = "Qt Creator Manual $QTC_VERSION" buildversion = "$IDE_DISPLAY_NAME Manual $QTC_VERSION"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -40,15 +40,15 @@
\commercial \commercial
\QC is integrated with the Linux Perf tool (commercial only) that can be \QC is integrated with the Linux Perf tool (commercial only) that can be
used to analyze the CPU usage of an application on embedded devices and, to used to analyze the CPU and memory usage of an application on embedded
a limited extent, on Linux desktop platforms. The CPU Usage Analyzer uses devices and, to a limited extent, on Linux desktop platforms. The
the Perf tool bundled with the Linux kernel to take periodic snapshots of Performance Analyzer uses the Perf tool bundled with the Linux kernel to
the call chain of an application and visualizes them in a timeline view or take periodic snapshots of the call chain of an application and visualizes
as a flame graph. them in a timeline view or as a flame graph.
\section1 Using the CPU Usage Analyzer \section1 Using the Performance Analyzer
The CPU Usage Analyzer usually needs to be able to locate debug symbols for The Performance Analyzer usually needs to be able to locate debug symbols for
the binaries involved. the binaries involved.
Profile builds produce optimized binaries with separate debug symbols and Profile builds produce optimized binaries with separate debug symbols and
@@ -69,16 +69,16 @@
\endlist \endlist
You can start the CPU Usage Analyzer in the following ways: You can start the Performance Analyzer in the following ways:
\list \list
\li Select \uicontrol Analyze > \uicontrol {CPU Usage Analyzer} to \li Select \uicontrol Analyze > \uicontrol {Performance Analyzer} to
profile the current application. profile the current application.
\li Select the \li Select the
\inlineimage qtcreator-analyze-start-button.png \inlineimage qtcreator-analyze-start-button.png
(\uicontrol Start) button to start the application from the (\uicontrol Start) button to start the application from the
CPU Usage Analyzer. Performance Analyzer.
\endlist \endlist
@@ -87,7 +87,7 @@
(\uicontrol {Collect profile data}) button. (\uicontrol {Collect profile data}) button.
When you start analyzing an application, the application is launched, and When you start analyzing an application, the application is launched, and
the CPU Usage Analyzer immediately begins to collect data. This is indicated the Performance Analyzer immediately begins to collect data. This is indicated
by the time running in the \uicontrol Recorded field. However, as the data by the time running in the \uicontrol Recorded field. However, as the data
is passed through the Perf tool and an extra helper program bundled with is passed through the Perf tool and an extra helper program bundled with
\QC, and both buffer and process it on the fly, data may arrive in \QC \QC, and both buffer and process it on the fly, data may arrive in \QC
@@ -103,16 +103,28 @@
Profile data will still be generated, but \QC will discard it until you Profile data will still be generated, but \QC will discard it until you
select the button again. select the button again.
\section1 Specifying CPU Usage Analyzer Settings \section1 Profiling Memory Usage on Devices
To specify global settings for the CPU Usage Analyzer, select To create trace points for profiling memory usage on a target device, select
\uicontrol Analyze > \uicontrol {Performance Analyzer Options} >
\uicontrol {Create Memory Trace Points}.
To add events for the trace points, see \l{Choosing Event Types}
You can record a memory trace to view usage graphs in the samples rows of
the timeline and to view memory allocations, peaks, and releases in the
flame graph.
\section1 Specifying Performance Analyzer Settings
To specify global settings for the Performance Analyzer, select
\uicontrol Tools > \uicontrol Options > \uicontrol Analyzer > \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
\uicontrol {CPU Usage Analyzer}. For each run configuration, you can also \uicontrol {CPU Usage}. For each run configuration, you can also
use specialized settings. Select \uicontrol Projects > \uicontrol Run, and use specialized settings. Select \uicontrol Projects > \uicontrol Run, and
then select \uicontrol Details next to then select \uicontrol Details next to
\uicontrol {CPU Usage Analyzer Settings}. \uicontrol {Performance Analyzer Settings}.
\image qtcreator-cpu-usage-analyzer-settings.png \image qtcreator-performance-analyzer-settings.png
To edit the settings for the current run configuration, you can also select To edit the settings for the current run configuration, you can also select
the dropdown menu next to the \uicontrol {Collect profile data} button. the dropdown menu next to the \uicontrol {Collect profile data} button.
@@ -120,12 +132,12 @@
\section2 Choosing Event Types \section2 Choosing Event Types
In the \uicontrol Events table, you can specify which events should trigger In the \uicontrol Events table, you can specify which events should trigger
the CPU Usage Analyzer to take a sample. The most common way of analyzing the Performance Analyzer to take a sample. The most common way of analyzing
CPU usage involves periodic sampling, driven by hardware performance CPU usage involves periodic sampling, driven by hardware performance
counters that react to the number of instructions or CPU cycles executed. counters that react to the number of instructions or CPU cycles executed.
Alternatively, a software counter that uses the CPU clock can be chosen. Alternatively, a software counter that uses the CPU clock can be chosen.
Select \uicontrol Add to add events to the table. Select \uicontrol {Add Event} to add events to the table.
In the \uicontrol {Event Type} column, you can choose the general type of In the \uicontrol {Event Type} column, you can choose the general type of
event to be sampled, most commonly \uicontrol {hardware} or event to be sampled, most commonly \uicontrol {hardware} or
\uicontrol {software}. In the \uicontrol {Counter} column, you can choose \uicontrol {software}. In the \uicontrol {Counter} column, you can choose
@@ -141,7 +153,19 @@
\uicontrol {L1-dcache} on the \uicontrol {load} operation with a result \uicontrol {L1-dcache} on the \uicontrol {load} operation with a result
of \uicontrol {misses}. That would sample L1-dcache misses on reading. of \uicontrol {misses}. That would sample L1-dcache misses on reading.
Select \uicontrol Remove to remove the selected event from the table. Select \uicontrol {Remove Event} to remove the selected event from the
table.
Select \uicontrol {Use Trace Points} to replace the current selection of
events with trace points defined on the target device and set the
\uicontrol {Sample mode} to \uicontrol {event count} and the
\uicontrol {Sample period} to \c {1}. If the trace points on the target
were defined using the \uicontrol {Create Trace Points} option, the
Performance Analyzer will automatically use them to profile memory usage.
Select \uicontrol {Reset} to revert the selection of events, as well as the
\uicontrol {Sample mode} and \uicontrol {Sample period} to the default
values.
\section2 Choosing a Sampling Mode and Period \section2 Choosing a Sampling Mode and Period
@@ -154,7 +178,7 @@
a sample every \c n times one of the chosen events has occurred, a sample every \c n times one of the chosen events has occurred,
where \c n is specified in the \uicontrol {Sample period} field. where \c n is specified in the \uicontrol {Sample period} field.
\li Sampling by \uicontrol {frequency} instructs the kernel to try and \li Sampling by \uicontrol {frequency (Hz)} instructs the kernel to try and
take a sample \c n times per second, by automatically adjusting the take a sample \c n times per second, by automatically adjusting the
sampling period. Specify \c n in the \uicontrol {Sample period} sampling period. Specify \c n in the \uicontrol {Sample period}
field. field.
@@ -168,7 +192,7 @@
There may be a significant difference between the sampling period you There may be a significant difference between the sampling period you
request and the actual result. request and the actual result.
In general, if you configure the CPU Usage Analyzer to collect more data In general, if you configure the Performance Analyzer to collect more data
than it can transmit over the connection between the target and the host than it can transmit over the connection between the target and the host
device, the application may get blocked while Perf is trying to send the device, the application may get blocked while Perf is trying to send the
data, and the processing delay may grow excessively. You should then change data, and the processing delay may grow excessively. You should then change
@@ -176,25 +200,33 @@
\section2 Selecting Call Graph Mode \section2 Selecting Call Graph Mode
In the \uicontrol {Call graph mode} field, you can specify how the CPU Usage In the \uicontrol {Call graph mode} field, you can specify how the
Analyzer recovers call chains from your application. Performance Analyzer recovers call chains from your application:
The \uicontrol {Frame Pointer}, or \c fp, mode relies on frame pointers \list
\li The \uicontrol {Frame Pointer}, or \c fp, mode relies on frame pointers
being available in the profiled application and will instruct the kernel on being available in the profiled application and will instruct the kernel on
the target device to walk the chain of frame pointers in order to retrieve the target device to walk the chain of frame pointers in order to retrieve
a call chain for each sample. a call chain for each sample.
The \uicontrol {Dwarf} mode works also without frame pointers, but \li The \uicontrol {Dwarf} mode works also without frame pointers, but
generates significantly more data. It takes a snapshot of the current generates significantly more data. It takes a snapshot of the current
application stack each time a sample is triggered and transmits that application stack each time a sample is triggered and transmits that
snapshot to the host computer for analysis. snapshot to the host computer for analysis.
\li The \uicontrol {Last Branch Record} mode does not use a memory buffer.
It automatically decodes the last 16 taken branches every time execution
stops. It is supported only on recent Intel CPUs.
\endlist
Qt and most system libraries are compiled without frame pointers by Qt and most system libraries are compiled without frame pointers by
default, so the frame pointer mode is only useful with customized systems. default, so the frame pointer mode is only useful with customized systems.
\section2 Setting Stack Snapshot Size \section2 Setting Stack Snapshot Size
The CPU Usage Analyzer will analyze and \e unwind the stack snapshots The Performance Analyzer will analyze and \e unwind the stack snapshots
generated by Perf in dwarf mode. Set the size of the stack snapshots in the generated by Perf in dwarf mode. Set the size of the stack snapshots in the
\uicontrol {Stack snapshot size} field. Large stack snapshots result in a \uicontrol {Stack snapshot size} field. Large stack snapshots result in a
larger volume of data to be transferred and processed. Small stack larger volume of data to be transferred and processed. Small stack
@@ -212,7 +244,7 @@
\section2 Resolving Names for JIT-compiled JavaScript Functions \section2 Resolving Names for JIT-compiled JavaScript Functions
Since version 5.6.0, Qt can generate perf.map files with information about Since version 5.6.0, Qt can generate perf.map files with information about
JavaScript functions. The CPU Usage Analyzer will read them and show the JavaScript functions. The Performance Analyzer will read them and show the
function names in the \uicontrol Timeline, \uicontrol Statistics, and function names in the \uicontrol Timeline, \uicontrol Statistics, and
\uicontrol {Flame Graph} views. This only works if the process being \uicontrol {Flame Graph} views. This only works if the process being
profiled is running on the host computer, not on the target device. To profiled is running on the host computer, not on the target device. To
@@ -225,30 +257,30 @@
The \uicontrol Timeline view displays a graphical representation of CPU The \uicontrol Timeline view displays a graphical representation of CPU
usage per thread and a condensed view of all recorded events. usage per thread and a condensed view of all recorded events.
\image cpu-usage-analyzer.png "CPU Usage Analyzer" \image qtcreator-performance-analyzer-timeline.png "Performance Analyzer"
Each category in the timeline describes a thread in the application. Move Each category in the timeline describes a thread in the application. Move
the cursor on an event (6) on a row to see how long it takes and which the cursor on an event (5) on a row to see how long it takes and which
function in the source it represents. To display the information only when function in the source it represents. To display the information only when
an event is selected, disable the an event is selected, disable the
\uicontrol {View Event Information on Mouseover} button (5). \uicontrol {View Event Information on Mouseover} button (4).
The outline (10) summarizes the period for which data was collected. Drag The outline (9) summarizes the period for which data was collected. Drag
the zoom range (8) or click the outline to move on the outline. You can the zoom range (7) or click the outline to move on the outline. You can
also move between events by selecting the also move between events by selecting the
\uicontrol {Jump to Previous Event} (1) and \uicontrol {Jump to Next Event} \uicontrol {Jump to Previous Event} and \uicontrol {Jump to Next Event}
(2) buttons. buttons (1).
Select the \uicontrol {Show Zoom Slider} button (3) to open a slider that Select the \uicontrol {Show Zoom Slider} button (2) to open a slider that
you can use to set the zoom level. You can also drag the zoom handles (9). you can use to set the zoom level. You can also drag the zoom handles (8).
To reset the default zoom level, right-click the timeline to open the To reset the default zoom level, right-click the timeline to open the
context menu, and select \uicontrol {Reset Zoom}. context menu, and select \uicontrol {Reset Zoom}.
\section2 Selecting Event Ranges \section2 Selecting Event Ranges
You can select an event range (7) to view the time it represents or to zoom You can select an event range (6) to view the time it represents or to zoom
into a specific region of the trace. Select the \uicontrol {Select Range} into a specific region of the trace. Select the \uicontrol {Select Range}
button (4) to activate the selection tool. Then click in the timeline to button (3) to activate the selection tool. Then click in the timeline to
specify the beginning of the event range. Drag the selection handle to specify the beginning of the event range. Drag the selection handle to
define the end of the range. define the end of the range.
@@ -276,10 +308,10 @@
events to move the cursor in the code editor to the part of the code the events to move the cursor in the code editor to the part of the code the
event is associated with. event is associated with.
As the Perf tool only provides periodic samples, the CPU Usage Analyzer As the Perf tool only provides periodic samples, the Performance Analyzer
cannot determine the exact time when a function was called or when it cannot determine the exact time when a function was called or when it
returned. You can, however, see exactly when a sample was taken in the returned. You can, however, see exactly when a sample was taken in the
second row of each thread. The CPU Usage Analyzer assumes that if the same second row of each thread. The Performance Analyzer assumes that if the same
function is present at the same place in the call chain in multiple function is present at the same place in the call chain in multiple
consecutive samples, then this represents a single call to the respective consecutive samples, then this represents a single call to the respective
function. This is, of course, a simplification. Also, there may be other function. This is, of course, a simplification. Also, there may be other
@@ -318,7 +350,7 @@
\section1 Viewing Statistics \section1 Viewing Statistics
\image qtcreator-cpu-usage-analyzer-statistics.png \image qtcreator-performance-analyzer-statistics.png
The \uicontrol Statistics view displays the number of samples each function The \uicontrol Statistics view displays the number of samples each function
in the timeline was contained in, in total and when on the top of the in the timeline was contained in, in total and when on the top of the
@@ -344,12 +376,39 @@
\section2 Visualizing Statistics as Flame Graphs \section2 Visualizing Statistics as Flame Graphs
\image qtcreator-cpu-usage-analyzer-flamegraph.png \image qtcreator-performance-analyzer-flamegraph.png
The \uicontrol {Flame Graph} view shows a more concise statistical overview The \uicontrol {Flame Graph} view shows a more concise statistical overview
of the execution. The horizontal bars show the total number of samples of the execution. The horizontal bars show an aspect of the samples
taken for a certain function, relative to the total number of samples. The taken for a certain function, relative to the same aspect of all samples
nesting shows which functions were called by which other ones. together. The nesting shows which functions were called by which other ones.
The \uicontrol {Visualize} button lets you choose what aspect to show in the
\uicontrol {Flame Graph}.
\list
\li \uicontrol {Samples} is the default visualization. The size of the
horizontal bars represents the number of samples recorded for the given
function.
\li In \uicontrol {Peak Usage} mode, the size of the horizontal bars
represents the amount of memory allocated by the respective functions, at
the point in time when the allocation's memory usage was at its peak.
\li In \uicontrol {Allocations} mode, the size of the horizontal bars
represents the number of memory allocations triggered by the respective
functions.
\li In \uicontrol {Releases} mode, the size of the horizontal bars
represents the number of memory releases triggered by the respective
functions.
\endlist
The \uicontrol {Peak Usage}, \uicontrol {Allocations}, and
\uicontrol {Releases} modes will only show any data if samples from memory
trace points have been recorded.
\section2 Interaction between the views \section2 Interaction between the views
@@ -357,19 +416,20 @@
\uicontrol {Flame Graph}, or \uicontrol {Statistics} views, information \uicontrol {Flame Graph}, or \uicontrol {Statistics} views, information
about it is displayed in the other two views. To view a time range in the about it is displayed in the other two views. To view a time range in the
\uicontrol {Statistics} and \uicontrol {Flame Graph} views, select \uicontrol {Statistics} and \uicontrol {Flame Graph} views, select
\uicontrol {Limit Statistics to Selected Range} in the context menu in the \uicontrol Analyze > \uicontrol {Performance Analyzer Options} >
\uicontrol {Timeline} view. \uicontrol {Limit to the Range Selected in Timeline}. To show the full
stack frame, select \uicontrol {Show Full Range}.
\section1 Loading Perf Data Files \section1 Loading Perf Data Files
You can load any \c perf.data files generated by recent versions of the You can load any \c perf.data files generated by recent versions of the
Linux Perf tool and view them in \QC. Select \uicontrol Analyze > Linux Perf tool and view them in \QC. Select \uicontrol Analyze >
\uicontrol {CPU Usage Analyzer Options} > \uicontrol {Load perf.data} to \uicontrol {Performance Analyzer Options} > \uicontrol {Load perf.data} to
load a file. load a file.
\image qtcreator-cpu-usage-analyzer-load-perf-trace.png \image qtcreator-cpu-usage-analyzer-load-perf-trace.png
The CPU Usage Analyzer needs to know the context in which the The Performance Analyzer needs to know the context in which the
data was recorded to find the debug symbols. Therefore, you have to specify data was recorded to find the debug symbols. Therefore, you have to specify
the kit that the application was built with and the folder where the the kit that the application was built with and the folder where the
application executable is located. application executable is located.
@@ -377,11 +437,11 @@
The Perf data files are generated by calling \c {perf record}. Make sure to The Perf data files are generated by calling \c {perf record}. Make sure to
generate call graphs when recording data by starting Perf with the generate call graphs when recording data by starting Perf with the
\c {--call-graph} option. Also check that the necessary debug symbols are \c {--call-graph} option. Also check that the necessary debug symbols are
available to the CPU Usage Analyzer, either at a standard location available to the Performance Analyzer, either at a standard location
(\c /usr/lib/debug or next to the binaries), or as part of the Qt package (\c /usr/lib/debug or next to the binaries), or as part of the Qt package
you are using. you are using.
The CPU Usage Analyzer can read Perf data files generated in either frame The Performance Analyzer can read Perf data files generated in either frame
pointer or dwarf mode. However, to generate the files correctly, numerous pointer or dwarf mode. However, to generate the files correctly, numerous
preconditions have to be met. All system images for the preconditions have to be met. All system images for the
\l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html} \l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
@@ -394,15 +454,15 @@
\section1 Loading and Saving Trace Files \section1 Loading and Saving Trace Files
You can save and load trace data in a format specific to the You can save and load trace data in a format specific to the
CPU Usage Analyzer with the respective entries in \uicontrol Analyze > Performance Analyzer with the respective entries in \uicontrol Analyze >
\uicontrol {CPU Usage Analyzer Options}. This format is self-contained, and \uicontrol {Performance Analyzer Options}. This format is self-contained, and
therefore loading it does not require you to specify the recording therefore loading it does not require you to specify the recording
environment. You can transfer such trace files to a different computer environment. You can transfer such trace files to a different computer
without any tool chain or debug symbols and analyze them there. without any tool chain or debug symbols and analyze them there.
\section1 Troubleshooting \section1 Troubleshooting
The CPU Usage Analyzer might fail to record data for the following reasons: The Performance Analyzer might fail to record data for the following reasons:
\list 1 \list 1
\li Perf events may be globally disabled on your system. The \li Perf events may be globally disabled on your system. The

View File

@@ -75,10 +75,10 @@
You can use the Heob heap observer on Windows to detect buffer You can use the Heob heap observer on Windows to detect buffer
overruns and memory leaks. overruns and memory leaks.
\li \l{Analyzing CPU Usage}{CPU Usage Analyzer} \li \l{Analyzing CPU Usage}{Performance Analyzer}
You can analyze the CPU usage of embedded applications and Linux You can analyze the CPU usage of embedded applications and Linux
desktop applications with the CPU Usage Analyzer (commercial only) desktop applications with the Performance Analyzer (commercial only)
that integrates the Linux Perf tool. that integrates the Linux Perf tool.
\endlist \endlist

View File

@@ -68,14 +68,12 @@
\li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}. \li Select \uicontrol Analyze > \uicontrol {Clang-Tidy and Clazy}.
\image qtcreator-files-to-analyze.png \image qtcreator-files-to-analyze.png "Analyzer Configuration dialog"
\li In the \uicontrol {Diagnostic Configuration} group, select \li In the \uicontrol {Diagnostic Configuration} group, select a Clang
\uicontrol {Custom Settings}, and then select \uicontrol Manage to configuration in the list of pre-defined configurations (1). For
specify the Clang-Tidy and Clazy checks to perform. more information about creating a custom configuration, see
\l {Configuring Clang Tools}.
\li Select the new custom configuration in the list of configurations
(1).
\li In the \uicontrol {Files to Analyze} group, select the files to \li In the \uicontrol {Files to Analyze} group, select the files to
apply the checks to. apply the checks to.
@@ -90,7 +88,10 @@
(\uicontrol Start) button to open the \uicontrol {Analyzer Configuration} (\uicontrol Start) button to open the \uicontrol {Analyzer Configuration}
dialog. dialog.
\image qtcreator-clang-tools.png The found issues are displayed in the \uicontrol {Clang-Tidy and Clazy}
view:
\image qtcreator-clang-tools.png "Clang-Tidy and Clazy view"
Select the link in the \uicontrol Location column to move to the location Select the link in the \uicontrol Location column to move to the location
where the issue appears in the code editor. where the issue appears in the code editor.
@@ -106,14 +107,35 @@
\list \list
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer > \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
\uicontrol {Clang Tools} > \uicontrol Manage. \uicontrol {Clang Tools}.
\image qtcreator-clang-tools-options.png \image qtcreator-clang-tools-options.png "Clang Tools options tab"
\li To build the project before running the Clang tools, select the
\uicontrol {Build the project before analysis} check box. The Clang
tools do not require the project to be built before analysis, but
they might display misleading warnings about files missing that are
generated during the build. For big projects, not building the
project might save some time.
\li In the \uicontrol {Simultaneous processes} field, select the number
of processes to run simultaneously to make the analysis faster on
multi-core processors.
\li In the \uicontrol {Diagnostic Configuration} group, select
\uicontrol Manage to create or edit a custom configuration.
\li Select \uicontrol Copy to create a custom Clang configuration.
\image qtcreator-diagnostics-configuration.png "Diagnostics Configuration dialog"
\li In the \uicontrol {Diagnostic configuration name} field, give the
configuration a name, and then select \uicontrol OK.
\li In the \uicontrol {Clang-Tidy} tab, select the checks to \li In the \uicontrol {Clang-Tidy} tab, select the checks to
perform. perform.
\image qtcreator-clang-tidy.png \image qtcreator-clang-tidy.png "Clang-Tidy tab"
\li To edit the selected check as plain text, select \li To edit the selected check as plain text, select
\uicontrol {Edit Checks as String}. \uicontrol {Edit Checks as String}.
@@ -121,7 +143,7 @@
\li In the \uicontrol Clazy tab, select the level of Clazy \li In the \uicontrol Clazy tab, select the level of Clazy
checks to perform. checks to perform.
\image qtcreator-clazy.png \image qtcreator-clazy.png "Clazy tab"
\endlist \endlist

View File

@@ -75,7 +75,7 @@
\section1 Supported Native Debugger Versions \section1 Supported Native Debugger Versions
Qt Creator supports native debuggers when working with compiled code. On \QC supports native debuggers when working with compiled code. On
most supported platforms, the GNU Symbolic Debugger GDB can be used. On most supported platforms, the GNU Symbolic Debugger GDB can be used. On
Microsoft Windows, when using the Microsoft tool chain the Microsoft Console Microsoft Windows, when using the Microsoft tool chain the Microsoft Console
Debugger CDB, is needed. On \macos, the LLDB debugger can be used. Basic Debugger CDB, is needed. On \macos, the LLDB debugger can be used. Basic
@@ -195,7 +195,7 @@
\note Visual Studio does not include the Debugging tools needed, \note Visual Studio does not include the Debugging tools needed,
and therefore, you must install them separately. and therefore, you must install them separately.
In addition, you must select \uicontrol {Qt Creator CDB Debugger Support} In addition, you must select \uicontrol {\QC CDB Debugger Support}
(in \uicontrol Qt > \uicontrol Tools > \uicontrol {\QC}) when you install (in \uicontrol Qt > \uicontrol Tools > \uicontrol {\QC}) when you install
Qt or the stand-alone \QC. Qt or the stand-alone \QC.
@@ -328,7 +328,7 @@
codesign -f -s "fsfgdb" $INSTALL_LOCATION/fsfgdb codesign -f -s "fsfgdb" $INSTALL_LOCATION/fsfgdb
\endcode \endcode
\li In \QC, select \uicontrol {Qt Creator} > \uicontrol Preferences > \li In \QC, select \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Kits > \uicontrol Add to \uicontrol Kits > \uicontrol Add to
create a kit that uses FSF GDB. create a kit that uses FSF GDB.

View File

@@ -223,7 +223,7 @@
The \QC installation program asks you whether you want to register \QC as a The \QC installation program asks you whether you want to register \QC as a
post-mortem debugger. To change the setting, select post-mortem debugger. To change the setting, select
\uicontrol Tools > \uicontrol Options > \uicontrol Debugger > \uicontrol Tools > \uicontrol Options > \uicontrol Debugger >
\uicontrol General > \uicontrol {Use Qt Creator for post-mortem debugging}. \uicontrol General > \uicontrol {Use \QC for post-mortem debugging}.
You can launch the debugger in the post-mortem mode if an application You can launch the debugger in the post-mortem mode if an application
crashes on Windows. Click the \uicontrol {Debug in \QC} button in the error crashes on Windows. Click the \uicontrol {Debug in \QC} button in the error
@@ -979,7 +979,7 @@
Unlike GDB's Unlike GDB's
\l{https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing} \l{https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing}
{pretty printers} and LLDB's \l{http://lldb.llvm.org/varformats.html} {pretty printers} and LLDB's \l{http://lldb.llvm.org/varformats.html}
{data formatters}, Qt Creator's debugging helpers are independent of the {data formatters}, \QC's debugging helpers are independent of the
native debugging backend. That is, the same code can be used with GDB on native debugging backend. That is, the same code can be used with GDB on
Linux, LLDB on macOS, and CDB on Windows, or any other platform on which at Linux, LLDB on macOS, and CDB on Windows, or any other platform on which at
least one of the three supported backends is available. least one of the three supported backends is available.

View File

@@ -138,34 +138,33 @@
edit the value for the \uicontrol {Do not index files greater than} edit the value for the \uicontrol {Do not index files greater than}
check box. To index all files, deselect the check box. check box. To index all files, deselect the check box.
\li Select \uicontrol Manage to specify the level for requesting Clang \li Select \uicontrol Manage to specify the Clang checks to perform.
warnings.
\image qtcreator-diagnostics-configuration.png \image qtcreator-diagnostics-configuration.png
\endlist \endlist
\section1 Clang Warnings \section1 Clang Checks
The predefined configurations request Clang warnings at the following The predefined configurations perform the following Clang checks:
levels:
\list \list
\li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic option that \li \uicontrol {Clang-only pedantic checks} uses the \c -Wpendantic
requests all the warnings demanded by strict ISO C and ISO C++. option that performs checks as required by strict ISO C and ISO C++.
\li \uicontrol {Warnings for Questionable Constructs} combines the \li \uicontrol {Clang-only checks for questionable constructs} combines
\c -Wall and \c -Wextra options to request all warnings about easily the \c -Wall and \c -Wextra checks for easily avoidable questionable
avoidable questionable constructions and some additional warnings. constructions and some additional issues.
\li \uicontrol {Warnings for Almost Everything} uses the \c -Weverything \li \uicontrol {Clang-only checks for almost everything} uses the
option with negative options to suppress some warnings. \c -Weverything option with negative options to suppress some
warnings.
\endlist \endlist
You can edit the predefined configurations to request specific warnings You can edit the predefined configurations to perform particular checks
beginning with \c -W. Each of these warnings also has a negative version beginning with \c -W. Each of these checks also has a negative version
that begins with \c -Wno. that begins with \c -Wno.
Keep in mind that some options turn on other options. For more information, Keep in mind that some options turn on other options. For more information,

View File

@@ -132,7 +132,7 @@
\QC creates the test in the specified project directory. \QC creates the test in the specified project directory.
For more information about creating Google tests, see the For more information about creating Google tests, see the
\l{https://github.com/google/googletest/blob/master/googletest/docs/Primer.md} \l{https://github.com/google/googletest/blob/master/googletest/docs/primer.md}
{Google Test Primer}. {Google Test Primer}.
\section1 Setting Up the Google C++ Testing Framework \section1 Setting Up the Google C++ Testing Framework

View File

@@ -645,13 +645,13 @@
\li Look In \li Look In
\row \row
\li \uicontrol Tools > \uicontrol Options \li \uicontrol Tools > \uicontrol Options
\li \uicontrol {Qt Creator} > \uicontrol Preferences \li \uicontrol {\QC} > \uicontrol Preferences
\row \row
\li \uicontrol Help > \uicontrol {About Plugins} \li \uicontrol Help > \uicontrol {About Plugins}
\li \uicontrol {Qt Creator} > \uicontrol {About Plugins} \li \uicontrol {\QC} > \uicontrol {About Plugins}
\row \row
\li Keyboard shortcuts \li Keyboard shortcuts
\li \uicontrol {Qt Creator} > \uicontrol Preferences > \uicontrol Environment > \li \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Environment >
\uicontrol Keyboard \uicontrol Keyboard
\endtable \endtable

View File

@@ -33,7 +33,7 @@
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\page creator-commercial-overview.html \page creator-commercial-overview.html
\title Qt Creator Commercial Features \title Commercial Features
\commercial \commercial
@@ -41,7 +41,7 @@
\l{http://qt.io/licensing/}{Qt license}: \l{http://qt.io/licensing/}{Qt license}:
\list \list
\li \l{Analyzing CPU Usage}{CPU Usage Analyzer} \li \l{Analyzing CPU Usage}{Performance Analyzer}
\li \l{Browsing ISO 7000 Icons} in \QMLD \li \l{Browsing ISO 7000 Icons} in \QMLD
\li \l{http://doc.qt.io/QtForDeviceCreation/index.html}{Developing for \li \l{http://doc.qt.io/QtForDeviceCreation/index.html}{Developing for
embedded devices} embedded devices}

View File

@@ -76,7 +76,7 @@
\image qtcreator-custom-wizard.png \image qtcreator-custom-wizard.png
\section1 Integrating Wizards into Qt Creator Builds \section1 Integrating Wizards into Builds
To integrate the wizard into \QC and to deliver it as part of the \QC build, To integrate the wizard into \QC and to deliver it as part of the \QC build,
place the wizard files in the \QC sources. Then select \uicontrol Build > place the wizard files in the \QC sources. Then select \uicontrol Build >

View File

@@ -68,7 +68,7 @@
settings directory to ensure that different \QC instances do not overwrite settings directory to ensure that different \QC instances do not overwrite
each other's profiles. If you only run one \QC instance, you can store the each other's profiles. If you only run one \QC instance, you can store the
profiles in the Qbs settings directory instead, by deselecting the profiles in the Qbs settings directory instead, by deselecting the
\uicontrol {Store profiles in Qt Creator settings directory} check box. \uicontrol {Store profiles in \QC settings directory} check box.
In the \uicontrol Kit field, select a build and run kit to view the In the \uicontrol Kit field, select a build and run kit to view the
properties of the associated Qbs profile. To modify the properties of the properties of the associated Qbs profile. To modify the properties of the

View File

@@ -160,7 +160,7 @@
To generate debug symbols also for applications compiled in release mode, To generate debug symbols also for applications compiled in release mode,
select the \uicontrol {Generate separate debug info} check box. For more select the \uicontrol {Generate separate debug info} check box. For more
information, see \l{Using the CPU Usage Analyzer}. information, see \l{Using the Performance Analyzer}.
\section3 Compiling QML \section3 Compiling QML

View File

@@ -47,7 +47,7 @@
This manual also describes features that are only available if you have the This manual also describes features that are only available if you have the
appropriate \l{http://qt.io/licensing/}{Qt license}. For more information, appropriate \l{http://qt.io/licensing/}{Qt license}. For more information,
see \l{Qt Creator Commercial Features}. see \l{Commercial Features}.
\table \table
\row \row

View File

@@ -55,7 +55,7 @@
\note Kits are listed if they have been specified in \uicontrol \note Kits are listed if they have been specified in \uicontrol
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux) Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
or in \uicontrol {Qt Creator} > \uicontrol Preferences > or in \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Kits (on \macos). \uicontrol Kits (on \macos).
\li Select \uicontrol Next. \li Select \uicontrol Next.

View File

@@ -173,7 +173,7 @@
\note Kits are listed if they have been specified in \uicontrol \note Kits are listed if they have been specified in \uicontrol
Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux) Tools > \uicontrol Options > \uicontrol Kits (on Windows and Linux)
or in \uicontrol {Qt Creator} > \uicontrol Preferences > or in \uicontrol {\QC} > \uicontrol Preferences >
\uicontrol Kits (on \macos). \uicontrol Kits (on \macos).
\li Select \uicontrol Next. \li Select \uicontrol Next.

View File

@@ -44,7 +44,7 @@
\section1 Exporting from Adobe Photoshop to QML \section1 Exporting from Adobe Photoshop to QML
You can use a QML Asset Exporter to export designs from Adobe Photoshop You can use a QML Asset Exporter to export designs from Adobe Photoshop
to .ui.qml files. The the QML Asset Exporter provides templates that are to .ui.qml files. The QML Asset Exporter provides templates that are
based on the \l{http://www.pngexpress.com}{PNG EXPRESS} plugin for based on the \l{http://www.pngexpress.com}{PNG EXPRESS} plugin for
Photoshop. They enable you to export PSD files to QML format, so that each Photoshop. They enable you to export PSD files to QML format, so that each
PSD file is converted into an .ui.qml file. PSD file is converted into an .ui.qml file.

View File

@@ -72,7 +72,7 @@
\note If only one kit is specified in \uicontrol Tools > \note If only one kit is specified in \uicontrol Tools >
\uicontrol Options > \uicontrol Kits (on Windows and Linux) or in \uicontrol Options > \uicontrol Kits (on Windows and Linux) or in
\uicontrol {Qt Creator} > \uicontrol Preferences > \uicontrol Kits \uicontrol {\QC} > \uicontrol Preferences > \uicontrol Kits
(on \macos), this dialog is skipped. (on \macos), this dialog is skipped.
The \uicontrol{Class Information} dialog opens. The \uicontrol{Class Information} dialog opens.

View File

@@ -5,6 +5,12 @@
isEmpty(VERSION): error("Include qtcreator.pri before including docs.pri!") isEmpty(VERSION): error("Include qtcreator.pri before including docs.pri!")
qtcname.name = IDE_DISPLAY_NAME
qtcname.value = "$$IDE_DISPLAY_NAME"
qtcid.name = IDE_ID
qtcid.value = $$IDE_ID
qtccasedid.name = IDE_CASED_ID
qtccasedid.value = $$IDE_CASED_ID
qtcver.name = QTC_VERSION qtcver.name = QTC_VERSION
qtcver.value = $$QTCREATOR_DISPLAY_VERSION qtcver.value = $$QTCREATOR_DISPLAY_VERSION
qtcvertag.name = QTC_VERSION_TAG qtcvertag.name = QTC_VERSION_TAG
@@ -17,7 +23,7 @@ qtcdocsdir.name = QTC_DOCS_DIR
qtcdocsdir.value = $$IDE_SOURCE_TREE/doc qtcdocsdir.value = $$IDE_SOURCE_TREE/doc
qtccopyrightyear.name = QTCREATOR_COPYRIGHT_YEAR qtccopyrightyear.name = QTCREATOR_COPYRIGHT_YEAR
qtccopyrightyear.value = $$QTCREATOR_COPYRIGHT_YEAR qtccopyrightyear.value = $$QTCREATOR_COPYRIGHT_YEAR
QDOC_ENV += qtcver qtcvertag qtdocs qdocindex qtcdocsdir qtccopyrightyear QDOC_ENV += qtcname qtcid qtccasedid qtcver qtcvertag qtdocs qdocindex qtcdocsdir qtccopyrightyear
DOC_INDEX_PATHS += $$IDE_BUILD_TREE/doc DOC_INDEX_PATHS += $$IDE_BUILD_TREE/doc
DOC_HTML_INSTALLDIR = $$INSTALL_DOC_PATH DOC_HTML_INSTALLDIR = $$INSTALL_DOC_PATH

View File

@@ -26,11 +26,10 @@
#include "qpacketprotocol.h" #include "qpacketprotocol.h"
#include <qelapsedtimer.h> #include <qelapsedtimer.h>
#include <qendian.h>
namespace QmlDebug { namespace QmlDebug {
static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
/*! /*!
\class QPacketProtocol \class QPacketProtocol
\internal \internal
@@ -98,15 +97,14 @@ class QPacketProtocolPrivate : public QObject
public: public:
QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev) QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
: QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE), : QObject(parent), inProgressSize(-1), waitingForPacket(false), dev(_dev)
waitingForPacket(false), dev(_dev)
{ {
Q_ASSERT(4 == sizeof(qint32)); Q_ASSERT(4 == sizeof(qint32));
QObject::connect(this, &QPacketProtocolPrivate::readyRead, QObject::connect(this, &QPacketProtocolPrivate::readyRead,
parent, &QPacketProtocol::readyRead); parent, &QPacketProtocol::readyRead);
QObject::connect(this, &QPacketProtocolPrivate::invalidPacket, QObject::connect(this, &QPacketProtocolPrivate::protocolError,
parent, &QPacketProtocol::invalidPacket); parent, &QPacketProtocol::protocolError);
QObject::connect(dev, &QIODevice::readyRead, QObject::connect(dev, &QIODevice::readyRead,
this, &QPacketProtocolPrivate::readyToRead); this, &QPacketProtocolPrivate::readyToRead);
QObject::connect(dev, &QIODevice::aboutToClose, QObject::connect(dev, &QIODevice::aboutToClose,
@@ -117,7 +115,7 @@ public:
signals: signals:
void readyRead(); void readyRead();
void invalidPacket(); void protocolError();
public: public:
void aboutToClose() void aboutToClose()
@@ -142,6 +140,17 @@ public:
} }
} }
void fail()
{
QObject::disconnect(dev, &QIODevice::readyRead,
this, &QPacketProtocolPrivate::readyToRead);
QObject::disconnect(dev, &QIODevice::aboutToClose,
this, &QPacketProtocolPrivate::aboutToClose);
QObject::disconnect(dev, &QIODevice::bytesWritten,
this, &QPacketProtocolPrivate::bytesWritten);
emit protocolError();
}
void readyToRead() void readyToRead()
{ {
while (true) { while (true) {
@@ -152,19 +161,15 @@ public:
return; return;
// Read size header // Read size header
int read = dev->read((char *)&inProgressSize, sizeof(qint32)); qint32 inProgressSizeLE;
const qint64 read = dev->read((char *)&inProgressSizeLE, sizeof(qint32));
Q_ASSERT(read == sizeof(qint32)); Q_ASSERT(read == sizeof(qint32));
Q_UNUSED(read); Q_UNUSED(read);
inProgressSize = qFromLittleEndian(inProgressSizeLE);
// Check sizing constraints // Check sizing constraints
if (inProgressSize > maxPacketSize) { if (inProgressSize < qint32(sizeof(qint32))) {
QObject::disconnect(dev, &QIODevice::readyRead, fail();
this, &QPacketProtocolPrivate::readyToRead);
QObject::disconnect(dev, &QIODevice::aboutToClose,
this, &QPacketProtocolPrivate::aboutToClose);
QObject::disconnect(dev, &QIODevice::bytesWritten,
this, &QPacketProtocolPrivate::bytesWritten);
emit invalidPacket();
return; return;
} }
@@ -187,11 +192,10 @@ public:
} }
public: public:
QList<qint64> sendingPackets; QList<qint32> sendingPackets;
QList<QByteArray> packets; QList<QByteArray> packets;
QByteArray inProgress; QByteArray inProgress;
qint32 inProgressSize; qint32 inProgressSize;
qint32 maxPacketSize;
bool waitingForPacket; bool waitingForPacket;
QIODevice *dev; QIODevice *dev;
}; };
@@ -211,18 +215,29 @@ QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
*/ */
void QPacketProtocol::send(const QByteArray &p) void QPacketProtocol::send(const QByteArray &p)
{ {
static const qint32 maxSize = std::numeric_limits<qint32>::max() - sizeof(qint32);
if (p.isEmpty()) if (p.isEmpty())
return; // We don't send empty packets return; // We don't send empty packets
qint64 sendSize = p.size() + sizeof(qint32); if (p.size() > maxSize) {
d->fail();
return;
}
const qint32 sendSize = p.size() + sizeof(qint32);
d->sendingPackets.append(sendSize); d->sendingPackets.append(sendSize);
qint32 sendSize32 = sendSize;
qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32)); const qint32 sendSizeLE = qToLittleEndian(sendSize);
Q_ASSERT(writeBytes == sizeof(qint32)); if (d->dev->write((char *)&sendSizeLE, sizeof(qint32)) != sizeof(qint32)) {
writeBytes = d->dev->write(p); d->fail();
Q_ASSERT(writeBytes == p.size()); return;
Q_UNUSED(writeBytes); // For building in release mode. }
if (d->dev->write(p) != p.size()) {
d->fail();
return;
}
} }
/*! /*!

View File

@@ -52,7 +52,7 @@ public:
signals: signals:
void readyRead(); void readyRead();
void invalidPacket(); void protocolError();
private: private:
QPacketProtocolPrivate *d; QPacketProtocolPrivate *d;

View File

@@ -700,7 +700,8 @@ static std::string dumplocalHelper(ExtensionCommandContext &exc,PCSTR args, int
return std::string(); return std::string();
} }
std::wstring value; std::wstring value;
if (!dumpSimpleType(n->asSymbolGroupNode(), SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), &value, &std::string())) { std::string tmp;
if (!dumpSimpleType(n->asSymbolGroupNode(), SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), &value, &tmp)) {
*errorMessage = "Cannot dump " + iname; *errorMessage = "Cannot dump " + iname;
return std::string(); return std::string();
} }

View File

@@ -228,8 +228,9 @@ SymbolAncestorInfo SymbolGroupValue::infoOfAncestor(const std::string &name) con
SymbolGroupValue SymbolGroupValue::addSymbol(const ULONG64 address, const std::string &type) const SymbolGroupValue SymbolGroupValue::addSymbol(const ULONG64 address, const std::string &type) const
{ {
const std::string &pointerToType = pointedToSymbolName(address, type); const std::string &pointerToType = pointedToSymbolName(address, type);
std::string tmp;
if (SymbolGroupNode *ancestorNode = if (SymbolGroupNode *ancestorNode =
node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &std::string())) { node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &tmp)) {
return SymbolGroupValue(ancestorNode, m_context); return SymbolGroupValue(ancestorNode, m_context);
} }
if (isValid() && SymbolGroupValue::verbose) { // Do not report subsequent errors if (isValid() && SymbolGroupValue::verbose) { // Do not report subsequent errors
@@ -2064,8 +2065,9 @@ static inline bool dumpQRegion(const SymbolGroupValue &v, std::wostream &str, vo
namestr << "(" << info.prependQtGuiModule("QRegionPrivate *") << ")(" namestr << "(" << info.prependQtGuiModule("QRegionPrivate *") << ")("
<< std::showbase << std::hex << d.pointerValue() << ')'; << std::showbase << std::hex << d.pointerValue() << ')';
std::string tmp;
SymbolGroupNode *qRegionPrivateNode SymbolGroupNode *qRegionPrivateNode
= v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &std::string()); = v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &tmp);
if (!qRegionPrivateNode) if (!qRegionPrivateNode)
return false; return false;
@@ -2128,14 +2130,15 @@ static inline bool dumpQHostAddress(const SymbolGroupValue &v, std::wostream &st
std::ostringstream namestr; std::ostringstream namestr;
namestr << '(' << info.prependQtNetworkModule("QHostAddressPrivate *") << ")(" namestr << '(' << info.prependQtNetworkModule("QHostAddressPrivate *") << ")("
<< std::showbase << std::hex << d.pointerValue() << ')'; << std::showbase << std::hex << d.pointerValue() << ')';
std::string tmp;
SymbolGroupNode *qHostAddressPrivateNode SymbolGroupNode *qHostAddressPrivateNode
= v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &std::string()); = v.node()->symbolGroup()->addSymbol(v.module(), namestr.str(), std::string(), &tmp);
if (!qHostAddressPrivateNode) if (!qHostAddressPrivateNode)
return false; return false;
const SymbolGroupValue qHostAddressPrivateValue = SymbolGroupValue(qHostAddressPrivateNode, v.context()); const SymbolGroupValue qHostAddressPrivateValue = SymbolGroupValue(qHostAddressPrivateNode, v.context());
const bool parsed = readPODFromMemory<bool>(qHostAddressPrivateValue.context().dataspaces, const bool parsed = readPODFromMemory<bool>(qHostAddressPrivateValue.context().dataspaces,
qHostAddressPrivateValue["isParsed"].address(), qHostAddressPrivateValue["isParsed"].address(),
sizeof(bool), false, &std::string()); sizeof(bool), false, &tmp);
if (parsed) { if (parsed) {
const int protocol = qHostAddressPrivateValue["protocol"].intValue(-1); const int protocol = qHostAddressPrivateValue["protocol"].intValue(-1);
if (protocol < 0) { if (protocol < 0) {
@@ -2888,7 +2891,8 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str, std::str
if (const SymbolGroupValue mv = dataV.typeCast(vmType.c_str())) { if (const SymbolGroupValue mv = dataV.typeCast(vmType.c_str())) {
SymbolGroupNode *mapNode = mv.node(); SymbolGroupNode *mapNode = mv.node();
std::wstring value; std::wstring value;
if (dumpSimpleType(mapNode, dataV.context(), &value, &std::string()) std::string tmp;
if (dumpSimpleType(mapNode, dataV.context(), &value, &tmp)
== SymbolGroupNode::SimpleDumperOk) { == SymbolGroupNode::SimpleDumperOk) {
str << value; str << value;
if (specialInfoIn) if (specialInfoIn)
@@ -2903,7 +2907,8 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str, std::str
if (const SymbolGroupValue vl = dataV.typeCast(vLType.c_str())) { if (const SymbolGroupValue vl = dataV.typeCast(vLType.c_str())) {
SymbolGroupNode *vListNode = vl.node(); SymbolGroupNode *vListNode = vl.node();
std::wstring value; std::wstring value;
if (dumpSimpleType(vListNode, dataV.context(), &value, &std::string()) std::string tmp;
if (dumpSimpleType(vListNode, dataV.context(), &value, &tmp)
== SymbolGroupNode::SimpleDumperOk) { == SymbolGroupNode::SimpleDumperOk) {
str << value; str << value;
if (specialInfoIn) if (specialInfoIn)
@@ -2929,7 +2934,8 @@ static bool dumpQVariant(const SymbolGroupValue &v, std::wostream &str, std::str
if (const SymbolGroupValue sl = dataV.typeCast(qtInfo.prependQtCoreModule("QStringList *").c_str())) { if (const SymbolGroupValue sl = dataV.typeCast(qtInfo.prependQtCoreModule("QStringList *").c_str())) {
SymbolGroupNode *listNode = sl.node(); SymbolGroupNode *listNode = sl.node();
std::wstring value; std::wstring value;
if (dumpSimpleType(listNode, dataV.context(), &value, &std::string()) std::string tmp;
if (dumpSimpleType(listNode, dataV.context(), &value, &tmp)
== SymbolGroupNode::SimpleDumperOk) { == SymbolGroupNode::SimpleDumperOk) {
str << value; str << value;
if (specialInfoIn) if (specialInfoIn)

View File

@@ -58,6 +58,13 @@ Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos
return optional; return optional;
} }
int positionInText(QTextDocument *textDocument, int line, int column)
{
// Deduct 1 from line and column since they are 1-based.
// Column should already be converted from UTF-8 byte offset to the TextEditor column.
return textDocument->findBlockByNumber(line - 1).position() + column - 1;
}
QString textAt(QTextCursor tc, int pos, int length) QString textAt(QTextCursor tc, int pos, int length)
{ {
if (pos < 0) if (pos < 0)

View File

@@ -43,6 +43,9 @@ QTCREATOR_UTILS_EXPORT bool convertPosition(const QTextDocument *document,
QTCREATOR_UTILS_EXPORT QTCREATOR_UTILS_EXPORT
Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos); Utils::OptionalLineColumn convertPosition(const QTextDocument *document, int pos);
// line and column are 1-based
QTCREATOR_UTILS_EXPORT int positionInText(QTextDocument *textDocument, int line, int column);
QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length); QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length);
QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length); QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);

View File

@@ -69,6 +69,8 @@ bool GTestResult::isDirectParentOf(const TestResult *other, bool *needsIntermedi
return false; return false;
const GTestResult *gtOther = static_cast<const GTestResult *>(other); const GTestResult *gtOther = static_cast<const GTestResult *>(other);
if (m_testSetName == gtOther->m_testSetName && other->result() == Result::MessageInternal)
return true;
if (m_iteration != gtOther->m_iteration) if (m_iteration != gtOther->m_iteration)
return false; return false;
return isTest() && gtOther->isTestSet(); return isTest() && gtOther->isTestSet();

View File

@@ -84,7 +84,9 @@ static bool isDerivedFromTestCase(QmlJS::AST::UiQualifiedId *id, const QmlJS::Do
bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
{ {
const QStringRef name = ast->qualifiedTypeNameId->name; const QStringRef name = ast->qualifiedTypeNameId->name;
m_objectStack.push(name.toString());
if (name != "TestCase") { if (name != "TestCase") {
m_insideTestCase = false;
if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot)) if (!isDerivedFromTestCase(ast->qualifiedTypeNameId, m_currentDoc, m_snapshot))
return true; return true;
} else if (!documentImportsQtTest(m_currentDoc.data())) { } else if (!documentImportsQtTest(m_currentDoc.data())) {
@@ -92,6 +94,7 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
} }
m_typeIsTestCase = true; m_typeIsTestCase = true;
m_insideTestCase = true;
m_currentTestCaseName.clear(); m_currentTestCaseName.clear();
const auto sourceLocation = ast->firstSourceLocation(); const auto sourceLocation = ast->firstSourceLocation();
m_testCaseLocation.m_name = m_currentDoc->fileName(); m_testCaseLocation.m_name = m_currentDoc->fileName();
@@ -101,6 +104,11 @@ bool TestQmlVisitor::visit(QmlJS::AST::UiObjectDefinition *ast)
return true; return true;
} }
void TestQmlVisitor::endVisit(QmlJS::AST::UiObjectDefinition *)
{
m_insideTestCase = m_objectStack.pop() == "TestCase";
}
bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast) bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
{ {
const QmlJS::AST::ExpressionNode *expr = ast->expression; const QmlJS::AST::ExpressionNode *expr = ast->expression;
@@ -109,8 +117,15 @@ bool TestQmlVisitor::visit(QmlJS::AST::ExpressionStatement *ast)
bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast) bool TestQmlVisitor::visit(QmlJS::AST::UiScriptBinding *ast)
{ {
const QStringRef name = ast->qualifiedId->name; if (m_insideTestCase)
return name == "name"; m_expectTestCaseName = ast->qualifiedId->name == "name";
return m_expectTestCaseName;
}
void TestQmlVisitor::endVisit(QmlJS::AST::UiScriptBinding *)
{
if (m_expectTestCaseName)
m_expectTestCaseName = false;
} }
bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast) bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
@@ -139,8 +154,10 @@ bool TestQmlVisitor::visit(QmlJS::AST::FunctionDeclaration *ast)
bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast) bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast)
{ {
if (m_typeIsTestCase) if (m_expectTestCaseName && m_currentTestCaseName.isEmpty()) {
m_currentTestCaseName = ast->value.toString(); m_currentTestCaseName = ast->value.toString();
m_expectTestCaseName = false;
}
return false; return false;
} }

View File

@@ -30,6 +30,8 @@
#include <qmljs/parser/qmljsastvisitor_p.h> #include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/qmljsdocument.h> #include <qmljs/qmljsdocument.h>
#include <QStack>
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
@@ -38,11 +40,13 @@ class TestQmlVisitor : public QmlJS::AST::Visitor
public: public:
explicit TestQmlVisitor(QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot); explicit TestQmlVisitor(QmlJS::Document::Ptr doc, const QmlJS::Snapshot &snapshot);
bool visit(QmlJS::AST::UiObjectDefinition *ast); bool visit(QmlJS::AST::UiObjectDefinition *ast) override;
bool visit(QmlJS::AST::ExpressionStatement *ast); void endVisit(QmlJS::AST::UiObjectDefinition *ast) override;
bool visit(QmlJS::AST::UiScriptBinding *ast); bool visit(QmlJS::AST::ExpressionStatement *ast) override;
bool visit(QmlJS::AST::FunctionDeclaration *ast); bool visit(QmlJS::AST::UiScriptBinding *ast) override;
bool visit(QmlJS::AST::StringLiteral *ast); void endVisit(QmlJS::AST::UiScriptBinding *ast) override;
bool visit(QmlJS::AST::FunctionDeclaration *ast) override;
bool visit(QmlJS::AST::StringLiteral *ast) override;
QString testCaseName() const { return m_currentTestCaseName; } QString testCaseName() const { return m_currentTestCaseName; }
TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; } TestCodeLocationAndType testCaseLocation() const { return m_testCaseLocation; }
@@ -55,7 +59,10 @@ private:
QString m_currentTestCaseName; QString m_currentTestCaseName;
TestCodeLocationAndType m_testCaseLocation; TestCodeLocationAndType m_testCaseLocation;
QMap<QString, TestCodeLocationAndType> m_testFunctions; QMap<QString, TestCodeLocationAndType> m_testFunctions;
QStack<QString> m_objectStack;
bool m_typeIsTestCase = false; bool m_typeIsTestCase = false;
bool m_insideTestCase = false;
bool m_expectTestCaseName = false;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -75,12 +75,14 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
TestRunMode runMode) TestRunMode runMode)
{ {
QTC_ASSERT(rc, return); QTC_ASSERT(rc, return);
QTC_ASSERT(m_project, return);
if (hasExecutable()) { if (hasExecutable()) {
qCDebug(LOG) << "Executable has been set already - not completing configuration again."; qCDebug(LOG) << "Executable has been set already - not completing configuration again.";
return; return;
} }
Project *project = SessionManager::startupProject(); Project *project = SessionManager::startupProject();
if (!project) if (!project || project != m_project)
return; return;
Target *target = project->activeTarget(); Target *target = project->activeTarget();
@@ -94,7 +96,6 @@ void TestConfiguration::completeTestInformation(ProjectExplorer::RunConfiguratio
m_runnable = rc->runnable(); m_runnable = rc->runnable();
m_displayName = rc->displayName(); m_displayName = rc->displayName();
m_project = rc->project();
const QString buildKey = rc->buildKey(); const QString buildKey = rc->buildKey();
BuildTargetInfo targetInfo = target->applicationTargets().buildTargetInfo(buildKey); BuildTargetInfo targetInfo = target->applicationTargets().buildTargetInfo(buildKey);
@@ -116,6 +117,7 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
{ {
QTC_ASSERT(!m_projectFile.isEmpty(), return); QTC_ASSERT(!m_projectFile.isEmpty(), return);
QTC_ASSERT(!m_buildTargets.isEmpty(), return); QTC_ASSERT(!m_buildTargets.isEmpty(), return);
QTC_ASSERT(m_project, return);
if (m_origRunConfig) { if (m_origRunConfig) {
qCDebug(LOG) << "Using run configuration specified by user or found by first call"; qCDebug(LOG) << "Using run configuration specified by user or found by first call";
@@ -129,8 +131,10 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
qCDebug(LOG) << "Failed to complete - using 'normal' way."; qCDebug(LOG) << "Failed to complete - using 'normal' way.";
} }
Project *project = SessionManager::startupProject(); Project *project = SessionManager::startupProject();
if (!project) if (!project || project != m_project) {
m_project = nullptr;
return; return;
}
Target *target = project->activeTarget(); Target *target = project->activeTarget();
if (!target) if (!target)
@@ -204,7 +208,6 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
m_runnable = runnable; m_runnable = runnable;
m_runnable.executable = currentExecutable; m_runnable.executable = currentExecutable;
m_displayName = runConfig->displayName(); m_displayName = runConfig->displayName();
m_project = project;
if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy) if (runMode == TestRunMode::Debug || runMode == TestRunMode::DebugWithoutDeploy)
m_runConfig = new TestRunConfiguration(runConfig->target(), this); m_runConfig = new TestRunConfiguration(runConfig->target(), this);
break; break;
@@ -224,7 +227,6 @@ void TestConfiguration::completeTestInformation(TestRunMode runMode)
if (isLocal(rc)) { // FIXME for now only Desktop support if (isLocal(rc)) { // FIXME for now only Desktop support
const Runnable runnable = rc->runnable(); const Runnable runnable = rc->runnable();
m_runnable.environment = runnable.environment; m_runnable.environment = runnable.environment;
m_project = project;
m_guessedConfiguration = true; m_guessedConfiguration = true;
m_guessedFrom = rc->displayName(); m_guessedFrom = rc->displayName();
if (runMode == TestRunMode::Debug) if (runMode == TestRunMode::Debug)

View File

@@ -154,6 +154,7 @@ void TestRunner::scheduleNext()
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return); QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers()); QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers());
QTC_ASSERT(m_fakeFutureInterface, onFinished(); return); QTC_ASSERT(m_fakeFutureInterface, onFinished(); return);
QTC_ASSERT(!m_canceled, onFinished(); return);
m_currentConfig = m_selectedTests.dequeue(); m_currentConfig = m_selectedTests.dequeue();
@@ -215,9 +216,16 @@ void TestRunner::scheduleNext()
void TestRunner::cancelCurrent(TestRunner::CancelReason reason) void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
{ {
m_canceled = true;
if (reason == UserCanceled) { if (reason == UserCanceled) {
if (!m_fakeFutureInterface->isCanceled()) // depends on using the button / progress bar // when using the stop button we need to report, for progress bar this happens automatically
if (m_fakeFutureInterface && !m_fakeFutureInterface->isCanceled())
m_fakeFutureInterface->reportCanceled(); m_fakeFutureInterface->reportCanceled();
} else if (reason == KitChanged) {
if (m_fakeFutureInterface)
m_fakeFutureInterface->reportCanceled();
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
tr("Current kit has changed. Canceling test run."))));
} }
if (m_currentProcess && m_currentProcess->state() != QProcess::NotRunning) { if (m_currentProcess && m_currentProcess->state() != QProcess::NotRunning) {
m_currentProcess->kill(); m_currentProcess->kill();
@@ -231,6 +239,7 @@ void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
void TestRunner::onProcessFinished() void TestRunner::onProcessFinished()
{ {
if (m_currentConfig) {
m_fakeFutureInterface->setProgressValue(m_fakeFutureInterface->progressValue() m_fakeFutureInterface->setProgressValue(m_fakeFutureInterface->progressValue()
+ m_currentConfig->testCaseCount()); + m_currentConfig->testCaseCount());
if (!m_fakeFutureInterface->isCanceled()) { if (!m_fakeFutureInterface->isCanceled()) {
@@ -246,7 +255,7 @@ void TestRunner::onProcessFinished()
+ rcInfo(m_currentConfig)))); + rcInfo(m_currentConfig))));
} }
} }
}
resetInternalPointers(); resetInternalPointers();
if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled()) if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled())
@@ -277,6 +286,7 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
} }
m_executingTests = true; m_executingTests = true;
m_canceled = false;
emit testRunStarted(); emit testRunStarted();
// clear old log and output pane // clear old log and output pane
@@ -299,6 +309,9 @@ void TestRunner::prepareToRunTests(TestRunMode mode)
return; return;
} }
m_targetConnect = connect(project, &ProjectExplorer::Project::activeTargetChanged,
[this]() { cancelCurrent(KitChanged); });
if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy
|| mode == TestRunMode::RunWithoutDeploy) { || mode == TestRunMode::RunWithoutDeploy) {
runOrDebugTests(); runOrDebugTests();
@@ -384,9 +397,13 @@ int TestRunner::precheckTestConfigurations()
void TestRunner::runTests() void TestRunner::runTests()
{ {
QList<TestConfiguration *> toBeRemoved; QList<TestConfiguration *> toBeRemoved;
bool projectChanged = false;
for (TestConfiguration *config : m_selectedTests) { for (TestConfiguration *config : m_selectedTests) {
config->completeTestInformation(TestRunMode::Run); config->completeTestInformation(TestRunMode::Run);
if (!config->hasExecutable()) { if (!config->project()) {
projectChanged = true;
toBeRemoved.append(config);
} else if (!config->hasExecutable()) {
if (auto rc = getRunConfiguration(firstTestCaseTarget(config))) if (auto rc = getRunConfiguration(firstTestCaseTarget(config)))
config->setOriginalRunConfiguration(rc); config->setOriginalRunConfiguration(rc);
else else
@@ -398,8 +415,10 @@ void TestRunner::runTests()
qDeleteAll(toBeRemoved); qDeleteAll(toBeRemoved);
toBeRemoved.clear(); toBeRemoved.clear();
if (m_selectedTests.isEmpty()) { if (m_selectedTests.isEmpty()) {
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, QString mssg = projectChanged ? tr("Startup project has changed. Canceling test run.")
tr("No test cases left for execution. Canceling test run.")))); : tr("No test cases left for execution. Canceling test run.");
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn, mssg)));
onFinished(); onFinished();
return; return;
} }
@@ -452,6 +471,12 @@ void TestRunner::debugTests()
TestConfiguration *config = m_selectedTests.first(); TestConfiguration *config = m_selectedTests.first();
config->completeTestInformation(TestRunMode::Debug); config->completeTestInformation(TestRunMode::Debug);
if (!config->project()) {
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
TestRunner::tr("Startup project has changed. Canceling test run."))));
onFinished();
return;
}
if (!config->hasExecutable()) { if (!config->hasExecutable()) {
if (auto *rc = getRunConfiguration(firstTestCaseTarget(config))) if (auto *rc = getRunConfiguration(firstTestCaseTarget(config)))
config->completeTestInformation(rc, TestRunMode::Debug); config->completeTestInformation(rc, TestRunMode::Debug);
@@ -571,7 +596,10 @@ void TestRunner::buildFinished(bool success)
this, &TestRunner::buildFinished); this, &TestRunner::buildFinished);
if (success) { if (success) {
if (!m_canceled)
runOrDebugTests(); runOrDebugTests();
else if (m_executingTests)
onFinished();
} else { } else {
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal, emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
tr("Build failed. Canceling test run.")))); tr("Build failed. Canceling test run."))));
@@ -585,6 +613,7 @@ void TestRunner::onFinished()
qDeleteAll(m_selectedTests); qDeleteAll(m_selectedTests);
m_selectedTests.clear(); m_selectedTests.clear();
disconnect(m_targetConnect);
m_fakeFutureInterface = nullptr; m_fakeFutureInterface = nullptr;
m_executingTests = false; m_executingTests = false;
emit testRunFinished(); emit testRunFinished();

View File

@@ -54,7 +54,7 @@ class AUTOTESTSHARED_EXPORT TestRunner : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum CancelReason { UserCanceled, Timeout }; enum CancelReason { UserCanceled, Timeout, KitChanged };
static TestRunner* instance(); static TestRunner* instance();
~TestRunner(); ~TestRunner();
@@ -91,6 +91,7 @@ private:
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr; QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
QQueue<TestConfiguration *> m_selectedTests; QQueue<TestConfiguration *> m_selectedTests;
bool m_executingTests = false; bool m_executingTests = false;
bool m_canceled = false;
TestConfiguration *m_currentConfig = nullptr; TestConfiguration *m_currentConfig = nullptr;
QProcess *m_currentProcess = nullptr; QProcess *m_currentProcess = nullptr;
TestOutputReader *m_currentOutputReader = nullptr; TestOutputReader *m_currentOutputReader = nullptr;
@@ -98,6 +99,8 @@ private:
// temporarily used if building before running is necessary // temporarily used if building before running is necessary
QMetaObject::Connection m_buildConnect; QMetaObject::Connection m_buildConnect;
// temporarily used for handling of switching the current target
QMetaObject::Connection m_targetConnect;
}; };
class RunConfigurationSelectionDialog : public QDialog class RunConfigurationSelectionDialog : public QDialog

View File

@@ -1673,7 +1673,11 @@ void BinEditorWidget::setNewWindowRequestAllowed(bool c)
void BinEditorWidget::updateContents() void BinEditorWidget::updateContents()
{ {
m_oldData = m_data; m_oldData = m_data;
setSizes(baseAddress() + cursorPosition(), m_size, m_blockSize); m_data.clear();
m_modifiedData.clear();
m_requests.clear();
for (auto it = m_oldData.constBegin(), et = m_oldData.constEnd(); it != et; ++it)
d->fetchData(m_baseAddr + it.key());
} }
QPoint BinEditorWidget::offsetToPos(qint64 offset) const QPoint BinEditorWidget::offsetToPos(qint64 offset) const

View File

@@ -63,18 +63,6 @@ QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainforma
return extraSelection; return extraSelection;
} }
int positionInText(QTextDocument *textDocument,
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
{
auto textBlock = textDocument->findBlockByNumber(
static_cast<int>(sourceLocationContainer.line) - 1);
// 'sourceLocationContainer' already has the CppEditor column converted from
// the utf8 byte offset from the beginning of the line provided by clang.
// - 1 is required for 0-based columns.
const int column = static_cast<int>(sourceLocationContainer.column) - 1;
return textBlock.position() + column;
}
void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic, void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
QTextDocument *textDocument, QTextDocument *textDocument,
const QTextCharFormat &contextFormat, const QTextCharFormat &contextFormat,
@@ -82,8 +70,13 @@ void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
{ {
for (auto &&range : diagnostic.ranges) { for (auto &&range : diagnostic.ranges) {
QTextCursor cursor(textDocument); QTextCursor cursor(textDocument);
cursor.setPosition(positionInText(textDocument, range.start)); cursor.setPosition(::Utils::Text::positionInText(textDocument,
cursor.setPosition(positionInText(textDocument, range.end), QTextCursor::KeepAnchor); range.start.line,
range.start.column));
cursor.setPosition(::Utils::Text::positionInText(textDocument,
range.end.line,
range.end.column),
QTextCursor::KeepAnchor);
auto extraSelection = createExtraSelections(contextFormat, cursor); auto extraSelection = createExtraSelections(contextFormat, cursor);
@@ -127,11 +120,15 @@ QTextCursor createSelectionCursor(QTextDocument *textDocument,
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer) const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
{ {
QTextCursor cursor(textDocument); QTextCursor cursor(textDocument);
cursor.setPosition(positionInText(textDocument, sourceLocationContainer)); cursor.setPosition(::Utils::Text::positionInText(textDocument,
sourceLocationContainer.line,
sourceLocationContainer.column));
selectToLocationEnd(cursor); selectToLocationEnd(cursor);
if (!cursor.hasSelection()) { if (!cursor.hasSelection()) {
cursor.setPosition(positionInText(textDocument, sourceLocationContainer) - 1); cursor.setPosition(::Utils::Text::positionInText(textDocument,
sourceLocationContainer.line,
sourceLocationContainer.column) - 1);
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 2);
} }

View File

@@ -205,20 +205,16 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(
} }
namespace { namespace {
int positionInText(QTextDocument *textDocument,
const ClangBackEnd::SourceLocationContainer &sourceLocationContainer)
{
auto textBlock = textDocument->findBlockByNumber(int(sourceLocationContainer.line) - 1);
return textBlock.position() + int(sourceLocationContainer.column) - 1;
}
TextEditor::BlockRange TextEditor::BlockRange
toTextEditorBlock(QTextDocument *textDocument, toTextEditorBlock(QTextDocument *textDocument,
const ClangBackEnd::SourceRangeContainer &sourceRangeContainer) const ClangBackEnd::SourceRangeContainer &sourceRangeContainer)
{ {
return TextEditor::BlockRange(positionInText(textDocument, sourceRangeContainer.start), return TextEditor::BlockRange(::Utils::Text::positionInText(textDocument,
positionInText(textDocument, sourceRangeContainer.end)); sourceRangeContainer.start.line,
sourceRangeContainer.start.column),
::Utils::Text::positionInText(textDocument,
sourceRangeContainer.end.line,
sourceRangeContainer.end.column));
} }
QList<TextEditor::BlockRange> QList<TextEditor::BlockRange>

View File

@@ -251,7 +251,10 @@ ClangTidyClazyTool::ClangTidyClazyTool()
m_applyFixitsButton->setEnabled(false); m_applyFixitsButton->setEnabled(false);
connect(m_diagnosticModel, connect(m_diagnosticModel,
&ClangToolsDiagnosticModel::fixItsToApplyCountChanged, &ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
[this](int c) { m_applyFixitsButton->setEnabled(c); }); [this](int c) {
m_applyFixitsButton->setEnabled(c);
static_cast<DiagnosticView *>(m_diagnosticView)->setSelectedFixItsCount(c);
});
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() { connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
QVector<DiagnosticItem *> diagnosticItems; QVector<DiagnosticItem *> diagnosticItems;
m_diagnosticModel->rootItem()->forChildrenAtLevel(1, [&](TreeItem *item){ m_diagnosticModel->rootItem()->forChildrenAtLevel(1, [&](TreeItem *item){

View File

@@ -328,6 +328,9 @@ QVariant DiagnosticItem::data(int column, int role) const
bool DiagnosticItem::setData(int column, const QVariant &data, int role) bool DiagnosticItem::setData(int column, const QVariant &data, int role)
{ {
if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) { if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
if (m_fixitStatus != FixitStatus::Scheduled && m_fixitStatus != FixitStatus::NotScheduled)
return false;
const FixitStatus newStatus = data.value<Qt::CheckState>() == Qt::Checked const FixitStatus newStatus = data.value<Qt::CheckState>() == Qt::Checked
? FixitStatus::Scheduled ? FixitStatus::Scheduled
: FixitStatus::NotScheduled; : FixitStatus::NotScheduled;

View File

@@ -35,12 +35,60 @@
#include <QAction> #include <QAction>
#include <QDebug> #include <QDebug>
#include <QHeaderView> #include <QHeaderView>
#include <QPainter>
using namespace Debugger; using namespace Debugger;
namespace ClangTools { namespace ClangTools {
namespace Internal { namespace Internal {
class ClickableFixItHeader : public QHeaderView
{
Q_OBJECT
public:
ClickableFixItHeader(Qt::Orientation orientation, QWidget *parent = 0)
: QHeaderView(orientation, parent)
{
}
void setState(QFlags<QStyle::StateFlag> newState)
{
state = newState;
}
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == DiagnosticView::FixItColumn) {
QStyleOptionButton option;
const int side = sizeHint().height();
option.rect = QRect(rect.left() + 1, 1, side - 3, side - 3);
option.state = state;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);
}
}
void mousePressEvent(QMouseEvent *event)
{
if (event->localPos().x() > sectionPosition(DiagnosticView::FixItColumn)) {
state = (state != QStyle::State_On) ? QStyle::State_On : QStyle::State_Off;
viewport()->update();
emit fixItColumnClicked(state == QStyle::State_On);
}
QHeaderView::mousePressEvent(event);
}
signals:
void fixItColumnClicked(bool checked);
private:
QFlags<QStyle::StateFlag> state = QStyle::State_Off;
};
DiagnosticView::DiagnosticView(QWidget *parent) DiagnosticView::DiagnosticView(QWidget *parent)
: Debugger::DetailedErrorView(parent) : Debugger::DetailedErrorView(parent)
{ {
@@ -104,12 +152,36 @@ bool DiagnosticView::eventFilter(QObject *watched, QEvent *event)
} }
} }
void DiagnosticView::setSelectedFixItsCount(int fixItsCount)
{
if (m_ignoreSetSelectedFixItsCount)
return;
auto *clickableFixItHeader = static_cast<ClickableFixItHeader *>(header());
clickableFixItHeader->setState(fixItsCount
? (QStyle::State_NoChange | QStyle::State_On | QStyle::State_Off)
: QStyle::State_Off);
clickableFixItHeader->viewport()->update();
}
void DiagnosticView::setModel(QAbstractItemModel *model) void DiagnosticView::setModel(QAbstractItemModel *model)
{ {
Debugger::DetailedErrorView::setModel(model); Debugger::DetailedErrorView::setModel(model);
auto *clickableFixItHeader = new ClickableFixItHeader(Qt::Horizontal, this);
connect(clickableFixItHeader, &ClickableFixItHeader::fixItColumnClicked,
this, [=](bool checked) {
m_ignoreSetSelectedFixItsCount = true;
for (int row = 0; row < model->rowCount(); ++row) {
QModelIndex index = model->index(row, FixItColumn, QModelIndex());
model->setData(index, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
}
m_ignoreSetSelectedFixItsCount = false;
});
setHeader(clickableFixItHeader);
header()->setStretchLastSection(false); header()->setStretchLastSection(false);
header()->setSectionResizeMode(0, QHeaderView::Stretch); header()->setSectionResizeMode(0, QHeaderView::Stretch);
} }
} // namespace Internal } // namespace Internal
} // namespace ClangTools } // namespace ClangTools
#include "clangtoolsdiagnosticview.moc"

View File

@@ -41,6 +41,8 @@ public:
FixItColumn = LocationColumn + 1, FixItColumn = LocationColumn + 1,
}; };
void setSelectedFixItsCount(int fixItsCount);
private: private:
void suppressCurrentDiagnostic(); void suppressCurrentDiagnostic();
@@ -49,6 +51,7 @@ private:
void setModel(QAbstractItemModel *model) override; void setModel(QAbstractItemModel *model) override;
QAction *m_suppressAction; QAction *m_suppressAction;
bool m_ignoreSetSelectedFixItsCount = false;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -118,8 +118,11 @@ void ClangToolsSettings::readSettings()
m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool(); m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
m_savedDiagnosticConfigId = m_diagnosticConfigId m_diagnosticConfigId = Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
= Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey))); if (!m_diagnosticConfigId.isValid())
m_diagnosticConfigId = "Builtin.TidyAndClazy";
m_savedDiagnosticConfigId = m_diagnosticConfigId;
updateSavedBuildBeforeAnalysiIfRequired(); updateSavedBuildBeforeAnalysiIfRequired();

View File

@@ -113,6 +113,13 @@
\" </magic>\", \" </magic>\",
\" </mime-type>\", \" </mime-type>\",
\" <mime-type type=\'text/x-dsrc\'>\",
\" <comment>D source code</comment>\",
\" <sub-class-of type=\'text/plain\'/>\",
\" <glob pattern=\'*.d\'/>\",
\" <glob pattern=\'*.di\'/>\",
\" </mime-type>\",
\"</mime-info>\" \"</mime-info>\"
] ]
} }

View File

@@ -37,8 +37,9 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode
{ {
ClangDiagnosticConfig config; ClangDiagnosticConfig config;
config.setId("Builtin.Questionable"); config.setId("Builtin.Questionable");
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate(
"Warnings for questionable constructs")); "ClangDiagnosticConfigsModel",
"Clang-only checks for questionable constructs"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setClangOptions(QStringList{ config.setClangOptions(QStringList{
QStringLiteral("-Wall"), QStringLiteral("-Wall"),
@@ -53,19 +54,33 @@ static void addConfigForPedanticWarnings(ClangDiagnosticConfigsModel &model)
ClangDiagnosticConfig config; ClangDiagnosticConfig config;
config.setId("Builtin.Pedantic"); config.setId("Builtin.Pedantic");
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Pedantic Warnings")); "Clang-only pedantic checks"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")}); config.setClangOptions(QStringList{QStringLiteral("-Wpedantic")});
model.appendOrUpdate(config); model.appendOrUpdate(config);
} }
constexpr const char *DEFAULT_TIDY_CHECKS = "-*,"
"bugprone-*,"
"cppcoreguidelines-*,"
"misc-*,"
"modernize-*,"
"performance-*,"
"readability-*,"
"-cppcoreguidelines-owning-memory,"
"-readability-braces-around-statements,"
"-readability-implicit-bool-conversion,"
"-readability-named-parameter";
constexpr const char *DEFAULT_CLAZY_CHECKS = "level0";
static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model) static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
{ {
ClangDiagnosticConfig config; ClangDiagnosticConfig config;
config.setId(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS); config.setId(Constants::CPP_CLANG_BUILTIN_CONFIG_ID_EVERYTHING_WITH_EXCEPTIONS);
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate(
"Warnings for almost everything")); "ClangDiagnosticConfigsModel",
"Clang-only checks for almost everything"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setClangOptions(QStringList{ config.setClangOptions(QStringList{
QStringLiteral("-Weverything"), QStringLiteral("-Weverything"),
@@ -86,11 +101,75 @@ static void addConfigForAlmostEveryWarning(ClangDiagnosticConfigsModel &model)
model.appendOrUpdate(config); model.appendOrUpdate(config);
} }
static void addConfigForTidy(ClangDiagnosticConfigsModel &model)
{
ClangDiagnosticConfig config;
config.setId("Builtin.Tidy");
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Clang-Tidy thorough checks"));
config.setIsReadOnly(true);
config.setClangOptions(QStringList{QStringLiteral("-w")});
config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
config.setClangTidyChecks(QString::fromUtf8(DEFAULT_TIDY_CHECKS));
model.appendOrUpdate(config);
}
static void addConfigForClangAnalyze(ClangDiagnosticConfigsModel &model)
{
ClangDiagnosticConfig config;
config.setId("Builtin.TidyClangAnalyze");
config.setDisplayName(QCoreApplication::translate(
"ClangDiagnosticConfigsModel",
"Clang-Tidy static analyzer checks"));
config.setIsReadOnly(true);
config.setClangOptions(QStringList{
QStringLiteral("-w"),
});
config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
config.setClangTidyChecks("-*,clang-analyzer-*");
model.appendOrUpdate(config);
}
static void addConfigForClazy(ClangDiagnosticConfigsModel &model)
{
ClangDiagnosticConfig config;
config.setId("Builtin.Clazy");
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Clazy level0 checks"));
config.setIsReadOnly(true);
config.setClangOptions(QStringList{QStringLiteral("-w")});
config.setClazyChecks(QString::fromUtf8(DEFAULT_CLAZY_CHECKS));
model.appendOrUpdate(config);
}
static void addConfigForTidyAndClazy(ClangDiagnosticConfigsModel &model)
{
ClangDiagnosticConfig config;
config.setId("Builtin.TidyAndClazy");
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Clang-Tidy and Clazy preselected checks"));
config.setIsReadOnly(true);
config.setClangOptions(QStringList{QStringLiteral("-w")});
config.setClangTidyMode(ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
config.setClangTidyChecks(QString::fromUtf8(DEFAULT_TIDY_CHECKS));
config.setClazyChecks(QString::fromUtf8(DEFAULT_CLAZY_CHECKS));
model.appendOrUpdate(config);
}
static void addBuiltinConfigs(ClangDiagnosticConfigsModel &model) static void addBuiltinConfigs(ClangDiagnosticConfigsModel &model)
{ {
addConfigForPedanticWarnings(model); addConfigForPedanticWarnings(model);
addConfigForQuestionableConstructs(model); addConfigForQuestionableConstructs(model);
addConfigForAlmostEveryWarning(model); addConfigForAlmostEveryWarning(model);
addConfigForTidy(model);
addConfigForClangAnalyze(model);
addConfigForClazy(model);
addConfigForTidyAndClazy(model);
} }
ClangDiagnosticConfigsModel::ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs) ClangDiagnosticConfigsModel::ClangDiagnosticConfigsModel(const ClangDiagnosticConfigs &customConfigs)

View File

@@ -112,7 +112,7 @@ public:
const QModelIndex index = indexForCheck(check); const QModelIndex index = indexForCheck(check);
if (!index.isValid()) if (!index.isValid())
continue; continue;
auto node = static_cast<ProjectExplorer::Tree *>(index.internalPointer()); auto *node = static_cast<ProjectExplorer::Tree *>(index.internalPointer());
node->checked = state; node->checked = state;
propagateUp(index); propagateUp(index);
propagateDown(index); propagateDown(index);
@@ -161,6 +161,18 @@ public:
return ProjectExplorer::SelectableFilesModel::data(index, role); return ProjectExplorer::SelectableFilesModel::data(index, role);
} }
void setEnabled(bool enabled)
{
m_enabled = enabled;
}
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override
{
if (role == Qt::CheckStateRole && !m_enabled)
return false;
return ProjectExplorer::SelectableFilesModel::setData(index, value, role);
}
private: private:
// TODO: Remove/replace this method after base class refactoring is done. // TODO: Remove/replace this method after base class refactoring is done.
@@ -220,6 +232,8 @@ private:
for (const ProjectExplorer::Tree *t : root->childDirectories) for (const ProjectExplorer::Tree *t : root->childDirectories)
collectChecks(t, checks); collectChecks(t, checks);
} }
bool m_enabled = true;
}; };
ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(const Core::Id &configToSelect, ClangDiagnosticConfigsWidget::ClangDiagnosticConfigsWidget(const Core::Id &configToSelect,
@@ -489,7 +503,11 @@ void ClangDiagnosticConfigsWidget::syncClangTidyWidgets(const ClangDiagnosticCon
break; break;
} }
m_tidyChecksWidget->setEnabled(!config.isReadOnly()); const bool enabled = !config.isReadOnly();
m_tidyChecks->tidyMode->setEnabled(enabled);
m_tidyChecks->plainTextEditButton->setText(enabled ? tr("Edit Checks as String...")
: tr("View Checks as String..."));
m_tidyTreeModel->setEnabled(enabled);
connectClangTidyItemChanged(); connectClangTidyItemChanged();
} }
@@ -650,12 +668,17 @@ void ClangDiagnosticConfigsWidget::setupTabs()
m_tidyChecks->checksPrefixesTree->header()->setStretchLastSection(false); m_tidyChecks->checksPrefixesTree->header()->setStretchLastSection(false);
m_tidyChecks->checksPrefixesTree->header()->setSectionResizeMode(0, QHeaderView::Stretch); m_tidyChecks->checksPrefixesTree->header()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this]() { connect(m_tidyChecks->plainTextEditButton, &QPushButton::clicked, this, [this]() {
const bool readOnly = selectedConfig().isReadOnly();
QDialog dialog; QDialog dialog;
dialog.setWindowTitle(tr("Checks")); dialog.setWindowTitle(tr("Checks"));
dialog.setLayout(new QVBoxLayout); dialog.setLayout(new QVBoxLayout);
auto *textEdit = new QTextEdit(&dialog); auto *textEdit = new QTextEdit(&dialog);
textEdit->setReadOnly(readOnly);
dialog.layout()->addWidget(textEdit); dialog.layout()->addWidget(textEdit);
auto *buttonsBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); auto *buttonsBox = new QDialogButtonBox(QDialogButtonBox::Ok
| (readOnly ? QDialogButtonBox::NoButton
: QDialogButtonBox::Cancel));
dialog.layout()->addWidget(buttonsBox); dialog.layout()->addWidget(buttonsBox);
QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); QObject::connect(buttonsBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); QObject::connect(buttonsBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);

View File

@@ -487,10 +487,6 @@ QString CompilerOptionsBuilder::includeOption() const
bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro &macro) const bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro &macro) const
{ {
// TODO: Remove in QtCreator 4.7
if (macro.key == "__cplusplus")
return true;
// Ignore for all compiler toolchains since LLVM has it's own implementation for // Ignore for all compiler toolchains since LLVM has it's own implementation for
// __has_include(STR) and __has_include_next(STR) // __has_include(STR) and __has_include_next(STR)
if (macro.key.startsWith("__has_include")) if (macro.key.startsWith("__has_include"))

View File

@@ -193,7 +193,7 @@ bool isDebuggerWinException(unsigned long code)
return code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP; return code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP;
} }
bool isFatalWinException(long code) bool isFatalWinException(unsigned long code)
{ {
switch (code) { switch (code) {
case EXCEPTION_BREAKPOINT: case EXCEPTION_BREAKPOINT:
@@ -217,7 +217,7 @@ bool winResumeThread(unsigned long, QString *) { return false; }
bool isWinProcessBeingDebugged(unsigned long) { return false; } bool isWinProcessBeingDebugged(unsigned long) { return false; }
void formatWindowsException(unsigned long , quint64, unsigned long, void formatWindowsException(unsigned long , quint64, unsigned long,
quint64, quint64, QTextStream &) { } quint64, quint64, QTextStream &) { }
bool isFatalWinException(long) { return false; } bool isFatalWinException(unsigned long) { return false; }
bool isDebuggerWinException(unsigned long) { return false; } bool isDebuggerWinException(unsigned long) { return false; }
#endif // !Q_OS_WIN #endif // !Q_OS_WIN

View File

@@ -40,7 +40,7 @@ bool winResumeThread(unsigned long dwThreadId, QString *errorMessage);
bool isWinProcessBeingDebugged(unsigned long pid); bool isWinProcessBeingDebugged(unsigned long pid);
// Special exception codes. // Special exception codes.
enum enum : unsigned long
{ {
winExceptionCppException = 0xe06d7363, winExceptionCppException = 0xe06d7363,
winExceptionSetThreadName = 0x406d1388, winExceptionSetThreadName = 0x406d1388,
@@ -60,7 +60,7 @@ void formatWindowsException(unsigned long code, quint64 address,
unsigned long flags, quint64 info1, quint64 info2, unsigned long flags, quint64 info1, quint64 info2,
QTextStream &str); QTextStream &str);
// Check for access violation, etc. // Check for access violation, etc.
bool isFatalWinException(long code); bool isFatalWinException(unsigned long code);
// Check for EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP // Check for EXCEPTION_BREAKPOINT, EXCEPTION_SINGLE_STEP
bool isDebuggerWinException(unsigned long code); bool isDebuggerWinException(unsigned long code);

View File

@@ -216,6 +216,23 @@ void GerritDialog::refresh()
m_ui->treeView->sortByColumn(-1); m_ui->treeView->sortByColumn(-1);
} }
void GerritDialog::scheduleUpdateRemotes()
{
if (isVisible())
updateRemotes();
else
m_shouldUpdateRemotes = true;
}
void GerritDialog::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
if (m_shouldUpdateRemotes) {
m_shouldUpdateRemotes = false;
updateRemotes();
}
}
void GerritDialog::remoteChanged() void GerritDialog::remoteChanged()
{ {
const GerritServer server = m_ui->remoteComboBox->currentServer(); const GerritServer server = m_ui->remoteComboBox->currentServer();

View File

@@ -62,6 +62,7 @@ public:
void fetchStarted(const QSharedPointer<Gerrit::Internal::GerritChange> &change); void fetchStarted(const QSharedPointer<Gerrit::Internal::GerritChange> &change);
void fetchFinished(); void fetchFinished();
void refresh(); void refresh();
void scheduleUpdateRemotes();
signals: signals:
void fetchDisplay(const QSharedPointer<Gerrit::Internal::GerritChange> &); void fetchDisplay(const QSharedPointer<Gerrit::Internal::GerritChange> &);
@@ -77,6 +78,7 @@ private:
void slotFetchCheckout(); void slotFetchCheckout();
void remoteChanged(); void remoteChanged();
void updateRemotes(bool forceReload = false); void updateRemotes(bool forceReload = false);
void showEvent(QShowEvent *event) override;
void manageProgressIndicator(); void manageProgressIndicator();
@@ -101,6 +103,7 @@ private:
QString m_repository; QString m_repository;
bool m_fetchRunning = false; bool m_fetchRunning = false;
bool m_updatingRemotes = false; bool m_updatingRemotes = false;
bool m_shouldUpdateRemotes = false;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -72,6 +72,7 @@ void GerritOptionsPage::apply()
newParameters.setPortFlagBySshType(); newParameters.setPortFlagBySshType();
*m_parameters = newParameters; *m_parameters = newParameters;
m_parameters->toSettings(Core::ICore::settings()); m_parameters->toSettings(Core::ICore::settings());
emit settingsChanged();
} }
} }
} }

View File

@@ -73,6 +73,9 @@ public:
void apply() override; void apply() override;
void finish() override; void finish() override;
signals:
void settingsChanged();
private: private:
const QSharedPointer<GerritParameters> &m_parameters; const QSharedPointer<GerritParameters> &m_parameters;
QPointer<GerritOptionsWidget> m_widget; QPointer<GerritOptionsWidget> m_widget;

View File

@@ -292,7 +292,12 @@ bool GerritPlugin::initialize(ActionContainer *ac)
connect(pushAction, &QAction::triggered, this, [this]() { push(); }); connect(pushAction, &QAction::triggered, this, [this]() { push(); });
ac->addAction(m_pushToGerritCommand); ac->addAction(m_pushToGerritCommand);
new GerritOptionsPage(m_parameters, this); auto options = new GerritOptionsPage(m_parameters, this);
connect(options, &GerritOptionsPage::settingsChanged,
this, [this] {
if (m_dialog)
m_dialog->scheduleUpdateRemotes();
});
return true; return true;
} }
@@ -340,7 +345,7 @@ void GerritPlugin::openView()
{ {
if (m_dialog.isNull()) { if (m_dialog.isNull()) {
while (!m_parameters->isValid()) { while (!m_parameters->isValid()) {
Core::AsynchronousMessageBox::warning(tr("Error"), QMessageBox::warning(Core::ICore::dialogParent(), tr("Error"),
tr("Invalid Gerrit configuration. Host, user and ssh binary are mandatory.")); tr("Invalid Gerrit configuration. Host, user and ssh binary are mandatory."));
if (!ICore::showOptionsDialog("Gerrit")) if (!ICore::showOptionsDialog("Gerrit"))
return; return;

View File

@@ -323,6 +323,7 @@ bool GerritServer::resolveRoot()
} }
break; break;
default: // unknown error - fail default: // unknown error - fail
authenticated = false;
return false; return false;
} }
} }

View File

@@ -1069,7 +1069,6 @@ bool GitPlugin::submitEditorAboutToClose()
// Go ahead! // Go ahead!
SubmitFileModel *model = qobject_cast<SubmitFileModel *>(editor->fileModel()); SubmitFileModel *model = qobject_cast<SubmitFileModel *>(editor->fileModel());
bool closeEditor = true;
CommitType commitType = editor->commitType(); CommitType commitType = editor->commitType();
QString amendSHA1 = editor->amendSHA1(); QString amendSHA1 = editor->amendSHA1();
if (model->hasCheckedFiles() || !amendSHA1.isEmpty()) { if (model->hasCheckedFiles() || !amendSHA1.isEmpty()) {
@@ -1077,12 +1076,12 @@ bool GitPlugin::submitEditorAboutToClose()
if (!DocumentManager::saveDocument(editorDocument)) if (!DocumentManager::saveDocument(editorDocument))
return false; return false;
closeEditor = m_gitClient->addAndCommit(m_submitRepository, editor->panelData(), if (!m_gitClient->addAndCommit(m_submitRepository, editor->panelData(), commitType,
commitType, amendSHA1, amendSHA1, m_commitMessageFileName, model)) {
m_commitMessageFileName, model); editor->updateFileModel();
}
if (!closeEditor)
return false; return false;
}
}
cleanCommitMessageFile(); cleanCommitMessageFile();
if (commitType == FixupCommit) { if (commitType == FixupCommit) {
if (!m_gitClient->beginStashScope(m_submitRepository, "Rebase-fixup", if (!m_gitClient->beginStashScope(m_submitRepository, "Rebase-fixup",

View File

@@ -62,10 +62,10 @@ public:
GitSubmitEditorPanelData panelData() const; GitSubmitEditorPanelData panelData() const;
CommitType commitType() const { return m_commitType; } CommitType commitType() const { return m_commitType; }
QString amendSHA1() const; QString amendSHA1() const;
void updateFileModel() override;
protected: protected:
QByteArray fileContents() const override; QByteArray fileContents() const override;
void updateFileModel() override;
void forceUpdateFileModel(); void forceUpdateFileModel();
private: private:

View File

@@ -28,6 +28,7 @@
#include "buildconfiguration.h" #include "buildconfiguration.h"
#include "buildstep.h" #include "buildstep.h"
#include "project.h" #include "project.h"
#include "target.h"
#include "task.h" #include "task.h"
#include <coreplugin/reaper.h> #include <coreplugin/reaper.h>
@@ -306,7 +307,10 @@ void AbstractProcessStep::processReadyReadStdOutput()
if (!m_process) if (!m_process)
return; return;
m_process->setReadChannel(QProcess::StandardOutput); m_process->setReadChannel(QProcess::StandardOutput);
const bool utf8Output = buildConfiguration()->environment().hasKey("VSLANG"); BuildConfiguration *bc = buildConfiguration();
if (!bc)
bc = target()->activeBuildConfiguration();
const bool utf8Output = bc && bc->environment().hasKey("VSLANG");
while (m_process->canReadLine()) { while (m_process->canReadLine()) {
QString line = utf8Output ? QString::fromUtf8(m_process->readLine()) QString line = utf8Output ? QString::fromUtf8(m_process->readLine())

View File

@@ -162,20 +162,15 @@ Kit::Kit(const QVariantMap &data) :
QVariantMap extra = data.value(QLatin1String(DATA_KEY)).toMap(); QVariantMap extra = data.value(QLatin1String(DATA_KEY)).toMap();
d->m_data.clear(); // remove default values d->m_data.clear(); // remove default values
const QVariantMap::ConstIterator cend = extra.constEnd(); const QVariantMap::ConstIterator cend = extra.constEnd();
for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it) { for (QVariantMap::ConstIterator it = extra.constBegin(); it != cend; ++it)
const QString key = it.key(); d->m_data.insert(Id::fromString(it.key()), it.value());
if (!key.isEmpty())
d->m_data.insert(Id::fromString(key), it.value());
}
QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList(); QStringList mutableInfoList = data.value(QLatin1String(MUTABLE_INFO_KEY)).toStringList();
foreach (const QString &mutableInfo, mutableInfoList) foreach (const QString &mutableInfo, mutableInfoList)
if (!mutableInfo.isEmpty())
d->m_mutable.insert(Id::fromString(mutableInfo)); d->m_mutable.insert(Id::fromString(mutableInfo));
QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList(); QStringList stickyInfoList = data.value(QLatin1String(STICKY_INFO_KEY)).toStringList();
foreach (const QString &stickyInfo, stickyInfoList) foreach (const QString &stickyInfo, stickyInfoList)
if (!stickyInfo.isEmpty())
d->m_sticky.insert(Id::fromString(stickyInfo)); d->m_sticky.insert(Id::fromString(stickyInfo));
} }

View File

@@ -368,18 +368,21 @@ public:
const QStyleOptionViewItem &option, const QModelIndex &idx) final const QStyleOptionViewItem &option, const QModelIndex &idx) final
{ {
if (ev->type() == QEvent::MouseButtonRelease) { if (ev->type() == QEvent::MouseButtonRelease) {
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(ev);
const Qt::MouseButtons button = mouseEvent->button();
const QPoint pos = static_cast<QMouseEvent *>(ev)->pos(); const QPoint pos = static_cast<QMouseEvent *>(ev)->pos();
const QRect rc(option.rect.right() - 24, option.rect.top(), 24, SESSION_LINE_HEIGHT); const QRect rc(option.rect.right() - 24, option.rect.top(), 24, SESSION_LINE_HEIGHT);
const QString sessionName = idx.data(Qt::DisplayRole).toString(); const QString sessionName = idx.data(Qt::DisplayRole).toString();
if (rc.contains(pos)) { if (rc.contains(pos) || button == Qt::RightButton) {
// The expand/collapse "button". // The expand/collapse "button".
if (m_expandedSessions.contains(sessionName)) if (m_expandedSessions.contains(sessionName))
m_expandedSessions.removeOne(sessionName); m_expandedSessions.removeOne(sessionName);
else else
m_expandedSessions.append(sessionName); m_expandedSessions.append(sessionName);
model->layoutChanged({QPersistentModelIndex(idx)}); model->layoutChanged({QPersistentModelIndex(idx)});
return false; return true;
} }
if (button == Qt::LeftButton) {
// One of the action links? // One of the action links?
const auto sessionModel = qobject_cast<SessionModel *>(model); const auto sessionModel = qobject_cast<SessionModel *>(model);
QTC_ASSERT(sessionModel, return false); QTC_ASSERT(sessionModel, return false);
@@ -393,6 +396,7 @@ public:
sessionModel->deleteSession(sessionName); sessionModel->deleteSession(sessionName);
return true; return true;
} }
}
if (ev->type() == QEvent::MouseMove) { if (ev->type() == QEvent::MouseMove) {
model->layoutChanged({QPersistentModelIndex(idx)}); // Somewhat brutish. model->layoutChanged({QPersistentModelIndex(idx)}); // Somewhat brutish.
//update(option.rect); //update(option.rect);
@@ -473,10 +477,14 @@ public:
const QStyleOptionViewItem &, const QModelIndex &idx) final const QStyleOptionViewItem &, const QModelIndex &idx) final
{ {
if (ev->type() == QEvent::MouseButtonRelease) { if (ev->type() == QEvent::MouseButtonRelease) {
QString projectFile = idx.data(ProjectModel::FilePathRole).toString(); const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(ev);
const Qt::MouseButtons button = mouseEvent->button();
if (button == Qt::LeftButton) {
const QString projectFile = idx.data(ProjectModel::FilePathRole).toString();
ProjectExplorerPlugin::openProjectWelcomePage(projectFile); ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
return true; return true;
} }
}
return false; return false;
} }
}; };

View File

@@ -72,6 +72,13 @@ private:
QPushButton * const m_changeButton; QPushButton * const m_changeButton;
}; };
QbsKitInformation::QbsKitInformation()
{
setObjectName(QLatin1String("QbsKitInformation"));
setId(QbsKitInformation::id());
setPriority(22000);
}
QString QbsKitInformation::displayName() QString QbsKitInformation::displayName()
{ {
return tr("Additional Qbs Profile Settings"); return tr("Additional Qbs Profile Settings");

View File

@@ -35,6 +35,8 @@ class QbsKitInformation final : public ProjectExplorer::KitInformation
Q_OBJECT Q_OBJECT
public: public:
QbsKitInformation();
static QString displayName(); static QString displayName();
static QString representation(const ProjectExplorer::Kit *kit); static QString representation(const ProjectExplorer::Kit *kit);
static QVariantMap properties(const ProjectExplorer::Kit *kit); static QVariantMap properties(const ProjectExplorer::Kit *kit);

View File

@@ -37,6 +37,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QFutureWatcher>
using namespace Utils; using namespace Utils;
@@ -55,6 +56,9 @@ QbsProjectParser::QbsProjectParser(QbsProject *project, QFutureInterface<bool> *
{ {
m_project = project->qbsProject(); m_project = project->qbsProject();
m_projectFilePath = project->projectFilePath().toString(); m_projectFilePath = project->projectFilePath().toString();
auto * const watcher = new QFutureWatcher<bool>(this);
connect(watcher, &QFutureWatcher<bool>::canceled, this, &QbsProjectParser::cancel);
watcher->setFuture(fi->future());
} }
QbsProjectParser::~QbsProjectParser() QbsProjectParser::~QbsProjectParser()

View File

@@ -78,7 +78,8 @@ GuiAppWizard::GuiAppWizard()
"Includes a Qt Designer-based main window.\n\n" "Includes a Qt Designer-based main window.\n\n"
"Preselects a desktop Qt for building the application if available.")); "Preselects a desktop Qt for building the application if available."));
setIcon(QIcon(QLatin1String(":/wizards/images/gui.png"))); setIcon(QIcon(QLatin1String(":/wizards/images/gui.png")));
setRequiredFeatures({QtSupport::Constants::FEATURE_QWIDGETS}); auto qt5 = Core::Id::fromString(QString(QtSupport::Constants::FEATURE_QT_PREFIX).append(".5"));
setRequiredFeatures({QtSupport::Constants::FEATURE_QWIDGETS, qt5});
} }
Core::BaseFileWizard *GuiAppWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) const Core::BaseFileWizard *GuiAppWizard::create(QWidget *parent, const Core::WizardDialogParameters &parameters) const
@@ -187,6 +188,7 @@ Core::GeneratedFiles GuiAppWizard::generateFiles(const QWizard *w,
QTextStream proStr(&contents); QTextStream proStr(&contents);
QtProjectParameters::writeProFileHeader(proStr); QtProjectParameters::writeProFileHeader(proStr);
projectParams.writeProFile(proStr); projectParams.writeProFile(proStr);
proStr << "\nCONFIG += c++11"; // ensure all Qt5 versions can handle the source
proStr << "\n\nSOURCES +=" proStr << "\n\nSOURCES +="
<< " \\\n " << Utils::FileName::fromString(mainSourceFileName).fileName() << " \\\n " << Utils::FileName::fromString(mainSourceFileName).fileName()
<< " \\\n " << Utils::FileName::fromString(formSource.path()).fileName() << " \\\n " << Utils::FileName::fromString(formSource.path()).fileName()

View File

@@ -84,6 +84,7 @@ QtProjectParameters GuiAppWizardDialog::projectParameters() const
rc.path = path(); rc.path = path();
rc.selectedModules = selectedModulesList(); rc.selectedModules = selectedModulesList();
rc.deselectedModules = deselectedModulesList(); rc.deselectedModules = deselectedModulesList();
rc.qtVersionSupport = QtProjectParameters::SupportQt5Only;
return rc; return rc;
} }

View File

@@ -42,9 +42,8 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
RangeType rangeType = MaximumRangeType; RangeType rangeType = MaximumRangeType;
if (!stream.atEnd()) { if (!stream.atEnd()) {
stream >> subtype; stream >> subtype;
if (subtype >= 0 && subtype < MaximumRangeType)
rangeType = static_cast<RangeType>(subtype); rangeType = static_cast<RangeType>(subtype);
if (rangeType < 0 || rangeType > MaximumRangeType)
rangeType = MaximumRangeType;
} else { } else {
subtype = -1; subtype = -1;
} }

View File

@@ -687,7 +687,7 @@ public:
QRegExp m_searchExpr; QRegExp m_searchExpr;
FindFlags m_findFlags; FindFlags m_findFlags;
void highlightSearchResults(const QTextBlock &block, TextEditorOverlay *overlay) const; void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const;
QTimer m_delayedUpdateTimer; QTimer m_delayedUpdateTimer;
void setExtraSelections(Core::Id kind, const QList<QTextEdit::ExtraSelection> &selections); void setExtraSelections(Core::Id kind, const QList<QTextEdit::ExtraSelection> &selections);
@@ -3657,8 +3657,7 @@ QTextBlock TextEditorWidgetPrivate::foldedBlockAt(const QPoint &pos, QRect *box)
return QTextBlock(); return QTextBlock();
} }
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const
TextEditorOverlay *overlay) const
{ {
if (m_searchExpr.isEmpty()) if (m_searchExpr.isEmpty())
return; return;
@@ -3671,6 +3670,13 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
int idx = -1; int idx = -1;
int l = 1; int l = 1;
const int left = data.viewportRect.left() - int(data.offset.x());
const int right = data.viewportRect.right() - int(data.offset.x());
const int top = data.viewportRect.top() - int(data.offset.y());
const int bottom = data.viewportRect.bottom() - int(data.offset.y());
const QColor &searchResultColor = m_document->fontSettings()
.toTextCharFormat(C_SEARCH_RESULT).background().color().darker(120);
while (idx < text.length()) { while (idx < text.length()) {
idx = m_searchExpr.indexIn(text, idx + l); idx = m_searchExpr.indexIn(text, idx + l);
if (idx < 0) if (idx < 0)
@@ -3683,19 +3689,44 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block,
|| (idx + l < text.length() && text.at(idx + l).isLetterOrNumber()))) || (idx + l < text.length() && text.at(idx + l).isLetterOrNumber())))
continue; continue;
if (!q->inFindScope(blockPosition + idx, blockPosition + idx + l)) const int start = blockPosition + idx;
const int end = start + l;
if (!q->inFindScope(start, end))
continue; continue;
const QTextCharFormat &searchResultFormat // check if the result is inside the visibale area for long blocks
= m_document->fontSettings().toTextCharFormat(C_SEARCH_RESULT); const QTextLine &startLine = block.layout()->lineForTextPosition(idx);
overlay->addOverlaySelection(blockPosition + idx, const QTextLine &endLine = block.layout()->lineForTextPosition(idx + l);
blockPosition + idx + l,
searchResultFormat.background().color().darker(120),
QColor(),
(idx == cursor.selectionStart() - blockPosition
&& idx + l == cursor.selectionEnd() - blockPosition)?
TextEditorOverlay::DropShadow : 0);
if (startLine.isValid() && endLine.isValid()
&& startLine.lineNumber() == endLine.lineNumber()) {
const int lineY = int(endLine.y() + q->blockBoundingGeometry(block).y());
if (startLine.cursorToX(idx) > right) { // result is behind the visible area
if (endLine.lineNumber() >= block.lineCount() - 1)
break; // this is the last line in the block, nothing more to add
// skip to the start of the next line
idx = block.layout()->lineAt(endLine.lineNumber() + 1).textStart();
l = 0;
continue;
} else if (endLine.cursorToX(idx + l, QTextLine::Trailing) < left) { // result is in front of the visible area skip it
continue;
} else if (lineY + endLine.height() < top) {
if (endLine.lineNumber() >= block.lineCount() - 1)
break; // this is the last line in the block, nothing more to add
// before visible area, skip to the start of the next line
idx = block.layout()->lineAt(endLine.lineNumber() + 1).textStart();
l = 0;
continue;
} else if (lineY > bottom) {
break; // under the visible area, nothing more to add
}
}
const uint flag = (idx == cursor.selectionStart() - blockPosition
&& idx + l == cursor.selectionEnd() - blockPosition) ?
TextEditorOverlay::DropShadow : 0;
m_searchResultOverlay->addOverlaySelection(start, end, searchResultColor, QColor(), flag);
} }
} }
@@ -4256,7 +4287,7 @@ void TextEditorWidgetPrivate::paintSearchResultOverlay(const PaintEventData &dat
if (blockBoundingRect.bottom() >= data.eventRect.top() - margin if (blockBoundingRect.bottom() >= data.eventRect.top() - margin
&& blockBoundingRect.top() <= data.eventRect.bottom() + margin) { && blockBoundingRect.top() <= data.eventRect.bottom() + margin) {
highlightSearchResults(block, m_searchResultOverlay); highlightSearchResults(block, data);
} }
offset.ry() += blockBoundingRect.height(); offset.ry() += blockBoundingRect.height();

View File

@@ -142,7 +142,12 @@ FollowSymbolResult FollowSymbol::followSymbol(CXTranslationUnit tu,
CXFile file = clang_getIncludedFile(cursors[tokenIndex]); CXFile file = clang_getIncludedFile(cursors[tokenIndex]);
const ClangString filename(clang_getFileName(file)); const ClangString filename(clang_getFileName(file));
const SourceLocation loc(tu, filename, 1, 1); const SourceLocation loc(tu, filename, 1, 1);
return SourceRangeContainer(SourceRange(loc, loc)); FollowSymbolResult result;
result.range = SourceRangeContainer(SourceRange(loc, loc));
// CLANG-UPGRADE-CHECK: Remove if we don't use empty generated ui_* headers anymore.
if (Utf8String(filename).contains("ui_"))
result.isResultOnlyForFallBack = true;
return result;
} }
// For definitions we can always find a declaration in current TU // For definitions we can always find a declaration in current TU

View File

@@ -85,7 +85,7 @@ def prepareBuildSettings(targetCount, currentTarget, setReleaseBuild=True, disab
def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings): def switchToBuildOrRunSettingsFor(targetCount, currentTarget, projectSettings):
def kitIsActivated(kit): def kitIsActivated(kit):
return not (str(kit.toolTip).startswith("<h3>Click to activate:</h3>") return not (str(kit.toolTip).startswith("<h3>Click to activate:</h3>")
or str(kit.toolTip).startswith("<h3>Kit is unsuited for Project</h3>")) or str(kit.toolTip).startswith("<h3>Kit is unsuited for project</h3>"))
try: try:
treeView = waitForObject(":Projects.ProjectNavigationTreeView") treeView = waitForObject(":Projects.ProjectNavigationTreeView")

View File

@@ -104,7 +104,6 @@ def renameFile(projectDir, proFile, branch, oldname, newname):
menu = ":Qt Creator.Project.Menu.File_QMenu" menu = ":Qt Creator.Project.Menu.File_QMenu"
activateItem(waitForObjectItem(menu, "Rename...")) activateItem(waitForObjectItem(menu, "Rename..."))
replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit") replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit")
if not (oldname.lower().endswith(".qrc") and JIRA.isBugStillOpen(20057)):
test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0], test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0],
"Only the filename without the extension is selected?") "Only the filename without the extension is selected?")
replaceEditorContent(replaceEdit, newname) replaceEditorContent(replaceEdit, newname)