Merge remote-tracking branch 'origin/7.0'

Conflicts:
	src/libs/utils/qtcprocess.cpp
	src/plugins/qmldesigner/components/curveeditor/curveeditorview.cpp
	src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp

Change-Id: Id0c31719e46d1c44770ea89663eee321a0517ff4
This commit is contained in:
Eike Ziller
2022-02-24 11:42:13 +01:00
115 changed files with 1239 additions and 969 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -157,14 +157,6 @@
re-scanning is incremental, so nothing is lost by closing and re-starting re-scanning is incremental, so nothing is lost by closing and re-starting
\QC. \QC.
Because clangd considers only the on-disk state of included header files
when parsing a source file, you need to save changes in header files to
have them considered elsewhere for completion, diagnostics, and so on.
Partly for this reason, files that are changed by refactoring actions are
saved automatically. To disable this feature, select \uicontrol Tools >
\uicontrol Options > \uicontrol Environment > \uicontrol System >
\uicontrol {Auto-save files after refactoring}.
The document outline in the \l{Viewing Defined Types and Symbols} The document outline in the \l{Viewing Defined Types and Symbols}
{Outline} view is backed by clangd's document symbol support, which {Outline} view is backed by clangd's document symbol support, which
makes the results more reliable than before. makes the results more reliable than before.

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -114,7 +114,7 @@
\c {share/qtcreator/templates/wizards/classes/mycpp} \c {share/qtcreator/templates/wizards/classes/mycpp}
\li Use the \uicontrol {Factory.Reset} action to make the wizard appear \li Use the \uicontrol {Factory.Reset} action to make the wizard appear
in \uicontrol File > \uicontrol {New File or Project} without in \uicontrol File > \uicontrol {New File} without
restarting \QC. restarting \QC.
\li Open the wizard configuration file, \c {wizard.json} for editing: \li Open the wizard configuration file, \c {wizard.json} for editing:
@@ -122,7 +122,7 @@
\list \list
\li The following settings determine the type of the wizard and \li The following settings determine the type of the wizard and
its place in the \uicontrol {New File or Project} dialog: its place in the \uicontrol {New File} dialog:
\code \code
"version": 1, "version": 1,
@@ -163,14 +163,14 @@
\li \c category is the category in which to place the wizard \li \c category is the category in which to place the wizard
in the list. You can use a leading letter to specify the in the list. You can use a leading letter to specify the
position of the category in the list in the position of the category in the list in the
\uicontrol {New File or Project} dialog. \uicontrol {New File} dialog.
This information is available in the wizard as This information is available in the wizard as
\c {%\{category\}}. \c {%\{category\}}.
\endlist \endlist
\li The following settings specify the icon and text that appear in \li The following settings specify the icon and text that appear in
the \uicontrol {New File or Project} dialog: the \uicontrol {New File} dialog:
\code \code
"trDescription": "Creates a C++ header and a source file for a new class that you can add to a C++ project.", "trDescription": "Creates a C++ header and a source file for a new class that you can add to a C++ project.",
@@ -194,9 +194,8 @@
This information is available in the wizard as This information is available in the wizard as
\c {%\{trDisplayName\}}. \c {%\{trDisplayName\}}.
\li \c trDisplayCategory appears in the \li \c trDisplayCategory appears in the \uicontrol {New File}
\uicontrol {New File or Project} dialog, under dialog, under \uicontrol {Files and Classes}.
\uicontrol Projects.
This information is available in the wizard as This information is available in the wizard as
\c {%\{trDisplayCategory\}}. \c {%\{trDisplayCategory\}}.
@@ -231,9 +230,9 @@
\c{false}. \c{false}.
\li \c enabled is evaluated to determine whether a wizard is \li \c enabled is evaluated to determine whether a wizard is
listed in \uicontrol Files > listed in \uicontrol File > \uicontrol {New Project} or
\uicontrol {New File or Project}, after \c featuresRequired \uicontrol {New File}, after \c featuresRequired has been
has been checked. checked.
The default value is \c true. The default value is \c true.
@@ -373,7 +372,8 @@
instance of \QC. instance of \QC.
\li \c Platform contains the platform selected in the \uicontrol File > \li \c Platform contains the platform selected in the \uicontrol File >
\uicontrol {New File or Project} dialog. This value may be empty. \uicontrol {New Project} or \uicontrol {New File} dialog. This value
may be empty.
\endlist \endlist
The following information is only available when the wizard was triggered The following information is only available when the wizard was triggered
@@ -487,7 +487,7 @@
\endcode \endcode
The page evaluates \c {%\{Platform\}} to set the platform selected in The page evaluates \c {%\{Platform\}} to set the platform selected in
\uicontrol File > \uicontrol {New File or Project}. \uicontrol File > \uicontrol {New Project} or \uicontrol {New File}.

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -59,8 +59,8 @@
wizard directory and instruct the recipients to extract it into one of the wizard directory and instruct the recipients to extract it into one of the
directories \QC searches wizards from. directories \QC searches wizards from.
\QC displays the wizards that it finds in the \QC displays the wizards that it finds in the \uicontrol {New Project}
\uicontrol {New File} and \uicontrol {New Project} dialogs. For each wizard, an icon (1), a and \uicontrol {New File} dialogs. For each wizard, an icon (1), a
display name (2), and a description (3) are displayed. display name (2), and a description (3) are displayed.
\image qtcreator-custom-wizard.png \image qtcreator-custom-wizard.png

View File

@@ -45,6 +45,8 @@
\uicontrol Environment > \uicontrol System, and then select \uicontrol Environment > \uicontrol System, and then select
\uicontrol Change in the \uicontrol Environment field. \uicontrol Change in the \uicontrol Environment field.
\image qtcreator-options-environment-system.png "Environment options System tab"
In addition, you can specify custom environment variables in the In addition, you can specify custom environment variables in the
\uicontrol {Project Settings} > \uicontrol Environment settings. \uicontrol {Project Settings} > \uicontrol Environment settings.
They are added to all build environments. The final build environment They are added to all build environments. The final build environment

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -30,7 +30,7 @@
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New Project} >
\uicontrol {Application (Qt)} > \uicontrol {Qt Quick Application}. \uicontrol {Application (Qt)} > \uicontrol {Qt Quick Application}.
\li Select \uicontrol Choose to open the \li Select \uicontrol Choose to open the

View File

@@ -63,6 +63,8 @@
\li Select the \uicontrol {Auto-save modified files} check box to \li Select the \uicontrol {Auto-save modified files} check box to
automatically save changed files at the intervals specified in automatically save changed files at the intervals specified in
the \uicontrol Interval field. the \uicontrol Interval field.
\li Select the \uicontrol {Auto-save files after refactoring} check
box to automatically save \l{Refactoring}{refactored files}.
\li Select the \uicontrol {Auto-suspend unmodified files} check \li Select the \uicontrol {Auto-suspend unmodified files} check
box to automatically free the resources of open files after box to automatically free the resources of open files after
prolonged inactivity. The files are still listed in the prolonged inactivity. The files are still listed in the

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Design Studio documentation. ** This file is part of the Design Studio documentation.
@@ -61,7 +61,7 @@
To create stylable UI controls: To create stylable UI controls:
\list 1 \list 1
\li Select \uicontrol File > \uicontrol {New File or Project} > \li Select \uicontrol File > \uicontrol {New File} >
\uicontrol {Files and Classes} > \uicontrol {Qt Quick Controls}. \uicontrol {Files and Classes} > \uicontrol {Qt Quick Controls}.
\li Select the control to create, and then select \uicontrol Choose. \li Select the control to create, and then select \uicontrol Choose.

View File

@@ -35,20 +35,18 @@
\image studio-examples-download.png "Examples for download in Welcome mode" \image studio-examples-download.png "Examples for download in Welcome mode"
To run an example project: To run an example project:
\list 1 \list 1
\li Select the example. \li Select the example project to open it. \QDS makes all necessary
\li Select the \inlineimage icons/live_preview.png downloads.
(\uicontrol {Show Live Preview}) button to preview the example. \li Select \inlineimage icons/run_small.png
(\uicontrol {Run}) to run the example.
\endlist \endlist
Some of the example projects require that you download them before you can run them, to do this: If there is an update available for an example project that you have
\list 1 installed, it is indicated by a yellow icon next to the example project name
\li Select an example. on the \uicontrol Welcome page. Select the icon to download the latest
\li Select \uicontrol {Start Download}. version of the example project.
\li Select the folder where the source files will be installed.
\li Select \uicontrol Continue to install the files.
\li Select \uicontrol Open to open the example in \QDS.
\endlist
\section1 Example Documentation \section1 Example Documentation

View File

