Merge "Merge remote-tracking branch 'origin/7.0'"

This commit is contained in:
The Qt Project
2022-02-16 10:19:15 +00:00
123 changed files with 1627 additions and 455 deletions

View File

@@ -101,6 +101,8 @@ if(Googletest_FOUND AND NOT TARGET Googletest)
GTEST_HAS_DEATH_TEST
)
set_target_properties(Googletest PROPERTIES AUTOMOC OFF AUTOUIC OFF)
set_property(TARGET Googletest PROPERTY POSITION_INDEPENDENT_CODE ON)
target_compile_definitions(Googletest PUBLIC GOOGLE_TEST_IS_FOUND)
target_link_libraries(Googletest Threads::Threads)
endif()

View File

@@ -763,7 +763,8 @@ function(extend_qtc_executable name)
endfunction()
function(add_qtc_test name)
cmake_parse_arguments(_arg "GTEST" "TIMEOUT" "DEFINES;DEPENDS;INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;SKIP_PCH" ${ARGN})
cmake_parse_arguments(_arg "GTEST;MANUALTEST" "TIMEOUT"
"DEFINES;DEPENDS;INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;SKIP_PCH;CONDITION" ${ARGN})
if ($_arg_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "add_qtc_test had unparsed arguments!")
@@ -771,6 +772,10 @@ function(add_qtc_test name)
update_cached_list(__QTC_TESTS "${name}")
if (NOT _arg_CONDITION)
set(_arg_CONDITION ON)
endif()
string(TOUPPER "BUILD_TEST_${name}" _build_test_var)
set(_build_test_default ${BUILD_TESTS_BY_DEFAULT})
if (DEFINED ENV{QTC_${_build_test_var}})
@@ -778,7 +783,7 @@ function(add_qtc_test name)
endif()
set(${_build_test_var} "${_build_test_default}" CACHE BOOL "Build test ${name}.")
if (NOT ${_build_test_var})
if (NOT ${_build_test_var} OR NOT ${_arg_CONDITION})
return()
endif()
@@ -820,7 +825,7 @@ function(add_qtc_test name)
enable_pch(${name})
endif()
if (NOT _arg_GTEST)
if (NOT _arg_GTEST AND NOT _arg_MANUALTEST)
add_test(NAME ${name} COMMAND ${name})
if (DEFINED _arg_TIMEOUT)
set(timeout_option TIMEOUT ${_arg_TIMEOUT})

View File

@@ -348,6 +348,15 @@
\li Qt 5.3
\li Qt Quick 2
\row
\li \uicontrol Quick3D
\li Displays the time spent rendering Qt Quick 3D frames, timing information
for frame preparation and synchronization, particle system update times
and particle update count, as well as texture and mesh memory allocations
and memory consumption.
\li Qt 6.3
\li Qt Quick 3D
\endtable
\section2 Analyzing Scene Graph Events
@@ -550,6 +559,75 @@
\li None
\endtable
\section2 Analyzing Qt Quick 3D Events
The following is the list of events for Qt Quick 3D. Each rendered frame
consists of synchronize, prepare, and render phases, which are done in that order.
Synchronize happens in scene graph synchronizing phase, while prepare and
render happen in scene graph rendering phase.
Setting the environment variable \c QSG_RENDERER_DEBUG=render will also give
additional textual output of render call counts of different rendering passes.
These call counts are summed up in the Render Frame event.
\table
\header
\li Event Type
\li Thread
\li Description
\row
\li \uicontrol {Render Frame}
\li Render
\li Render time of a frame. Also shows the number of draw calls.
\row
\li \uicontrol {Prepare Frame}
\li Render
\li Time taken for preparing a frame. Resources are allocated and loaded
in the prepare phase. The first frame after scene loading usually takes
longer than others since most resources are loaded at that time.
\row
\li \uicontrol {Synchronize Frame}
\li Render
\li Synchronize time of a frame. Synchronize takes care of updating backend
values from the frontend. Also manages shared resources between Qt Quick
Scene Graph and Qt Quick 3D.
\row
\li \uicontrol {Mesh Load}
\li Render
\li Load time of a mesh. Shows total memory usage of all meshes. Also shows
unloads.
\row
\li \uicontrol {Custom Mesh Load}
\li Render
\li Load time of a custom mesh. Shows total memory usage of all meshes.
Also shows unloads.
\row
\li \uicontrol {Texture Load}
\li Render
\li Load time of a texture. Shows total memory usage of all textures.
Also shows unloads.
\row
\li \uicontrol {Generate Shader}
\li Render
\li Time for generating a shader for a material.
\row
\li \uicontrol {Load Shader}
\li Render
\li Time for loading a built-in shader.
\row
\li \uicontrol {Particle Update}
\li GUI
\li Update time of a particle system. Shows the number of particles updated.
\row
\li \uicontrol {Mesh Memory Consumption}
\li Render
\li Shows a bar view of total mesh memory consumption.
\row
\li \uicontrol {Texture Memory Consumption}
\li Render
\li Shows a bar view of total texture memory consumption.
\endtable
\section1 Viewing Statistics
The \uicontrol Statistics view displays the number of times each binding, create,

View File

@@ -173,6 +173,7 @@ def build_qtcreator(args, paths):
'-DBUILD_QBS=' + cmake_option(build_qbs),
'-DBUILD_DEVELOPER_DOCS=' + cmake_option(not args.no_docs),
'-DBUILD_EXECUTABLE_SDKTOOL=OFF',
'-DQTC_FORCE_XCB=ON',
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install),
'-DWITH_TESTS=' + cmake_option(args.with_tests)]
cmake_args += common_cmake_arguments(args)

View File

@@ -445,7 +445,7 @@ Item {
hideHeader: dirDepth === 0
showLeftBorder: dirDepth > 0
expanded: dirExpanded
visible: !assetsModel.isEmpty && dirVisible
visible: dirVisible
expandOnClick: false
useDefaulContextMenu: false

View File

@@ -91,6 +91,12 @@ Item {
if (mouse.button === Qt.LeftButton)
rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y))
}
onDoubleClicked: (mouse)=> {
if (mouse.button === Qt.LeftButton && itemComponentSource) {
hide()
rootView.goIntoComponent(itemComponentSource)
}
}
}
}
}

View File

