diff --git a/CMakeLists.txt b/CMakeLists.txt index c226f78bdbb..c6f603c7981 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) ## Add paths to check for cmake modules: list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -138,15 +138,8 @@ endif() add_subdirectory(doc) -# TODO: Remove when cmake_minimum_required greater than 3.12 -if (CMAKE_VERSION VERSION_GREATER 3.12) - find_package(Python3 COMPONENTS Interpreter) - set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND}) - set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) -else() - find_package(PythonInterp) -endif() -if (NOT PYTHONINTERP_FOUND) +find_package(Python3 COMPONENTS Interpreter) +if (NOT Python3_Interpreter_FOUND) message("No python interpreter found, skipping \"Dependencies\" install component.") else() get_target_property(_qmake_binary Qt5::qmake IMPORTED_LOCATION) @@ -161,7 +154,7 @@ else() endif() install(CODE " execute_process(COMMAND - \"${PYTHON_EXECUTABLE}\" + \"${Python3_EXECUTABLE}\" \"${CMAKE_CURRENT_LIST_DIR}/scripts/deployqt.py\" ${_llvm_arg} ${_elfutils_arg} diff --git a/cmake/FindClang.cmake b/cmake/FindClang.cmake index 2e36d9752a3..1133558dc76 100644 --- a/cmake/FindClang.cmake +++ b/cmake/FindClang.cmake @@ -2,7 +2,7 @@ find_package(Clang CONFIG) # silence a lot of warnings from building against llvm if(MSVC AND TARGET libclang) - target_compile_options(libclang INTERFACE /wd4100 /wd4141 /wd4146 /wd4244 /wd4267 /wd4291) + target_compile_options(libclang INTERFACE /wd4267) endif() option(CLANGTOOLING_LINK_CLANG_DYLIB "Force linking of Clang tooling against clang-cpp" NO) diff --git a/cmake/QtCreatorAPI.cmake b/cmake/QtCreatorAPI.cmake index 566f5883d46..194852d6b7f 100644 --- a/cmake/QtCreatorAPI.cmake +++ b/cmake/QtCreatorAPI.cmake @@ -155,20 +155,6 @@ function(add_qtc_library name) return() endif() - # TODO copied from extend_qtc_target. - # Instead require CMake 3.11 and use extend_qtc_target for setting SOURCES. - # Requiring cmake 3.11 is necessary because before that add_library requires - # at least one source file. - if (_arg_SOURCES_PREFIX) - foreach(source IN LISTS _arg_SOURCES) - list(APPEND prefixed_sources "${_arg_SOURCES_PREFIX}/${source}") - endforeach() - if (NOT IS_ABSOLUTE ${_arg_SOURCES_PREFIX}) - set(_arg_SOURCES_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${_arg_SOURCES_PREFIX}") - endif() - set(_arg_SOURCES ${prefixed_sources}) - endif() - set(library_type SHARED) if (_arg_STATIC) set(library_type STATIC) @@ -177,16 +163,9 @@ function(add_qtc_library name) set(library_type OBJECT) endif() - add_library(${name} ${library_type} ${_arg_SOURCES}) + add_library(${name} ${library_type}) add_library(QtCreator::${name} ALIAS ${name}) - set_public_headers(${name} "${_arg_SOURCES}") - - # TODO remove, see above - if (_arg_SOURCES_PREFIX) - target_include_directories(${name} PRIVATE $) - endif() - if (${name} MATCHES "^[^0-9-]+$") string(TOUPPER "${name}_LIBRARY" EXPORT_SYMBOL) endif() @@ -201,6 +180,8 @@ function(add_qtc_library name) endif() extend_qtc_target(${name} + SOURCES_PREFIX ${_arg_SOURCES_PREFIX} + SOURCES ${_arg_SOURCES} INCLUDES ${_arg_INCLUDES} PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES} DEFINES ${EXPORT_SYMBOL} ${default_defines_copy} ${_arg_DEFINES} ${TEST_DEFINES} diff --git a/cmake/QtCreatorAPIInternal.cmake b/cmake/QtCreatorAPIInternal.cmake index 7c16d1dd2eb..86fe1c0d939 100644 --- a/cmake/QtCreatorAPIInternal.cmake +++ b/cmake/QtCreatorAPIInternal.cmake @@ -1,5 +1,5 @@ if (CMAKE_VERSION VERSION_LESS 3.18) - if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_VERSION VERSION_LESS 3.16) + if (CMAKE_CXX_COMPILER_ID STREQUAL GNU) set(BUILD_WITH_PCH OFF CACHE BOOL "" FORCE) endif() endif() @@ -183,31 +183,6 @@ function(update_cached_list name value) set("${name}" "${_tmp_list}" CACHE INTERNAL "*** Internal ***") endfunction() -function(separate_object_libraries libraries REGULAR_LIBS OBJECT_LIBS OBJECT_LIB_OBJECTS) - if (CMAKE_VERSION VERSION_LESS 3.14) - foreach(lib IN LISTS libraries) - if (TARGET ${lib}) - get_target_property(lib_type ${lib} TYPE) - if (lib_type STREQUAL "OBJECT_LIBRARY") - list(APPEND object_libs ${lib}) - list(APPEND object_libs_objects $) - else() - list(APPEND regular_libs ${lib}) - endif() - else() - list(APPEND regular_libs ${lib}) - endif() - set(${REGULAR_LIBS} ${regular_libs} PARENT_SCOPE) - set(${OBJECT_LIBS} ${object_libs} PARENT_SCOPE) - set(${OBJECT_LIB_OBJECTS} ${object_libs_objects} PARENT_SCOPE) - endforeach() - else() - set(${REGULAR_LIBS} ${libraries} PARENT_SCOPE) - unset(${OBJECT_LIBS} PARENT_SCOPE) - unset(${OBJECT_LIB_OBJECTS} PARENT_SCOPE) - endif() -endfunction(separate_object_libraries) - function(set_explicit_moc target_name file) unset(file_dependencies) if (file MATCHES "^.*plugin.h$") @@ -293,12 +268,8 @@ function(add_qtc_depends target_name) check_qtc_disabled_targets(${target_name} _arg_PRIVATE) check_qtc_disabled_targets(${target_name} _arg_PUBLIC) - separate_object_libraries("${_arg_PRIVATE}" - depends object_lib_depends object_lib_depends_objects) - separate_object_libraries("${_arg_PUBLIC}" - public_depends object_public_depends object_public_depends_objects) - - target_sources(${target_name} PRIVATE ${object_lib_depends_objects} ${object_public_depends_objects}) + set(depends "${_arg_PRIVATE}") + set(public_depends "${_arg_PUBLIC}") get_target_property(target_type ${target_name} TYPE) if (NOT target_type STREQUAL "OBJECT_LIBRARY") diff --git a/doc/qtcreator/images/qtcreator-language-client-inspector-capabilities.png b/doc/qtcreator/images/qtcreator-language-client-inspector-capabilities.png new file mode 100644 index 00000000000..e2e12e3624a Binary files /dev/null and b/doc/qtcreator/images/qtcreator-language-client-inspector-capabilities.png differ diff --git a/doc/qtcreator/images/qtcreator-language-client-inspector-log.png b/doc/qtcreator/images/qtcreator-language-client-inspector-log.png new file mode 100644 index 00000000000..f522fe87d4b Binary files /dev/null and b/doc/qtcreator/images/qtcreator-language-client-inspector-log.png differ diff --git a/doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.png b/doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.png new file mode 100644 index 00000000000..92ab52d28b9 Binary files /dev/null and b/doc/qtcreator/images/qtcreator-language-client-inspector-memory-usage.png differ diff --git a/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc b/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc index 0480cdeed66..377f50394f4 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-clang-codemodel.qdoc @@ -176,7 +176,7 @@ \list 1 \li Select \uicontrol Tools > \uicontrol Options > \uicontrol C++ > - \uicontrol Clangd > \uicontrol {Use clangd (EXPERIMENTAL)}. + \uicontrol Clangd > \uicontrol {Use clangd}. \image qtcreator-options-clangd.png "clangd options" \li In \uicontrol {Path to executable}, enter the path to clangd version 13, or later. diff --git a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc index 02e0a78f316..001e85c1462 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc @@ -1,6 +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 the Qt Creator documentation. @@ -32,7 +32,8 @@ For several programming languages, a \e {language server} is available that provides information about the code to IDEs as long as they support - communication via the language server protocol (LSP). This enables the + communication via the \l{Language Server Protocol} + {language server protocol (LSP)}. This enables the IDE to provide the following services: \list @@ -145,6 +146,7 @@ the Java language server \c .jar file. \endlist + \section1 Supported Locator Filters The locator enables you to browse not only files, but any items defined by @@ -158,6 +160,49 @@ definitions in your project \endlist + \section1 Inspecting Language Clients + + \QC sends messages (\e Requests) to the language server and receives + responses that contain the requested information if the language server is + capable of handling the requests. To inspect the communication between \QC + and language servers and view server capabilities, select \uicontrol Tools + > \uicontrol {Debug \QC} > \uicontrol {Inspect Language Client}. + + \image qtcreator-language-client-inspector-log.png "Language Client Inspector dialog" + + The dialog shows a list of running language servers. The value of the + \uicontrol {Startup behavior} field in the language server options + determines when the server is started. The information displayed depends on + the language server. + + \uicontrol Log displays additional information about the selected log entry. + You can see the \uicontrol {Content length} and \uicontrol {MIME type} of + a \uicontrol {Client Message} and \uicontrol {Server Message}, as well as + inspect the data sent between \QC and the language server. + + To remove old entries, select \uicontrol Clear. + + \section2 Capabilities + + In \uicontrol Capabilities, you can check whether a language server is + capable of a specific task. You cannot modify the server capabilities + in this dialog. + + You can view the \uicontrol Name, \uicontrol Value, and \uicontrol Type + of the capability. + + \image qtcreator-language-client-inspector-capabilities.png "Language Client Inspector Capabilities tab" + + For some language servers, \uicontrol {Dynamic Capabilities} lists the + \uicontrol Methods and \uicontrol Options available. + + \section2 Memory Usage + + For a clangd server, you can inspect the total amount of memory used by a + particular component in \uicontrol {Memory Usage}. + + \image qtcreator-language-client-inspector-capabilities.png "Language Client Inspector Capabilities tab" + \section1 Reporting Issues The language service client has been mostly tested with Python and Java. diff --git a/doc/qtcreator/src/external-resources/external-resources.qdoc b/doc/qtcreator/src/external-resources/external-resources.qdoc index dc3f15c4863..4bc40bc9d67 100644 --- a/doc/qtcreator/src/external-resources/external-resources.qdoc +++ b/doc/qtcreator/src/external-resources/external-resources.qdoc @@ -1,6 +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 the documentation of the Qt Toolkit. @@ -141,3 +141,7 @@ \externalpage https://cmake.org/cmake/help/latest/prop_sf/HEADER_FILE_ONLY.html \title CMake: HEADER_FILE_ONLY */ +/*! + \externalpage https://microsoft.github.io/language-server-protocol/ + \title Language Server Protocol +*/ diff --git a/doc/qtdesignstudio/examples/doc/images/imported-translations.png b/doc/qtdesignstudio/examples/doc/images/imported-translations.png index 7609394b8e0..1d30eb7be02 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/imported-translations.png and b/doc/qtdesignstudio/examples/doc/images/imported-translations.png differ diff --git a/doc/qtdesignstudio/examples/doc/images/loginui1-project-files.png b/doc/qtdesignstudio/examples/doc/images/loginui1-project-files.png index 47ff9b43032..7b7edd8fe1b 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/loginui1-project-files.png and b/doc/qtdesignstudio/examples/doc/images/loginui1-project-files.png differ diff --git a/doc/qtdesignstudio/examples/doc/images/loginui3-visibility.png b/doc/qtdesignstudio/examples/doc/images/loginui3-visibility.png index 48bedc6a485..d43dbb61075 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/loginui3-visibility.png and b/doc/qtdesignstudio/examples/doc/images/loginui3-visibility.png differ diff --git a/doc/qtdesignstudio/examples/doc/loginui1.qdoc b/doc/qtdesignstudio/examples/doc/loginui1.qdoc index 976c4923a44..78bc2192b56 100644 --- a/doc/qtdesignstudio/examples/doc/loginui1.qdoc +++ b/doc/qtdesignstudio/examples/doc/loginui1.qdoc @@ -41,6 +41,9 @@ project and a button UI control, and how to modify the files generated by the wizard templates to wireframe the UI. + You can donwnload the completed project from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui1}{here}. + The \e {Learn More} sections provide additional information about the tasks performed by the wizards and about other basic tasks and concepts. @@ -54,24 +57,19 @@ To create a project: \list 1 - \li Select \uicontrol File > \uicontrol {New Project} > - \uicontrol General > \uicontrol {Qt Quick Application - Empty} > - \uicontrol Choose. - \li In the \uicontrol Name field, enter the project name: \e {loginui1}. - When naming your own projects, keep in mind that they cannot be - easily renamed later. - \li In the \uicontrol {Create in} field, enter the path to the folder - where you want to store the project files. You can move project - folders later without problems. - \li Select \uicontrol Next (or \uicontrol Continue on \macos) to - continue to the \uicontrol {Define Project Details} page. - \li In the \uicontrol {Screen resolution} field, select the initial - size of the UI. In this tutorial, we use the predefined size - \e {720 x 1280 (HD)} (portrait) instead of the default size - (landscape). You can easily change the screen size later in - \l Properties. - \li Select \uicontrol Finish (or \uicontrol Done on \macos) to create - the project. + \li Select \uicontrol File > \uicontrol {New Project}. + \li In the \uicontrol Presets tab, select \uicontrol General > + \uicontrol {Empty}. + \li In the \uicontrol Details tab: + \list + \li Enter \e Loginui1 as the name for the project. Keep in mind + that projects cannot be easily renamed later. + \li Select the path for the project files. You can move project + folders later. + \li Set \uicontrol Width to 720 and \uicontrol Height to 1280. + You can change the screen size later in \l Properties. + \endlist + \li Select \uicontrol Create to create the project. \endlist Your project should now look something like this in the \uicontrol Design @@ -92,7 +90,7 @@ \section2 Learn More - Projects and Files \QDS creates a set of boilerplate files and folders that you need to create - a UI. The files are listed in the \l Projects view. + a UI. The files are listed in the \l{File System} view. \image loginui1-project-files.png @@ -112,6 +110,9 @@ Specifically, if you export and import designs using \QB, your main file is most likely called something else. For more information, see \l {Exporting from Design Tools}. + \li The \e CMakeLists.txt project configuration file allowing you to + share your project as a fully working C++ application with + developers. \li The \e {qtquickcontrols2.conf} file specifies the selected \l {Styling Qt Quick Controls}{UI style} and some style-specific arguments. @@ -230,7 +231,7 @@ adds the following \e import statements to the UI files (.ui.qml) that it creates: - \quotefromfile loginui1/Screen01.ui.qml + \quotefromfile Loginui1/Content/Screen01.ui.qml \skipto import \printuntil Controls @@ -333,7 +334,7 @@ To be able to use the functionality of the Button control, the wizard template adds the following \e import statements to the \e EntryField.ui.qml file: - \quotefromfile loginui1/EntryField.ui.qml + \quotefromfile Loginui1/Content/EntryField.ui.qml \skipto import \printuntil Controls @@ -364,7 +365,7 @@ to \e 100, to match the width of the tag line. \li In the \uicontrol Control section, deselect the \uicontrol Hover check box because we don't want the hover effect for the button. - \li Select the button background in \uicontrol Navigator to display its + \li Select \e buttonBackground in \uicontrol Navigator to display its properties in \uicontrol Properties. \li In \uicontrol Rectangle > \uicontrol {Fill color}, set the color to transparent light gray (\e #28e7e7e7) in \uicontrol Hex. You can @@ -372,7 +373,7 @@ \li In \uicontrol {Border Color}, select white (\e #ffffff). \li In \uicontrol Radius, enter \e 50 to give the button rounded corners. - \li Select the text component in \uicontrol Navigator to display its + \li Select \e textItem in \uicontrol Navigator to display its properties in \uicontrol Properties. \li In \uicontrol Character > \uicontrol Font, select \e {Titillium Web ExtraLight}. @@ -382,7 +383,7 @@ (\e #ffffff). \li In \uicontrol {Alignment H}, select the \uicontrol Left button to align the text horizontally to the left. - \li In the \uicontrol Padding section > \uicontrol Horizontal > + \li In \uicontrol Padding > \uicontrol Horizontal > \uicontrol Left, set the padding in the field between background border and text to \e 50. \image loginui1-text-properties-button.png "Text properties" @@ -450,13 +451,13 @@ to \e 100. \li In the \uicontrol Control section, deselect the \uicontrol Hover check box because we don't want the hover effect for the button. - \li Select the button background in \uicontrol Navigator to display its + \li Select \e buttonBackground in \uicontrol Navigator to display its properties in \uicontrol Properties. \li In \uicontrol Rectangle > \uicontrol {Border color}, select the green used in the logo (\e #41cd52). \li In \uicontrol Radius, enter \e 50 to give the button rounded corners. - \li Select the the text component in \uicontrol Navigator to display + \li Select \e textItem in \uicontrol Navigator to display its properties in \uicontrol Properties. \li In \uicontrol Character > \uicontrol Font, select \e {Titillium Web ExtraLight}. diff --git a/doc/qtdesignstudio/examples/doc/loginui2.qdoc b/doc/qtdesignstudio/examples/doc/loginui2.qdoc index bcf557825d7..c2ca170552e 100644 --- a/doc/qtdesignstudio/examples/doc/loginui2.qdoc +++ b/doc/qtdesignstudio/examples/doc/loginui2.qdoc @@ -24,7 +24,7 @@ ****************************************************************************/ /*! - \example loginui2 + \example Loginui2 \ingroup gstutorials \previouspage {Log In UI - Components} \nextpage {Log In UI - States} @@ -45,7 +45,12 @@ their proper places when you resize the UI on the desktop or on devices with different screen sizes, you will use anchors and positioners. - These instructions build on \l {Log In UI - Components}. + The starting point for this tutorial is the completed + \l{Log In UI - Components} project. You can download the project from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui1}{here}. + + Additionally, you can download the completed project of this tutorial from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui2}{here}. The \e {Learn More} sections provide additional information about the task at hand. @@ -79,6 +84,9 @@ anchor button to anchor \e adventurePage to its parent in the \uicontrol Target field. This attaches the background image to the rectangle on all sides. + Note: Selecting the anchor button should automatically select the + four buttons on the left side of it. If it doesn't, refresh + \uicontrol{Form Editor}. \image loginui2-layout.png "Layout properties" \li Select \e qt_logo_green_128x128px in \l Navigator. \li In \uicontrol Properties > \uicontrol Layout, select the diff --git a/doc/qtdesignstudio/examples/doc/loginui3.qdoc b/doc/qtdesignstudio/examples/doc/loginui3.qdoc index 34730dfc425..999215d90b1 100644 --- a/doc/qtdesignstudio/examples/doc/loginui3.qdoc +++ b/doc/qtdesignstudio/examples/doc/loginui3.qdoc @@ -46,12 +46,12 @@ login page, you will use \e states to show and hide UI components as necessary when a user selects the \e {Create Account} button. - These instructions build on: + The starting point for this tutorial is the completed + \l{Log In UI - Positioning} project. You can download the project from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui2}{here}. - \list - \li \l {Log In UI - Components} - \li \l {Log In UI - Positioning} - \endlist + Additionally, you can download the completed project of this tutorial from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui3}{here}. The \e {Learn More} sections provide additional information relevant to the task at hand. diff --git a/doc/qtdesignstudio/examples/doc/loginui4.qdoc b/doc/qtdesignstudio/examples/doc/loginui4.qdoc index a601d8aa8ec..a6a1ad77d4a 100644 --- a/doc/qtdesignstudio/examples/doc/loginui4.qdoc +++ b/doc/qtdesignstudio/examples/doc/loginui4.qdoc @@ -46,13 +46,13 @@ \l{Creating Timeline Animations}{timeline animations} that you bind to states. - These instructions build on: + The starting point for this tutorial is the completed + \l{Log In UI - States} project. You can download the project from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui3}{here}. + + Additionally, you can download the completed project of this tutorial from + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/Loginui4}{here}. - \list - \li \l {Log In UI - Components} - \li \l {Log In UI - Positioning} - \li \l {Log In UI - States} - \endlist The \e {Learn More} sections provide additional information relevant to the task at hand. @@ -94,7 +94,7 @@ \li Select \inlineimage icons/navigator-arrowup.png to move \e username below \e tagLine in \uicontrol Navigator to preserve the \l{Arranging Components}{component hierarchy}. - \li Repeat for \e password and \e repeatPassword. + \li Repeat step 3 and 4 for \e password and \e repeatPassword. \li Select \e fields in \uicontrol Navigator and press \key Delete to delete it. \li Select \e username in \uicontrol Navigator to display its properties @@ -196,8 +196,8 @@ to save your changes. \endlist - When you move the playhead along the timeline, you can see how the login - button fades out while the repeat password field fades in. + When you move the playhead along the timeline, you can see how the create + account button fades out while the repeat password field fades in. You will now animate the top anchor margin of the repeat password field to make it appear to slide down from the password field. @@ -219,7 +219,7 @@ frame 0, and select the record button for the \e anchors.topMargin property of \e repeatPassword. \li In the field next to the property, set a negative value for the - top anchor margin, -40, to place \e repeatPassword on top of + top anchor margin, -100, to place \e repeatPassword on top of \e password. \li Move the playhead to frame 1000 and change the top anchor margin to 20, so that, combined with the change in the \uicontrol Opacity @@ -312,7 +312,7 @@ the following \e import statement to the UI files where it uses the components: - \quotefromfile loginui4/Screen01.ui.qml + \quotefromfile Loginui4/Content/Screen01.ui.qml \skipto QtQuick.Timeline \printuntil 1.0 diff --git a/doc/qtdesignstudio/examples/doc/multilanguage.qdoc b/doc/qtdesignstudio/examples/doc/multilanguage.qdoc index 27afb9d02b2..e749ab59675 100644 --- a/doc/qtdesignstudio/examples/doc/multilanguage.qdoc +++ b/doc/qtdesignstudio/examples/doc/multilanguage.qdoc @@ -39,8 +39,8 @@ translations from a JSON file. You need to download the starting project for this tutorial from - \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/examples/ - loginui2}{here} before you start. + \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/multi-language%20tutorial/Loginui2}{here} + before you start. Download the project and open the \e loginui2.qmlproject file in \QDS to get started. @@ -48,8 +48,7 @@ This project consists of a login page with a couple of text elements. Additionally, you will use a JSON translation file in this tutorial. - Download it from \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/ - master/tutorial%20projects/multi-language}{here}. + Download it from \l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/multi-language}{here}. \section1 JSON Translation File @@ -133,10 +132,11 @@ First, you need to prepare your project for translation: \list 1 + \li In \uicontrol{Projects}, double-click \e{Screen01.ui.qml} to open it. \li All text strings that you want to translate need to be of \c qsTrId type. In this project the text strings are of \c qsTr type so you need to change them. Open \uicontrol{Text Editor}, find all five - occurrences of \c QsTr and replace them with \c{QsTrId}. For example, + occurrences of \c qsTr and replace them with \c{qsTrId}. For example, replace: \code text: qsTr("Qt Account") @@ -165,21 +165,14 @@ \li Go to \uicontrol View > \uicontrol Views and select \uicontrol Translations to open the \uicontrol Translations view. You can drag it to a workspace to dock it. - - When you open the \uicontrol Translations view for the first time, \QDS - prompts you to enable the multi-language database, select - \uicontrol{Yes}. - \image enable-multilanguage.png \li In \uicontrol Translations, select \inlineimage icons/select-languages.png . - - When you enable the multi-language database, an SQLite database named - \e translations.db is created in the project folder root. \li Select the languages that you want to support in your project, in this case \uicontrol{English - American English} and - \uicontrol{Swedish}. - \li Set \uicontrol English as primary language and select \uicontrol{OK}. + \uicontrol{Swedish - Svenska}. + \li Set \uicontrol{English - American English} as primary language and + select \uicontrol{Ok}. \li Select \inlineimage icons/import-json-translations.png and open the \e ml_translations.json file. Now you can see all your imported translations in the \uicontrol Translations view. diff --git a/doc/qtdesignstudio/examples/loginui1/EntryField.ui.qml b/doc/qtdesignstudio/examples/loginui1/content/EntryField.ui.qml similarity index 93% rename from doc/qtdesignstudio/examples/loginui1/EntryField.ui.qml rename to doc/qtdesignstudio/examples/loginui1/content/EntryField.ui.qml index 4232d16445b..02b4ce8d183 100644 --- a/doc/qtdesignstudio/examples/loginui1/EntryField.ui.qml +++ b/doc/qtdesignstudio/examples/loginui1/content/EntryField.ui.qml @@ -1,8 +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 the examples of the Qt Design Studio. @@ -49,6 +47,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + import QtQuick 2.15 import QtQuick.Controls 2.12 @@ -100,13 +99,16 @@ Button { when: !control.down PropertyChanges { - target: textItem - font.family: "Titillium Web ExtraLight" + target: buttonBackground + color: "#00000000" + border.color: "#ffffff" } PropertyChanges { - target: buttonBackground - color: "#28e7e7e7" + target: textItem + color: "#ffffff" + font.pixelSize: 34 + font.family: "Titillium Web ExtraLight" } }, State { @@ -115,12 +117,14 @@ Button { PropertyChanges { target: textItem color: "#ffffff" + border.color: "#ffffff" + font.family: "Titillium Web ExtraLight" } PropertyChanges { target: buttonBackground - color: "#e7e7e7" - border.color: "#ffffff" + color: "#28e7e7e7" + border.color: "#00000000" } } ] diff --git a/doc/qtdesignstudio/examples/loginui1/PushButton.ui.qml b/doc/qtdesignstudio/examples/loginui1/content/PushButton.ui.qml similarity index 88% rename from doc/qtdesignstudio/examples/loginui1/PushButton.ui.qml rename to doc/qtdesignstudio/examples/loginui1/content/PushButton.ui.qml index 3a0871f4fc8..cfd617703c8 100644 --- a/doc/qtdesignstudio/examples/loginui1/PushButton.ui.qml +++ b/doc/qtdesignstudio/examples/loginui1/content/PushButton.ui.qml @@ -1,8 +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 the examples of the Qt Design Studio. @@ -49,6 +47,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + import QtQuick 2.15 import QtQuick.Controls 2.12 @@ -68,6 +67,7 @@ Button { text: "My Button" hoverEnabled: false + enabled: true background: buttonBackground Rectangle { @@ -83,6 +83,8 @@ Button { contentItem: textItem Text { id: textItem + width: 500 + height: 100 text: control.text font.pixelSize: 34 @@ -101,6 +103,14 @@ Button { PropertyChanges { target: buttonBackground color: "#00000000" + border.color: "#41cd52" + } + + PropertyChanges { + target: textItem + color: "#41cd52" + font.pixelSize: 34 + font.family: "Titillium Web ExtraLight" } }, State { @@ -108,20 +118,17 @@ Button { when: control.down PropertyChanges { target: textItem - color: "#ffffff" + color: "#41cd52" + border.color: "#41cd52" + font.pixelSize: 34 + font.family: "Titillium Web ExtraLight" } PropertyChanges { target: buttonBackground color: "#41cd52" - border.color: "#00000000" + border.color: "#41cd52" } } ] } - -/*##^## -Designer { - D{i:0;height:100;width:500} -} -##^##*/ diff --git a/doc/qtdesignstudio/examples/loginui1/Screen01.ui.qml b/doc/qtdesignstudio/examples/loginui1/content/Screen01.ui.qml similarity index 89% rename from doc/qtdesignstudio/examples/loginui1/Screen01.ui.qml rename to doc/qtdesignstudio/examples/loginui1/content/Screen01.ui.qml index 9fbbf7fb090..de16a1ba014 100644 --- a/doc/qtdesignstudio/examples/loginui1/Screen01.ui.qml +++ b/doc/qtdesignstudio/examples/loginui1/content/Screen01.ui.qml @@ -1,8 +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 the examples of the Qt Design Studio. @@ -49,9 +47,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + import QtQuick import QtQuick.Controls -import loginui1 1.0 +import Loginui1 Rectangle { width: Constants.width @@ -70,47 +69,44 @@ Rectangle { Image { id: qt_logo_green_128x128px x: 296 - y: 40 + y: 0 source: "images/qt_logo_green_128x128px.png" fillMode: Image.PreserveAspectFit } Text { - id: tagLine - width: 541 - height: 78 color: "#ffffff" text: qsTr("Are you ready to explore?") font.pixelSize: 50 font.family: "Titillium Web ExtraLight" - anchors.verticalCenterOffset: -391 - anchors.horizontalCenterOffset: 18 + anchors.verticalCenterOffset: -430 + anchors.horizontalCenterOffset: 0 anchors.centerIn: parent } EntryField { id: username - x: 128 + x: 110 y: 470 - text: "Username or Email" + text: qsTr("Username or Email") } EntryField { id: password - x: 128 + x: 110 y: 590 text: qsTr("Password") } PushButton { id: login - x: 102 - y: 966 + x: 101 + y: 944 text: qsTr("Continue") } PushButton { - id: createAccount - x: 102 + id: creteAccount + x: 101 y: 1088 text: qsTr("Create Account") } @@ -118,7 +114,7 @@ Rectangle { /*##^## Designer { - D{i:0;formeditorZoom:0.33} + D{i:0;formeditorZoom:0.5}D{i:1}D{i:2}D{i:3}D{i:4}D{i:5}D{i:6}D{i:7} } ##^##*/ diff --git a/doc/qtdesignstudio/examples/loginui1/images/adventurePage.jpg b/doc/qtdesignstudio/examples/loginui1/content/images/adventurePage.jpg similarity index 100% rename from doc/qtdesignstudio/examples/loginui1/images/adventurePage.jpg rename to doc/qtdesignstudio/examples/loginui1/content/images/adventurePage.jpg diff --git a/doc/qtdesignstudio/examples/loginui1/content/images/qt_logo_green_128x128px.png b/doc/qtdesignstudio/examples/loginui1/content/images/qt_logo_green_128x128px.png new file mode 100644 index 00000000000..2f3c7550774 Binary files /dev/null and b/doc/qtdesignstudio/examples/loginui1/content/images/qt_logo_green_128x128px.png differ diff --git a/doc/qtdesignstudio/examples/loginui1/images/qt_logo_green_128x128px.png b/doc/qtdesignstudio/examples/loginui1/images/qt_logo_green_128x128px.png deleted file mode 100644 index 1a002353a55..00000000000 Binary files a/doc/qtdesignstudio/examples/loginui1/images/qt_logo_green_128x128px.png and /dev/null differ diff --git a/doc/qtdesignstudio/examples/loginui1/imports/loginui1/EventListModel.qml b/doc/qtdesignstudio/examples/loginui1/imports/loginui1/EventListModel.qml new file mode 100644 index 00000000000..b213175da8f --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui1/imports/loginui1/EventListModel.qml @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Quick Designer Components. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick + +ListModel { + id: eventListModel + + ListElement { + eventId: "enterPressed" + eventDescription: "Emitted when pressing the enter button" + shortcut: "Return" + parameters: "Enter" + } +} diff --git a/doc/qtdesignstudio/examples/loginui1/imports/loginui1/EventListSimulator.qml b/doc/qtdesignstudio/examples/loginui1/imports/loginui1/EventListSimulator.qml new file mode 100644 index 00000000000..a7d0fd5b772 --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui1/imports/loginui1/EventListSimulator.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Quick Designer Components. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Studio.EventSimulator 1.0 +import QtQuick.Studio.EventSystem 1.0 + +QtObject { + id: simulator + property bool active: true + + property Timer __timer: Timer { + id: timer + interval: 100 + onTriggered: { + EventSimulator.show() + } + } + + Component.onCompleted: { + EventSystem.init(Qt.resolvedUrl("EventListModel.qml")) + if (simulator.active) + timer.start() + } +} diff --git a/doc/qtdesignstudio/examples/loginui1/imports/loginui1/qmldir b/doc/qtdesignstudio/examples/loginui1/imports/loginui1/qmldir index 69846237302..e96c109449c 100644 --- a/doc/qtdesignstudio/examples/loginui1/imports/loginui1/qmldir +++ b/doc/qtdesignstudio/examples/loginui1/imports/loginui1/qmldir @@ -1,2 +1,6 @@ +Module Loginui1 singleton Constants 1.0 Constants.qml EventListSimulator 1.0 EventListSimulator.qml +EventListModel 1.0 EventListModel.qml +DirectoryFontLoader 1.0 DirectoryFontLoader.qml + diff --git a/doc/qtdesignstudio/examples/loginui1/loginui1.qml b/doc/qtdesignstudio/examples/loginui1/loginui1.qml deleted file mode 100644 index 68ded96dd7b..00000000000 --- a/doc/qtdesignstudio/examples/loginui1/loginui1.qml +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Design Studio. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick -import loginui1 1.0 - -Item { - width: Constants.width - height: Constants.height - - Screen01 { - } - -} diff --git a/doc/qtdesignstudio/examples/loginui1/loginui1.qmlproject b/doc/qtdesignstudio/examples/loginui1/loginui1.qmlproject index a11e3d77c75..5b34751fa51 100644 --- a/doc/qtdesignstudio/examples/loginui1/loginui1.qmlproject +++ b/doc/qtdesignstudio/examples/loginui1/loginui1.qmlproject @@ -1,21 +1,69 @@ -/* File generated by Qt Creator */ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Design Studio. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ -import QmlProject 1.1 +import QmlProject Project { - mainFile: "loginui1.qml" + mainFile: "content/App.qml" /* Include .qml, .js, and image files from current directory and subdirectories */ QmlFiles { - directory: "." + directory: "content" } JavaScriptFiles { - directory: "." + directory: "content" } ImageFiles { - directory: "." + directory: "content" } Files { @@ -32,9 +80,34 @@ Project { filter: "*.ttf;*.otf" } + Files { + filter: "*.wav;*.mp3" + } + + Files { + filter: "*.mp4" + } + + Files { + filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag" + } + + Files { + filter: "*.mesh" + directory: "asset_imports" + } + Environment { QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" QT_AUTO_SCREEN_SCALE_FACTOR: "1" + QT_LOGGING_RULES: "qt.qml.connections=false" + QT_ENABLE_HIGHDPI_SCALING: "0" + /* Useful for debugging + QSG_VISUALIZE=batches + QSG_VISUALIZE=clip + QSG_VISUALIZE=changes + QSG_VISUALIZE=overdraw + */ } qt6Project: true @@ -43,5 +116,10 @@ Project { importPaths: [ "imports", "asset_imports" ] /* Required for deployment */ - targetDirectory: "/opt/loginui1" + targetDirectory: "/opt/Loginui1" + + qdsVersion: "3.0" + + /* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */ + widgetApp: true } diff --git a/doc/qtdesignstudio/examples/loginui1/qtquickcontrols2.conf b/doc/qtdesignstudio/examples/loginui1/qtquickcontrols2.conf deleted file mode 100644 index 75b2cb8fffb..00000000000 --- a/doc/qtdesignstudio/examples/loginui1/qtquickcontrols2.conf +++ /dev/null @@ -1,6 +0,0 @@ -; This file can be edited to change the style of the application -; Read "Qt Quick Controls 2 Configuration File" for details: -; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html - -[Controls] -Style=Default diff --git a/doc/qtdesignstudio/examples/loginui4/loginui4.qml b/doc/qtdesignstudio/examples/loginui1/src/app_environment.h similarity index 85% rename from doc/qtdesignstudio/examples/loginui4/loginui4.qml rename to doc/qtdesignstudio/examples/loginui1/src/app_environment.h index 6ce943cc3da..5961a217045 100644 --- a/doc/qtdesignstudio/examples/loginui4/loginui4.qml +++ b/doc/qtdesignstudio/examples/loginui1/src/app_environment.h @@ -1,6 +1,11 @@ +/* + * This file is automatically generated by Qt Design Studio. + * Do not change. +*/ + /**************************************************************************** ** -** 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 the examples of the Qt Design Studio. @@ -48,14 +53,12 @@ ** ****************************************************************************/ -import QtQuick -import loginui4 1.0 - -Item { - width: Constants.width - height: Constants.height - - Screen01 { - } +#include +void set_qt_environment() +{ + qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1"); + qputenv("QT_ENABLE_HIGHDPI_SCALING", "0"); + qputenv("QT_LOGGING_RULES", "qt.qml.connections=false"); + qputenv("QT_QUICK_CONTROLS_CONF", ":/qtquickcontrols2.conf"); } diff --git a/doc/qtdesignstudio/examples/loginui1/src/import_qml_plugins.h b/doc/qtdesignstudio/examples/loginui1/src/import_qml_plugins.h new file mode 100644 index 00000000000..18e0e769915 --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui1/src/import_qml_plugins.h @@ -0,0 +1,9 @@ +/* + * This file is automatically generated by Qt Design Studio. + * Do not change. +*/ + +#include + +Q_IMPORT_QML_PLUGIN(contentPlugin) +Q_IMPORT_QML_PLUGIN(Loginui1Plugin) diff --git a/doc/qtdesignstudio/examples/loginui1/src/main.cpp b/doc/qtdesignstudio/examples/loginui1/src/main.cpp new file mode 100644 index 00000000000..aaf18173a1a --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui1/src/main.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Quick Studio Components. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "app_environment.h" +#include "import_qml_plugins.h" + +int main(int argc, char *argv[]) +{ + set_qt_environment(); + + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + const QUrl url(u"qrc:Main/main.qml"_qs); + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreated, &app, + [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, + Qt::QueuedConnection); + + engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml"); + engine.addImportPath(":/"); + + engine.load(url); + + if (engine.rootObjects().isEmpty()) { + return -1; + } + + return app.exec(); +} diff --git a/doc/qtdesignstudio/examples/loginui2/Loginui2.qmlproject b/doc/qtdesignstudio/examples/loginui2/Loginui2.qmlproject new file mode 100644 index 00000000000..467ccd3c545 --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui2/Loginui2.qmlproject @@ -0,0 +1,75 @@ +import QmlProject + +Project { + mainFile: "content/App.qml" + + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "content" + } + + JavaScriptFiles { + directory: "content" + } + + ImageFiles { + directory: "content" + } + + Files { + filter: "*.conf" + files: ["qtquickcontrols2.conf"] + } + + Files { + filter: "qmldir" + directory: "." + } + + Files { + filter: "*.ttf;*.otf" + } + + Files { + filter: "*.wav;*.mp3" + } + + Files { + filter: "*.mp4" + } + + Files { + filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag" + } + + Files { + filter: "*.mesh" + directory: "asset_imports" + } + + Environment { + QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" + QT_AUTO_SCREEN_SCALE_FACTOR: "1" + QT_LOGGING_RULES: "qt.qml.connections=false" + QT_ENABLE_HIGHDPI_SCALING: "0" + /* Useful for debugging + QSG_VISUALIZE=batches + QSG_VISUALIZE=clip + QSG_VISUALIZE=changes + QSG_VISUALIZE=overdraw + */ + } + + qt6Project: true + + /* List of plugin directories passed to QML runtime */ + importPaths: [ "imports", "asset_imports" ] + + /* Required for deployment */ + targetDirectory: "/opt/Loginui1" + + qdsVersion: "3.0" + + /* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */ + widgetApp: true +} diff --git a/doc/qtdesignstudio/examples/loginui2/Screen01.ui.qml b/doc/qtdesignstudio/examples/loginui2/content/Screen01.ui.qml similarity index 92% rename from doc/qtdesignstudio/examples/loginui2/Screen01.ui.qml rename to doc/qtdesignstudio/examples/loginui2/content/Screen01.ui.qml index 6466b19bd06..c806c43034a 100644 --- a/doc/qtdesignstudio/examples/loginui2/Screen01.ui.qml +++ b/doc/qtdesignstudio/examples/loginui2/content/Screen01.ui.qml @@ -1,8 +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 the examples of the Qt Design Studio. @@ -49,9 +47,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + import QtQuick import QtQuick.Controls -import loginui2 1.0 +import Loginui1 Rectangle { id: rectangle @@ -69,7 +68,6 @@ Rectangle { Image { id: qt_logo_green_128x128px - x: 296 anchors.top: parent.top source: "images/qt_logo_green_128x128px.png" anchors.horizontalCenter: parent.horizontalCenter @@ -78,8 +76,6 @@ Rectangle { } Text { id: tagLine - width: 541 - height: 78 color: "#ffffff" text: qsTr("Are you ready to explore?") anchors.top: qt_logo_green_128x128px.bottom @@ -87,11 +83,11 @@ Rectangle { anchors.topMargin: 40 anchors.horizontalCenter: parent.horizontalCenter font.family: "Titillium Web ExtraLight" + anchors.horizontalCenterOffset: 0 } Column { id: fields - x: 128 anchors.top: tagLine.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 170 @@ -99,7 +95,7 @@ Rectangle { EntryField { id: username - text: "Username or Email" + text: qsTr("Username or Email") } EntryField { @@ -110,11 +106,10 @@ Rectangle { Column { id: buttons - x: 102 - y: 966 + y: 944 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter - anchors.bottomMargin: 100 + anchors.bottomMargin: 50 spacing: 20 PushButton { @@ -123,7 +118,7 @@ Rectangle { } PushButton { - id: createAccount + id: creteAccount text: qsTr("Create Account") } } @@ -131,7 +126,7 @@ Rectangle { /*##^## Designer { - D{i:0;formeditorZoom:0.5}D{i:1}D{i:2}D{i:4} + D{i:0;formeditorZoom:0.66}D{i:1}D{i:2}D{i:3}D{i:5}D{i:6}D{i:4}D{i:8}D{i:9}D{i:7} } ##^##*/ diff --git a/doc/qtdesignstudio/examples/loginui2/imports/loginui2/Constants.qml b/doc/qtdesignstudio/examples/loginui2/imports/loginui2/Constants.qml deleted file mode 100644 index 6fef815fa14..00000000000 --- a/doc/qtdesignstudio/examples/loginui2/imports/loginui2/Constants.qml +++ /dev/null @@ -1,26 +0,0 @@ -pragma Singleton -import QtQuick - -QtObject { - readonly property int width: 720 - readonly property int height: 1280 - - property alias fontDirectory: directoryFontLoader.fontDirectory - property alias relativeFontDirectory: directoryFontLoader.relativeFontDirectory - - /* Edit this comment to add your custom font */ - readonly property font font: Qt.font({ - family: Qt.application.font.family, - pixelSize: Qt.application.font.pixelSize - }) - readonly property font largeFont: Qt.font({ - family: Qt.application.font.family, - pixelSize: Qt.application.font.pixelSize * 1.6 - }) - - readonly property color backgroundColor: "#c2c2c2" - - property DirectoryFontLoader directoryFontLoader: DirectoryFontLoader { - id: directoryFontLoader - } -} diff --git a/doc/qtdesignstudio/examples/loginui2/imports/loginui2/qmldir b/doc/qtdesignstudio/examples/loginui2/imports/loginui2/qmldir deleted file mode 100644 index 69846237302..00000000000 --- a/doc/qtdesignstudio/examples/loginui2/imports/loginui2/qmldir +++ /dev/null @@ -1,2 +0,0 @@ -singleton Constants 1.0 Constants.qml -EventListSimulator 1.0 EventListSimulator.qml diff --git a/doc/qtdesignstudio/examples/loginui2/loginui2.qml b/doc/qtdesignstudio/examples/loginui2/loginui2.qml deleted file mode 100644 index 127e947a1c5..00000000000 --- a/doc/qtdesignstudio/examples/loginui2/loginui2.qml +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Design Studio. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick -import loginui2 1.0 - -Item { - width: Constants.width - height: Constants.height - - Screen01 { - } - -} diff --git a/doc/qtdesignstudio/examples/loginui2/loginui2.qmlproject b/doc/qtdesignstudio/examples/loginui2/loginui2.qmlproject deleted file mode 100644 index 7d9e775731f..00000000000 --- a/doc/qtdesignstudio/examples/loginui2/loginui2.qmlproject +++ /dev/null @@ -1,47 +0,0 @@ -/* File generated by Qt Creator */ - -import QmlProject 1.1 - -Project { - mainFile: "loginui2.qml" - - /* Include .qml, .js, and image files from current directory and subdirectories */ - QmlFiles { - directory: "." - } - - JavaScriptFiles { - directory: "." - } - - ImageFiles { - directory: "." - } - - Files { - filter: "*.conf" - files: ["qtquickcontrols2.conf"] - } - - Files { - filter: "qmldir" - directory: "." - } - - Files { - filter: "*.ttf;*.otf" - } - - Environment { - QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" - QT_AUTO_SCREEN_SCALE_FACTOR: "1" - } - - qt6Project: true - - /* List of plugin directories passed to QML runtime */ - importPaths: [ "imports", "asset_imports" ] - - /* Required for deployment */ - targetDirectory: "/opt/loginui1" -} diff --git a/doc/qtdesignstudio/examples/loginui2/qtquickcontrols2.conf b/doc/qtdesignstudio/examples/loginui2/qtquickcontrols2.conf deleted file mode 100644 index 75b2cb8fffb..00000000000 --- a/doc/qtdesignstudio/examples/loginui2/qtquickcontrols2.conf +++ /dev/null @@ -1,6 +0,0 @@ -; This file can be edited to change the style of the application -; Read "Qt Quick Controls 2 Configuration File" for details: -; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html - -[Controls] -Style=Default diff --git a/doc/qtdesignstudio/examples/loginui3/Loginui3.qmlproject b/doc/qtdesignstudio/examples/loginui3/Loginui3.qmlproject new file mode 100644 index 00000000000..467ccd3c545 --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui3/Loginui3.qmlproject @@ -0,0 +1,75 @@ +import QmlProject + +Project { + mainFile: "content/App.qml" + + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "content" + } + + JavaScriptFiles { + directory: "content" + } + + ImageFiles { + directory: "content" + } + + Files { + filter: "*.conf" + files: ["qtquickcontrols2.conf"] + } + + Files { + filter: "qmldir" + directory: "." + } + + Files { + filter: "*.ttf;*.otf" + } + + Files { + filter: "*.wav;*.mp3" + } + + Files { + filter: "*.mp4" + } + + Files { + filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag" + } + + Files { + filter: "*.mesh" + directory: "asset_imports" + } + + Environment { + QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" + QT_AUTO_SCREEN_SCALE_FACTOR: "1" + QT_LOGGING_RULES: "qt.qml.connections=false" + QT_ENABLE_HIGHDPI_SCALING: "0" + /* Useful for debugging + QSG_VISUALIZE=batches + QSG_VISUALIZE=clip + QSG_VISUALIZE=changes + QSG_VISUALIZE=overdraw + */ + } + + qt6Project: true + + /* List of plugin directories passed to QML runtime */ + importPaths: [ "imports", "asset_imports" ] + + /* Required for deployment */ + targetDirectory: "/opt/Loginui1" + + qdsVersion: "3.0" + + /* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */ + widgetApp: true +} diff --git a/doc/qtdesignstudio/examples/loginui3/Screen01.ui.qml b/doc/qtdesignstudio/examples/loginui3/content/Screen01.ui.qml similarity index 93% rename from doc/qtdesignstudio/examples/loginui3/Screen01.ui.qml rename to doc/qtdesignstudio/examples/loginui3/content/Screen01.ui.qml index 28131577351..55bf71619d7 100644 --- a/doc/qtdesignstudio/examples/loginui3/Screen01.ui.qml +++ b/doc/qtdesignstudio/examples/loginui3/content/Screen01.ui.qml @@ -1,8 +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 the examples of the Qt Design Studio. @@ -49,9 +47,10 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + import QtQuick import QtQuick.Controls -import loginui3 1.0 +import Loginui1 Rectangle { id: rectangle @@ -70,7 +69,6 @@ Rectangle { Image { id: qt_logo_green_128x128px - x: 296 anchors.top: parent.top source: "images/qt_logo_green_128x128px.png" anchors.horizontalCenter: parent.horizontalCenter @@ -79,8 +77,6 @@ Rectangle { } Text { id: tagLine - width: 541 - height: 78 color: "#ffffff" text: qsTr("Are you ready to explore?") anchors.top: qt_logo_green_128x128px.bottom @@ -88,11 +84,11 @@ Rectangle { anchors.topMargin: 40 anchors.horizontalCenter: parent.horizontalCenter font.family: "Titillium Web ExtraLight" + anchors.horizontalCenterOffset: 0 } Column { id: fields - x: 128 anchors.top: tagLine.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 170 @@ -100,7 +96,7 @@ Rectangle { EntryField { id: username - text: "Username or Email" + text: qsTr("Username or Email") } EntryField { @@ -110,17 +106,16 @@ Rectangle { EntryField { id: repeatPassword - text: "Repeat Password" + text: qsTr("Repeat Password") } } Column { id: buttons - x: 102 - y: 966 + y: 944 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter - anchors.bottomMargin: 100 + anchors.bottomMargin: 50 spacing: 20 PushButton { @@ -160,7 +155,8 @@ Rectangle { /*##^## Designer { - D{i:0;formeditorZoom:0.5} + D{i:0;formeditorZoom:0.5}D{i:1}D{i:2}D{i:3}D{i:5}D{i:6}D{i:7}D{i:4}D{i:9}D{i:11}D{i:10} +D{i:8} } ##^##*/ diff --git a/doc/qtdesignstudio/examples/loginui3/imports/loginui3/Constants.qml b/doc/qtdesignstudio/examples/loginui3/imports/loginui3/Constants.qml deleted file mode 100644 index 6fef815fa14..00000000000 --- a/doc/qtdesignstudio/examples/loginui3/imports/loginui3/Constants.qml +++ /dev/null @@ -1,26 +0,0 @@ -pragma Singleton -import QtQuick - -QtObject { - readonly property int width: 720 - readonly property int height: 1280 - - property alias fontDirectory: directoryFontLoader.fontDirectory - property alias relativeFontDirectory: directoryFontLoader.relativeFontDirectory - - /* Edit this comment to add your custom font */ - readonly property font font: Qt.font({ - family: Qt.application.font.family, - pixelSize: Qt.application.font.pixelSize - }) - readonly property font largeFont: Qt.font({ - family: Qt.application.font.family, - pixelSize: Qt.application.font.pixelSize * 1.6 - }) - - readonly property color backgroundColor: "#c2c2c2" - - property DirectoryFontLoader directoryFontLoader: DirectoryFontLoader { - id: directoryFontLoader - } -} diff --git a/doc/qtdesignstudio/examples/loginui3/imports/loginui3/qmldir b/doc/qtdesignstudio/examples/loginui3/imports/loginui3/qmldir deleted file mode 100644 index 69846237302..00000000000 --- a/doc/qtdesignstudio/examples/loginui3/imports/loginui3/qmldir +++ /dev/null @@ -1,2 +0,0 @@ -singleton Constants 1.0 Constants.qml -EventListSimulator 1.0 EventListSimulator.qml diff --git a/doc/qtdesignstudio/examples/loginui3/loginui3.qml b/doc/qtdesignstudio/examples/loginui3/loginui3.qml deleted file mode 100644 index ea8b947d3ce..00000000000 --- a/doc/qtdesignstudio/examples/loginui3/loginui3.qml +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Design Studio. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick -import loginui3 1.0 - -Item { - width: Constants.width - height: Constants.height - - Screen01 { - } - -} diff --git a/doc/qtdesignstudio/examples/loginui3/loginui3.qmlproject b/doc/qtdesignstudio/examples/loginui3/loginui3.qmlproject deleted file mode 100644 index 3015de6092e..00000000000 --- a/doc/qtdesignstudio/examples/loginui3/loginui3.qmlproject +++ /dev/null @@ -1,47 +0,0 @@ -/* File generated by Qt Creator */ - -import QmlProject 1.1 - -Project { - mainFile: "loginui3.qml" - - /* Include .qml, .js, and image files from current directory and subdirectories */ - QmlFiles { - directory: "." - } - - JavaScriptFiles { - directory: "." - } - - ImageFiles { - directory: "." - } - - Files { - filter: "*.conf" - files: ["qtquickcontrols2.conf"] - } - - Files { - filter: "qmldir" - directory: "." - } - - Files { - filter: "*.ttf;*.otf" - } - - Environment { - QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" - QT_AUTO_SCREEN_SCALE_FACTOR: "1" - } - - qt6Project: true - - /* List of plugin directories passed to QML runtime */ - importPaths: [ "imports", "asset_imports" ] - - /* Required for deployment */ - targetDirectory: "/opt/loginui1" -} diff --git a/doc/qtdesignstudio/examples/loginui3/qtquickcontrols2.conf b/doc/qtdesignstudio/examples/loginui3/qtquickcontrols2.conf deleted file mode 100644 index caace6db8e4..00000000000 --- a/doc/qtdesignstudio/examples/loginui3/qtquickcontrols2.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Controls] -Style=Default diff --git a/doc/qtdesignstudio/examples/loginui4/Loginui4.qmlproject b/doc/qtdesignstudio/examples/loginui4/Loginui4.qmlproject new file mode 100644 index 00000000000..467ccd3c545 --- /dev/null +++ b/doc/qtdesignstudio/examples/loginui4/Loginui4.qmlproject @@ -0,0 +1,75 @@ +import QmlProject + +Project { + mainFile: "content/App.qml" + + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "content" + } + + JavaScriptFiles { + directory: "content" + } + + ImageFiles { + directory: "content" + } + + Files { + filter: "*.conf" + files: ["qtquickcontrols2.conf"] + } + + Files { + filter: "qmldir" + directory: "." + } + + Files { + filter: "*.ttf;*.otf" + } + + Files { + filter: "*.wav;*.mp3" + } + + Files { + filter: "*.mp4" + } + + Files { + filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag" + } + + Files { + filter: "*.mesh" + directory: "asset_imports" + } + + Environment { + QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" + QT_AUTO_SCREEN_SCALE_FACTOR: "1" + QT_LOGGING_RULES: "qt.qml.connections=false" + QT_ENABLE_HIGHDPI_SCALING: "0" + /* Useful for debugging + QSG_VISUALIZE=batches + QSG_VISUALIZE=clip + QSG_VISUALIZE=changes + QSG_VISUALIZE=overdraw + */ + } + + qt6Project: true + + /* List of plugin directories passed to QML runtime */ + importPaths: [ "imports", "asset_imports" ] + + /* Required for deployment */ + targetDirectory: "/opt/Loginui1" + + qdsVersion: "3.0" + + /* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */ + widgetApp: true +} diff --git a/doc/qtdesignstudio/examples/loginui4/Screen01.ui.qml b/doc/qtdesignstudio/examples/loginui4/content/Screen01.ui.qml similarity index 53% rename from doc/qtdesignstudio/examples/loginui4/Screen01.ui.qml rename to doc/qtdesignstudio/examples/loginui4/content/Screen01.ui.qml index e919f39d82e..fa8377b980f 100644 --- a/doc/qtdesignstudio/examples/loginui4/Screen01.ui.qml +++ b/doc/qtdesignstudio/examples/loginui4/content/Screen01.ui.qml @@ -1,57 +1,6 @@ - - -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Design Studio. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ import QtQuick import QtQuick.Controls -import loginui4 1.0 +import Loginui1 import QtQuick.Timeline 1.0 Rectangle { @@ -71,7 +20,6 @@ Rectangle { Image { id: qt_logo_green_128x128px - x: 296 anchors.top: parent.top source: "images/qt_logo_green_128x128px.png" anchors.horizontalCenter: parent.horizontalCenter @@ -80,8 +28,6 @@ Rectangle { } Text { id: tagLine - width: 541 - height: 78 color: "#ffffff" text: qsTr("Are you ready to explore?") anchors.top: qt_logo_green_128x128px.bottom @@ -89,30 +35,29 @@ Rectangle { anchors.topMargin: 40 anchors.horizontalCenter: parent.horizontalCenter font.family: "Titillium Web ExtraLight" + anchors.horizontalCenterOffset: 0 } EntryField { id: username - x: 110 - text: "Username or Email" + text: qsTr("Username or Email") anchors.top: tagLine.bottom - anchors.topMargin: 170 anchors.horizontalCenter: parent.horizontalCenter + anchors.topMargin: 170 } EntryField { id: password - x: 110 text: qsTr("Password") anchors.top: username.bottom anchors.horizontalCenter: parent.horizontalCenter - anchors.topMargin: 20 + anchors.topMargin: 21 } EntryField { id: repeatPassword - x: 110 - text: "Repeat Password" + opacity: 0 + text: qsTr("Repeat Password") anchors.top: password.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20 @@ -120,11 +65,10 @@ Rectangle { Column { id: buttons - x: 102 - y: 966 + y: 944 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter - anchors.bottomMargin: 100 + anchors.bottomMargin: 50 spacing: 20 PushButton { @@ -148,70 +92,68 @@ Rectangle { animations: [ TimelineAnimation { id: toCreateAccountState + duration: 1000 running: false loops: 1 - duration: 1000 to: 1000 from: 0 } ] endFrame: 1000 - startFrame: 0 enabled: true + startFrame: 0 KeyframeGroup { target: repeatPassword property: "opacity" - Keyframe { - frame: 0 value: 0 + frame: 0 } Keyframe { - frame: 999 value: 1 + frame: 1000 } } KeyframeGroup { target: createAccount property: "opacity" + Keyframe { + value: 1 + frame: 0 + } Keyframe { - frame: 1000 value: 0 + frame: 1000 } } KeyframeGroup { target: repeatPassword property: "anchors.topMargin" - Keyframe { + value: -100 frame: 0 - value: -40 } Keyframe { - easing.bezierCurve: [0.39,0.575,0.565,1,1,1] - frame: 999 + value: -100 + frame: 4 + } + + Keyframe { + easing.bezierCurve: [0.39, 0.575, 0.565, 1, 1, 1] value: 20 + frame: 999 } } } states: [ State { name: "login" - - PropertyChanges { - target: timeline - enabled: true - } - - PropertyChanges { - target: toCreateAccountState - } }, State { name: "createAccount" @@ -231,6 +173,8 @@ Rectangle { /*##^## Designer { - D{i:0;formeditorZoom:0.5}D{i:6}D{i:9}D{i:11} + D{i:0;formeditorZoom:0.5}D{i:1}D{i:2}D{i:3}D{i:4}D{i:5}D{i:6}D{i:8}D{i:10}D{i:9}D{i:7} +D{i:11} } ##^##*/ + diff --git a/doc/qtdesignstudio/examples/loginui4/imports/loginui4/Constants.qml b/doc/qtdesignstudio/examples/loginui4/imports/loginui4/Constants.qml deleted file mode 100644 index 6fef815fa14..00000000000 --- a/doc/qtdesignstudio/examples/loginui4/imports/loginui4/Constants.qml +++ /dev/null @@ -1,26 +0,0 @@ -pragma Singleton -import QtQuick - -QtObject { - readonly property int width: 720 - readonly property int height: 1280 - - property alias fontDirectory: directoryFontLoader.fontDirectory - property alias relativeFontDirectory: directoryFontLoader.relativeFontDirectory - - /* Edit this comment to add your custom font */ - readonly property font font: Qt.font({ - family: Qt.application.font.family, - pixelSize: Qt.application.font.pixelSize - }) - readonly property font largeFont: Qt.font({ - family: Qt.application.font.family, - pixelSize: Qt.application.font.pixelSize * 1.6 - }) - - readonly property color backgroundColor: "#c2c2c2" - - property DirectoryFontLoader directoryFontLoader: DirectoryFontLoader { - id: directoryFontLoader - } -} diff --git a/doc/qtdesignstudio/examples/loginui4/imports/loginui4/qmldir b/doc/qtdesignstudio/examples/loginui4/imports/loginui4/qmldir deleted file mode 100644 index 69846237302..00000000000 --- a/doc/qtdesignstudio/examples/loginui4/imports/loginui4/qmldir +++ /dev/null @@ -1,2 +0,0 @@ -singleton Constants 1.0 Constants.qml -EventListSimulator 1.0 EventListSimulator.qml diff --git a/doc/qtdesignstudio/examples/loginui4/loginui4.qmlproject b/doc/qtdesignstudio/examples/loginui4/loginui4.qmlproject deleted file mode 100644 index 9bb93ec5dd2..00000000000 --- a/doc/qtdesignstudio/examples/loginui4/loginui4.qmlproject +++ /dev/null @@ -1,47 +0,0 @@ -/* File generated by Qt Creator */ - -import QmlProject 1.1 - -Project { - mainFile: "loginui4.qml" - - /* Include .qml, .js, and image files from current directory and subdirectories */ - QmlFiles { - directory: "." - } - - JavaScriptFiles { - directory: "." - } - - ImageFiles { - directory: "." - } - - Files { - filter: "*.conf" - files: ["qtquickcontrols2.conf"] - } - - Files { - filter: "qmldir" - directory: "." - } - - Files { - filter: "*.ttf;*.otf" - } - - Environment { - QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" - QT_AUTO_SCREEN_SCALE_FACTOR: "1" - } - - qt6Project: true - - /* List of plugin directories passed to QML runtime */ - importPaths: [ "imports", "asset_imports" ] - - /* Required for deployment */ - targetDirectory: "/opt/loginui4" -} diff --git a/doc/qtdesignstudio/examples/loginui4/qtquickcontrols2.conf b/doc/qtdesignstudio/examples/loginui4/qtquickcontrols2.conf deleted file mode 100644 index caace6db8e4..00000000000 --- a/doc/qtdesignstudio/examples/loginui4/qtquickcontrols2.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Controls] -Style=Default diff --git a/doc/qtdesignstudio/images/enable-multilanguage.png b/doc/qtdesignstudio/images/enable-multilanguage.png deleted file mode 100644 index ebb528a81a2..00000000000 Binary files a/doc/qtdesignstudio/images/enable-multilanguage.png and /dev/null differ diff --git a/doc/qtdesignstudio/images/studio-translations-view.png b/doc/qtdesignstudio/images/studio-translations-view.png index 454e8ce2a23..d5a843d0df6 100644 Binary files a/doc/qtdesignstudio/images/studio-translations-view.png and b/doc/qtdesignstudio/images/studio-translations-view.png differ diff --git a/doc/qtdesignstudio/images/translation-tester.png b/doc/qtdesignstudio/images/translation-tester.png index 6b1e6f024df..6a3f7441805 100644 Binary files a/doc/qtdesignstudio/images/translation-tester.png and b/doc/qtdesignstudio/images/translation-tester.png differ diff --git a/doc/qtdesignstudio/src/views/studio-translations.qdoc b/doc/qtdesignstudio/src/views/studio-translations.qdoc index 75aaf32179f..c7767d98b8c 100644 --- a/doc/qtdesignstudio/src/views/studio-translations.qdoc +++ b/doc/qtdesignstudio/src/views/studio-translations.qdoc @@ -63,12 +63,14 @@ \li \l{Generating Qt Translation Source Files} \row \li \inlineimage icons/project-translation-test.png - \li Run project translation test. - \li \l{Running the Project Translation Test} + \li Run translation test for several documents and create a test report. + \li \l{Running Translation Test for Several Documents} \row \li \inlineimage icons/qml-translation-test.png - \li Run QML translation test to find missing and elided translations. - \li \l{Running the QML Translation Test} + \li Run translation test for the currently open document. This test + shows translation warnings in \uicontrol{From Editor} and creates a + test report. + \li \l{Running Translation Test for a Single Document} \row \li \inlineimage icons/export-translations.png \li Export all translations used in your project or all translations @@ -93,8 +95,8 @@ "translation": "Password" }, { - "language": "sv", - "translation": "Lösenord" + "language": "fi", + "translation": "Salasana" } ] } @@ -120,8 +122,8 @@ "translation": "Password" }, { - "language": "sv", - "translation": "Lösenord" + "language": "fi", + "translation": "Salasana" } ] \endcode @@ -139,14 +141,14 @@ in the \uicontrol Translations view. The files are generated in \e{/i18n}. - \section1 Running the QML Translation Test + \section1 Running Translation Test for a Single Document - You can run the QML language test to find missing - and elided translations. Running the QML language test - is a quick way to check the translations in the application you have open in - \uicontrol{Form Editor} as it highlights errors in the UI. + You can run the translation test to find missing translations + and translations where the text exceeds the text element boundaries. Running + the test is a quick way to check the translations in the document you have + open in \uicontrol{Form Editor} as it highlights errors in the UI. - To run the QML translation test: + To run the test for the currently open document: \list 1 \li In the \uicontrol Translations view, select @@ -155,12 +157,11 @@ \li Select the tests to run and the highlight color for each test: \list - \li \uicontrol{Show Translation Warnings} highlights missing - translations. - \li \uicontrol{Show Found Translations} highlights all translations - that are correct. - \li \uicontrol{Show Elide Warnings} highlights all translations where - the text is too long to fit in the text object and therefore is elided. + \li \uicontrol{Success} highlights translations without any warnings. + \li \uicontrol{Missing translation} highlights translations that are + missing for one or more languages. + \li \uicontrol{Exceeds boundaries} highlights translations where + the text is too long to fit in the text object. \endlist \image translation-tester.png \li Select \uicontrol{Run Tests}. @@ -205,16 +206,21 @@ The report shows the type of error as well as line and column of the affected text element in the \e{ui.qml} file. - \section1 Running the Project Translation Test + \section1 Running Translation Test for Several Documents You can run the project translation test on several \e{.ui.qml} files at the same time. \QDS runs the same tests as during the - \l{Running the QML Translation Test}{QML Translation Test} and generates the - same test reports but does not highlight errors in the UI. + \l{Running Translation Test for a Single Document}{Translation Test} and + generates the same test reports but does not highlight errors in the UI. - To run the project translation test, select - \inlineimage icons/project-translation-test.png - in the \uicontrol Translations view. + To run the translation test for several documents: + \list 1 + \li Select + \inlineimage icons/project-translation-test.png + in the \uicontrol Translations view. + \li Select the files that you want to include in the test. + \li Select \uicontrol{Run Tests}. + \endlist \section1 Exporting Translations in Other Ways diff --git a/share/qtcreator/android/sdk_definitions.json b/share/qtcreator/android/sdk_definitions.json index f1545c2ad69..56ac6b4f47d 100644 --- a/share/qtcreator/android/sdk_definitions.json +++ b/share/qtcreator/android/sdk_definitions.json @@ -9,7 +9,7 @@ "mac_sha256": "2c3822db1c916655223e5ee8ce0fbf6b73d0b99012045c9dc8eaa6a5736c0c55" }, "sdk_essential_packages": { - "default": ["platform-tools", "platforms;android-30", "cmdline-tools;latest"], + "default": ["platform-tools", "platforms;android-31", "cmdline-tools;latest"], "linux": [], "mac": [], "windows": ["extras;google;usb_driver"] @@ -18,7 +18,12 @@ "specific_qt_versions": [ { "versions": ["default"], - "sdk_essential_packages": ["build-tools;30.0.2", "ndk;21.3.6528147"], + "sdk_essential_packages": ["build-tools;31.0.0", "ndk;22.1.7171670"], + "ndk_path": "ndk/22.1.7171670" + }, + { + "versions": ["5.15.[0-8]", "5.14.[0-2]", "5.13.2"], + "sdk_essential_packages": ["build-tools;31.0.0", "ndk;21.3.6528147"], "ndk_path": "ndk/21.3.6528147" }, { diff --git a/share/qtcreator/debugger/boosttypes.py b/share/qtcreator/debugger/boosttypes.py index c48f64167fa..4cd8409ff8c 100644 --- a/share/qtcreator/debugger/boosttypes.py +++ b/share/qtcreator/debugger/boosttypes.py @@ -185,3 +185,16 @@ def qdump__boost__variant(d, value): dummy, val = value.split('%is{%s}' % (max(4, alignment), realType.name)) d.putItem(val) d.putBetterType(value.type) + + +def qdump__boost__container__devector(d, value): + inner_type = value.type[0] + buffer = value["m_"]["buffer"].pointer() + front_idx = value["m_"]["front_idx"].integer() + back_idx = value["m_"]["back_idx"].integer() + start = buffer + (front_idx * inner_type.size()) + size = int(back_idx - front_idx) + if size > 0: + d.checkPointer(start) + d.putItemCount(size) + d.putPlotData(start, size, inner_type) diff --git a/share/qtcreator/qml/qmlpuppet/commands/commands.pri b/share/qtcreator/qml/qmlpuppet/commands/commands.pri index 2a0913f72b1..f63b9486f68 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/commands.pri +++ b/share/qtcreator/qml/qmlpuppet/commands/commands.pri @@ -22,6 +22,7 @@ HEADERS += $$PWD/synchronizecommand.h \ \ $$PWD/clearscenecommand.h \ $$PWD/createinstancescommand.h \ $$PWD/informationchangedcommand.h \ + $$PWD/nanotracecommand.h \ $$PWD/pixmapchangedcommand.h \ $$PWD/removeinstancescommand.h \ $$PWD/removepropertiescommand.h \ @@ -54,6 +55,7 @@ SOURCES += $$PWD/synchronizecommand.cpp \ $$PWD/changestatecommand.cpp \ $$PWD/changevaluescommand.cpp \ $$PWD/informationchangedcommand.cpp \ + $$PWD/nanotracecommand.cpp \ $$PWD/removeinstancescommand.cpp \ $$PWD/removepropertiescommand.cpp \ $$PWD/reparentinstancescommand.cpp \ diff --git a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h index 43bd32e1a20..cb23b2c9ad5 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h @@ -47,6 +47,9 @@ public: OrientationToggle, EditLightToggle, ShowGrid, + ShowSelectionBox, + ShowIconGizmo, + ShowCameraFrustum, Edit3DParticleModeToggle, ParticlesPlay, ParticlesRestart, diff --git a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp b/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp index c1ca741e179..b0ce8ce23eb 100644 --- a/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp +++ b/share/qtcreator/qml/qmlpuppet/instances/nodeinstanceclientproxy.cpp @@ -77,7 +77,16 @@ #include "view3dactioncommand.h" #include "requestmodelnodepreviewimagecommand.h" #include "nanotracecommand.h" + +// Nanotrace headers are not exported to build dir at all if the feature is disabled, so +// runtime puppet build can't find them. +#if NANOTRACE_ENABLED #include "nanotrace/nanotrace.h" +#else +#define NANOTRACE_INIT(process, thread, filepath) +#define NANOTRACE_SHUTDOWN() +#define NANOTRACE_SCOPE_ARGS(cat, name, ...) +#endif namespace QmlDesigner { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml index a108190ff7a..11976378d27 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml @@ -30,6 +30,7 @@ IconGizmo { id: cameraGizmo property Model frustumModel: null + property bool globalShowFrustum: false iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png" @@ -46,8 +47,12 @@ IconGizmo { frustum.targetNode = targetNode; frustum.targetNode = Qt.binding(function() {return targetNode;}); - frustum.visible = visible || (targetNode && selected && activeScene === scene); - frustum.visible = Qt.binding(function() {return visible || (targetNode && selected && activeScene === scene);}); + frustum.visible = (canBeVisible && globalShowFrustum) + || (targetNode && selected && activeScene === scene); + frustum.visible = Qt.binding(function() { + return (canBeVisible && globalShowFrustum) + || (targetNode && selected && activeScene === scene); + }); } onActiveSceneChanged: { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml index 592e4ab72eb..0b15f190673 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml @@ -39,6 +39,9 @@ Item { property bool showEditLight: false property bool showGrid: true + property bool showSelectionBox: true + property bool showIconGizmo: true + property bool showCameraFrustum: false property bool usePerspective: true property bool globalOrientation: false property alias contentItem: contentItem @@ -70,6 +73,9 @@ Item { onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid); + onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox); + onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo); + onShowCameraFrustumChanged: _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum); onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode); @@ -220,6 +226,21 @@ Item { else if (resetToDefault) showGrid = true; + if ("showSelectionBox" in toolStates) + showSelectionBox = toolStates.showSelectionBox; + else if (resetToDefault) + showSelectionBox = true; + + if ("showIconGizmo" in toolStates) + showIconGizmo = toolStates.showIconGizmo; + else if (resetToDefault) + showIconGizmo = true; + + if ("showCameraFrustum" in toolStates) + showCameraFrustum = toolStates.showCameraFrustum; + else if (resetToDefault) + showCameraFrustum = false; + if ("usePerspective" in toolStates) usePerspective = toolStates.usePerspective; else if (resetToDefault) @@ -250,6 +271,9 @@ Item { { _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) _generalHelper.storeToolState(sceneId, "showGrid", showGrid) + _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox) + _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo) + _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum) _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); @@ -273,6 +297,7 @@ Item { "geometryName": geometryName}); selectionBoxes[selectionBoxes.length] = box; box.view3D = Qt.binding(function() {return editView;}); + box.visible = Qt.binding(function() {return showSelectionBox;}); } } } @@ -373,11 +398,13 @@ Item { "selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene, "locked": _generalHelper.isLocked(obj), - "hidden": _generalHelper.isHidden(obj)}); + "hidden": _generalHelper.isHidden(obj), + "globalShow": showIconGizmo}); lightIconGizmos[lightIconGizmos.length] = gizmo; gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;}); gizmo.activeScene = Qt.binding(function() {return activeScene;}); + gizmo.globalShow = Qt.binding(function() {return showIconGizmo;}); } } @@ -416,12 +443,15 @@ Item { overlayView, {"view3D": overlayView, "targetNode": obj, "selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene, - "locked": _generalHelper.isLocked(obj), "hidden": _generalHelper.isHidden(obj)}); + "locked": _generalHelper.isLocked(obj), "hidden": _generalHelper.isHidden(obj), + "globalShow": showIconGizmo, "globalShowFrustum": showCameraFrustum}); cameraGizmos[cameraGizmos.length] = gizmo; gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;}); gizmo.activeScene = Qt.binding(function() {return activeScene;}); + gizmo.globalShow = Qt.binding(function() {return showIconGizmo;}); + gizmo.globalShowFrustum = Qt.binding(function() {return showCameraFrustum;}); frustum.viewPortRect = Qt.binding(function() {return viewPortRect;}); gizmo.connectFrustum(frustum); } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml index 24459e08d4f..3ee4776aa52 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml @@ -45,6 +45,8 @@ Item { property bool hasMouse: false property bool hidden: false property bool locked: false + property bool globalShow: true + property bool canBeVisible: activeScene === scene && !hidden && (targetNode ? targetNode.visible : false) property alias iconSource: iconImage.source @@ -55,7 +57,7 @@ Item { hasMouse = false; } - visible: activeScene === scene && !hidden && (targetNode ? targetNode.visible : false) + visible: canBeVisible && globalShow Overlay2D { id: iconOverlay diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml index 42a7bc7bfaa..872c30a3452 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml @@ -30,6 +30,7 @@ IconGizmo { id: cameraGizmo property Model frustumModel: null + property bool globalShowFrustum: false iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png" @@ -46,8 +47,12 @@ IconGizmo { frustum.targetNode = targetNode; frustum.targetNode = Qt.binding(function() {return targetNode;}); - frustum.visible = visible || (targetNode && selected && activeScene === scene); - frustum.visible = Qt.binding(function() {return visible || (targetNode && selected && activeScene === scene);}); + frustum.visible = (canBeVisible && globalShowFrustum) + || (targetNode && selected && activeScene === scene); + frustum.visible = Qt.binding(function() { + return (canBeVisible && globalShowFrustum) + || (targetNode && selected && activeScene === scene); + }); } onActiveSceneChanged: { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml index 944c42b653b..eb7d50d2e4f 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml @@ -39,6 +39,9 @@ Item { property bool showEditLight: false property bool showGrid: true + property bool showSelectionBox: true + property bool showIconGizmo: true + property bool showCameraFrustum: false property bool usePerspective: true property bool globalOrientation: false property alias contentItem: contentItem @@ -71,6 +74,9 @@ Item { onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid); + onShowSelectionBoxChanged: _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox); + onShowIconGizmoChanged: _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo); + onShowCameraFrustumChanged: _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum); onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode); @@ -211,6 +217,21 @@ Item { else if (resetToDefault) showGrid = true; + if ("showSelectionBox" in toolStates) + showSelectionBox = toolStates.showSelectionBox; + else if (resetToDefault) + showSelectionBox = true; + + if ("showIconGizmo" in toolStates) + showIconGizmo = toolStates.showIconGizmo; + else if (resetToDefault) + showIconGizmo = true; + + if ("showCameraFrustum" in toolStates) + showCameraFrustum = toolStates.showCameraFrustum; + else if (resetToDefault) + showCameraFrustum = false; + if ("usePerspective" in toolStates) usePerspective = toolStates.usePerspective; else if (resetToDefault) @@ -241,6 +262,9 @@ Item { { _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight) _generalHelper.storeToolState(sceneId, "showGrid", showGrid) + _generalHelper.storeToolState(sceneId, "showSelectionBox", showSelectionBox) + _generalHelper.storeToolState(sceneId, "showIconGizmo", showIconGizmo) + _generalHelper.storeToolState(sceneId, "showCameraFrustum", showCameraFrustum) _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode); @@ -264,6 +288,7 @@ Item { "geometryName": geometryName}); selectionBoxes[selectionBoxes.length] = box; box.view3D = Qt.binding(function() {return editView;}); + box.visible = Qt.binding(function() {return showSelectionBox;}); } } } @@ -364,11 +389,13 @@ Item { "selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene, "locked": _generalHelper.isLocked(obj), - "hidden": _generalHelper.isHidden(obj)}); + "hidden": _generalHelper.isHidden(obj), + "globalShow": showIconGizmo}); lightIconGizmos[lightIconGizmos.length] = gizmo; gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;}); gizmo.activeScene = Qt.binding(function() {return activeScene;}); + gizmo.globalShow = Qt.binding(function() {return showIconGizmo;}); } } @@ -407,12 +434,15 @@ Item { overlayView, {"view3D": overlayView, "targetNode": obj, "selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene, - "locked": _generalHelper.isLocked(obj), "hidden": _generalHelper.isHidden(obj)}); + "locked": _generalHelper.isLocked(obj), "hidden": _generalHelper.isHidden(obj), + "globalShow": showIconGizmo, "globalShowFrustum": showCameraFrustum}); cameraGizmos[cameraGizmos.length] = gizmo; gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;}); gizmo.activeScene = Qt.binding(function() {return activeScene;}); + gizmo.globalShow = Qt.binding(function() {return showIconGizmo;}); + gizmo.globalShowFrustum = Qt.binding(function() {return showCameraFrustum;}); frustum.viewPortRect = Qt.binding(function() {return viewPortRect;}); gizmo.connectFrustum(frustum); } @@ -449,11 +479,13 @@ Item { "selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene, "locked": _generalHelper.isLocked(obj), - "hidden": _generalHelper.isHidden(obj)}); + "hidden": _generalHelper.isHidden(obj), + "globalShow": showIconGizmo}); particleSystemIconGizmos[particleSystemIconGizmos.length] = gizmo; gizmo.clicked.connect(handleObjectClicked); gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;}); gizmo.activeScene = Qt.binding(function() {return activeScene;}); + gizmo.globalShow = Qt.binding(function() {return showIconGizmo;}); } } @@ -840,6 +872,13 @@ Item { camera: viewRoot.usePerspective ? overlayPerspectiveCamera : overlayOrthoCamera importScene: overlayScene z: 2 + + environment: sceneEnv + SceneEnvironment { + id: sceneEnv + antialiasingMode: SceneEnvironment.MSAA + antialiasingQuality: SceneEnvironment.High + } } Overlay2D { diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml index 03087b658a9..7752693d559 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml @@ -45,6 +45,8 @@ Item { property bool hasMouse: false property bool hidden: false property bool locked: false + property bool globalShow: true + property bool canBeVisible: activeScene === scene && !hidden && (targetNode ? targetNode.visible : false) property alias iconSource: iconImage.source @@ -55,7 +57,7 @@ Item { hasMouse = false; } - visible: activeScene === scene && !hidden && (targetNode ? targetNode.visible : false) + visible: canBeVisible && globalShow Overlay2D { id: iconOverlay diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml index c75472096e7..e59392b1ee2 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml @@ -50,6 +50,13 @@ View3D { thresPerc = (grid_thresholds[thresIdx] - cameraZoomFactor) / (grid_thresholds[thresIdx] - grid_thresholds[thresIdx - 1]); } + environment: sceneEnv + SceneEnvironment { + id: sceneEnv + antialiasingMode: SceneEnvironment.MSAA + antialiasingQuality: SceneEnvironment.High + } + Node { id: sceneHelpers diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp index 4260921a378..046dc486063 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp @@ -142,6 +142,16 @@ void CameraGeometry::doUpdateGeometry() if (!QQuick3DObjectPrivate::get(m_camera)->spatialNode) { // Doing explicit viewport mapping forces cameraNode creation m_camera->mapToViewport({}, m_viewPortRect.width(), m_viewPortRect.height()); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (!m_nodeCreationUpdateDone) { + // Post-node creation update is done only once to avoid infinite loop in case the node + // creation fails. + m_nodeCreationUpdateDone = true; + m_cameraUpdatePending = true; + update(); + return; + } +#endif } GeometryBase::doUpdateGeometry(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h index 5b4fa66fe46..c65b0d1798e 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h @@ -67,6 +67,9 @@ private: QQuick3DCamera *m_camera = nullptr; QRectF m_viewPortRect; bool m_cameraUpdatePending = false; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + bool m_nodeCreationUpdateDone = false; +#endif }; } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp index a4e950b238b..cee091531a7 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/mousearea3d.cpp @@ -729,7 +729,8 @@ void MouseArea3D::applyFreeRotation(QQuick3DNode *node, const QVector3D &startRo if (dragVector.length() < 0.001f) return; - const float *dataPtr(sceneTransform().data()); + const auto &transform = sceneTransform(); + const float *dataPtr(transform.data()); QVector3D xAxis = QVector3D(dataPtr[0], dataPtr[1], dataPtr[2]).normalized(); QVector3D yAxis = QVector3D(dataPtr[4], dataPtr[5], dataPtr[6]).normalized(); QVector3D finalAxis = (dragVector.x() * yAxis + dragVector.y() * xAxis); @@ -1029,7 +1030,8 @@ void MouseArea3D::setHovering(bool enable) QVector3D MouseArea3D::getNormal() const { - const float *dataPtr(sceneTransform().data()); + const auto &transform = sceneTransform(); + const float *dataPtr(transform.data()); return QVector3D(dataPtr[8], dataPtr[9], dataPtr[10]).normalized(); } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp index 489c8b2b5c3..b37486f0481 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -72,7 +72,13 @@ #include #include +// Nanotrace headers are not exported to build dir at all if the feature is disabled, so +// runtime puppet build can't find them. +#if NANOTRACE_ENABLED #include "nanotrace/nanotrace.h" +#else +#define NANOTRACE_SCOPE(cat, name) +#endif #include #include diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index b2a84ff53f3..afde832afcb 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -2116,6 +2116,15 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c case View3DActionCommand::ShowGrid: updatedState.insert("showGrid", command.isEnabled()); break; + case View3DActionCommand::ShowSelectionBox: + updatedState.insert("showSelectionBox", command.isEnabled()); + break; + case View3DActionCommand::ShowIconGizmo: + updatedState.insert("showIconGizmo", command.isEnabled()); + break; + case View3DActionCommand::ShowCameraFrustum: + updatedState.insert("showCameraFrustum", command.isEnabled()); + break; #ifdef QUICK3D_PARTICLES_MODULE case View3DActionCommand::ParticlesPlay: m_particleAnimationPlaying = command.isEnabled(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp index a2627bee257..c97de4636aa 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp @@ -38,7 +38,14 @@ #include #include #include -#include + +// Nanotrace headers are not exported to build dir at all if the feature is disabled, so +// runtime puppet build can't find them. +#if NANOTRACE_ENABLED +#include "nanotrace/nanotrace.h" +#else +#define NANOTRACE_SCOPE(cat, name) +#endif #include #include diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp index 4b3d047142e..d5371e4b5e4 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp @@ -241,7 +241,7 @@ int internalMain(QGuiApplication *application) #endif #if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN) - startCrashpad(); + /* startCrashpad(); */ #endif new QmlDesigner::Qt5NodeInstanceClientProxy(application); diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index 8444a2c88f6..ab403d203b2 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -36,7 +36,9 @@ Item { property var selectedAssets: ({}) property int allExpandedState: 0 - property string delFilePath: "" + property string contextFilePath: "" + property var contextDir: undefined + property bool isDirContextMenu: false DropArea { id: dropArea @@ -67,6 +69,19 @@ Item { } } + MouseArea { // right clicking the empty area of the view + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: { + if (!assetsModel.isEmpty) { + contextFilePath = "" + contextDir = assetsModel.rootDir() + isDirContextMenu = false + contextMenu.popup() + } + } + } + // called from C++ to close context menu on focus out function handleViewFocusOut() { @@ -75,9 +90,139 @@ Item { selectedAssetsChanged() } + Dialog { + id: newFolderDialog + + title: qsTr("Create new folder") + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape + modal: true + + contentItem: Column { + spacing: 2 + + Row { + Text { + text: qsTr("Folder Name: ") + anchors.verticalCenter: parent.verticalCenter + color: StudioTheme.Values.themeTextColor + } + + StudioControls.TextField { + id: folderName + + actionIndicator.visible: false + translationIndicator.visible: false + + Keys.onEnterPressed: btnCreate.onClicked() + Keys.onReturnPressed: btnCreate.onClicked() + } + } + + Text { + text: qsTr("Folder Name cannot be empty.") + color: "#ff0000" + anchors.right: parent.right + visible: folderName.text === "" + } + + Item { // spacer + width: 1 + height: 20 + } + + Row { + anchors.right: parent.right + + Button { + id: btnCreate + + text: qsTr("Create") + enabled: folderName.text !== "" + onClicked: { + assetsModel.addNewFolder(contextDir.dirPath + '/' + folderName.text) + newFolderDialog.accept() + } + } + + Button { + text: qsTr("Cancel") + onClicked: newFolderDialog.reject() + } + } + } + + onOpened: { + folderName.text = "New folder" + folderName.selectAll() + folderName.forceActiveFocus() + } + } + + Dialog { + id: confirmDeleteFolderDialog + + title: qsTr("Folder not empty") + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape + implicitWidth: 300 + modal: true + + contentItem: Column { + spacing: 20 + width: parent.width + + Text { + id: folderNotEmpty + + text: qsTr("Folder '%1' is not empty. Are you sure you want to delete it?") + .arg(contextDir ? contextDir.dirName : "") + color: StudioTheme.Values.themeTextColor + wrapMode: Text.WordWrap + width: confirmDeleteFolderDialog.width + leftPadding: 10 + rightPadding: 10 + + Keys.onEnterPressed: btnDelete.onClicked() + Keys.onReturnPressed: btnDelete.onClicked() + } + + Text { + text: qsTr("If the folder has assets in use, deleting it might cause the project to not work correctly.") + color: StudioTheme.Values.themeTextColor + wrapMode: Text.WordWrap + width: confirmDeleteFolderDialog.width + leftPadding: 10 + rightPadding: 10 + } + + Row { + anchors.right: parent.right + Button { + id: btnDelete + + text: qsTr("Delete") + + onClicked: { + assetsModel.deleteFolder(contextDir.dirPath) + confirmDeleteFolderDialog.accept() + } + } + + Button { + text: qsTr("Cancel") + onClicked: confirmDeleteFolderDialog.reject() + } + } + } + + onOpened: folderNotEmpty.forceActiveFocus() + } + ScrollView { // TODO: experiment using ListView instead of ScrollView + Column id: assetsView anchors.fill: parent + interactive: assetsView.verticalScrollBarVisible Item { StudioControls.Menu { @@ -86,7 +231,7 @@ Item { StudioControls.MenuItem { text: qsTr("Expand All") enabled: allExpandedState !== 1 - visible: !delFilePath + visible: isDirContextMenu height: visible ? implicitHeight : 0 onTriggered: assetsModel.toggleExpandAll(true) } @@ -94,22 +239,51 @@ Item { StudioControls.MenuItem { text: qsTr("Collapse All") enabled: allExpandedState !== 2 - visible: !delFilePath + visible: isDirContextMenu height: visible ? implicitHeight : 0 onTriggered: assetsModel.toggleExpandAll(false) } + StudioControls.MenuSeparator { + visible: isDirContextMenu + height: visible ? StudioTheme.Values.border : 0 + } + StudioControls.MenuItem { text: qsTr("Delete File") - visible: delFilePath + visible: contextFilePath height: visible ? implicitHeight : 0 - onTriggered: assetsModel.removeFile(delFilePath) + onTriggered: assetsModel.deleteFile(contextFilePath) + } + + StudioControls.MenuSeparator { + visible: contextFilePath + height: visible ? StudioTheme.Values.border : 0 + } + + StudioControls.MenuItem { + text: qsTr("New Folder") + onTriggered: newFolderDialog.open() + } + + StudioControls.MenuItem { + text: qsTr("Delete Folder") + visible: isDirContextMenu + height: visible ? implicitHeight : 0 + onTriggered: { + var dirEmpty = !(contextDir.dirsModel && contextDir.dirsModel.rowCount() > 0) + && !(contextDir.filesModel && contextDir.filesModel.rowCount() > 0); + + if (dirEmpty) + assetsModel.deleteFolder(contextDir.dirPath) + else + confirmDeleteFolderDialog.open() + } } } } Column { - spacing: 2 Repeater { model: assetsModel // context property delegate: dirSection @@ -120,31 +294,35 @@ Item { Section { width: assetsView.width - - (assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) + (assetsView.verticalScrollBarVisible ? assetsView.verticalThickness : 0) - 5 caption: dirName sectionHeight: 30 sectionFontSize: 15 - levelShift: 20 leftPadding: 0 + topPadding: dirDepth > 0 ? 5 : 0 + bottomPadding: 0 hideHeader: dirDepth === 0 - showLeftBorder: true + showLeftBorder: dirDepth > 0 expanded: dirExpanded - visible: dirVisible + visible: !assetsModel.isEmpty && dirVisible expandOnClick: false useDefaulContextMenu: false onToggleExpand: { dirExpanded = !dirExpanded } + onShowContextMenu: { - delFilePath = "" + contextFilePath = "" + contextDir = model + isDirContextMenu = true allExpandedState = assetsModel.getAllExpandedState() contextMenu.popup() } Column { spacing: 5 - leftPadding: 15 + leftPadding: 5 Repeater { model: dirsModel @@ -155,6 +333,25 @@ Item { model: filesModel delegate: fileSection } + + Text { + text: qsTr("Empty folder") + color: StudioTheme.Values.themeTextColorDisabled + font.pixelSize: 12 + visible: !(dirsModel && dirsModel.rowCount() > 0) + && !(filesModel && filesModel.rowCount() > 0) + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: { + contextFilePath = "" + contextDir = model + isDirContextMenu = true + contextMenu.popup() + } + } + } } } } @@ -222,8 +419,11 @@ Item { if (currFileSelected) rootView.startDragAsset(selectedAssetsArr, mapToGlobal(mouse.x, mouse.y)) } else { - delFilePath = filePath + contextFilePath = filePath + contextDir = model.fileDir + tooltipBackend.hideTooltip() + isDirContextMenu = false contextMenu.popup() } } @@ -263,7 +463,7 @@ Item { // Placeholder when the assets panel is empty Column { id: colNoAssets - visible: assetsModel.isEmpty + visible: assetsModel.isEmpty && !rootView.searchActive spacing: 20 x: 20 @@ -307,4 +507,13 @@ Item { wrapMode: Text.WordWrap } } + + Text { + text: qsTr("No match found.") + x: 20 + y: 10 + color: StudioTheme.Values.themeTextColor + font.pixelSize: 12 + visible: assetsModel.isEmpty && rootView.searchActive + } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml index 66f05462c3e..3f8a3311894 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml @@ -173,7 +173,7 @@ Item { id: leftBorder visible: false width: 1 - height: parent.height - 15 + height: parent.height - bottomPadding color: header.color } diff --git a/share/qtcreator/qmldesigner/qt4mcu/metadata.qml b/share/qtcreator/qmldesigner/qt4mcu/metadata.qml index d26ef06fd56..ee889214065 100644 --- a/share/qtcreator/qmldesigner/qt4mcu/metadata.qml +++ b/share/qtcreator/qmldesigner/qt4mcu/metadata.qml @@ -27,29 +27,35 @@ Metadata { id: metadataFile - defaultVersion: v19 + defaultVersion: v20 VersionData { id: v14 - name: "QUL 1.4" + name: "Qt for MCUs 1.4" path: "qul-14.qml" } VersionData { id: v17 - name: "QUL 1.7" + name: "Qt for MCUs 1.7" path: "qul-17.qml" } VersionData { id: v18 - name: "QUL 1.8" + name: "Qt for MCUs 1.8" path: "qul-18.qml" } VersionData { id: v19 - name: "QUL 1.9" + name: "Qt for MCUs 1.9" path: "qul-19.qml" } + + VersionData { + id: v20 + name: "Qt for MCUs 2.0" + path: "qul-20.qml" + } } diff --git a/share/qtcreator/qmldesigner/qt4mcu/qul-14.qml b/share/qtcreator/qmldesigner/qt4mcu/qul-14.qml index 03110763f5b..56467f170f0 100644 --- a/share/qtcreator/qmldesigner/qt4mcu/qul-14.qml +++ b/share/qtcreator/qmldesigner/qt4mcu/qul-14.qml @@ -24,7 +24,7 @@ ****************************************************************************/ VersionData { - name: "QUL 1.4" + name: "Qt for MCUs 1.4" bannedItems: ["QtQuick.AnimatedImage", "QtQuick.FocusScope", @@ -34,6 +34,7 @@ VersionData { "QtQuick.Grid", "QtQuick.GridView", "QtQuick.PathView", + "QtQuick.Loader", "QtQuick.Controls", "QtQuick.Controls.BusyIndicator", "QtQuick.Controls.ButtonGroup", diff --git a/share/qtcreator/qmldesigner/qt4mcu/qul-17.qml b/share/qtcreator/qmldesigner/qt4mcu/qul-17.qml index 765c54bd9d7..190d9f398a4 100644 --- a/share/qtcreator/qmldesigner/qt4mcu/qul-17.qml +++ b/share/qtcreator/qmldesigner/qt4mcu/qul-17.qml @@ -24,7 +24,7 @@ ****************************************************************************/ VersionData { - name: "QUL 1.7" + name: "Qt for MCUs 1.7" bannedItems: ["QtQuick.AnimatedImage", "QtQuick.FocusScope", @@ -34,6 +34,7 @@ VersionData { "QtQuick.Grid", "QtQuick.GridView", "QtQuick.PathView", + "QtQuick.Loader", "QtQuick.Controls", "QtQuick.Controls.BusyIndicator", "QtQuick.Controls.ButtonGroup", diff --git a/share/qtcreator/qmldesigner/qt4mcu/qul-18.qml b/share/qtcreator/qmldesigner/qt4mcu/qul-18.qml index 4c0cf5d4b9f..dba879c9a10 100644 --- a/share/qtcreator/qmldesigner/qt4mcu/qul-18.qml +++ b/share/qtcreator/qmldesigner/qt4mcu/qul-18.qml @@ -24,7 +24,7 @@ ****************************************************************************/ VersionData { - name: "QUL 1.8" + name: "Qt for MCUs 1.8" bannedItems: ["QtQuick.AnimatedImage", "QtQuick.FocusScope", @@ -34,6 +34,7 @@ VersionData { "QtQuick.Grid", "QtQuick.GridView", "QtQuick.PathView", + "QtQuick.Loader", "QtQuick.Controls", "QtQuick.Controls.BusyIndicator", "QtQuick.Controls.ButtonGroup", @@ -63,7 +64,11 @@ VersionData { "QtQuick.Controls.TextArea", "QtQuick.Controls.TextField", "QtQuick.Controls.ToolSeparator", - "QtQuick.Controls.Tumbler"] + "QtQuick.Controls.Tumbler", + "QtQuick.Shapes.ConicalGradient", + "QtQuick.Shapes.LinearGradient", + "QtQuick.Shapes.RadialGradient", + "QtQuick.Shapes.ShapeGradient"] allowedImports: ["QtQuick", "QtQuick.Shapes", diff --git a/share/qtcreator/qmldesigner/qt4mcu/qul-19.qml b/share/qtcreator/qmldesigner/qt4mcu/qul-19.qml index be473bc8caf..55f720c45b7 100644 --- a/share/qtcreator/qmldesigner/qt4mcu/qul-19.qml +++ b/share/qtcreator/qmldesigner/qt4mcu/qul-19.qml @@ -24,7 +24,7 @@ ****************************************************************************/ VersionData { - name: "QUL 1.9" + name: "Qt for MCUs 1.9" bannedItems: ["QtQuick.AnimatedImage", "QtQuick.FocusScope", @@ -34,6 +34,7 @@ VersionData { "QtQuick.Grid", "QtQuick.GridView", "QtQuick.PathView", + "QtQuick.Loader", "QtQuick.Controls", "QtQuick.Controls.BusyIndicator", "QtQuick.Controls.ButtonGroup", @@ -63,7 +64,11 @@ VersionData { "QtQuick.Controls.TextArea", "QtQuick.Controls.TextField", "QtQuick.Controls.ToolSeparator", - "QtQuick.Controls.Tumbler"] + "QtQuick.Controls.Tumbler", + "QtQuick.Shapes.ConicalGradient", + "QtQuick.Shapes.LinearGradient", + "QtQuick.Shapes.RadialGradient", + "QtQuick.Shapes.ShapeGradient"] allowedImports: ["QtQuick", "QtQuick.Shapes", diff --git a/share/qtcreator/qmldesigner/qt4mcu/qul-20.qml b/share/qtcreator/qmldesigner/qt4mcu/qul-20.qml new file mode 100644 index 00000000000..d6b41cd0552 --- /dev/null +++ b/share/qtcreator/qmldesigner/qt4mcu/qul-20.qml @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2021 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. +** +****************************************************************************/ + +VersionData { + name: "Qt for MCUs 2.0" + + bannedItems: ["QtQuick.AnimatedImage", + "QtQuick.FocusScope", + "QtQuick.TextInput", + "QtQuick.TextEdit", + "QtQuick.Flow", + "QtQuick.Grid", + "QtQuick.GridView", + "QtQuick.PathView", + "QtQuick.Loader", + "QtQuick.Controls", + "QtQuick.Controls.BusyIndicator", + "QtQuick.Controls.ButtonGroup", + "QtQuick.Controls.CheckDelegate", + "QtQuick.Controls.Container", + "QtQuick.Controls.ComboBox", + "QtQuick.Controls.DelayButton", + "QtQuick.Controls.Frame", + "QtQuick.Controls.GroupBox", + "QtQuick.Controls.ItemDelegate", + "QtQuick.Controls.Label", + "QtQuick.Controls.Page", + "QtQuick.Controls.PageIndicator", + "QtQuick.Controls.Pane", + "QtQuick.Controls.RadioDelegate", + "QtQuick.Controls.RangeSlider", + "QtQuick.Controls.RoundButton", + "QtQuick.Controls.ScrollView", + "QtQuick.Controls.SpinBox", + "QtQuick.Controls.StackView", + "QtQuick.Controls.SwipeDelegate", + "QtQuick.Controls.SwitchDelegate", + "QtQuick.Controls.ToolBar", + "QtQuick.Controls.ToolButton", + "QtQuick.Controls.TabBar", + "QtQuick.Controls.TabButton", + "QtQuick.Controls.TextArea", + "QtQuick.Controls.TextField", + "QtQuick.Controls.ToolSeparator", + "QtQuick.Controls.Tumbler", + "QtQuick.Shapes.ConicalGradient", + "QtQuick.Shapes.LinearGradient", + "QtQuick.Shapes.RadialGradient", + "QtQuick.Shapes.ShapeGradient"] + + allowedImports: ["QtQuick", + "QtQuick.Shapes", + "QtQuick.Controls", + "QtQuick.Timeline", + "QtQuickUltralite.Extras", + "QtQuickUltralite.Layers"] + + bannedImports: ["FlowView"] + + //ComplexProperty is not a type, it's just a way to handle bigger props + ComplexProperty { + prefix: "font" + bannedProperties: ["wordSpacing", "letterSpacing", "hintingPreference", + "kerning", "preferShaping", "capitalization", + "strikeout", "underline", "styleName"] + } + + QtQuick.Item { + bannedProperties: ["layer", "opacity", "smooth", "antialiasing", + "baselineOffset", "focus", "activeFocusOnTab", + "rotation", "scale", "transformOrigin"] + } + + QtQuick.Rectangle { + bannedProperties: ["gradient", "border"] + } + + QtQuick.Flickable { + bannedProperties: ["boundsBehavior", "boundsMovement", "flickDeceleration", + "flickableDirection", "leftMargin", "rightMargin", "bottomMargin", "topMargin", + "originX", "originY", "pixelAligned", "pressDelay", "synchronousDrag"] + } + + QtQuick.MouseArea { + bannedProperties: ["propagateComposedEvents", "preventStealing", "cursorShape", + "scrollGestureEnabled", "drag", "acceptedButtons", "hoverEnabled"] + } + + QtQuick.Image { + allowChildren: false + allowedProperties: ["rotation", "scale", "transformOrigin"] + bannedProperties: ["mirror", "mipmap", "cache", "autoTransform", "asynchronous", + "sourceSize", "smooth"] + } + + QtQuick.BorderImage { + bannedProperties: ["asynchronous", "cache", "currentFrame", "frameCount", + "horizontalTileMode", "mirror", "progress", "smooth", "sourceSize", + "status", "verticalTileMode"] + } + + QtQuick.Text { + allowChildren: false + allowedProperties: ["rotation", "scale", "transformOrigin"] + bannedProperties: ["elide", "lineHeight", "lineHeightMode", "wrapMode", "style", + "styleColor", "minimumPointSize", "minimumPixelSize", + "fontSizeMode", "renderType", "renderTypeQuality", "textFormat", "maximumLineCount"] + } + + //Padding is not an actual item, but rather set of properties in Text + Padding { + bannedProperties: ["bottomPadding", "topPadding", "leftPadding", "rightPadding"] + } + + QtQuick.Column { + bannedProperties: ["bottomPadding", "leftPadding", "rightPadding", "topPadding"] + } + + QtQuick.Row { + bannedProperties: ["bottomPadding", "leftPadding", "rightPadding", "topPadding", + "effectiveLayoutDirection", "layoutDirection"] + } + + QtQuick.ListView { + bannedProperties: ["cacheBuffer", "highlightRangeMode", "highlightMoveDuration", + "highlightResizeDuration", "preferredHighlightBegin", "layoutDirection", + "preferredHighlightEnd", "highlightFollowsCurrentItem", "keyNavigationWraps", + "snapMode", "highlightMoveVelocity", "highlightResizeVelocity"] + } + + QtQuick.Animation { + bannedProperties: ["paused"] + } + + //Quick Controls2 Items and properties: + + QtQuick.Controls.Control { + bannedProperties: ["focusPolicy", "hoverEnabled", "wheelEnabled"] + } + + QtQuick.Controls.AbstractButton { + bannedProperties: ["display", "autoExclusive"] + } + + QtQuick.Controls.ProgressBar { + bannedProperties: ["indeterminate"] + } + + QtQuick.Controls.Slider { + bannedProperties: ["live", "snapMode", "touchDragThreshold"] + } + + //Path and Shapes related: + + QtQuick.Path { + bannedProperties: ["scale", "pathElements"] + } + + QtQuick.PathArc { + bannedProperties: ["relativeX", "relativeY"] + } + + QtQuick.PathLine { + bannedProperties: ["relativeX", "relativeY"] + } + + QtQuick.PathMove { + bannedProperties: ["relativeX", "relativeY"] + } + + QtQuick.PathQuad { + bannedProperties: ["relativeX", "relativeY", + "relativeControlX", "relativeControlY"] + } + + QtQuick.PathCubic { + bannedProperties: ["relativeX", "relativeY", + "relativeControl1X", "relativeControl1Y", + "relativeControl2X", "relativeControl2Y"] + } + + QtQuick.PathElement { + //nothing + } + + QtQuick.PathSvg { + //nothing + } + + QtQuick.Shapes.Shape { + bannedProperties: ["asynchronous", "containsMode", "data", + "renderType", "status", "vendorExtensionsEnabled"] + } + + QtQuick.Shapes.ShapePath { + bannedProperties: ["dashOffset", "dashPattern", + "fillGradient", "strokeStyle"] + } +} diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml index 08a7bc7dc3d..7d0aa14cfd6 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesDelegate.qml @@ -33,11 +33,8 @@ import StudioTheme 1.0 as StudioTheme Rectangle { id: myRoot - color: baseColor - property bool isBaseState property bool isCurrentState - property color baseColor property string delegateStateName property string delegateStateImageSource property bool delegateHasWhenCondition @@ -47,14 +44,14 @@ Rectangle { property int bottomAreaHeight property int stateMargin property int previewMargin - property int columnSpacing readonly property bool isDefaultState: isDefault property int closeButtonMargin: 6 property int textFieldMargin: 4 - signal delegateInteraction + property int scrollBarH: 0 + property int listMargin: 0 function autoComplete(text, pos, explicitComplete, filter) { var stringList = statesEditorModel.autoComplete(text, pos, explicitComplete) @@ -65,14 +62,16 @@ Rectangle { return statesEditorModel.hasAnnotation(internalNodeId) } + color: isCurrentState ? StudioTheme.Values.themeInteraction + : StudioTheme.Values.themeControlBackgroundInteraction MouseArea { id: mouseArea anchors.fill: parent + onClicked: { focus = true root.currentStateInternalId = internalNodeId contextMenu.dismiss() // close potentially open context menu - myRoot.delegateInteraction() } } @@ -89,7 +88,6 @@ Rectangle { visible: !isBaseState && isCurrentState onClicked: { - myRoot.delegateInteraction() if (isDefaultState) statesEditorModel.resetDefaultState() @@ -254,9 +252,8 @@ Rectangle { Rectangle { // separator width: column.width - height: myRoot.columnSpacing + height: 2 color: StudioTheme.Values.themeStateSeparator - visible: expanded } Rectangle { @@ -264,7 +261,6 @@ Rectangle { width: myRoot.width - 2 * myRoot.stateMargin height: myRoot.bottomAreaHeight color: StudioTheme.Values.themeStateBackground - visible: expanded Image { anchors.fill: stateImageBackground diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml index 6f2dfbbf3d0..ef2cbdf62f7 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml @@ -26,6 +26,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuickDesignerTheme 1.0 +import Qt.labs.qmlmodels 1.0 import HelperWidgets 2.0 import StudioControls 1.0 as StudioControls import StudioTheme 1.0 as StudioTheme @@ -33,27 +34,24 @@ import StudioTheme 1.0 as StudioTheme FocusScope { id: root - property int delegateTopAreaHeight: StudioTheme.Values.height + 8 - property int delegateBottomAreaHeight: delegateHeight - 2 * delegateStateMargin - delegateTopAreaHeight - delegateColumnSpacing - property int delegateColumnSpacing: 2 - property int delegateStateMargin: 16 - property int delegatePreviewMargin: 10 - property int effectiveHeight: root.expanded ? Math.max(85, Math.min(287, root.height)) : 85 // height of the states area + readonly property int delegateTopAreaHeight: StudioTheme.Values.height + 8 + readonly property int delegateBottomAreaHeight: delegateHeight - 2 * delegateStateMargin - delegateTopAreaHeight - 2 + readonly property int delegateStateMargin: 16 + readonly property int delegatePreviewMargin: 10 + readonly property int effectiveHeight: root.height < 130 ? 89 : Math.min(root.height, 287) + + readonly property int scrollBarH: statesListView.ScrollBar.horizontal.scrollBarVisible ? StudioTheme.Values.scrollBarThickness : 0 + readonly property int listMargin: 10 + readonly property int delegateWidth: 264 + readonly property int delegateHeight: Math.max(effectiveHeight - scrollBarH - 2 * listMargin, 69) + readonly property int innerSpacing: 2 + + property int currentStateInternalId: 0 signal createNewState signal deleteState(int internalNodeId) signal duplicateCurrentState - property int padding: 2 - property int delegateWidth: 264 - property int delegateHeight: effectiveHeight - - StudioTheme.Values.scrollBarThickness - - 2 * (root.padding + StudioTheme.Values.border) - property int innerSpacing: 2 - property int currentStateInternalId: 0 - - property bool expanded: true - Connections { target: statesEditorModel function onChangedToState(n) { root.currentStateInternalId = n } @@ -65,92 +63,117 @@ FocusScope { color: StudioTheme.Values.themePanelBackground } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton | Qt.RightButton - - onClicked: function(mouse) { - if (mouse.button === Qt.LeftButton) { - contextMenu.dismiss() - focus = true - } else if (mouse.button === Qt.RightButton) { - contextMenu.popup() - } - } - - StudioControls.Menu { - id: contextMenu - - StudioControls.MenuItem { - text: root.expanded ? qsTr("Collapse") : qsTr("Expand") - onTriggered: root.expanded = !root.expanded - } - } - } - AbstractButton { id: addStateButton - buttonIcon: root.expanded ? qsTr("Create New State") : StudioTheme.Constants.plus - iconFont: root.expanded ? StudioTheme.Constants.font : StudioTheme.Constants.iconFont - iconSize: root.expanded ? StudioTheme.Values.myFontSize : StudioTheme.Values.myIconFontSize - iconItalic: root.expanded + buttonIcon: StudioTheme.Constants.plus + iconFont: StudioTheme.Constants.iconFont + iconSize: StudioTheme.Values.myIconFontSize tooltip: qsTr("Add a new state.") visible: canAddNewStates anchors.right: parent.right - anchors.rightMargin: 8 - y: (Math.min(effectiveHeight, root.height) - height) / 2 - width: root.expanded ? 140 : 18 - height: root.expanded ? 60 : 18 + anchors.rightMargin: 4 + anchors.bottom: parent.bottom + anchors.bottomMargin: statesListView.contentWidth - statesListView.contentX - root.delegateWidth / 2 > statesListView.width ? scrollBarH + 5 : -35 + width: 35 + height: 35 - onClicked: { - contextMenu.dismiss() - root.createNewState() + Behavior on anchors.bottomMargin { + PropertyAnimation { + duration: 700 + easing.type: Easing.InOutBack + } } - } - Rectangle { // separator lines between state items - color: StudioTheme.Values.themeStateSeparator - x: root.padding - y: root.padding - width: statesListView.width - height: root.delegateHeight + onClicked: root.createNewState() } ListView { id: statesListView - boundsBehavior: Flickable.StopAtBounds clip: true - - x: root.padding - y: root.padding - width: Math.min(root.delegateWidth * statesListView.count + root.innerSpacing * (statesListView.count - 1), - root.width - addStateButton.width - root.padding - 16) // 16 = 2 * 8 (addStateButton margin) - height: root.delegateHeight + StudioTheme.Values.scrollBarThickness + anchors.fill: parent + anchors.topMargin: listMargin + anchors.leftMargin: listMargin + anchors.rightMargin: listMargin model: statesEditorModel orientation: ListView.Horizontal spacing: root.innerSpacing - delegate: StatesDelegate { - id: statesDelegate - width: root.delegateWidth - height: root.delegateHeight - isBaseState: 0 === internalNodeId - isCurrentState: root.currentStateInternalId === internalNodeId - baseColor: isCurrentState ? StudioTheme.Values.themeInteraction : background.color - delegateStateName: stateName - delegateStateImageSource: stateImageSource - delegateHasWhenCondition: hasWhenCondition - delegateWhenConditionString: whenConditionString - onDelegateInteraction: contextMenu.dismiss() + property int prevCount: 0 + onCountChanged: { + if (count > prevCount) + Qt.callLater(statesListView.positionViewAtEnd) + prevCount = count + } - columnSpacing: root.delegateColumnSpacing - topAreaHeight: root.delegateTopAreaHeight - bottomAreaHeight: root.delegateBottomAreaHeight - stateMargin: root.delegateStateMargin - previewMargin: root.delegatePreviewMargin + delegate: DelegateChooser { + role: "type" + + DelegateChoice { + roleValue: "state" + + StatesDelegate { + width: root.delegateWidth + height: root.delegateHeight + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + anchors.verticalCenterOffset: -.5 * (scrollBarH + listMargin) + isBaseState: 0 === internalNodeId + isCurrentState: root.currentStateInternalId === internalNodeId + delegateStateName: stateName + delegateStateImageSource: stateImageSource + delegateHasWhenCondition: hasWhenCondition + delegateWhenConditionString: whenConditionString + + topAreaHeight: root.delegateTopAreaHeight + bottomAreaHeight: root.delegateBottomAreaHeight + stateMargin: root.delegateStateMargin + previewMargin: root.delegatePreviewMargin + scrollBarH: root.scrollBarH + listMargin: root.listMargin + } + } + + DelegateChoice { + roleValue: "add" + + Rectangle { + visible: canAddNewStates + + width: root.delegateWidth + height: root.delegateHeight + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + anchors.verticalCenterOffset: -.5 * (scrollBarH + listMargin) + color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1) + + ToolTip.text: qsTr("Add a new state.") + ToolTip.visible: addState.containsMouse + ToolTip.delay: 1000 + + Rectangle { // inner rect + width: parent.width - 30 + height: parent.height - 30 + anchors.centerIn: parent + color: StudioTheme.Values.themeStateBackground + } + + Text { + text: "+" + anchors.centerIn: parent + anchors.verticalCenterOffset: -5 + font.pixelSize: parent.height * .5 + color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1) + } + + MouseArea { + id: addState + hoverEnabled: true + anchors.fill: parent + onClicked: root.createNewState() + } + } + } } ScrollBar.horizontal: HorizontalScrollBar {} diff --git a/share/qtcreator/translations/CMakeLists.txt b/share/qtcreator/translations/CMakeLists.txt index 648f885b771..f32138e7791 100644 --- a/share/qtcreator/translations/CMakeLists.txt +++ b/share/qtcreator/translations/CMakeLists.txt @@ -1,27 +1,19 @@ set(languages cs da de fr hr ja pl ru sl uk zh_CN zh_TW) set(bad_languages hu) # Fix these before including them in languages! -# TODO: Remove when cmake_minimum_required greater than 3.12 -if (CMAKE_VERSION VERSION_GREATER 3.12) - find_package(Python3 COMPONENTS Interpreter) - set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND}) - set(PYTHON_VERSION_STRING ${Python3_VERSION}) - set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) -else() - find_package(PythonInterp) -endif() +find_package(Python3 COMPONENTS Interpreter) set(json_wizards_h "") set(custom_wizards_h "") set(externaltools_h "") set(snippets_h "") -if (NOT PYTHONINTERP_FOUND OR NOT PYTHON_VERSION_STRING VERSION_GREATER_EQUAL "3.0.0") - message(WARNING "No python3 interpreter found, skipping extraction of data from XML and JSON files.\n *** Please pass -DPYTHON_EXECUTABLE=/path/to/python3 to cmake.") +if (NOT Python3_Interpreter_FOUND) + message(WARNING "No python3 interpreter found, skipping extraction of data from XML and JSON files.\n *** Please pass -DPython3_EXECUTABLE=/path/to/python3 to cmake.") else() set(json_wizards_h "${CMAKE_CURRENT_BINARY_DIR}/jsonwizards_tr.h") add_custom_command(OUTPUT "${json_wizards_h}" - COMMAND "${PYTHON_EXECUTABLE}" + COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/extract-jsonwizards.py" "${PROJECT_SOURCE_DIR}/share/qtcreator/templates/wizards" "${json_wizards_h}" COMMENT Generate translation data from JSON wizards @@ -29,7 +21,7 @@ else() set(custom_wizards_h "${CMAKE_CURRENT_BINARY_DIR}/customwizards_tr.h") add_custom_command(OUTPUT "${custom_wizards_h}" - COMMAND "${PYTHON_EXECUTABLE}" + COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/extract-customwizards.py" "${PROJECT_SOURCE_DIR}/share/qtcreator/templates/wizards" "${custom_wizards_h}" COMMENT Generate translation data from XML wizards @@ -37,7 +29,7 @@ else() set(externaltools_h "${CMAKE_CURRENT_BINARY_DIR}/externaltools_tr.h") add_custom_command(OUTPUT "${externaltools_h}" - COMMAND "${PYTHON_EXECUTABLE}" + COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/extract-externaltools.py" "${PROJECT_SOURCE_DIR}/src/share/qtcreator/externaltools" "${externaltools_h}" COMMENT Generate translation data from external tools definitions @@ -45,7 +37,7 @@ else() set(snippets_h "${CMAKE_CURRENT_BINARY_DIR}/snippets_tr.h") add_custom_command(OUTPUT "${snippets_h}" - COMMAND "${PYTHON_EXECUTABLE}" + COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/extract-snippets.py" "${PROJECT_SOURCE_DIR}/share/qtcreator/snippets" "${snippets_h}" COMMENT Generate translation data from snippets definitions diff --git a/share/qtcreator/translations/qtcreator_cs.ts b/share/qtcreator/translations/qtcreator_cs.ts index f0ea6449907..b7e0efc99e3 100644 --- a/share/qtcreator/translations/qtcreator_cs.ts +++ b/share/qtcreator/translations/qtcreator_cs.ts @@ -54911,28 +54911,28 @@ Nainstalujte, prosím, jedno SDK s API verze alespoň %1. <span style=" color:#ff0000;">Heslo je OK</span> - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">Heslo k úložišti klíče je příliš krátké</span> + Keystore password is too short. + Heslo k úložišti klíče je příliš krátké. - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">Hesla k úložišti klíče neodpovídají</span> + Keystore passwords do not match. + Hesla k úložišti klíče neodpovídají. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Heslo k certifikátu je příliš krátké</span> + Certificate password is too short. + Heslo k certifikátu je příliš krátké. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Hesla k certifikátům neodpovídají</span> + Certificate passwords do not match. + Hesla k certifikátům neodpovídají. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">Alias certifikátu chybí</span> + Certificate alias is missing. + Alias certifikátu chybí. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Neplatné číslo země (mezinárodní předvolba)</span> + Invalid country code. + Neplatné číslo země (mezinárodní předvolba). Keystore file name diff --git a/share/qtcreator/translations/qtcreator_da.ts b/share/qtcreator/translations/qtcreator_da.ts index 41fd7c673ca..4cfd3841b60 100644 --- a/share/qtcreator/translations/qtcreator_da.ts +++ b/share/qtcreator/translations/qtcreator_da.ts @@ -268,28 +268,28 @@ Minimum API-niveauet krævet af kittet er %1. Android::Internal::AndroidCreateKeystoreCertificate - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">Keystore adgangskode er for kort</span> + Keystore password is too short. + Keystore adgangskode er for kort. - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">Keystore adgangskoder matcher ikke</span> + Keystore passwords do not match. + Keystore adgangskoder matcher ikke. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Certifikat adgangskode er for kort</span> + Certificate password is too short. + Certifikat adgangskode er for kort. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Certifikat adgangskoder matcher ikke</span> + Certificate passwords do not match. + Certifikat adgangskoder matcher ikke. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">Certifikat-alias mangler</span> + Certificate alias is missing. + Certifikat-alias mangler. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Ugyldig sprogkode</span> + Invalid country code. + Ugyldig sprogkode. Keystore Filename diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index 8eaec177f8d..dece10295e4 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -19510,28 +19510,28 @@ should a repository require SSH-authentication (see documentation on SSH and the Android::Internal::AndroidCreateKeystoreCertificate - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">Das Keystore-Passwort ist zu kurz</span> + Keystore password is too short. + Das Keystore-Passwort ist zu kurz. - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">Die Keystore-Passwörter stimmen nicht überein</span> + Keystore passwords do not match. + Die Keystore-Passwörter stimmen nicht überein. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Das Passwort des Zertifikats ist zu kurz</span> + Certificate password is too short. + Das Passwort des Zertifikats ist zu kurz. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Die Passwörter des Zertifikats stimmen nicht überein</span> + Certificate passwords do not match. + Die Passwörter des Zertifikats stimmen nicht überein. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">Der Alias des Zertifikats fehlt</span> + Certificate alias is missing. + Der Alias des Zertifikats fehlt. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Ungültiger Ländercode</span> + Invalid country code. + Ungültiger Ländercode. Keystore Filename diff --git a/share/qtcreator/translations/qtcreator_fr.ts b/share/qtcreator/translations/qtcreator_fr.ts index 95808e6d7b9..ec42c365792 100644 --- a/share/qtcreator/translations/qtcreator_fr.ts +++ b/share/qtcreator/translations/qtcreator_fr.ts @@ -60828,28 +60828,28 @@ Veuillez installer un SDK supérieur à la version %1. <span style=" color:#00ff00;">Mot de passe correct</span> - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">Le mot de passe du trousseau de clés est trop court</span> + Keystore password is too short. + Le mot de passe du trousseau de clés est trop court. - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">Les mots de passe du trousseau de clés ne correspondent pas</span> + Keystore passwords do not match. + Les mots de passe du trousseau de clés ne correspondent pas. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Le mot de passe du certificat est manquant</span> + Certificate password is too short. + Le mot de passe du certificat est manquant. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Les mots de passe du certificat ne correspondent pas</span> + Certificate passwords do not match. + Les mots de passe du certificat ne correspondent pas. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">L'alias du certificat est manquant</span> + Certificate alias is missing. + L'alias du certificat est manquant. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Le code de pays est invalide</span> + Invalid country code. + Le code de pays est invalide. Keystore file name diff --git a/share/qtcreator/translations/qtcreator_hr.ts b/share/qtcreator/translations/qtcreator_hr.ts index 405ef04c3d0..e7a14f06a9c 100644 --- a/share/qtcreator/translations/qtcreator_hr.ts +++ b/share/qtcreator/translations/qtcreator_hr.ts @@ -14265,27 +14265,27 @@ The minimum API level required by the kit is %1. Android::Internal::AndroidCreateKeystoreCertificate - <span style=" color:#ff0000;">Keystore password is too short</span> + Keystore password is too short. - <span style=" color:#ff0000;">Keystore passwords do not match</span> + Keystore passwords do not match. - <span style=" color:#ff0000;">Certificate password is too short</span> + Certificate password is too short. - <span style=" color:#ff0000;">Certificate passwords do not match</span> + Certificate passwords do not match. - <span style=" color:#ff0000;">Certificate alias is missing</span> + Certificate alias is missing. - <span style=" color:#ff0000;">Invalid country code</span> + Invalid country code. diff --git a/share/qtcreator/translations/qtcreator_ja.ts b/share/qtcreator/translations/qtcreator_ja.ts index 890908ed99a..c65ccab4138 100644 --- a/share/qtcreator/translations/qtcreator_ja.ts +++ b/share/qtcreator/translations/qtcreator_ja.ts @@ -9625,28 +9625,28 @@ with a password, which you can enter below. Android::Internal::AndroidCreateKeystoreCertificate - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">キーストアパスワードが短すぎます</span> + Keystore password is too short. + キーストアパスワードが短すぎます。 - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">キーストアパスワードが一致しません</span> + Keystore passwords do not match. + キーストアパスワードが一致しません。 - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">証明書のパスワードが短すぎます</span> + Certificate password is too short. + 証明書のパスワードが短すぎます。 - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">証明書のパスワードが一致しません</span> + Certificate passwords do not match. + 証明書のパスワードが一致しません。 - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">証明書のエイリアスが見つかりません</span> + Certificate alias is missing. + 証明書のエイリアスが見つかりません。 - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">無効な国コードです</span> + Invalid country code. + 無効な国コードです。 Keystore file name diff --git a/share/qtcreator/translations/qtcreator_pl.ts b/share/qtcreator/translations/qtcreator_pl.ts index a088b92e294..4bd2dfddc49 100644 --- a/share/qtcreator/translations/qtcreator_pl.ts +++ b/share/qtcreator/translations/qtcreator_pl.ts @@ -21525,28 +21525,28 @@ Sprawdź dokumentację SSH i zmienną środowiskową SSH_ASKPASS. Android::Internal::AndroidCreateKeystoreCertificate - <span style=" color:#ff0000;">Keystore password is too short</span> + Keystore password is too short. - <span style=" color:#ff0000;">Keystore passwords do not match</span> + Keystore passwords do not match. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Hasło certyfikatu jest zbyt krótkie</span> + Certificate password is too short. + Hasło certyfikatu jest zbyt krótkie. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Hasła certyfikatu nie zgadzają się</span> + Certificate passwords do not match. + Hasła certyfikatu nie zgadzają się. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">Brak aliasu certyfikatu</span> + Certificate alias is missing. + Brak aliasu certyfikatu. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Niepoprawny kod kraju</span> + Invalid country code. + Niepoprawny kod kraju. Keystore Filename diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts index 343f1c468e4..1305808ff41 100644 --- a/share/qtcreator/translations/qtcreator_ru.ts +++ b/share/qtcreator/translations/qtcreator_ru.ts @@ -887,28 +887,28 @@ The files in the Android package source directory are copied to the build direct Android::Internal::AndroidCreateKeystoreCertificate - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">Пароль связки ключей слишком короткий</span> + Keystore password is too short. + Пароль связки ключей слишком короткий. - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">Неверный пароль связки ключей</span> + Keystore passwords do not match. + Неверный пароль связки ключей. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Пароль сертификата слишком короткий</span> + Certificate password is too short. + Пароль сертификата слишком короткий. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Неверный пароль сертификата</span> + Certificate passwords do not match. + Неверный пароль сертификата. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">Отсутствует алиас сертификата</span> + Certificate alias is missing. + Отсутствует алиас сертификата. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Неверный код страны</span> + Invalid country code. + Неверный код страны. Keystore Filename diff --git a/share/qtcreator/translations/qtcreator_uk.ts b/share/qtcreator/translations/qtcreator_uk.ts index f7de935b70e..7ed2f44691f 100644 --- a/share/qtcreator/translations/qtcreator_uk.ts +++ b/share/qtcreator/translations/qtcreator_uk.ts @@ -32522,28 +32522,28 @@ Please install an SDK of at least API version %1. <span style=" color:#00ff00;">Пароль вдалий</span> - <span style=" color:#ff0000;">Keystore password is too short</span> - <span style=" color:#ff0000;">Пароль сховища ключів закороткий</span> + Keystore password is too short. + Пароль сховища ключів закороткий. - <span style=" color:#ff0000;">Keystore passwords do not match</span> - <span style=" color:#ff0000;">Паролі сховища ключів не співпадають</span> + Keystore passwords do not match. + Паролі сховища ключів не співпадають. - <span style=" color:#ff0000;">Certificate password is too short</span> - <span style=" color:#ff0000;">Пароль сертифіката закороткий</span> + Certificate password is too short. + Пароль сертифіката закороткий. - <span style=" color:#ff0000;">Certificate passwords do not match</span> - <span style=" color:#ff0000;">Паролі сертифіката не співпадають</span> + Certificate passwords do not match. + Паролі сертифіката не співпадають. - <span style=" color:#ff0000;">Certificate alias is missing</span> - <span style=" color:#ff0000;">Відсутній псевдонім сертифіката</span> + Certificate alias is missing. + Відсутній псевдонім сертифіката. - <span style=" color:#ff0000;">Invalid country code</span> - <span style=" color:#ff0000;">Неправильний код країни</span> + Invalid country code. + Неправильний код країни. Keystore file name diff --git a/src/libs/qtcreatorcdbext/CMakeLists.txt b/src/libs/qtcreatorcdbext/CMakeLists.txt index 5b03103bc88..3797afd1cf2 100644 --- a/src/libs/qtcreatorcdbext/CMakeLists.txt +++ b/src/libs/qtcreatorcdbext/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake") @@ -60,17 +60,9 @@ add_qtc_library(qtcreatorcdbext qtc_library_enabled(_library_enabled qtcreatorcdbext) if (_library_enabled) - # TODO: Remove when cmake_minimum_required greater than 3.12 - if (CMAKE_VERSION VERSION_GREATER 3.12) - find_package(Python3 3.8 COMPONENTS Development) - set(PYTHONLIBS_FOUND ${Python3_Development_FOUND}) - set(PYTHON_LIBRARIES ${Python3_LIBRARIES}) - set(PYTHON_INCLUDE_DIR ${Python3_INCLUDE_DIRS}) - else() - find_package(PythonLibs 3.8) - endif() + find_package(Python3 3.8 COMPONENTS Development) - if (NOT ${PYTHONLIBS_FOUND}) + if (NOT ${Python3_Development_FOUND}) message(WARNING "PythonLibs (at least version 3.8) not found. qtcreatorcdbext will be built without Python support.") return() endif() @@ -80,7 +72,7 @@ if (_library_enabled) set(PythonRegex "^(.*)/(.*)/(python([0-9]+)_d)${CMAKE_IMPORT_LIBRARY_SUFFIX}$") endif() - foreach(lib IN LISTS PYTHON_LIBRARIES) + foreach(lib IN LISTS Python3_LIBRARIES) if (lib MATCHES ${PythonRegex}) if (CMAKE_BUILD_TYPE STREQUAL "Debug") set(PythonZipFileName "python${CMAKE_MATCH_4}_d.zip") @@ -105,8 +97,8 @@ if (_library_enabled) endif() extend_qtc_library(qtcreatorcdbext - DEPENDS "${PYTHON_LIBRARIES}" - INCLUDES "${PYTHON_INCLUDE_DIR}" + DEPENDS "${Python3_LIBRARIES}" + INCLUDES "${Python3_INCLUDE_DIRS}" DEFINES WITH_PYTHON=1 SOURCES pycdbextmodule.cpp pycdbextmodule.h diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 592830041e1..eb2bff71331 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -126,8 +126,8 @@ public: void setAbortOnMetaChars(bool abort); void start(); - void terminate(); - void interrupt(); + virtual void terminate(); + virtual void interrupt(); static bool startDetached(const CommandLine &cmd, const FilePath &workingDirectory = {}, qint64 *pid = nullptr); @@ -175,7 +175,7 @@ public: QByteArray rawStdOut() const; - int exitCode() const; + virtual int exitCode() const; QString exitMessage(); @@ -195,10 +195,10 @@ public: void setProcessChannelMode(QProcess::ProcessChannelMode mode); QProcess::ProcessError error() const; - QProcess::ProcessState state() const; + virtual QProcess::ProcessState state() const; bool isRunning() const; // Short for state() == QProcess::Running. - QString errorString() const; + virtual QString errorString() const; void setErrorString(const QString &str); qint64 processId() const; @@ -207,14 +207,14 @@ public: bool waitForReadyRead(int msecs = 30000); bool waitForFinished(int msecs = 30000); - QByteArray readAllStandardOutput(); - QByteArray readAllStandardError(); + virtual QByteArray readAllStandardOutput(); + virtual QByteArray readAllStandardError(); - QProcess::ExitStatus exitStatus() const; + virtual QProcess::ExitStatus exitStatus() const; - void kill(); + virtual void kill(); - qint64 write(const QByteArray &input); + virtual qint64 write(const QByteArray &input); void close(); void setStandardInputFile(const QString &inputFile); diff --git a/src/plugins/android/CMakeLists.txt b/src/plugins/android/CMakeLists.txt index b87f7ad1d24..2f4b06f634a 100644 --- a/src/plugins/android/CMakeLists.txt +++ b/src/plugins/android/CMakeLists.txt @@ -54,3 +54,9 @@ add_qtc_plugin(Android splashscreencontainerwidget.cpp splashscreencontainerwidget.h splashscreenwidget.cpp splashscreenwidget.h ) + +extend_qtc_plugin(Android + CONDITION WITH_TESTS + SOURCES + android_tst.qrc +) diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index 08e69d9421c..9d655cad61a 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -120,5 +120,13 @@ Project { "splashscreenwidget.cpp", "splashscreenwidget.h" ] + + Group { + name: "Unit tests" + condition: qtc.testsEnabled + files: [ + "android_tst.qrc", + ] + } } } diff --git a/src/plugins/android/android_tst.qrc b/src/plugins/android/android_tst.qrc new file mode 100644 index 00000000000..2d557291176 --- /dev/null +++ b/src/plugins/android/android_tst.qrc @@ -0,0 +1,71 @@ + + + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + android.qrc + + diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index ca8e29eb383..34383bad3a4 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -77,6 +77,11 @@ #include #include +#ifdef WITH_TESTS +# include +# include "androidplugin.h" +#endif // WITH_TESTS + using namespace QtSupport; using namespace ProjectExplorer; using namespace Utils; @@ -368,11 +373,11 @@ void AndroidConfig::parseDependenciesJson() } } -QVector AndroidConfig::availableNdkPlatforms(const QtVersion *qtVersion) const +static QList availableNdkPlatformsLegacy(const FilePath &ndkLocation) { - QVector availableNdkPlatforms; + QList availableNdkPlatforms; - ndkLocation(qtVersion) + ndkLocation .pathAppended("platforms") .iterateDirectory( [&availableNdkPlatforms](const FilePath &filePath) { @@ -384,10 +389,43 @@ QVector AndroidConfig::availableNdkPlatforms(const QtVersion *qtVersion) co }, {{"android-*"}, QDir::Dirs}); - Utils::sort(availableNdkPlatforms, std::greater<>()); return availableNdkPlatforms; } +static QList availableNdkPlatformsV21Plus(const FilePath &ndkLocation, const Abis &abis, + OsType hostOs) +{ + if (abis.isEmpty()) + return {}; + + const QString abi = AndroidConfig::toolsPrefix(abis.first()); + const FilePath libPath = + AndroidConfig::toolchainPathFromNdk(ndkLocation, hostOs) / "sysroot/usr/lib" / abi; + const QList dirEntries = libPath.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot); + const QList availableNdkPlatforms = + Utils::transform(dirEntries, [](const FilePath &path) { + return path.fileName().toInt(); }); + return availableNdkPlatforms; +} + +static QList availableNdkPlatformsImpl(const FilePath &ndkLocation, const Abis &abis, + OsType hostOs) +{ + QList result = availableNdkPlatformsLegacy(ndkLocation); + + if (result.isEmpty()) + result = availableNdkPlatformsV21Plus(ndkLocation, abis, hostOs); + + Utils::sort(result, std::greater<>()); + return result; +} + +QList AndroidConfig::availableNdkPlatforms(const QtVersion *qtVersion) const +{ + return availableNdkPlatformsImpl(ndkLocation(qtVersion), qtVersion->qtAbis(), + HostOsInfo::hostOs()); +} + QStringList AndroidConfig::getCustomNdkList() const { return m_customNdkList; @@ -513,7 +551,7 @@ FilePath AndroidConfig::avdManagerToolPath() const return FilePath(); } -FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation) +FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation, OsType hostOs) { const FilePath tcPath = ndkLocation / "toolchains/"; FilePath toolchainPath; @@ -525,7 +563,7 @@ FilePath AndroidConfig::toolchainPathFromNdk(const FilePath &ndkLocation) // detect toolchain host QStringList hostPatterns; - switch (HostOsInfo::hostOs()) { + switch (hostOs) { case OsTypeLinux: hostPatterns << QLatin1String("linux*"); break; @@ -881,7 +919,7 @@ bool AndroidConfig::isValidNdk(const QString &ndkLocation) const const FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms"); if (version.majorVersion() <= 22 && (!ndkPlatformsDir.exists() || ndkPlatformsDir.toString().contains(' '))) - return false; // TODO: Adapt code that assumes the presence of a "platforms" folder + return false; return true; } @@ -1641,4 +1679,62 @@ void AndroidConfigurations::updateAndroidDevice() AndroidConfigurations *AndroidConfigurations::m_instance = nullptr; +#ifdef WITH_TESTS +void AndroidPlugin::testAndroidConfigAvailableNdkPlatforms_data() +{ + QTest::addColumn("ndkPath"); + QTest::addColumn("abis"); + QTest::addColumn("hostOs"); + QTest::addColumn >("expectedPlatforms"); + + QTest::newRow("ndkLegacy") + << FilePath::fromUserInput(":/android/tst/ndk/19.2.5345600") + << Abis() + << OsTypeOther + << QList{28, 27, 26, 24, 23, 22, 21, 19, 18, 17, 16}; + + const FilePath ndkV21Plus = FilePath::fromUserInput(":/android/tst/ndk/23.1.7779620"); + const QList abis32Bit = {31, 30, 29, 28, 27, 26, 24, 23, 22, 21, 19, 18, 17, 16}; + const QList abis64Bit = {31, 30, 29, 28, 27, 26, 24, 23, 22, 21}; + QTest::newRow("ndkV21Plus armeabi-v7a OsTypeWindows") + << ndkV21Plus + << Abis{AndroidManager::androidAbi2Abi( + ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A)} + << OsTypeWindows + << abis32Bit; + + QTest::newRow("ndkV21Plus arm64-v8a OsTypeLinux") + << ndkV21Plus + << Abis{AndroidManager::androidAbi2Abi( + ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A)} + << OsTypeLinux + << abis64Bit; + + QTest::newRow("ndkV21Plus x86 OsTypeMac") + << ndkV21Plus + << Abis{AndroidManager::androidAbi2Abi( + ProjectExplorer::Constants::ANDROID_ABI_X86)} + << OsTypeMac + << abis32Bit; + + QTest::newRow("ndkV21Plus x86_64 OsTypeWindows") + << ndkV21Plus + << Abis{AndroidManager::androidAbi2Abi( + ProjectExplorer::Constants::ANDROID_ABI_X86_64)} + << OsTypeWindows + << abis64Bit; +} + +void AndroidPlugin::testAndroidConfigAvailableNdkPlatforms() +{ + QFETCH(FilePath, ndkPath); + QFETCH(Abis, abis); + QFETCH(OsType, hostOs); + QFETCH(QList, expectedPlatforms); + + const QList foundPlatforms = availableNdkPlatformsImpl(ndkPath, abis, hostOs); + QCOMPARE(foundPlatforms, expectedPlatforms); +} +#endif // WITH_TESTS + } // namespace Android diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index c924a3f3173..701e10190e9 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -135,7 +135,8 @@ public: Utils::FilePath avdManagerToolPath() const; Utils::FilePath toolchainPath(const QtSupport::QtVersion *qtVersion) const; - static Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation); + static Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation, + Utils::OsType hostOs = Utils::HostOsInfo::hostOs()); static Utils::FilePath clangPathFromNdk(const Utils::FilePath &ndkLocation); Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::QtVersion *qtVersion) const; @@ -189,7 +190,7 @@ private: void parseDependenciesJson(); - QVector availableNdkPlatforms(const QtSupport::QtVersion *qtVersion) const; + QList availableNdkPlatforms(const QtSupport::QtVersion *qtVersion) const; Utils::FilePath m_sdkLocation; QStringList m_sdkManagerToolArgs; @@ -248,3 +249,6 @@ private: }; } // namespace Android + +Q_DECLARE_METATYPE(ProjectExplorer::Abis) +Q_DECLARE_METATYPE(Utils::OsType) diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp index 42296720ed3..48c91c6bae8 100644 --- a/src/plugins/android/androidcreatekeystorecertificate.cpp +++ b/src/plugins/android/androidcreatekeystorecertificate.cpp @@ -42,6 +42,9 @@ AndroidCreateKeystoreCertificate::AndroidCreateKeystoreCertificate(QWidget *pare ui(new Ui::AndroidCreateKeystoreCertificate) { ui->setupUi(this); + ui->infoLabel->setType(InfoLabel::Error); + ui->infoLabel->hide(); + connect(ui->keystorePassLineEdit, &QLineEdit::textChanged, this, &AndroidCreateKeystoreCertificate::checkKeystorePassword); connect(ui->keystoreRetypePassLineEdit, &QLineEdit::textChanged, @@ -100,15 +103,17 @@ QString AndroidCreateKeystoreCertificate::certificatePassword() AndroidCreateKeystoreCertificate::PasswordStatus AndroidCreateKeystoreCertificate::checkKeystorePassword() { if (ui->keystorePassLineEdit->text().length() < 6) { - ui->infoLabel->setText(tr("Keystore password is too short")); + ui->infoLabel->show(); + ui->infoLabel->setText(tr("Keystore password is too short.")); return Invalid; } if (ui->keystorePassLineEdit->text() != ui->keystoreRetypePassLineEdit->text()) { - ui->infoLabel->setText(tr("Keystore passwords do not match")); - return NoMatch; + ui->infoLabel->show(); + ui->infoLabel->setText(tr("Keystore passwords do not match.")); + return NoMatch; } - ui->infoLabel->clear(); + ui->infoLabel->hide(); return Match; } @@ -118,37 +123,41 @@ AndroidCreateKeystoreCertificate::PasswordStatus AndroidCreateKeystoreCertificat return Match; if (ui->certificatePassLineEdit->text().length() < 6) { - ui->infoLabel->setText(tr("Certificate password is too short")); + ui->infoLabel->show(); + ui->infoLabel->setText(tr("Certificate password is too short.")); return Invalid; } if (ui->certificatePassLineEdit->text() != ui->certificateRetypePassLineEdit->text()) { - ui->infoLabel->setText(tr("Certificate passwords do not match")); + ui->infoLabel->show(); + ui->infoLabel->setText(tr("Certificate passwords do not match.")); return NoMatch; } - ui->infoLabel->clear(); + ui->infoLabel->hide(); return Match; } bool AndroidCreateKeystoreCertificate::checkCertificateAlias() { if (ui->certificateAliasLineEdit->text().length() == 0) { - ui->infoLabel->setText(tr("Certificate alias is missing")); + ui->infoLabel->show(); + ui->infoLabel->setText(tr("Certificate alias is missing.")); return false; } - ui->infoLabel->clear(); + ui->infoLabel->hide(); return true; } bool AndroidCreateKeystoreCertificate::checkCountryCode() { if (!ui->countryLineEdit->text().contains(QRegularExpression("[A-Z]{2}"))) { - ui->infoLabel->setText(tr("Invalid country code")); + ui->infoLabel->show(); + ui->infoLabel->setText(tr("Invalid country code.")); return false; } - ui->infoLabel->clear(); + ui->infoLabel->hide(); return true; } diff --git a/src/plugins/android/androidcreatekeystorecertificate.ui b/src/plugins/android/androidcreatekeystorecertificate.ui index 4c62e9e9414..639275329c1 100644 --- a/src/plugins/android/androidcreatekeystorecertificate.ui +++ b/src/plugins/android/androidcreatekeystorecertificate.ui @@ -299,17 +299,17 @@ - - - - - - Qt::AlignCenter - - + + + + Utils::InfoLabel + QLabel +
utils/infolabel.h
+
+
keystorePassLineEdit keystoreRetypePassLineEdit diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp index ab7dd8d4301..c92ec6af462 100644 --- a/src/plugins/android/androiddebugsupport.cpp +++ b/src/plugins/android/androiddebugsupport.cpp @@ -168,14 +168,15 @@ void AndroidDebugSupport::start() const int minimumNdk = qt ? qt->minimumNDK() : 0; int sdkVersion = qMax(AndroidManager::minimumSDK(kit), minimumNdk); - // TODO find a way to use the new sysroot layout - // instead ~/android/ndk-bundle/platforms/android-29/arch-arm64 - // use ~/android/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot if (qtVersion) { - Utils::FilePath sysRoot = AndroidConfigurations::currentConfig().ndkLocation(qtVersion) + const FilePath ndkLocation = + AndroidConfigurations::currentConfig().ndkLocation(qtVersion); + Utils::FilePath sysRoot = ndkLocation / "platforms" / QString("android-%1").arg(sdkVersion) - / devicePreferredAbi; + / devicePreferredAbi; // Legacy Ndk structure + if (!sysRoot.exists()) + sysRoot = AndroidConfig::toolchainPathFromNdk(ndkLocation) / "sysroot"; setSysRoot(sysRoot); qCDebug(androidDebugSupportLog) << "Sysroot: " << sysRoot; } diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index 5a4d2c2fe52..704deff6db1 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -515,6 +515,8 @@ QString AndroidManager::androidNameForApiLevel(int x) return QLatin1String("Android 11"); case 31: return QLatin1String("Android 12"); + case 32: + return QLatin1String("Android 12L"); default: return tr("Unknown Android version. API Level: %1").arg(x); } diff --git a/src/plugins/android/androidplugin.h b/src/plugins/android/androidplugin.h index d90449c3926..d4ad726cf05 100644 --- a/src/plugins/android/androidplugin.h +++ b/src/plugins/android/androidplugin.h @@ -48,6 +48,8 @@ class AndroidPlugin final : public ExtensionSystem::IPlugin private slots: void testAndroidSdkManagerProgressParser_data(); void testAndroidSdkManagerProgressParser(); + void testAndroidConfigAvailableNdkPlatforms_data(); + void testAndroidConfigAvailableNdkPlatforms(); #endif // WITH_TESTS }; diff --git a/src/plugins/android/androidsdkmanagerwidget.cpp b/src/plugins/android/androidsdkmanagerwidget.cpp index 6d330960f79..be93c03f609 100644 --- a/src/plugins/android/androidsdkmanagerwidget.cpp +++ b/src/plugins/android/androidsdkmanagerwidget.cpp @@ -137,7 +137,7 @@ AndroidSdkManagerWidget::AndroidSdkManagerWidget(AndroidConfig &config, }); connect(m_ui->applySelectionButton, &QPushButton::clicked, - this, &AndroidSdkManagerWidget::onApplyButton); + this, [this]() { onApplyButton(); }); connect(m_ui->cancelButton, &QPushButton::clicked, this, &AndroidSdkManagerWidget::onCancel); connect(m_ui->optionsButton, &QPushButton::clicked, @@ -204,7 +204,7 @@ AndroidSdkManagerWidget::~AndroidSdkManagerWidget() delete m_ui; } -void AndroidSdkManagerWidget::installEssentials() +void AndroidSdkManagerWidget::installEssentials(const QString &extraMessage) { m_sdkModel->selectMissingEssentials(); if (!m_sdkModel->missingEssentials().isEmpty()) { @@ -215,16 +215,19 @@ void AndroidSdkManagerWidget::installEssentials() .arg(Core::Constants::IDE_DISPLAY_NAME) .arg(m_sdkModel->missingEssentials().join("\", \""))); } - onApplyButton(); + onApplyButton(extraMessage); } void AndroidSdkManagerWidget::beginLicenseCheck() { m_formatter->appendMessage(tr("Checking pending licenses...\n"), Utils::NormalMessageFormat); + m_formatter->appendMessage(tr("The installation of Android SDK packages may fail if the " + "respective licenses are not accepted.\n"), + Utils::LogMessageFormat); addPackageFuture(m_sdkManager->checkPendingLicenses()); } -void AndroidSdkManagerWidget::onApplyButton() +void AndroidSdkManagerWidget::onApplyButton(const QString &extraMessage) { QTC_ASSERT(m_currentView == PackageListing, return); @@ -246,10 +249,11 @@ void AndroidSdkManagerWidget::onApplyButton() installPackages << str; } + QString message = tr("%n Android SDK packages shall be updated.", "", packagesToUpdate.count()); + if (!extraMessage.isEmpty()) + message.prepend(extraMessage + "\n\n"); QMessageBox messageDlg(QMessageBox::Information, tr("Android SDK Changes"), - tr("%n Android SDK packages shall be updated.", - "", packagesToUpdate.count()), - QMessageBox::Ok | QMessageBox::Cancel, this); + message, QMessageBox::Ok | QMessageBox::Cancel, this); QString details; if (!uninstallPackages.isEmpty()) @@ -317,20 +321,8 @@ void AndroidSdkManagerWidget::onLicenseCheckResult(const AndroidSdkManager::Oper // No assertion was found. Looks like all license are accepted. Go Ahead. runPendingCommand(); } else { - // Assertion was found. Provide user workflow to accept licenses. - QString warningMessage = tr("Review Android SDK package licenses that have not been " - "accepted?\nNote that the installation and use of " - "Android SDK packages may fail if respective licenses are not " - "accepted."); - int userSelection = QMessageBox::question(this, tr("Android SDK Licenses"), warningMessage, - QMessageBox::Yes | QMessageBox::No); - if (userSelection == QMessageBox::Yes) { - // Run license workflow. - beginLicenseWorkflow(); - } else { - // User decided to go ahead anyways. - runPendingCommand(); - } + // Run license workflow. + beginLicenseWorkflow(); } } diff --git a/src/plugins/android/androidsdkmanagerwidget.h b/src/plugins/android/androidsdkmanagerwidget.h index 58be2ce7af2..5266290b109 100644 --- a/src/plugins/android/androidsdkmanagerwidget.h +++ b/src/plugins/android/androidsdkmanagerwidget.h @@ -80,7 +80,7 @@ public: QWidget *parent = nullptr); ~AndroidSdkManagerWidget() override; - void installEssentials(); + void installEssentials(const QString &extraMessage = {}); signals: void updatingSdk(); @@ -88,7 +88,7 @@ signals: void licenseWorkflowStarted(); private: - void onApplyButton(); + void onApplyButton(const QString &extraMessage = {}); void onUpdatePackages(); void onCancel(); void onOperationResult(int index); diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index fda3366a95f..e928023937a 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -544,14 +544,9 @@ void AndroidSettingsWidget::validateSdk() AllEssentialsInstalledRow}); m_androidConfig.setSdkFullyConfigured(sdkToolsOk && componentsOk); if (sdkToolsOk && !componentsOk) { - // Ask user to install essential SDK components. Works only for sdk tools version >= 26.0.0 - QString message = tr("Android SDK installation is missing necessary packages. Do you " - "want to install the missing packages?"); - auto userInput = QMessageBox::information(this, tr("Missing Android SDK Packages"), - message, QMessageBox::Yes | QMessageBox::No); - if (userInput == QMessageBox::Yes) { - m_sdkManagerWidget->installEssentials(); - } + m_sdkManagerWidget->installEssentials( + "Android SDK installation is missing necessary packages. " + "Do you want to install the missing packages?"); } updateNdkList(); diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui index 227f4a5b5da..1dd2d8779ac 100644 --- a/src/plugins/android/androidsettingswidget.ui +++ b/src/plugins/android/androidsettingswidget.ui @@ -69,19 +69,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -89,6 +76,12 @@ + + + 0 + 0 + + QAbstractScrollArea::AdjustToContents diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index d7ecacc0668..02f596728dd 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -365,7 +365,6 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) } connect(bc->buildSystem(), &BuildSystem::parsingFinished, this, [this, stretcher] { - m_configModel->flush(); m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake()); m_configModel->setInitialParametersConfiguration( m_buildConfiguration->initialCMakeConfiguration()); @@ -481,12 +480,14 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) if (m_buildConfiguration->isEnabled()) setError(QString()); }); + connect(this, &QObject::destroyed, this, [this](const QObject *obj) { + updateInitialCMakeArguments(); + }); updateSelection(); updateConfigurationStateSelection(); } - void CMakeBuildSettingsWidget::batchEditConfiguration() { auto dialog = new QDialog(this); @@ -894,6 +895,30 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event) if ((action = createForceAction(ConfigModel::DataItem::STRING, idx))) menu->addAction(action); + menu->addSeparator(); + + auto applyKitOrInitialValue = new QAction(isInitialConfiguration() + ? tr("Apply Kit Value") + : tr("Apply Initial Configuration Value"), + this); + menu->addAction(applyKitOrInitialValue); + connect(applyKitOrInitialValue, &QAction::triggered, this, [this] { + const QModelIndexList selectedIndexes = m_configView->selectionModel()->selectedIndexes(); + + const QModelIndexList validIndexes = Utils::filtered(selectedIndexes, [](const QModelIndex &index) { + return index.isValid() && index.flags().testFlag(Qt::ItemIsSelectable); + }); + + for (const QModelIndex &index : validIndexes) { + if (isInitialConfiguration()) + m_configModel->applyKitValue(mapToSource(m_configView, index)); + else + m_configModel->applyInitialValue(mapToSource(m_configView, index)); + } + }); + + menu->addSeparator(); + auto copy = new QAction(tr("Copy"), this); menu->addAction(copy); connect(copy, &QAction::triggered, this, [this] { @@ -1622,6 +1647,8 @@ void InitialCMakeArgumentsAspect::setAllValues(const QString &values, QStringLis arg.replace("-T", "-DCMAKE_GENERATOR_TOOLSET:STRING="); } m_cmakeConfiguration = CMakeConfig::fromArguments(arguments, additionalArguments); + for (CMakeConfigItem &ci : m_cmakeConfiguration) + ci.isInitial = true; // Display the unknown arguments in "Additional CMake parameters" const QString additionalArgumentsValue = ProcessArgs::joinArgs(additionalArguments); @@ -1631,6 +1658,8 @@ void InitialCMakeArgumentsAspect::setAllValues(const QString &values, QStringLis void InitialCMakeArgumentsAspect::setCMakeConfiguration(const CMakeConfig &config) { m_cmakeConfiguration = config; + for (CMakeConfigItem &ci : m_cmakeConfiguration) + ci.isInitial = true; } void InitialCMakeArgumentsAspect::fromMap(const QVariantMap &map) diff --git a/src/plugins/cmakeprojectmanager/configmodel.cpp b/src/plugins/cmakeprojectmanager/configmodel.cpp index aa74f3986b6..af33564d5da 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.cpp +++ b/src/plugins/cmakeprojectmanager/configmodel.cpp @@ -180,6 +180,42 @@ void ConfigModel::toggleUnsetFlag(const QModelIndex &idx) emit dataChanged(keyIdx, valueIdx); } +void ConfigModel::applyKitValue(const QModelIndex &idx) +{ + applyKitOrInitialValue(idx, KitOrInitial::Kit); +} + +void ConfigModel::applyInitialValue(const QModelIndex &idx) +{ + applyKitOrInitialValue(idx, KitOrInitial::Initial); +} + +void ConfigModel::applyKitOrInitialValue(const QModelIndex &idx, KitOrInitial ki) +{ + Utils::TreeItem *item = itemForIndex(idx); + auto cmti = dynamic_cast(item); + + QTC_ASSERT(cmti, return ); + + auto dataItem = cmti->dataItem; + const QString &kitOrInitialValue = ki == KitOrInitial::Kit ? dataItem->kitValue + : dataItem->initialValue; + + // Allow a different value when the user didn't change anything (don't mark the same value as new) + // But allow the same value (going back) when the user did a change + const bool canSetValue = (dataItem->value != kitOrInitialValue && !dataItem->isUserChanged) + || dataItem->isUserChanged; + + if (!kitOrInitialValue.isEmpty() && canSetValue) { + dataItem->newValue = kitOrInitialValue; + dataItem->isUserChanged = dataItem->value != kitOrInitialValue; + + const QModelIndex valueIdx = idx.sibling(idx.row(), 1); + const QModelIndex keyIdx = idx.sibling(idx.row(), 0); + emit dataChanged(keyIdx, valueIdx); + } +} + ConfigModel::DataItem ConfigModel::dataItemFromIndex(const QModelIndex &idx) { const QAbstractItemModel *m = idx.model(); @@ -272,46 +308,68 @@ void ConfigModel::setInitialParametersConfiguration(const CMakeConfig &config) void ConfigModel::setConfiguration(const QList &config) { - QList tmp = config; - auto newIt = tmp.constBegin(); - auto newEndIt = tmp.constEnd(); - auto oldIt = m_configuration.constBegin(); - auto oldEndIt = m_configuration.constEnd(); + auto mergeLists = [](const QList &oldList, + const QList &newList) -> QList { + auto newIt = newList.constBegin(); + auto newEndIt = newList.constEnd(); + auto oldIt = oldList.constBegin(); + auto oldEndIt = oldList.constEnd(); - QList result; - while (newIt != newEndIt && oldIt != oldEndIt) { - if (oldIt->isUnset) { - ++oldIt; - } else if (newIt->isHidden || newIt->isUnset) { - ++newIt; - } else if (newIt->key < oldIt->key) { - // Add new entry: - result << *newIt; - ++newIt; - } else if (newIt->key > oldIt->key) { - // Keep old user settings, but skip other entries: - if (oldIt->isUserChanged || oldIt->isUserNew) - result << InternalDataItem(*oldIt); - ++oldIt; - } else { - // merge old/new entry: - InternalDataItem item(*newIt); - item.newValue = (newIt->value != oldIt->newValue) ? oldIt->newValue : QString(); - item.isUserChanged = !item.newValue.isEmpty() && (item.newValue != item.value); - result << item; - ++newIt; - ++oldIt; + QList result; + while (newIt != newEndIt && oldIt != oldEndIt) { + if (oldIt->isUnset) { + ++oldIt; + } else if (newIt->isHidden || newIt->isUnset) { + ++newIt; + } else if (newIt->key < oldIt->key) { + // Add new entry: + result << *newIt; + ++newIt; + } else if (newIt->key > oldIt->key) { + // Keep old user settings, but skip other entries: + if (oldIt->isUserChanged || oldIt->isUserNew) + result << InternalDataItem(*oldIt); + ++oldIt; + } else { + // merge old/new entry: + InternalDataItem item(*newIt); + item.newValue = (newIt->value != oldIt->newValue) ? oldIt->newValue : QString(); + + // Do not mark as user changed when we have a reset + if (oldIt->isUserChanged && !oldIt->newValue.isEmpty() && + !newIt->isUserChanged && newIt->newValue.isEmpty() && + oldIt->value == newIt->value) + item.newValue.clear(); + + item.isUserChanged = !item.newValue.isEmpty() && (item.newValue != item.value); + result << item; + ++newIt; + ++oldIt; + } } - } - // Add remaining new entries: - for (; newIt != newEndIt; ++newIt) { - if (newIt->isHidden) - continue; - result << InternalDataItem(*newIt); - } + // Add remaining new entries: + for (; newIt != newEndIt; ++newIt) { + if (newIt->isHidden) + continue; + result << InternalDataItem(*newIt); + } - m_configuration = result; + return result; + }; + + auto isInitial = [](const InternalDataItem &i) { return i.isInitial; }; + + QList initialOld; + QList currentOld; + std::tie(initialOld, currentOld) = Utils::partition(m_configuration, isInitial); + + QList initialNew; + QList currentNew; + std::tie(initialNew, currentNew) = Utils::partition(config, isInitial); + + m_configuration = mergeLists(initialOld, initialNew); + m_configuration.append(mergeLists(currentOld, currentNew)); generateTree(); } @@ -511,10 +569,9 @@ QString ConfigModelTreeItem::toolTip() const tooltip << QCoreApplication::translate("CMakeProjectManager", "

