Merge remote-tracking branch 'origin/3.6'
Conflicts: src/plugins/coreplugin/editormanager/editormanager.cpp Change-Id: Ibdf433b54e36e58182b7094f78d47ed3e8c81684
51
doc/examples/accelbubble/Bubble.qml
Normal 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
|
||||
}
|
||||
68
doc/examples/accelbubble/MainForm.ui.qml
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
TEMPLATE = app
|
||||
|
||||
QT += qml quick widgets
|
||||
QT += qml quick sensors svg xml
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
SOURCES += main.cpp
|
||||
|
||||
@@ -11,4 +13,3 @@ QML_IMPORT_PATH =
|
||||
|
||||
# Default rules for deployment.
|
||||
include(deployment.pri)
|
||||
|
||||
|
||||
52
doc/examples/accelbubble/main.cpp
Normal 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();
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
/**************************************************************************
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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:
|
||||
**
|
||||
** "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
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
** * 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
|
||||
@@ -33,43 +34,31 @@
|
||||
** (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 QtSensors 5.0
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtSensors 5.5
|
||||
|
||||
ApplicationWindow {
|
||||
title: qsTr("Accelerate Bubble")
|
||||
id: mainWindow
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
visible: true
|
||||
title: qsTr("Accelerate Bubble")
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu {
|
||||
title: qsTr("File")
|
||||
MenuItem {
|
||||
text: qsTr("&Open")
|
||||
onTriggered: console.log("Open action triggered");
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Exit")
|
||||
onTriggered: Qt.quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
MainForm {
|
||||
anchors.fill: parent
|
||||
bubble {
|
||||
id: bubble
|
||||
source: "Bluebubble.svg"
|
||||
smooth: true
|
||||
property real centerX: mainWindow.width / 2
|
||||
property real centerY: mainWindow.height / 2
|
||||
property real bubbleCenter: bubble.width / 2
|
||||
x: centerX - bubbleCenter
|
||||
y: centerY - bubbleCenter
|
||||
centerX: mainWindow.width / 2
|
||||
centerY: mainWindow.height / 2
|
||||
bubbleCenter: bubble.width / 2
|
||||
x: bubble.centerX - bubble.bubbleCenter
|
||||
y: bubble.centerY - bubble.bubbleCenter
|
||||
|
||||
Behavior on y {
|
||||
SmoothedAnimation {
|
||||
@@ -84,10 +73,12 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
}
|
||||
Accelerometer {
|
||||
}
|
||||
|
||||
Accelerometer {
|
||||
id: accel
|
||||
dataRate: 100
|
||||
active:true
|
||||
active: true
|
||||
|
||||
onReadingChanged: {
|
||||
var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
|
||||
|
||||
8
doc/examples/accelbubble/qml.qrc
Normal 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>
|
||||
BIN
doc/images/qmldesigner-borderimage-bindings-text.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
doc/images/qmldesigner-borderimage-bindings.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
doc/images/qmldesigner-borderimage-connections.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
doc/images/qmldesigner-borderimage-properties.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 8.5 KiB |
@@ -142,7 +142,7 @@
|
||||
|
||||
\li Select \uicontrol Tools > \uicontrol Options >
|
||||
\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,
|
||||
deselect the \uicontrol {Ignore pre-compiled headers} check box.
|
||||
|
||||
@@ -1510,7 +1510,7 @@
|
||||
defined file pattern only in the project you are currently
|
||||
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.
|
||||
|
||||
\li \uicontrol {Current File} searches only the current file.
|
||||
|
||||
@@ -354,7 +354,8 @@
|
||||
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
|
||||
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}
|
||||
{Version Control} panes, select
|
||||
|
||||
@@ -72,6 +72,12 @@
|
||||
\uicontrol {Clean Project}. To clean the build directory and then build the
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
@@ -93,20 +93,39 @@
|
||||
Normally, there is no need to pass any command line arguments for projects
|
||||
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
|
||||
|
||||
\QC builds CMake projects by running \c make, \c mingw32-make,
|
||||
\c nmake, or \c ninja depending on your platform. The build errors and
|
||||
warnings are parsed and displayed in the \uicontrol Issues output pane.
|
||||
|
||||
By default, \QC builds the \b{all} target. You can specify which
|
||||
targets to build in \uicontrol Projects mode, under
|
||||
\uicontrol {Build Settings}.
|
||||
By default, \QC uses the \uicontrol All \l{glossary-build-config}
|
||||
{build configuration}. You can select another build configuration in
|
||||
\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
|
||||
|
||||
\QC supports multiple build configurations. You can change the build
|
||||
directory after the initial import.
|
||||
You can change the build directory after the initial import.
|
||||
|
||||
The build and run kit that you select determines which CMake tool is used
|
||||
for building. For more information, see \l {Adding Kits}.
|
||||
|
||||
@@ -51,6 +51,11 @@
|
||||
\li Select projects that must be built before the current project is
|
||||
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
|
||||
|
||||
\QC calculates the build order based on the dependencies that you
|
||||
|
||||
@@ -57,113 +57,122 @@
|
||||
Program certificate that you receive from Apple. For more information, see
|
||||
\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} >
|
||||
\uicontrol Application > \uicontrol {Qt Quick Controls Application}
|
||||
> \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.
|
||||
The main view of the application displays an SVG bubble image that moves
|
||||
around the screen when you tilt the device.
|
||||
|
||||
To use \l{accelbubble/Bluebubble.svg}{Bluebubble.svg} in your project,
|
||||
copy it to the project directory (same subdirectory as the QML file).
|
||||
The image appears in \uicontrol Resources. You can also use any other
|
||||
image or a QML type, instead.
|
||||
|
||||
To create the UI in the \uicontrol Design mode:
|
||||
|
||||
\list 1
|
||||
|
||||
\li In the \uicontrol Projects view, double-click the main.qml file
|
||||
to open it in the code editor.
|
||||
\li In the \uicontrol Projects view, double-click the MainForm.ui.qml
|
||||
file to open it in \QMLD.
|
||||
|
||||
\li Click \uicontrol Design to open the file in \QMLD.
|
||||
|
||||
\li In the \uicontrol Navigator, select \uicontrol Label and press
|
||||
\li In the \uicontrol Navigator, select \uicontrol RowLayout and press
|
||||
\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.
|
||||
|
||||
\li Select the rectangle in the navigator to edit its properties:
|
||||
|
||||
\list a
|
||||
|
||||
\li In the \uicontrol Id field, enter \e mainWindow, to be able to
|
||||
reference the window from other places.
|
||||
\li In the \uicontrol Id field enter \e mainWindow, to be able
|
||||
to reference the rectangle from other places.
|
||||
|
||||
\li In the \uicontrol Title field, type \e {Accelerate Bubble}.
|
||||
\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
|
||||
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
|
||||
able to reference the image from other places.
|
||||
\li In the \uicontrol Properties pane, \uicontrol Id field, enter
|
||||
\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
|
||||
position the image at the center of the application window when the
|
||||
application starts:
|
||||
\li Select the \inlineimage qmldesigner-export-item-button.png
|
||||
(\uicontrol Export) button in the navigator to export the
|
||||
\e mainWindow and \e bubble as properties.
|
||||
|
||||
\endlist
|
||||
|
||||
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
|
||||
|
||||
The new project wizard adds boilerplate code to the main.qml file to create
|
||||
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 Image
|
||||
\printuntil bubble.width
|
||||
\skipto ApplicationWindow
|
||||
\printuntil title
|
||||
|
||||
\li Set the x and y position of the image based on the new properties:
|
||||
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:
|
||||
|
||||
\dots
|
||||
\printuntil centerY
|
||||
\skipto /^\}/
|
||||
\printuntil }
|
||||
|
||||
\endlist
|
||||
|
||||
For an example, see \l{accelbubble/main.qml}{main.qml}.
|
||||
|
||||
\section1 Moving the Bubble
|
||||
|
||||
Now that the visual elements are in place, let us move the bubble based on
|
||||
Accelerometer sensor values.
|
||||
Then add code to move the bubble based on Accelerometer sensor values:
|
||||
|
||||
\list 1
|
||||
\li Add the following import statement to main.qml:
|
||||
|
||||
\code
|
||||
import QtSensors 5.0
|
||||
import QtSensors 5.5
|
||||
\endcode
|
||||
|
||||
\li Add the \l{Accelerometer} type with the necessary properties:
|
||||
@@ -183,7 +192,7 @@
|
||||
\printuntil Math.atan(x
|
||||
\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
|
||||
values change:
|
||||
|
||||
@@ -194,7 +203,7 @@
|
||||
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
|
||||
(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.
|
||||
|
||||
\quotefromfile accelbubble/main.qml
|
||||
|
||||
@@ -30,41 +30,51 @@
|
||||
|
||||
\title Creating Buttons
|
||||
|
||||
To create a button component:
|
||||
To create a button type:
|
||||
|
||||
\list 1
|
||||
|
||||
\li Select \uicontrol {File > New File or Project > Qt > QML File > Choose}
|
||||
to create a QML file called Button.qml (for example).
|
||||
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
||||
\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.
|
||||
|
||||
\li Click \uicontrol {Design} to edit the file in the visual editor.
|
||||
|
||||
\li In the \uicontrol Navigator, click \uicontrol Rectangle to set properties
|
||||
for it.
|
||||
\li In the \uicontrol Navigator, select \uicontrol Item and set the
|
||||
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
|
||||
|
||||
\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 Radius field, use the slider to set the radius of
|
||||
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
|
||||
|
||||
\li Drag and drop a \uicontrol {Text} item on top of the \uicontrol Rectangle. This
|
||||
creates a nested item where \uicontrol Rectangle is the parent item
|
||||
of \uicontrol Text. Items are positioned relative to their parents.
|
||||
\li Drag and drop a \uicontrol {Text} type to the item in the navigator.
|
||||
|
||||
\li In the \uicontrol Properties pane, edit the properties of the \uicontrol Text
|
||||
item.
|
||||
type.
|
||||
|
||||
\list a
|
||||
|
||||
@@ -77,10 +87,8 @@
|
||||
\li In the \uicontrol Alignment field, select the center buttons to align
|
||||
the text to the center of the button.
|
||||
|
||||
\li Click \uicontrol {Layout}, and then click the
|
||||
\inlineimage qmldesigner-anchor-fill-screen.png
|
||||
(\uicontrol {Fill to Parent}) button to anchor the text to the whole
|
||||
button area.
|
||||
\li Select \uicontrol Layout > \uicontrol {Fill to Parent}
|
||||
to anchor the text to the whole button area.
|
||||
|
||||
\endlist
|
||||
|
||||
@@ -110,13 +118,13 @@
|
||||
\l{BorderImage} type to display an image, such as a PNG file, as a border
|
||||
and a background.
|
||||
|
||||
Use two Border Image items and suitable graphics to make it look like the
|
||||
button is pushed down when it is clicked. One of the Border Image items
|
||||
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 images
|
||||
is visible by default. You can specify that it is hidden and the other one
|
||||
becomes visible when the mouse is clicked.
|
||||
|
||||
Add a Mouse Area that covers the whole area and emits the clicked signal
|
||||
(\c {parent.clicked()}) when it detects a mouse click.
|
||||
Add a \l MouseArea type that covers the whole area and emits the clicked
|
||||
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
|
||||
then be initialized from the outside, making the button a reusable UI
|
||||
@@ -130,57 +138,54 @@
|
||||
|
||||
\list 1
|
||||
|
||||
\li Select \uicontrol {File > New File or Project > Qt > QML File > Choose}
|
||||
to create a QML file called Button.qml (for example).
|
||||
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
||||
\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.
|
||||
|
||||
\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.
|
||||
\note Types are listed in the \uicontrol Library only if the
|
||||
filename begins with a capital letter.
|
||||
|
||||
\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
|
||||
to the canvas.
|
||||
\li In the \uicontrol Navigator, select \uicontrol Item and set the
|
||||
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.
|
||||
|
||||
\li In the \uicontrol Navigator, select \uicontrol border_image1 to specify
|
||||
settings for it in the \uicontrol Properties pane:
|
||||
\image qmldesigner-borderimage-properties.png "Dynamic properties"
|
||||
|
||||
\list a
|
||||
|
||||
\li Select \uicontrol {Set Binding} in the menu next to the
|
||||
\uicontrol Visibility check box.
|
||||
\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 Enter the following expression to specify that the image is
|
||||
visible when the mouse is not pressed down:
|
||||
\c {!mouse_area1.pressed}.
|
||||
\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
|
||||
|
||||
\li Select \uicontrol Connections > \uicontrol {Bindings}
|
||||
> \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.
|
||||
|
||||
\image qmldesigner-borderimage-bindings.png "Border image bindings"
|
||||
|
||||
\li In the \uicontrol Source field, select the image file for the button,
|
||||
for example button_up.png.
|
||||
@@ -192,41 +197,48 @@
|
||||
|
||||
\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
|
||||
|
||||
\li Set the following epression for \uicontrol Visibility, to specify that
|
||||
the image is visible when the mouse is pressed down:
|
||||
\c {mouse_area1.pressed}.
|
||||
\li In \uicontrol Bindings, specify the \c visible property
|
||||
with the \c mouseArea source item and \c pressed source
|
||||
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
|
||||
when it is clicked, for example button_down.png.
|
||||
|
||||
\li Click \uicontrol {Layout}, and then click the
|
||||
\uicontrol {Fill to Parent}
|
||||
\li Select \uicontrol {Layout} > \uicontrol {Fill to Parent}
|
||||
button to anchor the border image to the \uicontrol Item.
|
||||
|
||||
\endlist
|
||||
|
||||
\li Select \uicontrol text1 to specify font size and color, and text
|
||||
scaling and rendering:
|
||||
\li Select the text to specify font size and color, and text scaling
|
||||
and rendering:
|
||||
|
||||
\list a
|
||||
|
||||
\li In the \uicontrol Color field, use the color picker to select
|
||||
the font color, or enter a value in the field.
|
||||
|
||||
\li In the \uicontrol Text field, select \uicontrol {Set Binding} and
|
||||
enter a pointer to the \c {text} property that you specified
|
||||
earlier: \c {parent.txt}.
|
||||
\li In \uicontrol Bindings, create bindings to properties:
|
||||
|
||||
\li In the \uicontrol Size field, select \uicontrol {Pixels} to specify the font
|
||||
size in pixels. By default, the size is specified in points.
|
||||
\image qmldesigner-borderimage-bindings-text.png "Text bindings"
|
||||
|
||||
\li In the \uicontrol Size field, select \uicontrol {Set Expression} and enter a
|
||||
pointer to the \c {fontSize} property that you specified
|
||||
earlier.
|
||||
\list
|
||||
|
||||
\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
|
||||
\inlineimage qmldesigner-center-in.png "Anchor buttons"
|
||||
@@ -234,20 +246,25 @@
|
||||
buttons to inherit the vertical and horizontal centering from
|
||||
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
|
||||
|
||||
\li In the code editor, add to the \c MouseArea a pointer to the
|
||||
\c clicked expression that you added earlier:
|
||||
\c {onClicked: parent.clicked()}.
|
||||
\li Select \uicontrol mouseArea in the navigator and then select
|
||||
\uicontrol Connections > \uicontrol Add to set \c item.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
|
||||
|
||||
|
||||
@@ -109,14 +109,20 @@
|
||||
Click the
|
||||
\inlineimage qmldesigner-show-hide-icon.png
|
||||
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
|
||||
check box or the \uicontrol Opacity field in the \uicontrol Properties pane. If you set
|
||||
\uicontrol Opacity to 0, items are hidden, but you can still apply animation
|
||||
to them.
|
||||
visibility of an item in the application, select the \uicontrol Visibility
|
||||
check box in the \uicontrol Properties pane or select \uicontrol Edit >
|
||||
\uicontrol Visibility in the context menu.
|
||||
|
||||
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
|
||||
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},
|
||||
\uicontrol {Open Documents}, or \uicontrol Projects in the menu.
|
||||
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
|
||||
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
|
||||
or move the item to the front or back of all its siblings. To remove the
|
||||
\c z property, select \uicontrol {Reset z Property}.
|
||||
|
||||
@@ -103,4 +103,8 @@
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
@@ -73,7 +73,7 @@ def is_debug(fpath):
|
||||
if coredebug.search(fpath):
|
||||
return True
|
||||
output = subprocess.check_output(['dumpbin', '/imports', fpath])
|
||||
return coredebug.search(output)
|
||||
return coredebug.search(output) != None
|
||||
|
||||
def is_debug_build(install_dir):
|
||||
return is_debug(os.path.join(install_dir, 'bin', 'qtcreator.exe'))
|
||||
|
||||
@@ -103,7 +103,11 @@ def qdump__boost__container__list(d, value):
|
||||
innerType = d.templateArgument(value.type, 0)
|
||||
offset = 2 * d.ptrSize()
|
||||
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):
|
||||
d.putSubItem("%s" % i, d.createValue(d.pointerValue(p) + offset, innerType))
|
||||
p = p["next_"]
|
||||
@@ -130,9 +134,36 @@ def qdump__boost__unordered__unordered_set(d, value):
|
||||
ptrSize = d.ptrSize()
|
||||
size = d.extractInt(base + 2 * ptrSize)
|
||||
d.putItemCount(size)
|
||||
|
||||
if d.isExpanded():
|
||||
innerType = d.templateArgument(value.type, 0)
|
||||
bucketCount = d.extractInt(base + ptrSize)
|
||||
#warn("A BUCKET COUNT: %s" % bucketCount)
|
||||
#warn("X BUCKET COUNT: %s" % d.parseAndEvaluate("s1.table_.bucket_count_"))
|
||||
try:
|
||||
# boost 1.58
|
||||
table = value["table_"]
|
||||
bucketsAddr = toInteger(table["buckets_"])
|
||||
#warn("A BUCKETS: 0x%x" % bucketsAddr)
|
||||
#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)
|
||||
|
||||
@@ -569,7 +569,9 @@ class DumperBase:
|
||||
elided, shown = self.computeLimit(size, limit)
|
||||
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
|
||||
elided, shown = self.computeLimit(bytelen, self.displayStringLimit)
|
||||
mem = self.readMemory(data, shown)
|
||||
@@ -595,6 +597,13 @@ class DumperBase:
|
||||
elided, shown = self.computeLimit(bytelen, 100000)
|
||||
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):
|
||||
data = self.extractBlob(addr, size).toBytes()
|
||||
return self.hexencode(data)
|
||||
@@ -795,14 +804,9 @@ class DumperBase:
|
||||
raise RuntimeError("Check failed")
|
||||
|
||||
def checkRef(self, ref):
|
||||
try:
|
||||
count = int(ref["atomic"]["_q_value"]) # Qt 5.
|
||||
minimum = -1
|
||||
except:
|
||||
count = int(ref["_q_value"]) # Qt 4.
|
||||
minimum = 0
|
||||
count = self.extractInt(ref.address)
|
||||
# Assume there aren't a million references to any object.
|
||||
self.check(count >= minimum)
|
||||
self.check(count >= -1)
|
||||
self.check(count < 1000000)
|
||||
|
||||
def readToFirstZero(self, p, tsize, maximum):
|
||||
@@ -1010,7 +1014,8 @@ class DumperBase:
|
||||
n = int(arrayByteSize / ts)
|
||||
if displayFormat != RawFormat and p:
|
||||
if innerTypeName == "char" or innerTypeName == "wchar_t":
|
||||
self.putCharArrayHelper(p, n, ts, self.currentItemFormat())
|
||||
self.putCharArrayHelper(p, n, ts, self.currentItemFormat(),
|
||||
makeExpandable = False)
|
||||
else:
|
||||
self.tryPutSimpleFormattedPointer(p, arrayType, innerTypeName,
|
||||
displayFormat, arrayByteSize)
|
||||
@@ -1410,8 +1415,7 @@ class DumperBase:
|
||||
addr += 1
|
||||
return result
|
||||
|
||||
def listChildrenGenerator(self, addr, typeName):
|
||||
innerType = self.lookupType(self.qtNamespace() + typeName)
|
||||
def listChildrenGenerator(self, addr, innerType):
|
||||
base = self.extractPointer(addr)
|
||||
begin = self.extractInt(base + 8)
|
||||
end = self.extractInt(base + 12)
|
||||
@@ -1430,6 +1434,14 @@ class DumperBase:
|
||||
p = self.extractPointer(addr + i * stepSize)
|
||||
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
|
||||
def putQObjectGuts(self, qobject, smo):
|
||||
@@ -1454,6 +1466,7 @@ class DumperBase:
|
||||
|
||||
with SubItem(self, "[properties]"):
|
||||
propertyCount = 0
|
||||
usesVector = self.qtVersion() >= 0x50700
|
||||
if self.isExpanded():
|
||||
propertyNames = self.staticQObjectPropertyNames(smo)
|
||||
propertyCount = len(propertyNames) # Doesn't include dynamic properties.
|
||||
@@ -1465,8 +1478,13 @@ class DumperBase:
|
||||
|
||||
# Dynamic properties.
|
||||
if extraData:
|
||||
names = self.listChildrenGenerator(extraData + ptrSize, "QByteArray")
|
||||
values = self.listChildrenGenerator(extraData + 2 * ptrSize, "QVariant")
|
||||
byteArrayType = self.lookupQtType("QByteArray")
|
||||
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):
|
||||
with SubItem(self, propertyCount):
|
||||
self.put('key="%s",' % self.encodeByteArray(k))
|
||||
|
||||
@@ -226,6 +226,11 @@ class Dumper(DumperBase):
|
||||
self.qtNamespaceToReport = None
|
||||
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):
|
||||
self.output = []
|
||||
self.currentIName = ""
|
||||
@@ -238,11 +243,6 @@ class Dumper(DumperBase):
|
||||
self.currentType = ReportItem()
|
||||
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.expandedINames = set(args.get("expanded", []))
|
||||
self.stringCutOff = int(args.get("stringcutoff", 10000))
|
||||
@@ -1159,6 +1159,38 @@ class Dumper(DumperBase):
|
||||
# return mem.tobytes()
|
||||
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):
|
||||
fields = value.type.fields()
|
||||
if self.sortStructMembers:
|
||||
|
||||
@@ -1115,21 +1115,41 @@ class Dumper(DumperBase):
|
||||
self.putItem(child)
|
||||
return
|
||||
|
||||
n = value.GetNumChildren()
|
||||
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)
|
||||
memberBase = 0 # Start of members.
|
||||
|
||||
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]",' % child.name)
|
||||
self.putItem(child)
|
||||
self.put('name="[%s]",' % baseObject.name)
|
||||
self.putItem(baseObject.value)
|
||||
|
||||
children = [value.GetChildAtIndex(i) for i in xrange(m, n)]
|
||||
memberCount = value.GetNumChildren()
|
||||
if memberCount > 10000:
|
||||
memberCount = 10000
|
||||
children = [value.GetChildAtIndex(memberBase + i) for i in xrange(memberCount)]
|
||||
if self.sortStructMembers:
|
||||
children.sort(key = lambda child: str(child.GetName()))
|
||||
for child in children:
|
||||
@@ -1747,14 +1767,9 @@ class Dumper(DumperBase):
|
||||
|
||||
# Used in dumper auto test.
|
||||
class Tester(Dumper):
|
||||
def __init__(self, binary, expandedINames):
|
||||
def __init__(self, binary, args):
|
||||
Dumper.__init__(self)
|
||||
lldb.theDumper = self
|
||||
|
||||
self.expandedINames = set(expandedINames)
|
||||
self.passExceptions = True
|
||||
self.sortStructMembers = True
|
||||
|
||||
self.loadDumpers({'token': 1})
|
||||
error = lldb.SBError()
|
||||
self.target = self.debugger.CreateTarget(binary, None, None, True, error)
|
||||
@@ -1763,14 +1778,14 @@ class Tester(Dumper):
|
||||
warn("ERROR: %s" % error)
|
||||
return
|
||||
|
||||
s = threading.Thread(target=self.testLoop, args=[])
|
||||
s = threading.Thread(target=self.testLoop, args=(args,))
|
||||
s.start()
|
||||
s.join(30)
|
||||
|
||||
def reportDumpers(self, msg):
|
||||
pass
|
||||
|
||||
def testLoop(self):
|
||||
def testLoop(self, args):
|
||||
# Disable intermediate reporting.
|
||||
savedReport = self.report
|
||||
self.report = lambda stuff: 0
|
||||
@@ -1813,7 +1828,7 @@ class Tester(Dumper):
|
||||
if line != 0:
|
||||
self.report = savedReport
|
||||
self.process.SetSelectedThread(stoppedThread)
|
||||
self.fetchVariables({'token':2, 'fancy':1})
|
||||
self.fetchVariables(args)
|
||||
#self.describeLocation(frame)
|
||||
self.report("@NS@%s@" % self.qtNamespace())
|
||||
#self.report("ENV=%s" % os.environ.items())
|
||||
|
||||
@@ -33,24 +33,24 @@ from dumper import *
|
||||
|
||||
|
||||
def qdump__QAtomicInt(d, value):
|
||||
d.putValue(int(value["_q_value"]))
|
||||
d.putValue(d.extractInt(value.address))
|
||||
d.putNumChild(0)
|
||||
|
||||
|
||||
def qdump__QBasicAtomicInt(d, value):
|
||||
d.putValue(int(value["_q_value"]))
|
||||
d.putValue(d.extractInt(value.address))
|
||||
d.putNumChild(0)
|
||||
|
||||
|
||||
def qdump__QAtomicPointer(d, value):
|
||||
d.putType(value.type)
|
||||
q = value["_q_value"]
|
||||
q = d.extractPointer(value.address)
|
||||
p = toInteger(q)
|
||||
d.putValue("@0x%x" % p)
|
||||
d.putNumChild(1 if p else 0)
|
||||
if d.isExpanded():
|
||||
with Children(d):
|
||||
d.putSubItem("_q_value", q.dereference())
|
||||
d.putSubItem("[pointee]", q.dereference())
|
||||
|
||||
def qform__QByteArray():
|
||||
return [Latin1StringFormat, SeparateLatin1StringFormat,
|
||||
@@ -422,7 +422,12 @@ def qdump__QFile(d, value):
|
||||
# 9fc0965 and a373ffcd change the layout of the private structure
|
||||
qtVersion = d.qtVersion()
|
||||
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():
|
||||
offset = 164 if is32bit else 248
|
||||
else:
|
||||
@@ -697,6 +702,39 @@ def qdump__QHostAddress(d, value):
|
||||
# bool isParsed (2*ptrSize + 24)
|
||||
|
||||
privAddress = d.extractPointer(value)
|
||||
if d.qtVersion() >= 0x050700:
|
||||
sizeofQString = d.ptrSize()
|
||||
ipStringAddress = privAddress
|
||||
a6Address = privAddress + 2 * sizeofQString + d.ptrSize() # Include padding
|
||||
protoAddress = a6Address + 16
|
||||
isParsedAddress = protoAddress + 4
|
||||
# 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
|
||||
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)
|
||||
@@ -1656,7 +1694,7 @@ def qdump__QSet(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)
|
||||
|
||||
|
||||
@@ -2213,8 +2251,8 @@ def qdump__QWeakPointer(d, value):
|
||||
d.putValue("<invalid>")
|
||||
d.putNumChild(0)
|
||||
return
|
||||
weakref = int(d_ptr["weakref"]["_q_value"])
|
||||
strongref = int(d_ptr["strongref"]["_q_value"])
|
||||
weakref = d.extractInt(d_ptr["weakref"].address)
|
||||
strongref = d.extractInt(d_ptr["strongref"].address)
|
||||
d.check(strongref >= -1)
|
||||
d.check(strongref <= weakref)
|
||||
d.check(weakref <= 10*1000*1000)
|
||||
|
||||
@@ -172,6 +172,9 @@ def qdump__std__list__QNX(d, value):
|
||||
def qdump__std____debug__list(d, value):
|
||||
qdump__std__list(d, value)
|
||||
|
||||
def qdump__std____cxx11__list(d, value):
|
||||
qdump__std__list(d, value)
|
||||
|
||||
def qform__std__map():
|
||||
return mapForms()
|
||||
|
||||
@@ -289,7 +292,12 @@ def stdTreeIteratorHelper(d, value):
|
||||
nodeTypeName = str(value.type).replace("_Rb_tree_iterator", "_Rb_tree_node", 1)
|
||||
nodeTypeName = nodeTypeName.replace("_Rb_tree_const_iterator", "_Rb_tree_node", 1)
|
||||
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")
|
||||
if first:
|
||||
d.putSubItem("first", first)
|
||||
@@ -463,7 +471,7 @@ def qdump__std____1__wstring(d, value):
|
||||
size = firstByte / 2
|
||||
data = base + 4
|
||||
d.putCharArrayHelper(data, size, 4)
|
||||
d.putType("std::xxwstring")
|
||||
d.putType("std::wstring")
|
||||
|
||||
|
||||
def qdump__std__shared_ptr(d, value):
|
||||
@@ -796,13 +804,29 @@ def qform__std__wstring():
|
||||
|
||||
def qdump__std__wstring(d, value):
|
||||
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())
|
||||
|
||||
def qdump__std__basic_string(d, value):
|
||||
innerType = d.templateArgument(value.type, 0)
|
||||
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):
|
||||
innerType = str(d.templateArgument(value.type, 0))
|
||||
if innerType == "char":
|
||||
|
||||
@@ -159,6 +159,28 @@ static inline int askMsgSendFailed()
|
||||
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.
|
||||
static bool copyRecursively(const QString &srcFilePath,
|
||||
const QString &tgtFilePath)
|
||||
@@ -280,12 +302,7 @@ static const char *SHARE_PATH =
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 6, 0))
|
||||
if (Utils::HostOsInfo().isWindowsHost()
|
||||
&& !qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO")) {
|
||||
qputenv("QT_DEVICE_PIXEL_RATIO", "auto");
|
||||
}
|
||||
#endif // < Qt 5.6
|
||||
const char *highDpiEnvironmentVariable = setHighDpiEnvironmentVariable();
|
||||
|
||||
QLoggingCategory::setFilterRules(QLatin1String("qtc.*.debug=false"));
|
||||
#ifdef Q_OS_MAC
|
||||
@@ -299,6 +316,9 @@ int main(int argc, char **argv)
|
||||
|
||||
SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);
|
||||
|
||||
if (highDpiEnvironmentVariable)
|
||||
qunsetenv(highDpiEnvironmentVariable);
|
||||
|
||||
if (Utils::HostOsInfo().isWindowsHost()
|
||||
&& !qFuzzyCompare(qApp->devicePixelRatio(), 1.0)
|
||||
&& QApplication::style()->objectName().startsWith(
|
||||
|
||||
@@ -54,9 +54,11 @@ FileContainer::FileContainer(const Utf8String &filePath,
|
||||
|
||||
FileContainer::FileContainer(const Utf8String &filePath,
|
||||
const Utf8String &projectPartId,
|
||||
const Utf8StringVector &fileArguments,
|
||||
quint32 documentRevision)
|
||||
: filePath_(filePath),
|
||||
projectPartId_(projectPartId),
|
||||
fileArguments_(fileArguments),
|
||||
documentRevision_(documentRevision),
|
||||
hasUnsavedFileContent_(false)
|
||||
{
|
||||
@@ -72,6 +74,11 @@ const Utf8String &FileContainer::projectPartId() const
|
||||
return projectPartId_;
|
||||
}
|
||||
|
||||
const Utf8StringVector &FileContainer::fileArguments() const
|
||||
{
|
||||
return fileArguments_;
|
||||
}
|
||||
|
||||
const Utf8String &FileContainer::unsavedFileContent() const
|
||||
{
|
||||
return unsavedFileContent_;
|
||||
@@ -91,6 +98,7 @@ QDataStream &operator<<(QDataStream &out, const FileContainer &container)
|
||||
{
|
||||
out << container.filePath_;
|
||||
out << container.projectPartId_;
|
||||
out << container.fileArguments_;
|
||||
out << container.unsavedFileContent_;
|
||||
out << container.documentRevision_;
|
||||
out << container.hasUnsavedFileContent_;
|
||||
@@ -102,6 +110,7 @@ QDataStream &operator>>(QDataStream &in, FileContainer &container)
|
||||
{
|
||||
in >> container.filePath_;
|
||||
in >> container.projectPartId_;
|
||||
in >> container.fileArguments_;
|
||||
in >> container.unsavedFileContent_;
|
||||
in >> container.documentRevision_;
|
||||
in >> container.hasUnsavedFileContent_;
|
||||
@@ -127,6 +136,7 @@ QDebug operator<<(QDebug debug, const FileContainer &container)
|
||||
debug.nospace() << "FileContainer("
|
||||
<< container.filePath() << ", "
|
||||
<< container.projectPartId() << ", "
|
||||
<< container.fileArguments() << ", "
|
||||
<< container.documentRevision();
|
||||
|
||||
if (container.hasUnsavedFileContent()) {
|
||||
@@ -147,6 +157,7 @@ void PrintTo(const FileContainer &container, ::std::ostream* os)
|
||||
*os << "FileContainer("
|
||||
<< container.filePath().constData() << ", "
|
||||
<< container.projectPartId().constData() << ", "
|
||||
<< container.fileArguments().constData() << ", "
|
||||
<< container.documentRevision();
|
||||
|
||||
if (container.hasUnsavedFileContent())
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <clangbackendipc_global.h>
|
||||
|
||||
#include <utf8string.h>
|
||||
#include <utf8stringvector.h>
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
@@ -54,10 +55,12 @@ public:
|
||||
quint32 documentRevision = 0);
|
||||
FileContainer(const Utf8String &filePath,
|
||||
const Utf8String &projectPartId,
|
||||
const Utf8StringVector &fileArguments,
|
||||
quint32 documentRevision);
|
||||
|
||||
const Utf8String &filePath() const;
|
||||
const Utf8String &projectPartId() const;
|
||||
const Utf8StringVector &fileArguments() const;
|
||||
const Utf8String &unsavedFileContent() const;
|
||||
bool hasUnsavedFileContent() const;
|
||||
quint32 documentRevision() const;
|
||||
@@ -65,6 +68,7 @@ public:
|
||||
private:
|
||||
Utf8String filePath_;
|
||||
Utf8String projectPartId_;
|
||||
Utf8StringVector fileArguments_;
|
||||
Utf8String unsavedFileContent_;
|
||||
quint32 documentRevision_;
|
||||
bool hasUnsavedFileContent_ = false;
|
||||
|
||||
@@ -1549,6 +1549,7 @@ CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snaps
|
||||
: _snapshot(snapshot)
|
||||
, _control(QSharedPointer<Control>(new Control))
|
||||
, _expandTemplates(false)
|
||||
, _depth(0)
|
||||
{
|
||||
_globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0);
|
||||
_currentLookupScope = _globalNamespace;
|
||||
@@ -1978,8 +1979,13 @@ void CreateBindings::initializeSubst(Clone &cloner,
|
||||
{
|
||||
const unsigned argumentCountOfSpecialization = specialization->templateParameterCount();
|
||||
|
||||
if (_depth > 15)
|
||||
return;
|
||||
|
||||
++_depth;
|
||||
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
|
||||
resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i);
|
||||
--_depth;
|
||||
}
|
||||
|
||||
} // namespace CPlusPlus
|
||||
|
||||
@@ -209,6 +209,7 @@ private:
|
||||
LookupScope *_globalNamespace;
|
||||
LookupScope *_currentLookupScope;
|
||||
bool _expandTemplates;
|
||||
int _depth;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT LookupContext
|
||||
|
||||
@@ -102,9 +102,12 @@ TimelineRenderPass::State *TimelineSelectionRenderPass::update(
|
||||
top = TimelineModel::defaultRowHeight() * (row + 1) - height;
|
||||
}
|
||||
|
||||
qint64 startTime = model->startTime(selectedItem);
|
||||
qint64 left = qMax(startTime - parentState->start(), (qint64)0);
|
||||
qint64 width = qMin(parentState->end() - startTime, model->duration(selectedItem));
|
||||
qint64 startTime = qBound(parentState->start(), model->startTime(selectedItem),
|
||||
parentState->end());
|
||||
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
|
||||
// left and width the error on the left border is inherited by the right border. Like this
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QPointer>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QTimer>
|
||||
|
||||
@@ -130,14 +131,20 @@ namespace FadingIndicator {
|
||||
|
||||
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->run(2500); // deletes itself
|
||||
}
|
||||
|
||||
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->run(300); // deletes itself
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "fileutils_mac.h"
|
||||
|
||||
#include "autoreleasepool.h"
|
||||
#include "qtcassert.h"
|
||||
|
||||
#include <QDir>
|
||||
@@ -44,18 +43,19 @@ namespace Internal {
|
||||
|
||||
QUrl filePathUrl(const QUrl &url)
|
||||
{
|
||||
Utils::AutoreleasePool pool; Q_UNUSED(pool)
|
||||
QUrl ret = url;
|
||||
@autoreleasepool {
|
||||
NSURL *nsurl = url.toNSURL();
|
||||
if ([nsurl isFileReferenceURL])
|
||||
ret = QUrl::fromNSURL([nsurl filePathURL]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString normalizePathName(const QString &filePath)
|
||||
{
|
||||
AutoreleasePool pool; Q_UNUSED(pool)
|
||||
|
||||
QString result;
|
||||
@autoreleasepool {
|
||||
// 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
|
||||
@@ -64,7 +64,6 @@ QString normalizePathName(const QString &filePath)
|
||||
if (QFileInfo(filePath).isRelative())
|
||||
return filePath;
|
||||
|
||||
QString result;
|
||||
QString path = QDir::cleanPath(filePath);
|
||||
// avoid empty paths and paths like "/../foo" or "/.."
|
||||
if (path.isEmpty() || path.contains(QLatin1String("/../")) || path.endsWith(QLatin1String("/..")))
|
||||
@@ -83,6 +82,7 @@ QString normalizePathName(const QString &filePath)
|
||||
path = info.path();
|
||||
}
|
||||
QTC_ASSERT(path == QLatin1String("/"), return filePath);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,14 +230,20 @@ bool MimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
|
||||
const QString resolvedParent = provider()->resolveAlias(parent);
|
||||
//Q_ASSERT(provider()->resolveAlias(mime) == mime);
|
||||
QStack<QString> toCheck;
|
||||
QSet<QString> seen; // avoid endless loop on bogus mime data
|
||||
toCheck.push(mime);
|
||||
seen.insert(mime);
|
||||
while (!toCheck.isEmpty()) {
|
||||
const QString current = toCheck.pop();
|
||||
if (current == resolvedParent)
|
||||
return true;
|
||||
foreach (const QString &par, provider()->parents(current))
|
||||
foreach (const QString &par, provider()->parents(current)) {
|
||||
int seenSize = seen.size();
|
||||
seen.insert(par);
|
||||
if (seen.size() != seenSize) // haven't seen before, so add
|
||||
toCheck.push(par);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,11 +66,11 @@ void setCreatorTheme(Theme *theme)
|
||||
m_creatorTheme = theme;
|
||||
}
|
||||
|
||||
Theme::Theme(const QString &name, QObject *parent)
|
||||
Theme::Theme(const QString &id, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new ThemePrivate)
|
||||
{
|
||||
d->name = name;
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
Theme::~Theme()
|
||||
@@ -88,6 +88,11 @@ QStringList Theme::preferredStyles() const
|
||||
return d->preferredStyles;
|
||||
}
|
||||
|
||||
QString Theme::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
bool Theme::flag(Theme::Flag f) const
|
||||
{
|
||||
return d->flags[f];
|
||||
@@ -130,14 +135,14 @@ QString Theme::filePath() const
|
||||
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
|
||||
@@ -185,7 +190,7 @@ void Theme::writeSettings(const QString &filename) const
|
||||
|
||||
const QMetaObject &m = *metaObject();
|
||||
{
|
||||
settings.setValue(QLatin1String("ThemeName"), d->name);
|
||||
settings.setValue(QLatin1String("ThemeName"), d->displayName);
|
||||
settings.setValue(QLatin1String("PreferredStyles"), d->preferredStyles);
|
||||
}
|
||||
{
|
||||
@@ -264,7 +269,7 @@ void Theme::readSettings(QSettings &settings)
|
||||
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.removeAll(QLatin1String(""));
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class QTCREATOR_UTILS_EXPORT Theme : public QObject
|
||||
Q_ENUMS(WidgetStyle)
|
||||
|
||||
public:
|
||||
Theme(const QString &name, QObject *parent = 0);
|
||||
Theme(const QString &id, QObject *parent = 0);
|
||||
~Theme();
|
||||
|
||||
enum Color {
|
||||
@@ -265,9 +265,10 @@ public:
|
||||
QPalette palette() const;
|
||||
QStringList preferredStyles() const;
|
||||
|
||||
QString id() const;
|
||||
QString filePath() const;
|
||||
QString name() const;
|
||||
void setName(const QString &name);
|
||||
QString displayName() const;
|
||||
void setDisplayName(const QString &displayName);
|
||||
|
||||
QVariantHash values() const;
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ class QTCREATOR_UTILS_EXPORT ThemePrivate
|
||||
public:
|
||||
ThemePrivate();
|
||||
|
||||
QString id;
|
||||
QString fileName;
|
||||
QString name;
|
||||
QString displayName;
|
||||
QStringList preferredStyles;
|
||||
QVector<QPair<QColor, QString> > colors;
|
||||
QVector<QString> imageFiles;
|
||||
|
||||
@@ -210,7 +210,7 @@ FORMS += $$PWD/filewizardpage.ui \
|
||||
RESOURCES += $$PWD/utils.qrc
|
||||
|
||||
osx {
|
||||
HEADERS += $$PWD/autoreleasepool.h \
|
||||
HEADERS += \
|
||||
$$PWD/fileutils_mac.h
|
||||
OBJECTIVE_SOURCES += \
|
||||
$$PWD/fileutils_mac.mm
|
||||
|
||||
@@ -41,7 +41,7 @@ const char ACTION_ID[] = "BareMetal.Action";
|
||||
const char MENU_ID[] = "BareMetal.Menu";
|
||||
|
||||
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 GDB_PROVIDERS_SETTINGS_ID[] = "AA.BareMetal.GdbServerProvidersOptions";
|
||||
|
||||
@@ -306,12 +306,44 @@ void IpcCommunicator::initializeBackend()
|
||||
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());
|
||||
registerProjectPartsForEditor({ClangBackEnd::ProjectPartContainer(
|
||||
Utf8String(),
|
||||
Utf8StringVector())});
|
||||
|
||||
const auto projectPart = CppTools::CppModelManager::instance()->fallbackProjectPart();
|
||||
const auto projectPartContainer = toProjectPartContainer(projectPart);
|
||||
|
||||
registerProjectPartsForEditor({projectPartContainer});
|
||||
}
|
||||
|
||||
void IpcCommunicator::registerCurrentProjectParts()
|
||||
@@ -343,49 +375,12 @@ void IpcCommunicator::registerCurrentCodeModelUiHeaders()
|
||||
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)
|
||||
{
|
||||
const auto projectPartContainers = toProjectPartContainers(projectParts);
|
||||
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)
|
||||
{
|
||||
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,
|
||||
const QByteArray &contents,
|
||||
uint documentRevision)
|
||||
@@ -495,6 +471,7 @@ void IpcCommunicator::requestDiagnostics(Core::IDocument *document)
|
||||
|
||||
requestDiagnostics(FileContainer(filePath,
|
||||
projectPartId,
|
||||
Utf8StringVector(),
|
||||
textDocument->document()->revision()));
|
||||
}
|
||||
|
||||
@@ -547,7 +524,7 @@ void IpcCommunicator::onCoreAboutToClose()
|
||||
|
||||
void IpcCommunicator::initializeBackendWithCurrentData()
|
||||
{
|
||||
registerEmptyProjectForProjectLessFiles();
|
||||
registerFallbackProjectPart();
|
||||
registerCurrentProjectParts();
|
||||
registerCurrentCppEditorDocuments();
|
||||
registerCurrentCodeModelUiHeaders();
|
||||
|
||||
@@ -133,8 +133,6 @@ public:
|
||||
|
||||
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 updateTranslationUnit(Core::IDocument *document);
|
||||
void updateUnsavedFile(Core::IDocument *document);
|
||||
@@ -146,6 +144,8 @@ public:
|
||||
void requestDiagnostics(Core::IDocument *document);
|
||||
void updateChangeContentStartPosition(const QString &filePath, int position);
|
||||
|
||||
void registerFallbackProjectPart();
|
||||
|
||||
public: // for tests
|
||||
IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender);
|
||||
void killBackendProcess();
|
||||
@@ -158,7 +158,6 @@ private:
|
||||
|
||||
void initializeBackend();
|
||||
void initializeBackendWithCurrentData();
|
||||
void registerEmptyProjectForProjectLessFiles();
|
||||
void registerCurrentProjectParts();
|
||||
void registerCurrentCppEditorDocuments();
|
||||
void registerCurrentCodeModelUiHeaders();
|
||||
|
||||
@@ -58,6 +58,11 @@ static void initializeTextMarks()
|
||||
Utils::Theme::ClangCodeModel_Error_TextMarkColor);
|
||||
}
|
||||
|
||||
ClangCodeModelPlugin::ClangCodeModelPlugin()
|
||||
{
|
||||
qRegisterMetaType<CppTools::ProjectPart::Ptr>();
|
||||
}
|
||||
|
||||
bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
{
|
||||
Q_UNUSED(arguments)
|
||||
|
||||
@@ -50,6 +50,8 @@ class ClangCodeModelPlugin: public ExtensionSystem::IPlugin
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json")
|
||||
|
||||
public:
|
||||
ClangCodeModelPlugin();
|
||||
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage);
|
||||
void extensionsInitialized();
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InM
|
||||
State state_ = state();
|
||||
state_.projectPart = determineProjectPart(filePath(), configuration(), state_);
|
||||
setState(state_);
|
||||
emit projectPartDetermined(state_.projectPart);
|
||||
|
||||
// Determine message line arguments
|
||||
const QStringList options = createOptions(filePath(), state_.projectPart, true);
|
||||
|
||||
@@ -50,6 +50,9 @@ public:
|
||||
QList<SemanticMarker::Range> ifdefedOutBlocks() const;
|
||||
SemanticMarker::Ptr semanticMarker() const;
|
||||
|
||||
signals:
|
||||
void projectPartDetermined(CppTools::ProjectPart::Ptr projectPart);
|
||||
|
||||
private:
|
||||
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override;
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@
|
||||
#include <diagnosticcontainer.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 <texteditor/convenience.h>
|
||||
@@ -87,6 +89,9 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
||||
, m_semanticHighlighter(document)
|
||||
, 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
|
||||
// editor (widget) related features that are not yet implemented by the clang plugin.
|
||||
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
|
||||
@@ -230,9 +235,10 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa
|
||||
&& (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)) {
|
||||
updateTranslationUnitForEditor(projectPart.data());
|
||||
@@ -242,6 +248,12 @@ void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
|
||||
}
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::onParserDeterminedProjectPart(
|
||||
CppTools::ProjectPart::Ptr projectPart)
|
||||
{
|
||||
updateProjectPartAndTranslationUnitForEditor(projectPart);
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::onParserFinished()
|
||||
{
|
||||
if (revision() != m_parserRevision)
|
||||
@@ -253,8 +265,6 @@ void ClangEditorDocumentProcessor::onParserFinished()
|
||||
|
||||
// Run semantic highlighter
|
||||
m_semanticHighlighter.run();
|
||||
|
||||
updateProjectPartAndTranslationUnitForEditor();
|
||||
}
|
||||
|
||||
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
|
||||
ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) const
|
||||
{
|
||||
if (projectPart)
|
||||
return {filePath(), projectPart->id(), revision()};
|
||||
const auto projectPartId = projectPart
|
||||
? Utf8String::fromString(projectPart->id())
|
||||
: Utf8String();
|
||||
const QStringList theFileArguments = fileArguments(filePath(), projectPart);
|
||||
|
||||
return {filePath(), Utf8String(), revision()};
|
||||
return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()};
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -85,10 +85,11 @@ public:
|
||||
static ClangEditorDocumentProcessor *get(const QString &filePath);
|
||||
|
||||
private slots:
|
||||
void onParserDeterminedProjectPart(CppTools::ProjectPart::Ptr projectPart);
|
||||
void onParserFinished();
|
||||
|
||||
private:
|
||||
void updateProjectPartAndTranslationUnitForEditor();
|
||||
void updateProjectPartAndTranslationUnitForEditor(CppTools::ProjectPart::Ptr projectPart);
|
||||
void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
|
||||
void requestDiagnostics(CppTools::ProjectPart *projectPart);
|
||||
void requestDiagnostics();
|
||||
|
||||
@@ -300,7 +300,9 @@ void ModelManagerSupportClang::onProjectPartsUpdated(ProjectExplorer::Project *p
|
||||
QTC_ASSERT(project, return);
|
||||
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
|
||||
QTC_ASSERT(projectInfo.isValid(), return);
|
||||
|
||||
m_ipcCommunicator.registerProjectsParts(projectInfo.projectParts());
|
||||
m_ipcCommunicator.registerFallbackProjectPart();
|
||||
}
|
||||
|
||||
void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectPartIds)
|
||||
@@ -308,6 +310,7 @@ void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectP
|
||||
if (!projectPartIds.isEmpty()) {
|
||||
unregisterTranslationUnitsWithProjectParts(projectPartIds);
|
||||
m_ipcCommunicator.unregisterProjectPartsForEditor(projectPartIds);
|
||||
m_ipcCommunicator.registerFallbackProjectPart();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,16 +104,6 @@ static QString getResourceDir()
|
||||
return dir.canonicalPath();
|
||||
}
|
||||
|
||||
static bool maybeIncludeBorlandExtensions()
|
||||
{
|
||||
return
|
||||
#if defined(CINDEX_VERSION) // clang 3.2 or higher
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
}
|
||||
|
||||
class LibClangOptionsBuilder : public CompilerOptionsBuilder
|
||||
{
|
||||
public:
|
||||
@@ -122,13 +112,13 @@ public:
|
||||
if (projectPart.isNull())
|
||||
return QStringList();
|
||||
|
||||
LibClangOptionsBuilder optionsBuilder(projectPart);
|
||||
LibClangOptionsBuilder optionsBuilder(*projectPart.data());
|
||||
|
||||
if (verboseRunLog().isDebugEnabled())
|
||||
optionsBuilder.add(QLatin1String("-v"));
|
||||
|
||||
optionsBuilder.addLanguageOption(fileKind);
|
||||
optionsBuilder.addOptionsForLanguage(maybeIncludeBorlandExtensions());
|
||||
optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
|
||||
|
||||
optionsBuilder.addToolchainAndProjectDefines();
|
||||
|
||||
@@ -137,15 +127,13 @@ public:
|
||||
optionsBuilder.addHeaderPathOptions();
|
||||
optionsBuilder.addProjectConfigFileInclude();
|
||||
|
||||
optionsBuilder.addDiagnosticOptions();
|
||||
|
||||
optionsBuilder.addExtraOptions();
|
||||
|
||||
return optionsBuilder.options();
|
||||
}
|
||||
|
||||
private:
|
||||
LibClangOptionsBuilder(const CppTools::ProjectPart::Ptr &projectPart)
|
||||
LibClangOptionsBuilder(const CppTools::ProjectPart &projectPart)
|
||||
: CompilerOptionsBuilder(projectPart)
|
||||
{
|
||||
}
|
||||
@@ -181,7 +169,7 @@ private:
|
||||
static const QString wrappedQtHeaders = ICore::instance()->resourcePath()
|
||||
+ QLatin1String("/cplusplus/wrappedQtHeaders");
|
||||
|
||||
if (m_projectPart->qtVersion != ProjectPart::NoQt) {
|
||||
if (m_projectPart.qtVersion != ProjectPart::NoQt) {
|
||||
add(QLatin1String("-I") + wrappedQtHeaders);
|
||||
add(QLatin1String("-I") + wrappedQtHeaders + QLatin1String("/QtCore"));
|
||||
}
|
||||
@@ -189,9 +177,9 @@ private:
|
||||
|
||||
void addProjectConfigFileInclude()
|
||||
{
|
||||
if (!m_projectPart->projectConfigFile.isEmpty()) {
|
||||
if (!m_projectPart.projectConfigFile.isEmpty()) {
|
||||
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("-fmacro-backtrace-limit=0"));
|
||||
add(QLatin1String("-fretain-comments-from-system-headers"));
|
||||
// TODO: -Xclang -ferror-limit -Xclang 0 ?
|
||||
}
|
||||
|
||||
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"));
|
||||
add(QLatin1String("-ferror-limit=1000"));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1037,6 +1037,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile(
|
||||
CppTools::Tests::ProjectOpenerAndCloser projectManager;
|
||||
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
|
||||
QVERIFY(projectInfo.isValid());
|
||||
QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
|
||||
|
||||
// Open file with ui object
|
||||
const QString completionFile = testDir.absolutePath("mainwindow.cpp");
|
||||
@@ -1046,7 +1047,6 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile(
|
||||
QVERIFY(openSource.succeeded());
|
||||
|
||||
// ...and check comletions
|
||||
QVERIFY(monitorGeneratedUiFile.waitUntilGenerated());
|
||||
ProposalModel proposal = completionResults(openSource.editor());
|
||||
QVERIFY(hasItem(proposal, "menuBar"));
|
||||
QVERIFY(hasItem(proposal, "statusBar"));
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "modemanager.h"
|
||||
#include "infobar.h"
|
||||
#include "iwizardfactory.h"
|
||||
#include "themesettings.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/documentmanager.h>
|
||||
@@ -48,6 +49,7 @@
|
||||
|
||||
#include <extensionsystem/pluginerroroverview.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/savefile.h>
|
||||
@@ -58,7 +60,6 @@
|
||||
#include <QtPlugin>
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QMenu>
|
||||
|
||||
using namespace Core;
|
||||
@@ -97,39 +98,13 @@ CorePlugin::~CorePlugin()
|
||||
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)
|
||||
{
|
||||
const QString defaultTheme = QLatin1String("default");
|
||||
QString themeName = ICore::settings()->value(
|
||||
QLatin1String(Constants::SETTINGS_THEME), defaultTheme).toString();
|
||||
const Id settingsThemeId = Id::fromSetting(ICore::settings()->value(
|
||||
QLatin1String(Constants::SETTINGS_THEME), QLatin1String("default")));
|
||||
Id themeId = settingsThemeId;
|
||||
QColor overrideColor;
|
||||
bool presentationMode = false;
|
||||
bool userProvidedTheme = false;
|
||||
|
||||
for (int i = 0; i < arguments.size(); ++i) {
|
||||
if (arguments.at(i) == QLatin1String("-color")) {
|
||||
@@ -140,28 +115,27 @@ void CorePlugin::parseArguments(const QStringList &arguments)
|
||||
if (arguments.at(i) == QLatin1String("-presentationMode"))
|
||||
presentationMode = true;
|
||||
if (arguments.at(i) == QLatin1String("-theme")) {
|
||||
themeName = arguments.at(i + 1);
|
||||
userProvidedTheme = true;
|
||||
themeId = Id::fromString(arguments.at(i + 1));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
QString themeURI = absoluteThemePath(themeName, userProvidedTheme);
|
||||
if (themeURI.isEmpty()) {
|
||||
themeName = defaultTheme;
|
||||
themeURI = QStringLiteral("%1/themes/%2.creatortheme").arg(ICore::resourcePath()).arg(themeName);
|
||||
if (themeURI.isEmpty()) {
|
||||
qCritical("%s", qPrintable(QCoreApplication::translate("Application", "No valid theme \"%1\"")
|
||||
.arg(themeName)));
|
||||
const QList<ThemeEntry> availableThemes = ThemeSettings::availableThemes();
|
||||
int themeIndex = Utils::indexOf(availableThemes, Utils::equal(&ThemeEntry::id, themeId));
|
||||
if (themeIndex < 0) {
|
||||
themeIndex = Utils::indexOf(availableThemes,
|
||||
Utils::equal(&ThemeEntry::id, settingsThemeId));
|
||||
}
|
||||
}
|
||||
|
||||
QSettings themeSettings(themeURI, QSettings::IniFormat);
|
||||
Theme *theme = new Theme(themeName, qApp);
|
||||
if (themeIndex < 0)
|
||||
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);
|
||||
}
|
||||
|
||||
// defer creation of these widgets until here,
|
||||
// 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)
|
||||
{
|
||||
if (ThemeSettings::availableThemes().isEmpty()) {
|
||||
*errorMessage = tr("No themes found in installation.");
|
||||
return false;
|
||||
}
|
||||
new ActionManager(this);
|
||||
Theme::initialPalette(); // Initialize palette before setting it
|
||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||
|
||||
@@ -189,6 +189,7 @@ using namespace Core::Internal;
|
||||
|
||||
bool NewDialog::m_isRunning = false;
|
||||
QString NewDialog::m_lastCategory = QString();
|
||||
QString NewDialog::m_lastPlatform = QString();
|
||||
|
||||
NewDialog::NewDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -301,6 +302,9 @@ void NewDialog::showDialog()
|
||||
{
|
||||
QModelIndex idx;
|
||||
|
||||
if (!m_lastPlatform.isEmpty())
|
||||
m_ui->comboBox->setCurrentIndex(m_ui->comboBox->findData(m_lastPlatform));
|
||||
|
||||
if (!m_lastCategory.isEmpty())
|
||||
foreach (QStandardItem* item, m_categoryItems) {
|
||||
if (item->data(Qt::UserRole) == m_lastCategory)
|
||||
@@ -446,6 +450,7 @@ void NewDialog::saveState()
|
||||
QStandardItem *currentItem = m_model->itemFromIndex(m_twoLevelProxyModel->mapToSource(idx));
|
||||
if (currentItem)
|
||||
m_lastCategory = currentItem->data(Qt::UserRole).toString();
|
||||
m_lastPlatform = m_ui->comboBox->currentData().toString();
|
||||
}
|
||||
|
||||
void NewDialog::accept()
|
||||
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
void saveState();
|
||||
|
||||
static QString m_lastCategory;
|
||||
static QString m_lastPlatform;
|
||||
static bool m_isRunning;
|
||||
|
||||
Ui::NewDialog *m_ui;
|
||||
|
||||
@@ -373,12 +373,15 @@ bool ShortcutSettingsWidget::filterColumn(const QString &filterString, QTreeWidg
|
||||
int column) const
|
||||
{
|
||||
QString text;
|
||||
if (column == item->columnCount() - 1) {
|
||||
if (column == item->columnCount() - 1) { // shortcut
|
||||
// filter on the shortcut edit text
|
||||
if (!item->data(0, Qt::UserRole).isValid())
|
||||
return true;
|
||||
ShortcutItem *scitem = qvariant_cast<ShortcutItem *>(item->data(0, Qt::UserRole));
|
||||
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 {
|
||||
text = item->text(column);
|
||||
}
|
||||
|
||||
@@ -490,10 +490,6 @@ void EditorManagerPrivate::init()
|
||||
connect(m_autoSaveTimer, SIGNAL(timeout()), SLOT(autoSave()));
|
||||
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();
|
||||
ExtensionSystem::PluginManager::addObject(d->m_openEditorsFactory);
|
||||
|
||||
@@ -518,6 +514,13 @@ void EditorManagerPrivate::init()
|
||||
});
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return d;
|
||||
@@ -2487,7 +2490,9 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
|
||||
// * application/octet-stream
|
||||
// * text/plain
|
||||
QList<Utils::MimeType> queue;
|
||||
QSet<QString> seen;
|
||||
queue.append(mimeType);
|
||||
seen.insert(mimeType.name());
|
||||
while (!queue.isEmpty()) {
|
||||
Utils::MimeType mt = queue.takeFirst();
|
||||
// check for matching factories
|
||||
@@ -2507,8 +2512,14 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
|
||||
QStringList parentNames = mt.parentMimeTypes();
|
||||
foreach (const QString &parentName, parentNames) {
|
||||
const Utils::MimeType parent = mdb.mimeTypeForName(parentName);
|
||||
if (parent.isValid())
|
||||
if (parent.isValid()) {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@ class EditorManagerPrivate : public QObject
|
||||
public:
|
||||
static EditorManagerPrivate *instance();
|
||||
|
||||
static void extensionsInitialized(); // only use from MainWindow
|
||||
|
||||
static EditorArea *mainEditorArea();
|
||||
static EditorView *currentEditorView();
|
||||
static void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false);
|
||||
|
||||
@@ -53,9 +53,13 @@ using namespace Utils;
|
||||
namespace Core {
|
||||
namespace Internal {
|
||||
|
||||
FancyToolButton::FancyToolButton(QWidget *parent)
|
||||
FancyToolButton::FancyToolButton(QAction *action, QWidget *parent)
|
||||
: QToolButton(parent), m_fader(0)
|
||||
{
|
||||
setDefaultAction(action);
|
||||
connect(action, &QAction::changed, this, &FancyToolButton::actionChanged);
|
||||
actionChanged();
|
||||
|
||||
setAttribute(Qt::WA_Hover, true);
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
}
|
||||
@@ -364,18 +368,12 @@ FancyActionBar::FancyActionBar(QWidget *parent)
|
||||
|
||||
void FancyActionBar::addProjectSelector(QAction *action)
|
||||
{
|
||||
FancyToolButton* toolButton = new FancyToolButton(this);
|
||||
toolButton->setDefaultAction(action);
|
||||
connect(action, SIGNAL(changed()), toolButton, SLOT(actionChanged()));
|
||||
m_actionsLayout->insertWidget(0, toolButton);
|
||||
m_actionsLayout->insertWidget(0, new FancyToolButton(action, this));
|
||||
|
||||
}
|
||||
void FancyActionBar::insertAction(int index, QAction *action)
|
||||
{
|
||||
FancyToolButton *toolButton = new FancyToolButton(this);
|
||||
toolButton->setDefaultAction(action);
|
||||
connect(action, SIGNAL(changed()), toolButton, SLOT(actionChanged()));
|
||||
m_actionsLayout->insertWidget(index, toolButton);
|
||||
m_actionsLayout->insertWidget(index, new FancyToolButton(action, this));
|
||||
}
|
||||
|
||||
QLayout *FancyActionBar::actionsLayout() const
|
||||
|
||||
@@ -47,7 +47,7 @@ class FancyToolButton : public QToolButton
|
||||
Q_PROPERTY(float fader READ fader WRITE setFader)
|
||||
|
||||
public:
|
||||
FancyToolButton(QWidget *parent = 0);
|
||||
FancyToolButton(QAction *action, QWidget *parent = 0);
|
||||
|
||||
void paintEvent(QPaintEvent *event);
|
||||
bool event(QEvent *e);
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
a text based search term (potentially with find flags like
|
||||
searching case sensitively or using regular expressions). Existing
|
||||
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.
|
||||
|
||||
To make your find scope available to the user, you need to implement this
|
||||
|
||||
@@ -410,11 +410,11 @@ bool LocatorWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
}
|
||||
} else if (obj == m_fileLineEdit && event->type() == QEvent::FocusOut) {
|
||||
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_fileLineEdit->clearFocus();
|
||||
}
|
||||
} else if (obj == m_fileLineEdit && event->type() == QEvent::FocusIn) {
|
||||
QFocusEvent *fev = static_cast<QFocusEvent *>(event);
|
||||
if (fev->reason() != Qt::ActiveWindowFocusReason)
|
||||
showPopupNow();
|
||||
} else if (obj == this && event->type() == QEvent::ShortcutOverride) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
||||
@@ -584,9 +584,7 @@ void LocatorWidget::show(const QString &text, int selectionStart, int selectionL
|
||||
{
|
||||
if (!text.isEmpty())
|
||||
m_fileLineEdit->setText(text);
|
||||
if (!m_fileLineEdit->hasFocus())
|
||||
m_fileLineEdit->setFocus();
|
||||
else
|
||||
showPopupNow();
|
||||
ICore::raiseWindow(ICore::mainWindow());
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "spotlightlocatorfilter.h"
|
||||
|
||||
#include <utils/autoreleasepool.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QMutex>
|
||||
@@ -38,7 +37,6 @@
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSMetadata.h>
|
||||
#include <Foundation/NSNotification.h>
|
||||
@@ -85,7 +83,7 @@ SpotlightIterator::SpotlightIterator(const QString &expression)
|
||||
m_queueIndex(-1),
|
||||
m_finished(false)
|
||||
{
|
||||
Utils::AutoreleasePool pool; Q_UNUSED(pool)
|
||||
@autoreleasepool {
|
||||
NSPredicate *predicate = [NSPredicate predicateWithFormat:expression.toNSString()];
|
||||
m_query = [[NSMetadataQuery alloc] init];
|
||||
m_query.predicate = predicate;
|
||||
@@ -112,6 +110,7 @@ SpotlightIterator::SpotlightIterator(const QString &expression)
|
||||
m_waitForItems.wakeAll();
|
||||
}] retain];
|
||||
[m_query startQuery];
|
||||
}
|
||||
}
|
||||
|
||||
SpotlightIterator::~SpotlightIterator()
|
||||
@@ -163,7 +162,7 @@ void SpotlightIterator::ensureNext()
|
||||
return;
|
||||
if (m_index >= 10000) // limit the amount of data that is passed on
|
||||
return;
|
||||
Utils::AutoreleasePool pool; Q_UNUSED(pool)
|
||||
@autoreleasepool {
|
||||
// check if there are items in the queue, otherwise wait for some
|
||||
m_mutex.lock();
|
||||
bool itemAvailable = (m_queueIndex + 1 < m_queue.count);
|
||||
@@ -179,6 +178,7 @@ void SpotlightIterator::ensureNext()
|
||||
|
||||
}
|
||||
m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma mark -- SpotlightLocatorFilter
|
||||
|
||||
@@ -347,6 +347,7 @@ bool MainWindow::init(QString *errorMessage)
|
||||
|
||||
void MainWindow::extensionsInitialized()
|
||||
{
|
||||
EditorManagerPrivate::extensionsInitialized();
|
||||
MimeTypeSettings::restoreSettings();
|
||||
m_windowSupport = new WindowSupport(this, Context("Core.MainWindow"));
|
||||
m_windowSupport->setCloseActionEnabled(false);
|
||||
|
||||
@@ -222,7 +222,7 @@ void ThemeSettingsTableModel::initFrom(Theme *theme)
|
||||
}
|
||||
|
||||
m_widgetStyle = theme->widgetStyle();
|
||||
m_name = theme->d->name;
|
||||
m_displayName = theme->d->displayName;
|
||||
m_preferredStyles = theme->d->preferredStyles;
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ void ThemeSettingsTableModel::toTheme(Theme *t) const
|
||||
}
|
||||
|
||||
theme->widgetStyle = m_widgetStyle;
|
||||
theme->name = m_name;
|
||||
theme->displayName = m_displayName;
|
||||
theme->preferredStyles = m_preferredStyles;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
void initFrom(Utils::Theme *theme);
|
||||
void toTheme(Utils::Theme *theme) const;
|
||||
|
||||
QString m_name;
|
||||
QString m_displayName;
|
||||
QStringList m_preferredStyles;
|
||||
|
||||
public:
|
||||
|
||||
@@ -31,14 +31,55 @@
|
||||
#include "themesettings.h"
|
||||
#include "themesettingswidget.h"
|
||||
#include "coreconstants.h"
|
||||
#include "icore.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
|
||||
static const char themeNameKey[] = "ThemeName";
|
||||
|
||||
namespace Core {
|
||||
namespace Internal {
|
||||
|
||||
ThemeSettings::ThemeSettings() :
|
||||
m_widget(0)
|
||||
ThemeEntry::ThemeEntry(Id id, const QString &filePath, bool readOnly)
|
||||
: 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);
|
||||
setDisplayName(tr("Theme"));
|
||||
@@ -71,5 +112,38 @@ void ThemeSettings::finish()
|
||||
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 Core
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#ifndef THEMESETTINGS_H
|
||||
#define THEMESETTINGS_H
|
||||
|
||||
#include "id.h"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
|
||||
namespace Core {
|
||||
@@ -38,6 +40,24 @@ namespace Internal {
|
||||
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -50,7 +70,9 @@ public:
|
||||
void apply();
|
||||
void finish();
|
||||
|
||||
ThemeSettingsWidget *m_widget;
|
||||
static QList<ThemeEntry> availableThemes();
|
||||
private:
|
||||
ThemeSettingsWidget *m_widget = 0;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
#include "icore.h"
|
||||
#include "manhattanstyle.h"
|
||||
#include "themeeditor/themesettingstablemodel.h"
|
||||
#include "themesettings.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/theme/theme_p.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -52,8 +54,6 @@ using namespace Utils;
|
||||
namespace Core {
|
||||
namespace Internal {
|
||||
|
||||
const char themeNameKey[] = "ThemeName";
|
||||
|
||||
static QString customThemesPath()
|
||||
{
|
||||
return ICore::userResourcePath() + QLatin1String("/themes/");
|
||||
@@ -81,42 +81,6 @@ static QString createThemeFileName(const QString &pattern)
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -179,7 +143,7 @@ ThemeSettingsPrivate::ThemeSettingsPrivate(QWidget *widget)
|
||||
, m_refreshingThemeList(false)
|
||||
, 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);
|
||||
// TODO: Restore the editor and the buttons after improving the editor
|
||||
m_ui->editor->hide();
|
||||
@@ -216,44 +180,15 @@ ThemeSettingsWidget::~ThemeSettingsWidget()
|
||||
|
||||
void ThemeSettingsWidget::refreshThemeList()
|
||||
{
|
||||
QList<ThemeEntry> themes;
|
||||
|
||||
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];
|
||||
const QList<ThemeEntry> themes = ThemeSettings::availableThemes();
|
||||
const int selected = Utils::indexOf(themes, Utils::equal(&ThemeEntry::id, d->m_currentTheme.id()));
|
||||
|
||||
d->m_refreshingThemeList = true;
|
||||
d->m_themeListModel->setThemes(themes);
|
||||
if (selected >= 0) {
|
||||
d->m_currentTheme = themes[selected];
|
||||
d->m_ui->themeComboBox->setCurrentIndex(selected);
|
||||
}
|
||||
d->m_refreshingThemeList = false;
|
||||
}
|
||||
|
||||
@@ -270,7 +205,7 @@ void ThemeSettingsWidget::themeSelected(int index)
|
||||
d->m_currentTheme = entry;
|
||||
|
||||
QSettings settings(entry.filePath(), QSettings::IniFormat);
|
||||
Theme theme(entry.name());
|
||||
Theme theme(entry.id().toString());
|
||||
theme.readSettings(settings);
|
||||
d->m_ui->editor->initFrom(&theme);
|
||||
}
|
||||
@@ -354,7 +289,7 @@ void ThemeSettingsWidget::maybeSaveTheme()
|
||||
messageBox->setDefaultButton(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);
|
||||
newTheme.writeSettings(d->m_currentTheme.filePath());
|
||||
}
|
||||
@@ -373,7 +308,7 @@ void ThemeSettingsWidget::renameTheme()
|
||||
dialog->setInputMode(QInputDialog::TextInput);
|
||||
dialog->setWindowTitle(tr("Rename Theme"));
|
||||
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();
|
||||
QString newName = dialog->textValue();
|
||||
delete dialog;
|
||||
@@ -382,9 +317,9 @@ void ThemeSettingsWidget::renameTheme()
|
||||
return;
|
||||
|
||||
// overwrite file with new name
|
||||
Theme newTheme(entry.name());
|
||||
Theme newTheme(entry.id().toString());
|
||||
d->m_ui->editor->model()->toTheme(&newTheme);
|
||||
newTheme.setName(newName);
|
||||
newTheme.setDisplayName(newName);
|
||||
newTheme.writeSettings(entry.filePath());
|
||||
|
||||
refreshThemeList();
|
||||
@@ -401,8 +336,9 @@ void ThemeSettingsWidget::copyThemeByName(const QString &name)
|
||||
QString baseFileName = QFileInfo(entry.filePath()).completeBaseName();
|
||||
baseFileName += QLatin1String("_copy%1.creatortheme");
|
||||
QString fileName = createThemeFileName(baseFileName);
|
||||
QString id = QFileInfo(fileName).completeBaseName();
|
||||
|
||||
if (fileName.isEmpty())
|
||||
if (fileName.isEmpty() || id.isEmpty())
|
||||
return;
|
||||
|
||||
// Ask about saving any existing modifactions
|
||||
@@ -410,18 +346,18 @@ void ThemeSettingsWidget::copyThemeByName(const QString &name)
|
||||
|
||||
Theme newTheme(fileName);
|
||||
d->m_ui->editor->model()->toTheme(&newTheme);
|
||||
newTheme.setName(name);
|
||||
newTheme.setDisplayName(name);
|
||||
newTheme.writeSettings(fileName);
|
||||
|
||||
d->m_currentTheme = ThemeEntry(fileName, fileName, true);
|
||||
d->m_currentTheme = ThemeEntry(Id::fromString(id), fileName, true);
|
||||
|
||||
refreshThemeList();
|
||||
}
|
||||
|
||||
void ThemeSettingsWidget::apply()
|
||||
{
|
||||
const QString themeName = d->m_currentTheme.name();
|
||||
Theme *newTheme = new Theme(themeName);
|
||||
const QString themeId = d->m_currentTheme.id().toString();
|
||||
Theme *newTheme = new Theme(themeId);
|
||||
if (d->m_currentTheme.readOnly()) {
|
||||
QSettings themeSettings(d->m_currentTheme.filePath(), QSettings::IniFormat);
|
||||
newTheme->readSettings(themeSettings);
|
||||
@@ -447,7 +383,7 @@ void ThemeSettingsWidget::apply()
|
||||
|
||||
// save filename of selected theme in global config
|
||||
QSettings *settings = ICore::settings();
|
||||
settings->setValue(QLatin1String(Constants::SETTINGS_THEME), themeName);
|
||||
settings->setValue(QLatin1String(Constants::SETTINGS_THEME), themeId);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -36,6 +36,7 @@ using namespace CppTools;
|
||||
|
||||
static QLatin1String cppHeaderMimeType(Constants::CPP_HEADER_MIMETYPE);
|
||||
static QLatin1String cHeaderMimeType(Constants::C_HEADER_MIMETYPE);
|
||||
static QLatin1String clangExtraOptionsKey(Constants::CPPTOOLS_EXTRA_CLANG_OPTIONS);
|
||||
|
||||
void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
{
|
||||
@@ -45,6 +46,8 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
|
||||
foreach (const QString &mimeType, supportedMimeTypes())
|
||||
setIdForMimeType(supporters, mimeType);
|
||||
|
||||
setExtraClangOptions(s->value(clangExtraOptionsKey, defaultExtraClangOptions()).toStringList());
|
||||
|
||||
QVariant v = s->value(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), PchUse_None);
|
||||
setPCHUsage(static_cast<PCHUsage>(v.toInt()));
|
||||
s->endGroup();
|
||||
@@ -59,6 +62,7 @@ void CppCodeModelSettings::toSettings(QSettings *s)
|
||||
foreach (const QString &mimeType, m_modelManagerSupportByMimeType.keys())
|
||||
var[mimeType] = m_modelManagerSupportByMimeType[mimeType];
|
||||
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->endGroup();
|
||||
|
||||
@@ -116,6 +120,33 @@ bool CppCodeModelSettings::hasModelManagerSupportIdForMimeType(const QString &mi
|
||||
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)
|
||||
{
|
||||
QHash<QString, QVariant> mimeToId = var.toHash();
|
||||
|
||||
@@ -73,6 +73,10 @@ public:
|
||||
void setDefaultId(const QString &defaultId)
|
||||
{ m_defaultId = defaultId; }
|
||||
|
||||
static QStringList defaultExtraClangOptions();
|
||||
QStringList extraClangOptions() const;
|
||||
void setExtraClangOptions(const QStringList &extraClangOptions);
|
||||
|
||||
PCHUsage pchUsage() const { return m_pchUsage; }
|
||||
void setPCHUsage(PCHUsage pchUsage) { m_pchUsage = pchUsage; }
|
||||
|
||||
@@ -90,6 +94,7 @@ private:
|
||||
private:
|
||||
QHash<QString, QString> m_modelManagerSupportByMimeType;
|
||||
QHash<QString, QString> m_modelManagerSupportsByName;
|
||||
QStringList m_extraClangOptions;
|
||||
QString m_defaultId;
|
||||
PCHUsage m_pchUsage;
|
||||
};
|
||||
|
||||
@@ -46,7 +46,11 @@ CppCodeModelSettingsWidget::CppCodeModelSettingsWidget(QWidget *parent)
|
||||
{
|
||||
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()
|
||||
@@ -58,41 +62,16 @@ void CppCodeModelSettingsWidget::setSettings(const QSharedPointer<CppCodeModelSe
|
||||
{
|
||||
m_settings = s;
|
||||
|
||||
applyToWidget(m_ui->cChooser, QLatin1String(Constants::C_SOURCE_MIMETYPE));
|
||||
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));
|
||||
|
||||
setupClangCodeModelWidgets();
|
||||
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
|
||||
{
|
||||
bool changed = false;
|
||||
changed |= applyToSettings(m_ui->cChooser, QLatin1String(Constants::C_SOURCE_MIMETYPE));
|
||||
changed |= applyToSettings(m_ui->cppChooser, QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
|
||||
changed |= applyToSettings(m_ui->objcChooser,
|
||||
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 (applyClangCodeModelWidgetsToSettings())
|
||||
changed = true;
|
||||
|
||||
if (m_ui->ignorePCHCheckBox->isChecked() !=
|
||||
(m_settings->pchUsage() == CppCodeModelSettings::PchUse_None)) {
|
||||
@@ -106,14 +85,46 @@ void CppCodeModelSettingsWidget::applyToSettings() const
|
||||
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();
|
||||
QString currentId = m_settings->modelManagerSupportIdForMimeType(mimeType);
|
||||
if (newId == currentId)
|
||||
return false;
|
||||
const QString currentCodeModelId
|
||||
= settings.modelManagerSupportIdForMimeType(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
|
||||
return currentCodeModelId != settings.defaultId();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,8 +58,8 @@ public:
|
||||
void applyToSettings() const;
|
||||
|
||||
private:
|
||||
bool applyToSettings(QComboBox *chooser, const QString &mimeType) const;
|
||||
void applyToWidget(QComboBox *chooser, const QString &mimeType) const;
|
||||
void setupClangCodeModelWidgets() const;
|
||||
bool applyClangCodeModelWidgetsToSettings() const;
|
||||
|
||||
private:
|
||||
Ui::CppCodeModelSettingsPage *m_ui;
|
||||
|
||||
@@ -15,74 +15,54 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="theGroupBox">
|
||||
<widget class="QLabel" name="activateClangCodeModelPluginHint">
|
||||
<property name="text">
|
||||
<string><i>Activate the Clang Code Model plugin to enable the options here.</i></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="clangSettingsGroupBox">
|
||||
<property name="title">
|
||||
<string>Code Completion and Semantic Highlighting</string>
|
||||
<string>Use Clang Code Model</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="cLabel">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="clangOptionsGeneralHintLabel">
|
||||
<property name="text">
|
||||
<string>C</string>
|
||||
<string>Append additional command line options to Clang, one per line. <i>Use this with care.</i></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cChooser">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="clangOptionsToAppendTextEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="cppLabel">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="clangOptionsResetButton">
|
||||
<property name="text">
|
||||
<string>C++</string>
|
||||
<string>Reset Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cppChooser">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="objcLabel">
|
||||
<property name="text">
|
||||
<string>Objective C</string>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</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"/>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -384,9 +384,9 @@ bool CppModelManager::replaceDocument(Document::Ptr newDoc)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Make sure that m_projectMutex is locked when calling this.
|
||||
void CppModelManager::ensureUpdated()
|
||||
{
|
||||
QMutexLocker locker(&d->m_projectMutex);
|
||||
if (!d->m_dirty)
|
||||
return;
|
||||
|
||||
@@ -475,8 +475,7 @@ void CppModelManager::dumpModelManagerConfiguration(const QString &logFileId)
|
||||
dumper.dumpProjectInfos(projectInfos());
|
||||
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
|
||||
dumper.dumpWorkingCopy(workingCopy());
|
||||
ensureUpdated();
|
||||
dumper.dumpMergedEntities(d->m_headerPaths, d->m_definedMacros);
|
||||
dumper.dumpMergedEntities(headerPaths(), definedMacros());
|
||||
}
|
||||
|
||||
QSet<AbstractEditorSupport *> CppModelManager::abstractEditorSupports() const
|
||||
@@ -941,14 +940,19 @@ QList<ProjectPart::Ptr> CppModelManager::projectPartFromDependencies(
|
||||
return parts.values();
|
||||
}
|
||||
|
||||
ProjectPart::Ptr CppModelManager::fallbackProjectPart() const
|
||||
ProjectPart::Ptr CppModelManager::fallbackProjectPart()
|
||||
{
|
||||
ProjectPart::Ptr part(new ProjectPart);
|
||||
|
||||
part->projectDefines = d->m_definedMacros;
|
||||
part->headerPaths = d->m_headerPaths;
|
||||
part->projectDefines = definedMacros();
|
||||
part->headerPaths = headerPaths();
|
||||
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::ObjectiveCExtensions;
|
||||
|
||||
part->qtVersion = ProjectPart::Qt5;
|
||||
part->updateLanguageFeatures();
|
||||
|
||||
@@ -1254,24 +1258,31 @@ CppIndexingSupport *CppModelManager::indexingSupport()
|
||||
|
||||
QStringList CppModelManager::projectFiles()
|
||||
{
|
||||
QMutexLocker locker(&d->m_projectMutex);
|
||||
ensureUpdated();
|
||||
|
||||
return d->m_projectFiles;
|
||||
}
|
||||
|
||||
ProjectPart::HeaderPaths CppModelManager::headerPaths()
|
||||
{
|
||||
QMutexLocker locker(&d->m_projectMutex);
|
||||
ensureUpdated();
|
||||
|
||||
return d->m_headerPaths;
|
||||
}
|
||||
|
||||
void CppModelManager::setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths)
|
||||
{
|
||||
QMutexLocker locker(&d->m_projectMutex);
|
||||
d->m_headerPaths = headerPaths;
|
||||
}
|
||||
|
||||
QByteArray CppModelManager::definedMacros()
|
||||
{
|
||||
QMutexLocker locker(&d->m_projectMutex);
|
||||
ensureUpdated();
|
||||
|
||||
return d->m_definedMacros;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
QList<ProjectPart::Ptr> projectPartFromDependencies(const Utils::FileName &fileName) const;
|
||||
/// \return A synthetic \c ProjectPart which consists of all defines/includes/frameworks from
|
||||
/// all loaded projects.
|
||||
ProjectPart::Ptr fallbackProjectPart() const;
|
||||
ProjectPart::Ptr fallbackProjectPart();
|
||||
|
||||
CPlusPlus::Snapshot snapshot() const;
|
||||
Document::Ptr document(const QString &fileName) const;
|
||||
|
||||
@@ -505,7 +505,7 @@ void ProjectPartBuilder::createProjectPart(const QStringList &theSources,
|
||||
}
|
||||
|
||||
|
||||
CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart::Ptr &projectPart)
|
||||
CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart)
|
||||
: m_projectPart(projectPart)
|
||||
{
|
||||
}
|
||||
@@ -544,7 +544,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
|
||||
QStringList result;
|
||||
|
||||
foreach (const HeaderPath &headerPath , m_projectPart->headerPaths) {
|
||||
foreach (const HeaderPath &headerPath , m_projectPart.headerPaths) {
|
||||
if (headerPath.path.isEmpty())
|
||||
continue;
|
||||
|
||||
@@ -571,7 +571,7 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
|
||||
|
||||
void CompilerOptionsBuilder::addToolchainAndProjectDefines()
|
||||
{
|
||||
QByteArray extendedDefines = m_projectPart->toolchainDefines + m_projectPart->projectDefines;
|
||||
QByteArray extendedDefines = m_projectPart.toolchainDefines + m_projectPart.projectDefines;
|
||||
QStringList result;
|
||||
|
||||
foreach (QByteArray def, extendedDefines.split('\n')) {
|
||||
@@ -645,7 +645,7 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc
|
||||
|
||||
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);
|
||||
m_options.append(options);
|
||||
}
|
||||
@@ -653,9 +653,9 @@ void CompilerOptionsBuilder::addLanguageOption(ProjectFile::Kind fileKind)
|
||||
void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtensions)
|
||||
{
|
||||
QStringList opts;
|
||||
const ProjectPart::LanguageExtensions languageExtensions = m_projectPart->languageExtensions;
|
||||
const ProjectPart::LanguageExtensions languageExtensions = m_projectPart.languageExtensions;
|
||||
const bool gnuExtensions = languageExtensions & ProjectPart::GnuExtensions;
|
||||
switch (m_projectPart->languageVersion) {
|
||||
switch (m_projectPart.languageVersion) {
|
||||
case ProjectPart::C89:
|
||||
opts << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89"));
|
||||
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
|
||||
// override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
|
||||
// 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"))
|
||||
return true;
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ private:
|
||||
class CPPTOOLS_EXPORT CompilerOptionsBuilder
|
||||
{
|
||||
public:
|
||||
CompilerOptionsBuilder(const ProjectPart::Ptr &projectPart);
|
||||
CompilerOptionsBuilder(const ProjectPart &projectPart);
|
||||
virtual ~CompilerOptionsBuilder() {}
|
||||
|
||||
QStringList options() const;
|
||||
@@ -237,7 +237,7 @@ protected:
|
||||
virtual QString defineOption() const;
|
||||
virtual QString includeOption() const;
|
||||
|
||||
const ProjectPart::Ptr m_projectPart;
|
||||
const ProjectPart m_projectPart;
|
||||
|
||||
private:
|
||||
QString defineLineToDefineOption(const QByteArray &defineLine);
|
||||
@@ -247,4 +247,6 @@ private:
|
||||
|
||||
} // namespace CppTools
|
||||
|
||||
Q_DECLARE_METATYPE(CppTools::ProjectPart::Ptr)
|
||||
|
||||
#endif // CPPPROJECTPART_H
|
||||
|
||||
@@ -55,6 +55,7 @@ enum { lowerCaseFilesDefault = 1 };
|
||||
const char CPPTOOLS_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview";
|
||||
const char CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY[] = "ModelManagerSupporters";
|
||||
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_NAME[] = QT_TRANSLATE_NOOP("CppTools", "Code Style");
|
||||
|
||||
@@ -391,7 +391,7 @@ QList<IncludeGroup> IncludeGroup::detectIncludeGroupsByIncludeType(const QList<I
|
||||
{
|
||||
// Create sub groups
|
||||
QList<IncludeGroup> result;
|
||||
Client::IncludeType lastIncludeType;
|
||||
Client::IncludeType lastIncludeType = Client::IncludeLocal;
|
||||
QList<Include> currentIncludes;
|
||||
bool isFirst = true;
|
||||
foreach (const Include &include, includes) {
|
||||
|
||||
@@ -340,8 +340,8 @@ void CdbEngine::syncOperateByInstruction(bool operateByInstruction)
|
||||
return;
|
||||
QTC_ASSERT(m_accessible, return);
|
||||
m_operateByInstruction = operateByInstruction;
|
||||
runCommand(DebuggerCommand(m_operateByInstruction ? QByteArray("l-t") : QByteArray("l+t")));
|
||||
runCommand(DebuggerCommand(m_operateByInstruction ? QByteArray("l-s") : QByteArray("l+s")));
|
||||
runCommand({m_operateByInstruction ? "l-t" : "l+t", NoFlags});
|
||||
runCommand({m_operateByInstruction ? "l-s" : "l+s", NoFlags});
|
||||
}
|
||||
|
||||
void CdbEngine::syncVerboseLog(bool verboseLog)
|
||||
@@ -350,7 +350,7 @@ void CdbEngine::syncVerboseLog(bool verboseLog)
|
||||
return;
|
||||
QTC_ASSERT(m_accessible, return);
|
||||
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
|
||||
@@ -474,11 +474,9 @@ void CdbEngine::consoleStubExited()
|
||||
|
||||
void CdbEngine::createFullBacktrace()
|
||||
{
|
||||
DebuggerCommand cmd("~*kp");
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
runCommand({"~*kp", BuiltinCommand, [this](const DebuggerResponse &response) {
|
||||
Internal::openTextEditor(QLatin1String("Backtrace $"), response.data.toLatin1());
|
||||
};
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
}});
|
||||
}
|
||||
|
||||
void CdbEngine::setupEngine()
|
||||
@@ -646,7 +644,7 @@ bool CdbEngine::launchCDB(const DebuggerRunParameters &sp, QString *errorMessage
|
||||
m_hasDebuggee = true;
|
||||
if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
|
||||
m_accessible = true;
|
||||
runCommand(DebuggerCommand(".load " + extensionFileName.toLocal8Bit()));
|
||||
runCommand({".load " + extensionFileName.toLocal8Bit(), NoFlags});
|
||||
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk")
|
||||
notifyEngineSetupOk();
|
||||
}
|
||||
@@ -659,27 +657,25 @@ void CdbEngine::setupInferior()
|
||||
qDebug("setupInferior");
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
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
|
||||
// (attemptBreakpointSynchronization() will be directly called then)
|
||||
attemptBreakpointSynchronization();
|
||||
if (rp.breakOnMain) {
|
||||
const BreakpointParameters bp(BreakpointAtMain);
|
||||
BreakpointModelId id(quint16(-1));
|
||||
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, id, true));
|
||||
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, id, true), BuiltinCommand,
|
||||
[this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); }});
|
||||
}
|
||||
runCommand(DebuggerCommand("sxn 0x4000001f")); // Do not break on WowX86 exceptions.
|
||||
runCommand(DebuggerCommand("sxn ibp")); // Do not break on initial breakpoints.
|
||||
runCommand(DebuggerCommand(".asm source_line")); // Source line in assembly
|
||||
runCommand(DebuggerCommand(m_extensionCommandPrefixBA + "setparameter maxStringLength="
|
||||
runCommand({"sxn 0x4000001f", NoFlags}); // Do not break on WowX86 exceptions.
|
||||
runCommand({"sxn ibp", NoFlags}); // Do not break on initial breakpoints.
|
||||
runCommand({".asm source_line", NoFlags}); // Source line in assembly
|
||||
runCommand({m_extensionCommandPrefixBA + "setparameter maxStringLength="
|
||||
+ action(MaximalStringLength)->value().toByteArray()
|
||||
+ " maxStackDepth="
|
||||
+ action(MaximalStackDepth)->value().toByteArray()));
|
||||
+ action(MaximalStackDepth)->value().toByteArray(), NoFlags});
|
||||
|
||||
DebuggerCommand cmd("pid");
|
||||
cmd.callback = [this](const DebuggerResponse &response) {
|
||||
runCommand({"pid", ExtensionCommand, [this](const DebuggerResponse &response) {
|
||||
// Fails for core dumps.
|
||||
if (response.resultClass == ResultDone)
|
||||
notifyInferiorPid(response.data.data().toULongLong());
|
||||
@@ -692,8 +688,7 @@ void CdbEngine::setupInferior()
|
||||
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupFailed")
|
||||
notifyInferiorSetupFailed();
|
||||
}
|
||||
};
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
}});
|
||||
}
|
||||
|
||||
static QByteArray msvcRunTime(const Abi::OSFlavor flavour)
|
||||
@@ -736,35 +731,25 @@ void CdbEngine::runEngine()
|
||||
|
||||
const QStringList breakEvents = stringListSetting(CdbBreakEvents);
|
||||
foreach (const QString &breakEvent, breakEvents)
|
||||
runCommand(DebuggerCommand(QByteArray("sxe ") + breakEvent.toLatin1()));
|
||||
runCommand({"sxe " + breakEvent.toLatin1(), NoFlags});
|
||||
// Break functions: each function must be fully qualified,
|
||||
// else the debugger will slow down considerably.
|
||||
DebuggerCommand cmd;
|
||||
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
|
||||
const auto cb = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
|
||||
if (boolSetting(CdbBreakOnCrtDbgReport)) {
|
||||
const QByteArray module = msvcRunTime(runParameters().toolChainAbi.osFlavor());
|
||||
const QByteArray debugModule = module + 'D';
|
||||
const QByteArray wideFunc = QByteArray(CdbOptionsPage::crtDbgReport).append('W');
|
||||
cmd.function = breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module);
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
cmd.function = breakAtFunctionCommand(wideFunc, module);
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
cmd.function = breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule);
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
cmd.function = breakAtFunctionCommand(wideFunc, debugModule);
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, module), BuiltinCommand, cb});
|
||||
runCommand({breakAtFunctionCommand(wideFunc, module), BuiltinCommand, cb});
|
||||
runCommand({breakAtFunctionCommand(CdbOptionsPage::crtDbgReport, debugModule), BuiltinCommand, cb});
|
||||
}
|
||||
if (boolSetting(BreakOnWarning)) {
|
||||
cmd.function = "bm /( QtCored4!qWarning"; // 'bm': All overloads.
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
cmd.function = "bm /( Qt5Cored!QMessageLogger::warning";
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"bm /( QtCored4!qWarning", BuiltinCommand}); // 'bm': All overloads.
|
||||
runCommand({"bm /( Qt5Cored!QMessageLogger::warning", BuiltinCommand});
|
||||
}
|
||||
if (boolSetting(BreakOnFatal)) {
|
||||
cmd.function = "bm /( QtCored4!qFatal"; // 'bm': All overloads.
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
cmd.function = "bm /( Qt5Cored!QMessageLogger::fatal";
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"bm /( QtCored4!qFatal", BuiltinCommand}); // 'bm': All overloads.
|
||||
runCommand({"bm /( Qt5Cored!QMessageLogger::fatal", BuiltinCommand});
|
||||
}
|
||||
if (runParameters().startMode == AttachCore) {
|
||||
QTC_ASSERT(!m_coreStopReason.isNull(), return; );
|
||||
@@ -848,10 +833,10 @@ void CdbEngine::shutdownEngine()
|
||||
detachDebugger();
|
||||
// Remote requires a bit more force to quit.
|
||||
if (m_effectiveStartMode == AttachToRemoteServer) {
|
||||
runCommand(DebuggerCommand(m_extensionCommandPrefixBA + "shutdownex"));
|
||||
runCommand(DebuggerCommand("qq"));
|
||||
runCommand({m_extensionCommandPrefixBA + "shutdownex", NoFlags});
|
||||
runCommand({"qq", NoFlags});
|
||||
} else {
|
||||
runCommand(DebuggerCommand("q"));
|
||||
runCommand({"q", NoFlags});
|
||||
}
|
||||
} else {
|
||||
// Remote process. No can do, currently
|
||||
@@ -885,7 +870,7 @@ void CdbEngine::processFinished()
|
||||
|
||||
void CdbEngine::detachDebugger()
|
||||
{
|
||||
runCommand(DebuggerCommand(".detach"));
|
||||
runCommand({".detach", NoFlags});
|
||||
}
|
||||
|
||||
static inline bool isWatchIName(const QByteArray &iname)
|
||||
@@ -913,21 +898,21 @@ void CdbEngine::executeStep()
|
||||
{
|
||||
if (!m_operateByInstruction)
|
||||
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")
|
||||
notifyInferiorRunRequested();
|
||||
}
|
||||
|
||||
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")
|
||||
notifyInferiorRunRequested();
|
||||
}
|
||||
|
||||
void CdbEngine::executeNext()
|
||||
{
|
||||
runCommand(DebuggerCommand(QByteArray("p"))); // Step over -> p
|
||||
runCommand({"p", NoFlags}); // Step over -> p
|
||||
STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorRunRequested")
|
||||
notifyInferiorRunRequested();
|
||||
}
|
||||
@@ -951,7 +936,7 @@ void CdbEngine::continueInferior()
|
||||
|
||||
void CdbEngine::doContinueInferior()
|
||||
{
|
||||
runCommand(DebuggerCommand(QByteArray("g")));
|
||||
runCommand({"g", NoFlags});
|
||||
}
|
||||
|
||||
bool CdbEngine::canInterruptInferior() const
|
||||
@@ -1025,9 +1010,8 @@ void CdbEngine::executeRunToLine(const ContextData &data)
|
||||
bp.lineNumber = data.lineNumber;
|
||||
}
|
||||
|
||||
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true));
|
||||
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), BuiltinCommand,
|
||||
[this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }});
|
||||
continueInferior();
|
||||
}
|
||||
|
||||
@@ -1036,10 +1020,8 @@ void CdbEngine::executeRunToFunction(const QString &functionName)
|
||||
// Add one-shot breakpoint
|
||||
BreakpointParameters bp(BreakpointByFunction);
|
||||
bp.functionName = functionName;
|
||||
|
||||
DebuggerCommand cmd(cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true));
|
||||
cmd.callback = [this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({cdbAddBreakpointCommand(bp, m_sourcePathMappings, BreakpointModelId(), true), BuiltinCommand,
|
||||
[this](const DebuggerResponse &r) { handleBreakInsert(r, BreakpointModelId()); }});
|
||||
continueInferior();
|
||||
}
|
||||
|
||||
@@ -1049,7 +1031,7 @@ void CdbEngine::setRegisterValue(const QByteArray &name, const QString &value)
|
||||
QByteArray cmd;
|
||||
ByteArrayInputStream str(cmd);
|
||||
str << "r " << name << '=' << value;
|
||||
runCommand(DebuggerCommand(cmd));
|
||||
runCommand({cmd, NoFlags});
|
||||
reloadRegisters();
|
||||
}
|
||||
|
||||
@@ -1061,25 +1043,25 @@ void CdbEngine::executeJumpToLine(const ContextData &data)
|
||||
gotoLocation(Location(data.address));
|
||||
} else {
|
||||
// Jump to source line: Resolve source line address and go to that location
|
||||
DebuggerCommand cmd;
|
||||
ByteArrayInputStream str(cmd.function);
|
||||
QByteArray cmd;
|
||||
ByteArrayInputStream str(cmd);
|
||||
str << "? `" << QDir::toNativeSeparators(data.fileName) << ':' << data.lineNumber << '`';
|
||||
cmd.callback = [this, data](const DebuggerResponse &r) { handleJumpToLineAddressResolution(r, data); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({cmd, BuiltinCommand, [this, data](const DebuggerResponse &r) {
|
||||
handleJumpToLineAddressResolution(r, data); }});
|
||||
}
|
||||
}
|
||||
|
||||
void CdbEngine::jumpToAddress(quint64 address)
|
||||
{
|
||||
// Fake a jump to address by setting the PC register.
|
||||
QByteArray registerCmd;
|
||||
ByteArrayInputStream str(registerCmd);
|
||||
QByteArray cmd;
|
||||
ByteArrayInputStream str(cmd);
|
||||
// PC-register depending on 64/32bit.
|
||||
str << "r " << (runParameters().toolChainAbi.wordWidth() == 64 ? "rip" : "eip") << '=';
|
||||
str.setHexPrefix(true);
|
||||
str.setIntegerBase(16);
|
||||
str << address;
|
||||
runCommand(DebuggerCommand(registerCmd));
|
||||
runCommand({cmd, NoFlags});
|
||||
}
|
||||
|
||||
void CdbEngine::handleJumpToLineAddressResolution(const DebuggerResponse &response, const ContextData &context)
|
||||
@@ -1144,7 +1126,7 @@ void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const Q
|
||||
break;
|
||||
}
|
||||
|
||||
runCommand(DebuggerCommand(cmd));
|
||||
runCommand({cmd, NoFlags});
|
||||
// Update all locals in case we change a union or something pointed to
|
||||
// that affects other variables, too.
|
||||
updateLocals();
|
||||
@@ -1168,11 +1150,11 @@ void CdbEngine::handleThreads(const DebuggerResponse &response)
|
||||
void CdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages languages)
|
||||
{
|
||||
if (languages & CppLanguage)
|
||||
runCommand(DebuggerCommand(command.toLocal8Bit()));
|
||||
runCommand({command.toLocal8Bit(), NoFlags});
|
||||
}
|
||||
|
||||
// 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();
|
||||
if (!m_accessible) {
|
||||
@@ -1184,7 +1166,7 @@ void CdbEngine::runCommand(const DebuggerCommand &dbgCmd, int flags)
|
||||
|
||||
QByteArray fullCmd;
|
||||
ByteArrayInputStream str(fullCmd);
|
||||
if (flags & BuiltinCommand) {
|
||||
if (dbgCmd.flags & BuiltinCommand) {
|
||||
// Post a built-in-command producing free-format output with a callback.
|
||||
// In order to catch the output, it is enclosed in 'echo' commands
|
||||
// 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"
|
||||
<< cmd << "\n.echo \"" << m_tokenPrefix << token << ">\"";
|
||||
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,
|
||||
// pass along token for identification in hash.
|
||||
const int token = m_nextCommandToken++;
|
||||
@@ -1331,10 +1313,10 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
|
||||
if (partialUpdate)
|
||||
str << blankSeparator << updateParameters.partialVariable;
|
||||
|
||||
DebuggerCommand cmd("locals");
|
||||
DebuggerCommand cmd("locals", ExtensionCommand);
|
||||
cmd.args = QLatin1String(arguments);
|
||||
cmd.callback = [this, partialUpdate](const DebuggerResponse &r) { handleLocals(r, partialUpdate); };
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void CdbEngine::updateAll()
|
||||
@@ -1349,9 +1331,8 @@ void CdbEngine::selectThread(ThreadId threadId)
|
||||
|
||||
threadsHandler()->setCurrentThread(threadId);
|
||||
|
||||
DebuggerCommand cmd('~' + QByteArray::number(threadId.raw()) + " s");
|
||||
cmd.callback = [this](const DebuggerResponse &) { reloadFullStack(); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({'~' + QByteArray::number(threadId.raw()) + " s", BuiltinCommand,
|
||||
[this](const DebuggerResponse &) { reloadFullStack(); }});
|
||||
}
|
||||
|
||||
// Default address range for showing disassembly.
|
||||
@@ -1401,7 +1382,8 @@ void CdbEngine::postDisassemblerCommand(quint64 address, quint64 endAddress,
|
||||
// Parse: "00000000`77606060 cc int 3"
|
||||
agent->setContents(parseCdbDisassembler(response.data.data()));
|
||||
};
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
cmd.flags = BuiltinCommand;
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
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);
|
||||
if (addresses.isEmpty()) {
|
||||
showMessage(QLatin1String("Resolving symbol: ") + symbol + QLatin1String("..."), LogMisc);
|
||||
DebuggerCommand cmd(QByteArray("x ") + symbol.toLatin1());
|
||||
cmd.callback = [this, symbol, agent](const DebuggerResponse &r) {
|
||||
handleResolveSymbol(r, symbol, agent);
|
||||
};
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"x " + symbol.toLatin1(), BuiltinCommand,
|
||||
[this, symbol, agent](const DebuggerResponse &r) { handleResolveSymbol(r, symbol, agent); }});
|
||||
} else {
|
||||
showMessage(QString::fromLatin1("Using cached addresses for %1.").
|
||||
arg(symbol), LogMisc);
|
||||
showMessage(QString::fromLatin1("Using cached addresses for %1.").arg(symbol), LogMisc);
|
||||
handleResolveSymbolHelper(addresses, agent);
|
||||
}
|
||||
}
|
||||
@@ -1556,7 +1534,7 @@ void CdbEngine::fetchMemory(MemoryAgent *agent, QObject *editor, quint64 addr, q
|
||||
|
||||
void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
|
||||
{
|
||||
DebuggerCommand cmd("memory");
|
||||
DebuggerCommand cmd("memory", ExtensionCommand);
|
||||
QByteArray args;
|
||||
ByteArrayInputStream str(args);
|
||||
str << cookie.address << ' ' << cookie.length;
|
||||
@@ -1570,7 +1548,7 @@ void CdbEngine::postFetchMemory(const MemoryViewCookie &cookie)
|
||||
showMessage(response.data["msg"].toLatin1(), LogWarning);
|
||||
}
|
||||
};
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
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);
|
||||
doInterruptInferiorCustomSpecialStop(qVariantFromValue(cookie));
|
||||
} else {
|
||||
runCommand(DebuggerCommand(cdbWriteMemoryCommand(addr, data)));
|
||||
runCommand({cdbWriteMemoryCommand(addr, data), NoFlags});
|
||||
}
|
||||
}
|
||||
|
||||
void CdbEngine::reloadModules()
|
||||
{
|
||||
DebuggerCommand cmd("modules");
|
||||
cmd.callback = CB(handleModules);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand({"modules", ExtensionCommand, CB(handleModules)});
|
||||
}
|
||||
|
||||
void CdbEngine::loadSymbols(const QString & /* moduleName */)
|
||||
@@ -1607,9 +1583,7 @@ void CdbEngine::requestModuleSymbols(const QString &moduleName)
|
||||
void CdbEngine::reloadRegisters()
|
||||
{
|
||||
QTC_ASSERT(threadsHandler()->currentThreadIndex() >= 0, return);
|
||||
DebuggerCommand cmd("registers");
|
||||
cmd.callback = CB(handleRegistersExt);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand({"registers", ExtensionCommand, CB(handleRegistersExt)});
|
||||
}
|
||||
|
||||
void CdbEngine::reloadSourceFiles()
|
||||
@@ -1620,18 +1594,18 @@ void CdbEngine::reloadFullStack()
|
||||
{
|
||||
if (debug)
|
||||
qDebug("%s", Q_FUNC_INFO);
|
||||
DebuggerCommand cmd("stack");
|
||||
DebuggerCommand cmd("stack", ExtensionCommand);
|
||||
cmd.args = QStringLiteral("unlimited");
|
||||
cmd.callback = CB(handleStackTrace);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void CdbEngine::listBreakpoints()
|
||||
{
|
||||
DebuggerCommand cmd("breakpoints");
|
||||
DebuggerCommand cmd("breakpoints", ExtensionCommand);
|
||||
cmd.args = QStringLiteral("-v");
|
||||
cmd.callback = CB(handleBreakPoints);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void CdbEngine::handleModules(const DebuggerResponse &response)
|
||||
@@ -1845,8 +1819,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
|
||||
if (!conditionalBreakPointTriggered && !parameters.condition.isEmpty()) {
|
||||
*message = msgCheckingConditionalBreakPoint(id, number, parameters.condition,
|
||||
QString::number(threadId));
|
||||
|
||||
DebuggerCommand cmd("expression");
|
||||
DebuggerCommand cmd("expression", ExtensionCommand);
|
||||
QByteArray args = parameters.condition;
|
||||
if (args.contains(' ') && !args.startsWith('"')) {
|
||||
args.prepend('"');
|
||||
@@ -1856,7 +1829,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
|
||||
cmd.callback = [this, id, stopReason](const DebuggerResponse &response) {
|
||||
handleExpression(response, id, stopReason);
|
||||
};
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand(cmd);
|
||||
|
||||
return StopReportLog;
|
||||
}
|
||||
@@ -2004,7 +1977,7 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
|
||||
// Start sequence to get all relevant data.
|
||||
if (stopFlags & StopInArtificialThread) {
|
||||
showMessage(tr("Switching to main thread..."), LogMisc);
|
||||
runCommand(DebuggerCommand("~0 s"));
|
||||
runCommand({"~0 s", NoFlags});
|
||||
forcedThreadId = ThreadId(0);
|
||||
// Re-fetch stack again.
|
||||
reloadFullStack();
|
||||
@@ -2019,9 +1992,8 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
|
||||
executeStepOut();
|
||||
return;
|
||||
case ParseStackWow64:
|
||||
DebuggerCommand cmd("lm m wow64");
|
||||
cmd.callback = [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"lm m wow64", BuiltinCommand,
|
||||
[this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }});
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -2112,9 +2084,8 @@ void CdbEngine::handleCheckWow64(const DebuggerResponse &response, const GdbMi &
|
||||
// start end module name
|
||||
// 00000000`77490000 00000000`774d5000 wow64 (deferred)
|
||||
if (response.data.data().contains("wow64")) {
|
||||
DebuggerCommand cmd("k");
|
||||
cmd.callback = [this, stack](const DebuggerResponse &r) { ensureUsing32BitStackInWow64(r, stack); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"k", BuiltinCommand,
|
||||
[this, stack](const DebuggerResponse &r) { ensureUsing32BitStackInWow64(r, stack); }});
|
||||
return;
|
||||
}
|
||||
m_wow64State = noWow64Stack;
|
||||
@@ -2134,9 +2105,7 @@ void CdbEngine::ensureUsing32BitStackInWow64(const DebuggerResponse &response, c
|
||||
return;
|
||||
} else if (line.startsWith("Child-SP")) {
|
||||
m_wow64State = wow64Stack64Bit;
|
||||
DebuggerCommand cmd("!wow64exts.sw");
|
||||
cmd.callback = CB(handleSwitchWow64Stack);
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"!wow64exts.sw", BuiltinCommand, CB(handleSwitchWow64Stack)});
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2153,9 +2122,7 @@ void CdbEngine::handleSwitchWow64Stack(const DebuggerResponse &response)
|
||||
else
|
||||
m_wow64State = noWow64Stack;
|
||||
// reload threads and the stack after switching the mode
|
||||
DebuggerCommand cmd("threads");
|
||||
cmd.callback = CB(handleThreads);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand({"threads", ExtensionCommand, CB(handleThreads)});
|
||||
}
|
||||
|
||||
void CdbEngine::handleSessionAccessible(unsigned long cdbExState)
|
||||
@@ -2670,6 +2637,7 @@ void CdbEngine::attemptBreakpointSynchronization()
|
||||
foreach (Breakpoint bp, bps) {
|
||||
BreakpointParameters parameters = bp.parameters();
|
||||
BreakpointModelId id = bp.id();
|
||||
const auto handleBreakInsertCB = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
|
||||
BreakpointResponse response;
|
||||
response.fromParameters(parameters);
|
||||
response.id = BreakpointResponseId(id.majorPart(), id.minorPart());
|
||||
@@ -2688,16 +2656,14 @@ void CdbEngine::attemptBreakpointSynchronization()
|
||||
lineCorrection.reset(new BreakpointCorrectionContext(Internal::cppCodeModelSnapshot(),
|
||||
CppTools::CppModelManager::instance()->workingCopy()));
|
||||
response.lineNumber = lineCorrection->fixLineNumber(parameters.fileName, parameters.lineNumber);
|
||||
DebuggerCommand cmd(cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false));
|
||||
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
QByteArray cmd = cdbAddBreakpointCommand(response, m_sourcePathMappings, id, false);
|
||||
runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
|
||||
} else {
|
||||
DebuggerCommand cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
|
||||
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
QByteArray cmd = cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false);
|
||||
runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
|
||||
}
|
||||
if (!parameters.enabled)
|
||||
runCommand(DebuggerCommand("bd " + QByteArray::number(breakPointIdToCdbId(id))));
|
||||
runCommand({"bd " + QByteArray::number(breakPointIdToCdbId(id)), NoFlags});
|
||||
bp.notifyBreakpointInsertProceeding();
|
||||
bp.notifyBreakpointInsertOk();
|
||||
m_pendingBreakpointMap.insert(id, response);
|
||||
@@ -2716,24 +2682,23 @@ void CdbEngine::attemptBreakpointSynchronization()
|
||||
qPrintable(parameters.toString()));
|
||||
if (parameters.enabled != bp.response().enabled) {
|
||||
// Change enabled/disabled breakpoints without triggering update.
|
||||
runCommand(DebuggerCommand((parameters.enabled ? "be " : "bd ")
|
||||
+ QByteArray::number(breakPointIdToCdbId(id))));
|
||||
runCommand({(parameters.enabled ? "be " : "bd ")
|
||||
+ QByteArray::number(breakPointIdToCdbId(id)), NoFlags});
|
||||
response.pending = false;
|
||||
response.enabled = parameters.enabled;
|
||||
bp.setResponse(response);
|
||||
} else {
|
||||
// Delete and re-add, triggering update
|
||||
addedChanged = true;
|
||||
runCommand(DebuggerCommand(cdbClearBreakpointCommand(id)));
|
||||
DebuggerCommand cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
|
||||
cmd.callback = [this, id](const DebuggerResponse &r) { handleBreakInsert(r, id); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({cdbClearBreakpointCommand(id), NoFlags});
|
||||
QByteArray cmd(cdbAddBreakpointCommand(parameters, m_sourcePathMappings, id, false));
|
||||
runCommand({cmd, BuiltinCommand, handleBreakInsertCB});
|
||||
m_pendingBreakpointMap.insert(id, response);
|
||||
}
|
||||
bp.notifyBreakpointChangeOk();
|
||||
break;
|
||||
case BreakpointRemoveRequested:
|
||||
runCommand(DebuggerCommand(cdbClearBreakpointCommand(id)));
|
||||
runCommand({cdbClearBreakpointCommand(id), NoFlags});
|
||||
bp.notifyBreakpointRemoveProceeding();
|
||||
bp.notifyBreakpointRemoveOk();
|
||||
m_pendingBreakpointMap.remove(id);
|
||||
@@ -2745,7 +2710,7 @@ void CdbEngine::attemptBreakpointSynchronization()
|
||||
foreach (BreakpointModelId id, m_insertSubBreakpointMap.keys()) {
|
||||
addedChanged = true;
|
||||
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_pendingSubBreakpointMap.insert(id, response);
|
||||
}
|
||||
@@ -2873,9 +2838,7 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
|
||||
|
||||
void CdbEngine::loadAdditionalQmlStack()
|
||||
{
|
||||
DebuggerCommand cmd("qmlstack");
|
||||
cmd.callback = CB(handleAdditionalQmlStack);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand({"qmlstack", ExtensionCommand, CB(handleAdditionalQmlStack)});
|
||||
}
|
||||
|
||||
void CdbEngine::handleAdditionalQmlStack(const DebuggerResponse &response)
|
||||
@@ -2920,9 +2883,8 @@ void CdbEngine::handleStackTrace(const DebuggerResponse &response)
|
||||
GdbMi stack = response.data;
|
||||
if (response.resultClass == ResultDone) {
|
||||
if (parseStackTrace(stack, false) == ParseStackWow64) {
|
||||
DebuggerCommand cmd("lm m wow64");
|
||||
cmd.callback = [this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); };
|
||||
runCommand(cmd, BuiltinCommand);
|
||||
runCommand({"lm m wow64", BuiltinCommand,
|
||||
[this, stack](const DebuggerResponse &r) { handleCheckWow64(r, stack); }});
|
||||
}
|
||||
} else {
|
||||
showMessage(stack["msg"].toLatin1(), LogError);
|
||||
@@ -3096,17 +3058,16 @@ void CdbEngine::watchPoint(const QPoint &p)
|
||||
|
||||
void CdbEngine::postWidgetAtCommand()
|
||||
{
|
||||
DebuggerCommand cmd("widgetat");
|
||||
DebuggerCommand cmd("widgetat", ExtensionCommand);
|
||||
cmd.args = QString::fromLatin1("%1 %2").arg(m_watchPointX, m_watchPointY);
|
||||
cmd.callback = CB(handleWidgetAt);
|
||||
runCommand(cmd, ExtensionCommand);
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
void CdbEngine::handleCustomSpecialStop(const QVariant &v)
|
||||
{
|
||||
if (v.canConvert<MemoryChangeCookie>()) {
|
||||
const MemoryChangeCookie changeData = qvariant_cast<MemoryChangeCookie>(v);
|
||||
runCommand(DebuggerCommand(cdbWriteMemoryCommand(changeData.address, changeData.data)));
|
||||
runCommand({cdbWriteMemoryCommand(changeData.address, changeData.data), NoFlags});
|
||||
return;
|
||||
}
|
||||
if (v.canConvert<MemoryViewCookie>()) {
|
||||
|
||||
@@ -127,7 +127,7 @@ private slots:
|
||||
void readyReadStandardError();
|
||||
void processError();
|
||||
void processFinished();
|
||||
void runCommand(const DebuggerCommand &cmd, int flags = 0);
|
||||
void runCommand(const DebuggerCommand &cmd) override;
|
||||
void operateByInstructionTriggered(bool);
|
||||
void verboseLogTriggered(bool);
|
||||
|
||||
@@ -164,7 +164,7 @@ private:
|
||||
ParseStackWow64 = 3 // Hit on a frame with 32bit emulation, switch debugger to 32 bit mode
|
||||
};
|
||||
enum CommandFlags {
|
||||
NoCallBack = 0,
|
||||
NoFlags = 0,
|
||||
BuiltinCommand,
|
||||
ExtensionCommand,
|
||||
};
|
||||
|
||||
@@ -102,10 +102,6 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
|
||||
checkBoxUseToolTipsInMainEditor = new QCheckBox(behaviorBox);
|
||||
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 "
|
||||
"will automatically open views associated with the current location.") + QLatin1Char('\n');
|
||||
checkBoxCloseSourceBuffersOnExit = new QCheckBox(behaviorBox);
|
||||
@@ -174,11 +170,10 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
|
||||
gridLayout->addLayout(horizontalLayout, 7, 0, 1, 2);
|
||||
|
||||
gridLayout->addWidget(checkBoxFontSizeFollowsEditor, 0, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxListSourceFiles, 1, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxSwitchModeOnExit, 2, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxShowQmlObjectTree, 3, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxKeepEditorStationaryWhileStepping, 4, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxRegisterForPostMortem, 5, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxSwitchModeOnExit, 1, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxShowQmlObjectTree, 2, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxKeepEditorStationaryWhileStepping, 3, 1, 1, 1);
|
||||
gridLayout->addWidget(checkBoxRegisterForPostMortem, 4, 1, 1, 1);
|
||||
|
||||
QVBoxLayout *verticalLayout = new QVBoxLayout(this);
|
||||
verticalLayout->addWidget(behaviorBox);
|
||||
@@ -187,8 +182,6 @@ CommonOptionsPageWidget::CommonOptionsPageWidget
|
||||
|
||||
m_group->clear();
|
||||
|
||||
m_group->insert(action(ListSourceFiles),
|
||||
checkBoxListSourceFiles);
|
||||
m_group->insert(action(UseAlternatingRowColors),
|
||||
checkBoxUseAlternatingRowColors);
|
||||
m_group->insert(action(UseToolTipsInMainEditor),
|
||||
|
||||
@@ -556,13 +556,6 @@ DebuggerSettings::DebuggerSettings()
|
||||
item->setCheckable(true);
|
||||
item->setDefaultValue(false);
|
||||
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->setSettingsKey(debugModeGroup, QLatin1String("SkipKnownFrames"));
|
||||
|
||||
@@ -162,9 +162,6 @@ enum DebuggerActionCode
|
||||
MaximalStringLength,
|
||||
DisplayStringLimit,
|
||||
|
||||
// Source List
|
||||
ListSourceFiles,
|
||||
|
||||
// Running
|
||||
SkipKnownFrames,
|
||||
EnableReverseDebugging,
|
||||
|
||||
@@ -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 *)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "debugger_global.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggerprotocol.h"
|
||||
#include "debuggerstartparameters.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/idevice.h>
|
||||
@@ -61,7 +62,6 @@ namespace Internal {
|
||||
class DebuggerEnginePrivate;
|
||||
class DebuggerPluginPrivate;
|
||||
class DisassemblerAgent;
|
||||
class GdbMi;
|
||||
class MemoryAgent;
|
||||
class WatchData;
|
||||
class WatchItem;
|
||||
@@ -98,7 +98,6 @@ public:
|
||||
QString coreFile;
|
||||
QString overrideStartScript; // Used in attach to core and remote debugging
|
||||
QString startMessage; // First status message shown.
|
||||
QMap<QString, QString> sourcePathMap;
|
||||
QString debugInfoLocation; // Gdb "set-debug-file-directory".
|
||||
QStringList debugSourceLocation; // Gdb "directory"
|
||||
QString serverStartScript;
|
||||
@@ -217,6 +216,7 @@ public:
|
||||
MemoryView = 0x4 //!< Open a separate view (using the pos-parameter).
|
||||
};
|
||||
|
||||
virtual void runCommand(const DebuggerCommand &cmd);
|
||||
virtual void openMemoryView(const MemoryViewSetupData &data);
|
||||
virtual void fetchMemory(Internal::MemoryAgent *, QObject *,
|
||||
quint64 addr, quint64 length);
|
||||
|
||||
@@ -52,9 +52,10 @@ public:
|
||||
typedef std::function<void(const DebuggerResponse &)> Callback;
|
||||
|
||||
DebuggerCommand() {}
|
||||
DebuggerCommand(const char *f, int fl = 0) : function(f), flags(fl) {}
|
||||
DebuggerCommand(const QByteArray &f, int fl = 0) : function(f), flags(fl) {}
|
||||
DebuggerCommand(const char *f, const QJsonValue &a, int fl = 0) : function(f), args(a), flags(fl) {}
|
||||
DebuggerCommand(const QByteArray &f) : function(f), flags(0) {}
|
||||
DebuggerCommand(const QByteArray &f, const QJsonValue &a) : function(f), args(a), flags(0) {}
|
||||
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 *name, int value);
|
||||
|
||||
@@ -95,6 +95,9 @@ public:
|
||||
QSsh::SshConnectionParameters connParams;
|
||||
bool remoteSetupNeeded = false;
|
||||
|
||||
// Used by Mer plugin (3rd party)
|
||||
QMap<QString, QString> sourcePathMap;
|
||||
|
||||
// Used by baremetal plugin
|
||||
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
|
||||
|
||||
@@ -75,9 +75,8 @@ void GdbAttachEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
const qint64 pid = runParameters().attachPID;
|
||||
DebuggerCommand cmd("attach " + QByteArray::number(pid));
|
||||
cmd.callback = [this](const DebuggerResponse &r) { handleAttach(r); };
|
||||
runCommand(cmd);
|
||||
runCommand({"attach " + QByteArray::number(pid), NoFlags,
|
||||
[this](const DebuggerResponse &r) { handleAttach(r); }});
|
||||
showStatusMessage(tr("Attached to process %1.").arg(inferiorPid()));
|
||||
}
|
||||
|
||||
|
||||
@@ -212,9 +212,8 @@ void GdbCoreEngine::setupInferior()
|
||||
// Do that first, otherwise no symbols are loaded.
|
||||
QFileInfo fi(m_executable);
|
||||
QByteArray path = fi.absoluteFilePath().toLocal8Bit();
|
||||
DebuggerCommand cmd("-file-exec-and-symbols \"" + path + '"');
|
||||
cmd.callback = CB(handleFileExecAndSymbols);
|
||||
runCommand(cmd);
|
||||
runCommand({"-file-exec-and-symbols \"" + path + '"', NoFlags,
|
||||
CB(handleFileExecAndSymbols)});
|
||||
}
|
||||
|
||||
void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
|
||||
@@ -237,9 +236,8 @@ void GdbCoreEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
|
||||
void GdbCoreEngine::runEngine()
|
||||
{
|
||||
CHECK_STATE(EngineRunRequested);
|
||||
DebuggerCommand cmd("target core " + coreFileName().toLocal8Bit());
|
||||
cmd.callback = CB(handleTargetCore);
|
||||
runCommand(cmd);
|
||||
runCommand({"target core " + coreFileName().toLocal8Bit(), NoFlags,
|
||||
CB(handleTargetCore)});
|
||||
}
|
||||
|
||||
void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
|
||||
@@ -252,7 +250,7 @@ void GdbCoreEngine::handleTargetCore(const DebuggerResponse &response)
|
||||
// symbols yet. Load them in order of importance.
|
||||
reloadStack();
|
||||
reloadModulesInternal();
|
||||
runCommand("p 5", CB(handleRoundTrip));
|
||||
runCommand({"p 5", NoFlags, CB(handleRoundTrip)});
|
||||
return;
|
||||
}
|
||||
showStatusMessage(tr("Attach to core \"%1\" failed:").arg(runParameters().coreFile)
|
||||
|
||||
@@ -735,7 +735,6 @@ void GdbEngine::handleAsyncOutput(const QByteArray &asyncClass, const GdbMi &res
|
||||
foreach (const GdbMi &bkpt, res.children()) {
|
||||
const QByteArray nr = bkpt["number"].data();
|
||||
BreakpointResponseId rid(nr);
|
||||
if (!isHiddenBreakpoint(rid)) {
|
||||
if (nr.contains('.')) {
|
||||
// A sub-breakpoint.
|
||||
BreakpointResponse sub;
|
||||
@@ -751,7 +750,6 @@ void GdbEngine::handleAsyncOutput(const QByteArray &asyncClass, const GdbMi &res
|
||||
bp.setResponse(br);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (asyncClass == "breakpoint-created") {
|
||||
// "{bkpt={number="1",type="breakpoint",disp="del",enabled="y",
|
||||
// addr="<PENDING>",pending="main",times="0",
|
||||
@@ -851,7 +849,7 @@ void GdbEngine::interruptInferior()
|
||||
return;
|
||||
|
||||
if (usesExecInterrupt()) {
|
||||
runCommand("-exec-interrupt");
|
||||
runCommand({"-exec-interrupt", NoFlags});
|
||||
} else {
|
||||
showStatusMessage(tr("Stop requested..."), 5000);
|
||||
showMessage(_("TRYING TO INTERRUPT INFERIOR"));
|
||||
@@ -898,20 +896,6 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
|
||||
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)
|
||||
{
|
||||
const int token = ++currentToken();
|
||||
@@ -1227,7 +1211,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages
|
||||
if (!(languages & CppLanguage))
|
||||
return;
|
||||
QTC_CHECK(acceptsDebuggerCommands());
|
||||
runCommand(command.toLatin1());
|
||||
runCommand({command.toLatin1(), NoFlags});
|
||||
}
|
||||
|
||||
// This is triggered when switching snapshots.
|
||||
@@ -1240,7 +1224,7 @@ void GdbEngine::updateAll()
|
||||
cmd.callback = [this](const DebuggerResponse &r) { handleStackListFrames(r, false); };
|
||||
runCommand(cmd);
|
||||
stackHandler()->setCurrentIndex(0);
|
||||
runCommand("-thread-info", CB(handleThreadInfo));
|
||||
runCommand({"-thread-info", NoFlags, CB(handleThreadInfo)});
|
||||
reloadRegisters();
|
||||
updateLocals();
|
||||
}
|
||||
@@ -1386,9 +1370,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
bool gotoHandleStop1 = true;
|
||||
if (!m_fullStartDone) {
|
||||
m_fullStartDone = true;
|
||||
DebuggerCommand cmd("sharedlibrary .*");
|
||||
cmd.callback = [this, data](const DebuggerResponse &) { handleStop1(data); };
|
||||
runCommand(cmd);
|
||||
runCommand({"sharedlibrary .*", NoFlags,
|
||||
[this, data](const DebuggerResponse &) { handleStop1(data); }});
|
||||
gotoHandleStop1 = false;
|
||||
}
|
||||
|
||||
@@ -1413,7 +1396,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
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.
|
||||
Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid);
|
||||
const BreakpointResponse &response = bp.response();
|
||||
@@ -1430,7 +1413,6 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
// Quickly set the location marker.
|
||||
if (lineNumber && !boolSetting(OperateByInstruction)
|
||||
&& QFileInfo::exists(fullName)
|
||||
&& !isQFatalBreakpoint(rid)
|
||||
&& function != "qt_v4TriggeredBreakpointHook"
|
||||
&& function != "qt_qmlDebugMessageAvailable"
|
||||
&& language != "js")
|
||||
@@ -1544,9 +1526,9 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
||||
if (!m_systemDumpersLoaded) {
|
||||
m_systemDumpersLoaded = true;
|
||||
if (m_gdbVersion >= 70400 && boolSetting(LoadGdbDumpers))
|
||||
runCommand("importPlainDumpers on");
|
||||
runCommand({"importPlainDumpers on", NoFlags});
|
||||
else
|
||||
runCommand("importPlainDumpers off");
|
||||
runCommand({"importPlainDumpers off", NoFlags});
|
||||
}
|
||||
|
||||
handleStop2(data);
|
||||
@@ -1701,12 +1683,12 @@ void GdbEngine::handleShowVersion(const DebuggerResponse &response)
|
||||
.arg(gdbBuildVersion).arg(_(isMacGdb ? " (APPLE)" : "")));
|
||||
|
||||
if (usesExecInterrupt())
|
||||
runCommand("set target-async on", ConsoleCommand);
|
||||
runCommand({"set target-async on", ConsoleCommand});
|
||||
else
|
||||
runCommand("set target-async off", ConsoleCommand);
|
||||
runCommand({"set target-async off", ConsoleCommand});
|
||||
|
||||
if (runParameters().multiProcess)
|
||||
runCommand("set detach-on-fork off", ConsoleCommand);
|
||||
runCommand({"set detach-on-fork off", ConsoleCommand});
|
||||
|
||||
//runCommand("set build-id-verbose 2", ConsoleCommand);
|
||||
}
|
||||
@@ -1892,8 +1874,8 @@ void GdbEngine::notifyAdapterShutdownOk()
|
||||
switch (m_gdbProc.state()) {
|
||||
case QProcess::Running: {
|
||||
if (runParameters().closeMode == KillAndExitMonitorAtClose)
|
||||
runCommand("monitor exit");
|
||||
runCommand("exitGdb", CB(handleGdbExit), ExitRequest|PythonCommand);
|
||||
runCommand({"monitor exit", NoFlags});
|
||||
runCommand({"exitGdb", ExitRequest|PythonCommand, CB(handleGdbExit)});
|
||||
break;
|
||||
}
|
||||
case QProcess::NotRunning:
|
||||
@@ -2093,20 +2075,19 @@ void GdbEngine::executeStepI()
|
||||
void GdbEngine::executeStepOut()
|
||||
{
|
||||
CHECK_STATE(InferiorStopOk);
|
||||
runCommand("-stack-select-frame 0", Discardable);
|
||||
runCommand({"-stack-select-frame 0", Discardable});
|
||||
setTokenBarrier();
|
||||
notifyInferiorRunRequested();
|
||||
showStatusMessage(tr("Finish function requested..."), 5000);
|
||||
if (isNativeMixedActiveFrame()) {
|
||||
DebuggerCommand cmd("executeStepOut", RunRequest|PythonCommand);
|
||||
runCommand(cmd);
|
||||
runCommand({"executeStepOut", RunRequest|PythonCommand});
|
||||
} else {
|
||||
runCommand("-exec-finish", CB(handleExecuteContinue), RunRequest);
|
||||
runCommand({"-exec-finish", RunRequest, CB(handleExecuteContinue)});
|
||||
// -exec-finish in 'main' results (correctly) in
|
||||
// 40^error,msg="\"finish\" not meaningful in the outermost frame."
|
||||
// However, this message does not seem to get flushed before
|
||||
// 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
|
||||
loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':'
|
||||
+ QByteArray::number(data.lineNumber);
|
||||
runCommand("tbreak " + loc);
|
||||
runCommand({"tbreak " + loc, NoFlags});
|
||||
|
||||
DebuggerCommand cmd("continue", RunRequest);
|
||||
cmd.callback = CB(handleExecuteRunToLine);
|
||||
runCommand(cmd);
|
||||
runCommand({"continue", RunRequest, CB(handleExecuteRunToLine)});
|
||||
#else
|
||||
// Seems to jump to unpredicatable places. Observed in the manual
|
||||
// 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);
|
||||
setTokenBarrier();
|
||||
runCommand("-break-insert -t " + functionName.toLatin1());
|
||||
runCommand({"-break-insert -t " + functionName.toLatin1(), NoFlags});
|
||||
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
|
||||
continueInferiorInternal();
|
||||
}
|
||||
@@ -2218,12 +2197,10 @@ void GdbEngine::executeJumpToLine(const ContextData &data)
|
||||
else
|
||||
loc = '"' + breakLocation(data.fileName).toLocal8Bit() + '"' + ':'
|
||||
+ QByteArray::number(data.lineNumber);
|
||||
runCommand("tbreak " + loc);
|
||||
runCommand({"tbreak " + loc, NoFlags});
|
||||
notifyInferiorRunRequested();
|
||||
|
||||
DebuggerCommand cmd("jump" + loc, RunRequest);
|
||||
cmd.callback = CB(handleExecuteJumpToLine);
|
||||
runCommand(cmd);
|
||||
runCommand({"jump" + loc, RunRequest, CB(handleExecuteJumpToLine)});
|
||||
// will produce something like
|
||||
// &"jump \"/home/apoenitz/dev/work/test1/test1.cpp\":242"
|
||||
// ~"Continuing at 0x4058f3."
|
||||
@@ -2238,7 +2215,7 @@ void GdbEngine::executeReturn()
|
||||
setTokenBarrier();
|
||||
notifyInferiorRunRequested();
|
||||
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)
|
||||
@@ -2572,10 +2549,6 @@ void GdbEngine::handleBreakInsert1(const DebuggerResponse &response, Breakpoint
|
||||
// the "main" entry. Use the "main" entry to retrieve the
|
||||
// already known data from the BreakpointManager, and then
|
||||
// iterate over all items to update main- and sub-data.
|
||||
const GdbMi mainbkpt = response.data["bkpt"];
|
||||
const QByteArray mainnr = mainbkpt["number"].data();
|
||||
const BreakpointResponseId mainrid(mainnr);
|
||||
if (!isHiddenBreakpoint(mainrid)) {
|
||||
foreach (const GdbMi &bkpt, response.data.children())
|
||||
handleBkpt(bkpt, bp);
|
||||
if (bp.needsChange()) {
|
||||
@@ -2584,7 +2557,6 @@ void GdbEngine::handleBreakInsert1(const DebuggerResponse &response, Breakpoint
|
||||
} else {
|
||||
bp.notifyBreakpointInsertOk();
|
||||
}
|
||||
}
|
||||
} else if (response.data["msg"].data().contains("Unknown option")) {
|
||||
// Older version of gdb don't know the -a option to set tracepoints
|
||||
// ^error,msg="mi_cmd_break_insert: Unknown option ``a''"
|
||||
@@ -2891,7 +2863,7 @@ void GdbEngine::removeBreakpoint(Breakpoint bp)
|
||||
void GdbEngine::loadSymbols(const QString &modulePath)
|
||||
{
|
||||
// FIXME: gdb does not understand quoted names here (tested with 6.8)
|
||||
runCommand("sharedlibrary " + dotEscape(modulePath.toLocal8Bit()));
|
||||
runCommand({"sharedlibrary " + dotEscape(modulePath.toLocal8Bit()), NoFlags});
|
||||
reloadModulesInternal();
|
||||
reloadStack();
|
||||
updateLocals();
|
||||
@@ -2899,7 +2871,7 @@ void GdbEngine::loadSymbols(const QString &modulePath)
|
||||
|
||||
void GdbEngine::loadAllSymbols()
|
||||
{
|
||||
runCommand("sharedlibrary .*");
|
||||
runCommand({"sharedlibrary .*", NoFlags});
|
||||
reloadModulesInternal();
|
||||
reloadStack();
|
||||
updateLocals();
|
||||
@@ -2915,8 +2887,8 @@ void GdbEngine::loadSymbolsForStack()
|
||||
foreach (const Module &module, modules) {
|
||||
if (module.startAddress <= frame.address
|
||||
&& frame.address < module.endAddress) {
|
||||
runCommand("sharedlibrary "
|
||||
+ dotEscape(module.modulePath.toLocal8Bit()));
|
||||
runCommand({"sharedlibrary " + dotEscape(module.modulePath.toLocal8Bit()),
|
||||
NoFlags});
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
@@ -3059,7 +3031,7 @@ void GdbEngine::reloadModules()
|
||||
|
||||
void GdbEngine::reloadModulesInternal()
|
||||
{
|
||||
runCommand("info shared", CB(handleModulesList), NeedsStop);
|
||||
runCommand({"info shared", NeedsStop, CB(handleModulesList)});
|
||||
}
|
||||
|
||||
static QString nameFromPath(const QString &path)
|
||||
@@ -3246,10 +3218,9 @@ void GdbEngine::loadAdditionalQmlStack()
|
||||
return;
|
||||
}
|
||||
// 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"
|
||||
+ QByteArray::number(contextAddress, 16) + ")\"";
|
||||
cmd.callback = CB(handleQmlStackTrace);
|
||||
runCommand(cmd);
|
||||
runCommand({"-data-evaluate-expression \"qt_v4StackTrace((QV4::ExecutionContext *)0x"
|
||||
+ QByteArray::number(contextAddress, 16) + ")\"",
|
||||
NoFlags, CB(handleQmlStackTrace)});
|
||||
};
|
||||
runCommand(cmd);
|
||||
}
|
||||
@@ -3345,8 +3316,7 @@ void GdbEngine::activateFrame(int frameIndex)
|
||||
// after a response to this -stack-select-frame here.
|
||||
//if (!m_currentThread.isEmpty())
|
||||
// cmd += " --thread " + m_currentThread;
|
||||
DebuggerCommand cmd("-stack-select-frame " + QByteArray::number(frameIndex), Discardable);
|
||||
runCommand(cmd);
|
||||
runCommand({"-stack-select-frame " + QByteArray::number(frameIndex), Discardable});
|
||||
}
|
||||
|
||||
updateLocals();
|
||||
@@ -3366,14 +3336,14 @@ void GdbEngine::handleThreadInfo(const DebuggerResponse &response)
|
||||
}
|
||||
updateViews(); // Adjust Threads combobox.
|
||||
if (boolSetting(ShowThreadNames)) {
|
||||
runCommand("threadnames " + action(MaximalStackDepth)->value().toByteArray(),
|
||||
CB(handleThreadNames), Discardable);
|
||||
runCommand({"threadnames " + action(MaximalStackDepth)->value().toByteArray(),
|
||||
Discardable, CB(handleThreadNames)});
|
||||
}
|
||||
reloadStack(); // Will trigger register reload.
|
||||
} else {
|
||||
// Fall back for older versions: Try to get at least a list
|
||||
// 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) {
|
||||
// The MI version does not give register size.
|
||||
// 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;
|
||||
}
|
||||
// Can cause i386-linux-nat.c:571: internal-error: Got request
|
||||
// for bad register number 41.\nA problem internal to GDB has been detected.
|
||||
runCommand("-data-list-register-values r",
|
||||
CB(handleRegisterListValues), Discardable);
|
||||
runCommand({"-data-list-register-values r", Discardable,
|
||||
CB(handleRegisterListValues)});
|
||||
} 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;
|
||||
if (name.startsWith("xmm"))
|
||||
fullName += ".uint128";
|
||||
runCommand("set $" + fullName + "=" + value.toLatin1());
|
||||
runCommand({"set $" + fullName + "=" + value.toLatin1(), NoFlags});
|
||||
reloadRegisters();
|
||||
}
|
||||
|
||||
@@ -3684,9 +3656,8 @@ void GdbEngine::watchPoint(const QPoint &pnt)
|
||||
{
|
||||
QByteArray x = QByteArray::number(pnt.x());
|
||||
QByteArray y = QByteArray::number(pnt.y());
|
||||
runCommand("print " + qtNamespace() + "QApplication::widgetAt("
|
||||
+ x + ',' + y + ')',
|
||||
CB(handleWatchPoint), NeedsStop);
|
||||
runCommand({"print " + qtNamespace() + "QApplication::widgetAt(" + x + ',' + y + ')',
|
||||
NeedsStop, CB(handleWatchPoint)});
|
||||
}
|
||||
|
||||
void GdbEngine::handleWatchPoint(const DebuggerResponse &response)
|
||||
@@ -3822,9 +3793,9 @@ public:
|
||||
void GdbEngine::fetchDisassembler(DisassemblerAgent *agent)
|
||||
{
|
||||
if (boolSetting(IntelFlavor))
|
||||
runCommand("set disassembly-flavor intel");
|
||||
runCommand({"set disassembly-flavor intel"});
|
||||
else
|
||||
runCommand("set disassembly-flavor att");
|
||||
runCommand({"set disassembly-flavor att"});
|
||||
|
||||
fetchDisassemblerByCliPointMixed(agent);
|
||||
}
|
||||
@@ -4025,9 +3996,9 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
}
|
||||
|
||||
showMessage(_("GDB STARTED, INITIALIZING IT"));
|
||||
runCommand("show version", CB(handleShowVersion));
|
||||
runCommand({"show version", NoFlags, CB(handleShowVersion)});
|
||||
//runCommand("-list-features", CB(handleListFeatures));
|
||||
runCommand("show debug-file-directory",CB(handleDebugInfoLocation));
|
||||
runCommand({"show debug-file-directory", NoFlags, CB(handleDebugInfoLocation)});
|
||||
|
||||
//runCommand("-enable-timings");
|
||||
//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 hook-call\nprint 6\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 exec-done-display 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):
|
||||
//runCommand("set print inferior-events 1");
|
||||
|
||||
runCommand("set breakpoint pending on");
|
||||
runCommand("set print elements 10000");
|
||||
runCommand({"set breakpoint pending on"});
|
||||
runCommand({"set print elements 10000"});
|
||||
|
||||
// Produces a few messages during symtab loading
|
||||
//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
|
||||
// when Custom DebuggingHelper crash (which happen regularly when accessing
|
||||
// uninitialized variables).
|
||||
runCommand("handle SIGSEGV nopass stop print");
|
||||
runCommand({"handle SIGSEGV nopass stop print"});
|
||||
|
||||
runCommand("set unwindonsignal on");
|
||||
runCommand("set width 0");
|
||||
runCommand("set height 0");
|
||||
runCommand({"set unwindonsignal on"});
|
||||
runCommand({"set width 0"});
|
||||
runCommand({"set height 0"});
|
||||
|
||||
// FIXME: Provide proper Gui settings for these:
|
||||
//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();
|
||||
it != cend;
|
||||
++it) {
|
||||
runCommand("set substitute-path " + it.key().toLocal8Bit()
|
||||
+ " " + it.value().toLocal8Bit());
|
||||
runCommand({"set substitute-path " + it.key().toLocal8Bit()
|
||||
+ " " + it.value().toLocal8Bit(), NoFlags});
|
||||
}
|
||||
|
||||
// Spaces just will not work.
|
||||
foreach (const QString &src, rp.debugSourceLocation) {
|
||||
if (QDir(src).exists())
|
||||
runCommand("directory " + src.toLocal8Bit());
|
||||
runCommand({"directory " + src.toLocal8Bit(), NoFlags});
|
||||
else
|
||||
showMessage(_("# directory does not exist: ") + src, LogInput);
|
||||
}
|
||||
|
||||
const QByteArray sysroot = rp.sysRoot.toLocal8Bit();
|
||||
if (!sysroot.isEmpty()) {
|
||||
runCommand("set sysroot " + sysroot);
|
||||
runCommand({"set sysroot " + sysroot, NoFlags});
|
||||
// sysroot is not enough to correctly locate the sources, so explicitly
|
||||
// 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();
|
||||
//if (!ba.isEmpty())
|
||||
// runCommand("set solib-search-path " + ba);
|
||||
if (attemptQuickStart()) {
|
||||
runCommand("set auto-solib-add off", ConsoleCommand);
|
||||
runCommand({"set auto-solib-add off", ConsoleCommand});
|
||||
} else {
|
||||
m_fullStartDone = true;
|
||||
runCommand("set auto-solib-add on", ConsoleCommand);
|
||||
runCommand({"set auto-solib-add on", ConsoleCommand});
|
||||
}
|
||||
|
||||
if (boolSetting(MultiInferior)) {
|
||||
//runCommand("set follow-exec-mode new");
|
||||
runCommand("set detach-on-fork off");
|
||||
runCommand({"set detach-on-fork off"});
|
||||
}
|
||||
|
||||
// Finally, set up Python.
|
||||
@@ -4154,15 +4125,15 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
ICore::resourcePath().toLocal8Bit() + "/debugger/";
|
||||
|
||||
if (terminal()->isUsable())
|
||||
runCommand("set inferior-tty " + terminal()->slaveDevice());
|
||||
runCommand({"set inferior-tty " + terminal()->slaveDevice(), NoFlags});
|
||||
|
||||
const QFileInfo gdbBinaryFile(m_gdb);
|
||||
const QByteArray uninstalledData = gdbBinaryFile.absolutePath().toLocal8Bit()
|
||||
+ "/data-directory/python";
|
||||
|
||||
runCommand("python sys.path.insert(1, '" + dumperSourcePath + "')");
|
||||
runCommand("python sys.path.append('" + uninstalledData + "')");
|
||||
runCommand("python from gdbbridge import *");
|
||||
runCommand({"python sys.path.insert(1, '" + dumperSourcePath + "')", NoFlags});
|
||||
runCommand({"python sys.path.append('" + uninstalledData + "')", NoFlags});
|
||||
runCommand({"python from gdbbridge import *", NoFlags});
|
||||
|
||||
const QString path = stringSetting(ExtraDumperFile);
|
||||
if (!path.isEmpty() && QFileInfo(path).isReadable()) {
|
||||
@@ -4173,11 +4144,9 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
|
||||
const QString commands = stringSetting(ExtraDumperCommands);
|
||||
if (!commands.isEmpty())
|
||||
runCommand(commands.toLocal8Bit());
|
||||
runCommand({commands.toLocal8Bit(), NoFlags});
|
||||
|
||||
DebuggerCommand cmd("loadDumpers", PythonCommand);
|
||||
cmd.callback = CB(handlePythonSetup);
|
||||
runCommand(cmd);
|
||||
runCommand({"loadDumpers", PythonCommand, CB(handlePythonSetup)});
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbStartFailed()
|
||||
@@ -4189,7 +4158,7 @@ void GdbEngine::loadInitScript()
|
||||
const QString script = runParameters().overrideStartScript;
|
||||
if (!script.isEmpty()) {
|
||||
if (QFileInfo(script).isReadable()) {
|
||||
runCommand("source " + script.toLocal8Bit());
|
||||
runCommand({"source " + script.toLocal8Bit(), NoFlags});
|
||||
} else {
|
||||
AsynchronousMessageBox::warning(
|
||||
tr("Cannot find debugger initialization script"),
|
||||
@@ -4201,7 +4170,7 @@ void GdbEngine::loadInitScript()
|
||||
} else {
|
||||
const QString commands = stringSetting(GdbStartupCommands);
|
||||
if (!commands.isEmpty())
|
||||
runCommand(commands.toLocal8Bit());
|
||||
runCommand({commands.toLocal8Bit(), NoFlags});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4211,15 +4180,16 @@ void GdbEngine::setEnvironmentVariables()
|
||||
Environment runEnv = runParameters().environment;
|
||||
foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
|
||||
if (item.unset)
|
||||
runCommand("unset environment " + item.name.toUtf8());
|
||||
runCommand({"unset environment " + item.name.toUtf8(), NoFlags});
|
||||
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()
|
||||
{
|
||||
runCommand("reloadDumpers", PythonCommand);
|
||||
runCommand({"reloadDumpers", PythonCommand});
|
||||
reloadLocals();
|
||||
}
|
||||
|
||||
@@ -4274,7 +4244,7 @@ void GdbEngine::resetInferior()
|
||||
foreach (QByteArray command, commands.split('\n')) {
|
||||
command = command.trimmed();
|
||||
if (!command.isEmpty())
|
||||
runCommand(command, int(ConsoleCommand | NeedsStop));
|
||||
runCommand({command, ConsoleCommand | NeedsStop});
|
||||
}
|
||||
}
|
||||
m_rerunPending = true;
|
||||
@@ -4313,16 +4283,15 @@ void GdbEngine::handleInferiorPrepared()
|
||||
|
||||
if (!rp.commandsAfterConnect.isEmpty()) {
|
||||
QByteArray commands = globalMacroExpander()->expand(rp.commandsAfterConnect);
|
||||
foreach (QByteArray command, commands.split('\n')) {
|
||||
runCommand(command);
|
||||
}
|
||||
foreach (QByteArray command, commands.split('\n'))
|
||||
runCommand({command, NoFlags});
|
||||
}
|
||||
|
||||
//runCommand("set follow-exec-mode new");
|
||||
if (rp.breakOnMain) {
|
||||
QByteArray cmd = "tbreak ";
|
||||
cmd += rp.toolChainAbi.os() == Abi::WindowsOS ? "qMain" : "main";
|
||||
runCommand(cmd);
|
||||
runCommand({cmd, NoFlags});
|
||||
}
|
||||
|
||||
// Initial attempt to set breakpoints.
|
||||
@@ -4344,23 +4313,24 @@ void GdbEngine::finishInferiorSetup()
|
||||
{
|
||||
CHECK_STATE(InferiorSetupRequested);
|
||||
|
||||
if (runParameters().startMode == AttachCore) {
|
||||
notifyInferiorSetupOk(); // No breakpoints in core files.
|
||||
} else {
|
||||
if (boolSetting(BreakOnAbort))
|
||||
runCommand("-break-insert -f abort");
|
||||
if (boolSetting(BreakOnWarning)) {
|
||||
runCommand("-break-insert -f '" + qtNamespace() + "qWarning'");
|
||||
runCommand("-break-insert -f '" + qtNamespace() + "QMessageLogger::warning'");
|
||||
if (runParameters().startMode != AttachCore) { // No breakpoints in core files.
|
||||
const bool onAbort = boolSetting(BreakOnAbort);
|
||||
const bool onWarning = boolSetting(BreakOnWarning);
|
||||
const bool onFatal = boolSetting(BreakOnFatal);
|
||||
if (onAbort || onWarning || onFatal) {
|
||||
DebuggerCommand cmd("createSpecialBreakpoints", PythonCommand);
|
||||
cmd.arg("breakonabort", onAbort);
|
||||
cmd.arg("breakonwarning", onWarning);
|
||||
cmd.arg("breakonfatal", onFatal);
|
||||
runCommand(cmd);
|
||||
}
|
||||
if (boolSetting(BreakOnFatal)) {
|
||||
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 {
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -4369,32 +4339,12 @@ void GdbEngine::handleDebugInfoLocation(const DebuggerResponse &response)
|
||||
const QByteArray debugInfoLocation = runParameters().debugInfoLocation.toLocal8Bit();
|
||||
if (QFile::exists(QString::fromLocal8Bit(debugInfoLocation))) {
|
||||
const QByteArray curDebugInfoLocations = response.consoleStreamOutput.split('"').value(1);
|
||||
if (curDebugInfoLocations.isEmpty()) {
|
||||
runCommand("set debug-file-directory " + debugInfoLocation);
|
||||
} else {
|
||||
runCommand("set debug-file-directory " + debugInfoLocation
|
||||
+ HostOsInfo::pathListSeparator().toLatin1()
|
||||
+ curDebugInfoLocations);
|
||||
QByteArray cmd = "set debug-file-directory " + debugInfoLocation;
|
||||
if (!curDebugInfoLocations.isEmpty())
|
||||
cmd += HostOsInfo::pathListSeparator().toLatin1() + curDebugInfoLocations;
|
||||
runCommand({cmd, NoFlags});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -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
|
||||
{
|
||||
DebuggerStartMode mode = runParameters().startMode;
|
||||
|
||||
@@ -172,12 +172,7 @@ private: ////////// Gdb Command Management //////////
|
||||
};
|
||||
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
||||
|
||||
protected:
|
||||
void runCommand(const DebuggerCommand &command);
|
||||
void runCommand(const QByteArray &command, int flags);
|
||||
void runCommand(const QByteArray &command,
|
||||
const DebuggerCommand::Callback &callback,
|
||||
int flags = NoFlags);
|
||||
void runCommand(const DebuggerCommand &command) override;
|
||||
|
||||
private:
|
||||
Q_SLOT void commandTimeout();
|
||||
@@ -336,8 +331,6 @@ private: ////////// View & Data Stuff //////////
|
||||
void fetchDisassemblerByCliRangePlain(const DisassemblerAgentCookie &ac);
|
||||
bool handleCliDisassemblerResult(const QByteArray &response, DisassemblerAgent *agent);
|
||||
|
||||
void handleBreakOnQFatal(const DebuggerResponse &response, bool continueSetup);
|
||||
|
||||
//
|
||||
// Source file specific stuff
|
||||
//
|
||||
@@ -426,14 +419,10 @@ protected:
|
||||
// while updating locals.
|
||||
bool m_inUpdateLocals;
|
||||
|
||||
bool isQFatalBreakpoint(const BreakpointResponseId &id) const;
|
||||
bool isHiddenBreakpoint(const BreakpointResponseId &id) const;
|
||||
|
||||
// HACK:
|
||||
QByteArray m_currentThread;
|
||||
QString m_lastWinException;
|
||||
QString m_lastMissingDebugInfo;
|
||||
BreakpointResponseId m_qFatalBreakpointResponseId;
|
||||
bool m_terminalTrap;
|
||||
bool m_temporaryStopPending;
|
||||
bool usesExecInterrupt() const;
|
||||
|
||||
@@ -60,10 +60,10 @@ void GdbPlainEngine::setupInferior()
|
||||
setEnvironmentVariables();
|
||||
if (!runParameters().processArgs.isEmpty()) {
|
||||
QString args = runParameters().processArgs;
|
||||
runCommand("-exec-arguments " + toLocalEncoding(args));
|
||||
runCommand({"-exec-arguments " + toLocalEncoding(args), NoFlags});
|
||||
}
|
||||
runCommand("-file-exec-and-symbols \"" + execFilePath() + '"',
|
||||
CB(handleFileExecAndSymbols));
|
||||
runCommand({"-file-exec-and-symbols \"" + execFilePath() + '"', NoFlags,
|
||||
CB(handleFileExecAndSymbols)});
|
||||
}
|
||||
|
||||
void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
|
||||
@@ -84,9 +84,9 @@ void GdbPlainEngine::handleFileExecAndSymbols(const DebuggerResponse &response)
|
||||
void GdbPlainEngine::runEngine()
|
||||
{
|
||||
if (runParameters().useContinueInsteadOfRun)
|
||||
runCommand("-exec-continue", CB(handleExecuteContinue), RunRequest);
|
||||
runCommand({"-exec-continue", RunRequest, CB(handleExecuteContinue)});
|
||||
else
|
||||
runCommand("-exec-run", CB(handleExecRun), RunRequest);
|
||||
runCommand({"-exec-run", RunRequest, CB(handleExecRun)});
|
||||
}
|
||||
void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ void GdbPlainEngine::handleExecRun(const DebuggerResponse &response)
|
||||
showMessage(msgInferiorSetupOk(), StatusBar);
|
||||
// FIXME: That's the wrong place for it.
|
||||
if (boolSetting(EnableReverseDebugging))
|
||||
runCommand("target record");
|
||||
runCommand({"target record", NoFlags});
|
||||
} else {
|
||||
QString msg = fromLocalEncoding(response.data["msg"].data());
|
||||
//QTC_CHECK(status() == InferiorRunOk);
|
||||
|
||||
@@ -183,10 +183,10 @@ void GdbRemoteServerEngine::setupInferior()
|
||||
// postCommand("set architecture " + remoteArch);
|
||||
const QString solibSearchPath = rp.solibSearchPath.join(HostOsInfo::pathListSeparator());
|
||||
if (!solibSearchPath.isEmpty())
|
||||
runCommand("set solib-search-path " + solibSearchPath.toLocal8Bit());
|
||||
runCommand({"set solib-search-path " + solibSearchPath.toLocal8Bit(), NoFlags});
|
||||
|
||||
if (!args.isEmpty())
|
||||
runCommand("-exec-arguments " + args.toLocal8Bit());
|
||||
runCommand({"-exec-arguments " + args.toLocal8Bit(), NoFlags});
|
||||
|
||||
setEnvironmentVariables();
|
||||
|
||||
@@ -210,7 +210,7 @@ void GdbRemoteServerEngine::setupInferior()
|
||||
// mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)'
|
||||
// failed.\nA problem internal to GDB has been detected,[...]
|
||||
if (boolSetting(TargetAsync))
|
||||
runCommand("set target-async on", CB(handleSetTargetAsync));
|
||||
runCommand({"set target-async on", NoFlags, CB(handleSetTargetAsync)});
|
||||
|
||||
if (executableFileName.isEmpty()) {
|
||||
showMessage(tr("No symbol file given."), StatusBar);
|
||||
@@ -219,8 +219,8 @@ void GdbRemoteServerEngine::setupInferior()
|
||||
}
|
||||
|
||||
if (!executableFileName.isEmpty()) {
|
||||
runCommand("-file-exec-and-symbols \"" + executableFileName.toLocal8Bit() + '"',
|
||||
CB(handleFileExecAndSymbols));
|
||||
runCommand({"-file-exec-and-symbols \"" + executableFileName.toLocal8Bit() + '"',
|
||||
NoFlags, CB(handleFileExecAndSymbols)});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,11 +270,11 @@ void GdbRemoteServerEngine::callTargetRemote()
|
||||
}
|
||||
|
||||
if (m_isQnxGdb)
|
||||
runCommand("target qnx " + channel, CB(handleTargetQnx));
|
||||
runCommand({"target qnx " + channel, NoFlags, CB(handleTargetQnx)});
|
||||
else if (runParameters().multiProcess)
|
||||
runCommand("target extended-remote " + channel, CB(handleTargetExtendedRemote));
|
||||
runCommand({"target extended-remote " + channel, NoFlags, CB(handleTargetExtendedRemote)});
|
||||
else
|
||||
runCommand("target remote " + channel, CB(handleTargetRemote));
|
||||
runCommand({"target remote " + channel, NoFlags, CB(handleTargetRemote)});
|
||||
}
|
||||
|
||||
void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
|
||||
@@ -287,7 +287,7 @@ void GdbRemoteServerEngine::handleTargetRemote(const DebuggerResponse &response)
|
||||
QString postAttachCommands = stringSetting(GdbPostAttachCommands);
|
||||
if (!postAttachCommands.isEmpty()) {
|
||||
foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n')))
|
||||
runCommand(cmd.toLatin1());
|
||||
runCommand({cmd.toLatin1(), NoFlags});
|
||||
}
|
||||
handleInferiorPrepared();
|
||||
} else {
|
||||
@@ -307,15 +307,15 @@ void GdbRemoteServerEngine::handleTargetExtendedRemote(const DebuggerResponse &r
|
||||
QString postAttachCommands = stringSetting(GdbPostAttachCommands);
|
||||
if (!postAttachCommands.isEmpty()) {
|
||||
foreach (const QString &cmd, postAttachCommands.split(QLatin1Char('\n')))
|
||||
runCommand(cmd.toLatin1());
|
||||
runCommand({cmd.toLatin1(), NoFlags});
|
||||
}
|
||||
if (runParameters().attachPID > 0) { // attach to pid if valid
|
||||
// gdb server will stop the remote application itself.
|
||||
runCommand("attach " + QByteArray::number(runParameters().attachPID),
|
||||
CB(handleTargetExtendedAttach));
|
||||
runCommand({"attach " + QByteArray::number(runParameters().attachPID),
|
||||
NoFlags, CB(handleTargetExtendedAttach)});
|
||||
} else {
|
||||
runCommand("-gdb-set remote exec-file " + runParameters().remoteExecutable.toLatin1(),
|
||||
CB(handleTargetExtendedAttach));
|
||||
runCommand({"-gdb-set remote exec-file " + runParameters().remoteExecutable.toLatin1(),
|
||||
NoFlags, CB(handleTargetExtendedAttach)});
|
||||
}
|
||||
} else {
|
||||
QString msg = msgConnectRemoteServerFailed(
|
||||
@@ -349,9 +349,9 @@ void GdbRemoteServerEngine::handleTargetQnx(const DebuggerResponse &response)
|
||||
const qint64 pid = isMasterEngine() ? runParameters().attachPID : masterEngine()->runParameters().attachPID;
|
||||
const QString remoteExecutable = isMasterEngine() ? runParameters().remoteExecutable : masterEngine()->runParameters().remoteExecutable;
|
||||
if (pid > -1)
|
||||
runCommand("attach " + QByteArray::number(pid), CB(handleAttach));
|
||||
runCommand({"attach " + QByteArray::number(pid), NoFlags, CB(handleAttach)});
|
||||
else if (!remoteExecutable.isEmpty())
|
||||
runCommand("set nto-executable " + remoteExecutable.toLatin1(), CB(handleSetNtoExecutable));
|
||||
runCommand({"set nto-executable " + remoteExecutable.toLatin1(), NoFlags, CB(handleSetNtoExecutable)});
|
||||
else
|
||||
handleInferiorPrepared();
|
||||
} else {
|
||||
@@ -409,7 +409,7 @@ void GdbRemoteServerEngine::runEngine()
|
||||
|
||||
const QString remoteExecutable = runParameters().remoteExecutable;
|
||||
if (!remoteExecutable.isEmpty()) {
|
||||
runCommand("-exec-run", CB(handleExecRun), RunRequest);
|
||||
runCommand({"-exec-run", RunRequest, CB(handleExecRun)});
|
||||
} else {
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
continueInferiorInternal();
|
||||
@@ -434,7 +434,7 @@ void GdbRemoteServerEngine::interruptInferior2()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
|
||||
if (boolSetting(TargetAsync)) {
|
||||
runCommand("-exec-interrupt", CB(handleInterruptInferior));
|
||||
runCommand({"-exec-interrupt", NoFlags, CB(handleInterruptInferior)});
|
||||
} else if (m_isQnxGdb && HostOsInfo::isWindowsHost()) {
|
||||
m_gdbProc.interrupt();
|
||||
} else {
|
||||
|
||||
@@ -134,9 +134,8 @@ void GdbTermEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
const qint64 attachedPID = m_stubProc.applicationPID();
|
||||
DebuggerCommand cmd("attach " + QByteArray::number(attachedPID));
|
||||
cmd.callback = [this](const DebuggerResponse &r) { handleStubAttached(r); };
|
||||
runCommand(cmd);
|
||||
runCommand({"attach " + QByteArray::number(attachedPID), NoFlags,
|
||||
[this](const DebuggerResponse &r) { handleStubAttached(r); }});
|
||||
}
|
||||
|
||||
void GdbTermEngine::handleStubAttached(const DebuggerResponse &response)
|
||||
|
||||