@@ -28,6 +28,7 @@
#include "sharedmemory.h" #include "sharedmemory.h"
#include <QCache> #include <QCache>
#include <QDebug> #include <QDebug>
#include <QLoggingCategory>
#include <cstring> #include <cstring>
@@ -36,6 +37,8 @@
#define QTC_ASSERT_STRING(cond) qDebug("SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " QTC_ASSERT_STRINGIFY(__LINE__)) #define QTC_ASSERT_STRING(cond) qDebug("SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " QTC_ASSERT_STRINGIFY(__LINE__))
#define QTC_ASSERT(cond, action) if (cond) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0) #define QTC_ASSERT(cond, action) if (cond) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)
static Q_LOGGING_CATEGORY(imageContainerDebug, "qtc.imagecontainer.debug", QtDebugMsg)
namespace QmlDesigner { namespace QmlDesigner {
// using cache as a container which deletes sharedmemory pointers at process exit // using cache as a container which deletes sharedmemory pointers at process exit
@@ -202,7 +205,7 @@ static void readSharedMemory(qint32 key, ImageContainer &container)
image.setDevicePixelRatio(pixelRatio); image.setDevicePixelRatio(pixelRatio);
if (image.isNull()) if (image.isNull())
qDebug() << Q_FUNC_INFO << "Not able to create image:" << imageWidth << imageHeight << imageFormat; qCInfo(imageContainerDebug()) << Q_FUNC_INFO << "Not able to create image:" << imageWidth << imageHeight << imageFormat;
else else
std::memcpy(image.bits(), reinterpret_cast<const qint32*>(sharedMemory.constData()) + 6, byteCount); std::memcpy(image.bits(), reinterpret_cast<const qint32*>(sharedMemory.constData()) + 6, byteCount);

View File

@@ -125,6 +125,7 @@ bool startCrashpad()
// Optional arguments to pass to the handler // Optional arguments to pass to the handler
std::vector<std::string> arguments; std::vector<std::string> arguments;
arguments.push_back("--no-rate-limit");
CrashpadClient *client = new CrashpadClient(); CrashpadClient *client = new CrashpadClient();
bool success = client->StartHandler( bool success = client->StartHandler(

View File

@@ -424,7 +424,7 @@ Item {
width: parent.width width: parent.width
height: parent.height - y height: parent.height - y
clip: true clip: true
interactive: assetsView.verticalScrollBarVisible interactive: assetsView.verticalScrollBarVisible && !contextMenu.opened
Column { Column {
Repeater { Repeater {

View File

@@ -246,6 +246,7 @@ Item {
id: verticalScrollView id: verticalScrollView
anchors.fill: parent anchors.fill: parent
clip: true clip: true
interactive: !itemContextMenu.opened && !moduleContextMenu.opened
onContentHeightChanged: { onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - verticalScrollView.height, 0) var maxPosition = Math.max(contentHeight - verticalScrollView.height, 0)
@@ -362,6 +363,7 @@ Item {
width: 270 width: 270
height: parent.height height: parent.height
clip: true clip: true
interactive: !itemContextMenu.opened && !moduleContextMenu.opened
onContentHeightChanged: { onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - horizontalScrollView.height, 0) var maxPosition = Math.max(contentHeight - horizontalScrollView.height, 0)

View File

@@ -99,7 +99,7 @@ PropertyEditorPane {
anchors.right: parent.right anchors.right: parent.right
StudioControls.TabButton { StudioControls.TabButton {
text: backendValues.className.value text: backendValues.__classNamePrivateInternal.value
} }
StudioControls.TabButton { StudioControls.TabButton {
text: qsTr("Layout") text: qsTr("Layout")

View File

@@ -56,13 +56,13 @@ Section {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding anchors.leftMargin: StudioTheme.Values.inputHorizontalPadding
anchors.topMargin: StudioTheme.Values.typeLabelVerticalShift anchors.topMargin: StudioTheme.Values.typeLabelVerticalShift
text: backendValues.className.value text: backendValues.__classNamePrivateInternal.value
} }
ToolTipArea { ToolTipArea {
anchors.fill: parent anchors.fill: parent
onDoubleClicked: { onDoubleClicked: {
typeLineEdit.text = backendValues.className.value typeLineEdit.text = backendValues.__classNamePrivateInternal.value
typeLineEdit.visible = !typeLineEdit.visible typeLineEdit.visible = !typeLineEdit.visible
typeLineEdit.forceActiveFocus() typeLineEdit.forceActiveFocus()
} }

View File

@@ -86,7 +86,7 @@ QtObject {
property real contextMenuHorizontalPadding: Math.round(6 * values.scaleFactor) property real contextMenuHorizontalPadding: Math.round(6 * values.scaleFactor)
property real inputHorizontalPadding: Math.round(6 * values.scaleFactor) property real inputHorizontalPadding: Math.round(6 * values.scaleFactor)
property real typeLabelVerticalShift: Math.round(5 * values.scaleFactor) property real typeLabelVerticalShift: Math.round(6 * values.scaleFactor)
property real scrollBarThickness: 10 property real scrollBarThickness: 10

View File

@@ -1,5 +1,12 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.12 import QtQuick.Controls 2.15
Button { Button {
id: control id: control

View File

@@ -1,5 +1,12 @@
import QtQuick 2.12 /*
import QtQuick.Controls 2.12 This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
CheckBox { CheckBox {
id: control id: control

View File

@@ -1,5 +1,12 @@
import QtQuick 2.12 /*
import QtQuick.Controls 2.12 This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
Dial { Dial {
id: control id: control

View File

@@ -1,5 +1,12 @@
import QtQuick 2.12 /*
import QtQuick.Controls 2.12 This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
Slider { Slider {
id: control id: control

View File

@@ -1,5 +1,12 @@
import QtQuick 2.12 /*
import QtQuick.Controls 2.12 This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
SpinBox { SpinBox {
id: control id: control

View File

@@ -1,5 +1,12 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.12 import QtQuick.Controls 2.15
Switch { Switch {
id: control id: control

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
@if %{UseQtQuickControls2} @if %{UseQtQuickControls2}
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
@@ -8,6 +15,11 @@ import %{ApplicationImport}
import FlowView 1.0 import FlowView 1.0
FlowItem { FlowItem {
@if %{UseImport}
width: Constants.width width: Constants.width
height: Constants.height height: Constants.height
@else
width: 800
height: 600
@endif
} }

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
@if %{UseImport} @if %{UseImport}
import %{ApplicationImport} import %{ApplicationImport}
@@ -5,8 +12,13 @@ import %{ApplicationImport}
import FlowView 1.0 import FlowView 1.0
FlowView { FlowView {
@if %{UseImport}
width: Constants.width width: Constants.width
height: Constants.height height: Constants.height
@else
width: 800
height: 600
@endif
defaultTransition: FlowTransition { defaultTransition: FlowTransition {
id: defaultTransition id: defaultTransition

View File

@@ -1,6 +1,6 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.15
import QtQuick.Controls 2.3 import QtQuick.Controls 2.15
import %{ApplicationImport} import %{ApplicationImport}
Pane { Pane {

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
GridView { GridView {

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
Item { Item {

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
ListView { ListView {

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
@if %{UseQtQuickControls2} @if %{UseQtQuickControls2}
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15

View File

@@ -1,6 +1,6 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.15
import QtQuick.Controls 2.3 import QtQuick.Controls 2.15
import %{ApplicationImport} import %{ApplicationImport}
Item { Item {

View File

@@ -1,6 +1,6 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.15
import QtQuick.Controls 2.3 import QtQuick.Controls 2.15
import %{ApplicationImport} import %{ApplicationImport}
Item { Item {

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import QtQuick3D %{QtQuick3DVersion} import QtQuick3D %{QtQuick3DVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick 2.15 import QtQuick 2.15
import Constants 1.0 import Constants 1.0

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -1,3 +1,10 @@
/*
This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
It is supposed to be strictly declarative and only uses a subset of QML. If you edit
this file manually, you might introduce QML code that is not supported by Qt Design Studio.
Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
*/
import QtQuick %{QtQuickVersion} import QtQuick %{QtQuickVersion}
import QtQuick.Controls %{QtQuickVersion} import QtQuick.Controls %{QtQuickVersion}
import %{ImportModuleName} %{ImportModuleVersion} import %{ImportModuleName} %{ImportModuleVersion}

View File

@@ -438,6 +438,7 @@ bool startCrashpad(const QString &libexecPath, bool crashReportingEnabled)
// Optional arguments to pass to the handler // Optional arguments to pass to the handler
std::vector<std::string> arguments; std::vector<std::string> arguments;
arguments.push_back("--no-rate-limit");
CrashpadClient *client = new CrashpadClient(); CrashpadClient *client = new CrashpadClient();
bool success = client->StartHandler( bool success = client->StartHandler(

View File

@@ -723,8 +723,10 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
} }
value = pluginMetaData.value(QLatin1String(PLUGIN_METADATA)); value = pluginMetaData.value(QLatin1String(PLUGIN_METADATA));
if (!value.isObject()) if (!value.isObject()) {
return reportError(tr("Plugin meta data not found")); return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Plugin meta data not found"));
}
metaData = value.toObject(); metaData = value.toObject();
value = metaData.value(QLatin1String(PLUGIN_NAME)); value = metaData.value(QLatin1String(PLUGIN_NAME));
@@ -806,10 +808,12 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
const QString platformSpec = value.toString().trimmed(); const QString platformSpec = value.toString().trimmed();
if (!platformSpec.isEmpty()) { if (!platformSpec.isEmpty()) {
platformSpecification.setPattern(platformSpec); platformSpecification.setPattern(platformSpec);
if (!platformSpecification.isValid()) if (!platformSpecification.isValid()) {
return reportError(tr("Invalid platform specification \"%1\": %2") return reportError(::ExtensionSystem::Internal::PluginSpecPrivate::tr(
"Invalid platform specification \"%1\": %2")
.arg(platformSpec, platformSpecification.errorString())); .arg(platformSpec, platformSpecification.errorString()));
} }
}
value = metaData.value(QLatin1String(DEPENDENCIES)); value = metaData.value(QLatin1String(DEPENDENCIES));
if (!value.isUndefined() && !value.isArray()) if (!value.isUndefined() && !value.isArray())
@@ -822,22 +826,36 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
QJsonObject dependencyObject = v.toObject(); QJsonObject dependencyObject = v.toObject();
PluginDependency dep; PluginDependency dep;
value = dependencyObject.value(QLatin1String(DEPENDENCY_NAME)); value = dependencyObject.value(QLatin1String(DEPENDENCY_NAME));
if (value.isUndefined()) if (value.isUndefined()) {
return reportError(tr("Dependency: %1").arg(msgValueMissing(DEPENDENCY_NAME))); return reportError(
if (!value.isString()) ::ExtensionSystem::Internal::PluginSpecPrivate::tr("Dependency: %1")
return reportError(tr("Dependency: %1").arg(msgValueIsNotAString(DEPENDENCY_NAME))); .arg(msgValueMissing(DEPENDENCY_NAME)));
}
if (!value.isString()) {
return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Dependency: %1")
.arg(msgValueIsNotAString(DEPENDENCY_NAME)));
}
dep.name = value.toString(); dep.name = value.toString();
value = dependencyObject.value(QLatin1String(DEPENDENCY_VERSION)); value = dependencyObject.value(QLatin1String(DEPENDENCY_VERSION));
if (!value.isUndefined() && !value.isString()) if (!value.isUndefined() && !value.isString()) {
return reportError(tr("Dependency: %1").arg(msgValueIsNotAString(DEPENDENCY_VERSION))); return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Dependency: %1")
.arg(msgValueIsNotAString(DEPENDENCY_VERSION)));
}
dep.version = value.toString(); dep.version = value.toString();
if (!isValidVersion(dep.version)) if (!isValidVersion(dep.version)) {
return reportError(tr("Dependency: %1").arg(msgInvalidFormat(DEPENDENCY_VERSION, return reportError(
dep.version))); ::ExtensionSystem::Internal::PluginSpecPrivate::tr("Dependency: %1")
.arg(msgInvalidFormat(DEPENDENCY_VERSION, dep.version)));
}
dep.type = PluginDependency::Required; dep.type = PluginDependency::Required;
value = dependencyObject.value(QLatin1String(DEPENDENCY_TYPE)); value = dependencyObject.value(QLatin1String(DEPENDENCY_TYPE));
if (!value.isUndefined() && !value.isString()) if (!value.isUndefined() && !value.isString()) {
return reportError(tr("Dependency: %1").arg(msgValueIsNotAString(DEPENDENCY_TYPE))); return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Dependency: %1")
.arg(msgValueIsNotAString(DEPENDENCY_TYPE)));
}
if (!value.isUndefined()) { if (!value.isUndefined()) {
const QString typeValue = value.toString(); const QString typeValue = value.toString();
if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_HARD)) { if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_HARD)) {
@@ -847,7 +865,9 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
} else if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_TEST)) { } else if (typeValue.toLower() == QLatin1String(DEPENDENCY_TYPE_TEST)) {
dep.type = PluginDependency::Test; dep.type = PluginDependency::Test;
} else { } else {
return reportError(tr("Dependency: \"%1\" must be \"%2\" or \"%3\" (is \"%4\").") return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr(
"Dependency: \"%1\" must be \"%2\" or \"%3\" (is \"%4\").")
.arg(QLatin1String(DEPENDENCY_TYPE), .arg(QLatin1String(DEPENDENCY_TYPE),
QLatin1String(DEPENDENCY_TYPE_HARD), QLatin1String(DEPENDENCY_TYPE_HARD),
QLatin1String(DEPENDENCY_TYPE_SOFT), QLatin1String(DEPENDENCY_TYPE_SOFT),
@@ -869,20 +889,35 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &pluginMetaData)
QJsonObject argumentObject = v.toObject(); QJsonObject argumentObject = v.toObject();
PluginArgumentDescription arg; PluginArgumentDescription arg;
value = argumentObject.value(QLatin1String(ARGUMENT_NAME)); value = argumentObject.value(QLatin1String(ARGUMENT_NAME));
if (value.isUndefined()) if (value.isUndefined()) {
return reportError(tr("Argument: %1").arg(msgValueMissing(ARGUMENT_NAME))); return reportError(
if (!value.isString()) ::ExtensionSystem::Internal::PluginSpecPrivate::tr("Argument: %1")
return reportError(tr("Argument: %1").arg(msgValueIsNotAString(ARGUMENT_NAME))); .arg(msgValueMissing(ARGUMENT_NAME)));
}
if (!value.isString()) {
return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Argument: %1")
.arg(msgValueIsNotAString(ARGUMENT_NAME)));
}
arg.name = value.toString(); arg.name = value.toString();
if (arg.name.isEmpty()) if (arg.name.isEmpty()) {
return reportError(tr("Argument: \"%1\" is empty").arg(QLatin1String(ARGUMENT_NAME))); return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Argument: \"%1\" is empty")
.arg(QLatin1String(ARGUMENT_NAME)));
}
value = argumentObject.value(QLatin1String(ARGUMENT_DESCRIPTION)); value = argumentObject.value(QLatin1String(ARGUMENT_DESCRIPTION));
if (!value.isUndefined() && !value.isString()) if (!value.isUndefined() && !value.isString()) {
return reportError(tr("Argument: %1").arg(msgValueIsNotAString(ARGUMENT_DESCRIPTION))); return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Argument: %1")
.arg(msgValueIsNotAString(ARGUMENT_DESCRIPTION)));
}
arg.description = value.toString(); arg.description = value.toString();
value = argumentObject.value(QLatin1String(ARGUMENT_PARAMETER)); value = argumentObject.value(QLatin1String(ARGUMENT_PARAMETER));
if (!value.isUndefined() && !value.isString()) if (!value.isUndefined() && !value.isString()) {
return reportError(tr("Argument: %1").arg(msgValueIsNotAString(ARGUMENT_PARAMETER))); return reportError(
::ExtensionSystem::Internal::PluginSpecPrivate::tr("Argument: %1")
.arg(msgValueIsNotAString(ARGUMENT_PARAMETER)));
}
arg.parameter = value.toString(); arg.parameter = value.toString();
argumentDescriptions.append(arg); argumentDescriptions.append(arg);
qCDebug(pluginLog) << "Argument:" << arg.name << "Parameter:" << arg.parameter qCDebug(pluginLog) << "Argument:" << arg.name << "Parameter:" << arg.parameter

View File

@@ -35,6 +35,7 @@
#include <utils/variant.h> // revert when macos minimum target is >= 10.14 #include <utils/variant.h> // revert when macos minimum target is >= 10.14
#include <chrono>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -34,7 +34,6 @@ add_qtc_library(Utils
differ.cpp differ.h differ.cpp differ.h
displayname.cpp displayname.h displayname.cpp displayname.h
dropsupport.cpp dropsupport.h dropsupport.cpp dropsupport.h
dynamiclicensecheck.h
elfreader.cpp elfreader.h elfreader.cpp elfreader.h
elidinglabel.cpp elidinglabel.h elidinglabel.cpp elidinglabel.h
environment.cpp environment.h environment.cpp environment.h

View File

@@ -1,5 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com> ** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@@ -752,48 +753,6 @@ QString AndroidConfig::getAvdName(const QString &serialnumber)
return QString::fromLatin1(name).trimmed(); return QString::fromLatin1(name).trimmed();
} }
static SdkToolResult emulatorNameAdbCommand(const QString &serialNumber)
{
QStringList args = AndroidDeviceInfo::adbSelector(serialNumber);
args.append({"emu", "avd", "name"});
return AndroidManager::runAdbCommand(args);
}
QString AndroidConfig::getRunningAvdsSerialNumber(const QString &name) const
{
for (const AndroidDeviceInfo &dev : connectedDevices()) {
if (!dev.serialNumber.startsWith("emulator"))
continue;
SdkToolResult result = emulatorNameAdbCommand(dev.serialNumber);
const QString stdOut = result.stdOut();
if (stdOut.isEmpty())
continue; // Not an avd
const QStringList outputLines = stdOut.split('\n');
if (outputLines.size() > 1 && outputLines.first() == name)
return dev.serialNumber;
}
return {};
}
QStringList AndroidConfig::getRunningAvdsFromDevices(const QVector<AndroidDeviceInfo> &devs)
{
QStringList runningDevs;
for (const AndroidDeviceInfo &dev : devs) {
if (!dev.serialNumber.startsWith("emulator"))
continue;
SdkToolResult result = emulatorNameAdbCommand(dev.serialNumber);
const QString stdOut = result.stdOut();
if (stdOut.isEmpty())
continue; // Not an avd
const QStringList outputLines = stdOut.split('\n');
if (outputLines.size() > 1)
runningDevs.append(outputLines.first());
}
return runningDevs;
}
AndroidConfig::OpenGl AndroidConfig::getOpenGLEnabled(const QString &emulator) const AndroidConfig::OpenGl AndroidConfig::getOpenGLEnabled(const QString &emulator) const
{ {
QDir dir = QDir::home(); QDir dir = QDir::home();

View File

@@ -1,5 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com> ** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@@ -176,15 +177,12 @@ public:
static Utils::FilePath getJdkPath(); static Utils::FilePath getJdkPath();
static QStringList getAbis(const QString &device); static QStringList getAbis(const QString &device);
static int getSDKVersion(const QString &device);
QString getRunningAvdsSerialNumber(const QString &name) const;
static QStringList getRunningAvdsFromDevices(const QVector<AndroidDeviceInfo> &devs);
private: private:
static QString getDeviceProperty(const QString &device, const QString &property); static QString getDeviceProperty(const QString &device, const QString &property);
Utils::FilePath openJDKBinPath() const; Utils::FilePath openJDKBinPath() const;
static int getSDKVersion(const QString &device);
static QString getAvdName(const QString &serialnumber); static QString getAvdName(const QString &serialnumber);
void parseDependenciesJson(); void parseDependenciesJson();

View File

@@ -182,7 +182,7 @@ bool AndroidDeployQtStep::init()
return false; return false;
} }
if (!dev->canSupportAbis(selectedAbis)) { if (!selectedAbis.isEmpty() && !dev->canSupportAbis(selectedAbis)) {
const QString error = tr("The deployment device \"%1\" does not support the " const QString error = tr("The deployment device \"%1\" does not support the "
"architectures used by the kit.\n" "architectures used by the kit.\n"
"The kit supports \"%2\", but the device uses \"%3\".") "The kit supports \"%2\", but the device uses \"%3\".")

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com> ** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@@ -52,6 +52,10 @@
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QMessageBox> #include <QMessageBox>
#include <QPushButton> #include <QPushButton>
#include <QTimer>
#include <QRegularExpression>
#include <utils/qtcprocess.h>
using namespace ProjectExplorer; using namespace ProjectExplorer;
@@ -59,9 +63,6 @@ namespace {
static Q_LOGGING_CATEGORY(androidDeviceLog, "qtc.android.androiddevice", QtWarningMsg) static Q_LOGGING_CATEGORY(androidDeviceLog, "qtc.android.androiddevice", QtWarningMsg)
} }
// interval for updating the list of connected Android devices and emulators
constexpr int deviceUpdaterMsInterval = 30000;
namespace Android { namespace Android {
namespace Internal { namespace Internal {
@@ -328,7 +329,7 @@ QString AndroidDevice::serialNumber() const
if (machineType() == Hardware) if (machineType() == Hardware)
return serialNumber; return serialNumber;
return AndroidConfigurations::currentConfig().getRunningAvdsSerialNumber(avdName()); return AndroidDeviceManager::instance()->getRunningAvdsSerialNumber(avdName());
} }
QString AndroidDevice::avdName() const QString AndroidDevice::avdName() const
@@ -419,36 +420,28 @@ QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
return url; return url;
} }
void AndroidDeviceManager::updateDevicesList() void AndroidDeviceManager::updateAvdsList()
{ {
// If a non-Android Kit is currently active, skip the device list update if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists())
const Target *startupTarget = SessionManager::startupTarget();
if (!startupTarget)
return;
const Kit *kit = startupTarget->kit();
if (!kit)
return;
if (DeviceTypeKitAspect::deviceTypeId(kit) != Constants::ANDROID_DEVICE_TYPE)
return;
updateDevicesListOnce();
}
void AndroidDeviceManager::updateDevicesListOnce()
{
if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists()) {
m_avdsFutureWatcher.setFuture(m_avdManager.avdList()); m_avdsFutureWatcher.setFuture(m_avdManager.avdList());
m_devicesFutureWatcher.setFuture(Utils::runAsync([this]() {
return m_androidConfig.connectedDevices();
}));
}
} }
void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::Ptr &device) IDevice::DeviceState AndroidDeviceManager::getDeviceState(const QString &serial,
IDevice::MachineType type) const
{ {
const AndroidDevice *dev = static_cast<AndroidDevice *>(device.data()); const QStringList args = AndroidDeviceInfo::adbSelector(serial) << "shell" << "echo 1";
const SdkToolResult result = AndroidManager::runAdbCommand(args);
if (result.success())
return IDevice::DeviceReadyToUse;
else if (type == IDevice::Emulator || result.stdErr().contains("unauthorized"))
return IDevice::DeviceConnected;
return IDevice::DeviceDisconnected;
}
void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::ConstPtr &device)
{
const AndroidDevice *dev = static_cast<const AndroidDevice *>(device.data());
const QString serial = dev->serialNumber(); const QString serial = dev->serialNumber();
DeviceManager *const devMgr = DeviceManager::instance(); DeviceManager *const devMgr = DeviceManager::instance();
const Utils::Id id = dev->id(); const Utils::Id id = dev->id();
@@ -457,15 +450,7 @@ void AndroidDeviceManager::updateDeviceState(const ProjectExplorer::IDevice::Ptr
return; return;
} }
const QStringList args = AndroidDeviceInfo::adbSelector(serial) << "shell" << "echo" << "1"; devMgr->setDeviceState(id, getDeviceState(serial, dev->machineType()));
const SdkToolResult result = AndroidManager::runAdbCommand(args);
const int success = result.success();
if (success)
devMgr->setDeviceState(id, IDevice::DeviceReadyToUse);
else if (dev->machineType() == IDevice::Emulator || result.stdErr().contains("unauthorized"))
devMgr->setDeviceState(id, IDevice::DeviceConnected);
else
devMgr->setDeviceState(id, IDevice::DeviceDisconnected);
} }
void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent) void AndroidDeviceManager::startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent)
@@ -523,6 +508,13 @@ void AndroidDeviceManager::handleAvdRemoved()
} }
} }
QString AndroidDeviceManager::emulatorName(const QString &serialNumber) const
{
QStringList args = AndroidDeviceInfo::adbSelector(serialNumber);
args.append({"emu", "avd", "name"});
return AndroidManager::runAdbCommand(args).stdOut();
}
void AndroidDeviceManager::setEmulatorArguments(QWidget *parent) void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
{ {
const QString helpUrl = const QString helpUrl =
@@ -546,73 +538,122 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
m_androidConfig.setEmulatorArgs(Utils::ProcessArgs::splitArgs(dialog.textValue())); m_androidConfig.setEmulatorArgs(Utils::ProcessArgs::splitArgs(dialog.textValue()));
} }
QString AndroidDeviceManager::getRunningAvdsSerialNumber(const QString &name) const
{
for (const AndroidDeviceInfo &dev : m_androidConfig.connectedDevices()) {
if (!dev.serialNumber.startsWith("emulator"))
continue;
const QString stdOut = emulatorName(dev.serialNumber);
if (stdOut.isEmpty())
continue; // Not an avd
const QStringList outputLines = stdOut.split('\n');
if (outputLines.size() > 1 && outputLines.first() == name)
return dev.serialNumber;
}
return {};
}
void AndroidDeviceManager::setupDevicesWatcher() void AndroidDeviceManager::setupDevicesWatcher()
{ {
if (!m_devicesUpdaterTimer.isActive()) { if (!m_androidConfig.adbToolPath().exists()) {
// The call to avdmanager is always slower than the call to adb devices, qCDebug(androidDeviceLog) << "Cannot start ADB device watcher"
// so connecting the slot to the slower call should be enough. << "because adb path does not exist.";
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished, return;
this, &AndroidDeviceManager::devicesListUpdated); }
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
updateDevicesList(); if (!m_adbDeviceWatcherProcess)
m_adbDeviceWatcherProcess.reset(new Utils::QtcProcess(this));
if (m_adbDeviceWatcherProcess->isRunning()) {
qCDebug(androidDeviceLog) << "ADB device watcher is already running.";
return;
}
connect(m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::finished, this,
[]() { qCDebug(androidDeviceLog) << "ADB device watcher finished."; });
connect(m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::errorOccurred, this,
[this](QProcess::ProcessError) {
qCDebug(androidDeviceLog) << "ADB device watcher encountered an error:"
<< m_adbDeviceWatcherProcess->errorString();
if (!m_adbDeviceWatcherProcess->isRunning()) {
qCDebug(androidDeviceLog) << "Restarting the ADB device watcher now.";
QTimer::singleShot(0, m_adbDeviceWatcherProcess.get(), &Utils::QtcProcess::start);
}
}); });
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
m_adbDeviceWatcherProcess->setStdErrLineCallback([](const QString &error) {
qCDebug(androidDeviceLog) << "ADB device watcher error" << error; });
m_adbDeviceWatcherProcess->setStdOutLineCallback([this](const QString &output) {
HandleDevicesListChange(output);
});
const Utils::CommandLine command = Utils::CommandLine(m_androidConfig.adbToolPath(),
{"track-devices"});
m_adbDeviceWatcherProcess->setCommand(command);
m_adbDeviceWatcherProcess->setEnvironment(AndroidConfigurations::toolsEnvironment(m_androidConfig));
m_adbDeviceWatcherProcess->start();
// Setup AVD filesystem watcher to listen for changes when an avd is created/deleted,
// or started/stopped
QString avdEnvVar = qEnvironmentVariable("ANDROID_AVD_HOME");
if (avdEnvVar.isEmpty()) {
avdEnvVar = qEnvironmentVariable("ANDROID_SDK_HOME");
if (avdEnvVar.isEmpty())
avdEnvVar = qEnvironmentVariable("HOME");
avdEnvVar.append("/.android/avd");
} }
updateDevicesListOnce(); const Utils::FilePath avdPath = Utils::FilePath::fromUserInput(avdEnvVar);
m_avdFileSystemWatcher.addPath(avdPath.toString());
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
this, &AndroidDeviceManager::HandleAvdsListChange);
connect(&m_avdFileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, [this]() {
// If the avd list upate command is running no need to call it again.
if (!m_avdsFutureWatcher.isRunning())
updateAvdsList();
});
// Call initial update
updateAvdsList();
} }
void AndroidDeviceManager::devicesListUpdated() void AndroidDeviceManager::HandleAvdsListChange()
{ {
QVector<AndroidDeviceInfo> connectedDevicesInfos;
connectedDevicesInfos = m_devicesFutureWatcher.result();
// For checking the state of avds, since running avds are assigned a serial number of
// the form emulator-xxxx, thus we have to manually check for the names.
const QStringList runningAvds = m_androidConfig.getRunningAvdsFromDevices(connectedDevicesInfos);
AndroidDeviceInfoList devices = m_avdsFutureWatcher.result();
const QSet<QString> startedAvds = Utils::transform<QSet>(connectedDevicesInfos,
&AndroidDeviceInfo::avdname);
for (const AndroidDeviceInfo &dev : devices)
if (!startedAvds.contains(dev.avdname))
connectedDevicesInfos << dev;
DeviceManager *const devMgr = DeviceManager::instance(); DeviceManager *const devMgr = DeviceManager::instance();
QVector<IDevice::ConstPtr> existingDevs; QVector<IDevice::ConstPtr> existingAvds;
QVector<IDevice::ConstPtr> connectedDevs;
for (int i = 0; i < devMgr->deviceCount(); ++i) { for (int i = 0; i < devMgr->deviceCount(); ++i) {
const IDevice::ConstPtr dev = devMgr->deviceAt(i); const IDevice::ConstPtr dev = devMgr->deviceAt(i);
if (dev->id().toString().startsWith(Constants::ANDROID_DEVICE_ID)) { const bool isEmulator = dev->machineType() == IDevice::Emulator;
existingDevs.append(dev); if (isEmulator && dev->type() == Constants::ANDROID_DEVICE_TYPE)
} existingAvds.append(dev);
} }
for (auto item : connectedDevicesInfos) { QVector<IDevice::ConstPtr> connectedDevs;
for (auto item : m_avdsFutureWatcher.result()) {
const Utils::Id deviceId = AndroidDevice::idFromDeviceInfo(item); const Utils::Id deviceId = AndroidDevice::idFromDeviceInfo(item);
const QString displayName = AndroidDevice::displayNameFromInfo(item); const QString displayName = AndroidDevice::displayNameFromInfo(item);
IDevice::ConstPtr dev = devMgr->find(deviceId); IDevice::ConstPtr dev = devMgr->find(deviceId);
if (!dev.isNull()) { if (!dev.isNull()) {
if (dev->displayName() == displayName) { const auto androidDev = static_cast<const AndroidDevice *>(dev.data());
IDevice::DeviceState newState; // DeviceManager doens't seem to hav a way to directly update the name, if the name
// If an AVD is not already running set its state to Connected instead of // of the device has changed, remove it and register it again with the new name.
// ReadyToUse. // Also account for the case of an AVD registered through old QC which might have
if (dev->machineType() == IDevice::Emulator && !runningAvds.contains(displayName)) // invalid data by checking the sdcard size value.
newState = IDevice::DeviceConnected; if (dev->displayName() != displayName
else || androidDev->sdcardSize() == AndroidDevice::tr("Unknown")) {
newState = item.state; devMgr->removeDevice(dev->id());
if (dev->deviceState() != newState) { } else {
// Find the state of the AVD retrieved from the AVD watcher
const QString serial = getRunningAvdsSerialNumber(item.avdname);
const IDevice::DeviceState state = getDeviceState(serial, IDevice::Emulator);
if (dev->deviceState() != state) {
devMgr->setDeviceState(dev->id(), state);
qCDebug(androidDeviceLog, "Device id \"%s\" changed its state.", qCDebug(androidDeviceLog, "Device id \"%s\" changed its state.",
dev->id().toString().toUtf8().data()); dev->id().toString().toUtf8().data());
devMgr->setDeviceState(dev->id(), newState);
} }
connectedDevs.append(dev); connectedDevs.append(dev);
continue; continue;
} else {
// DeviceManager doens't seem to hav a way to directly update the name, if the name
// of the device has changed, remove it and register it again with the new name.
devMgr->removeDevice(dev->id());
} }
} }
@@ -625,17 +666,86 @@ void AndroidDeviceManager::devicesListUpdated()
qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".", qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".",
newDev->id().toString().toUtf8().data()); newDev->id().toString().toUtf8().data());
const IDevice::ConstPtr constNewDev = IDevice::ConstPtr(newDev); const IDevice::ConstPtr constNewDev = IDevice::ConstPtr(newDev);
devMgr->addDevice(constNewDev); devMgr->addDevice(IDevice::ConstPtr(constNewDev));
connectedDevs.append(constNewDev); connectedDevs.append(constNewDev);
}
// Set devices no longer connected to disconnected state. // Set devices no longer connected to disconnected state.
for (const IDevice::ConstPtr &dev : existingDevs) { for (const IDevice::ConstPtr &dev : existingAvds) {
if (dev->id() != Constants::ANDROID_DEVICE_ID && !connectedDevs.contains(dev) if (!connectedDevs.contains(dev)) {
&& dev->deviceState() != IDevice::DeviceDisconnected) { qCDebug(androidDeviceLog, "Removing AVD id \"%s\" because it no longer exists.",
qCDebug(androidDeviceLog, "Device id \"%s\" is no longer connected.",
dev->id().toString().toUtf8().data()); dev->id().toString().toUtf8().data());
devMgr->setDeviceState(dev->id(), IDevice::DeviceDisconnected); devMgr->removeDevice(dev->id());
}
}
}
}
void AndroidDeviceManager::HandleDevicesListChange(const QString &serialNumber)
{
DeviceManager *const devMgr = DeviceManager::instance();
const QStringList serialBits = serialNumber.split('\t');
if (serialBits.size() < 2)
return;
// Sample output of adb track-devices, the first 4 digits are for state type
// and sometimes 4 zeros are reported as part for the serial number.
// 00546db0e8d7 authorizing
// 00546db0e8d7 device
// 0000001711201JEC207789 offline
// emulator-5554 device
QString dirtySerial = serialBits.first().trimmed();
if (dirtySerial.startsWith("0000"))
dirtySerial = dirtySerial.mid(4);
if (dirtySerial.startsWith("00"))
dirtySerial = dirtySerial.mid(4);
const bool isEmulator = dirtySerial.startsWith("emulator");
const QString &serial = dirtySerial;
const QString stateStr = serialBits.at(1).trimmed();
IDevice::DeviceState state;
if (stateStr == "device")
state = IDevice::DeviceReadyToUse;
else if (stateStr == "offline")
state = IDevice::DeviceDisconnected;
else
state = IDevice::DeviceConnected;
if (isEmulator) {
const QString avdName = emulatorName(serial);
const Utils::Id avdId = Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + avdName);
devMgr->setDeviceState(avdId, state);
} else {
const Utils::Id id = Utils::Id(Constants::ANDROID_DEVICE_ID).withSuffix(':' + serial);
QString displayName = AndroidConfigurations::currentConfig().getProductModel(serial);
// Check if the device is connected via WiFi. A sample serial of such devices can be
// like: "192.168.1.190:5555"
const QRegularExpression wifiSerialRegExp(
QLatin1String("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}):(\\d{1,5})"));
if (wifiSerialRegExp.match(serial).hasMatch())
displayName += QLatin1String(" (WiFi)");
if (IDevice::ConstPtr dev = devMgr->find(id)) {
// DeviceManager doens't seem to have a way to directly update the name, if the name
// of the device has changed, remove it and register it again with the new name.
if (dev->displayName() == displayName)
devMgr->setDeviceState(id, state);
else
devMgr->removeDevice(id);
} else {
AndroidDevice *newDev = new AndroidDevice();
newDev->setupId(IDevice::AutoDetected, id);
newDev->setDisplayName(displayName);
newDev->setMachineType(IDevice::Hardware);
newDev->setDeviceState(state);
newDev->setExtraData(Constants::AndroidSerialNumber, serial);
newDev->setExtraData(Constants::AndroidCpuAbi, m_androidConfig.getAbis(serial));
newDev->setExtraData(Constants::AndroidSdk, m_androidConfig.getSDKVersion(serial));
qCDebug(androidDeviceLog, "Registering new Android device id \"%s\".",
newDev->id().toString().toUtf8().data());
devMgr->addDevice(IDevice::ConstPtr(newDev));
} }
} }
} }
@@ -652,9 +762,12 @@ AndroidDeviceManager::AndroidDeviceManager(QObject *parent)
m_avdManager(m_androidConfig) m_avdManager(m_androidConfig)
{ {
connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() { connect(qApp, &QCoreApplication::aboutToQuit, this, [this]() {
m_devicesUpdaterTimer.stop(); if (m_adbDeviceWatcherProcess) {
m_adbDeviceWatcherProcess->terminate();
m_adbDeviceWatcherProcess->waitForFinished();
m_adbDeviceWatcherProcess.reset();
}
m_avdsFutureWatcher.waitForFinished(); m_avdsFutureWatcher.waitForFinished();
m_devicesFutureWatcher.waitForFinished();
m_removeAvdFutureWatcher.waitForFinished(); m_removeAvdFutureWatcher.waitForFinished();
}); });

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2022 The Qt Company Ltd.
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com> ** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@@ -33,8 +33,10 @@
#include <projectexplorer/devicesupport/idevice.h> #include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/devicesupport/idevicefactory.h> #include <projectexplorer/devicesupport/idevicefactory.h>
#include <utils/qtcprocess.h>
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QTimer> #include <QFileSystemWatcher>
namespace Android { namespace Android {
namespace Internal { namespace Internal {
@@ -70,6 +72,7 @@ public:
QString androidTargetName() const; QString androidTargetName() const;
QString sdcardSize() const; QString sdcardSize() const;
QString openGlStatusString() const; QString openGlStatusString() const;
// TODO: remove not used
AndroidConfig::OpenGl openGlStatus() const; AndroidConfig::OpenGl openGlStatus() const;
protected: protected:
@@ -98,24 +101,29 @@ class AndroidDeviceManager : public QObject
public: public:
static AndroidDeviceManager *instance(); static AndroidDeviceManager *instance();
void setupDevicesWatcher(); void setupDevicesWatcher();
void updateDevicesList(); void updateAvdsList();
void updateDevicesListOnce(); IDevice::DeviceState getDeviceState(const QString &serial, IDevice::MachineType type) const;
void updateDeviceState(const ProjectExplorer::IDevice::Ptr &device); void updateDeviceState(const ProjectExplorer::IDevice::ConstPtr &device);
void startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr); void startAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
void eraseAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr); void eraseAvd(const ProjectExplorer::IDevice::Ptr &device, QWidget *parent = nullptr);
void setEmulatorArguments(QWidget *parent = nullptr); void setEmulatorArguments(QWidget *parent = nullptr);
QString getRunningAvdsSerialNumber(const QString &name) const;
private: private:
AndroidDeviceManager(QObject *parent = nullptr); AndroidDeviceManager(QObject *parent = nullptr);
void devicesListUpdated(); void HandleDevicesListChange(const QString &serialNumber);
void HandleAvdsListChange();
void handleAvdRemoved(); void handleAvdRemoved();
QString emulatorName(const QString &serialNumber) const;
QFutureWatcher<AndroidDeviceInfoList> m_avdsFutureWatcher; QFutureWatcher<AndroidDeviceInfoList> m_avdsFutureWatcher;
QFutureWatcher<QVector<AndroidDeviceInfo>> m_devicesFutureWatcher;
QFutureWatcher<QPair<ProjectExplorer::IDevice::ConstPtr, bool>> m_removeAvdFutureWatcher; QFutureWatcher<QPair<ProjectExplorer::IDevice::ConstPtr, bool>> m_removeAvdFutureWatcher;
QTimer m_devicesUpdaterTimer; QFileSystemWatcher m_avdFileSystemWatcher;
std::unique_ptr<Utils::QtcProcess> m_adbDeviceWatcherProcess;
AndroidConfig &m_androidConfig; AndroidConfig &m_androidConfig;
AndroidAvdManager m_avdManager; AndroidAvdManager m_avdManager;
}; };

View File

@@ -2779,6 +2779,8 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|| path.rbegin()->kind() == "CXXConstruct")) { || path.rbegin()->kind() == "CXXConstruct")) {
return false; return false;
} }
if (path.rbegin()->hasConstType())
return false;
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) { for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
if (it->kind() == "Call" || it->kind() == "CXXConstruct" if (it->kind() == "Call" || it->kind() == "CXXConstruct"
|| it->kind() == "MemberInitializer") { || it->kind() == "MemberInitializer") {
@@ -2810,8 +2812,9 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
const AstNode n = firstChildTree.takeFirst(); const AstNode n = firstChildTree.takeFirst();
const QString detail = n.detail().value_or(QString()); const QString detail = n.detail().value_or(QString());
if (detail.startsWith("operator")) { if (detail.startsWith("operator")) {
return !detail.contains('=') && !detail.contains("++") return !detail.contains('=')
&& !detail.contains("--"); && !detail.contains("++") && !detail.contains("--")
&& !detail.contains("<<") && !detail.contains(">>");
} }
firstChildTree << n.children().value_or(QList<AstNode>()); firstChildTree << n.children().value_or(QList<AstNode>());
} }
@@ -4122,7 +4125,7 @@ class MemoryTreeModel : public Utils::BaseTreeModel
public: public:
MemoryTreeModel(QObject *parent) : BaseTreeModel(parent) MemoryTreeModel(QObject *parent) : BaseTreeModel(parent)
{ {
setHeader({tr("Component"), tr("Total Memory")}); setHeader({MemoryUsageWidget::tr("Component"), MemoryUsageWidget::tr("Total Memory")});
} }
void update(const MemoryTree &tree) void update(const MemoryTree &tree)

View File

@@ -1295,6 +1295,13 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("keywords: true") << 920 << 15 << 920 << 19 << QList<int>{C_KEYWORD} << 0; QTest::newRow("keywords: true") << 920 << 15 << 920 << 19 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("keywords: false") << 921 << 15 << 921 << 20 << QList<int>{C_KEYWORD} << 0; QTest::newRow("keywords: false") << 921 << 15 << 921 << 20 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("keywords: nullptr") << 922 << 15 << 922 << 22 << QList<int>{C_KEYWORD} << 0; QTest::newRow("keywords: nullptr") << 922 << 15 << 922 << 22 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("operator<<") << 934 << 10 << 934 << 14 << QList<int>{C_GLOBAL} << 0;
QTest::newRow("operator>>") << 936 << 10 << 936 << 13 << QList<int>{C_GLOBAL} << 0;
QTest::newRow("operator>>") << 936 << 17 << 936 << 18 << QList<int>{C_LOCAL} << 0;
QTest::newRow("input arg from passed object") << 945 << 17 << 945 << 18
<< QList<int>{C_FIELD} << 0;
QTest::newRow("output arg") << 945 << 20 << 945 << 23
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
} }
void ClangdTestHighlighting::test() void ClangdTestHighlighting::test()

