Merge remote-tracking branch 'origin/3.6'

Conflicts:
	src/plugins/coreplugin/editormanager/editormanager.cpp

Change-Id: Ibdf433b54e36e58182b7094f78d47ed3e8c81684
This commit is contained in:
Eike Ziller
2015-11-12 13:43:08 +01:00
181 changed files with 13518 additions and 2106 deletions

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
Image {
source: "Bluebubble.svg"
smooth: true
property real centerX
property real centerY
property real bubbleCenter
}

View File

@@ -0,0 +1,68 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
Item {
id: id
width: 640
height: 480
property alias bubble: bubble
property alias mainWindow: mainWindow
Rectangle {
id: mainWindow
color: "#ffffff"
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
anchors.fill: parent
}
Bubble {
id: bubble
x: 10
y: 18
}
}

View File

@@ -1,6 +1,8 @@
TEMPLATE = app TEMPLATE = app
QT += qml quick widgets QT += qml quick sensors svg xml
CONFIG += c++11
SOURCES += main.cpp SOURCES += main.cpp
@@ -11,4 +13,3 @@ QML_IMPORT_PATH =
# Default rules for deployment. # Default rules for deployment.
include(deployment.pri) include(deployment.pri)

View File

@@ -0,0 +1,52 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}

View File

@@ -1,10 +1,11 @@
/************************************************************************** /****************************************************************************
** **
** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing ** Contact: http://www.qt.io/licensing/
** **
** This file is part of Qt Creator ** This file is part of the examples of the Qt Toolkit.
** **
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows: ** You may use this file under the terms of the BSD license as follows:
** **
** "Redistribution and use in source and binary forms, with or without ** "Redistribution and use in source and binary forms, with or without
@@ -16,10 +17,10 @@
** notice, this list of conditions and the following disclaimer in ** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the ** the documentation and/or other materials provided with the
** distribution. ** distribution.
** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor ** * Neither the name of The Qt Company Ltd nor the names of its
** the names of its contributors may be used to endorse or promote ** contributors may be used to endorse or promote products derived
** products derived from this software without specific prior written ** from this software without specific prior written permission.
** permission. **
** **
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -33,90 +34,80 @@
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
** **
**************************************************************************/ ** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.5 import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtSensors 5.0 import QtSensors 5.5
ApplicationWindow { ApplicationWindow {
title: qsTr("Accelerate Bubble")
id: mainWindow id: mainWindow
visible: true
width: 640 width: 640
height: 480 height: 480
visible: true title: qsTr("Accelerate Bubble")
menuBar: MenuBar { MainForm {
Menu { anchors.fill: parent
title: qsTr("File") bubble {
MenuItem { id: bubble
text: qsTr("&Open") centerX: mainWindow.width / 2
onTriggered: console.log("Open action triggered"); centerY: mainWindow.height / 2
} bubbleCenter: bubble.width / 2
MenuItem { x: bubble.centerX - bubble.bubbleCenter
text: qsTr("Exit") y: bubble.centerY - bubble.bubbleCenter
onTriggered: Qt.quit();
}
}
}
Image { Behavior on y {
id: bubble SmoothedAnimation {
source: "Bluebubble.svg" easing.type: Easing.Linear
smooth: true duration: 100
property real centerX: mainWindow.width / 2
property real centerY: mainWindow.height / 2
property real bubbleCenter: bubble.width / 2
x: centerX - bubbleCenter
y: centerY - bubbleCenter
Behavior on y {
SmoothedAnimation {
easing.type: Easing.Linear
duration: 100
} }
} }
Behavior on x { Behavior on x {
SmoothedAnimation { SmoothedAnimation {
easing.type: Easing.Linear easing.type: Easing.Linear
duration: 100 duration: 100
} }
} }
}
Accelerometer {
id: accel
dataRate: 100
active:true
onReadingChanged: {
var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
if (isNaN(newX) || isNaN(newY))
return;
if (newX < 0)
newX = 0
if (newX > mainWindow.width - bubble.width)
newX = mainWindow.width - bubble.width
if (newY < 18)
newY = 18
if (newY > mainWindow.height - bubble.height)
newY = mainWindow.height - bubble.height
bubble.x = newX
bubble.y = newY
} }
} }
function calcPitch(x, y, z) { Accelerometer {
return -(Math.atan(y / Math.sqrt(x * x + z * z)) * 57.2957795); id: accel
} dataRate: 100
function calcRoll(x, y, z) { active: true
return -(Math.atan(x / Math.sqrt(y * y + z * z)) * 57.2957795);
} onReadingChanged: {
var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
if (isNaN(newX) || isNaN(newY))
return;
if (newX < 0)
newX = 0
if (newX > mainWindow.width - bubble.width)
newX = mainWindow.width - bubble.width
if (newY < 18)
newY = 18
if (newY > mainWindow.height - bubble.height)
newY = mainWindow.height - bubble.height
bubble.x = newX
bubble.y = newY
}
}
function calcPitch(x, y, z) {
return -(Math.atan(y / Math.sqrt(x * x + z * z)) * 57.2957795);
}
function calcRoll(x, y, z) {
return -(Math.atan(x / Math.sqrt(y * y + z * z)) * 57.2957795);
}
} }

View File

@@ -0,0 +1,8 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>MainForm.ui.qml</file>
<file>Bubble.qml</file>
<file>Bluebubble.svg</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@@ -142,7 +142,7 @@
\li Select \uicontrol Tools > \uicontrol Options > \li Select \uicontrol Tools > \uicontrol Options >
\uicontrol {C++} > \uicontrol {Code Model}, \uicontrol {C++} > \uicontrol {Code Model},
and select the parser to use for files of each type. and select \uicontrol {Use Clang Code Model}.
\li To process pre-compiled headers before processing any project files, \li To process pre-compiled headers before processing any project files,
deselect the \uicontrol {Ignore pre-compiled headers} check box. deselect the \uicontrol {Ignore pre-compiled headers} check box.

View File

@@ -1510,7 +1510,7 @@
defined file pattern only in the project you are currently defined file pattern only in the project you are currently
editing. editing.
\li \uicontrol {Files on File System} recursively searches files \li \uicontrol {Files in File System} recursively searches files
matching the defined file pattern in the selected directory. matching the defined file pattern in the selected directory.
\li \uicontrol {Current File} searches only the current file. \li \uicontrol {Current File} searches only the current file.

View File

@@ -354,7 +354,8 @@
To search within the \uicontrol{Application Output} and \uicontrol{Compile Output} To search within the \uicontrol{Application Output} and \uicontrol{Compile Output}
panes, press \key {Ctrl+F} when the pane is active. Enter search criteria in panes, press \key {Ctrl+F} when the pane is active. Enter search criteria in
the \uicontrol Find field and click the left and right arrows to search down and the \uicontrol Find field and click the left and right arrows to search down and
up in the pane. up in the pane. In these panes, you can also use the zoom buttons to increase and
decrease the text size of the output.
To open the \uicontrol{General Messages} and \l{Using Version Control Systems} To open the \uicontrol{General Messages} and \l{Using Version Control Systems}
{Version Control} panes, select {Version Control} panes, select

View File

@@ -72,6 +72,12 @@
\uicontrol {Clean Project}. To clean the build directory and then build the \uicontrol {Clean Project}. To clean the build directory and then build the
project, select \uicontrol Build > \uicontrol {Rebuild All} or \uicontrol {Rebuild Project}. project, select \uicontrol Build > \uicontrol {Rebuild All} or \uicontrol {Rebuild Project}.
To build and clean projects without dependencies, select the
\uicontrol {Build Without Dependencies},
\uicontrol {Rebuild Without Dependencies}, and
\uicontrol {Clean Without Dependencies} options in the context menu in the
\uicontrol Projects view.
To run qmake to generate new Makefiles, select \uicontrol Build > \uicontrol qmake. To run qmake to generate new Makefiles, select \uicontrol Build > \uicontrol qmake.
*/ */

View File

@@ -93,20 +93,39 @@
Normally, there is no need to pass any command line arguments for projects Normally, there is no need to pass any command line arguments for projects
that are already built, as CMake caches that information. that are already built, as CMake caches that information.
\section1 Editing CMake Configuration Files
You can open CMake configuration files in \QC for editing. The following
features are supported:
\list
\li Pressing \key F2 when the cursor is on a filename to open the file
\li Keyword completion
\li Auto-indentation
\li Matching parentheses and quotes
\endlist
\section1 Building CMake Projects \section1 Building CMake Projects
\QC builds CMake projects by running \c make, \c mingw32-make, \QC builds CMake projects by running \c make, \c mingw32-make,
\c nmake, or \c ninja depending on your platform. The build errors and \c nmake, or \c ninja depending on your platform. The build errors and
warnings are parsed and displayed in the \uicontrol Issues output pane. warnings are parsed and displayed in the \uicontrol Issues output pane.
By default, \QC builds the \b{all} target. You can specify which By default, \QC uses the \uicontrol All \l{glossary-build-config}
targets to build in \uicontrol Projects mode, under {build configuration}. You can select another build configuration in
\uicontrol {Build Settings}. \uicontrol Projects > \uicontrol {Edit build configuration}. In addition to
debug and release build configurations, you can create a release build that
contains debug information or a release build with the smallest possible
size.
\image qtcreator-cmake-build-settings.png \image qtcreator-cmake-build-settings.png
\QC supports multiple build configurations. You can change the build You can change the build directory after the initial import.
directory after the initial import.
The build and run kit that you select determines which CMake tool is used The build and run kit that you select determines which CMake tool is used
for building. For more information, see \l {Adding Kits}. for building. For more information, see \l {Adding Kits}.

View File

@@ -51,6 +51,11 @@
\li Select projects that must be built before the current project is \li Select projects that must be built before the current project is
built. built.
\li Select the \uicontrol {Synchronize configuration} check box to
use the same kit as well as the same build and deploy
configuration to build and deploy all dependent projects loaded
in a session.
\endlist \endlist
\QC calculates the build order based on the dependencies that you \QC calculates the build order based on the dependencies that you

View File

@@ -57,113 +57,122 @@
Program certificate that you receive from Apple. For more information, see Program certificate that you receive from Apple. For more information, see
\l{Connecting iOS Devices}. \l{Connecting iOS Devices}.
\section1 Creating the Project \include creator-tutorial-create-qq-project.qdocinc
\list 1 \section1 Creating the Accelbubble Main View
\li Select \uicontrol File > \uicontrol {New File or Project} > The main view of the application displays an SVG bubble image that moves
\uicontrol Application > \uicontrol {Qt Quick Controls Application} around the screen when you tilt the device.
> \uicontrol Choose.
\li In the \uicontrol Name field, type \e {accelbubble}.
\li In the \uicontrol {Create in} field, enter the path for the project
files, and then click \uicontrol Next (or \uicontrol Continue on
OS X).
\li In the \uicontrol {Minimal required Qt version} field, select the Qt
version to develop with.
\note This page determines the set of files that the wizard
generates and their contents. The instructions in this tutorial
might not apply if you select the \uicontrol {With .ui.qml file}
check box.
\li Select \l{glossary-buildandrun-kit}{kits} for Android ARM and iPhone
OS, and click \uicontrol{Next}.
\note Kits are listed if they have been specified in \uicontrol Tools >
\uicontrol Options > \uicontrol {Build & Run} > \uicontrol Kits (on Windows and Linux)
or in \uicontrol {Qt Creator} > \uicontrol Preferences \uicontrol {Build & Run} >
\uicontrol Kits (on OS X).
\li Select \uicontrol Next in the following dialogs to use the default
settings.
\li Review the project settings, and click \uicontrol{Finish} (or \uicontrol Done on
OS X).
\endlist
\QC generates a default QML file that you can modify to create the main view
of the application.
\section1 Creating the Main View
The main view of the application displays an SVG bubble image at the center
of the main window.
To use \l{accelbubble/Bluebubble.svg}{Bluebubble.svg} in your project, To use \l{accelbubble/Bluebubble.svg}{Bluebubble.svg} in your project,
copy it to the project directory (same subdirectory as the QML file). copy it to the project directory (same subdirectory as the QML file).
The image appears in \uicontrol Resources. You can also use any other The image appears in \uicontrol Resources. You can also use any other
image or a QML type, instead. image or a QML type, instead.
To create the UI in the \uicontrol Design mode:
\list 1 \list 1
\li In the \uicontrol Projects view, double-click the main.qml file \li In the \uicontrol Projects view, double-click the MainForm.ui.qml
to open it in the code editor. file to open it in \QMLD.
\li Click \uicontrol Design to open the file in \QMLD. \li In the \uicontrol Navigator, select \uicontrol RowLayout and press
\li In the \uicontrol Navigator, select \uicontrol Label and press
\key Delete to delete it. \key Delete to delete it.
\li Select \uicontrol ApplicationWindow to edit its properties. \li In \uicontrol Library > \uicontrol {QML Types}, select
\uicontrol Rectangle and drag and drop it to the \uicontrol Item in
the navigator.
\list a \li Select the rectangle in the navigator to edit its properties:
\li In the \uicontrol Id field, enter \e mainWindow, to be able to \list a
reference the window from other places.
\li In the \uicontrol Title field, type \e {Accelerate Bubble}. \li In the \uicontrol Id field enter \e mainWindow, to be able
to reference the rectangle from other places.
\endlist \li Select the \uicontrol Layout tab, and then click
the \inlineimage qmldesigner-anchor-fill-screen.png
(\uicontrol {Fill to Parent}) button to anchor the rectangle
to the item.
\endlist
\li In \uicontrol Library > \uicontrol Resources, select Bluebubble.svg \li In \uicontrol Library > \uicontrol Resources, select Bluebubble.svg
and drag and drop it to the canvas. and drag and drop it to \e mainWindow in the navigator.
\li In the \uicontrol Properties pane, \uicontrol Id field, enter \e bubble to be \li In the \uicontrol Properties pane, \uicontrol Id field, enter
able to reference the image from other places. \e bubble to be able to reference the image from other places.
\li In the code editor, add the following new properties to the image to \li Select the \inlineimage qmldesigner-export-item-button.png
position the image at the center of the application window when the (\uicontrol Export) button in the navigator to export the
application starts: \e mainWindow and \e bubble as properties.
\quotefromfile accelbubble/main.qml
\skipto Image
\printuntil bubble.width
\li Set the x and y position of the image based on the new properties:
\dots
\printuntil centerY
\skipto /^\}/
\printuntil }
\endlist \endlist
For an example, see \l{accelbubble/main.qml}{main.qml}. We want to modify the properties of the bubble in ways that are not
supported by \QMLD, and therefore we create a custom QML type for it:
\list 1
\li Select \uicontrol Edit to open MainForm.ui.qml in the code editor.
\li Right-click \uicontrol Image and select \uicontrol Refactoring >
\uicontrol {Move Component into Separate File}.
\li In the \uicontrol {Component name} field, enter \e Bubble and
select \uicontrol OK to create \e Bubble.qml.
\endlist
\QC creates a reference to Bubble.qml in MainForm.ui.qml.
To check your code, you can compare MainForm.ui.qml with the
\l{accelbubble/MainForm.ui.qml}{MainForm.ui.qml} example file and Bubble.qml
with the \l{accelbubble/Bubble.qml}{Bubble.qml} example file.
The UI is now ready and you can switch to editing the main.qml and
Bubble.qml files in the \uicontrol Edit mode, as described in the
following section.
\section1 Moving the Bubble \section1 Moving the Bubble
Now that the visual elements are in place, let us move the bubble based on The new project wizard adds boilerplate code to the main.qml file to create
Accelerometer sensor values. menu items and push buttons. Modify the boilerplate code by removing
obsolete code and by adding new code. You removed the push buttons from the
UI Form, so you also need to remove the corresponding code from main.qml (or
the application cannot be built).
In the code editor, edit Bubble.qml to add properties that we will use to
position the image:
\quotefromfile accelbubble/Bubble.qml
\skipto Image
\printuntil }
In the code editor, edit the main.qml to specify the application title, as
illustrated by the following code snippet:
\quotefromfile accelbubble/main.qml
\skipto ApplicationWindow
\printuntil title
Use the bubble properties to position the image:
\printuntil bubbleCenter
Then set the x and y position of the image based on the new properties:
\printuntil centerY
\skipto /^\}/
\printuntil }
Then add code to move the bubble based on Accelerometer sensor values:
\list 1 \list 1
\li Add the following import statement to main.qml: \li Add the following import statement to main.qml:
\code \code
import QtSensors 5.0 import QtSensors 5.5
\endcode \endcode
\li Add the \l{Accelerometer} type with the necessary properties: \li Add the \l{Accelerometer} type with the necessary properties:
@@ -183,7 +192,7 @@
\printuntil Math.atan(x \printuntil Math.atan(x
\printuntil } \printuntil }
\li Add the following JavaScript code for \a onReadingChanged signal of \li Add the following JavaScript code for \c onReadingChanged signal of
Accelerometer type to make the bubble move when the Accelerometer Accelerometer type to make the bubble move when the Accelerometer
values change: values change:
@@ -194,7 +203,7 @@
We want to ensure that the position of the bubble is always within We want to ensure that the position of the bubble is always within
the bounds of the screen. If the Accelerometer returns not a number the bounds of the screen. If the Accelerometer returns not a number
(NaN), the value is ignored and the bubble position is not updated. (NaN), the value is ignored and the bubble position is not updated.
\li Add SmoothedAnimation behavior on the \a x and \a y properties of \li Add SmoothedAnimation behavior on the \c x and \c y properties of
the bubble to make its movement look smoother. the bubble to make its movement look smoother.
\quotefromfile accelbubble/main.qml \quotefromfile accelbubble/main.qml

View File

@@ -30,41 +30,51 @@
\title Creating Buttons \title Creating Buttons
To create a button component: To create a button type:
\list 1 \list 1
\li Select \uicontrol {File > New File or Project > Qt > QML File > Choose} \li Select \uicontrol File > \uicontrol {New File or Project} >
to create a QML file called Button.qml (for example). \uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\uicontrol Choose to create a QML file called Button.qml (for
example).
\note Components are listed in the \uicontrol Library only if the \note Types are listed in the \uicontrol Library only if the
filename begins with a capital letter. filename begins with a capital letter.
\li Click \uicontrol {Design} to edit the file in the visual editor. \li Click \uicontrol {Design} to edit the file in the visual editor.
\li In the \uicontrol Navigator, click \uicontrol Rectangle to set properties \li In the \uicontrol Navigator, select \uicontrol Item and set the
for it. width (\uicontrol W) and height (\uicontrol H) of the button in the
\uicontrol Properties pane.
\li In the \uicontrol Properties pane, modify the appearance of the button. \li Drag and drop a \uicontrol Rectangle from the \uicontrol Library to
the item in the navigator. This creates a nested item where the
item is the parent of the rectangle. Items are positioned relative
to their parents.
\li In the \uicontrol Properties pane, modify the appearance of the
rectangle:
\list a \list a
\li In the \uicontrol Size field, set the width (\uicontrol W) and height
(\uicontrol H) of the button.
\li In the \uicontrol Color field, select the button color. \li In the \uicontrol Color field, select the button color.
\li In the \uicontrol Radius field, use the slider to set the radius of \li In the \uicontrol Radius field, use the slider to set the radius of
the rectangle and produce rounded corners for the button. the rectangle and produce rounded corners for the button.
\li Select \uicontrol {Layout}, and then select the
\inlineimage qmldesigner-anchor-fill-screen.png
(\uicontrol {Fill to Parent}) button to anchor the rectangle to
the item.
\endlist \endlist
\li Drag and drop a \uicontrol {Text} item on top of the \uicontrol Rectangle. This \li Drag and drop a \uicontrol {Text} type to the item in the navigator.
creates a nested item where \uicontrol Rectangle is the parent item
of \uicontrol Text. Items are positioned relative to their parents.
\li In the \uicontrol Properties pane, edit the properties of the \uicontrol Text \li In the \uicontrol Properties pane, edit the properties of the \uicontrol Text
item. type.
\list a \list a
@@ -77,10 +87,8 @@
\li In the \uicontrol Alignment field, select the center buttons to align \li In the \uicontrol Alignment field, select the center buttons to align
the text to the center of the button. the text to the center of the button.
\li Click \uicontrol {Layout}, and then click the \li Select \uicontrol Layout > \uicontrol {Fill to Parent}
\inlineimage qmldesigner-anchor-fill-screen.png to anchor the text to the whole button area.
(\uicontrol {Fill to Parent}) button to anchor the text to the whole
button area.
\endlist \endlist
@@ -110,13 +118,13 @@
\l{BorderImage} type to display an image, such as a PNG file, as a border \l{BorderImage} type to display an image, such as a PNG file, as a border
and a background. and a background.
Use two Border Image items and suitable graphics to make it look like the Use two border images and suitable graphics to make it look like the
button is pushed down when it is clicked. One of the Border Image items button is pushed down when it is clicked. One of the border images
is visible by default. You can specify that it is hidden and the other one is visible by default. You can specify that it is hidden and the other one
becomes visible when the mouse is clicked. becomes visible when the mouse is clicked.
Add a Mouse Area that covers the whole area and emits the clicked signal Add a \l MouseArea type that covers the whole area and emits the clicked
(\c {parent.clicked()}) when it detects a mouse click. signal (\c {item.clicked()}) when it detects a mouse click.
You can add text to the button and set it up as a property. The text can You can add text to the button and set it up as a property. The text can
then be initialized from the outside, making the button a reusable UI then be initialized from the outside, making the button a reusable UI
@@ -130,57 +138,54 @@
\list 1 \list 1
\li Select \uicontrol {File > New File or Project > Qt > QML File > Choose} \li Select \uicontrol File > \uicontrol {New File or Project} >
to create a QML file called Button.qml (for example). \uicontrol Qt > \uicontrol {QML File (Qt Quick 2)} >
\uicontrol Choose to create a QML file called Button.qml (for
example).
\li Double-click the file to open it in the code editor. \note Types are listed in the \uicontrol Library only if the
filename begins with a capital letter.
\li Replace the \uicontrol Rectangle with an \uicontrol Item, as illustrated by the
following code snippet:
\qml
Item {
}
\endqml
\li Specify properties and set expressions for the \uicontrol Item, as
illustrated by the following code snippet:
\qml
Item {
property string text: ""
property int fontSize: 10
signal clicked
width: 60
height: 40
}
\endqml
You will point to the properties and expression later.
\li Click \uicontrol {Design} to edit the file in the visual editor. \li Click \uicontrol {Design} to edit the file in the visual editor.
\li Drag and drop two \uicontrol {Border Image} items from the \uicontrol Library \li In the \uicontrol Navigator, select \uicontrol Item and set the
to the canvas. width (\uicontrol W) and height (\uicontrol H) of the button in the
\uicontrol Properties pane.
\li Drag and drop a \uicontrol Text item to the canvas. \li Select \uicontrol Connections > \uicontrol {Dynamic Properties} >
\uicontrol Add to add properties for the item:
\li Drag and drop a \uicontrol {Mouse Area} to the canvas. \image qmldesigner-borderimage-properties.png "Dynamic properties"
\li In the \uicontrol Navigator, select \uicontrol border_image1 to specify \list a
settings for it in the \uicontrol Properties pane:
\li Double-click in the columns in the view to specify a \c text
property with the type \c string and an empty value.
\li Specify another property, \c fontSize, with the type \c int
and the value \c 10.
\endlist
\li Drag and drop two \uicontrol {Border Image} types from the
\uicontrol Library to the item in the \uicontrol Navigator.
\li Drag and drop a \uicontrol Text type to the item in the navigator.
\li Drag and drop a \uicontrol {Mouse Area} to the item in the
navigator.
\li In the navigator, select a border image to specify settings for it
in the \uicontrol Properties pane:
\list a \list a
\li Select \uicontrol {Set Binding} in the menu next to the \li Select \uicontrol Connections > \uicontrol {Bindings}
\uicontrol Visibility check box. > \uicontrol Add to hide the image when the mouse button is not
pressed down. Specify the \c visible property with the
\c !mouseArea source item and \c pressed source property.
\li Enter the following expression to specify that the image is \image qmldesigner-borderimage-bindings.png "Border image bindings"
visible when the mouse is not pressed down:
\c {!mouse_area1.pressed}.
\li In the \uicontrol Source field, select the image file for the button, \li In the \uicontrol Source field, select the image file for the button,
for example button_up.png. for example button_up.png.
@@ -192,41 +197,48 @@
\endlist \endlist
\li Select \uicontrol border_image2 to specify similar settings for it: \li Select the other border image to specify similar settings for it:
\list a \list a
\li Set the following epression for \uicontrol Visibility, to specify that \li In \uicontrol Bindings, specify the \c visible property
the image is visible when the mouse is pressed down: with the \c mouseArea source item and \c pressed source
\c {mouse_area1.pressed}. property to show the image when the mouse button is pressed
down.
\li In the \uicontrol Source field, select the image file for the button \li In the \uicontrol Source field, select the image file for the button
when it is clicked, for example button_down.png. when it is clicked, for example button_down.png.
\li Click \uicontrol {Layout}, and then click the \li Select \uicontrol {Layout} > \uicontrol {Fill to Parent}
\uicontrol {Fill to Parent}
button to anchor the border image to the \uicontrol Item. button to anchor the border image to the \uicontrol Item.
\endlist \endlist
\li Select \uicontrol text1 to specify font size and color, and text \li Select the text to specify font size and color, and text scaling
scaling and rendering: and rendering:
\list a \list a
\li In the \uicontrol Color field, use the color picker to select \li In the \uicontrol Color field, use the color picker to select
the font color, or enter a value in the field. the font color, or enter a value in the field.
\li In the \uicontrol Text field, select \uicontrol {Set Binding} and \li In \uicontrol Bindings, create bindings to properties:
enter a pointer to the \c {text} property that you specified
earlier: \c {parent.txt}.
\li In the \uicontrol Size field, select \uicontrol {Pixels} to specify the font \image qmldesigner-borderimage-bindings-text.png "Text bindings"
size in pixels. By default, the size is specified in points.
\li In the \uicontrol Size field, select \uicontrol {Set Expression} and enter a \list
pointer to the \c {fontSize} property that you specified
earlier. \li Set the source property of the \c text property as
\c text and the source item as \c parent.
\li Set the source property of the \c font.pixelSize as
\c fontSize and the source item as \c parent.
\li Set the source property of \c scale as
\c {if (!mouseArea} and the source item as
\c {pressed) { 1 } else { 0.95 }}.
\endlist
\li Click \uicontrol {Layout}, and then click the \li Click \uicontrol {Layout}, and then click the
\inlineimage qmldesigner-center-in.png "Anchor buttons" \inlineimage qmldesigner-center-in.png "Anchor buttons"
@@ -234,20 +246,25 @@
buttons to inherit the vertical and horizontal centering from buttons to inherit the vertical and horizontal centering from
the parent. the parent.
\li Click \uicontrol Advanced to specify scaling for the text in the
\uicontrol Scale field.
\li Select \uicontrol {Set Binding} and enter the following expression:
\c {if (!mousearea1.pressed) { 1 } else { 0.95 }}.
\note You can enter long and complicated expressions also in the
code editor.
\endlist \endlist
\li In the code editor, add to the \c MouseArea a pointer to the \li Select \uicontrol mouseArea in the navigator and then select
\c clicked expression that you added earlier: \uicontrol Connections > \uicontrol Add to set \c item.clicked()
\c {onClicked: parent.clicked()}. as the value of the \c onClicked signal handler.
\image qmldesigner-borderimage-connections.png "Item connections"
\li In the code editor, specify the \c clicked signal for the Item:
\qml
Item {
id: item
property string text: ""
property int fontSize: 10
signal clicked
}
\endqml
\endlist \endlist

View File

@@ -109,14 +109,20 @@
Click the Click the
\inlineimage qmldesigner-show-hide-icon.png \inlineimage qmldesigner-show-hide-icon.png
icon to change the visibility of an item on the canvas. To change the icon to change the visibility of an item on the canvas. To change the
visibility of an item in the application, use the \uicontrol Visibility visibility of an item in the application, select the \uicontrol Visibility
check box or the \uicontrol Opacity field in the \uicontrol Properties pane. If you set check box in the \uicontrol Properties pane or select \uicontrol Edit >
\uicontrol Opacity to 0, items are hidden, but you can still apply animation \uicontrol Visibility in the context menu.
to them.
You can also set the \uicontrol Opacity field to 0 to hide items that you
want to apply animation to.
As all properties, visibility and opacity are inherited from the parent As all properties, visibility and opacity are inherited from the parent
item. To hide or show child items, edit the properties of the parent item. item. To hide or show child items, edit the properties of the parent item.
To reset item size, position, or anchors, select context menu commands. To
change the source of an Image type, select \uicontrol {Change Source URL} in
the context menu.
To view lists of files or projects, instead, select \uicontrol {File System}, To view lists of files or projects, instead, select \uicontrol {File System},
\uicontrol {Open Documents}, or \uicontrol Projects in the menu. \uicontrol {Open Documents}, or \uicontrol Projects in the menu.
To view several types of content at a time, split the sidebar by clicking To view several types of content at a time, split the sidebar by clicking
@@ -132,7 +138,8 @@
stacking value are drawn in the order they are listed, from the last item stacking value are drawn in the order they are listed, from the last item
up. up.
To change the stacking order of an item, right-click it on the canvas and To change the stacking order of an item, right-click it in the navigator or
on the canvas and
select \uicontrol {Stack (z)}. You can raise or lower the stack value of an item select \uicontrol {Stack (z)}. You can raise or lower the stack value of an item
or move the item to the front or back of all its siblings. To remove the or move the item to the front or back of all its siblings. To remove the
\c z property, select \uicontrol {Reset z Property}. \c z property, select \uicontrol {Reset z Property}.

View File

@@ -103,4 +103,8 @@
You can also assign properties or define behavior or transitions. You can also assign properties or define behavior or transitions.
To move from the \uicontrol Design mode directly to the implementation of a
type in the .qml file, right-click the type in the \uicontrol Navigator and
select \uicontrol {Go to Implementation} in the context menu.
*/ */

View File

@@ -73,7 +73,7 @@ def is_debug(fpath):
if coredebug.search(fpath): if coredebug.search(fpath):
return True return True
output = subprocess.check_output(['dumpbin', '/imports', fpath]) output = subprocess.check_output(['dumpbin', '/imports', fpath])
return coredebug.search(output) return coredebug.search(output) != None
def is_debug_build(install_dir): def is_debug_build(install_dir):
return is_debug(os.path.join(install_dir, 'bin', 'qtcreator.exe')) return is_debug(os.path.join(install_dir, 'bin', 'qtcreator.exe'))

View File