@@ -76,8 +76,9 @@ itemLibraryModel [
Item {
id: itemsView
property string importToRemove: ""
property string importToAdd: ""
property string importToRemove
property string importToAdd
property string componentSource
property var currentCategory: null
property var currentImport: null
property bool isHorizontalView: false
@@ -123,7 +124,7 @@ Item {
text: qsTr("Remove Module")
visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0
enabled: itemsView.importToRemove !== "" && !rootView.subCompEditMode
enabled: itemsView.importToRemove && !rootView.subCompEditMode
onTriggered: rootView.removeImport(itemsView.importToRemove)
}
@@ -184,14 +185,23 @@ Item {
StudioControls.Menu {
id: itemContextMenu
// Workaround for menu item implicit width not properly propagating to menu
width: importMenuItem.implicitWidth
width: Math.max(importMenuItem.implicitWidth, openSourceItem.implicitWidth)
StudioControls.MenuItem {
id: importMenuItem
text: qsTr("Add Module: ") + itemsView.importToAdd
enabled: itemsView.importToAdd !== ""
visible: itemsView.importToAdd
height: visible ? implicitHeight : 0
onTriggered: rootView.addImportForItem(itemsView.importToAdd)
}
StudioControls.MenuItem {
id: openSourceItem
text: qsTr("Go into Component")
visible: itemsView.componentSource
height: visible ? implicitHeight : 0
onTriggered: rootView.goIntoComponent(itemsView.componentSource)
}
}
}
@@ -323,8 +333,9 @@ Item {
width: styleConstants.cellWidth
height: styleConstants.cellHeight
onShowContextMenu: {
if (!itemUsable) {
itemsView.importToAdd = itemRequiredImport
if (!itemUsable || itemComponentSource) {
itemsView.importToAdd = !itemUsable ? itemRequiredImport : ""
itemsView.componentSource = itemComponentSource
itemContextMenu.popup()
}
}
@@ -480,8 +491,9 @@ Item {
width: styleConstants.cellWidth
height: styleConstants.cellHeight
onShowContextMenu: {
if (!itemUsable) {
itemsView.importToAdd = itemRequiredImport
if (!itemUsable || itemComponentSource) {
itemsView.importToAdd = !itemUsable ? itemRequiredImport : ""
itemsView.componentSource = itemComponentSource
itemContextMenu.popup()
}
}

View File

@@ -32,6 +32,11 @@ MouseArea {
signal showContextMenu()
function hide()
{
tooltipBackend.hideTooltip()
}
onExited: tooltipBackend.hideTooltip()
onCanceled: tooltipBackend.hideTooltip()
onPositionChanged: tooltipBackend.reposition()

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Custom Button",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_button.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Custom CheckBox",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_checkbox.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Custom Dial",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_dial.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Custom Slider",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_slider.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Custom SpinBox",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_spinbox.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Custom Switch",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_switch.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Flow Item",
"trDisplayCategory": "Qt Quick Files",
"icon": "flow_item.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Flow View",
"trDisplayCategory": "Qt Quick Files",
"icon": "flow_view.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Java Script File",
"trDisplayCategory": "Java Script",
"icon": "file_javascript.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,

View File

@@ -7,7 +7,6 @@
"trDisplayName": "ListModel",
"trDisplayCategory": "QML Files",
"icon": "data_listmodel.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Pane",
"trDisplayCategory": "Qt Quick Controls",
"icon": "custom_panes.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Qt Quick File",
"trDisplayCategory": "Qt Quick Files",
"icon": "file_qml.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Qt Quick Views",
"trDisplayCategory": "Qt Quick Files",
"icon": "data_gridmodel.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -7,7 +7,6 @@
"trDisplayName": "Qt Quick UI File",
"trDisplayCategory": "Qt Quick Files",
"icon": "file_ui.png",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -6,7 +6,6 @@
"trDescription": "Creates a UI file (.ui.qml) with a Stacked Layout as the root component.",
"trDisplayName": "Stacked Layout",
"trDisplayCategory": "Qt Quick Controls",
"featuresRequired": [ "QtStudio" ],
"icon": "custom_stacked_view.png",
"platformIndependent": true,

View File

@@ -6,7 +6,6 @@
"trDescription": "Creates a UI file (.ui.qml) with a Swipe View as the root component.",
"trDisplayName": "Swipe View",
"trDisplayCategory": "Qt Quick Controls",
"featuresRequired": [ "QtStudio" ],
"icon": "custom_swipe_view.png",
"platformIndependent": true,

View File

@@ -9,7 +9,6 @@
"icon": "desktop_blank.png",
"fontIconName": "wizardsGeneric",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -9,7 +9,6 @@
"icon": "desktop_blank.png",
"fontIconName": "wizardsMcuEmpty",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -9,7 +9,6 @@
"icon": "desktop_blank.png",
"fontIconName": "wizardsGeneric",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -9,7 +9,6 @@
"icon": "desktop_launcher.png",
"fontIconName": "wizardsDesktop",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -9,7 +9,6 @@
"icon": "mobile_scroll.png",
"fontIconName": "wizardsMobile",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -9,7 +9,6 @@
"icon": "mobile_stack.png",
"fontIconName": "wizardsMobile",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -9,7 +9,6 @@
"icon": "mobile_swipe.png",
"fontIconName": "wizardsMobile",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtStudio" ],
"platformIndependent": true,
"options":

View File

@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@if %{HasTranslation}

View File

@@ -1,6 +1,6 @@
QT -= gui
CONFIG += c++11 console
CONFIG += c++17 console
CONFIG -= app_bundle
# You can make your code fail to compile if it uses deprecated APIs.

View File

@@ -1,4 +1,4 @@
project('%{ProjectName}', 'cpp',default_options : ['cpp_std=c++11'], meson_version:'>=0.44')
project('%{ProjectName}', 'cpp',default_options : ['cpp_std=c++17'], meson_version:'>=0.44')
# Documentation: https://mesonbuild.com/Qt5-module.html
qt5 = import('qt5')

View File

@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
@endif
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@if '%{QtModule}' != 'none'

View File

@@ -1,8 +1,8 @@
project('%{ProjectName}', 'cpp',
@if %{IsStatic}
default_options : ['cpp_std=c++11', 'default_library=static'],
default_options : ['cpp_std=c++17', 'default_library=static'],
@else
default_options : ['cpp_std=c++11', 'default_library=shared'],
default_options : ['cpp_std=c++17', 'default_library=shared'],
@endif
meson_version:'>=0.48')

View File

@@ -15,7 +15,7 @@ CONFIG += plugin
DEFINES += %{LibraryDefine}
@endif
CONFIG += c++11
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.

View File

@@ -11,7 +11,7 @@ DynamicLibrary {
Depends { name: "Qt.%{QtModule}" }
@endif
cpp.cxxLanguageVersion: "c++11"
cpp.cxxLanguageVersion: "c++17"
cpp.defines: [
@if %{IsShared}
"%{LibraryDefine}",

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5)
project(%{ProjectName} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(%{ProjectName} %{CppFileName})

View File

@@ -1,5 +1,5 @@
TEMPLATE = app
CONFIG += console c++11
CONFIG += console c++17
CONFIG -= app_bundle
CONFIG -= qt

View File

@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@if %{HasTranslation}

View File

@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@if %{HasTranslation}

View File

@@ -2,7 +2,7 @@ QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.

View File

@@ -24,6 +24,12 @@ add_qtc_executable(qtcreator
QTC_RUNNABLE
)
extend_qtc_executable(qtcreator
CONDITION APPLE
SOURCES
main_mac.mm
)
if (NOT TARGET qtcreator)
return()
endif()
@@ -86,6 +92,13 @@ if (APPLE)
)
endif()
option(QTC_FORCE_XCB "Enables that Qt Creator forces XCB on Linux if QT_QPA_PLATFORM is not set." OFF)
extend_qtc_executable(qtcreator
CONDITION QTC_FORCE_XCB
DEFINES
QTC_FORCE_XCB
)
extend_qtc_executable(qtcreator
CONDITION BUILD_WITH_CRASHPAD
DEFINES

View File

@@ -500,6 +500,26 @@ int main(int argc, char **argv)
qputenv("QT_ENABLE_REGEXP_JIT", "0");
}
#if defined(QTC_FORCE_XCB)
if (Utils::HostOsInfo::isLinuxHost() && !qEnvironmentVariableIsSet("QT_QPA_PLATFORM")) {
// Enforce XCB on Linux/Gnome, if the user didn't override via QT_QPA_PLATFORM
// This was previously done in Qt, but removed in Qt 6.3. We found that bad things can still happen,
// like the Wayland session simply crashing when starting Qt Creator.
// TODO: Reconsider when Qt/Wayland is reliably working on the supported distributions
const bool hasWaylandDisplay = qEnvironmentVariableIsSet("WAYLAND_DISPLAY");
const bool isWaylandSessionType = qgetenv("XDG_SESSION_TYPE") == "wayland";
const QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
const QByteArray sessionDesktop = qgetenv("XDG_SESSION_DESKTOP").toLower();
const bool isGnome = currentDesktop.contains("gnome") || sessionDesktop.contains("gnome");
const bool isWayland = hasWaylandDisplay || isWaylandSessionType;
if (isGnome && isWayland) {
qInfo() << "Warning: Ignoring WAYLAND_DISPLAY on Gnome."
<< "Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.";
qputenv("QT_QPA_PLATFORM", "xcb");
}
}
#endif
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
#ifdef Q_OS_MACOS

38
src/app/main_mac.mm Normal file
View File

@@ -0,0 +1,38 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include <qglobal.h>
#include <Foundation/NSNumberFormatter.h>
#include <Foundation/NSUserDefaults.h>
// Disable "ApplePressAndHold". That feature allows entering special characters by holding
// a key, e.g. holding the 'l' key opens a popup that allows entering 'ł'.
// Since that disables key repeat, we don't want it, though.
static void initializeCreatorDefaults()
{
[NSUserDefaults.standardUserDefaults registerDefaults:@{@"ApplePressAndHoldEnabled": @NO}];
}
Q_CONSTRUCTOR_FUNCTION(initializeCreatorDefaults);

View File

@@ -28,6 +28,7 @@ import QtCreator.Tracing 1.0
import QtQml 2.2
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.3
ScrollView {
id: root
@@ -315,6 +316,7 @@ ScrollView {
ComboBox {
id: modesMenu
width: 260 // TODO: Use implicitContentWidthPolicy (Qt6-only)
x: flickable.width - width
y: flickable.contentY
model: root.modes.map(function(role) { return root.trRoleNames[role] });

View File

@@ -41,7 +41,7 @@ namespace OsSpecificAspects {
inline QString withExecutableSuffix(OsType osType, const QString &executable)
{
QString finalName = executable;
if (osType == OsTypeWindows)
if (osType == OsTypeWindows && !finalName.endsWith(QTC_WIN_EXE_SUFFIX))
finalName += QLatin1String(QTC_WIN_EXE_SUFFIX);
return finalName;
}

View File

@@ -544,7 +544,7 @@ void VariableChooserPrivate::updatePositionAndShow(bool)
{
if (QWidget *w = q->parentWidget()) {
QPoint parentCenter = w->mapToGlobal(w->geometry().center());
q->move(parentCenter.x() - q->width()/2, parentCenter.y() - q->height()/2);
q->move(parentCenter.x() - q->width()/2, qMax(parentCenter.y() - q->height()/2, 0));
}
q->show();
q->raise();

View File

@@ -1782,8 +1782,7 @@ void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Loca
}
qCDebug(clangdLog) << "document count is" << refData->fileData.size();
if (refData->replacementData || q->versionNumber() < QVersionNumber(13)
|| !refData->categorize) {
if (refData->replacementData || !refData->categorize) {
qCDebug(clangdLog) << "skipping AST retrieval";
reportAllSearchResultsAndFinish(*refData);
return;
@@ -1953,11 +1952,6 @@ void ClangdClient::followSymbol(TextDocument *document,
};
symbolSupport().findLinkAt(document, adjustedCursor, std::move(gotoDefCallback), true);
if (versionNumber() < QVersionNumber(12)) {
d->followSymbolData->cursorNode.emplace(AstNode());
return;
}
const auto astHandler = [this, id = d->followSymbolData->id]
(const AstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast response for cursor";
@@ -2747,6 +2741,11 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
const QList<AstNode> path = getAstPath(ast, range);
if (path.size() < 2)
return false;
if (token.type == "property"
&& (path.rbegin()->kind() == "MemberInitializer"
|| path.rbegin()->kind() == "CXXConstruct")) {
return false;
}
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
if (it->kind() == "Call" || it->kind() == "CXXConstruct"
|| it->kind() == "MemberInitializer") {
@@ -2859,7 +2858,6 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
styles.mainStyle = C_FIELD;
} else if (token.type == "enum") {
styles.mainStyle = C_TYPE;
styles.mixinStyles.push_back(C_ENUMERATION);
} else if (token.type == "enumMember") {
styles.mainStyle = C_ENUMERATION;
} else if (token.type == "parameter") {
@@ -3640,9 +3638,11 @@ void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
if (node.kind().endsWith("Literal")) {
HighlightingResult result;
result.useTextSyles = true;
const bool isStringLike = node.kind().startsWith("String")
|| node.kind().startsWith("Character");
result.textStyles.mainStyle = isStringLike ? C_STRING : C_NUMBER;
const bool isKeyword = node.kind() == "CXXBoolLiteral"
|| node.kind() == "CXXNullPtrLiteral";
const bool isStringLike = !isKeyword && (node.kind().startsWith("String")
|| node.kind().startsWith("Character"));
result.textStyles.mainStyle = isKeyword ? C_KEYWORD : isStringLike ? C_STRING : C_NUMBER;
setResultPosFromRange(result, node.range());
insertResult(result);
return;

View File

@@ -260,7 +260,7 @@ void ClangFollowSymbol::switchDeclDef(const CppEditor::CursorInEditor &data,
{
ClangdClient * const client
= ClangModelManagerSupport::instance()->clientForFile(data.filePath());
if (client && client->isFullyIndexed() && client->versionNumber() >= QVersionNumber(13)) {
if (client && client->isFullyIndexed()) {
client->switchDeclDef(data.textDocument(), data.cursor(), data.editorWidget(),
std::move(processLinkCallback));
return;

View File

@@ -179,7 +179,6 @@ ClangdTestFindReferences::ClangdTestFindReferences()
{
setProjectFileName("find-usages.pro");
setSourceFileNames({"defs.h", "main.cpp"});
setMinimumVersion(13);
}
void ClangdTestFindReferences::initTestCase()
@@ -322,7 +321,6 @@ ClangdTestFollowSymbol::ClangdTestFollowSymbol()
{
setProjectFileName("follow-symbol.pro");
setSourceFileNames({"main.cpp", "header.h"});
setMinimumVersion(12);
}
void ClangdTestFollowSymbol::test_data()
@@ -409,7 +407,6 @@ ClangdTestLocalReferences::ClangdTestLocalReferences()
{
setProjectFileName("local-references.pro");
setSourceFileNames({"references.cpp"});
setMinimumVersion(13);
}
// We currently only support local variables, but if and when clangd implements
@@ -525,7 +522,6 @@ ClangdTestTooltips::ClangdTestTooltips()
{
setProjectFileName("tooltips.pro");
setSourceFileNames({"tooltips.cpp"});
setMinimumVersion(13);
}
void ClangdTestTooltips::test_data()
@@ -668,7 +664,6 @@ ClangdTestHighlighting::ClangdTestHighlighting()
{
setProjectFileName("highlighting.pro");
setSourceFileNames({"highlighting.cpp"});
setMinimumVersion(13);
}
void ClangdTestHighlighting::initTestCase()
@@ -744,11 +739,11 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("static member function call") << 114 << 15 << 114 << 27
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("enum declaration") << 118 << 6 << 118 << 17
<< QList<int>{C_TYPE, C_ENUMERATION, C_DECLARATION} << 0;
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
QTest::newRow("enumerator declaration") << 120 << 5 << 120 << 15
<< QList<int>{C_ENUMERATION, C_DECLARATION} << 0;
QTest::newRow("enum in variable declaration") << 125 << 5 << 125 << 16
<< QList<int>{C_TYPE, C_ENUMERATION} << 0;
<< QList<int>{C_TYPE} << 0;
QTest::newRow("enum variable declaration") << 125 << 17 << 125 << 28
<< QList<int>{C_LOCAL, C_DECLARATION} << 0;
QTest::newRow("enum variable reference") << 127 << 5 << 127 << 16 << QList<int>{C_LOCAL} << 0;
@@ -966,7 +961,7 @@ void ClangdTestHighlighting::test_data()
<< 310 << 29 << 310 << 38
<< QList<int>{C_FIELD} << 0;
QTest::newRow("enum declaration with underlying type") << 316 << 6 << 316 << 21
<< QList<int>{C_TYPE, C_ENUMERATION, C_DECLARATION} << 0;
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
QTest::newRow("type in static_cast") << 328 << 23 << 328 << 33
<< QList<int>{C_TYPE} << 0;
QTest::newRow("opening angle bracket in static_cast") << 328 << 16 << 328 << 17
@@ -1293,6 +1288,13 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_LOCAL} << 0;
QTest::newRow("const operator()") << 903 << 5 << 903 << 7
<< QList<int>{C_LOCAL} << 0;
QTest::newRow("member initialization: member (user-defined type)") << 911 << 14 << 911 << 18
<< QList<int>{C_FIELD} << 0;
QTest::newRow("member initialization: member (built-in type)") << 911 << 23 << 911 << 27
<< QList<int>{C_FIELD} << 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: nullptr") << 922 << 15 << 922 << 22 << QList<int>{C_KEYWORD} << 0;
}
void ClangdTestHighlighting::test()
@@ -2015,9 +2017,10 @@ void ClangdTestExternalChanges::test()
header.close();
ClangdClient * const oldClient = client();
QVERIFY(oldClient);
QVERIFY(!waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
&ClangModelManagerSupport::createdClient, timeOutInMs()));
waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
&ClangModelManagerSupport::createdClient, timeOutInMs());
QCOMPARE(client(), oldClient);
QCOMPARE(client(), ClangModelManagerSupport::instance()->clientForProject(project()));
const TextDocument * const curDoc = document("main.cpp");
QVERIFY(curDoc);
QVERIFY(curDoc->marks().isEmpty());

View File

@@ -902,3 +902,22 @@ void callOperators()
Callable2 c2;
c2();
}
namespace std { template<typename T> struct atomic { atomic(int) {} }; }
void constructorMemberInitialization()
{
struct S {
S(): m_m1(1), m_m2(0) {}
std::atomic<int> m_m1;
int m_m2;
};
}
void keywords()
{
bool b1 = true;
bool b2 = false;
void *p = nullptr;
}

View File

@@ -428,6 +428,13 @@ static QIcon interruptIcon(bool toolBarStyle)
return toolBarStyle ? iconToolBar : icon;
}
static bool hideAnalyzeMenu()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
.toBool();
}
QAction *addAction(const QObject *parent, QMenu *menu, const QString &display, bool on,
const std::function<void()> &onTriggered)
{
@@ -775,7 +782,8 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR);
ActionContainer *mtools = ActionManager::actionContainer(M_TOOLS);
menubar->addMenu(mtools, m_menu);
if (!hideAnalyzeMenu())
menubar->addMenu(mtools, m_menu);
m_menu->addSeparator(G_ANALYZER_TOOLS);
m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS);

View File

@@ -156,7 +156,8 @@ void OutputCollector::newConnectionAvailable()
void OutputCollector::bytesAvailable()
{
#ifdef Q_OS_WIN
emit byteDelivery(m_socket->readAll());
if (m_socket)
emit byteDelivery(m_socket->readAll());
#else
size_t nbytes = 0;
if (::ioctl(m_serverFd, FIONREAD, (char *) &nbytes) < 0)

View File

@@ -34,7 +34,6 @@ const char ACTION_ID[] = "Docker.Action";
const char MENU_ID[] = "Docker.Menu";
const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType";
const char DOCKER_RUN_FLAGS[] = "DockerRunFlags";
const char DOCKER_BUILDHOST_BUILDSTEP_ID[] = "Docker.BuildStep.BuildHost";

View File

@@ -123,8 +123,6 @@ void DockerDeviceProcess::start()
DockerDevice::ConstPtr dockerDevice = qSharedPointerCast<const DockerDevice>(device());
QTC_ASSERT(dockerDevice, return);
const QStringList dockerRunFlags = extraData(Constants::DOCKER_RUN_FLAGS).toStringList();
connect(this, &DeviceProcess::readyReadStandardOutput, this, [this] {
MessageManager::writeSilently(QString::fromLocal8Bit(readAllStandardError()));
});

View File

@@ -105,6 +105,10 @@ Client::Client(BaseClientInterface *clientInterface)
connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
connect(Core::EditorManager::instance(),
&Core::EditorManager::documentClosed,
this,
&Client::documentClosed);
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
@@ -308,13 +312,11 @@ void Client::initialize()
initRequest.setResponseCallback([this](const InitializeRequest::Response &initResponse){
initializeCallback(initResponse);
});
// directly send data otherwise the state check would fail;
if (Utils::optional<ResponseHandler> responseHandler = initRequest.responseHandler())
m_responseHandlers[responseHandler->id] = responseHandler->callback;
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage,
name(),
initRequest.toBaseMessage());
// directly send message otherwise the state check of sendContent would fail
sendMessage(initRequest.toBaseMessage());
m_clientInterface->sendMessage(initRequest.toBaseMessage());
m_state = InitializeRequested;
}
@@ -427,9 +429,7 @@ void Client::sendContent(const IContent &content, SendDocUpdates sendUpdates)
QString error;
if (!QTC_GUARD(content.isValid(&error)))
Core::MessageManager::writeFlashing(error);
const BaseMessage message = content.toBaseMessage();
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
m_clientInterface->sendMessage(message);
sendMessage(content.toBaseMessage());
}
void Client::cancelRequest(const MessageId &id)
@@ -632,6 +632,12 @@ void Client::deactivateDocument(TextEditor::TextDocument *document)
}
}
void Client::documentClosed(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
closeDocument(textDocument);
}
bool Client::documentOpen(const TextEditor::TextDocument *document) const
{
return m_openedDocument.contains(const_cast<TextEditor::TextDocument *>(document));
@@ -1486,6 +1492,12 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
}
}
void Client::sendMessage(const BaseMessage &message)
{
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
m_clientInterface->sendMessage(message);
}
bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
{
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
@@ -1602,8 +1614,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
qDebug() << error;
return;
}
// directly send data otherwise the state check would fail;
m_clientInterface->sendMessage(ExitNotification().toBaseMessage());
// directly send message otherwise the state check of sendContent would fail
sendMessage(ExitNotification().toBaseMessage());
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown";
m_state = Shutdown;
}

View File

@@ -227,6 +227,7 @@ protected:
virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params);
private:
void sendMessage(const LanguageServerProtocol::BaseMessage &message);
void handleResponse(const LanguageServerProtocol::MessageId &id, const QByteArray &content,
QTextCodec *codec);
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
@@ -252,6 +253,7 @@ private:
void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
void documentClosed(Core::IDocument *document);
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}

View File

@@ -542,11 +542,8 @@ void LanguageClientManager::documentOpened(Core::IDocument *document)
void LanguageClientManager::documentClosed(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document)) {
for (Client *client : qAsConst(m_clients))
client->closeDocument(textDocument);
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
m_clientForDocument.remove(textDocument);
}
}
void LanguageClientManager::documentContentsSaved(Core::IDocument *document)

View File

@@ -7,7 +7,7 @@ add_qtc_plugin(McuSupport
mcusupport_global.h
mcusupportconstants.h
mcusupportdevice.cpp mcusupportdevice.h
mcusupportoptions.cpp mcusupportoptions.h
mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h
mcusupportoptionspage.cpp mcusupportoptionspage.h
mcupackage.cpp mcupackage.h
mcusupportplugin.cpp mcusupportplugin.h
@@ -15,4 +15,7 @@ add_qtc_plugin(McuSupport
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
mcusupportversiondetection.cpp mcusupportversiondetection.h
mcusupportcmakemapper.cpp mcusupportcmakemapper.h
mcutargetdescription.h
)
add_subdirectory(test)

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QObject>
namespace Utils {
class FilePath;
} // namespace Utils
namespace McuSupport::Internal {
class McuAbstractPackage : public QObject
{
Q_OBJECT
public:
enum class Status {
EmptyPath,
InvalidPath,
ValidPathInvalidPackage,
ValidPackageMismatchedVersion,
ValidPackage
};
virtual Utils::FilePath basePath() const = 0;
virtual Utils::FilePath path() const = 0;
virtual QString label() const = 0;
virtual Utils::FilePath defaultPath() const = 0;
virtual QString detectionPath() const = 0;
virtual QString statusText() const = 0;
virtual void updateStatus() = 0;
virtual Status status() const = 0;
virtual bool validStatus() const = 0;
virtual const QString &environmentVariableName() const = 0;
virtual void setAddToPath(bool) = 0;
virtual bool addToPath() const = 0;
virtual void writeGeneralSettings() const = 0;
virtual bool writeToSettings() const = 0;
virtual void setRelativePathModifier(const QString &) = 0;
virtual void setVersions(const QStringList &) = 0;
virtual bool automaticKitCreationEnabled() const = 0;
virtual void setAutomaticKitCreationEnabled(const bool enabled) = 0;
virtual QWidget *widget() = 0;
signals:
void changed();
void statusChanged();
}; // class McuAbstractPackage
} // namespace McuSupport::Internal

View File

@@ -38,8 +38,7 @@
using namespace Utils;
namespace McuSupport {
namespace Internal {
namespace McuSupport::Internal {
static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope)
{
@@ -144,8 +143,7 @@ McuPackage::Status McuPackage::status() const
bool McuPackage::validStatus() const
{
return m_status == McuPackage::ValidPackage
|| m_status == McuPackage::ValidPackageMismatchedVersion;
return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
}
const QString &McuPackage::environmentVariableName() const
@@ -221,11 +219,11 @@ void McuPackage::updateStatus()
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|| m_versions.contains(m_detectedVersion);
m_status = validPath
? (validPackage ? (validVersion ? ValidPackage : ValidPackageMismatchedVersion)
: ValidPathInvalidPackage)
: m_path.isEmpty() ? EmptyPath
: InvalidPath;
m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage
: Status::ValidPackageMismatchedVersion)
: Status::ValidPathInvalidPackage)
: m_path.isEmpty() ? Status::EmptyPath
: Status::InvalidPath;
emit statusChanged();
}
@@ -233,10 +231,10 @@ void McuPackage::updateStatus()
void McuPackage::updateStatusUi()
{
switch (m_status) {
case ValidPackage:
case Status::ValidPackage:
m_infoLabel->setType(InfoLabel::Ok);
break;
case ValidPackageMismatchedVersion:
case Status::ValidPackageMismatchedVersion:
m_infoLabel->setType(InfoLabel::Warning);
break;
default:
@@ -261,7 +259,7 @@ QString McuPackage::statusText() const
QString response;
switch (m_status) {
case ValidPackage:
case Status::ValidPackage:
response = m_detectionPath.isEmpty()
? (m_detectedVersion.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath)
@@ -270,23 +268,22 @@ QString McuPackage::statusText() const
: tr("Path %1 is valid, %2 was found.")
.arg(displayPackagePath, displayDetectedPath);
break;
case 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);
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 ValidPathInvalidPackage:
case Status::ValidPathInvalidPackage:
response = tr("Path %1 exists, but does not contain %2.")
.arg(displayPackagePath, displayRequiredPath);
break;
case InvalidPath:
case Status::InvalidPath:
response = tr("Path %1 does not exist.").arg(displayPackagePath);
break;
case EmptyPath:
case Status::EmptyPath:
response = m_detectionPath.isEmpty()
? tr("Path is empty.")
: tr("Path is empty, %1 not found.").arg(displayRequiredPath);
@@ -316,5 +313,4 @@ bool McuToolChainPackage::isDesktopToolchain() const
return m_type == Type::MSVC || m_type == Type::GCC;
}
} // namespace Internal
} // namespace McuSupport
} // namespace McuSupport::Internal

View File

@@ -25,6 +25,7 @@
#pragma once
#include "mcuabstractpackage.h"
#include "mcusupportversiondetection.h"
#include <utils/filepath.h>
@@ -46,19 +47,11 @@ class InfoLabel;
namespace McuSupport {
namespace Internal {
class McuPackage : public QObject
class McuPackage : public McuAbstractPackage
{
Q_OBJECT
public:
enum Status {
EmptyPath,
InvalidPath,
ValidPathInvalidPackage,
ValidPackageMismatchedVersion,
ValidPackage
};
McuPackage(const QString &label,
const Utils::FilePath &defaultPath,
const QString &detectionPath,
@@ -66,31 +59,32 @@ public:
const QString &envVarName = {},
const QString &downloadUrl = {},
const McuPackageVersionDetector *versionDetector = nullptr);
virtual ~McuPackage() = default;
~McuPackage() override = default;
Utils::FilePath basePath() const;
Utils::FilePath path() const;
QString label() const;
Utils::FilePath defaultPath() const;
QString detectionPath() const;
QString statusText() const;
void updateStatus();
Utils::FilePath basePath() const override;
Utils::FilePath path() const override;
QString label() const override;
Utils::FilePath defaultPath() const override;
QString detectionPath() const override;
QString statusText() const override;
void updateStatus() override;
Status status() const;
bool validStatus() const;
void setAddToPath(bool addToPath);
bool addToPath() const;
void writeGeneralSettings() const;
bool writeToSettings() const;
void setRelativePathModifier(const QString &path);
void setVersions(const QStringList &versions);
Status status() const override;
bool validStatus() const override;
void setAddToPath(bool addToPath) override;
bool addToPath() const override;
void writeGeneralSettings() const override;
bool writeToSettings() const override;
void setRelativePathModifier(const QString &path) override;
void setVersions(const QStringList &versions) override;
bool automaticKitCreationEnabled() const;
void setAutomaticKitCreationEnabled(const bool enabled);
//TODO(piotr.mucko): Why every package knows about automatic kit creation. This should be outside of this class.
bool automaticKitCreationEnabled() const override;
void setAutomaticKitCreationEnabled(const bool enabled) override;
QWidget *widget();
QWidget *widget() override;
const QString &environmentVariableName() const;
const QString &environmentVariableName() const override;
signals:
void changed();
@@ -119,7 +113,7 @@ private:
bool m_addToPath = false;
bool m_automaticKitCreation = true;
Status m_status = InvalidPath;
Status m_status = Status::InvalidPath;
};
class McuToolChainPackage : public McuPackage

View File

@@ -15,6 +15,7 @@ QtcPlugin {
Depends { name: "QtSupport" }
files: [
"mcuabstractpackage.h",
"mcupackage.cpp",
"mcupackage.h",
"mcusupport.qrc",
@@ -36,6 +37,7 @@ QtcPlugin {
"mcusupportversiondetection.h",
"mcusupportcmakemapper.h",
"mcusupportcmakemapper.cpp",
"mcutargetdescription.h",
"mcukitinformation.cpp",
"mcukitinformation.h"
]

View File

@@ -66,6 +66,8 @@
#include <QVBoxLayout>
#include <QVariant>
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using namespace ProjectExplorer;
using namespace Utils;
@@ -81,22 +83,6 @@ static bool kitNeedsQtVersion()
return !HostOsInfo::isWindowsHost();
}
static void remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
{
using namespace CMakeProjectManager;
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
// First filter out all Qul2.x CMake vars
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
[&](const auto &configItem) {
return !cmakeVarNames.contains(configItem.key);
});
// Then append them with new values
config.append(cmakeVars);
CMakeConfigurationKitAspect::setConfiguration(kit, config);
}
static ToolChain *msvcToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
@@ -275,7 +261,7 @@ QVariant McuToolChainPackage::debuggerId() const
McuTarget::McuTarget(const QVersionNumber &qulVersion,
const Platform &platform,
OS os,
const QVector<McuPackage *> &packages,
const QVector<McuAbstractPackage *> &packages,
const McuToolChainPackage *toolChainPackage,
int colorDepth)
: m_qulVersion(qulVersion)
@@ -286,7 +272,7 @@ McuTarget::McuTarget(const QVersionNumber &qulVersion,
, m_colorDepth(colorDepth)
{}
const QVector<McuPackage *> &McuTarget::packages() const
const QVector<McuAbstractPackage *> &McuTarget::packages() const
{
return m_packages;
}
@@ -308,7 +294,7 @@ const McuTarget::Platform &McuTarget::platform() const
bool McuTarget::isValid() const
{
return Utils::allOf(packages(), [](McuPackage *package) {
return Utils::allOf(packages(), [](McuAbstractPackage *package) {
package->updateStatus();
return package->validStatus();
});
@@ -318,18 +304,20 @@ void McuTarget::printPackageProblems() const
{
for (auto package : packages()) {
package->updateStatus();
if (!package->validStatus())
if (!package->validStatus()) {
printMessage(tr("Error creating kit for target %1, package %2: %3")
.arg(McuSupportOptions::kitName(this),
package->label(),
package->statusText()),
true);
if (package->status() == McuPackage::ValidPackageMismatchedVersion)
}
if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) {
printMessage(tr("Warning creating kit for target %1, package %2: %3")
.arg(McuSupportOptions::kitName(this),
package->label(),
package->statusText()),
false);
}
}
}
@@ -356,7 +344,7 @@ McuSupportOptions::McuSupportOptions(QObject *parent)
, qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
{
connect(qtForMCUsSdkPackage,
&McuPackage::changed,
&McuAbstractPackage::changed,
this,
&McuSupportOptions::populatePackagesAndTargets);
}
@@ -425,7 +413,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir)
if (qtForMCUsSdkPackage->validStatus())
Sdk::targetsAndPackages(dir, &sdkRepository);
for (const auto &package : qAsConst(sdkRepository.packages))
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::changed);
emit changed();
}
@@ -469,6 +457,22 @@ static void setKitProperties(const QString &kitName,
k->setIrrelevantAspects(irrelevant);
}
void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
{
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
// First filter out all Qul2.x CMake vars
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
[&](const auto &configItem) {
return !cmakeVarNames.contains(configItem.key);
});
// Then append them with new values
config.append(cmakeVars);
CMakeConfigurationKitAspect::setConfiguration(kit, config);
}
static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
{
switch (tcPackage->type()) {
@@ -541,9 +545,9 @@ static bool expectsCmakeVars(const McuTarget *mcuTarget)
return mcuTarget->qulVersion() >= QVersionNumber{2, 0};
}
static void setKitEnvironment(Kit *k,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
void McuSupportOptions::setKitEnvironment(Kit *k,
const McuTarget *mcuTarget,
const McuAbstractPackage *qtForMCUsSdkPackage)
{
EnvironmentItems changes;
QStringList pathAdditions;
@@ -555,7 +559,7 @@ static void setKitEnvironment(Kit *k,
&& !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi())
pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput());
auto processPackage = [&pathAdditions, &changes](const McuPackage *package) {
auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) {
if (package->addToPath())
pathAdditions.append(package->path().toUserOutput());
if (!package->environmentVariableName().isEmpty())
@@ -578,7 +582,7 @@ static void setKitEnvironment(Kit *k,
// Hack, this problem should be solved in lower layer
if (expectsCmakeVars(mcuTarget)) {
remapQul2xCmakeVars(k, changes);
McuSupportOptions::remapQul2xCmakeVars(k, changes);
}
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
@@ -586,11 +590,11 @@ static void setKitEnvironment(Kit *k,
static void setKitDependencies(Kit *k,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
NameValueItems dependencies;
auto processPackage = [&dependencies](const McuPackage *package) {
auto processPackage = [&dependencies](const McuAbstractPackage *package) {
if (!package->environmentVariableName().isEmpty())
dependencies.append({package->environmentVariableName(),
QDir::toNativeSeparators(package->detectionPath())});
@@ -606,7 +610,7 @@ static void setKitDependencies(Kit *k,
k->setIrrelevantAspects(irrelevant);
}
static void updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
{
EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k);
for (auto package : mcuTarget->packages()) {
@@ -741,7 +745,7 @@ QList<Kit *> McuSupportOptions::existingKits(const McuTarget *mcuTarget)
}
QList<Kit *> McuSupportOptions::matchingKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
@@ -749,7 +753,7 @@ QList<Kit *> McuSupportOptions::matchingKits(const McuTarget *mcuTarget,
}
QList<Kit *> McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return !kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
@@ -761,10 +765,9 @@ QList<Kit *> McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget *
return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) {
const auto environment = Utils::NameValueDictionary(
Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit)));
return Utils::anyOf(mcuTarget->packages(), [&environment](const McuPackage *package) {
return !package->environmentVariableName().isEmpty()
&& environment.value(package->environmentVariableName())
!= package->path().toUserOutput();
return Utils::anyOf(mcuTarget->packages(), [&environment](const McuAbstractPackage *package) {
return !package->environmentVariableName().isEmpty() &&
environment.value(package->environmentVariableName()) != package->path().toUserOutput();
});
});
}
@@ -783,7 +786,7 @@ void McuSupportOptions::removeOutdatedKits()
KitManager::deregisterKit(kit);
}
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk)
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk)
{
const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) {
KitGuard kitGuard(k);
@@ -831,7 +834,7 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName)
bool McuSupportOptions::kitUpToDate(const Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
return kitQulVersion(kit) == mcuTarget->qulVersion()
&& kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput()
@@ -873,22 +876,22 @@ void McuSupportOptions::createAutomaticKits()
qtForMCUsPackage->updateStatus();
if (!qtForMCUsPackage->validStatus()) {
switch (qtForMCUsPackage->status()) {
case McuPackage::ValidPathInvalidPackage: {
const QString displayPath
= FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput();
case McuAbstractPackage::Status::ValidPathInvalidPackage: {
const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath())
.toUserOutput();
printMessage(tr("Path %1 exists, but does not contain %2.")
.arg(qtForMCUsPackage->path().toUserOutput(), displayPath),
true);
break;
}
case McuPackage::InvalidPath: {
case McuAbstractPackage::Status::InvalidPath: {
printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > "
"Devices > MCU.")
.arg(qtForMCUsPackage->path().toUserOutput()),
true);
break;
}
case McuPackage::EmptyPath: {
case McuAbstractPackage::Status::EmptyPath: {
printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.")
.arg(qtForMCUsPackage->detectionPath()),
true);
@@ -984,7 +987,7 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption)
void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdk)
const McuAbstractPackage *qtForMCUsSdk)
{
setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path());
setKitEnvironment(kit, mcuTarget, qtForMCUsSdk);
@@ -1000,7 +1003,7 @@ void McuSupportOptions::fixKitsDependencies()
Sdk::targetsAndPackages(dir, &repo);
for (const auto &target : qAsConst(repo.mcuTargets)) {
if (target->isValid()) {
for (auto kit : kitsWithMismatchedDependencies(target)) {
for (auto* kit : kitsWithMismatchedDependencies(target)) {
updateKitEnvironment(kit, target);
}
}

View File

@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2021
** The Qt Company Ltd.
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -26,8 +25,7 @@
#pragma once
#include "mcusupport_global.h"
#include <utils/environmentfwd.h>
#include <QObject>
#include <QVector>
#include <QVersionNumber>
@@ -48,7 +46,7 @@ class ToolChain;
namespace McuSupport {
namespace Internal {
class McuPackage;
class McuAbstractPackage;
class McuToolChainPackage;
void printMessage(const QString &message, bool important);
@@ -72,12 +70,12 @@ public:
McuTarget(const QVersionNumber &qulVersion,
const Platform &platform,
OS os,
const QVector<McuPackage *> &packages,
const QVector<McuAbstractPackage *> &packages,
const McuToolChainPackage *toolChainPackage,
int colorDepth = UnspecifiedColorDepth);
const QVersionNumber &qulVersion() const;
const QVector<McuPackage *> &packages() const;
const QVector<McuAbstractPackage *> &packages() const;
const McuToolChainPackage *toolChainPackage() const;
const Platform &platform() const;
OS os() const;
@@ -89,15 +87,15 @@ private:
const QVersionNumber m_qulVersion;
const Platform m_platform;
const OS m_os;
const QVector<McuPackage *> m_packages;
const QVector<McuAbstractPackage *> m_packages;
const McuToolChainPackage *m_toolChainPackage;
const int m_colorDepth;
};
}; // class McuTarget
class McuSdkRepository
{
public:
QVector<McuPackage *> packages;
QVector<McuAbstractPackage *> packages;
QVector<McuTarget *> mcuTargets;
void deletePackagesAndTargets();
@@ -110,32 +108,34 @@ class McuSupportOptions : public QObject
public:
enum UpgradeOption { Ignore, Keep, Replace };
McuSupportOptions(QObject *parent = nullptr);
explicit McuSupportOptions(QObject *parent = nullptr);
~McuSupportOptions() override;
McuPackage *qtForMCUsSdkPackage = nullptr;
McuAbstractPackage *qtForMCUsSdkPackage = nullptr;
McuSdkRepository sdkRepository;
void setQulDir(const Utils::FilePath &dir);
static void setKitEnvironment(ProjectExplorer::Kit *, const McuTarget *, const McuAbstractPackage *);
static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *);
static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &);
static Utils::FilePath qulDirFromSettings();
static QString kitName(const McuTarget *mcuTarget);
static QList<ProjectExplorer::Kit *> existingKits(const McuTarget *mcuTarget);
static QList<ProjectExplorer::Kit *> matchingKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage);
static QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage);
const McuAbstractPackage *qtForMCUsSdkPackage);
static QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage);
static QList<ProjectExplorer::Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget);
static QList<ProjectExplorer::Kit *> outdatedKits();
static void removeOutdatedKits();
static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk);
static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk);
static void createAutomaticKits();
static UpgradeOption askForKitUpgrades();
static void upgradeKits(UpgradeOption upgradeOption);
static void upgradeKitInPlace(ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdk);
const McuAbstractPackage *qtForMCUsSdk);
static void fixKitsDependencies();
void checkUpgradeableKits();
static void fixExistingKits();
@@ -148,7 +148,7 @@ public:
static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit);
static bool kitUpToDate(const ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage);
const McuAbstractPackage *qtForMCUsSdkPackage);
private:
void deletePackagesAndTargets();