View File

@@ -921,3 +921,26 @@ void keywords()
bool b2 = false; bool b2 = false;
void *p = nullptr; void *p = nullptr;
} }
namespace std {
struct Debug {};
Debug& operator<<(Debug &dbg, int) { return dbg; }
Debug& operator>>(Debug &dbg, int&) { return dbg; }
static Debug cout;
static Debug cin;
}
void outputOperator()
{
std::cout << 0;
int i;
std::cin >> i;
}
template <typename To, typename From, typename Op>
void transform(const From &from, To &&to, Op op) {}
struct WithVector { std::vector<int> v; };
void inputsAndOutputsFromObject(const WithVector &s)
{
std::vector<int> out;
transform(s.v, out, [] {});
}

View File

@@ -268,7 +268,7 @@ bool ConfigModel::hasChanges(bool initialParameters) const
return initialParameters ? i.isInitial : !i.isInitial; return initialParameters ? i.isInitial : !i.isInitial;
}); });
return Utils::contains(filtered, [initialParameters](const InternalDataItem &i) { return Utils::contains(filtered, [](const InternalDataItem &i) {
return i.isUserChanged || i.isUserNew || i.isUnset; return i.isUserChanged || i.isUserNew || i.isUnset;
}); });
} }

View File

@@ -40,7 +40,6 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/settingsutils.h> #include <utils/settingsutils.h>
static const char groupPostfix[] = "IndentSettings";
static const char indentBlockBracesKey[] = "IndentBlockBraces"; static const char indentBlockBracesKey[] = "IndentBlockBraces";
static const char indentBlockBodyKey[] = "IndentBlockBody"; static const char indentBlockBodyKey[] = "IndentBlockBody";
static const char indentClassBracesKey[] = "IndentClassBraces"; static const char indentClassBracesKey[] = "IndentClassBraces";