@@ -103,7 +103,11 @@ def qdump__boost__container__list(d, value):
innerType = d.templateArgument(value.type, 0) innerType = d.templateArgument(value.type, 0)
offset = 2 * d.ptrSize() offset = 2 * d.ptrSize()
with Children(d, n): with Children(d, n):
p = r["root_"]["next_"] try:
root = r["root_"]
except:
root = r["m_header"]
p = root["next_"]
for i in xrange(n): for i in xrange(n):
d.putSubItem("%s" % i, d.createValue(d.pointerValue(p) + offset, innerType)) d.putSubItem("%s" % i, d.createValue(d.pointerValue(p) + offset, innerType))
p = p["next_"] p = p["next_"]
@@ -130,14 +134,41 @@ def qdump__boost__unordered__unordered_set(d, value):
ptrSize = d.ptrSize() ptrSize = d.ptrSize()
size = d.extractInt(base + 2 * ptrSize) size = d.extractInt(base + 2 * ptrSize)
d.putItemCount(size) d.putItemCount(size)
if d.isExpanded(): if d.isExpanded():
innerType = d.templateArgument(value.type, 0) innerType = d.templateArgument(value.type, 0)
bucketCount = d.extractInt(base + ptrSize) bucketCount = d.extractInt(base + ptrSize)
offset = int((innerType.sizeof + ptrSize - 1) / ptrSize) * ptrSize #warn("A BUCKET COUNT: %s" % bucketCount)
with Children(d, size, maxNumChild=10000): #warn("X BUCKET COUNT: %s" % d.parseAndEvaluate("s1.table_.bucket_count_"))
afterBuckets = d.extractPointer(base + 5 * ptrSize) try:
afterBuckets += bucketCount * ptrSize # boost 1.58
item = d.extractPointer(afterBuckets) table = value["table_"]
for j in d.childRange(): bucketsAddr = toInteger(table["buckets_"])
d.putSubItem(j, d.createValue(item - offset, innerType)) #warn("A BUCKETS: 0x%x" % bucketsAddr)
item = d.extractPointer(item) #warn("X BUCKETS: %s" % d.parseAndEvaluate("s1.table_.buckets_"))
lastBucketAddr = bucketsAddr + bucketCount * ptrSize
#warn("A LAST BUCKET: 0x%x" % lastBucketAddr)
#warn("X LAST BUCKET: %s" % d.parseAndEvaluate("s1.table_.get_bucket(s1.table_.bucket_count_)"))
previousStartAddr = lastBucketAddr
#warn("A PREVIOUS START: 0x%x" % previousStartAddr)
#warn("X PREVIOUS START: %s" % d.parseAndEvaluate("s1.table_.get_previous_start()"))
item = d.extractPointer(previousStartAddr)
#warn("A KEY ADDR: 0x%x" % item)
#warn("X KEY ADDR: %s" % d.parseAndEvaluate("s1.table_.get_previous_start()->next_"))
item = d.extractPointer(previousStartAddr)
#warn("A VALUE: %x" % d.extractInt(item + ptrSize))
#warn("X VALUE: %s" % d.parseAndEvaluate("*(int*)(s1.table_.get_previous_start()->next_ + 1)"))
with Children(d, size, maxNumChild=10000):
for j in d.childRange():
d.putSubItem(j, d.createValue(item + 2 * ptrSize, innerType))
item = d.extractPointer(item)
except:
# boost 1.48
offset = int((innerType.sizeof + ptrSize - 1) / ptrSize) * ptrSize
with Children(d, size, maxNumChild=10000):
afterBuckets = d.extractPointer(base + 5 * ptrSize)
afterBuckets += bucketCount * ptrSize
item = d.extractPointer(afterBuckets)
for j in d.childRange():
d.putSubItem(j, d.createValue(item - offset, innerType))
item = d.extractPointer(item)

View File

@@ -569,7 +569,9 @@ class DumperBase:
elided, shown = self.computeLimit(size, limit) elided, shown = self.computeLimit(size, limit)
return elided, self.readMemory(data, shown) return elided, self.readMemory(data, shown)
def putCharArrayHelper(self, data, size, charSize, displayFormat = AutomaticFormat): def putCharArrayHelper(self, data, size, charSize,
displayFormat = AutomaticFormat,
makeExpandable = True):
bytelen = size * charSize bytelen = size * charSize
elided, shown = self.computeLimit(bytelen, self.displayStringLimit) elided, shown = self.computeLimit(bytelen, self.displayStringLimit)
mem = self.readMemory(data, shown) mem = self.readMemory(data, shown)
@@ -595,6 +597,13 @@ class DumperBase:
elided, shown = self.computeLimit(bytelen, 100000) elided, shown = self.computeLimit(bytelen, 100000)
self.putField("editvalue", self.readMemory(data, shown)) self.putField("editvalue", self.readMemory(data, shown))
if makeExpandable:
self.putNumChild(size)
if self.isExpanded():
with Children(self):
for i in range(size):
self.putSubItem(size, data[i])
def readMemory(self, addr, size): def readMemory(self, addr, size):
data = self.extractBlob(addr, size).toBytes() data = self.extractBlob(addr, size).toBytes()
return self.hexencode(data) return self.hexencode(data)
@@ -795,14 +804,9 @@ class DumperBase:
raise RuntimeError("Check failed") raise RuntimeError("Check failed")
def checkRef(self, ref): def checkRef(self, ref):
try: count = self.extractInt(ref.address)
count = int(ref["atomic"]["_q_value"]) # Qt 5.
minimum = -1
except:
count = int(ref["_q_value"]) # Qt 4.
minimum = 0
# Assume there aren't a million references to any object. # Assume there aren't a million references to any object.
self.check(count >= minimum) self.check(count >= -1)
self.check(count < 1000000) self.check(count < 1000000)
def readToFirstZero(self, p, tsize, maximum): def readToFirstZero(self, p, tsize, maximum):
@@ -1010,7 +1014,8 @@ class DumperBase:
n = int(arrayByteSize / ts) n = int(arrayByteSize / ts)
if displayFormat != RawFormat and p: if displayFormat != RawFormat and p:
if innerTypeName == "char" or innerTypeName == "wchar_t": if innerTypeName == "char" or innerTypeName == "wchar_t":
self.putCharArrayHelper(p, n, ts, self.currentItemFormat()) self.putCharArrayHelper(p, n, ts, self.currentItemFormat(),
makeExpandable = False)
else: else:
self.tryPutSimpleFormattedPointer(p, arrayType, innerTypeName, self.tryPutSimpleFormattedPointer(p, arrayType, innerTypeName,
displayFormat, arrayByteSize) displayFormat, arrayByteSize)
@@ -1410,8 +1415,7 @@ class DumperBase:
addr += 1 addr += 1
return result return result
def listChildrenGenerator(self, addr, typeName): def listChildrenGenerator(self, addr, innerType):
innerType = self.lookupType(self.qtNamespace() + typeName)
base = self.extractPointer(addr) base = self.extractPointer(addr)
begin = self.extractInt(base + 8) begin = self.extractInt(base + 8)
end = self.extractInt(base + 12) end = self.extractInt(base + 12)
@@ -1430,6 +1434,14 @@ class DumperBase:
p = self.extractPointer(addr + i * stepSize) p = self.extractPointer(addr + i * stepSize)
yield self.createValue(p, innerType) yield self.createValue(p, innerType)
def vectorChildrenGenerator(self, addr, innerType):
base = self.extractPointer(addr)
size = self.extractInt(base + 4)
data = base + self.extractPointer(base + 8 + self.ptrSize())
innerSize = innerType.sizeof
for i in range(size):
yield self.createValue(data + i * innerSize, innerType)
# This is called is when a QObject derived class is expanded # This is called is when a QObject derived class is expanded
def putQObjectGuts(self, qobject, smo): def putQObjectGuts(self, qobject, smo):
@@ -1454,6 +1466,7 @@ class DumperBase:
with SubItem(self, "[properties]"): with SubItem(self, "[properties]"):
propertyCount = 0 propertyCount = 0
usesVector = self.qtVersion() >= 0x50700
if self.isExpanded(): if self.isExpanded():
propertyNames = self.staticQObjectPropertyNames(smo) propertyNames = self.staticQObjectPropertyNames(smo)
propertyCount = len(propertyNames) # Doesn't include dynamic properties. propertyCount = len(propertyNames) # Doesn't include dynamic properties.
@@ -1465,8 +1478,13 @@ class DumperBase:
# Dynamic properties. # Dynamic properties.
if extraData: if extraData:
names = self.listChildrenGenerator(extraData + ptrSize, "QByteArray") byteArrayType = self.lookupQtType("QByteArray")
values = self.listChildrenGenerator(extraData + 2 * ptrSize, "QVariant") variantType = self.lookupQtType("QVariant")
names = self.listChildrenGenerator(extraData + ptrSize, byteArrayType)
if usesVector:
values = self.vectorChildrenGenerator(extraData + 2 * ptrSize, variantType)
else:
values = self.listChildrenGenerator(extraData + 2 * ptrSize, variantType)
for (k, v) in zip(names, values): for (k, v) in zip(names, values):
with SubItem(self, propertyCount): with SubItem(self, propertyCount):
self.put('key="%s",' % self.encodeByteArray(k)) self.put('key="%s",' % self.encodeByteArray(k))

View File

@@ -226,6 +226,11 @@ class Dumper(DumperBase):
self.qtNamespaceToReport = None self.qtNamespaceToReport = None
self.interpreterBreakpointResolvers = [] self.interpreterBreakpointResolvers = []
# The guess does not need to be updated during a fetchVariables()
# as the result is fixed during that time (ignoring "active"
# dumpers causing loading of shared objects etc).
self.currentQtNamespaceGuess = None
def prepare(self, args): def prepare(self, args):
self.output = [] self.output = []
self.currentIName = "" self.currentIName = ""
@@ -238,11 +243,6 @@ class Dumper(DumperBase):
self.currentType = ReportItem() self.currentType = ReportItem()
self.currentAddress = None self.currentAddress = None
# The guess does not need to be updated during a fetchVariables()
# as the result is fixed during that time (ignoring "active"
# dumpers causing loading of shared objects etc).
self.currentQtNamespaceGuess = None
self.resultVarName = args.get("resultvarname", "") self.resultVarName = args.get("resultvarname", "")
self.expandedINames = set(args.get("expanded", [])) self.expandedINames = set(args.get("expanded", []))
self.stringCutOff = int(args.get("stringcutoff", 10000)) self.stringCutOff = int(args.get("stringcutoff", 10000))
@@ -1159,6 +1159,38 @@ class Dumper(DumperBase):
# return mem.tobytes() # return mem.tobytes()
return mem return mem
def createSpecialBreakpoints(self, args):
self.specialBreakpoints = []
def newSpecial(spec):
class SpecialBreakpoint(gdb.Breakpoint):
def __init__(self, spec):
super(SpecialBreakpoint, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True)
self.spec = spec
def stop(self):
print("Breakpoint on '%s' hit." % self.spec)
return True
return SpecialBreakpoint(spec)
# FIXME: ns is accessed too early. gdb.Breakpoint() has no
# 'rbreak' replacement, and breakpoints created with
# 'gdb.execute("rbreak...") cannot be made invisible.
# So let's ignore the existing of namespaced builds for this
# fringe feature here for now.
ns = self.qtNamespace()
if args.get('breakonabort', 0):
self.specialBreakpoints.append(newSpecial("abort"))
if args.get('breakonwarning', 0):
self.specialBreakpoints.append(newSpecial(ns + "qWarning"))
self.specialBreakpoints.append(newSpecial(ns + "QMessageLogger::warning"))
if args.get('breakonfatal', 0):
self.specialBreakpoints.append(newSpecial(ns + "qFatal"))
self.specialBreakpoints.append(newSpecial(ns + "QMessageLogger::fatal"))
def putFields(self, value, dumpBase = True): def putFields(self, value, dumpBase = True):
fields = value.type.fields() fields = value.type.fields()
if self.sortStructMembers: if self.sortStructMembers:

View File

@@ -1115,21 +1115,41 @@ class Dumper(DumperBase):
self.putItem(child) self.putItem(child)
return return
n = value.GetNumChildren() memberBase = 0 # Start of members.
m = value.GetType().GetNumberOfDirectBaseClasses()
if n > 10000:
n = 10000
# seems to happen in the 'inheritance' autotest
if m > n:
m = n
for i in xrange(m):
child = value.GetChildAtIndex(i)
with UnnamedSubItem(self, "@%d" % (i + 1)):
self.put('iname="%s",' % self.currentIName)
self.put('name="[%s]",' % child.name)
self.putItem(child)
children = [value.GetChildAtIndex(i) for i in xrange(m, n)] class ChildItem:
def __init__(self, name, value):
self.name = name
self.value = value
baseObjects = []
for i in xrange(value.GetType().GetNumberOfDirectBaseClasses()):
baseClass = value.GetType().GetDirectBaseClassAtIndex(i).GetType()
baseChildCount = baseClass.GetNumberOfFields() \
+ baseClass.GetNumberOfDirectBaseClasses() \
+ baseClass.GetNumberOfVirtualBaseClasses()
if baseChildCount:
memberBase += 1
baseObjects.append(ChildItem(baseClass.GetName(), value.GetChildAtIndex(i)))
else:
# This base object is empty, but exists and will *not* be reported
# by value.GetChildCount(). So manually report the empty base class.
baseObject = value.Cast(baseClass)
baseObjects.append(ChildItem(baseClass.GetName(), baseObject))
if self.sortStructMembers:
baseObjects.sort(key = lambda baseObject: str(baseObject.name))
for i in xrange(len(baseObjects)):
baseObject = baseObjects[i]
with UnnamedSubItem(self, "@%d" % (i + 1)):
self.put('iname="%s",' % self.currentIName)
self.put('name="[%s]",' % baseObject.name)
self.putItem(baseObject.value)
memberCount = value.GetNumChildren()
if memberCount > 10000:
memberCount = 10000
children = [value.GetChildAtIndex(memberBase + i) for i in xrange(memberCount)]
if self.sortStructMembers: if self.sortStructMembers:
children.sort(key = lambda child: str(child.GetName())) children.sort(key = lambda child: str(child.GetName()))
for child in children: for child in children:
@@ -1747,14 +1767,9 @@ class Dumper(DumperBase):
# Used in dumper auto test. # Used in dumper auto test.
class Tester(Dumper): class Tester(Dumper):
def __init__(self, binary, expandedINames): def __init__(self, binary, args):
Dumper.__init__(self) Dumper.__init__(self)
lldb.theDumper = self lldb.theDumper = self
self.expandedINames = set(expandedINames)
self.passExceptions = True
self.sortStructMembers = True
self.loadDumpers({'token': 1}) self.loadDumpers({'token': 1})
error = lldb.SBError() error = lldb.SBError()
self.target = self.debugger.CreateTarget(binary, None, None, True, error) self.target = self.debugger.CreateTarget(binary, None, None, True, error)
@@ -1763,14 +1778,14 @@ class Tester(Dumper):
warn("ERROR: %s" % error) warn("ERROR: %s" % error)
return return
s = threading.Thread(target=self.testLoop, args=[]) s = threading.Thread(target=self.testLoop, args=(args,))
s.start() s.start()
s.join(30) s.join(30)
def reportDumpers(self, msg): def reportDumpers(self, msg):
pass pass
def testLoop(self): def testLoop(self, args):
# Disable intermediate reporting. # Disable intermediate reporting.
savedReport = self.report savedReport = self.report
self.report = lambda stuff: 0 self.report = lambda stuff: 0
@@ -1813,7 +1828,7 @@ class Tester(Dumper):
if line != 0: if line != 0:
self.report = savedReport self.report = savedReport
self.process.SetSelectedThread(stoppedThread) self.process.SetSelectedThread(stoppedThread)
self.fetchVariables({'token':2, 'fancy':1}) self.fetchVariables(args)
#self.describeLocation(frame) #self.describeLocation(frame)
self.report("@NS@%s@" % self.qtNamespace()) self.report("@NS@%s@" % self.qtNamespace())
#self.report("ENV=%s" % os.environ.items()) #self.report("ENV=%s" % os.environ.items())

View File