View File

@@ -121,10 +121,8 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
&QComboBox::currentTextChanged,
this,
&McuSupportOptionsWidget::showMcuTargetPackages);
connect(m_options.qtForMCUsSdkPackage,
&McuPackage::changed,
this,
&McuSupportOptionsWidget::populateMcuTargetsComboBox);
connect(m_options.qtForMCUsSdkPackage, &McuAbstractPackage::changed,
this, &McuSupportOptionsWidget::populateMcuTargetsComboBox);
}
{

View File

@@ -31,6 +31,10 @@
#include "mcusupportoptionspage.h"
#include "mcusupportrunconfiguration.h"
#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND)
#include "test/unittest.h"
#endif
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
@@ -59,14 +63,9 @@ public:
{Constants::RUNCONFIGURATION}};
McuSupportOptionsPage optionsPage;
McuDependenciesKitAspect environmentPathsKitAspect;
};
}; // class McuSupportPluginPrivate
static McuSupportPluginPrivate *dd = nullptr;
McuSupportPlugin::McuSupportPlugin()
{
setObjectName("McuSupportPlugin");
}
static McuSupportPluginPrivate* dd{nullptr};
McuSupportPlugin::~McuSupportPlugin()
{
@@ -79,6 +78,7 @@ bool McuSupportPlugin::initialize(const QStringList &arguments, QString *errorSt
Q_UNUSED(arguments)
Q_UNUSED(errorString)
setObjectName("McuSupportPlugin");
dd = new McuSupportPluginPrivate;
McuSupportOptions::registerQchFiles();
@@ -147,5 +147,14 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade()
ICore::infoBar()->addInfo(info);
}
QVector<QObject *> McuSupportPlugin::createTestObjects() const
{
QVector<QObject *> tests;
#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND)
tests << new Test::McuSupportTest;
#endif
return tests;
}
} // namespace Internal
} // namespace McuSupport