View File

@@ -276,8 +276,6 @@ void ImageView::doScale(qreal factor)
void ImageView::wheelEvent(QWheelEvent *event) void ImageView::wheelEvent(QWheelEvent *event)
{ {
qreal factor = qPow(Constants::DEFAULT_SCALE_FACTOR, event->angleDelta().y() / 240.0); qreal factor = qPow(Constants::DEFAULT_SCALE_FACTOR, event->angleDelta().y() / 240.0);
qreal currentScale = transform().m11();
qreal newScale = currentScale * factor;
// cap to 0.001 - 1000 // cap to 0.001 - 1000
qreal actualFactor = qBound(0.001, factor, 1000.0); qreal actualFactor = qBound(0.001, factor, 1000.0);
doScale(actualFactor); doScale(actualFactor);

View File

@@ -622,7 +622,7 @@ void Client::activateDocument(TextEditor::TextDocument *document)
void Client::deactivateDocument(TextEditor::TextDocument *document) void Client::deactivateDocument(TextEditor::TextDocument *document)
{ {
m_diagnosticManager.hideDiagnostics(document); m_diagnosticManager.hideDiagnostics(document->filePath());
resetAssistProviders(document); resetAssistProviders(document);
document->setFormatter(nullptr); document->setFormatter(nullptr);
m_tokenSupport.clearHighlight(document); m_tokenSupport.clearHighlight(document);
@@ -1628,12 +1628,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
m_shutdownTimer.stop(); m_shutdownTimer.stop();
QTC_ASSERT(m_state == ShutdownRequested, return); QTC_ASSERT(m_state == ShutdownRequested, return);
QTC_ASSERT(m_clientInterface, return); QTC_ASSERT(m_clientInterface, return);
optional<ShutdownRequest::Response::Error> errorValue = shutdownResponse.error(); if (optional<ShutdownRequest::Response::Error> error = shutdownResponse.error())
if (errorValue.has_value()) { log(*error);
ShutdownRequest::Response::Error error = errorValue.value();
qDebug() << error;
return;
}
// directly send message otherwise the state check of sendContent would fail // directly send message otherwise the state check of sendContent would fail
sendMessage(ExitNotification().toBaseMessage()); sendMessage(ExitNotification().toBaseMessage());
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown"; qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown";

View File

@@ -88,26 +88,19 @@ void DiagnosticManager::setDiagnostics(const LanguageServerProtocol::DocumentUri
const QList<LanguageServerProtocol::Diagnostic> &diagnostics, const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
const Utils::optional<int> &version) const Utils::optional<int> &version)
{ {
removeDiagnostics(uri); hideDiagnostics(uri.toFilePath());
m_diagnostics[uri] = {version, diagnostics}; m_diagnostics[uri] = {version, diagnostics};
} }
void DiagnosticManager::hideDiagnostics(TextDocument *doc) void DiagnosticManager::hideDiagnostics(const Utils::FilePath &filePath)
{ {
if (!doc)
return;
if (m_hideHandler) if (m_hideHandler)
m_hideHandler(); m_hideHandler();
if (auto doc = TextDocument::textDocumentForFilePath(filePath)) {
for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc)) for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc))
editor->editorWidget()->setExtraSelections(TextEditorWidget::CodeWarningsSelection, {}); editor->editorWidget()->setExtraSelections(TextEditorWidget::CodeWarningsSelection, {});
qDeleteAll(Utils::filtered(doc->marks(), Utils::equal(&TextMark::category, m_client->id())));
} }
qDeleteAll(m_marks.take(filePath));
void DiagnosticManager::removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri)
{
hideDiagnostics(TextDocument::textDocumentForFilePath(uri.toFilePath()));
m_diagnostics.remove(uri);
} }
static QTextEdit::ExtraSelection toDiagnosticsSelections(const Diagnostic &diagnostic, static QTextEdit::ExtraSelection toDiagnosticsSelections(const Diagnostic &diagnostic,
@@ -134,7 +127,7 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
if (versionedDiagnostics.version.value_or(version) == version) { if (versionedDiagnostics.version.value_or(version) == version) {
for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) { for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) {
extraSelections << toDiagnosticsSelections(diagnostic, doc->document()); extraSelections << toDiagnosticsSelections(diagnostic, doc->document());
doc->addMark(m_textMarkCreator(filePath, diagnostic)); m_marks[filePath].append(m_textMarkCreator(filePath, diagnostic));
} }
} }
@@ -164,7 +157,13 @@ TextEditor::TextMark *DiagnosticManager::createTextMark(const FilePath &filePath
void DiagnosticManager::clearDiagnostics() void DiagnosticManager::clearDiagnostics()
{ {
for (const DocumentUri &uri : m_diagnostics.keys()) for (const DocumentUri &uri : m_diagnostics.keys())
removeDiagnostics(uri); hideDiagnostics(uri.toFilePath());
m_diagnostics.clear();
if (!QTC_GUARD(m_marks.isEmpty())) {
for (const QList<TextEditor::TextMark *> &marks : qAsConst(m_marks))
qDeleteAll(marks);
m_marks.clear();
}
} }
QList<Diagnostic> DiagnosticManager::diagnosticsAt(const DocumentUri &uri, QList<Diagnostic> DiagnosticManager::diagnosticsAt(const DocumentUri &uri,

View File

@@ -56,10 +56,9 @@ public:
void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri, void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics, const QList<LanguageServerProtocol::Diagnostic> &diagnostics,
const Utils::optional<int> &version); const Utils::optional<int> &version);
void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri);
void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version); void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version);
void hideDiagnostics(TextEditor::TextDocument *doc); void hideDiagnostics(const Utils::FilePath &filePath);
void clearDiagnostics(); void clearDiagnostics();
@@ -81,6 +80,7 @@ private:
QList<LanguageServerProtocol::Diagnostic> diagnostics; QList<LanguageServerProtocol::Diagnostic> diagnostics;
}; };
QMap<LanguageServerProtocol::DocumentUri, VersionedDiagnostics> m_diagnostics; QMap<LanguageServerProtocol::DocumentUri, VersionedDiagnostics> m_diagnostics;
QMap<Utils::FilePath, QList<TextEditor::TextMark *>> m_marks;
TextMarkCreator m_textMarkCreator; TextMarkCreator m_textMarkCreator;
HideDiagnosticsHandler m_hideHandler; HideDiagnosticsHandler m_hideHandler;
Client *m_client; Client *m_client;

View File

@@ -427,7 +427,7 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse(
items = Utils::get<QList<CompletionItem>>(*result); items = Utils::get<QList<CompletionItem>>(*result);
} }
auto proposalItems = generateCompletionItems(items); auto proposalItems = generateCompletionItems(items);
if (!proposalItems.isEmpty() && !m_snippetsGroup.isEmpty()) { if (!m_snippetsGroup.isEmpty()) {
proposalItems << TextEditor::SnippetAssistCollector( proposalItems << TextEditor::SnippetAssistCollector(
m_snippetsGroup, QIcon(":/texteditor/images/snippet.png")).collect(); m_snippetsGroup, QIcon(":/texteditor/images/snippet.png")).collect();
} }

View File

@@ -45,22 +45,22 @@ public:
ValidPackage ValidPackage
}; };
virtual QString label() const = 0;
virtual const QString &environmentVariableName() const = 0;
virtual bool isAddToSystemPath() const = 0;
virtual void setVersions(const QStringList &) = 0;
virtual Utils::FilePath basePath() const = 0; virtual Utils::FilePath basePath() const = 0;
virtual Utils::FilePath path() const = 0; virtual Utils::FilePath path() const = 0;
virtual QString label() const = 0;
virtual Utils::FilePath defaultPath() const = 0; virtual Utils::FilePath defaultPath() const = 0;
virtual QString detectionPath() const = 0; virtual Utils::FilePath detectionPath() const = 0;
virtual QString statusText() const = 0;
virtual void updateStatus() = 0;
virtual void updateStatus() = 0;
virtual Status status() const = 0; virtual Status status() const = 0;
virtual bool validStatus() const = 0; virtual QString statusText() const = 0;
virtual const QString &environmentVariableName() const = 0; virtual bool isValidStatus() const = 0;
virtual void setAddToPath(bool) = 0;
virtual bool addToPath() const = 0;
virtual bool writeToSettings() const = 0; virtual bool writeToSettings() const = 0;
virtual void setRelativePathModifier(const QString &) = 0;
virtual void setVersions(const QStringList &) = 0;
virtual QWidget *widget() = 0; virtual QWidget *widget() = 0;

View File

