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 GTEST_HAS_DEATH_TEST
) )
set_target_properties(Googletest PROPERTIES AUTOMOC OFF AUTOUIC OFF) 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) target_link_libraries(Googletest Threads::Threads)
endif() endif()

View File

@@ -763,7 +763,8 @@ function(extend_qtc_executable name)
endfunction() endfunction()
function(add_qtc_test name) 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) if ($_arg_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "add_qtc_test had 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}") update_cached_list(__QTC_TESTS "${name}")
if (NOT _arg_CONDITION)
set(_arg_CONDITION ON)
endif()
string(TOUPPER "BUILD_TEST_${name}" _build_test_var) string(TOUPPER "BUILD_TEST_${name}" _build_test_var)
set(_build_test_default ${BUILD_TESTS_BY_DEFAULT}) set(_build_test_default ${BUILD_TESTS_BY_DEFAULT})
if (DEFINED ENV{QTC_${_build_test_var}}) if (DEFINED ENV{QTC_${_build_test_var}})
@@ -778,7 +783,7 @@ function(add_qtc_test name)
endif() endif()
set(${_build_test_var} "${_build_test_default}" CACHE BOOL "Build test ${name}.") 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() return()
endif() endif()
@@ -820,7 +825,7 @@ function(add_qtc_test name)
enable_pch(${name}) enable_pch(${name})
endif() endif()
if (NOT _arg_GTEST) if (NOT _arg_GTEST AND NOT _arg_MANUALTEST)
add_test(NAME ${name} COMMAND ${name}) add_test(NAME ${name} COMMAND ${name})
if (DEFINED _arg_TIMEOUT) if (DEFINED _arg_TIMEOUT)
set(timeout_option TIMEOUT ${_arg_TIMEOUT}) set(timeout_option TIMEOUT ${_arg_TIMEOUT})

View File

@@ -348,6 +348,15 @@
\li Qt 5.3 \li Qt 5.3
\li Qt Quick 2 \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 \endtable
\section2 Analyzing Scene Graph Events \section2 Analyzing Scene Graph Events
@@ -550,6 +559,75 @@
\li None \li None
\endtable \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 \section1 Viewing Statistics
The \uicontrol Statistics view displays the number of times each binding, create, 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_QBS=' + cmake_option(build_qbs),
'-DBUILD_DEVELOPER_DOCS=' + cmake_option(not args.no_docs), '-DBUILD_DEVELOPER_DOCS=' + cmake_option(not args.no_docs),
'-DBUILD_EXECUTABLE_SDKTOOL=OFF', '-DBUILD_EXECUTABLE_SDKTOOL=OFF',
'-DQTC_FORCE_XCB=ON',
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install), '-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install),
'-DWITH_TESTS=' + cmake_option(args.with_tests)] '-DWITH_TESTS=' + cmake_option(args.with_tests)]
cmake_args += common_cmake_arguments(args) cmake_args += common_cmake_arguments(args)

View File

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

View File