View File

@@ -29,23 +29,25 @@
#include <extensionsystem/iplugin.h>
namespace McuSupport {
namespace Internal {
namespace McuSupport::Internal {
class McuSupportPlugin : public ExtensionSystem::IPlugin
class McuSupportPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "McuSupport.json")
public:
McuSupportPlugin();
~McuSupportPlugin() override;
~McuSupportPlugin() final;
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final;
bool initialize(const QStringList &arguments, QString *errorString) override;
void extensionsInitialized() override;
static void askUserAboutMcuSupportKitsSetup();
static void askUserAboutMcuSupportKitsUpgrade();
};
} // namespace Internal
} // namespace McuSupport
private:
QVector<QObject *> createTestObjects() const final;
}; // class McuSupportPlugin
} // namespace McuSupport::Internal

View File

@@ -28,6 +28,7 @@
#include "mcusupportconstants.h"
#include "mcusupportoptions.h"
#include "mcusupportversiondetection.h"
#include "mcutargetdescription.h"
#include <baremetal/baremetalconstants.h>
#include <coreplugin/icore.h>
@@ -330,40 +331,6 @@ static McuPackage *createRenesasProgrammerPackage()
envVar);
return result;
}
struct McuTargetDescription
{
enum class TargetType { MCU, Desktop };
QString qulVersion;
QString compatVersion;
struct
{
QString id;
QString name;
QString vendor;
QVector<int> colorDepths;
TargetType type;
} platform;
struct
{
QString id;
QStringList versions;
} toolchain;
struct
{
QString name;
QString defaultPath;
QString envVar;
QStringList versions;
} boardSdk;
struct
{
QString envVar;
QString boardSdkSubDir;
} freeRTOS;
};
static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar)
{
if (envVar.startsWith("EVK"))
@@ -463,9 +430,9 @@ struct McuTargetFactory
return createTargetsImpl(description);
}
QVector<McuPackage *> getMcuPackages() const
QVector<McuAbstractPackage *> getMcuPackages() const
{
QVector<McuPackage *> packages;
QVector<McuAbstractPackage *> packages;
for (auto *package : qAsConst(boardSdkPkgs))
packages.append(package);
for (auto *package : qAsConst(freeRTOSPkgs))
@@ -483,7 +450,7 @@ protected:
tcPkg = createUnsupportedToolChainPackage();
for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
for (int colorDepth : desc.platform.colorDepths) {
QVector<McuPackage *> required3rdPartyPkgs = {tcPkg};
QVector<McuAbstractPackage *> required3rdPartyPkgs = {tcPkg};
if (vendorPkgs.contains(desc.platform.vendor))
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
@@ -566,7 +533,7 @@ protected:
} else
tcPkg = createUnsupportedToolChainPackage();
for (int colorDepth : desc.platform.colorDepths) {
QVector<McuPackage *> required3rdPartyPkgs;
QVector<McuAbstractPackage *> required3rdPartyPkgs;
// Desktop toolchains don't need any additional settings
if (tcPkg && !tcPkg->isDesktopToolchain()
&& tcPkg->type() != McuToolChainPackage::Type::Unsupported)
@@ -620,10 +587,10 @@ private:
QHash<QString, McuPackage *> boardSdkPkgs;
QHash<QString, McuPackage *> freeRTOSPkgs;
};
}; // struct McuTargetFactory
static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
QVector<McuPackage *> *packages)
QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
QVector<McuAbstractPackage *> *packages)
{
const QHash<QString, McuToolChainPackage *> tcPkgs = {
{{"armgcc"}, createArmGccPackage()},
@@ -652,8 +619,10 @@ static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescrip
}
packages->append(
Utils::transform<QVector<McuPackage *>>(tcPkgs.values(),
[&](McuToolChainPackage *tcPkg) { return tcPkg; }));
Utils::transform<QVector<McuAbstractPackage *>>(tcPkgs.values(),
[&](McuToolChainPackage *tcPkg) {
return tcPkg;
}));
for (auto *package : vendorPkgs)
packages->append(package);
packages->append(targetFactory.getMcuPackages());
@@ -755,7 +724,7 @@ static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion,
return description;
}
static McuTargetDescription parseDescriptionJson(const QByteArray &data)
McuTargetDescription parseDescriptionJson(const QByteArray &data)
{
const QJsonDocument document = QJsonDocument::fromJson(data);
const QJsonObject target = document.object();

View File

@@ -33,18 +33,26 @@
namespace McuSupport {
namespace Internal {
#define MAX_COMPATIBILITY_VERSION 1
constexpr int MAX_COMPATIBILITY_VERSION {1};
class McuSdkRepository;
class McuAbstractPackage;
class McuPackage;
class McuTarget;
namespace Sdk {
struct McuTargetDescription;
McuPackage *createQtForMCUsPackage();
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo);
McuTargetDescription parseDescriptionJson(const QByteArray &);
QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &, QVector<McuAbstractPackage *> *);
Utils::FilePath kitsPath(const Utils::FilePath &dir);
Utils::FilePath packagePathFromSettings(const QString &settingsKey,

View File

@@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QString>
#include <QStringList>
#include <QVector>
namespace McuSupport::Internal::Sdk {
struct McuTargetDescription
{
enum class TargetType { MCU, Desktop };
QString qulVersion;
QString compatVersion;
struct
{
QString id;
QString name;
QString vendor;
QVector<int> colorDepths;
TargetType type;
} platform;
struct
{
QString id;
QStringList versions;
} toolchain;
struct
{
QString name;
QString defaultPath;
QString envVar;
QStringList versions;
} boardSdk;
struct
{
QString envVar;
QString boardSdkSubDir;
} freeRTOS;
};
} // namespace McuSupport::Internal::Sdk

View File

@@ -0,0 +1,13 @@
find_package(Googletest MODULE)
if(TARGET Googletest)
message("Googletest target is present")
extend_qtc_plugin(McuSupport
CONDITION WITH_TESTS
DEPENDS Googletest
SOURCES
unittest.h unittest.cpp packagemock.h
)
else()
message("Googletest target is missing")
endif()

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
constexpr auto nxp_1064_json = R"({
"boardSdk": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "QUL_BOARD_SDK_DIR",
"description": "Board SDK for MIMXRT1064-EVK",
"id": "NXP_SDK_DIR",
"optional": false,
"type": "path"
}
],
"envVar": "EVK_MIMXRT1064_SDK_PATH",
"versions": ["2.10.0"]
},
"compatVersion": "1",
"freeRTOS": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "FREERTOS_DIR",
"defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel",
"description": "FreeRTOS SDK for MIMXRT1064-EVK",
"id": "NXP_FREERTOS_DIR",
"optional": false,
"type": "path"
}
],
"envVar": "IMXRT1064_FREERTOS_DIR"
},
"platform": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "Qul_ROOT",
"description": "Qt for MCUs SDK",
"id": "Qul_DIR",
"optional": false,
"type": "path"
},
{
"cmakeOptionName": "MCUXPRESSO_IDE_PATH",
"defaultValue": {
"unix": "/usr/local/mcuxpressoide/",
"windows": "$ROOT/nxp/MCUXpressoIDE*"
}
}
],
"colorDepths": [16],
"environmentEntries": [],
"id": "MIMXRT1064-EVK-FREERTOS",
"pathEntries": [],
"vendor": "NXP"
},
"qulVersion": "2.0.0",
"toolchain": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "QUL_TARGET_TOOLCHAIN_DIR",
"description": "IAR ARM Compiler",
"id": "IAR_DIR",
"optional": false,
"type": "path"
}
],
"id": "iar",
"versions": ["8.50.9"]
}
})";