@@ -57,30 +57,21 @@ namespace McuKitManager {
static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change
static FilePath qulDocsDir()
{
const FilePath qulDir = McuSupportOptions::qulDirFromSettings();
if (qulDir.isEmpty() || !qulDir.exists())
return {};
const FilePath docsDir = qulDir.pathAppended("docs");
return docsDir.exists() ? docsDir : FilePath();
}
static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage) static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
{ {
switch (tcPackage->type()) { switch (tcPackage->toolchainType()) {
case McuToolChainPackage::Type::Unsupported: case McuToolChainPackage::ToolChainType::Unsupported:
return; return;
case McuToolChainPackage::Type::GHS: case McuToolChainPackage::ToolChainType::GHS:
case McuToolChainPackage::Type::GHSArm: case McuToolChainPackage::ToolChainType::GHSArm:
return; // No Green Hills toolchain, because support for it is missing. return; // No Green Hills toolchain, because support for it is missing.
case McuToolChainPackage::Type::IAR: case McuToolChainPackage::ToolChainType::IAR:
case McuToolChainPackage::Type::KEIL: case McuToolChainPackage::ToolChainType::KEIL:
case McuToolChainPackage::Type::MSVC: case McuToolChainPackage::ToolChainType::MSVC:
case McuToolChainPackage::Type::GCC: case McuToolChainPackage::ToolChainType::GCC:
case McuToolChainPackage::Type::ArmGcc: case McuToolChainPackage::ToolChainType::ArmGcc:
ToolChainKitAspect::setToolChain(k, ToolChainKitAspect::setToolChain(k,
tcPackage->toolChain( tcPackage->toolChain(
ProjectExplorer::Constants::C_LANGUAGE_ID)); ProjectExplorer::Constants::C_LANGUAGE_ID));
@@ -136,17 +127,17 @@ static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage)
return; return;
} }
switch (tcPackage->type()) { switch (tcPackage->toolchainType()) {
case McuToolChainPackage::Type::Unsupported: case McuToolChainPackage::ToolChainType::Unsupported:
case McuToolChainPackage::Type::GHS: case McuToolChainPackage::ToolChainType::GHS:
case McuToolChainPackage::Type::GHSArm: case McuToolChainPackage::ToolChainType::GHSArm:
case McuToolChainPackage::Type::IAR: case McuToolChainPackage::ToolChainType::IAR:
return; // No Green Hills and IAR debugger, because support for it is missing. return; // No Green Hills and IAR debugger, because support for it is missing.
case McuToolChainPackage::Type::KEIL: case McuToolChainPackage::ToolChainType::KEIL:
case McuToolChainPackage::Type::MSVC: case McuToolChainPackage::ToolChainType::MSVC:
case McuToolChainPackage::Type::GCC: case McuToolChainPackage::ToolChainType::GCC:
case McuToolChainPackage::Type::ArmGcc: { case McuToolChainPackage::ToolChainType::ArmGcc: {
const QVariant debuggerId = tcPackage->debuggerId(); const QVariant debuggerId = tcPackage->debuggerId();
if (debuggerId.isValid()) { if (debuggerId.isValid()) {
Debugger::DebuggerKitAspect::setDebugger(k, debuggerId); Debugger::DebuggerKitAspect::setDebugger(k, debuggerId);
@@ -168,11 +159,6 @@ static void setKitDevice(Kit *k, const McuTarget *mcuTarget)
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE); DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
} }
static bool expectsCmakeVars(const McuTarget *mcuTarget)
{
return mcuTarget->qulVersion() >= QVersionNumber{2, 0};
}
static void setKitDependencies(Kit *k, static void setKitDependencies(Kit *k,
const McuTarget *mcuTarget, const McuTarget *mcuTarget,
const McuAbstractPackage *qtForMCUsSdkPackage) const McuAbstractPackage *qtForMCUsSdkPackage)
@@ -182,7 +168,7 @@ static void setKitDependencies(Kit *k,
auto processPackage = [&dependencies](const McuAbstractPackage *package) { auto processPackage = [&dependencies](const McuAbstractPackage *package) {
if (!package->environmentVariableName().isEmpty()) if (!package->environmentVariableName().isEmpty())
dependencies.append({package->environmentVariableName(), dependencies.append({package->environmentVariableName(),
QDir::toNativeSeparators(package->detectionPath())}); package->detectionPath().toUserOutput()});
}; };
for (auto package : mcuTarget->packages()) for (auto package : mcuTarget->packages())
processPackage(package); processPackage(package);
@@ -201,8 +187,8 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
// CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously // CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously
if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHS if (mcuTarget->toolChainPackage()->toolchainType() != McuToolChainPackage::ToolChainType::GHS
&& mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHSArm) { && mcuTarget->toolChainPackage()->toolchainType() != McuToolChainPackage::ToolChainType::GHSArm) {
config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}")); config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}"));
config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}")); config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}"));
} }
@@ -240,8 +226,8 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat
CMakeConfigurationKitAspect::setConfiguration(k, config); CMakeConfigurationKitAspect::setConfiguration(k, config);
if (HostOsInfo::isWindowsHost()) { if (HostOsInfo::isWindowsHost()) {
auto type = mcuTarget->toolChainPackage()->type(); auto type = mcuTarget->toolChainPackage()->toolchainType();
if (type == McuToolChainPackage::Type::GHS || type == McuToolChainPackage::Type::GHSArm) { if (type == McuToolChainPackage::ToolChainType::GHS || type == McuToolChainPackage::ToolChainType::GHSArm) {
// See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802 // See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802
// and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803 // and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803
CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM"); CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM");
@@ -389,13 +375,12 @@ void createAutomaticKits()
const auto createKits = [qtForMCUsPackage]() { const auto createKits = [qtForMCUsPackage]() {
if (McuSupportOptions::automaticKitCreationFromSettings()) { if (McuSupportOptions::automaticKitCreationFromSettings()) {
qtForMCUsPackage->updateStatus(); qtForMCUsPackage->updateStatus();
if (!qtForMCUsPackage->validStatus()) { if (!qtForMCUsPackage->isValidStatus()) {
switch (qtForMCUsPackage->status()) { switch (qtForMCUsPackage->status()) {
case McuAbstractPackage::Status::ValidPathInvalidPackage: { case McuAbstractPackage::Status::ValidPathInvalidPackage: {
const QString displayPath
= FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput();
printMessage(McuPackage::tr("Path %1 exists, but does not contain %2.") printMessage(McuPackage::tr("Path %1 exists, but does not contain %2.")
.arg(qtForMCUsPackage->path().toUserOutput(), displayPath), .arg(qtForMCUsPackage->path().toUserOutput(),
qtForMCUsPackage->detectionPath().toUserOutput()),
true); true);
break; break;
} }
@@ -408,7 +393,7 @@ void createAutomaticKits()
} }
case McuAbstractPackage::Status::EmptyPath: { case McuAbstractPackage::Status::EmptyPath: {
printMessage(McuPackage::tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") printMessage(McuPackage::tr("Missing %1. Add the path in Tools > Options > Devices > MCU.")
.arg(qtForMCUsPackage->detectionPath()), .arg(qtForMCUsPackage->detectionPath().toUserOutput()),
true); true);
return; return;
} }
@@ -575,7 +560,7 @@ void fixExistingKits()
// Fix kit dependencies for known targets // Fix kit dependencies for known targets
auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); auto qtForMCUsPackage = Sdk::createQtForMCUsPackage();
qtForMCUsPackage->updateStatus(); qtForMCUsPackage->updateStatus();
if (qtForMCUsPackage->validStatus()) { if (qtForMCUsPackage->isValidStatus()) {
FilePath dir = qtForMCUsPackage->path(); FilePath dir = qtForMCUsPackage->path();
McuSdkRepository repo; McuSdkRepository repo;
Sdk::targetsAndPackages(dir, &repo); Sdk::targetsAndPackages(dir, &repo);

View File

@@ -28,37 +28,69 @@
#include "mcusupportversiondetection.h" #include "mcusupportversiondetection.h"
#include "mcusupportsdk.h" #include "mcusupportsdk.h"
#include <baremetal/baremetalconstants.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/algorithm.h>
#include <utils/infolabel.h> #include <utils/infolabel.h>
#include <utils/pathchooser.h> #include <utils/pathchooser.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainmanager.h>
#include <debugger/debuggeritem.h>
#include <debugger/debuggeritemmanager.h>
#include <QDesktopServices> #include <QDesktopServices>
#include <QGridLayout> #include <QGridLayout>
#include <QToolButton> #include <QToolButton>
using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace McuSupport::Internal { namespace McuSupport::Internal {
McuPackage::McuPackage(const QString &label, McuPackage::McuPackage(const QString &label,
const FilePath &defaultPath, const FilePath &defaultPath,
const QString &detectionPath, const FilePath &detectionPath,
const QString &settingsKey, const QString &settingsKey,
const QString &envVarName, const QString &envVarName,
const QString &downloadUrl, const QString &downloadUrl,
const McuPackageVersionDetector *versionDetector) const McuPackageVersionDetector *versionDetector,
const bool addToSystemPath,
const FilePath &relativePathModifier)
: m_label(label) : m_label(label)
, m_defaultPath(Sdk::packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath)) , m_defaultPath(Sdk::packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath))
, m_detectionPath(detectionPath) , m_detectionPath(detectionPath)
, m_settingsKey(settingsKey) , m_settingsKey(settingsKey)
, m_versionDetector(versionDetector) , m_versionDetector(versionDetector)
, m_relativePathModifier(relativePathModifier)
, m_environmentVariableName(envVarName) , m_environmentVariableName(envVarName)
, m_downloadUrl(downloadUrl) , m_downloadUrl(downloadUrl)
, m_addToSystemPath(addToSystemPath)
{ {
m_path = Sdk::packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath); m_path = Sdk::packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath);
} }
QString McuPackage::label() const
{
return m_label;
}
const QString &McuPackage::environmentVariableName() const
{
return m_environmentVariableName;
}
bool McuPackage::isAddToSystemPath() const
{
return m_addToSystemPath;
}
void McuPackage::setVersions(const QStringList &versions)
{
m_versions = versions;
}
FilePath McuPackage::basePath() const FilePath McuPackage::basePath() const
{ {
return m_fileChooser != nullptr ? m_fileChooser->filePath() : m_path; return m_fileChooser != nullptr ? m_fileChooser->filePath() : m_path;
@@ -69,21 +101,131 @@ FilePath McuPackage::path() const
return basePath().resolvePath(m_relativePathModifier).absoluteFilePath(); return basePath().resolvePath(m_relativePathModifier).absoluteFilePath();
} }
QString McuPackage::label() const
{
return m_label;
}
FilePath McuPackage::defaultPath() const FilePath McuPackage::defaultPath() const
{ {
return m_defaultPath; return m_defaultPath;
} }
QString McuPackage::detectionPath() const FilePath McuPackage::detectionPath() const
{ {
return m_detectionPath; return m_detectionPath;
} }
void McuPackage::updatePath()
{
m_path = m_fileChooser->rawFilePath();
m_fileChooser->lineEdit()->button(FancyLineEdit::Right)->setEnabled(m_path != m_defaultPath);
updateStatus();
}
void McuPackage::updateStatus()
{
bool validPath = !m_path.isEmpty() && m_path.exists();
const FilePath detectionPath = basePath().resolvePath(m_detectionPath);
const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists();
m_detectedVersion = validPath && validPackage && m_versionDetector
? m_versionDetector->parseVersion(basePath().toString())
: QString();
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|| m_versions.contains(m_detectedVersion);
m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage
: Status::ValidPackageMismatchedVersion)
: Status::ValidPathInvalidPackage)
: m_path.isEmpty() ? Status::EmptyPath
: Status::InvalidPath;
emit statusChanged();
}
McuPackage::Status McuPackage::status() const
{
return m_status;
}
bool McuPackage::isValidStatus() const
{
return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
}
void McuPackage::updateStatusUi()
{
switch (m_status) {
case Status::ValidPackage:
m_infoLabel->setType(InfoLabel::Ok);
break;
case Status::ValidPackageMismatchedVersion:
m_infoLabel->setType(InfoLabel::Warning);
break;
default:
m_infoLabel->setType(InfoLabel::NotOk);
break;
}
m_infoLabel->setText(statusText());
}
QString McuPackage::statusText() const
{
const QString displayPackagePath = m_path.toUserOutput();
const QString displayVersions = m_versions.join(" or ");
const QString outDetectionPath = m_detectionPath.toUserOutput();
const QString displayRequiredPath = m_versions.empty() ? outDetectionPath
: QString("%1 %2").arg(outDetectionPath,
displayVersions);
const QString displayDetectedPath = m_versions.empty()
? outDetectionPath
: QString("%1 %2").arg(outDetectionPath,
m_detectedVersion);
QString response;
switch (m_status) {
case Status::ValidPackage:
response = m_detectionPath.isEmpty()
? (m_detectedVersion.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath)
: tr("Path %1 exists. Version %2 was found.")
.arg(displayPackagePath, m_detectedVersion))
: tr("Path %1 is valid, %2 was found.")
.arg(displayPackagePath, displayDetectedPath);
break;
case Status::ValidPackageMismatchedVersion: {
const QString versionWarning
= m_versions.size() == 1
? tr("but only version %1 is supported").arg(m_versions.first())
: tr("but only versions %1 are supported").arg(displayVersions);
response = tr("Path %1 is valid, %2 was found, %3.")
.arg(displayPackagePath, displayDetectedPath, versionWarning);
break;
}
case Status::ValidPathInvalidPackage:
response = tr("Path %1 exists, but does not contain %2.")
.arg(displayPackagePath, displayRequiredPath);
break;
case Status::InvalidPath:
response = tr("Path %1 does not exist.").arg(displayPackagePath);
break;
case Status::EmptyPath:
response = m_detectionPath.isEmpty()
? tr("Path is empty.")
: tr("Path is empty, %1 not found.").arg(displayRequiredPath);
break;
}
return response;
}
bool McuPackage::writeToSettings() const
{
const FilePath savedPath = Sdk::packagePathFromSettings(m_settingsKey,
QSettings::UserScope,
m_defaultPath);
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
Core::ICore::settings()->setValueWithDefault(key, m_path.toString(), m_defaultPath.toString());
return savedPath != m_path;
}
QWidget *McuPackage::widget() QWidget *McuPackage::widget()
{ {
if (m_widget) if (m_widget)
@@ -127,164 +269,201 @@ QWidget *McuPackage::widget()
return m_widget; return m_widget;
} }
McuPackage::Status McuPackage::status() const
{
return m_status;
}
bool McuPackage::validStatus() const
{
return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
}
const QString &McuPackage::environmentVariableName() const
{
return m_environmentVariableName;
}
void McuPackage::setAddToPath(bool addToPath)
{
m_addToPath = addToPath;
}
bool McuPackage::addToPath() const
{
return m_addToPath;
}
bool McuPackage::writeToSettings() const
{
const FilePath savedPath = Sdk::packagePathFromSettings(m_settingsKey,
QSettings::UserScope,
m_defaultPath);
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/'
+ QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
Core::ICore::settings()->setValueWithDefault(key, m_path.toString(), m_defaultPath.toString());
return savedPath != m_path;
}
void McuPackage::setRelativePathModifier(const QString &path)
{
m_relativePathModifier = path;
}
void McuPackage::setVersions(const QStringList &versions)
{
m_versions = versions;
}
void McuPackage::updatePath()
{
m_path = m_fileChooser->rawFilePath();
m_fileChooser->lineEdit()->button(FancyLineEdit::Right)->setEnabled(m_path != m_defaultPath);
updateStatus();
}
void McuPackage::updateStatus()
{
bool validPath = !m_path.isEmpty() && m_path.exists();
const FilePath detectionPath = basePath() / m_detectionPath;
const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists();
m_detectedVersion = validPath && validPackage && m_versionDetector
? m_versionDetector->parseVersion(basePath().toString())
: QString();
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|| m_versions.contains(m_detectedVersion);
m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage
: Status::ValidPackageMismatchedVersion)
: Status::ValidPathInvalidPackage)
: m_path.isEmpty() ? Status::EmptyPath
: Status::InvalidPath;
emit statusChanged();
}
void McuPackage::updateStatusUi()
{
switch (m_status) {
case Status::ValidPackage:
m_infoLabel->setType(InfoLabel::Ok);
break;
case Status::ValidPackageMismatchedVersion:
m_infoLabel->setType(InfoLabel::Warning);
break;
default:
m_infoLabel->setType(InfoLabel::NotOk);
break;
}
m_infoLabel->setText(statusText());
}
QString McuPackage::statusText() const
{
const QString displayPackagePath = m_path.toUserOutput();
const QString displayVersions = m_versions.join(" or ");
const QString outDetectionPath = FilePath::fromString(m_detectionPath).toUserOutput();
const QString displayRequiredPath = m_versions.empty() ? outDetectionPath
: QString("%1 %2").arg(outDetectionPath,
displayVersions);
const QString displayDetectedPath = m_versions.empty()
? outDetectionPath
: QString("%1 %2").arg(outDetectionPath,
m_detectedVersion);
QString response;
switch (m_status) {
case Status::ValidPackage:
response = m_detectionPath.isEmpty()
? (m_detectedVersion.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath)
: tr("Path %1 exists. Version %2 was found.")
.arg(displayPackagePath, m_detectedVersion))
: tr("Path %1 is valid, %2 was found.")
.arg(displayPackagePath, displayDetectedPath);
break;
case Status::ValidPackageMismatchedVersion: {
const QString versionWarning
= m_versions.size() == 1
? tr("but only version %1 is supported").arg(m_versions.first())
: tr("but only versions %1 are supported").arg(displayVersions);
response = tr("Path %1 is valid, %2 was found, %3.")
.arg(displayPackagePath, displayDetectedPath, versionWarning);
break;
}
case Status::ValidPathInvalidPackage:
response = tr("Path %1 exists, but does not contain %2.")
.arg(displayPackagePath, displayRequiredPath);
break;
case Status::InvalidPath:
response = tr("Path %1 does not exist.").arg(displayPackagePath);
break;
case Status::EmptyPath:
response = m_detectionPath.isEmpty()
? tr("Path is empty.")
: tr("Path is empty, %1 not found.").arg(displayRequiredPath);
break;
}
return response;
}
McuToolChainPackage::McuToolChainPackage(const QString &label, McuToolChainPackage::McuToolChainPackage(const QString &label,
const FilePath &defaultPath, const FilePath &defaultPath,
const QString &detectionPath, const FilePath &detectionPath,
const QString &settingsKey, const QString &settingsKey,
McuToolChainPackage::Type type, McuToolChainPackage::ToolChainType type,
const QString &envVarName, const QString &envVarName,
const McuPackageVersionDetector *versionDetector) const McuPackageVersionDetector *versionDetector)
: McuPackage(label, defaultPath, detectionPath, settingsKey, envVarName, {}, versionDetector) : McuPackage(label, defaultPath, detectionPath, settingsKey, envVarName, {}, versionDetector)
, m_type(type) , m_type(type)
{} {}
McuToolChainPackage::Type McuToolChainPackage::type() const McuToolChainPackage::ToolChainType McuToolChainPackage::toolchainType() const
{ {
return m_type; return m_type;
} }
bool McuToolChainPackage::isDesktopToolchain() const bool McuToolChainPackage::isDesktopToolchain() const
{ {
return m_type == Type::MSVC || m_type == Type::GCC; return m_type == ToolChainType::MSVC || m_type == ToolChainType::GCC;
}
static ToolChain *msvcToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
const Abi abi = t->targetAbi();
// TODO: Should Abi::WindowsMsvc2022Flavor be added too?
return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor
|| abi.osFlavor() == Abi::WindowsMsvc2019Flavor)
&& abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64
&& t->language() == language;
});
return toolChain;
}
static ToolChain *gccToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
const Abi abi = t->targetAbi();
return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture
&& abi.wordWidth() == 64 && t->language() == language;
});
return toolChain;
}
static ToolChain *armGccToolChain(const FilePath &path, Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) {
return t->compilerCommand() == path && t->language() == language;
});
if (!toolChain) {
ToolChainFactory *gccFactory
= Utils::findOrDefault(ToolChainFactory::allToolChainFactories(),
[](ToolChainFactory *f) {
return f->supportedToolChainType()
== ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
});
if (gccFactory) {
const QList<ToolChain *> detected = gccFactory->detectForImport({path, language});
if (!detected.isEmpty()) {
toolChain = detected.first();
toolChain->setDetection(ToolChain::ManualDetection);
toolChain->setDisplayName("Arm GCC");
ToolChainManager::registerToolChain(toolChain);
}
}
}
return toolChain;
}
static ToolChain *iarToolChain(const FilePath &path, Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID
&& t->language() == language;
});
if (!toolChain) {
ToolChainFactory *iarFactory
= Utils::findOrDefault(ToolChainFactory::allToolChainFactories(),
[](ToolChainFactory *f) {
return f->supportedToolChainType()
== BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
});
if (iarFactory) {
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}));
if (detected.isEmpty())
detected = iarFactory->detectForImport({path, language});
for (auto tc : detected) {
if (tc->language() == language) {
toolChain = tc;
toolChain->setDetection(ToolChain::ManualDetection);
toolChain->setDisplayName("IAREW");
ToolChainManager::registerToolChain(toolChain);
}
}
}
}
return toolChain;
}
ToolChain *McuToolChainPackage::toolChain(Id language) const
{
switch (m_type) {
case ToolChainType::MSVC:
return msvcToolChain(language);
case ToolChainType::GCC:
return gccToolChain(language);
case ToolChainType::IAR: {
const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix();
return iarToolChain(compiler, language);
}
case ToolChainType::ArmGcc:
case ToolChainType::KEIL:
case ToolChainType::GHS:
case ToolChainType::GHSArm:
case ToolChainType::Unsupported: {
const QLatin1String compilerName(
language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++");
const QString comp = QLatin1String(m_type == ToolChainType::ArmGcc ? "/bin/arm-none-eabi-%1"
: "/bar/foo-keil-%1")
.arg(compilerName);
const FilePath compiler = path().pathAppended(comp).withExecutableSuffix();
return armGccToolChain(compiler, language);
}
default:
Q_UNREACHABLE();
}
}
QString McuToolChainPackage::toolChainName() const
{
switch (m_type) {
case ToolChainType::ArmGcc:
return QLatin1String("armgcc");
case ToolChainType::IAR:
return QLatin1String("iar");
case ToolChainType::KEIL:
return QLatin1String("keil");
case ToolChainType::GHS:
return QLatin1String("ghs");
case ToolChainType::GHSArm:
return QLatin1String("ghs-arm");
default:
return QLatin1String("unsupported");
}
}
QString McuToolChainPackage::cmakeToolChainFileName() const
{
return toolChainName() + QLatin1String(".cmake");
}
QVariant McuToolChainPackage::debuggerId() const
{
using namespace Debugger;
QString sub, displayName;
DebuggerEngineType engineType;
switch (m_type) {
case ToolChainType::ArmGcc: {
sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py");
displayName = McuPackage::tr("Arm GDB at %1");
engineType = Debugger::GdbEngineType;
break;
}
case ToolChainType::IAR: {
sub = QString::fromLatin1("../common/bin/CSpyBat");
displayName = QLatin1String("CSpy");
engineType = Debugger::NoEngineType; // support for IAR missing
break;
}
case ToolChainType::KEIL: {
sub = QString::fromLatin1("UV4/UV4");
displayName = QLatin1String("KEIL uVision Debugger");
engineType = Debugger::UvscEngineType;
break;
}
default:
return QVariant();
}
const FilePath command = path().pathAppended(sub).withExecutableSuffix();
if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) {
return debugger->id();
}
DebuggerItem newDebugger;
newDebugger.setCommand(command);
newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput()));
newDebugger.setEngineType(engineType);
return DebuggerItemManager::registerDebugger(newDebugger);
} }

View File