@@ -33,24 +33,24 @@ from dumper import *
def qdump__QAtomicInt(d, value): def qdump__QAtomicInt(d, value):
d.putValue(int(value["_q_value"])) d.putValue(d.extractInt(value.address))
d.putNumChild(0) d.putNumChild(0)
def qdump__QBasicAtomicInt(d, value): def qdump__QBasicAtomicInt(d, value):
d.putValue(int(value["_q_value"])) d.putValue(d.extractInt(value.address))
d.putNumChild(0) d.putNumChild(0)
def qdump__QAtomicPointer(d, value): def qdump__QAtomicPointer(d, value):
d.putType(value.type) d.putType(value.type)
q = value["_q_value"] q = d.extractPointer(value.address)
p = toInteger(q) p = toInteger(q)
d.putValue("@0x%x" % p) d.putValue("@0x%x" % p)
d.putNumChild(1 if p else 0) d.putNumChild(1 if p else 0)
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
d.putSubItem("_q_value", q.dereference()) d.putSubItem("[pointee]", q.dereference())
def qform__QByteArray(): def qform__QByteArray():
return [Latin1StringFormat, SeparateLatin1StringFormat, return [Latin1StringFormat, SeparateLatin1StringFormat,
@@ -422,7 +422,12 @@ def qdump__QFile(d, value):
# 9fc0965 and a373ffcd change the layout of the private structure # 9fc0965 and a373ffcd change the layout of the private structure
qtVersion = d.qtVersion() qtVersion = d.qtVersion()
is32bit = d.is32bit() is32bit = d.is32bit()
if qtVersion >= 0x050500: if qtVersion >= 0x050600:
if d.isWindowsTarget():
offset = 164 if is32bit else 248
else:
offset = 168 if is32bit else 248
elif qtVersion >= 0x050500:
if d.isWindowsTarget(): if d.isWindowsTarget():
offset = 164 if is32bit else 248 offset = 164 if is32bit else 248
else: else:
@@ -697,38 +702,71 @@ def qdump__QHostAddress(d, value):
# bool isParsed (2*ptrSize + 24) # bool isParsed (2*ptrSize + 24)
privAddress = d.extractPointer(value) privAddress = d.extractPointer(value)
isQt5 = d.qtVersion() >= 0x050000 if d.qtVersion() >= 0x050700:
sizeofQString = d.ptrSize() sizeofQString = d.ptrSize()
ipStringAddress = privAddress + (0 if isQt5 else 24) ipStringAddress = privAddress
isParsedAddress = privAddress + 24 + 2 * sizeofQString a6Address = privAddress + 2 * sizeofQString + d.ptrSize() # Include padding
# value.d.d->ipString protoAddress = a6Address + 16
ipString = d.encodeString(ipStringAddress, limit=100) isParsedAddress = protoAddress + 4
if d.extractByte(isParsedAddress) and len(ipString) > 0: # value.d.d->ipString
d.putValue(ipString, Hex4EncodedLittleEndian) ipString = d.encodeString(ipStringAddress, limit=100)
else: if d.extractByte(isParsedAddress) and len(ipString) > 0:
# value.d.d->protocol: d.putValue(ipString, Hex4EncodedLittleEndian)
# QAbstractSocket::IPv4Protocol = 0
# QAbstractSocket::IPv6Protocol = 1
protoAddress = privAddress + 20 + (2 * sizeofQString if isQt5 else 0);
proto = d.extractInt(protoAddress)
if proto == 1:
# value.d.d->a6
a6Offset = 4 + (2 * sizeofQString if isQt5 else 0)
data = d.readMemory(privAddress + a6Offset, 16)
address = ':'.join("%x" % int(data[i:i+4], 16) for i in xrange(0, 32, 4))
scopeId = privAddress + sizeofQString + (0 if isQt5 else 24)
scopeId = d.encodeString(scopeId, limit=100)
d.putValue("%s%%%s" % (address, scopeId), IPv6AddressAndHexScopeId)
elif proto == 0:
# value.d.d->a
a = d.extractInt(privAddress + (2 * sizeofQString if isQt5 else 0))
a, n4 = divmod(a, 256)
a, n3 = divmod(a, 256)
a, n2 = divmod(a, 256)
a, n1 = divmod(a, 256)
d.putValue("%d.%d.%d.%d" % (n1, n2, n3, n4));
else: else:
d.putValue("<unspecified>") # value.d.d->protocol:
# QAbstractSocket::IPv4Protocol = 0
# QAbstractSocket::IPv6Protocol = 1
proto = d.extractInt(protoAddress)
if proto == 1:
# value.d.d->a6
data = d.readMemory(a6Address, 16)
address = ':'.join("%x" % int(data[i:i+4], 16) for i in xrange(0, 32, 4))
scopeIdAddress = ipStringAddress + sizeofQString
scopeId = d.encodeString(scopeIdAddress, limit=100)
d.putValue("%s%%%s" % (address, scopeId), IPv6AddressAndHexScopeId)
elif proto == 0:
# value.d.d->a
a = d.extractInt(privAddress + 2 * sizeofQString)
a, n4 = divmod(a, 256)
a, n3 = divmod(a, 256)
a, n2 = divmod(a, 256)
a, n1 = divmod(a, 256)
d.putValue("%d.%d.%d.%d" % (n1, n2, n3, n4));
else:
d.putValue("<unspecified>")
else:
isQt5 = d.qtVersion() >= 0x050000
sizeofQString = d.ptrSize()
ipStringAddress = privAddress + (0 if isQt5 else 24)
isParsedAddress = privAddress + 24 + 2 * sizeofQString
# value.d.d->ipString
ipString = d.encodeString(ipStringAddress, limit=100)
if d.extractByte(isParsedAddress) and len(ipString) > 0:
d.putValue(ipString, Hex4EncodedLittleEndian)
else:
# value.d.d->protocol:
# QAbstractSocket::IPv4Protocol = 0
# QAbstractSocket::IPv6Protocol = 1
protoAddress = privAddress + 20 + (2 * sizeofQString if isQt5 else 0);
proto = d.extractInt(protoAddress)
if proto == 1:
# value.d.d->a6
a6Offset = 4 + (2 * sizeofQString if isQt5 else 0)
data = d.readMemory(privAddress + a6Offset, 16)
address = ':'.join("%x" % int(data[i:i+4], 16) for i in xrange(0, 32, 4))
scopeId = privAddress + sizeofQString + (0 if isQt5 else 24)
scopeId = d.encodeString(scopeId, limit=100)
d.putValue("%s%%%s" % (address, scopeId), IPv6AddressAndHexScopeId)
elif proto == 0:
# value.d.d->a
a = d.extractInt(privAddress + (2 * sizeofQString if isQt5 else 0))
a, n4 = divmod(a, 256)
a, n3 = divmod(a, 256)
a, n2 = divmod(a, 256)
a, n1 = divmod(a, 256)
d.putValue("%d.%d.%d.%d" % (n1, n2, n3, n4));
else:
d.putValue("<unspecified>")
d.putPlainChildren(value["d"]["d"].dereference()) d.putPlainChildren(value["d"]["d"].dereference())
@@ -1656,7 +1694,7 @@ def qdump__QSet(d, value):
def qdump__QSharedData(d, value): def qdump__QSharedData(d, value):
d.putValue("ref: %s" % value["ref"]["_q_value"]) d.putValue("ref: %s" % d.extractInt(value["ref"].address))
d.putNumChild(0) d.putNumChild(0)
@@ -2213,8 +2251,8 @@ def qdump__QWeakPointer(d, value):
d.putValue("<invalid>") d.putValue("<invalid>")
d.putNumChild(0) d.putNumChild(0)
return return
weakref = int(d_ptr["weakref"]["_q_value"]) weakref = d.extractInt(d_ptr["weakref"].address)
strongref = int(d_ptr["strongref"]["_q_value"]) strongref = d.extractInt(d_ptr["strongref"].address)
d.check(strongref >= -1) d.check(strongref >= -1)
d.check(strongref <= weakref) d.check(strongref <= weakref)
d.check(weakref <= 10*1000*1000) d.check(weakref <= 10*1000*1000)

View File

@@ -172,6 +172,9 @@ def qdump__std__list__QNX(d, value):
def qdump__std____debug__list(d, value): def qdump__std____debug__list(d, value):
qdump__std__list(d, value) qdump__std__list(d, value)
def qdump__std____cxx11__list(d, value):
qdump__std__list(d, value)
def qform__std__map(): def qform__std__map():
return mapForms() return mapForms()
@@ -289,7 +292,12 @@ def stdTreeIteratorHelper(d, value):
nodeTypeName = str(value.type).replace("_Rb_tree_iterator", "_Rb_tree_node", 1) nodeTypeName = str(value.type).replace("_Rb_tree_iterator", "_Rb_tree_node", 1)
nodeTypeName = nodeTypeName.replace("_Rb_tree_const_iterator", "_Rb_tree_node", 1) nodeTypeName = nodeTypeName.replace("_Rb_tree_const_iterator", "_Rb_tree_node", 1)
nodeType = d.lookupType(nodeTypeName + '*') nodeType = d.lookupType(nodeTypeName + '*')
data = node.cast(nodeType).dereference()["_M_value_field"] nnode = node.cast(nodeType).dereference()
try:
data = nnode["_M_value_field"]
except: # GCC 5.x, C++11.
data = nnode["_M_storage"] # __gnu_cxx::__aligned_membuf<T>
data = data.cast(d.templateArgument(data.type, 0))
first = d.childWithName(data, "first") first = d.childWithName(data, "first")
if first: if first:
d.putSubItem("first", first) d.putSubItem("first", first)
@@ -463,7 +471,7 @@ def qdump__std____1__wstring(d, value):
size = firstByte / 2 size = firstByte / 2
data = base + 4 data = base + 4
d.putCharArrayHelper(data, size, 4) d.putCharArrayHelper(data, size, 4)
d.putType("std::xxwstring") d.putType("std::wstring")
def qdump__std__shared_ptr(d, value): def qdump__std__shared_ptr(d, value):
@@ -796,13 +804,29 @@ def qform__std__wstring():
def qdump__std__wstring(d, value): def qdump__std__wstring(d, value):
charSize = d.lookupType('wchar_t').sizeof charSize = d.lookupType('wchar_t').sizeof
# HACK: Shift format by 4 to account for latin1 and utf8
qdump__std__stringHelper1(d, value, charSize, d.currentItemFormat()) qdump__std__stringHelper1(d, value, charSize, d.currentItemFormat())
def qdump__std__basic_string(d, value): def qdump__std__basic_string(d, value):
innerType = d.templateArgument(value.type, 0) innerType = d.templateArgument(value.type, 0)
qdump__std__stringHelper1(d, value, innerType.sizeof, d.currentItemFormat()) qdump__std__stringHelper1(d, value, innerType.sizeof, d.currentItemFormat())
def qdump__std____cxx11__basic_string(d, value):
innerType = d.templateArgument(value.type, 0)
data = value["_M_dataplus"]["_M_p"]
size = int(value["_M_string_length"])
d.check(0 <= size) #and size <= alloc and alloc <= 100*1000*1000)
d.putCharArrayHelper(data, size, innerType.sizeof, d.currentItemFormat())
def qform__std____cxx11__string(d, value):
qdump__std____cxx11__basic_string(d, value)
# Needed only to trigger the form report above.
def qform__std____cxx11__string():
return qform__std__string()
def qform__std____cxx11__wstring():
return qform__std__wstring()
def qdump__std____1__basic_string(d, value): def qdump__std____1__basic_string(d, value):
innerType = str(d.templateArgument(value.type, 0)) innerType = str(d.templateArgument(value.type, 0))
if innerType == "char": if innerType == "char":

File diff suppressed because it is too large Load Diff

View File

@@ -159,6 +159,28 @@ static inline int askMsgSendFailed()
QMessageBox::Retry); QMessageBox::Retry);
} }
static const char *setHighDpiEnvironmentVariable()
{
const char* envVarName = 0;
static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO";
#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
if (Utils::HostOsInfo().isWindowsHost()
&& !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO)) {
envVarName = ENV_VAR_QT_DEVICE_PIXEL_RATIO;
qputenv(envVarName, "auto");
}
#else
if (Utils::HostOsInfo().isWindowsHost()
&& !qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) // legacy in 5.6, but still functional
&& !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR")
&& !qEnvironmentVariableIsSet("QT_SCALE_FACTOR")
&& !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
}
#endif // < Qt 5.6
return envVarName;
}
// taken from utils/fileutils.cpp. We can not use utils here since that depends app_version.h. // taken from utils/fileutils.cpp. We can not use utils here since that depends app_version.h.
static bool copyRecursively(const QString &srcFilePath, static bool copyRecursively(const QString &srcFilePath,
const QString &tgtFilePath) const QString &tgtFilePath)
@@ -280,12 +302,7 @@ static const char *SHARE_PATH =
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0)) const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable();
if (Utils::HostOsInfo().isWindowsHost()
&& !qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO")) {
qputenv("QT_DEVICE_PIXEL_RATIO", "auto");
}
#endif // < Qt 5.6
QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false")); QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false"));
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@@ -299,6 +316,9 @@ int main(int argc, char **argv)
SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv); SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);
if (highDpiEnvironmentVariable)
qunsetenv(highDpiEnvironmentVariable);
if (Utils::HostOsInfo().isWindowsHost() if (Utils::HostOsInfo().isWindowsHost()
&& !qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && !qFuzzyCompare(qApp->devicePixelRatio(), 1.0)
&& QApplication::style()->objectName().startsWith( && QApplication::style()->objectName().startsWith(

View File

@@ -54,9 +54,11 @@ FileContainer::FileContainer(const Utf8String &filePath,
FileContainer::FileContainer(const Utf8String &filePath, FileContainer::FileContainer(const Utf8String &filePath,
const Utf8String &projectPartId, const Utf8String &projectPartId,
const Utf8StringVector &fileArguments,
quint32 documentRevision) quint32 documentRevision)
: filePath_(filePath), : filePath_(filePath),
projectPartId_(projectPartId), projectPartId_(projectPartId),
fileArguments_(fileArguments),
documentRevision_(documentRevision), documentRevision_(documentRevision),
hasUnsavedFileContent_(false) hasUnsavedFileContent_(false)
{ {
@@ -72,6 +74,11 @@ const Utf8String &FileContainer::projectPartId() const
return projectPartId_; return projectPartId_;
} }
const Utf8StringVector &FileContainer::fileArguments() const
{
return fileArguments_;
}
const Utf8String &FileContainer::unsavedFileContent() const const Utf8String &FileContainer::unsavedFileContent() const
{ {
return unsavedFileContent_; return unsavedFileContent_;
@@ -91,6 +98,7 @@ QDataStream &operator<<(QDataStream &out, const FileContainer &container)
{ {
out << container.filePath_; out << container.filePath_;
out << container.projectPartId_; out << container.projectPartId_;
out << container.fileArguments_;
out << container.unsavedFileContent_; out << container.unsavedFileContent_;
out << container.documentRevision_; out << container.documentRevision_;
out << container.hasUnsavedFileContent_; out << container.hasUnsavedFileContent_;
@@ -102,6 +110,7 @@ QDataStream &operator>>(QDataStream &in, FileContainer &container)
{ {
in >> container.filePath_; in >> container.filePath_;
in >> container.projectPartId_; in >> container.projectPartId_;
in >> container.fileArguments_;
in >> container.unsavedFileContent_; in >> container.unsavedFileContent_;
in >> container.documentRevision_; in >> container.documentRevision_;
in >> container.hasUnsavedFileContent_; in >> container.hasUnsavedFileContent_;
@@ -127,6 +136,7 @@ QDebug operator<<(QDebug debug, const FileContainer &container)
debug.nospace() << "FileContainer(" debug.nospace() << "FileContainer("
<< container.filePath() << ", " << container.filePath() << ", "
<< container.projectPartId() << ", " << container.projectPartId() << ", "
<< container.fileArguments() << ", "
<< container.documentRevision(); << container.documentRevision();
if (container.hasUnsavedFileContent()) { if (container.hasUnsavedFileContent()) {
@@ -147,6 +157,7 @@ void PrintTo(const FileContainer &container, ::std::ostream* os)
*os << "FileContainer(" *os << "FileContainer("
<< container.filePath().constData() << ", " << container.filePath().constData() << ", "
<< container.projectPartId().constData() << ", " << container.projectPartId().constData() << ", "
<< container.fileArguments().constData() << ", "
<< container.documentRevision(); << container.documentRevision();
if (container.hasUnsavedFileContent()) if (container.hasUnsavedFileContent())

View File

@@ -34,6 +34,7 @@
#include <clangbackendipc_global.h> #include <clangbackendipc_global.h>
#include <utf8string.h> #include <utf8string.h>
#include <utf8stringvector.h>
#include <QMetaType> #include <QMetaType>
@@ -54,10 +55,12 @@ public:
quint32 documentRevision = 0); quint32 documentRevision = 0);
FileContainer(const Utf8String &filePath, FileContainer(const Utf8String &filePath,
const Utf8String &projectPartId, const Utf8String &projectPartId,
const Utf8StringVector &fileArguments,
quint32 documentRevision); quint32 documentRevision);
const Utf8String &filePath() const; const Utf8String &filePath() const;
const Utf8String &projectPartId() const; const Utf8String &projectPartId() const;
const Utf8StringVector &fileArguments() const;
const Utf8String &unsavedFileContent() const; const Utf8String &unsavedFileContent() const;
bool hasUnsavedFileContent() const; bool hasUnsavedFileContent() const;
quint32 documentRevision() const; quint32 documentRevision() const;
@@ -65,6 +68,7 @@ public:
private: private:
Utf8String filePath_; Utf8String filePath_;
Utf8String projectPartId_; Utf8String projectPartId_;
Utf8StringVector fileArguments_;
Utf8String unsavedFileContent_; Utf8String unsavedFileContent_;
quint32 documentRevision_; quint32 documentRevision_;
bool hasUnsavedFileContent_ = false; bool hasUnsavedFileContent_ = false;

View File

@@ -1549,6 +1549,7 @@ CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snaps
: _snapshot(snapshot) : _snapshot(snapshot)
, _control(QSharedPointer<Control>(new Control)) , _control(QSharedPointer<Control>(new Control))
, _expandTemplates(false) , _expandTemplates(false)
, _depth(0)
{ {
_globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0); _globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0);
_currentLookupScope = _globalNamespace; _currentLookupScope = _globalNamespace;
@@ -1978,8 +1979,13 @@ void CreateBindings::initializeSubst(Clone &cloner,
{ {
const unsigned argumentCountOfSpecialization = specialization->templateParameterCount(); const unsigned argumentCountOfSpecialization = specialization->templateParameterCount();
if (_depth > 15)
return;
++_depth;
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i); resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i);
--_depth;
} }
} // namespace CPlusPlus } // namespace CPlusPlus

View File

@@ -209,6 +209,7 @@ private:
LookupScope *_globalNamespace; LookupScope *_globalNamespace;
LookupScope *_currentLookupScope; LookupScope *_currentLookupScope;
bool _expandTemplates; bool _expandTemplates;
int _depth;
}; };
class CPLUSPLUS_EXPORT LookupContext class CPLUSPLUS_EXPORT LookupContext

View File

@@ -102,9 +102,12 @@ TimelineRenderPass::State *TimelineSelectionRenderPass::update(
top = TimelineModel::defaultRowHeight() * (row + 1) - height; top = TimelineModel::defaultRowHeight() * (row + 1) - height;
} }
qint64 startTime = model->startTime(selectedItem); qint64 startTime = qBound(parentState->start(), model->startTime(selectedItem),
qint64 left = qMax(startTime - parentState->start(), (qint64)0); parentState->end());
qint64 width = qMin(parentState->end() - startTime, model->duration(selectedItem)); qint64 endTime = qBound(parentState->start(), model->endTime(selectedItem),
parentState->end());
qint64 left = startTime - parentState->start();
qint64 width = endTime - startTime;
// Construct from upper left and lower right for better precision. When constructing from // Construct from upper left and lower right for better precision. When constructing from
// left and width the error on the left border is inherited by the right border. Like this // left and width the error on the left border is inherited by the right border. Like this

View File

@@ -37,6 +37,7 @@
#include <QLabel> #include <QLabel>
#include <QPainter> #include <QPainter>
#include <QPixmap> #include <QPixmap>
#include <QPointer>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include <QTimer> #include <QTimer>
@@ -130,14 +131,20 @@ namespace FadingIndicator {
void showText(QWidget *parent, const QString &text, TextSize size) void showText(QWidget *parent, const QString &text, TextSize size)
{ {
auto indicator = new Internal::FadingIndicatorPrivate(parent, size); static QPointer<Internal::FadingIndicatorPrivate> indicator;
if (indicator)
delete indicator;
indicator = new Internal::FadingIndicatorPrivate(parent, size);
indicator->setText(text); indicator->setText(text);
indicator->run(2500); // deletes itself indicator->run(2500); // deletes itself
} }
void showPixmap(QWidget *parent, const QString &pixmap) void showPixmap(QWidget *parent, const QString &pixmap)
{ {
auto indicator = new Internal::FadingIndicatorPrivate(parent, LargeText); static QPointer<Internal::FadingIndicatorPrivate> indicator;
if (indicator)
delete indicator;
indicator = new Internal::FadingIndicatorPrivate(parent, LargeText);
indicator->setPixmap(pixmap); indicator->setPixmap(pixmap);
indicator->run(300); // deletes itself indicator->run(300); // deletes itself
} }

View File

@@ -30,7 +30,6 @@
#include "fileutils_mac.h" #include "fileutils_mac.h"
#include "autoreleasepool.h"
#include "qtcassert.h" #include "qtcassert.h"
#include <QDir> #include <QDir>
@@ -44,45 +43,46 @@ namespace Internal {
QUrl filePathUrl(const QUrl &url) QUrl filePathUrl(const QUrl &url)
{ {
Utils::AutoreleasePool pool; Q_UNUSED(pool)
QUrl ret = url; QUrl ret = url;
NSURL *nsurl = url.toNSURL(); @autoreleasepool {
if ([nsurl isFileReferenceURL]) NSURL *nsurl = url.toNSURL();
ret = QUrl::fromNSURL([nsurl filePathURL]); if ([nsurl isFileReferenceURL])
ret = QUrl::fromNSURL([nsurl filePathURL]);
}
return ret; return ret;
} }
QString normalizePathName(const QString &filePath) QString normalizePathName(const QString &filePath)
{ {
AutoreleasePool pool; Q_UNUSED(pool)
// NSURL getResourceValue returns values based on the cleaned path so we need to work on that.
// It also returns the disk name for "/" and "/.." and errors on "" and relative paths,
// so avoid that
// we cannot know the normalized name for relative paths
if (QFileInfo(filePath).isRelative())
return filePath;
QString result; QString result;
QString path = QDir::cleanPath(filePath); @autoreleasepool {
// avoid empty paths and paths like "/../foo" or "/.." // NSURL getResourceValue returns values based on the cleaned path so we need to work on that.
if (path.isEmpty() || path.contains(QLatin1String("/../")) || path.endsWith(QLatin1String("/.."))) // It also returns the disk name for "/" and "/.." and errors on "" and relative paths,
return filePath; // so avoid that
while (path != QLatin1String("/") /*be defensive->*/&& path != QLatin1String(".") && !path.isEmpty()) { // we cannot know the normalized name for relative paths
QFileInfo info(path); if (QFileInfo(filePath).isRelative())
NSURL *nsurl = [NSURL fileURLWithPath:path.toNSString()]; return filePath;
NSString *out;
QString component; QString path = QDir::cleanPath(filePath);
if ([nsurl getResourceValue:(NSString **)&out forKey:NSURLNameKey error:nil]) // avoid empty paths and paths like "/../foo" or "/.."
component = QString::fromNSString(out); if (path.isEmpty() || path.contains(QLatin1String("/../")) || path.endsWith(QLatin1String("/..")))
else // e.g. if the full path does not exist return filePath;
component = info.fileName();
result.prepend(QLatin1Char('/') + component); while (path != QLatin1String("/") /*be defensive->*/&& path != QLatin1String(".") && !path.isEmpty()) {
path = info.path(); QFileInfo info(path);
NSURL *nsurl = [NSURL fileURLWithPath:path.toNSString()];
NSString *out;
QString component;
if ([nsurl getResourceValue:(NSString **)&out forKey:NSURLNameKey error:nil])
component = QString::fromNSString(out);
else // e.g. if the full path does not exist
component = info.fileName();
result.prepend(QLatin1Char('/') + component);
path = info.path();
}
QTC_ASSERT(path == QLatin1String("/"), return filePath);
} }
QTC_ASSERT(path == QLatin1String("/"), return filePath);
return result; return result;
} }

View File

@@ -230,13 +230,19 @@ bool MimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
const QString resolvedParent = provider()->resolveAlias(parent); const QString resolvedParent = provider()->resolveAlias(parent);
//Q_ASSERT(provider()->resolveAlias(mime) == mime); //Q_ASSERT(provider()->resolveAlias(mime) == mime);
QStack<QString> toCheck; QStack<QString> toCheck;
QSet<QString> seen; // avoid endless loop on bogus mime data
toCheck.push(mime); toCheck.push(mime);
seen.insert(mime);
while (!toCheck.isEmpty()) { while (!toCheck.isEmpty()) {
const QString current = toCheck.pop(); const QString current = toCheck.pop();
if (current == resolvedParent) if (current == resolvedParent)
return true; return true;
foreach (const QString &par, provider()->parents(current)) foreach (const QString &par, provider()->parents(current)) {
toCheck.push(par); int seenSize = seen.size();
seen.insert(par);
if (seen.size() != seenSize) // haven't seen before, so add
toCheck.push(par);
}
} }
return false; return false;
} }

View File

@@ -66,11 +66,11 @@ void setCreatorTheme(Theme *theme)
m_creatorTheme = theme; m_creatorTheme = theme;
} }
Theme::Theme(const QString &name, QObject *parent) Theme::Theme(const QString &id, QObject *parent)
: QObject(parent) : QObject(parent)
, d(new ThemePrivate) , d(new ThemePrivate)
{ {
d->name = name; d->id = id;
} }
Theme::~Theme() Theme::~Theme()
@@ -88,6 +88,11 @@ QStringList Theme::preferredStyles() const
return d->preferredStyles; return d->preferredStyles;
} }
QString Theme::id() const
{
return d->id;
}
bool Theme::flag(Theme::Flag f) const bool Theme::flag(Theme::Flag f) const
{ {
return d->flags[f]; return d->flags[f];
@@ -130,14 +135,14 @@ QString Theme::filePath() const
return d->fileName; return d->fileName;
} }
QString Theme::name() const QString Theme::displayName() const
{ {
return d->name; return d->displayName;
} }
void Theme::setName(const QString &name) void Theme::setDisplayName(const QString &name)
{ {
d->name = name; d->displayName = name;
} }
QVariantHash Theme::values() const QVariantHash Theme::values() const
@@ -185,7 +190,7 @@ void Theme::writeSettings(const QString &filename) const
const QMetaObject &m = *metaObject(); const QMetaObject &m = *metaObject();
{ {
settings.setValue(QLatin1String("ThemeName"), d->name); settings.setValue(QLatin1String("ThemeName"), d->displayName);
settings.setValue(QLatin1String("PreferredStyles"), d->preferredStyles); settings.setValue(QLatin1String("PreferredStyles"), d->preferredStyles);
} }
{ {
@@ -264,7 +269,7 @@ void Theme::readSettings(QSettings &settings)
const QMetaObject &m = *metaObject(); const QMetaObject &m = *metaObject();
{ {
d->name = settings.value(QLatin1String("ThemeName"), QLatin1String("unnamed")).toString(); d->displayName = settings.value(QLatin1String("ThemeName"), QLatin1String("unnamed")).toString();
d->preferredStyles = settings.value(QLatin1String("PreferredStyles")).toStringList(); d->preferredStyles = settings.value(QLatin1String("PreferredStyles")).toStringList();
d->preferredStyles.removeAll(QLatin1String("")); d->preferredStyles.removeAll(QLatin1String(""));
} }

View File

@@ -54,7 +54,7 @@ class QTCREATOR_UTILS_EXPORT Theme : public QObject
Q_ENUMS(WidgetStyle) Q_ENUMS(WidgetStyle)
public: public:
Theme(const QString &name, QObject *parent = 0); Theme(const QString &id, QObject *parent = 0);
~Theme(); ~Theme();
enum Color { enum Color {
@@ -265,9 +265,10 @@ public:
QPalette palette() const; QPalette palette() const;
QStringList preferredStyles() const; QStringList preferredStyles() const;
QString id() const;
QString filePath() const; QString filePath() const;
QString name() const; QString displayName() const;
void setName(const QString &name); void setDisplayName(const QString &displayName);
QVariantHash values() const; QVariantHash values() const;

View File

@@ -44,8 +44,9 @@ class QTCREATOR_UTILS_EXPORT ThemePrivate
public: public:
ThemePrivate(); ThemePrivate();
QString id;
QString fileName; QString fileName;
QString name; QString displayName;
QStringList preferredStyles; QStringList preferredStyles;
QVector<QPair<QColor, QString> > colors; QVector<QPair<QColor, QString> > colors;
QVector<QString> imageFiles; QVector<QString> imageFiles;

View File

@@ -210,7 +210,7 @@ FORMS += $$PWD/filewizardpage.ui \
RESOURCES += $$PWD/utils.qrc RESOURCES += $$PWD/utils.qrc
osx { osx {
HEADERS += $$PWD/autoreleasepool.h \ HEADERS += \
$$PWD/fileutils_mac.h $$PWD/fileutils_mac.h
OBJECTIVE_SOURCES += \ OBJECTIVE_SOURCES += \
$$PWD/fileutils_mac.mm $$PWD/fileutils_mac.mm

View File

@@ -41,7 +41,7 @@ const char ACTION_ID[] = "BareMetal.Action";
const char MENU_ID[] = "BareMetal.Menu"; const char MENU_ID[] = "BareMetal.Menu";
const char BAREMETAL_SETTINGS_CATEGORY[] = "ZZ.BareMetal"; const char BAREMETAL_SETTINGS_CATEGORY[] = "ZZ.BareMetal";
const char BAREMETAL_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("BareMetal", "BareMetal"); const char BAREMETAL_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("BareMetal", "Bare Metal");
const char BAREMETAL_SETTINGS_CATEGORY_ICON[] = ":/baremetal/images/QtBareMetal.png"; const char BAREMETAL_SETTINGS_CATEGORY_ICON[] = ":/baremetal/images/QtBareMetal.png";
const char GDB_PROVIDERS_SETTINGS_ID[] = "AA.BareMetal.GdbServerProvidersOptions"; const char GDB_PROVIDERS_SETTINGS_ID[] = "AA.BareMetal.GdbServerProvidersOptions";

View File

@@ -306,12 +306,44 @@ void IpcCommunicator::initializeBackend()
initializeBackendWithCurrentData(); initializeBackendWithCurrentData();
} }
void IpcCommunicator::registerEmptyProjectForProjectLessFiles() static QStringList projectPartOptions(const CppTools::ProjectPart::Ptr &projectPart)
{
QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
CppTools::ProjectFile::Unclassified); // No language option
if (PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart))
options += ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName());
return options;
}
static ClangBackEnd::ProjectPartContainer toProjectPartContainer(
const CppTools::ProjectPart::Ptr &projectPart)
{
const QStringList options = projectPartOptions(projectPart);
return ClangBackEnd::ProjectPartContainer(projectPart->id(), Utf8StringVector(options));
}
static QVector<ClangBackEnd::ProjectPartContainer> toProjectPartContainers(
const QList<CppTools::ProjectPart::Ptr> projectParts)
{
QVector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
projectPartContainers.reserve(projectParts.size());
foreach (const CppTools::ProjectPart::Ptr &projectPart, projectParts)
projectPartContainers << toProjectPartContainer(projectPart);
return projectPartContainers;
}
void IpcCommunicator::registerFallbackProjectPart()
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection.isConnected());
registerProjectPartsForEditor({ClangBackEnd::ProjectPartContainer(
Utf8String(), const auto projectPart = CppTools::CppModelManager::instance()->fallbackProjectPart();
Utf8StringVector())}); const auto projectPartContainer = toProjectPartContainer(projectPart);
registerProjectPartsForEditor({projectPartContainer});
} }
void IpcCommunicator::registerCurrentProjectParts() void IpcCommunicator::registerCurrentProjectParts()
@@ -343,49 +375,12 @@ void IpcCommunicator::registerCurrentCodeModelUiHeaders()
updateUnsavedFile(es->fileName(), es->contents(), es->revision()); updateUnsavedFile(es->fileName(), es->contents(), es->revision());
} }
static QStringList projectPartMessageLine(const CppTools::ProjectPart::Ptr &projectPart)
{
QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
CppTools::ProjectFile::Unclassified); // No language option
if (PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart))
options += ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName());
return options;
}
static ClangBackEnd::ProjectPartContainer toProjectPartContainer(
const CppTools::ProjectPart::Ptr &projectPart)
{
const QStringList arguments = projectPartMessageLine(projectPart);
return ClangBackEnd::ProjectPartContainer(projectPart->id(), Utf8StringVector(arguments));
}
static QVector<ClangBackEnd::ProjectPartContainer> toProjectPartContainers(
const QList<CppTools::ProjectPart::Ptr> projectParts)
{
QVector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
projectPartContainers.reserve(projectParts.size());
foreach (const CppTools::ProjectPart::Ptr &projectPart, projectParts)
projectPartContainers << toProjectPartContainer(projectPart);
return projectPartContainers;
}
void IpcCommunicator::registerProjectsParts(const QList<CppTools::ProjectPart::Ptr> projectParts) void IpcCommunicator::registerProjectsParts(const QList<CppTools::ProjectPart::Ptr> projectParts)
{ {
const auto projectPartContainers = toProjectPartContainers(projectParts); const auto projectPartContainers = toProjectPartContainers(projectParts);
registerProjectPartsForEditor(projectPartContainers); registerProjectPartsForEditor(projectPartContainers);
} }
void IpcCommunicator::registerTranslationUnit(TextEditor::TextDocument *document)
{
const QString filePath = document->filePath().toString();
const QString projectPartId = Utils::projectPartIdForFile(filePath);
registerTranslationUnitsForEditor({{Utf8String(filePath),
Utf8String(projectPartId),
uint(document->document()->revision())}});
}
void IpcCommunicator::updateTranslationUnitFromCppEditorDocument(const QString &filePath) void IpcCommunicator::updateTranslationUnitFromCppEditorDocument(const QString &filePath)
{ {
const auto document = CppTools::CppModelManager::instance()->cppEditorDocument(filePath); const auto document = CppTools::CppModelManager::instance()->cppEditorDocument(filePath);
@@ -426,25 +421,6 @@ void setLastSentDocumentRevision(const QString &filePath,
} }
} }
void IpcCommunicator::registerTranslationUnit(const QString &filePath,
const QByteArray &contents,
uint documentRevision)
{
const QString projectPartId = Utils::projectPartIdForFile(filePath);
if (documentHasChanged(filePath)) {
const bool hasUnsavedContent = true;
registerTranslationUnitsForEditor({{filePath,
projectPartId,
Utf8String::fromByteArray(contents),
hasUnsavedContent,
documentRevision}});
setLastSentDocumentRevision(filePath, documentRevision);
}
}
void IpcCommunicator::updateTranslationUnit(const QString &filePath, void IpcCommunicator::updateTranslationUnit(const QString &filePath,
const QByteArray &contents, const QByteArray &contents,
uint documentRevision) uint documentRevision)
@@ -495,6 +471,7 @@ void IpcCommunicator::requestDiagnostics(Core::IDocument *document)
requestDiagnostics(FileContainer(filePath, requestDiagnostics(FileContainer(filePath,
projectPartId, projectPartId,
Utf8StringVector(),
textDocument->document()->revision())); textDocument->document()->revision()));
} }
@@ -547,7 +524,7 @@ void IpcCommunicator::onCoreAboutToClose()
void IpcCommunicator::initializeBackendWithCurrentData() void IpcCommunicator::initializeBackendWithCurrentData()
{ {
registerEmptyProjectForProjectLessFiles(); registerFallbackProjectPart();
registerCurrentProjectParts(); registerCurrentProjectParts();
registerCurrentCppEditorDocuments(); registerCurrentCppEditorDocuments();
registerCurrentCodeModelUiHeaders(); registerCurrentCodeModelUiHeaders();

View File

@@ -133,8 +133,6 @@ public:
void registerProjectsParts(const QList<CppTools::ProjectPart::Ptr> projectParts); void registerProjectsParts(const QList<CppTools::ProjectPart::Ptr> projectParts);
void registerTranslationUnit(TextEditor::TextDocument *document);
void registerTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision);
void updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document); void updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document);
void updateTranslationUnit(Core::IDocument *document); void updateTranslationUnit(Core::IDocument *document);
void updateUnsavedFile(Core::IDocument *document); void updateUnsavedFile(Core::IDocument *document);
@@ -146,6 +144,8 @@ public:
void requestDiagnostics(Core::IDocument *document); void requestDiagnostics(Core::IDocument *document);
void updateChangeContentStartPosition(const QString &filePath, int position); void updateChangeContentStartPosition(const QString &filePath, int position);
void registerFallbackProjectPart();
public: // for tests public: // for tests
IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender); IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender);
void killBackendProcess(); void killBackendProcess();
@@ -158,7 +158,6 @@ private:
void initializeBackend(); void initializeBackend();
void initializeBackendWithCurrentData(); void initializeBackendWithCurrentData();
void registerEmptyProjectForProjectLessFiles();
void registerCurrentProjectParts(); void registerCurrentProjectParts();
void registerCurrentCppEditorDocuments(); void registerCurrentCppEditorDocuments();
void registerCurrentCodeModelUiHeaders(); void registerCurrentCodeModelUiHeaders();

View File

@@ -58,6 +58,11 @@ static void initializeTextMarks()
Utils::Theme::ClangCodeModel_Error_TextMarkColor); Utils::Theme::ClangCodeModel_Error_TextMarkColor);
} }
ClangCodeModelPlugin::ClangCodeModelPlugin()
{
qRegisterMetaType<CppTools::ProjectPart::Ptr>();
}
bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage) bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{ {
Q_UNUSED(arguments) Q_UNUSED(arguments)

View File

@@ -50,6 +50,8 @@ class ClangCodeModelPlugin: public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json") Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json")
public: public:
ClangCodeModelPlugin();
bool initialize(const QStringList &arguments, QString *errorMessage); bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized(); void extensionsInitialized();

View File

@@ -99,6 +99,7 @@ void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InM
State state_ = state(); State state_ = state();
state_.projectPart = determineProjectPart(filePath(), configuration(), state_); state_.projectPart = determineProjectPart(filePath(), configuration(), state_);
setState(state_); setState(state_);
emit projectPartDetermined(state_.projectPart);
// Determine message line arguments // Determine message line arguments
const QStringList options = createOptions(filePath(), state_.projectPart, true); const QStringList options = createOptions(filePath(), state_.projectPart, true);

View File

@@ -50,6 +50,9 @@ public:
QList<SemanticMarker::Range> ifdefedOutBlocks() const; QList<SemanticMarker::Range> ifdefedOutBlocks() const;
SemanticMarker::Ptr semanticMarker() const; SemanticMarker::Ptr semanticMarker() const;
signals:
void projectPartDetermined(CppTools::ProjectPart::Ptr projectPart);
private: private:
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override; void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override;

View File

@@ -41,7 +41,9 @@
#include <diagnosticcontainer.h> #include <diagnosticcontainer.h>
#include <sourcelocationcontainer.h> #include <sourcelocationcontainer.h>
#include <cpptools/cpptoolsplugin.h> #include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cppprojects.h>
#include <cpptools/cpptoolsreuse.h>
#include <cpptools/cppworkingcopy.h> #include <cpptools/cppworkingcopy.h>
#include <texteditor/convenience.h> #include <texteditor/convenience.h>
@@ -87,6 +89,9 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
, m_semanticHighlighter(document) , m_semanticHighlighter(document)
, m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false) , m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
{ {
connect(m_parser.data(), &ClangEditorDocumentParser::projectPartDetermined,
this, &ClangEditorDocumentProcessor::onParserDeterminedProjectPart);
// Forwarding the semantic info from the builtin processor enables us to provide all // Forwarding the semantic info from the builtin processor enables us to provide all
// editor (widget) related features that are not yet implemented by the clang plugin. // editor (widget) related features that are not yet implemented by the clang plugin.
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated, connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
@@ -230,9 +235,10 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa
&& (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart)); && (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart));
} }
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor() void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
CppTools::ProjectPart::Ptr projectPart)
{ {
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPart(); QTC_ASSERT(projectPart, return);
if (isProjectPartLoadedOrIsFallback(projectPart)) { if (isProjectPartLoadedOrIsFallback(projectPart)) {
updateTranslationUnitForEditor(projectPart.data()); updateTranslationUnitForEditor(projectPart.data());
@@ -242,6 +248,12 @@ void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
} }
} }
void ClangEditorDocumentProcessor::onParserDeterminedProjectPart(
CppTools::ProjectPart::Ptr projectPart)
{
updateProjectPartAndTranslationUnitForEditor(projectPart);
}
void ClangEditorDocumentProcessor::onParserFinished() void ClangEditorDocumentProcessor::onParserFinished()
{ {
if (revision() != m_parserRevision) if (revision() != m_parserRevision)
@@ -253,8 +265,6 @@ void ClangEditorDocumentProcessor::onParserFinished()
// Run semantic highlighter // Run semantic highlighter
m_semanticHighlighter.run(); m_semanticHighlighter.run();
updateProjectPartAndTranslationUnitForEditor();
} }
void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart) void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart)
@@ -294,13 +304,37 @@ void ClangEditorDocumentProcessor::requestDiagnostics()
} }
} }
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
{
if (projectPart)
return *projectPart;
return *CppTools::CppModelManager::instance()->fallbackProjectPart().data();
}
static QStringList languageOptions(const QString &filePath, CppTools::ProjectPart *projectPart)
{
const auto theProjectPart = projectPartForLanguageOption(projectPart);
CppTools::CompilerOptionsBuilder builder(theProjectPart);
builder.addLanguageOption(CppTools::ProjectFile::classify(filePath));
return builder.options();
}
static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart)
{
return QStringList(languageOptions(filePath, projectPart))
+ CppTools::codeModelSettings()->extraClangOptions();
}
ClangBackEnd::FileContainer ClangBackEnd::FileContainer
ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) const ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) const
{ {
if (projectPart) const auto projectPartId = projectPart
return {filePath(), projectPart->id(), revision()}; ? Utf8String::fromString(projectPart->id())
: Utf8String();
const QStringList theFileArguments = fileArguments(filePath(), projectPart);
return {filePath(), Utf8String(), revision()}; return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()};
} }
} // namespace Internal } // namespace Internal

View File

@@ -85,10 +85,11 @@ public:
static ClangEditorDocumentProcessor *get(const QString &filePath); static ClangEditorDocumentProcessor *get(const QString &filePath);
private slots: private slots:
void onParserDeterminedProjectPart(CppTools::ProjectPart::Ptr projectPart);
void onParserFinished(); void onParserFinished();
private: private:
void updateProjectPartAndTranslationUnitForEditor(); void updateProjectPartAndTranslationUnitForEditor(CppTools::ProjectPart::Ptr projectPart);
void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart); void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
void requestDiagnostics(CppTools::ProjectPart *projectPart); void requestDiagnostics(CppTools::ProjectPart *projectPart);
void requestDiagnostics(); void requestDiagnostics();

View File

@@ -300,7 +300,9 @@ void ModelManagerSupportClang::onProjectPartsUpdated(ProjectExplorer::Project *p
QTC_ASSERT(project, return); QTC_ASSERT(project, return);
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project); const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
QTC_ASSERT(projectInfo.isValid(), return); QTC_ASSERT(projectInfo.isValid(), return);
m_ipcCommunicator.registerProjectsParts(projectInfo.projectParts()); m_ipcCommunicator.registerProjectsParts(projectInfo.projectParts());
m_ipcCommunicator.registerFallbackProjectPart();
} }
void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectPartIds) void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectPartIds)
@@ -308,6 +310,7 @@ void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectP
if (!projectPartIds.isEmpty()) { if (!projectPartIds.isEmpty()) {
unregisterTranslationUnitsWithProjectParts(projectPartIds); unregisterTranslationUnitsWithProjectParts(projectPartIds);
m_ipcCommunicator.unregisterProjectPartsForEditor(projectPartIds); m_ipcCommunicator.unregisterProjectPartsForEditor(projectPartIds);
m_ipcCommunicator.registerFallbackProjectPart();
} }
} }

View File

@@ -104,16 +104,6 @@ static QString getResourceDir()
return dir.canonicalPath(); return dir.canonicalPath();
} }
static bool maybeIncludeBorlandExtensions()
{
return
#if defined(CINDEX_VERSION) // clang 3.2 or higher
true;
#else
false;
#endif
}
class LibClangOptionsBuilder : public CompilerOptionsBuilder class LibClangOptionsBuilder : public CompilerOptionsBuilder
{ {
public: public:
@@ -122,13 +112,13 @@ public:
if (projectPart.isNull()) if (projectPart.isNull())
return QStringList(); return QStringList();
LibClangOptionsBuilder optionsBuilder(projectPart); LibClangOptionsBuilder optionsBuilder(*projectPart.data());
if (verboseRunLog().isDebugEnabled()) if (verboseRunLog().isDebugEnabled())
optionsBuilder.add(QLatin1String("-v")); optionsBuilder.add(QLatin1String("-v"));
optionsBuilder.addLanguageOption(fileKind); optionsBuilder.addLanguageOption(fileKind);
optionsBuilder.addOptionsForLanguage(maybeIncludeBorlandExtensions()); optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.addToolchainAndProjectDefines();
@@ -137,15 +127,13 @@ public:
optionsBuilder.addHeaderPathOptions(); optionsBuilder.addHeaderPathOptions();
optionsBuilder.addProjectConfigFileInclude(); optionsBuilder.addProjectConfigFileInclude();
optionsBuilder.addDiagnosticOptions();
optionsBuilder.addExtraOptions(); optionsBuilder.addExtraOptions();
return optionsBuilder.options(); return optionsBuilder.options();
} }
private: private:
LibClangOptionsBuilder(const CppTools::ProjectPart::Ptr &projectPart) LibClangOptionsBuilder(const CppTools::ProjectPart &projectPart)
: CompilerOptionsBuilder(projectPart) : CompilerOptionsBuilder(projectPart)
{ {
} }
@@ -181,7 +169,7 @@ private:
static const QString wrappedQtHeaders = ICore::instance()->resourcePath() static const QString wrappedQtHeaders = ICore::instance()->resourcePath()
+ QLatin1String("/cplusplus/wrappedQtHeaders"); + QLatin1String("/cplusplus/wrappedQtHeaders");
if (m_projectPart->qtVersion != ProjectPart::NoQt) { if (m_projectPart.qtVersion != ProjectPart::NoQt) {
add(QLatin1String("-I") + wrappedQtHeaders); add(QLatin1String("-I") + wrappedQtHeaders);
add(QLatin1String("-I") + wrappedQtHeaders + QLatin1String("/QtCore")); add(QLatin1String("-I") + wrappedQtHeaders + QLatin1String("/QtCore"));
} }
@@ -189,9 +177,9 @@ private:
void addProjectConfigFileInclude() void addProjectConfigFileInclude()
{ {
if (!m_projectPart->projectConfigFile.isEmpty()) { if (!m_projectPart.projectConfigFile.isEmpty()) {
add(QLatin1String("-include")); add(QLatin1String("-include"));
add(m_projectPart->projectConfigFile); add(m_projectPart.projectConfigFile);
} }
} }
@@ -201,30 +189,7 @@ private:
add(QLatin1String("-fdiagnostics-show-note-include-stack")); add(QLatin1String("-fdiagnostics-show-note-include-stack"));
add(QLatin1String("-fmacro-backtrace-limit=0")); add(QLatin1String("-fmacro-backtrace-limit=0"));
add(QLatin1String("-fretain-comments-from-system-headers")); add(QLatin1String("-fretain-comments-from-system-headers"));
// TODO: -Xclang -ferror-limit -Xclang 0 ? add(QLatin1String("-ferror-limit=1000"));
}
void addDiagnosticOptions()
{
add(QStringLiteral("-fmessage-length=0"));
add(QStringLiteral("-fdiagnostics-show-note-include-stack"));
add(QStringLiteral("-fmacro-backtrace-limit=0"));
add(QStringLiteral("-fretain-comments-from-system-headers"));
add(QStringLiteral("-ferror-limit=1000"));
add(QStringLiteral("-Weverything"));
add(QStringLiteral("-Wno-c++98-compat"));
add(QStringLiteral("-Wno-c++98-compat-pedantic"));
add(QStringLiteral("-Wno-unused-macros"));
add(QStringLiteral("-Wno-newline-eof"));
add(QStringLiteral("-Wno-exit-time-destructors"));
add(QStringLiteral("-Wno-global-constructors"));
add(QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"));
add(QStringLiteral("-Wno-documentation"));
add(QStringLiteral("-Wno-shadow"));
if (m_projectPart->languageVersion >= ProjectPart::CXX98)
add(QStringLiteral("-Wno-missing-prototypes"));
} }
}; };