View File

@@ -0,0 +1,63 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "mcuabstractpackage.h"
#include <utils/filepath.h>
#include <gmock/gmock.h>
namespace McuSupport::Internal {
class PackageMock : public McuAbstractPackage
{
public:
MOCK_METHOD(Utils::FilePath, basePath, (), (const));
MOCK_METHOD(Utils::FilePath, path, (), (const));
MOCK_METHOD(QString, label, (), (const));
MOCK_METHOD(Utils::FilePath, defaultPath, (), (const));
MOCK_METHOD(QString, detectionPath, (), (const));
MOCK_METHOD(QString, statusText, (), (const));
MOCK_METHOD(void, updateStatus, ());
MOCK_METHOD(Status, status, (), (const));
MOCK_METHOD(bool, validStatus, (), (const));
MOCK_METHOD(void, setDownloadUrl, (const QString &) );
MOCK_METHOD(void, setEnvironmentVariableName, (const QString &) );
MOCK_METHOD(const QString&, environmentVariableName, (), (const));
MOCK_METHOD(void, setAddToPath, (bool) );
MOCK_METHOD(bool, addToPath, (), (const));
MOCK_METHOD(void, writeGeneralSettings, (), (const));
MOCK_METHOD(bool, writeToSettings, (), (const));
MOCK_METHOD(void, setRelativePathModifier, (const QString &) );
MOCK_METHOD(void, setVersions, (const QStringList &) );
MOCK_METHOD(bool, automaticKitCreationEnabled, (), (const));
MOCK_METHOD(void, setAutomaticKitCreationEnabled, (const bool enabled));
MOCK_METHOD(QWidget *, widget, ());
}; // class PackageMock
} // namespace McuSupport::Internal

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "mcutargetdescription.h"
#include "nxp_1064_json.h"
#include "unittest.h"
#include "utils/filepath.h"
#include <cmakeprojectmanager/cmakeconfigitem.h>
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <gmock/gmock.h>
#include <QJsonArray>
#include <QJsonDocument>
namespace McuSupport::Internal::Test {
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using ProjectExplorer::EnvironmentKitAspect;
using ProjectExplorer::KitManager;
using testing::Return;
using testing::ReturnRef;
using Utils::FilePath;
void McuSupportTest::initTestCase()
{
EXPECT_CALL(freeRtosPackage, environmentVariableName()).WillRepeatedly(ReturnRef(freeRtosEnvVar));
EXPECT_CALL(freeRtosPackage, validStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(freeRtosPackage, path())
.WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath)));
}
void McuSupportTest::test_parseBasicInfoFromJson()
{
const auto description = Sdk::parseDescriptionJson(nxp_1064_json);
QVERIFY(not description.freeRTOS.envVar.isEmpty());
QVERIFY(description.freeRTOS.boardSdkSubDir.isEmpty());
}
void McuSupportTest::test_addNewKit()
{
auto &kitManager{*KitManager::instance()};
QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded);
auto *newKit{McuSupportOptions::newKit(&mcuTarget, &freeRtosPackage)};
QVERIFY(newKit != nullptr);
QCOMPARE(kitAddedSpy.count(), 1);
QList<QVariant> arguments = kitAddedSpy.takeFirst();
auto *createdKit = qvariant_cast<Kit *>(arguments.at(0));
QVERIFY(createdKit != nullptr);
QCOMPARE(createdKit, newKit);
auto cmakeAspect{CMakeConfigurationKitAspect{}};
QVERIFY(createdKit->hasValue(cmakeAspect.id()));
QVERIFY(createdKit->value(cmakeAspect.id(), freeRtosCmakeVar).isValid());
}
void McuSupportTest::test_addFreeRtosCmakeVarToKit()
{
McuSupportOptions::updateKitEnvironment(&kit, &mcuTarget);
QVERIFY(kit.hasValue(EnvironmentKitAspect::id()));
QVERIFY(kit.isValid());
QVERIFY(not kit.allKeys().empty());
const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)};
QCOMPARE(cmakeConfig.size(), 1);
CMakeConfigItem expectedCmakeVar{freeRtosCmakeVar.toLocal8Bit(),
defaultfreeRtosPath.toLocal8Bit()};
QVERIFY(cmakeConfig.contains(expectedCmakeVar));
}
} // namespace McuSupport::Internal::Test

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "mcusupportoptions.h"
#include "mcusupportplugin.h"
#include "mcusupportsdk.h"
#include "mcupackage.h"
#include "packagemock.h"
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <utils/filepath.h>
#include <utils/fileutils.h>
#include <QObject>
#include <QSignalSpy>
#include <QTest>
namespace McuSupport::Internal::Test {
using ProjectExplorer::Kit;
class McuSupportTest : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void test_addFreeRtosCmakeVarToKit();
void test_addNewKit();
void test_parseBasicInfoFromJson();
private:
QVersionNumber currentQulVersion{2, 0};
const QString id{"target_id"};
const QString name{"target_name"};
const QString vendor{"target_vendor"};
const QString freeRtosEnvVar{"EVK_MIMXRT1170_FREERTOS_PATH"};
const QString freeRtosCmakeVar{"FREERTOS_DIR"};
const QString defaultfreeRtosPath{"/opt/freertos/default"};
PackageMock freeRtosPackage;
Kit kit;
McuToolChainPackage toolchainPackage{{}, {}, {}, {}, {}};
const McuTarget::Platform platform{id, name, vendor};
McuTarget mcuTarget{currentQulVersion,
platform,
McuTarget::OS::FreeRTOS,
{&freeRtosPackage},
&toolchainPackage};
}; // class McuSupportTest
} // namespace McuSupport::Internal::Test