@@ -55,33 +55,35 @@ class McuPackage : public McuAbstractPackage
public: public:
McuPackage(const QString &label, McuPackage(const QString &label,
const Utils::FilePath &defaultPath, const Utils::FilePath &defaultPath,
const QString &detectionPath, const Utils::FilePath &detectionPath,
const QString &settingsKey, const QString &settingsKey,
const QString &envVarName = {}, const QString &envVarName = {},
const QString &downloadUrl = {}, const QString &downloadUrl = {},
const McuPackageVersionDetector *versionDetector = nullptr); const McuPackageVersionDetector *versionDetector = nullptr,
const bool addToPath = false,
const Utils::FilePath &relativePathModifier = Utils::FilePath());
~McuPackage() override = default; ~McuPackage() override = default;
QString label() const override;
const QString &environmentVariableName() const override;
bool isAddToSystemPath() const override;
void setVersions(const QStringList &versions) override;
Utils::FilePath basePath() const override; Utils::FilePath basePath() const override;
Utils::FilePath path() const override; Utils::FilePath path() const override;
QString label() const override;
Utils::FilePath defaultPath() const override; Utils::FilePath defaultPath() const override;
QString detectionPath() const override; Utils::FilePath detectionPath() const override;
QString statusText() const override;
void updateStatus() override;
void updateStatus() override;
Status status() const override; Status status() const override;
bool validStatus() const override; bool isValidStatus() const override;
void setAddToPath(bool addToPath) override; QString statusText() const override;
bool addToPath() const override;
bool writeToSettings() const override; bool writeToSettings() const override;
void setRelativePathModifier(const QString &path) override;
void setVersions(const QStringList &versions) override;
QWidget *widget() override; QWidget *widget() override;
const QString &environmentVariableName() const override;
private: private:
void updatePath(); void updatePath();
void updateStatusUi(); void updateStatusUi();
@@ -92,17 +94,17 @@ private:
const QString m_label; const QString m_label;
const Utils::FilePath m_defaultPath; const Utils::FilePath m_defaultPath;
const QString m_detectionPath; const Utils::FilePath m_detectionPath;
const QString m_settingsKey; const QString m_settingsKey;
const McuPackageVersionDetector *m_versionDetector; const McuPackageVersionDetector *m_versionDetector;
Utils::FilePath m_path; Utils::FilePath m_path;
QString m_relativePathModifier; // relative path to m_path to be returned by path() Utils::FilePath m_relativePathModifier; // relative path to m_path to be returned by path()
QString m_detectedVersion; QString m_detectedVersion;
QStringList m_versions; QStringList m_versions;
const QString m_environmentVariableName; const QString m_environmentVariableName;
const QString m_downloadUrl; const QString m_downloadUrl;
bool m_addToPath = false; const bool m_addToSystemPath;
Status m_status = Status::InvalidPath; Status m_status = Status::InvalidPath;
}; };
@@ -110,17 +112,17 @@ private:
class McuToolChainPackage : public McuPackage class McuToolChainPackage : public McuPackage
{ {
public: public:
enum class Type { IAR, KEIL, MSVC, GCC, ArmGcc, GHS, GHSArm, Unsupported }; enum class ToolChainType { IAR, KEIL, MSVC, GCC, ArmGcc, GHS, GHSArm, Unsupported };
McuToolChainPackage(const QString &label, McuToolChainPackage(const QString &label,
const Utils::FilePath &defaultPath, const Utils::FilePath &defaultPath,
const QString &detectionPath, const Utils::FilePath &detectionPath,
const QString &settingsKey, const QString &settingsKey,
Type type, ToolChainType toolchainType,
const QString &envVarName = {}, const QString &envVarName = {},
const McuPackageVersionDetector *versionDetector = nullptr); const McuPackageVersionDetector *versionDetector = nullptr);
Type type() const; ToolChainType toolchainType() const;
bool isDesktopToolchain() const; bool isDesktopToolchain() const;
ProjectExplorer::ToolChain *toolChain(Utils::Id language) const; ProjectExplorer::ToolChain *toolChain(Utils::Id language) const;
QString toolChainName() const; QString toolChainName() const;
@@ -128,7 +130,7 @@ public:
QVariant debuggerId() const; QVariant debuggerId() const;
private: private:
const Type m_type; const ToolChainType m_type;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -134,7 +134,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir)
{ {
deletePackagesAndTargets(); deletePackagesAndTargets();
qtForMCUsSdkPackage->updateStatus(); qtForMCUsSdkPackage->updateStatus();
if (qtForMCUsSdkPackage->validStatus()) if (qtForMCUsSdkPackage->isValidStatus())
Sdk::targetsAndPackages(dir, &sdkRepository); Sdk::targetsAndPackages(dir, &sdkRepository);
for (const auto &package : qAsConst(sdkRepository.packages)) for (const auto &package : qAsConst(sdkRepository.packages))
connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::packagesChanged); connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::packagesChanged);
@@ -164,73 +164,6 @@ void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &en
CMakeConfigurationKitAspect::setConfiguration(kit, config); CMakeConfigurationKitAspect::setConfiguration(kit, config);
} }
static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
{
switch (tcPackage->type()) {
case McuToolChainPackage::Type::Unsupported:
return;
case McuToolChainPackage::Type::GHS:
case McuToolChainPackage::Type::GHSArm:
return; // No Green Hills toolchain, because support for it is missing.
case McuToolChainPackage::Type::IAR:
case McuToolChainPackage::Type::KEIL:
case McuToolChainPackage::Type::MSVC:
case McuToolChainPackage::Type::GCC:
case McuToolChainPackage::Type::ArmGcc:
ToolChainKitAspect::setToolChain(k,
tcPackage->toolChain(
ProjectExplorer::Constants::C_LANGUAGE_ID));
ToolChainKitAspect::setToolChain(k,
tcPackage->toolChain(
ProjectExplorer::Constants::CXX_LANGUAGE_ID));
return;
default:
Q_UNREACHABLE();
}
}
static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage)
{
if (tcPackage->isDesktopToolchain()) {
// Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain
return;
}
switch (tcPackage->type()) {
case McuToolChainPackage::Type::Unsupported:
case McuToolChainPackage::Type::GHS:
case McuToolChainPackage::Type::GHSArm:
case McuToolChainPackage::Type::IAR:
return; // No Green Hills and IAR debugger, because support for it is missing.
case McuToolChainPackage::Type::KEIL:
case McuToolChainPackage::Type::MSVC:
case McuToolChainPackage::Type::GCC:
case McuToolChainPackage::Type::ArmGcc: {
const QVariant debuggerId = tcPackage->debuggerId();
if (debuggerId.isValid()) {
Debugger::DebuggerKitAspect::setDebugger(k, debuggerId);
}
return;
}
default:
Q_UNREACHABLE();
}
}
static void setKitDevice(Kit *k, const McuTarget *mcuTarget)
{
// "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit
if (mcuTarget->toolChainPackage()->isDesktopToolchain())
return;
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE);
}
static bool expectsCmakeVars(const McuTarget *mcuTarget) static bool expectsCmakeVars(const McuTarget *mcuTarget)
{ {
return mcuTarget->qulVersion() >= QVersionNumber{2, 0}; return mcuTarget->qulVersion() >= QVersionNumber{2, 0};
@@ -251,7 +184,7 @@ void McuSupportOptions::setKitEnvironment(Kit *k,
pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput()); pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput());
auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) { auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) {
if (package->addToPath()) if (package->isAddToSystemPath())
pathAdditions.append(package->path().toUserOutput()); pathAdditions.append(package->path().toUserOutput());
if (!package->environmentVariableName().isEmpty()) if (!package->environmentVariableName().isEmpty())
changes.append({package->environmentVariableName(), package->path().toUserOutput()}); changes.append({package->environmentVariableName(), package->path().toUserOutput()});
@@ -271,34 +204,12 @@ void McuSupportOptions::setKitEnvironment(Kit *k,
EnvironmentKitAspect::setEnvironmentChanges(k, changes); EnvironmentKitAspect::setEnvironmentChanges(k, changes);
} }
static void setKitDependencies(Kit *k,
const McuTarget *mcuTarget,
const McuAbstractPackage *qtForMCUsSdkPackage)
{
NameValueItems dependencies;
auto processPackage = [&dependencies](const McuAbstractPackage *package) {
if (!package->environmentVariableName().isEmpty())
dependencies.append({package->environmentVariableName(),
QDir::toNativeSeparators(package->detectionPath())});
};
for (auto package : mcuTarget->packages())
processPackage(package);
processPackage(qtForMCUsSdkPackage);
McuDependenciesKitAspect::setDependencies(k, dependencies);
auto irrelevant = k->irrelevantAspects();
irrelevant.insert(McuDependenciesKitAspect::id());
k->setIrrelevantAspects(irrelevant);
}
void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget) void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
{ {
EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k); EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k);
for (auto package : mcuTarget->packages()) { for (auto package : mcuTarget->packages()) {
const QString varName = package->environmentVariableName(); const QString varName = package->environmentVariableName();
if (!varName.isEmpty() && package->validStatus()) { if (!varName.isEmpty() && package->isValidStatus()) {
const int index = Utils::indexOf(changes, [varName](const EnvironmentItem &item) { const int index = Utils::indexOf(changes, [varName](const EnvironmentItem &item) {
return item.name == varName; return item.name == varName;
}); });
@@ -319,76 +230,6 @@ void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
EnvironmentKitAspect::setEnvironmentChanges(k, changes); EnvironmentKitAspect::setEnvironmentChanges(k, changes);
} }
static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePath &qulDir)
{
using namespace CMakeProjectManager;
CMakeConfig config = CMakeConfigurationKitAspect::configuration(k);
// CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously
if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHS
&& mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHSArm) {
config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}"));
config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}"));
}
if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) {
const FilePath cMakeToolchainFile = qulDir.pathAppended(
"lib/cmake/Qul/toolchain/" + mcuTarget->toolChainPackage()->cmakeToolChainFileName());
config.append(
CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", cMakeToolchainFile.toString().toUtf8()));
if (!cMakeToolchainFile.exists()) {
printMessage(McuTarget::tr(
"Warning for target %1: missing CMake toolchain file expected at %2.")
.arg(McuKitManager::kitName(mcuTarget),
cMakeToolchainFile.toUserOutput()),
false);
}
}
const FilePath generatorsPath = qulDir.pathAppended("/lib/cmake/Qul/QulGenerators.cmake");
config.append(CMakeConfigItem("QUL_GENERATORS", generatorsPath.toString().toUtf8()));
if (!generatorsPath.exists()) {
printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.")
.arg(McuKitManager::kitName(mcuTarget), generatorsPath.toUserOutput()),
false);
}
config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->platform().name.toUtf8()));
if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth)
config.append(CMakeConfigItem("QUL_COLOR_DEPTH",
QString::number(mcuTarget->colorDepth()).toLatin1()));
if (McuSupportOptions::kitsNeedQtVersion())
config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}"));
CMakeConfigurationKitAspect::setConfiguration(k, config);
if (HostOsInfo::isWindowsHost()) {
auto type = mcuTarget->toolChainPackage()->type();
if (type == McuToolChainPackage::Type::GHS || type == McuToolChainPackage::Type::GHSArm) {
// See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802
// and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803
CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM");
}
}
}
static void setKitQtVersionOptions(Kit *k)
{
if (!McuSupportOptions::kitsNeedQtVersion())
QtSupport::QtKitAspect::setQtVersion(k, nullptr);
// else: auto-select a Qt version
}
static FilePath kitDependencyPath(const Kit *kit, const QString &variableName)
{
for (const NameValueItem &nameValueItem : EnvironmentKitAspect::environmentChanges(kit)) {
if (nameValueItem.name == variableName)
return FilePath::fromUserInput(nameValueItem.value);
}
return FilePath();
}
McuKitManager::UpgradeOption McuSupportOptions::askForKitUpgrades() McuKitManager::UpgradeOption McuSupportOptions::askForKitUpgrades()
{ {
QMessageBox upgradePopup(Core::ICore::dialogParent()); QMessageBox upgradePopup(Core::ICore::dialogParent());
@@ -417,7 +258,7 @@ void McuSupportOptions::deletePackagesAndTargets()
void McuSupportOptions::checkUpgradeableKits() void McuSupportOptions::checkUpgradeableKits()
{ {
if (!qtForMCUsSdkPackage->validStatus() || sdkRepository.mcuTargets.length() == 0) if (!qtForMCUsSdkPackage->isValidStatus() || sdkRepository.mcuTargets.length() == 0)
return; return;
if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTarget *target) { if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTarget *target) {

View File

@@ -197,7 +197,7 @@ void McuSupportOptionsWidget::updateStatus()
// Page elements // Page elements
{ {
m_qtForMCUsSdkGroupBox->setVisible(cMakeAvailable); m_qtForMCUsSdkGroupBox->setVisible(cMakeAvailable);
const bool valid = cMakeAvailable && m_options.qtForMCUsSdkPackage->validStatus(); const bool valid = cMakeAvailable && m_options.qtForMCUsSdkPackage->isValidStatus();
const bool ready = valid && mcuTarget; const bool ready = valid && mcuTarget;
m_mcuTargetsGroupBox->setVisible(ready); m_mcuTargetsGroupBox->setVisible(ready);
m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty()); m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty());

View File

@@ -71,24 +71,24 @@ McuPackage *createQtForMCUsPackage()
{ {
return new McuPackage(McuPackage::tr("Qt for MCUs SDK"), return new McuPackage(McuPackage::tr("Qt for MCUs SDK"),
FileUtils::homePath(), // defaultPath FileUtils::homePath(), // defaultPath
FilePath("bin/qmltocpp").withExecutableSuffix().toString(), // detectionPath FilePath("bin/qmltocpp").withExecutableSuffix(), // detectionPath
Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK, // settingsKey Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK, // settingsKey
QStringLiteral("Qul_DIR")); // envVarName QStringLiteral("Qul_DIR")); // envVarName
} }
static McuToolChainPackage *createMsvcToolChainPackage() static McuToolChainPackage *createMsvcToolChainPackage()
{ {
return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::Type::MSVC); return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::ToolChainType::MSVC);
} }
static McuToolChainPackage *createGccToolChainPackage() static McuToolChainPackage *createGccToolChainPackage()
{ {
return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::Type::GCC); return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::ToolChainType::GCC);
} }
static McuToolChainPackage *createUnsupportedToolChainPackage() static McuToolChainPackage *createUnsupportedToolChainPackage()
{ {
return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::Type::Unsupported); return new McuToolChainPackage({}, {}, {}, {}, McuToolChainPackage::ToolChainType::Unsupported);
} }
static McuToolChainPackage *createArmGccPackage() static McuToolChainPackage *createArmGccPackage()
@@ -109,7 +109,7 @@ static McuToolChainPackage *createArmGccPackage()
} }
} }
const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"); const Utils::FilePath detectionPath = FilePath("bin/arm-none-eabi-g++").withExecutableSuffix();
const auto versionDetector const auto versionDetector
= new McuPackageExecutableVersionDetector(detectionPath, = new McuPackageExecutableVersionDetector(detectionPath,
{"--version"}, {"--version"},
@@ -119,7 +119,7 @@ static McuToolChainPackage *createArmGccPackage()
defaultPath, defaultPath,
detectionPath, detectionPath,
"GNUArmEmbeddedToolchain", // settingsKey "GNUArmEmbeddedToolchain", // settingsKey
McuToolChainPackage::Type::ArmGcc, McuToolChainPackage::ToolChainType::ArmGcc,
envVar, envVar,
versionDetector); versionDetector);
} }
@@ -131,16 +131,15 @@ static McuToolChainPackage *createGhsToolchainPackage()
const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar)); const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
const auto versionDetector const auto versionDetector
= new McuPackageExecutableVersionDetector(Utils::HostOsInfo::withExecutableSuffix("as850"), = new McuPackageExecutableVersionDetector(FilePath("as850").withExecutableSuffix(),
{"-V"}, {"-V"},
"\\bv(\\d+\\.\\d+\\.\\d+)\\b"); "\\bv(\\d+\\.\\d+\\.\\d+)\\b");
return new McuToolChainPackage("Green Hills Compiler", return new McuToolChainPackage("Green Hills Compiler",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix( FilePath("ccv850").withExecutableSuffix(), // detectionPath
"ccv850"), // detectionPath
"GHSToolchain", // settingsKey "GHSToolchain", // settingsKey
McuToolChainPackage::Type::GHS, McuToolChainPackage::ToolChainType::GHS,
envVar, envVar,
versionDetector); versionDetector);
} }
@@ -152,15 +151,15 @@ static McuToolChainPackage *createGhsArmToolchainPackage()
const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar)); const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar));
const auto versionDetector const auto versionDetector
= new McuPackageExecutableVersionDetector(Utils::HostOsInfo::withExecutableSuffix("asarm"), = new McuPackageExecutableVersionDetector(FilePath("asarm").withExecutableSuffix(),
{"-V"}, {"-V"},
"\\bv(\\d+\\.\\d+\\.\\d+)\\b"); "\\bv(\\d+\\.\\d+\\.\\d+)\\b");
return new McuToolChainPackage("Green Hills Compiler for ARM", return new McuToolChainPackage("Green Hills Compiler for ARM",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("cxarm"), // detectionPath FilePath("cxarm").withExecutableSuffix(), // detectionPath
"GHSArmToolchain", // settingsKey "GHSArmToolchain", // settingsKey
McuToolChainPackage::Type::GHSArm, McuToolChainPackage::ToolChainType::GHSArm,
envVar, envVar,
versionDetector); versionDetector);
} }
@@ -183,7 +182,7 @@ static McuToolChainPackage *createIarToolChainPackage()
} }
} }
const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/iccarm"); const FilePath detectionPath = FilePath("bin/iccarm").withExecutableSuffix();
const auto versionDetector const auto versionDetector
= new McuPackageExecutableVersionDetector(detectionPath, = new McuPackageExecutableVersionDetector(detectionPath,
{"--version"}, {"--version"},
@@ -193,7 +192,7 @@ static McuToolChainPackage *createIarToolChainPackage()
defaultPath, defaultPath,
detectionPath, detectionPath,
"IARToolchain", // settings key "IARToolchain", // settings key
McuToolChainPackage::Type::IAR, McuToolChainPackage::ToolChainType::IAR,
envVar, envVar,
versionDetector); versionDetector);
} }
@@ -237,17 +236,24 @@ static McuPackage *createStm32CubeProgrammerPackage()
if (programPath.exists()) if (programPath.exists())
defaultPath = programPath; defaultPath = programPath;
} }
const FilePath detectionPath = FilePath::fromString(
QLatin1String(Utils::HostOsInfo::isWindowsHost()
? "/bin/STM32_Programmer_CLI.exe"
: "/bin/STM32_Programmer.sh")
);
auto result auto result
= new McuPackage(McuPackage::tr("STM32CubeProgrammer"), = new McuPackage(McuPackage::tr("STM32CubeProgrammer"),
defaultPath, defaultPath,
QLatin1String(Utils::HostOsInfo::isWindowsHost() detectionPath,
? "/bin/STM32_Programmer_CLI.exe"
: "/bin/STM32_Programmer.sh"), // detection path
"Stm32CubeProgrammer", "Stm32CubeProgrammer",
{}, // env var {}, // env var
"https://www.st.com/en/development-tools/stm32cubeprog.html"); // download url "https://www.st.com/en/development-tools/stm32cubeprog.html", // download url
result->setRelativePathModifier("/bin"); nullptr, // version detector
result->setAddToPath(true); true, // add to path
"/bin" // relative path modifier
);
return result; return result;
} }
@@ -276,8 +282,7 @@ static McuPackage *createMcuXpressoIdePackage()
return new McuPackage("MCUXpresso IDE", return new McuPackage("MCUXpresso IDE",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix( FilePath("ide/binaries/crt_emu_cm_redlink").withExecutableSuffix(), // detection path
"ide/binaries/crt_emu_cm_redlink"), // detection path
"MCUXpressoIDE", // settings key "MCUXpressoIDE", // settings key
envVar, envVar,
"https://www.nxp.com/mcuxpresso/ide"); // download url "https://www.nxp.com/mcuxpresso/ide"); // download url
@@ -303,7 +308,7 @@ static McuPackage *createCypressProgrammerPackage()
auto result = new McuPackage("Cypress Auto Flash Utility", auto result = new McuPackage("Cypress Auto Flash Utility",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("/bin/openocd"), FilePath("/bin/openocd").withExecutableSuffix(),
"CypressAutoFlashUtil", "CypressAutoFlashUtil",
envVar); envVar);
return result; return result;
@@ -329,7 +334,7 @@ static McuPackage *createRenesasProgrammerPackage()
auto result = new McuPackage("Renesas Flash Programmer", auto result = new McuPackage("Renesas Flash Programmer",
defaultPath, defaultPath,
Utils::HostOsInfo::withExecutableSuffix("rfp-cli"), FilePath("rfp-cli").withExecutableSuffix(),
"RenesasFlashProgrammer", "RenesasFlashProgrammer",
envVar); envVar);
return result; return result;
@@ -538,7 +543,7 @@ protected:
QVector<McuAbstractPackage *> required3rdPartyPkgs; QVector<McuAbstractPackage *> required3rdPartyPkgs;
// Desktop toolchains don't need any additional settings // Desktop toolchains don't need any additional settings
if (tcPkg && !tcPkg->isDesktopToolchain() if (tcPkg && !tcPkg->isDesktopToolchain()
&& tcPkg->type() != McuToolChainPackage::Type::Unsupported) && tcPkg->toolchainType() != McuToolChainPackage::ToolChainType::Unsupported)
required3rdPartyPkgs.append(tcPkg); required3rdPartyPkgs.append(tcPkg);
// Add setting specific to platform IDE // Add setting specific to platform IDE

View File

@@ -46,7 +46,7 @@ QString matchRegExp(const QString &text, const QString &regExp)
McuPackageVersionDetector::McuPackageVersionDetector() {} McuPackageVersionDetector::McuPackageVersionDetector() {}
McuPackageExecutableVersionDetector::McuPackageExecutableVersionDetector( McuPackageExecutableVersionDetector::McuPackageExecutableVersionDetector(
const QString &detectionPath, const QStringList &detectionArgs, const QString &detectionRegExp) const Utils::FilePath &detectionPath, const QStringList &detectionArgs, const QString &detectionRegExp)
: McuPackageVersionDetector() : McuPackageVersionDetector()
, m_detectionPath(detectionPath) , m_detectionPath(detectionPath)
, m_detectionArgs(detectionArgs) , m_detectionArgs(detectionArgs)
@@ -58,7 +58,7 @@ QString McuPackageExecutableVersionDetector::parseVersion(const QString &package
if (m_detectionPath.isEmpty() || m_detectionRegExp.isEmpty()) if (m_detectionPath.isEmpty() || m_detectionRegExp.isEmpty())
return QString(); return QString();
const Utils::FilePath binaryPath = Utils::FilePath::fromString(packagePath) / m_detectionPath; const Utils::FilePath binaryPath = Utils::FilePath::fromString(packagePath).resolvePath(m_detectionPath);
if (!binaryPath.exists()) if (!binaryPath.exists())
return QString(); return QString();

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <utils/filepath.h>
namespace McuSupport { namespace McuSupport {
namespace Internal { namespace Internal {
@@ -43,13 +44,13 @@ public:
class McuPackageExecutableVersionDetector : public McuPackageVersionDetector class McuPackageExecutableVersionDetector : public McuPackageVersionDetector
{ {
public: public:
McuPackageExecutableVersionDetector(const QString &detectionPath, McuPackageExecutableVersionDetector(const Utils::FilePath &detectionPath,
const QStringList &detectionArgs, const QStringList &detectionArgs,
const QString &detectionRegExp); const QString &detectionRegExp);
QString parseVersion(const QString &packagePath) const final; QString parseVersion(const QString &packagePath) const final;
private: private:
const QString m_detectionPath; const Utils::FilePath m_detectionPath;
const QStringList m_detectionArgs; const QStringList m_detectionArgs;
const QString m_detectionRegExp; const QString m_detectionRegExp;
}; };

View File

@@ -26,196 +26,14 @@
#include "mcutarget.h" #include "mcutarget.h"
#include "mcupackage.h" #include "mcupackage.h"
#include "mcukitmanager.h" #include "mcukitmanager.h"
#include "mcusupportplugin.h" #include "mcusupportplugin.h"
#include <baremetal/baremetalconstants.h> #include <utils/algorithm.h>
#include <debugger/debuggeritem.h>
#include <debugger/debuggeritemmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/toolchainmanager.h>
using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace McuSupport::Internal { namespace McuSupport::Internal {
static ToolChain *msvcToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
const Abi abi = t->targetAbi();
// TODO: Should Abi::WindowsMsvc2022Flavor be added too?
return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor
|| abi.osFlavor() == Abi::WindowsMsvc2019Flavor)
&& abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64
&& t->language() == language;
});
return toolChain;
}
static ToolChain *gccToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
const Abi abi = t->targetAbi();
return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture
&& abi.wordWidth() == 64 && t->language() == language;
});
return toolChain;
}
static ToolChain *armGccToolChain(const FilePath &path, Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) {
return t->compilerCommand() == path && t->language() == language;
});
if (!toolChain) {
ToolChainFactory *gccFactory
= Utils::findOrDefault(ToolChainFactory::allToolChainFactories(),
[](ToolChainFactory *f) {
return f->supportedToolChainType()
== ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
});
if (gccFactory) {
const QList<ToolChain *> detected = gccFactory->detectForImport({path, language});
if (!detected.isEmpty()) {
toolChain = detected.first();
toolChain->setDetection(ToolChain::ManualDetection);
toolChain->setDisplayName("Arm GCC");
ToolChainManager::registerToolChain(toolChain);
}
}
}
return toolChain;
}
static ToolChain *iarToolChain(const FilePath &path, Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID
&& t->language() == language;
});
if (!toolChain) {
ToolChainFactory *iarFactory
= Utils::findOrDefault(ToolChainFactory::allToolChainFactories(),
[](ToolChainFactory *f) {
return f->supportedToolChainType()
== BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
});
if (iarFactory) {
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}));
if (detected.isEmpty())
detected = iarFactory->detectForImport({path, language});
for (auto tc : detected) {
if (tc->language() == language) {
toolChain = tc;
toolChain->setDetection(ToolChain::ManualDetection);
toolChain->setDisplayName("IAREW");
ToolChainManager::registerToolChain(toolChain);
}
}
}
}
return toolChain;
}
ToolChain *McuToolChainPackage::toolChain(Id language) const
{
switch (m_type) {
case Type::MSVC:
return msvcToolChain(language);
case Type::GCC:
return gccToolChain(language);
case Type::IAR: {
const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix();
return iarToolChain(compiler, language);
}
case Type::ArmGcc:
case Type::KEIL:
case Type::GHS:
case Type::GHSArm:
case Type::Unsupported: {
const QLatin1String compilerName(
language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++");
const QString comp = QLatin1String(m_type == Type::ArmGcc ? "/bin/arm-none-eabi-%1"
: "/bar/foo-keil-%1")
.arg(compilerName);
const FilePath compiler = path().pathAppended(comp).withExecutableSuffix();
return armGccToolChain(compiler, language);
}
default:
Q_UNREACHABLE();
}
}
QString McuToolChainPackage::toolChainName() const
{
switch (m_type) {
case Type::ArmGcc:
return QLatin1String("armgcc");
case Type::IAR:
return QLatin1String("iar");
case Type::KEIL:
return QLatin1String("keil");
case Type::GHS:
return QLatin1String("ghs");
case Type::GHSArm:
return QLatin1String("ghs-arm");
default:
return QLatin1String("unsupported");
}
}
QString McuToolChainPackage::cmakeToolChainFileName() const
{
return toolChainName() + QLatin1String(".cmake");
}
QVariant McuToolChainPackage::debuggerId() const
{
using namespace Debugger;
QString sub, displayName;
DebuggerEngineType engineType;
switch (m_type) {
case Type::ArmGcc: {
sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py");
displayName = McuPackage::tr("Arm GDB at %1");
engineType = Debugger::GdbEngineType;
break;
}
case Type::IAR: {
sub = QString::fromLatin1("../common/bin/CSpyBat");
displayName = QLatin1String("CSpy");
engineType = Debugger::NoEngineType; // support for IAR missing
break;
}
case Type::KEIL: {
sub = QString::fromLatin1("UV4/UV4");
displayName = QLatin1String("KEIL uVision Debugger");
engineType = Debugger::UvscEngineType;
break;
}
default:
return QVariant();
}
const FilePath command = path().pathAppended(sub).withExecutableSuffix();
if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) {
return debugger->id();
}
DebuggerItem newDebugger;
newDebugger.setCommand(command);
newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput()));
newDebugger.setEngineType(engineType);
return DebuggerItemManager::registerDebugger(newDebugger);
}
McuTarget::McuTarget(const QVersionNumber &qulVersion, McuTarget::McuTarget(const QVersionNumber &qulVersion,
const Platform &platform, const Platform &platform,
OS os, OS os,
@@ -254,7 +72,7 @@ bool McuTarget::isValid() const
{ {
return Utils::allOf(packages(), [](McuAbstractPackage *package) { return Utils::allOf(packages(), [](McuAbstractPackage *package) {
package->updateStatus(); package->updateStatus();
return package->validStatus(); return package->isValidStatus();
}); });
} }
@@ -262,7 +80,7 @@ void McuTarget::printPackageProblems() const
{ {
for (auto package : packages()) { for (auto package : packages()) {
package->updateStatus(); package->updateStatus();
if (!package->validStatus()) if (!package->isValidStatus())
printMessage(tr("Error creating kit for target %1, package %2: %3") printMessage(tr("Error creating kit for target %1, package %2: %3")
.arg(McuKitManager::kitName(this), .arg(McuKitManager::kitName(this),
package->label(), package->label(),

View File

@@ -39,17 +39,15 @@ public:
MOCK_METHOD(Utils::FilePath, path, (), (const)); MOCK_METHOD(Utils::FilePath, path, (), (const));
MOCK_METHOD(QString, label, (), (const)); MOCK_METHOD(QString, label, (), (const));
MOCK_METHOD(Utils::FilePath, defaultPath, (), (const)); MOCK_METHOD(Utils::FilePath, defaultPath, (), (const));
MOCK_METHOD(QString, detectionPath, (), (const)); MOCK_METHOD(Utils::FilePath, detectionPath, (), (const));
MOCK_METHOD(QString, statusText, (), (const)); MOCK_METHOD(QString, statusText, (), (const));
MOCK_METHOD(void, updateStatus, ()); MOCK_METHOD(void, updateStatus, ());
MOCK_METHOD(Status, status, (), (const)); MOCK_METHOD(Status, status, (), (const));
MOCK_METHOD(bool, validStatus, (), (const)); MOCK_METHOD(bool, isValidStatus, (), (const));
MOCK_METHOD(const QString &, environmentVariableName, (), (const)); MOCK_METHOD(const QString &, environmentVariableName, (), (const));
MOCK_METHOD(void, setAddToPath, (bool) ); MOCK_METHOD(bool, isAddToSystemPath, (), (const));
MOCK_METHOD(bool, addToPath, (), (const));
MOCK_METHOD(bool, writeToSettings, (), (const)); MOCK_METHOD(bool, writeToSettings, (), (const));
MOCK_METHOD(void, setRelativePathModifier, (const QString &) );
MOCK_METHOD(void, setVersions, (const QStringList &) ); MOCK_METHOD(void, setVersions, (const QStringList &) );
MOCK_METHOD(QWidget *, widget, ()); MOCK_METHOD(QWidget *, widget, ());

View File

@@ -47,7 +47,7 @@ using Utils::FilePath;
void McuSupportTest::initTestCase() void McuSupportTest::initTestCase()
{ {
EXPECT_CALL(freeRtosPackage, environmentVariableName()).WillRepeatedly(ReturnRef(freeRtosEnvVar)); EXPECT_CALL(freeRtosPackage, environmentVariableName()).WillRepeatedly(ReturnRef(freeRtosEnvVar));
EXPECT_CALL(freeRtosPackage, validStatus()).WillRepeatedly(Return(true)); EXPECT_CALL(freeRtosPackage, isValidStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(freeRtosPackage, path()) EXPECT_CALL(freeRtosPackage, path())
.WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath))); .WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath)));
} }

View File

@@ -32,6 +32,7 @@ add_qtc_plugin(QmlDesigner
cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h
cmakeprojectconverter.cpp cmakeprojectconverter.h cmakeprojectconverter.cpp cmakeprojectconverter.h
cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h
dynamiclicensecheck.h
generateresource.cpp generateresource.h generateresource.cpp generateresource.h
generatecmakelists.cpp generatecmakelists.h generatecmakelists.cpp generatecmakelists.h
generatecmakelistsconstants.h generatecmakelistsconstants.h

View File

@@ -29,7 +29,9 @@
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h> #include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
@@ -63,13 +65,46 @@ void CmakeProjectConverter::generateMenuEntry()
Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject"); Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject");
menu->addAction(cmd, Core::Constants::G_FILE_EXPORT); menu->addAction(cmd, Core::Constants::G_FILE_EXPORT);
action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr); action->setEnabled(isProjectConvertable(ProjectExplorer::SessionManager::startupProject()));
QObject::connect(ProjectExplorer::SessionManager::instance(), QObject::connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged, [action]() { &ProjectExplorer::SessionManager::startupProjectChanged, [action]() {
action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr); action->setEnabled(isProjectConvertable(ProjectExplorer::SessionManager::startupProject()));
}); });
} }
bool CmakeProjectConverter::isProjectConvertable(const ProjectExplorer::Project *project)
{
if (!project)
return false;
return !isProjectCurrentFormat(project);
}
const QStringList sanityCheckFiles({FILENAME_CMAKELISTS,
FILENAME_MODULES,
FILENAME_MAINQML,
QString(DIRNAME_CONTENT)+'/'+FILENAME_CMAKELISTS,
QString(DIRNAME_IMPORT)+'/'+FILENAME_CMAKELISTS,
QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP,
QString(DIRNAME_CPP)+'/'+FILENAME_ENV_HEADER,
QString(DIRNAME_CPP)+'/'+FILENAME_MAINCPP_HEADER
});
bool CmakeProjectConverter::isProjectCurrentFormat(const ProjectExplorer::Project *project)
{
const QmlProjectManager::QmlProject *qmlprj = qobject_cast<const QmlProjectManager::QmlProject*>(project);
if (!qmlprj)
return false;
FilePath rootDir = qmlprj->rootProjectDirectory();
for (const QString &file : sanityCheckFiles)
if (!rootDir.pathAppended(file).exists())
return false;
return true;
}
void CmakeProjectConverter::onConvertProject() void CmakeProjectConverter::onConvertProject()
{ {
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
@@ -100,10 +135,16 @@ bool CmakeProjectConverter::convertProject(const QmlProjectManager::QmlProject *
bool retVal = prepareAndExecute(); bool retVal = prepareAndExecute();
if (retVal) if (retVal) {
QMessageBox::information(nullptr, SUCCESS_TITLE, SUCCESS_TEXT); QMessageBox::information(Core::ICore::dialogParent(), SUCCESS_TITLE, SUCCESS_TEXT);
else ProjectExplorer::ProjectExplorerPlugin::OpenProjectResult result
QMessageBox::critical(nullptr, ERROR_TITLE, ERROR_TEXT.arg(m_errorText)); = ProjectExplorer::ProjectExplorerPlugin::openProject(newProjectFile());
if (!result)
ProjectExplorer::ProjectExplorerPlugin::showOpenProjectError(result);
}
else {
QMessageBox::critical(Core::ICore::dialogParent(), ERROR_TITLE, ERROR_TEXT.arg(m_errorText));
}
return retVal; return retVal;
} }
@@ -298,31 +339,36 @@ bool CmakeProjectConverter::createPreparedProject()
return true; return true;
} }
const FilePath CmakeProjectConverter::contentDir() const FilePath CmakeProjectConverter::contentDir() const
{ {
return m_newProjectDir.pathAppended(DIRNAME_CONTENT); return m_newProjectDir.pathAppended(DIRNAME_CONTENT);
} }
const FilePath CmakeProjectConverter::sourceDir() const FilePath CmakeProjectConverter::sourceDir() const
{ {
return m_newProjectDir.pathAppended(DIRNAME_CPP); return m_newProjectDir.pathAppended(DIRNAME_CPP);
} }
const FilePath CmakeProjectConverter::importDir() const FilePath CmakeProjectConverter::importDir() const
{ {
return m_newProjectDir.pathAppended(DIRNAME_IMPORT); return m_newProjectDir.pathAppended(DIRNAME_IMPORT);
} }
const FilePath CmakeProjectConverter::assetDir() const FilePath CmakeProjectConverter::assetDir() const
{ {
return contentDir().pathAppended(DIRNAME_ASSET); return contentDir().pathAppended(DIRNAME_ASSET);
} }
const FilePath CmakeProjectConverter::assetImportDir() const FilePath CmakeProjectConverter::assetImportDir() const
{ {
return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT); return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT);
} }
const FilePath CmakeProjectConverter::newProjectFile() const
{
return m_newProjectDir.pathAppended(m_project->projectFilePath().fileName());
}
const FilePath CmakeProjectConverter::projectMainFile() const const FilePath CmakeProjectConverter::projectMainFile() const
{ {
auto *target = m_project->activeTarget(); auto *target = m_project->activeTarget();
@@ -370,17 +416,20 @@ bool CmakeProjectConverter::modifyProjectFile()
QString projectFileName = m_project->projectFilePath().fileName(); QString projectFileName = m_project->projectFilePath().fileName();
FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName); FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName);
QFile projectFile(projectFilePath.toString()); QFile projectFile(projectFilePath.toString());
projectFile.open(QIODevice::ReadWrite); projectFile.open(QIODevice::ReadOnly);
if (!projectFile.isOpen()) if (!projectFile.isOpen())
return false; return false;
QString projectFileContent = QString::fromUtf8(projectFile.readAll()); QString projectFileContent = QString::fromUtf8(projectFile.readAll());
projectFile.close();
const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption); const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption);
const QString mainFileString(" mainFile: \"content/App.qml\""); const QString mainFileString(" mainFile: \"content/App.qml\"");
projectFileContent.replace(mainFilePattern, mainFileString); projectFileContent.replace(mainFilePattern, mainFileString);
projectFile.reset(); projectFile.open(QIODevice::WriteOnly|QIODevice::Truncate);
if (!projectFile.isOpen())
return false;
projectFile.write(projectFileContent.toUtf8()); projectFile.write(projectFileContent.toUtf8());
projectFile.close(); projectFile.close();