View File

@@ -1037,6 +1037,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile(
CppTools::Tests::ProjectOpenerAndCloser projectManager; CppTools::Tests::ProjectOpenerAndCloser projectManager;
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true); const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
QVERIFY(projectInfo.isValid()); QVERIFY(projectInfo.isValid());
QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
// Open file with ui object // Open file with ui object
const QString completionFile = testDir.absolutePath("mainwindow.cpp"); const QString completionFile = testDir.absolutePath("mainwindow.cpp");
@@ -1046,7 +1047,6 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile(
QVERIFY(openSource.succeeded()); QVERIFY(openSource.succeeded());
// ...and check comletions // ...and check comletions
QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
ProposalModel proposal = completionResults(openSource.editor()); ProposalModel proposal = completionResults(openSource.editor());
QVERIFY(hasItem(proposal, "menuBar")); QVERIFY(hasItem(proposal, "menuBar"));
QVERIFY(hasItem(proposal, "statusBar")); QVERIFY(hasItem(proposal, "statusBar"));

View File

@@ -37,6 +37,7 @@
#include "modemanager.h" #include "modemanager.h"
#include "infobar.h" #include "infobar.h"
#include "iwizardfactory.h" #include "iwizardfactory.h"
#include "themesettings.h"
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/documentmanager.h> #include <coreplugin/documentmanager.h>
@@ -48,6 +49,7 @@
#include <extensionsystem/pluginerroroverview.h> #include <extensionsystem/pluginerroroverview.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/macroexpander.h> #include <utils/macroexpander.h>
#include <utils/savefile.h> #include <utils/savefile.h>
@@ -58,7 +60,6 @@
#include <QtPlugin> #include <QtPlugin>
#include <QDebug> #include <QDebug>
#include <QDateTime> #include <QDateTime>
#include <QDir>
#include <QMenu> #include <QMenu>
using namespace Core; using namespace Core;
@@ -97,39 +98,13 @@ CorePlugin::~CorePlugin()
setCreatorTheme(0); setCreatorTheme(0);
} }
static QString absoluteThemePath(const QString &themeName, bool userProvidedTheme)
{
if (themeName.isEmpty())
return themeName;
QString res = QDir::fromNativeSeparators(themeName);
QFileInfo fi(res);
bool tryRawName = userProvidedTheme || fi.isAbsolute();
// Try the given name
if (tryRawName && fi.exists())
return fi.absoluteFilePath();
const QString suffix = QLatin1String("creatortheme");
// Try name.creatortheme
if (fi.suffix() != suffix) {
res = themeName + QLatin1Char('.') + suffix;
fi.setFile(res);
if (tryRawName && fi.exists())
return fi.absoluteFilePath();
}
if (fi.path().isEmpty())
return QString(); // absolute/relative path, but not found
// If only name was given, look it up in qtcreator/themes
res.prepend(ICore::resourcePath() + QLatin1String("/themes/"));
return QFileInfo::exists(res) ? res : QString();
}
void CorePlugin::parseArguments(const QStringList &arguments) void CorePlugin::parseArguments(const QStringList &arguments)
{ {
const QString defaultTheme = QLatin1String("default"); const Id settingsThemeId = Id::fromSetting(ICore::settings()->value(
QString themeName = ICore::settings()->value( QLatin1String(Constants::SETTINGS_THEME), QLatin1String("default")));
QLatin1String(Constants::SETTINGS_THEME), defaultTheme).toString(); Id themeId = settingsThemeId;
QColor overrideColor; QColor overrideColor;
bool presentationMode = false; bool presentationMode = false;
bool userProvidedTheme = false;
for (int i = 0; i < arguments.size(); ++i) { for (int i = 0; i < arguments.size(); ++i) {
if (arguments.at(i) == QLatin1String("-color")) { if (arguments.at(i) == QLatin1String("-color")) {
@@ -140,28 +115,27 @@ void CorePlugin::parseArguments(const QStringList &arguments)
if (arguments.at(i) == QLatin1String("-presentationMode")) if (arguments.at(i) == QLatin1String("-presentationMode"))
presentationMode = true; presentationMode = true;
if (arguments.at(i) == QLatin1String("-theme")) { if (arguments.at(i) == QLatin1String("-theme")) {
themeName = arguments.at(i + 1); themeId = Id::fromString(arguments.at(i + 1));
userProvidedTheme = true;
i++; i++;
} }
} }
const QList<ThemeEntry> availableThemes = ThemeSettings::availableThemes();
QString themeURI = absoluteThemePath(themeName, userProvidedTheme); int themeIndex = Utils::indexOf(availableThemes, Utils::equal(&ThemeEntry::id, themeId));
if (themeURI.isEmpty()) { if (themeIndex < 0) {
themeName = defaultTheme; themeIndex = Utils::indexOf(availableThemes,
themeURI = QStringLiteral("%1/themes/%2.creatortheme").arg(ICore::resourcePath()).arg(themeName); Utils::equal(&ThemeEntry::id, settingsThemeId));
if (themeURI.isEmpty()) { }
qCritical("%s", qPrintable(QCoreApplication::translate("Application", "No valid theme \"%1\"") if (themeIndex < 0)
.arg(themeName))); themeIndex = 0;
} if (themeIndex < availableThemes.size()) {
const ThemeEntry themeEntry = availableThemes.at(themeIndex);
QSettings themeSettings(themeEntry.filePath(), QSettings::IniFormat);
Theme *theme = new Theme(themeEntry.id().toString(), qApp);
theme->readSettings(themeSettings);
if (theme->flag(Theme::ApplyThemePaletteGlobally))
QApplication::setPalette(theme->palette());
setCreatorTheme(theme);
} }
QSettings themeSettings(themeURI, QSettings::IniFormat);
Theme *theme = new Theme(themeName, qApp);
theme->readSettings(themeSettings);
if (theme->flag(Theme::ApplyThemePaletteGlobally))
QApplication::setPalette(theme->palette());
setCreatorTheme(theme);
// defer creation of these widgets until here, // defer creation of these widgets until here,
// because they need a valid theme set // because they need a valid theme set
@@ -176,6 +150,10 @@ void CorePlugin::parseArguments(const QStringList &arguments)
bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage) bool CorePlugin::initialize(const QStringList &arguments, QString *errorMessage)
{ {
if (ThemeSettings::availableThemes().isEmpty()) {
*errorMessage = tr("No themes found in installation.");
return false;
}
new ActionManager(this); new ActionManager(this);
Theme::initialPalette(); // Initialize palette before setting it Theme::initialPalette(); // Initialize palette before setting it
qsrand(QDateTime::currentDateTime().toTime_t()); qsrand(QDateTime::currentDateTime().toTime_t());

View File

@@ -189,6 +189,7 @@ using namespace Core::Internal;
bool NewDialog::m_isRunning = false; bool NewDialog::m_isRunning = false;
QString NewDialog::m_lastCategory = QString(); QString NewDialog::m_lastCategory = QString();
QString NewDialog::m_lastPlatform = QString();
NewDialog::NewDialog(QWidget *parent) : NewDialog::NewDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
@@ -301,6 +302,9 @@ void NewDialog::showDialog()
{ {
QModelIndex idx; QModelIndex idx;
if (!m_lastPlatform.isEmpty())
m_ui->comboBox->setCurrentIndex(m_ui->comboBox->findData(m_lastPlatform));
if (!m_lastCategory.isEmpty()) if (!m_lastCategory.isEmpty())
foreach (QStandardItem* item, m_categoryItems) { foreach (QStandardItem* item, m_categoryItems) {
if (item->data(Qt::UserRole) == m_lastCategory) if (item->data(Qt::UserRole) == m_lastCategory)
@@ -446,6 +450,7 @@ void NewDialog::saveState()
QStandardItem *currentItem = m_model->itemFromIndex(m_twoLevelProxyModel->mapToSource(idx)); QStandardItem *currentItem = m_model->itemFromIndex(m_twoLevelProxyModel->mapToSource(idx));
if (currentItem) if (currentItem)
m_lastCategory = currentItem->data(Qt::UserRole).toString(); m_lastCategory = currentItem->data(Qt::UserRole).toString();
m_lastPlatform = m_ui->comboBox->currentData().toString();
} }
void NewDialog::accept() void NewDialog::accept()

View File

@@ -86,6 +86,7 @@ private:
void saveState(); void saveState();
static QString m_lastCategory; static QString m_lastCategory;
static QString m_lastPlatform;
static bool m_isRunning; static bool m_isRunning;
Ui::NewDialog *m_ui; Ui::NewDialog *m_ui;

View File

@@ -373,12 +373,15 @@ bool ShortcutSettingsWidget::filterColumn(const QString &filterString, QTreeWidg
int column) const int column) const
{ {
QString text; QString text;
if (column == item->columnCount() - 1) { if (column == item->columnCount() - 1) { // shortcut
// filter on the shortcut edit text // filter on the shortcut edit text
if (!item->data(0, Qt::UserRole).isValid()) if (!item->data(0, Qt::UserRole).isValid())
return true; return true;
ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(item->data(0, Qt::UserRole)); ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(item->data(0, Qt::UserRole));
text = keySequenceToEditString(scitem->m_key); text = keySequenceToEditString(scitem->m_key);
} else if (column == 0 && item->data(0, Qt::UserRole).isValid()) { // command id
ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(item->data(0, Qt::UserRole));
text = scitem->m_cmd->id().toString();
} else { } else {
text = item->text(column); text = item->text(column);
} }

View File

@@ -490,10 +490,6 @@ void EditorManagerPrivate::init()
connect(m_autoSaveTimer, SIGNAL(timeout()), SLOT(autoSave())); connect(m_autoSaveTimer, SIGNAL(timeout()), SLOT(autoSave()));
updateAutoSave(); updateAutoSave();
// Do not ask for files to save.
// MainWindow::closeEvent has already done that.
ICore::addPreCloseListener([]() -> bool { return EditorManager::closeAllEditors(false); });
d->m_openEditorsFactory = new OpenEditorsViewFactory(); d->m_openEditorsFactory = new OpenEditorsViewFactory();
ExtensionSystem::PluginManager::addObject(d->m_openEditorsFactory); ExtensionSystem::PluginManager::addObject(d->m_openEditorsFactory);
@@ -515,7 +511,14 @@ void EditorManagerPrivate::init()
[]() -> int { []() -> int {
IEditor *editor = EditorManager::currentEditor(); IEditor *editor = EditorManager::currentEditor();
return editor ? editor->widget()->mapToGlobal(QPoint(0, 0)).y() : 0; return editor ? editor->widget()->mapToGlobal(QPoint(0, 0)).y() : 0;
}); });
}
void EditorManagerPrivate::extensionsInitialized()
{
// Do not ask for files to save.
// MainWindow::closeEvent has already done that.
ICore::addPreCloseListener([]() -> bool { return EditorManager::closeAllEditors(false); });
} }
EditorManagerPrivate *EditorManagerPrivate::instance() EditorManagerPrivate *EditorManagerPrivate::instance()
@@ -2487,7 +2490,9 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
// * application/octet-stream // * application/octet-stream
// * text/plain // * text/plain
QList<Utils::MimeType> queue; QList<Utils::MimeType> queue;
QSet<QString> seen;
queue.append(mimeType); queue.append(mimeType);
seen.insert(mimeType.name());
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
Utils::MimeType mt = queue.takeFirst(); Utils::MimeType mt = queue.takeFirst();
// check for matching factories // check for matching factories
@@ -2507,8 +2512,14 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
QStringList parentNames = mt.parentMimeTypes(); QStringList parentNames = mt.parentMimeTypes();
foreach (const QString &parentName, parentNames) { foreach (const QString &parentName, parentNames) {
const Utils::MimeType parent = mdb.mimeTypeForName(parentName); const Utils::MimeType parent = mdb.mimeTypeForName(parentName);
if (parent.isValid()) if (parent.isValid()) {
queue.append(parent); int seenSize = seen.size();
seen.insert(parent.name());
if (seen.size() != seenSize) // not seen before, so add
queue.append(parent);
else
qWarning("MimeTypes: Parent hierarchy loop detected for '%s'!", qPrintable(parent.name()));
}
} }
} }
} }

View File

@@ -69,6 +69,8 @@ class EditorManagerPrivate : public QObject
public: public:
static EditorManagerPrivate *instance(); static EditorManagerPrivate *instance();
static void extensionsInitialized(); // only use from MainWindow
static EditorArea *mainEditorArea(); static EditorArea *mainEditorArea();
static EditorView *currentEditorView(); static EditorView *currentEditorView();
static void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false); static void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false);

View File

@@ -53,9 +53,13 @@ using namespace Utils;
namespace Core { namespace Core {
namespace Internal { namespace Internal {
FancyToolButton::FancyToolButton(QWidget *parent) FancyToolButton::FancyToolButton(QAction *action, QWidget *parent)
: QToolButton(parent), m_fader(0) : QToolButton(parent), m_fader(0)
{ {
setDefaultAction(action);
connect(action, &QAction::changed, this, &FancyToolButton::actionChanged);
actionChanged();
setAttribute(Qt::WA_Hover, true); setAttribute(Qt::WA_Hover, true);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
} }
@@ -364,18 +368,12 @@ FancyActionBar::FancyActionBar(QWidget *parent)
void FancyActionBar::addProjectSelector(QAction *action) void FancyActionBar::addProjectSelector(QAction *action)
{ {
FancyToolButton* toolButton = new FancyToolButton(this); m_actionsLayout->insertWidget(0, new FancyToolButton(action, this));
toolButton->setDefaultAction(action);
connect(action, SIGNAL(changed()), toolButton, SLOT(actionChanged()));
m_actionsLayout->insertWidget(0, toolButton);
} }
void FancyActionBar::insertAction(int index, QAction *action) void FancyActionBar::insertAction(int index, QAction *action)
{ {
FancyToolButton *toolButton = new FancyToolButton(this); m_actionsLayout->insertWidget(index, new FancyToolButton(action, this));
toolButton->setDefaultAction(action);
connect(action, SIGNAL(changed()), toolButton, SLOT(actionChanged()));
m_actionsLayout->insertWidget(index, toolButton);
} }
QLayout *FancyActionBar::actionsLayout() const QLayout *FancyActionBar::actionsLayout() const

View File

@@ -47,7 +47,7 @@ class FancyToolButton : public QToolButton
Q_PROPERTY(float fader READ fader WRITE setFader) Q_PROPERTY(float fader READ fader WRITE setFader)
public: public:
FancyToolButton(QWidget *parent = 0); FancyToolButton(QAction *action, QWidget *parent = 0);
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent *event);
bool event(QEvent *e); bool event(QEvent *e);

View File

@@ -44,7 +44,7 @@
a text based search term (potentially with find flags like a text based search term (potentially with find flags like
searching case sensitively or using regular expressions). Existing searching case sensitively or using regular expressions). Existing
scopes are \gui {All Projects} that searches from all files in all projects scopes are \gui {All Projects} that searches from all files in all projects
and \gui {Files on File System} where the user provides a directory and file and \gui {Files in File System} where the user provides a directory and file
patterns to search. patterns to search.
To make your find scope available to the user, you need to implement this To make your find scope available to the user, you need to implement this

View File

@@ -410,12 +410,12 @@ bool LocatorWidget::eventFilter(QObject *obj, QEvent *event)
} }
} else if (obj == m_fileLineEdit && event->type() == QEvent::FocusOut) { } else if (obj == m_fileLineEdit && event->type() == QEvent::FocusOut) {
QFocusEvent *fev = static_cast<QFocusEvent *>(event); QFocusEvent *fev = static_cast<QFocusEvent *>(event);
if (fev->reason() != Qt::ActiveWindowFocusReason || !m_completionList->isActiveWindow()) { if (fev->reason() != Qt::ActiveWindowFocusReason || !m_completionList->isActiveWindow())
m_completionList->hide(); m_completionList->hide();
m_fileLineEdit->clearFocus();
}
} else if (obj == m_fileLineEdit && event->type() == QEvent::FocusIn) { } else if (obj == m_fileLineEdit && event->type() == QEvent::FocusIn) {
showPopupNow(); QFocusEvent *fev = static_cast<QFocusEvent *>(event);
if (fev->reason() != Qt::ActiveWindowFocusReason)
showPopupNow();
} else if (obj == this && event->type() == QEvent::ShortcutOverride) { } else if (obj == this && event->type() == QEvent::ShortcutOverride) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event); QKeyEvent *ke = static_cast<QKeyEvent *>(event);
switch (ke->key()) { switch (ke->key()) {
@@ -584,10 +584,8 @@ void LocatorWidget::show(const QString &text, int selectionStart, int selectionL
{ {
if (!text.isEmpty()) if (!text.isEmpty())
m_fileLineEdit->setText(text); m_fileLineEdit->setText(text);
if (!m_fileLineEdit->hasFocus()) m_fileLineEdit->setFocus();
m_fileLineEdit->setFocus(); showPopupNow();
else
showPopupNow();
ICore::raiseWindow(ICore::mainWindow()); ICore::raiseWindow(ICore::mainWindow());
if (selectionStart >= 0) { if (selectionStart >= 0) {

View File

@@ -30,7 +30,6 @@
#include "spotlightlocatorfilter.h" #include "spotlightlocatorfilter.h"
#include <utils/autoreleasepool.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QMutex> #include <QMutex>
@@ -38,7 +37,6 @@
#include <QWaitCondition> #include <QWaitCondition>
#include <Foundation/NSArray.h> #include <Foundation/NSArray.h>
#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSDictionary.h> #include <Foundation/NSDictionary.h>
#include <Foundation/NSMetadata.h> #include <Foundation/NSMetadata.h>
#include <Foundation/NSNotification.h> #include <Foundation/NSNotification.h>
@@ -85,33 +83,34 @@ SpotlightIterator::SpotlightIterator(const QString &expression)
m_queueIndex(-1), m_queueIndex(-1),
m_finished(false) m_finished(false)
{ {
Utils::AutoreleasePool pool; Q_UNUSED(pool) @autoreleasepool {
NSPredicate *predicate = [NSPredicate predicateWithFormat:expression.toNSString()]; NSPredicate *predicate = [NSPredicate predicateWithFormat:expression.toNSString()];
m_query = [[NSMetadataQuery alloc] init]; m_query = [[NSMetadataQuery alloc] init];
m_query.predicate = predicate; m_query.predicate = predicate;
m_query.searchScopes = [NSArray arrayWithObject:NSMetadataQueryLocalComputerScope]; m_query.searchScopes = [NSArray arrayWithObject:NSMetadataQueryLocalComputerScope];
m_queue = [[NSMutableArray alloc] init]; m_queue = [[NSMutableArray alloc] init];
m_progressObserver = [[[NSNotificationCenter defaultCenter] m_progressObserver = [[[NSNotificationCenter defaultCenter]
addObserverForName:NSMetadataQueryGatheringProgressNotification addObserverForName:NSMetadataQueryGatheringProgressNotification
object:m_query object:m_query
queue:nil queue:nil
usingBlock:^(NSNotification *note) { usingBlock:^(NSNotification *note) {
[m_query disableUpdates]; [m_query disableUpdates];
QMutexLocker lock(&m_mutex); Q_UNUSED(lock) QMutexLocker lock(&m_mutex); Q_UNUSED(lock)
[m_queue addObjectsFromArray:[note.userInfo objectForKey:(NSString *)kMDQueryUpdateAddedItems]]; [m_queue addObjectsFromArray:[note.userInfo objectForKey:(NSString *)kMDQueryUpdateAddedItems]];
[m_query enableUpdates]; [m_query enableUpdates];
m_waitForItems.wakeAll(); m_waitForItems.wakeAll();
}] retain]; }] retain];
m_finishObserver = [[[NSNotificationCenter defaultCenter] m_finishObserver = [[[NSNotificationCenter defaultCenter]
addObserverForName:NSMetadataQueryDidFinishGatheringNotification addObserverForName:NSMetadataQueryDidFinishGatheringNotification
object:m_query object:m_query
queue:nil queue:nil
usingBlock:^(NSNotification *) { usingBlock:^(NSNotification *) {
QMutexLocker lock(&m_mutex); Q_UNUSED(lock) QMutexLocker lock(&m_mutex); Q_UNUSED(lock)
m_finished = true; m_finished = true;
m_waitForItems.wakeAll(); m_waitForItems.wakeAll();
}] retain]; }] retain];
[m_query startQuery]; [m_query startQuery];
}
} }
SpotlightIterator::~SpotlightIterator() SpotlightIterator::~SpotlightIterator()
@@ -163,22 +162,23 @@ void SpotlightIterator::ensureNext()
return; return;
if (m_index >= 10000) // limit the amount of data that is passed on if (m_index >= 10000) // limit the amount of data that is passed on
return; return;
Utils::AutoreleasePool pool; Q_UNUSED(pool) @autoreleasepool {
// check if there are items in the queue, otherwise wait for some // check if there are items in the queue, otherwise wait for some
m_mutex.lock(); m_mutex.lock();
bool itemAvailable = (m_queueIndex + 1 < m_queue.count); bool itemAvailable = (m_queueIndex + 1 < m_queue.count);
if (!itemAvailable && !m_finished) { if (!itemAvailable && !m_finished) {
m_waitForItems.wait(&m_mutex); m_waitForItems.wait(&m_mutex);
itemAvailable = (m_queueIndex + 1 < m_queue.count); itemAvailable = (m_queueIndex + 1 < m_queue.count);
} }
if (itemAvailable) { if (itemAvailable) {
++m_queueIndex; ++m_queueIndex;
NSMetadataItem *item = [m_queue objectAtIndex:m_queueIndex]; NSMetadataItem *item = [m_queue objectAtIndex:m_queueIndex];
m_filePaths.append(QString::fromNSString([item valueForAttribute:NSMetadataItemPathKey])); m_filePaths.append(QString::fromNSString([item valueForAttribute:NSMetadataItemPathKey]));
m_fileNames.append(QString::fromNSString([item valueForAttribute:NSMetadataItemFSNameKey])); m_fileNames.append(QString::fromNSString([item valueForAttribute:NSMetadataItemFSNameKey]));
}
m_mutex.unlock();
} }
m_mutex.unlock();
} }
// #pragma mark -- SpotlightLocatorFilter // #pragma mark -- SpotlightLocatorFilter

View File

@@ -347,6 +347,7 @@ bool MainWindow::init(QString *errorMessage)
void MainWindow::extensionsInitialized() void MainWindow::extensionsInitialized()
{ {
EditorManagerPrivate::extensionsInitialized();
MimeTypeSettings::restoreSettings(); MimeTypeSettings::restoreSettings();
m_windowSupport = new WindowSupport(this, Context("Core.MainWindow")); m_windowSupport = new WindowSupport(this, Context("Core.MainWindow"));
m_windowSupport->setCloseActionEnabled(false); m_windowSupport->setCloseActionEnabled(false);

View File

@@ -222,7 +222,7 @@ void ThemeSettingsTableModel::initFrom(Theme *theme)
} }
m_widgetStyle = theme->widgetStyle(); m_widgetStyle = theme->widgetStyle();
m_name = theme->d->name; m_displayName = theme->d->displayName;
m_preferredStyles = theme->d->preferredStyles; m_preferredStyles = theme->d->preferredStyles;
} }
@@ -252,7 +252,7 @@ void ThemeSettingsTableModel::toTheme(Theme *t) const
} }
theme->widgetStyle = m_widgetStyle; theme->widgetStyle = m_widgetStyle;
theme->name = m_name; theme->displayName = m_displayName;
theme->preferredStyles = m_preferredStyles; theme->preferredStyles = m_preferredStyles;
} }

View File

@@ -76,7 +76,7 @@ public:
void initFrom(Utils::Theme *theme); void initFrom(Utils::Theme *theme);
void toTheme(Utils::Theme *theme) const; void toTheme(Utils::Theme *theme) const;
QString m_name; QString m_displayName;
QStringList m_preferredStyles; QStringList m_preferredStyles;
public: public:

View File