View File

@@ -1110,6 +1110,10 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
<< ("*-*-*-*-" + compilerName
+ "-[1-9]*"); // "x86_64-pc-linux-gnu-gcc-7.4.1"
}
nameFilters = transform(nameFilters,
[os = device ? device->osType() : HostOsInfo::hostOs()](const QString &baseName) {
return OsSpecificAspects::withExecutableSuffix(os, baseName);
});
FilePaths compilerPaths;
@@ -1145,9 +1149,6 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
for (const FilePath &dir : qAsConst(searchPaths)) {
static const QRegularExpression regexp(binaryRegexp);
QDir binDir(dir.toString());
nameFilters = transform(nameFilters, [](const QString &baseName) {
return HostOsInfo::withExecutableSuffix(baseName);
});
const QStringList fileNames = binDir.entryList(nameFilters,
QDir::Files | QDir::Executable);
for (const QString &fileName : fileNames) {

View File

@@ -166,8 +166,8 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
QPair<FilePath, int> position = parseFileName(match.captured(1));
const FilePath filePath = absoluteFilePath(position.first);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
if (!m_lastTask.isNull() && line.contains("note: ")) {
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
const int offset = std::accumulate(m_lastTask.details.cbegin(),
m_lastTask.details.cend(), 0,
[](int total, const QString &line) { return total + line.length() + 1;});
@@ -181,6 +181,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
m_lastTask = CompileTask(taskType(match.captured(2)),
match.captured(3) + match.captured(4).trimmed(), // description
filePath, position.second);
m_linkSpecs << linkSpecs;
m_lines = 1;
}
return {Status::InProgress, linkSpecs};

View File

@@ -314,6 +314,16 @@ static const RunConfiguration *runConfigForNode(const Target *target, const Proj
return target->activeRunConfiguration();
}
static bool hideBuildMenu()
{
return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_BUILD, false).toBool();
}
static bool hideDebugMenu()
{
return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_DEBUG, false).toBool();
}
static bool canOpenTerminalWithRunEnv(const Project *project, const ProjectNode *node)
{
if (!project)
@@ -938,14 +948,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// build menu
ActionContainer *mbuild =
ActionManager::createMenu(Constants::M_BUILDPROJECT);
mbuild->menu()->setTitle(tr("&Build"));
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
if (!hideBuildMenu())
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
// debug menu
ActionContainer *mdebug =
ActionManager::createMenu(Constants::M_DEBUG);
mdebug->menu()->setTitle(tr("&Debug"));
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
if (!hideDebugMenu())
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
ActionContainer *mstartdebugging =
ActionManager::createMenu(Constants::M_DEBUG_STARTDEBUGGING);

View File

@@ -235,6 +235,9 @@ const char ADD_FILES_DIALOG_FILTER_HISTORY_KEY[] = "ProjectExplorer.AddFilesFilt
const char PROJECT_ROOT_PATH_KEY[] = "ProjectExplorer.Project.RootPath";
const char STARTUPSESSION_KEY[] = "ProjectExplorer/SessionToRestore";
const char LASTSESSION_KEY[] = "ProjectExplorer/StartupSession";
const char SETTINGS_MENU_HIDE_BUILD[] = "Menu/HideBuild";
const char SETTINGS_MENU_HIDE_DEBUG[] = "Menu/HideDebug";
const char SETTINGS_MENU_HIDE_ANALYZE[] = "Menu/HideAnalyze";
// UI texts
PROJECTEXPLORER_EXPORT QString msgAutoDetected();

View File

@@ -144,6 +144,9 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
return true;
dir.cdUp();
saveExpandedState(loadExpandedState(folderPath), dir.absoluteFilePath(newName));
return dir.rename(oldName, newName);
}
@@ -341,8 +344,14 @@ void AssetsLibraryModel::setRootPath(const QString &path)
beginResetModel();
m_assetsDir = new AssetsLibraryDir(path, 0, true, this);
bool noAssets = parseDirRecursive(m_assetsDir, 1);
setIsEmpty(noAssets);
bool isEmpty = parseDirRecursive(m_assetsDir, 1);
setIsEmpty(isEmpty);
bool noAssets = m_searchText.isEmpty() && isEmpty;
// noAssets: the model has no asset files (project has no assets added)
// isEmpty: the model has no asset files (assets could exist but are filtered out)
m_assetsDir->setDirVisible(!noAssets); // if there are no assets, hide all empty asset folders
endResetModel();
}

View File

@@ -59,6 +59,8 @@ public:
void setRootPath(const QString &path);
void setSearchText(const QString &searchText);
bool isEmpty() const;
static const QStringList &supportedImageSuffixes();
static const QStringList &supportedFragmentShaderSuffixes();
static const QStringList &supportedShaderSuffixes();
@@ -93,7 +95,6 @@ signals:
private:
const QSet<QString> &supportedSuffixes() const;
bool isEmpty() const;
void setIsEmpty(bool empty);
SynchronousImageCache &m_fontImageCache;

View File