View File

@@ -51,6 +51,8 @@ public:
const Utils::FilePath &targetDir); const Utils::FilePath &targetDir);
static void generateMenuEntry(); static void generateMenuEntry();
static void onConvertProject(); static void onConvertProject();
static bool isProjectConvertable(const ProjectExplorer::Project *project);
static bool isProjectCurrentFormat(const ProjectExplorer::Project *project);
private: private:
bool prepareAndExecute(); bool prepareAndExecute();
@@ -68,11 +70,12 @@ private:
const Utils::FilePath &original, const Utils::FilePath &target); const Utils::FilePath &original, const Utils::FilePath &target);
bool createPreparedProject(); bool createPreparedProject();
const Utils::FilePath contentDir(); const Utils::FilePath contentDir() const;
const Utils::FilePath sourceDir(); const Utils::FilePath sourceDir() const;
const Utils::FilePath importDir(); const Utils::FilePath importDir() const;
const Utils::FilePath assetDir(); const Utils::FilePath assetDir() const;
const Utils::FilePath assetImportDir(); const Utils::FilePath assetImportDir() const;
const Utils::FilePath newProjectFile() const;
const QString environmentVariable(const QString &key) const; const QString environmentVariable(const QString &key) const;
const Utils::FilePath projectMainFile() const; const Utils::FilePath projectMainFile() const;

View File

@@ -121,6 +121,12 @@ void AssetsLibraryView::modelAboutToBeDetached(Model *model)
void AssetsLibraryView::setResourcePath(const QString &resourcePath) void AssetsLibraryView::setResourcePath(const QString &resourcePath)
{ {
if (resourcePath == m_lastResourcePath)
return;
m_lastResourcePath = resourcePath;
if (m_widget.isNull()) { if (m_widget.isNull()) {
m_widget = new AssetsLibraryWidget{m_imageCacheData->cache, m_widget = new AssetsLibraryWidget{m_imageCacheData->cache,
m_imageCacheData->asynchronousFontImageCache, m_imageCacheData->asynchronousFontImageCache,

View File

@@ -62,6 +62,7 @@ private:
std::once_flag imageCacheFlag; std::once_flag imageCacheFlag;
std::unique_ptr<ImageCacheData> m_imageCacheData; std::unique_ptr<ImageCacheData> m_imageCacheData;
QPointer<AssetsLibraryWidget> m_widget; QPointer<AssetsLibraryWidget> m_widget;
QString m_lastResourcePath;
}; };
} }

View File

@@ -321,6 +321,8 @@ static QHash<QByteArray, QStringList> allImageFormats()
void AssetsLibraryWidget::addResources(const QStringList &files) void AssetsLibraryWidget::addResources(const QStringList &files)
{ {
clearSearchFilter();
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
QTC_ASSERT(document, return); QTC_ASSERT(document, return);

View File

@@ -141,12 +141,6 @@ void DesignerActionManagerView::bindingPropertiesChanged(const QList<BindingProp
setupContext(SelectionContext::UpdateMode::Properties); setupContext(SelectionContext::UpdateMode::Properties);
} }
void DesignerActionManagerView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &)
{
if (hasSingleSelectedModelNode())
setupContext(SelectionContext::UpdateMode::Properties);
}
void DesignerActionManagerView::customNotification(const AbstractView * /*view*/, void DesignerActionManagerView::customNotification(const AbstractView * /*view*/,
const QString &identifier, const QString &identifier,
const QList<ModelNode> & /* nodeList */, const QList<ModelNode> & /* nodeList */,

View File

@@ -64,8 +64,6 @@ public:
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override; void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override;
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override; void bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChangeFlag) override;
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
DesignerActionManager &designerActionManager(); DesignerActionManager &designerActionManager();
const DesignerActionManager &designerActionManager() const; const DesignerActionManager &designerActionManager() const;
void emitSelectionChanged(); void emitSelectionChanged();

View File

@@ -69,8 +69,7 @@ bool CurveEditorView::hasWidget() const
WidgetInfo CurveEditorView::widgetInfo() WidgetInfo CurveEditorView::widgetInfo()
{ {
return createWidgetInfo( return createWidgetInfo(m_editor, "CurveEditorId", WidgetInfo::BottomPane, 0, tr("Curve Editor"));
m_editor, "CurveEditorId", WidgetInfo::BottomPane, 0, tr("CurveEditor"));
} }
void CurveEditorView::modelAttached(Model *model) void CurveEditorView::modelAttached(Model *model)

View File

@@ -2246,6 +2246,9 @@ void FormEditor3dPreview::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, const QStyleOptionGraphicsItem *option,
QWidget *widget) QWidget *widget)
{ {
Q_UNUSED(option)
Q_UNUSED(widget)
if (!painter->isActive()) if (!painter->isActive())
return; return;

View File

@@ -357,6 +357,8 @@ void FormEditorWidget::initialize()
defaultZoom = m_formEditorView->rootModelNode().auxiliaryData("formeditorZoom").toDouble(); defaultZoom = m_formEditorView->rootModelNode().auxiliaryData("formeditorZoom").toDouble();
} }
m_graphicsView->setZoomFactor(defaultZoom); m_graphicsView->setZoomFactor(defaultZoom);
if (m_formEditorView->scene() && m_formEditorView->scene()->rootFormEditorItem())
m_graphicsView->centerOn(m_formEditorView->scene()->rootFormEditorItem());
m_zoomAction->setZoomFactor(defaultZoom); m_zoomAction->setZoomFactor(defaultZoom);
updateActions(); updateActions();
} }

View File

@@ -128,11 +128,9 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(
importPaths = model->importPaths(); importPaths = model->importPaths();
} }
QString targetDir = defaulTargetDirectory; QString targetDir = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath().toString();
if (targetDir.isEmpty())
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(doc->fileName()); targetDir = defaulTargetDirectory;
if (currentProject)
targetDir = currentProject->projectDirectory().toString();
// Import is always done under known folder. The order of preference for folder is: // Import is always done under known folder. The order of preference for folder is:
// 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path // 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path

View File

@@ -234,11 +234,6 @@ void ItemLibraryModel::showAllHiddenCategories()
void ItemLibraryModel::setFlowMode(bool b) void ItemLibraryModel::setFlowMode(bool b)
{ {
m_flowMode = b; m_flowMode = b;
bool changed = false;
if (updateVisibility(&changed); changed) {
beginResetModel();
endResetModel();
}
} }
ItemLibraryModel::ItemLibraryModel(QObject *parent) ItemLibraryModel::ItemLibraryModel(QObject *parent)

View File

@@ -254,6 +254,20 @@ void ItemLibraryWidget::handleSearchfilterChanged(const QString &filterText)
} }
} }
QString ItemLibraryWidget::getDependencyImport(const Import &import)
{
static QStringList prefixDependencies = {"QtQuick3D"};
const QStringList splitImport = import.url().split('.');
if (splitImport.count() > 1) {
if (prefixDependencies.contains(splitImport.first()))
return splitImport.first();
}
return {};
}
void ItemLibraryWidget::handleAddImport(int index) void ItemLibraryWidget::handleAddImport(int index)
{ {
Import import = m_addModuleModel->getImportAt(index); Import import = m_addModuleModel->getImportAt(index);
@@ -263,8 +277,19 @@ void ItemLibraryWidget::handleAddImport(int index)
+ import.toImportString()); + import.toImportString());
} }
QList<Import> imports;
const QString dependency = getDependencyImport(import);
auto document = QmlDesignerPlugin::instance()->currentDesignDocument(); auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
document->documentModel()->changeImports({import}, {}); Model *model = document->documentModel();
if (!dependency.isEmpty()) {
Import dependencyImport = m_addModuleModel->getImport(dependency);
if (!dependencyImport.isEmpty())
imports.append(dependencyImport);
}
imports.append(import);
model->changeImports(imports, {});
QMetaObject::invokeMethod(m_itemsWidget->rootObject(), "switchToComponentsView"); QMetaObject::invokeMethod(m_itemsWidget->rootObject(), "switchToComponentsView");
updateSearch(); updateSearch();

View File

@@ -110,6 +110,7 @@ private:
void updateSearch(); void updateSearch();
void handlePriorityImportsChanged(); void handlePriorityImportsChanged();
static QString getDependencyImport(const Import &import);
QTimer m_compressionTimer; QTimer m_compressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;

View File

@@ -421,14 +421,19 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode); context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode);
// className // className
auto valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("className")))); auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject(
m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY)));
if (!valueObject) if (!valueObject)
valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
valueObject->setName("className"); valueObject->setName(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY);
valueObject->setModelNode(qmlObjectNode.modelNode()); valueObject->setModelNode(qmlObjectNode.modelNode());
valueObject->setValue(m_backendModelNode.simplifiedTypeName()); valueObject->setValue(m_backendModelNode.simplifiedTypeName());
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); QObject::connect(valueObject,
m_backendValuesPropertyMap.insert(QLatin1String("className"), QVariant::fromValue(valueObject)); &PropertyEditorValue::valueChanged,
&backendValuesPropertyMap(),
&DesignerPropertyMap::valueChanged);
m_backendValuesPropertyMap.insert(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY,
QVariant::fromValue(valueObject));
// id // id
valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("id")))); valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("id"))));
@@ -506,14 +511,19 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
foreach (const PropertyName &propertyName, metaInfo.propertyNames()) foreach (const PropertyName &propertyName, metaInfo.propertyNames())
setupPropertyEditorValue(propertyName, propertyEditor, QString::fromUtf8(metaInfo.propertyTypeName(propertyName))); setupPropertyEditorValue(propertyName, propertyEditor, QString::fromUtf8(metaInfo.propertyTypeName(propertyName)));
auto valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("className")))); auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject(
m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY)));
if (!valueObject) if (!valueObject)
valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap); valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
valueObject->setName("className"); valueObject->setName(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY);
valueObject->setValue(typeName); valueObject->setValue(typeName);
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged); QObject::connect(valueObject,
m_backendValuesPropertyMap.insert(QLatin1String("className"), QVariant::fromValue(valueObject)); &PropertyEditorValue::valueChanged,
&backendValuesPropertyMap(),
&DesignerPropertyMap::valueChanged);
m_backendValuesPropertyMap.insert(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY,
QVariant::fromValue(valueObject));
// id // id
valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("id")))); valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("id"))));

View File

@@ -144,7 +144,7 @@ void PropertyEditorView::changeValue(const QString &name)
if (locked()) if (locked())
return; return;
if (propertyName == "className") if (propertyName == Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY)
return; return;
if (noValidSelection()) if (noValidSelection())

View File

@@ -464,7 +464,8 @@ void RewriterView::auxiliaryDataChanged(const ModelNode &node, const PropertyNam
return; return;
if (node.isRootNode()) { if (node.isRootNode()) {
if (name == "width" || name == "height" || name == "autoSize" || name == "formeditorColor") if (name == "width" || name == "height" || name == "autoSize" || name == "formeditorColor"
|| name == "formeditorZoom")
return; return;
} }

View File

@@ -43,7 +43,7 @@ class ProjectStorage;
using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>; using PathCache = SourcePathCache<ProjectStorage<Sqlite::Database>, NonLockingMutex>;
class FileSystem final : public FileSystemInterface class FileSystem : public FileSystemInterface
{ {
public: public:
FileSystem(PathCache &sourcePathCache) FileSystem(PathCache &sourcePathCache)

View File

@@ -1924,6 +1924,8 @@ private:
void createTypesAndePropertyDeclarationsTables(Database &database, void createTypesAndePropertyDeclarationsTables(Database &database,
const Sqlite::Column &foreignModuleIdColumn) const Sqlite::Column &foreignModuleIdColumn)
{ {
Q_UNUSED(foreignModuleIdColumn)
Sqlite::Table typesTable; Sqlite::Table typesTable;
typesTable.setUseIfNotExists(true); typesTable.setUseIfNotExists(true);
typesTable.setName("types"); typesTable.setName("types");

View File

@@ -214,11 +214,7 @@ void DesignModeWidget::setup()
m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet)); m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet));
// Setup icons // Setup icons
const QColor iconColor(Theme::getColor(Theme::DStitleBarIcon));
const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::adsClose); const QString closeUnicode = Theme::getIconUnicode(Theme::Icon::adsClose);
const QString menuUnicode = Theme::getIconUnicode(Theme::Icon::adsDropDown);
const QString undockUnicode = Theme::getIconUnicode(Theme::Icon::adsDetach);
const QString fontName = "qtds_propertyIconFont.ttf"; const QString fontName = "qtds_propertyIconFont.ttf";
const QSize size = QSize(28, 28); const QSize size = QSize(28, 28);

View File

@@ -34,7 +34,7 @@
#include <QMetaObject> #include <QMetaObject>
namespace Utils { namespace QmlDesigner {
enum FoundLicense { enum FoundLicense {
community, community,

View File

@@ -107,6 +107,8 @@ const char EVENT_TIMELINE_TIME[] = "Timeline";
const char EVENT_TRANSITIONEDITOR_TIME[] = "Transition Editor"; const char EVENT_TRANSITIONEDITOR_TIME[] = "Transition Editor";
const char EVENT_CURVEDITOR_TIME[] = "Curve Editor"; const char EVENT_CURVEDITOR_TIME[] = "Curve Editor";
const char PROPERTY_EDITOR_CLASSNAME_PROPERTY[] = "__classNamePrivateInternal";
namespace Internal { namespace Internal {
enum { debug = 0 }; enum { debug = 0 };
} }

View File

@@ -312,8 +312,11 @@ bool QmlDesignerPlugin::delayedInitialize()
d->viewManager.registerFormEditorTool(std::make_unique<QmlDesigner::PathTool>()); d->viewManager.registerFormEditorTool(std::make_unique<QmlDesigner::PathTool>());
d->viewManager.registerFormEditorTool(std::make_unique<QmlDesigner::TransitionTool>()); d->viewManager.registerFormEditorTool(std::make_unique<QmlDesigner::TransitionTool>());
if (QmlProjectManager::QmlProject::isQtDesignStudio()) if (QmlProjectManager::QmlProject::isQtDesignStudio()) {
emitUsageStatistics("StandaloneMode"); emitUsageStatistics("StandaloneMode");
if (QmlProjectManager::QmlProject::isQtDesignStudioStartedFromQtC())
emitUsageStatistics("QDSlaunchedFromQtC");
}
return true; return true;
} }

View File

@@ -135,8 +135,6 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
disconnect(m_openFileConnection); disconnect(m_openFileConnection);
if (target && success) { if (target && success) {
const Utils::FilePath &folder = projectDirectory() + "/content";
Utils::FilePaths uiFiles = getUiQmlFilesForFolder(projectDirectory() Utils::FilePaths uiFiles = getUiQmlFilesForFolder(projectDirectory()
+ "/content"); + "/content");
if (uiFiles.isEmpty()) if (uiFiles.isEmpty())
@@ -517,6 +515,11 @@ bool QmlProject::isQtDesignStudio()
return settings->value(qdsStandaloneEntry, false).toBool(); return settings->value(qdsStandaloneEntry, false).toBool();
} }
bool QmlProject::isQtDesignStudioStartedFromQtC()
{
return qEnvironmentVariableIsSet(Constants::enviromentLaunchedQDS);
}
ProjectExplorer::DeploymentKnowledge QmlProject::deploymentKnowledge() const ProjectExplorer::DeploymentKnowledge QmlProject::deploymentKnowledge() const
{ {
return DeploymentKnowledge::Perfect; return DeploymentKnowledge::Perfect;

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