@@ -31,14 +31,55 @@
#include "themesettings.h" #include "themesettings.h"
#include "themesettingswidget.h" #include "themesettingswidget.h"
#include "coreconstants.h" #include "coreconstants.h"
#include "icore.h"
#include <utils/algorithm.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QSettings>
static const char themeNameKey[] = "ThemeName";
namespace Core { namespace Core {
namespace Internal { namespace Internal {
ThemeSettings::ThemeSettings() : ThemeEntry::ThemeEntry(Id id, const QString &filePath, bool readOnly)
m_widget(0) : m_id(id),
m_filePath(filePath),
m_readOnly(readOnly)
{
}
Id ThemeEntry::id() const
{
return m_id;
}
QString ThemeEntry::displayName() const
{
if (m_displayName.isEmpty() && !m_filePath.isEmpty()) {
QSettings settings(m_filePath, QSettings::IniFormat);
m_displayName = settings.value(QLatin1String(themeNameKey),
QCoreApplication::tr("unnamed")).toString();
if (false) // TODO: Revert to m_readOnly
m_displayName = QCoreApplication::tr("%1 (built-in)").arg(m_displayName);
}
return m_displayName;
}
QString ThemeEntry::filePath() const
{
return m_filePath;
}
bool ThemeEntry::readOnly() const
{
return m_readOnly;
}
ThemeSettings::ThemeSettings()
{ {
setId(Constants::SETTINGS_ID_INTERFACE); setId(Constants::SETTINGS_ID_INTERFACE);
setDisplayName(tr("Theme")); setDisplayName(tr("Theme"));
@@ -71,5 +112,38 @@ void ThemeSettings::finish()
m_widget = 0; m_widget = 0;
} }
static void addThemesFromPath(const QString &path, bool readOnly, QList<ThemeEntry> *themes)
{
static const QLatin1String extension(".creatortheme");
QDir themeDir(path);
themeDir.setNameFilters(QStringList() << QLatin1String("*.creatortheme"));
themeDir.setFilter(QDir::Files);
const QStringList themeList = themeDir.entryList();
foreach (const QString &fileName, themeList) {
QString id = QFileInfo(fileName).completeBaseName();
themes->append(ThemeEntry(Id::fromString(id), themeDir.absoluteFilePath(fileName), readOnly));
}
}
QList<ThemeEntry> ThemeSettings::availableThemes()
{
QList<ThemeEntry> themes;
static const QString installThemeDir = ICore::resourcePath() + QLatin1String("/themes");
static const QString userThemeDir = ICore::userResourcePath() + QLatin1String("/themes");
addThemesFromPath(installThemeDir, /*readOnly=*/true, &themes);
if (themes.isEmpty())
qWarning() << "Warning: No themes found in installation: "
<< QDir::toNativeSeparators(installThemeDir);
// move default theme to front
int defaultIndex = Utils::indexOf(themes, Utils::equal(&ThemeEntry::id, Id("default")));
if (defaultIndex > 0) { // == exists and not at front
ThemeEntry defaultEntry = themes.takeAt(defaultIndex);
themes.prepend(defaultEntry);
}
addThemesFromPath(userThemeDir, /*readOnly=*/false, &themes);
return themes;
}
} // namespace Internal } // namespace Internal
} // namespace Core } // namespace Core

View File

@@ -31,6 +31,8 @@
#ifndef THEMESETTINGS_H #ifndef THEMESETTINGS_H
#define THEMESETTINGS_H #define THEMESETTINGS_H
#include "id.h"
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
namespace Core { namespace Core {
@@ -38,6 +40,24 @@ namespace Internal {
class ThemeSettingsWidget; class ThemeSettingsWidget;
class ThemeEntry
{
public:
ThemeEntry() = default;
ThemeEntry(Id id, const QString &filePath, bool readOnly);
Id id() const;
QString displayName() const;
QString filePath() const;
bool readOnly() const;
private:
Id m_id;
QString m_filePath;
mutable QString m_displayName;
bool m_readOnly = true;
};
class ThemeSettings : public IOptionsPage class ThemeSettings : public IOptionsPage
{ {
Q_OBJECT Q_OBJECT
@@ -50,7 +70,9 @@ public:
void apply(); void apply();
void finish(); void finish();
ThemeSettingsWidget *m_widget; static QList<ThemeEntry> availableThemes();
private:
ThemeSettingsWidget *m_widget = 0;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -33,7 +33,9 @@
#include "icore.h" #include "icore.h"
#include "manhattanstyle.h" #include "manhattanstyle.h"
#include "themeeditor/themesettingstablemodel.h" #include "themeeditor/themesettingstablemodel.h"
#include "themesettings.h"
#include <utils/algorithm.h>
#include <utils/theme/theme.h> #include <utils/theme/theme.h>
#include <utils/theme/theme_p.h> #include <utils/theme/theme_p.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -52,8 +54,6 @@ using namespace Utils;
namespace Core { namespace Core {
namespace Internal { namespace Internal {
const char themeNameKey[] = "ThemeName";
static QString customThemesPath() static QString customThemesPath()
{ {
return ICore::userResourcePath() + QLatin1String("/themes/"); return ICore::userResourcePath() + QLatin1String("/themes/");
@@ -81,42 +81,6 @@ static QString createThemeFileName(const QString &pattern)
return fileName; return fileName;
} }
struct ThemeEntry
{
ThemeEntry() : m_readOnly(true) {}
ThemeEntry(const QString &name, const QString &filePath, bool readOnly):
m_name(name),
m_filePath(filePath),
m_readOnly(readOnly)
{
}
QString name() const { return m_name; }
QString displayName() const;
QString filePath() const { return m_filePath; }
bool readOnly() const { return m_readOnly; }
private:
QString m_name;
QString m_filePath;
mutable QString m_displayName;
bool m_readOnly;
};
QString ThemeEntry::displayName() const
{
if (m_displayName.isEmpty()) {
QSettings settings(filePath(), QSettings::IniFormat);
m_displayName = settings.value(QLatin1String(themeNameKey),
QCoreApplication::tr("unnamed")).toString();
if (false) // TODO: Revert to m_readOnly
m_displayName = QCoreApplication::tr("%1 (built-in)").arg(m_displayName);
}
return m_displayName;
}
class ThemeListModel : public QAbstractListModel class ThemeListModel : public QAbstractListModel
{ {
public: public:
@@ -179,7 +143,7 @@ ThemeSettingsPrivate::ThemeSettingsPrivate(QWidget *widget)
, m_refreshingThemeList(false) , m_refreshingThemeList(false)
, m_ui(new Ui::ThemeSettings) , m_ui(new Ui::ThemeSettings)
{ {
m_currentTheme = ThemeEntry(creatorTheme()->name(), creatorTheme()->filePath(), true); m_currentTheme = ThemeEntry(Id::fromString(creatorTheme()->id()), creatorTheme()->filePath(), true);
m_ui->setupUi(widget); m_ui->setupUi(widget);
// TODO: Restore the editor and the buttons after improving the editor // TODO: Restore the editor and the buttons after improving the editor
m_ui->editor->hide(); m_ui->editor->hide();
@@ -216,44 +180,15 @@ ThemeSettingsWidget::~ThemeSettingsWidget()
void ThemeSettingsWidget::refreshThemeList() void ThemeSettingsWidget::refreshThemeList()
{ {
QList<ThemeEntry> themes; const QList<ThemeEntry> themes = ThemeSettings::availableThemes();
const int selected = Utils::indexOf(themes, Utils::equal(&ThemeEntry::id, d->m_currentTheme.id()));
QDir themeDir(ICore::resourcePath() + QLatin1String("/themes"));
themeDir.setNameFilters(QStringList() << QLatin1String("*.creatortheme"));
themeDir.setFilter(QDir::Files);
int selected = 0;
QStringList themeList = themeDir.entryList();
const QString defaultTheme = QLatin1String("default.creatortheme");
if (themeList.removeOne(defaultTheme))
themeList.prepend(defaultTheme);
const QLatin1String extension(".creatortheme");
for (int i = 0, total = themeList.count(); i < total; ++i) {
const QString fileName = themeList.at(i);
if (d->m_currentTheme.name() + extension == fileName)
selected = i;
QString name = fileName;
name.remove(extension);
themes.append(ThemeEntry(name, themeDir.absoluteFilePath(fileName), true));
}
if (themes.isEmpty())
qWarning() << "Warning: no themes found in path:" << themeDir.path();
themeDir.setPath(customThemesPath());
foreach (const QString &file, themeDir.entryList()) {
const QString fileName = themeDir.absoluteFilePath(file);
if (d->m_currentTheme.name() == fileName)
selected = themes.size();
themes.append(ThemeEntry(fileName, fileName, false));
}
d->m_currentTheme = themes[selected];
d->m_refreshingThemeList = true; d->m_refreshingThemeList = true;
d->m_themeListModel->setThemes(themes); d->m_themeListModel->setThemes(themes);
d->m_ui->themeComboBox->setCurrentIndex(selected); if (selected >= 0) {
d->m_currentTheme = themes[selected];
d->m_ui->themeComboBox->setCurrentIndex(selected);
}
d->m_refreshingThemeList = false; d->m_refreshingThemeList = false;
} }
@@ -270,7 +205,7 @@ void ThemeSettingsWidget::themeSelected(int index)
d->m_currentTheme = entry; d->m_currentTheme = entry;
QSettings settings(entry.filePath(), QSettings::IniFormat); QSettings settings(entry.filePath(), QSettings::IniFormat);
Theme theme(entry.name()); Theme theme(entry.id().toString());
theme.readSettings(settings); theme.readSettings(settings);
d->m_ui->editor->initFrom(&theme); d->m_ui->editor->initFrom(&theme);
} }
@@ -354,7 +289,7 @@ void ThemeSettingsWidget::maybeSaveTheme()
messageBox->setDefaultButton(QMessageBox::Save); messageBox->setDefaultButton(QMessageBox::Save);
if (messageBox->exec() == QMessageBox::Save) { if (messageBox->exec() == QMessageBox::Save) {
Theme newTheme(d->m_currentTheme.name()); Theme newTheme(d->m_currentTheme.id().toString());
d->m_ui->editor->model()->toTheme(&newTheme); d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.writeSettings(d->m_currentTheme.filePath()); newTheme.writeSettings(d->m_currentTheme.filePath());
} }
@@ -373,7 +308,7 @@ void ThemeSettingsWidget::renameTheme()
dialog->setInputMode(QInputDialog::TextInput); dialog->setInputMode(QInputDialog::TextInput);
dialog->setWindowTitle(tr("Rename Theme")); dialog->setWindowTitle(tr("Rename Theme"));
dialog->setLabelText(tr("Theme name:")); dialog->setLabelText(tr("Theme name:"));
dialog->setTextValue(d->m_ui->editor->model()->m_name); dialog->setTextValue(d->m_ui->editor->model()->m_displayName);
int ret = dialog->exec(); int ret = dialog->exec();
QString newName = dialog->textValue(); QString newName = dialog->textValue();
delete dialog; delete dialog;
@@ -382,9 +317,9 @@ void ThemeSettingsWidget::renameTheme()
return; return;
// overwrite file with new name // overwrite file with new name
Theme newTheme(entry.name()); Theme newTheme(entry.id().toString());
d->m_ui->editor->model()->toTheme(&newTheme); d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.setName(newName); newTheme.setDisplayName(newName);
newTheme.writeSettings(entry.filePath()); newTheme.writeSettings(entry.filePath());
refreshThemeList(); refreshThemeList();
@@ -401,8 +336,9 @@ void ThemeSettingsWidget::copyThemeByName(const QString &name)
QString baseFileName = QFileInfo(entry.filePath()).completeBaseName(); QString baseFileName = QFileInfo(entry.filePath()).completeBaseName();
baseFileName += QLatin1String("_copy%1.creatortheme"); baseFileName += QLatin1String("_copy%1.creatortheme");
QString fileName = createThemeFileName(baseFileName); QString fileName = createThemeFileName(baseFileName);
QString id = QFileInfo(fileName).completeBaseName();
if (fileName.isEmpty()) if (fileName.isEmpty() || id.isEmpty())
return; return;
// Ask about saving any existing modifactions // Ask about saving any existing modifactions
@@ -410,18 +346,18 @@ void ThemeSettingsWidget::copyThemeByName(const QString &name)
Theme newTheme(fileName); Theme newTheme(fileName);
d->m_ui->editor->model()->toTheme(&newTheme); d->m_ui->editor->model()->toTheme(&newTheme);
newTheme.setName(name); newTheme.setDisplayName(name);
newTheme.writeSettings(fileName); newTheme.writeSettings(fileName);
d->m_currentTheme = ThemeEntry(fileName, fileName, true); d->m_currentTheme = ThemeEntry(Id::fromString(id), fileName, true);
refreshThemeList(); refreshThemeList();
} }
void ThemeSettingsWidget::apply() void ThemeSettingsWidget::apply()
{ {
const QString themeName = d->m_currentTheme.name(); const QString themeId = d->m_currentTheme.id().toString();
Theme *newTheme = new Theme(themeName); Theme *newTheme = new Theme(themeId);
if (d->m_currentTheme.readOnly()) { if (d->m_currentTheme.readOnly()) {
QSettings themeSettings(d->m_currentTheme.filePath(), QSettings::IniFormat); QSettings themeSettings(d->m_currentTheme.filePath(), QSettings::IniFormat);
newTheme->readSettings(themeSettings); newTheme->readSettings(themeSettings);
@@ -447,7 +383,7 @@ void ThemeSettingsWidget::apply()
// save filename of selected theme in global config // save filename of selected theme in global config
QSettings *settings = ICore::settings(); QSettings *settings = ICore::settings();
settings->setValue(QLatin1String(Constants::SETTINGS_THEME), themeName); settings->setValue(QLatin1String(Constants::SETTINGS_THEME), themeId);
} }
} // namespace Internal } // namespace Internal

View File

@@ -36,6 +36,7 @@ using namespace CppTools;
static QLatin1String cppHeaderMimeType(Constants::CPP_HEADER_MIMETYPE); static QLatin1String cppHeaderMimeType(Constants::CPP_HEADER_MIMETYPE);
static QLatin1String cHeaderMimeType(Constants::C_HEADER_MIMETYPE); static QLatin1String cHeaderMimeType(Constants::C_HEADER_MIMETYPE);
static QLatin1String clangExtraOptionsKey(Constants::CPPTOOLS_EXTRA_CLANG_OPTIONS);
void CppCodeModelSettings::fromSettings(QSettings *s) void CppCodeModelSettings::fromSettings(QSettings *s)
{ {
@@ -45,6 +46,8 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
foreach (const QString &mimeType, supportedMimeTypes()) foreach (const QString &mimeType, supportedMimeTypes())
setIdForMimeType(supporters, mimeType); setIdForMimeType(supporters, mimeType);
setExtraClangOptions(s->value(clangExtraOptionsKey, defaultExtraClangOptions()).toStringList());
QVariant v = s->value(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), PchUse_None); QVariant v = s->value(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), PchUse_None);
setPCHUsage(static_cast<PCHUsage>(v.toInt())); setPCHUsage(static_cast<PCHUsage>(v.toInt()));
s->endGroup(); s->endGroup();
@@ -59,6 +62,7 @@ void CppCodeModelSettings::toSettings(QSettings *s)
foreach (const QString &mimeType, m_modelManagerSupportByMimeType.keys()) foreach (const QString &mimeType, m_modelManagerSupportByMimeType.keys())
var[mimeType] = m_modelManagerSupportByMimeType[mimeType]; var[mimeType] = m_modelManagerSupportByMimeType[mimeType];
s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY), QVariant(var)); s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY), QVariant(var));
s->setValue(clangExtraOptionsKey, extraClangOptions());
s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), pchUsage()); s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), pchUsage());
s->endGroup(); s->endGroup();
@@ -116,6 +120,33 @@ bool CppCodeModelSettings::hasModelManagerSupportIdForMimeType(const QString &mi
return m_modelManagerSupportByMimeType.value(mimeType) == id; return m_modelManagerSupportByMimeType.value(mimeType) == id;
} }
QStringList CppCodeModelSettings::defaultExtraClangOptions()
{
return {
QStringLiteral("-Weverything"),
QStringLiteral("-Wno-c++98-compat"),
QStringLiteral("-Wno-c++98-compat-pedantic"),
QStringLiteral("-Wno-unused-macros"),
QStringLiteral("-Wno-newline-eof"),
QStringLiteral("-Wno-exit-time-destructors"),
QStringLiteral("-Wno-global-constructors"),
QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"),
QStringLiteral("-Wno-documentation"),
QStringLiteral("-Wno-shadow"),
QStringLiteral("-Wno-missing-prototypes"), // Not optimal for C projects.
};
}
QStringList CppCodeModelSettings::extraClangOptions() const
{
return m_extraClangOptions;
}
void CppCodeModelSettings::setExtraClangOptions(const QStringList &extraClangOptions)
{
m_extraClangOptions = extraClangOptions;
}
void CppCodeModelSettings::setIdForMimeType(const QVariant &var, const QString &mimeType) void CppCodeModelSettings::setIdForMimeType(const QVariant &var, const QString &mimeType)
{ {
QHash<QString, QVariant> mimeToId = var.toHash(); QHash<QString, QVariant> mimeToId = var.toHash();

View File

@@ -73,6 +73,10 @@ public:
void setDefaultId(const QString &defaultId) void setDefaultId(const QString &defaultId)
{ m_defaultId = defaultId; } { m_defaultId = defaultId; }
static QStringList defaultExtraClangOptions();
QStringList extraClangOptions() const;
void setExtraClangOptions(const QStringList &extraClangOptions);
PCHUsage pchUsage() const { return m_pchUsage; } PCHUsage pchUsage() const { return m_pchUsage; }
void setPCHUsage(PCHUsage pchUsage) { m_pchUsage = pchUsage; } void setPCHUsage(PCHUsage pchUsage) { m_pchUsage = pchUsage; }
@@ -90,6 +94,7 @@ private:
private: private:
QHash<QString, QString> m_modelManagerSupportByMimeType; QHash<QString, QString> m_modelManagerSupportByMimeType;
QHash<QString, QString> m_modelManagerSupportsByName; QHash<QString, QString> m_modelManagerSupportsByName;
QStringList m_extraClangOptions;
QString m_defaultId; QString m_defaultId;
PCHUsage m_pchUsage; PCHUsage m_pchUsage;
}; };

View File

@@ -46,7 +46,11 @@ CppCodeModelSettingsWidget::CppCodeModelSettingsWidget(QWidget *parent)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->theGroupBox->setVisible(true); m_ui->clangSettingsGroupBox->setVisible(true);
connect(m_ui->clangOptionsResetButton, &QPushButton::clicked, [this]() {
const QString options = m_settings->defaultExtraClangOptions().join(QLatin1Char('\n'));
m_ui->clangOptionsToAppendTextEdit->document()->setPlainText(options);
});
} }
CppCodeModelSettingsWidget::~CppCodeModelSettingsWidget() CppCodeModelSettingsWidget::~CppCodeModelSettingsWidget()
@@ -58,41 +62,16 @@ void CppCodeModelSettingsWidget::setSettings(const QSharedPointer<CppCodeModelSe
{ {
m_settings = s; m_settings = s;
applyToWidget(m_ui->cChooser, QLatin1String(Constants::C_SOURCE_MIMETYPE)); setupClangCodeModelWidgets();
applyToWidget(m_ui->cppChooser, QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
applyToWidget(m_ui->objcChooser, QLatin1String(Constants::OBJECTIVE_C_SOURCE_MIMETYPE));
applyToWidget(m_ui->objcppChooser, QLatin1String(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
applyToWidget(m_ui->hChooser, QLatin1String(Constants::C_HEADER_MIMETYPE));
m_ui->ignorePCHCheckBox->setChecked(s->pchUsage() == CppCodeModelSettings::PchUse_None); m_ui->ignorePCHCheckBox->setChecked(s->pchUsage() == CppCodeModelSettings::PchUse_None);
} }
void CppCodeModelSettingsWidget::applyToWidget(QComboBox *chooser, const QString &mimeType) const
{
chooser->clear();
QStringList names = m_settings->availableModelManagerSupportProvidersByName().keys();
Utils::sort(names);
foreach (const QString &name, names) {
const QString &id = m_settings->availableModelManagerSupportProvidersByName()[name];
chooser->addItem(name, id);
if (id == m_settings->modelManagerSupportIdForMimeType(mimeType))
chooser->setCurrentIndex(chooser->count() - 1);
}
chooser->setEnabled(names.size() > 1);
}
void CppCodeModelSettingsWidget::applyToSettings() const void CppCodeModelSettingsWidget::applyToSettings() const
{ {
bool changed = false; bool changed = false;
changed |= applyToSettings(m_ui->cChooser, QLatin1String(Constants::C_SOURCE_MIMETYPE));
changed |= applyToSettings(m_ui->cppChooser, QLatin1String(Constants::CPP_SOURCE_MIMETYPE)); if (applyClangCodeModelWidgetsToSettings())
changed |= applyToSettings(m_ui->objcChooser, changed = true;
QLatin1String(Constants::OBJECTIVE_C_SOURCE_MIMETYPE));
changed |= applyToSettings(m_ui->objcppChooser,
QLatin1String(Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
changed |= applyToSettings(m_ui->hChooser,
QLatin1String(Constants::C_HEADER_MIMETYPE));
if (m_ui->ignorePCHCheckBox->isChecked() != if (m_ui->ignorePCHCheckBox->isChecked() !=
(m_settings->pchUsage() == CppCodeModelSettings::PchUse_None)) { (m_settings->pchUsage() == CppCodeModelSettings::PchUse_None)) {
@@ -106,14 +85,46 @@ void CppCodeModelSettingsWidget::applyToSettings() const
m_settings->toSettings(Core::ICore::settings()); m_settings->toSettings(Core::ICore::settings());
} }
bool CppCodeModelSettingsWidget::applyToSettings(QComboBox *chooser, const QString &mimeType) const static bool isClangCodeModelActive(const CppCodeModelSettings &settings)
{ {
QString newId = chooser->itemData(chooser->currentIndex()).toString(); const QString currentCodeModelId
QString currentId = m_settings->modelManagerSupportIdForMimeType(mimeType); = settings.modelManagerSupportIdForMimeType(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
if (newId == currentId) return currentCodeModelId != settings.defaultId();
return false; }
void CppCodeModelSettingsWidget::setupClangCodeModelWidgets() const
{
bool isClangActive = false;
const bool isClangAvailable = m_settings->availableModelManagerSupportProvidersByName().size() > 1;
if (isClangAvailable)
isClangActive = isClangCodeModelActive(*m_settings.data());
m_ui->activateClangCodeModelPluginHint->setVisible(!isClangAvailable);
m_ui->clangSettingsGroupBox->setEnabled(isClangAvailable);
m_ui->clangSettingsGroupBox->setChecked(isClangActive);
const QString extraClangOptions = m_settings->extraClangOptions().join(QLatin1Char('\n'));
m_ui->clangOptionsToAppendTextEdit->document()->setPlainText(extraClangOptions);
}
bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
{
// Once the underlying settings are not mime type based anymore, simplify here.
// Until then, ensure that the settings are set uniformly for all the mime types
// to avoid surprises.
const QString activeCodeModelId = m_ui->clangSettingsGroupBox->isChecked()
? QLatin1String("ClangCodeMode.ClangCodeMode")
: QLatin1String("CppTools.BuiltinCodeModel");
foreach (const QString &mimeType, m_settings->supportedMimeTypes())
m_settings->setModelManagerSupportIdForMimeType(mimeType, activeCodeModelId);
const QString clangOptionsText = m_ui->clangOptionsToAppendTextEdit->document()->toPlainText();
const QStringList extraClangOptions = clangOptionsText.split(QLatin1Char('\n'),
QString::SkipEmptyParts);
m_settings->setExtraClangOptions(extraClangOptions);
m_settings->setModelManagerSupportIdForMimeType(mimeType, newId);
return true; return true;
} }

View File

@@ -58,8 +58,8 @@ public:
void applyToSettings() const; void applyToSettings() const;
private: private:
bool applyToSettings(QComboBox *chooser, const QString &mimeType) const; void setupClangCodeModelWidgets() const;
void applyToWidget(QComboBox *chooser, const QString &mimeType) const; bool applyClangCodeModelWidgetsToSettings() const;
private: private:
Ui::CppCodeModelSettingsPage *m_ui; Ui::CppCodeModelSettingsPage *m_ui;

View File

@@ -15,74 +15,54 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QGroupBox" name="theGroupBox"> <widget class="QLabel" name="activateClangCodeModelPluginHint">
<property name="title"> <property name="text">
<string>Code Completion and Semantic Highlighting</string> <string>&lt;i&gt;Activate the Clang Code Model plugin to enable the options here.&lt;/i&gt;</string>
</property> </property>
<layout class="QFormLayout" name="formLayout"> </widget>
<item row="0" column="0"> </item>
<widget class="QLabel" name="cLabel"> <item>
<widget class="QGroupBox" name="clangSettingsGroupBox">
<property name="title">
<string>Use Clang Code Model</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="clangOptionsGeneralHintLabel">
<property name="text"> <property name="text">
<string>C</string> <string>Append additional command line options to Clang, one per line. &lt;i&gt;Use this with care.&lt;/i&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item>
<widget class="QComboBox" name="cChooser"> <widget class="QPlainTextEdit" name="clangOptionsToAppendTextEdit"/>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item> </item>
<item row="1" column="0"> <item>
<widget class="QLabel" name="cppLabel"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="text"> <item>
<string>C++</string> <widget class="QPushButton" name="clangOptionsResetButton">
</property> <property name="text">
</widget> <string>Reset Options</string>
</item> </property>
<item row="1" column="1"> </widget>
<widget class="QComboBox" name="cppChooser"> </item>
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> <spacer name="horizontalSpacer">
<horstretch>0</horstretch> <property name="orientation">
<verstretch>0</verstretch> <enum>Qt::Horizontal</enum>
</sizepolicy> </property>
</property> <property name="sizeHint" stdset="0">
</widget> <size>
</item> <width>40</width>
<item row="2" column="0"> <height>20</height>
<widget class="QLabel" name="objcLabel"> </size>
<property name="text"> </property>
<string>Objective C</string> </spacer>
</property> </item>
</widget> </layout>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="objcChooser"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="objcppLabel">
<property name="text">
<string>Objective C++</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="objcppChooser"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="hLabel">
<property name="text">
<string>Headers</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="hChooser"/>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@@ -384,9 +384,9 @@ bool CppModelManager::replaceDocument(Document::Ptr newDoc)
return true; return true;
} }
/// Make sure that m_projectMutex is locked when calling this.
void CppModelManager::ensureUpdated() void CppModelManager::ensureUpdated()
{ {
QMutexLocker locker(&d->m_projectMutex);
if (!d->m_dirty) if (!d->m_dirty)
return; return;
@@ -475,8 +475,7 @@ void CppModelManager::dumpModelManagerConfiguration(const QString &logFileId)
dumper.dumpProjectInfos(projectInfos()); dumper.dumpProjectInfos(projectInfos());
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true); dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
dumper.dumpWorkingCopy(workingCopy()); dumper.dumpWorkingCopy(workingCopy());
ensureUpdated(); dumper.dumpMergedEntities(headerPaths(), definedMacros());
dumper.dumpMergedEntities(d->m_headerPaths, d->m_definedMacros);
} }
QSet<AbstractEditorSupport *> CppModelManager::abstractEditorSupports() const QSet<AbstractEditorSupport *> CppModelManager::abstractEditorSupports() const
@@ -941,14 +940,19 @@ QList<ProjectPart::Ptr> CppModelManager::projectPartFromDependencies(
return parts.values(); return parts.values();
} }
ProjectPart::Ptr CppModelManager::fallbackProjectPart() const ProjectPart::Ptr CppModelManager::fallbackProjectPart()
{ {
ProjectPart::Ptr part(new ProjectPart); ProjectPart::Ptr part(new ProjectPart);
part->projectDefines = d->m_definedMacros; part->projectDefines = definedMacros();
part->headerPaths = d->m_headerPaths; part->headerPaths = headerPaths();
part->languageVersion = ProjectPart::CXX14; part->languageVersion = ProjectPart::CXX14;
// Do not activate ObjectiveCExtensions since this will lead to the
// "objective-c++" language option for a project-less *.cpp file.
part->languageExtensions = ProjectPart::AllExtensions; part->languageExtensions = ProjectPart::AllExtensions;
part->languageExtensions &= ~ProjectPart::ObjectiveCExtensions;
part->qtVersion = ProjectPart::Qt5; part->qtVersion = ProjectPart::Qt5;
part->updateLanguageFeatures(); part->updateLanguageFeatures();
@@ -1254,24 +1258,31 @@ CppIndexingSupport *CppModelManager::indexingSupport()
QStringList CppModelManager::projectFiles() QStringList CppModelManager::projectFiles()
{ {
QMutexLocker locker(&d->m_projectMutex);
ensureUpdated(); ensureUpdated();
return d->m_projectFiles; return d->m_projectFiles;
} }
ProjectPart::HeaderPaths CppModelManager::headerPaths() ProjectPart::HeaderPaths CppModelManager::headerPaths()
{ {
QMutexLocker locker(&d->m_projectMutex);
ensureUpdated(); ensureUpdated();
return d->m_headerPaths; return d->m_headerPaths;
} }
void CppModelManager::setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths) void CppModelManager::setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths)
{ {
QMutexLocker locker(&d->m_projectMutex);
d->m_headerPaths = headerPaths; d->m_headerPaths = headerPaths;
} }
QByteArray CppModelManager::definedMacros() QByteArray CppModelManager::definedMacros()
{ {
QMutexLocker locker(&d->m_projectMutex);
ensureUpdated(); ensureUpdated();
return d->m_definedMacros; return d->m_definedMacros;
} }

View File

@@ -109,7 +109,7 @@ public:
QList<ProjectPart::Ptr> projectPartFromDependencies(const Utils::FileName &fileName) const; QList<ProjectPart::Ptr> projectPartFromDependencies(const Utils::FileName &fileName) const;
/// \return A synthetic \c ProjectPart which consists of all defines/includes/frameworks from /// \return A synthetic \c ProjectPart which consists of all defines/includes/frameworks from
/// all loaded projects. /// all loaded projects.
ProjectPart::Ptr fallbackProjectPart() const; ProjectPart::Ptr fallbackProjectPart();
CPlusPlus::Snapshot snapshot() const; CPlusPlus::Snapshot snapshot() const;
Document::Ptr document(const QString &fileName) const; Document::Ptr document(const QString &fileName) const;

View File

@@ -505,7 +505,7 @@ void ProjectPartBuilder::createProjectPart(const QStringList &theSources,
} }
CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart::Ptr &projectPart) CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart)
: m_projectPart(projectPart) : m_projectPart(projectPart)
{ {
} }
@@ -544,7 +544,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
QStringList result; QStringList result;
foreach (const HeaderPath &headerPath , m_projectPart->headerPaths) { foreach (const HeaderPath &headerPath , m_projectPart.headerPaths) {
if (headerPath.path.isEmpty()) if (headerPath.path.isEmpty())
continue; continue;
@@ -571,7 +571,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
void CompilerOptionsBuilder::addToolchainAndProjectDefines() void CompilerOptionsBuilder::addToolchainAndProjectDefines()
{ {
QByteArray extendedDefines = m_projectPart->toolchainDefines + m_projectPart->projectDefines; QByteArray extendedDefines = m_projectPart.toolchainDefines + m_projectPart.projectDefines;
QStringList result; QStringList result;
foreach (QByteArray def, extendedDefines.split('\n')) { foreach (QByteArray def, extendedDefines.split('\n')) {
@@ -645,7 +645,7 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc
void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind) void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind)
{ {
const bool objcExt = m_projectPart->languageExtensions & ProjectPart::ObjectiveCExtensions; const bool objcExt = m_projectPart.languageExtensions & ProjectPart::ObjectiveCExtensions;
const QStringList options = createLanguageOptionGcc(fileKind, objcExt); const QStringList options = createLanguageOptionGcc(fileKind, objcExt);
m_options.append(options); m_options.append(options);
} }
@@ -653,9 +653,9 @@ void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind)
void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions) void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions)
{ {
QStringList opts; QStringList opts;
const ProjectPart::LanguageExtensions languageExtensions = m_projectPart->languageExtensions; const ProjectPart::LanguageExtensions languageExtensions = m_projectPart.languageExtensions;
const bool gnuExtensions = languageExtensions & ProjectPart::GnuExtensions; const bool gnuExtensions = languageExtensions & ProjectPart::GnuExtensions;
switch (m_projectPart->languageVersion) { switch (m_projectPart.languageVersion) {
case ProjectPart::C89: case ProjectPart::C89:
opts << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89")); opts << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89"));
break; break;
@@ -716,7 +716,7 @@ bool CompilerOptionsBuilder::excludeDefineLine(const QByteArray &defineLine) con
// The right-hand sides are gcc built-ins that clang does not understand, and they'd // The right-hand sides are gcc built-ins that clang does not understand, and they'd
// override clang's own (non-macro, it seems) definitions of the symbols on the left-hand // override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
// side. // side.
const bool isGccToolchain = m_projectPart->toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; const bool isGccToolchain = m_projectPart.toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
if (isGccToolchain && defineLine.contains("has_include")) if (isGccToolchain && defineLine.contains("has_include"))
return true; return true;

View File

@@ -215,7 +215,7 @@ private:
class CPPTOOLS_EXPORT CompilerOptionsBuilder class CPPTOOLS_EXPORT CompilerOptionsBuilder
{ {
public: public:
CompilerOptionsBuilder(const ProjectPart::Ptr &projectPart); CompilerOptionsBuilder(const ProjectPart &projectPart);
virtual ~CompilerOptionsBuilder() {} virtual ~CompilerOptionsBuilder() {}
QStringList options() const; QStringList options() const;
@@ -237,7 +237,7 @@ protected:
virtual QString defineOption() const; virtual QString defineOption() const;
virtual QString includeOption() const; virtual QString includeOption() const;
const ProjectPart::Ptr m_projectPart; const ProjectPart m_projectPart;
private: private:
QString defineLineToDefineOption(const QByteArray &defineLine); QString defineLineToDefineOption(const QByteArray &defineLine);
@@ -247,4 +247,6 @@ private:
} // namespace CppTools } // namespace CppTools
Q_DECLARE_METATYPE(CppTools::ProjectPart::Ptr)
#endif // CPPPROJECTPART_H #endif // CPPPROJECTPART_H

View File

@@ -55,6 +55,7 @@ enum { lowerCaseFilesDefault = 1 };
const char CPPTOOLS_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview"; const char CPPTOOLS_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview";
const char CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY[] = "ModelManagerSupporters"; const char CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY[] = "ModelManagerSupporters";
const char CPPTOOLS_MODEL_MANAGER_PCH_USAGE[] = "PCHUsage"; const char CPPTOOLS_MODEL_MANAGER_PCH_USAGE[] = "PCHUsage";
const char CPPTOOLS_EXTRA_CLANG_OPTIONS[] = "ExtraClangOptions";
const char CPP_CODE_STYLE_SETTINGS_ID[] = "A.Cpp.Code Style"; const char CPP_CODE_STYLE_SETTINGS_ID[] = "A.Cpp.Code Style";
const char CPP_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("CppTools", "Code Style"); const char CPP_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("CppTools", "Code Style");

View File

@@ -391,7 +391,7 @@ QList<IncludeGroup> IncludeGroup::detectIncludeGroupsByIncludeType(const QList<I
{ {
// Create sub groups // Create sub groups
QList<IncludeGroup> result; QList<IncludeGroup> result;
Client::IncludeType lastIncludeType; Client::IncludeType lastIncludeType = Client::IncludeLocal;
QList<Include> currentIncludes; QList<Include> currentIncludes;
bool isFirst = true; bool isFirst = true;
foreach (const Include &include, includes) { foreach (const Include &include, includes) {

View File

@@ -340,8 +340,8 @@ void CdbEngine::syncOperateByInstruction(bool operateByInstruction)
return; return;
QTC_ASSERT(m_accessible, return); QTC_ASSERT(m_accessible, return);
m_operateByInstruction = operateByInstruction; m_operateByInstruction = operateByInstruction;
runCommand(DebuggerCommand(m_operateByInstruction ? QByteArray("l-t") : QByteArray("l+t"))); runCommand({m_operateByInstruction ? "l-t" : "l+t", NoFlags});
runCommand(DebuggerCommand(m_operateByInstruction ? QByteArray("l-s") : QByteArray("l+s"))); runCommand({m_operateByInstruction ? "l-s" : "l+s", NoFlags});
} }
void CdbEngine::syncVerboseLog(bool verboseLog) void CdbEngine::syncVerboseLog(bool verboseLog)
@@ -350,7 +350,7 @@ void CdbEngine::syncVerboseLog(bool verboseLog)
return; return;
QTC_ASSERT(m_accessible, return); QTC_ASSERT(m_accessible, return);
m_verboseLog = verboseLog; m_verboseLog = verboseLog;
runCommand(DebuggerCommand(m_verboseLog ? QByteArray("!sym noisy") : QByteArray("!sym quiet"))); runCommand({m_verboseLog ? "!sym noisy" : "!sym quiet", NoFlags});
} }
bool CdbEngine::canHandleToolTip(const DebuggerToolTipContext &context) const bool CdbEngine::canHandleToolTip(const DebuggerToolTipContext &context) const
@@ -474,11 +474,9 @@ void CdbEngine::consoleStubExited()
void CdbEngine::createFullBacktrace() void CdbEngine::createFullBacktrace()
{ {
DebuggerCommand cmd("~*kp"); runCommand({"~*kp", BuiltinCommand, [this](const DebuggerResponse &response) {
cmd.callback = [this](const DebuggerResponse &response) {
Internal::openTextEditor(QLatin1String("Backtrace $"), response.data.toLatin1()); Internal::openTextEditor(QLatin1String("Backtrace $"), response.data.toLatin1());
}; }});
runCommand(cmd, BuiltinCommand);
} }
void CdbEngine::setupEngine() void CdbEngine::setupEngine()
@@ -646,7 +644,7 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
m_hasDebuggee = true; m_hasDebuggee = true;
if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
m_accessible = true; m_accessible = true;
runCommand(DebuggerCommand(".load " + extensionFileName.toLocal8Bit())); runCommand({".load " + extensionFileName.toLocal8Bit(), NoFlags});
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk") STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk")
notifyEngineSetupOk(); notifyEngineSetupOk();
} }
@@ -659,27 +657,25 @@ void CdbEngine::setupInferior()
qDebug("setupInferior"); qDebug("setupInferior");
const DebuggerRunParameters &rp = runParameters(); const DebuggerRunParameters &rp = runParameters();
if (!rp.commandsAfterConnect.isEmpty()) if (!rp.commandsAfterConnect.isEmpty())
runCommand(DebuggerCommand(rp.commandsAfterConnect)); runCommand({rp.commandsAfterConnect, NoFlags});
// QmlCppEngine expects the QML engine to be connected before any breakpoints are hit // QmlCppEngine expects the QML engine to be connected before any breakpoints are hit
// (attemptBreakpointSynchronization() will be directly called then) // (attemptBreakpointSynchronization() will be directly called then)
attemptBreakpointSynchronization(); attemptBreakpointSynchronization();
if (rp.breakOnMain) { if (rp.breakOnMain) {
const BreakpointParameters bp(BreakpointAtMain); const BreakpointParameters bp(BreakpointAtMain);
BreakpointModelId id(quint16(-1)); BreakpointModelId id(quint16(-1));
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, id, true)); runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, id, true), BuiltinCommand,
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }; [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }});
runCommand(cmd, BuiltinCommand);
} }
runCommand(DebuggerCommand("sxn 0x4000001f")); // Do not break on WowX86 exceptions. runCommand({"sxn 0x4000001f", NoFlags}); // Do not break on WowX86 exceptions.
runCommand(DebuggerCommand("sxn ibp")); // Do not break on initial breakpoints. runCommand({"sxn ibp", NoFlags}); // Do not break on initial breakpoints.
runCommand(DebuggerCommand(".asm source_line")); // Source line in assembly runCommand({".asm source_line", NoFlags}); // Source line in assembly
runCommand(DebuggerCommand(m_extensionCommandPrefixBA + "setparameter maxStringLength=" runCommand({m_extensionCommandPrefixBA + "setparameter maxStringLength="
+ action(MaximalStringLength)->value().toByteArray() + action(MaximalStringLength)->value().toByteArray()
+ " maxStackDepth=" + " maxStackDepth="
+ action(MaximalStackDepth)->value().toByteArray())); + action(MaximalStackDepth)->value().toByteArray(), NoFlags});
DebuggerCommand cmd("pid"); runCommand({"pid", ExtensionCommand, [this](const DebuggerResponse &response) {
cmd.callback = [this](const DebuggerResponse &response) {
// Fails for core dumps. // Fails for core dumps.
if (response.resultClass == ResultDone) if (response.resultClass == ResultDone)
notifyInferiorPid(response.data.data().toULongLong()); notifyInferiorPid(response.data.data().toULongLong());
@@ -692,8 +688,7 @@ void CdbEngine::setupInferior()
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupFailed") STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupFailed")
notifyInferiorSetupFailed(); notifyInferiorSetupFailed();
} }
}; }});
runCommand(cmd, ExtensionCommand);
} }
static QByteArray msvcRunTime(const Abi::OSFlavor flavour) static QByteArray msvcRunTime(const Abi::OSFlavor flavour)
@@ -736,35 +731,25 @@ void CdbEngine::runEngine()
const QStringList breakEvents = stringListSetting(CdbBreakEvents); const QStringList breakEvents = stringListSetting(CdbBreakEvents);
foreach (const QString &breakEvent, breakEvents) foreach (const QString &breakEvent, breakEvents)
runCommand(DebuggerCommand(QByteArray("sxe ") + breakEvent.toLatin1())); runCommand({"sxe " + breakEvent.toLatin1(), NoFlags});
// Break functions: each function must be fully qualified, // Break functions: each function must be fully qualified,
// else the debugger will slow down considerably. // else the debugger will slow down considerably.
DebuggerCommand cmd; const auto cb = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
if (boolSetting(CdbBreakOnCrtDbgReport)) { if (boolSetting(CdbBreakOnCrtDbgReport)) {
const QByteArray module = msvcRunTime(runParameters().toolChainAbi.osFlavor()); const QByteArray module = msvcRunTime(runParameters().toolChainAbi.osFlavor());
const QByteArray debugModule = module + 'D'; const QByteArray debugModule = module + 'D';
const QByteArray wideFunc = QByteArray(CdbOptionsPage::crtDbgReport).append('W'); const QByteArray wideFunc = QByteArray(CdbOptionsPage::crtDbgReport).append('W');
cmd.function = breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module); runCommand({breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module), BuiltinCommand, cb});
runCommand(cmd, BuiltinCommand); runCommand({breakAtFunctionCommand(wideFunc, module), BuiltinCommand, cb});
cmd.function = breakAtFunctionCommand(wideFunc, module); runCommand({breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule), BuiltinCommand, cb});
runCommand(cmd, BuiltinCommand);
cmd.function = breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule);
runCommand(cmd, BuiltinCommand);
cmd.function = breakAtFunctionCommand(wideFunc, debugModule);
runCommand(cmd, BuiltinCommand);
} }
if (boolSetting(BreakOnWarning)) { if (boolSetting(BreakOnWarning)) {
cmd.function = "bm /( QtCored4!qWarning"; // 'bm': All overloads. runCommand({"bm /( QtCored4!qWarning", BuiltinCommand}); // 'bm': All overloads.
runCommand(cmd, BuiltinCommand); runCommand({"bm /( Qt5Cored!QMessageLogger::warning", BuiltinCommand});
cmd.function = "bm /( Qt5Cored!QMessageLogger::warning";
runCommand(cmd, BuiltinCommand);
} }
if (boolSetting(BreakOnFatal)) { if (boolSetting(BreakOnFatal)) {
cmd.function = "bm /( QtCored4!qFatal"; // 'bm': All overloads. runCommand({"bm /( QtCored4!qFatal", BuiltinCommand}); // 'bm': All overloads.
runCommand(cmd, BuiltinCommand); runCommand({"bm /( Qt5Cored!QMessageLogger::fatal", BuiltinCommand});
cmd.function = "bm /( Qt5Cored!QMessageLogger::fatal";
runCommand(cmd, BuiltinCommand);
} }
if (runParameters().startMode == AttachCore) { if (runParameters().startMode == AttachCore) {
QTC_ASSERT(!m_coreStopReason.isNull(), return; ); QTC_ASSERT(!m_coreStopReason.isNull(), return; );
@@ -848,10 +833,10 @@ void CdbEngine::shutdownEngine()
detachDebugger(); detachDebugger();
// Remote requires a bit more force to quit. // Remote requires a bit more force to quit.
if (m_effectiveStartMode == AttachToRemoteServer) { if (m_effectiveStartMode == AttachToRemoteServer) {
runCommand(DebuggerCommand(m_extensionCommandPrefixBA + "shutdownex")); runCommand({m_extensionCommandPrefixBA + "shutdownex", NoFlags});
runCommand(DebuggerCommand("qq")); runCommand({"qq", NoFlags});
} else { } else {
runCommand(DebuggerCommand("q")); runCommand({"q", NoFlags});
} }
} else { } else {
// Remote process. No can do, currently // Remote process. No can do, currently
@@ -885,7 +870,7 @@ void CdbEngine::processFinished()
void CdbEngine::detachDebugger() void CdbEngine::detachDebugger()
{ {
runCommand(DebuggerCommand(".detach")); runCommand({".detach", NoFlags});
} }
static inline bool isWatchIName(const QByteArray &iname) static inline bool isWatchIName(const QByteArray &iname)
@@ -913,21 +898,21 @@ void CdbEngine::executeStep()
{ {
if (!m_operateByInstruction) if (!m_operateByInstruction)
m_sourceStepInto = true; // See explanation at handleStackTrace(). m_sourceStepInto = true; // See explanation at handleStackTrace().
runCommand(DebuggerCommand(QByteArray("t"))); // Step into-> t (trace) runCommand({"t", NoFlags}); // Step into-> t (trace)
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested") STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
notifyInferiorRunRequested(); notifyInferiorRunRequested();
} }
void CdbEngine::executeStepOut() void CdbEngine::executeStepOut()
{ {
runCommand(DebuggerCommand(QByteArray("gu"))); // Step out-> gu (go up) runCommand({"gu", NoFlags}); // Step out-> gu (go up)
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested") STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
notifyInferiorRunRequested(); notifyInferiorRunRequested();
} }
void CdbEngine::executeNext() void CdbEngine::executeNext()
{ {
runCommand(DebuggerCommand(QByteArray("p"))); // Step over -> p runCommand({"p", NoFlags}); // Step over -> p
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested") STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
notifyInferiorRunRequested(); notifyInferiorRunRequested();
} }
@@ -951,7 +936,7 @@ void CdbEngine::continueInferior()
void CdbEngine::doContinueInferior() void CdbEngine::doContinueInferior()
{ {
runCommand(DebuggerCommand(QByteArray("g"))); runCommand({"g", NoFlags});
} }
bool CdbEngine::canInterruptInferior() const bool CdbEngine::canInterruptInferior() const
@@ -1025,9 +1010,8 @@ void CdbEngine::executeRunToLine(const ContextData &data)
bp.lineNumber = data.lineNumber; bp.lineNumber = data.lineNumber;
} }
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true)); runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), BuiltinCommand,
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }; [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }});
runCommand(cmd, BuiltinCommand);
continueInferior(); continueInferior();
} }
@@ -1036,10 +1020,8 @@ void CdbEngine::executeRunToFunction(const QString &functionName)
// Add one-shot breakpoint // Add one-shot breakpoint
BreakpointParameters bp(BreakpointByFunction); BreakpointParameters bp(BreakpointByFunction);
bp.functionName = functionName; bp.functionName = functionName;
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), BuiltinCommand,
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true)); [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }});
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
runCommand(cmd, BuiltinCommand);
continueInferior(); continueInferior();
} }
@@ -1049,7 +1031,7 @@ void CdbEngine::setRegisterValue(const QByteArray &name, const QString &value)
QByteArray cmd; QByteArray cmd;
ByteArrayInputStream str(cmd); ByteArrayInputStream str(cmd);
str << "r " << name << '=' << value; str << "r " << name << '=' << value;
runCommand(DebuggerCommand(cmd)); runCommand({cmd, NoFlags});
reloadRegisters(); reloadRegisters();
} }
@@ -1061,25 +1043,25 @@ void CdbEngine::executeJumpToLine(const ContextData &data)
gotoLocation(Location(data.address)); gotoLocation(Location(data.address));
} else { } else {
// Jump to source line: Resolve source line address and go to that location // Jump to source line: Resolve source line address and go to that location
DebuggerCommand cmd; QByteArray cmd;
ByteArrayInputStream str(cmd.function); ByteArrayInputStream str(cmd);
str << "? `" << QDir::toNativeSeparators(data.fileName) << ':' << data.lineNumber << '`'; str << "? `" << QDir::toNativeSeparators(data.fileName) << ':' << data.lineNumber << '`';
cmd.callback = [this, data](const DebuggerResponse &r) { handleJumpToLineAddressResolution(r, data); }; runCommand({cmd, BuiltinCommand, [this, data](const DebuggerResponse &r) {
runCommand(cmd, BuiltinCommand); handleJumpToLineAddressResolution(r, data); }});
} }
} }
void CdbEngine::jumpToAddress(quint64 address) void CdbEngine::jumpToAddress(quint64 address)
{ {
// Fake a jump to address by setting the PC register. // Fake a jump to address by setting the PC register.
QByteArray registerCmd; QByteArray cmd;
ByteArrayInputStream str(registerCmd); ByteArrayInputStream str(cmd);
// PC-register depending on 64/32bit. // PC-register depending on 64/32bit.
str << "r " << (runParameters().toolChainAbi.wordWidth() == 64 ? "rip" : "eip") << '='; str << "r " << (runParameters().toolChainAbi.wordWidth() == 64 ? "rip" : "eip") << '=';
str.setHexPrefix(true); str.setHexPrefix(true);
str.setIntegerBase(16); str.setIntegerBase(16);
str << address; str << address;
runCommand(DebuggerCommand(registerCmd)); runCommand({cmd, NoFlags});
} }
void CdbEngine::handleJumpToLineAddressResolution(const DebuggerResponse &response, const ContextData &context) void CdbEngine::handleJumpToLineAddressResolution(const DebuggerResponse &response, const ContextData &context)
@@ -1144,7 +1126,7 @@ void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const Q
break; break;
} }
runCommand(DebuggerCommand(cmd)); runCommand({cmd, NoFlags});
// Update all locals in case we change a union or something pointed to // Update all locals in case we change a union or something pointed to
// that affects other variables, too. // that affects other variables, too.
updateLocals(); updateLocals();
@@ -1168,11 +1150,11 @@ void CdbEngine::handleThreads(const DebuggerResponse &response)
void CdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages languages) void CdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages languages)
{ {
if (languages & CppLanguage) if (languages & CppLanguage)
runCommand(DebuggerCommand(command.toLocal8Bit())); runCommand({command.toLocal8Bit(), NoFlags});
} }
// Post command to the cdb process // Post command to the cdb process
void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags) void CdbEngine::runCommand(const DebuggerCommand &dbgCmd)
{ {
QByteArray cmd = dbgCmd.function + dbgCmd.argsToString(); QByteArray cmd = dbgCmd.function + dbgCmd.argsToString();
if (!m_accessible) { if (!m_accessible) {
@@ -1184,7 +1166,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags)
QByteArray fullCmd; QByteArray fullCmd;
ByteArrayInputStream str(fullCmd); ByteArrayInputStream str(fullCmd);
if (flags & BuiltinCommand) { if (dbgCmd.flags & BuiltinCommand) {
// Post a built-in-command producing free-format output with a callback. // Post a built-in-command producing free-format output with a callback.
// In order to catch the output, it is enclosed in 'echo' commands // In order to catch the output, it is enclosed in 'echo' commands
// printing a specially formatted token to be identifiable in the output. // printing a specially formatted token to be identifiable in the output.
@@ -1192,7 +1174,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags)
str << ".echo \"" << m_tokenPrefix << token << "<\"\n" str << ".echo \"" << m_tokenPrefix << token << "<\"\n"
<< cmd << "\n.echo \"" << m_tokenPrefix << token << ">\""; << cmd << "\n.echo \"" << m_tokenPrefix << token << ">\"";
m_commandForToken.insert(token, dbgCmd); m_commandForToken.insert(token, dbgCmd);
} else if (flags & ExtensionCommand) { } else if (dbgCmd.flags & ExtensionCommand) {
// Post an extension command producing one-line output with a callback, // Post an extension command producing one-line output with a callback,
// pass along token for identification in hash. // pass along token for identification in hash.
const int token = m_nextCommandToken++; const int token = m_nextCommandToken++;
@@ -1331,10 +1313,10 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
if (partialUpdate) if (partialUpdate)
str << blankSeparator << updateParameters.partialVariable; str << blankSeparator << updateParameters.partialVariable;
DebuggerCommand cmd("locals"); DebuggerCommand cmd("locals", ExtensionCommand);
cmd.args = QLatin1String(arguments); cmd.args = QLatin1String(arguments);
cmd.callback = [this, partialUpdate](const DebuggerResponse &r) { handleLocals(r, partialUpdate); }; cmd.callback = [this, partialUpdate](const DebuggerResponse &r) { handleLocals(r, partialUpdate); };
runCommand(cmd, ExtensionCommand); runCommand(cmd);
} }
void CdbEngine::updateAll() void CdbEngine::updateAll()
@@ -1349,9 +1331,8 @@ void CdbEngine::selectThread(ThreadId threadId)
threadsHandler()->setCurrentThread(threadId); threadsHandler()->setCurrentThread(threadId);
DebuggerCommand cmd('~' + QByteArray::number(threadId.raw()) + " s"); runCommand({'~' + QByteArray::number(threadId.raw()) + " s", BuiltinCommand,
cmd.callback = [this](const DebuggerResponse &) { reloadFullStack(); }; [this](const DebuggerResponse &) { reloadFullStack(); }});
runCommand(cmd, BuiltinCommand);
} }
// Default address range for showing disassembly. // Default address range for showing disassembly.
@@ -1401,7 +1382,8 @@ void CdbEngine::postDisassemblerCommand(quint64 address, quint64 endAddress,
// Parse: "00000000`77606060 cc int 3" // Parse: "00000000`77606060 cc int 3"
agent->setContents(parseCdbDisassembler(response.data.data())); agent->setContents(parseCdbDisassembler(response.data.data()));
}; };
runCommand(cmd, BuiltinCommand); cmd.flags = BuiltinCommand;
runCommand(cmd);
} }
void CdbEngine::postResolveSymbol(const QString &module, const QString &function, void CdbEngine::postResolveSymbol(const QString &module, const QString &function,
@@ -1413,14 +1395,10 @@ void CdbEngine::postResolveSymbol(const QString &module, const QString &function
const QList<quint64> addresses = m_symbolAddressCache.values(symbol); const QList<quint64> addresses = m_symbolAddressCache.values(symbol);
if (addresses.isEmpty()) { if (addresses.isEmpty()) {
showMessage(QLatin1String("Resolving symbol: ") + symbol + QLatin1String("..."), LogMisc); showMessage(QLatin1String("Resolving symbol: ") + symbol + QLatin1String("..."), LogMisc);
DebuggerCommand cmd(QByteArray("x ") + symbol.toLatin1()); runCommand({"x " + symbol.toLatin1(), BuiltinCommand,
cmd.callback = [this, symbol, agent](const DebuggerResponse &r) { [this, symbol, agent](const DebuggerResponse &r) { handleResolveSymbol(r, symbol, agent); }});
handleResolveSymbol(r, symbol, agent);
};
runCommand(cmd, BuiltinCommand);
} else { } else {
showMessage(QString::fromLatin1("Using cached addresses for %1."). showMessage(QString::fromLatin1("Using cached addresses for %1.").arg(symbol), LogMisc);
arg(symbol), LogMisc);
handleResolveSymbolHelper(addresses, agent); handleResolveSymbolHelper(addresses, agent);
} }
} }
@@ -1556,7 +1534,7 @@ void CdbEngine::fetchMemory(MemoryAgent *agent, QObject *editor, quint64 addr, q
void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie) void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
{ {
DebuggerCommand cmd("memory"); DebuggerCommand cmd("memory", ExtensionCommand);
QByteArray args; QByteArray args;
ByteArrayInputStream str(args); ByteArrayInputStream str(args);
str << cookie.address << ' ' << cookie.length; str << cookie.address << ' ' << cookie.length;
@@ -1570,7 +1548,7 @@ void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
showMessage(response.data["msg"].toLatin1(), LogWarning); showMessage(response.data["msg"].toLatin1(), LogWarning);
} }
}; };
runCommand(cmd, ExtensionCommand); runCommand(cmd);
} }
void CdbEngine::changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr, const QByteArray &data) void CdbEngine::changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr, const QByteArray &data)
@@ -1580,15 +1558,13 @@ void CdbEngine::changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr, c
const MemoryChangeCookie cookie(addr, data); const MemoryChangeCookie cookie(addr, data);
doInterruptInferiorCustomSpecialStop(qVariantFromValue(cookie)); doInterruptInferiorCustomSpecialStop(qVariantFromValue(cookie));
} else { } else {
runCommand(DebuggerCommand(cdbWriteMemoryCommand(addr, data))); runCommand({cdbWriteMemoryCommand(addr, data), NoFlags});
} }
} }
void CdbEngine::reloadModules() void CdbEngine::reloadModules()
{ {
DebuggerCommand cmd("modules"); runCommand({"modules", ExtensionCommand, CB(handleModules)});
cmd.callback = CB(handleModules);
runCommand(cmd, ExtensionCommand);
} }
void CdbEngine::loadSymbols(const QString & /* moduleName */) void CdbEngine::loadSymbols(const QString & /* moduleName */)
@@ -1607,9 +1583,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName)
void CdbEngine::reloadRegisters() void CdbEngine::reloadRegisters()
{ {
QTC_ASSERT(threadsHandler()->currentThreadIndex() >= 0, return); QTC_ASSERT(threadsHandler()->currentThreadIndex() >= 0, return);
DebuggerCommand cmd("registers"); runCommand({"registers", ExtensionCommand, CB(handleRegistersExt)});
cmd.callback = CB(handleRegistersExt);
runCommand(cmd, ExtensionCommand);
} }
void CdbEngine::reloadSourceFiles() void CdbEngine::reloadSourceFiles()
@@ -1620,18 +1594,18 @@ void CdbEngine::reloadFullStack()
{ {
if (debug) if (debug)
qDebug("%s", Q_FUNC_INFO); qDebug("%s", Q_FUNC_INFO);
DebuggerCommand cmd("stack"); DebuggerCommand cmd("stack", ExtensionCommand);
cmd.args = QStringLiteral("unlimited"); cmd.args = QStringLiteral("unlimited");
cmd.callback = CB(handleStackTrace); cmd.callback = CB(handleStackTrace);
runCommand(cmd, ExtensionCommand); runCommand(cmd);
} }
void CdbEngine::listBreakpoints() void CdbEngine::listBreakpoints()
{ {
DebuggerCommand cmd("breakpoints"); DebuggerCommand cmd("breakpoints", ExtensionCommand);
cmd.args = QStringLiteral("-v"); cmd.args = QStringLiteral("-v");
cmd.callback = CB(handleBreakPoints); cmd.callback = CB(handleBreakPoints);
runCommand(cmd, ExtensionCommand); runCommand(cmd);
} }
void CdbEngine::handleModules(const DebuggerResponse &response) void CdbEngine::handleModules(const DebuggerResponse &response)
@@ -1845,8 +1819,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
if (!conditionalBreakPointTriggered && !parameters.condition.isEmpty()) { if (!conditionalBreakPointTriggered && !parameters.condition.isEmpty()) {
*message = msgCheckingConditionalBreakPoint(id, number, parameters.condition, *message = msgCheckingConditionalBreakPoint(id, number, parameters.condition,
QString::number(threadId)); QString::number(threadId));
DebuggerCommand cmd("expression", ExtensionCommand);
DebuggerCommand cmd("expression");
QByteArray args = parameters.condition; QByteArray args = parameters.condition;
if (args.contains(' ') && !args.startsWith('"')) { if (args.contains(' ') && !args.startsWith('"')) {
args.prepend('"'); args.prepend('"');
@@ -1856,7 +1829,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
cmd.callback = [this, id, stopReason](const DebuggerResponse &response) { cmd.callback = [this, id, stopReason](const DebuggerResponse &response) {
handleExpression(response, id, stopReason); handleExpression(response, id, stopReason);
}; };
runCommand(cmd, ExtensionCommand); runCommand(cmd);
return StopReportLog; return StopReportLog;
} }
@@ -2004,7 +1977,7 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
// Start sequence to get all relevant data. // Start sequence to get all relevant data.
if (stopFlags & StopInArtificialThread) { if (stopFlags & StopInArtificialThread) {
showMessage(tr("Switching to main thread..."), LogMisc); showMessage(tr("Switching to main thread..."), LogMisc);
runCommand(DebuggerCommand("~0 s")); runCommand({"~0 s", NoFlags});
forcedThreadId = ThreadId(0); forcedThreadId = ThreadId(0);
// Re-fetch stack again. // Re-fetch stack again.
reloadFullStack(); reloadFullStack();
@@ -2019,9 +1992,8 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
executeStepOut(); executeStepOut();
return; return;
case ParseStackWow64: case ParseStackWow64:
DebuggerCommand cmd("lm m wow64"); runCommand({"lm m wow64", BuiltinCommand,
cmd.callback = [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }; [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }});
runCommand(cmd, BuiltinCommand);
break; break;
} }
} else { } else {
@@ -2112,9 +2084,8 @@ void CdbEngine::handleCheckWow64(const DebuggerResponse &response, const GdbMi &
// start end module name // start end module name
// 00000000`77490000 00000000`774d5000 wow64 (deferred) // 00000000`77490000 00000000`774d5000 wow64 (deferred)
if (response.data.data().contains("wow64")) { if (response.data.data().contains("wow64")) {
DebuggerCommand cmd("k"); runCommand({"k", BuiltinCommand,
cmd.callback = [this, stack](const DebuggerResponse &r) { ensureUsing32BitStackInWow64(r, stack); }; [this, stack](const DebuggerResponse &r) { ensureUsing32BitStackInWow64(r, stack); }});
runCommand(cmd, BuiltinCommand);
return; return;
} }
m_wow64State = noWow64Stack; m_wow64State = noWow64Stack;
@@ -2134,9 +2105,7 @@ void CdbEngine::ensureUsing32BitStackInWow64(const DebuggerResponse &response, c
return; return;
} else if (line.startsWith("Child-SP")) { } else if (line.startsWith("Child-SP")) {
m_wow64State = wow64Stack64Bit; m_wow64State = wow64Stack64Bit;
DebuggerCommand cmd("!wow64exts.sw"); runCommand({"!wow64exts.sw", BuiltinCommand, CB(handleSwitchWow64Stack)});
cmd.callback = CB(handleSwitchWow64Stack);
runCommand(cmd, BuiltinCommand);
return; return;
} }
} }
@@ -2153,9 +2122,7 @@ void CdbEngine::handleSwitchWow64Stack(const DebuggerResponse &response)
else else
m_wow64State = noWow64Stack; m_wow64State = noWow64Stack;
// reload threads and the stack after switching the mode // reload threads and the stack after switching the mode
DebuggerCommand cmd("threads"); runCommand({"threads", ExtensionCommand, CB(handleThreads)});
cmd.callback = CB(handleThreads);
runCommand(cmd, ExtensionCommand);
} }
void CdbEngine::handleSessionAccessible(unsigned long cdbExState) void CdbEngine::handleSessionAccessible(unsigned long cdbExState)
@@ -2670,6 +2637,7 @@ void CdbEngine::attemptBreakpointSynchronization()
foreach (Breakpoint bp, bps) { foreach (Breakpoint bp, bps) {
BreakpointParameters parameters = bp.parameters(); BreakpointParameters parameters = bp.parameters();
BreakpointModelId id = bp.id(); BreakpointModelId id = bp.id();
const auto handleBreakInsertCB = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
BreakpointResponse response; BreakpointResponse response;
response.fromParameters(parameters); response.fromParameters(parameters);
response.id = BreakpointResponseId(id.majorPart(), id.minorPart()); response.id = BreakpointResponseId(id.majorPart(), id.minorPart());
@@ -2688,16 +2656,14 @@ void CdbEngine::attemptBreakpointSynchronization()
lineCorrection.reset(new BreakpointCorrectionContext(Internal::cppCodeModelSnapshot(), lineCorrection.reset(new BreakpointCorrectionContext(Internal::cppCodeModelSnapshot(),
CppTools::CppModelManager::instance()->workingCopy())); CppTools::CppModelManager::instance()->workingCopy()));
response.lineNumber = lineCorrection->fixLineNumber(parameters.fileName, parameters.lineNumber); response.lineNumber = lineCorrection->fixLineNumber(parameters.fileName, parameters.lineNumber);
DebuggerCommand cmd(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false)); QByteArray cmd = cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false);
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }; runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
runCommand(cmd, BuiltinCommand);
} else { } else {
DebuggerCommand cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false)); QByteArray cmd = cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false);
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }; runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
runCommand(cmd, BuiltinCommand);
} }
if (!parameters.enabled) if (!parameters.enabled)
runCommand(DebuggerCommand("bd " + QByteArray::number(breakPointIdToCdbId(id)))); runCommand({"bd " + QByteArray::number(breakPointIdToCdbId(id)), NoFlags});
bp.notifyBreakpointInsertProceeding(); bp.notifyBreakpointInsertProceeding();
bp.notifyBreakpointInsertOk(); bp.notifyBreakpointInsertOk();
m_pendingBreakpointMap.insert(id, response); m_pendingBreakpointMap.insert(id, response);
@@ -2716,24 +2682,23 @@ void CdbEngine::attemptBreakpointSynchronization()
qPrintable(parameters.toString())); qPrintable(parameters.toString()));
if (parameters.enabled != bp.response().enabled) { if (parameters.enabled != bp.response().enabled) {
// Change enabled/disabled breakpoints without triggering update. // Change enabled/disabled breakpoints without triggering update.
runCommand(DebuggerCommand((parameters.enabled ? "be " : "bd ") runCommand({(parameters.enabled ? "be " : "bd ")
+ QByteArray::number(breakPointIdToCdbId(id)))); + QByteArray::number(breakPointIdToCdbId(id)), NoFlags});
response.pending = false; response.pending = false;
response.enabled = parameters.enabled; response.enabled = parameters.enabled;
bp.setResponse(response); bp.setResponse(response);
} else { } else {
// Delete and re-add, triggering update // Delete and re-add, triggering update
addedChanged = true; addedChanged = true;
runCommand(DebuggerCommand(cdbClearBreakpointCommand(id))); runCommand({cdbClearBreakpointCommand(id), NoFlags});
DebuggerCommand cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false)); QByteArray cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }; runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
runCommand(cmd, BuiltinCommand);
m_pendingBreakpointMap.insert(id, response); m_pendingBreakpointMap.insert(id, response);
} }
bp.notifyBreakpointChangeOk(); bp.notifyBreakpointChangeOk();
break; break;
case BreakpointRemoveRequested: case BreakpointRemoveRequested:
runCommand(DebuggerCommand(cdbClearBreakpointCommand(id))); runCommand({cdbClearBreakpointCommand(id), NoFlags});
bp.notifyBreakpointRemoveProceeding(); bp.notifyBreakpointRemoveProceeding();
bp.notifyBreakpointRemoveOk(); bp.notifyBreakpointRemoveOk();
m_pendingBreakpointMap.remove(id); m_pendingBreakpointMap.remove(id);
@@ -2745,7 +2710,7 @@ void CdbEngine::attemptBreakpointSynchronization()
foreach (BreakpointModelId id, m_insertSubBreakpointMap.keys()) { foreach (BreakpointModelId id, m_insertSubBreakpointMap.keys()) {
addedChanged = true; addedChanged = true;
const BreakpointResponse &response = m_insertSubBreakpointMap.value(id); const BreakpointResponse &response = m_insertSubBreakpointMap.value(id);
runCommand(DebuggerCommand(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false))); runCommand({cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false), NoFlags});
m_insertSubBreakpointMap.remove(id); m_insertSubBreakpointMap.remove(id);
m_pendingSubBreakpointMap.insert(id, response); m_pendingSubBreakpointMap.insert(id, response);
} }
@@ -2873,9 +2838,7 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
void CdbEngine::loadAdditionalQmlStack() void CdbEngine::loadAdditionalQmlStack()
{ {
DebuggerCommand cmd("qmlstack"); runCommand({"qmlstack", ExtensionCommand, CB(handleAdditionalQmlStack)});
cmd.callback = CB(handleAdditionalQmlStack);
runCommand(cmd, ExtensionCommand);
} }
void CdbEngine::handleAdditionalQmlStack(const DebuggerResponse &response) void CdbEngine::handleAdditionalQmlStack(const DebuggerResponse &response)
@@ -2920,9 +2883,8 @@ void CdbEngine::handleStackTrace(const DebuggerResponse &response)
GdbMi stack = response.data; GdbMi stack = response.data;
if (response.resultClass == ResultDone) { if (response.resultClass == ResultDone) {
if (parseStackTrace(stack, false) == ParseStackWow64) { if (parseStackTrace(stack, false) == ParseStackWow64) {
DebuggerCommand cmd("lm m wow64"); runCommand({"lm m wow64", BuiltinCommand,
cmd.callback = [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }; [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }});
runCommand(cmd, BuiltinCommand);
} }
} else { } else {
showMessage(stack["msg"].toLatin1(), LogError); showMessage(stack["msg"].toLatin1(), LogError);
@@ -3096,17 +3058,16 @@ void CdbEngine::watchPoint(const QPoint &p)
void CdbEngine::postWidgetAtCommand() void CdbEngine::postWidgetAtCommand()
{ {
DebuggerCommand cmd("widgetat"); DebuggerCommand cmd("widgetat", ExtensionCommand);
cmd.args = QString::fromLatin1("%1 %2").arg(m_watchPointX, m_watchPointY); cmd.args = QString::fromLatin1("%1 %2").arg(m_watchPointX, m_watchPointY);
cmd.callback = CB(handleWidgetAt); runCommand(cmd);
runCommand(cmd, ExtensionCommand);
} }
void CdbEngine::handleCustomSpecialStop(const QVariant &v) void CdbEngine::handleCustomSpecialStop(const QVariant &v)
{ {
if (v.canConvert<MemoryChangeCookie>()) { if (v.canConvert<MemoryChangeCookie>()) {
const MemoryChangeCookie changeData = qvariant_cast<MemoryChangeCookie>(v); const MemoryChangeCookie changeData = qvariant_cast<MemoryChangeCookie>(v);
runCommand(DebuggerCommand(cdbWriteMemoryCommand(changeData.address, changeData.data))); runCommand({cdbWriteMemoryCommand(changeData.address, changeData.data), NoFlags});
return; return;
} }
if (v.canConvert<MemoryViewCookie>()) { if (v.canConvert<MemoryViewCookie>()) {

View File

@@ -127,7 +127,7 @@ private slots:
void readyReadStandardError(); void readyReadStandardError();
void processError(); void processError();
void processFinished(); void processFinished();
void runCommand(const DebuggerCommand &cmd, int flags = 0); void runCommand(const DebuggerCommand &cmd) override;
void operateByInstructionTriggered(bool); void operateByInstructionTriggered(bool);
void verboseLogTriggered(bool); void verboseLogTriggered(bool);
@@ -164,7 +164,7 @@ private:
ParseStackWow64 = 3 // Hit on a frame with 32bit emulation, switch debugger to 32 bit mode ParseStackWow64 = 3 // Hit on a frame with 32bit emulation, switch debugger to 32 bit mode
}; };
enum CommandFlags { enum CommandFlags {
NoCallBack = 0, NoFlags = 0,
BuiltinCommand, BuiltinCommand,
ExtensionCommand, ExtensionCommand,
}; };

View File

@@ -102,10 +102,6 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
checkBoxUseToolTipsInMainEditor = new QCheckBox(behaviorBox); checkBoxUseToolTipsInMainEditor = new QCheckBox(behaviorBox);
checkBoxUseToolTipsInMainEditor->setText(tr("Use tooltips in main editor while debugging")); checkBoxUseToolTipsInMainEditor->setText(tr("Use tooltips in main editor while debugging"));
checkBoxListSourceFiles = new QCheckBox(behaviorBox);
checkBoxListSourceFiles->setToolTip(tr("Populates the source file view automatically. This might slow down debugger startup considerably."));
checkBoxListSourceFiles->setText(tr("Populate source file view automatically"));
QString t = tr("Stopping and stepping in the debugger " QString t = tr("Stopping and stepping in the debugger "
"will automatically open views associated with the current location.") + QLatin1Char('\n'); "will automatically open views associated with the current location.") + QLatin1Char('\n');
checkBoxCloseSourceBuffersOnExit = new QCheckBox(behaviorBox); checkBoxCloseSourceBuffersOnExit = new QCheckBox(behaviorBox);
@@ -174,11 +170,10 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
gridLayout->addLayout(horizontalLayout, 7, 0, 1, 2); gridLayout->addLayout(horizontalLayout, 7, 0, 1, 2);
gridLayout->addWidget(checkBoxFontSizeFollowsEditor, 0, 1, 1, 1); gridLayout->addWidget(checkBoxFontSizeFollowsEditor, 0, 1, 1, 1);
gridLayout->addWidget(checkBoxListSourceFiles, 1, 1, 1, 1); gridLayout->addWidget(checkBoxSwitchModeOnExit, 1, 1, 1, 1);
gridLayout->addWidget(checkBoxSwitchModeOnExit, 2, 1, 1, 1); gridLayout->addWidget(checkBoxShowQmlObjectTree, 2, 1, 1, 1);
gridLayout->addWidget(checkBoxShowQmlObjectTree, 3, 1, 1, 1); gridLayout->addWidget(checkBoxKeepEditorStationaryWhileStepping, 3, 1, 1, 1);
gridLayout->addWidget(checkBoxKeepEditorStationaryWhileStepping, 4, 1, 1, 1); gridLayout->addWidget(checkBoxRegisterForPostMortem, 4, 1, 1, 1);
gridLayout->addWidget(checkBoxRegisterForPostMortem, 5, 1, 1, 1);
QVBoxLayout *verticalLayout = new QVBoxLayout(this); QVBoxLayout *verticalLayout = new QVBoxLayout(this);
verticalLayout->addWidget(behaviorBox); verticalLayout->addWidget(behaviorBox);
@@ -187,8 +182,6 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
m_group->clear(); m_group->clear();
m_group->insert(action(ListSourceFiles),
checkBoxListSourceFiles);
m_group->insert(action(UseAlternatingRowColors), m_group->insert(action(UseAlternatingRowColors),
checkBoxUseAlternatingRowColors); checkBoxUseAlternatingRowColors);
m_group->insert(action(UseToolTipsInMainEditor), m_group->insert(action(UseToolTipsInMainEditor),

View File

@@ -556,13 +556,6 @@ DebuggerSettings::DebuggerSettings()
item->setCheckable(true); item->setCheckable(true);
item->setDefaultValue(false); item->setDefaultValue(false);
insertItem(UseAddressInStackView, item); insertItem(UseAddressInStackView, item);
item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("ListSourceFiles"));
item->setText(tr("List Source Files"));
item->setCheckable(true);
item->setDefaultValue(false);
insertItem(ListSourceFiles, item);
item = new SavedAction(this); item = new SavedAction(this);
item->setSettingsKey(debugModeGroup, QLatin1String("SkipKnownFrames")); item->setSettingsKey(debugModeGroup, QLatin1String("SkipKnownFrames"));

View File

@@ -162,9 +162,6 @@ enum DebuggerActionCode
MaximalStringLength, MaximalStringLength,
DisplayStringLimit, DisplayStringLimit,
// Source List
ListSourceFiles,
// Running // Running
SkipKnownFrames, SkipKnownFrames,
EnableReverseDebugging, EnableReverseDebugging,

View File

@@ -1479,6 +1479,12 @@ void DebuggerEngine::watchPoint(const QPoint &)
{ {
} }
void DebuggerEngine::runCommand(const DebuggerCommand &)
{
// Overridden in the engines that use the interface.
QTC_CHECK(false);
}
void DebuggerEngine::fetchDisassembler(DisassemblerAgent *) void DebuggerEngine::fetchDisassembler(DisassemblerAgent *)
{ {
} }

View File

@@ -33,6 +33,7 @@
#include "debugger_global.h" #include "debugger_global.h"
#include "debuggerconstants.h" #include "debuggerconstants.h"
#include "debuggerprotocol.h"
#include "debuggerstartparameters.h" #include "debuggerstartparameters.h"
#include <projectexplorer/devicesupport/idevice.h> #include <projectexplorer/devicesupport/idevice.h>
@@ -61,7 +62,6 @@ namespace Internal {
class DebuggerEnginePrivate; class DebuggerEnginePrivate;
class DebuggerPluginPrivate; class DebuggerPluginPrivate;
class DisassemblerAgent; class DisassemblerAgent;
class GdbMi;
class MemoryAgent; class MemoryAgent;
class WatchData; class WatchData;
class WatchItem; class WatchItem;
@@ -98,7 +98,6 @@ public:
QString coreFile; QString coreFile;
QString overrideStartScript; // Used in attach to core and remote debugging QString overrideStartScript; // Used in attach to core and remote debugging
QString startMessage; // First status message shown. QString startMessage; // First status message shown.
QMap<QString, QString> sourcePathMap;
QString debugInfoLocation; // Gdb "set-debug-file-directory". QString debugInfoLocation; // Gdb "set-debug-file-directory".
QStringList debugSourceLocation; // Gdb "directory" QStringList debugSourceLocation; // Gdb "directory"
QString serverStartScript; QString serverStartScript;
@@ -217,6 +216,7 @@ public:
MemoryView = 0x4 //!< Open a separate view (using the pos-parameter). MemoryView = 0x4 //!< Open a separate view (using the pos-parameter).
}; };
virtual void runCommand(const DebuggerCommand &cmd);
virtual void openMemoryView(const MemoryViewSetupData &data); virtual void openMemoryView(const MemoryViewSetupData &data);
virtual void fetchMemory(Internal::MemoryAgent *, QObject *, virtual void fetchMemory(Internal::MemoryAgent *, QObject *,
quint64 addr, quint64 length); quint64 addr, quint64 length);

View File

@@ -52,9 +52,10 @@ public:
typedef std::function<void(const DebuggerResponse &)> Callback; typedef std::function<void(const DebuggerResponse &)> Callback;
DebuggerCommand() {} DebuggerCommand() {}
DebuggerCommand(const char *f, int fl = 0) : function(f), flags(fl) {} DebuggerCommand(const QByteArray &f) : function(f), flags(0) {}
DebuggerCommand(const QByteArray &f, int fl = 0) : function(f), flags(fl) {} DebuggerCommand(const QByteArray &f, const QJsonValue &a) : function(f), args(a), flags(0) {}
DebuggerCommand(const char *f, const QJsonValue &a, int fl = 0) : function(f), args(a), flags(fl) {} DebuggerCommand(const QByteArray &f, int fl) : function(f), flags(fl) {}
DebuggerCommand(const QByteArray &f, int fl, const Callback &cb) : function(f), callback(cb), flags(fl) {}
void arg(const char *value); void arg(const char *value);
void arg(const char *name, int value); void arg(const char *name, int value);

View File

@@ -95,6 +95,9 @@ public:
QSsh::SshConnectionParameters connParams; QSsh::SshConnectionParameters connParams;
bool remoteSetupNeeded = false; bool remoteSetupNeeded = false;
// Used by Mer plugin (3rd party)
QMap<QString, QString> sourcePathMap;
// Used by baremetal plugin // Used by baremetal plugin
QByteArray commandsForReset; // commands used for resetting the inferior QByteArray commandsForReset; // commands used for resetting the inferior
bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used

View File

@@ -75,9 +75,8 @@ void GdbAttachEngine::runEngine()
{ {
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
const qint64 pid = runParameters().attachPID; const qint64 pid = runParameters().attachPID;
DebuggerCommand cmd("attach " + QByteArray::number(pid)); runCommand({"attach " + QByteArray::number(pid), NoFlags,
cmd.callback = [this](const DebuggerResponse &r) { handleAttach(r); }; [this](const DebuggerResponse &r) { handleAttach(r); }});
runCommand(cmd);
showStatusMessage(tr("Attached to process %1.").arg(inferiorPid())); showStatusMessage(tr("Attached to process %1.").arg(inferiorPid()));
} }

View File

@@ -212,9 +212,8 @@ void GdbCoreEngine::setupInferior()
// Do that first, otherwise no symbols are loaded. // Do that first, otherwise no symbols are loaded.
QFileInfo fi(m_executable); QFileInfo fi(m_executable);
QByteArray path = fi.absoluteFilePath().toLocal8Bit(); QByteArray path = fi.absoluteFilePath().toLocal8Bit();
DebuggerCommand cmd("-file-exec-and-symbols \"" + path + '"'); runCommand({"-file-exec-and-symbols \"" + path + '"', NoFlags,
cmd.callback = CB(handleFileExecAndSymbols); CB(handleFileExecAndSymbols)});
runCommand(cmd);
} }
void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response) void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
@@ -237,9 +236,8 @@ void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
void GdbCoreEngine::runEngine() void GdbCoreEngine::runEngine()
{ {
CHECK_STATE(EngineRunRequested); CHECK_STATE(EngineRunRequested);
DebuggerCommand cmd("target core " + coreFileName().toLocal8Bit()); runCommand({"target core " + coreFileName().toLocal8Bit(), NoFlags,
cmd.callback = CB(handleTargetCore); CB(handleTargetCore)});
runCommand(cmd);
} }
void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response) void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
@@ -252,7 +250,7 @@ void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
// symbols yet. Load them in order of importance. // symbols yet. Load them in order of importance.
reloadStack(); reloadStack();
reloadModulesInternal(); reloadModulesInternal();
runCommand("p 5", CB(handleRoundTrip)); runCommand({"p 5", NoFlags, CB(handleRoundTrip)});
return; return;
} }
showStatusMessage(tr("Attach to core \"%1\" failed:").arg(runParameters().coreFile) showStatusMessage(tr("Attach to core \"%1\" failed:").arg(runParameters().coreFile)

View File

@@ -735,21 +735,19 @@ void GdbEngine::handleAsyncOutput(const QByteArray &asyncClass, const GdbMi &res
foreach (const GdbMi &bkpt, res.children()) { foreach (const GdbMi &bkpt, res.children()) {
const QByteArray nr = bkpt["number"].data(); const QByteArray nr = bkpt["number"].data();
BreakpointResponseId rid(nr); BreakpointResponseId rid(nr);
if (!isHiddenBreakpoint(rid)) { if (nr.contains('.')) {
if (nr.contains('.')) { // A sub-breakpoint.
// A sub-breakpoint. BreakpointResponse sub;
BreakpointResponse sub; updateResponse(sub, bkpt);
updateResponse(sub, bkpt); sub.id = rid;
sub.id = rid; sub.type = br.type;
sub.type = br.type; bp.insertSubBreakpoint(sub);
bp.insertSubBreakpoint(sub); } else {
} else { // A primary breakpoint.
// A primary breakpoint. bp = handler->findBreakpointByResponseId(rid);
bp = handler->findBreakpointByResponseId(rid); br = bp.response();
br = bp.response(); updateResponse(br, bkpt);
updateResponse(br, bkpt); bp.setResponse(br);
bp.setResponse(br);
}
} }
} }
} else if (asyncClass == "breakpoint-created") { } else if (asyncClass == "breakpoint-created") {
@@ -851,7 +849,7 @@ void GdbEngine::interruptInferior()
return; return;
if (usesExecInterrupt()) { if (usesExecInterrupt()) {
runCommand("-exec-interrupt"); runCommand({"-exec-interrupt", NoFlags});
} else { } else {
showStatusMessage(tr("Stop requested..."), 5000); showStatusMessage(tr("Stop requested..."), 5000);
showMessage(_("TRYING TO INTERRUPT INFERIOR")); showMessage(_("TRYING TO INTERRUPT INFERIOR"));
@@ -898,20 +896,6 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
notifyInferiorPid(pid); notifyInferiorPid(pid);
} }
void GdbEngine::runCommand(const QByteArray &command, const DebuggerCommand::Callback &callback, int flags)
{
DebuggerCommand cmd(command);
cmd.callback = callback;
cmd.flags = flags;
runCommand(cmd);
}
void GdbEngine::runCommand(const QByteArray &command, int flags)
{
DebuggerCommand cmd(command, flags);
runCommand(cmd);
}
void GdbEngine::runCommand(const DebuggerCommand &command) void GdbEngine::runCommand(const DebuggerCommand &command)
{ {
const int token = ++currentToken(); const int token = ++currentToken();
@@ -1227,7 +1211,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages
if (!(languages & CppLanguage)) if (!(languages & CppLanguage))
return; return;
QTC_CHECK(acceptsDebuggerCommands()); QTC_CHECK(acceptsDebuggerCommands());
runCommand(command.toLatin1()); runCommand({command.toLatin1(), NoFlags});
} }
// This is triggered when switching snapshots. // This is triggered when switching snapshots.
@@ -1240,7 +1224,7 @@ void GdbEngine::updateAll()
cmd.callback = [this](const DebuggerResponse &r) { handleStackListFrames(r, false); }; cmd.callback = [this](const DebuggerResponse &r) { handleStackListFrames(r, false); };
runCommand(cmd); runCommand(cmd);
stackHandler()->setCurrentIndex(0); stackHandler()->setCurrentIndex(0);
runCommand("-thread-info", CB(handleThreadInfo)); runCommand({"-thread-info", NoFlags, CB(handleThreadInfo)});
reloadRegisters(); reloadRegisters();
updateLocals(); updateLocals();
} }
@@ -1386,9 +1370,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
bool gotoHandleStop1 = true; bool gotoHandleStop1 = true;
if (!m_fullStartDone) { if (!m_fullStartDone) {
m_fullStartDone = true; m_fullStartDone = true;
DebuggerCommand cmd("sharedlibrary .*"); runCommand({"sharedlibrary .*", NoFlags,
cmd.callback = [this, data](const DebuggerResponse &) { handleStop1(data); }; [this, data](const DebuggerResponse &) { handleStop1(data); }});
runCommand(cmd);
gotoHandleStop1 = false; gotoHandleStop1 = false;
} }
@@ -1413,7 +1396,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
showMessage(_("INVALID STOPPED REASON"), LogWarning); showMessage(_("INVALID STOPPED REASON"), LogWarning);
} }
if (rid.isValid() && frame.isValid() && !isQFatalBreakpoint(rid)) { if (rid.isValid() && frame.isValid()) {
// Use opportunity to update the breakpoint marker position. // Use opportunity to update the breakpoint marker position.
Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid); Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid);
const BreakpointResponse &response = bp.response(); const BreakpointResponse &response = bp.response();
@@ -1430,7 +1413,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// Quickly set the location marker. // Quickly set the location marker.
if (lineNumber && !boolSetting(OperateByInstruction) if (lineNumber && !boolSetting(OperateByInstruction)
&& QFileInfo::exists(fullName) && QFileInfo::exists(fullName)
&& !isQFatalBreakpoint(rid)
&& function != "qt_v4TriggeredBreakpointHook" && function != "qt_v4TriggeredBreakpointHook"
&& function != "qt_qmlDebugMessageAvailable" && function != "qt_qmlDebugMessageAvailable"
&& language != "js") && language != "js")
@@ -1544,9 +1526,9 @@ void GdbEngine::handleStop1(const GdbMi &data)
if (!m_systemDumpersLoaded) { if (!m_systemDumpersLoaded) {
m_systemDumpersLoaded = true; m_systemDumpersLoaded = true;
if (m_gdbVersion >= 70400 && boolSetting(LoadGdbDumpers)) if (m_gdbVersion >= 70400 && boolSetting(LoadGdbDumpers))
runCommand("importPlainDumpers on"); runCommand({"importPlainDumpers on", NoFlags});
else else
runCommand("importPlainDumpers off"); runCommand({"importPlainDumpers off", NoFlags});
} }
handleStop2(data); handleStop2(data);
@@ -1701,12 +1683,12 @@ void GdbEngine::handleShowVersion(const DebuggerResponse &response)
.arg(gdbBuildVersion).arg(_(isMacGdb ? " (APPLE)" : ""))); .arg(gdbBuildVersion).arg(_(isMacGdb ? " (APPLE)" : "")));
if (usesExecInterrupt()) if (usesExecInterrupt())
runCommand("set target-async on", ConsoleCommand); runCommand({"set target-async on", ConsoleCommand});
else else
runCommand("set target-async off", ConsoleCommand); runCommand({"set target-async off", ConsoleCommand});
if (runParameters().multiProcess) if (runParameters().multiProcess)
runCommand("set detach-on-fork off", ConsoleCommand); runCommand({"set detach-on-fork off", ConsoleCommand});
//runCommand("set build-id-verbose 2", ConsoleCommand); //runCommand("set build-id-verbose 2", ConsoleCommand);
} }
@@ -1892,8 +1874,8 @@ void GdbEngine::notifyAdapterShutdownOk()
switch (m_gdbProc.state()) { switch (m_gdbProc.state()) {
case QProcess::Running: { case QProcess::Running: {
if (runParameters().closeMode == KillAndExitMonitorAtClose) if (runParameters().closeMode == KillAndExitMonitorAtClose)
runCommand("monitor exit"); runCommand({"monitor exit", NoFlags});
runCommand("exitGdb", CB(handleGdbExit), ExitRequest|PythonCommand); runCommand({"exitGdb", ExitRequest|PythonCommand, CB(handleGdbExit)});
break; break;
} }
case QProcess::NotRunning: case QProcess::NotRunning:
@@ -2093,20 +2075,19 @@ void GdbEngine::executeStepI()
void GdbEngine::executeStepOut() void GdbEngine::executeStepOut()
{ {
CHECK_STATE(InferiorStopOk); CHECK_STATE(InferiorStopOk);
runCommand("-stack-select-frame 0", Discardable); runCommand({"-stack-select-frame 0", Discardable});
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Finish function requested..."), 5000); showStatusMessage(tr("Finish function requested..."), 5000);
if (isNativeMixedActiveFrame()) { if (isNativeMixedActiveFrame()) {
DebuggerCommand cmd("executeStepOut", RunRequest|PythonCommand); runCommand({"executeStepOut", RunRequest|PythonCommand});
runCommand(cmd);
} else { } else {
runCommand("-exec-finish", CB(handleExecuteContinue), RunRequest); runCommand({"-exec-finish", RunRequest, CB(handleExecuteContinue)});
// -exec-finish in 'main' results (correctly) in // -exec-finish in 'main' results (correctly) in
// 40^error,msg="\"finish\" not meaningful in the outermost frame." // 40^error,msg="\"finish\" not meaningful in the outermost frame."
// However, this message does not seem to get flushed before // However, this message does not seem to get flushed before
// anything else happen - i.e. "never". Force some extra output. // anything else happen - i.e. "never". Force some extra output.
runCommand("print 32"); runCommand({"print 32"});
} }
} }
@@ -2186,11 +2167,9 @@ void GdbEngine::executeRunToLine(const ContextData &data)
else else
loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':' loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':'
+ QByteArray::number(data.lineNumber); + QByteArray::number(data.lineNumber);
runCommand("tbreak " + loc); runCommand({"tbreak " + loc, NoFlags});
DebuggerCommand cmd("continue", RunRequest); runCommand({"continue", RunRequest, CB(handleExecuteRunToLine)});
cmd.callback = CB(handleExecuteRunToLine);
runCommand(cmd);
#else #else
// Seems to jump to unpredicatable places. Observed in the manual // Seems to jump to unpredicatable places. Observed in the manual
// tests in the Foo::Foo() constructor with both gdb 6.8 and 7.1. // tests in the Foo::Foo() constructor with both gdb 6.8 and 7.1.
@@ -2204,7 +2183,7 @@ void GdbEngine::executeRunToFunction(const QString &functionName)
{ {
CHECK_STATE(InferiorStopOk); CHECK_STATE(InferiorStopOk);
setTokenBarrier(); setTokenBarrier();
runCommand("-break-insert -t " + functionName.toLatin1()); runCommand({"-break-insert -t " + functionName.toLatin1(), NoFlags});
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000); showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
continueInferiorInternal(); continueInferiorInternal();
} }
@@ -2218,12 +2197,10 @@ void GdbEngine::executeJumpToLine(const ContextData &data)
else else
loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':' loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':'
+ QByteArray::number(data.lineNumber); + QByteArray::number(data.lineNumber);
runCommand("tbreak " + loc); runCommand({"tbreak " + loc, NoFlags});
notifyInferiorRunRequested(); notifyInferiorRunRequested();
DebuggerCommand cmd("jump" + loc, RunRequest); runCommand({"jump" + loc, RunRequest, CB(handleExecuteJumpToLine)});
cmd.callback = CB(handleExecuteJumpToLine);
runCommand(cmd);
// will produce something like // will produce something like
// &"jump \"/home/apoenitz/dev/work/test1/test1.cpp\":242" // &"jump \"/home/apoenitz/dev/work/test1/test1.cpp\":242"
// ~"Continuing at 0x4058f3." // ~"Continuing at 0x4058f3."
@@ -2238,7 +2215,7 @@ void GdbEngine::executeReturn()
setTokenBarrier(); setTokenBarrier();
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Immediate return from function requested..."), 5000); showStatusMessage(tr("Immediate return from function requested..."), 5000);
runCommand("-exec-finish", CB(handleExecuteReturn), RunRequest); runCommand({"-exec-finish", RunRequest, CB(handleExecuteReturn)});
} }
void GdbEngine::handleExecuteReturn(const DebuggerResponse &response) void GdbEngine::handleExecuteReturn(const DebuggerResponse &response)
@@ -2572,18 +2549,13 @@ void GdbEngine::handleBreakInsert1(const DebuggerResponse &response, Breakpoint
// the "main" entry. Use the "main" entry to retrieve the // the "main" entry. Use the "main" entry to retrieve the
// already known data from the BreakpointManager, and then // already known data from the BreakpointManager, and then
// iterate over all items to update main- and sub-data. // iterate over all items to update main- and sub-data.
const GdbMi mainbkpt = response.data["bkpt"]; foreach (const GdbMi &bkpt, response.data.children())
const QByteArray mainnr = mainbkpt["number"].data(); handleBkpt(bkpt, bp);
const BreakpointResponseId mainrid(mainnr); if (bp.needsChange()) {
if (!isHiddenBreakpoint(mainrid)) { bp.notifyBreakpointChangeAfterInsertNeeded();
foreach (const GdbMi &bkpt, response.data.children()) changeBreakpoint(bp);
handleBkpt(bkpt, bp); } else {
if (bp.needsChange()) { bp.notifyBreakpointInsertOk();
bp.notifyBreakpointChangeAfterInsertNeeded();
changeBreakpoint(bp);
} else {
bp.notifyBreakpointInsertOk();
}
} }
} else if (response.data["msg"].data().contains("Unknown option")) { } else if (response.data["msg"].data().contains("Unknown option")) {
// Older version of gdb don't know the -a option to set tracepoints // Older version of gdb don't know the -a option to set tracepoints
@@ -2891,7 +2863,7 @@ void GdbEngine::removeBreakpoint(Breakpoint bp)
void GdbEngine::loadSymbols(const QString &modulePath) void GdbEngine::loadSymbols(const QString &modulePath)
{ {
// FIXME: gdb does not understand quoted names here (tested with 6.8) // FIXME: gdb does not understand quoted names here (tested with 6.8)
runCommand("sharedlibrary " + dotEscape(modulePath.toLocal8Bit())); runCommand({"sharedlibrary " + dotEscape(modulePath.toLocal8Bit()), NoFlags});
reloadModulesInternal(); reloadModulesInternal();
reloadStack(); reloadStack();
updateLocals(); updateLocals();
@@ -2899,7 +2871,7 @@ void GdbEngine::loadSymbols(const QString &modulePath)
void GdbEngine::loadAllSymbols() void GdbEngine::loadAllSymbols()
{ {
runCommand("sharedlibrary .*"); runCommand({"sharedlibrary .*", NoFlags});
reloadModulesInternal(); reloadModulesInternal();
reloadStack(); reloadStack();
updateLocals(); updateLocals();
@@ -2915,8 +2887,8 @@ void GdbEngine::loadSymbolsForStack()
foreach (const Module &module, modules) { foreach (const Module &module, modules) {
if (module.startAddress <= frame.address if (module.startAddress <= frame.address
&& frame.address < module.endAddress) { && frame.address < module.endAddress) {
runCommand("sharedlibrary " runCommand({"sharedlibrary " + dotEscape(module.modulePath.toLocal8Bit()),
+ dotEscape(module.modulePath.toLocal8Bit())); NoFlags});
needUpdate = true; needUpdate = true;
} }
} }
@@ -3059,7 +3031,7 @@ void GdbEngine::reloadModules()
void GdbEngine::reloadModulesInternal() void GdbEngine::reloadModulesInternal()
{ {
runCommand("info shared", CB(handleModulesList), NeedsStop); runCommand({"info shared", NeedsStop, CB(handleModulesList)});
} }
static QString nameFromPath(const QString &path) static QString nameFromPath(const QString &path)
@@ -3246,10 +3218,9 @@ void GdbEngine::loadAdditionalQmlStack()
return; return;
} }
// Call the debug function of QML with the context address to obtain the QML stack trace. // Call the debug function of QML with the context address to obtain the QML stack trace.
DebuggerCommand cmd = "-data-evaluate-expression \"qt_v4StackTrace((QV4::ExecutionContext *)0x" runCommand({"-data-evaluate-expression \"qt_v4StackTrace((QV4::ExecutionContext *)0x"
+ QByteArray::number(contextAddress, 16) + ")\""; + QByteArray::number(contextAddress, 16) + ")\"",
cmd.callback = CB(handleQmlStackTrace); NoFlags, CB(handleQmlStackTrace)});
runCommand(cmd);
}; };
runCommand(cmd); runCommand(cmd);
} }
@@ -3345,8 +3316,7 @@ void GdbEngine::activateFrame(int frameIndex)
// after a response to this -stack-select-frame here. // after a response to this -stack-select-frame here.
//if (!m_currentThread.isEmpty()) //if (!m_currentThread.isEmpty())
// cmd += " --thread " + m_currentThread; // cmd += " --thread " + m_currentThread;
DebuggerCommand cmd("-stack-select-frame " + QByteArray::number(frameIndex), Discardable); runCommand({"-stack-select-frame " + QByteArray::number(frameIndex), Discardable});
runCommand(cmd);
} }
updateLocals(); updateLocals();
@@ -3366,14 +3336,14 @@ void GdbEngine::handleThreadInfo(const DebuggerResponse &response)
} }
updateViews(); // Adjust Threads combobox. updateViews(); // Adjust Threads combobox.
if (boolSetting(ShowThreadNames)) { if (boolSetting(ShowThreadNames)) {
runCommand("threadnames " + action(MaximalStackDepth)->value().toByteArray(), runCommand({"threadnames " + action(MaximalStackDepth)->value().toByteArray(),
CB(handleThreadNames), Discardable); Discardable, CB(handleThreadNames)});
} }
reloadStack(); // Will trigger register reload. reloadStack(); // Will trigger register reload.
} else { } else {
// Fall back for older versions: Try to get at least a list // Fall back for older versions: Try to get at least a list
// of running threads. // of running threads.
runCommand("-thread-list-ids", CB(handleThreadListIds), Discardable); runCommand({"-thread-list-ids", Discardable, CB(handleThreadListIds)});
} }
} }
@@ -3474,15 +3444,17 @@ void GdbEngine::reloadRegisters()
if (!m_registerNamesListed) { if (!m_registerNamesListed) {
// The MI version does not give register size. // The MI version does not give register size.
// runCommand("-data-list-register-names", CB(handleRegisterListNames)); // runCommand("-data-list-register-names", CB(handleRegisterListNames));
runCommand("maintenance print raw-registers", CB(handleRegisterListing)); runCommand({"maintenance print raw-registers", NoFlags,
CB(handleRegisterListing)});
m_registerNamesListed = true; m_registerNamesListed = true;
} }
// Can cause i386-linux-nat.c:571: internal-error: Got request // Can cause i386-linux-nat.c:571: internal-error: Got request
// for bad register number 41.\nA problem internal to GDB has been detected. // for bad register number 41.\nA problem internal to GDB has been detected.
runCommand("-data-list-register-values r", runCommand({"-data-list-register-values r", Discardable,
CB(handleRegisterListValues), Discardable); CB(handleRegisterListValues)});
} else { } else {
runCommand("maintenance print cooked-registers", CB(handleMaintPrintRegisters)); runCommand({"maintenance print cooked-registers", NoFlags,
CB(handleMaintPrintRegisters)});
} }
} }
@@ -3547,7 +3519,7 @@ void GdbEngine::setRegisterValue(const QByteArray &name, const QString &value)
QByteArray fullName = name; QByteArray fullName = name;
if (name.startsWith("xmm")) if (name.startsWith("xmm"))
fullName += ".uint128"; fullName += ".uint128";
runCommand("set $" + fullName + "=" + value.toLatin1()); runCommand({"set $" + fullName + "=" + value.toLatin1(), NoFlags});
reloadRegisters(); reloadRegisters();
} }
@@ -3684,9 +3656,8 @@ void GdbEngine::watchPoint(const QPoint &pnt)
{ {
QByteArray x = QByteArray::number(pnt.x()); QByteArray x = QByteArray::number(pnt.x());
QByteArray y = QByteArray::number(pnt.y()); QByteArray y = QByteArray::number(pnt.y());
runCommand("print " + qtNamespace() + "QApplication::widgetAt(" runCommand({"print " + qtNamespace() + "QApplication::widgetAt(" + x + ',' + y + ')',
+ x + ',' + y + ')', NeedsStop, CB(handleWatchPoint)});
CB(handleWatchPoint), NeedsStop);
} }
void GdbEngine::handleWatchPoint(const DebuggerResponse &response) void GdbEngine::handleWatchPoint(const DebuggerResponse &response)
@@ -3822,9 +3793,9 @@ public:
void GdbEngine::fetchDisassembler(DisassemblerAgent *agent) void GdbEngine::fetchDisassembler(DisassemblerAgent *agent)
{ {
if (boolSetting(IntelFlavor)) if (boolSetting(IntelFlavor))
runCommand("set disassembly-flavor intel"); runCommand({"set disassembly-flavor intel"});
else else
runCommand("set disassembly-flavor att"); runCommand({"set disassembly-flavor att"});
fetchDisassemblerByCliPointMixed(agent); fetchDisassemblerByCliPointMixed(agent);
} }
@@ -4025,9 +3996,9 @@ void GdbEngine::startGdb(const QStringList &args)
} }
showMessage(_("GDB STARTED, INITIALIZING IT")); showMessage(_("GDB STARTED, INITIALIZING IT"));
runCommand("show version", CB(handleShowVersion)); runCommand({"show version", NoFlags, CB(handleShowVersion)});
//runCommand("-list-features", CB(handleListFeatures)); //runCommand("-list-features", CB(handleListFeatures));
runCommand("show debug-file-directory",CB(handleDebugInfoLocation)); runCommand({"show debug-file-directory", NoFlags, CB(handleDebugInfoLocation)});
//runCommand("-enable-timings"); //runCommand("-enable-timings");
//rurun print static-members off"); // Seemingly doesn't work. //rurun print static-members off"); // Seemingly doesn't work.
@@ -4037,7 +4008,7 @@ void GdbEngine::startGdb(const QStringList &args)
//runCommand("define hookpost-stop\nprint 5\nend"); //runCommand("define hookpost-stop\nprint 5\nend");
//runCommand("define hook-call\nprint 6\nend"); //runCommand("define hook-call\nprint 6\nend");
//runCommand("define hookpost-call\nprint 7\nend"); //runCommand("define hookpost-call\nprint 7\nend");
runCommand("set print object on"); runCommand({"set print object on"});
//runCommand("set step-mode on"); // we can't work with that yes //runCommand("set step-mode on"); // we can't work with that yes
//runCommand("set exec-done-display on"); //runCommand("set exec-done-display on");
//runCommand("set print pretty on"); //runCommand("set print pretty on");
@@ -4048,8 +4019,8 @@ void GdbEngine::startGdb(const QStringList &args)
// (Mac OS 10.6), but does so for gdb-966 (10.5): // (Mac OS 10.6), but does so for gdb-966 (10.5):
//runCommand("set print inferior-events 1"); //runCommand("set print inferior-events 1");
runCommand("set breakpoint pending on"); runCommand({"set breakpoint pending on"});
runCommand("set print elements 10000"); runCommand({"set print elements 10000"});
// Produces a few messages during symtab loading // Produces a few messages during symtab loading
//runCommand("set verbose on"); //runCommand("set verbose on");
@@ -4077,11 +4048,11 @@ void GdbEngine::startGdb(const QStringList &args)
// We need "print" as otherwise we will get no feedback whatsoever // We need "print" as otherwise we will get no feedback whatsoever
// when Custom DebuggingHelper crash (which happen regularly when accessing // when Custom DebuggingHelper crash (which happen regularly when accessing
// uninitialized variables). // uninitialized variables).
runCommand("handle SIGSEGV nopass stop print"); runCommand({"handle SIGSEGV nopass stop print"});
runCommand("set unwindonsignal on"); runCommand({"set unwindonsignal on"});
runCommand("set width 0"); runCommand({"set width 0"});
runCommand("set height 0"); runCommand({"set height 0"});
// FIXME: Provide proper Gui settings for these: // FIXME: Provide proper Gui settings for these:
//runCommand("set breakpoint always-inserted on", ConsoleCommand); //runCommand("set breakpoint always-inserted on", ConsoleCommand);
@@ -4111,39 +4082,39 @@ void GdbEngine::startGdb(const QStringList &args)
for (auto it = completeSourcePathMap.constBegin(), cend = completeSourcePathMap.constEnd(); for (auto it = completeSourcePathMap.constBegin(), cend = completeSourcePathMap.constEnd();
it != cend; it != cend;
++it) { ++it) {
runCommand("set substitute-path " + it.key().toLocal8Bit() runCommand({"set substitute-path " + it.key().toLocal8Bit()
+ " " + it.value().toLocal8Bit()); + " " + it.value().toLocal8Bit(), NoFlags});
} }
// Spaces just will not work. // Spaces just will not work.
foreach (const QString &src, rp.debugSourceLocation) { foreach (const QString &src, rp.debugSourceLocation) {
if (QDir(src).exists()) if (QDir(src).exists())
runCommand("directory " + src.toLocal8Bit()); runCommand({"directory " + src.toLocal8Bit(), NoFlags});
else else
showMessage(_("# directory does not exist: ") + src, LogInput); showMessage(_("# directory does not exist: ") + src, LogInput);
} }
const QByteArray sysroot = rp.sysRoot.toLocal8Bit(); const QByteArray sysroot = rp.sysRoot.toLocal8Bit();
if (!sysroot.isEmpty()) { if (!sysroot.isEmpty()) {
runCommand("set sysroot " + sysroot); runCommand({"set sysroot " + sysroot, NoFlags});
// sysroot is not enough to correctly locate the sources, so explicitly // sysroot is not enough to correctly locate the sources, so explicitly
// relocate the most likely place for the debug source // relocate the most likely place for the debug source
runCommand("set substitute-path /usr/src " + sysroot + "/usr/src"); runCommand({"set substitute-path /usr/src " + sysroot + "/usr/src", NoFlags});
} }
//QByteArray ba = QFileInfo(sp.dumperLibrary).path().toLocal8Bit(); //QByteArray ba = QFileInfo(sp.dumperLibrary).path().toLocal8Bit();
//if (!ba.isEmpty()) //if (!ba.isEmpty())
// runCommand("set solib-search-path " + ba); // runCommand("set solib-search-path " + ba);
if (attemptQuickStart()) { if (attemptQuickStart()) {
runCommand("set auto-solib-add off", ConsoleCommand); runCommand({"set auto-solib-add off", ConsoleCommand});
} else { } else {
m_fullStartDone = true; m_fullStartDone = true;
runCommand("set auto-solib-add on", ConsoleCommand); runCommand({"set auto-solib-add on", ConsoleCommand});
} }
if (boolSetting(MultiInferior)) { if (boolSetting(MultiInferior)) {
//runCommand("set follow-exec-mode new"); //runCommand("set follow-exec-mode new");
runCommand("set detach-on-fork off"); runCommand({"set detach-on-fork off"});
} }
// Finally, set up Python. // Finally, set up Python.
@@ -4154,15 +4125,15 @@ void GdbEngine::startGdb(const QStringList &args)
ICore::resourcePath().toLocal8Bit() + "/debugger/"; ICore::resourcePath().toLocal8Bit() + "/debugger/";
if (terminal()->isUsable()) if (terminal()->isUsable())
runCommand("set inferior-tty " + terminal()->slaveDevice()); runCommand({"set inferior-tty " + terminal()->slaveDevice(), NoFlags});
const QFileInfo gdbBinaryFile(m_gdb); const QFileInfo gdbBinaryFile(m_gdb);
const QByteArray uninstalledData = gdbBinaryFile.absolutePath().toLocal8Bit() const QByteArray uninstalledData = gdbBinaryFile.absolutePath().toLocal8Bit()
+ "/data-directory/python"; + "/data-directory/python";
runCommand("python sys.path.insert(1, '" + dumperSourcePath + "')"); runCommand({"python sys.path.insert(1, '" + dumperSourcePath + "')", NoFlags});
runCommand("python sys.path.append('" + uninstalledData + "')"); runCommand({"python sys.path.append('" + uninstalledData + "')", NoFlags});
runCommand("python from gdbbridge import *"); runCommand({"python from gdbbridge import *", NoFlags});
const QString path = stringSetting(ExtraDumperFile); const QString path = stringSetting(ExtraDumperFile);
if (!path.isEmpty() && QFileInfo(path).isReadable()) { if (!path.isEmpty() && QFileInfo(path).isReadable()) {
@@ -4173,11 +4144,9 @@ void GdbEngine::startGdb(const QStringList &args)
const QString commands = stringSetting(ExtraDumperCommands); const QString commands = stringSetting(ExtraDumperCommands);
if (!commands.isEmpty()) if (!commands.isEmpty())
runCommand(commands.toLocal8Bit()); runCommand({commands.toLocal8Bit(), NoFlags});
DebuggerCommand cmd("loadDumpers", PythonCommand); runCommand({"loadDumpers", PythonCommand, CB(handlePythonSetup)});
cmd.callback = CB(handlePythonSetup);
runCommand(cmd);
} }
void GdbEngine::handleGdbStartFailed() void GdbEngine::handleGdbStartFailed()
@@ -4189,7 +4158,7 @@ void GdbEngine::loadInitScript()
const QString script = runParameters().overrideStartScript; const QString script = runParameters().overrideStartScript;
if (!script.isEmpty()) { if (!script.isEmpty()) {
if (QFileInfo(script).isReadable()) { if (QFileInfo(script).isReadable()) {
runCommand("source " + script.toLocal8Bit()); runCommand({"source " + script.toLocal8Bit(), NoFlags});
} else { } else {
AsynchronousMessageBox::warning( AsynchronousMessageBox::warning(
tr("Cannot find debugger initialization script"), tr("Cannot find debugger initialization script"),
@@ -4201,7 +4170,7 @@ void GdbEngine::loadInitScript()
} else { } else {
const QString commands = stringSetting(GdbStartupCommands); const QString commands = stringSetting(GdbStartupCommands);
if (!commands.isEmpty()) if (!commands.isEmpty())
runCommand(commands.toLocal8Bit()); runCommand({commands.toLocal8Bit(), NoFlags});
} }
} }
@@ -4211,15 +4180,16 @@ void GdbEngine::setEnvironmentVariables()
Environment runEnv = runParameters().environment; Environment runEnv = runParameters().environment;
foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) { foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
if (item.unset) if (item.unset)
runCommand("unset environment " + item.name.toUtf8()); runCommand({"unset environment " + item.name.toUtf8(), NoFlags});
else else
runCommand("-gdb-set environment " + item.name.toUtf8() + '=' + item.value.toUtf8()); runCommand({"-gdb-set environment " + item.name.toUtf8() + '='
+ item.value.toUtf8(), NoFlags});
} }
} }
void GdbEngine::reloadDebuggingHelpers() void GdbEngine::reloadDebuggingHelpers()
{ {
runCommand("reloadDumpers", PythonCommand); runCommand({"reloadDumpers", PythonCommand});
reloadLocals(); reloadLocals();
} }
@@ -4274,7 +4244,7 @@ void GdbEngine::resetInferior()
foreach (QByteArray command, commands.split('\n')) { foreach (QByteArray command, commands.split('\n')) {
command = command.trimmed(); command = command.trimmed();
if (!command.isEmpty()) if (!command.isEmpty())
runCommand(command, int(ConsoleCommand | NeedsStop)); runCommand({command, ConsoleCommand | NeedsStop});
} }
} }
m_rerunPending = true; m_rerunPending = true;
@@ -4313,16 +4283,15 @@ void GdbEngine::handleInferiorPrepared()
if (!rp.commandsAfterConnect.isEmpty()) { if (!rp.commandsAfterConnect.isEmpty()) {
QByteArray commands = globalMacroExpander()->expand(rp.commandsAfterConnect); QByteArray commands = globalMacroExpander()->expand(rp.commandsAfterConnect);
foreach (QByteArray command, commands.split('\n')) { foreach (QByteArray command, commands.split('\n'))
runCommand(command); runCommand({command, NoFlags});
}
} }
//runCommand("set follow-exec-mode new"); //runCommand("set follow-exec-mode new");
if (rp.breakOnMain) { if (rp.breakOnMain) {
QByteArray cmd = "tbreak "; QByteArray cmd = "tbreak ";
cmd += rp.toolChainAbi.os() == Abi::WindowsOS ? "qMain" : "main"; cmd += rp.toolChainAbi.os() == Abi::WindowsOS ? "qMain" : "main";
runCommand(cmd); runCommand({cmd, NoFlags});
} }
// Initial attempt to set breakpoints. // Initial attempt to set breakpoints.
@@ -4344,23 +4313,24 @@ void GdbEngine::finishInferiorSetup()
{ {
CHECK_STATE(InferiorSetupRequested); CHECK_STATE(InferiorSetupRequested);
if (runParameters().startMode == AttachCore) { if (runParameters().startMode != AttachCore) { // No breakpoints in core files.
notifyInferiorSetupOk(); // No breakpoints in core files. const bool onAbort = boolSetting(BreakOnAbort);
} else { const bool onWarning = boolSetting(BreakOnWarning);
if (boolSetting(BreakOnAbort)) const bool onFatal = boolSetting(BreakOnFatal);
runCommand("-break-insert -f abort"); if (onAbort || onWarning || onFatal) {
if (boolSetting(BreakOnWarning)) { DebuggerCommand cmd("createSpecialBreakpoints", PythonCommand);
runCommand("-break-insert -f '" + qtNamespace() + "qWarning'"); cmd.arg("breakonabort", onAbort);
runCommand("-break-insert -f '" + qtNamespace() + "QMessageLogger::warning'"); cmd.arg("breakonwarning", onWarning);
} cmd.arg("breakonfatal", onFatal);
if (boolSetting(BreakOnFatal)) { runCommand(cmd);
auto cb = [this](const DebuggerResponse &r) { handleBreakOnQFatal(r, false); };
runCommand("-break-insert -f '" + qtNamespace() + "qFatal'", cb);
runCommand("-break-insert -f '" + qtNamespace() + "QMessageLogger::fatal'", cb);
} else {
notifyInferiorSetupOk();
} }
} }
// It is ok to cut corners here and not wait for createSpecialBreakpoints()'s
// response, as the command is synchronous from Creator's point of view,
// and even if it fails (e.g. due to stripped binaries), continuing with
// the start up is the best we can do.
notifyInferiorSetupOk();
} }
void GdbEngine::handleDebugInfoLocation(const DebuggerResponse &response) void GdbEngine::handleDebugInfoLocation(const DebuggerResponse &response)
@@ -4369,34 +4339,14 @@ void GdbEngine::handleDebugInfoLocation(const DebuggerResponse &response)
const QByteArray debugInfoLocation = runParameters().debugInfoLocation.toLocal8Bit(); const QByteArray debugInfoLocation = runParameters().debugInfoLocation.toLocal8Bit();
if (QFile::exists(QString::fromLocal8Bit(debugInfoLocation))) { if (QFile::exists(QString::fromLocal8Bit(debugInfoLocation))) {
const QByteArray curDebugInfoLocations = response.consoleStreamOutput.split('"').value(1); const QByteArray curDebugInfoLocations = response.consoleStreamOutput.split('"').value(1);
if (curDebugInfoLocations.isEmpty()) { QByteArray cmd = "set debug-file-directory " + debugInfoLocation;
runCommand("set debug-file-directory " + debugInfoLocation); if (!curDebugInfoLocations.isEmpty())
} else { cmd += HostOsInfo::pathListSeparator().toLatin1() + curDebugInfoLocations;
runCommand("set debug-file-directory " + debugInfoLocation runCommand({cmd, NoFlags});
+ HostOsInfo::pathListSeparator().toLatin1()
+ curDebugInfoLocations);
}
} }
} }
} }
void GdbEngine::handleBreakOnQFatal(const DebuggerResponse &response, bool continueSetup)
{
if (response.resultClass == ResultDone) {
GdbMi bkpt = response.data["bkpt"];
GdbMi number = bkpt["number"];
BreakpointResponseId rid(number.data());
if (rid.isValid()) {
m_qFatalBreakpointResponseId = rid;
runCommand("-break-commands " + number.data() + " return");
}
}
// Continue setup.
if (continueSetup)
notifyInferiorSetupOk();
}
void GdbEngine::notifyInferiorSetupFailed(const QString &msg) void GdbEngine::notifyInferiorSetupFailed(const QString &msg)
{ {
showStatusMessage(tr("Failed to start application:") + QLatin1Char(' ') + msg); showStatusMessage(tr("Failed to start application:") + QLatin1Char(' ') + msg);
@@ -4457,16 +4407,6 @@ void GdbEngine::resetCommandQueue()
} }
} }
bool GdbEngine::isQFatalBreakpoint(const BreakpointResponseId &id) const
{
return id.isValid() && m_qFatalBreakpointResponseId == id;
}
bool GdbEngine::isHiddenBreakpoint(const BreakpointResponseId &id) const
{
return isQFatalBreakpoint(id);
}
bool GdbEngine::usesExecInterrupt() const bool GdbEngine::usesExecInterrupt() const
{ {
DebuggerStartMode mode = runParameters().startMode; DebuggerStartMode mode = runParameters().startMode;

View File

@@ -172,12 +172,7 @@ private: ////////// Gdb Command Management //////////
}; };
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag) Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
protected: void runCommand(const DebuggerCommand &command) override;
void runCommand(const DebuggerCommand &command);
void runCommand(const QByteArray &command, int flags);
void runCommand(const QByteArray &command,
const DebuggerCommand::Callback &callback,
int flags = NoFlags);
private: private:
Q_SLOT void commandTimeout(); Q_SLOT void commandTimeout();
@@ -336,8 +331,6 @@ private: ////////// View & Data Stuff //////////
void fetchDisassemblerByCliRangePlain(const DisassemblerAgentCookie &ac); void fetchDisassemblerByCliRangePlain(const DisassemblerAgentCookie &ac);
bool handleCliDisassemblerResult(const QByteArray &response, DisassemblerAgent *agent); bool handleCliDisassemblerResult(const QByteArray &response, DisassemblerAgent *agent);
void handleBreakOnQFatal(const DebuggerResponse &response, bool continueSetup);
// //
// Source file specific stuff // Source file specific stuff
// //
@@ -426,14 +419,10 @@ protected:
// while updating locals. // while updating locals.
bool m_inUpdateLocals; bool m_inUpdateLocals;
bool isQFatalBreakpoint(const BreakpointResponseId &id) const;
bool isHiddenBreakpoint(const BreakpointResponseId &id) const;
// HACK: // HACK:
QByteArray m_currentThread; QByteArray m_currentThread;
QString m_lastWinException; QString m_lastWinException;
QString m_lastMissingDebugInfo; QString m_lastMissingDebugInfo;
BreakpointResponseId m_qFatalBreakpointResponseId;
bool m_terminalTrap; bool m_terminalTrap;
bool m_temporaryStopPending; bool m_temporaryStopPending;
bool usesExecInterrupt() const; bool usesExecInterrupt() const;