@@ -201,10 +201,11 @@ QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
void AssetsLibraryWidget::handleSearchfilterChanged(const QString &filterText)
{
if (filterText != m_filterText) {
m_filterText = filterText;
updateSearch();
}
if (filterText == m_filterText || (m_assetsModel->isEmpty() && filterText.contains(m_filterText)))
return;
m_filterText = filterText;
updateSearch();
}
void AssetsLibraryWidget::handleAddAsset()

View File

@@ -389,7 +389,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd)
if (braceIdx != -1) {
int nlIdx = content.lastIndexOf('\n', braceIdx);
QByteArray rootItem = content.mid(nlIdx, braceIdx - nlIdx).trimmed();
if (rootItem == "Node") { // a 3D object
if (rootItem == "Node" || rootItem == "Model") { // a 3D object
// create hints file with proper hints
QFile file(outDir.path() + '/' + fi.baseName() + ".hints");
file.open(QIODevice::WriteOnly | QIODevice::Text);

View File

@@ -68,6 +68,11 @@ QString ItemLibraryItem::requiredImport() const
return m_itemLibraryEntry.requiredImport();
}
QString ItemLibraryItem::componentSource() const
{
return m_itemLibraryEntry.customComponentSource();
}
bool ItemLibraryItem::setVisible(bool isVisible)
{
if (isVisible != m_isVisible) {

View File

@@ -45,6 +45,7 @@ class ItemLibraryItem: public QObject
Q_PROPERTY(QString componentPath READ componentPath FINAL)
Q_PROPERTY(bool itemUsable READ isUsable FINAL)
Q_PROPERTY(QString itemRequiredImport READ requiredImport FINAL)
Q_PROPERTY(QString itemComponentSource READ componentSource FINAL)
public:
ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isImported, QObject *parent);
@@ -55,6 +56,7 @@ public:
QString itemLibraryIconPath() const;
QString componentPath() const;
QString requiredImport() const;
QString componentSource() const;
bool setVisible(bool isVisible);
bool isVisible() const;

View File

@@ -32,6 +32,7 @@
#include <designeractionmanager.h>
#include <designermcumanager.h>
#include <documentmanager.h>
#include <itemlibraryimageprovider.h>
#include <itemlibraryinfo.h>
#include <itemlibrarymodel.h>
@@ -269,6 +270,11 @@ void ItemLibraryWidget::handleAddImport(int index)
updateSearch();
}
void ItemLibraryWidget::goIntoComponent(const QString &source)
{
DocumentManager::goIntoComponent(source);
}
void ItemLibraryWidget::delayedUpdateModel()
{
static bool disableTimer = DesignerSettings::getValue(DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER).toBool();

View File

@@ -95,6 +95,7 @@ public:
Q_INVOKABLE void addImportForItem(const QString &importUrl);
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
Q_INVOKABLE void handleAddImport(int index);
Q_INVOKABLE void goIntoComponent(const QString &source);
signals:
void itemActivated(const QString &itemName);

View File

@@ -34,35 +34,64 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
const NodeMetaInfo &parentInfo,
bool breakOnFirst)
{
TypeName typeName = insertInfo.typeName();
TypeName superClass = insertInfo.directSuperClass().typeName();
TypeName nodePackage = insertInfo.typeName().replace(insertInfo.simplifiedTypeName(), "");
TypeName targetPackage = parentInfo.typeName().replace(parentInfo.simplifiedTypeName(), "");
if (!nodePackage.contains(targetPackage))
return;
// TODO: Metainfo based matching system (QDS-6240)
// Common base types cause too many rarely valid matches, so they are ignored
const QSet<TypeName> ignoredTypes {"<cpp>.QObject",
"<cpp>.QQuickItem",
"<cpp>.QQuick3DObject",
"QtQuick.Item",
"QtQuick3D.Object3D",
"QtQuick3D.Node",
"QtQuick3D.Particles3D.ParticleSystem3D"};
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
for (const PropertyName &name : targetNodeNameList) {
if (!name.contains('.')) {
TypeName propType = parentInfo.propertyTypeName(name).replace("<cpp>.", targetPackage);
// Skip properties that are not sub classes of anything
if (propType.contains('.')
&& !ignoredTypes.contains(propType)
&& (typeName == propType || propType == superClass)
&& parentInfo.propertyIsWritable(propType)) {
propertyList.append(QString::fromLatin1(name));
if (breakOnFirst)
break;
// Fall back to a hardcoded list of supported cases:
// Texture
// -> DefaultMaterial
// -> PrincipledMaterial
// -> SpriteParticle3D
// -> TextureInput
// -> SceneEnvironment
// Effect
// -> SceneEnvironment
// Shader, Command, Buffer
// -> Pass
// InstanceListEntry
// -> InstanceList
// Pass
// -> Effect
const TypeName textureType = "QtQuick3D.Texture";
if (insertInfo.isSubclassOf(textureType)) {
const TypeName textureTypeCpp = "<cpp>.QQuick3DTexture";
if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial")
|| parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
// All texture properties are valid targets
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
for (const PropertyName &name : targetNodeNameList) {
TypeName propType = parentInfo.propertyTypeName(name);
if (propType == textureType || propType == textureTypeCpp) {
propertyList.append(QString::fromLatin1(name));
if (breakOnFirst)
return;
}
}
} else if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
propertyList.append("sprite");
} else if (parentInfo.isSubclassOf("QtQuick3D.TextureInput")) {
propertyList.append("texture");
} else if (parentInfo.isSubclassOf("QtQuick3D.SceneEnvironment")) {
propertyList.append("lightProbe");
}
} else if (insertInfo.isSubclassOf("QtQuick3D.Effect")) {
if (parentInfo.isSubclassOf("QtQuick3D.SceneEnvironment"))
propertyList.append("effects");
} else if (insertInfo.isSubclassOf("QtQuick3D.Shader")) {
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
propertyList.append("shaders");
} else if (insertInfo.isSubclassOf("QtQuick3D.Command")) {
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
propertyList.append("commands");
} else if (insertInfo.isSubclassOf("QtQuick3D.Buffer")) {
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
propertyList.append("output");
} else if (insertInfo.isSubclassOf("QtQuick3D.InstanceListEntry")) {
if (parentInfo.isSubclassOf("QtQuick3D.InstanceList"))
propertyList.append("instances");
} else if (insertInfo.isSubclassOf("QtQuick3D.Pass")) {
if (parentInfo.isSubclassOf("QtQuick3D.Effect"))
propertyList.append("passes");
}
}
@@ -110,14 +139,6 @@ TypeName ChooseFromPropertyListDialog::selectedProperty() const
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
const ModelNode &targetNode, const ModelNode &newNode, QWidget *parent)
{
TypeName typeName = newNode.type();
// Component matches cases where you don't want to insert a plain component,
// such as layer.effect. Also, default property is often a Component (typically 'delegate'),
// and inserting into such property will silently overwrite implicit component, if any.
if (typeName == "QtQml.Component")
return nullptr;
const NodeMetaInfo info = newNode.metaInfo();
const NodeMetaInfo targetInfo = targetNode.metaInfo();
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(info, targetInfo);

View File

@@ -581,21 +581,29 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
addImport(import);
}
bool moveNodesAfter = true;
m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] {
for (const QString &assetPath : assetsPaths) {
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetPath);
QString assetType = assetTypeAndData.first;
QString assetData = QString::fromUtf8(assetTypeAndData.second);
if (assetType == "application/vnd.bauhaus.libraryresource.image")
currNode = handleItemLibraryImageDrop(assetPath, targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.font")
currNode = handleItemLibraryFontDrop(assetData, targetProperty, rowModelIndex); // assetData is fontFamily
else if (assetType == "application/vnd.bauhaus.libraryresource.shader")
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f", targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.sound")
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d")
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty, rowModelIndex);
if (assetType == "application/vnd.bauhaus.libraryresource.image") {
currNode = handleItemLibraryImageDrop(assetPath, targetProperty,
rowModelIndex, moveNodesAfter);
} else if (assetType == "application/vnd.bauhaus.libraryresource.font") {
currNode = handleItemLibraryFontDrop(assetData, // assetData is fontFamily
targetProperty, rowModelIndex);
} else if (assetType == "application/vnd.bauhaus.libraryresource.shader") {
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f",
targetProperty, rowModelIndex,
moveNodesAfter);
} else if (assetType == "application/vnd.bauhaus.libraryresource.sound") {
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty,
rowModelIndex);
} else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d") {
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
rowModelIndex, moveNodesAfter);
}
if (currNode.isValid())
addedNodes.append(currNode);
@@ -603,7 +611,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
});
if (!addedNodes.isEmpty()) {
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
if (moveNodesAfter)
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
m_view->setSelectedModelNodes(addedNodes);
}
}
@@ -682,21 +691,22 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
dialog->exec();
if (soloProperty || dialog->result() == QDialog::Accepted) {
TypeName selectedProp = dialog->selectedProperty();
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
if ((newModelNode.isSubclassOf("QtQuick3D.Shader") || newModelNode.isSubclassOf("QtQuick3D.Command"))
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) {
NodeAbstractProperty parentProp = targetProperty.parentProperty();
if (parentProp.isValid()) {
targetProperty = parentProp;
ModelNode targetModel = targetProperty.parentModelNode();
targetRowNumber = rowCount(indexForModelNode(targetModel));
// Move node to new parent within the same transaction as we don't
// want undo to place the node under invalid parent
moveNodesInteractive(targetProperty, {newQmlObjectNode}, targetRowNumber, false);
moveNodesAfter = false;
}
// Pass and TextureInput can't have children, so we have to move nodes under parent
if (((newModelNode.isSubclassOf("QtQuick3D.Shader")
|| newModelNode.isSubclassOf("QtQuick3D.Command")
|| newModelNode.isSubclassOf("QtQuick3D.Buffer"))
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass"))
|| (newModelNode.isSubclassOf("QtQuick3D.Texture")
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.TextureInput"))) {
if (moveNodeToParent(targetProperty, newQmlObjectNode)) {
targetProperty = targetProperty.parentProperty();
moveNodesAfter = false;
}
}
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
listProp.addModelNodeToArray(newModelNode);
validContainer = true;
} else {
@@ -778,7 +788,8 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{
QTC_ASSERT(m_view, return {});
@@ -788,7 +799,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePat
ModelNode newModelNode;
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode)) {
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode, outMoveNodesAfter)) {
if (targetNode.isSubclassOf("QtQuick.Image") || targetNode.isSubclassOf("QtQuick.BorderImage")) {
// if dropping an image on an existing image, set the source
targetNode.variantProperty("source").setValue(imagePathRelative);
@@ -846,9 +857,23 @@ void NavigatorTreeModel::addImport(const QString &importName)
}
}
bool QmlDesigner::NavigatorTreeModel::moveNodeToParent(const NodeAbstractProperty &targetProperty,
const ModelNode &node)
{
NodeAbstractProperty parentProp = targetProperty.parentProperty();
if (parentProp.isValid()) {
ModelNode targetModel = parentProp.parentModelNode();
int targetRowNumber = rowCount(indexForModelNode(targetModel));
moveNodesInteractive(parentProp, {node}, targetRowNumber, false);
return true;
}
return false;
}
ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{
QTC_ASSERT(m_view, return {});
@@ -863,29 +888,37 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
: "Shader.Vertex");
targetNode.variantProperty("shader").setValue(relPath);
} else {
// create a new Shader
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
// create a new Shader
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
// set shader properties
PropertyName prop = "shader";
QString type = "QByteArray";
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
prop = "stage";
type = "enum";
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
itemLibraryEntry.addProperty(prop, type, val);
// set shader properties
PropertyName prop = "shader";
QString type = "QByteArray";
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
prop = "stage";
type = "enum";
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
itemLibraryEntry.addProperty(prop, type, val);
// create a texture
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
targetProperty, false);
// create a texture
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
targetProperty, false);
// Rename the node based on shader source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
// Rename the node based on shader source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
// Passes can't have children, so move shader node under parent
if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) {
BindingProperty listProp = targetNode.bindingProperty("shaders");
listProp.addModelNodeToArray(newModelNode);
outMoveNodesAfter = !moveNodeToParent(targetProperty, newModelNode);
}
});
}
return newModelNode;
@@ -932,7 +965,8 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{
QTC_ASSERT(m_view, return {});
@@ -947,7 +981,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
ModelNode newModelNode;
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) {
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode, outMoveNodesAfter)) {
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
// create a standalone Texture3D at drop location
newModelNode = createTextureNode(targetProperty, imagePath);
@@ -962,8 +996,23 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
const NodeAbstractProperty &targetProp,
const QString &imagePath,
ModelNode &newNode)
ModelNode &newNode,
bool &outMoveNodesAfter)
{
auto bindToProperty = [&](const PropertyName &propName, bool sibling) {
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
newNode = createTextureNode(targetProp, imagePath);
if (newNode.isValid()) {
targetNode.bindingProperty(propName).setExpression(newNode.validId());
// If dropping an image on e.g. TextureInput, create a texture on the same level as
// target, as the target doesn't support Texture children (QTBUG-86219)
if (sibling)
outMoveNodesAfter = !moveNodeToParent(targetProp, newNode);
}
});
};
if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")
|| targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
// if dropping an image on a material, create a texture instead of image
@@ -986,16 +1035,13 @@ bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
delete dialog;
return true;
} else if (targetNode.isSubclassOf("QtQuick3D.TextureInput")) {
// If dropping an image on a TextureInput, create a texture on the same level as
// TextureInput, as the TextureInput doesn't support Texture children (QTBUG-86219)
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
NodeAbstractProperty parentProp = targetProp.parentProperty();
newNode = createTextureNode(parentProp, imagePath);
if (newNode.isValid()) {
// Automatically set the texture to texture property
targetNode.bindingProperty("texture").setExpression(newNode.validId());
}
});
bindToProperty("texture", true);
return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
bindToProperty("sprite", false);
return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.SceneEnvironment")) {
bindToProperty("lightProbe", false);
return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.Texture")) {
// if dropping an image on an existing texture, set the source