Kit: %1

") .arg(dataItem->kitValue); - if (dataItem->value != dataItem->newValue) - tooltip << QCoreApplication::translate("CMakeProjectManager", - "

Initial Configuration: %1

") - .arg(dataItem->value); + tooltip << QCoreApplication::translate("CMakeProjectManager", + "

Initial Configuration: %1

") + .arg(dataItem->currentValue()); } else { if (!dataItem->initialValue.isEmpty()) tooltip << QCoreApplication::translate("CMakeProjectManager", @@ -522,10 +579,9 @@ QString ConfigModelTreeItem::toolTip() const .arg(dataItem->initialValue); if (dataItem->inCMakeCache) { - if (dataItem->value != dataItem->newValue) - tooltip << QCoreApplication::translate("CMakeProjectManager", - "

Current Configuration: %1

") - .arg(dataItem->value); + tooltip << QCoreApplication::translate("CMakeProjectManager", + "

Current Configuration: %1

") + .arg(dataItem->currentValue()); } else { tooltip << QCoreApplication::translate("CMakeProjectManager", "

Not in CMakeCache.txt

"); diff --git a/src/plugins/cmakeprojectmanager/configmodel.h b/src/plugins/cmakeprojectmanager/configmodel.h index 87f37fcaed6..b50aea536a8 100644 --- a/src/plugins/cmakeprojectmanager/configmodel.h +++ b/src/plugins/cmakeprojectmanager/configmodel.h @@ -158,6 +158,9 @@ public: void toggleUnsetFlag(const QModelIndex &idx); + void applyKitValue(const QModelIndex &idx); + void applyInitialValue(const QModelIndex &idx); + static DataItem dataItemFromIndex(const QModelIndex &idx); QList configurationForCMake() const; @@ -166,6 +169,9 @@ public: void setMacroExpander(Utils::MacroExpander *newExpander); private: + enum class KitOrInitial { Kit, Initial }; + void applyKitOrInitialValue(const QModelIndex &idx, KitOrInitial ki); + class InternalDataItem : public DataItem { public: diff --git a/src/plugins/coreplugin/find/findtoolbar.cpp b/src/plugins/coreplugin/find/findtoolbar.cpp index 4a374fa742e..f7345f28c9c 100644 --- a/src/plugins/coreplugin/find/findtoolbar.cpp +++ b/src/plugins/coreplugin/find/findtoolbar.cpp @@ -224,12 +224,12 @@ FindToolBar::FindToolBar(CurrentDocumentFind *currentDocumentFind) m_selectAllAction = new QAction(tr("Select All"), this); cmd = ActionManager::registerAction(m_selectAllAction, Constants::FIND_SELECT_ALL); - cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Return"))); + cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Return"))); mfind->addAction(cmd, Constants::G_FIND_ACTIONS); connect(m_selectAllAction, &QAction::triggered, this, &FindToolBar::selectAll); m_localSelectAllAction = new QAction(m_selectAllAction->text(), this); cmd = ActionManager::registerAction(m_localSelectAllAction, Constants::FIND_SELECT_ALL, findcontext); - cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Return"))); + cmd->augmentActionWithShortcutToolTip(m_localSelectAllAction); connect(m_localSelectAllAction, &QAction::triggered, this, &FindToolBar::selectAll); m_ui.selectAllButton->setDefaultAction(m_localSelectAllAction); diff --git a/src/plugins/coreplugin/foldernavigationwidget.cpp b/src/plugins/coreplugin/foldernavigationwidget.cpp index 4726b3264a4..52cae412877 100644 --- a/src/plugins/coreplugin/foldernavigationwidget.cpp +++ b/src/plugins/coreplugin/foldernavigationwidget.cpp @@ -299,6 +299,7 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent m_listView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_listView->setDragEnabled(true); m_listView->setDragDropMode(QAbstractItemView::DragOnly); + m_listView->viewport()->installEventFilter(this); showOnlyFirstColumn(m_listView); setFocusProxy(m_listView); @@ -521,6 +522,20 @@ void FolderNavigationWidget::syncWithFilePath(const Utils::FilePath &filePath) selectFile(filePath); } +bool FolderNavigationWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_listView->viewport()) { + if (event->type() == QEvent::MouseButtonPress) { + // select the current root when clicking outside any other item + auto me = static_cast(event); + const QModelIndex index = m_listView->indexAt(me->pos()); + if (!index.isValid()) + m_listView->setCurrentIndex(m_listView->rootIndex()); + } + } + return false; +} + bool FolderNavigationWidget::autoSynchronization() const { return m_autoSync; diff --git a/src/plugins/coreplugin/foldernavigationwidget.h b/src/plugins/coreplugin/foldernavigationwidget.h index dbc3baec370..4cee261369a 100644 --- a/src/plugins/coreplugin/foldernavigationwidget.h +++ b/src/plugins/coreplugin/foldernavigationwidget.h @@ -130,6 +130,8 @@ public: void syncWithFilePath(const Utils::FilePath &filePath); + bool eventFilter(QObject *obj, QEvent *event) override; + protected: void contextMenuEvent(QContextMenuEvent *ev) override; diff --git a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp index 187413c30b8..780ae671ccd 100644 --- a/src/plugins/cppeditor/cppcodemodelsettingspage.cpp +++ b/src/plugins/cppeditor/cppcodemodelsettingspage.cpp @@ -219,7 +219,7 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD : d(new Private) { const ClangdSettings settings(settingsData); - d->useClangdCheckBox.setText(tr("Use clangd (EXPERIMENTAL)")); + d->useClangdCheckBox.setText(tr("Use clangd")); d->useClangdCheckBox.setChecked(settings.useClangd()); d->clangdChooser.setExpectedKind(Utils::PathChooser::ExistingCommand); d->clangdChooser.setFilePath(settings.clangdFilePath()); diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index a2284f50a81..383f05e9c0d 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -105,35 +105,18 @@ public: ~DockerDeviceProcess() {} void start(const Runnable &runnable) override; - void interrupt() override; - void terminate() override { m_process.terminate(); } - void kill() override; - - QProcess::ProcessState state() const override; - QProcess::ExitStatus exitStatus() const override; - int exitCode() const override; - QString errorString() const override; - - QByteArray readAllStandardOutput() override; - QByteArray readAllStandardError() override; - - qint64 write(const QByteArray &data) override { return m_process.write(data); } - -private: - QtcProcess m_process; }; DockerDeviceProcess::DockerDeviceProcess(const QSharedPointer &device, - QObject *parent) - : DeviceProcess(device, parent) - , m_process(ProcessMode::Writer) + QObject *parent) + : DeviceProcess(device, ProcessMode::Writer, parent) { } void DockerDeviceProcess::start(const Runnable &runnable) { - QTC_ASSERT(m_process.state() == QProcess::NotRunning, return); + QTC_ASSERT(state() == QProcess::NotRunning, return); DockerDevice::ConstPtr dockerDevice = qSharedPointerCast(device()); QTC_ASSERT(dockerDevice, return); @@ -146,68 +129,23 @@ void DockerDeviceProcess::start(const Runnable &runnable) MessageManager::writeDisrupting(QString::fromLocal8Bit(readAllStandardError())); }); - disconnect(&m_process); - CommandLine command = runnable.command; command.setExecutable( command.executable().withNewPath(dockerDevice->mapToDevicePath(command.executable()))); - m_process.setCommand(command); - m_process.setEnvironment(runnable.environment); - m_process.setWorkingDirectory(runnable.workingDirectory); - connect(&m_process, &QtcProcess::errorOccurred, this, &DeviceProcess::errorOccurred); - connect(&m_process, &QtcProcess::finished, this, &DeviceProcess::finished); - connect(&m_process, &QtcProcess::readyReadStandardOutput, - this, &DeviceProcess::readyReadStandardOutput); - connect(&m_process, &QtcProcess::readyReadStandardError, - this, &DeviceProcess::readyReadStandardError); - connect(&m_process, &QtcProcess::started, this, &DeviceProcess::started); + setCommand(command); + setEnvironment(runnable.environment); + setWorkingDirectory(runnable.workingDirectory); LOG("Running process:" << command.toUserOutput() << "in" << runnable.workingDirectory.toUserOutput()); - dockerDevice->runProcess(m_process); + dockerDevice->runProcess(*this); } void DockerDeviceProcess::interrupt() { - device()->signalOperation()->interruptProcess(m_process.processId()); + device()->signalOperation()->interruptProcess(processId()); } -void DockerDeviceProcess::kill() -{ - m_process.kill(); -} - -QProcess::ProcessState DockerDeviceProcess::state() const -{ - return m_process.state(); -} - -QProcess::ExitStatus DockerDeviceProcess::exitStatus() const -{ - return m_process.exitStatus(); -} - -int DockerDeviceProcess::exitCode() const -{ - return m_process.exitCode(); -} - -QString DockerDeviceProcess::errorString() const -{ - return m_process.errorString(); -} - -QByteArray DockerDeviceProcess::readAllStandardOutput() -{ - return m_process.readAllStandardOutput(); -} - -QByteArray DockerDeviceProcess::readAllStandardError() -{ - return m_process.readAllStandardError(); -} - - class DockerPortsGatheringMethod : public PortsGatheringMethod { Runnable runnable(QAbstractSocket::NetworkLayerProtocol protocol) const override diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 91e441ca682..3a51e2c043b 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -2225,10 +2225,12 @@ Environment GitClient::processEnvironment() const environment.prependOrSetPath(FilePath::fromUserInput(gitPath)); if (HostOsInfo::isWindowsHost() && settings().winSetHomeEnvironment.value()) { QString homePath; - if (const char *homeDrive = qgetenv("HOMEDRIVE")) - homePath = QString::fromLocal8Bit(homeDrive) + QString::fromLocal8Bit(qgetenv("HOMEPATH")); - else + if (qEnvironmentVariableIsEmpty("HOMESHARE")) { homePath = QDir::toNativeSeparators(QDir::homePath()); + } else { + homePath = QString::fromLocal8Bit(qgetenv("HOMEDRIVE")) + + QString::fromLocal8Bit(qgetenv("HOMEPATH")); + } environment.set("HOME", homePath); } environment.set("GIT_EDITOR", m_disableEditor ? "true" : m_gitQtcEditor); diff --git a/src/plugins/imageviewer/imageview.cpp b/src/plugins/imageviewer/imageview.cpp index c435666d15f..c5ef478e595 100644 --- a/src/plugins/imageviewer/imageview.cpp +++ b/src/plugins/imageviewer/imageview.cpp @@ -57,10 +57,31 @@ namespace ImageViewer { namespace Constants { const qreal DEFAULT_SCALE_FACTOR = 1.2; + const qreal zoomLevels[] = { 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 4.0, 8.0 }; } namespace Internal { +static qreal nextLevel(qreal currentLevel) +{ + auto iter = std::find_if(std::begin(Constants::zoomLevels), std::end(Constants::zoomLevels), [&](qreal val) { + return val > currentLevel; + }); + if (iter != std::end(Constants::zoomLevels)) + return *iter; + return currentLevel; +} + +static qreal previousLevel(qreal currentLevel) +{ + auto iter = std::find_if(std::rbegin(Constants::zoomLevels), std::rend(Constants::zoomLevels), [&](qreal val) { + return val < currentLevel; + }); + if (iter != std::rend(Constants::zoomLevels)) + return *iter; + return currentLevel; +} + ImageView::ImageView(ImageViewerFile *file) : m_file(file) { @@ -245,16 +266,7 @@ void ImageView::setViewOutline(bool enable) void ImageView::doScale(qreal factor) { - qreal currentScale = transform().m11(); - qreal newScale = currentScale * factor; - qreal actualFactor = factor; - // cap to 0.001 - 1000 - if (newScale > 1000) - actualFactor = 1000./currentScale; - else if (newScale < 0.001) - actualFactor = 0.001/currentScale; - - scale(actualFactor, actualFactor); + scale(factor, factor); emitScaleFactor(); if (auto pixmapItem = dynamic_cast(m_imageItem)) pixmapItem->setTransformationMode( @@ -264,18 +276,26 @@ void ImageView::doScale(qreal factor) void ImageView::wheelEvent(QWheelEvent *event) { qreal factor = qPow(Constants::DEFAULT_SCALE_FACTOR, event->angleDelta().y() / 240.0); - doScale(factor); + qreal currentScale = transform().m11(); + qreal newScale = currentScale * factor; + // cap to 0.001 - 1000 + qreal actualFactor = qBound(0.001, factor, 1000.0); + doScale(actualFactor); event->accept(); } void ImageView::zoomIn() { - doScale(Constants::DEFAULT_SCALE_FACTOR); + qreal nextZoomLevel = nextLevel(transform().m11()); + resetTransform(); + doScale(nextZoomLevel); } void ImageView::zoomOut() { - doScale(1. / Constants::DEFAULT_SCALE_FACTOR); + qreal previousZoomLevel = previousLevel(transform().m11()); + resetTransform(); + doScale(previousZoomLevel); } void ImageView::resetToOriginalSize() diff --git a/src/plugins/projectexplorer/applicationlauncher.cpp b/src/plugins/projectexplorer/applicationlauncher.cpp index 475622c7038..b3dfc5a2161 100644 --- a/src/plugins/projectexplorer/applicationlauncher.cpp +++ b/src/plugins/projectexplorer/applicationlauncher.cpp @@ -100,7 +100,7 @@ public: bool m_runAsRoot = false; // Local - QtcProcess *m_localProcess = nullptr; + std::unique_ptr m_localProcess; bool m_useTerminal = false; QProcess::ProcessChannelMode m_processChannelMode; // Keep track whether we need to emit a finished signal @@ -334,27 +334,26 @@ void ApplicationLauncherPrivate::start(const Runnable &runnable, const IDevice:: m_isLocal = local; if (m_isLocal) { - QTC_ASSERT(!m_localProcess, return); const QtcProcess::TerminalMode terminalMode = m_useTerminal ? QtcProcess::TerminalOn : QtcProcess::TerminalOff; - m_localProcess = new QtcProcess(terminalMode, this); + m_localProcess.reset(new QtcProcess(terminalMode, this)); m_localProcess->setProcessChannelMode(m_processChannelMode); if (m_processChannelMode == QProcess::SeparateChannels) { - connect(m_localProcess, &QtcProcess::readyReadStandardError, + connect(m_localProcess.get(), &QtcProcess::readyReadStandardError, this, &ApplicationLauncherPrivate::readLocalStandardError); } if (!m_useTerminal) { - connect(m_localProcess, &QtcProcess::readyReadStandardOutput, + connect(m_localProcess.get(), &QtcProcess::readyReadStandardOutput, this, &ApplicationLauncherPrivate::readLocalStandardOutput); } - connect(m_localProcess, &QtcProcess::started, + connect(m_localProcess.get(), &QtcProcess::started, this, &ApplicationLauncherPrivate::handleProcessStarted); - connect(m_localProcess, &QtcProcess::finished, this, [this] { + connect(m_localProcess.get(), &QtcProcess::finished, this, [this] { localProcessDone(m_localProcess->exitCode(), m_localProcess->exitStatus()); }); - connect(m_localProcess, &QtcProcess::errorOccurred, + connect(m_localProcess.get(), &QtcProcess::errorOccurred, this, &ApplicationLauncherPrivate::localProcessError); diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp index 004eef0af51..c2106967f77 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.cpp @@ -39,76 +39,23 @@ namespace Internal { DesktopDeviceProcess::DesktopDeviceProcess(const QSharedPointer &device, QObject *parent) - : DeviceProcess(device, parent) - , m_process(ProcessMode::Writer) + : DeviceProcess(device, ProcessMode::Writer, parent) { - connect(&m_process, &QtcProcess::errorOccurred, this, &DeviceProcess::errorOccurred); - connect(&m_process, &QtcProcess::finished, this, &DeviceProcess::finished); - connect(&m_process, &QtcProcess::readyReadStandardOutput, - this, &DeviceProcess::readyReadStandardOutput); - connect(&m_process, &QtcProcess::readyReadStandardError, - this, &DeviceProcess::readyReadStandardError); - connect(&m_process, &QtcProcess::started, this, &DeviceProcess::started); } void DesktopDeviceProcess::start(const Runnable &runnable) { - QTC_ASSERT(m_process.state() == QProcess::NotRunning, return); + QTC_ASSERT(state() == QProcess::NotRunning, return); if (runnable.environment.size()) - m_process.setEnvironment(runnable.environment); - m_process.setWorkingDirectory(runnable.workingDirectory); - m_process.setCommand(runnable.command); - m_process.start(); + setEnvironment(runnable.environment); + setWorkingDirectory(runnable.workingDirectory); + setCommand(runnable.command); + QtcProcess::start(); } void DesktopDeviceProcess::interrupt() { - device()->signalOperation()->interruptProcess(m_process.processId()); -} - -void DesktopDeviceProcess::terminate() -{ - m_process.terminate(); -} - -void DesktopDeviceProcess::kill() -{ - m_process.kill(); -} - -QProcess::ProcessState DesktopDeviceProcess::state() const -{ - return m_process.state(); -} - -QProcess::ExitStatus DesktopDeviceProcess::exitStatus() const -{ - return m_process.exitStatus(); -} - -int DesktopDeviceProcess::exitCode() const -{ - return m_process.exitCode(); -} - -QString DesktopDeviceProcess::errorString() const -{ - return m_process.errorString(); -} - -QByteArray DesktopDeviceProcess::readAllStandardOutput() -{ - return m_process.readAllStandardOutput(); -} - -QByteArray DesktopDeviceProcess::readAllStandardError() -{ - return m_process.readAllStandardError(); -} - -qint64 DesktopDeviceProcess::write(const QByteArray &data) -{ - return m_process.write(data); + device()->signalOperation()->interruptProcess(processId()); } } // namespace Internal diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h index 72c3e962caa..ed926112a2d 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h +++ b/src/plugins/projectexplorer/devicesupport/desktopdeviceprocess.h @@ -41,21 +41,6 @@ public: void start(const Runnable &runnable) override; void interrupt() override; - void terminate() override; - void kill() override; - - QProcess::ProcessState state() const override; - QProcess::ExitStatus exitStatus() const override; - int exitCode() const override; - QString errorString() const override; - - QByteArray readAllStandardOutput() override; - QByteArray readAllStandardError() override; - - qint64 write(const QByteArray &data) override; - -private: - Utils::QtcProcess m_process; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp index 766e21cb999..84c692e5a47 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp +++ b/src/plugins/projectexplorer/devicesupport/deviceprocess.cpp @@ -30,10 +30,14 @@ #include #include +using namespace Utils; + namespace ProjectExplorer { -DeviceProcess::DeviceProcess(const IDevice::ConstPtr &device, QObject *parent) - : QObject(parent), m_device(device) +DeviceProcess::DeviceProcess(const IDevice::ConstPtr &device, + const QtcProcess::Setup &setup, + QObject *parent) + : QtcProcess(setup, parent), m_device(device) { } diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocess.h b/src/plugins/projectexplorer/devicesupport/deviceprocess.h index c097bc6d09b..215b26879b4 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceprocess.h +++ b/src/plugins/projectexplorer/devicesupport/deviceprocess.h @@ -27,8 +27,8 @@ #include "../projectexplorer_export.h" -#include -#include +#include + #include #include @@ -37,38 +37,21 @@ namespace ProjectExplorer { class IDevice; class Runnable; -class PROJECTEXPLORER_EXPORT DeviceProcess : public QObject +class PROJECTEXPLORER_EXPORT DeviceProcess : public Utils::QtcProcess { Q_OBJECT public: + using Utils::QtcProcess::start; virtual void start(const Runnable &runnable) = 0; - virtual void interrupt() = 0; - virtual void terminate() = 0; - virtual void kill() = 0; - - virtual QProcess::ProcessState state() const = 0; - virtual QProcess::ExitStatus exitStatus() const = 0; - virtual int exitCode() const = 0; - virtual QString errorString() const = 0; - - virtual QByteArray readAllStandardOutput() = 0; - virtual QByteArray readAllStandardError() = 0; - - virtual qint64 write(const QByteArray &data) = 0; void setRunInTerminal(bool term) { m_runInTerminal = term; } bool runInTerminal() const { return m_runInTerminal; } -signals: - void started(); - void finished(); - void errorOccurred(QProcess::ProcessError error); - - void readyReadStandardOutput(); - void readyReadStandardError(); - protected: - explicit DeviceProcess(const QSharedPointer &device, QObject *parent = nullptr); + explicit DeviceProcess(const QSharedPointer &device, + const Utils::QtcProcess::Setup &setup, + QObject *parent = nullptr); + QSharedPointer device() const; private: diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp index 6456cdacfb3..5d7d285e668 100644 --- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp +++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.cpp @@ -48,20 +48,17 @@ enum class Signal { Interrupt, Terminate, Kill }; class SshDeviceProcess::SshDeviceProcessPrivate { public: - SshDeviceProcessPrivate(SshDeviceProcess *q) : q(q), consoleProcess(QtcProcess::TerminalOn) {} + SshDeviceProcessPrivate(SshDeviceProcess *q) : q(q) {} SshDeviceProcess * const q; + bool ignoreFinished = true; QSsh::SshConnection *connection = nullptr; - QSsh::SshRemoteProcessPtr process; - QtcProcess consoleProcess; + QSsh::SshRemoteProcessPtr remoteProcess; Runnable runnable; QString errorMessage; QProcess::ExitStatus exitStatus = QProcess::NormalExit; DeviceProcessSignalOperation::Ptr killOperation; QTimer killTimer; - QByteArray stdOut; - QByteArray stdErr; - int exitCode = -1; enum State { Inactive, Connecting, Connected, ProcessRunning } state = Inactive; void setState(State newState); @@ -74,8 +71,10 @@ public: }; SshDeviceProcess::SshDeviceProcess(const IDevice::ConstPtr &device, QObject *parent) - : DeviceProcess(device, parent), d(std::make_unique(this)) + : DeviceProcess(device, QtcProcess::TerminalOn, parent), + d(std::make_unique(this)) { + connect(this, &QtcProcess::finished, this, &SshDeviceProcess::handleThisProcessFinished); connect(&d->killTimer, &QTimer::timeout, this, &SshDeviceProcess::handleKillOperationTimeout); } @@ -91,7 +90,6 @@ void SshDeviceProcess::start(const Runnable &runnable) d->setState(SshDeviceProcessPrivate::Connecting); d->errorMessage.clear(); - d->exitCode = -1; d->exitStatus = QProcess::NormalExit; d->runnable = runnable; QSsh::SshConnectionParameters params = device()->sshParameters(); @@ -147,13 +145,13 @@ QProcess::ProcessState SshDeviceProcess::state() const QProcess::ExitStatus SshDeviceProcess::exitStatus() const { - return d->exitStatus == QProcess::NormalExit && d->exitCode != 255 + return d->exitStatus == QProcess::NormalExit && exitCode() != 255 ? QProcess::NormalExit : QProcess::CrashExit; } int SshDeviceProcess::exitCode() const { - return d->exitCode; + return runInTerminal() ? QtcProcess::exitCode() : d->remoteProcess->exitCode(); } QString SshDeviceProcess::errorString() const @@ -163,16 +161,12 @@ QString SshDeviceProcess::errorString() const QByteArray SshDeviceProcess::readAllStandardOutput() { - const QByteArray data = d->stdOut; - d->stdOut.clear(); - return data; + return d->remoteProcess.get() ? d->remoteProcess->readAllStandardOutput() : QByteArray(); } QByteArray SshDeviceProcess::readAllStandardError() { - const QByteArray data = d->stdErr; - d->stdErr.clear(); - return data; + return d->remoteProcess.get() ? d->remoteProcess->readAllStandardError() : QByteArray(); } qint64 SshDeviceProcess::processId() const @@ -185,32 +179,27 @@ void SshDeviceProcess::handleConnected() QTC_ASSERT(d->state == SshDeviceProcessPrivate::Connecting, return); d->setState(SshDeviceProcessPrivate::Connected); - d->process = runInTerminal() && d->runnable.command.isEmpty() + d->remoteProcess = runInTerminal() && d->runnable.command.isEmpty() ? d->connection->createRemoteShell() : d->connection->createRemoteProcess(fullCommandLine(d->runnable)); const QString display = d->displayName(); if (!display.isEmpty()) - d->process->requestX11Forwarding(display); + d->remoteProcess->requestX11Forwarding(display); if (runInTerminal()) { - connect(&d->consoleProcess, &QtcProcess::errorOccurred, - this, &DeviceProcess::errorOccurred); - connect(&d->consoleProcess, &QtcProcess::started, - this, &SshDeviceProcess::handleProcessStarted); - connect(&d->consoleProcess, &QtcProcess::finished, - this, [this] { handleProcessFinished(d->consoleProcess.errorString()); }); - d->consoleProcess.setAbortOnMetaChars(false); - d->consoleProcess.setCommand(d->process->fullLocalCommandLine(true)); - d->consoleProcess.start(); + d->ignoreFinished = false; + setAbortOnMetaChars(false); + setCommand(d->remoteProcess->fullLocalCommandLine(true)); + QtcProcess::start(); } else { - connect(d->process.get(), &QSsh::SshRemoteProcess::started, + connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::started, this, &SshDeviceProcess::handleProcessStarted); - connect(d->process.get(), &QSsh::SshRemoteProcess::done, - this, &SshDeviceProcess::handleProcessFinished); - connect(d->process.get(), &QSsh::SshRemoteProcess::readyReadStandardOutput, - this, &SshDeviceProcess::handleStdout); - connect(d->process.get(), &QSsh::SshRemoteProcess::readyReadStandardError, - this, &SshDeviceProcess::handleStderr); - d->process->start(); + connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::done, + this, &SshDeviceProcess::handleRemoteProcessFinished); + connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::readyReadStandardOutput, + this, &QtcProcess::readyReadStandardOutput); + connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::readyReadStandardError, + this, &QtcProcess::readyReadStandardError); + d->remoteProcess->start(); } } @@ -248,32 +237,29 @@ void SshDeviceProcess::handleProcessStarted() emit started(); } -void SshDeviceProcess::handleProcessFinished(const QString &error) +void SshDeviceProcess::handleThisProcessFinished() +{ + if (d->ignoreFinished) + return; + // Hack: we rely on fact that this slot was called before any other external slot connected + // to finished() signal. That's why we don't emit finished() signal from inside + // handleProcessFinished() since this signal will reach all other external slots anyway. + handleProcessFinished(QtcProcess::errorString(), false); +} + +void SshDeviceProcess::handleRemoteProcessFinished(const QString &error) +{ + handleProcessFinished(error, true); +} + +void SshDeviceProcess::handleProcessFinished(const QString &error, bool emitFinished) { d->errorMessage = error; - d->exitCode = runInTerminal() ? d->consoleProcess.exitCode() : d->process->exitCode(); if (d->killOperation && error.isEmpty()) d->errorMessage = tr("The process was ended forcefully."); d->setState(SshDeviceProcessPrivate::Inactive); - emit finished(); -} - -void SshDeviceProcess::handleStdout() -{ - QByteArray output = d->process->readAllStandardOutput(); - if (output.isEmpty()) - return; - d->stdOut += output; - emit readyReadStandardOutput(); -} - -void SshDeviceProcess::handleStderr() -{ - QByteArray output = d->process->readAllStandardError(); - if (output.isEmpty()) - return; - d->stdErr += output; - emit readyReadStandardError(); + if (emitFinished) + emit finished(); } void SshDeviceProcess::handleKillOperationFinished(const QString &errorMessage) @@ -356,12 +342,12 @@ void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDe killOperation->disconnect(q); killOperation.clear(); if (q->runInTerminal()) - QMetaObject::invokeMethod(&consoleProcess, &QtcProcess::stopProcess, Qt::QueuedConnection); + QMetaObject::invokeMethod(q, &QtcProcess::stopProcess, Qt::QueuedConnection); } killTimer.stop(); - consoleProcess.disconnect(); - if (process) - process->disconnect(q); + ignoreFinished = true; + if (remoteProcess) + remoteProcess->disconnect(q); if (connection) { connection->disconnect(q); QSsh::SshConnectionManager::releaseConnection(connection); @@ -372,7 +358,7 @@ void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDe qint64 SshDeviceProcess::write(const QByteArray &data) { QTC_ASSERT(!runInTerminal(), return -1); - return d->process->write(data); + return d->remoteProcess->write(data); } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h index 8c1da7cf558..11b5a92bc12 100644 --- a/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h +++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocess.h @@ -60,9 +60,9 @@ private: void handleConnectionError(); void handleDisconnected(); void handleProcessStarted(); - void handleProcessFinished(const QString &error); - void handleStdout(); - void handleStderr(); + void handleThisProcessFinished(); + void handleRemoteProcessFinished(const QString &error); + void handleProcessFinished(const QString &error, bool emitFinished); void handleKillOperationFinished(const QString &errorMessage); void handleKillOperationTimeout(); diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp index 44fc5ae511a..6a4b2264880 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp +++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp @@ -1538,7 +1538,7 @@ void MiniProjectTargetSelector::updateSummary() activeTarget->activeRunConfiguration()->expandedDisplayName())); } else if (startupProject->needsConfiguration()) { summary = tr("" + "a:link {color: rgb(128, 128, 255);}" "The project %1 is not yet configured

" "You can configure it in the Projects mode
") .arg(startupProject->displayName()); diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp index 7da09f1a340..f0824ead6e0 100644 --- a/src/plugins/projectexplorer/runcontrol.cpp +++ b/src/plugins/projectexplorer/runcontrol.cpp @@ -1123,7 +1123,8 @@ bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlStat return to == RunControlState::Stopped || to == RunControlState::Finishing; case RunControlState::Stopped: - return to == RunControlState::Finishing; + return to == RunControlState::Starting + || to == RunControlState::Finishing; case RunControlState::Finishing: return to == RunControlState::Finished; case RunControlState::Finished: diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index fcf71902c8e..68532c1a534 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -158,6 +158,7 @@ extend_qtc_plugin(QmlDesigner edit3dwidget.cpp edit3dwidget.h edit3dcanvas.cpp edit3dcanvas.h edit3dactions.cpp edit3dactions.h + edit3dvisibilitytogglesmenu.cpp edit3dvisibilitytogglesmenu.h edit3d.qrc ) diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.cpp b/src/plugins/qmldesigner/cmakegeneratordialog.cpp index a972147051d..eb7a35f170c 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialog.cpp +++ b/src/plugins/qmldesigner/cmakegeneratordialog.cpp @@ -28,6 +28,7 @@ #include "generatecmakelistsconstants.h" #include +#include #include #include @@ -50,17 +51,14 @@ CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePa m_model = new CMakeGeneratorDialogTreeModel(rootDir, files, this); - QVBoxLayout *layout = new QVBoxLayout(this); - setLayout(layout); + QVBoxLayout *dialogLayout = new QVBoxLayout(this); + dialogLayout->setSizeConstraint(QLayout::SetFixedSize); + setLayout(dialogLayout); - QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); - - auto *okButton = buttons->button(QDialogButtonBox::Ok); - okButton->setDefault(true); - - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText); + QWidget *advancedInnerWidget = new QWidget(this); + QVBoxLayout *advancedInnerLayout = new QVBoxLayout(advancedInnerWidget); + advancedInnerWidget->setLayout(advancedInnerLayout); + advancedInnerWidget->setMinimumHeight(640); QTreeView *tree = new QTreeView(this); tree->setModel(m_model); @@ -72,9 +70,31 @@ CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePa refreshNotificationText(); - layout->addWidget(tree, 2); - layout->addWidget(m_notifications, 1); - layout->addWidget(buttons); + advancedInnerLayout->addWidget(tree, 2); + advancedInnerLayout->addWidget(m_notifications, 1); + + DetailsWidget *advancedWidget = new DetailsWidget(this); + advancedWidget->setMinimumWidth(600); + advancedWidget->setWidget(advancedInnerWidget); + advancedWidget->setSummaryText(QCoreApplication::translate("QmlDesigner::GenerateCmake", + "Advanced Options")); + + QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + auto *okButton = buttons->button(QDialogButtonBox::Ok); + okButton->setDefault(true); + + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(m_model, &CMakeGeneratorDialogTreeModel::checkedStateChanged, this, &CmakeGeneratorDialog::refreshNotificationText); + + QLabel *mainLabel = new QLabel(QCoreApplication::translate("QmlDesigner::GenerateCmake", + "Start CMakeFiles.txt generation"), + this); + mainLabel->setMargin(50); + + dialogLayout->addWidget(mainLabel); + dialogLayout->addWidget(advancedWidget); + dialogLayout->addWidget(buttons); } FilePaths CmakeGeneratorDialog::getFilePaths() diff --git a/src/plugins/qmldesigner/components/edit3d/edit3d.qrc b/src/plugins/qmldesigner/components/edit3d/edit3d.qrc index bb1f6fd09c1..bf042b645b2 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3d.qrc +++ b/src/plugins/qmldesigner/components/edit3d/edit3d.qrc @@ -8,10 +8,6 @@ images/edit_light_off@2x.png images/edit_light_on.png images/edit_light_on@2x.png - images/grid_off.png - images/grid_off@2x.png - images/grid_on.png - images/grid_on@2x.png images/fit_selected.png images/fit_selected@2x.png images/move_off.png diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp index e7838e720e8..c5240a0cbd6 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.cpp @@ -60,7 +60,7 @@ void Edit3DActionTemplate::actionTriggered(bool b) Edit3DAction::Edit3DAction(const QByteArray &menuId, View3DActionCommand::Type type, const QString &description, const QKeySequence &key, bool checkable, bool checked, const QIcon &iconOff, const QIcon &iconOn, - SelectionContextOperation selectionAction) + SelectionContextOperation selectionAction, const QString &toolTip) : AbstractAction(new Edit3DActionTemplate(description, selectionAction, type)) , m_menuId(menuId) { @@ -68,6 +68,11 @@ Edit3DAction::Edit3DAction(const QByteArray &menuId, View3DActionCommand::Type t action()->setShortcutContext(Qt::WidgetWithChildrenShortcut); action()->setCheckable(checkable); action()->setChecked(checked); + + // Description will be used as tooltip by default if no explicit tooltip is provided + if (!toolTip.isEmpty()) + action()->setToolTip(toolTip); + if (checkable) { QIcon onOffIcon; const auto onAvail = iconOn.availableSizes(); // Assume both icons have same sizes available diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h index 27b8fb7342d..ca95608629e 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dactions.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dactions.h @@ -54,7 +54,8 @@ public: Edit3DAction(const QByteArray &menuId, View3DActionCommand::Type type, const QString &description, const QKeySequence &key, bool checkable, bool checked, const QIcon &iconOff, const QIcon &iconOn, - SelectionContextOperation selectionAction = nullptr); + SelectionContextOperation selectionAction = nullptr, + const QString &toolTip = {}); QByteArray category() const override; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index 386f6a1137f..8e6d75efc37 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -42,6 +42,7 @@ #include #include +#include namespace QmlDesigner { @@ -113,14 +114,17 @@ void Edit3DView::renderImage3DChanged(const QImage &img) void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) { - const QString sceneKey = QStringLiteral("sceneInstanceId"); - const QString selectKey = QStringLiteral("selectionMode"); - const QString transformKey = QStringLiteral("transformMode"); - const QString perspectiveKey = QStringLiteral("usePerspective"); - const QString orientationKey = QStringLiteral("globalOrientation"); - const QString editLightKey = QStringLiteral("showEditLight"); - const QString gridKey = QStringLiteral("showGrid"); - const QString particlesPlayKey = QStringLiteral("particlePlay"); + const QString sceneKey = QStringLiteral("sceneInstanceId"); + const QString selectKey = QStringLiteral("selectionMode"); + const QString transformKey = QStringLiteral("transformMode"); + const QString perspectiveKey = QStringLiteral("usePerspective"); + const QString orientationKey = QStringLiteral("globalOrientation"); + const QString editLightKey = QStringLiteral("showEditLight"); + const QString gridKey = QStringLiteral("showGrid"); + const QString selectionBoxKey = QStringLiteral("showSelectionBox"); + const QString iconGizmoKey = QStringLiteral("showIconGizmo"); + const QString cameraFrustumKey = QStringLiteral("showCameraFrustum"); + const QString particlesPlayKey = QStringLiteral("particlePlay"); if (sceneState.contains(sceneKey)) { qint32 newActiveScene = sceneState[sceneKey].value(); @@ -165,6 +169,21 @@ void Edit3DView::updateActiveScene3D(const QVariantMap &sceneState) else m_showGridAction->action()->setChecked(false); + if (sceneState.contains(selectionBoxKey)) + m_showSelectionBoxAction->action()->setChecked(sceneState[selectionBoxKey].toBool()); + else + m_showSelectionBoxAction->action()->setChecked(false); + + if (sceneState.contains(iconGizmoKey)) + m_showIconGizmoAction->action()->setChecked(sceneState[iconGizmoKey].toBool()); + else + m_showIconGizmoAction->action()->setChecked(false); + + if (sceneState.contains(cameraFrustumKey)) + m_showCameraFrustumAction->action()->setChecked(sceneState[cameraFrustumKey].toBool()); + else + m_showCameraFrustumAction->action()->setChecked(false); + if (sceneState.contains(particlesPlayKey)) m_particlesPlayAction->action()->setChecked(sceneState[particlesPlayKey].toBool()); else @@ -301,9 +320,27 @@ void Edit3DView::createEdit3DActions() m_showGridAction = new Edit3DAction( QmlDesigner::Constants::EDIT3D_EDIT_SHOW_GRID, View3DActionCommand::ShowGrid, - QCoreApplication::translate("ShowGridAction", "Toggle Grid Visibility"), - QKeySequence(Qt::Key_G), true, true, Icons::EDIT3D_GRID_OFF.icon(), - Icons::EDIT3D_GRID_ON.icon()); + QCoreApplication::translate("ShowGridAction", "Show Grid"), + QKeySequence(Qt::Key_G), true, true, {}, {}, nullptr, + QCoreApplication::translate("ShowGridAction", "Toggle the visibility of the helper grid.")); + + m_showSelectionBoxAction = new Edit3DAction( + QmlDesigner::Constants::EDIT3D_EDIT_SHOW_SELECTION_BOX, View3DActionCommand::ShowSelectionBox, + QCoreApplication::translate("ShowSelectionBoxAction", "Show Selection Boxes"), + QKeySequence(Qt::Key_S), true, true, {}, {}, nullptr, + QCoreApplication::translate("ShowSelectionBoxAction", "Toggle the visibility of selection boxes.")); + + m_showIconGizmoAction = new Edit3DAction( + QmlDesigner::Constants::EDIT3D_EDIT_SHOW_ICON_GIZMO, View3DActionCommand::ShowIconGizmo, + QCoreApplication::translate("ShowIconGizmoAction", "Show Icon Gizmos"), + QKeySequence(Qt::Key_I), true, true, {}, {}, nullptr, + QCoreApplication::translate("ShowIconGizmoAction", "Toggle the visibility of icon gizmos, such as light and camera icons.")); + + m_showCameraFrustumAction = new Edit3DAction( + QmlDesigner::Constants::EDIT3D_EDIT_SHOW_CAMERA_FRUSTUM, View3DActionCommand::ShowCameraFrustum, + QCoreApplication::translate("ShowCameraFrustumAction", "Always Show Camera Frustums"), + QKeySequence(Qt::Key_C), true, false, {}, {}, nullptr, + QCoreApplication::translate("ShowCameraFrustumAction", "Toggle between always showing the camera frustum visualization and only showing it when the camera is selected.")); SelectionContextOperation resetTrigger = [this](const SelectionContext &) { m_particlesPlayAction->action()->setEnabled(particlemode); @@ -360,6 +397,29 @@ void Edit3DView::createEdit3DActions() QKeySequence(Qt::Key_P), false, false, Utils::Icons::RESET_TOOLBAR.icon(), {}, resetTrigger); + SelectionContextOperation visibilityTogglesTrigger = [this](const SelectionContext &) { + if (!edit3DWidget()->visibilityTogglesMenu()) + return; + + QPoint pos; + const auto &actionWidgets = m_visibilityTogglesAction->action()->associatedWidgets(); + for (auto actionWidget : actionWidgets) { + if (auto button = qobject_cast(actionWidget)) { + pos = button->mapToGlobal(QPoint(0, 0)); + break; + } + } + + edit3DWidget()->showVisibilityTogglesMenu(!edit3DWidget()->visibilityTogglesMenu()->isVisible(), + pos); + }; + + m_visibilityTogglesAction = new Edit3DAction( + QmlDesigner::Constants::EDIT3D_VISIBILITY_TOGGLES, View3DActionCommand::Empty, + QCoreApplication::translate("VisibilityTogglesAction", "Visibility Toggles"), + QKeySequence(), false, false, Utils::Icons::EYE_OPEN_TOOLBAR.icon(), + {}, visibilityTogglesTrigger); + m_leftActions << m_selectionModeAction; m_leftActions << nullptr; // Null indicates separator m_leftActions << nullptr; // Second null after separator indicates an exclusive group @@ -372,16 +432,22 @@ void Edit3DView::createEdit3DActions() m_leftActions << m_cameraModeAction; m_leftActions << m_orientationModeAction; m_leftActions << m_editLightAction; - m_leftActions << m_showGridAction; m_leftActions << nullptr; m_leftActions << m_alignCamerasAction; m_leftActions << m_alignViewAction; + m_leftActions << nullptr; + m_leftActions << m_visibilityTogglesAction; m_rightActions << m_particleViewModeAction; m_rightActions << m_particlesPlayAction; m_rightActions << m_particlesRestartAction; m_rightActions << nullptr; m_rightActions << m_resetAction; + + m_visibilityToggleActions << m_showGridAction; + m_visibilityToggleActions << m_showSelectionBoxAction; + m_visibilityToggleActions << m_showIconGizmoAction; + m_visibilityToggleActions << m_showCameraFrustumAction; } QVector Edit3DView::leftActions() const @@ -394,6 +460,11 @@ QVector Edit3DView::rightActions() const return m_rightActions; } +QVector Edit3DView::visibilityToggleActions() const +{ + return m_visibilityToggleActions; +} + void Edit3DView::addQuick3DImport() { DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument(); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index a61f78301c0..721a69bfa2e 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -71,6 +71,7 @@ public: void createEdit3DActions(); QVector leftActions() const; QVector rightActions() const; + QVector visibilityToggleActions() const; void setSeeker(SeekerSlider *slider); void addQuick3DImport(); @@ -84,6 +85,7 @@ private: QPointer m_edit3DWidget; QVector m_leftActions; QVector m_rightActions; + QVector m_visibilityToggleActions; Edit3DAction *m_selectionModeAction = nullptr; Edit3DAction *m_moveToolAction = nullptr; Edit3DAction *m_rotateToolAction = nullptr; @@ -95,10 +97,14 @@ private: Edit3DAction *m_orientationModeAction = nullptr; Edit3DAction *m_editLightAction = nullptr; Edit3DAction *m_showGridAction = nullptr; + Edit3DAction *m_showSelectionBoxAction = nullptr; + Edit3DAction *m_showIconGizmoAction = nullptr; + Edit3DAction *m_showCameraFrustumAction = nullptr; Edit3DAction *m_resetAction = nullptr; Edit3DAction *m_particleViewModeAction = nullptr; Edit3DAction *m_particlesPlayAction = nullptr; Edit3DAction *m_particlesRestartAction = nullptr; + Edit3DAction *m_visibilityTogglesAction = nullptr; SeekerSlider *m_seeker = nullptr; int particlemode; }; diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dvisibilitytogglesmenu.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dvisibilitytogglesmenu.cpp new file mode 100644 index 00000000000..9769411e904 --- /dev/null +++ b/src/plugins/qmldesigner/components/edit3d/edit3dvisibilitytogglesmenu.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** 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 "edit3dvisibilitytogglesmenu.h" + +namespace QmlDesigner { + +Edit3DVisibilityTogglesMenu::Edit3DVisibilityTogglesMenu(QWidget *parent) : + QMenu(parent) +{ + setToolTipsVisible(true); +} + +void Edit3DVisibilityTogglesMenu::mouseReleaseEvent(QMouseEvent *e) +{ + QAction *action = activeAction(); + if (action && action->isEnabled()) { + // Prevent the menu from closing on click on any item + action->setEnabled(false); + QMenu::mouseReleaseEvent(e); + action->setEnabled(true); + action->trigger(); + } else { + QMenu::mouseReleaseEvent(e); + } +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dvisibilitytogglesmenu.h b/src/plugins/qmldesigner/components/edit3d/edit3dvisibilitytogglesmenu.h new file mode 100644 index 00000000000..1838068b0f3 --- /dev/null +++ b/src/plugins/qmldesigner/components/edit3d/edit3dvisibilitytogglesmenu.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** 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 + +namespace QmlDesigner { + +class Edit3DVisibilityTogglesMenu : public QMenu +{ + Q_OBJECT + +public: + explicit Edit3DVisibilityTogglesMenu(QWidget *parent = nullptr); + +protected: + void mouseReleaseEvent(QMouseEvent *e) override; + +private: +}; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index 06630e3a4de..d88cf612c15 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -28,6 +28,7 @@ #include "edit3dcanvas.h" #include "edit3dview.h" #include "edit3dwidget.h" +#include "edit3dvisibilitytogglesmenu.h" #include "metainfo.h" #include "qmldesignerconstants.h" #include "qmldesignerplugin.h" @@ -75,27 +76,37 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) : // Iterate through view actions. A null action indicates a separator and a second null action // after separator indicates an exclusive group. - auto addActionsToToolBox = [this, &context](const QVector &actions, bool left) { + auto handleActions = [this, &context](const QVector &actions, QMenu *menu, bool left) { bool previousWasSeparator = true; QActionGroup *group = nullptr; for (auto action : actions) { if (action) { + QAction *a = action->action(); if (group) - group->addAction(action->action()); - addAction(action->action()); - if (left) - m_toolBox->addLeftSideAction(action->action()); - else - m_toolBox->addRightSideAction(action->action()); + group->addAction(a); + if (menu) { + menu->addAction(a); + } else { + addAction(a); + if (left) + m_toolBox->addLeftSideAction(a); + else + m_toolBox->addRightSideAction(a); + } previousWasSeparator = false; // Register action as creator command to make it configurable Core::Command *command = Core::ActionManager::registerAction( - action->action(), action->menuId().constData(), context); - command->setDefaultKeySequence(action->action()->shortcut()); - command->augmentActionWithShortcutToolTip(action->action()); + a, action->menuId().constData(), context); + command->setDefaultKeySequence(a->shortcut()); + // Menu actions will have custom tooltips + if (menu) + a->setToolTip(command->stringWithAppendedShortcut(a->toolTip())); + else + command->augmentActionWithShortcutToolTip(a); + // Clear action shortcut so it doesn't conflict with command's override action - action->action()->setShortcut({}); + a->setShortcut({}); } else { if (previousWasSeparator) { group = new QActionGroup(this); @@ -104,18 +115,26 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) : group = nullptr; auto separator = new QAction(this); separator->setSeparator(true); - addAction(separator); - if (left) - m_toolBox->addLeftSideAction(separator); - else - m_toolBox->addRightSideAction(separator); + if (menu) { + menu->addAction(separator); + } else { + addAction(separator); + if (left) + m_toolBox->addLeftSideAction(separator); + else + m_toolBox->addRightSideAction(separator); + } previousWasSeparator = true; } } } }; - addActionsToToolBox(view->leftActions(), true); - addActionsToToolBox(view->rightActions(), false); + + handleActions(view->leftActions(), nullptr, true); + handleActions(view->rightActions(), nullptr, false); + + m_visibilityTogglesMenu = new Edit3DVisibilityTogglesMenu(this); + handleActions(view->visibilityToggleActions(), m_visibilityTogglesMenu, false); view->setSeeker(seeker); seeker->setToolTip(QLatin1String("Seek particle system time when paused.")); @@ -162,6 +181,21 @@ void Edit3DWidget::showCanvas(bool show) m_onboardingLabel->setVisible(!show); } +QMenu *Edit3DWidget::visibilityTogglesMenu() const +{ + return m_visibilityTogglesMenu.data(); +} + +void Edit3DWidget::showVisibilityTogglesMenu(bool show, const QPoint &pos) +{ + if (m_visibilityTogglesMenu.isNull()) + return; + if (show) + m_visibilityTogglesMenu->popup(pos); + else + m_visibilityTogglesMenu->close(); +} + void Edit3DWidget::linkActivated(const QString &link) { Q_UNUSED(link) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h index e7223ceb8c9..5a4ed48e28e 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -47,6 +48,8 @@ public: void contextHelp(const Core::IContext::HelpCallback &callback) const; void showCanvas(bool show); + QMenu *visibilityTogglesMenu() const; + void showVisibilityTogglesMenu(bool show, const QPoint &pos); protected: void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override; @@ -61,6 +64,7 @@ private: QPointer m_onboardingLabel; QPointer m_toolBox; Core::IContext *m_context = nullptr; + QPointer m_visibilityTogglesMenu; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_off.png b/src/plugins/qmldesigner/components/edit3d/images/grid_off.png deleted file mode 100644 index 4c355f70a89..00000000000 Binary files a/src/plugins/qmldesigner/components/edit3d/images/grid_off.png and /dev/null differ diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_off@2x.png b/src/plugins/qmldesigner/components/edit3d/images/grid_off@2x.png deleted file mode 100644 index 88db6b9badd..00000000000 Binary files a/src/plugins/qmldesigner/components/edit3d/images/grid_off@2x.png and /dev/null differ diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_on.png b/src/plugins/qmldesigner/components/edit3d/images/grid_on.png deleted file mode 100644 index 4c355f70a89..00000000000 Binary files a/src/plugins/qmldesigner/components/edit3d/images/grid_on.png and /dev/null differ diff --git a/src/plugins/qmldesigner/components/edit3d/images/grid_on@2x.png b/src/plugins/qmldesigner/components/edit3d/images/grid_on@2x.png deleted file mode 100644 index 88db6b9badd..00000000000 Binary files a/src/plugins/qmldesigner/components/edit3d/images/grid_on@2x.png and /dev/null differ diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.cpp index 1140ba43d7e..271f330fd23 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.cpp @@ -34,6 +34,7 @@ ItemLibraryAssetsFilesModel::ItemLibraryAssetsFilesModel(QObject *parent) // add roles m_roleNames.insert(FileNameRole, "fileName"); m_roleNames.insert(FilePathRole, "filePath"); + m_roleNames.insert(FileDirRole, "fileDir"); } QVariant ItemLibraryAssetsFilesModel::data(const QModelIndex &index, int role) const @@ -49,6 +50,9 @@ QVariant ItemLibraryAssetsFilesModel::data(const QModelIndex &index, int role) c if (role == FilePathRole) return m_files[index.row()]; + if (role == FileDirRole) + return QVariant::fromValue(parent()); + qWarning() << Q_FUNC_INFO << "Invalid role requested: " << QString::number(role); return {}; } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.h index 25577dce515..5b44878eefc 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsfilesmodel.h @@ -44,7 +44,8 @@ public: private: enum Roles {FileNameRole = Qt::UserRole + 1, - FilePathRole}; + FilePathRole, + FileDirRole}; QStringList m_files; QHash m_roleNames; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.cpp index a09391570d5..a04ff0f48f4 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,7 @@ void ItemLibraryAssetsModel::toggleExpandAll(bool expand) endResetModel(); } -void ItemLibraryAssetsModel::removeFile(const QString &filePath) +void ItemLibraryAssetsModel::deleteFile(const QString &filePath) { bool askBeforeDelete = DesignerSettings::getValue( DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool(); @@ -134,6 +135,52 @@ void ItemLibraryAssetsModel::removeFile(const QString &filePath) } } +void ItemLibraryAssetsModel::addNewFolder(const QString &folderPath) +{ + QString iterPath = folderPath; + QRegularExpression rgx("\\d+$"); // matches a number at the end of a string + QDir dir{folderPath}; + + while (dir.exists()) { + // if the folder name ends with a number, increment it + QRegularExpressionMatch match = rgx.match(iterPath); + if (match.hasMatch()) { // ends with a number + QString numStr = match.captured(0); + int num = match.captured(0).toInt(); + + // get number of padding zeros, ex: for "005" = 2 + int nPaddingZeros = 0; + for (; nPaddingZeros < numStr.size() && numStr[nPaddingZeros] == '0'; ++nPaddingZeros); + + ++num; + + // if the incremented number's digits increased, decrease the padding zeros + if (std::fmod(std::log10(num), 1.0) == 0) + --nPaddingZeros; + + iterPath = folderPath.mid(0, match.capturedStart()) + + QString('0').repeated(nPaddingZeros) + + QString::number(num); + } else { + iterPath = folderPath + '1'; + } + + dir.setPath(iterPath); + } + + dir.mkpath(iterPath); +} + +void ItemLibraryAssetsModel::deleteFolder(const QString &folderPath) +{ + QDir{folderPath}.removeRecursively(); +} + +QObject *ItemLibraryAssetsModel::rootDir() const +{ + return m_assetsDir; +} + const QStringList &ItemLibraryAssetsModel::supportedImageSuffixes() { static QStringList retList; @@ -270,7 +317,7 @@ void ItemLibraryAssetsModel::setRootPath(const QString &path) isEmpty &= parseDirRecursive(assetsDir, currDepth + 1); } - if (isEmpty) + if (!m_searchText.isEmpty() && isEmpty) currAssetsDir->setDirVisible(false); return isEmpty; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h index f7621563492..e429605b9a6 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetsmodel.h @@ -83,7 +83,10 @@ public: Q_INVOKABLE void toggleExpandAll(bool expand); Q_INVOKABLE DirExpandState getAllExpandedState() const; - Q_INVOKABLE void removeFile(const QString &filePath); + Q_INVOKABLE void deleteFile(const QString &filePath); + Q_INVOKABLE void addNewFolder(const QString &folderPath); + Q_INVOKABLE void deleteFolder(const QString &folderPath); + Q_INVOKABLE QObject *rootDir() const; signals: void isEmptyChanged(); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp index 1828317a9e8..2d96d01a9dc 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.cpp @@ -53,7 +53,6 @@ StatesEditorModel::StatesEditorModel(StatesEditorView *view) { } - int StatesEditorModel::count() const { return rowCount(); @@ -64,9 +63,8 @@ QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &par if (m_statesEditorView.isNull()) return {}; - int internalNodeId = 0; - if (row > 0) + if (row > 0 && row < rowCount() - 1) // first and last rows are base state, add state internalNodeId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId(); return hasIndex(row, column, parent) ? createIndex(row, column, internalNodeId) : QModelIndex(); @@ -78,9 +76,9 @@ int StatesEditorModel::rowCount(const QModelIndex &parent) const return 0; if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states")) - return 1; + return 2; // base state + add new state - return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 1; + return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 2; // 2 = base state + add new state } void StatesEditorModel::reset() @@ -101,16 +99,16 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const switch (role) { case StateNameRole: { - if (index.row() == 0) { - return tr("base state", "Implicit default state"); - } else { - if (stateNode.hasVariantProperty("name")) - return stateNode.variantProperty("name").value(); - else - return QVariant(); - } - + if (index.row() == 0) { + return tr("base state", "Implicit default state"); + } else { + if (stateNode.hasVariantProperty("name")) + return stateNode.variantProperty("name").value(); + else + return QVariant(); } + } + case StateImageSourceRole: { static int randomNumber = 0; randomNumber++; @@ -119,9 +117,12 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const else return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.internalId()).arg(randomNumber); } - case InternalNodeId: return index.internalId(); - case HasWhenCondition: return stateNode.isValid() && stateNode.hasProperty("when"); + case InternalNodeId: + return index.internalId(); + + case HasWhenCondition: + return stateNode.isValid() && stateNode.hasProperty("when"); case WhenConditionString: { if (stateNode.isValid() && stateNode.hasBindingProperty("when")) @@ -137,10 +138,11 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const return false; } - case ModelHasDefaultState: { + case ModelHasDefaultState: return hasDefaultState(); - } + case StateType: + return index.row() == rowCount() - 1 ? "add" : "state"; } return QVariant(); @@ -148,14 +150,15 @@ QVariant StatesEditorModel::data(const QModelIndex &index, int role) const QHash StatesEditorModel::roleNames() const { - static QHash roleNames{ + static QHash roleNames { {StateNameRole, "stateName"}, {StateImageSourceRole, "stateImageSource"}, {InternalNodeId, "internalNodeId"}, {HasWhenCondition, "hasWhenCondition"}, {WhenConditionString, "whenConditionString"}, {IsDefault, "isDefault"}, - {ModelHasDefaultState, "modelHasDefaultState"} + {ModelHasDefaultState, "modelHasDefaultState"}, + {StateType, "type"} }; return roleNames; } @@ -163,10 +166,8 @@ QHash StatesEditorModel::roleNames() const void StatesEditorModel::insertState(int stateIndex) { if (stateIndex >= 0) { - const int updateIndex = stateIndex + 1; beginInsertRows(QModelIndex(), updateIndex, updateIndex); - endInsertRows(); emit dataChanged(index(updateIndex, 0), index(updateIndex, 0)); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h index 65c1385e897..d467e4fceb1 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditormodel.h @@ -44,7 +44,8 @@ class StatesEditorModel : public QAbstractListModel HasWhenCondition, WhenConditionString, IsDefault, - ModelHasDefaultState + ModelHasDefaultState, + StateType }; public: diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index 997852cfb25..cf1f3771412 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -85,12 +85,6 @@ void StatesEditorView::rootNodeTypeChanged(const QString &/*type*/, int /*majorV checkForStatesAvailability(); } -void StatesEditorView::toggleStatesViewExpanded() -{ - if (m_statesEditorWidget) - m_statesEditorWidget->toggleStatesViewExpanded(); -} - void StatesEditorView::removeState(int nodeId) { try { @@ -102,6 +96,22 @@ void StatesEditorView::removeState(int nodeId) if (modelState.isValid()) { QStringList lockedTargets; const auto propertyChanges = modelState.propertyChanges(); + + // confirm removing not empty states + if (!propertyChanges.isEmpty()) { + QMessageBox msgBox; + msgBox.setTextFormat(Qt::RichText); + msgBox.setIcon(QMessageBox::Question); + msgBox.setWindowTitle(tr("Remove State")); + msgBox.setText(tr("This state is not empty. Are you sure you want to remove it?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Yes); + + if (msgBox.exec() == QMessageBox::Cancel) + return; + } + + // confirm removing states with locked targets for (const QmlPropertyChanges &change : propertyChanges) { const ModelNode target = change.target(); QTC_ASSERT(target.isValid(), continue); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h index 1ac7a6f39fa..71a82711eaa 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h @@ -87,8 +87,6 @@ public: void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion) override; - void toggleStatesViewExpanded(); - public slots: void synchonizeCurrentStateFromWidget(); void createNewState(); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp index 4701a4079eb..b7b391944ad 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.cpp @@ -133,13 +133,6 @@ QString StatesEditorWidget::qmlSourcesPath() return Core::ICore::resourcePath("qmldesigner/statesEditorQmlSources").toString(); } -void StatesEditorWidget::toggleStatesViewExpanded() -{ - QTC_ASSERT(rootObject(), return); - bool expanded = rootObject()->property("expanded").toBool(); - rootObject()->setProperty("expanded", !expanded); -} - void StatesEditorWidget::showEvent(QShowEvent *event) { QQuickWidget::showEvent(event); @@ -168,18 +161,6 @@ void StatesEditorWidget::reloadQmlSource() connect(rootObject(), SIGNAL(createNewState()), m_statesEditorView.data(), SLOT(createNewState())); connect(rootObject(), SIGNAL(deleteState(int)), m_statesEditorView.data(), SLOT(removeState(int))); m_statesEditorView.data()->synchonizeCurrentStateFromWidget(); - - if (!DesignerSettings::getValue(DesignerSettingsKey::STATESEDITOR_EXPANDED).toBool()) - toggleStatesViewExpanded(); - - connect(rootObject(), SIGNAL(expandedChanged()), this, SLOT(handleExpandedChanged())); } -void StatesEditorWidget::handleExpandedChanged() -{ - QTC_ASSERT(rootObject(), return); - - bool expanded = rootObject()->property("expanded").toBool(); - DesignerSettings::setValue(DesignerSettingsKey::STATESEDITOR_EXPANDED, expanded); -} -} +} // QmlDesigner diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h index e4e9668abb0..b613e600c44 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorwidget.h @@ -57,14 +57,11 @@ public: static QString qmlSourcesPath(); - void toggleStatesViewExpanded(); - protected: void showEvent(QShowEvent *) override; private: void reloadQmlSource(); - Q_SLOT void handleExpandedChanged(); private: QPointer m_statesEditorView; diff --git a/src/plugins/qmldesigner/designercore/include/viewmanager.h b/src/plugins/qmldesigner/designercore/include/viewmanager.h index 166f458f619..ecfec36860b 100644 --- a/src/plugins/qmldesigner/designercore/include/viewmanager.h +++ b/src/plugins/qmldesigner/designercore/include/viewmanager.h @@ -100,8 +100,6 @@ public: DesignerActionManager &designerActionManager(); const DesignerActionManager &designerActionManager() const; - void toggleStatesViewExpanded(); - void qmlJSEditorContextHelp(const Core::IContext::HelpCallback &callback) const; DesignDocument *currentDesignDocument() const; diff --git a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp index 6b6a37c35b9..127925df1b3 100644 --- a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp +++ b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp @@ -394,11 +394,6 @@ const DesignerActionManager &ViewManager::designerActionManager() const return d->designerActionManagerView.designerActionManager(); } -void ViewManager::toggleStatesViewExpanded() -{ - d->statesEditorView.toggleStatesViewExpanded(); -} - void ViewManager::qmlJSEditorContextHelp(const Core::IContext::HelpCallback &callback) const { d->textEditorView.qmlJSEditorContextHelp(callback); diff --git a/src/plugins/qmldesigner/designersettings.cpp b/src/plugins/qmldesigner/designersettings.cpp index 08788ca5bef..8ecaaa6edd9 100644 --- a/src/plugins/qmldesigner/designersettings.cpp +++ b/src/plugins/qmldesigner/designersettings.cpp @@ -72,7 +72,6 @@ void DesignerSettings::fromSettings(QSettings *settings) restoreValue(settings, DesignerSettingsKey::FORWARD_PUPPET_OUTPUT, QString()); restoreValue(settings, DesignerSettingsKey::REFORMAT_UI_QML_FILES, true); restoreValue(settings, DesignerSettingsKey::IGNORE_DEVICE_PIXEL_RATIO, false); - restoreValue(settings, DesignerSettingsKey::STATESEDITOR_EXPANDED, true); restoreValue(settings, DesignerSettingsKey::NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS, true); restoreValue(settings, DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER, false); restoreValue(settings, DesignerSettingsKey::STANDALONE_MODE, false); diff --git a/src/plugins/qmldesigner/designersettings.h b/src/plugins/qmldesigner/designersettings.h index 0afb86d6dd6..bb25e2e04c9 100644 --- a/src/plugins/qmldesigner/designersettings.h +++ b/src/plugins/qmldesigner/designersettings.h @@ -60,7 +60,6 @@ const char ENABLE_MODEL_EXCEPTION_OUTPUT[] = "WarnException"; const char PUPPET_KILL_TIMEOUT[] = "PuppetKillTimeout"; const char DEBUG_PUPPET[] = "DebugPuppet"; const char FORWARD_PUPPET_OUTPUT[] = "ForwardPuppetOutput"; -const char STATESEDITOR_EXPANDED[] = "StatesEditorExpanded"; const char NAVIGATOR_SHOW_ONLY_VISIBLE_ITEMS[] = "NavigatorShowOnlyVisibleItems"; const char NAVIGATOR_REVERSE_ITEM_ORDER[] = "NavigatorReverseItemOrder"; const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */ diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index 2f195c3c89e..a0ef9a52128 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -511,8 +511,14 @@ bool DocumentManager::belongsToQmakeProject() Utils::FilePath DocumentManager::currentResourcePath() { Utils::FilePath resourcePath = currentProjectDirPath(); + if (resourcePath.isEmpty()) return currentFilePath().absolutePath(); + + FilePath contentFilePath = resourcePath.pathAppended("content"); + if (contentFilePath.exists()) + return contentFilePath; + return resourcePath; } diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index c11f20436ca..1dc5cd1bc81 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -205,8 +205,6 @@ bool showConfirmationDialog(const Utils::FilePath &rootDir) files.append(file.filePath); CmakeGeneratorDialog dialog(rootDir, files); - dialog.setMinimumWidth(600); - dialog.setMinimumHeight(640); if (dialog.exec()) { Utils::FilePaths confirmedFiles = dialog.getFilePaths(); removeUnconfirmedQueuedFiles(confirmedFiles); diff --git a/src/plugins/qmldesigner/qmldesignerconstants.h b/src/plugins/qmldesigner/qmldesignerconstants.h index 53edd711d5c..3830c9e8da8 100644 --- a/src/plugins/qmldesigner/qmldesignerconstants.h +++ b/src/plugins/qmldesigner/qmldesignerconstants.h @@ -65,10 +65,14 @@ const char EDIT3D_EDIT_CAMERA[] = "QmlDesigner.Editor3D.EditCameraToggle"; const char EDIT3D_ORIENTATION[] = "QmlDesigner.Editor3D.OrientationToggle"; const char EDIT3D_EDIT_LIGHT[] = "QmlDesigner.Editor3D.EditLightToggle"; const char EDIT3D_EDIT_SHOW_GRID[] = "QmlDesigner.Editor3D.ToggleGrid"; +const char EDIT3D_EDIT_SHOW_SELECTION_BOX[] = "QmlDesigner.Editor3D.ToggleSelectionBox"; +const char EDIT3D_EDIT_SHOW_ICON_GIZMO[] = "QmlDesigner.Editor3D.ToggleIconGizmo"; +const char EDIT3D_EDIT_SHOW_CAMERA_FRUSTUM[] = "QmlDesigner.Editor3D.ToggleCameraFrustum"; const char EDIT3D_RESET_VIEW[] = "QmlDesigner.Editor3D.ResetView"; const char EDIT3D_PARTICLE_MODE[] = "QmlDesigner.Editor3D.ParticleViewModeToggle"; const char EDIT3D_PARTICLES_PLAY[] = "QmlDesigner.Editor3D.ParticlesPlay"; const char EDIT3D_PARTICLES_RESTART[] = "QmlDesigner.Editor3D.ParticlesRestart"; +const char EDIT3D_VISIBILITY_TOGGLES[] = "QmlDesigner.Editor3D.VisibilityToggles"; const char QML_DESIGNER_SUBFOLDER[] = "/designer/"; diff --git a/src/plugins/qmldesigner/qmldesignericons.h b/src/plugins/qmldesigner/qmldesignericons.h index 3323ceb49a9..75ec4ab2d3f 100644 --- a/src/plugins/qmldesigner/qmldesignericons.h +++ b/src/plugins/qmldesigner/qmldesignericons.h @@ -61,10 +61,6 @@ const Utils::Icon EDIT3D_PARTICLE_PAUSE({ {":/edit3d/images/particles_pause.png", Utils::Theme::QmlDesigner_HighlightColor}}); const Utils::Icon EDIT3D_PARTICLE_RESTART({ {":/edit3d/images/particles_restart.png", Utils::Theme::QmlDesigner_HighlightColor}}); -const Utils::Icon EDIT3D_GRID_ON({ - {":/edit3d/images/grid_on.png", Utils::Theme::QmlDesigner_HighlightColor}}); -const Utils::Icon EDIT3D_GRID_OFF({ - {":/edit3d/images/grid_off.png", Utils::Theme::IconsBaseColor}}); const Utils::Icon EDIT3D_SELECTION_MODE_ON({ {":/edit3d/images/select_group.png", Utils::Theme::QmlDesigner_HighlightColor}}); const Utils::Icon EDIT3D_SELECTION_MODE_OFF({ diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index ff16d0de7e3..e8bd9e68a04 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -514,6 +514,8 @@ Project { "edit3d/edit3dcanvas.h", "edit3d/edit3dactions.cpp", "edit3d/edit3dactions.h", + "edit3d/edit3dvisibilitytogglesmenu.cpp", + "edit3d/edit3dvisibilitytogglesmenu.h", "edit3d/edit3d.qrc", "formeditor/abstractcustomtool.cpp", "formeditor/abstractcustomtool.h", diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp index 25d1c27c471..e82e7a04c01 100644 --- a/src/plugins/qmldesigner/shortcutmanager.cpp +++ b/src/plugins/qmldesigner/shortcutmanager.cpp @@ -69,7 +69,6 @@ ShortCutManager::ShortCutManager() m_copyAction(tr("&Copy")), m_pasteAction(tr("&Paste")), m_selectAllAction(tr("Select &All")), - m_collapseExpandStatesAction(tr("Toggle States")), m_escapeAction(this) { @@ -97,10 +96,6 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex connect(&m_selectAllAction,&QAction::triggered, this, &ShortCutManager::selectAll); - connect(&m_collapseExpandStatesAction, &QAction::triggered, [] { - QmlDesignerPlugin::instance()->viewManager().toggleStatesViewExpanded(); - }); - // Revert to saved Core::EditorManager *em = Core::EditorManager::instance(); Core::ActionManager::registerAction(&m_revertToSavedAction,Core::Constants::REVERTTOSAVED, qmlDesignerMainContext); @@ -188,13 +183,6 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex command->setDefaultKeySequence(QKeySequence::SelectAll); editMenu->addAction(command, Core::Constants::G_EDIT_SELECTALL); - Core::ActionContainer *viewsMenu = Core::ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS); - - command = Core::ActionManager::registerAction(&m_collapseExpandStatesAction, Constants::TOGGLE_STATES_EDITOR, qmlDesignerMainContext); - command->setAttribute(Core::Command::CA_Hide); - command->setDefaultKeySequence(QKeySequence("Ctrl+Alt+s")); - viewsMenu->addAction(command); - /* Registering disabled action for Escape, because Qt Quick does not support shortcut overrides. */ command = Core::ActionManager::registerAction(&m_escapeAction, Core::Constants::S_RETURNTOEDITOR, qmlDesignerMainContext); command->setDefaultKeySequence(QKeySequence(Qt::Key_Escape)); diff --git a/src/plugins/qmldesigner/shortcutmanager.h b/src/plugins/qmldesigner/shortcutmanager.h index 6e5b5ec23bd..4bc4ae5f848 100644 --- a/src/plugins/qmldesigner/shortcutmanager.h +++ b/src/plugins/qmldesigner/shortcutmanager.h @@ -83,7 +83,6 @@ private: QAction m_copyAction; QAction m_pasteAction; QAction m_selectAllAction; - QAction m_collapseExpandStatesAction; QAction m_escapeAction; }; diff --git a/src/plugins/remotelinux/linuxdeviceprocess.cpp b/src/plugins/remotelinux/linuxdeviceprocess.cpp index 654e975afc3..4953c8e5aba 100644 --- a/src/plugins/remotelinux/linuxdeviceprocess.cpp +++ b/src/plugins/remotelinux/linuxdeviceprocess.cpp @@ -49,11 +49,6 @@ LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer &device, QObject *parent = nullptr); - // Files to source before executing the command (if they exist). Overrides the default. - void setRcFilesToSource(const QStringList &filePaths); - QByteArray readAllStandardOutput() override; private: QString fullCommandLine(const ProjectExplorer::Runnable &) const override; qint64 processId() const override; - const QStringList rcFilesToSource() const; - - QStringList m_rcFilesToSource; QByteArray m_output; qint64 m_processId = 0; bool m_pidParsed = false; diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index f26e8511509..9ba6ed9b808 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -581,7 +581,8 @@ void StudioWelcomePlugin::extensionsInitialized() Core::ModeManager::activateMode(m_welcomeMode->id()); // Enable QDS new project dialog - Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); }); + if (Core::ICore::settings()->value("QML/Designer/StandAloneMode", false).toBool()) + Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); }); if (showSplashScreen()) { connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] { diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 3d6698a0bcc..731c5ba779e 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -2984,7 +2984,7 @@ bool TextEditorWidget::event(QEvent *e) && (ke->key() < Qt::Key_Escape)); d->m_maybeFakeTooltipEvent = false; } - break; + return true; } case QEvent::ApplicationPaletteChange: { // slight hack: ignore palette changes diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index 5299f36f6ce..ef4c969be66 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -288,7 +288,7 @@ public: newVBox->setSpacing(buttonSpacing / 3); vbox->addItem(newVBox); - auto newLabel = new QLabel(tr("New to Qt?"), this); + auto newLabel = new QLabel(tr("New to Qt?"), mainWidget); newLabel->setFont(brandFont()); newLabel->setAlignment(Qt::AlignHCenter); newVBox->addWidget(newLabel); @@ -461,7 +461,7 @@ void WelcomeMode::addPage(IWelcomePage *page) if (m_pluginList.at(idx)->priority() >= pagePriority) break; } - auto pageButton = new WelcomePageButton(m_sideArea); + auto pageButton = new WelcomePageButton(m_sideArea->widget()); auto pageId = page->id(); pageButton->setText(page->title()); pageButton->setActiveChecker([this, pageId] { return m_activePage == pageId; }); diff --git a/src/shared/modeltest/modeltest.cpp b/src/shared/modeltest/modeltest.cpp index 75000e9f3b9..c44b50ab34f 100644 --- a/src/shared/modeltest/modeltest.cpp +++ b/src/shared/modeltest/modeltest.cpp @@ -433,11 +433,11 @@ void ModelTest::data() } // General Purpose roles that should return a QColor - QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole); + QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundRole); if (colorVariant.isValid()) Q_ASSERT(colorVariant.canConvert(QVariant::Color)); - colorVariant = model->data(model->index(0, 0), Qt::TextColorRole); + colorVariant = model->data(model->index(0, 0), Qt::ForegroundRole); if (colorVariant.isValid()) Q_ASSERT(colorVariant.canConvert(QVariant::Color)); diff --git a/src/tools/iostool/CMakeLists.txt b/src/tools/iostool/CMakeLists.txt index 230f5b91f43..e02bf7463d4 100644 --- a/src/tools/iostool/CMakeLists.txt +++ b/src/tools/iostool/CMakeLists.txt @@ -21,9 +21,5 @@ add_qtc_executable(iostool ) if (TARGET iostool) - if (CMAKE_VERSION VERSION_LESS 3.13) - target_link_libraries(iostool PRIVATE "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/Info.plist") - else() - target_link_options(iostool PRIVATE "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/Info.plist") - endif() + target_link_options(iostool PRIVATE "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/Info.plist") endif() diff --git a/src/tools/perfparser b/src/tools/perfparser index 84180a4bbe9..d494f98900b 160000 --- a/src/tools/perfparser +++ b/src/tools/perfparser @@ -1 +1 @@ -Subproject commit 84180a4bbe9fad1426b6f6633b3d3b2f8d14d361 +Subproject commit d494f98900b2cd880ce3450074c69f708962804f diff --git a/src/tools/sdktool/CMakeLists.txt b/src/tools/sdktool/CMakeLists.txt index 486ec21d071..7726969b307 100644 --- a/src/tools/sdktool/CMakeLists.txt +++ b/src/tools/sdktool/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake") diff --git a/src/tools/wininterrupt/CMakeLists.txt b/src/tools/wininterrupt/CMakeLists.txt index b16e2e1e65b..4a41fa7b08f 100644 --- a/src/tools/wininterrupt/CMakeLists.txt +++ b/src/tools/wininterrupt/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake") diff --git a/tests/auto/debugger/CMakeLists.txt b/tests/auto/debugger/CMakeLists.txt index bde1800a637..5ab4c63f244 100644 --- a/tests/auto/debugger/CMakeLists.txt +++ b/tests/auto/debugger/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) if (NOT QT_CREATOR_API_DEFINED) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake") diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index 15ed0174182..072345c3fcf 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -2201,7 +2201,7 @@ namespace plugin { QLibrary lib(dir + "/libsimple_test_plugin.dylib"); #endif #ifdef Q_OS_WIN - QLibrary lib(dir + "/debug/simple_test_plugin.dll"); + QLibrary lib(dir + "/simple_test_plugin.dll"); #endif BREAK_HERE; // CheckType dir QString. diff --git a/tests/manual/process/main.cpp b/tests/manual/process/main.cpp index 78222ffbd41..86c7ca7788d 100644 --- a/tests/manual/process/main.cpp +++ b/tests/manual/process/main.cpp @@ -25,6 +25,7 @@ #include "mainwindow.h" +#include #include #include @@ -49,7 +50,7 @@ static int testSynchronous(const QString &cmd, const QStringList &args) std::fprintf(stdout, "testSynchronous %s %s\n", qPrintable(cmd), qPrintable(args.join(QLatin1Char(' ')))); Utils::QtcProcess p; - p.setCommand({cmd, args}); + p.setCommand({Utils::FilePath::fromString(cmd), args}); p.start(); if (!p.waitForStarted()) return -2; diff --git a/tests/manual/process/mainwindow.cpp b/tests/manual/process/mainwindow.cpp index 9f0c8d50279..ceb15e8a533 100644 --- a/tests/manual/process/mainwindow.cpp +++ b/tests/manual/process/mainwindow.cpp @@ -57,7 +57,7 @@ void MainWindow::test() qDebug() << "Async: " << cmd << args; process.setStdOutCallback([this](const QString &s) { append(s); }); process.setStdErrCallback([this](const QString &s) { append(s); }); - process.setCommand({cmd, args}); + process.setCommand({Utils::FilePath::fromString(cmd), args}); process.runBlocking(); qDebug() << process; } diff --git a/tests/manual/qml/testprojects/modulemapping/CMakeLists.txt b/tests/manual/qml/testprojects/modulemapping/CMakeLists.txt index a138dd3f98a..4160cc976c3 100644 --- a/tests/manual/qml/testprojects/modulemapping/CMakeLists.txt +++ b/tests/manual/qml/testprojects/modulemapping/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.16) project(test_project) add_executable(test_exe test.cc test.qml) diff --git a/tests/manual/ssh/sftpfsmodel/main.cpp b/tests/manual/ssh/sftpfsmodel/main.cpp index d1a7365dc20..15fa8535fac 100644 --- a/tests/manual/ssh/sftpfsmodel/main.cpp +++ b/tests/manual/ssh/sftpfsmodel/main.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -35,6 +36,8 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); + Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/' + + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH)); Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() + "/qtc-ssh-shelltest-XXXXXX"); SftpFsWindow w; diff --git a/tests/system/shared/editor_utils.py b/tests/system/shared/editor_utils.py index 9af13028486..bb6e8ba299d 100644 --- a/tests/system/shared/editor_utils.py +++ b/tests/system/shared/editor_utils.py @@ -37,7 +37,7 @@ def placeCursorToLine(editor, line, isRegex=False): return waitForObject(editor) isDarwin = platform.system() == 'Darwin' - if not isinstance(editor, (str, unicode)): + if not isString(editor): editor = objectMap.realName(editor) oldPosition = 0 jumpToFirstLine(getEditor()) @@ -120,7 +120,7 @@ def replaceEditorContent(editor, newcontent): type(editor, newcontent) def typeLines(editor, lines): - if isinstance(lines, (str, unicode)): + if isString(lines): lines = [lines] if isinstance(lines, (list, tuple)): for line in lines: diff --git a/tests/system/shared/fs_utils.py b/tests/system/shared/fs_utils.py index f36fbd7fbf2..ee24d6f0ca3 100644 --- a/tests/system/shared/fs_utils.py +++ b/tests/system/shared/fs_utils.py @@ -35,10 +35,10 @@ def changeFilePermissions(dirPath, readPerm, writePerm, excludeFileNames=None): permission |= stat.S_IWRITE if excludeFileNames == None: excludeFileNames = [] - elif isinstance(excludeFileNames, (str, unicode)): + elif isString(excludeFileNames): excludeFileNames = [excludeFileNames] if not isinstance(excludeFileNames, (tuple, list)): - test.warning("File names to exclude must be of type str, unicode, list, tuple or None - " + test.warning("File names to exclude must be of type str, list, tuple or None - " "ignoring parameter this time.") excludeFileNames = [] if not os.path.isdir(dirPath): diff --git a/tests/system/shared/project_explorer.py b/tests/system/shared/project_explorer.py index 587574ff0a5..a4abeb7a723 100644 --- a/tests/system/shared/project_explorer.py +++ b/tests/system/shared/project_explorer.py @@ -95,8 +95,8 @@ def setRunInTerminal(wantedKit, runInTerminal=True): switchViewTo(ViewConstants.EDIT) def __getTargetFromToolTip__(toolTip): - if toolTip == None or not isinstance(toolTip, (str, unicode)): - test.warning("Parameter toolTip must be of type str or unicode and can't be None!") + if toolTip == None or not isString(toolTip): + test.warning("Parameter toolTip must be of type str and can't be None!") return None pattern = re.compile(".*Kit:(.*)Deploy.*") target = pattern.match(toolTip) @@ -108,7 +108,7 @@ def __getTargetFromToolTip__(toolTip): def getExecutableAndTargetFromToolTip(toolTip): target = __getTargetFromToolTip__(toolTip) - if toolTip == None or not isinstance(toolTip, (str, unicode)): + if toolTip == None or not isString(toolTip): return None, target pattern = re.compile('.*Run:(.*) 2: + return isinstance(sth, str) + else: + return isinstance(sth, (str, unicode)) diff --git a/tests/system/suite_editors/tst_qml_editor/test.py b/tests/system/suite_editors/tst_qml_editor/test.py index c26207ea6ec..e75db758939 100644 --- a/tests/system/suite_editors/tst_qml_editor/test.py +++ b/tests/system/suite_editors/tst_qml_editor/test.py @@ -87,7 +87,6 @@ def testRenameId(): formerTxt = editor.plainText originalText = originalTexts.get(file).replace("mainView", "renamedView") test.compare(originalText,formerTxt, "Comparing %s" % file.replace("Core.","").replace("\\","")) - invokeMenuItem("File","Save All") def __invokeFindUsage__(filename, line, additionalKeyPresses, expectedCount): openDocument(focusDocumentPath % filename) diff --git a/tests/system/suite_editors/tst_rename_macros/test.py b/tests/system/suite_editors/tst_rename_macros/test.py index 491cc3bd200..f1111f8583c 100644 --- a/tests/system/suite_editors/tst_rename_macros/test.py +++ b/tests/system/suite_editors/tst_rename_macros/test.py @@ -46,6 +46,8 @@ def main(): expectedHeaderName=headerName) if not testRenameMacroAfterSourceMoving(): return + # save and exit + invokeMenuItem("File", "Save All") invokeMenuItem("File", "Exit") def testRenameMacroAfterSourceModification(): @@ -156,8 +158,7 @@ def revertChanges(files): simpleName = simpleFileName(f) if openDocument(f): try: - invokeMenuItem('File', 'Revert "%s" to Saved' % simpleName) - clickButton(waitForObject(":Revert to Saved.Proceed_QPushButton")) + invokeMenuItem('Edit', 'Undo') test.log("Reverted changes inside %s" % simpleName) except: test.warning("File '%s' cannot be reverted." % simpleName, diff --git a/tests/system/suite_general/tst_default_settings/test.py b/tests/system/suite_general/tst_default_settings/test.py index 2cb40725b82..29c65425b09 100644 --- a/tests/system/suite_general/tst_default_settings/test.py +++ b/tests/system/suite_general/tst_default_settings/test.py @@ -306,7 +306,7 @@ def __compareCompilers__(foundCompilers, expectedCompilers): if isinstance(currentFound, dict): foundExp = False for currentExp in expectedCompilers: - if isinstance(currentExp, (str, unicode)): + if isString(currentExp): continue key = currentExp.keys()[0] # special case for (fuzzy) regex comparison on Windows (internal LLVM) @@ -353,7 +353,7 @@ def __compareDebuggers__(foundDebuggers, expectedDebuggers): def __lowerStrs__(iterable): for it in iterable: - if isinstance(it, (str, unicode)): + if isString(it): yield it.lower() else: yield it diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index f6712030bdb..815b20fa182 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) if (NOT QT_CREATOR_API_DEFINED) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake")