forked from qt-creator/qt-creator
Merge "Merge remote-tracking branch 'origin/7.0'"
This commit is contained in:
@@ -101,6 +101,8 @@ if(Googletest_FOUND AND NOT TARGET Googletest)
|
||||
GTEST_HAS_DEATH_TEST
|
||||
)
|
||||
set_target_properties(Googletest PROPERTIES AUTOMOC OFF AUTOUIC OFF)
|
||||
set_property(TARGET Googletest PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_compile_definitions(Googletest PUBLIC GOOGLE_TEST_IS_FOUND)
|
||||
|
||||
target_link_libraries(Googletest Threads::Threads)
|
||||
endif()
|
||||
|
@@ -763,7 +763,8 @@ function(extend_qtc_executable name)
|
||||
endfunction()
|
||||
|
||||
function(add_qtc_test name)
|
||||
cmake_parse_arguments(_arg "GTEST" "TIMEOUT" "DEFINES;DEPENDS;INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;SKIP_PCH" ${ARGN})
|
||||
cmake_parse_arguments(_arg "GTEST;MANUALTEST" "TIMEOUT"
|
||||
"DEFINES;DEPENDS;INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;SKIP_PCH;CONDITION" ${ARGN})
|
||||
|
||||
if ($_arg_UNPARSED_ARGUMENTS)
|
||||
message(FATAL_ERROR "add_qtc_test had unparsed arguments!")
|
||||
@@ -771,6 +772,10 @@ function(add_qtc_test name)
|
||||
|
||||
update_cached_list(__QTC_TESTS "${name}")
|
||||
|
||||
if (NOT _arg_CONDITION)
|
||||
set(_arg_CONDITION ON)
|
||||
endif()
|
||||
|
||||
string(TOUPPER "BUILD_TEST_${name}" _build_test_var)
|
||||
set(_build_test_default ${BUILD_TESTS_BY_DEFAULT})
|
||||
if (DEFINED ENV{QTC_${_build_test_var}})
|
||||
@@ -778,7 +783,7 @@ function(add_qtc_test name)
|
||||
endif()
|
||||
set(${_build_test_var} "${_build_test_default}" CACHE BOOL "Build test ${name}.")
|
||||
|
||||
if (NOT ${_build_test_var})
|
||||
if (NOT ${_build_test_var} OR NOT ${_arg_CONDITION})
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -820,7 +825,7 @@ function(add_qtc_test name)
|
||||
enable_pch(${name})
|
||||
endif()
|
||||
|
||||
if (NOT _arg_GTEST)
|
||||
if (NOT _arg_GTEST AND NOT _arg_MANUALTEST)
|
||||
add_test(NAME ${name} COMMAND ${name})
|
||||
if (DEFINED _arg_TIMEOUT)
|
||||
set(timeout_option TIMEOUT ${_arg_TIMEOUT})
|
||||
|
@@ -348,6 +348,15 @@
|
||||
\li Qt 5.3
|
||||
\li Qt Quick 2
|
||||
|
||||
\row
|
||||
\li \uicontrol Quick3D
|
||||
\li Displays the time spent rendering Qt Quick 3D frames, timing information
|
||||
for frame preparation and synchronization, particle system update times
|
||||
and particle update count, as well as texture and mesh memory allocations
|
||||
and memory consumption.
|
||||
\li Qt 6.3
|
||||
\li Qt Quick 3D
|
||||
|
||||
\endtable
|
||||
|
||||
\section2 Analyzing Scene Graph Events
|
||||
@@ -550,6 +559,75 @@
|
||||
\li None
|
||||
\endtable
|
||||
|
||||
\section2 Analyzing Qt Quick 3D Events
|
||||
|
||||
The following is the list of events for Qt Quick 3D. Each rendered frame
|
||||
consists of synchronize, prepare, and render phases, which are done in that order.
|
||||
Synchronize happens in scene graph synchronizing phase, while prepare and
|
||||
render happen in scene graph rendering phase.
|
||||
|
||||
Setting the environment variable \c QSG_RENDERER_DEBUG=render will also give
|
||||
additional textual output of render call counts of different rendering passes.
|
||||
These call counts are summed up in the Render Frame event.
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Event Type
|
||||
\li Thread
|
||||
\li Description
|
||||
\row
|
||||
\li \uicontrol {Render Frame}
|
||||
\li Render
|
||||
\li Render time of a frame. Also shows the number of draw calls.
|
||||
\row
|
||||
\li \uicontrol {Prepare Frame}
|
||||
\li Render
|
||||
\li Time taken for preparing a frame. Resources are allocated and loaded
|
||||
in the prepare phase. The first frame after scene loading usually takes
|
||||
longer than others since most resources are loaded at that time.
|
||||
\row
|
||||
\li \uicontrol {Synchronize Frame}
|
||||
\li Render
|
||||
\li Synchronize time of a frame. Synchronize takes care of updating backend
|
||||
values from the frontend. Also manages shared resources between Qt Quick
|
||||
Scene Graph and Qt Quick 3D.
|
||||
\row
|
||||
\li \uicontrol {Mesh Load}
|
||||
\li Render
|
||||
\li Load time of a mesh. Shows total memory usage of all meshes. Also shows
|
||||
unloads.
|
||||
\row
|
||||
\li \uicontrol {Custom Mesh Load}
|
||||
\li Render
|
||||
\li Load time of a custom mesh. Shows total memory usage of all meshes.
|
||||
Also shows unloads.
|
||||
\row
|
||||
\li \uicontrol {Texture Load}
|
||||
\li Render
|
||||
\li Load time of a texture. Shows total memory usage of all textures.
|
||||
Also shows unloads.
|
||||
\row
|
||||
\li \uicontrol {Generate Shader}
|
||||
\li Render
|
||||
\li Time for generating a shader for a material.
|
||||
\row
|
||||
\li \uicontrol {Load Shader}
|
||||
\li Render
|
||||
\li Time for loading a built-in shader.
|
||||
\row
|
||||
\li \uicontrol {Particle Update}
|
||||
\li GUI
|
||||
\li Update time of a particle system. Shows the number of particles updated.
|
||||
\row
|
||||
\li \uicontrol {Mesh Memory Consumption}
|
||||
\li Render
|
||||
\li Shows a bar view of total mesh memory consumption.
|
||||
\row
|
||||
\li \uicontrol {Texture Memory Consumption}
|
||||
\li Render
|
||||
\li Shows a bar view of total texture memory consumption.
|
||||
\endtable
|
||||
|
||||
\section1 Viewing Statistics
|
||||
|
||||
The \uicontrol Statistics view displays the number of times each binding, create,
|
||||
|
@@ -173,6 +173,7 @@ def build_qtcreator(args, paths):
|
||||
'-DBUILD_QBS=' + cmake_option(build_qbs),
|
||||
'-DBUILD_DEVELOPER_DOCS=' + cmake_option(not args.no_docs),
|
||||
'-DBUILD_EXECUTABLE_SDKTOOL=OFF',
|
||||
'-DQTC_FORCE_XCB=ON',
|
||||
'-DCMAKE_INSTALL_PREFIX=' + common.to_posix_path(paths.install),
|
||||
'-DWITH_TESTS=' + cmake_option(args.with_tests)]
|
||||
cmake_args += common_cmake_arguments(args)
|
||||
|
@@ -445,7 +445,7 @@ Item {
|
||||
hideHeader: dirDepth === 0
|
||||
showLeftBorder: dirDepth > 0
|
||||
expanded: dirExpanded
|
||||
visible: !assetsModel.isEmpty && dirVisible
|
||||
visible: dirVisible
|
||||
expandOnClick: false
|
||||
useDefaulContextMenu: false
|
||||
|
||||
|
@@ -91,6 +91,12 @@ Item {
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y))
|
||||
}
|
||||
onDoubleClicked: (mouse)=> {
|
||||
if (mouse.button === Qt.LeftButton && itemComponentSource) {
|
||||
hide()
|
||||
rootView.goIntoComponent(itemComponentSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -76,8 +76,9 @@ itemLibraryModel [
|
||||
Item {
|
||||
id: itemsView
|
||||
|
||||
property string importToRemove: ""
|
||||
property string importToAdd: ""
|
||||
property string importToRemove
|
||||
property string importToAdd
|
||||
property string componentSource
|
||||
property var currentCategory: null
|
||||
property var currentImport: null
|
||||
property bool isHorizontalView: false
|
||||
@@ -123,7 +124,7 @@ Item {
|
||||
text: qsTr("Remove Module")
|
||||
visible: itemsView.currentCategory === null
|
||||
height: visible ? implicitHeight : 0
|
||||
enabled: itemsView.importToRemove !== "" && !rootView.subCompEditMode
|
||||
enabled: itemsView.importToRemove && !rootView.subCompEditMode
|
||||
onTriggered: rootView.removeImport(itemsView.importToRemove)
|
||||
}
|
||||
|
||||
@@ -184,14 +185,23 @@ Item {
|
||||
StudioControls.Menu {
|
||||
id: itemContextMenu
|
||||
// Workaround for menu item implicit width not properly propagating to menu
|
||||
width: importMenuItem.implicitWidth
|
||||
width: Math.max(importMenuItem.implicitWidth, openSourceItem.implicitWidth)
|
||||
|
||||
StudioControls.MenuItem {
|
||||
id: importMenuItem
|
||||
text: qsTr("Add Module: ") + itemsView.importToAdd
|
||||
enabled: itemsView.importToAdd !== ""
|
||||
visible: itemsView.importToAdd
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: rootView.addImportForItem(itemsView.importToAdd)
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
id: openSourceItem
|
||||
text: qsTr("Go into Component")
|
||||
visible: itemsView.componentSource
|
||||
height: visible ? implicitHeight : 0
|
||||
onTriggered: rootView.goIntoComponent(itemsView.componentSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,8 +333,9 @@ Item {
|
||||
width: styleConstants.cellWidth
|
||||
height: styleConstants.cellHeight
|
||||
onShowContextMenu: {
|
||||
if (!itemUsable) {
|
||||
itemsView.importToAdd = itemRequiredImport
|
||||
if (!itemUsable || itemComponentSource) {
|
||||
itemsView.importToAdd = !itemUsable ? itemRequiredImport : ""
|
||||
itemsView.componentSource = itemComponentSource
|
||||
itemContextMenu.popup()
|
||||
}
|
||||
}
|
||||
@@ -480,8 +491,9 @@ Item {
|
||||
width: styleConstants.cellWidth
|
||||
height: styleConstants.cellHeight
|
||||
onShowContextMenu: {
|
||||
if (!itemUsable) {
|
||||
itemsView.importToAdd = itemRequiredImport
|
||||
if (!itemUsable || itemComponentSource) {
|
||||
itemsView.importToAdd = !itemUsable ? itemRequiredImport : ""
|
||||
itemsView.componentSource = itemComponentSource
|
||||
itemContextMenu.popup()
|
||||
}
|
||||
}
|
||||
|
@@ -32,6 +32,11 @@ MouseArea {
|
||||
|
||||
signal showContextMenu()
|
||||
|
||||
function hide()
|
||||
{
|
||||
tooltipBackend.hideTooltip()
|
||||
}
|
||||
|
||||
onExited: tooltipBackend.hideTooltip()
|
||||
onCanceled: tooltipBackend.hideTooltip()
|
||||
onPositionChanged: tooltipBackend.reposition()
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Custom Button",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_button.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Custom CheckBox",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_checkbox.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Custom Dial",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_dial.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Custom Slider",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_slider.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Custom SpinBox",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_spinbox.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Custom Switch",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_switch.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Flow Item",
|
||||
"trDisplayCategory": "Qt Quick Files",
|
||||
"icon": "flow_item.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Flow View",
|
||||
"trDisplayCategory": "Qt Quick Files",
|
||||
"icon": "flow_view.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Java Script File",
|
||||
"trDisplayCategory": "Java Script",
|
||||
"icon": "file_javascript.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "ListModel",
|
||||
"trDisplayCategory": "QML Files",
|
||||
"icon": "data_listmodel.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Pane",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"icon": "custom_panes.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Qt Quick File",
|
||||
"trDisplayCategory": "Qt Quick Files",
|
||||
"icon": "file_qml.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Qt Quick Views",
|
||||
"trDisplayCategory": "Qt Quick Files",
|
||||
"icon": "data_gridmodel.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -7,7 +7,6 @@
|
||||
"trDisplayName": "Qt Quick UI File",
|
||||
"trDisplayCategory": "Qt Quick Files",
|
||||
"icon": "file_ui.png",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -6,7 +6,6 @@
|
||||
"trDescription": "Creates a UI file (.ui.qml) with a Stacked Layout as the root component.",
|
||||
"trDisplayName": "Stacked Layout",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"icon": "custom_stacked_view.png",
|
||||
"platformIndependent": true,
|
||||
|
||||
|
@@ -6,7 +6,6 @@
|
||||
"trDescription": "Creates a UI file (.ui.qml) with a Swipe View as the root component.",
|
||||
"trDisplayName": "Swipe View",
|
||||
"trDisplayCategory": "Qt Quick Controls",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"icon": "custom_swipe_view.png",
|
||||
"platformIndependent": true,
|
||||
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "desktop_blank.png",
|
||||
"fontIconName": "wizardsGeneric",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "desktop_blank.png",
|
||||
"fontIconName": "wizardsMcuEmpty",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "desktop_blank.png",
|
||||
"fontIconName": "wizardsGeneric",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "desktop_launcher.png",
|
||||
"fontIconName": "wizardsDesktop",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "mobile_scroll.png",
|
||||
"fontIconName": "wizardsMobile",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "mobile_stack.png",
|
||||
"fontIconName": "wizardsMobile",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"icon": "mobile_swipe.png",
|
||||
"fontIconName": "wizardsMobile",
|
||||
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
|
||||
"featuresRequired": [ "QtStudio" ],
|
||||
"platformIndependent": true,
|
||||
|
||||
"options":
|
||||
|
@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@if %{HasTranslation}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
QT -= gui
|
||||
|
||||
CONFIG += c++11 console
|
||||
CONFIG += c++17 console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
project('%{ProjectName}', 'cpp',default_options : ['cpp_std=c++11'], meson_version:'>=0.44')
|
||||
project('%{ProjectName}', 'cpp',default_options : ['cpp_std=c++17'], meson_version:'>=0.44')
|
||||
|
||||
# Documentation: https://mesonbuild.com/Qt5-module.html
|
||||
qt5 = import('qt5')
|
||||
|
@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
@endif
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@if '%{QtModule}' != 'none'
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
project('%{ProjectName}', 'cpp',
|
||||
@if %{IsStatic}
|
||||
default_options : ['cpp_std=c++11', 'default_library=static'],
|
||||
default_options : ['cpp_std=c++17', 'default_library=static'],
|
||||
@else
|
||||
default_options : ['cpp_std=c++11', 'default_library=shared'],
|
||||
default_options : ['cpp_std=c++17', 'default_library=shared'],
|
||||
@endif
|
||||
meson_version:'>=0.48')
|
||||
|
||||
|
@@ -15,7 +15,7 @@ CONFIG += plugin
|
||||
DEFINES += %{LibraryDefine}
|
||||
@endif
|
||||
|
||||
CONFIG += c++11
|
||||
CONFIG += c++17
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
|
@@ -11,7 +11,7 @@ DynamicLibrary {
|
||||
Depends { name: "Qt.%{QtModule}" }
|
||||
@endif
|
||||
|
||||
cpp.cxxLanguageVersion: "c++11"
|
||||
cpp.cxxLanguageVersion: "c++17"
|
||||
cpp.defines: [
|
||||
@if %{IsShared}
|
||||
"%{LibraryDefine}",
|
||||
|
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(%{ProjectName} LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_executable(%{ProjectName} %{CppFileName})
|
||||
|
@@ -1,5 +1,5 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += console c++11
|
||||
CONFIG += console c++17
|
||||
CONFIG -= app_bundle
|
||||
CONFIG -= qt
|
||||
|
||||
|
@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@if %{HasTranslation}
|
||||
|
@@ -8,7 +8,7 @@ set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
@if %{HasTranslation}
|
||||
|
@@ -2,7 +2,7 @@ QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += c++11
|
||||
CONFIG += c++17
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
|
@@ -24,6 +24,12 @@ add_qtc_executable(qtcreator
|
||||
QTC_RUNNABLE
|
||||
)
|
||||
|
||||
extend_qtc_executable(qtcreator
|
||||
CONDITION APPLE
|
||||
SOURCES
|
||||
main_mac.mm
|
||||
)
|
||||
|
||||
if (NOT TARGET qtcreator)
|
||||
return()
|
||||
endif()
|
||||
@@ -86,6 +92,13 @@ if (APPLE)
|
||||
)
|
||||
endif()
|
||||
|
||||
option(QTC_FORCE_XCB "Enables that Qt Creator forces XCB on Linux if QT_QPA_PLATFORM is not set." OFF)
|
||||
extend_qtc_executable(qtcreator
|
||||
CONDITION QTC_FORCE_XCB
|
||||
DEFINES
|
||||
QTC_FORCE_XCB
|
||||
)
|
||||
|
||||
extend_qtc_executable(qtcreator
|
||||
CONDITION BUILD_WITH_CRASHPAD
|
||||
DEFINES
|
||||
|
@@ -500,6 +500,26 @@ int main(int argc, char **argv)
|
||||
qputenv("QT_ENABLE_REGEXP_JIT", "0");
|
||||
}
|
||||
|
||||
#if defined(QTC_FORCE_XCB)
|
||||
if (Utils::HostOsInfo::isLinuxHost() && !qEnvironmentVariableIsSet("QT_QPA_PLATFORM")) {
|
||||
// Enforce XCB on Linux/Gnome, if the user didn't override via QT_QPA_PLATFORM
|
||||
// This was previously done in Qt, but removed in Qt 6.3. We found that bad things can still happen,
|
||||
// like the Wayland session simply crashing when starting Qt Creator.
|
||||
// TODO: Reconsider when Qt/Wayland is reliably working on the supported distributions
|
||||
const bool hasWaylandDisplay = qEnvironmentVariableIsSet("WAYLAND_DISPLAY");
|
||||
const bool isWaylandSessionType = qgetenv("XDG_SESSION_TYPE") == "wayland";
|
||||
const QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
|
||||
const QByteArray sessionDesktop = qgetenv("XDG_SESSION_DESKTOP").toLower();
|
||||
const bool isGnome = currentDesktop.contains("gnome") || sessionDesktop.contains("gnome");
|
||||
const bool isWayland = hasWaylandDisplay || isWaylandSessionType;
|
||||
if (isGnome && isWayland) {
|
||||
qInfo() << "Warning: Ignoring WAYLAND_DISPLAY on Gnome."
|
||||
<< "Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.";
|
||||
qputenv("QT_QPA_PLATFORM", "xcb");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/" + Core::Constants::IDE_CASED_ID + "-XXXXXX");
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
|
38
src/app/main_mac.mm
Normal file
38
src/app/main_mac.mm
Normal 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);
|
Submodule src/libs/qlitehtml updated: 4931b7aa30...1d73f76fac
@@ -28,6 +28,7 @@ import QtCreator.Tracing 1.0
|
||||
import QtQml 2.2
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Controls.Material 2.3
|
||||
|
||||
ScrollView {
|
||||
id: root
|
||||
@@ -315,6 +316,7 @@ ScrollView {
|
||||
|
||||
ComboBox {
|
||||
id: modesMenu
|
||||
width: 260 // TODO: Use implicitContentWidthPolicy (Qt6-only)
|
||||
x: flickable.width - width
|
||||
y: flickable.contentY
|
||||
model: root.modes.map(function(role) { return root.trRoleNames[role] });
|
||||
|
@@ -41,7 +41,7 @@ namespace OsSpecificAspects {
|
||||
inline QString withExecutableSuffix(OsType osType, const QString &executable)
|
||||
{
|
||||
QString finalName = executable;
|
||||
if (osType == OsTypeWindows)
|
||||
if (osType == OsTypeWindows && !finalName.endsWith(QTC_WIN_EXE_SUFFIX))
|
||||
finalName += QLatin1String(QTC_WIN_EXE_SUFFIX);
|
||||
return finalName;
|
||||
}
|
||||
|
@@ -544,7 +544,7 @@ void VariableChooserPrivate::updatePositionAndShow(bool)
|
||||
{
|
||||
if (QWidget *w = q->parentWidget()) {
|
||||
QPoint parentCenter = w->mapToGlobal(w->geometry().center());
|
||||
q->move(parentCenter.x() - q->width()/2, parentCenter.y() - q->height()/2);
|
||||
q->move(parentCenter.x() - q->width()/2, qMax(parentCenter.y() - q->height()/2, 0));
|
||||
}
|
||||
q->show();
|
||||
q->raise();
|
||||
|
@@ -1782,8 +1782,7 @@ void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Loca
|
||||
}
|
||||
|
||||
qCDebug(clangdLog) << "document count is" << refData->fileData.size();
|
||||
if (refData->replacementData || q->versionNumber() < QVersionNumber(13)
|
||||
|| !refData->categorize) {
|
||||
if (refData->replacementData || !refData->categorize) {
|
||||
qCDebug(clangdLog) << "skipping AST retrieval";
|
||||
reportAllSearchResultsAndFinish(*refData);
|
||||
return;
|
||||
@@ -1953,11 +1952,6 @@ void ClangdClient::followSymbol(TextDocument *document,
|
||||
};
|
||||
symbolSupport().findLinkAt(document, adjustedCursor, std::move(gotoDefCallback), true);
|
||||
|
||||
if (versionNumber() < QVersionNumber(12)) {
|
||||
d->followSymbolData->cursorNode.emplace(AstNode());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto astHandler = [this, id = d->followSymbolData->id]
|
||||
(const AstNode &ast, const MessageId &) {
|
||||
qCDebug(clangdLog) << "received ast response for cursor";
|
||||
@@ -2747,6 +2741,11 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
const QList<AstNode> path = getAstPath(ast, range);
|
||||
if (path.size() < 2)
|
||||
return false;
|
||||
if (token.type == "property"
|
||||
&& (path.rbegin()->kind() == "MemberInitializer"
|
||||
|| path.rbegin()->kind() == "CXXConstruct")) {
|
||||
return false;
|
||||
}
|
||||
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
|
||||
if (it->kind() == "Call" || it->kind() == "CXXConstruct"
|
||||
|| it->kind() == "MemberInitializer") {
|
||||
@@ -2859,7 +2858,6 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
styles.mainStyle = C_FIELD;
|
||||
} else if (token.type == "enum") {
|
||||
styles.mainStyle = C_TYPE;
|
||||
styles.mixinStyles.push_back(C_ENUMERATION);
|
||||
} else if (token.type == "enumMember") {
|
||||
styles.mainStyle = C_ENUMERATION;
|
||||
} else if (token.type == "parameter") {
|
||||
@@ -3640,9 +3638,11 @@ void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
|
||||
if (node.kind().endsWith("Literal")) {
|
||||
HighlightingResult result;
|
||||
result.useTextSyles = true;
|
||||
const bool isStringLike = node.kind().startsWith("String")
|
||||
|| node.kind().startsWith("Character");
|
||||
result.textStyles.mainStyle = isStringLike ? C_STRING : C_NUMBER;
|
||||
const bool isKeyword = node.kind() == "CXXBoolLiteral"
|
||||
|| node.kind() == "CXXNullPtrLiteral";
|
||||
const bool isStringLike = !isKeyword && (node.kind().startsWith("String")
|
||||
|| node.kind().startsWith("Character"));
|
||||
result.textStyles.mainStyle = isKeyword ? C_KEYWORD : isStringLike ? C_STRING : C_NUMBER;
|
||||
setResultPosFromRange(result, node.range());
|
||||
insertResult(result);
|
||||
return;
|
||||
|
@@ -260,7 +260,7 @@ void ClangFollowSymbol::switchDeclDef(const CppEditor::CursorInEditor &data,
|
||||
{
|
||||
ClangdClient * const client
|
||||
= ClangModelManagerSupport::instance()->clientForFile(data.filePath());
|
||||
if (client && client->isFullyIndexed() && client->versionNumber() >= QVersionNumber(13)) {
|
||||
if (client && client->isFullyIndexed()) {
|
||||
client->switchDeclDef(data.textDocument(), data.cursor(), data.editorWidget(),
|
||||
std::move(processLinkCallback));
|
||||
return;
|
||||
|
@@ -179,7 +179,6 @@ ClangdTestFindReferences::ClangdTestFindReferences()
|
||||
{
|
||||
setProjectFileName("find-usages.pro");
|
||||
setSourceFileNames({"defs.h", "main.cpp"});
|
||||
setMinimumVersion(13);
|
||||
}
|
||||
|
||||
void ClangdTestFindReferences::initTestCase()
|
||||
@@ -322,7 +321,6 @@ ClangdTestFollowSymbol::ClangdTestFollowSymbol()
|
||||
{
|
||||
setProjectFileName("follow-symbol.pro");
|
||||
setSourceFileNames({"main.cpp", "header.h"});
|
||||
setMinimumVersion(12);
|
||||
}
|
||||
|
||||
void ClangdTestFollowSymbol::test_data()
|
||||
@@ -409,7 +407,6 @@ ClangdTestLocalReferences::ClangdTestLocalReferences()
|
||||
{
|
||||
setProjectFileName("local-references.pro");
|
||||
setSourceFileNames({"references.cpp"});
|
||||
setMinimumVersion(13);
|
||||
}
|
||||
|
||||
// We currently only support local variables, but if and when clangd implements
|
||||
@@ -525,7 +522,6 @@ ClangdTestTooltips::ClangdTestTooltips()
|
||||
{
|
||||
setProjectFileName("tooltips.pro");
|
||||
setSourceFileNames({"tooltips.cpp"});
|
||||
setMinimumVersion(13);
|
||||
}
|
||||
|
||||
void ClangdTestTooltips::test_data()
|
||||
@@ -668,7 +664,6 @@ ClangdTestHighlighting::ClangdTestHighlighting()
|
||||
{
|
||||
setProjectFileName("highlighting.pro");
|
||||
setSourceFileNames({"highlighting.cpp"});
|
||||
setMinimumVersion(13);
|
||||
}
|
||||
|
||||
void ClangdTestHighlighting::initTestCase()
|
||||
@@ -744,11 +739,11 @@ void ClangdTestHighlighting::test_data()
|
||||
QTest::newRow("static member function call") << 114 << 15 << 114 << 27
|
||||
<< QList<int>{C_FUNCTION} << 0;
|
||||
QTest::newRow("enum declaration") << 118 << 6 << 118 << 17
|
||||
<< QList<int>{C_TYPE, C_ENUMERATION, C_DECLARATION} << 0;
|
||||
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
|
||||
QTest::newRow("enumerator declaration") << 120 << 5 << 120 << 15
|
||||
<< QList<int>{C_ENUMERATION, C_DECLARATION} << 0;
|
||||
QTest::newRow("enum in variable declaration") << 125 << 5 << 125 << 16
|
||||
<< QList<int>{C_TYPE, C_ENUMERATION} << 0;
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("enum variable declaration") << 125 << 17 << 125 << 28
|
||||
<< QList<int>{C_LOCAL, C_DECLARATION} << 0;
|
||||
QTest::newRow("enum variable reference") << 127 << 5 << 127 << 16 << QList<int>{C_LOCAL} << 0;
|
||||
@@ -966,7 +961,7 @@ void ClangdTestHighlighting::test_data()
|
||||
<< 310 << 29 << 310 << 38
|
||||
<< QList<int>{C_FIELD} << 0;
|
||||
QTest::newRow("enum declaration with underlying type") << 316 << 6 << 316 << 21
|
||||
<< QList<int>{C_TYPE, C_ENUMERATION, C_DECLARATION} << 0;
|
||||
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
|
||||
QTest::newRow("type in static_cast") << 328 << 23 << 328 << 33
|
||||
<< QList<int>{C_TYPE} << 0;
|
||||
QTest::newRow("opening angle bracket in static_cast") << 328 << 16 << 328 << 17
|
||||
@@ -1293,6 +1288,13 @@ void ClangdTestHighlighting::test_data()
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("const operator()") << 903 << 5 << 903 << 7
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("member initialization: member (user-defined type)") << 911 << 14 << 911 << 18
|
||||
<< QList<int>{C_FIELD} << 0;
|
||||
QTest::newRow("member initialization: member (built-in type)") << 911 << 23 << 911 << 27
|
||||
<< QList<int>{C_FIELD} << 0;
|
||||
QTest::newRow("keywords: true") << 920 << 15 << 920 << 19 << QList<int>{C_KEYWORD} << 0;
|
||||
QTest::newRow("keywords: false") << 921 << 15 << 921 << 20 << QList<int>{C_KEYWORD} << 0;
|
||||
QTest::newRow("keywords: nullptr") << 922 << 15 << 922 << 22 << QList<int>{C_KEYWORD} << 0;
|
||||
}
|
||||
|
||||
void ClangdTestHighlighting::test()
|
||||
@@ -2015,9 +2017,10 @@ void ClangdTestExternalChanges::test()
|
||||
header.close();
|
||||
ClangdClient * const oldClient = client();
|
||||
QVERIFY(oldClient);
|
||||
QVERIFY(!waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
|
||||
&ClangModelManagerSupport::createdClient, timeOutInMs()));
|
||||
waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
|
||||
&ClangModelManagerSupport::createdClient, timeOutInMs());
|
||||
QCOMPARE(client(), oldClient);
|
||||
QCOMPARE(client(), ClangModelManagerSupport::instance()->clientForProject(project()));
|
||||
const TextDocument * const curDoc = document("main.cpp");
|
||||
QVERIFY(curDoc);
|
||||
QVERIFY(curDoc->marks().isEmpty());
|
||||
|
@@ -902,3 +902,22 @@ void callOperators()
|
||||
Callable2 c2;
|
||||
c2();
|
||||
}
|
||||
|
||||
namespace std { template<typename T> struct atomic { atomic(int) {} }; }
|
||||
|
||||
void constructorMemberInitialization()
|
||||
{
|
||||
struct S {
|
||||
S(): m_m1(1), m_m2(0) {}
|
||||
|
||||
std::atomic<int> m_m1;
|
||||
int m_m2;
|
||||
};
|
||||
}
|
||||
|
||||
void keywords()
|
||||
{
|
||||
bool b1 = true;
|
||||
bool b2 = false;
|
||||
void *p = nullptr;
|
||||
}
|
||||
|
@@ -428,6 +428,13 @@ static QIcon interruptIcon(bool toolBarStyle)
|
||||
return toolBarStyle ? iconToolBar : icon;
|
||||
}
|
||||
|
||||
static bool hideAnalyzeMenu()
|
||||
{
|
||||
return Core::ICore::settings()
|
||||
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
|
||||
.toBool();
|
||||
}
|
||||
|
||||
QAction *addAction(const QObject *parent, QMenu *menu, const QString &display, bool on,
|
||||
const std::function<void()> &onTriggered)
|
||||
{
|
||||
@@ -775,7 +782,8 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
|
||||
|
||||
ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR);
|
||||
ActionContainer *mtools = ActionManager::actionContainer(M_TOOLS);
|
||||
menubar->addMenu(mtools, m_menu);
|
||||
if (!hideAnalyzeMenu())
|
||||
menubar->addMenu(mtools, m_menu);
|
||||
|
||||
m_menu->addSeparator(G_ANALYZER_TOOLS);
|
||||
m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS);
|
||||
|
@@ -156,7 +156,8 @@ void OutputCollector::newConnectionAvailable()
|
||||
void OutputCollector::bytesAvailable()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
emit byteDelivery(m_socket->readAll());
|
||||
if (m_socket)
|
||||
emit byteDelivery(m_socket->readAll());
|
||||
#else
|
||||
size_t nbytes = 0;
|
||||
if (::ioctl(m_serverFd, FIONREAD, (char *) &nbytes) < 0)
|
||||
|
@@ -34,7 +34,6 @@ const char ACTION_ID[] = "Docker.Action";
|
||||
const char MENU_ID[] = "Docker.Menu";
|
||||
|
||||
const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType";
|
||||
const char DOCKER_RUN_FLAGS[] = "DockerRunFlags";
|
||||
|
||||
const char DOCKER_BUILDHOST_BUILDSTEP_ID[] = "Docker.BuildStep.BuildHost";
|
||||
|
||||
|
@@ -123,8 +123,6 @@ void DockerDeviceProcess::start()
|
||||
DockerDevice::ConstPtr dockerDevice = qSharedPointerCast<const DockerDevice>(device());
|
||||
QTC_ASSERT(dockerDevice, return);
|
||||
|
||||
const QStringList dockerRunFlags = extraData(Constants::DOCKER_RUN_FLAGS).toStringList();
|
||||
|
||||
connect(this, &DeviceProcess::readyReadStandardOutput, this, [this] {
|
||||
MessageManager::writeSilently(QString::fromLocal8Bit(readAllStandardError()));
|
||||
});
|
||||
|
@@ -105,6 +105,10 @@ Client::Client(BaseClientInterface *clientInterface)
|
||||
connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
|
||||
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
|
||||
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
|
||||
connect(Core::EditorManager::instance(),
|
||||
&Core::EditorManager::documentClosed,
|
||||
this,
|
||||
&Client::documentClosed);
|
||||
|
||||
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
|
||||
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
|
||||
@@ -308,13 +312,11 @@ void Client::initialize()
|
||||
initRequest.setResponseCallback([this](const InitializeRequest::Response &initResponse){
|
||||
initializeCallback(initResponse);
|
||||
});
|
||||
// directly send data otherwise the state check would fail;
|
||||
if (Utils::optional<ResponseHandler> responseHandler = initRequest.responseHandler())
|
||||
m_responseHandlers[responseHandler->id] = responseHandler->callback;
|
||||
|
||||
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage,
|
||||
name(),
|
||||
initRequest.toBaseMessage());
|
||||
// directly send message otherwise the state check of sendContent would fail
|
||||
sendMessage(initRequest.toBaseMessage());
|
||||
m_clientInterface->sendMessage(initRequest.toBaseMessage());
|
||||
m_state = InitializeRequested;
|
||||
}
|
||||
@@ -427,9 +429,7 @@ void Client::sendContent(const IContent &content, SendDocUpdates sendUpdates)
|
||||
QString error;
|
||||
if (!QTC_GUARD(content.isValid(&error)))
|
||||
Core::MessageManager::writeFlashing(error);
|
||||
const BaseMessage message = content.toBaseMessage();
|
||||
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
|
||||
m_clientInterface->sendMessage(message);
|
||||
sendMessage(content.toBaseMessage());
|
||||
}
|
||||
|
||||
void Client::cancelRequest(const MessageId &id)
|
||||
@@ -632,6 +632,12 @@ void Client::deactivateDocument(TextEditor::TextDocument *document)
|
||||
}
|
||||
}
|
||||
|
||||
void Client::documentClosed(Core::IDocument *document)
|
||||
{
|
||||
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
|
||||
closeDocument(textDocument);
|
||||
}
|
||||
|
||||
bool Client::documentOpen(const TextEditor::TextDocument *document) const
|
||||
{
|
||||
return m_openedDocument.contains(const_cast<TextEditor::TextDocument *>(document));
|
||||
@@ -1486,6 +1492,12 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
||||
}
|
||||
}
|
||||
|
||||
void Client::sendMessage(const BaseMessage &message)
|
||||
{
|
||||
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
|
||||
m_clientInterface->sendMessage(message);
|
||||
}
|
||||
|
||||
bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
|
||||
{
|
||||
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
|
||||
@@ -1602,8 +1614,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
|
||||
qDebug() << error;
|
||||
return;
|
||||
}
|
||||
// directly send data otherwise the state check would fail;
|
||||
m_clientInterface->sendMessage(ExitNotification().toBaseMessage());
|
||||
// directly send message otherwise the state check of sendContent would fail
|
||||
sendMessage(ExitNotification().toBaseMessage());
|
||||
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown";
|
||||
m_state = Shutdown;
|
||||
}
|
||||
|
@@ -227,6 +227,7 @@ protected:
|
||||
virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams ¶ms);
|
||||
|
||||
private:
|
||||
void sendMessage(const LanguageServerProtocol::BaseMessage &message);
|
||||
void handleResponse(const LanguageServerProtocol::MessageId &id, const QByteArray &content,
|
||||
QTextCodec *codec);
|
||||
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
|
||||
@@ -252,6 +253,7 @@ private:
|
||||
void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
|
||||
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
|
||||
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
|
||||
void documentClosed(Core::IDocument *document);
|
||||
|
||||
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
|
||||
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}
|
||||
|
@@ -542,11 +542,8 @@ void LanguageClientManager::documentOpened(Core::IDocument *document)
|
||||
|
||||
void LanguageClientManager::documentClosed(Core::IDocument *document)
|
||||
{
|
||||
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document)) {
|
||||
for (Client *client : qAsConst(m_clients))
|
||||
client->closeDocument(textDocument);
|
||||
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
|
||||
m_clientForDocument.remove(textDocument);
|
||||
}
|
||||
}
|
||||
|
||||
void LanguageClientManager::documentContentsSaved(Core::IDocument *document)
|
||||
|
@@ -7,7 +7,7 @@ add_qtc_plugin(McuSupport
|
||||
mcusupport_global.h
|
||||
mcusupportconstants.h
|
||||
mcusupportdevice.cpp mcusupportdevice.h
|
||||
mcusupportoptions.cpp mcusupportoptions.h
|
||||
mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h
|
||||
mcusupportoptionspage.cpp mcusupportoptionspage.h
|
||||
mcupackage.cpp mcupackage.h
|
||||
mcusupportplugin.cpp mcusupportplugin.h
|
||||
@@ -15,4 +15,7 @@ add_qtc_plugin(McuSupport
|
||||
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
|
||||
mcusupportversiondetection.cpp mcusupportversiondetection.h
|
||||
mcusupportcmakemapper.cpp mcusupportcmakemapper.h
|
||||
mcutargetdescription.h
|
||||
)
|
||||
|
||||
add_subdirectory(test)
|
||||
|
76
src/plugins/mcusupport/mcuabstractpackage.h
Normal file
76
src/plugins/mcusupport/mcuabstractpackage.h
Normal 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
|
@@ -38,8 +38,7 @@
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace McuSupport {
|
||||
namespace Internal {
|
||||
namespace McuSupport::Internal {
|
||||
|
||||
static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope)
|
||||
{
|
||||
@@ -144,8 +143,7 @@ McuPackage::Status McuPackage::status() const
|
||||
|
||||
bool McuPackage::validStatus() const
|
||||
{
|
||||
return m_status == McuPackage::ValidPackage
|
||||
|| m_status == McuPackage::ValidPackageMismatchedVersion;
|
||||
return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
|
||||
}
|
||||
|
||||
const QString &McuPackage::environmentVariableName() const
|
||||
@@ -221,11 +219,11 @@ void McuPackage::updateStatus()
|
||||
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|
||||
|| m_versions.contains(m_detectedVersion);
|
||||
|
||||
m_status = validPath
|
||||
? (validPackage ? (validVersion ? ValidPackage : ValidPackageMismatchedVersion)
|
||||
: ValidPathInvalidPackage)
|
||||
: m_path.isEmpty() ? EmptyPath
|
||||
: InvalidPath;
|
||||
m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage
|
||||
: Status::ValidPackageMismatchedVersion)
|
||||
: Status::ValidPathInvalidPackage)
|
||||
: m_path.isEmpty() ? Status::EmptyPath
|
||||
: Status::InvalidPath;
|
||||
|
||||
emit statusChanged();
|
||||
}
|
||||
@@ -233,10 +231,10 @@ void McuPackage::updateStatus()
|
||||
void McuPackage::updateStatusUi()
|
||||
{
|
||||
switch (m_status) {
|
||||
case ValidPackage:
|
||||
case Status::ValidPackage:
|
||||
m_infoLabel->setType(InfoLabel::Ok);
|
||||
break;
|
||||
case ValidPackageMismatchedVersion:
|
||||
case Status::ValidPackageMismatchedVersion:
|
||||
m_infoLabel->setType(InfoLabel::Warning);
|
||||
break;
|
||||
default:
|
||||
@@ -261,7 +259,7 @@ QString McuPackage::statusText() const
|
||||
|
||||
QString response;
|
||||
switch (m_status) {
|
||||
case ValidPackage:
|
||||
case Status::ValidPackage:
|
||||
response = m_detectionPath.isEmpty()
|
||||
? (m_detectedVersion.isEmpty()
|
||||
? tr("Path %1 exists.").arg(displayPackagePath)
|
||||
@@ -270,23 +268,22 @@ QString McuPackage::statusText() const
|
||||
: tr("Path %1 is valid, %2 was found.")
|
||||
.arg(displayPackagePath, displayDetectedPath);
|
||||
break;
|
||||
case ValidPackageMismatchedVersion: {
|
||||
const QString versionWarning
|
||||
= m_versions.size() == 1
|
||||
? tr("but only version %1 is supported").arg(m_versions.first())
|
||||
: tr("but only versions %1 are supported").arg(displayVersions);
|
||||
case Status::ValidPackageMismatchedVersion: {
|
||||
const QString versionWarning = m_versions.size() == 1 ?
|
||||
tr("but only version %1 is supported").arg(m_versions.first()) :
|
||||
tr("but only versions %1 are supported").arg(displayVersions);
|
||||
response = tr("Path %1 is valid, %2 was found, %3.")
|
||||
.arg(displayPackagePath, displayDetectedPath, versionWarning);
|
||||
break;
|
||||
}
|
||||
case ValidPathInvalidPackage:
|
||||
case Status::ValidPathInvalidPackage:
|
||||
response = tr("Path %1 exists, but does not contain %2.")
|
||||
.arg(displayPackagePath, displayRequiredPath);
|
||||
break;
|
||||
case InvalidPath:
|
||||
case Status::InvalidPath:
|
||||
response = tr("Path %1 does not exist.").arg(displayPackagePath);
|
||||
break;
|
||||
case EmptyPath:
|
||||
case Status::EmptyPath:
|
||||
response = m_detectionPath.isEmpty()
|
||||
? tr("Path is empty.")
|
||||
: tr("Path is empty, %1 not found.").arg(displayRequiredPath);
|
||||
@@ -316,5 +313,4 @@ bool McuToolChainPackage::isDesktopToolchain() const
|
||||
return m_type == Type::MSVC || m_type == Type::GCC;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace McuSupport
|
||||
} // namespace McuSupport::Internal
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mcuabstractpackage.h"
|
||||
#include "mcusupportversiondetection.h"
|
||||
|
||||
#include <utils/filepath.h>
|
||||
@@ -46,19 +47,11 @@ class InfoLabel;
|
||||
namespace McuSupport {
|
||||
namespace Internal {
|
||||
|
||||
class McuPackage : public QObject
|
||||
class McuPackage : public McuAbstractPackage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Status {
|
||||
EmptyPath,
|
||||
InvalidPath,
|
||||
ValidPathInvalidPackage,
|
||||
ValidPackageMismatchedVersion,
|
||||
ValidPackage
|
||||
};
|
||||
|
||||
McuPackage(const QString &label,
|
||||
const Utils::FilePath &defaultPath,
|
||||
const QString &detectionPath,
|
||||
@@ -66,31 +59,32 @@ public:
|
||||
const QString &envVarName = {},
|
||||
const QString &downloadUrl = {},
|
||||
const McuPackageVersionDetector *versionDetector = nullptr);
|
||||
virtual ~McuPackage() = default;
|
||||
~McuPackage() override = default;
|
||||
|
||||
Utils::FilePath basePath() const;
|
||||
Utils::FilePath path() const;
|
||||
QString label() const;
|
||||
Utils::FilePath defaultPath() const;
|
||||
QString detectionPath() const;
|
||||
QString statusText() const;
|
||||
void updateStatus();
|
||||
Utils::FilePath basePath() const override;
|
||||
Utils::FilePath path() const override;
|
||||
QString label() const override;
|
||||
Utils::FilePath defaultPath() const override;
|
||||
QString detectionPath() const override;
|
||||
QString statusText() const override;
|
||||
void updateStatus() override;
|
||||
|
||||
Status status() const;
|
||||
bool validStatus() const;
|
||||
void setAddToPath(bool addToPath);
|
||||
bool addToPath() const;
|
||||
void writeGeneralSettings() const;
|
||||
bool writeToSettings() const;
|
||||
void setRelativePathModifier(const QString &path);
|
||||
void setVersions(const QStringList &versions);
|
||||
Status status() const override;
|
||||
bool validStatus() const override;
|
||||
void setAddToPath(bool addToPath) override;
|
||||
bool addToPath() const override;
|
||||
void writeGeneralSettings() const override;
|
||||
bool writeToSettings() const override;
|
||||
void setRelativePathModifier(const QString &path) override;
|
||||
void setVersions(const QStringList &versions) override;
|
||||
|
||||
bool automaticKitCreationEnabled() const;
|
||||
void setAutomaticKitCreationEnabled(const bool enabled);
|
||||
//TODO(piotr.mucko): Why every package knows about automatic kit creation. This should be outside of this class.
|
||||
bool automaticKitCreationEnabled() const override;
|
||||
void setAutomaticKitCreationEnabled(const bool enabled) override;
|
||||
|
||||
QWidget *widget();
|
||||
QWidget *widget() override;
|
||||
|
||||
const QString &environmentVariableName() const;
|
||||
const QString &environmentVariableName() const override;
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
@@ -119,7 +113,7 @@ private:
|
||||
bool m_addToPath = false;
|
||||
bool m_automaticKitCreation = true;
|
||||
|
||||
Status m_status = InvalidPath;
|
||||
Status m_status = Status::InvalidPath;
|
||||
};
|
||||
|
||||
class McuToolChainPackage : public McuPackage
|
||||
|
@@ -15,6 +15,7 @@ QtcPlugin {
|
||||
Depends { name: "QtSupport" }
|
||||
|
||||
files: [
|
||||
"mcuabstractpackage.h",
|
||||
"mcupackage.cpp",
|
||||
"mcupackage.h",
|
||||
"mcusupport.qrc",
|
||||
@@ -36,6 +37,7 @@ QtcPlugin {
|
||||
"mcusupportversiondetection.h",
|
||||
"mcusupportcmakemapper.h",
|
||||
"mcusupportcmakemapper.cpp",
|
||||
"mcutargetdescription.h",
|
||||
"mcukitinformation.cpp",
|
||||
"mcukitinformation.h"
|
||||
]
|
||||
|
@@ -66,6 +66,8 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QVariant>
|
||||
|
||||
using CMakeProjectManager::CMakeConfigItem;
|
||||
using CMakeProjectManager::CMakeConfigurationKitAspect;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
@@ -81,22 +83,6 @@ static bool kitNeedsQtVersion()
|
||||
return !HostOsInfo::isWindowsHost();
|
||||
}
|
||||
|
||||
static void remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
|
||||
{
|
||||
using namespace CMakeProjectManager;
|
||||
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
|
||||
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
|
||||
|
||||
// First filter out all Qul2.x CMake vars
|
||||
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
|
||||
[&](const auto &configItem) {
|
||||
return !cmakeVarNames.contains(configItem.key);
|
||||
});
|
||||
// Then append them with new values
|
||||
config.append(cmakeVars);
|
||||
CMakeConfigurationKitAspect::setConfiguration(kit, config);
|
||||
}
|
||||
|
||||
static ToolChain *msvcToolChain(Id language)
|
||||
{
|
||||
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
|
||||
@@ -275,7 +261,7 @@ QVariant McuToolChainPackage::debuggerId() const
|
||||
McuTarget::McuTarget(const QVersionNumber &qulVersion,
|
||||
const Platform &platform,
|
||||
OS os,
|
||||
const QVector<McuPackage *> &packages,
|
||||
const QVector<McuAbstractPackage *> &packages,
|
||||
const McuToolChainPackage *toolChainPackage,
|
||||
int colorDepth)
|
||||
: m_qulVersion(qulVersion)
|
||||
@@ -286,7 +272,7 @@ McuTarget::McuTarget(const QVersionNumber &qulVersion,
|
||||
, m_colorDepth(colorDepth)
|
||||
{}
|
||||
|
||||
const QVector<McuPackage *> &McuTarget::packages() const
|
||||
const QVector<McuAbstractPackage *> &McuTarget::packages() const
|
||||
{
|
||||
return m_packages;
|
||||
}
|
||||
@@ -308,7 +294,7 @@ const McuTarget::Platform &McuTarget::platform() const
|
||||
|
||||
bool McuTarget::isValid() const
|
||||
{
|
||||
return Utils::allOf(packages(), [](McuPackage *package) {
|
||||
return Utils::allOf(packages(), [](McuAbstractPackage *package) {
|
||||
package->updateStatus();
|
||||
return package->validStatus();
|
||||
});
|
||||
@@ -318,18 +304,20 @@ void McuTarget::printPackageProblems() const
|
||||
{
|
||||
for (auto package : packages()) {
|
||||
package->updateStatus();
|
||||
if (!package->validStatus())
|
||||
if (!package->validStatus()) {
|
||||
printMessage(tr("Error creating kit for target %1, package %2: %3")
|
||||
.arg(McuSupportOptions::kitName(this),
|
||||
package->label(),
|
||||
package->statusText()),
|
||||
true);
|
||||
if (package->status() == McuPackage::ValidPackageMismatchedVersion)
|
||||
}
|
||||
if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) {
|
||||
printMessage(tr("Warning creating kit for target %1, package %2: %3")
|
||||
.arg(McuSupportOptions::kitName(this),
|
||||
package->label(),
|
||||
package->statusText()),
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +344,7 @@ McuSupportOptions::McuSupportOptions(QObject *parent)
|
||||
, qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
|
||||
{
|
||||
connect(qtForMCUsSdkPackage,
|
||||
&McuPackage::changed,
|
||||
&McuAbstractPackage::changed,
|
||||
this,
|
||||
&McuSupportOptions::populatePackagesAndTargets);
|
||||
}
|
||||
@@ -425,7 +413,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir)
|
||||
if (qtForMCUsSdkPackage->validStatus())
|
||||
Sdk::targetsAndPackages(dir, &sdkRepository);
|
||||
for (const auto &package : qAsConst(sdkRepository.packages))
|
||||
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
|
||||
connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::changed);
|
||||
|
||||
emit changed();
|
||||
}
|
||||
@@ -469,6 +457,22 @@ static void setKitProperties(const QString &kitName,
|
||||
k->setIrrelevantAspects(irrelevant);
|
||||
}
|
||||
|
||||
void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
|
||||
{
|
||||
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
|
||||
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
|
||||
|
||||
// First filter out all Qul2.x CMake vars
|
||||
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
|
||||
[&](const auto &configItem) {
|
||||
return !cmakeVarNames.contains(configItem.key);
|
||||
});
|
||||
// Then append them with new values
|
||||
config.append(cmakeVars);
|
||||
CMakeConfigurationKitAspect::setConfiguration(kit, config);
|
||||
}
|
||||
|
||||
|
||||
static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
|
||||
{
|
||||
switch (tcPackage->type()) {
|
||||
@@ -541,9 +545,9 @@ static bool expectsCmakeVars(const McuTarget *mcuTarget)
|
||||
return mcuTarget->qulVersion() >= QVersionNumber{2, 0};
|
||||
}
|
||||
|
||||
static void setKitEnvironment(Kit *k,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage)
|
||||
void McuSupportOptions::setKitEnvironment(Kit *k,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage)
|
||||
{
|
||||
EnvironmentItems changes;
|
||||
QStringList pathAdditions;
|
||||
@@ -555,7 +559,7 @@ static void setKitEnvironment(Kit *k,
|
||||
&& !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi())
|
||||
pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput());
|
||||
|
||||
auto processPackage = [&pathAdditions, &changes](const McuPackage *package) {
|
||||
auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) {
|
||||
if (package->addToPath())
|
||||
pathAdditions.append(package->path().toUserOutput());
|
||||
if (!package->environmentVariableName().isEmpty())
|
||||
@@ -578,7 +582,7 @@ static void setKitEnvironment(Kit *k,
|
||||
|
||||
// Hack, this problem should be solved in lower layer
|
||||
if (expectsCmakeVars(mcuTarget)) {
|
||||
remapQul2xCmakeVars(k, changes);
|
||||
McuSupportOptions::remapQul2xCmakeVars(k, changes);
|
||||
}
|
||||
|
||||
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
|
||||
@@ -586,11 +590,11 @@ static void setKitEnvironment(Kit *k,
|
||||
|
||||
static void setKitDependencies(Kit *k,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage)
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage)
|
||||
{
|
||||
NameValueItems dependencies;
|
||||
|
||||
auto processPackage = [&dependencies](const McuPackage *package) {
|
||||
auto processPackage = [&dependencies](const McuAbstractPackage *package) {
|
||||
if (!package->environmentVariableName().isEmpty())
|
||||
dependencies.append({package->environmentVariableName(),
|
||||
QDir::toNativeSeparators(package->detectionPath())});
|
||||
@@ -606,7 +610,7 @@ static void setKitDependencies(Kit *k,
|
||||
k->setIrrelevantAspects(irrelevant);
|
||||
}
|
||||
|
||||
static void updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
|
||||
void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
|
||||
{
|
||||
EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k);
|
||||
for (auto package : mcuTarget->packages()) {
|
||||
@@ -741,7 +745,7 @@ QList<Kit *> McuSupportOptions::existingKits(const McuTarget *mcuTarget)
|
||||
}
|
||||
|
||||
QList<Kit *> McuSupportOptions::matchingKits(const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage)
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage)
|
||||
{
|
||||
return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
|
||||
return kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
|
||||
@@ -749,7 +753,7 @@ QList<Kit *> McuSupportOptions::matchingKits(const McuTarget *mcuTarget,
|
||||
}
|
||||
|
||||
QList<Kit *> McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage)
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage)
|
||||
{
|
||||
return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
|
||||
return !kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
|
||||
@@ -761,10 +765,9 @@ QList<Kit *> McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget *
|
||||
return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) {
|
||||
const auto environment = Utils::NameValueDictionary(
|
||||
Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit)));
|
||||
return Utils::anyOf(mcuTarget->packages(), [&environment](const McuPackage *package) {
|
||||
return !package->environmentVariableName().isEmpty()
|
||||
&& environment.value(package->environmentVariableName())
|
||||
!= package->path().toUserOutput();
|
||||
return Utils::anyOf(mcuTarget->packages(), [&environment](const McuAbstractPackage *package) {
|
||||
return !package->environmentVariableName().isEmpty() &&
|
||||
environment.value(package->environmentVariableName()) != package->path().toUserOutput();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -783,7 +786,7 @@ void McuSupportOptions::removeOutdatedKits()
|
||||
KitManager::deregisterKit(kit);
|
||||
}
|
||||
|
||||
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk)
|
||||
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk)
|
||||
{
|
||||
const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) {
|
||||
KitGuard kitGuard(k);
|
||||
@@ -831,7 +834,7 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName)
|
||||
|
||||
bool McuSupportOptions::kitUpToDate(const Kit *kit,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage)
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage)
|
||||
{
|
||||
return kitQulVersion(kit) == mcuTarget->qulVersion()
|
||||
&& kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput()
|
||||
@@ -873,22 +876,22 @@ void McuSupportOptions::createAutomaticKits()
|
||||
qtForMCUsPackage->updateStatus();
|
||||
if (!qtForMCUsPackage->validStatus()) {
|
||||
switch (qtForMCUsPackage->status()) {
|
||||
case McuPackage::ValidPathInvalidPackage: {
|
||||
const QString displayPath
|
||||
= FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput();
|
||||
case McuAbstractPackage::Status::ValidPathInvalidPackage: {
|
||||
const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath())
|
||||
.toUserOutput();
|
||||
printMessage(tr("Path %1 exists, but does not contain %2.")
|
||||
.arg(qtForMCUsPackage->path().toUserOutput(), displayPath),
|
||||
true);
|
||||
break;
|
||||
}
|
||||
case McuPackage::InvalidPath: {
|
||||
case McuAbstractPackage::Status::InvalidPath: {
|
||||
printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > "
|
||||
"Devices > MCU.")
|
||||
.arg(qtForMCUsPackage->path().toUserOutput()),
|
||||
true);
|
||||
break;
|
||||
}
|
||||
case McuPackage::EmptyPath: {
|
||||
case McuAbstractPackage::Status::EmptyPath: {
|
||||
printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.")
|
||||
.arg(qtForMCUsPackage->detectionPath()),
|
||||
true);
|
||||
@@ -984,7 +987,7 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption)
|
||||
|
||||
void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdk)
|
||||
const McuAbstractPackage *qtForMCUsSdk)
|
||||
{
|
||||
setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path());
|
||||
setKitEnvironment(kit, mcuTarget, qtForMCUsSdk);
|
||||
@@ -1000,7 +1003,7 @@ void McuSupportOptions::fixKitsDependencies()
|
||||
Sdk::targetsAndPackages(dir, &repo);
|
||||
for (const auto &target : qAsConst(repo.mcuTargets)) {
|
||||
if (target->isValid()) {
|
||||
for (auto kit : kitsWithMismatchedDependencies(target)) {
|
||||
for (auto* kit : kitsWithMismatchedDependencies(target)) {
|
||||
updateKitEnvironment(kit, target);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021
|
||||
** The Qt Company Ltd.
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
@@ -26,8 +25,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mcusupport_global.h"
|
||||
|
||||
#include <utils/environmentfwd.h>
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QVersionNumber>
|
||||
@@ -48,7 +46,7 @@ class ToolChain;
|
||||
namespace McuSupport {
|
||||
namespace Internal {
|
||||
|
||||
class McuPackage;
|
||||
class McuAbstractPackage;
|
||||
class McuToolChainPackage;
|
||||
|
||||
void printMessage(const QString &message, bool important);
|
||||
@@ -72,12 +70,12 @@ public:
|
||||
McuTarget(const QVersionNumber &qulVersion,
|
||||
const Platform &platform,
|
||||
OS os,
|
||||
const QVector<McuPackage *> &packages,
|
||||
const QVector<McuAbstractPackage *> &packages,
|
||||
const McuToolChainPackage *toolChainPackage,
|
||||
int colorDepth = UnspecifiedColorDepth);
|
||||
|
||||
const QVersionNumber &qulVersion() const;
|
||||
const QVector<McuPackage *> &packages() const;
|
||||
const QVector<McuAbstractPackage *> &packages() const;
|
||||
const McuToolChainPackage *toolChainPackage() const;
|
||||
const Platform &platform() const;
|
||||
OS os() const;
|
||||
@@ -89,15 +87,15 @@ private:
|
||||
const QVersionNumber m_qulVersion;
|
||||
const Platform m_platform;
|
||||
const OS m_os;
|
||||
const QVector<McuPackage *> m_packages;
|
||||
const QVector<McuAbstractPackage *> m_packages;
|
||||
const McuToolChainPackage *m_toolChainPackage;
|
||||
const int m_colorDepth;
|
||||
};
|
||||
}; // class McuTarget
|
||||
|
||||
class McuSdkRepository
|
||||
{
|
||||
public:
|
||||
QVector<McuPackage *> packages;
|
||||
QVector<McuAbstractPackage *> packages;
|
||||
QVector<McuTarget *> mcuTargets;
|
||||
|
||||
void deletePackagesAndTargets();
|
||||
@@ -110,32 +108,34 @@ class McuSupportOptions : public QObject
|
||||
public:
|
||||
enum UpgradeOption { Ignore, Keep, Replace };
|
||||
|
||||
McuSupportOptions(QObject *parent = nullptr);
|
||||
explicit McuSupportOptions(QObject *parent = nullptr);
|
||||
~McuSupportOptions() override;
|
||||
|
||||
McuPackage *qtForMCUsSdkPackage = nullptr;
|
||||
McuAbstractPackage *qtForMCUsSdkPackage = nullptr;
|
||||
McuSdkRepository sdkRepository;
|
||||
|
||||
void setQulDir(const Utils::FilePath &dir);
|
||||
static void setKitEnvironment(ProjectExplorer::Kit *, const McuTarget *, const McuAbstractPackage *);
|
||||
static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *);
|
||||
static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &);
|
||||
static Utils::FilePath qulDirFromSettings();
|
||||
|
||||
static QString kitName(const McuTarget *mcuTarget);
|
||||
|
||||
static QList<ProjectExplorer::Kit *> existingKits(const McuTarget *mcuTarget);
|
||||
static QList<ProjectExplorer::Kit *> matchingKits(const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage);
|
||||
static QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage);
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage);
|
||||
static QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage);
|
||||
static QList<ProjectExplorer::Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget);
|
||||
static QList<ProjectExplorer::Kit *> outdatedKits();
|
||||
static void removeOutdatedKits();
|
||||
static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk);
|
||||
static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk);
|
||||
static void createAutomaticKits();
|
||||
static UpgradeOption askForKitUpgrades();
|
||||
static void upgradeKits(UpgradeOption upgradeOption);
|
||||
static void upgradeKitInPlace(ProjectExplorer::Kit *kit,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdk);
|
||||
const McuAbstractPackage *qtForMCUsSdk);
|
||||
static void fixKitsDependencies();
|
||||
void checkUpgradeableKits();
|
||||
static void fixExistingKits();
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit);
|
||||
static bool kitUpToDate(const ProjectExplorer::Kit *kit,
|
||||
const McuTarget *mcuTarget,
|
||||
const McuPackage *qtForMCUsSdkPackage);
|
||||
const McuAbstractPackage *qtForMCUsSdkPackage);
|
||||
|
||||
private:
|
||||
void deletePackagesAndTargets();
|
||||
|
@@ -121,10 +121,8 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
|
||||
&QComboBox::currentTextChanged,
|
||||
this,
|
||||
&McuSupportOptionsWidget::showMcuTargetPackages);
|
||||
connect(m_options.qtForMCUsSdkPackage,
|
||||
&McuPackage::changed,
|
||||
this,
|
||||
&McuSupportOptionsWidget::populateMcuTargetsComboBox);
|
||||
connect(m_options.qtForMCUsSdkPackage, &McuAbstractPackage::changed,
|
||||
this, &McuSupportOptionsWidget::populateMcuTargetsComboBox);
|
||||
}
|
||||
|
||||
{
|
||||
|
@@ -31,6 +31,10 @@
|
||||
#include "mcusupportoptionspage.h"
|
||||
#include "mcusupportrunconfiguration.h"
|
||||
|
||||
#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND)
|
||||
#include "test/unittest.h"
|
||||
#endif
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -59,14 +63,9 @@ public:
|
||||
{Constants::RUNCONFIGURATION}};
|
||||
McuSupportOptionsPage optionsPage;
|
||||
McuDependenciesKitAspect environmentPathsKitAspect;
|
||||
};
|
||||
}; // class McuSupportPluginPrivate
|
||||
|
||||
static McuSupportPluginPrivate *dd = nullptr;
|
||||
|
||||
McuSupportPlugin::McuSupportPlugin()
|
||||
{
|
||||
setObjectName("McuSupportPlugin");
|
||||
}
|
||||
static McuSupportPluginPrivate* dd{nullptr};
|
||||
|
||||
McuSupportPlugin::~McuSupportPlugin()
|
||||
{
|
||||
@@ -79,6 +78,7 @@ bool McuSupportPlugin::initialize(const QStringList &arguments, QString *errorSt
|
||||
Q_UNUSED(arguments)
|
||||
Q_UNUSED(errorString)
|
||||
|
||||
setObjectName("McuSupportPlugin");
|
||||
dd = new McuSupportPluginPrivate;
|
||||
|
||||
McuSupportOptions::registerQchFiles();
|
||||
@@ -147,5 +147,14 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade()
|
||||
ICore::infoBar()->addInfo(info);
|
||||
}
|
||||
|
||||
QVector<QObject *> McuSupportPlugin::createTestObjects() const
|
||||
{
|
||||
QVector<QObject *> tests;
|
||||
#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND)
|
||||
tests << new Test::McuSupportTest;
|
||||
#endif
|
||||
return tests;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace McuSupport
|
||||
|
@@ -29,23 +29,25 @@
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
namespace McuSupport {
|
||||
namespace Internal {
|
||||
namespace McuSupport::Internal {
|
||||
|
||||
class McuSupportPlugin : public ExtensionSystem::IPlugin
|
||||
class McuSupportPlugin final : public ExtensionSystem::IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "McuSupport.json")
|
||||
|
||||
public:
|
||||
McuSupportPlugin();
|
||||
~McuSupportPlugin() override;
|
||||
~McuSupportPlugin() final;
|
||||
|
||||
bool initialize(const QStringList &arguments, QString *errorString) final;
|
||||
void extensionsInitialized() final;
|
||||
|
||||
bool initialize(const QStringList &arguments, QString *errorString) override;
|
||||
void extensionsInitialized() override;
|
||||
static void askUserAboutMcuSupportKitsSetup();
|
||||
static void askUserAboutMcuSupportKitsUpgrade();
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace McuSupport
|
||||
private:
|
||||
QVector<QObject *> createTestObjects() const final;
|
||||
|
||||
}; // class McuSupportPlugin
|
||||
|
||||
} // namespace McuSupport::Internal
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "mcusupportconstants.h"
|
||||
#include "mcusupportoptions.h"
|
||||
#include "mcusupportversiondetection.h"
|
||||
#include "mcutargetdescription.h"
|
||||
|
||||
#include <baremetal/baremetalconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -330,40 +331,6 @@ static McuPackage *createRenesasProgrammerPackage()
|
||||
envVar);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct McuTargetDescription
|
||||
{
|
||||
enum class TargetType { MCU, Desktop };
|
||||
|
||||
QString qulVersion;
|
||||
QString compatVersion;
|
||||
struct
|
||||
{
|
||||
QString id;
|
||||
QString name;
|
||||
QString vendor;
|
||||
QVector<int> colorDepths;
|
||||
TargetType type;
|
||||
} platform;
|
||||
struct
|
||||
{
|
||||
QString id;
|
||||
QStringList versions;
|
||||
} toolchain;
|
||||
struct
|
||||
{
|
||||
QString name;
|
||||
QString defaultPath;
|
||||
QString envVar;
|
||||
QStringList versions;
|
||||
} boardSdk;
|
||||
struct
|
||||
{
|
||||
QString envVar;
|
||||
QString boardSdkSubDir;
|
||||
} freeRTOS;
|
||||
};
|
||||
|
||||
static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar)
|
||||
{
|
||||
if (envVar.startsWith("EVK"))
|
||||
@@ -463,9 +430,9 @@ struct McuTargetFactory
|
||||
return createTargetsImpl(description);
|
||||
}
|
||||
|
||||
QVector<McuPackage *> getMcuPackages() const
|
||||
QVector<McuAbstractPackage *> getMcuPackages() const
|
||||
{
|
||||
QVector<McuPackage *> packages;
|
||||
QVector<McuAbstractPackage *> packages;
|
||||
for (auto *package : qAsConst(boardSdkPkgs))
|
||||
packages.append(package);
|
||||
for (auto *package : qAsConst(freeRTOSPkgs))
|
||||
@@ -483,7 +450,7 @@ protected:
|
||||
tcPkg = createUnsupportedToolChainPackage();
|
||||
for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
|
||||
for (int colorDepth : desc.platform.colorDepths) {
|
||||
QVector<McuPackage *> required3rdPartyPkgs = {tcPkg};
|
||||
QVector<McuAbstractPackage *> required3rdPartyPkgs = {tcPkg};
|
||||
if (vendorPkgs.contains(desc.platform.vendor))
|
||||
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
|
||||
|
||||
@@ -566,7 +533,7 @@ protected:
|
||||
} else
|
||||
tcPkg = createUnsupportedToolChainPackage();
|
||||
for (int colorDepth : desc.platform.colorDepths) {
|
||||
QVector<McuPackage *> required3rdPartyPkgs;
|
||||
QVector<McuAbstractPackage *> required3rdPartyPkgs;
|
||||
// Desktop toolchains don't need any additional settings
|
||||
if (tcPkg && !tcPkg->isDesktopToolchain()
|
||||
&& tcPkg->type() != McuToolChainPackage::Type::Unsupported)
|
||||
@@ -620,10 +587,10 @@ private:
|
||||
|
||||
QHash<QString, McuPackage *> boardSdkPkgs;
|
||||
QHash<QString, McuPackage *> freeRTOSPkgs;
|
||||
};
|
||||
}; // struct McuTargetFactory
|
||||
|
||||
static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
|
||||
QVector<McuPackage *> *packages)
|
||||
QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
|
||||
QVector<McuAbstractPackage *> *packages)
|
||||
{
|
||||
const QHash<QString, McuToolChainPackage *> tcPkgs = {
|
||||
{{"armgcc"}, createArmGccPackage()},
|
||||
@@ -652,8 +619,10 @@ static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescrip
|
||||
}
|
||||
|
||||
packages->append(
|
||||
Utils::transform<QVector<McuPackage *>>(tcPkgs.values(),
|
||||
[&](McuToolChainPackage *tcPkg) { return tcPkg; }));
|
||||
Utils::transform<QVector<McuAbstractPackage *>>(tcPkgs.values(),
|
||||
[&](McuToolChainPackage *tcPkg) {
|
||||
return tcPkg;
|
||||
}));
|
||||
for (auto *package : vendorPkgs)
|
||||
packages->append(package);
|
||||
packages->append(targetFactory.getMcuPackages());
|
||||
@@ -755,7 +724,7 @@ static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion,
|
||||
return description;
|
||||
}
|
||||
|
||||
static McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
||||
McuTargetDescription parseDescriptionJson(const QByteArray &data)
|
||||
{
|
||||
const QJsonDocument document = QJsonDocument::fromJson(data);
|
||||
const QJsonObject target = document.object();
|
||||
|
@@ -33,18 +33,26 @@
|
||||
namespace McuSupport {
|
||||
namespace Internal {
|
||||
|
||||
#define MAX_COMPATIBILITY_VERSION 1
|
||||
constexpr int MAX_COMPATIBILITY_VERSION {1};
|
||||
|
||||
class McuSdkRepository;
|
||||
class McuAbstractPackage;
|
||||
class McuPackage;
|
||||
class McuTarget;
|
||||
|
||||
namespace Sdk {
|
||||
|
||||
struct McuTargetDescription;
|
||||
|
||||
McuPackage *createQtForMCUsPackage();
|
||||
|
||||
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
|
||||
|
||||
void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo);
|
||||
|
||||
McuTargetDescription parseDescriptionJson(const QByteArray &);
|
||||
QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &, QVector<McuAbstractPackage *> *);
|
||||
|
||||
Utils::FilePath kitsPath(const Utils::FilePath &dir);
|
||||
|
||||
Utils::FilePath packagePathFromSettings(const QString &settingsKey,
|
||||
|
67
src/plugins/mcusupport/mcutargetdescription.h
Normal file
67
src/plugins/mcusupport/mcutargetdescription.h
Normal 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
|
13
src/plugins/mcusupport/test/CMakeLists.txt
Normal file
13
src/plugins/mcusupport/test/CMakeLists.txt
Normal 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()
|
93
src/plugins/mcusupport/test/nxp_1064_json.h
Normal file
93
src/plugins/mcusupport/test/nxp_1064_json.h
Normal 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"]
|
||||
}
|
||||
})";
|
63
src/plugins/mcusupport/test/packagemock.h
Normal file
63
src/plugins/mcusupport/test/packagemock.h
Normal 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
|
98
src/plugins/mcusupport/test/unittest.cpp
Normal file
98
src/plugins/mcusupport/test/unittest.cpp
Normal 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
|
82
src/plugins/mcusupport/test/unittest.h
Normal file
82
src/plugins/mcusupport/test/unittest.h
Normal 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
|
@@ -1110,6 +1110,10 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
||||
<< ("*-*-*-*-" + compilerName
|
||||
+ "-[1-9]*"); // "x86_64-pc-linux-gnu-gcc-7.4.1"
|
||||
}
|
||||
nameFilters = transform(nameFilters,
|
||||
[os = device ? device->osType() : HostOsInfo::hostOs()](const QString &baseName) {
|
||||
return OsSpecificAspects::withExecutableSuffix(os, baseName);
|
||||
});
|
||||
|
||||
FilePaths compilerPaths;
|
||||
|
||||
@@ -1145,9 +1149,6 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
||||
for (const FilePath &dir : qAsConst(searchPaths)) {
|
||||
static const QRegularExpression regexp(binaryRegexp);
|
||||
QDir binDir(dir.toString());
|
||||
nameFilters = transform(nameFilters, [](const QString &baseName) {
|
||||
return HostOsInfo::withExecutableSuffix(baseName);
|
||||
});
|
||||
const QStringList fileNames = binDir.entryList(nameFilters,
|
||||
QDir::Files | QDir::Executable);
|
||||
for (const QString &fileName : fileNames) {
|
||||
|
@@ -166,8 +166,8 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
|
||||
QPair<FilePath, int> position = parseFileName(match.captured(1));
|
||||
const FilePath filePath = absoluteFilePath(position.first);
|
||||
LinkSpecs linkSpecs;
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
|
||||
if (!m_lastTask.isNull() && line.contains("note: ")) {
|
||||
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
|
||||
const int offset = std::accumulate(m_lastTask.details.cbegin(),
|
||||
m_lastTask.details.cend(), 0,
|
||||
[](int total, const QString &line) { return total + line.length() + 1;});
|
||||
@@ -181,6 +181,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
|
||||
m_lastTask = CompileTask(taskType(match.captured(2)),
|
||||
match.captured(3) + match.captured(4).trimmed(), // description
|
||||
filePath, position.second);
|
||||
m_linkSpecs << linkSpecs;
|
||||
m_lines = 1;
|
||||
}
|
||||
return {Status::InProgress, linkSpecs};
|
||||
|
@@ -314,6 +314,16 @@ static const RunConfiguration *runConfigForNode(const Target *target, const Proj
|
||||
return target->activeRunConfiguration();
|
||||
}
|
||||
|
||||
static bool hideBuildMenu()
|
||||
{
|
||||
return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_BUILD, false).toBool();
|
||||
}
|
||||
|
||||
static bool hideDebugMenu()
|
||||
{
|
||||
return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_DEBUG, false).toBool();
|
||||
}
|
||||
|
||||
static bool canOpenTerminalWithRunEnv(const Project *project, const ProjectNode *node)
|
||||
{
|
||||
if (!project)
|
||||
@@ -938,14 +948,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
||||
// build menu
|
||||
ActionContainer *mbuild =
|
||||
ActionManager::createMenu(Constants::M_BUILDPROJECT);
|
||||
|
||||
mbuild->menu()->setTitle(tr("&Build"));
|
||||
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
|
||||
if (!hideBuildMenu())
|
||||
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
|
||||
|
||||
// debug menu
|
||||
ActionContainer *mdebug =
|
||||
ActionManager::createMenu(Constants::M_DEBUG);
|
||||
mdebug->menu()->setTitle(tr("&Debug"));
|
||||
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
|
||||
if (!hideDebugMenu())
|
||||
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
|
||||
|
||||
ActionContainer *mstartdebugging =
|
||||
ActionManager::createMenu(Constants::M_DEBUG_STARTDEBUGGING);
|
||||
|
@@ -235,6 +235,9 @@ const char ADD_FILES_DIALOG_FILTER_HISTORY_KEY[] = "ProjectExplorer.AddFilesFilt
|
||||
const char PROJECT_ROOT_PATH_KEY[] = "ProjectExplorer.Project.RootPath";
|
||||
const char STARTUPSESSION_KEY[] = "ProjectExplorer/SessionToRestore";
|
||||
const char LASTSESSION_KEY[] = "ProjectExplorer/StartupSession";
|
||||
const char SETTINGS_MENU_HIDE_BUILD[] = "Menu/HideBuild";
|
||||
const char SETTINGS_MENU_HIDE_DEBUG[] = "Menu/HideDebug";
|
||||
const char SETTINGS_MENU_HIDE_ANALYZE[] = "Menu/HideAnalyze";
|
||||
|
||||
// UI texts
|
||||
PROJECTEXPLORER_EXPORT QString msgAutoDetected();
|
||||
|
@@ -144,6 +144,9 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
|
||||
return true;
|
||||
|
||||
dir.cdUp();
|
||||
|
||||
saveExpandedState(loadExpandedState(folderPath), dir.absoluteFilePath(newName));
|
||||
|
||||
return dir.rename(oldName, newName);
|
||||
}
|
||||
|
||||
@@ -341,8 +344,14 @@ void AssetsLibraryModel::setRootPath(const QString &path)
|
||||
|
||||
beginResetModel();
|
||||
m_assetsDir = new AssetsLibraryDir(path, 0, true, this);
|
||||
bool noAssets = parseDirRecursive(m_assetsDir, 1);
|
||||
setIsEmpty(noAssets);
|
||||
bool isEmpty = parseDirRecursive(m_assetsDir, 1);
|
||||
setIsEmpty(isEmpty);
|
||||
|
||||
bool noAssets = m_searchText.isEmpty() && isEmpty;
|
||||
// noAssets: the model has no asset files (project has no assets added)
|
||||
// isEmpty: the model has no asset files (assets could exist but are filtered out)
|
||||
|
||||
m_assetsDir->setDirVisible(!noAssets); // if there are no assets, hide all empty asset folders
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,8 @@ public:
|
||||
void setRootPath(const QString &path);
|
||||
void setSearchText(const QString &searchText);
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
static const QStringList &supportedImageSuffixes();
|
||||
static const QStringList &supportedFragmentShaderSuffixes();
|
||||
static const QStringList &supportedShaderSuffixes();
|
||||
@@ -93,7 +95,6 @@ signals:
|
||||
private:
|
||||
const QSet<QString> &supportedSuffixes() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
void setIsEmpty(bool empty);
|
||||
|
||||
SynchronousImageCache &m_fontImageCache;
|
||||
|
@@ -201,10 +201,11 @@ QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
|
||||
|
||||
void AssetsLibraryWidget::handleSearchfilterChanged(const QString &filterText)
|
||||
{
|
||||
if (filterText != m_filterText) {
|
||||
m_filterText = filterText;
|
||||
updateSearch();
|
||||
}
|
||||
if (filterText == m_filterText || (m_assetsModel->isEmpty() && filterText.contains(m_filterText)))
|
||||
return;
|
||||
|
||||
m_filterText = filterText;
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
void AssetsLibraryWidget::handleAddAsset()
|
||||
|
@@ -389,7 +389,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd)
|
||||
if (braceIdx != -1) {
|
||||
int nlIdx = content.lastIndexOf('\n', braceIdx);
|
||||
QByteArray rootItem = content.mid(nlIdx, braceIdx - nlIdx).trimmed();
|
||||
if (rootItem == "Node") { // a 3D object
|
||||
if (rootItem == "Node" || rootItem == "Model") { // a 3D object
|
||||
// create hints file with proper hints
|
||||
QFile file(outDir.path() + '/' + fi.baseName() + ".hints");
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
|
@@ -68,6 +68,11 @@ QString ItemLibraryItem::requiredImport() const
|
||||
return m_itemLibraryEntry.requiredImport();
|
||||
}
|
||||
|
||||
QString ItemLibraryItem::componentSource() const
|
||||
{
|
||||
return m_itemLibraryEntry.customComponentSource();
|
||||
}
|
||||
|
||||
bool ItemLibraryItem::setVisible(bool isVisible)
|
||||
{
|
||||
if (isVisible != m_isVisible) {
|
||||
|
@@ -45,6 +45,7 @@ class ItemLibraryItem: public QObject
|
||||
Q_PROPERTY(QString componentPath READ componentPath FINAL)
|
||||
Q_PROPERTY(bool itemUsable READ isUsable FINAL)
|
||||
Q_PROPERTY(QString itemRequiredImport READ requiredImport FINAL)
|
||||
Q_PROPERTY(QString itemComponentSource READ componentSource FINAL)
|
||||
|
||||
public:
|
||||
ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isImported, QObject *parent);
|
||||
@@ -55,6 +56,7 @@ public:
|
||||
QString itemLibraryIconPath() const;
|
||||
QString componentPath() const;
|
||||
QString requiredImport() const;
|
||||
QString componentSource() const;
|
||||
|
||||
bool setVisible(bool isVisible);
|
||||
bool isVisible() const;
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <designeractionmanager.h>
|
||||
#include <designermcumanager.h>
|
||||
#include <documentmanager.h>
|
||||
#include <itemlibraryimageprovider.h>
|
||||
#include <itemlibraryinfo.h>
|
||||
#include <itemlibrarymodel.h>
|
||||
@@ -269,6 +270,11 @@ void ItemLibraryWidget::handleAddImport(int index)
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
void ItemLibraryWidget::goIntoComponent(const QString &source)
|
||||
{
|
||||
DocumentManager::goIntoComponent(source);
|
||||
}
|
||||
|
||||
void ItemLibraryWidget::delayedUpdateModel()
|
||||
{
|
||||
static bool disableTimer = DesignerSettings::getValue(DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER).toBool();
|
||||
|
@@ -95,6 +95,7 @@ public:
|
||||
Q_INVOKABLE void addImportForItem(const QString &importUrl);
|
||||
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
||||
Q_INVOKABLE void handleAddImport(int index);
|
||||
Q_INVOKABLE void goIntoComponent(const QString &source);
|
||||
|
||||
signals:
|
||||
void itemActivated(const QString &itemName);
|
||||
|
@@ -34,35 +34,64 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
|
||||
const NodeMetaInfo &parentInfo,
|
||||
bool breakOnFirst)
|
||||
{
|
||||
TypeName typeName = insertInfo.typeName();
|
||||
TypeName superClass = insertInfo.directSuperClass().typeName();
|
||||
TypeName nodePackage = insertInfo.typeName().replace(insertInfo.simplifiedTypeName(), "");
|
||||
TypeName targetPackage = parentInfo.typeName().replace(parentInfo.simplifiedTypeName(), "");
|
||||
if (!nodePackage.contains(targetPackage))
|
||||
return;
|
||||
// TODO: Metainfo based matching system (QDS-6240)
|
||||
|
||||
// Common base types cause too many rarely valid matches, so they are ignored
|
||||
const QSet<TypeName> ignoredTypes {"<cpp>.QObject",
|
||||
"<cpp>.QQuickItem",
|
||||
"<cpp>.QQuick3DObject",
|
||||
"QtQuick.Item",
|
||||
"QtQuick3D.Object3D",
|
||||
"QtQuick3D.Node",
|
||||
"QtQuick3D.Particles3D.ParticleSystem3D"};
|
||||
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
|
||||
for (const PropertyName &name : targetNodeNameList) {
|
||||
if (!name.contains('.')) {
|
||||
TypeName propType = parentInfo.propertyTypeName(name).replace("<cpp>.", targetPackage);
|
||||
// Skip properties that are not sub classes of anything
|
||||
if (propType.contains('.')
|
||||
&& !ignoredTypes.contains(propType)
|
||||
&& (typeName == propType || propType == superClass)
|
||||
&& parentInfo.propertyIsWritable(propType)) {
|
||||
propertyList.append(QString::fromLatin1(name));
|
||||
if (breakOnFirst)
|
||||
break;
|
||||
// Fall back to a hardcoded list of supported cases:
|
||||
// Texture
|
||||
// -> DefaultMaterial
|
||||
// -> PrincipledMaterial
|
||||
// -> SpriteParticle3D
|
||||
// -> TextureInput
|
||||
// -> SceneEnvironment
|
||||
// Effect
|
||||
// -> SceneEnvironment
|
||||
// Shader, Command, Buffer
|
||||
// -> Pass
|
||||
// InstanceListEntry
|
||||
// -> InstanceList
|
||||
// Pass
|
||||
// -> Effect
|
||||
|
||||
const TypeName textureType = "QtQuick3D.Texture";
|
||||
if (insertInfo.isSubclassOf(textureType)) {
|
||||
const TypeName textureTypeCpp = "<cpp>.QQuick3DTexture";
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial")
|
||||
|| parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
|
||||
// All texture properties are valid targets
|
||||
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
|
||||
for (const PropertyName &name : targetNodeNameList) {
|
||||
TypeName propType = parentInfo.propertyTypeName(name);
|
||||
if (propType == textureType || propType == textureTypeCpp) {
|
||||
propertyList.append(QString::fromLatin1(name));
|
||||
if (breakOnFirst)
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
|
||||
propertyList.append("sprite");
|
||||
} else if (parentInfo.isSubclassOf("QtQuick3D.TextureInput")) {
|
||||
propertyList.append("texture");
|
||||
} else if (parentInfo.isSubclassOf("QtQuick3D.SceneEnvironment")) {
|
||||
propertyList.append("lightProbe");
|
||||
}
|
||||
} else if (insertInfo.isSubclassOf("QtQuick3D.Effect")) {
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.SceneEnvironment"))
|
||||
propertyList.append("effects");
|
||||
} else if (insertInfo.isSubclassOf("QtQuick3D.Shader")) {
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
|
||||
propertyList.append("shaders");
|
||||
} else if (insertInfo.isSubclassOf("QtQuick3D.Command")) {
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
|
||||
propertyList.append("commands");
|
||||
} else if (insertInfo.isSubclassOf("QtQuick3D.Buffer")) {
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
|
||||
propertyList.append("output");
|
||||
} else if (insertInfo.isSubclassOf("QtQuick3D.InstanceListEntry")) {
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.InstanceList"))
|
||||
propertyList.append("instances");
|
||||
} else if (insertInfo.isSubclassOf("QtQuick3D.Pass")) {
|
||||
if (parentInfo.isSubclassOf("QtQuick3D.Effect"))
|
||||
propertyList.append("passes");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,14 +139,6 @@ TypeName ChooseFromPropertyListDialog::selectedProperty() const
|
||||
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
|
||||
const ModelNode &targetNode, const ModelNode &newNode, QWidget *parent)
|
||||
{
|
||||
TypeName typeName = newNode.type();
|
||||
|
||||
// Component matches cases where you don't want to insert a plain component,
|
||||
// such as layer.effect. Also, default property is often a Component (typically 'delegate'),
|
||||
// and inserting into such property will silently overwrite implicit component, if any.
|
||||
if (typeName == "QtQml.Component")
|
||||
return nullptr;
|
||||
|
||||
const NodeMetaInfo info = newNode.metaInfo();
|
||||
const NodeMetaInfo targetInfo = targetNode.metaInfo();
|
||||
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(info, targetInfo);
|
||||
|
@@ -581,21 +581,29 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
||||
addImport(import);
|
||||
}
|
||||
|
||||
bool moveNodesAfter = true;
|
||||
m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] {
|
||||
for (const QString &assetPath : assetsPaths) {
|
||||
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetPath);
|
||||
QString assetType = assetTypeAndData.first;
|
||||
QString assetData = QString::fromUtf8(assetTypeAndData.second);
|
||||
if (assetType == "application/vnd.bauhaus.libraryresource.image")
|
||||
currNode = handleItemLibraryImageDrop(assetPath, targetProperty, rowModelIndex);
|
||||
else if (assetType == "application/vnd.bauhaus.libraryresource.font")
|
||||
currNode = handleItemLibraryFontDrop(assetData, targetProperty, rowModelIndex); // assetData is fontFamily
|
||||
else if (assetType == "application/vnd.bauhaus.libraryresource.shader")
|
||||
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f", targetProperty, rowModelIndex);
|
||||
else if (assetType == "application/vnd.bauhaus.libraryresource.sound")
|
||||
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty, rowModelIndex);
|
||||
else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d")
|
||||
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty, rowModelIndex);
|
||||
if (assetType == "application/vnd.bauhaus.libraryresource.image") {
|
||||
currNode = handleItemLibraryImageDrop(assetPath, targetProperty,
|
||||
rowModelIndex, moveNodesAfter);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.font") {
|
||||
currNode = handleItemLibraryFontDrop(assetData, // assetData is fontFamily
|
||||
targetProperty, rowModelIndex);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.shader") {
|
||||
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f",
|
||||
targetProperty, rowModelIndex,
|
||||
moveNodesAfter);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.sound") {
|
||||
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty,
|
||||
rowModelIndex);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d") {
|
||||
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
|
||||
rowModelIndex, moveNodesAfter);
|
||||
}
|
||||
|
||||
if (currNode.isValid())
|
||||
addedNodes.append(currNode);
|
||||
@@ -603,7 +611,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
||||
});
|
||||
|
||||
if (!addedNodes.isEmpty()) {
|
||||
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
|
||||
if (moveNodesAfter)
|
||||
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
|
||||
m_view->setSelectedModelNodes(addedNodes);
|
||||
}
|
||||
}
|
||||
@@ -682,21 +691,22 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
||||
dialog->exec();
|
||||
if (soloProperty || dialog->result() == QDialog::Accepted) {
|
||||
TypeName selectedProp = dialog->selectedProperty();
|
||||
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
|
||||
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
|
||||
if ((newModelNode.isSubclassOf("QtQuick3D.Shader") || newModelNode.isSubclassOf("QtQuick3D.Command"))
|
||||
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) {
|
||||
NodeAbstractProperty parentProp = targetProperty.parentProperty();
|
||||
if (parentProp.isValid()) {
|
||||
targetProperty = parentProp;
|
||||
ModelNode targetModel = targetProperty.parentModelNode();
|
||||
targetRowNumber = rowCount(indexForModelNode(targetModel));
|
||||
// Move node to new parent within the same transaction as we don't
|
||||
// want undo to place the node under invalid parent
|
||||
moveNodesInteractive(targetProperty, {newQmlObjectNode}, targetRowNumber, false);
|
||||
moveNodesAfter = false;
|
||||
}
|
||||
|
||||
// Pass and TextureInput can't have children, so we have to move nodes under parent
|
||||
if (((newModelNode.isSubclassOf("QtQuick3D.Shader")
|
||||
|| newModelNode.isSubclassOf("QtQuick3D.Command")
|
||||
|| newModelNode.isSubclassOf("QtQuick3D.Buffer"))
|
||||
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass"))
|
||||
|| (newModelNode.isSubclassOf("QtQuick3D.Texture")
|
||||
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.TextureInput"))) {
|
||||
if (moveNodeToParent(targetProperty, newQmlObjectNode)) {
|
||||
targetProperty = targetProperty.parentProperty();
|
||||
moveNodesAfter = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
|
||||
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
|
||||
listProp.addModelNodeToArray(newModelNode);
|
||||
validContainer = true;
|
||||
} else {
|
||||
@@ -778,7 +788,8 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
||||
|
||||
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
|
||||
NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex)
|
||||
const QModelIndex &rowModelIndex,
|
||||
bool &outMoveNodesAfter)
|
||||
{
|
||||
QTC_ASSERT(m_view, return {});
|
||||
|
||||
@@ -788,7 +799,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePat
|
||||
|
||||
ModelNode newModelNode;
|
||||
|
||||
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode)) {
|
||||
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode, outMoveNodesAfter)) {
|
||||
if (targetNode.isSubclassOf("QtQuick.Image") || targetNode.isSubclassOf("QtQuick.BorderImage")) {
|
||||
// if dropping an image on an existing image, set the source
|
||||
targetNode.variantProperty("source").setValue(imagePathRelative);
|
||||
@@ -846,9 +857,23 @@ void NavigatorTreeModel::addImport(const QString &importName)
|
||||
}
|
||||
}
|
||||
|
||||
bool QmlDesigner::NavigatorTreeModel::moveNodeToParent(const NodeAbstractProperty &targetProperty,
|
||||
const ModelNode &node)
|
||||
{
|
||||
NodeAbstractProperty parentProp = targetProperty.parentProperty();
|
||||
if (parentProp.isValid()) {
|
||||
ModelNode targetModel = parentProp.parentModelNode();
|
||||
int targetRowNumber = rowCount(indexForModelNode(targetModel));
|
||||
moveNodesInteractive(parentProp, {node}, targetRowNumber, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
|
||||
NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex)
|
||||
const QModelIndex &rowModelIndex,
|
||||
bool &outMoveNodesAfter)
|
||||
{
|
||||
QTC_ASSERT(m_view, return {});
|
||||
|
||||
@@ -863,29 +888,37 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
|
||||
: "Shader.Vertex");
|
||||
targetNode.variantProperty("shader").setValue(relPath);
|
||||
} else {
|
||||
// create a new Shader
|
||||
ItemLibraryEntry itemLibraryEntry;
|
||||
itemLibraryEntry.setName("Shader");
|
||||
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
|
||||
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
|
||||
// create a new Shader
|
||||
ItemLibraryEntry itemLibraryEntry;
|
||||
itemLibraryEntry.setName("Shader");
|
||||
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
|
||||
|
||||
// set shader properties
|
||||
PropertyName prop = "shader";
|
||||
QString type = "QByteArray";
|
||||
QVariant val = relPath;
|
||||
itemLibraryEntry.addProperty(prop, type, val);
|
||||
prop = "stage";
|
||||
type = "enum";
|
||||
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
|
||||
itemLibraryEntry.addProperty(prop, type, val);
|
||||
// set shader properties
|
||||
PropertyName prop = "shader";
|
||||
QString type = "QByteArray";
|
||||
QVariant val = relPath;
|
||||
itemLibraryEntry.addProperty(prop, type, val);
|
||||
prop = "stage";
|
||||
type = "enum";
|
||||
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
|
||||
itemLibraryEntry.addProperty(prop, type, val);
|
||||
|
||||
// create a texture
|
||||
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
|
||||
targetProperty, false);
|
||||
// create a texture
|
||||
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
|
||||
targetProperty, false);
|
||||
|
||||
// Rename the node based on shader source
|
||||
QFileInfo fi(relPath);
|
||||
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
|
||||
"shader"));
|
||||
// Rename the node based on shader source
|
||||
QFileInfo fi(relPath);
|
||||
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
|
||||
"shader"));
|
||||
// Passes can't have children, so move shader node under parent
|
||||
if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) {
|
||||
BindingProperty listProp = targetNode.bindingProperty("shaders");
|
||||
listProp.addModelNodeToArray(newModelNode);
|
||||
outMoveNodesAfter = !moveNodeToParent(targetProperty, newModelNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return newModelNode;
|
||||
@@ -932,7 +965,8 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
|
||||
|
||||
ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath,
|
||||
NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex)
|
||||
const QModelIndex &rowModelIndex,
|
||||
bool &outMoveNodesAfter)
|
||||
{
|
||||
QTC_ASSERT(m_view, return {});
|
||||
|
||||
@@ -947,7 +981,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
|
||||
|
||||
ModelNode newModelNode;
|
||||
|
||||
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) {
|
||||
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode, outMoveNodesAfter)) {
|
||||
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
|
||||
// create a standalone Texture3D at drop location
|
||||
newModelNode = createTextureNode(targetProperty, imagePath);
|
||||
@@ -962,8 +996,23 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
|
||||
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
||||
const NodeAbstractProperty &targetProp,
|
||||
const QString &imagePath,
|
||||
ModelNode &newNode)
|
||||
ModelNode &newNode,
|
||||
bool &outMoveNodesAfter)
|
||||
{
|
||||
auto bindToProperty = [&](const PropertyName &propName, bool sibling) {
|
||||
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
||||
newNode = createTextureNode(targetProp, imagePath);
|
||||
if (newNode.isValid()) {
|
||||
targetNode.bindingProperty(propName).setExpression(newNode.validId());
|
||||
|
||||
// If dropping an image on e.g. TextureInput, create a texture on the same level as
|
||||
// target, as the target doesn't support Texture children (QTBUG-86219)
|
||||
if (sibling)
|
||||
outMoveNodesAfter = !moveNodeToParent(targetProp, newNode);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")
|
||||
|| targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
|
||||
// if dropping an image on a material, create a texture instead of image
|
||||
@@ -986,16 +1035,13 @@ bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
||||
delete dialog;
|
||||
return true;
|
||||
} else if (targetNode.isSubclassOf("QtQuick3D.TextureInput")) {
|
||||
// If dropping an image on a TextureInput, create a texture on the same level as
|
||||
// TextureInput, as the TextureInput doesn't support Texture children (QTBUG-86219)
|
||||
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
||||
NodeAbstractProperty parentProp = targetProp.parentProperty();
|
||||
newNode = createTextureNode(parentProp, imagePath);
|
||||
if (newNode.isValid()) {
|
||||
// Automatically set the texture to texture property
|
||||
targetNode.bindingProperty("texture").setExpression(newNode.validId());
|
||||
}
|
||||
});
|
||||
bindToProperty("texture", true);
|
||||
return newNode.isValid();
|
||||
} else if (targetNode.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
|
||||
bindToProperty("sprite", false);
|
||||
return newNode.isValid();
|
||||
} else if (targetNode.isSubclassOf("QtQuick3D.SceneEnvironment")) {
|
||||
bindToProperty("lightProbe", false);
|
||||
return newNode.isValid();
|
||||
} else if (targetNode.isSubclassOf("QtQuick3D.Texture")) {
|
||||
// if dropping an image on an existing texture, set the source
|
||||
|
@@ -115,21 +115,24 @@ private:
|
||||
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||
ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex);
|
||||
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
||||
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex);
|
||||
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
|
||||
NodeAbstractProperty targetProperty, const QModelIndex &rowModelIndex);
|
||||
NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex,
|
||||
bool &outMoveNodesAfter);
|
||||
ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex);
|
||||
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
|
||||
const QModelIndex &rowModelIndex);
|
||||
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
||||
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
|
||||
const QString &imagePath, ModelNode &newNode);
|
||||
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
|
||||
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
|
||||
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
|
||||
void addImport(const QString &importName);
|
||||
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) const;
|
||||
bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const ModelNode &newModelNode);
|
||||
|
||||
QPointer<NavigatorView> m_view;
|
||||
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;
|
||||
|
@@ -108,14 +108,19 @@ static inline void applyProperties(ModelNode &node, const QHash<PropertyName, QV
|
||||
}
|
||||
}
|
||||
|
||||
static void openFileComponent(const ModelNode &modelNode)
|
||||
static void openFileComponentForFile(const QString &fileName)
|
||||
{
|
||||
QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally();
|
||||
Core::EditorManager::openEditor(FilePath::fromString(modelNode.metaInfo().componentFileName()),
|
||||
Core::EditorManager::openEditor(FilePath::fromString(fileName),
|
||||
Utils::Id(),
|
||||
Core::EditorManager::DoNotMakeVisible);
|
||||
}
|
||||
|
||||
static void openFileComponent(const ModelNode &modelNode)
|
||||
{
|
||||
openFileComponentForFile(modelNode.metaInfo().componentFileName());
|
||||
}
|
||||
|
||||
static void openFileComponentForDelegate(const ModelNode &modelNode)
|
||||
{
|
||||
openFileComponent(modelNode.nodeProperty("delegate").modelNode());
|
||||
@@ -305,6 +310,11 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
void DocumentManager::goIntoComponent(const QString &fileName)
|
||||
{
|
||||
openFileComponentForFile(fileName);
|
||||
}
|
||||
|
||||
bool DocumentManager::createFile(const QString &filePath, const QString &contents)
|
||||
{
|
||||
Utils::TextFileFormat textFileFormat;
|
||||
|
@@ -52,6 +52,7 @@ public:
|
||||
void removeEditors(const QList<Core::IEditor *> &editors);
|
||||
|
||||
static bool goIntoComponent(const ModelNode &modelNode);
|
||||
static void goIntoComponent(const QString &fileName);
|
||||
|
||||
static bool createFile(const QString &filePath, const QString &contents);
|
||||
static void addFileToVersionControl(const QString &directoryPath, const QString &newFilePath);
|
||||
|
@@ -146,7 +146,7 @@ void FileDownloader::start()
|
||||
QNetworkRequest::UserVerifiedRedirectPolicy);
|
||||
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
|
||||
QNetworkReply::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() {
|
||||
m_tempFile.write(reply->readAll());
|
||||
});
|
||||
|
||||
@@ -165,7 +165,7 @@ void FileDownloader::start()
|
||||
emit reply->redirectAllowed();
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
if (reply->error()) {
|
||||
m_tempFile.remove();
|
||||
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
|
||||
@@ -246,7 +246,7 @@ void FileDownloader::probeUrl()
|
||||
emit reply->redirectAllowed();
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
if (reply->error())
|
||||
return;
|
||||
|
||||
@@ -259,6 +259,7 @@ void FileDownloader::probeUrl()
|
||||
|
||||
QNetworkReply::connect(reply,
|
||||
&QNetworkReply::errorOccurred,
|
||||
this,
|
||||
[this, reply](QNetworkReply::NetworkError code) {
|
||||
// QNetworkReply::HostNotFoundError
|
||||
// QNetworkReply::ContentNotFoundError
|
||||
@@ -282,7 +283,7 @@ FileExtractor::FileExtractor(QObject *parent)
|
||||
m_timer.setInterval(100);
|
||||
m_timer.setSingleShot(false);
|
||||
|
||||
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, [this]() {
|
||||
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, this, [this]() {
|
||||
if (targetFolderExists()) {
|
||||
m_birthTime = QFileInfo(m_targetPath.toString() + "/" + m_archiveName).birthTime();
|
||||
} else
|
||||
@@ -389,33 +390,34 @@ void FileExtractor::extract()
|
||||
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||
qint64 compressedSize = QFileInfo(m_sourceFile.toString()).size();
|
||||
|
||||
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder, compressedSize]() {
|
||||
static QHash<QString, int> hash;
|
||||
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
|
||||
QTimer::connect(
|
||||
&m_timer, &QTimer::timeout, this, [this, bytesBefore, targetFolder, compressedSize]() {
|
||||
static QHash<QString, int> hash;
|
||||
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
|
||||
|
||||
int count = 0;
|
||||
while (it.hasNext()) {
|
||||
if (!hash.contains(it.fileName())) {
|
||||
m_currentFile = it.fileName();
|
||||
hash.insert(m_currentFile, 0);
|
||||
emit currentFileChanged();
|
||||
int count = 0;
|
||||
while (it.hasNext()) {
|
||||
if (!hash.contains(it.fileName())) {
|
||||
m_currentFile = it.fileName();
|
||||
hash.insert(m_currentFile, 0);
|
||||
emit currentFileChanged();
|
||||
}
|
||||
it.next();
|
||||
count++;
|
||||
}
|
||||
it.next();
|
||||
count++;
|
||||
}
|
||||
|
||||
qint64 currentSize = bytesBefore
|
||||
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||
qint64 currentSize = bytesBefore
|
||||
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||
|
||||
// We can not get the uncompressed size of the archive yet, that is why we use an
|
||||
// approximation. We assume a 50% compression rate.
|
||||
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
|
||||
emit progressChanged();
|
||||
// We can not get the uncompressed size of the archive yet, that is why we use an
|
||||
// approximation. We assume a 50% compression rate.
|
||||
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
|
||||
emit progressChanged();
|
||||
|
||||
m_size = QString::number(currentSize);
|
||||
m_count = QString::number(count);
|
||||
emit sizeChanged();
|
||||
});
|
||||
m_size = QString::number(currentSize);
|
||||
m_count = QString::number(count);
|
||||
emit sizeChanged();
|
||||
});
|
||||
|
||||
QObject::connect(archive, &Utils::Archive::outputReceived, this, [this](const QString &output) {
|
||||
m_detailedText += output;
|
||||
|
@@ -43,6 +43,7 @@
|
||||
|
||||
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
|
||||
#include <qmlprojectmanager/qmlproject.h>
|
||||
@@ -59,18 +60,21 @@
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileInfo>
|
||||
#include <QFontDatabase>
|
||||
#include <QGroupBox>
|
||||
#include <QPointer>
|
||||
#include <QShortcut>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlEngine>
|
||||
#include <QQuickItem>
|
||||
#include <QQuickView>
|
||||
#include <QQuickWidget>
|
||||
#include <QSettings>
|
||||
#include <QShortcut>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@@ -758,11 +762,109 @@ WelcomeMode::WelcomeMode()
|
||||
[](const QString &path) { return QFileInfo::exists(path); }));
|
||||
}
|
||||
|
||||
static bool hideBuildMenuSetting()
|
||||
{
|
||||
return Core::ICore::settings()
|
||||
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD, false)
|
||||
.toBool();
|
||||
}
|
||||
|
||||
static bool hideDebugMenuSetting()
|
||||
{
|
||||
return Core::ICore::settings()
|
||||
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG, false)
|
||||
.toBool();
|
||||
}
|
||||
|
||||
static bool hideAnalyzeMenuSetting()
|
||||
{
|
||||
return Core::ICore::settings()
|
||||
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
|
||||
.toBool();
|
||||
}
|
||||
|
||||
void setSettingIfDifferent(const QString &key, bool value, bool &dirty)
|
||||
{
|
||||
QSettings *s = Core::ICore::settings();
|
||||
if (s->value(key, false).toBool() != value) {
|
||||
dirty = false;
|
||||
s->setValue(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
WelcomeMode::~WelcomeMode()
|
||||
{
|
||||
delete m_modeWidget;
|
||||
}
|
||||
|
||||
StudioSettingsPage::StudioSettingsPage()
|
||||
: m_buildCheckBox(new QCheckBox(tr("Build")))
|
||||
, m_debugCheckBox(new QCheckBox(tr("Debug")))
|
||||
, m_analyzeCheckBox(new QCheckBox(tr("Analyze")))
|
||||
{
|
||||
const QString toolTip = tr(
|
||||
"Hide top-level menus with advanced functionality to simplify the UI. <b>Build</b> is "
|
||||
"generally not required in the context of Qt Design Studio.<b>Debug</b> and <b>Analyze</b>"
|
||||
"are only required for debugging and profiling.");
|
||||
|
||||
QVBoxLayout *boxLayout = new QVBoxLayout(this);
|
||||
setLayout(boxLayout);
|
||||
auto groupBox = new QGroupBox(tr("Hide Menu"));
|
||||
groupBox->setToolTip(toolTip);
|
||||
boxLayout->addWidget(groupBox);
|
||||
boxLayout->addSpacerItem(
|
||||
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
|
||||
auto verticalLayout = new QVBoxLayout();
|
||||
groupBox->setLayout(verticalLayout);
|
||||
|
||||
m_buildCheckBox->setToolTip(toolTip);
|
||||
m_debugCheckBox->setToolTip(toolTip);
|
||||
m_analyzeCheckBox->setToolTip(toolTip);
|
||||
|
||||
verticalLayout->addWidget(m_buildCheckBox);
|
||||
verticalLayout->addWidget(m_debugCheckBox);
|
||||
verticalLayout->addWidget(m_analyzeCheckBox);
|
||||
verticalLayout->addSpacerItem(
|
||||
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
|
||||
m_buildCheckBox->setChecked(hideBuildMenuSetting());
|
||||
m_debugCheckBox->setChecked(hideDebugMenuSetting());
|
||||
m_analyzeCheckBox->setChecked(hideAnalyzeMenuSetting());
|
||||
}
|
||||
|
||||
void StudioSettingsPage::apply()
|
||||
{
|
||||
bool dirty = false;
|
||||
|
||||
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD,
|
||||
m_buildCheckBox->isChecked(),
|
||||
dirty);
|
||||
|
||||
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG,
|
||||
m_debugCheckBox->isChecked(),
|
||||
dirty);
|
||||
|
||||
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE,
|
||||
m_analyzeCheckBox->isChecked(),
|
||||
dirty);
|
||||
|
||||
|
||||
if (dirty) {
|
||||
const QString restartText = tr("The menu visibility change will take effect after restart.");
|
||||
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
|
||||
restartDialog.exec();
|
||||
}
|
||||
}
|
||||
|
||||
StudioWelcomeSettingsPage::StudioWelcomeSettingsPage()
|
||||
{
|
||||
setId("Z.StudioWelcome.Settings");
|
||||
setDisplayName(tr("Qt Design Studio Configuration"));
|
||||
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
|
||||
setWidgetCreator([] { return new StudioSettingsPage; });
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace StudioWelcome
|
||||
|
||||
|
@@ -26,12 +26,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QCheckBox)
|
||||
|
||||
namespace StudioWelcome {
|
||||
namespace Internal {
|
||||
|
||||
class StudioSettingsPage : public Core::IOptionsPageWidget
|
||||
{
|
||||
public:
|
||||
void apply() final;
|
||||
|
||||
StudioSettingsPage();
|
||||
|
||||
private:
|
||||
QCheckBox *m_buildCheckBox;
|
||||
QCheckBox *m_debugCheckBox;
|
||||
QCheckBox *m_analyzeCheckBox;
|
||||
};
|
||||
|
||||
class StudioWelcomeSettingsPage : public Core::IOptionsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StudioWelcomeSettingsPage();
|
||||
};
|
||||
|
||||
class StudioWelcomePlugin final : public ExtensionSystem::IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -55,6 +79,7 @@ public:
|
||||
private:
|
||||
class WelcomeMode *m_welcomeMode = nullptr;
|
||||
QTimer m_removeSplashTimer;
|
||||
StudioWelcomeSettingsPage m_settingsPage;
|
||||
int m_removeSplashRemainingTime = 0;
|
||||
};
|
||||
|
||||
|
@@ -70,8 +70,7 @@ void WizardFactories::filter()
|
||||
{
|
||||
QList<JsonWizardFactory *> acceptedFactories = Utils::filtered(m_factories, [&](auto *wizard) {
|
||||
return wizard->isAvailable(m_platform)
|
||||
&& wizard->kind() == JsonWizardFactory::ProjectWizard
|
||||
&& wizard->requiredFeatures().contains("QtStudio");
|
||||
&& wizard->kind() == JsonWizardFactory::ProjectWizard;
|
||||
});
|
||||
|
||||
m_factories = acceptedFactories;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user