View File

@@ -115,21 +115,24 @@ private:
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty, const QModelIndex &rowModelIndex);
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter);
ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
const QString &imagePath, ModelNode &newNode);
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
void addImport(const QString &importName);
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) const;
bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const ModelNode &newModelNode);
QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;

View File

@@ -108,14 +108,19 @@ static inline void applyProperties(ModelNode &node, const QHash<PropertyName, QV
}
}
static void openFileComponent(const ModelNode &modelNode)
static void openFileComponentForFile(const QString &fileName)
{
QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally();
Core::EditorManager::openEditor(FilePath::fromString(modelNode.metaInfo().componentFileName()),
Core::EditorManager::openEditor(FilePath::fromString(fileName),
Utils::Id(),
Core::EditorManager::DoNotMakeVisible);
}
static void openFileComponent(const ModelNode &modelNode)
{
openFileComponentForFile(modelNode.metaInfo().componentFileName());
}
static void openFileComponentForDelegate(const ModelNode &modelNode)
{
openFileComponent(modelNode.nodeProperty("delegate").modelNode());
@@ -305,6 +310,11 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
return false;
}
void DocumentManager::goIntoComponent(const QString &fileName)
{
openFileComponentForFile(fileName);
}
bool DocumentManager::createFile(const QString &filePath, const QString &contents)
{
Utils::TextFileFormat textFileFormat;

View File

@@ -52,6 +52,7 @@ public:
void removeEditors(const QList<Core::IEditor *> &editors);
static bool goIntoComponent(const ModelNode &modelNode);
static void goIntoComponent(const QString &fileName);
static bool createFile(const QString &filePath, const QString &contents);
static void addFileToVersionControl(const QString &directoryPath, const QString &newFilePath);

View File

@@ -146,7 +146,7 @@ void FileDownloader::start()
QNetworkRequest::UserVerifiedRedirectPolicy);
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
QNetworkReply::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() {
m_tempFile.write(reply->readAll());
});
@@ -165,7 +165,7 @@ void FileDownloader::start()
emit reply->redirectAllowed();
});
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error()) {
m_tempFile.remove();
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
@@ -246,7 +246,7 @@ void FileDownloader::probeUrl()
emit reply->redirectAllowed();
});
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error())
return;
@@ -259,6 +259,7 @@ void FileDownloader::probeUrl()
QNetworkReply::connect(reply,
&QNetworkReply::errorOccurred,
this,
[this, reply](QNetworkReply::NetworkError code) {
// QNetworkReply::HostNotFoundError
// QNetworkReply::ContentNotFoundError
@@ -282,7 +283,7 @@ FileExtractor::FileExtractor(QObject *parent)
m_timer.setInterval(100);
m_timer.setSingleShot(false);
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, [this]() {
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, this, [this]() {
if (targetFolderExists()) {
m_birthTime = QFileInfo(m_targetPath.toString() + "/" + m_archiveName).birthTime();
} else
@@ -389,33 +390,34 @@ void FileExtractor::extract()
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
qint64 compressedSize = QFileInfo(m_sourceFile.toString()).size();
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder, compressedSize]() {
static QHash<QString, int> hash;
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
QTimer::connect(
&m_timer, &QTimer::timeout, this, [this, bytesBefore, targetFolder, compressedSize]() {
static QHash<QString, int> hash;
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
int count = 0;
while (it.hasNext()) {
if (!hash.contains(it.fileName())) {
m_currentFile = it.fileName();
hash.insert(m_currentFile, 0);
emit currentFileChanged();
int count = 0;
while (it.hasNext()) {
if (!hash.contains(it.fileName())) {
m_currentFile = it.fileName();
hash.insert(m_currentFile, 0);
emit currentFileChanged();
}
it.next();
count++;
}
it.next();
count++;
}
qint64 currentSize = bytesBefore
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
qint64 currentSize = bytesBefore
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
// We can not get the uncompressed size of the archive yet, that is why we use an
// approximation. We assume a 50% compression rate.
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
emit progressChanged();
// We can not get the uncompressed size of the archive yet, that is why we use an
// approximation. We assume a 50% compression rate.
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
emit progressChanged();
m_size = QString::number(currentSize);
m_count = QString::number(count);
emit sizeChanged();
});
m_size = QString::number(currentSize);
m_count = QString::number(count);
emit sizeChanged();
});
QObject::connect(archive, &Utils::Archive::outputReceived, this, [this](const QString &output) {
m_detailedText += output;

View File

@@ -43,6 +43,7 @@
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <qmlprojectmanager/qmlproject.h>
@@ -59,18 +60,21 @@
#include <QAbstractListModel>
#include <QApplication>
#include <QCheckBox>
#include <QDesktopServices>
#include <QFileInfo>
#include <QFontDatabase>
#include <QGroupBox>
#include <QPointer>
#include <QShortcut>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickView>
#include <QQuickWidget>
#include <QSettings>
#include <QShortcut>
#include <QTimer>
#include <QVBoxLayout>
#include <algorithm>
#include <memory>
@@ -758,11 +762,109 @@ WelcomeMode::WelcomeMode()
[](const QString &path) { return QFileInfo::exists(path); }));
}
static bool hideBuildMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD, false)
.toBool();
}
static bool hideDebugMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG, false)
.toBool();
}
static bool hideAnalyzeMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
.toBool();
}
void setSettingIfDifferent(const QString &key, bool value, bool &dirty)
{
QSettings *s = Core::ICore::settings();
if (s->value(key, false).toBool() != value) {
dirty = false;
s->setValue(key, value);
}
}
WelcomeMode::~WelcomeMode()
{
delete m_modeWidget;
}
StudioSettingsPage::StudioSettingsPage()
: m_buildCheckBox(new QCheckBox(tr("Build")))
, m_debugCheckBox(new QCheckBox(tr("Debug")))
, m_analyzeCheckBox(new QCheckBox(tr("Analyze")))
{
const QString toolTip = tr(
"Hide top-level menus with advanced functionality to simplify the UI. <b>Build</b> is "
"generally not required in the context of Qt Design Studio.<b>Debug</b> and <b>Analyze</b>"
"are only required for debugging and profiling.");
QVBoxLayout *boxLayout = new QVBoxLayout(this);
setLayout(boxLayout);
auto groupBox = new QGroupBox(tr("Hide Menu"));
groupBox->setToolTip(toolTip);
boxLayout->addWidget(groupBox);
boxLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
auto verticalLayout = new QVBoxLayout();
groupBox->setLayout(verticalLayout);
m_buildCheckBox->setToolTip(toolTip);
m_debugCheckBox->setToolTip(toolTip);
m_analyzeCheckBox->setToolTip(toolTip);
verticalLayout->addWidget(m_buildCheckBox);
verticalLayout->addWidget(m_debugCheckBox);
verticalLayout->addWidget(m_analyzeCheckBox);
verticalLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
m_buildCheckBox->setChecked(hideBuildMenuSetting());
m_debugCheckBox->setChecked(hideDebugMenuSetting());
m_analyzeCheckBox->setChecked(hideAnalyzeMenuSetting());
}
void StudioSettingsPage::apply()
{
bool dirty = false;
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD,
m_buildCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG,
m_debugCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE,
m_analyzeCheckBox->isChecked(),
dirty);
if (dirty) {
const QString restartText = tr("The menu visibility change will take effect after restart.");
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
restartDialog.exec();
}
}
StudioWelcomeSettingsPage::StudioWelcomeSettingsPage()
{
setId("Z.StudioWelcome.Settings");
setDisplayName(tr("Qt Design Studio Configuration"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setWidgetCreator([] { return new StudioSettingsPage; });
}
} // namespace Internal
} // namespace StudioWelcome

View File

@@ -26,12 +26,36 @@
#pragma once
#include <extensionsystem/iplugin.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <QTimer>
QT_FORWARD_DECLARE_CLASS(QCheckBox)
namespace StudioWelcome {
namespace Internal {
class StudioSettingsPage : public Core::IOptionsPageWidget
{
public:
void apply() final;
StudioSettingsPage();
private:
QCheckBox *m_buildCheckBox;
QCheckBox *m_debugCheckBox;
QCheckBox *m_analyzeCheckBox;
};
class StudioWelcomeSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
StudioWelcomeSettingsPage();
};
class StudioWelcomePlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -55,6 +79,7 @@ public:
private:
class WelcomeMode *m_welcomeMode = nullptr;
QTimer m_removeSplashTimer;
StudioWelcomeSettingsPage m_settingsPage;
int m_removeSplashRemainingTime = 0;
};

View File

@@ -70,8 +70,7 @@ void WizardFactories::filter()
{
QList<JsonWizardFactory *> acceptedFactories = Utils::filtered(m_factories, [&](auto *wizard) {
return wizard->isAvailable(m_platform)
&& wizard->kind() == JsonWizardFactory::ProjectWizard
&& wizard->requiredFeatures().contains("QtStudio");
&& wizard->kind() == JsonWizardFactory::ProjectWizard;
});
m_factories = acceptedFactories;

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