@@ -91,6 +91,12 @@ Item {
if (mouse.button === Qt.LeftButton) if (mouse.button === Qt.LeftButton)
rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y)) 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 { Item {
id: itemsView id: itemsView
property string importToRemove: "" property string importToRemove
property string importToAdd: "" property string importToAdd
property string componentSource
property var currentCategory: null property var currentCategory: null
property var currentImport: null property var currentImport: null
property bool isHorizontalView: false property bool isHorizontalView: false
@@ -123,7 +124,7 @@ Item {
text: qsTr("Remove Module") text: qsTr("Remove Module")
visible: itemsView.currentCategory === null visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
enabled: itemsView.importToRemove !== "" && !rootView.subCompEditMode enabled: itemsView.importToRemove && !rootView.subCompEditMode
onTriggered: rootView.removeImport(itemsView.importToRemove) onTriggered: rootView.removeImport(itemsView.importToRemove)
} }
@@ -184,14 +185,23 @@ Item {
StudioControls.Menu { StudioControls.Menu {
id: itemContextMenu id: itemContextMenu
// Workaround for menu item implicit width not properly propagating to menu // Workaround for menu item implicit width not properly propagating to menu
width: importMenuItem.implicitWidth width: Math.max(importMenuItem.implicitWidth, openSourceItem.implicitWidth)
StudioControls.MenuItem { StudioControls.MenuItem {
id: importMenuItem id: importMenuItem
text: qsTr("Add Module: ") + itemsView.importToAdd text: qsTr("Add Module: ") + itemsView.importToAdd
enabled: itemsView.importToAdd !== "" visible: itemsView.importToAdd
height: visible ? implicitHeight : 0
onTriggered: rootView.addImportForItem(itemsView.importToAdd) 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 width: styleConstants.cellWidth
height: styleConstants.cellHeight height: styleConstants.cellHeight
onShowContextMenu: { onShowContextMenu: {
if (!itemUsable) { if (!itemUsable || itemComponentSource) {
itemsView.importToAdd = itemRequiredImport itemsView.importToAdd = !itemUsable ? itemRequiredImport : ""
itemsView.componentSource = itemComponentSource
itemContextMenu.popup() itemContextMenu.popup()
} }
} }
@@ -480,8 +491,9 @@ Item {
width: styleConstants.cellWidth width: styleConstants.cellWidth
height: styleConstants.cellHeight height: styleConstants.cellHeight
onShowContextMenu: { onShowContextMenu: {
if (!itemUsable) { if (!itemUsable || itemComponentSource) {
itemsView.importToAdd = itemRequiredImport itemsView.importToAdd = !itemUsable ? itemRequiredImport : ""
itemsView.componentSource = itemComponentSource
itemContextMenu.popup() itemContextMenu.popup()
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
QT -= gui QT -= gui
CONFIG += c++11 console CONFIG += c++17 console
CONFIG -= app_bundle CONFIG -= app_bundle
# You can make your code fail to compile if it uses deprecated APIs. # 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 # Documentation: https://mesonbuild.com/Qt5-module.html
qt5 = import('qt5') qt5 = import('qt5')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,6 +24,12 @@ add_qtc_executable(qtcreator
QTC_RUNNABLE QTC_RUNNABLE
) )
extend_qtc_executable(qtcreator
CONDITION APPLE
SOURCES
main_mac.mm
)
if (NOT TARGET qtcreator) if (NOT TARGET qtcreator)
return() return()
endif() endif()
@@ -86,6 +92,13 @@ if (APPLE)
) )
endif() 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 extend_qtc_executable(qtcreator
CONDITION BUILD_WITH_CRASHPAD CONDITION BUILD_WITH_CRASHPAD
DEFINES DEFINES

View File

@@ -500,6 +500,26 @@ int main(int argc, char **argv)
qputenv("QT_ENABLE_REGEXP_JIT", "0"); 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"); Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
#ifdef Q_OS_MACOS #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 QtQml 2.2
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.3
ScrollView { ScrollView {
id: root id: root
@@ -315,6 +316,7 @@ ScrollView {
ComboBox { ComboBox {
id: modesMenu id: modesMenu
width: 260 // TODO: Use implicitContentWidthPolicy (Qt6-only)
x: flickable.width - width x: flickable.width - width
y: flickable.contentY y: flickable.contentY
model: root.modes.map(function(role) { return root.trRoleNames[role] }); 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) inline QString withExecutableSuffix(OsType osType, const QString &executable)
{ {
QString finalName = executable; QString finalName = executable;
if (osType == OsTypeWindows) if (osType == OsTypeWindows && !finalName.endsWith(QTC_WIN_EXE_SUFFIX))
finalName += QLatin1String(QTC_WIN_EXE_SUFFIX); finalName += QLatin1String(QTC_WIN_EXE_SUFFIX);
return finalName; return finalName;
} }

View File

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

View File

@@ -260,7 +260,7 @@ void ClangFollowSymbol::switchDeclDef(const CppEditor::CursorInEditor &data,
{ {
ClangdClient * const client ClangdClient * const client
= ClangModelManagerSupport::instance()->clientForFile(data.filePath()); = 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(), client->switchDeclDef(data.textDocument(), data.cursor(), data.editorWidget(),
std::move(processLinkCallback)); std::move(processLinkCallback));
return; return;

View File

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

View File

@@ -902,3 +902,22 @@ void callOperators()
Callable2 c2; Callable2 c2;
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; 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, QAction *addAction(const QObject *parent, QMenu *menu, const QString &display, bool on,
const std::function<void()> &onTriggered) const std::function<void()> &onTriggered)
{ {
@@ -775,7 +782,8 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR); ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR);
ActionContainer *mtools = ActionManager::actionContainer(M_TOOLS); 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_TOOLS);
m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS); m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS);

View File

@@ -156,7 +156,8 @@ void OutputCollector::newConnectionAvailable()
void OutputCollector::bytesAvailable() void OutputCollector::bytesAvailable()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
emit byteDelivery(m_socket->readAll()); if (m_socket)
emit byteDelivery(m_socket->readAll());
#else #else
size_t nbytes = 0; size_t nbytes = 0;
if (::ioctl(m_serverFd, FIONREAD, (char *) &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 MENU_ID[] = "Docker.Menu";
const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType"; const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType";
const char DOCKER_RUN_FLAGS[] = "DockerRunFlags";
const char DOCKER_BUILDHOST_BUILDSTEP_ID[] = "Docker.BuildStep.BuildHost"; 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()); DockerDevice::ConstPtr dockerDevice = qSharedPointerCast<const DockerDevice>(device());
QTC_ASSERT(dockerDevice, return); QTC_ASSERT(dockerDevice, return);
const QStringList dockerRunFlags = extraData(Constants::DOCKER_RUN_FLAGS).toStringList();
connect(this, &DeviceProcess::readyReadStandardOutput, this, [this] { connect(this, &DeviceProcess::readyReadStandardOutput, this, [this] {
MessageManager::writeSilently(QString::fromLocal8Bit(readAllStandardError())); 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::messageReceived, this, &Client::handleMessage);
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError); connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished); connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
connect(Core::EditorManager::instance(),
&Core::EditorManager::documentClosed,
this,
&Client::documentClosed);
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap()); m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap()); m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
@@ -308,13 +312,11 @@ void Client::initialize()
initRequest.setResponseCallback([this](const InitializeRequest::Response &initResponse){ initRequest.setResponseCallback([this](const InitializeRequest::Response &initResponse){
initializeCallback(initResponse); initializeCallback(initResponse);
}); });
// directly send data otherwise the state check would fail;
if (Utils::optional<ResponseHandler> responseHandler = initRequest.responseHandler()) if (Utils::optional<ResponseHandler> responseHandler = initRequest.responseHandler())
m_responseHandlers[responseHandler->id] = responseHandler->callback; m_responseHandlers[responseHandler->id] = responseHandler->callback;
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, // directly send message otherwise the state check of sendContent would fail
name(), sendMessage(initRequest.toBaseMessage());
initRequest.toBaseMessage());
m_clientInterface->sendMessage(initRequest.toBaseMessage()); m_clientInterface->sendMessage(initRequest.toBaseMessage());
m_state = InitializeRequested; m_state = InitializeRequested;
} }
@@ -427,9 +429,7 @@ void Client::sendContent(const IContent &content, SendDocUpdates sendUpdates)
QString error; QString error;
if (!QTC_GUARD(content.isValid(&error))) if (!QTC_GUARD(content.isValid(&error)))
Core::MessageManager::writeFlashing(error); Core::MessageManager::writeFlashing(error);
const BaseMessage message = content.toBaseMessage(); sendMessage(content.toBaseMessage());
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
m_clientInterface->sendMessage(message);
} }
void Client::cancelRequest(const MessageId &id) 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 bool Client::documentOpen(const TextEditor::TextDocument *document) const
{ {
return m_openedDocument.contains(const_cast<TextEditor::TextDocument *>(document)); 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 bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
{ {
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) { return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
@@ -1602,8 +1614,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
qDebug() << error; qDebug() << error;
return; return;
} }
// directly send data otherwise the state check would fail; // directly send message otherwise the state check of sendContent would fail
m_clientInterface->sendMessage(ExitNotification().toBaseMessage()); sendMessage(ExitNotification().toBaseMessage());
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown"; qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown";
m_state = Shutdown; m_state = Shutdown;
} }

View File

@@ -227,6 +227,7 @@ protected:
virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params); virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params);
private: private:
void sendMessage(const LanguageServerProtocol::BaseMessage &message);
void handleResponse(const LanguageServerProtocol::MessageId &id, const QByteArray &content, void handleResponse(const LanguageServerProtocol::MessageId &id, const QByteArray &content,
QTextCodec *codec); QTextCodec *codec);
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id, void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
@@ -252,6 +253,7 @@ private:
void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget); void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const; LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens); void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
void documentClosed(Core::IDocument *document);
virtual void handleDocumentClosed(TextEditor::TextDocument *) {} virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(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) void LanguageClientManager::documentClosed(Core::IDocument *document)
{ {
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document)) { if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
for (Client *client : qAsConst(m_clients))
client->closeDocument(textDocument);
m_clientForDocument.remove(textDocument); m_clientForDocument.remove(textDocument);
}
} }
void LanguageClientManager::documentContentsSaved(Core::IDocument *document) void LanguageClientManager::documentContentsSaved(Core::IDocument *document)