View File

@@ -60,10 +60,10 @@ void GdbPlainEngine::setupInferior()
setEnvironmentVariables(); setEnvironmentVariables();
if (!runParameters().processArgs.isEmpty()) { if (!runParameters().processArgs.isEmpty()) {
QString args = runParameters().processArgs; QString args = runParameters().processArgs;
runCommand("-exec-arguments " + toLocalEncoding(args)); runCommand({"-exec-arguments " + toLocalEncoding(args), NoFlags});
} }
runCommand("-file-exec-and-symbols \"" + execFilePath() + '"', runCommand({"-file-exec-and-symbols \"" + execFilePath() + '"', NoFlags,
CB(handleFileExecAndSymbols)); CB(handleFileExecAndSymbols)});
} }
void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response) void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
@@ -84,9 +84,9 @@ void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
void GdbPlainEngine::runEngine() void GdbPlainEngine::runEngine()
{ {
if (runParameters().useContinueInsteadOfRun) if (runParameters().useContinueInsteadOfRun)
runCommand("-exec-continue", CB(handleExecuteContinue), RunRequest); runCommand({"-exec-continue", RunRequest, CB(handleExecuteContinue)});
else else
runCommand("-exec-run", CB(handleExecRun), RunRequest); runCommand({"-exec-run", RunRequest, CB(handleExecRun)});
} }
void GdbPlainEngine::handleExecRun(const DebuggerResponse &response) void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
{ {
@@ -98,7 +98,7 @@ void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
showMessage(msgInferiorSetupOk(), StatusBar); showMessage(msgInferiorSetupOk(), StatusBar);
// FIXME: That's the wrong place for it. // FIXME: That's the wrong place for it.
if (boolSetting(EnableReverseDebugging)) if (boolSetting(EnableReverseDebugging))
runCommand("target record"); runCommand({"target record", NoFlags});
} else { } else {
QString msg = fromLocalEncoding(response.data["msg"].data()); QString msg = fromLocalEncoding(response.data["msg"].data());
//QTC_CHECK(status() == InferiorRunOk); //QTC_CHECK(status() == InferiorRunOk);

View File

@@ -183,10 +183,10 @@ void GdbRemoteServerEngine::setupInferior()
// postCommand("set architecture " + remoteArch); // postCommand("set architecture " + remoteArch);
const QString solibSearchPath = rp.solibSearchPath.join(HostOsInfo::pathListSeparator()); const QString solibSearchPath = rp.solibSearchPath.join(HostOsInfo::pathListSeparator());
if (!solibSearchPath.isEmpty()) if (!solibSearchPath.isEmpty())
runCommand("set solib-search-path " + solibSearchPath.toLocal8Bit()); runCommand({"set solib-search-path " + solibSearchPath.toLocal8Bit(), NoFlags});
if (!args.isEmpty()) if (!args.isEmpty())
runCommand("-exec-arguments " + args.toLocal8Bit()); runCommand({"-exec-arguments " + args.toLocal8Bit(), NoFlags});
setEnvironmentVariables(); setEnvironmentVariables();
@@ -210,7 +210,7 @@ void GdbRemoteServerEngine::setupInferior()
// mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)' // mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)'
// failed.\nA problem internal to GDB has been detected,[...] // failed.\nA problem internal to GDB has been detected,[...]
if (boolSetting(TargetAsync)) if (boolSetting(TargetAsync))
runCommand("set target-async on", CB(handleSetTargetAsync)); runCommand({"set target-async on", NoFlags, CB(handleSetTargetAsync)});
if (executableFileName.isEmpty()) { if (executableFileName.isEmpty()) {
showMessage(tr("No symbol file given."), StatusBar); showMessage(tr("No symbol file given."), StatusBar);
@@ -219,8 +219,8 @@ void GdbRemoteServerEngine::setupInferior()
} }
if (!executableFileName.isEmpty()) { if (!executableFileName.isEmpty()) {
runCommand("-file-exec-and-symbols \"" + executableFileName.toLocal8Bit() + '"', runCommand({"-file-exec-and-symbols \"" + executableFileName.toLocal8Bit() + '"',
CB(handleFileExecAndSymbols)); NoFlags, CB(handleFileExecAndSymbols)});
} }
} }
@@ -270,11 +270,11 @@ void GdbRemoteServerEngine::callTargetRemote()
} }
if (m_isQnxGdb) if (m_isQnxGdb)
runCommand("target qnx " + channel, CB(handleTargetQnx)); runCommand({"target qnx " + channel, NoFlags, CB(handleTargetQnx)});
else if (runParameters().multiProcess) else if (runParameters().multiProcess)
runCommand("target extended-remote " + channel, CB(handleTargetExtendedRemote)); runCommand({"target extended-remote " + channel, NoFlags, CB(handleTargetExtendedRemote)});
else else
runCommand("target remote " + channel, CB(handleTargetRemote)); runCommand({"target remote " + channel, NoFlags, CB(handleTargetRemote)});
} }
void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response) void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
@@ -287,7 +287,7 @@ void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
QString postAttachCommands = stringSetting(GdbPostAttachCommands); QString postAttachCommands = stringSetting(GdbPostAttachCommands);
if (!postAttachCommands.isEmpty()) { if (!postAttachCommands.isEmpty()) {
foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n'))) foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n')))
runCommand(cmd.toLatin1()); runCommand({cmd.toLatin1(), NoFlags});
} }
handleInferiorPrepared(); handleInferiorPrepared();
} else { } else {
@@ -307,15 +307,15 @@ void GdbRemoteServerEngine::handleTargetExtendedRemote(const DebuggerResponse &r
QString postAttachCommands = stringSetting(GdbPostAttachCommands); QString postAttachCommands = stringSetting(GdbPostAttachCommands);
if (!postAttachCommands.isEmpty()) { if (!postAttachCommands.isEmpty()) {
foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n'))) foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n')))
runCommand(cmd.toLatin1()); runCommand({cmd.toLatin1(), NoFlags});
} }
if (runParameters().attachPID > 0) { // attach to pid if valid if (runParameters().attachPID > 0) { // attach to pid if valid
// gdb server will stop the remote application itself. // gdb server will stop the remote application itself.
runCommand("attach " + QByteArray::number(runParameters().attachPID), runCommand({"attach " + QByteArray::number(runParameters().attachPID),
CB(handleTargetExtendedAttach)); NoFlags, CB(handleTargetExtendedAttach)});
} else { } else {
runCommand("-gdb-set remote exec-file " + runParameters().remoteExecutable.toLatin1(), runCommand({"-gdb-set remote exec-file " + runParameters().remoteExecutable.toLatin1(),
CB(handleTargetExtendedAttach)); NoFlags, CB(handleTargetExtendedAttach)});
} }
} else { } else {
QString msg = msgConnectRemoteServerFailed( QString msg = msgConnectRemoteServerFailed(
@@ -349,9 +349,9 @@ void GdbRemoteServerEngine::handleTargetQnx(const DebuggerResponse &response)
const qint64 pid = isMasterEngine() ? runParameters().attachPID : masterEngine()->runParameters().attachPID; const qint64 pid = isMasterEngine() ? runParameters().attachPID : masterEngine()->runParameters().attachPID;
const QString remoteExecutable = isMasterEngine() ? runParameters().remoteExecutable : masterEngine()->runParameters().remoteExecutable; const QString remoteExecutable = isMasterEngine() ? runParameters().remoteExecutable : masterEngine()->runParameters().remoteExecutable;
if (pid > -1) if (pid > -1)
runCommand("attach " + QByteArray::number(pid), CB(handleAttach)); runCommand({"attach " + QByteArray::number(pid), NoFlags, CB(handleAttach)});
else if (!remoteExecutable.isEmpty()) else if (!remoteExecutable.isEmpty())
runCommand("set nto-executable " + remoteExecutable.toLatin1(), CB(handleSetNtoExecutable)); runCommand({"set nto-executable " + remoteExecutable.toLatin1(), NoFlags, CB(handleSetNtoExecutable)});
else else
handleInferiorPrepared(); handleInferiorPrepared();
} else { } else {
@@ -409,7 +409,7 @@ void GdbRemoteServerEngine::runEngine()
const QString remoteExecutable = runParameters().remoteExecutable; const QString remoteExecutable = runParameters().remoteExecutable;
if (!remoteExecutable.isEmpty()) { if (!remoteExecutable.isEmpty()) {
runCommand("-exec-run", CB(handleExecRun), RunRequest); runCommand({"-exec-run", RunRequest, CB(handleExecRun)});
} else { } else {
notifyEngineRunAndInferiorStopOk(); notifyEngineRunAndInferiorStopOk();
continueInferiorInternal(); continueInferiorInternal();
@@ -434,7 +434,7 @@ void GdbRemoteServerEngine::interruptInferior2()
{ {
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
if (boolSetting(TargetAsync)) { if (boolSetting(TargetAsync)) {
runCommand("-exec-interrupt", CB(handleInterruptInferior)); runCommand({"-exec-interrupt", NoFlags, CB(handleInterruptInferior)});
} else if (m_isQnxGdb && HostOsInfo::isWindowsHost()) { } else if (m_isQnxGdb && HostOsInfo::isWindowsHost()) {
m_gdbProc.interrupt(); m_gdbProc.interrupt();
} else { } else {

View File

@@ -134,9 +134,8 @@ void GdbTermEngine::runEngine()
{ {
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
const qint64 attachedPID = m_stubProc.applicationPID(); const qint64 attachedPID = m_stubProc.applicationPID();
DebuggerCommand cmd("attach " + QByteArray::number(attachedPID)); runCommand({"attach " + QByteArray::number(attachedPID), NoFlags,
cmd.callback = [this](const DebuggerResponse &r) { handleStubAttached(r); }; [this](const DebuggerResponse &r) { handleStubAttached(r); }});
runCommand(cmd);
} }
void GdbTermEngine::handleStubAttached(const DebuggerResponse &response) void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)

Some files were not shown because too many files have changed in this diff Show More