View File

@@ -7,7 +7,7 @@ add_qtc_plugin(McuSupport
mcusupport_global.h mcusupport_global.h
mcusupportconstants.h mcusupportconstants.h
mcusupportdevice.cpp mcusupportdevice.h mcusupportdevice.cpp mcusupportdevice.h
mcusupportoptions.cpp mcusupportoptions.h mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h
mcusupportoptionspage.cpp mcusupportoptionspage.h mcusupportoptionspage.cpp mcusupportoptionspage.h
mcupackage.cpp mcupackage.h mcupackage.cpp mcupackage.h
mcusupportplugin.cpp mcusupportplugin.h mcusupportplugin.cpp mcusupportplugin.h
@@ -15,4 +15,7 @@ add_qtc_plugin(McuSupport
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
mcusupportversiondetection.cpp mcusupportversiondetection.h mcusupportversiondetection.cpp mcusupportversiondetection.h
mcusupportcmakemapper.cpp mcusupportcmakemapper.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; using namespace Utils;
namespace McuSupport { namespace McuSupport::Internal {
namespace Internal {
static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope) static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope)
{ {
@@ -144,8 +143,7 @@ McuPackage::Status McuPackage::status() const
bool McuPackage::validStatus() const bool McuPackage::validStatus() const
{ {
return m_status == McuPackage::ValidPackage return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
|| m_status == McuPackage::ValidPackageMismatchedVersion;
} }
const QString &McuPackage::environmentVariableName() const const QString &McuPackage::environmentVariableName() const
@@ -221,11 +219,11 @@ void McuPackage::updateStatus()
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty() const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|| m_versions.contains(m_detectedVersion); || m_versions.contains(m_detectedVersion);
m_status = validPath m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage
? (validPackage ? (validVersion ? ValidPackage : ValidPackageMismatchedVersion) : Status::ValidPackageMismatchedVersion)
: ValidPathInvalidPackage) : Status::ValidPathInvalidPackage)
: m_path.isEmpty() ? EmptyPath : m_path.isEmpty() ? Status::EmptyPath
: InvalidPath; : Status::InvalidPath;
emit statusChanged(); emit statusChanged();
} }
@@ -233,10 +231,10 @@ void McuPackage::updateStatus()
void McuPackage::updateStatusUi() void McuPackage::updateStatusUi()
{ {
switch (m_status) { switch (m_status) {
case ValidPackage: case Status::ValidPackage:
m_infoLabel->setType(InfoLabel::Ok); m_infoLabel->setType(InfoLabel::Ok);
break; break;
case ValidPackageMismatchedVersion: case Status::ValidPackageMismatchedVersion:
m_infoLabel->setType(InfoLabel::Warning); m_infoLabel->setType(InfoLabel::Warning);
break; break;
default: default:
@@ -261,7 +259,7 @@ QString McuPackage::statusText() const
QString response; QString response;
switch (m_status) { switch (m_status) {
case ValidPackage: case Status::ValidPackage:
response = m_detectionPath.isEmpty() response = m_detectionPath.isEmpty()
? (m_detectedVersion.isEmpty() ? (m_detectedVersion.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath) ? tr("Path %1 exists.").arg(displayPackagePath)
@@ -270,23 +268,22 @@ QString McuPackage::statusText() const
: tr("Path %1 is valid, %2 was found.") : tr("Path %1 is valid, %2 was found.")
.arg(displayPackagePath, displayDetectedPath); .arg(displayPackagePath, displayDetectedPath);
break; break;
case ValidPackageMismatchedVersion: { case Status::ValidPackageMismatchedVersion: {
const QString versionWarning const QString versionWarning = m_versions.size() == 1 ?
= m_versions.size() == 1 tr("but only version %1 is supported").arg(m_versions.first()) :
? tr("but only version %1 is supported").arg(m_versions.first()) tr("but only versions %1 are supported").arg(displayVersions);
: tr("but only versions %1 are supported").arg(displayVersions);
response = tr("Path %1 is valid, %2 was found, %3.") response = tr("Path %1 is valid, %2 was found, %3.")
.arg(displayPackagePath, displayDetectedPath, versionWarning); .arg(displayPackagePath, displayDetectedPath, versionWarning);
break; break;
} }
case ValidPathInvalidPackage: case Status::ValidPathInvalidPackage:
response = tr("Path %1 exists, but does not contain %2.") response = tr("Path %1 exists, but does not contain %2.")
.arg(displayPackagePath, displayRequiredPath); .arg(displayPackagePath, displayRequiredPath);
break; break;
case InvalidPath: case Status::InvalidPath:
response = tr("Path %1 does not exist.").arg(displayPackagePath); response = tr("Path %1 does not exist.").arg(displayPackagePath);
break; break;
case EmptyPath: case Status::EmptyPath:
response = m_detectionPath.isEmpty() response = m_detectionPath.isEmpty()
? tr("Path is empty.") ? tr("Path is empty.")
: tr("Path is empty, %1 not found.").arg(displayRequiredPath); : 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; return m_type == Type::MSVC || m_type == Type::GCC;
} }
} // namespace Internal } // namespace McuSupport::Internal
} // namespace McuSupport

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,18 +33,26 @@
namespace McuSupport { namespace McuSupport {
namespace Internal { namespace Internal {
#define MAX_COMPATIBILITY_VERSION 1 constexpr int MAX_COMPATIBILITY_VERSION {1};
class McuSdkRepository; class McuSdkRepository;
class McuAbstractPackage;
class McuPackage; class McuPackage;
class McuTarget;
namespace Sdk { namespace Sdk {
struct McuTargetDescription;
McuPackage *createQtForMCUsPackage(); McuPackage *createQtForMCUsPackage();
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message); bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo); 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 kitsPath(const Utils::FilePath &dir);
Utils::FilePath packagePathFromSettings(const QString &settingsKey, 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 << ("*-*-*-*-" + compilerName
+ "-[1-9]*"); // "x86_64-pc-linux-gnu-gcc-7.4.1" + "-[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; FilePaths compilerPaths;
@@ -1145,9 +1149,6 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
for (const FilePath &dir : qAsConst(searchPaths)) { for (const FilePath &dir : qAsConst(searchPaths)) {
static const QRegularExpression regexp(binaryRegexp); static const QRegularExpression regexp(binaryRegexp);
QDir binDir(dir.toString()); QDir binDir(dir.toString());
nameFilters = transform(nameFilters, [](const QString &baseName) {
return HostOsInfo::withExecutableSuffix(baseName);
});
const QStringList fileNames = binDir.entryList(nameFilters, const QStringList fileNames = binDir.entryList(nameFilters,
QDir::Files | QDir::Executable); QDir::Files | QDir::Executable);
for (const QString &fileName : fileNames) { 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)); QPair<FilePath, int> position = parseFileName(match.captured(1));
const FilePath filePath = absoluteFilePath(position.first); const FilePath filePath = absoluteFilePath(position.first);
LinkSpecs linkSpecs; LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
if (!m_lastTask.isNull() && line.contains("note: ")) { if (!m_lastTask.isNull() && line.contains("note: ")) {
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
const int offset = std::accumulate(m_lastTask.details.cbegin(), const int offset = std::accumulate(m_lastTask.details.cbegin(),
m_lastTask.details.cend(), 0, m_lastTask.details.cend(), 0,
[](int total, const QString &line) { return total + line.length() + 1;}); [](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)), m_lastTask = CompileTask(taskType(match.captured(2)),
match.captured(3) + match.captured(4).trimmed(), // description match.captured(3) + match.captured(4).trimmed(), // description
filePath, position.second); filePath, position.second);
m_linkSpecs << linkSpecs;
m_lines = 1; m_lines = 1;
} }
return {Status::InProgress, linkSpecs}; return {Status::InProgress, linkSpecs};

View File

@@ -314,6 +314,16 @@ static const RunConfiguration *runConfigForNode(const Target *target, const Proj
return target->activeRunConfiguration(); 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) static bool canOpenTerminalWithRunEnv(const Project *project, const ProjectNode *node)
{ {
if (!project) if (!project)
@@ -938,14 +948,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// build menu // build menu
ActionContainer *mbuild = ActionContainer *mbuild =
ActionManager::createMenu(Constants::M_BUILDPROJECT); ActionManager::createMenu(Constants::M_BUILDPROJECT);
mbuild->menu()->setTitle(tr("&Build")); mbuild->menu()->setTitle(tr("&Build"));
menubar->addMenu(mbuild, Core::Constants::G_VIEW); if (!hideBuildMenu())
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
// debug menu // debug menu
ActionContainer *mdebug = ActionContainer *mdebug =
ActionManager::createMenu(Constants::M_DEBUG); ActionManager::createMenu(Constants::M_DEBUG);
mdebug->menu()->setTitle(tr("&Debug")); mdebug->menu()->setTitle(tr("&Debug"));
menubar->addMenu(mdebug, Core::Constants::G_VIEW); if (!hideDebugMenu())
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
ActionContainer *mstartdebugging = ActionContainer *mstartdebugging =
ActionManager::createMenu(Constants::M_DEBUG_STARTDEBUGGING); 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 PROJECT_ROOT_PATH_KEY[] = "ProjectExplorer.Project.RootPath";
const char STARTUPSESSION_KEY[] = "ProjectExplorer/SessionToRestore"; const char STARTUPSESSION_KEY[] = "ProjectExplorer/SessionToRestore";
const char LASTSESSION_KEY[] = "ProjectExplorer/StartupSession"; 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 // UI texts
PROJECTEXPLORER_EXPORT QString msgAutoDetected(); PROJECTEXPLORER_EXPORT QString msgAutoDetected();

View File

@@ -144,6 +144,9 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
return true; return true;
dir.cdUp(); dir.cdUp();
saveExpandedState(loadExpandedState(folderPath), dir.absoluteFilePath(newName));
return dir.rename(oldName, newName); return dir.rename(oldName, newName);
} }
@@ -341,8 +344,14 @@ void AssetsLibraryModel::setRootPath(const QString &path)
beginResetModel(); beginResetModel();
m_assetsDir = new AssetsLibraryDir(path, 0, true, this); m_assetsDir = new AssetsLibraryDir(path, 0, true, this);
bool noAssets = parseDirRecursive(m_assetsDir, 1); bool isEmpty = parseDirRecursive(m_assetsDir, 1);
setIsEmpty(noAssets); 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(); endResetModel();
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,35 +34,64 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
const NodeMetaInfo &parentInfo, const NodeMetaInfo &parentInfo,
bool breakOnFirst) bool breakOnFirst)
{ {
TypeName typeName = insertInfo.typeName(); // TODO: Metainfo based matching system (QDS-6240)
TypeName superClass = insertInfo.directSuperClass().typeName();
TypeName nodePackage = insertInfo.typeName().replace(insertInfo.simplifiedTypeName(), "");
TypeName targetPackage = parentInfo.typeName().replace(parentInfo.simplifiedTypeName(), "");
if (!nodePackage.contains(targetPackage))
return;
// Common base types cause too many rarely valid matches, so they are ignored // Fall back to a hardcoded list of supported cases:
const QSet<TypeName> ignoredTypes {"<cpp>.QObject", // Texture
"<cpp>.QQuickItem", // -> DefaultMaterial
"<cpp>.QQuick3DObject", // -> PrincipledMaterial
"QtQuick.Item", // -> SpriteParticle3D
"QtQuick3D.Object3D", // -> TextureInput
"QtQuick3D.Node", // -> SceneEnvironment
"QtQuick3D.Particles3D.ParticleSystem3D"}; // Effect
const PropertyNameList targetNodeNameList = parentInfo.propertyNames(); // -> SceneEnvironment
for (const PropertyName &name : targetNodeNameList) { // Shader, Command, Buffer
if (!name.contains('.')) { // -> Pass
TypeName propType = parentInfo.propertyTypeName(name).replace("<cpp>.", targetPackage); // InstanceListEntry
// Skip properties that are not sub classes of anything // -> InstanceList
if (propType.contains('.') // Pass
&& !ignoredTypes.contains(propType) // -> Effect
&& (typeName == propType || propType == superClass)
&& parentInfo.propertyIsWritable(propType)) { const TypeName textureType = "QtQuick3D.Texture";
propertyList.append(QString::fromLatin1(name)); if (insertInfo.isSubclassOf(textureType)) {
if (breakOnFirst) const TypeName textureTypeCpp = "<cpp>.QQuick3DTexture";
break; 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( ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
const ModelNode &targetNode, const ModelNode &newNode, QWidget *parent) 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 info = newNode.metaInfo();
const NodeMetaInfo targetInfo = targetNode.metaInfo(); const NodeMetaInfo targetInfo = targetNode.metaInfo();
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(info, targetInfo); ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(info, targetInfo);

View File

@@ -581,21 +581,29 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
addImport(import); addImport(import);
} }
bool moveNodesAfter = true;
m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] { m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] {
for (const QString &assetPath : assetsPaths) { for (const QString &assetPath : assetsPaths) {
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetPath); auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetPath);
QString assetType = assetTypeAndData.first; QString assetType = assetTypeAndData.first;
QString assetData = QString::fromUtf8(assetTypeAndData.second); QString assetData = QString::fromUtf8(assetTypeAndData.second);
if (assetType == "application/vnd.bauhaus.libraryresource.image") if (assetType == "application/vnd.bauhaus.libraryresource.image") {
currNode = handleItemLibraryImageDrop(assetPath, targetProperty, rowModelIndex); currNode = handleItemLibraryImageDrop(assetPath, targetProperty,
else if (assetType == "application/vnd.bauhaus.libraryresource.font") rowModelIndex, moveNodesAfter);
currNode = handleItemLibraryFontDrop(assetData, targetProperty, rowModelIndex); // assetData is fontFamily } else if (assetType == "application/vnd.bauhaus.libraryresource.font") {
else if (assetType == "application/vnd.bauhaus.libraryresource.shader") currNode = handleItemLibraryFontDrop(assetData, // assetData is fontFamily
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f", targetProperty, rowModelIndex); targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.sound") } else if (assetType == "application/vnd.bauhaus.libraryresource.shader") {
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty, rowModelIndex); currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f",
else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d") targetProperty, rowModelIndex,
currNode = handleItemLibraryTexture3dDrop(assetPath, 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()) if (currNode.isValid())
addedNodes.append(currNode); addedNodes.append(currNode);
@@ -603,7 +611,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
}); });
if (!addedNodes.isEmpty()) { if (!addedNodes.isEmpty()) {
moveNodesInteractive(targetProperty, addedNodes, rowNumber); if (moveNodesAfter)
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
m_view->setSelectedModelNodes(addedNodes); m_view->setSelectedModelNodes(addedNodes);
} }
} }
@@ -682,21 +691,22 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
dialog->exec(); dialog->exec();
if (soloProperty || dialog->result() == QDialog::Accepted) { if (soloProperty || dialog->result() == QDialog::Accepted) {
TypeName selectedProp = dialog->selectedProperty(); TypeName selectedProp = dialog->selectedProperty();
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) { // Pass and TextureInput can't have children, so we have to move nodes under parent
if ((newModelNode.isSubclassOf("QtQuick3D.Shader") || newModelNode.isSubclassOf("QtQuick3D.Command")) if (((newModelNode.isSubclassOf("QtQuick3D.Shader")
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) { || newModelNode.isSubclassOf("QtQuick3D.Command")
NodeAbstractProperty parentProp = targetProperty.parentProperty(); || newModelNode.isSubclassOf("QtQuick3D.Buffer"))
if (parentProp.isValid()) { && targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass"))
targetProperty = parentProp; || (newModelNode.isSubclassOf("QtQuick3D.Texture")
ModelNode targetModel = targetProperty.parentModelNode(); && targetProperty.parentModelNode().isSubclassOf("QtQuick3D.TextureInput"))) {
targetRowNumber = rowCount(indexForModelNode(targetModel)); if (moveNodeToParent(targetProperty, newQmlObjectNode)) {
// Move node to new parent within the same transaction as we don't targetProperty = targetProperty.parentProperty();
// want undo to place the node under invalid parent moveNodesAfter = false;
moveNodesInteractive(targetProperty, {newQmlObjectNode}, targetRowNumber, false);
moveNodesAfter = false;
}
} }
}
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
listProp.addModelNodeToArray(newModelNode); listProp.addModelNodeToArray(newModelNode);
validContainer = true; validContainer = true;
} else { } else {
@@ -778,7 +788,8 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath, ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
NodeAbstractProperty targetProperty, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex) const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{ {
QTC_ASSERT(m_view, return {}); QTC_ASSERT(m_view, return {});
@@ -788,7 +799,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePat
ModelNode newModelNode; 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 (targetNode.isSubclassOf("QtQuick.Image") || targetNode.isSubclassOf("QtQuick.BorderImage")) {
// if dropping an image on an existing image, set the source // if dropping an image on an existing image, set the source
targetNode.variantProperty("source").setValue(imagePathRelative); 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, ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex) const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{ {
QTC_ASSERT(m_view, return {}); QTC_ASSERT(m_view, return {});
@@ -863,29 +888,37 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
: "Shader.Vertex"); : "Shader.Vertex");
targetNode.variantProperty("shader").setValue(relPath); targetNode.variantProperty("shader").setValue(relPath);
} else { } else {
// create a new Shader m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
ItemLibraryEntry itemLibraryEntry; // create a new Shader
itemLibraryEntry.setName("Shader"); ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0); itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
// set shader properties // set shader properties
PropertyName prop = "shader"; PropertyName prop = "shader";
QString type = "QByteArray"; QString type = "QByteArray";
QVariant val = relPath; QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val); itemLibraryEntry.addProperty(prop, type, val);
prop = "stage"; prop = "stage";
type = "enum"; type = "enum";
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex"; val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
itemLibraryEntry.addProperty(prop, type, val); itemLibraryEntry.addProperty(prop, type, val);
// create a texture // create a texture
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {}, newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
targetProperty, false); targetProperty, false);
// Rename the node based on shader source // Rename the node based on shader source
QFileInfo fi(relPath); QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader")); "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; return newModelNode;
@@ -932,7 +965,8 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath, ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath,
NodeAbstractProperty targetProperty, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex) const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{ {
QTC_ASSERT(m_view, return {}); QTC_ASSERT(m_view, return {});
@@ -947,7 +981,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
ModelNode newModelNode; ModelNode newModelNode;
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) { if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode, outMoveNodesAfter)) {
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] { m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
// create a standalone Texture3D at drop location // create a standalone Texture3D at drop location
newModelNode = createTextureNode(targetProperty, imagePath); newModelNode = createTextureNode(targetProperty, imagePath);
@@ -962,8 +996,23 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode, bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
const NodeAbstractProperty &targetProp, const NodeAbstractProperty &targetProp,
const QString &imagePath, 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") if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")
|| targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) { || targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
// if dropping an image on a material, create a texture instead of image // 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; delete dialog;
return true; return true;
} else if (targetNode.isSubclassOf("QtQuick3D.TextureInput")) { } else if (targetNode.isSubclassOf("QtQuick3D.TextureInput")) {
// If dropping an image on a TextureInput, create a texture on the same level as bindToProperty("texture", true);
// TextureInput, as the TextureInput doesn't support Texture children (QTBUG-86219) return newNode.isValid();
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] { } else if (targetNode.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
NodeAbstractProperty parentProp = targetProp.parentProperty(); bindToProperty("sprite", false);
newNode = createTextureNode(parentProp, imagePath); return newNode.isValid();
if (newNode.isValid()) { } else if (targetNode.isSubclassOf("QtQuick3D.SceneEnvironment")) {
// Automatically set the texture to texture property bindToProperty("lightProbe", false);
targetNode.bindingProperty("texture").setExpression(newNode.validId());
}
});
return newNode.isValid(); return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.Texture")) { } else if (targetNode.isSubclassOf("QtQuick3D.Texture")) {
// if dropping an image on an existing texture, set the source // 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 handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
void handleItemLibraryItemDrop(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, ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex); const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty, ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex); const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader, 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, ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex); const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty, ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex); const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp, 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); ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes); QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
void addImport(const QString &importName); void addImport(const QString &importName);
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) const; QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) const;
bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const ModelNode &newModelNode);
QPointer<NavigatorView> m_view; QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash; 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(); QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally();
Core::EditorManager::openEditor(FilePath::fromString(modelNode.metaInfo().componentFileName()), Core::EditorManager::openEditor(FilePath::fromString(fileName),
Utils::Id(), Utils::Id(),
Core::EditorManager::DoNotMakeVisible); Core::EditorManager::DoNotMakeVisible);
} }
static void openFileComponent(const ModelNode &modelNode)
{
openFileComponentForFile(modelNode.metaInfo().componentFileName());
}
static void openFileComponentForDelegate(const ModelNode &modelNode) static void openFileComponentForDelegate(const ModelNode &modelNode)
{ {
openFileComponent(modelNode.nodeProperty("delegate").modelNode()); openFileComponent(modelNode.nodeProperty("delegate").modelNode());
@@ -305,6 +310,11 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
return false; return false;
} }
void DocumentManager::goIntoComponent(const QString &fileName)
{
openFileComponentForFile(fileName);
}
bool DocumentManager::createFile(const QString &filePath, const QString &contents) bool DocumentManager::createFile(const QString &filePath, const QString &contents)
{ {
Utils::TextFileFormat textFileFormat; Utils::TextFileFormat textFileFormat;

View File

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

View File

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

View File

@@ -43,6 +43,7 @@
#include <projectexplorer/jsonwizard/jsonwizardfactory.h> #include <projectexplorer/jsonwizard/jsonwizardfactory.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h> #include <projectexplorer/projectmanager.h>
#include <qmlprojectmanager/qmlproject.h> #include <qmlprojectmanager/qmlproject.h>
@@ -59,18 +60,21 @@
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QApplication> #include <QApplication>
#include <QCheckBox>
#include <QDesktopServices> #include <QDesktopServices>
#include <QFileInfo> #include <QFileInfo>
#include <QFontDatabase> #include <QFontDatabase>
#include <QGroupBox>
#include <QPointer> #include <QPointer>
#include <QShortcut>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlEngine> #include <QQmlEngine>
#include <QQuickItem> #include <QQuickItem>
#include <QQuickView> #include <QQuickView>
#include <QQuickWidget> #include <QQuickWidget>
#include <QSettings> #include <QSettings>
#include <QShortcut>
#include <QTimer> #include <QTimer>
#include <QVBoxLayout>
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
@@ -758,11 +762,109 @@ WelcomeMode::WelcomeMode()
[](const QString &path) { return QFileInfo::exists(path); })); [](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() WelcomeMode::~WelcomeMode()
{ {
delete m_modeWidget; 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 Internal
} // namespace StudioWelcome } // namespace StudioWelcome

View File

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

View File

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

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