diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0e7aa764b2e..3a25deece0b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,20 +52,17 @@ find_package(Qt5
)
if (Qt5_VERSION VERSION_LESS 6.0.0)
install(TARGETS Qt6Core5Compat EXPORT QtCreator)
- set(BUILD_WITH_PCH_DEFAULT ON)
# Specify standards conformance mode to MSVC 2017 and later
# Qt6 has the values as part of the Qt6::Platform target interface
if (MSVC AND MSVC_VERSION GREATER_EQUAL 1910)
add_compile_options(/permissive- /Zc:__cplusplus)
endif()
-else()
- set(BUILD_WITH_PCH_DEFAULT OFF)
endif()
find_package(Qt5 COMPONENTS LinguistTools QUIET)
find_package(Qt5 COMPONENTS Designer DesignerComponents Help SerialPort Svg Tools QUIET)
-option(BUILD_WITH_PCH "Build with precompiled headers" ${BUILD_WITH_PCH_DEFAULT})
+option(BUILD_WITH_PCH "Build with precompiled headers" ON)
find_package(Threads)
find_package(Clang QUIET)
diff --git a/cmake/QtCreatorAPIInternal.cmake b/cmake/QtCreatorAPIInternal.cmake
index 20e18d5be91..7ebd2d31d71 100644
--- a/cmake/QtCreatorAPIInternal.cmake
+++ b/cmake/QtCreatorAPIInternal.cmake
@@ -1,6 +1,6 @@
if (CMAKE_VERSION VERSION_LESS 3.18)
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_VERSION VERSION_LESS 3.16)
- set(BUILD_WITH_PCH OFF)
+ set(BUILD_WITH_PCH OFF CACHE BOOL "" FORCE)
endif()
endif()
diff --git a/doc/qtcreator/images/icons/pause-icon.png b/doc/qtcreator/images/icons/pause-icon.png
new file mode 100644
index 00000000000..a3eeab1c0e5
Binary files /dev/null and b/doc/qtcreator/images/icons/pause-icon.png differ
diff --git a/doc/qtcreator/images/qtcreator-build-cmake-output.png b/doc/qtcreator/images/qtcreator-build-cmake-output.png
new file mode 100644
index 00000000000..88638020652
Binary files /dev/null and b/doc/qtcreator/images/qtcreator-build-cmake-output.png differ
diff --git a/doc/qtcreator/images/qtcreator-debugger-general-options.png b/doc/qtcreator/images/qtcreator-debugger-general-options.png
index 7823c7668d9..6ab957dd76a 100644
Binary files a/doc/qtcreator/images/qtcreator-debugger-general-options.png and b/doc/qtcreator/images/qtcreator-debugger-general-options.png differ
diff --git a/doc/qtcreator/images/qtcreator-debugger-start-external.png b/doc/qtcreator/images/qtcreator-debugger-start-external.png
index 2dc696115fb..0faa3811419 100644
Binary files a/doc/qtcreator/images/qtcreator-debugger-start-external.png and b/doc/qtcreator/images/qtcreator-debugger-start-external.png differ
diff --git a/doc/qtcreator/images/qtcreator-editor-settings.png b/doc/qtcreator/images/qtcreator-editor-settings.png
index 0c5265a6a2f..2ad6d12e217 100644
Binary files a/doc/qtcreator/images/qtcreator-editor-settings.png and b/doc/qtcreator/images/qtcreator-editor-settings.png differ
diff --git a/doc/qtcreator/images/qtcreator-options-text-editor-display.png b/doc/qtcreator/images/qtcreator-options-text-editor-display.png
new file mode 100644
index 00000000000..d49884ae624
Binary files /dev/null and b/doc/qtcreator/images/qtcreator-options-text-editor-display.png differ
diff --git a/doc/qtcreator/images/qtcreator-syntax-highlighter.png b/doc/qtcreator/images/qtcreator-syntax-highlighter.png
index 80ac3a7f25c..1d295060dc1 100644
Binary files a/doc/qtcreator/images/qtcreator-syntax-highlighter.png and b/doc/qtcreator/images/qtcreator-syntax-highlighter.png differ
diff --git a/doc/qtcreator/images/qtquick-color-animation.gif b/doc/qtcreator/images/qtquick-color-animation.gif
new file mode 100644
index 00000000000..bb3bcb6e51a
Binary files /dev/null and b/doc/qtcreator/images/qtquick-color-animation.gif differ
diff --git a/doc/qtcreator/images/qtquick-number-animation.gif b/doc/qtcreator/images/qtquick-number-animation.gif
new file mode 100644
index 00000000000..4b3a9e2b744
Binary files /dev/null and b/doc/qtcreator/images/qtquick-number-animation.gif differ
diff --git a/doc/qtcreator/images/qtquick-properties-animation.png b/doc/qtcreator/images/qtquick-properties-animation.png
new file mode 100644
index 00000000000..06c58d946da
Binary files /dev/null and b/doc/qtcreator/images/qtquick-properties-animation.png differ
diff --git a/doc/qtcreator/images/qtquick-properties-coloranimation.png b/doc/qtcreator/images/qtquick-properties-coloranimation.png
new file mode 100644
index 00000000000..b429265acb1
Binary files /dev/null and b/doc/qtcreator/images/qtquick-properties-coloranimation.png differ
diff --git a/doc/qtcreator/images/qtquick-properties-numberanimation.png b/doc/qtcreator/images/qtquick-properties-numberanimation.png
new file mode 100644
index 00000000000..863c8418059
Binary files /dev/null and b/doc/qtcreator/images/qtquick-properties-numberanimation.png differ
diff --git a/doc/qtcreator/images/qtquick-properties-propertyaction.png b/doc/qtcreator/images/qtquick-properties-propertyaction.png
new file mode 100644
index 00000000000..788cf325a6b
Binary files /dev/null and b/doc/qtcreator/images/qtquick-properties-propertyaction.png differ
diff --git a/doc/qtcreator/images/qtquick-property-action.gif b/doc/qtcreator/images/qtquick-property-action.gif
new file mode 100644
index 00000000000..95f4f9589b6
Binary files /dev/null and b/doc/qtcreator/images/qtquick-property-action.gif differ
diff --git a/doc/qtcreator/images/timeline-rotation-animation.gif b/doc/qtcreator/images/timeline-rotation-animation.gif
new file mode 100644
index 00000000000..c03478c5a35
Binary files /dev/null and b/doc/qtcreator/images/timeline-rotation-animation.gif differ
diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc
index 57c62502330..66ae154d58c 100644
--- a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc
+++ b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc
@@ -119,6 +119,26 @@
\image qtcreator-build-run-options-cmake.png "CMake Build & Run options"
+ \section1 Viewing CMake Output
+
+ Output from CMake is displayed next to the \uicontrol {Build Settings} and
+ \uicontrol {Run Settings} panes in the \uicontrol Projects mode.
+
+ \image qtcreator-build-cmake-output.png "CMake output in Projects mode"
+
+ To clear the search results, select the \inlineimage clean_pane_small.png
+ (\uicontrol Clear) button.
+
+ You can enter a string in the \uicontrol Filter field to filter output.
+ To specify filtering options, select the \inlineimage magnifier.png "Filtering options menu"
+ button. You can filter output by using regular expressions or
+ case-sensitivity. Select \uicontrol {Show Non-matching Lines} to
+ hide the lines that match the filter.
+
+ To increase or decrease the output text size, select \inlineimage plus.png
+ (\uicontrol {Zoom In}) or \inlineimage minus.png
+ (\uicontrol {Zoom Out}), or press \key Ctrl++ or \key Ctrl+-.
+
\section1 CMake Build Steps
\QC builds CMake projects by running \c {cmake . --build}, which then runs
diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc b/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc
index 3b62b68bf6b..72cd80d3a30 100644
--- a/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc
+++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger-settings.qdocinc
@@ -39,6 +39,14 @@
\l{Specifying Breakpoint Settings}{specify settings for breakpoints},
and map source paths to target paths.
+ You can view debug output in the \uicontrol {Debugger Log} view.
+ However, in some Linux distributions, such as Arch Linux, debug
+ output is sent to the system log. To override this behavior, select
+ the \uicontrol {Force logging to console} check box. This sets
+ \c QT_LOGGING_TO_CONSOLE=1 in the environment of the debugged
+ program, which effectively prevents storing debug output in
+ system logs.
+
\section2 Mapping Source Paths
To enable the debugger to step into the code and display the source code
diff --git a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc
index 6fc4a634167..67b271053d2 100644
--- a/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc
+++ b/doc/qtcreator/src/debugger/creator-only/creator-debugger.qdoc
@@ -220,6 +220,15 @@
applications.
\li Select the \uicontrol {Break at "main"} check box to stop the
debugger at the main function.
+ \li Select the \uicontrol {Use target extended-remote to connect}
+ check box to create the connection in the
+ \c {target extended-remote mode}. In this mode, when the debugged
+ application exits or you detach from it, the debugger remains
+ connected to the target. You can rerun the application, attach
+ to a running application, or use monitor commands specific to the
+ target. For example, GDB does not exit unless it was invoked using
+ the \c {--once} option, but you can make it exit by using the
+ \c {monitor exit} command.
\li In the \uicontrol {Override SysRoot} field, specify the path to
the \c sysroot to use instead of the default \c sysroot.
\li In the \uicontrol {Debug information} field, specify the location
diff --git a/doc/qtcreator/src/editors/creator-code-indentation.qdoc b/doc/qtcreator/src/editors/creator-code-indentation.qdoc
index 716c5cec20c..f23e5b48502 100644
--- a/doc/qtcreator/src/editors/creator-code-indentation.qdoc
+++ b/doc/qtcreator/src/editors/creator-code-indentation.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -48,6 +48,29 @@
\li Other text files
\endlist
+ To fix the indentation in the file currently open in the editor,
+ select options in the \uicontrol Edit > \uicontrol Advanced menu
+ or use \l{Keyboard Shortcuts}{keyboard shortcuts}:
+
+ \list
+ \li To automatically indent the highlighted text, select
+ \uicontrol {Auto-indent Selection} or press \key {Ctrl+I}.
+ \li To automatically format the highlighted text, select
+ \uicontrol {Auto-format Selection} or press \key {Ctrl+;}.
+ \li To adjust the wrapping of the selected paragraph, select
+ \uicontrol {Rewrap Paragraph} or press \key {Ctrl+E}
+ followed by \key R.
+ \li To toggle text wrapping, select \uicontrol {Enable Text Wrapping}
+ or press \key {Ctrl+E} followed by \key {Ctrl+W}.
+ \li To visualize whitespace in the editor, select
+ \uicontrol {Visualize Whitespace} or press \key {Ctrl+E}
+ followed by \key {Ctrl+V}.
+ \li To clear all whitespace characters from the currently open file,
+ select \uicontrol {Clean Whitespace}.
+ \endlist
+
+ \section1 Specifying Indentation Settings
+
You can also specify indentation separately for each project. You can
specify several sets of code style settings and easily switch between them.
In addition, you can import and export code style settings.
@@ -61,7 +84,20 @@
\image qtcreator-options-text-editor-behavior.png "Text Editor Behavior options"
+ To visualize whitespace in the editor, select \uicontrol Tools >
+ \uicontrol Options > \uicontrol {Text Editor} > \uicontrol Display >
+ \uicontrol {Visualize whitespace}.
+
+ \image qtcreator-options-text-editor-display.png "Text Editor Display options"
+
+ To help you keep line length at a particular number of characters, set the
+ number of characters in the \uicontrol {Display right margin at column}
+ field. To use a context-specific margin when available, select the
+ \uicontrol {Use context-specific margin} check box.
\if defined(qtcreator)
+ For example, the margin could be set by the \c ColumnLimit option of the
+ \l{Specifying Code Style Settings}{Clang Format plugin}.
+
\section1 Indenting C++ Files
To specify indentation settings for the C++ editor:
diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc
index c7e25fbcd78..c2c6c1f2eaf 100644
--- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc
+++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc
@@ -184,10 +184,9 @@
split view, select \uicontrol Window > \uicontrol {Remove All Splits} or
press \key {Ctrl+E, 1}.
- \if defined(qtcreator)
\section1 Using Bookmarks
- To insert or delete a bookmark:
+ To insert or delete a bookmark in the \uicontrol Edit mode:
\list
@@ -245,7 +244,8 @@
\section1 Moving to Symbol Definition or Declaration
- You can move directly to the definition or the declaration of a symbol by
+ You can move directly to the definition or the declaration of a symbol
+ in the \uicontrol Edit mode by
holding the \key Ctrl key and clicking the symbol. If you have multiple
splits opened, you can open the link in the next split by holding \key Ctrl
and \key Alt while clicking the symbol.
@@ -290,6 +290,7 @@
\uicontrol {Open Corresponding Header/Source in Next Split}. You can also
press \key F4 or \key {Ctrl+E,F4}, respectively.
+ \if defined(qtcreator)
\section1 Reparsing Externally Changed Files
If source files are modified from outside \QC, the opened files will be
diff --git a/doc/qtcreator/src/editors/creator-locator.qdoc b/doc/qtcreator/src/editors/creator-locator.qdoc
index cfd44c19de5..cae350b2d58 100644
--- a/doc/qtcreator/src/editors/creator-locator.qdoc
+++ b/doc/qtcreator/src/editors/creator-locator.qdoc
@@ -139,11 +139,12 @@
\li Executing shell commands (\c {!})
- \li Executing version control system commands (\c {git}).
+ \li Executing version control system commands
\if defined(qtcreator)
- For more information, see \l{Using Version Control Systems}
+ (\c {bzr}, \c {cvs}, \c {git}, \c {hg}, or \c {svn}).
+ For more information, see \l{Using Version Control Systems}.
\else
- For more information, see \l{Using Git}
+ (\c {git}). For more information, see \l{Using Git}.
\endif
\li Triggering menu items from the main menu (\c {t})
diff --git a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc
index 8b1f056a118..efe8ecc058a 100644
--- a/doc/qtcreator/src/editors/creator-quick-fixes.qdoc
+++ b/doc/qtcreator/src/editors/creator-quick-fixes.qdoc
@@ -571,6 +571,21 @@
\endlist
\li \c Q_PROPERTY
\row
+ \li Generate Q_PROPERTY and Missing Members
+ \li Generates a Q_PROPERTY and adds missing members to it, as
+ described above.
+ \li Class member
+ \row
+ \li Generate Constant Q_PROPERTY and Missing Members
+ \li Generates a constant Q_PROPERTY and adds missing members
+ to it, as described above.
+ \li Class member
+ \row
+ \li Generate Q_PROPERTY and Missing Members with Reset Function
+ \li Generates a Q_PROPERTY and adds missing members to it, as
+ described above, but with an additional \c reset function.
+ \li Class member
+ \row
\li Apply Changes
\li Keeps function declarations and definitions synchronized by
checking for the matching declaration or definition when you
@@ -617,6 +632,19 @@
\li Creates either both getter and setter member functions for
member variables or only a getter or setter.
\li Member variable in class definition
+ \row
+ \li Generate Getter and Setter
+ \li Creates getter and setter member functions for a member
+ variable.
+ \li Member variable in class definition
+ \row
+ \li Generate Getter
+ \li Creates a getter member function for a member variable.
+ \li Member variable in class definition
+ \row
+ \li Generate Setter
+ \li Creates a setter member function for a member variable.
+ \li Member variable in class definition
\row
\li Generate Constructor
\li Creates a constructor for a class.
diff --git a/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc b/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc
index 728936dec27..42983fe6325 100644
--- a/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc
+++ b/doc/qtcreator/src/editors/creator-semantic-highlighting.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -56,16 +56,25 @@
syntax definitions. \QC comes with most of the commonly used syntax files,
and you can download additional files. For more information about the
definition files, see
- \l{https://docs.kde.org/stable5/en/applications/katepart/highlight.html}
+ \l{https://docs.kde.org/trunk5/en/kate/katepart/highlight.html}
{Working with Syntax Highlighting}.
Font attributes that a syntax definition file explicitly specifies, such as
bold, italic, underline, or strike through, are applied. Colors are applied
if they are readable with \QC themes.
+ If more than one highlight definition is available for the file that you
+ open for editing, the editor asks you to select the one to use. To save
+ the selection, select \uicontrol {Remember My Choice}. To reset the
+ remembered definitions, select \uicontrol Tools > \uicontrol Options >
+ \uicontrol {Text Editor} > \uicontrol {Generic Highlighter} >
+ \uicontrol {Reset Remembered Definitions}.
+
If the editor cannot find the highlight definition for a file that you open
- for editing, it prompts you to update the highlight definition files. Select
- \uicontrol {Update Definitions} to update the files.
+ for editing, it prompts you to download additional highlight definition
+ files. Select \uicontrol {Download Definitions} to download the files.
+ Information about the downloaded files is displayed in the
+ \uicontrol {General Messages} \l{Viewing Output}{output pane}.
To suppress the message for a particular file pattern, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor}
@@ -76,10 +85,9 @@
If you have written your own syntax definition files, you
can provide an additional definition search path in the
- \uicontrol {User Highlight Definition Files} field.
-
- To manually update the highlight definition files, select
- \uicontrol {Update Definitions}.
+ \uicontrol {User Highlight Definition Files} field. To
+ apply the changes you make to the definition files, select
+ \uicontrol {Reload Definitions}.
\section1 Highlighting and Folding Blocks
@@ -101,6 +109,8 @@
\uicontrol {Text Editor} > \uicontrol Display >
\uicontrol {Display folding markers}. This option is enabled by default.
+ \image qtcreator-options-text-editor-display.png "Text Editor Display options"
+
When the cursor is on a brace, the matching brace is animated by default. To
turn off the animation and just highlight the block and the braces, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
@@ -117,4 +127,6 @@
\key {Ctrl+Alt+Shift+U}. To enable smart block selection, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
\uicontrol Behavior > \uicontrol {Enable smart selection changing}.
+
+ \image qtcreator-options-text-editor-behavior.png "Text Editor Behavior options"
*/
diff --git a/doc/qtcreator/src/howto/creator-telemetry.qdoc b/doc/qtcreator/src/howto/creator-telemetry.qdoc
index 8cb24c64e6b..746c4b4efb6 100644
--- a/doc/qtcreator/src/howto/creator-telemetry.qdoc
+++ b/doc/qtcreator/src/howto/creator-telemetry.qdoc
@@ -148,7 +148,7 @@
/*!
\page creator-crashpad.html
\previouspage collecting-user-feedback.html
- \nextpage studio-help.html
+ \nextpage studio-packaging.html
\title Reporting Crashes
diff --git a/doc/qtcreator/src/overview/creator-only/qtcreator-ui-best-practices.qdoc b/doc/qtcreator/src/overview/creator-only/qtcreator-ui-best-practices.qdoc
deleted file mode 100644
index 5df04a583fa..00000000000
--- a/doc/qtcreator/src/overview/creator-only/qtcreator-ui-best-practices.qdoc
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Creator documentation.
-**
-** 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 Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-**
-****************************************************************************/
-
-/*!
- \previouspage adding-plugins.html
- \page creator-ui-best-practices.html
- \nextpage creator-usability.html
-
- \title Best Practices
-
- Apply the best practices to ensure that the UIs you create work
- efficiently on the intended platforms, such as mobile devices.
-
- \list
- \li \l {Optimizing Applications for Mobile Devices}
-
- Guidelines to help you design and develop usable applications for
- mobile devices with varying characteristics.
-
- \li \l {Qt Quick Best Practices}
-
- Guidelines describing the most efficient ways to use \QDS to
- create UIs and scenes that run flawlessly on the intended platforms.
- \endlist
-*/
diff --git a/doc/qtcreator/src/qtcreator-toc.qdoc b/doc/qtcreator/src/qtcreator-toc.qdoc
index b812857a1ab..dfb84f20f71 100644
--- a/doc/qtcreator/src/qtcreator-toc.qdoc
+++ b/doc/qtcreator/src/qtcreator-toc.qdoc
@@ -150,7 +150,6 @@
\li \l{Creating Scalable Buttons and Borders}
\endlist
\endlist
- \li \l{Creating Optimized 3D Scenes}
\li \l{Specifying Component Properties}
\li \l{Scalable Layouts}
\li \l{Using Custom Fonts}
@@ -187,9 +186,14 @@
\li \l{Motion Design}
\list
\li \l{Introduction to Animation Techniques}
- \li \l{Creating Animations}
+ \li \l{Creating Timeline Animations}
\li \l{Editing Easing Curves}
- \endlist
+ \li \l{Production Quality}
+ \li \l{Optimizing Designs}
+ \list
+ \li \l{Creating Optimized 3D Scenes}
+ \endlist
+ \endlist
\li \l {Browsing ISO 7000 Icons}
\li \l {Converting UI Projects to Applications}
\endlist
diff --git a/doc/qtcreator/src/qtcreator.qdoc b/doc/qtcreator/src/qtcreator.qdoc
index 9492de89225..cb53dc7b6c7 100644
--- a/doc/qtcreator/src/qtcreator.qdoc
+++ b/doc/qtcreator/src/qtcreator.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -52,6 +52,8 @@
see \l{Commercial Features}.
\table
+ \row
+ \li {4,1} \b {\l{All Topics}}
\row
\li \inlineimage front-gs.png
\li \inlineimage front-projects.png
@@ -77,7 +79,7 @@
\list
\li \l{Developing Qt Quick Applications}
\li \l{Developing Widget Based Applications}
- \li \l{Best Practices}
+ \li \l{Optimizing Applications for Mobile Devices}
\endlist
\li \b {\l{Coding}}
\list
@@ -125,20 +127,20 @@
\li \l{Glossary}
\endlist
\row
- \li {4,1} \l{All Topics}
- \row
- \li {4,1} \note To report bugs and suggestions to the
- \l{https://bugreports.qt.io/}{Qt Project Bug Tracker},
- select \uicontrol Help > \uicontrol {Report Bug}.
- To copy and paste detailed information about your system to the
- bug report, select \uicontrol Help >
- \uicontrol {System Information}.
-
- You can also join the \QC mailing list at:
- \l{http://lists.qt-project.org/mailman/listinfo/}
- {lists.qt-project.org Mailing Lists}.
-
- For credits and a list of third-party libraries, see
- \l {Acknowledgements}.
+ \li {4,1} \b {Contact Us}
+ \list
+ \li To report bugs and suggestions to the
+ \l{https://bugreports.qt.io/}{Qt Project Bug Tracker},
+ select \uicontrol Help > \uicontrol {Report Bug}.
+ \li To copy and paste detailed information about your
+ system to the bug report, select \uicontrol Help >
+ \uicontrol {System Information}.
+ \li To join the \l{https://lists.qt-project.org/listinfo/qt-creator}
+ {\QC mailing list} or \l{https://web.libera.chat/#qt-creator}
+ {#qt-creator} channel on Libera.Chat IRC, select
+ \uicontrol Help > \uicontrol Contact.
+ \li For credits and a list of third-party libraries, see
+ \l {Acknowledgements}.
+ \endlist
\endtable
*/
diff --git a/doc/qtcreator/src/qtquick/library/qtquick-component-instances.qdoc b/doc/qtcreator/src/qtquick/library/qtquick-component-instances.qdoc
index da2e8f49b3e..2a499236a4c 100644
--- a/doc/qtcreator/src/qtquick/library/qtquick-component-instances.qdoc
+++ b/doc/qtcreator/src/qtquick/library/qtquick-component-instances.qdoc
@@ -65,7 +65,8 @@
\li Add states to apply sets of changes to the property values of one
or several component instances in the \uicontrol States view.
For more information, see \l{Adding States}.
- \li Animate the properties of component instances in the \uicontrol
- Timeline view. For more information, see \l{Creating Animations}.
+ \li Animate the properties of component instances in the
+ \uicontrol Timeline view. For more information, see
+ \l{Creating Timeline Animations}.
\endlist
*/
diff --git a/doc/qtcreator/src/qtquick/library/qtquick-controls.qdoc b/doc/qtcreator/src/qtquick/library/qtquick-controls.qdoc
index 31e9c028e39..d1d6b59339c 100644
--- a/doc/qtcreator/src/qtquick/library/qtquick-controls.qdoc
+++ b/doc/qtcreator/src/qtquick/library/qtquick-controls.qdoc
@@ -392,7 +392,7 @@
\section1 Selectors
Qt Quick Controls offers a set of selector-like controls, such as sliders,
- dial, sping box, combo box, and tumbler, for specific use cases. The
+ dial, spin box, combo box, and tumbler, for specific use cases. The
following sections contain guidelines for choosing the selector most
suitable for a use case.
diff --git a/doc/qtcreator/src/qtquick/qtdesignstudio-optimized-3d-scenes.qdoc b/doc/qtcreator/src/qtquick/qtdesignstudio-optimized-3d-scenes.qdoc
index 35878e73b9a..86045cb93f4 100644
--- a/doc/qtcreator/src/qtquick/qtdesignstudio-optimized-3d-scenes.qdoc
+++ b/doc/qtcreator/src/qtquick/qtdesignstudio-optimized-3d-scenes.qdoc
@@ -25,8 +25,12 @@
/*!
\page studio-optimized-3d-scenes.html
- \previouspage quick-scalable-image.html
- \nextpage qtquick-properties.html
+ \previouspage qtquick-optimizing-designs.html
+ \if defined(qtdesignstudio)
+ \nextpage creator-coding.html
+ \else
+ \nextpage qtquick-iso-icon-browser.html
+ \endif
\title Creating Optimized 3D Scenes
@@ -40,7 +44,12 @@
\section1 The Optimal 3D Scene Example
- The \l {Optimal 3D Scene} example features four versions of the same kitchen
+ \if defined(qtdesignstudio)
+ The \l {Optimal 3D Scene}
+ \else
+ The Optimal 3D Scene
+ \endif
+ example features four versions of the same kitchen
scene that have been created using different strategies: High, Low, Combined,
and Vertex Color. The High Scene includes a significantly higher number of
objects compared to the other versions of the scene. The Low, Combined and
diff --git a/doc/qtcreator/src/qtquick/qtquick-animation-overview.qdoc b/doc/qtcreator/src/qtquick/qtquick-animation-overview.qdoc
index 638cbce6ce6..672e62c8ae4 100644
--- a/doc/qtcreator/src/qtquick/qtquick-animation-overview.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-animation-overview.qdoc
@@ -26,9 +26,12 @@
/*!
\page quick-animation-overview.html
\previouspage qtquick-motion-design.html
+ \nextpage studio-timeline.html
\title Introduction to Animation Techniques
+ \image timeline-rotation-animation.gif "Timeline animation of rotation and opacity"
+
\QDS supports the following types of animation techniques that are suitable
for different purposes:
@@ -207,8 +210,8 @@
\section2 Programmatic Animation
You can control property animation programmatically. Property animations
- are created by binding \l{Animations}{Animation} components to property
- values of component instances to gradually change the properties values
+ are created by binding \uicontrol Animation components to property
+ values of component instances to gradually change the property values
over time. The property animations apply smooth movement by interpolating
values between property value changes. They provide timing controls and
enable different interpolations through easing curves.
@@ -219,95 +222,42 @@
You can create instances of preset animation components available in
\l Library > \uicontrol Components > \uicontrol {Default Components} >
- \uicontrol Animation to create \l{Animations}{animations} depending on
- the type of the property that is to be animated and the behavior that
- you want.
+ \uicontrol Animation to create animations depending on the type of the
+ property and the behavior that you want.
+
+ For more information about \uicontrol Animation components and their
+ properties, see \l{Animations}.
\table
\header
- \li Animation Type
+ \li Component
\li Use Case
\row
- \li Property animation
+ \li \uicontrol {Property Animation}
\li Applying animation when the value of a property changes. Color
and number animations are property animation types for specific
purposes.
\row
- \li Property action
+ \li \uicontrol {Property Action}
\li Setting non-animated property values during an animation.
\row
- \li Color animation
+ \li \uicontrol {Color Animation}
\li Applying animation when a color value changes.
\row
- \li Number animation
+ \li \uicontrol {Number Animation}
\li Applying animation when a numerical value changes.
\row
- \li Parallel animation
+ \li \uicontrol {Parallel Animation}
\li Running animations in parallel.
\row
- \li Sequential Animation
+ \li \uicontrol {Sequential Animation}
\li Running animations sequentially.
\row
- \li Pause animation
+ \li \uicontrol {Pause Animation}
\li Creating a step in a sequential animation where nothing happens for
a specified duration.
\row
- \li Script action
+ \li \uicontrol {Script Action}
\li Executing JavaScript during an animation.
\endtable
-
- \section3 Property Animation and Action
-
- A property animation is applied when the value of a property changes.
-
- To immediately change a property value during an animation without
- animating the property change, use a property action instead. This
- is useful for setting non-animated property values during an animation.
-
- For example, you can use a sequential animation that contains two property
- actions around a number animation to set the value of the opacity property
- of an \l{Images}{Image} to \c 0.5, animate the width of the image, and then
- set the opacity back to \c 1.
-
- \section3 Color Animation
-
- A color animation is a specialized property animation that defines an
- animation to be applied when a color value changes.
-
- For example, you can apply animation to the color property of a \l Rectangle
- to change its value from its current color to another color over a period
- of time specified in milliseconds.
-
- \section3 Number Animation
-
- A number animation is a specialized property animation that defines an
- animation to be applied when a numerical value changes.
-
- For example, you can apply animation to the x property of a \l Rectangle
- to make it appear to move from its current position on the x axis to another
- position over a period of time specified in milliseconds.
-
- \section3 Parallel and Sequential Animation
-
- Animations can run in parallel or in sequence. Parallel animations will
- play a group of animations at the same time while sequential animations
- play a group of animations in order, one after the other.
-
- For example, a banner component may have several icons or slogans to
- display, one after the other. The opacity property could change to
- \c 1.0 denoting an opaque object. Using a sequential animation, the
- opacity animations will play after the preceding animation finishes,
- whereas a parallel animation will play the animations at the same time.
-
- Once individual animations are placed into a group of parallel or sequential
- animations, they can no longer be started and stopped independently. The
- sequential or parallel animations must be started and stopped as a group.
-
- \section3 Pause Animation
-
- When used in a sequential animation, a pause animation is a step when
- nothing happens, for a specified duration.
-
- For example, you could specify a 500-millisecond animation sequence, with
- a 100-millisecond pause between two animations.
*/
diff --git a/doc/qtcreator/src/qtquick/qtquick-animation-types.qdoc b/doc/qtcreator/src/qtquick/qtquick-animation-types.qdoc
index 101a489a63a..f6ff808a74a 100644
--- a/doc/qtcreator/src/qtquick/qtquick-animation-types.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-animation-types.qdoc
@@ -34,43 +34,207 @@
\title Animations
- To create an animation, use an appropriate animation type for the type of
- the property that is to be animated, and apply the animation depending on
- the type of behavior that is required.
+ To create an animation, use the appropriate animation type for the property
+ that is to be animated, and apply the animation depending on the type of
+ behavior that is required.
- You can drag and drop the following components from \l Library >
+ You can drag-and-drop animation components from \l Library >
\uicontrol Components > \uicontrol {Default Components} >
- \uicontrol Animation to \l Navigator or \l {Form Editor}:
+ \uicontrol Animation to \l Navigator or \l {Form Editor} to
+ create instances of them.
- \list
- \li \l [QML] {ColorAnimation}{Color Animation} is a specialized
- property animation that defines an animation to be applied when a
- color value changes.
- \li \l [QML] {NumberAnimation}{Number Animation} is a specialized
- property animation that defines an animation to be applied when a
- numerical value changes.
- \li \l [QML] {ParallelAnimation}{Parallel Animation} enables
- animations to be run in parallel.
- \li \l [QML] {PauseAnimation}{Pause Animation} is used in a
- sequential animation to create a step where nothing happens, for
+ You can achieve similar results by using different animation techniques.
+ For more information, see \l{Introduction to Animation Techniques}.
+
+ \section1 Applying Animation
+
+ A property animation is applied when the value of a property changes.
+ Color and number animations are property animation types for specific
+ purposes. Specify settings for animations in \l Properties >
+ \uicontrol {Animation Targets}.
+
+ \section2 Animating Color Changes
+
+ For example, you can apply animation to the value of the \uicontrol Color
+ property of an instance of a \l Rectangle component to change its value
+ from its current color to another color over a period of time specified in
+ milliseconds.
+
+ \image qtquick-color-animation.gif "Color animation"
+
+ First create an instance of the \uicontrol {Color Animation} component.
+ Select the component to animate in the \uicontrol Target field, and enter
+ the property to animate in the \uicontrol Property field. To animate several
+ properties, enter them into the \uicontrol Properties field separated by
+ commas.
+
+ \image qtquick-properties-coloranimation.png "Color Animation properties"
+
+ Select the original color in the \uicontrol {From color} field and the new
+ color in the \uicontrol {To color} field. Specify the duration of the
+ animation in the \uicontrol Duration field.
+
+ \section2 Animating Changes in Numerical Values
+
+ Similarly, to apply animation when a numerical value of a property changes,
+ create an instance of the \uicontrol {Number Animation} component.
+
+ \image qtquick-properties-numberanimation.png "Number Animation properties"
+
+ Select the original value in the \uicontrol From field and the new value in
+ the \uicontrol To field. Then specify the duration of the animation in the
+ \uicontrol Duration field.
+
+ For example, you can apply animation to the value of the \uicontrol X
+ property of a \l Rectangle instance to make it appear to move from its
+ current position on the x axis to another position over a period of time
+ specified in milliseconds. To make the component appear to move both on
+ the x and y axis, enter x and y into the \uicontrol Properties field
+ separated by a comma.
+
+ \image qtquick-number-animation.gif "Number animation"
+
+ \section2 Setting Non-Animated Properties
+
+ To immediately change a property value during an animation
+ without animating the property change, create an instance
+ of the \uicontrol {Property Action} component instead, and
+ set the value in the \uicontrol Value field. This is useful
+ for setting non-animated property values during an animation.
+
+ \image qtquick-properties-propertyaction.png "Property Action properties"
+
+ For example, you can create an instance of the
+ \uicontrol {Sequential Animation} component that contains two instances
+ of the \uicontrol {Property Action} component around an instance of the
+ \uicontrol {Number Animation} component. The first property action sets
+ the \uicontrol Opacity property of a \l{Rectangle} to \c 0.5, the number
+ animation changes the width of the image, and the second property action
+ sets the opacity back to \c 1.
+
+ \image qtquick-property-action.gif "Sequential property actions and number animation"
+
+ \section1 Playing Animations
+
+ Specify settings for playing animations in the \uicontrol Animation group.
+
+ \image qtquick-properties-animation.png "Animation properties"
+
+ To run animations automatically, select the \uicontrol Running
+ check box. Animations are run for the time you specify in the
+ \uicontrol Duration field.
+
+ You can connect the running property of an animation to a signal emitted
+ by a component to play the animation when users click a button, for
+ example. For more information, see \l{Connecting Components to Signals}.
+
+ To run animations several times in a loop, set the number of times they
+ should play in the \uicontrol Loops field. Set the value to -1 to have
+ the animation continuously repeat until it is explicitly stopped.
+
+ To specify that animations should run to completion when they are stopped,
+ select the \uicontrol {Run to end} check box. This behavior is most useful
+ when the \uicontrol Loops property is set, as the animation will finish
+ playing normally but not restart.
+
+ All animations defined for a component are run in parallel,
+ unless you include them in a \uicontrol {Parallel Animation} or
+ \uicontrol {Sequential Animation} component for managing them as a
+ group.
+
+ To pause animations, select the \inlineimage icons/pause-icon.png
+ (\uicontrol Paused) check box.
+
+ To attach an \l{Editing Easing Curves}{easing curve} to
+ the animation, select the \inlineimage curve_editor.png
+ (\uicontrol {Easing Curve Editor}) button in the
+ \uicontrol {Easing Curve} field.
+
+ \section2 Playing Groups of Animations
+
+ You can create several animations that can run in parallel or in sequence.
+ To manage a group of animations that will play at the same time, create an
+ instance of a \uicontrol {Parallel Animation} component and drag-and-drop
+ the other animations to it. To play the animations in the specified order,
+ one after the other, create an instance of a
+ \uicontrol {Sequential Animation} instead.
+
+ For example, a banner component may have several icons or slogans to
+ display, one after the other. The value of the \uicontrol Opacity property
+ could change to \c 1.0 denoting an opaque object. Using a sequential
+ animation, each opacity animation will play after the preceding animation
+ finishes, whereas using a parallel animation will play the animations at
+ the same time.
+
+ Once individual animations are placed into a group of parallel or sequential
+ animations, they can no longer be started and stopped independently. The
+ sequential or parallel animations must be started and stopped as a group.
+
+ When used in a \uicontrol {Sequential Animation}, a
+ \uicontrol {Pause Animation} is a step when nothing
+ happens, for a specified duration. To specify a pause
+ between two animations, select the \uicontrol Paused
+ check box and specify the duration of the pause in the
+ \uicontrol Duration field.
+
+ \section1 Performance Considerations
+
+ \QDS enables you to use fluidity and dynamic transitions as well as visual
+ effects to great effect in a UI. However, you need to take some care when
+ using some of the supported features because they can affect the
+ performance of the UI.
+
+ In general, animating a property will cause any bindings which reference
+ that property to be re-evaluated. Usually, this is what is desired, but in
+ some cases it may be better to disable the binding prior to performing
+ the animation and then reassign the binding once the animation has
+ completed.
+
+ Avoid running JavaScript during animation. For example, running a complex
+ JavaScript expression for each frame of an x property animation should be
+ avoided.
+
+ Take special care when creating instances of the \uicontrol {Script Action}
+ component because script animations are run in the main thread and can
+ therefore cause frames to be skipped if they take too long to complete.
+
+ \section1 Summary of Animation Components
+
+ The following table lists the components that you can use to animate
+ component properties programmatically. They are available in \l Library
+ > \uicontrol Components > \uicontrol {Default Components} >
+ \uicontrol Animation
+
+ \table
+ \header
+ \li Component
+ \li Use Case
+ \row
+ \li \uicontrol {Property Animation}
+ \li Applying animation when the value of a property changes. Color
+ and number animations are property animation types for specific
+ purposes.
+ \row
+ \li \uicontrol {Property Action}
+ \li Setting non-animated property values during an animation.
+ \row
+ \li \uicontrol {Color Animation}
+ \li Applying animation when a color value changes.
+ \row
+ \li \uicontrol {Number Animation}
+ \li Applying animation when a numerical value changes.
+ \row
+ \li \uicontrol {Parallel Animation}
+ \li Running animations in parallel.
+ \row
+ \li \uicontrol {Sequential Animation}
+ \li Running animations sequentially.
+ \row
+ \li \uicontrol {Pause Animation}
+ \li Creating a step in a sequential animation where nothing happens for
a specified duration.
- \li \l [QML] {PropertyAction}{Property Action} immediately changes
- a property value during an animation, without animating the
- property change.
- \li \l [QML] {PropertyAnimation}{Property Animation} animates
- changes in the value of a property.
- \li \l [QML] {ScriptAction}{Script Action} defines scripts to be
- run during an animation.
- \li \l [QML] {SequentialAnimation}{Sequential Animation} enables
- animations to be run sequentially.
- \endlist
-
- For more information about using the components, see
- \l{Animation and Transitions in Qt Quick}.
-
- For more information about animating properties in the \l Timeline
- view, see \l{Creating Animations}. For more information about animating
- property changes in states, see \l{Animating Transitions Between States}.
-
-//! [qtquick animation types]
+ \row
+ \li \uicontrol {Script Action}
+ \li Executing JavaScript during an animation.
+ \endtable
*/
diff --git a/doc/qtcreator/src/qtquick/qtquick-annotations.qdoc b/doc/qtcreator/src/qtquick/qtquick-annotations.qdoc
index 79bc0f1e774..8cd779c892e 100644
--- a/doc/qtcreator/src/qtquick/qtquick-annotations.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-annotations.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -30,7 +30,7 @@
\nextpage qtquick-prototyping.html
\else
\previouspage qtquick-fonts.html
- \nextpage qtquick-ui-forms.html
+ \nextpage creator-quick-ui-forms.html
\endif
\title Annotating Designs
diff --git a/doc/qtcreator/src/qtquick/qtquick-designer.qdoc b/doc/qtcreator/src/qtquick/qtquick-designer.qdoc
index fed9a25ca26..fcdcf9c31a3 100644
--- a/doc/qtcreator/src/qtquick/qtquick-designer.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-designer.qdoc
@@ -110,7 +110,7 @@
\li \l Timeline
\li Provides a timeline and keyframe based editor for animating
the properties of components.
- \li \l{Creating Animations}
+ \li \l{Creating Timeline Animations}
\row
\li \l{Curve Editor}
\li Enables you to view and modify the whole animation curve by
diff --git a/doc/qtcreator/src/qtquick/qtquick-easing-curve-editor.qdoc b/doc/qtcreator/src/qtquick/qtquick-easing-curve-editor.qdoc
index 04e03ac5a0b..5a6825ca6cb 100644
--- a/doc/qtcreator/src/qtquick/qtquick-easing-curve-editor.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-easing-curve-editor.qdoc
@@ -26,14 +26,28 @@
/*!
\page qtquick-editing-easing-curves.html
\previouspage studio-timeline.html
- \nextpage qmldesigner-connections.html
+ \nextpage qtquick-production-quality-animation.html
\title Editing Easing Curves
- You can use \uicontrol {Easing Curve Editor} to edit the easing curve
- between two keyframes.
+ Easing curves define the progress of animation to make motion appear more
+ natural because real objects don't usually move at a constant speed nor
+ start and stop instantly. You can add and edit easing curves for nonlinear
+ interpolation to make components appear to pick up speed, slow down, or
+ bounce back at the end of an animation.
- \image studio-easing-curve-editor.png "Easing Curve Editor"
+ You can attach easing curves to:
+
+ \list
+ \li Keyframes in timeline animations
+ \li Transitions
+ \li Property animation component instances
+ \endlist
+
+ You can use \uicontrol {Easing Curve Editor} to select and edit easing
+ curves.
+
+ \section1 Selecting Easing Curves
You can use the preset curves or modify them by dragging the curve handles
around. You can add points to the curve and drag them and the point handles
@@ -41,13 +55,28 @@
a custom curve. For more information about easing curve types, see the
technical documentation for \l [QML] {PropertyAnimation}{easing curves}.
+ \image studio-easing-curve-editor.png "Easing Curve Editor"
+
+ To select an easing curve:
+
+ \list 1
+ \li Select an easing curve in the \uicontrol Presets tab.
+ \li In the \uicontrol {Duration (ms)} field, select the
+ duration of the easing function in milliseconds.
+ \li Select \uicontrol Preview to preview the curve.
+ \li Select \uicontrol OK to attach the easing curve and
+ return to the view where you are adding the curve.
+ \endlist
+
To zoom into and out of the easing curve editor, use the mouse
roller. To reset the zoom factor, right-click in the picker and
select \uicontrol {Reset Zoom}.
- You can also use the more advanced \l {Curve Editor} that
- shows the interpolated values of an animated property over
- the \l{Creating Animations}{animation} range.
+ \section1 Easing Curves in Timeline Animations
+
+ For timeline animations, you can also use the more advanced
+ \l {Curve Editor} that shows the interpolated values of an animated
+ property over the \l{Creating Timeline Animations}{animation} range.
The animation curves present a more readable view of the animation by
showing the effective values of the animated properties over the animation
@@ -61,20 +90,14 @@
and are therefore painted in a different color and without handles.
\endlist
- \section1 Attaching Easing Curves to Keyframes
+ \section2 Attaching Easing Curves to Keyframes
To attach easing curves to keyframes:
\list 1
\li Right-click a keyframe in \l Timeline and select
\uicontrol {Easing Curve Editor} in the context menu.
- \li Select an easing curve in the \uicontrol Presets tab.
- \li In the \uicontrol {Duration (ms)} field, select the
- duration of the easing function in milliseconds.
- \li Select \uicontrol Preview to preview the curve.
- \li Select \uicontrol OK to attach the easing curve to the
- keyframe, close \uicontrol {Easing Curve Editor}, and
- return to \l Timeline.
+ \li Select an easing curve, as described in \l{Selecting Easing Curves}.
\endlist
When you attach easing curves to keyframes, the shape of the
@@ -82,6 +105,28 @@
\l Timeline changes from \inlineimage keyframe_linear_inactive.png
to a marker that describes the type of the selected easing curve.
+ \section1 Attaching Easing Curves to Transitions
+
+ To attach easing curves to transitions:
+
+ \list 1
+ \li In \l{Transition Editor}, select the \inlineimage curve_editor.png
+ (\uicontrol {Easing Curve Editor}) button.
+ \li Select an easing curve, as described in \l{Selecting Easing Curves}.
+ \endlist
+
+ \section1 Attaching Easing Curves to Property Animations
+
+ To attach easing curves to property animations:
+
+ \list 1
+ \li In \l Navigator, select an \l{Animations}{Animation} component
+ instance.
+ \li In \l Properties, select the \inlineimage curve_editor.png
+ (\uicontrol {Easing Curve Editor}) button.
+ \li Select an easing curve, as described in \l{Selecting Easing Curves}.
+ \endlist
+
\section1 Customizing Easing Curves
To customize easing curves:
diff --git a/doc/qtcreator/src/qtquick/qtquick-fonts.qdoc b/doc/qtcreator/src/qtquick/qtquick-fonts.qdoc
index 41a17fc6234..bf79ffa20b9 100644
--- a/doc/qtcreator/src/qtquick/qtquick-fonts.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-fonts.qdoc
@@ -25,7 +25,7 @@
/*!
\page qtquick-fonts.html
- \if defined{qtdesignstudio}
+ \if defined(qtdesignstudio)
\previouspage studio-importing-2d.html
\nextpage studio-importing-3d.html
\else
diff --git a/doc/qtcreator/src/qtquick/qtquick-motion-design.qdoc b/doc/qtcreator/src/qtquick/qtquick-motion-design.qdoc
index 9d68b374bbc..91f842e08e0 100644
--- a/doc/qtcreator/src/qtquick/qtquick-motion-design.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-motion-design.qdoc
@@ -30,10 +30,15 @@
\title Motion Design
- You can use different animation techniques for different purposes. \QDS
- supports common motion design techniques, such as timeline and keyframe
- based animation and easing curves, as well as screen-to-screen or
- state-to-state application flows and data-driven UI logic animation.
+ \table
+ \row
+ \li \image studio-animation.png
+ \li You can use different animation techniques for different
+ purposes. \QDS supports common motion design techniques,
+ such as timeline and keyframe based animation and easing
+ curves, as well as screen-to-screen or state-to-state
+ application flows and data-driven UI logic animation.
+ \endtable
\list
\li \l {Introduction to Animation Techniques}
@@ -41,21 +46,28 @@
Learn more about which animation techniques are supported by \QDS
and the use cases they are most suitable for.
- \li \l {Creating Animations}
+ \li \l {Creating Timeline Animations}
You can use a timeline and keyframe based editor in the
- \uicontrol Timeline view to animate the properties of UI
+ \l Timeline view to animate the properties of UI
components. Animating properties enables their values to
move through intermediate values at specified keyframes
instead of immediately changing to the target value.
- \li Production Quality (TODO)
+ \li \l{Editing Easing Curves}
- After the wireframing and prototyping phases, you can use the
- supported motion design techniques to fine-tune your UI for
- production.
- \li Optimizing for Target Devices (TODO)
+ Specify easing curves for nonlinear interpolation between
+ keyframes in timeline animations, as well as between original
+ and new property values in property animations and between
+ transitions.
+ \li \l {Production Quality}
+
+ After the wireframing and prototyping phases, you can use previewing
+ and profiling tools to fine-tune your UI for production.
+ \li \l{Optimizing Designs}
You can test your UIs on the target devices to make sure you get
- the best performance out of your animations.
+ the best performance out of your animations. To solve performance
+ problems, you typically need to optimize the graphical assets used
+ in the UI, such as images, effects, or 3D scenes.
\endlist
*/
diff --git a/doc/qtcreator/src/qtquick/qtquick-optimizing-designs.qdoc b/doc/qtcreator/src/qtquick/qtquick-optimizing-designs.qdoc
new file mode 100644
index 00000000000..0f6c31fe84d
--- /dev/null
+++ b/doc/qtcreator/src/qtquick/qtquick-optimizing-designs.qdoc
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Creator documentation.
+**
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+/*!
+ \page qtquick-optimizing-designs.html
+ \previouspage qtquick-production-quality-animation.html
+ \nextpage studio-optimized-3d-scenes.html
+
+ \title Optimizing Designs
+
+ You can test your UIs on the target devices to make sure you get the best
+ performance out of your animations. To solve performance problems, you
+ typically need to optimize the graphical assets used in the UI, such as
+ images, effects, or 3D scenes.
+
+ How to optimize UIs for different target devices:
+
+ \list
+ \li Minimize image size
+ \li Use transparency sparingly
+ \endlist
+
+ For more useful information for application developers, see
+ \l {Performance Considerations And Suggestions}.
+
+ For more information about optimizing 3D scenes, see
+ \l{Creating Optimized 3D Scenes}.
+
+ \section1 Minimizing Image Size
+
+ Images are a vital part of any user interface. Unfortunately, they are also
+ a big source of problems due to the time it takes to load them, the amount
+ of memory they consume, and the way in which they are used.
+
+ We recommend that you make image size as small as possible without
+ negatively affecting image quality.
+
+ For more information about how to use images efficiently in your UI, see
+ \l{Images}.
+
+ \section1 Avoid Transparency
+
+ Opaque content is generally a lot faster to draw than transparent because
+ the latter needs blending and the renderer can potentially optimize opaque
+ content better.
+
+ An image with one transparent pixel is treated as fully transparent, even
+ though it is mostly opaque. The same is true for a \l {Border Image} with
+ transparent edges.
+*/
diff --git a/doc/qtcreator/src/qtquick/qtquick-production-quality-animation.qdoc b/doc/qtcreator/src/qtquick/qtquick-production-quality-animation.qdoc
new file mode 100644
index 00000000000..bfdf435cf6e
--- /dev/null
+++ b/doc/qtcreator/src/qtquick/qtquick-production-quality-animation.qdoc
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Creator documentation.
+**
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+/*!
+ \page qtquick-production-quality-animation.html
+ \previouspage qtquick-editing-easing-curves.html
+ \nextpage qtquick-optimizing-designs.html
+
+ \title Production Quality
+
+ After the wireframing and prototyping phases, you can use previewing and
+ profiling tools to fine-tune your UI for production.
+
+ How to achieve production quality motion in UIs:
+
+ \list
+ \li Preview the UI to check the FPS refresh rate.
+ \li Profile the UI code to find causes for slowness, unresponsiveness,
+ and stuttering.
+ \endlist
+
+ \section1 FPS Refresh Rate
+
+ As a general rule, animators strive to allow the rendering engine to
+ achieve a consistent 60 frames-per-second (FPS) refresh rate. 60 FPS
+ means that there is approximately 16 milliseconds between each frame
+ in which processing can be done, which includes the processing required
+ to upload the draw primitives to the graphics hardware.
+
+ The frames-per-second (FPS) refresh rate of animations is displayed in the
+ \uicontrol FPS field on the \l{Summary of Main Toolbar Actions}{toolbar}
+ in the \uicontrol Design mode.
+
+ To improve the FPS rate, application developers should:
+
+ \list
+ \li Use asynchronous, event-driven programming wherever possible.
+ \li Use worker threads to do significant processing.
+ \li Never manually spin the event loop.
+ \li Never spend more than a couple of milliseconds per frame within
+ blocking functions to avoid skipped frames, which negatively
+ affect the user experience.
+ \endlist
+
+ For more information about previewing UIs on devices, see
+ \l{Validating with Target Hardware}.
+
+ \section1 Profiling UI Code
+
+ You can use \l{Profiling QML Applications}{QML Profiler} that is integrated
+ into \QC to find causes for typical performance problems in your UI. For
+ example, your UI might be slow, unresponsive, or stuttering. Typically, such
+ problems are caused by executing too much JavaScript in too few frames. All
+ JavaScript must return before the GUI thread can proceed, and frames are
+ delayed or dropped if the GUI thread is not ready.
+
+ In general, knowing where time is spent in a UI enables you to focus on
+ problem areas that actually exist, rather than problem areas that
+ potentially exist.
+
+ Determining which bindings are being run the most often or which functions
+ your application is spending the most time on enables you to decide whether
+ you need to optimize the problem areas, or redesign some implementation
+ details of your application so that the performance is improved. Attempting
+ to optimize code without profiling is likely to result in very minor rather
+ than significant performance improvements.
+
+ For more information, see \l{Profiling QML Applications}.
+*/
diff --git a/doc/qtcreator/src/qtquick/qtquick-properties.qdoc b/doc/qtcreator/src/qtquick/qtquick-properties.qdoc
index ad9962daa9a..75b12c420a5 100644
--- a/doc/qtcreator/src/qtquick/qtquick-properties.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-properties.qdoc
@@ -132,7 +132,7 @@
Changing a component's opacity does not affect whether the component
receives user input events.
- You can \l{Creating Animations}{animate} the opacity value to make a
+ You can \l{Creating Timeline Animations}{animate} the opacity value to make a
component fade in and out.
If the \uicontrol Clip check box is selected, the component and its children
diff --git a/doc/qtcreator/src/qtquick/qtquick-states.qdoc b/doc/qtcreator/src/qtquick/qtquick-states.qdoc
index f02e150a874..1b83f5ae694 100644
--- a/doc/qtcreator/src/qtquick/qtquick-states.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-states.qdoc
@@ -147,9 +147,11 @@
when: control.pressed || control.checked && !control.hovered
\endcode
+ \if defined(qtdesignstudio)
If you are not familiar with writing expressions, you can use preset
\l{Logic Helpers}{logic helpers} from \l Library > \uicontrol Components
> \uicontrol {Qt Quick Studio Logic Helper}.
+ \endif
\section1 Using States
diff --git a/doc/qtcreator/src/qtquick/qtquick-timeline-view.qdoc b/doc/qtcreator/src/qtquick/qtquick-timeline-view.qdoc
index 0084125fc67..2c3984d55f9 100644
--- a/doc/qtcreator/src/qtquick/qtquick-timeline-view.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-timeline-view.qdoc
@@ -74,7 +74,7 @@
For more information about creating timeline animations, see
- \l{Creating Animations}.
+ \l{Creating Timeline Animations}.
\section1 Navigating in Timeline
diff --git a/doc/qtcreator/src/qtquick/qtquick-timeline.qdoc b/doc/qtcreator/src/qtquick/qtquick-timeline.qdoc
index 05c09eb267b..6c8f5525574 100644
--- a/doc/qtcreator/src/qtquick/qtquick-timeline.qdoc
+++ b/doc/qtcreator/src/qtquick/qtquick-timeline.qdoc
@@ -24,12 +24,15 @@
****************************************************************************/
/*!
- \previouspage qtquick-adding-dynamics.html
+ \previouspage quick-animation-overview.html
\page studio-timeline.html
- \nextpage qmldesigner-connections.html
+ \nextpage qtquick-editing-easing-curves.html
- \title Creating Animations
+ \title Creating Timeline Animations
+ You can create timeline and keyframe based animations for linear
+ interpolation through intermediate values at specified keyframes
+ instead of immediately changing to the target value.
\section1 Creating Timelines
diff --git a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
index acff67c5884..2cdeb3fc89b 100644
--- a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
+++ b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc
@@ -32,8 +32,8 @@
/*!
\page creator-vcs-git.html
\if defined(qtdesignstudio)
- \previouspage studio-projects.html
- \nextpage studio-importing-designs.html
+ \previouspage studio-packaging.html
+ \nextpage quick-converting-ui-projects.html
\else
\previouspage creator-vcs-cvs.html
\nextpage creator-vcs-mercurial.html
diff --git a/doc/qtcreator/src/widgets/qtdesigner-plugins.qdoc b/doc/qtcreator/src/widgets/qtdesigner-plugins.qdoc
index 1cbb4040ca4..9ceeef0e255 100644
--- a/doc/qtcreator/src/widgets/qtdesigner-plugins.qdoc
+++ b/doc/qtcreator/src/widgets/qtdesigner-plugins.qdoc
@@ -32,7 +32,7 @@
/*!
\previouspage creator-using-qt-designer.html
\page adding-plugins.html
- \nextpage creator-ui-best-practices.html
+ \nextpage creator-usability.html
\title Adding Qt Designer Plugins
diff --git a/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc b/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc
index 463cf53ac6d..9b954da5869 100644
--- a/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc
+++ b/doc/qtdesignstudio/examples/doc/coffeemachine.qdoc
@@ -141,7 +141,8 @@
When we deselect the record button to stop recording the timeline, the
new timeline appears in the view.
- For more information about using the timeline, see \l {Creating Animations}.
+ For more information about using the timeline, see
+ \l {Creating Timeline Animations}.
\section1 Using States to Move Between Screens
diff --git a/doc/qtdesignstudio/examples/doc/ebikedesign.qdoc b/doc/qtdesignstudio/examples/doc/ebikedesign.qdoc
index 5f15994e700..ab24a48dcbd 100644
--- a/doc/qtdesignstudio/examples/doc/ebikedesign.qdoc
+++ b/doc/qtdesignstudio/examples/doc/ebikedesign.qdoc
@@ -89,7 +89,8 @@
to fade out the current screen when moving to another one and to make the
speedometer grow and shrink in size depending on its current position.
- For more information about using the timeline, see \l {Creating Animations}.
+ For more information about using the timeline, see
+ \l {Creating Timeline Animations}.
\section1 Using States to Move Between Screens
diff --git a/doc/qtdesignstudio/examples/doc/loginui4.qdoc b/doc/qtdesignstudio/examples/doc/loginui4.qdoc
index 319fd90e301..91698be34a7 100644
--- a/doc/qtdesignstudio/examples/doc/loginui4.qdoc
+++ b/doc/qtdesignstudio/examples/doc/loginui4.qdoc
@@ -40,10 +40,11 @@
some basic UI components, such as pages, buttons, and entry fields. Part 4
describes how to use the timeline and states to animate UI components.
- In Part 3, you learned how to use states to simulate page changes in a UI
- and connections to provide user interaction with it. In Part 4, you will now
- learn another way of animating the UI by creating \l{Creating Animations}
- {timeline animations} that you bind to states.
+ In Part 3, you learned how to use states to simulate page changes
+ in a UI and connections to provide user interaction with it. In
+ Part 4, you will now learn another way of animating the UI by creating
+ \l{Creating Timeline Animations}{timeline animations} that you bind
+ to states.
These instructions build on:
@@ -128,7 +129,7 @@
\section2 Adding a Timeline and Animation Settings
- You are now ready to add the \l{Creating Animations}{timeline}. You will
+ You are now ready to add the \l{Creating Timeline Animations}{timeline}. You will
need two animations, one for moving into the registration page and another
for returning to the login page. You can use the same animation for both
cases, by running it either from the beginning to the end or from the
@@ -314,7 +315,7 @@
All the properties and functions of the components from this module are
available in the \uicontrol Design mode, and therefore it is enough to
learn how to use \uicontrol Timeline, as described in
- \l {Creating Animations}.
+ \l {Creating Timeline Animations}.
\section1 Next Steps
diff --git a/doc/qtdesignstudio/examples/doc/progressbar.qdoc b/doc/qtdesignstudio/examples/doc/progressbar.qdoc
index ddfc9c69eca..f8d6a9af528 100644
--- a/doc/qtdesignstudio/examples/doc/progressbar.qdoc
+++ b/doc/qtdesignstudio/examples/doc/progressbar.qdoc
@@ -82,7 +82,8 @@
changing color. To animate the label and indicator, we'll add timelines
in the \l Timeline view.
- For more information about using the timeline, see \l {Creating Animations}.
+ For more information about using the timeline, see
+ \l {Creating Timeline Animations}.
\section2 Adding Color Animation
diff --git a/doc/qtdesignstudio/examples/doc/sidemenu.qdoc b/doc/qtdesignstudio/examples/doc/sidemenu.qdoc
index 2f7e39ec4b1..9725732aa8b 100644
--- a/doc/qtdesignstudio/examples/doc/sidemenu.qdoc
+++ b/doc/qtdesignstudio/examples/doc/sidemenu.qdoc
@@ -185,7 +185,8 @@
apply when the animation finishes. In the lower part of the
dialog, we bind the states that don't have animations to fixed frames.
- For more information about using the timeline, see \l {Creating Animations}.
+ For more information about using the timeline, see
+ \l {Creating Timeline Animations}.
\section1 Connecting the Burger Menu to Actions
diff --git a/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc b/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc
index 56743812022..7a3cd6ab20c 100644
--- a/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc
+++ b/doc/qtdesignstudio/examples/doc/washingMachineUI.qdoc
@@ -48,8 +48,9 @@
Users select buttons to navigate between the screens.
We use \l{Connecting Components to Signals}{connections} to determine which
screen to open when users select a particular button and \l{Adding States}
- {states} to show the screens. We use the \l{Creating Animations}{timeline}
- to create progress indicators for buttons and the \e Running screen.
+ {states} to show the screens. We use the \l{Creating Timeline Animations}
+ {timeline} to create progress indicators for buttons and the \e Running
+ screen.
In addition, all screens contain a small clock component that displays
the current time. We implement a \e TimeDate JavaScript object to
diff --git a/doc/qtdesignstudio/examples/doc/webinardemo.qdoc b/doc/qtdesignstudio/examples/doc/webinardemo.qdoc
index 4dddd367674..805e545cd31 100644
--- a/doc/qtdesignstudio/examples/doc/webinardemo.qdoc
+++ b/doc/qtdesignstudio/examples/doc/webinardemo.qdoc
@@ -191,5 +191,6 @@
\image webinardemo-timeline.png "Popup animations in the Timeline view"
- For more information about using the timeline, see \l {Creating Animations}.
+ For more information about using the timeline, see
+ \l {Creating Timeline Animations}.
*/
diff --git a/doc/qtdesignstudio/images/studio-add-resources.png b/doc/qtdesignstudio/images/studio-add-resources.png
new file mode 100644
index 00000000000..802d5b73a48
Binary files /dev/null and b/doc/qtdesignstudio/images/studio-add-resources.png differ
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc
index 1e8f73ac6fe..bf725577dfa 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-faq.qdoc
@@ -94,7 +94,7 @@
Yes, you can create custom components and controls by using wizard templates
or move component instances into separate files to turn them into new
components that you can create instances of. For more information, see
- \l {Creating Components}.
+ \l {Components}.
\section2 What are the 3D import formats for \QDS?
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
new file mode 100644
index 00000000000..36e302415e4
--- /dev/null
+++ b/doc/qtdesignstudio/src/qtdesignstudio-packaging.qdoc
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Creator documentation.
+**
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+**
+****************************************************************************/
+
+/*!
+ \page studio-packaging.html
+ \previouspage creator-crashpad.html
+ \nextpage creator-vcs-git.html
+
+ \title Packaging Applications
+
+ When you are ready to deliver your application to users or upload it to
+ app stores, you can use \QDS to create suitable packages that contain all
+ the necessary files, such as fonts, images, components, and modules.
+
+ \section1 Adding Resources to Packages
+
+ \QDS supports the \e{Qt Resource System} (QRC), which is a
+ platform-independent mechanism for storing files in the application's
+ executable. This is useful if your application always needs a certain
+ set of files (icons, translation files, and so on) and you don't want
+ to run the risk of losing the files.
+
+ To package your application, select \uicontrol Build >
+ \uicontrol {Generate QRC Resource File}. Then select the
+ files to package in the \uicontrol {Add Resources} dialog.
+
+ \image studio-add-resources.png "Add Resources dialog"
+
+ The dialog displays all the files listed in the project file (.qmlproject)
+ and located in the project folder. Files that are listed in the project
+ file are marked with bold text in the UI, to make it easy to identify the
+ differences between the project file and the resource collection file.
+
+ When you select \uicontrol OK, \QDS creates a resource collection file
+ (.qrc) in the project folder.
+
+ If you remove files from the project that you already added to the
+ resource collection file, you can recreate the resource collection
+ file to remove them also from there.
+
+ \section1 Embedding Resources into Applications
+
+ Alternatively, you can embedd the resources into your application by
+ selecting \uicontrol Build > \uicontrol {Generate RCC Resource File}.
+ Select the location for the .qmlrc file, and then select the files to
+ embedd in the \uicontrol {Add Resources} dialog.
+
+ When you select \uicontrol OK, \QDS creates a resource collection file
+ (.qmlrc) in the location you selected.
+*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc
index f22c988c771..b0f2e3d1d9f 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Studio documentation.
@@ -58,7 +58,8 @@
\QB is available for the following design tools:
\list
- \li Adobe Photoshop version 20.0.0
- \li Sketch 55.1
+ \li Adobe Photoshop version 22.3.1
+ \li Figma version 97.x
+ \li Sketch version 72.2
\endlist
*/
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc
index e1460b6f4f1..d31bbc0cf47 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-terms.qdoc
@@ -34,18 +34,28 @@
\list
\li \l{glossary-asset}{Asset}
+ \li \l{glossary-binding}{Binding}
\li \l{glossary-component}{Component}
+ \li \l{glossary-connection}{Connection}
\li \l{glossary-device}{Device}
- \li \l{glossary-Project}{Project}
+ \li \l{glossary-mode}{Mode}
+ \li \l{glossary-project}{Project}
+ \li \l{glossary-property}{Property}
+ \li \l{glossary-signal}{Signal}
+ \li \l{glossary-state}{State}
+ \li \l{glossary-transition}{Transition}
\endlist
\section1 Asset
\target glossary-asset
An \e asset is an image, font file, 3D model, or other supported file that
- you add to your \e project.
+ you add to your \l{glossary-project}{project}.
- Assets are packaged with \e components for delivery to users.
+ \image qtquick-assets-tab.png "Assets in Library"
+
+ Assets are packaged with \l{glossary-component}{components} for delivery
+ to users.
Read more about assets:
@@ -53,6 +63,34 @@
\li \l{Assets}
\endlist
+ \section1 Binding
+ \target glossary-binding
+
+ A \e binding is a declarative way of specifying the value of a
+ \l{glossary-property}{property}. Binding allows a property value
+ to be expressed as a JavaScript expression that defines the value
+ relative to other property values or data accessible in the
+ application. The property value is automatically updated if the
+ other properties or data values change.
+
+ At its simplest, a binding may be a reference to another property. For
+ example, the height of a \l{glossary-component}{component} can be bound
+ to the height of its parent, so that when the parent height changes, the
+ component height is adjusted automatically. Similarly, the opacity of a
+ component can be bound to the opacity of its parent component.
+
+ \image qtquick-connection-editor-assignment.png "Binding Editor"
+
+ Property bindings are created implicitly whenever a property is assigned a
+ JavaScript expression.
+
+ Read more about bindings:
+
+ \list
+ \li \l{Adding Bindings Between Properties}
+ \li \l{Setting Bindings}
+ \endlist
+
\section1 Component
\target glossary-component
@@ -62,14 +100,17 @@
creating instances of them. These are similar to \e Symbols in Sketch or
\e Prefab in Unity.
+ \image qtquick-components-tab.png "Preset components in Library"
+
Some of the \l {Component Types}{preset components} represent simple shapes,
text, or images, while others represent complex UI controls with full
functionality, such as spin boxes or sliders. You can also add instances of
- preset \l {Using 3D Components}{3D components} to your UIs. You can find all
+ preset \l {3D Components}{3D components} to your UIs. You can find all
the preset components in \l Library.
To build \l {Creating Component Instances}{your own components}, you can
- modify the \e properties of the component instances and combine them.
+ modify the \l{glossary-property}{properties} of the component instances
+ and combine them.
A component is specified within one file (with the file extension
\e ui.qml or \e .qml). For example, a Button component may be defined
@@ -87,6 +128,24 @@
\li \l {Creating Custom Components}
\endlist
+ \section1 Connection
+ \target glossary-connection
+
+ A \e connection can be created between a \l{glossary-component}{component}
+ and \l{glossary-signal}{signal} to determine how the UI should react to
+ application events. Another way to create connections between components
+ is to create \l{glossary-binding}{bindings} between the values of their
+ \l{glossary-property}{properties}.
+
+ \image qmldesigner-connections.png "Connection View"
+
+ Read more about connections:
+
+ \list
+ \li \l{Connection View}
+ \li \l{Adding Connections}
+ \endlist
+
\section1 Device
\target glossary-device
@@ -98,24 +157,138 @@
\li \l{Previewing on Devices}
\endlist
+ \section1 Mode
+ \target glossary-mode
+
+ A \e mode adapts the \QDS UI to the different UI design
+ tasks at hand. Each mode has its own view that shows only the information
+ required for performing a particular task, and provides only the most
+ relevant features and functions related to it. As a result, the majority
+ of the \QDS window area is always dedicated to the actual task.
+
+ For a designer, the most important modes are \uicontrol Design for the
+ actual work, \uicontrol Welcome for opening examples and tutorials, and
+ \uicontrol Help for reading documentation. The other modes are mostly
+ needed for application development.
+
+ \image studio-design-mode.png "Design mode"
+
+ Read more about modes:
+
+ \list
+ \li \l{Selecting Modes}
+ \li \l{Design Views}
+ \endlist
+
\section1 Project
\target glossary-project
- A project is a container for the \e components and \e assets that you
- use in your UI. You can \e package the UI and preview or run it on
- different operating systems on the desktop or a \l{glossary-device}{device}.
+ A project is a container for the \l{glossary-component}{components} and
+ \l{glossary-asset}{assets} that you use in your UI. You can \e package
+ the UI and preview or run it on different operating systems on the desktop
+ or a \l{glossary-device}{device}.
You use templates to create different types of projects according to your
needs. The templates add preset components to the project by default. For
example, if you create a 3D project, preset 3D components are added to it.
You can add more preset components in \uicontrol Library.
+ \image studio-project-wizards.png "New File or Project dialog"
+
Read more about projects:
\list
\li \l{Creating Projects}
\endlist
+ \section1 Property
+ \target glossary-property
+
+ A \e property is an attribute of a \l{glossary-component}{component}
+ that can be assigned a static value or bound to a dynamic expression.
+ A property's value can be read by other components. Generally, it can
+ also be modified by another component, unless a particular component
+ type has explicitly disallowed this for a specific property.
+
+ \image qtquick-item-properties-common.png "Properties view"
+
+ Read more about properties:
+
+ \list
+ \li \l{Properties}
+ \li \l{Preset Components}
+ \li \l{Specifying Component Properties}
+ \li \l{Adding Bindings Between Properties}
+ \li \l{Specifying Dynamic Properties}
+ \endlist
+
+ \section1 Signal
+ \target glossary-signal
+
+ A \e signal represents an application event, such as a user clicking a
+ button or the value of a \l{glossary-property}{property} of a
+ \l{glossary-component}{component} changing. The application needs this
+ information to perform actions or to relay it to other applications.
+
+ Components have predefined signals that are emitted when users interact with
+ the application. For example, the \l {Mouse Area} component has a \c clicked
+ signal that is emitted whenever the mouse is clicked within the area. Since
+ the signal name is \c clicked, the signal handler for receiving this signal
+ is named \c onClicked.
+
+ \image washingmachineui-connections.png "Connection View, Connections tab"
+
+ Further, a signal is automatically emitted when the value of a
+ \l{glossary-property}{property} changes.
+
+ Read more about signals:
+
+ \list
+ \li \l{Connecting Components to Signals}
+ \li \l{Mouse Area}
+ \endlist
+
+ \section1 State
+ \target glossary-state
+
+ The \e state of a particular visual \l{glossary-component}{component} is
+ the set of information that describes how and where the individual parts
+ of the component are displayed within it, and all the data associated with
+ that state. Most visual components in a UI will have a limited number of
+ states, each with well-defined \l{glossary-property}{properties}.
+
+ For example, an element in a list may be either selected or not, and if
+ selected, it may either be the currently active single selection or it may
+ be part of a selection group. Each of those states may have certain
+ associated visual appearance (neutral highlighted, expanded, and so forth).
+
+ Similarly, the appearance of a button can change to indicate a \e pressed
+ state.
+
+ \image studio-custom-button.gif "Button states"
+
+ Read more about states:
+
+ \list
+ \li \l{States}
+ \li \l{Adding States}
+ \endlist
+
+ \section1 Transition
+ \target glossary-transition
+
+ When a visual \l{glossary-component}{component} transitions from one
+ \l{glossary-state}{state} to another, its appearance changes. A
+ \e transition is an \e edge between two states. It may trigger other
+ events to occur, as other parts of the application may have behavior
+ that is triggered when a certain state is entered or left.
+
+ Read more about transitions:
+
+ \list
+ \li \l{Transition Editor}
+ \li \l{Animating Transitions Between States}
+ \endlist
\omit
## The following terms might or might not come back, but for now, the
@@ -135,15 +308,6 @@
Each kit consists of a set of values that define one environment, such as a
\l{glossary-device} {device} to preview the UI on.
- \section1 Mode
- \target glossary-mode
-
- Adapts the \QDS UI to the different UI design
- tasks at hand. Each mode has its own view that shows only the information
- required for performing a particular task, and provides only the most
- relevant features and functions related to it. As a result, the majority
- of the \QDS window area is always dedicated to the actual task.
-
\section1 Run Configuration
\target glossary-run-config
diff --git a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
index da5b29fca83..9442cbfd6db 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc
@@ -179,17 +179,16 @@
\li \l{Motion Design}
\list
\li \l{Introduction to Animation Techniques}
- \li \l{Creating Animations}
+ \li \l{Creating Timeline Animations}
\li \l{Editing Easing Curves}
- \li \l{Production Quality} (NEW)
+ \li \l{Production Quality}
+ \li \l{Optimizing Designs}
\list
- \li \l{Detailed Motion Design} (NEW)
+ \li \l{Creating Optimized 3D Scenes}
\endlist
- \li \l{Optimizing for Target Hardware} (NEW)
\endlist
\li \l{Implementing Applications} (NEW)
\list
- \li\l{Creating Optimized 3D Scenes}
\li Using Flows in Production (NEW)
\li \l{Coding}{Cross-Platform Development} (NEW)
\list
@@ -243,6 +242,7 @@
\li \l {Collecting User Feedback}
\li \l {Reporting Crashes}
\endlist
+ \li {Packaging Applications}
\endlist
\li \l{Developer Topics} (NEW)
\list
diff --git a/doc/qtdesignstudio/src/qtdesignstudio.qdoc b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
index 1761fe504ce..27bea4cf72f 100644
--- a/doc/qtdesignstudio/src/qtdesignstudio.qdoc
+++ b/doc/qtdesignstudio/src/qtdesignstudio.qdoc
@@ -74,11 +74,10 @@
\li \b {\l{Motion Design}}
\list
\li \l{Introduction to Animation Techniques}
- \li \l{Creating Animations}
+ \li \l{Creating Timeline Animations}
\li \l{Editing Easing Curves}
- \li \l{Production Quality} (NEW)
- \li \l{Importing from Content Creation Tools}
- \li \l{Optimizing for Target Hardware} (NEW)
+ \li \l{Production Quality}
+ \li \l{Optimizing Designs}
\endlist
\row
\li \inlineimage front-preview.png
@@ -101,6 +100,7 @@
\endlist
\li \b {\l{Developer Topics}} (NEW)
\list
+ \li \l{Packaging Applications}
\li \l{Using Git}
\li \l{Converting UI Projects to Applications}
\li \l{Using External Tools}
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/exporting-3d/exporting-from-qt3ds.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/exporting-3d/exporting-from-qt3ds.qdoc
index 96ecbb8b0d3..3b24cf2815a 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/exporting-3d/exporting-from-qt3ds.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/exporting-3d/exporting-from-qt3ds.qdoc
@@ -243,7 +243,7 @@
\li Recreate animations in subpresentation_ADAS according to the original
project. For more information on creating animations in \QDS, see
- \l {Creating Animations}.
+ \l {Creating Timeline Animations}.
\image exporting-from-qt3ds/24-recreate-animations.png "Recreate animations"
\li Go to the \uicontrol Timeline View to review the timeline for the
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
index a7ac4612629..43b307c27ff 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc
@@ -43,7 +43,7 @@
tools, you also import a \l{Cameras}{scene camera},
\l{Lights}{light}, \l{3D Models}{model}, and
\l {Materials and Shaders}{materials}. If your scene did not contain
- them, you can add the corresponding \l {Using 3D Components}{Qt Quick 3D}
+ them, you can add the corresponding \l {3D Components}{Qt Quick 3D}
components from \l Library > \uicontrol Components > \inlineimage plus.png
> \uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D}.
@@ -55,7 +55,10 @@
\uicontrol Properties to transform the component around a point other than
its local origin. A line is drawn in \uicontrol {3D Editor} from the pivot
point to the center of the component to provide a visual connection between
- them.
+ them. Especially when working with complex scenes, it may be useful to use
+ the \l {Showing and Hiding Components}{showing and hiding} or the
+ \l {Locking Components}{locking} features in \l Navigator to avoid
+ transforming components by mistake while editing your scene.
Toggle between local and global orientation to determine whether the gizmos
affect only the local transformations of the component or whether they
@@ -170,6 +173,12 @@
To toggle the selection mode, press \key Q.
+ To multiselect, hold \key Ctrl and click the components you wish to select.
+
+ After selecting a component, you can apply the usual \l {Keyboard Shortcuts}
+ {keyboard shortcuts} applicable to your operating system, for example,
+ \key Ctrl+C and \key Ctrl+V on Windows to copy-paste components.
+
\section1 Moving Components
\image studio-3d-editor-move.png "3D Editor in move mode"
diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-materials-shaders.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-materials-shaders.qdoc
index 85b5d1b3d65..b593f544e02 100644
--- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-materials-shaders.qdoc
+++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-materials-shaders.qdoc
@@ -73,7 +73,7 @@
by any other colors specified for the material.
You can animate material properties in the \uicontrol Timeline view, as
- instructed in \l {Creating Animations}.
+ instructed in \l {Creating Timeline Animations}.
\section1 Blending Colors
diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc b/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc
new file mode 100644
index 00000000000..6f1aa104f93
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/editor3d_qt5.qrc
@@ -0,0 +1,55 @@
+
+
+ mockfiles/meshes/arrow.mesh
+ mockfiles/meshes/scalerod.mesh
+ mockfiles/meshes/ring.mesh
+ mockfiles/meshes/ringselect.mesh
+ mockfiles/meshes/axishelper.mesh
+ mockfiles/images/editor_camera.png
+ mockfiles/images/editor_camera@2x.png
+ mockfiles/images/area.png
+ mockfiles/images/area@2x.png
+ mockfiles/images/directional.png
+ mockfiles/images/directional@2x.png
+ mockfiles/images/point.png
+ mockfiles/images/point@2x.png
+ mockfiles/images/spot.png
+ mockfiles/images/spot@2x.png
+ mockfiles/qt5/AdjustableArrow.qml
+ mockfiles/qt5/AreaLightHandle.qml
+ mockfiles/qt5/Arrow.qml
+ mockfiles/qt5/AutoScaleHelper.qml
+ mockfiles/qt5/AxisHelper.qml
+ mockfiles/qt5/AxisHelperArm.qml
+ mockfiles/qt5/CameraFrustum.qml
+ mockfiles/qt5/CameraGizmo.qml
+ mockfiles/qt5/DirectionalDraggable.qml
+ mockfiles/qt5/EditCameraController.qml
+ mockfiles/qt5/EditView3D.qml
+ mockfiles/qt5/FadeHandle.qml
+ mockfiles/qt5/HelperGrid.qml
+ mockfiles/qt5/IconGizmo.qml
+ mockfiles/qt5/IconRenderer3D.qml
+ mockfiles/qt5/LightGizmo.qml
+ mockfiles/qt5/LightIconGizmo.qml
+ mockfiles/qt5/LightModel.qml
+ mockfiles/qt5/Line3D.qml
+ mockfiles/qt5/MaterialNodeView.qml
+ mockfiles/qt5/ModelNode2DImageView.qml
+ mockfiles/qt5/ModelNode3DImageView.qml
+ mockfiles/qt5/ModelNodeView.qml
+ mockfiles/qt5/MoveGizmo.qml
+ mockfiles/qt5/NodeNodeView.qml
+ mockfiles/qt5/Overlay2D.qml
+ mockfiles/qt5/PlanarDraggable.qml
+ mockfiles/qt5/PlanarMoveHandle.qml
+ mockfiles/qt5/PlanarScaleHandle.qml
+ mockfiles/qt5/RotateGizmo.qml
+ mockfiles/qt5/RotateRing.qml
+ mockfiles/qt5/ScaleGizmo.qml
+ mockfiles/qt5/ScaleRod.qml
+ mockfiles/qt5/SceneView3D.qml
+ mockfiles/qt5/SelectionBox.qml
+ mockfiles/qt5/SpotLightHandle.qml
+
+
diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc b/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc
new file mode 100644
index 00000000000..c89e2806f6c
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc
@@ -0,0 +1,55 @@
+
+
+ mockfiles/meshes/arrow.mesh
+ mockfiles/meshes/scalerod.mesh
+ mockfiles/meshes/ring.mesh
+ mockfiles/meshes/ringselect.mesh
+ mockfiles/meshes/axishelper.mesh
+ mockfiles/images/editor_camera.png
+ mockfiles/images/editor_camera@2x.png
+ mockfiles/images/area.png
+ mockfiles/images/area@2x.png
+ mockfiles/images/directional.png
+ mockfiles/images/directional@2x.png
+ mockfiles/images/point.png
+ mockfiles/images/point@2x.png
+ mockfiles/images/spot.png
+ mockfiles/images/spot@2x.png
+ mockfiles/qt6/AdjustableArrow.qml
+ mockfiles/qt6/AreaLightHandle.qml
+ mockfiles/qt6/Arrow.qml
+ mockfiles/qt6/AutoScaleHelper.qml
+ mockfiles/qt6/AxisHelper.qml
+ mockfiles/qt6/AxisHelperArm.qml
+ mockfiles/qt6/CameraFrustum.qml
+ mockfiles/qt6/CameraGizmo.qml
+ mockfiles/qt6/DirectionalDraggable.qml
+ mockfiles/qt6/EditCameraController.qml
+ mockfiles/qt6/EditView3D.qml
+ mockfiles/qt6/FadeHandle.qml
+ mockfiles/qt6/HelperGrid.qml
+ mockfiles/qt6/IconGizmo.qml
+ mockfiles/qt6/IconRenderer3D.qml
+ mockfiles/qt6/LightGizmo.qml
+ mockfiles/qt6/LightIconGizmo.qml
+ mockfiles/qt6/LightModel.qml
+ mockfiles/qt6/Line3D.qml
+ mockfiles/qt6/MaterialNodeView.qml
+ mockfiles/qt6/ModelNode2DImageView.qml
+ mockfiles/qt6/ModelNode3DImageView.qml
+ mockfiles/qt6/ModelNodeView.qml
+ mockfiles/qt6/MoveGizmo.qml
+ mockfiles/qt6/NodeNodeView.qml
+ mockfiles/qt6/Overlay2D.qml
+ mockfiles/qt6/PlanarDraggable.qml
+ mockfiles/qt6/PlanarMoveHandle.qml
+ mockfiles/qt6/PlanarScaleHandle.qml
+ mockfiles/qt6/RotateGizmo.qml
+ mockfiles/qt6/RotateRing.qml
+ mockfiles/qt6/ScaleGizmo.qml
+ mockfiles/qt6/ScaleRod.qml
+ mockfiles/qt6/SceneView3D.qml
+ mockfiles/qt6/SelectionBox.qml
+ mockfiles/qt6/SpotLightHandle.qml
+
+
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AdjustableArrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AdjustableArrow.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/AdjustableArrow.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AdjustableArrow.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AreaLightHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AreaLightHandle.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/AreaLightHandle.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AreaLightHandle.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Arrow.qml
similarity index 98%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Arrow.qml
index 8b5993a76f1..b9d0b0b07dc 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/Arrow.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Arrow.qml
@@ -28,7 +28,7 @@ import QtQuick3D 1.15
DirectionalDraggable {
id: arrow
- source: "meshes/arrow.mesh"
+ source: "../meshes/arrow.mesh"
signal positionCommit()
signal positionMove()
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AutoScaleHelper.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/AutoScaleHelper.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AutoScaleHelper.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelper.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelper.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelper.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelperArm.qml
similarity index 98%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelperArm.qml
index 0121938cada..a148c5beb92 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/AxisHelperArm.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/AxisHelperArm.qml
@@ -42,7 +42,7 @@ Node {
property bool hovering: false
property vector3d cameraRotation: armRoot.camRotPos
- source: "meshes/axishelper.mesh"
+ source: "../meshes/axishelper.mesh"
materials: DefaultMaterial {
id: posMat
diffuseColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/CameraFrustum.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraFrustum.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/CameraFrustum.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraFrustum.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/CameraGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/CameraGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/DirectionalDraggable.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/DirectionalDraggable.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/DirectionalDraggable.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditCameraController.qml
similarity index 94%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditCameraController.qml
index 2b23117aa28..55e310f053d 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditCameraController.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditCameraController.qml
@@ -88,14 +88,21 @@ Item {
}
- function focusObject(targetObject, rotation, updateZoom, closeUp)
+ function focusObject(targetNodes, rotation, updateZoom, closeUp)
{
if (!camera)
return;
+ // targetNodes could be a list of nodes or a single node
+ var nodes = [];
+ if (targetNodes instanceof Node)
+ nodes.push(targetNodes);
+ else
+ nodes = targetNodes
+
camera.eulerRotation = rotation;
- var newLookAtAndZoom = _generalHelper.focusObjectToCamera(
- camera, _defaultCameraLookAtDistance, targetObject, view3d, _zoomFactor,
+ var newLookAtAndZoom = _generalHelper.focusNodesToCamera(
+ camera, _defaultCameraLookAtDistance, nodes, view3d, _zoomFactor,
updateZoom, closeUp);
_lookAtPoint = newLookAtAndZoom.toVector3d();
_zoomFactor = newLookAtAndZoom.w;
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml
similarity index 98%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml
index 318673e0c9e..cda0808b734 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/EditView3D.qml
@@ -176,9 +176,16 @@ Item {
function fitToView()
{
if (editView) {
- var targetNode = selectionBoxes.length > 0
- ? selectionBoxes[0].model : null;
- cameraControl.focusObject(targetNode, editView.camera.eulerRotation, true, false);
+ var boxModels = [];
+ if (selectedNodes.length > 1) {
+ for (var i = 0; i < selectedNodes.length; ++i) {
+ if (selectionBoxes.length > i)
+ boxModels.push(selectionBoxes[i].model)
+ }
+ } else if (selectedNodes.length > 0 && selectionBoxes.length > 0) {
+ boxModels.push(selectionBoxes[0].model);
+ }
+ cameraControl.focusObject(boxModels, editView.camera.eulerRotation, true, false);
}
}
@@ -857,7 +864,8 @@ Item {
width: 100
height: width
editCameraCtrl: cameraControl
- selectedNode : viewRoot.selectedNodes.length ? selectionBoxes[0].model : null
+ selectedNode: viewRoot.selectedNodes.length === 1 ? viewRoot.selectionBoxes[0].model
+ : viewRoot.selectedNode
}
Text {
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/FadeHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/FadeHandle.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/FadeHandle.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/FadeHandle.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/HelperGrid.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/HelperGrid.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/HelperGrid.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/IconGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconRenderer3D.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/IconRenderer3D.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/LightGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/LightIconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightIconGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/LightIconGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightIconGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/LightModel.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightModel.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/LightModel.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/LightModel.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Line3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Line3D.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/Line3D.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Line3D.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MaterialNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/MaterialNodeView.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MaterialNodeView.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode2DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode2DImageView.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode2DImageView.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode2DImageView.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/ModelNode3DImageView.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNode3DImageView.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ModelNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNodeView.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/ModelNodeView.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ModelNodeView.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MoveGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/MoveGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/MoveGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/NodeNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/NodeNodeView.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/NodeNodeView.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/NodeNodeView.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Overlay2D.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/Overlay2D.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/Overlay2D.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarDraggable.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/PlanarDraggable.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarDraggable.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarMoveHandle.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/PlanarMoveHandle.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarMoveHandle.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/PlanarScaleHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarScaleHandle.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/PlanarScaleHandle.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/PlanarScaleHandle.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/RotateGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateRing.qml
similarity index 98%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateRing.qml
index e54b6301be1..003fd985177 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/RotateRing.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/RotateRing.qml
@@ -49,12 +49,12 @@ Model {
signal rotateCommit()
signal rotateChange()
- source: "meshes/ring.mesh"
+ source: "../meshes/ring.mesh"
Model {
id: pickModel
objectName: "PickModel for " + rotateRing.objectName
- source: "meshes/ringselect.mesh"
+ source: "../meshes/ringselect.mesh"
pickable: true
}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleGizmo.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/ScaleGizmo.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleGizmo.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleRod.qml
similarity index 98%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleRod.qml
index a6f684ce62c..06cfdf5c3a9 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/ScaleRod.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/ScaleRod.qml
@@ -29,7 +29,7 @@ import MouseArea3D 1.0
DirectionalDraggable {
id: scaleRod
- source: "meshes/scalerod.mesh"
+ source: "../meshes/scalerod.mesh"
property vector3d axis
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SceneView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SceneView3D.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/SceneView3D.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SceneView3D.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SelectionBox.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/SelectionBox.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SelectionBox.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/SpotLightHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SpotLightHandle.qml
similarity index 100%
rename from share/qtcreator/qml/qmlpuppet/mockfiles/SpotLightHandle.qml
rename to share/qtcreator/qml/qmlpuppet/mockfiles/qt5/SpotLightHandle.qml
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AdjustableArrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AdjustableArrow.qml
new file mode 100644
index 00000000000..d71b245d334
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AdjustableArrow.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import LineGeometry 1.0
+
+DirectionalDraggable {
+ id: arrowRoot
+
+ Model {
+ geometry: LineGeometry {
+ id: lineGeometry
+ name: "Edit 3D ScalableArrow"
+ startPos: Qt.vector3d(0, 0, 0)
+ endPos: Qt.vector3d(0, 1, 0)
+ }
+ scale: Qt.vector3d(1, arrowRoot.length, 1)
+ materials: [ arrowRoot.material ]
+ }
+
+ Model {
+ id: arrowHead
+ source: "#Cone"
+ materials: [ arrowRoot.material ]
+ y: arrowRoot.length - 3
+ scale: Qt.vector3d(0.02, 0.035, 0.02)
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AreaLightHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AreaLightHandle.qml
new file mode 100644
index 00000000000..78e97e81d42
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AreaLightHandle.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+DirectionalDraggable {
+ id: handleRoot
+
+ property string currentLabel
+ property point currentMousePos
+ property string propName
+ property real propValue: 0
+ property real newValue: 0
+ property real baseScale: 5
+
+ scale: autoScaler.getScale(Qt.vector3d(baseScale, baseScale, baseScale))
+ length: 3
+ offset: -1.5
+
+ Model {
+ id: handle
+ source: "#Sphere"
+ materials: [ handleRoot.material ]
+ scale: Qt.vector3d(0.02, 0.02, 0.02)
+ }
+
+ AutoScaleHelper {
+ id: autoScaler
+ active: handleRoot.active
+ view3D: handleRoot.view3D
+ }
+
+ property real _startValue
+ property real _startScale
+
+ signal valueCommit()
+ signal valueChange()
+
+ function updateValue(relativeDistance, screenPos)
+ {
+ handleRoot.newValue = Math.round(Math.min(999999, Math.max(0, _startValue + (relativeDistance * _startScale))));
+ var l = Qt.locale();
+ handleRoot.currentLabel = propName + qsTr(": ") + Number(newValue).toLocaleString(l, 'f', 0);
+ handleRoot.currentMousePos = screenPos;
+ }
+
+ onPressed: (mouseArea, screenPos)=> {
+ _startScale = autoScaler.relativeScale * baseScale;
+ _startValue = propValue;
+ updateValue(0, screenPos);
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateValue(relativeDistance, screenPos);
+ handleRoot.valueChange();
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateValue(relativeDistance, screenPos);
+ handleRoot.valueCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Arrow.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Arrow.qml
new file mode 100644
index 00000000000..b49d5bbf5f7
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Arrow.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+DirectionalDraggable {
+ id: arrow
+ source: "../meshes/arrow.mesh"
+
+ signal positionCommit()
+ signal positionMove()
+
+ function localPos(sceneRelativeDistance)
+ {
+ var newScenePos = Qt.vector3d(
+ _targetStartPos.x + sceneRelativeDistance.x,
+ _targetStartPos.y + sceneRelativeDistance.y,
+ _targetStartPos.z + sceneRelativeDistance.z);
+ return targetNode.parent ? targetNode.parent.mapPositionFromScene(newScenePos) : newScenePos;
+ }
+
+ onPressed: {
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance)=> {
+ targetNode.position = localPos(sceneRelativeDistance);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.moveMultiSelection(false);
+ positionMove();
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance)=> {
+ targetNode.position = localPos(sceneRelativeDistance);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.moveMultiSelection(true);
+ positionCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AutoScaleHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AutoScaleHelper.qml
new file mode 100644
index 00000000000..3ff484b61a4
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AutoScaleHelper.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Node {
+ id: overlayNode
+
+ property View3D view3D
+ property Camera camera: view3D.camera
+ property bool active: true
+
+ // Read-only
+ property real relativeScale: 1
+
+ onActiveChanged: updateScale()
+ onSceneTransformChanged: updateScale()
+ // Trigger delayed update on camera change to ensure camera values are correct
+ onCameraChanged: _generalHelper.requestOverlayUpdate();
+
+ Connections {
+ target: camera
+ function onSceneTransformChanged() { updateScale() }
+ }
+
+ Connections {
+ target: _generalHelper
+ function onOverlayUpdateNeeded() { updateScale() }
+ }
+
+ function getScale(baseScale)
+ {
+ return Qt.vector3d(baseScale.x * relativeScale, baseScale.y * relativeScale,
+ baseScale.z * relativeScale);
+ }
+
+ function updateScale()
+ {
+ if (active)
+ relativeScale = helper.getRelativeScale(overlayNode);
+ else
+ relativeScale = 1;
+ }
+
+ MouseArea3D {
+ id: helper
+ active: false
+ view3D: overlayNode.view3D
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelper.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelper.qml
new file mode 100644
index 00000000000..eba9beab23f
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelper.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+View3D {
+ id: axisHelperView
+
+ property var editCameraCtrl
+ property Node selectedNode
+
+ camera: axisHelperCamera
+
+ Node {
+ OrthographicCamera {
+ id: axisHelperCamera
+ rotation: editCameraCtrl.camera ? editCameraCtrl.camera.rotation : Qt.quaternion(1, 0, 0, 0)
+ position: editCameraCtrl.camera ? editCameraCtrl.camera.position.minus(editCameraCtrl._lookAtPoint)
+ .normalized().times(600) : Qt.vector3d(0, 0, 0)
+ }
+
+ AutoScaleHelper {
+ id: autoScale
+ view3D: axisHelperView
+ position: axisHelperGizmo.scenePosition
+ }
+
+ Node {
+ id: axisHelperGizmo
+ scale: autoScale.getScale(Qt.vector3d(4, 4, 4))
+
+ AxisHelperArm {
+ id: armX
+ eulerRotation: Qt.vector3d(0, 0, -90)
+ color: Qt.rgba(1, 0, 0, 1)
+ hoverColor: Qt.lighter(Qt.rgba(1, 0, 0, 1))
+ view3D: axisHelperView
+ camRotPos: Qt.vector3d(0, 90, 0)
+ camRotNeg: Qt.vector3d(0, -90, 0)
+ }
+
+ AxisHelperArm {
+ id: armY
+ eulerRotation: Qt.vector3d(0, 0, 0)
+ color: Qt.rgba(0, 0.6, 0, 1)
+ hoverColor: Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
+ view3D: axisHelperView
+ camRotPos: Qt.vector3d(-90, 0, 0)
+ camRotNeg: Qt.vector3d(90, 0, 0)
+ }
+
+ AxisHelperArm {
+ id: armZ
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ color: Qt.rgba(0, 0, 1, 1)
+ hoverColor: Qt.lighter(Qt.rgba(0, 0, 1, 1))
+ view3D: axisHelperView
+ camRotPos: Qt.vector3d(0, 0, 0)
+ camRotNeg: Qt.vector3d(0, 180, 0)
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ acceptedButtons: Qt.LeftButton
+
+ property var pickObj: null
+
+ function cancelHover()
+ {
+ if (pickObj) {
+ pickObj.hovering = false;
+ pickObj = null;
+ }
+ }
+
+ function pick(mouse)
+ {
+ var result = axisHelperView.pick(mouse.x, mouse.y);
+ if (result.objectHit) {
+ if (result.objectHit !== pickObj) {
+ cancelHover();
+ pickObj = result.objectHit;
+ pickObj.hovering = true;
+ }
+ } else {
+ cancelHover();
+ }
+ }
+
+ onPositionChanged: (mouse)=> {
+ pick(mouse);
+ }
+
+ onPressed: (mouse)=> {
+ pick(mouse);
+ if (pickObj) {
+ axisHelperView.editCameraCtrl.focusObject(axisHelperView.selectedNode,
+ pickObj.cameraRotation, false, false);
+ } else {
+ mouse.accepted = false;
+ }
+ }
+
+ onExited: cancelHover()
+ onCanceled: cancelHover()
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelperArm.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelperArm.qml
new file mode 100644
index 00000000000..cb50b0efbc4
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/AxisHelperArm.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+Node {
+ id: armRoot
+ property alias posModel: posModel
+ property alias negModel: negModel
+ property View3D view3D
+ property color hoverColor
+ property color color
+ property vector3d camRotPos
+ property vector3d camRotNeg
+
+ Model {
+ id: posModel
+
+ property bool hovering: false
+ property vector3d cameraRotation: armRoot.camRotPos
+
+ source: "../meshes/axishelper.mesh"
+ materials: DefaultMaterial {
+ id: posMat
+ diffuseColor: posModel.hovering ? armRoot.hoverColor : armRoot.color
+ lighting: DefaultMaterial.NoLighting
+ }
+ pickable: true
+ }
+
+ Model {
+ id: negModel
+
+ property bool hovering: false
+ property vector3d cameraRotation: armRoot.camRotNeg
+
+ source: "#Sphere"
+ y: -6
+ scale: Qt.vector3d(0.025, 0.025, 0.025)
+ materials: DefaultMaterial {
+ id: negMat
+ diffuseColor: negModel.hovering ? armRoot.hoverColor : armRoot.color
+ lighting: DefaultMaterial.NoLighting
+ }
+ pickable: true
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraFrustum.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraFrustum.qml
new file mode 100644
index 00000000000..adf3d53ab9b
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraFrustum.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import CameraGeometry 1.0
+
+Model {
+ id: cameraFrustum
+
+ property alias geometryName: cameraGeometry.name // Name must be unique for each geometry
+ property alias viewPortRect: cameraGeometry.viewPortRect
+ property Node targetNode: null
+ property Node scene: null
+ property bool selected: false
+
+ function updateGeometry()
+ {
+ cameraGeometry.update();
+ }
+
+ position: targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0)
+ rotation: targetNode ? targetNode.sceneRotation : Qt.quaternion(1, 0, 0, 0)
+
+ geometry: cameraGeometry
+ materials: [
+ DefaultMaterial {
+ id: defaultMaterial
+ diffuseColor: cameraFrustum.selected ? "#FF0000" : "#555555"
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+
+ CameraGeometry {
+ id: cameraGeometry
+ camera: cameraFrustum.scene && cameraFrustum.targetNode ? cameraFrustum.targetNode : null
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml
new file mode 100644
index 00000000000..42a7bc7bfaa
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/CameraGizmo.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+IconGizmo {
+ id: cameraGizmo
+
+ property Model frustumModel: null
+
+ iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_camera.png"
+
+ function connectFrustum(frustum)
+ {
+ frustumModel = frustum;
+
+ frustum.selected = selected;
+ frustum.selected = Qt.binding(function() {return selected;});
+
+ frustum.scene = scene;
+ frustum.scene = Qt.binding(function() {return scene;});
+
+ 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);});
+ }
+
+ onActiveSceneChanged: {
+ if (frustumModel && activeScene == scene)
+ frustumModel.updateGeometry();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/DirectionalDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/DirectionalDraggable.qml
new file mode 100644
index 00000000000..5a2f0911dd8
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/DirectionalDraggable.qml
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Model {
+ id: rootModel
+
+ property View3D view3D
+ property alias color: material.diffuseColor
+ property Node targetNode: null
+ property bool dragging: mouseAreaYZ.dragging || mouseAreaXZ.dragging
+ property bool active: false
+ property MouseArea3D dragHelper: null
+ property alias material: material
+ property real length: 12
+ property real offset: 0
+
+ readonly property bool hovering: mouseAreaYZ.hovering || mouseAreaXZ.hovering
+
+ property vector3d _scenePosPressed
+ property real _posPressed
+ property vector3d _targetStartPos
+
+ signal pressed(var mouseArea, point screenPos)
+ signal dragged(var mouseArea, vector3d sceneRelativeDistance, real relativeDistance, point screenPos)
+ signal released(var mouseArea, vector3d sceneRelativeDistance, real relativeDistance, point screenPos)
+
+ DefaultMaterial {
+ id: material
+ diffuseColor: "white"
+ lighting: DefaultMaterial.NoLighting
+ }
+
+ materials: [ material ]
+
+ function handlePressed(mouseArea, planePos, screenPos)
+ {
+ if (!targetNode)
+ return;
+
+ var maskedPosition = Qt.vector3d(planePos.x, 0, 0);
+ _posPressed = planePos.x;
+ _scenePosPressed = mouseArea.dragHelper.mapPositionToScene(maskedPosition);
+ _targetStartPos = mouseArea.pivotScenePosition(targetNode);
+ pressed(mouseArea, screenPos);
+ }
+
+ function calcRelativeDistance(mouseArea, planePos)
+ {
+ var maskedPosition = Qt.vector3d(planePos.x, 0, 0);
+ var scenePointerPos = mouseArea.dragHelper.mapPositionToScene(maskedPosition);
+ return scenePointerPos.minus(_scenePosPressed);
+ }
+
+ function handleDragged(mouseArea, planePos, screenPos)
+ {
+ if (!targetNode)
+ return;
+
+ dragged(mouseArea, calcRelativeDistance(mouseArea, planePos), planePos.x - _posPressed, screenPos);
+ }
+
+ function handleReleased(mouseArea, planePos, screenPos)
+ {
+ if (!targetNode)
+ return;
+
+ released(mouseArea, calcRelativeDistance(mouseArea, planePos), planePos.x - _posPressed, screenPos);
+ }
+
+ MouseArea3D {
+ id: mouseAreaYZ
+ view3D: rootModel.view3D
+ x: rootModel.offset
+ y: -1.5
+ width: rootModel.length
+ height: 3
+ eulerRotation: Qt.vector3d(0, 0, 90)
+ grabsMouse: targetNode
+ active: rootModel.active
+ dragHelper: rootModel.dragHelper
+ priority: 5
+
+ onPressed: (planePos, screenPos)=> {
+ rootModel.handlePressed(mouseAreaYZ, planePos, screenPos);
+ }
+ onDragged: (planePos, screenPos)=> {
+ rootModel.handleDragged(mouseAreaYZ, planePos, screenPos);
+ }
+ onReleased: (planePos, screenPos)=> {
+ rootModel.handleReleased(mouseAreaYZ, planePos, screenPos);
+ }
+ }
+
+ MouseArea3D {
+ id: mouseAreaXZ
+ view3D: rootModel.view3D
+ x: rootModel.offset
+ y: -1.5
+ width: rootModel.length
+ height: 3
+ eulerRotation: Qt.vector3d(0, 90, 90)
+ grabsMouse: targetNode
+ active: rootModel.active
+ dragHelper: rootModel.dragHelper
+ priority: 5
+
+ onPressed: (planePos, screenPos)=> {
+ rootModel.handlePressed(mouseAreaXZ, planePos, screenPos);
+ }
+ onDragged: (planePos, screenPos)=> {
+ rootModel.handleDragged(mouseAreaXZ, planePos, screenPos);
+ }
+ onReleased: (planePos, screenPos)=> {
+ rootModel.handleReleased(mouseAreaXZ, planePos, screenPos);
+ }
+ }
+}
+
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditCameraController.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditCameraController.qml
new file mode 100644
index 00000000000..13743094219
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditCameraController.qml
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+Item {
+ id: cameraCtrl
+
+ property Camera camera: null
+ property View3D view3d: null
+ property string sceneId
+ property vector3d _lookAtPoint
+ property vector3d _pressPoint
+ property vector3d _prevPoint
+ property vector3d _startRotation
+ property vector3d _startPosition
+ property vector3d _startLookAtPoint
+ property matrix4x4 _startTransform
+ property bool _dragging
+ property int _button
+ property real _zoomFactor: 1
+ property Camera _prevCamera: null
+ readonly property vector3d _defaultCameraPosition: Qt.vector3d(0, 600, 600)
+ readonly property vector3d _defaultCameraRotation: Qt.vector3d(-45, 0, 0)
+ readonly property real _defaultCameraLookAtDistance: _defaultCameraPosition.length()
+ property bool ignoreToolState: false
+
+ function restoreCameraState(cameraState)
+ {
+ if (!camera || ignoreToolState)
+ return;
+
+ _lookAtPoint = cameraState[0];
+ _zoomFactor = cameraState[1];
+ camera.position = cameraState[2];
+ camera.rotation = cameraState[3];
+ _generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
+ _zoomFactor, false);
+ }
+
+ function restoreDefaultState()
+ {
+ if (!camera)
+ return;
+
+ _lookAtPoint = Qt.vector3d(0, 0, 0);
+ _zoomFactor = 1;
+ camera.position = _defaultCameraPosition;
+ camera.eulerRotation = _defaultCameraRotation;
+ _generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
+ _zoomFactor, false);
+ }
+
+ function storeCameraState(delay)
+ {
+ if (!camera || ignoreToolState)
+ return;
+
+ var cameraState = [];
+ cameraState[0] = _lookAtPoint;
+ cameraState[1] = _zoomFactor;
+ cameraState[2] = camera.position;
+ cameraState[3] = camera.rotation;
+ _generalHelper.storeToolState(sceneId, "editCamState", cameraState, delay);
+ }
+
+
+ function focusObject(targetNodes, rotation, updateZoom, closeUp)
+ {
+ if (!camera)
+ return;
+
+ // targetNodes could be a list of nodes or a single node
+ var nodes = [];
+ if (targetNodes instanceof Node)
+ nodes.push(targetNodes);
+ else
+ nodes = targetNodes
+
+ camera.eulerRotation = rotation;
+ var newLookAtAndZoom = _generalHelper.focusNodesToCamera(
+ camera, _defaultCameraLookAtDistance, nodes, view3d, _zoomFactor,
+ updateZoom, closeUp);
+ _lookAtPoint = newLookAtAndZoom.toVector3d();
+ _zoomFactor = newLookAtAndZoom.w;
+ storeCameraState(0);
+ }
+
+ function zoomRelative(distance)
+ {
+ if (!camera)
+ return;
+
+ _zoomFactor = _generalHelper.zoomCamera(camera, distance, _defaultCameraLookAtDistance,
+ _lookAtPoint, _zoomFactor, true);
+ }
+
+ onCameraChanged: {
+ if (camera && _prevCamera) {
+ // Reset zoom on previous camera to ensure it's properties are good to copy to new cam
+ _generalHelper.zoomCamera(_prevCamera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
+ 1, false);
+
+ camera.position = _prevCamera.position;
+ camera.rotation = _prevCamera.rotation;
+
+ // Apply correct zoom to new camera
+ _generalHelper.zoomCamera(camera, 0, _defaultCameraLookAtDistance, _lookAtPoint,
+ _zoomFactor, false);
+ }
+ _prevCamera = camera;
+ }
+
+ MouseArea {
+ id: mouseHandler
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
+ hoverEnabled: false
+ anchors.fill: parent
+ onPositionChanged: (mouse)=> {
+ if (cameraCtrl.camera && mouse.modifiers === Qt.AltModifier && cameraCtrl._dragging) {
+ var currentPoint = Qt.vector3d(mouse.x, mouse.y, 0);
+ if (cameraCtrl._button == Qt.LeftButton) {
+ _generalHelper.orbitCamera(cameraCtrl.camera, cameraCtrl._startRotation,
+ cameraCtrl._lookAtPoint, cameraCtrl._pressPoint,
+ currentPoint);
+ } else if (cameraCtrl._button == Qt.MiddleButton) {
+ cameraCtrl._lookAtPoint = _generalHelper.panCamera(
+ cameraCtrl.camera, cameraCtrl._startTransform,
+ cameraCtrl._startPosition, cameraCtrl._startLookAtPoint,
+ cameraCtrl._pressPoint, currentPoint, _zoomFactor);
+ } else if (cameraCtrl._button == Qt.RightButton) {
+ cameraCtrl.zoomRelative(currentPoint.y - cameraCtrl._prevPoint.y)
+ cameraCtrl._prevPoint = currentPoint;
+ }
+ }
+ }
+ onPressed: (mouse)=> {
+ if (cameraCtrl.camera && mouse.modifiers === Qt.AltModifier) {
+ cameraCtrl._dragging = true;
+ cameraCtrl._startRotation = cameraCtrl.camera.eulerRotation;
+ cameraCtrl._startPosition = cameraCtrl.camera.position;
+ cameraCtrl._startLookAtPoint = _lookAtPoint;
+ cameraCtrl._pressPoint = Qt.vector3d(mouse.x, mouse.y, 0);
+ cameraCtrl._prevPoint = cameraCtrl._pressPoint;
+ cameraCtrl._button = mouse.button;
+ cameraCtrl._startTransform = cameraCtrl.camera.sceneTransform;
+ } else {
+ mouse.accepted = false;
+ }
+ }
+
+ function handleRelease() {
+ cameraCtrl._dragging = false;
+ cameraCtrl.storeCameraState(0);
+ }
+
+ onReleased: handleRelease()
+ onCanceled: handleRelease()
+
+ onWheel: (wheel)=> {
+ if (cameraCtrl.camera) {
+ // Empirically determined divisor for nice zoom
+ cameraCtrl.zoomRelative(wheel.angleDelta.y / -40);
+ cameraCtrl.storeCameraState(500);
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml
new file mode 100644
index 00000000000..83e37050402
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml
@@ -0,0 +1,892 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Item {
+ id: viewRoot
+ width: 1024
+ height: 768
+ visible: true
+
+ property Node activeScene: null
+ property View3D editView: null
+ property string sceneId
+
+ property bool showEditLight: false
+ property bool showGrid: true
+ property bool usePerspective: true
+ property bool globalOrientation: false
+ property alias contentItem: contentItem
+
+ enum SelectionMode { Item, Group }
+ enum TransformMode { Move, Rotate, Scale }
+
+ property int selectionMode: EditView3D.SelectionMode.Item
+ property int transformMode: EditView3D.TransformMode.Move
+
+ property Node selectedNode: null // This is multiSelectionNode in multi-selection case
+ property var selectedNodes: [] // All selected nodes
+
+ property var lightIconGizmos: []
+ property var cameraGizmos: []
+ property var selectionBoxes: []
+ property rect viewPortRect: Qt.rect(0, 0, 1000, 1000)
+
+ property bool shuttingDown: false
+
+ property real fps: 0
+
+ signal selectionChanged(var selectedNodes)
+ signal commitObjectProperty(var objects, var propNames)
+ signal changeObjectProperty(var objects, var propNames)
+ signal notifyActiveSceneChange()
+
+ onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
+ onShowEditLightChanged: _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
+ onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
+ onShowGridChanged: _generalHelper.storeToolState(sceneId, "showGrid", showGrid);
+ onSelectionModeChanged: _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
+ onTransformModeChanged: _generalHelper.storeToolState(sceneId, "transformMode", transformMode);
+
+ onActiveSceneChanged: updateActiveScene()
+
+ function aboutToShutDown()
+ {
+ shuttingDown = true;
+ }
+
+ function createEditView()
+ {
+ var component = Qt.createComponent("SceneView3D.qml");
+ if (component.status === Component.Ready) {
+ editView = component.createObject(viewRect,
+ {"usePerspective": usePerspective,
+ "showSceneLight": showEditLight,
+ "showGrid": showGrid,
+ "importScene": activeScene,
+ "cameraZoomFactor": cameraControl._zoomFactor,
+ "z": 1});
+ editView.usePerspective = Qt.binding(function() {return usePerspective;});
+ editView.showSceneLight = Qt.binding(function() {return showEditLight;});
+ editView.showGrid = Qt.binding(function() {return showGrid;});
+ editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;});
+
+ selectionBoxes.length = 0;
+ return true;
+ }
+ return false;
+ }
+
+ function updateActiveScene()
+ {
+ if (editView) {
+ // Destroy is async, so make sure we don't get any more updates for the old editView
+ _generalHelper.enableItemUpdate(editView, false);
+ editView.visible = false;
+ editView.destroy();
+ }
+
+ // importScene cannot be updated after initial set, so we need to reconstruct entire View3D
+ if (createEditView()) {
+ if (activeScene) {
+ var toolStates = _generalHelper.getToolStates(sceneId);
+ if (Object.keys(toolStates).length > 0) {
+ updateToolStates(toolStates, true);
+ } else {
+ // Don't inherit the edit light state from the previous scene, but rather
+ // turn the edit light on for scenes that do not have any scene
+ // lights, and turn it off for scenes that have.
+ var hasSceneLight = false;
+ for (var i = 0; i < lightIconGizmos.length; ++i) {
+ if (lightIconGizmos[i].scene === activeScene) {
+ hasSceneLight = true;
+ break;
+ }
+ }
+ showEditLight = !hasSceneLight;
+ storeCurrentToolStates();
+ }
+ } else {
+ // When active scene is deleted, this function gets called by object deletion
+ // handlers without going through setActiveScene, so make sure sceneId is cleared.
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (!shuttingDown) {
+ sceneId = "";
+ storeCurrentToolStates();
+ }
+ }
+
+ notifyActiveSceneChange();
+ }
+ }
+
+ function setActiveScene(newScene, newSceneId)
+ {
+ var needExplicitUpdate = !activeScene && !newScene;
+
+ sceneId = newSceneId;
+ activeScene = newScene;
+
+ if (needExplicitUpdate)
+ updateActiveScene();
+ }
+
+ // Disables edit view update if scene doesn't match current activeScene.
+ // If it matches, updates are enabled.
+ function enableEditViewUpdate(scene)
+ {
+ if (editView)
+ _generalHelper.enableItemUpdate(editView, (scene && scene === activeScene));
+ }
+
+ function handleActiveSceneIdChange(newId)
+ {
+ if (sceneId !== newId) {
+ sceneId = newId;
+ storeCurrentToolStates();
+ }
+ }
+
+ function fitToView()
+ {
+ if (editView) {
+ var boxModels = [];
+ if (selectedNodes.length > 1) {
+ for (var i = 0; i < selectedNodes.length; ++i) {
+ if (selectionBoxes.length > i)
+ boxModels.push(selectionBoxes[i].model)
+ }
+ } else if (selectedNodes.length > 0 && selectionBoxes.length > 0) {
+ boxModels.push(selectionBoxes[0].model);
+ }
+ cameraControl.focusObject(boxModels, editView.camera.eulerRotation, true, false);
+ }
+ }
+
+ // If resetToDefault is true, tool states not specifically set to anything will be reset to
+ // their default state.
+ function updateToolStates(toolStates, resetToDefault)
+ {
+ if ("showEditLight" in toolStates)
+ showEditLight = toolStates.showEditLight;
+ else if (resetToDefault)
+ showEditLight = false;
+
+ if ("showGrid" in toolStates)
+ showGrid = toolStates.showGrid;
+ else if (resetToDefault)
+ showGrid = true;
+
+ if ("usePerspective" in toolStates)
+ usePerspective = toolStates.usePerspective;
+ else if (resetToDefault)
+ usePerspective = true;
+
+ if ("globalOrientation" in toolStates)
+ globalOrientation = toolStates.globalOrientation;
+ else if (resetToDefault)
+ globalOrientation = false;
+
+ if ("selectionMode" in toolStates)
+ selectionMode = toolStates.selectionMode;
+ else if (resetToDefault)
+ selectionMode = EditView3D.SelectionMode.Item;
+
+ if ("transformMode" in toolStates)
+ transformMode = toolStates.transformMode;
+ else if (resetToDefault)
+ transformMode = EditView3D.TransformMode.Move;
+
+ if ("editCamState" in toolStates)
+ cameraControl.restoreCameraState(toolStates.editCamState);
+ else if (resetToDefault)
+ cameraControl.restoreDefaultState();
+ }
+
+ function storeCurrentToolStates()
+ {
+ _generalHelper.storeToolState(sceneId, "showEditLight", showEditLight)
+ _generalHelper.storeToolState(sceneId, "showGrid", showGrid)
+ _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective)
+ _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation)
+ _generalHelper.storeToolState(sceneId, "selectionMode", selectionMode);
+ _generalHelper.storeToolState(sceneId, "transformMode", transformMode);
+
+ cameraControl.storeCameraState(0);
+ }
+
+ function ensureSelectionBoxes(count)
+ {
+ var needMore = count - selectionBoxes.length
+ if (needMore > 0) {
+ var component = Qt.createComponent("SelectionBox.qml");
+ if (component.status === Component.Ready) {
+ for (var i = 0; i < needMore; ++i) {
+ var geometryName = _generalHelper.generateUniqueName("SelectionBoxGeometry");
+ var boxParent = null;
+ if (editView)
+ boxParent = editView.sceneHelpers;
+ var box = component.createObject(boxParent, {"view3D": editView,
+ "geometryName": geometryName});
+ selectionBoxes[selectionBoxes.length] = box;
+ box.view3D = Qt.binding(function() {return editView;});
+ }
+ }
+ }
+ }
+
+ function selectObjects(objects)
+ {
+ // Create selection boxes as necessary. One more box than is actually needed is created, so
+ // that we always have a previously created box to use for new selection.
+ // This fixes an occasional visual glitch when creating a new box.
+ ensureSelectionBoxes(objects.length + 1)
+
+ var i;
+ for (i = 0; i < objects.length; ++i)
+ selectionBoxes[i].targetNode = objects[i];
+ for (i = objects.length; i < selectionBoxes.length; ++i)
+ selectionBoxes[i].targetNode = null;
+
+ selectedNodes = objects;
+ if (objects.length === 0) {
+ selectedNode = null;
+ } else if (objects.length > 1) {
+ selectedNode = multiSelectionNode;
+ _generalHelper.setMultiSelectionTargets(multiSelectionNode, objects);
+ } else {
+ selectedNode = objects[0];
+ }
+ }
+
+ function handleObjectClicked(object, multi)
+ {
+ var clickedObject;
+
+ // Click on locked object is treated same as click on empty space
+ if (!_generalHelper.isLocked(object))
+ clickedObject = object;
+
+ if (selectionMode === EditView3D.SelectionMode.Group) {
+ while (clickedObject && clickedObject !== activeScene
+ && (activeScene instanceof Model || clickedObject.parent !== activeScene)) {
+ clickedObject = clickedObject.parent;
+ }
+ }
+ // Object selection logic:
+ // Regular click: Clear any multiselection, single-selects the clicked object
+ // Ctrl-click: No objects selected: Act as single select
+ // One or more objects selected: Multiselect
+ // Null object always clears entire selection
+ var newSelection = [];
+ if (clickedObject) {
+ if (multi && selectedNodes.length > 0) {
+ var deselect = false;
+ for (var i = 0; i < selectedNodes.length; ++i) {
+ // Multiselecting already selected object clears that object from selection
+ if (selectedNodes[i] !== clickedObject)
+ newSelection[newSelection.length] = selectedNodes[i];
+ else
+ deselect = true;
+ }
+ if (!deselect)
+ newSelection[newSelection.length] = clickedObject;
+ } else {
+ newSelection[0] = clickedObject;
+ }
+ }
+ selectObjects(newSelection);
+ selectionChanged(newSelection);
+ }
+
+ function addLightGizmo(scene, obj)
+ {
+ // Insert into first available gizmo if we don't already have gizmo for this object
+ var slotFound = -1;
+ for (var i = 0; i < lightIconGizmos.length; ++i) {
+ if (!lightIconGizmos[i].targetNode) {
+ slotFound = i;
+ } else if (lightIconGizmos[i].targetNode === obj) {
+ lightIconGizmos[i].scene = scene;
+ return;
+ }
+ }
+
+ if (slotFound !== -1) {
+ lightIconGizmos[slotFound].scene = scene;
+ lightIconGizmos[slotFound].targetNode = obj;
+ lightIconGizmos[slotFound].locked = _generalHelper.isLocked(obj);
+ lightIconGizmos[slotFound].hidden = _generalHelper.isHidden(obj);
+ _generalHelper.registerGizmoTarget(obj);
+ return;
+ }
+
+ // No free gizmos available, create a new one
+ var gizmoComponent = Qt.createComponent("LightIconGizmo.qml");
+ if (gizmoComponent.status === Component.Ready) {
+ _generalHelper.registerGizmoTarget(obj);
+ var gizmo = gizmoComponent.createObject(overlayView,
+ {"view3D": overlayView, "targetNode": obj,
+ "selectedNodes": selectedNodes, "scene": scene,
+ "activeScene": activeScene,
+ "locked": _generalHelper.isLocked(obj),
+ "hidden": _generalHelper.isHidden(obj)});
+ lightIconGizmos[lightIconGizmos.length] = gizmo;
+ gizmo.clicked.connect(handleObjectClicked);
+ gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;});
+ gizmo.activeScene = Qt.binding(function() {return activeScene;});
+ }
+ }
+
+ function addCameraGizmo(scene, obj)
+ {
+ // Insert into first available gizmo if we don't already have gizmo for this object
+ var slotFound = -1;
+ for (var i = 0; i < cameraGizmos.length; ++i) {
+ if (!cameraGizmos[i].targetNode) {
+ slotFound = i;
+ } else if (cameraGizmos[i].targetNode === obj) {
+ cameraGizmos[i].scene = scene;
+ return;
+ }
+ }
+
+ if (slotFound !== -1) {
+ cameraGizmos[slotFound].scene = scene;
+ cameraGizmos[slotFound].targetNode = obj;
+ cameraGizmos[slotFound].locked = _generalHelper.isLocked(obj);
+ cameraGizmos[slotFound].hidden = _generalHelper.isHidden(obj);
+ _generalHelper.registerGizmoTarget(obj);
+ return;
+ }
+
+ // No free gizmos available, create a new one
+ var gizmoComponent = Qt.createComponent("CameraGizmo.qml");
+ var frustumComponent = Qt.createComponent("CameraFrustum.qml");
+ if (gizmoComponent.status === Component.Ready && frustumComponent.status === Component.Ready) {
+ _generalHelper.registerGizmoTarget(obj);
+ var geometryName = _generalHelper.generateUniqueName("CameraGeometry");
+ var frustum = frustumComponent.createObject(
+ overlayScene,
+ {"geometryName": geometryName, "viewPortRect": viewPortRect});
+ var gizmo = gizmoComponent.createObject(
+ overlayView,
+ {"view3D": overlayView, "targetNode": obj,
+ "selectedNodes": selectedNodes, "scene": scene, "activeScene": activeScene,
+ "locked": _generalHelper.isLocked(obj), "hidden": _generalHelper.isHidden(obj)});
+
+ cameraGizmos[cameraGizmos.length] = gizmo;
+ gizmo.clicked.connect(handleObjectClicked);
+ gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;});
+ gizmo.activeScene = Qt.binding(function() {return activeScene;});
+ frustum.viewPortRect = Qt.binding(function() {return viewPortRect;});
+ gizmo.connectFrustum(frustum);
+ }
+ }
+
+ function releaseLightGizmo(obj)
+ {
+ for (var i = 0; i < lightIconGizmos.length; ++i) {
+ if (lightIconGizmos[i].targetNode === obj) {
+ lightIconGizmos[i].scene = null;
+ lightIconGizmos[i].targetNode = null;
+ _generalHelper.unregisterGizmoTarget(obj);
+ return;
+ }
+ }
+ }
+
+ function releaseCameraGizmo(obj)
+ {
+ for (var i = 0; i < cameraGizmos.length; ++i) {
+ if (cameraGizmos[i].targetNode === obj) {
+ cameraGizmos[i].scene = null;
+ cameraGizmos[i].targetNode = null;
+ _generalHelper.unregisterGizmoTarget(obj);
+ return;
+ }
+ }
+ }
+
+ function updateLightGizmoScene(scene, obj)
+ {
+ for (var i = 0; i < lightIconGizmos.length; ++i) {
+ if (lightIconGizmos[i].targetNode === obj) {
+ lightIconGizmos[i].scene = scene;
+ return;
+ }
+ }
+ }
+
+ function updateCameraGizmoScene(scene, obj)
+ {
+ for (var i = 0; i < cameraGizmos.length; ++i) {
+ if (cameraGizmos[i].targetNode === obj) {
+ cameraGizmos[i].scene = scene;
+ return;
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ createEditView();
+ selectObjects([]);
+ // Work-around the fact that the projection matrix for the camera is not calculated until
+ // the first frame is rendered, so any initial calls to mapFrom3DScene() will fail.
+ _generalHelper.requestOverlayUpdate();
+ }
+
+ onWidthChanged: _generalHelper.requestOverlayUpdate()
+ onHeightChanged: _generalHelper.requestOverlayUpdate()
+
+ Connections {
+ target: _generalHelper
+ function onLockedStateChanged(node)
+ {
+ for (var i = 0; i < cameraGizmos.length; ++i) {
+ if (cameraGizmos[i].targetNode === node) {
+ cameraGizmos[i].locked = _generalHelper.isLocked(node);
+ return;
+ }
+ }
+ for (var i = 0; i < lightIconGizmos.length; ++i) {
+ if (lightIconGizmos[i].targetNode === node) {
+ lightIconGizmos[i].locked = _generalHelper.isLocked(node);
+ return;
+ }
+ }
+ }
+ function onHiddenStateChanged(node)
+ {
+ for (var i = 0; i < cameraGizmos.length; ++i) {
+ if (cameraGizmos[i].targetNode === node) {
+ cameraGizmos[i].hidden = _generalHelper.isHidden(node);
+ return;
+ }
+ }
+ for (var i = 0; i < lightIconGizmos.length; ++i) {
+ if (lightIconGizmos[i].targetNode === node) {
+ lightIconGizmos[i].hidden = _generalHelper.isHidden(node);
+ return;
+ }
+ }
+ }
+ }
+
+ Node {
+ id: overlayScene
+
+ PerspectiveCamera {
+ id: overlayPerspectiveCamera
+ clipFar: viewRoot.editView ? viewRoot.editView.perspectiveCamera.clipFar : 1000
+ clipNear: viewRoot.editView ? viewRoot.editView.perspectiveCamera.clipNear : 1
+ position: viewRoot.editView ? viewRoot.editView.perspectiveCamera.position : Qt.vector3d(0, 0, 0)
+ rotation: viewRoot.editView ? viewRoot.editView.perspectiveCamera.rotation : Qt.quaternion(1, 0, 0, 0)
+ }
+
+ OrthographicCamera {
+ id: overlayOrthoCamera
+ clipFar: viewRoot.editView ? viewRoot.editView.orthoCamera.clipFar : 1000
+ clipNear: viewRoot.editView ? viewRoot.editView.orthoCamera.clipNear : 1
+ position: viewRoot.editView ? viewRoot.editView.orthoCamera.position : Qt.vector3d(0, 0, 0)
+ rotation: viewRoot.editView ? viewRoot.editView.orthoCamera.rotation : Qt.quaternion(1, 0, 0, 0)
+ scale: viewRoot.editView ? viewRoot.editView.orthoCamera.scale : Qt.vector3d(0, 0, 0)
+ }
+
+ MouseArea3D {
+ id: gizmoDragHelper
+ view3D: overlayView
+ }
+
+ Node {
+ id: multiSelectionNode
+ objectName: "multiSelectionNode"
+ }
+
+ MoveGizmo {
+ id: moveGizmo
+ scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
+ highlightOnHover: true
+ targetNode: viewRoot.selectedNode
+ globalOrientation: viewRoot.globalOrientation
+ visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Move
+ view3D: overlayView
+ dragHelper: gizmoDragHelper
+ property var propertyNames: ["position"]
+
+ onPositionCommit: {
+ if (targetNode == multiSelectionNode)
+ viewRoot.commitObjectProperty(_generalHelper.multiSelectionTargets(), propertyNames);
+ else
+ viewRoot.commitObjectProperty([viewRoot.selectedNode], propertyNames);
+ }
+ onPositionMove: {
+ if (targetNode == multiSelectionNode)
+ viewRoot.changeObjectProperty(_generalHelper.multiSelectionTargets(), propertyNames);
+ else
+ viewRoot.changeObjectProperty([viewRoot.selectedNode], propertyNames);
+ }
+ }
+
+ ScaleGizmo {
+ id: scaleGizmo
+ scale: autoScale.getScale(Qt.vector3d(5, 5, 5))
+ highlightOnHover: true
+ targetNode: viewRoot.selectedNode
+ visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Scale
+ view3D: overlayView
+ dragHelper: gizmoDragHelper
+ property var propertyNames: ["scale"]
+ property var propertyNamesMulti: ["position", "scale"]
+
+ onScaleCommit: {
+ if (targetNode == multiSelectionNode)
+ viewRoot.commitObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
+ else
+ viewRoot.commitObjectProperty([viewRoot.selectedNode], propertyNames);
+ }
+ onScaleChange: {
+ if (targetNode == multiSelectionNode)
+ viewRoot.changeObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
+ else
+ viewRoot.changeObjectProperty([viewRoot.selectedNode], propertyNames);
+ }
+ }
+
+ RotateGizmo {
+ id: rotateGizmo
+ scale: autoScale.getScale(Qt.vector3d(7, 7, 7))
+ highlightOnHover: true
+ targetNode: viewRoot.selectedNode
+ globalOrientation: viewRoot.globalOrientation
+ visible: viewRoot.selectedNode && transformMode === EditView3D.TransformMode.Rotate
+ view3D: overlayView
+ dragHelper: gizmoDragHelper
+ property var propertyNames: ["eulerRotation"]
+ property var propertyNamesMulti: ["position", "eulerRotation"]
+
+ onRotateCommit: {
+ if (targetNode == multiSelectionNode)
+ viewRoot.commitObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
+ else
+ viewRoot.commitObjectProperty([viewRoot.selectedNode], propertyNames);
+ }
+ onRotateChange: {
+ if (targetNode == multiSelectionNode)
+ viewRoot.changeObjectProperty(_generalHelper.multiSelectionTargets(), propertyNamesMulti);
+ else
+ viewRoot.changeObjectProperty([viewRoot.selectedNode], propertyNames);
+ }
+ }
+
+ LightGizmo {
+ id: lightGizmo
+ targetNode: viewRoot.selectedNode != multiSelectionNode ? viewRoot.selectedNode : null
+ view3D: overlayView
+ dragHelper: gizmoDragHelper
+
+ onPropertyValueCommit: (propName)=> {
+ viewRoot.commitObjectProperty([targetNode], [propName]);
+ }
+ onPropertyValueChange: (propName)=> {
+ viewRoot.changeObjectProperty([targetNode], [propName]);
+ }
+ }
+
+ AutoScaleHelper {
+ id: autoScale
+ view3D: overlayView
+ position: moveGizmo.scenePosition
+ }
+
+ AutoScaleHelper {
+ id: pivotAutoScale
+ view3D: overlayView
+ position: pivotLine.startPos
+ }
+
+ Line3D {
+ id: pivotLine
+ visible: viewRoot.selectedNode && viewRoot.selectedNode != multiSelectionNode
+ name: "3D Edit View Pivot Line"
+ color: "#ddd600"
+
+ startPos: viewRoot.selectedNode ? viewRoot.selectedNode.scenePosition
+ : Qt.vector3d(0, 0, 0)
+ Connections {
+ target: viewRoot
+ function onSelectedNodeChanged()
+ {
+ pivotLine.endPos = gizmoDragHelper.pivotScenePosition(viewRoot.selectedNode);
+ }
+ }
+ Connections {
+ target: viewRoot.selectedNode
+ function onSceneTransformChanged()
+ {
+ pivotLine.endPos = gizmoDragHelper.pivotScenePosition(viewRoot.selectedNode);
+ }
+ }
+
+ Model {
+ id: pivotCap
+ source: "#Sphere"
+ scale: pivotAutoScale.getScale(Qt.vector3d(0.03, 0.03, 0.03))
+ position: pivotLine.startPos
+ materials: [
+ DefaultMaterial {
+ id: lineMat
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ diffuseColor: pivotLine.color
+ }
+ ]
+ }
+ }
+ }
+
+ Item {
+ id: contentItem
+ anchors.fill: parent
+
+ Rectangle {
+ id: viewRect
+ anchors.fill: parent
+
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "#222222" }
+ GradientStop { position: 0.0; color: "#999999" }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton
+ hoverEnabled: false
+
+ property MouseArea3D freeDraggerArea
+ property point pressPoint
+ property bool initialMoveBlock: false
+
+ onPressed: (mouse)=> {
+ if (viewRoot.editView) {
+ var pickResult = viewRoot.editView.pick(mouse.x, mouse.y);
+ handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit),
+ mouse.modifiers & Qt.ControlModifier);
+
+ if (pickResult.objectHit) {
+ if (transformMode === EditView3D.TransformMode.Move)
+ freeDraggerArea = moveGizmo.freeDraggerArea;
+ else if (transformMode === EditView3D.TransformMode.Rotate)
+ freeDraggerArea = rotateGizmo.freeDraggerArea;
+ else if (transformMode === EditView3D.TransformMode.Scale)
+ freeDraggerArea = scaleGizmo.freeDraggerArea;
+ pressPoint.x = mouse.x;
+ pressPoint.y = mouse.y;
+ initialMoveBlock = true;
+ } else {
+ mouse.accepted = false;
+ }
+ }
+ }
+ onPositionChanged: (mouse)=> {
+ if (freeDraggerArea) {
+ if (initialMoveBlock && Math.abs(pressPoint.x - mouse.x) + Math.abs(pressPoint.y - mouse.y) > 10) {
+ // Don't force press event at actual press, as that puts the gizmo
+ // in free-dragging state, which is bad UX if drag is not actually done
+ freeDraggerArea.forcePressEvent(pressPoint.x, pressPoint.y);
+ freeDraggerArea.forceMoveEvent(mouse.x, mouse.y);
+ initialMoveBlock = false;
+ } else {
+ freeDraggerArea.forceMoveEvent(mouse.x, mouse.y);
+ }
+ }
+ }
+
+ function handleRelease(mouse)
+ {
+ if (freeDraggerArea) {
+ if (initialMoveBlock)
+ freeDraggerArea.forceReleaseEvent(pressPoint.x, pressPoint.y);
+ else
+ freeDraggerArea.forceReleaseEvent(mouse.x, mouse.y);
+ freeDraggerArea = null;
+ }
+ }
+
+ onReleased: (mouse)=> {
+ handleRelease(mouse);
+ }
+ onCanceled: (mouse)=> {
+ handleRelease(mouse);
+ }
+ }
+
+ DropArea {
+ anchors.fill: parent
+ }
+
+ View3D {
+ id: overlayView
+ anchors.fill: parent
+ camera: viewRoot.usePerspective ? overlayPerspectiveCamera : overlayOrthoCamera
+ importScene: overlayScene
+ z: 2
+ }
+
+ Overlay2D {
+ id: gizmoLabel
+ targetNode: moveGizmo.visible ? moveGizmo : scaleGizmo
+ targetView: overlayView
+ visible: targetNode.dragging
+ z: 3
+
+ Rectangle {
+ color: "white"
+ x: -width / 2
+ y: -height - 8
+ width: gizmoLabelText.width + 4
+ height: gizmoLabelText.height + 4
+ border.width: 1
+ Text {
+ id: gizmoLabelText
+ text: {
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (shuttingDown)
+ return text;
+ var l = Qt.locale();
+ var targetProperty;
+ if (viewRoot.selectedNode) {
+ if (gizmoLabel.targetNode === moveGizmo)
+ targetProperty = viewRoot.selectedNode.position;
+ else
+ targetProperty = viewRoot.selectedNode.scale;
+ return qsTr("x:") + Number(targetProperty.x).toLocaleString(l, 'f', 1)
+ + qsTr(" y:") + Number(targetProperty.y).toLocaleString(l, 'f', 1)
+ + qsTr(" z:") + Number(targetProperty.z).toLocaleString(l, 'f', 1);
+ } else {
+ return "";
+ }
+ }
+ anchors.centerIn: parent
+ }
+ }
+ }
+
+ Rectangle {
+ id: rotateGizmoLabel
+ color: "white"
+ x: rotateGizmo.currentMousePos.x - (10 + width)
+ y: rotateGizmo.currentMousePos.y - (10 + height)
+ width: rotateGizmoLabelText.width + 4
+ height: rotateGizmoLabelText.height + 4
+ border.width: 1
+ visible: rotateGizmo.dragging
+ parent: rotateGizmo.view3D
+ z: 3
+
+ Text {
+ id: rotateGizmoLabelText
+ text: {
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (shuttingDown)
+ return text;
+ var l = Qt.locale();
+ if (rotateGizmo.targetNode) {
+ var degrees = rotateGizmo.currentAngle * (180 / Math.PI);
+ return Number(degrees).toLocaleString(l, 'f', 1);
+ } else {
+ return "";
+ }
+ }
+ anchors.centerIn: parent
+ }
+ }
+
+ Rectangle {
+ id: lightGizmoLabel
+ color: "white"
+ x: lightGizmo.currentMousePos.x - (10 + width)
+ y: lightGizmo.currentMousePos.y - (10 + height)
+ width: lightGizmoLabelText.width + 4
+ height: lightGizmoLabelText.height + 4
+ border.width: 1
+ visible: lightGizmo.dragging
+ parent: lightGizmo.view3D
+ z: 3
+
+ Text {
+ id: lightGizmoLabelText
+ text: lightGizmo.currentLabel
+ anchors.centerIn: parent
+ }
+ }
+
+ EditCameraController {
+ id: cameraControl
+ camera: viewRoot.editView ? viewRoot.editView.camera : null
+ anchors.fill: parent
+ view3d: viewRoot.editView
+ sceneId: viewRoot.sceneId
+ }
+ }
+
+ AxisHelper {
+ anchors.right: parent.right
+ anchors.top: parent.top
+ width: 100
+ height: width
+ editCameraCtrl: cameraControl
+ selectedNode: viewRoot.selectedNodes.length === 1 ? viewRoot.selectionBoxes[0].model
+ : viewRoot.selectedNode
+ }
+
+ Text {
+ id: sceneLabel
+ text: viewRoot.sceneId
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.margins: 4
+ font.pixelSize: 14
+ color: "white"
+ }
+
+ Text {
+ id: fpsLabel
+ text: viewRoot.fps
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.margins: 4
+ font.pixelSize: 12
+ color: "white"
+ visible: viewRoot.fps > 0
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/FadeHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/FadeHandle.qml
new file mode 100644
index 00000000000..c50406c147f
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/FadeHandle.qml
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+DirectionalDraggable {
+ id: handleRoot
+
+ property string currentLabel
+ property point currentMousePos
+ property real fadeScale
+ property real baseScale: 5
+ property real dragScale: 1
+
+ scale: autoScaler.getScale(Qt.vector3d(baseScale, baseScale, baseScale))
+ length: 3
+ offset: -1.5
+
+ Model {
+ id: handle
+ source: "#Sphere"
+ materials: [ handleRoot.material ]
+ scale: Qt.vector3d(0.02, 0.02, 0.02)
+ }
+
+ AutoScaleHelper {
+ id: autoScaler
+ active: handleRoot.active
+ view3D: handleRoot.view3D
+ }
+
+ property real _q // quadratic fade
+ property real _l // linear fade
+ property real _c // constant fade
+ property real _d: 20 // Divisor from fadeScale calc in lightGizmo
+ property real _startScale
+ property real _startFadeScale
+ property string _currentProp
+
+ signal valueCommit(string propName)
+ signal valueChange(string propName)
+
+ function updateFade(relativeDistance, screenPos)
+ {
+ // Solved from fadeScale equation in LightGizmo
+ var newValue = 0;
+ var _x = Math.max(0, (_startFadeScale - (relativeDistance * _startScale)) / 100);
+
+ // Fades capped to range 0-10 because property editor caps them to that range
+ if (_currentProp === "quadraticFade") {
+ if (_x === 0)
+ newValue = 10;
+ else
+ newValue = Math.max(0, Math.min(10, -(_c - _d + (_l * _x)) / (_x * _x)));
+ if (newValue < 0.01)
+ newValue = 0; // To avoid having tiny positive value when UI shows 0.00
+ targetNode.quadraticFade = newValue;
+ } else if (_currentProp === "linearFade") {
+ if (_x === 0)
+ newValue = 10;
+ else
+ newValue = Math.max(0, Math.min(10, -(_c - _d) / _x));
+ if (newValue < 0.01)
+ newValue = 0; // To avoid having tiny positive value when UI shows 0.00
+ targetNode.linearFade = newValue;
+ } else {
+ // Since pure constant fade equates to infinitely long cone, fadeScale calc assumes
+ // linear fade of one in this case.
+ newValue = Math.max(0, Math.min(10, _d - _x));
+ targetNode.constantFade = newValue;
+ }
+
+ var l = Qt.locale();
+ handleRoot.currentLabel = _currentProp + qsTr(": ") + Number(newValue).toLocaleString(l, 'f', 2);
+ handleRoot.currentMousePos = screenPos;
+ }
+
+ onPressed: (mouseArea, screenPos)=> {
+ _startScale = autoScaler.relativeScale * baseScale * dragScale;
+ _startFadeScale = fadeScale;
+ _l = targetNode.linearFade;
+ _c = targetNode.constantFade;
+ _q = targetNode.quadraticFade;
+ if (targetNode.quadraticFade === 0) {
+ if (targetNode.linearFade === 0) {
+ _currentProp = "constantFade";
+ } else {
+ _currentProp = "linearFade";
+ }
+ } else {
+ _currentProp = "quadraticFade";
+ }
+ updateFade(0, screenPos);
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateFade(relativeDistance, screenPos);
+ handleRoot.valueChange(_currentProp);
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateFade(relativeDistance, screenPos);
+ handleRoot.valueCommit(_currentProp);
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/HelperGrid.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/HelperGrid.qml
new file mode 100644
index 00000000000..b7807d8192f
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/HelperGrid.qml
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import GridGeometry 1.0
+
+Node {
+ id: grid
+
+ property alias lines: gridGeometry.lines
+ property alias step: gridGeometry.step
+ property alias subdivAlpha: subGridMaterial.opacity
+
+ eulerRotation.x: 90
+
+ // Note: Only one instance of HelperGrid is supported, as the geometry names are fixed
+
+ Model { // Main grid lines
+ geometry: GridGeometry {
+ id: gridGeometry
+ name: "3D Edit View Helper Grid"
+ }
+
+ materials: [
+ DefaultMaterial {
+ id: mainGridMaterial
+ diffuseColor: "#aaaaaa"
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+ }
+
+ Model { // Subdivision lines
+ geometry: GridGeometry {
+ lines: gridGeometry.lines
+ step: gridGeometry.step
+ isSubdivision: true
+ name: "3D Edit View Helper Grid subdivisions"
+ }
+
+ materials: [
+ DefaultMaterial {
+ id: subGridMaterial
+ diffuseColor: mainGridMaterial.diffuseColor
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+ }
+
+ Model { // Z Axis
+ geometry: GridGeometry {
+ lines: gridGeometry.lines
+ step: gridGeometry.step
+ isCenterLine: true
+ name: "3D Edit View Helper Grid Z Axis"
+ }
+ materials: [
+ DefaultMaterial {
+ id: vCenterLineMaterial
+ diffuseColor: "#00a1d2"
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+ }
+ Model { // X Axis
+ eulerRotation.z: 90
+ geometry: GridGeometry {
+ lines: gridGeometry.lines
+ step: gridGeometry.step
+ isCenterLine: true
+ name: "3D Edit View Helper Grid X Axis"
+ }
+ materials: [
+ DefaultMaterial {
+ id: hCenterLineMaterial
+ diffuseColor: "#cb211a"
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml
new file mode 100644
index 00000000000..03087b658a9
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconGizmo.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+Item {
+ id: iconGizmo
+
+ property Node activeScene: null
+ property Node scene: null
+ property View3D view3D
+ property bool highlightOnHover: true
+ property Node targetNode: null
+ property var selectedNodes: []
+ readonly property bool selected: {
+ for (var i = 0; i < selectedNodes.length; ++i) {
+ if (selectedNodes[i] === targetNode)
+ return true;
+ }
+ return false;
+ }
+ property bool hasMouse: false
+ property bool hidden: false
+ property bool locked: false
+
+ property alias iconSource: iconImage.source
+
+ signal clicked(Node node, bool multi)
+
+ onSelectedChanged: {
+ if (selected)
+ hasMouse = false;
+ }
+
+ visible: activeScene === scene && !hidden && (targetNode ? targetNode.visible : false)
+
+ Overlay2D {
+ id: iconOverlay
+ targetNode: iconGizmo.targetNode
+ targetView: view3D
+ visible: iconGizmo.visible && !isBehindCamera
+
+ Rectangle {
+ id: iconRect
+
+ width: iconImage.width
+ height: iconImage.height
+ x: -width / 2
+ y: -height / 2
+ color: "transparent"
+ border.color: "#7777ff"
+ border.width: !iconGizmo.locked && iconGizmo.highlightOnHover && iconGizmo.hasMouse ? 2 : 0
+ radius: 5
+ opacity: iconGizmo.selected ? 0.2 : 1
+ Image {
+ id: iconImage
+ fillMode: Image.Pad
+ MouseArea {
+ id: iconMouseArea
+ anchors.fill: parent
+ onPressed: (mouse)=> {
+ // Ignore singleselection mouse presses when we have single object selected
+ // so that the icon gizmo doesn't hijack mouse clicks meant for other gizmos
+ if (iconGizmo.selected && !(mouse.modifiers & Qt.ControlModifier)
+ && selectedNodes.length === 1) {
+ mouse.accepted = false;
+ }
+ }
+
+ onClicked: (mouse)=> {
+ iconGizmo.clicked(iconGizmo.targetNode,
+ mouse.modifiers & Qt.ControlModifier);
+ }
+ hoverEnabled: iconGizmo.highlightOnHover && !iconGizmo.selected
+ acceptedButtons: Qt.LeftButton
+
+ // onPositionChanged, onContainsMouseAreaChanged, and hasMouse are used instead
+ // of just using containsMouse directly, because containsMouse
+ // cannot be relied upon to update correctly in some situations.
+ // This is likely because the overlapping 3D mouse areas of the gizmos get
+ // the mouse events instead of this area, so mouse leaving the area
+ // doesn't always update containsMouse property.
+ onPositionChanged: {
+ if (!iconGizmo.selected)
+ iconGizmo.hasMouse = containsMouse;
+ }
+
+ onContainsMouseChanged: {
+ if (!iconGizmo.selected)
+ iconGizmo.hasMouse = containsMouse;
+ else
+ iconGizmo.hasMouse = false;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconRenderer3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconRenderer3D.qml
new file mode 100644
index 00000000000..623bf21cdec
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/IconRenderer3D.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+Item {
+ id: viewRoot
+ width: 1024
+ height: 1024
+ visible: true
+
+ property alias view3D: view3D
+ property alias camPos: viewCamera.position
+
+ function setSceneToBox()
+ {
+ selectionBox.targetNode = view3D.importScene;
+ }
+
+ function fitAndHideBox()
+ {
+ cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true, true);
+ if (cameraControl._zoomFactor < 0.1)
+ view3D.importScene.scale = view3D.importScene.scale.times(10);
+ if (cameraControl._zoomFactor > 10)
+ view3D.importScene.scale = view3D.importScene.scale.times(0.1);
+
+ selectionBox.visible = false;
+ }
+
+ View3D {
+ id: view3D
+ camera: viewCamera
+ environment: sceneEnv
+
+ SceneEnvironment {
+ id: sceneEnv
+ antialiasingMode: SceneEnvironment.MSAA
+ antialiasingQuality: SceneEnvironment.VeryHigh
+ }
+
+ PerspectiveCamera {
+ id: viewCamera
+ position: Qt.vector3d(-200, 200, 200)
+ eulerRotation: Qt.vector3d(-45, -45, 0)
+ }
+
+ DirectionalLight {
+ rotation: viewCamera.rotation
+ }
+
+ SelectionBox {
+ id: selectionBox
+ view3D: view3D
+ geometryName: "SB"
+ }
+
+ EditCameraController {
+ id: cameraControl
+ camera: view3D.camera
+ view3d: view3D
+ ignoreToolState: true
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightGizmo.qml
new file mode 100644
index 00000000000..32f047cff68
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightGizmo.qml
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+import LightUtils 1.0
+
+Node {
+ id: lightGizmo
+
+ property View3D view3D
+ property Node targetNode: null
+ property MouseArea3D dragHelper: null
+ property color color: Qt.rgba(1, 1, 0, 1)
+ property real fadeScale: {
+ // Value indicates area where intensity is above certain percent of total brightness.
+ if (lightGizmo.targetNode instanceof SpotLight || lightGizmo.targetNode instanceof PointLight) {
+ var l = targetNode.linearFade;
+ var q = targetNode.quadraticFade;
+ var c = targetNode.constantFade;
+ var d = 20; // divisor to target intensity value. E.g. 20 = 1/20 = 5%
+ if (l === 0 && q === 0)
+ l = 1; // For pure constant fade, cone would be infinite, so pretend we have linear fade
+ // Solved from equation in shader:
+ // 1 / d = 1 / (c + (l + q * dist) * dist);
+ if (q === 0)
+ return 100 * Math.max(((d - c) / l), 1);
+ else
+ return 100 * ((Math.sqrt(4 * q * (d - c) + (l * l)) - l) / (2 * q));
+ } else {
+ return 100;
+ }
+ }
+ readonly property bool dragging: primaryArrow.dragging
+ || spotLightHandle.dragging
+ || spotLightInnerHandle.dragging
+ || spotLightFadeHandle.dragging
+ || areaHeightHandle.dragging
+ || areaWidthHandle.dragging
+ || pointLightFadeHandle.dragging
+ property point currentMousePos
+ property string currentLabel
+ property int brightnessDecimals: _generalHelper.brightnessScaler() > 10. ? 0 : 2;
+ property real brightnessMultiplier: Math.pow(10, brightnessDecimals);
+
+ signal propertyValueCommit(string propName)
+ signal propertyValueChange(string propName)
+
+ position: targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0)
+ visible: lightGizmo.targetNode instanceof SpotLight
+ || lightGizmo.targetNode instanceof AreaLight
+ || lightGizmo.targetNode instanceof DirectionalLight
+ || lightGizmo.targetNode instanceof PointLight
+
+ AutoScaleHelper {
+ id: autoScaler
+ view3D: lightGizmo.view3D
+ }
+
+ Node {
+ id: pointLightParts
+ rotation: lightGizmo.view3D.camera.rotation
+ visible: lightGizmo.targetNode instanceof PointLight
+
+ LightModel {
+ id: pointModel
+ geometryName: "Edit 3D PointLight"
+ geometryType: LightGeometry.Point
+ material: lightMaterial
+ scale: Qt.vector3d(lightGizmo.fadeScale, lightGizmo.fadeScale, lightGizmo.fadeScale)
+ }
+
+ FadeHandle {
+ id: pointLightFadeHandle
+ view3D: lightGizmo.view3D
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ position: lightGizmo.targetNode instanceof PointLight ? Qt.vector3d(-pointModel.scale.x, 0, 0)
+ : Qt.vector3d(0, 0, 0)
+ eulerRotation: Qt.vector3d(0, 0, -90)
+ targetNode: lightGizmo.targetNode instanceof PointLight ? lightGizmo.targetNode : null
+ active: lightGizmo.targetNode instanceof PointLight
+ dragHelper: lightGizmo.dragHelper
+ fadeScale: lightGizmo.fadeScale
+
+ onCurrentMousePosChanged: {
+ lightGizmo.currentMousePos = currentMousePos;
+ lightGizmo.currentLabel = currentLabel;
+ }
+ onValueChange: (propName)=> {
+ lightGizmo.propertyValueChange(propName);
+ }
+ onValueCommit: (propName)=> {
+ lightGizmo.propertyValueCommit(propName);
+ }
+ }
+ }
+
+
+ Node {
+ rotation: !lightGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
+ : lightGizmo.targetNode.sceneRotation
+
+ Node {
+ id: spotParts
+ visible: lightGizmo.targetNode instanceof SpotLight
+
+ LightModel {
+ id: spotModel
+
+ property real coneXYScale: spotParts.visible && lightGizmo.targetNode
+ ? lightGizmo.fadeScale * Math.tan(Math.PI * lightGizmo.targetNode.coneAngle / 180)
+ : 1
+
+ geometryName: "Edit 3D SpotLight Cone"
+ geometryType: LightGeometry.Spot
+ material: lightMaterial
+ scale: Qt.vector3d(coneXYScale, coneXYScale,
+ spotParts.visible && lightGizmo.targetNode && lightGizmo.targetNode.coneAngle > 90
+ ? -lightGizmo.fadeScale : lightGizmo.fadeScale)
+ }
+
+ LightModel {
+ id: spotInnerModel
+
+ property real coneXYScale: spotParts.visible && lightGizmo.targetNode
+ ? lightGizmo.fadeScale * Math.tan(Math.PI * lightGizmo.targetNode.innerConeAngle / 180)
+ : 1
+
+ geometryName: "Edit 3D SpotLight Inner Cone"
+ geometryType: LightGeometry.Spot
+ material: lightMaterial
+ scale: Qt.vector3d(coneXYScale, coneXYScale,
+ spotParts.visible && lightGizmo.targetNode && lightGizmo.targetNode.innerConeAngle > 90
+ ? -lightGizmo.fadeScale : lightGizmo.fadeScale)
+ }
+
+ SpotLightHandle {
+ id: spotLightHandle
+ view3D: lightGizmo.view3D
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ position: lightGizmo.targetNode instanceof SpotLight ? Qt.vector3d(0, spotModel.scale.y, -spotModel.scale.z)
+ : Qt.vector3d(0, 0, 0)
+ targetNode: lightGizmo.targetNode instanceof SpotLight ? lightGizmo.targetNode : null
+ active: lightGizmo.targetNode instanceof SpotLight
+ dragHelper: lightGizmo.dragHelper
+ propName: "coneAngle"
+ propValue: lightGizmo.targetNode instanceof SpotLight ? targetNode.coneAngle : 0
+
+ onNewValueChanged: targetNode.coneAngle = newValue
+ onCurrentMousePosChanged: {
+ lightGizmo.currentMousePos = currentMousePos;
+ lightGizmo.currentLabel = currentLabel;
+ }
+ onValueChange: lightGizmo.propertyValueChange(propName)
+ onValueCommit: {
+ if (targetNode.innerConeAngle > targetNode.coneAngle)
+ targetNode.innerConeAngle = targetNode.coneAngle;
+ lightGizmo.propertyValueCommit(propName)
+ lightGizmo.propertyValueCommit(spotLightInnerHandle.propName);
+ }
+ }
+
+ SpotLightHandle {
+ id: spotLightInnerHandle
+ view3D: lightGizmo.view3D
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ position: lightGizmo.targetNode instanceof SpotLight ? Qt.vector3d(0, -spotInnerModel.scale.y, -spotInnerModel.scale.z)
+ : Qt.vector3d(0, 0, 0)
+ eulerRotation: Qt.vector3d(180, 0, 0)
+ targetNode: lightGizmo.targetNode instanceof SpotLight ? lightGizmo.targetNode : null
+ active: lightGizmo.targetNode instanceof SpotLight
+ dragHelper: lightGizmo.dragHelper
+ propName: "innerConeAngle"
+ propValue: lightGizmo.targetNode instanceof SpotLight ? targetNode.innerConeAngle : 0
+
+ onNewValueChanged: targetNode.innerConeAngle = newValue
+ onCurrentMousePosChanged: {
+ lightGizmo.currentMousePos = currentMousePos;
+ lightGizmo.currentLabel = currentLabel;
+ }
+ onValueChange: lightGizmo.propertyValueChange(propName)
+ onValueCommit: {
+ if (targetNode.coneAngle < targetNode.innerConeAngle)
+ targetNode.coneAngle = targetNode.innerConeAngle;
+ lightGizmo.propertyValueCommit(propName)
+ lightGizmo.propertyValueCommit(spotLightHandle.propName);
+ }
+ }
+
+ FadeHandle {
+ id: spotLightFadeHandle
+ view3D: lightGizmo.view3D
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ position: lightGizmo.targetNode instanceof SpotLight ? Qt.vector3d(spotModel.scale.x / 2, 0, -spotInnerModel.scale.z / 2)
+ : Qt.vector3d(0, 0, 0)
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ targetNode: lightGizmo.targetNode instanceof SpotLight ? lightGizmo.targetNode : null
+ active: lightGizmo.targetNode instanceof SpotLight
+ dragHelper: lightGizmo.dragHelper
+ fadeScale: lightGizmo.fadeScale
+ dragScale: 2
+
+ onCurrentMousePosChanged: {
+ lightGizmo.currentMousePos = currentMousePos;
+ lightGizmo.currentLabel = currentLabel;
+ }
+ onValueChange: (propName)=> {
+ lightGizmo.propertyValueChange(propName);
+ }
+ onValueCommit: (propName)=> {
+ lightGizmo.propertyValueCommit(propName);
+ }
+ }
+ }
+ Node {
+ id: areaParts
+ visible: lightGizmo.targetNode instanceof AreaLight
+
+ LightModel {
+ id: areaModel
+ geometryName: "Edit 3D AreaLight"
+ geometryType: LightGeometry.Area
+ material: lightMaterial
+ scale: areaParts.visible ? Qt.vector3d(lightGizmo.targetNode.width / 2,
+ lightGizmo.targetNode.height / 2, 1)
+ .times(lightGizmo.targetNode.scale)
+ : Qt.vector3d(1, 1, 1)
+ }
+
+ AreaLightHandle {
+ id: areaWidthHandle
+ view3D: lightGizmo.view3D
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ position: lightGizmo.targetNode instanceof AreaLight ? Qt.vector3d(-areaModel.scale.x, 0, 0)
+ : Qt.vector3d(0, 0, 0)
+ eulerRotation: Qt.vector3d(0, 0, 90)
+ targetNode: lightGizmo.targetNode instanceof AreaLight ? lightGizmo.targetNode : null
+ active: lightGizmo.targetNode instanceof AreaLight
+ dragHelper: lightGizmo.dragHelper
+ propName: "width"
+ propValue: lightGizmo.targetNode instanceof AreaLight ? targetNode.width : 0
+
+ onNewValueChanged: targetNode.width = newValue
+ onCurrentMousePosChanged: {
+ lightGizmo.currentMousePos = currentMousePos;
+ lightGizmo.currentLabel = currentLabel;
+ }
+ onValueChange: lightGizmo.propertyValueChange(propName)
+ onValueCommit: lightGizmo.propertyValueCommit(propName)
+ }
+
+ AreaLightHandle {
+ id: areaHeightHandle
+ view3D: lightGizmo.view3D
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ position: lightGizmo.targetNode instanceof AreaLight ? Qt.vector3d(0, -areaModel.scale.y, 0)
+ : Qt.vector3d(0, 0, 0)
+ eulerRotation: Qt.vector3d(0, 0, 180)
+ targetNode: lightGizmo.targetNode instanceof AreaLight ? lightGizmo.targetNode : null
+ active: lightGizmo.targetNode instanceof AreaLight
+ dragHelper: lightGizmo.dragHelper
+ propName: "height"
+ propValue: lightGizmo.targetNode instanceof AreaLight ? targetNode.height : 0
+
+ onNewValueChanged: targetNode.height = newValue
+ onCurrentMousePosChanged: {
+ lightGizmo.currentMousePos = currentMousePos;
+ lightGizmo.currentLabel = currentLabel;
+ }
+ onValueChange: lightGizmo.propertyValueChange(propName)
+ onValueCommit: lightGizmo.propertyValueCommit(propName)
+ }
+ }
+
+ LightModel {
+ id: directionalModel
+ geometryName: "Edit 3D DirLight"
+ geometryType: LightGeometry.Directional
+ material: lightMaterial
+ visible: lightGizmo.targetNode instanceof DirectionalLight
+ scale: autoScaler.getScale(Qt.vector3d(50, 50, 50))
+ }
+
+ AdjustableArrow {
+ id: primaryArrow
+ eulerRotation: Qt.vector3d(-90, 0, 0)
+ targetNode: lightGizmo.targetNode
+ color: (hovering || dragging) ? Qt.rgba(1, 1, 1, 1) : lightGizmo.color
+ view3D: lightGizmo.view3D
+ active: lightGizmo.visible
+ dragHelper: lightGizmo.dragHelper
+ scale: autoScaler.getScale(Qt.vector3d(5, 5, 5))
+ length: targetNode ? Math.max(1.0, 1.0 + targetNode.brightness / _generalHelper.brightnessScaler() * 10.0) + 3 : 10
+
+ property real _startBrightness
+
+ function updateBrightness(relativeDistance, screenPos)
+ {
+ var currentValue = Math.max(0, (_startBrightness + relativeDistance * _generalHelper.brightnessScaler() / 10.0));
+ currentValue *= brightnessMultiplier;
+ currentValue = Math.round(currentValue);
+ currentValue /= brightnessMultiplier;
+
+ var l = Qt.locale();
+ lightGizmo.currentLabel = "brightness" + qsTr(": ") + Number(currentValue).toLocaleString(l, 'f', brightnessDecimals);
+ lightGizmo.currentMousePos = screenPos;
+ targetNode.brightness = currentValue;
+ }
+
+ onPressed: (mouseArea, screenPos)=> {
+ _startBrightness = targetNode.brightness;
+ updateBrightness(0, screenPos);
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateBrightness(relativeDistance, screenPos);
+ lightGizmo.propertyValueChange("brightness");
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateBrightness(relativeDistance, screenPos);
+ lightGizmo.propertyValueCommit("brightness");
+ }
+ }
+
+ DefaultMaterial {
+ id: lightMaterial
+ diffuseColor: lightGizmo.color
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightIconGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightIconGizmo.qml
new file mode 100644
index 00000000000..b7bb272b630
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightIconGizmo.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import LightUtils 1.0
+
+IconGizmo {
+ id: lightIconGizmo
+
+ property color overlayColor: targetNode ? targetNode.color : "transparent"
+
+ iconSource: targetNode
+ ? targetNode instanceof DirectionalLight
+ ? "image://IconGizmoImageProvider/directional.png:" + overlayColor
+ : targetNode instanceof AreaLight
+ ? "image://IconGizmoImageProvider/area.png:" + overlayColor
+ : targetNode instanceof PointLight
+ ? "image://IconGizmoImageProvider/point.png:" + overlayColor
+ : "image://IconGizmoImageProvider/spot.png:" + overlayColor
+ : "image://IconGizmoImageProvider/point.png:" + overlayColor
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightModel.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightModel.qml
new file mode 100644
index 00000000000..c500f6fbb0e
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/LightModel.qml
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import LightUtils 1.0
+
+Model {
+ id: lightModel
+
+ property alias geometryName: lightGeometry.name // Name must be unique for each geometry
+ property alias geometryType: lightGeometry.lightType
+ property Material material
+
+ function updateGeometry()
+ {
+ lightGeometry.update();
+ }
+
+ scale: Qt.vector3d(50, 50, 50)
+
+ geometry: lightGeometry
+ materials: [ material ]
+
+ LightGeometry {
+ id: lightGeometry
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Line3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Line3D.qml
new file mode 100644
index 00000000000..7e034ff75f7
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Line3D.qml
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import LineGeometry 1.0
+
+Node {
+ id: pivotLine
+
+ property alias startPos: lineGeometry.startPos
+ property alias endPos: lineGeometry.endPos
+ property alias name: lineGeometry.name // Name must be unique for each line
+ property alias color: lineMat.diffuseColor
+
+ Model {
+ geometry: LineGeometry {
+ id: lineGeometry
+ }
+ materials: [
+ DefaultMaterial {
+ id: lineMat
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml
new file mode 100644
index 00000000000..7b5e2a15b21
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MaterialNodeView.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick3D 6.0
+
+View3D {
+ id: root
+ anchors.fill: parent
+ environment: sceneEnv
+
+ property Material previewMaterial
+
+ SceneEnvironment {
+ id: sceneEnv
+ antialiasingMode: SceneEnvironment.MSAA
+ antialiasingQuality: SceneEnvironment.High
+ }
+
+ Node {
+ DirectionalLight {
+ eulerRotation.x: -30
+ eulerRotation.y: -30
+ }
+
+ PerspectiveCamera {
+ z: 120
+ clipFar: 1000
+ clipNear: 1
+ }
+
+ Model {
+ id: model
+ source: "#Sphere"
+ materials: previewMaterial
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode2DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode2DImageView.qml
new file mode 100644
index 00000000000..827999de4b4
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode2DImageView.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+
+Item {
+ id: root
+ width: 150
+ height: 150
+
+ property alias contentItem: contentItem
+
+ /*
+ View3D {
+ // Dummy view to hold the context in case View3D items are used in the component
+ // TODO remove when QTBUG-87678 is fixed
+ }
+ */
+
+ Item {
+ id: contentItem
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml
new file mode 100644
index 00000000000..f0722c660fb
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNode3DImageView.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+Item {
+ id: root
+ width: 150
+ height: 150
+ visible: true
+
+ property View3D view: null
+ property alias contentItem: contentItem
+
+ property var previewObject
+
+ property var materialViewComponent
+ property var modelViewComponent
+ property var nodeViewComponent
+
+ property bool ready: false
+
+ function destroyView()
+ {
+ previewObject = null;
+ if (view)
+ view.destroy();
+ }
+
+ function createViewForObject(obj)
+ {
+ if (obj instanceof Material)
+ createViewForMaterial(obj);
+ else if (obj instanceof Model)
+ createViewForModel(obj);
+ else if (obj instanceof Node)
+ createViewForNode(obj);
+
+ previewObject = obj;
+ }
+
+ function createViewForMaterial(material)
+ {
+ if (!materialViewComponent)
+ materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
+
+ // Always recreate the view to ensure material is up to date
+ if (materialViewComponent.status === Component.Ready)
+ view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
+ }
+
+ function createViewForModel(model)
+ {
+ if (!modelViewComponent)
+ modelViewComponent = Qt.createComponent("ModelNodeView.qml");
+
+ // Always recreate the view to ensure model is up to date
+ if (modelViewComponent.status === Component.Ready)
+ view = modelViewComponent.createObject(viewRect, {"sourceModel": model});
+ }
+
+ function createViewForNode(node)
+ {
+ if (!nodeViewComponent)
+ nodeViewComponent = Qt.createComponent("NodeNodeView.qml");
+
+ // Always recreate the view to ensure node is up to date
+ if (nodeViewComponent.status === Component.Ready)
+ view = nodeViewComponent.createObject(viewRect, {"importScene": node});
+ }
+
+ function afterRender()
+ {
+ if (previewObject instanceof Node) {
+ view.fitToViewPort();
+ ready = view.ready;
+ } else {
+ ready = true;
+ }
+ }
+
+ View3D {
+ // Dummy view to hold the context
+ // TODO remove when QTBUG-87678 is fixed
+ }
+
+ Item {
+ id: contentItem
+ anchors.fill: parent
+
+ Rectangle {
+ id: viewRect
+ anchors.fill: parent
+
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "#222222" }
+ GradientStop { position: 0.0; color: "#999999" }
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml
new file mode 100644
index 00000000000..657b0f4c944
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ModelNodeView.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+View3D {
+ id: root
+ anchors.fill: parent
+ environment: sceneEnv
+ camera: theCamera
+
+ property bool ready: false
+ property real prevZoomFactor: -1
+ property Model sourceModel
+
+ function fitToViewPort()
+ {
+ cameraControl.focusObject(model, theCamera.eulerRotation, true, false);
+
+ if (cameraControl._zoomFactor < 0.1) {
+ model.scale = model.scale.times(10);
+ } else if (cameraControl._zoomFactor > 10) {
+ model.scale = model.scale.times(0.1);
+ } else {
+ // We need one more render after zoom factor change, so only set ready when zoom factor
+ // or scaling hasn't changed from the previous frame
+ ready = _generalHelper.fuzzyCompare(cameraControl._zoomFactor, prevZoomFactor);
+ prevZoomFactor = cameraControl._zoomFactor;
+ }
+ }
+
+ SceneEnvironment {
+ id: sceneEnv
+ antialiasingMode: SceneEnvironment.MSAA
+ antialiasingQuality: SceneEnvironment.High
+ }
+
+ EditCameraController {
+ id: cameraControl
+ camera: theCamera
+ anchors.fill: parent
+ view3d: root
+ ignoreToolState: true
+ }
+
+ DirectionalLight {
+ eulerRotation.x: -30
+ eulerRotation.y: -30
+ }
+
+ PerspectiveCamera {
+ id: theCamera
+ z: 600
+ y: 600
+ eulerRotation.x: -45
+ clipFar: 10000
+ clipNear: 1
+ }
+
+ Model {
+ id: model
+ eulerRotation.y: 45
+
+ source: sourceModel.source
+ geometry: sourceModel.geometry
+
+ materials: [
+ DefaultMaterial {
+ diffuseColor: "#4aee45"
+ }
+ ]
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MoveGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MoveGizmo.qml
new file mode 100644
index 00000000000..b8f968b59ea
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/MoveGizmo.qml
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Node {
+ id: moveGizmo
+
+ property View3D view3D
+ property bool highlightOnHover: false
+ property Node targetNode: null
+ property bool globalOrientation: true
+ readonly property bool dragging: arrowX.dragging || arrowY.dragging || arrowZ.dragging
+ || planeX.dragging || planeY.dragging || planeZ.dragging
+ || centerBall.dragging
+ property MouseArea3D dragHelper: null
+ property alias freeDraggerArea: centerBall.mouseArea
+
+ position: dragHelper.pivotScenePosition(targetNode)
+
+ onTargetNodeChanged: position = dragHelper.pivotScenePosition(targetNode)
+
+ Connections {
+ target: moveGizmo.targetNode
+ function onSceneTransformChanged()
+ {
+ moveGizmo.position = moveGizmo.dragHelper.pivotScenePosition(moveGizmo.targetNode);
+ }
+ }
+
+ signal positionCommit()
+ signal positionMove()
+
+ Node {
+ rotation: globalOrientation || !moveGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
+ : moveGizmo.targetNode.sceneRotation
+ Arrow {
+ id: arrowX
+ eulerRotation: Qt.vector3d(0, 0, -90)
+ targetNode: moveGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
+ : Qt.rgba(1, 0, 0, 1)
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+
+ Arrow {
+ id: arrowY
+ eulerRotation: Qt.vector3d(0, 0, 0)
+ targetNode: moveGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
+ : Qt.rgba(0, 0.6, 0, 1)
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+
+ Arrow {
+ id: arrowZ
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ targetNode: moveGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
+ : Qt.rgba(0, 0, 1, 1)
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+
+ PlanarMoveHandle {
+ id: planeX
+
+ y: 10
+ z: 10
+
+ eulerRotation: Qt.vector3d(0, 90, 0)
+ targetNode: moveGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
+ : Qt.rgba(1, 0, 0, 1)
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+
+ PlanarMoveHandle {
+ id: planeY
+
+ x: 10
+ z: 10
+
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ targetNode: moveGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
+ : Qt.rgba(0, 0.6, 0, 1)
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+
+ PlanarMoveHandle {
+ id: planeZ
+
+ x: 10
+ y: 10
+
+ eulerRotation: Qt.vector3d(0, 0, 0)
+ targetNode: moveGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
+ : Qt.rgba(0, 0, 1, 1)
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+ }
+
+ PlanarMoveHandle {
+ id: centerBall
+
+ source: "#Sphere"
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
+ : Qt.rgba(0.5, 0.5, 0.5, 1)
+ rotation: view3D.camera.rotation
+ priority: 10
+ targetNode: moveGizmo.targetNode
+
+ view3D: moveGizmo.view3D
+ active: moveGizmo.visible
+ dragHelper: moveGizmo.dragHelper
+
+ onPositionCommit: moveGizmo.positionCommit()
+ onPositionMove: moveGizmo.positionMove()
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/NodeNodeView.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/NodeNodeView.qml
new file mode 100644
index 00000000000..49d88d4c8a9
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/NodeNodeView.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+View3D {
+ id: root
+ anchors.fill: parent
+ environment: sceneEnv
+ camera: theCamera
+
+ property bool ready: false
+ property bool first: true
+ property real prevZoomFactor: -1
+
+ function fitToViewPort()
+ {
+ if (first) {
+ first = false;
+ selectionBox.targetNode = root.importScene;
+ } else {
+ cameraControl.focusObject(selectionBox.model, theCamera.eulerRotation, true, false);
+
+ if (cameraControl._zoomFactor < 0.1) {
+ root.importScene.scale = root.importScene.scale.times(10);
+ } else if (cameraControl._zoomFactor > 10) {
+ root.importScene.scale = root.importScene.scale.times(0.1);
+ } else {
+ // We need one more render after zoom factor change, so only set ready when zoom factor
+ // or scaling hasn't changed from the previous frame
+ ready = _generalHelper.fuzzyCompare(cameraControl._zoomFactor, prevZoomFactor);
+ prevZoomFactor = cameraControl._zoomFactor;
+ selectionBox.visible = false;
+ }
+ }
+ }
+
+ SceneEnvironment {
+ id: sceneEnv
+ antialiasingMode: SceneEnvironment.MSAA
+ antialiasingQuality: SceneEnvironment.High
+ }
+
+ SelectionBox {
+ id: selectionBox
+ view3D: root
+ geometryName: "NodeNodeViewSB"
+ }
+
+ EditCameraController {
+ id: cameraControl
+ camera: theCamera
+ anchors.fill: parent
+ view3d: root
+ ignoreToolState: true
+ }
+
+ DirectionalLight {
+ eulerRotation.x: -30
+ eulerRotation.y: -30
+ }
+
+ PerspectiveCamera {
+ id: theCamera
+ z: 600
+ y: 600
+ x: 600
+ eulerRotation.x: -45
+ eulerRotation.y: -45
+ clipFar: 10000
+ clipNear: 1
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Overlay2D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Overlay2D.qml
new file mode 100644
index 00000000000..30655a2787f
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/Overlay2D.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+Item {
+ id: root
+ property Node targetNode
+ property View3D targetView
+
+ property vector3d offset: Qt.vector3d(0, 0, 0)
+
+ property bool isBehindCamera
+
+ onTargetNodeChanged: updateOverlay()
+
+ Connections {
+ target: targetNode
+ function onSceneTransformChanged() { updateOverlay() }
+ }
+
+ Connections {
+ target: targetView.camera
+ function onSceneTransformChanged() { updateOverlay() }
+ }
+
+ Connections {
+ target: _generalHelper
+ function onOverlayUpdateNeeded() { updateOverlay() }
+ }
+
+ function updateOverlay()
+ {
+ var scenePos = targetNode ? targetNode.scenePosition : Qt.vector3d(0, 0, 0);
+ // Need separate variable as scenePos is reference to read-only property
+ var scenePosWithOffset = Qt.vector3d(scenePos.x + offset.x,
+ scenePos.y + offset.y,
+ scenePos.z + offset.z);
+ var viewPos = targetView ? targetView.mapFrom3DScene(scenePosWithOffset)
+ : Qt.vector3d(0, 0, 0);
+ root.x = viewPos.x;
+ root.y = viewPos.y;
+
+ isBehindCamera = viewPos.z <= 0;
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarDraggable.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarDraggable.qml
new file mode 100644
index 00000000000..1a1fea9f9ce
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarDraggable.qml
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Model {
+ id: rootModel
+
+ property View3D view3D
+ property alias color: gizmoMaterial.diffuseColor
+ property alias priority: mouseArea.priority
+ property Node targetNode: null
+ property bool dragging: mouseArea.dragging
+ property bool active: false
+ property MouseArea3D dragHelper: null
+ property alias mouseArea: mouseArea
+
+ readonly property bool hovering: mouseArea.hovering
+
+ property vector3d _scenePosPressed
+ property vector2d _planePosPressed
+ property vector3d _targetStartPos
+
+ signal pressed(var mouseArea)
+ signal dragged(var mouseArea, vector3d sceneRelativeDistance, vector2d relativeDistance)
+ signal released(var mouseArea, vector3d sceneRelativeDistance, vector2d relativeDistance)
+
+ source: "#Rectangle"
+
+ DefaultMaterial {
+ id: gizmoMaterial
+ diffuseColor: "white"
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ materials: gizmoMaterial
+
+ function handlePressed(mouseArea, planePos)
+ {
+ if (!targetNode)
+ return;
+
+ _planePosPressed = planePos;
+ _scenePosPressed = mouseArea.dragHelper.mapPositionToScene(planePos.toVector3d());
+ _targetStartPos = mouseArea.pivotScenePosition(targetNode);
+ pressed(mouseArea);
+ }
+
+ function calcRelativeDistance(mouseArea, planePos)
+ {
+ var scenePointerPos = mouseArea.dragHelper.mapPositionToScene(planePos.toVector3d());
+ return scenePointerPos.minus(_scenePosPressed);
+ }
+
+ function handleDragged(mouseArea, planePos)
+ {
+ if (!targetNode)
+ return;
+
+ dragged(mouseArea, calcRelativeDistance(mouseArea, planePos),
+ planePos.minus(_planePosPressed));
+ }
+
+ function handleReleased(mouseArea, planePos)
+ {
+ if (!targetNode)
+ return;
+
+ released(mouseArea, calcRelativeDistance(mouseArea, planePos),
+ planePos.minus(_planePosPressed));
+ }
+
+ MouseArea3D {
+ id: mouseArea
+ view3D: rootModel.view3D
+ x: -60
+ y: -60
+ width: 120
+ height: 120
+ grabsMouse: targetNode
+ active: rootModel.active
+ dragHelper: rootModel.dragHelper
+
+ onPressed: (planePos)=> {
+ rootModel.handlePressed(mouseArea, planePos);
+ }
+ onDragged: (planePos)=> {
+ rootModel.handleDragged(mouseArea, planePos);
+ }
+ onReleased: (planePos)=> {
+ rootModel.handleReleased(mouseArea, planePos);
+ }
+ }
+}
+
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarMoveHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarMoveHandle.qml
new file mode 100644
index 00000000000..795f208a6b6
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarMoveHandle.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+PlanarDraggable {
+ id: planarHandle
+ scale: Qt.vector3d(0.024, 0.024, 0.024)
+
+ signal positionCommit()
+ signal positionMove()
+
+ function localPos(sceneRelativeDistance)
+ {
+ var newScenePos = Qt.vector3d(
+ _targetStartPos.x + sceneRelativeDistance.x,
+ _targetStartPos.y + sceneRelativeDistance.y,
+ _targetStartPos.z + sceneRelativeDistance.z);
+ return targetNode.parent ? targetNode.parent.mapPositionFromScene(newScenePos) : newScenePos;
+ }
+
+ onPressed: {
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance)=> {
+ targetNode.position = localPos(sceneRelativeDistance);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.moveMultiSelection(false);
+ positionMove();
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance)=> {
+ targetNode.position = localPos(sceneRelativeDistance);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.moveMultiSelection(true);
+ positionCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarScaleHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarScaleHandle.qml
new file mode 100644
index 00000000000..ee4e2e673e5
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/PlanarScaleHandle.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+PlanarDraggable {
+ id: planarHandle
+ scale: Qt.vector3d(0.024, 0.024, 0.024)
+
+ property bool globalOrientation: false
+ property vector3d axisX
+ property vector3d axisY
+
+ signal scaleCommit()
+ signal scaleChange()
+
+ property vector3d _startScale
+
+ onPressed: {
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+ _startScale = targetNode.scale;
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
+ targetNode.scale = mouseArea.getNewScale(_startScale, relativeDistance.times(scale.x),
+ axisX, axisY);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.scaleMultiSelection(false);
+ scaleChange();
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
+ targetNode.scale = mouseArea.getNewScale(_startScale, relativeDistance.times(scale.x),
+ axisX, axisY);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.scaleMultiSelection(true);
+ scaleCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateGizmo.qml
new file mode 100644
index 00000000000..4998974dabf
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateGizmo.qml
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Node {
+ id: rotateGizmo
+
+ property View3D view3D
+ property bool highlightOnHover: true
+ property Node targetNode: null
+ property bool globalOrientation: true
+ readonly property bool dragging: cameraRing.dragging
+ || rotRingX.dragging || rotRingY.dragging || rotRingZ.dragging
+ property MouseArea3D dragHelper: null
+ property real currentAngle
+ property point currentMousePos
+ property alias freeDraggerArea: mouseAreaFree
+ property bool blocked: false
+
+ position: dragHelper.pivotScenePosition(targetNode)
+
+ onTargetNodeChanged: {
+ position = dragHelper.pivotScenePosition(targetNode);
+ blocked = _generalHelper.isRotationBlocked(targetNode);
+ }
+
+ Connections {
+ target: rotateGizmo.targetNode
+ function onSceneTransformChanged()
+ {
+ rotateGizmo.position = dragHelper.pivotScenePosition(targetNode);
+ }
+ }
+
+ Connections {
+ target: _generalHelper
+ function onRotationBlocksChanged()
+ {
+ blocked = _generalHelper.isRotationBlocked(targetNode);
+ }
+ }
+
+ signal rotateCommit()
+ signal rotateChange()
+
+ function copyRingProperties(srcRing) {
+ draggingRing.rotation = srcRing.sceneRotation;
+ draggingRing.color = srcRing.color;
+ draggingRing.scale = srcRing.scale;
+ }
+
+ onDraggingChanged: {
+ if (rotRingX.dragging)
+ copyRingProperties(rotRingX)
+ else if (rotRingY.dragging)
+ copyRingProperties(rotRingY)
+ else if (rotRingZ.dragging)
+ copyRingProperties(rotRingZ)
+ }
+
+ Node {
+ id: rotNode
+ rotation: globalOrientation || !rotateGizmo.targetNode ? Qt.quaternion(1, 0, 0, 0)
+ : rotateGizmo.targetNode.sceneRotation
+ visible: !rotateGizmo.dragging && !freeRotator.dragging
+
+ RotateRing {
+ id: rotRingX
+ objectName: "Rotate Ring X"
+ eulerRotation: Qt.vector3d(0, 90, 0)
+ targetNode: rotateGizmo.targetNode
+ color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
+ : highlightOnHover && (hovering || dragging)
+ ? Qt.lighter(Qt.rgba(1, 0, 0, 1)) : Qt.rgba(1, 0, 0, 1)
+ priority: 40
+ view3D: rotateGizmo.view3D
+ active: rotateGizmo.visible && !rotateGizmo.blocked
+ dragHelper: rotateGizmo.dragHelper
+
+ onRotateCommit: rotateGizmo.rotateCommit()
+ onRotateChange: rotateGizmo.rotateChange()
+ onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
+ onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
+ }
+
+ RotateRing {
+ id: rotRingY
+ objectName: "Rotate Ring Y"
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ targetNode: rotateGizmo.targetNode
+ color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
+ : highlightOnHover && (hovering || dragging)
+ ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1)) : Qt.rgba(0, 0.6, 0, 1)
+ // Just a smidge smaller than higher priority rings so that it doesn't obscure them
+ scale: Qt.vector3d(0.998, 0.998, 0.998)
+ priority: 30
+ view3D: rotateGizmo.view3D
+ active: rotateGizmo.visible && !rotateGizmo.blocked
+ dragHelper: rotateGizmo.dragHelper
+
+ onRotateCommit: rotateGizmo.rotateCommit()
+ onRotateChange: rotateGizmo.rotateChange()
+ onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
+ onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
+ }
+
+ RotateRing {
+ id: rotRingZ
+ objectName: "Rotate Ring Z"
+ eulerRotation: Qt.vector3d(0, 0, 0)
+ targetNode: rotateGizmo.targetNode
+ color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
+ : highlightOnHover && (hovering || dragging)
+ ? Qt.lighter(Qt.rgba(0, 0, 1, 1)) : Qt.rgba(0, 0, 1, 1)
+ // Just a smidge smaller than higher priority rings so that it doesn't obscure them
+ scale: Qt.vector3d(0.996, 0.996, 0.996)
+ priority: 20
+ view3D: rotateGizmo.view3D
+ active: rotateGizmo.visible && !rotateGizmo.blocked
+ dragHelper: rotateGizmo.dragHelper
+
+ onRotateCommit: rotateGizmo.rotateCommit()
+ onRotateChange: rotateGizmo.rotateChange()
+ onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
+ onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
+ }
+ }
+
+ RotateRing {
+ // This ring is used as visual proxy during dragging to display the currently dragged
+ // plane in static position, as rotation planes can wobble when ancestors don't have
+ // uniform scaling.
+ // Camera ring doesn't need dragging proxy as it doesn't wobble.
+ id: draggingRing
+ objectName: "draggingRing"
+ targetNode: rotateGizmo.targetNode
+ view3D: rotateGizmo.view3D
+ active: false
+ visible: rotRingX.dragging || rotRingY.dragging || rotRingZ.dragging
+ }
+
+ RotateRing {
+ id: cameraRing
+ objectName: "cameraRing"
+ rotation: rotateGizmo.view3D.camera.rotation
+ targetNode: rotateGizmo.targetNode
+ color: rotateGizmo.blocked ? Qt.rgba(0.5, 0.5, 0.5, 1)
+ : highlightOnHover && (hovering || dragging)
+ ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
+ : Qt.rgba(0.5, 0.5, 0.5, 1)
+ scale: Qt.vector3d(1.1, 1.1, 1.1)
+ priority: 10
+ view3D: rotateGizmo.view3D
+ active: rotateGizmo.visible && !rotateGizmo.blocked
+ dragHelper: rotateGizmo.dragHelper
+ visible: !rotRingX.dragging && !rotRingY.dragging && !rotRingZ.dragging && !freeRotator.dragging
+
+ onRotateCommit: rotateGizmo.rotateCommit()
+ onRotateChange: rotateGizmo.rotateChange()
+ onCurrentAngleChanged: rotateGizmo.currentAngle = currentAngle
+ onCurrentMousePosChanged: rotateGizmo.currentMousePos = currentMousePos
+ }
+
+ Model {
+ id: freeRotator
+
+ source: "#Sphere"
+ materials: DefaultMaterial {
+ id: material
+ diffuseColor: "black"
+ opacity: mouseAreaFree.hovering && !rotateGizmo.blocked ? 0.15 : 0
+ lighting: DefaultMaterial.NoLighting
+ }
+ scale: Qt.vector3d(0.15, 0.15, 0.15)
+ visible: !rotateGizmo.dragging && !dragging
+
+ property bool dragging: false
+ property vector3d _pointerPosPressed
+ property vector3d _startRotation
+
+ function handlePressed(screenPos)
+ {
+ if (!rotateGizmo.targetNode)
+ return;
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+
+ // Need to recreate vector as we need to adjust it and we can't do that on reference of
+ // scenePosition, which is read-only property
+ var scenePos = rotateGizmo.dragHelper.pivotScenePosition(rotateGizmo.targetNode);
+ _pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0);
+
+ // Recreate vector so we don't follow the changes in targetNode.rotation
+ _startRotation = Qt.vector3d(rotateGizmo.targetNode.eulerRotation.x,
+ rotateGizmo.targetNode.eulerRotation.y,
+ rotateGizmo.targetNode.eulerRotation.z);
+ // Ensure we never set NaN values for rotation, even if target node originally has them
+ if (isNaN(_startRotation.x))
+ _startRotation.x = 0;
+ if (isNaN(_startRotation.y))
+ _startRotation.y = 0;
+ if (isNaN(_startRotation.z))
+ _startRotation.z = 0;
+
+ dragging = true;
+ }
+
+ function handleDragged(screenPos)
+ {
+ if (!rotateGizmo.targetNode)
+ return;
+
+ mouseAreaFree.applyFreeRotation(
+ rotateGizmo.targetNode, _startRotation, _pointerPosPressed,
+ Qt.vector3d(screenPos.x, screenPos.y, 0));
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.rotateMultiSelection(false);
+
+ rotateGizmo.rotateChange();
+ }
+
+ function handleReleased(screenPos)
+ {
+ if (!rotateGizmo.targetNode)
+ return;
+
+ mouseAreaFree.applyFreeRotation(
+ rotateGizmo.targetNode, _startRotation, _pointerPosPressed,
+ Qt.vector3d(screenPos.x, screenPos.y, 0));
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.rotateMultiSelection(true);
+
+ rotateGizmo.rotateCommit();
+ dragging = false;
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.resetMultiSelectionNode();
+ }
+
+ MouseArea3D {
+ id: mouseAreaFree
+ view3D: rotateGizmo.view3D
+ rotation: rotateGizmo.view3D.camera.rotation
+ objectName: "Free rotator plane"
+ x: -50
+ y: -50
+ width: 100
+ height: 100
+ circlePickArea: Qt.point(25, 50)
+ grabsMouse: rotateGizmo.targetNode
+ active: rotateGizmo.visible && !rotateGizmo.blocked
+ dragHelper: rotateGizmo.dragHelper
+
+ onPressed: (planePos, screenPos)=> {
+ freeRotator.handlePressed(screenPos);
+ }
+ onDragged: (planePos, screenPos)=> {
+ freeRotator.handleDragged(screenPos);
+ }
+ onReleased: (planePos, screenPos)=> {
+ freeRotator.handleReleased(screenPos);
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateRing.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateRing.qml
new file mode 100644
index 00000000000..385806008ee
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/RotateRing.qml
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Model {
+ id: rotateRing
+
+ property View3D view3D
+ property alias color: material.diffuseColor
+ property Node targetNode: null
+ property bool dragging: mouseAreaMain.dragging
+ property bool active: false
+ property alias hovering: mouseAreaMain.hovering
+ property alias priority: mouseAreaMain.priority
+ property real currentAngle
+ property point currentMousePos
+ property MouseArea3D dragHelper: null
+
+ property vector3d _pointerPosPressed
+ property vector3d _targetPosOnScreen
+ property vector3d _startRotation
+ property bool _trackBall
+
+ signal rotateCommit()
+ signal rotateChange()
+
+ source: "../meshes/ring.mesh"
+
+ Model {
+ id: pickModel
+ objectName: "PickModel for " + rotateRing.objectName
+ source: "../meshes/ringselect.mesh"
+ pickable: true
+ }
+
+ materials: DefaultMaterial {
+ id: material
+ diffuseColor: "white"
+ lighting: DefaultMaterial.NoLighting
+ }
+
+ function applyLocalRotation(screenPos)
+ {
+ currentAngle = mouseAreaMain.dragHelper.getNewRotationAngle(
+ targetNode, _pointerPosPressed, Qt.vector3d(screenPos.x, screenPos.y, 0),
+ _targetPosOnScreen, currentAngle, _trackBall);
+ mouseAreaMain.dragHelper.applyRotationAngleToNode(targetNode, _startRotation, currentAngle);
+ }
+
+ function handlePressed(screenPos, angle)
+ {
+ if (!targetNode)
+ return;
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+
+ // Need to recreate vector as we need to adjust it and we can't do that on reference of
+ // scenePosition, which is read-only property
+ var scenePos = mouseAreaMain.pivotScenePosition(targetNode);
+
+ _targetPosOnScreen = view3D.mapFrom3DScene(scenePos);
+ _targetPosOnScreen.z = 0;
+ _pointerPosPressed = Qt.vector3d(screenPos.x, screenPos.y, 0);
+ _trackBall = angle < 0.1;
+
+ // Recreate vector so we don't follow the changes in targetNode.eulerRotation
+ _startRotation = Qt.vector3d(targetNode.eulerRotation.x,
+ targetNode.eulerRotation.y,
+ targetNode.eulerRotation.z);
+ // Ensure we never set NaN values for rotation, even if target node originally has them
+ if (isNaN(_startRotation.x))
+ _startRotation.x = 0;
+ if (isNaN(_startRotation.y))
+ _startRotation.y = 0;
+ if (isNaN(_startRotation.z))
+ _startRotation.z = 0;
+ currentAngle = 0;
+ currentMousePos = screenPos;
+ }
+
+ function handleDragged(screenPos)
+ {
+ if (!targetNode)
+ return;
+
+ applyLocalRotation(screenPos);
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.rotateMultiSelection(false);
+
+ currentMousePos = screenPos;
+ rotateChange();
+ }
+
+ function handleReleased(screenPos)
+ {
+ if (!targetNode)
+ return;
+
+ applyLocalRotation(screenPos);
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.rotateMultiSelection(true);
+
+ rotateCommit();
+ currentAngle = 0;
+ currentMousePos = screenPos;
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.resetMultiSelectionNode();
+ }
+
+ MouseArea3D {
+ id: mouseAreaMain
+ view3D: rotateRing.view3D
+ objectName: "Main plane of " + rotateRing.objectName
+ x: -30
+ y: -30
+ width: 60
+ height: 60
+ circlePickArea: Qt.point(9.2, 1.4)
+ grabsMouse: targetNode
+ active: rotateRing.active
+ pickNode: pickModel
+ minAngle: 0.05
+ dragHelper: rotateRing.dragHelper
+
+ onPressed: (planePos, screenPos, angle)=> {
+ rotateRing.handlePressed(screenPos, angle);
+ }
+ onDragged: (planePos, screenPos)=> {
+ rotateRing.handleDragged(screenPos);
+ }
+ onReleased: (planePos, screenPos)=> {
+ rotateRing.handleReleased(screenPos);
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleGizmo.qml
new file mode 100644
index 00000000000..e76809f32fd
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleGizmo.qml
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+Node {
+ id: scaleGizmo
+
+ property View3D view3D
+ property bool highlightOnHover: false
+ property Node targetNode: null
+ readonly property bool dragging: scaleRodX.dragging || scaleRodY.dragging || scaleRodZ.dragging
+ || planeX.dragging || planeY.dragging || planeZ.dragging
+ || centerMouseArea.dragging
+ property MouseArea3D dragHelper: null
+ property alias freeDraggerArea: centerMouseArea
+
+ position: dragHelper.pivotScenePosition(targetNode)
+
+ onTargetNodeChanged: position = dragHelper.pivotScenePosition(targetNode)
+
+ Connections {
+ target: scaleGizmo.targetNode
+ function onSceneTransformChanged()
+ {
+ scaleGizmo.position = scaleGizmo.dragHelper.pivotScenePosition(scaleGizmo.targetNode);
+ }
+ }
+
+ signal scaleCommit()
+ signal scaleChange()
+
+ Node {
+ rotation: !targetNode ? Qt.quaternion(1, 0, 0, 0) : targetNode.sceneRotation
+
+ ScaleRod {
+ id: scaleRodX
+ eulerRotation: Qt.vector3d(0, 0, -90)
+ axis: Qt.vector3d(1, 0, 0)
+ targetNode: scaleGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
+ : Qt.rgba(1, 0, 0, 1)
+ view3D: scaleGizmo.view3D
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ ScaleRod {
+ id: scaleRodY
+ eulerRotation: Qt.vector3d(0, 0, 0)
+ axis: Qt.vector3d(0, 1, 0)
+ targetNode: scaleGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
+ : Qt.rgba(0, 0.6, 0, 1)
+ view3D: scaleGizmo.view3D
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ ScaleRod {
+ id: scaleRodZ
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ axis: Qt.vector3d(0, 0, 1)
+ targetNode: scaleGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
+ : Qt.rgba(0, 0, 1, 1)
+ view3D: scaleGizmo.view3D
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ PlanarScaleHandle {
+ id: planeX
+
+ y: 10
+ z: 10
+
+ eulerRotation: Qt.vector3d(0, 90, 0)
+ axisX: Qt.vector3d(0, 0, -1)
+ axisY: Qt.vector3d(0, 1, 0)
+ targetNode: scaleGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(1, 0, 0, 1))
+ : Qt.rgba(1, 0, 0, 1)
+ view3D: scaleGizmo.view3D
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ PlanarScaleHandle {
+ id: planeY
+
+ x: 10
+ z: 10
+
+ eulerRotation: Qt.vector3d(90, 0, 0)
+ axisX: Qt.vector3d(1, 0, 0)
+ axisY: Qt.vector3d(0, 0, 1)
+ targetNode: scaleGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0.6, 0, 1))
+ : Qt.rgba(0, 0.6, 0, 1)
+ view3D: scaleGizmo.view3D
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+
+ PlanarScaleHandle {
+ id: planeZ
+
+ x: 10
+ y: 10
+
+ eulerRotation: Qt.vector3d(0, 0, 0)
+ axisX: Qt.vector3d(1, 0, 0)
+ axisY: Qt.vector3d(0, 1, 0)
+ targetNode: scaleGizmo.targetNode
+ color: highlightOnHover && (hovering || dragging) ? Qt.lighter(Qt.rgba(0, 0, 1, 1))
+ : Qt.rgba(0, 0, 1, 1)
+ view3D: scaleGizmo.view3D
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ onScaleCommit: scaleGizmo.scaleCommit()
+ onScaleChange: scaleGizmo.scaleChange()
+ }
+ }
+
+ Model {
+ id: centerCube
+
+ source: "#Cube"
+ scale: Qt.vector3d(0.024, 0.024, 0.024)
+ materials: DefaultMaterial {
+ id: material
+ diffuseColor: highlightOnHover
+ && (centerMouseArea.hovering || centerMouseArea.dragging)
+ ? Qt.lighter(Qt.rgba(0.5, 0.5, 0.5, 1))
+ : Qt.rgba(0.5, 0.5, 0.5, 1)
+ lighting: DefaultMaterial.NoLighting
+ }
+
+ MouseArea3D {
+ id: centerMouseArea
+ view3D: scaleGizmo.view3D
+ x: -60
+ y: -60
+ width: 120
+ height: 120
+ rotation: view3D.camera.rotation
+ grabsMouse: scaleGizmo.targetNode
+ priority: 10
+ active: scaleGizmo.visible
+ dragHelper: scaleGizmo.dragHelper
+
+ property vector3d _startScale
+ property point _startScreenPos
+
+ function localScale(screenPos)
+ {
+ var yDelta = screenPos.y - _startScreenPos.y;
+ if (yDelta === 0)
+ return _startScale;
+ var scaler = 1.0 + (yDelta * 0.025);
+ if (scaler === 0)
+ scaler = 0.0001;
+ return Qt.vector3d(scaler * _startScale.x,
+ scaler * _startScale.y,
+ scaler * _startScale.z);
+ }
+
+ onPressed: (planePos, screenPos)=> {
+ if (!scaleGizmo.targetNode)
+ return;
+
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+
+ // Recreate vector so we don't follow the changes in targetNode.scale
+ _startScale = Qt.vector3d(scaleGizmo.targetNode.scale.x,
+ scaleGizmo.targetNode.scale.y,
+ scaleGizmo.targetNode.scale.z);
+ _startScreenPos = screenPos;
+ }
+ onDragged: (planePos, screenPos)=> {
+ if (!scaleGizmo.targetNode)
+ return;
+ scaleGizmo.targetNode.scale = localScale(screenPos);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.scaleMultiSelection(false);
+ scaleGizmo.scaleChange();
+ }
+ onReleased: (planePos, screenPos)=> {
+ if (!scaleGizmo.targetNode)
+ return;
+
+ scaleGizmo.targetNode.scale = localScale(screenPos);
+ if (targetNode == multiSelectionNode)
+ _generalHelper.scaleMultiSelection(true);
+ scaleGizmo.scaleCommit();
+ }
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleRod.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleRod.qml
new file mode 100644
index 00000000000..1857bfddda6
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ScaleRod.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import MouseArea3D 1.0
+
+DirectionalDraggable {
+ id: scaleRod
+ source: "../meshes/scalerod.mesh"
+
+ property vector3d axis
+
+ signal scaleCommit()
+ signal scaleChange()
+
+ property vector3d _startScale
+
+ Model {
+ source: "#Cube"
+ y: 10
+ scale: Qt.vector3d(0.020, 0.020, 0.020)
+ materials: DefaultMaterial {
+ id: material
+ diffuseColor: scaleRod.color
+ lighting: DefaultMaterial.NoLighting
+ }
+ }
+
+ onPressed: {
+ if (targetNode == multiSelectionNode)
+ _generalHelper.restartMultiSelection();
+ _startScale = targetNode.scale;
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
+ targetNode.scale = mouseArea.getNewScale(_startScale, Qt.vector2d(relativeDistance, 0),
+ axis, Qt.vector3d(0, 0, 0));
+ if (targetNode == multiSelectionNode)
+ _generalHelper.scaleMultiSelection(false);
+ scaleChange();
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance, relativeDistance)=> {
+ targetNode.scale = mouseArea.getNewScale(_startScale, Qt.vector2d(relativeDistance, 0),
+ axis, Qt.vector3d(0, 0, 0));
+ if (targetNode == multiSelectionNode)
+ _generalHelper.scaleMultiSelection(true);
+ scaleCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml
new file mode 100644
index 00000000000..c75472096e7
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SceneView3D.qml
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick3D 6.0
+
+View3D {
+ id: sceneView
+ anchors.fill: parent
+
+ property bool usePerspective: false
+ property alias showSceneLight: sceneLight.visible
+ property alias showGrid: helperGrid.visible
+ property alias sceneHelpers: sceneHelpers
+ property alias perspectiveCamera: scenePerspectiveCamera
+ property alias orthoCamera: sceneOrthoCamera
+ property double cameraZoomFactor: .55;
+
+ // Empirical cameraZoomFactor values at which the grid zoom level is doubled. The values are
+ // approximately uniformally distributed over the non-linear range of cameraZoomFactor.
+ readonly property var grid_thresholds: [0.55, 1.10, 2.35, 4.9, 10.0, 20.5, 42.0, 85.0, 999999.0]
+ property var thresIdx: 1
+ property var thresPerc: 1.0 // percentage of cameraZoomFactor to the current grid zoom threshold (0.0 - 1.0)
+
+ camera: usePerspective ? scenePerspectiveCamera : sceneOrthoCamera
+
+ onCameraZoomFactorChanged: {
+ thresIdx = Math.max(1, grid_thresholds.findIndex(v => v > cameraZoomFactor));
+ thresPerc = (grid_thresholds[thresIdx] - cameraZoomFactor) / (grid_thresholds[thresIdx] - grid_thresholds[thresIdx - 1]);
+ }
+
+ Node {
+ id: sceneHelpers
+
+ HelperGrid {
+ id: helperGrid
+ lines: Math.pow(2, grid_thresholds.length - thresIdx - 1);
+ step: 100 * grid_thresholds[0] * Math.pow(2, thresIdx - 1);
+ subdivAlpha: thresPerc;
+ }
+
+ PointLight {
+ id: sceneLight
+ position: usePerspective ? scenePerspectiveCamera.position
+ : sceneOrthoCamera.position
+ quadraticFade: 0
+ linearFade: 0
+ }
+
+ // Initial camera position and rotation should be such that they look at origin.
+ // Otherwise EditCameraController._lookAtPoint needs to be initialized to correct
+ // point.
+ PerspectiveCamera {
+ id: scenePerspectiveCamera
+ z: 600
+ y: 600
+ eulerRotation.x: -45
+ clipFar: 100000
+ clipNear: 1
+ }
+
+ OrthographicCamera {
+ id: sceneOrthoCamera
+ z: 600
+ y: 600
+ eulerRotation.x: -45
+ clipFar: 100000
+ clipNear: -10000
+ }
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SelectionBox.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SelectionBox.qml
new file mode 100644
index 00000000000..1e7cc7b11ac
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SelectionBox.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+import SelectionBoxGeometry 1.0
+
+Node {
+ id: selectionBox
+
+ property View3D view3D
+ property Node targetNode: null
+ property alias model: selectionBoxModel
+ property alias geometryName: selectionBoxGeometry.name
+
+ SelectionBoxGeometry {
+ id: selectionBoxGeometry
+ name: "Selection Box of 3D Edit View"
+ view3D: selectionBox.view3D
+ targetNode: selectionBox.targetNode
+ rootNode: selectionBox
+ }
+
+ Model {
+ id: selectionBoxModel
+ geometry: selectionBoxGeometry
+
+ scale: selectionBox.targetNode ? selectionBox.targetNode.scale : Qt.vector3d(1, 1, 1)
+ rotation: selectionBox.targetNode ? selectionBox.targetNode.rotation : Qt.quaternion(1, 0, 0, 0)
+ position: selectionBox.targetNode ? selectionBox.targetNode.position : Qt.vector3d(0, 0, 0)
+ pivot: selectionBox.targetNode ? selectionBox.targetNode.pivot : Qt.vector3d(0, 0, 0)
+
+ visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty
+
+ materials: [
+ DefaultMaterial {
+ diffuseColor: "#fff600"
+ lighting: DefaultMaterial.NoLighting
+ cullMode: Material.NoCulling
+ }
+ ]
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SpotLightHandle.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SpotLightHandle.qml
new file mode 100644
index 00000000000..1c7322f4e28
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/SpotLightHandle.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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.
+**
+****************************************************************************/
+
+import QtQuick 6.0
+import QtQuick3D 6.0
+
+DirectionalDraggable {
+ id: handleRoot
+
+ property string currentLabel
+ property point currentMousePos
+ property string propName
+ property real propValue: 0
+ property real newValue: 0
+
+ scale: autoScaler.getScale(Qt.vector3d(5, 5, 5))
+ length: 3
+ offset: -1.5
+
+ Model {
+ id: handle
+ source: "#Sphere"
+ materials: [ handleRoot.material ]
+ scale: Qt.vector3d(0.02, 0.02, 0.02)
+ }
+
+ AutoScaleHelper {
+ id: autoScaler
+ active: handleRoot.active
+ view3D: handleRoot.view3D
+ }
+
+ property real _startAngle
+
+ signal valueCommit()
+ signal valueChange()
+
+ function updateAngle(relativeDistance, screenPos)
+ {
+ handleRoot.newValue = Math.round(Math.min(180, Math.max(0, _startAngle + relativeDistance)));
+ var l = Qt.locale();
+ handleRoot.currentLabel = propName + qsTr(": ") + Number(newValue).toLocaleString(l, 'f', 0);
+ handleRoot.currentMousePos = screenPos;
+ }
+
+ onPressed: (mouseArea, screenPos)=> {
+ _startAngle = propValue;
+ updateAngle(0, screenPos);
+ }
+
+ onDragged: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateAngle(relativeDistance, screenPos);
+ handleRoot.valueChange();
+ }
+
+ onReleased: (mouseArea, sceneRelativeDistance, relativeDistance, screenPos)=> {
+ updateAngle(relativeDistance, screenPos);
+ handleRoot.valueCommit();
+ }
+}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp
index c1f533fedaf..c80343bb466 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.cpp
@@ -27,7 +27,6 @@
#include "camerageometry.h"
-#include
#include
#include
#include
@@ -35,7 +34,6 @@
#include
#include
#include
-#include
#include
@@ -43,7 +41,7 @@ namespace QmlDesigner {
namespace Internal {
CameraGeometry::CameraGeometry()
- : QQuick3DGeometry()
+ : GeometryBase()
{
}
@@ -51,19 +49,6 @@ CameraGeometry::~CameraGeometry()
{
}
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-QString CameraGeometry::name() const
-{
- return objectName();
-}
-
-void CameraGeometry::setName(const QString &name)
-{
- setObjectName(name);
- emit nameChanged();
-}
-#endif
-
QQuick3DCamera *CameraGeometry::camera() const
{
return m_camera;
@@ -111,7 +96,7 @@ void CameraGeometry::setCamera(QQuick3DCamera *camera)
this, &CameraGeometry::handleCameraPropertyChange);
}
emit cameraChanged();
- update();
+ handleCameraPropertyChange();
}
void CameraGeometry::setViewPortRect(const QRectF &rect)
@@ -121,26 +106,37 @@ void CameraGeometry::setViewPortRect(const QRectF &rect)
m_viewPortRect = rect;
emit viewPortRectChanged();
- update();
+ updateGeometry();
}
void CameraGeometry::handleCameraPropertyChange()
{
m_cameraUpdatePending = true;
+ clear();
+ setStride(12); // To avoid div by zero inside QtQuick3D
update();
}
QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
+{
+ if (m_cameraUpdatePending) {
+ m_cameraUpdatePending = false;
+ updateGeometry();
+ }
+
+ return QQuick3DGeometry::updateSpatialNode(node);
+}
+
+void CameraGeometry::doUpdateGeometry()
{
if (!m_camera)
- return node;
+ return;
// If camera properties have been updated, we need to defer updating the frustum geometry
// to the next frame to ensure camera's spatial node has been properly updated.
if (m_cameraUpdatePending) {
- QTimer::singleShot(0, this, &CameraGeometry::update);
- m_cameraUpdatePending = false;
- return node;
+ update();
+ return;
}
if (!m_camera->cameraNode()) {
@@ -148,11 +144,7 @@ QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *
m_camera->mapToViewport({}, m_viewPortRect.width(), m_viewPortRect.height());
}
- setStride(12); // Silence a warning
- node = QQuick3DGeometry::updateSpatialNode(node);
- QSSGRenderGeometry *geometry = static_cast(node);
-
- geometry->clear();
+ GeometryBase::doUpdateGeometry();
QByteArray vertexData;
QByteArray indexData;
@@ -160,25 +152,11 @@ QSSGRenderGraphObject *CameraGeometry::updateSpatialNode(QSSGRenderGraphObject *
QVector3D maxBounds;
fillVertexData(vertexData, indexData, minBounds, maxBounds);
- geometry->setStride(12);
-#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
- geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::F32Type);
- geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::U16Type);
- geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
-#else
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
- QSSGMesh::Mesh::ComponentType::Float32);
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::IndexSemantic, 0,
- QSSGMesh::Mesh::ComponentType::UnsignedInt16);
- geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
-#endif
- geometry->setVertexData(vertexData);
- geometry->setIndexData(indexData);
- geometry->setBounds(minBounds, maxBounds);
-
- return node;
+ addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0,
+ QQuick3DGeometry::Attribute::U16Type);
+ setVertexData(vertexData);
+ setIndexData(indexData);
+ setBounds(minBounds, maxBounds);
}
void CameraGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData,
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h
index 55d31ca389e..5b4fa66fe46 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/camerageometry.h
@@ -27,29 +27,19 @@
#ifdef QUICK3D_MODULE
-#include
+#include "geometrybase.h"
+
#include
namespace QmlDesigner {
namespace Internal {
-class CameraGeometry : public QQuick3DGeometry
+class CameraGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QQuick3DCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged)
Q_PROPERTY(QRectF viewPortRect READ viewPortRect WRITE setViewPortRect NOTIFY viewPortRectChanged)
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- // Name property was removed in Qt 6, so define it here for compatibility.
- // Name maps to object name.
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
-public:
- QString name() const;
- void setName(const QString &name);
-signals:
- void nameChanged();
-#endif
-
public:
CameraGeometry();
~CameraGeometry() override;
@@ -68,10 +58,12 @@ signals:
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
+ void doUpdateGeometry() override;
private:
void fillVertexData(QByteArray &vertexData, QByteArray &indexData,
QVector3D &minBounds, QVector3D &maxBounds);
+
QQuick3DCamera *m_camera = nullptr;
QRectF m_viewPortRect;
bool m_cameraUpdatePending = false;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri
index bcfbc5e12ed..6eedaad8f1f 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/editor3d.pri
@@ -1,5 +1,6 @@
HEADERS += $$PWD/generalhelper.h \
$$PWD/mousearea3d.h \
+ $$PWD/geometrybase.h \
$$PWD/camerageometry.h \
$$PWD/lightgeometry.h \
$$PWD/gridgeometry.h \
@@ -9,6 +10,7 @@ HEADERS += $$PWD/generalhelper.h \
SOURCES += $$PWD/generalhelper.cpp \
$$PWD/mousearea3d.cpp \
+ $$PWD/geometrybase.cpp \
$$PWD/camerageometry.cpp \
$$PWD/lightgeometry.cpp \
$$PWD/gridgeometry.cpp \
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
index d76d335fd7e..39ca48b8e31 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp
@@ -46,6 +46,8 @@
#include
#include
+#include
+
namespace QmlDesigner {
namespace Internal {
@@ -151,56 +153,90 @@ float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float de
}
// Return value contains new lookAt point (xyz) and zoom factor (w)
-QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
- QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
- float oldZoom, bool updateZoom, bool closeUp)
+QVector4D GeneralHelper::focusNodesToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
+ const QVariant &nodes, QQuick3DViewport *viewPort,
+ float oldZoom, bool updateZoom, bool closeUp)
{
if (!camera)
return QVector4D(0.f, 0.f, 0.f, 1.f);
- QVector3D lookAt = targetObject ? targetObject->scenePosition() : QVector3D();
+ QList nodeList;
+ const QVariantList varNodes = nodes.value();
+ for (const auto &varNode : varNodes) {
+ auto model = varNode.value();
+ if (model)
+ nodeList.append(model);
+ }
- // Get object bounds
+ // Get bounds
+ QVector3D totalMinBound;
+ QVector3D totalMaxBound;
const qreal defaultExtent = 200.;
- qreal maxExtent = defaultExtent;
- if (auto modelNode = qobject_cast(targetObject)) {
- auto targetPriv = QQuick3DObjectPrivate::get(targetObject);
- if (auto renderModel = static_cast(targetPriv->spatialNode)) {
- QWindow *window = static_cast(viewPort->window());
- if (window) {
- QSSGRef context;
+
+ if (!nodeList.isEmpty()) {
+ static const float floatMin = std::numeric_limits::lowest();
+ static const float floatMax = std::numeric_limits::max();
+ totalMinBound = {floatMax, floatMax, floatMax};
+ totalMaxBound = {floatMin, floatMin, floatMin};
+ } else {
+ const float halfExtent = defaultExtent / 2.f;
+ totalMinBound = {-halfExtent, -halfExtent, -halfExtent};
+ totalMaxBound = {halfExtent, halfExtent, halfExtent};
+ }
+ for (const auto node : qAsConst(nodeList)) {
+ auto model = qobject_cast(node);
+ qreal maxExtent = defaultExtent;
+ QVector3D center = node->scenePosition();
+ if (model) {
+ auto targetPriv = QQuick3DObjectPrivate::get(model);
+ if (auto renderModel = static_cast(targetPriv->spatialNode)) {
+ QWindow *window = static_cast(viewPort->window());
+ if (window) {
+ QSSGRef context;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window));
+ context = QSSGRenderContextInterface::getRenderContextInterface(quintptr(window));
#else
- context = targetPriv->sceneManager->rci;
+ context = targetPriv->sceneManager->rci;
#endif
- if (!context.isNull()) {
- QSSGBounds3 bounds;
- auto geometry = qobject_cast(modelNode->geometry());
- if (geometry) {
- bounds = geometry->bounds();
- } else {
- auto bufferManager = context->bufferManager();
- bounds = renderModel->getModelBounds(bufferManager);
+ if (!context.isNull()) {
+ QSSGBounds3 bounds;
+ auto geometry = qobject_cast(model->geometry());
+ if (geometry) {
+ bounds = geometry->bounds();
+ } else {
+ auto bufferManager = context->bufferManager();
+ bounds = renderModel->getModelBounds(bufferManager);
+ }
+
+ center = renderModel->globalTransform.map(bounds.center());
+ const QVector3D e = bounds.extents();
+ const QVector3D s = model->sceneScale();
+ qreal maxScale = qSqrt(qreal(s.x() * s.x() + s.y() * s.y() + s.z() * s.z()));
+ maxExtent = qSqrt(qreal(e.x() * e.x() + e.y() * e.y() + e.z() * e.z()));
+ maxExtent *= maxScale;
+
+ if (maxExtent < 0.0001)
+ maxExtent = defaultExtent;
}
-
- QVector3D center = bounds.center();
- const QVector3D e = bounds.extents();
- const QVector3D s = targetObject->sceneScale();
- qreal maxScale = qSqrt(qreal(s.x() * s.x() + s.y() * s.y() + s.z() * s.z()));
- maxExtent = qSqrt(qreal(e.x() * e.x() + e.y() * e.y() + e.z() * e.z()));
- maxExtent *= maxScale;
-
- if (maxExtent < 0.0001)
- maxExtent = defaultExtent;
-
- // Adjust lookAt to look directly at the center of the object bounds
- lookAt = renderModel->globalTransform.map(center);
}
}
}
+ float halfExtent = float(maxExtent / 2.);
+ const QVector3D halfExtents {halfExtent, halfExtent, halfExtent};
+
+ const QVector3D minBound = center - halfExtents;
+ const QVector3D maxBound = center + halfExtents;
+
+ for (int i = 0; i < 3; ++i) {
+ totalMinBound[i] = qMin(minBound[i], totalMinBound[i]);
+ totalMaxBound[i] = qMax(maxBound[i], totalMaxBound[i]);
+ }
}
+ QVector3D extents = totalMaxBound - totalMinBound;
+ QVector3D lookAt = totalMinBound + (extents / 2.f);
+ float maxExtent = qMax(extents.x(), qMax(extents.y(), extents.z()));
+
// Reset camera position to default zoom
QMatrix4x4 m = camera->sceneTransform();
const float *dataPtr(m.data());
@@ -210,9 +246,9 @@ QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defau
camera->setPosition(lookAt + newLookVector);
- qreal divisor = closeUp ? 900. : 725.;
+ float divisor = closeUp ? 900.f : 725.f;
- float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / divisor), 100.f) : oldZoom;
+ float newZoomFactor = updateZoom ? qBound(.01f, maxExtent / divisor, 100.f) : oldZoom;
float cameraZoomFactor = zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false);
return QVector4D(lookAt, cameraZoomFactor);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
index 05ec29249eb..6e888980f81 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h
@@ -67,10 +67,10 @@ public:
Q_INVOKABLE float zoomCamera(QQuick3DCamera *camera, float distance,
float defaultLookAtDistance, const QVector3D &lookAt,
float zoomFactor, bool relative);
- Q_INVOKABLE QVector4D focusObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
- QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
- float oldZoom, bool updateZoom = true,
- bool closeUp = false);
+ Q_INVOKABLE QVector4D focusNodesToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
+ const QVariant &nodes, QQuick3DViewport *viewPort,
+ float oldZoom, bool updateZoom = true,
+ bool closeUp = false);
Q_INVOKABLE bool fuzzyCompare(double a, double b);
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.cpp
new file mode 100644
index 00000000000..70d48fb20b5
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#ifdef QUICK3D_MODULE
+
+#include "geometrybase.h"
+
+namespace QmlDesigner {
+namespace Internal {
+
+GeometryBase::GeometryBase()
+ : QQuick3DGeometry()
+{
+ m_updatetimer.setSingleShot(true);
+ m_updatetimer.setInterval(0);
+ connect(&m_updatetimer, &QTimer::timeout, this, &GeometryBase::doUpdateGeometry);
+ updateGeometry();
+ setStride(12); // To avoid div by zero inside QtQuick3D
+}
+
+GeometryBase::~GeometryBase()
+{
+}
+
+void GeometryBase::doUpdateGeometry()
+{
+ clear();
+
+ setStride(12);
+
+ addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
+ QQuick3DGeometry::Attribute::F32Type);
+ setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
+
+ update();
+}
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+QString GeometryBase::name() const
+{
+ return objectName();
+}
+
+void GeometryBase::setName(const QString &name)
+{
+ setObjectName(name);
+ emit nameChanged();
+}
+#endif
+
+void GeometryBase::updateGeometry()
+{
+ m_updatetimer.start();
+}
+
+}
+}
+
+#endif // QUICK3D_MODULE
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.h
new file mode 100644
index 00000000000..f8486a6c837
--- /dev/null
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/geometrybase.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#pragma once
+
+#ifdef QUICK3D_MODULE
+
+#include
+
+#include
+
+namespace QmlDesigner {
+namespace Internal {
+
+class GeometryBase : public QQuick3DGeometry
+{
+ Q_OBJECT
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ // Name property was removed in Qt 6, so define it here for compatibility.
+ // Name maps to object name.
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+public:
+ QString name() const;
+ void setName(const QString &name);
+signals:
+ void nameChanged();
+#endif
+
+public:
+ GeometryBase();
+ ~GeometryBase() override;
+
+protected:
+ void updateGeometry();
+ virtual void doUpdateGeometry();
+
+private:
+ QTimer m_updatetimer;
+};
+
+}
+}
+
+QML_DECLARE_TYPE(QmlDesigner::Internal::GeometryBase)
+
+#endif // QUICK3D_MODULE
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.cpp
index a9e12f69f45..123153c0c9a 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.cpp
@@ -27,33 +27,19 @@
#include "gridgeometry.h"
-#include
-
namespace QmlDesigner {
namespace Internal {
GridGeometry::GridGeometry()
- : QQuick3DGeometry()
+ : GeometryBase()
{
+ updateGeometry();
}
GridGeometry::~GridGeometry()
{
}
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-QString GridGeometry::name() const
-{
- return objectName();
-}
-
-void GridGeometry::setName(const QString &name)
-{
- setObjectName(name);
- emit nameChanged();
-}
-#endif
-
int GridGeometry::lines() const
{
return m_lines;
@@ -79,7 +65,7 @@ void GridGeometry::setLines(int count)
return;
m_lines = qMax(count, 1);
emit linesChanged();
- update();
+ updateGeometry();
}
// Space between lines
@@ -90,7 +76,7 @@ void GridGeometry::setStep(float step)
return;
m_step = step;
emit stepChanged();
- update();
+ updateGeometry();
}
void GridGeometry::setIsCenterLine(bool enabled)
@@ -100,36 +86,22 @@ void GridGeometry::setIsCenterLine(bool enabled)
m_isCenterLine = enabled;
emit isCenterLineChanged();
- update();
+ updateGeometry();
}
-QSSGRenderGraphObject *GridGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
+void GridGeometry::doUpdateGeometry()
{
- setStride(12); // Silence a warning
- node = QQuick3DGeometry::updateSpatialNode(node);
- QSSGRenderGeometry *geometry = static_cast(node);
- geometry->clear();
+ GeometryBase::doUpdateGeometry();
QByteArray vertexData;
fillVertexData(vertexData);
- geometry->setStride(12);
-#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
- geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::F32Type);
- geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
-#else
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
- QSSGMesh::Mesh::ComponentType::Float32);
- geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
-#endif
- geometry->setVertexData(vertexData);
+ setVertexData(vertexData);
int lastIndex = (vertexData.size() - 1) / int(sizeof(QVector3D));
auto vertexPtr = reinterpret_cast(vertexData.data());
- geometry->setBounds(QVector3D(vertexPtr[0][0], vertexPtr[0][1], 0.0),
- QVector3D(vertexPtr[lastIndex][0], vertexPtr[lastIndex][1], 0.0));
- return node;
+ setBounds(QVector3D(vertexPtr[0][0], vertexPtr[0][1], 0.0),
+ QVector3D(vertexPtr[lastIndex][0], vertexPtr[lastIndex][1], 0.0));
}
void GridGeometry::fillVertexData(QByteArray &vertexData)
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.h
index 6074fb42453..39d9c38e2d0 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/gridgeometry.h
@@ -27,12 +27,12 @@
#ifdef QUICK3D_MODULE
-#include
+#include "geometrybase.h"
namespace QmlDesigner {
namespace Internal {
-class GridGeometry : public QQuick3DGeometry
+class GridGeometry : public GeometryBase
{
Q_OBJECT
@@ -41,17 +41,6 @@ class GridGeometry : public QQuick3DGeometry
Q_PROPERTY(bool isCenterLine READ isCenterLine WRITE setIsCenterLine NOTIFY isCenterLineChanged)
Q_PROPERTY(bool isSubdivision MEMBER m_isSubdivision)
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- // Name property was removed in Qt 6, so define it here for compatibility.
- // Name maps to object name.
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
-public:
- QString name() const;
- void setName(const QString &name);
-signals:
- void nameChanged();
-#endif
-
public:
GridGeometry();
~GridGeometry() override;
@@ -71,7 +60,7 @@ signals:
void isCenterLineChanged();
protected:
- QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
+ void doUpdateGeometry() override;
private:
void fillVertexData(QByteArray &vertexData);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.cpp
index 735c237a0fb..cae1090cad9 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.cpp
@@ -37,7 +37,7 @@ namespace QmlDesigner {
namespace Internal {
LightGeometry::LightGeometry()
- : QQuick3DGeometry()
+ : GeometryBase()
{
}
@@ -45,19 +45,6 @@ LightGeometry::~LightGeometry()
{
}
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-QString LightGeometry::name() const
-{
- return objectName();
-}
-
-void LightGeometry::setName(const QString &name)
-{
- setObjectName(name);
- emit nameChanged();
-}
-#endif
-
LightGeometry::LightType LightGeometry::lightType() const
{
return m_lightType;
@@ -71,45 +58,29 @@ void LightGeometry::setLightType(LightGeometry::LightType lightType)
m_lightType = lightType;
emit lightTypeChanged();
- update();
+ updateGeometry();
}
-QSSGRenderGraphObject *LightGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
+void LightGeometry::doUpdateGeometry()
{
if (m_lightType == LightType::Invalid)
- return node;
+ return;
- setStride(12); // Silence a warning
- node = QQuick3DGeometry::updateSpatialNode(node);
- QSSGRenderGeometry *geometry = static_cast(node);
-
- geometry->clear();
+ GeometryBase::doUpdateGeometry();
QByteArray vertexData;
QByteArray indexData;
QVector3D minBounds;
QVector3D maxBounds;
+
fillVertexData(vertexData, indexData, minBounds, maxBounds);
- geometry->setStride(12);
-#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
- geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::F32Type);
- geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::U16Type);
- geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
-#else
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
- QSSGMesh::Mesh::ComponentType::Float32);
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::IndexSemantic, 0,
- QSSGMesh::Mesh::ComponentType::UnsignedInt16);
- geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
-#endif
- geometry->setVertexData(vertexData);
- geometry->setIndexData(indexData);
- geometry->setBounds(minBounds, maxBounds);
+ addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0,
+ QQuick3DGeometry::Attribute::U16Type);
- return node;
+ setVertexData(vertexData);
+ setIndexData(indexData);
+ setBounds(minBounds, maxBounds);
}
void LightGeometry::fillVertexData(QByteArray &vertexData, QByteArray &indexData,
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.h
index e9ba7182183..6c9c2d2a12e 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/lightgeometry.h
@@ -27,27 +27,16 @@
#ifdef QUICK3D_MODULE
-#include
+#include "geometrybase.h"
namespace QmlDesigner {
namespace Internal {
-class LightGeometry : public QQuick3DGeometry
+class LightGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(LightType lightType READ lightType WRITE setLightType NOTIFY lightTypeChanged)
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- // Name property was removed in Qt 6, so define it here for compatibility.
- // Name maps to object name.
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
-public:
- QString name() const;
- void setName(const QString &name);
-signals:
- void nameChanged();
-#endif
-
public:
enum class LightType {
Invalid,
@@ -70,7 +59,7 @@ signals:
void lightTypeChanged();
protected:
- QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
+ void doUpdateGeometry() override;
private:
void fillVertexData(QByteArray &vertexData, QByteArray &indexData,
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.cpp
index 314b7a3136b..5feffa19b83 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.cpp
@@ -27,13 +27,11 @@
#include "linegeometry.h"
-#include
-
namespace QmlDesigner {
namespace Internal {
LineGeometry::LineGeometry()
- : QQuick3DGeometry()
+ : GeometryBase()
{
}
@@ -41,19 +39,6 @@ LineGeometry::~LineGeometry()
{
}
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-QString LineGeometry::name() const
-{
- return objectName();
-}
-
-void LineGeometry::setName(const QString &name)
-{
- setObjectName(name);
- emit nameChanged();
-}
-#endif
-
QVector3D LineGeometry::startPos() const
{
return m_startPos;
@@ -69,7 +54,7 @@ void LineGeometry::setStartPos(const QVector3D &pos)
if (pos != m_startPos) {
m_startPos = pos;
emit startPosChanged();
- update();
+ updateGeometry();
}
}
@@ -78,16 +63,13 @@ void LineGeometry::setEndPos(const QVector3D &pos)
if (pos != m_endPos) {
m_endPos = pos;
emit endPosChanged();
- update();
+ updateGeometry();
}
}
-QSSGRenderGraphObject *LineGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
+void LineGeometry::doUpdateGeometry()
{
- setStride(12); // Silence a warning
- node = QQuick3DGeometry::updateSpatialNode(node);
- QSSGRenderGeometry *geometry = static_cast(node);
- geometry->clear();
+ GeometryBase::doUpdateGeometry();
QByteArray vertexData;
vertexData.resize(2 * 3 * 4); // 2 vertices of 3 floats each 4 bytes
@@ -100,20 +82,8 @@ QSSGRenderGraphObject *LineGeometry::updateSpatialNode(QSSGRenderGraphObject *no
dataPtr[4] = m_endPos[1];
dataPtr[5] = m_endPos[2];
- geometry->setStride(12);
-#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
- geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::F32Type);
- geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
-#else
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
- QSSGMesh::Mesh::ComponentType::Float32);
- geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
-#endif
- geometry->setVertexData(vertexData);
- geometry->setBounds(m_startPos, m_endPos);
-
- return node;
+ setVertexData(vertexData);
+ setBounds(m_startPos, m_endPos);
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.h
index df83f89b258..034cce0c934 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/linegeometry.h
@@ -27,29 +27,19 @@
#ifdef QUICK3D_MODULE
-#include
+#include "geometrybase.h"
+
#include
namespace QmlDesigner {
namespace Internal {
-class LineGeometry : public QQuick3DGeometry
+class LineGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QVector3D startPos READ startPos WRITE setStartPos NOTIFY startPosChanged)
Q_PROPERTY(QVector3D endPos READ endPos WRITE setEndPos NOTIFY endPosChanged)
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- // Name property was removed in Qt 6, so define it here for compatibility.
- // Name maps to object name.
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
-public:
- QString name() const;
- void setName(const QString &name);
-signals:
- void nameChanged();
-#endif
-
public:
LineGeometry();
~LineGeometry() override;
@@ -66,7 +56,7 @@ signals:
void endPosChanged();
protected:
- QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
+ void doUpdateGeometry() override;
private:
QVector3D m_startPos;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp
index 7e340ff25dc..9e2bd181dbd 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.cpp
@@ -27,7 +27,6 @@
#include "selectionboxgeometry.h"
-#include
#include
#include
#include
@@ -36,7 +35,6 @@
#include
#include
#include
-#include
#include
@@ -49,7 +47,7 @@ static const QVector3D maxVec = QVector3D(floatMax, floatMax, floatMax);
static const QVector3D minVec = QVector3D(floatMin, floatMin, floatMin);
SelectionBoxGeometry::SelectionBoxGeometry()
- : QQuick3DGeometry()
+ : GeometryBase()
{
}
@@ -60,19 +58,6 @@ SelectionBoxGeometry::~SelectionBoxGeometry()
m_connections.clear();
}
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-QString SelectionBoxGeometry::name() const
-{
- return objectName();
-}
-
-void SelectionBoxGeometry::setName(const QString &name)
-{
- setObjectName(name);
- emit nameChanged();
-}
-#endif
-
QQuick3DNode *SelectionBoxGeometry::targetNode() const
{
return m_targetNode;
@@ -93,11 +78,26 @@ bool QmlDesigner::Internal::SelectionBoxGeometry::isEmpty() const
return m_isEmpty;
}
+void SelectionBoxGeometry::setEmpty(bool isEmpty)
+{
+ if (m_isEmpty != isEmpty) {
+ m_isEmpty = isEmpty;
+ emit isEmptyChanged();
+ }
+}
+
QSSGBounds3 SelectionBoxGeometry::bounds() const
{
return m_bounds;
}
+void SelectionBoxGeometry::clearGeometry()
+{
+ clear();
+ setStride(12); // To avoid div by zero inside QtQuick3D
+ setEmpty(true);
+}
+
void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode)
{
if (m_targetNode == targetNode)
@@ -109,17 +109,18 @@ void SelectionBoxGeometry::setTargetNode(QQuick3DNode *targetNode)
if (auto model = qobject_cast(m_targetNode)) {
QObject::connect(model, &QQuick3DModel::sourceChanged,
- this, &SelectionBoxGeometry::targetMeshUpdated, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::spatialNodeUpdateNeeded, Qt::QueuedConnection);
QObject::connect(model, &QQuick3DModel::geometryChanged,
- this, &SelectionBoxGeometry::targetMeshUpdated, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::spatialNodeUpdateNeeded, Qt::QueuedConnection);
}
if (m_targetNode) {
QObject::connect(m_targetNode, &QQuick3DNode::parentChanged,
- this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::spatialNodeUpdateNeeded, Qt::QueuedConnection);
}
+ clearGeometry();
emit targetNodeChanged();
- update();
+ spatialNodeUpdateNeeded();
}
void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode)
@@ -130,7 +131,7 @@ void SelectionBoxGeometry::setRootNode(QQuick3DNode *rootNode)
m_rootNode = rootNode;
emit rootNodeChanged();
- update();
+ spatialNodeUpdateNeeded();
}
void SelectionBoxGeometry::setView3D(QQuick3DViewport *view)
@@ -141,24 +142,31 @@ void SelectionBoxGeometry::setView3D(QQuick3DViewport *view)
m_view3D = view;
emit view3DChanged();
- update();
+ spatialNodeUpdateNeeded();
}
QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
{
- // If target node mesh has been updated, we need to defer updating the box geometry
- // to the next frame to ensure target node geometry has been updated
- if (m_meshUpdatePending) {
- QTimer::singleShot(0, this, &SelectionBoxGeometry::update);
- m_meshUpdatePending = false;
- return node;
+
+ if (m_spatialNodeUpdatePending) {
+ m_spatialNodeUpdatePending = false;
+ updateGeometry();
}
- setStride(12); // Silence a warning
- node = QQuick3DGeometry::updateSpatialNode(node);
- QSSGRenderGeometry *geometry = static_cast(node);
+ return QQuick3DGeometry::updateSpatialNode(node);
+}
+
+void SelectionBoxGeometry::doUpdateGeometry()
+{
+ // Some changes require a frame to be rendered for us to be able to calculate geometry,
+ // so defer calculations until after next frame.
+ if (m_spatialNodeUpdatePending) {
+ update();
+ return;
+ }
+
+ GeometryBase::doUpdateGeometry();
- geometry->clear();
for (auto &connection : qAsConst(m_connections))
QObject::disconnect(connection);
m_connections.clear();
@@ -186,15 +194,10 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb
rootRN->localTransform = m;
rootRN->markDirty(QSSGRenderNode::TransformDirtyFlag::TransformNotDirty);
rootRN->calculateGlobalVariables();
- m_spatialNodeUpdatePending = false;
} else if (!m_spatialNodeUpdatePending) {
+ // Necessary spatial nodes do not yet exist. Defer selection box creation one frame.
m_spatialNodeUpdatePending = true;
- // A necessary spatial node doesn't yet exist. Defer selection box creation one frame.
- // Note: We don't share pending flag with target mesh update, which is checked and
- // cleared at the beginning of this method, as there would be potential for an endless
- // loop in case we can't ever resolve one of the spatial nodes.
- QTimer::singleShot(0, this, &SelectionBoxGeometry::update);
- return node;
+ update();
}
getBounds(m_targetNode, vertexData, indexData, minBounds, maxBounds);
appendVertexData(QMatrix4x4(), vertexData, indexData, minBounds, maxBounds);
@@ -212,34 +215,15 @@ QSSGRenderGraphObject *SelectionBoxGeometry::updateSpatialNode(QSSGRenderGraphOb
appendVertexData(QMatrix4x4(), vertexData, indexData, minBounds, maxBounds);
}
- geometry->setStride(12);
-#if QT_VERSION < QT_VERSION_CHECK(6, 1, 0)
- geometry->addAttribute(QSSGRenderGeometry::Attribute::PositionSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::F32Type);
- geometry->addAttribute(QSSGRenderGeometry::Attribute::IndexSemantic, 0,
- QSSGRenderGeometry::Attribute::ComponentType::U16Type);
- geometry->setPrimitiveType(QSSGRenderGeometry::Lines);
-#else
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::PositionSemantic, 0,
- QSSGMesh::Mesh::ComponentType::Float32);
- geometry->addAttribute(QSSGMesh::RuntimeMeshData::Attribute::IndexSemantic, 0,
- QSSGMesh::Mesh::ComponentType::UnsignedInt16);
- geometry->setPrimitiveType(QSSGMesh::Mesh::DrawMode::Lines);
-#endif
- geometry->setVertexData(vertexData);
- geometry->setIndexData(indexData);
- geometry->setBounds(minBounds, maxBounds);
+ addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0,
+ QQuick3DGeometry::Attribute::U16Type);
+ setVertexData(vertexData);
+ setIndexData(indexData);
+ setBounds(minBounds, maxBounds);
m_bounds = QSSGBounds3(minBounds, maxBounds);
- bool empty = minBounds.isNull() && maxBounds.isNull();
- if (m_isEmpty != empty) {
- m_isEmpty = empty;
- // Delay notification until we're done with spatial node updates
- QTimer::singleShot(0, this, &SelectionBoxGeometry::isEmptyChanged);
- }
-
- return node;
+ setEmpty(minBounds.isNull() && maxBounds.isNull());
}
void SelectionBoxGeometry::getBounds(
@@ -405,18 +389,19 @@ void SelectionBoxGeometry::appendVertexData(const QMatrix4x4 &m, QByteArray &ver
void SelectionBoxGeometry::trackNodeChanges(QQuick3DNode *node)
{
m_connections << QObject::connect(node, &QQuick3DNode::sceneScaleChanged,
- this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::sceneRotationChanged,
- this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::scenePositionChanged,
- this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
m_connections << QObject::connect(node, &QQuick3DNode::pivotChanged,
- this, &SelectionBoxGeometry::update, Qt::QueuedConnection);
+ this, &SelectionBoxGeometry::updateGeometry, Qt::QueuedConnection);
}
-void SelectionBoxGeometry::targetMeshUpdated()
+void SelectionBoxGeometry::spatialNodeUpdateNeeded()
{
- m_meshUpdatePending = true;
+ m_spatialNodeUpdatePending = true;
+ clearGeometry();
update();
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h
index 947ef7d54ab..ff173942f1d 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/selectionboxgeometry.h
@@ -27,15 +27,16 @@
#ifdef QUICK3D_MODULE
+#include "geometrybase.h"
+
#include
-#include
#include
#include
namespace QmlDesigner {
namespace Internal {
-class SelectionBoxGeometry : public QQuick3DGeometry
+class SelectionBoxGeometry : public GeometryBase
{
Q_OBJECT
Q_PROPERTY(QQuick3DNode *targetNode READ targetNode WRITE setTargetNode NOTIFY targetNodeChanged)
@@ -43,17 +44,6 @@ class SelectionBoxGeometry : public QQuick3DGeometry
Q_PROPERTY(QQuick3DViewport *view3D READ view3D WRITE setView3D NOTIFY view3DChanged)
Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- // Name property was removed in Qt 6, so define it here for compatibility.
- // Name maps to object name.
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
-public:
- QString name() const;
- void setName(const QString &name);
-signals:
- void nameChanged();
-#endif
-
public:
SelectionBoxGeometry();
~SelectionBoxGeometry() override;
@@ -62,6 +52,7 @@ public:
QQuick3DNode *rootNode() const;
QQuick3DViewport *view3D() const;
bool isEmpty() const;
+ void setEmpty(bool isEmpty);
QSSGBounds3 bounds() const;
@@ -78,6 +69,7 @@ signals:
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
+ void doUpdateGeometry() override;
private:
void getBounds(QQuick3DNode *node, QByteArray &vertexData,
@@ -85,7 +77,8 @@ private:
void appendVertexData(const QMatrix4x4 &m, QByteArray &vertexData, QByteArray &indexData,
const QVector3D &minBounds, const QVector3D &maxBounds);
void trackNodeChanges(QQuick3DNode *node);
- void targetMeshUpdated();
+ void spatialNodeUpdateNeeded();
+ void clearGeometry();
QQuick3DNode *m_targetNode = nullptr;
QQuick3DViewport *m_view3D = nullptr;
@@ -94,7 +87,6 @@ private:
QVector m_connections;
QSSGBounds3 m_bounds;
bool m_spatialNodeUpdatePending = false;
- bool m_meshUpdatePending = false;
};
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp
index d3dc35f2210..2dd653273cd 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp
@@ -96,11 +96,13 @@ void IconRenderer::setupRender()
if (auto scene = qobject_cast(iconItem)) {
qmlRegisterType("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry");
QQmlComponent component(engine);
- component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/IconRenderer3D.qml"));
- m_containerItem = qobject_cast(component.create());
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt5/IconRenderer3D.qml"));
+ m_containerItem = qobject_cast(component.create());
DesignerSupport::setRootItem(view, m_containerItem);
#else
+ component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt6/IconRenderer3D.qml"));
+ m_containerItem = qobject_cast(component.create());
m_window->contentItem()->setSize(m_containerItem->size());
m_window->setGeometry(0, 0, m_containerItem->width(), m_containerItem->height());
m_containerItem->setParentItem(m_window->contentItem());
@@ -133,7 +135,7 @@ void IconRenderer::setupRender()
resizeContent(m_size);
if (!initRhi())
QTimer::singleShot(0, qGuiApp, &QGuiApplication::quit);
- QTimer::singleShot(0, this, &IconRenderer::createIcon);
+ QTimer::singleShot(0, this, &IconRenderer::startCreateIcon);
} else {
QTimer::singleShot(0, qGuiApp, &QGuiApplication::quit);
}
@@ -142,25 +144,41 @@ void IconRenderer::setupRender()
}
}
-void IconRenderer::createIcon()
+void IconRenderer::startCreateIcon()
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
m_designerSupport.refFromEffectItem(m_containerItem, false);
#endif
QQuickDesignerSupportItems::disableNativeTextRendering(m_containerItem);
+
+ if (m_is3D)
+ QTimer::singleShot(0, this, &IconRenderer::focusCamera);
+ else
+ QTimer::singleShot(0, this, &IconRenderer::finishCreateIcon);
+}
+
+void IconRenderer::focusCamera()
+{
#ifdef QUICK3D_MODULE
- if (m_is3D) {
- // Render once to make sure scene is up to date before we set up the selection box
- render({});
- QMetaObject::invokeMethod(m_containerItem, "setSceneToBox");
- int tries = 0;
- while (tries < 10) {
- ++tries;
- render({});
- QMetaObject::invokeMethod(m_containerItem, "fitAndHideBox");
- }
+ if (m_focusStep >= 10) {
+ QTimer::singleShot(0, this, &IconRenderer::finishCreateIcon);
+ return;
}
+
+ render({});
+
+ if (m_focusStep == 0) {
+ QMetaObject::invokeMethod(m_containerItem, "setSceneToBox");
+ } else if (m_focusStep > 1 && m_focusStep < 10) {
+ QMetaObject::invokeMethod(m_containerItem, "fitAndHideBox");
+ }
+ ++m_focusStep;
+ QTimer::singleShot(0, this, &IconRenderer::focusCamera);
#endif
+}
+
+void IconRenderer::finishCreateIcon()
+{
QFileInfo fi(m_filePath);
// Render regular size image
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h
index 6f5e36720d0..64880249305 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h
@@ -53,7 +53,9 @@ public:
void setupRender();
private:
- void createIcon();
+ void startCreateIcon();
+ void focusCamera();
+ void finishCreateIcon();
void render(const QString &fileName);
void resizeContent(int dimensions);
bool initRhi();
@@ -66,6 +68,7 @@ private:
QQuickItem *m_containerItem = nullptr;
DesignerSupport m_designerSupport;
bool m_is3D = false;
+ int m_focusStep = 0;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QQuickRenderControl *m_renderControl = nullptr;
QRhi *m_rhi = nullptr;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index 743b06a6ed7..94f71cd52ff 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -373,6 +373,8 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
#ifdef QUICK3D_MODULE
qmlRegisterRevision("MouseArea3D", 1, 0);
qmlRegisterType("MouseArea3D", 1, 0, "MouseArea3D");
+ qmlRegisterUncreatableType("GeometryBase", 1, 0, "GeometryBase",
+ "Abstract Base Class");
qmlRegisterType("CameraGeometry", 1, 0, "CameraGeometry");
qmlRegisterType("LightUtils", 1, 0, "LightGeometry");
qmlRegisterType("GridGeometry", 1, 0, "GridGeometry");
@@ -390,8 +392,11 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
new QmlDesigner::Internal::IconGizmoImageProvider);
m_3dHelper = helper;
- createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/EditView3D.qml"), m_editView3DData);
-
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/EditView3D.qml"), m_editView3DData);
+#else
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt5/EditView3D.qml"), m_editView3DData);
+#endif
if (m_editView3DData.rootItem)
helper->setParent(m_editView3DData.rootItem);
#endif
@@ -795,8 +800,7 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView()
#else
if (m_render2D) {
// Render 2D content, as it might be used by 3D content
- grabWindow();
- m_render2D = false;
+ m_render2D = !renderWindow();
}
renderImage = grabRenderControl(m_editView3DData);
#endif
@@ -1190,12 +1194,22 @@ void Qt5InformationNodeInstanceServer::initializeAuxiliaryViews()
#ifdef QUICK3D_MODULE
if (isQuick3DMode())
createEditView3D();
- createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode3DImageView.qml"),
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml"),
+ m_modelNode3DImageViewData);
+#else
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt5/ModelNode3DImageView.qml"),
m_modelNode3DImageViewData);
#endif
+#endif
- createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode2DImageView.qml"),
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode2DImageView.qml"),
m_modelNode2DImageViewData);
+#else
+ createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt5/ModelNode2DImageView.qml"),
+ m_modelNode2DImageViewData);
+#endif
m_modelNode2DImageViewData.window->setDefaultAlphaBuffer(true);
m_modelNode2DImageViewData.window->setColor(Qt::transparent);
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
index a669aad6fc9..da9f7ed8233 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
@@ -308,6 +308,23 @@ QImage Qt5NodeInstanceServer::grabRenderControl(RenderViewData &viewData)
return renderImage;
}
+// This method simply renders the window without grabbing it
+bool Qt5NodeInstanceServer::renderWindow()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (!m_viewData.rootItem || (m_viewData.bufferDirty && !initRhi(m_viewData)))
+ return false;
+
+ m_viewData.renderControl->polishItems();
+ m_viewData.renderControl->beginFrame();
+ m_viewData.renderControl->sync();
+ m_viewData.renderControl->render();
+ m_viewData.renderControl->endFrame();
+ return true;
+#endif
+ return false;
+}
+
QImage Qt5NodeInstanceServer::grabWindow()
{
if (m_viewData.rootItem)
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
index e6a2754f997..9a7d43635df 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
@@ -94,6 +94,7 @@ protected:
virtual bool initRhi(RenderViewData &viewData);
virtual QImage grabRenderControl(RenderViewData &viewData);
+ virtual bool renderWindow();
private:
RenderViewData m_viewData;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri
index 189324f478e..0b364d32b3e 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri
@@ -29,6 +29,9 @@ include (import3d/import3d.pri)
SOURCES += $$PWD/qml2puppetmain.cpp
RESOURCES += $$PWD/../qmlpuppet.qrc
+versionAtLeast(QT_VERSION, 6.0.0): RESOURCES += $$PWD/../editor3d_qt6.qrc
+else: RESOURCES += $$PWD/../editor3d_qt5.qrc
+
DISTFILES += Info.plist
unix:!openbsd:!osx: LIBS += -lrt # posix shared memory
diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
index e0f8dcbb80a..162c955ac14 100644
--- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
+++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc
@@ -9,58 +9,7 @@
mockfiles/SwipeView.qml
mockfiles/GenericBackend.qml
mockfiles/Dialog.qml
- mockfiles/IconRenderer3D.qml
- mockfiles/EditView3D.qml
- mockfiles/EditCameraController.qml
- mockfiles/Arrow.qml
- mockfiles/AutoScaleHelper.qml
- mockfiles/MoveGizmo.qml
- mockfiles/CameraFrustum.qml
- mockfiles/CameraGizmo.qml
- mockfiles/LightModel.qml
- mockfiles/LightIconGizmo.qml
- mockfiles/LightGizmo.qml
- mockfiles/AdjustableArrow.qml
- mockfiles/FadeHandle.qml
- mockfiles/AreaLightHandle.qml
- mockfiles/SpotLightHandle.qml
- mockfiles/IconGizmo.qml
- mockfiles/Overlay2D.qml
- mockfiles/HelperGrid.qml
- mockfiles/DirectionalDraggable.qml
- mockfiles/PlanarDraggable.qml
- mockfiles/PlanarMoveHandle.qml
- mockfiles/PlanarScaleHandle.qml
- mockfiles/ScaleRod.qml
- mockfiles/ScaleGizmo.qml
mockfiles/ToolBarButton.qml
mockfiles/ToggleButton.qml
- mockfiles/RotateGizmo.qml
- mockfiles/RotateRing.qml
- mockfiles/SceneView3D.qml
- mockfiles/SelectionBox.qml
- mockfiles/AxisHelper.qml
- mockfiles/AxisHelperArm.qml
- mockfiles/Line3D.qml
- mockfiles/ModelNode3DImageView.qml
- mockfiles/ModelNode2DImageView.qml
- mockfiles/MaterialNodeView.qml
- mockfiles/ModelNodeView.qml
- mockfiles/NodeNodeView.qml
- mockfiles/meshes/arrow.mesh
- mockfiles/meshes/scalerod.mesh
- mockfiles/meshes/ring.mesh
- mockfiles/meshes/ringselect.mesh
- mockfiles/meshes/axishelper.mesh
- mockfiles/images/editor_camera.png
- mockfiles/images/editor_camera@2x.png
- mockfiles/images/area.png
- mockfiles/images/area@2x.png
- mockfiles/images/directional.png
- mockfiles/images/directional@2x.png
- mockfiles/images/point.png
- mockfiles/images/point@2x.png
- mockfiles/images/spot.png
- mockfiles/images/spot@2x.png
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
index a29a2716e5b..cb9c5bce84d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml
@@ -111,7 +111,7 @@ Section {
}
PropertyLabel {
- text: qsTr("Focus on Tab")
+ text: qsTr("Focus on tab")
tooltip: qsTr("Adds the component to the tab focus chain.")
disabledState: !backendValues.activeFocusOnTab.isAvailable
}
@@ -129,7 +129,7 @@ Section {
}
PropertyLabel {
- text: qsTr("Baseline Offset")
+ text: qsTr("Baseline offset")
tooltip: qsTr("Position of the component's baseline in local coordinates.")
disabledState: !backendValues.baselineOffset.isAvailable
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AlignDistributeSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AlignDistributeSection.qml
index 0b435c48eab..e2228795935 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AlignDistributeSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AlignDistributeSection.qml
@@ -124,7 +124,7 @@ Section {
}
}
- PropertyLabel { text: qsTr("Distribute Objects") }
+ PropertyLabel { text: qsTr("Distribute objects") }
SecondColumnLayout {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
@@ -196,7 +196,7 @@ Section {
}
}
- PropertyLabel { text: qsTr("Distribute Spacing") }
+ PropertyLabel { text: qsTr("Distribute spacing") }
SecondColumnLayout {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
@@ -275,7 +275,7 @@ Section {
}
}
- PropertyLabel { text: qsTr("Pixel Spacing") }
+ PropertyLabel { text: qsTr("Pixel spacing") }
SecondColumnLayout {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
@@ -318,7 +318,7 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("Key Object") }
+ PropertyLabel { text: qsTr("Key object") }
SecondColumnLayout {
ComboBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml
index 1d4e8fe87ce..5aa93dd2f2e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AnimatedImageSpecifics.qml
@@ -69,7 +69,7 @@ Column {
PropertyLabel {
text: qsTr("Playing")
- tooltip: qsTr("Whether the animation is playing and/or paused.")
+ tooltip: qsTr("Whether the animation is playing or paused.")
disabledState: !backendValues.playing.isAvailable && !backendValues.paused.isAvailable
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ComponentSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ComponentSection.qml
index f723adaf567..266ac2b0274 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ComponentSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ComponentSection.qml
@@ -103,7 +103,7 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("id") }
+ PropertyLabel { text: qsTr("ID") }
SecondColumnLayout {
Spacer { implicitWidth: StudioTheme.Values.actionIndicatorWidth }
@@ -161,7 +161,7 @@ Section {
when: hasAliasExport
PropertyChanges {
target: aliasIndicatorIcon
- color: StudioTheme.Values.themeLinkIndicatorColorInteraction
+ color: StudioTheme.Values.themeAliasIconChecked
}
},
State {
@@ -187,7 +187,7 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("id Annotation") }
+ PropertyLabel { text: qsTr("Name") }
SecondColumnLayout {
enabled: !modelNodeBackend.multiSelection
@@ -205,7 +205,7 @@ Section {
- removeAnnotationButton.width
+ 2 * StudioTheme.Values.border
backendValue: backendValues.customId__AUX
- placeholderText: qsTr("customId")
+ placeholderText: qsTr("Descriptive text")
text: backendValue.value
showTranslateCheckBox: false
showExtendedFunctionButton: false
@@ -233,7 +233,7 @@ Section {
implicitWidth: StudioTheme.Values.singleControlColumnWidth
width: StudioTheme.Values.singleControlColumnWidth
visible: !annotationEditor.hasAuxData
- buttonIcon: qsTr("add")
+ buttonIcon: qsTr("Add Annotation")
iconFont: StudioTheme.Constants.font
onClicked: annotationEditor.showWidget()
onHoveredChanged: annotationEditor.checkAux()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ConnectionsSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ConnectionsSpecifics.qml
index 0eaee579db5..98d03a35458 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ConnectionsSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ConnectionsSpecifics.qml
@@ -52,7 +52,7 @@ Column {
Label {
text: qsTr("Ignore unknown signals")
- tooltip: qsTr("A connection to a non-existent signal produces runtime errors. If this property is set to true, such errors are ignored")
+ tooltip: qsTr("Ignores runtime errors produced by connections to non-existent signals.")
}
SecondColumnLayout {
CheckBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml
index b9f36804145..0a92222b578 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/BusyIndicatorSpecifics.qml
@@ -44,7 +44,7 @@ Column {
width: parent.width
Section {
- caption: qsTr("Busy indicator")
+ caption: qsTr("Busy Indicator")
width: parent.width
@@ -56,7 +56,7 @@ Column {
SecondColumnLayout {
CheckBox {
- text: qsTr("live")
+ text: qsTr("Live")
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.running
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml
index 1985f3ccffe..edf449fcaf7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/CheckSection.qml
@@ -41,7 +41,7 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Section {
- caption: qsTr("Check box")
+ caption: qsTr("Check Box")
anchors.left: parent.left
anchors.right: parent.right
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml
index 2a72cb6436f..995997af65a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DelayButtonSpecifics.qml
@@ -43,7 +43,7 @@ Column {
width: parent.width
Section {
- caption: qsTr("Delay button")
+ caption: qsTr("Delay Button")
width: parent.width
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml
index e5ddf049504..e3fae4a024a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/DialSpecifics.qml
@@ -68,7 +68,7 @@ Column {
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
CheckBox {
- text: qsTr("live")
+ text: qsTr("Live")
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.live
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml
index fa746a930e0..33b98e44814 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/FrameSpecifics.qml
@@ -51,7 +51,7 @@ Column {
PaddingSection {}
FontSection {
- caption: qsTr("Font inheritance")
+ caption: qsTr("Font Inheritance")
expanded: false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml
index 67618f58782..a8b5801fde1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/GroupBoxSpecifics.qml
@@ -43,7 +43,7 @@ Column {
width: parent.width
Section {
- caption: qsTr("Group box")
+ caption: qsTr("Group Box")
width: parent.width
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml
index ffe81ef7fa4..fc5c0e5f0d5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ItemDelegateSection.qml
@@ -42,7 +42,7 @@ import StudioTheme 1.0 as StudioTheme
Section {
id: section
- caption: qsTr("Item delegate")
+ caption: qsTr("Item Delegate")
anchors.left: parent.left
anchors.right: parent.right
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml
index 426e35b78f9..1f188f4e2ba 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PageIndicatorSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Section {
width: parent.width
- caption: qsTr("PageIndicator")
+ caption: qsTr("Page Indicator")
SectionLayout {
PropertyLabel {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml
index 2b1ad460026..dde8aab73d1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/PaneSpecifics.qml
@@ -49,7 +49,7 @@ Column {
PaddingSection {}
FontSection {
- caption: qsTr("Font inheritance")
+ caption: qsTr("Font Inheritance")
expanded: false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml
index c53893b861b..104803b72f2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ProgressBarSpecifics.qml
@@ -43,7 +43,7 @@ Column {
width: parent.width
Section {
- caption: qsTr("Progress bar")
+ caption: qsTr("Progress Bar")
width: parent.width
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml
index 92e814a624f..31e32eeed7a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RadioDelegateSpecifics.qml
@@ -43,7 +43,7 @@ Column {
width: parent.width
ItemDelegateSection {
- caption: qsTr("Radio delegate")
+ caption: qsTr("Radio Delegate")
}
AbstractButtonSection {}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml
index d51943cb4b1..430a7b49987 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RangeSliderSpecifics.qml
@@ -43,7 +43,7 @@ Column {
width: parent.width
Section {
- caption: qsTr("Range slider")
+ caption: qsTr("Range Slider")
width: parent.width
@@ -67,7 +67,7 @@ Column {
Spacer { implicitWidth: StudioTheme.Values.twoControlColumnGap }
CheckBox {
- text: qsTr("live")
+ text: qsTr("Live")
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.live
@@ -156,7 +156,7 @@ Column {
PropertyLabel {
text: qsTr("Drag threshold")
- tooltip: qsTr("The threshold (in logical pixels) at which a Drag event will be initiated.")
+ tooltip: qsTr("The threshold (in logical pixels) at which a drag event will be initiated.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml
index 6a7fbda94de..85ddd4fab50 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/RoundButtonSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Section {
width: parent.width
- caption: qsTr("Round button")
+ caption: qsTr("Round Button")
SectionLayout {
PropertyLabel {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml
index 7088f08faf2..5de17cb387b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ScrollViewSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Section {
width: parent.width
- caption: qsTr("Scroll view")
+ caption: qsTr("Scroll View")
SectionLayout {
PropertyLabel { text: qsTr("Content size") }
@@ -96,7 +96,7 @@ Column {
PaddingSection {}
FontSection {
- caption: qsTr("Font inheritance")
+ caption: qsTr("Font Inheritance")
expanded: false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml
index 577693824f0..4bc16353bc5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SliderSpecifics.qml
@@ -66,7 +66,7 @@ Column {
Spacer { implicitWidth: StudioTheme.Values.twoControlColumnGap }
CheckBox {
- text: qsTr("live")
+ text: qsTr("Live")
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.live
@@ -135,7 +135,7 @@ Column {
PropertyLabel {
text: qsTr("Drag threshold")
- tooltip: qsTr("The threshold (in logical pixels) at which a Drag event will be initiated.")
+ tooltip: qsTr("The threshold (in logical pixels) at which a drag event will be initiated.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml
index c6bb8362a60..01322a57ba2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SpinBoxSpecifics.qml
@@ -44,12 +44,12 @@ Column {
Section {
width: parent.width
- caption: qsTr("Spin box")
+ caption: qsTr("Spin Box")
SectionLayout {
PropertyLabel {
text: qsTr("Value")
- tooltip: qsTr("The current value of the spinbox.")
+ tooltip: qsTr("The current value of the spin box.")
}
SecondColumnLayout {
@@ -67,7 +67,7 @@ Column {
PropertyLabel {
text: qsTr("From")
- tooltip: qsTr("The starting value of the spinbox range.")
+ tooltip: qsTr("The starting value of the spin box range.")
}
SecondColumnLayout {
@@ -85,7 +85,7 @@ Column {
PropertyLabel {
text: qsTr("To")
- tooltip: qsTr("The ending value of the spinbox range.")
+ tooltip: qsTr("The ending value of the spin box range.")
}
SecondColumnLayout {
@@ -103,7 +103,7 @@ Column {
PropertyLabel {
text: qsTr("Step size")
- tooltip: qsTr("The step size of the spinbox.")
+ tooltip: qsTr("The step size of the spin box.")
}
SecondColumnLayout {
@@ -121,7 +121,7 @@ Column {
PropertyLabel {
text: qsTr("Editable")
- tooltip: qsTr("Whether the spinbox is editable.")
+ tooltip: qsTr("Whether the spin box is editable.")
}
SecondColumnLayout {
@@ -137,7 +137,7 @@ Column {
PropertyLabel {
text: qsTr("Wrap")
- tooltip: qsTr("Whether the spinbox wraps.")
+ tooltip: qsTr("Whether the spin box values wrap.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml
index 37ba9bb66c9..3f8bb535cf5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/StackViewSpecifics.qml
@@ -47,7 +47,7 @@ Column {
PaddingSection {}
FontSection {
- caption: qsTr("Font inheritance")
+ caption: qsTr("Font Inheritance")
expanded: false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml
index 525b61dc640..aab4f96a29e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/SwipeViewSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Section {
width: parent.width
- caption: qsTr("Swipe view")
+ caption: qsTr("Swipe View")
SectionLayout {
PropertyLabel {
@@ -90,7 +90,7 @@ Column {
PaddingSection {}
FontSection {
- caption: qsTr("Font inheritance")
+ caption: qsTr("Font Inheritance")
expanded: false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml
index 5c5ff6d4431..4d465955066 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TabBarSpecifics.qml
@@ -45,12 +45,12 @@ Column {
Section {
width: parent.width
- caption: qsTr("Tab bar")
+ caption: qsTr("Tab Bar")
SectionLayout {
PropertyLabel {
text: qsTr("Position")
- tooltip: qsTr("Position of the tabbar.")
+ tooltip: qsTr("Position of the tab bar.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml
index e5d7edb79fe..3c4c0dc8dc4 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextFieldSpecifics.qml
@@ -44,7 +44,7 @@ Column {
width: parent.width
TextSection {
- caption: qsTr("Text field")
+ caption: qsTr("Text Field")
}
CharacterSection {}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml
index 7e23e522283..e5b2bcae655 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TextSection.qml
@@ -41,7 +41,7 @@ import StudioTheme 1.0 as StudioTheme
Section {
width: parent.width
- caption: qsTr("Text area")
+ caption: qsTr("Text Area")
SectionLayout {
PropertyLabel {
@@ -62,7 +62,7 @@ Section {
PropertyLabel {
text: qsTr("Placeholder color")
- tooltip: qsTr("Placeholder text color")
+ tooltip: qsTr("Placeholder text color.")
}
ColorEditor {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml
index 582f2120c3a..445c3bc256b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolBarSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Section {
width: parent.width
- caption: qsTr("Tool bar")
+ caption: qsTr("Tool Bar")
SectionLayout {
PropertyLabel {
@@ -74,7 +74,7 @@ Column {
PaddingSection {}
FontSection {
- caption: qsTr("Font inheritance")
+ caption: qsTr("Font Inheritance")
expanded: false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml
index 0c456d8c76a..53345e711a5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/ToolSeparatorSpecifics.qml
@@ -44,7 +44,7 @@ Column {
Section {
width: parent.width
- caption: qsTr("Tool separator")
+ caption: qsTr("Tool Separator")
SectionLayout {
PropertyLabel {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml
index d56d529ea48..487cd148606 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/TumblerSpecifics.qml
@@ -85,7 +85,7 @@ Column {
PropertyLabel {
text: qsTr("Wrap")
- tooltip: qsTr("Whether the tumbler wrap.")
+ tooltip: qsTr("Whether the tumbler values wrap.")
}
SecondColumnLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GeometrySection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GeometrySection.qml
index 8021e9c0e6a..275640af7bf 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GeometrySection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/GeometrySection.qml
@@ -30,42 +30,83 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Section {
- caption: qsTr("Geometry - 2d")
+ id: root
+ caption: qsTr("Geometry - 2D")
anchors.left: parent.left
anchors.right: parent.right
+ readonly property string disbaledTooltip: qsTr("This property is defined by an anchor or a layout.")
+
+ function positionDisabled() {
+ return anchorBackend.isFilled || anchorBackend.isInLayout
+ }
+
+ function xDisabled() {
+ return anchorBackend.leftAnchored
+ || anchorBackend.rightAnchored
+ || anchorBackend.horizontalCentered
+ }
+
+ function yDisabled() {
+ return anchorBackend.topAnchored
+ || anchorBackend.bottomAnchored
+ || anchorBackend.verticalCentered
+ }
+
+ function sizeDisabled() {
+ return anchorBackend.isFilled
+ }
+
+ function widthDisabled() {
+ return anchorBackend.leftAnchored && anchorBackend.rightAnchored
+ }
+
+ function heightDisabled() {
+ return anchorBackend.topAnchored && anchorBackend.bottomAnchored
+ }
+
SectionLayout {
PropertyLabel { text: qsTr("Position") }
SecondColumnLayout {
SpinBox {
+ id: xSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.x
maximumValue: 0xffff
minimumValue: -0xffff
decimals: 0
+ enabled: !root.positionDisabled() && !root.xDisabled()
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
- ControlLabel { text: "X" }
+ ControlLabel {
+ text: "X"
+ tooltip: xSpinBox.enabled ? "X" : root.disbaledTooltip
+ }
Spacer { implicitWidth: StudioTheme.Values.controlGap }
SpinBox {
+ id: ySpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.y
maximumValue: 0xffff
minimumValue: -0xffff
decimals: 0
+ enabled: !root.positionDisabled() && !root.yDisabled()
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
- ControlLabel { text: "Y" }
+ ControlLabel {
+ text: "Y"
+ tooltip: xSpinBox.enabled ? "Y" : root.disbaledTooltip
+ }
Spacer { implicitWidth: StudioTheme.Values.controlGap }
@@ -78,32 +119,42 @@ Section {
SecondColumnLayout {
SpinBox {
+ id: widthSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.width
maximumValue: 0xffff
minimumValue: 0
decimals: 0
+ enabled: !root.sizeDisabled() && !root.widthDisabled()
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
- ControlLabel { text: qsTr("W") }
+ ControlLabel {
+ text: qsTr("W")
+ tooltip: widthSpinBox.enabled ? qsTr("Width") : root.disbaledTooltip
+ }
Spacer { implicitWidth: StudioTheme.Values.controlGap }
SpinBox {
+ id: heightSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: backendValues.height
maximumValue: 0xffff
minimumValue: 0
decimals: 0
+ enabled: !root.sizeDisabled() && !root.heightDisabled()
}
Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
- ControlLabel { text: qsTr("H") }
+ ControlLabel {
+ text: qsTr("H")
+ tooltip: heightSpinBox.enabled ? qsTr("Height") : root.disbaledTooltip
+ }
Spacer { implicitWidth: StudioTheme.Values.controlGap }
@@ -180,7 +231,7 @@ Section {
ExpandingSpacer {}
}
- PropertyLabel { text: qsTr("Z Stack") }
+ PropertyLabel { text: qsTr("Z stack") }
SecondColumnLayout {
SpinBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml
index 2afadcf282d..063a2bbb309 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml
@@ -52,7 +52,7 @@ Section {
}
PropertyLabel {
- text: qsTr("Sampler Name")
+ text: qsTr("Sampler name")
tooltip: qsTr("Name of the effect's source texture property.")
}
@@ -185,7 +185,7 @@ Section {
}
PropertyLabel {
- text: qsTr("Texture Mirroring")
+ text: qsTr("Texture mirroring")
tooltip: qsTr("Sets how the generated OpenGL texture should be mirrored.")
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml
new file mode 100644
index 00000000000..1caca948bd4
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/ColumnLayoutSpecifics.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Column Layout")
+
+ SectionLayout {
+ PropertyLabel { text: qsTr("Column spacing") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.spacing
+ minimumValue: -4000
+ maximumValue: 4000
+ decimals: 0
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml
index e51868d78e3..57d7881bbd2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/GridLayoutSpecifics.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,113 +23,117 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
import HelperWidgets 2.0
-import QtQuick.Layouts 1.0
+import StudioTheme 1.0 as StudioTheme
-Column {
+Section {
anchors.left: parent.left
anchors.right: parent.right
+ caption: qsTr("Grid Layout")
- Section {
- anchors.left: parent.left
- anchors.right: parent.right
- caption: qsTr("GridLayout")
+ SectionLayout {
+ PropertyLabel { text: qsTr("Columns & Rows") }
-
- SectionLayout {
-
- Label {
- text: qsTr("Columns")
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.columns
+ minimumValue: 0
+ maximumValue: 2000
+ decimals: 0
}
- SecondColumnLayout {
- SpinBox {
- backendValue: backendValues.columns
- minimumValue: 0
- maximumValue: 2000
- decimals: 0
- }
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
- ExpandingSpacer {
- }
+ IconLabel { icon: StudioTheme.Constants.columnsAndRows }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlGap }
+
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.rows
+ minimumValue: 0
+ maximumValue: 2000
+ decimals: 0
}
- Label {
- text: qsTr("Rows")
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ IconLabel {
+ icon: StudioTheme.Constants.columnsAndRows
+ rotation: 90
}
- SecondColumnLayout {
- SpinBox {
- backendValue: backendValues.rows
- minimumValue: 0
- maximumValue: 2000
- decimals: 0
- }
+ ExpandingSpacer {}
+ }
- ExpandingSpacer {
- }
+ PropertyLabel { text: qsTr("Spacing") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.columnSpacing
+ minimumValue: -4000
+ maximumValue: 4000
+ decimals: 0
}
- Label {
- text: qsTr("Flow")
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ IconLabel { icon: StudioTheme.Constants.columnsAndRows }
+
+ Spacer { implicitWidth: StudioTheme.Values.controlGap }
+
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.rowSpacing
+ minimumValue: -4000
+ maximumValue: 4000
+ decimals: 0
}
- SecondColumnLayout {
- ComboBox {
- model: ["LeftToRight", "TopToBottom"]
- backendValue: backendValues.flow
- Layout.fillWidth: true
- scope: "GridLayout"
- }
+ Spacer { implicitWidth: StudioTheme.Values.controlLabelGap }
+
+ IconLabel {
+ icon: StudioTheme.Constants.columnsAndRows
+ rotation: 90
}
- Label {
- text: qsTr("Layout Direction")
+ ExpandingSpacer {}
+ }
+
+ PropertyLabel { text: qsTr("Flow") }
+
+ SecondColumnLayout {
+ ComboBox {
+ model: ["LeftToRight", "TopToBottom"]
+ backendValue: backendValues.flow
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ scope: "GridLayout"
}
- SecondColumnLayout {
- ComboBox {
- model: ["LeftToRight", "RightToLeft"]
- backendValue: backendValues.layoutDirection
- Layout.fillWidth: true
- scope: "Qt"
- }
+ ExpandingSpacer {}
+ }
+ PropertyLabel { text: qsTr("Layout direction") }
+
+ SecondColumnLayout {
+ ComboBox {
+ model: ["LeftToRight", "RightToLeft"]
+ backendValue: backendValues.layoutDirection
+ implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ scope: "Qt"
}
-
- Label {
- text: qsTr("Row Spacing")
- }
-
- SecondColumnLayout {
- SpinBox {
- backendValue: backendValues.rowSpacing
- minimumValue: -4000
- maximumValue: 4000
- decimals: 0
- }
-
- ExpandingSpacer {
- }
- }
-
- Label {
- text: qsTr("Column Spacing")
- }
-
- SecondColumnLayout {
- SpinBox {
- backendValue: backendValues.columnSpacing
- minimumValue: -4000
- maximumValue: 4000
- decimals: 0
- }
-
- ExpandingSpacer {
- }
- }
+ ExpandingSpacer {}
}
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml
new file mode 100644
index 00000000000..1cedc5465a8
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/RowLayoutSpecifics.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Row Layout")
+
+ SectionLayout {
+ PropertyLabel { text: qsTr("Row spacing") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.spacing
+ minimumValue: -4000
+ maximumValue: 4000
+ decimals: 0
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml
new file mode 100644
index 00000000000..ace3447ba53
--- /dev/null
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Layouts/StackLayoutSpecifics.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import HelperWidgets 2.0
+import StudioTheme 1.0 as StudioTheme
+
+Section {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ caption: qsTr("Stack Layout")
+
+ SectionLayout {
+ PropertyLabel { text: qsTr("Current index") }
+
+ SecondColumnLayout {
+ SpinBox {
+ implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ + StudioTheme.Values.actionIndicatorWidth
+ backendValue: backendValues.currentIndex
+ minimumValue: 0
+ maximumValue: 1000
+ decimals: 0
+ }
+
+ ExpandingSpacer {}
+ }
+ }
+}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ListViewSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ListViewSpecifics.qml
index 40e91577b04..d6540e72d3d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ListViewSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/ListViewSpecifics.qml
@@ -43,7 +43,7 @@ Column {
SectionLayout {
PropertyLabel {
text: qsTr("Orientation")
- tooltip: qsTr("Orientation of the list")
+ tooltip: qsTr("Orientation of the list.")
}
SecondColumnLayout {
@@ -118,7 +118,7 @@ Column {
PropertyLabel {
text: qsTr("Cache")
- tooltip: qsTr("Cache buffer")
+ tooltip: qsTr("Cache buffer.")
disabledState: !backendValues.cacheBuffer.isAvailable
}
@@ -165,7 +165,7 @@ Column {
SectionLayout {
PropertyLabel {
text: qsTr("Range")
- tooltip: qsTr("Highlight range")
+ tooltip: qsTr("Highlight range.")
disabledState: !backendValues.highlightRangeMode.isAvailable
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml
index 9baf18e690d..b3eb942d4fb 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/MouseAreaSpecifics.qml
@@ -34,7 +34,7 @@ Column {
anchors.right: parent.right
Section {
- caption: qsTr("Mouse area")
+ caption: qsTr("Mouse Area")
anchors.left: parent.left
anchors.right: parent.right
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/StateSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/StateSpecifics.qml
index 7010ba2bcf1..2f7fddfd4d9 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/StateSpecifics.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/StateSpecifics.qml
@@ -52,7 +52,7 @@ Column {
Label {
text: qsTr("Name")
- tooltip: qsTr("Holds the name of the state.")
+ tooltip: qsTr("The name of the state.")
}
SecondColumnLayout {
LineEdit {
@@ -65,7 +65,7 @@ Column {
Label {
text: qsTr("Extend")
- tooltip: qsTr("Holds the state that this state extends.")
+ tooltip: qsTr("The state that this state extends.")
}
SecondColumnLayout {
LineEdit {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ActionIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ActionIndicator.qml
index f8925d00617..eda4d58b51e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ActionIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ActionIndicator.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,7 +23,7 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
import StudioControls 1.0 as StudioControls
StudioControls.ActionIndicator {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml
index f85b32ca6f8..45266780b6c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentHorizontalButtons.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,7 +23,7 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
@@ -32,9 +32,9 @@ Row {
id: alignmentHorizontalButtons
property bool blueHighlight: false
- property variant backendValue: backendValues.horizontalAlignment;
+ property variant backendValue: backendValues.horizontalAlignment
property variant value: backendValue.enumeration
- property bool baseStateFlag: isBaseState;
+ property bool baseStateFlag: isBaseState
property color __currentColor: blueHighlight ? StudioTheme.Values.themeIconColorInteraction
: StudioTheme.Values.themeIconColor
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml
index ba95a23d660..0896c67a18e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/AligmentVerticalButtons.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,7 +23,7 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
@@ -32,13 +32,9 @@ Row {
id: alignmentVerticalButtons
property bool blueHighlight: false
-
- property variant backendValue: backendValues.verticalAlignment;
-
+ property variant backendValue: backendValues.verticalAlignment
property variant value: backendValue.enumeration
-
- property bool baseStateFlag: isBaseState;
-
+ property bool baseStateFlag: isBaseState
property color __currentColor: blueHighlight ? StudioTheme.Values.themeIconColorInteraction
: StudioTheme.Values.themeIconColor
@@ -48,37 +44,32 @@ Row {
buttonAlignBottom.checked = false
if (value !== undefined) {
- if (value === "AlignTop") {
+ if (value === "AlignTop")
buttonAlignTop.checked = true
- } else if (value === "AlignVCenter") {
+ else if (value === "AlignVCenter")
buttonAlignVCenter.checked = true
- } else if (value === "AlignBottom") {
+ else if (value === "AlignBottom")
buttonAlignBottom.checked = true
- }
}
evaluate()
}
- property bool isInModel: backendValue.isInModel;
- onIsInModelChanged: {
- evaluate();
- }
- property bool isInSubState: backendValue.isInSubState;
- onIsInSubStateChanged: {
- evaluate();
- }
+ property bool isInModel: backendValue.isInModel
+ onIsInModelChanged: evaluate()
+ property bool isInSubState: backendValue.isInSubState
+ onIsInSubStateChanged: evaluate()
function evaluate() {
if (baseStateFlag) {
if (backendValue !== null && backendValue.isInModel)
- blueHighlight = true;
+ blueHighlight = true
else
- blueHighlight = false;
+ blueHighlight = false
} else {
if (backendValue !== null && backendValue.isInSubState)
- blueHighlight = true;
+ blueHighlight = true
else
- blueHighlight = false;
+ blueHighlight = false
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml
index 45ee8e65724..53a331591ea 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Button.qml
@@ -69,7 +69,7 @@ T.AbstractButton {
},
State {
name: "hovered"
- when: myButton.hovered && !myButton.pressed
+ when: myButton.enabled && myButton.hovered && !myButton.pressed
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundHover
@@ -77,7 +77,7 @@ T.AbstractButton {
},
State {
name: "pressed"
- when: myButton.hovered && myButton.pressed
+ when: myButton.enabled && myButton.hovered && myButton.pressed
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundInteraction
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow.qml
index 28851f28c40..068462441dd 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,7 +23,7 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
import QtQuick.Layouts 1.0
RowLayout {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow2.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow2.qml
index 39d8159184d..3a971b3d922 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow2.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRow2.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,22 +23,15 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
import QtQuick.Layouts 1.0
Row {
-
id: buttonRow
property bool exclusive: false
-
property int initalChecked: 0
-
property int checkedIndex: 0
signal toggled (int index, bool checked)
-
- Component.onCompleted: {
- }
-
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
index ffac673a3e3..e6151e7181d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ButtonRowButton.qml
@@ -30,44 +30,40 @@ import StudioTheme 1.0 as StudioTheme
Item {
id: buttonRowButton
+
+ property int leftPadding: 0
property bool checked: false
-
property bool roundLeftButton: true
-
property alias iconSource: image.source
+ property alias tooltip: toolTipArea.tooltip
signal clicked()
-
signal doubleClicked()
- property alias tooltip: toolTipArea.tooltip
-
width: StudioTheme.Values.height + leftPadding
height: StudioTheme.Values.height
- property int leftPadding: 0
-
function index() {
for (var i = 0; i < parent.children.length; i++) {
if (parent.children[i] === buttonRowButton)
- return i;
+ return i
}
- return -1;
+ return -1
}
function isFirst() {
- return index() === 0;
+ return index() === 0
}
function isLast() {
- return index() === (parent.children.length - 1);
+ return index() === (parent.children.length - 1)
}
Item {
anchors.fill: parent
+
RoundedPanel {
roundLeft: isFirst() && buttonRowButton.roundLeftButton
-
anchors.fill: parent
visible: checked
color: StudioTheme.Values.themeControlBackgroundInteraction
@@ -75,7 +71,6 @@ Item {
RoundedPanel {
roundLeft: isFirst()
-
anchors.fill: parent
visible: !checked
color: StudioTheme.Values.themeControlBackground
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
index 89d1a35aa04..22f8e340532 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml
@@ -635,7 +635,7 @@ SecondColumnLayout {
anchors.fill: parent
tooltip: originalColorRectangle.color
acceptedButtons: Qt.LeftButton | Qt.RightButton
- onClicked: {
+ onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton)
colorEditor.color = colorEditor.originalColor
@@ -667,7 +667,7 @@ SecondColumnLayout {
anchors.fill: parent
tooltip: newColorRectangle.color
acceptedButtons: Qt.RightButton
- onClicked: {
+ onClicked: function(mouse) {
if (mouse.button === Qt.RightButton) {
contextMenuFavorite.currentColor = colorEditor.color
contextMenuFavorite.popup()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPalette.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPalette.qml
index 6d1d9a42faf..4ff74c7aa73 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPalette.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPalette.qml
@@ -77,7 +77,7 @@ Column {
acceptedButtons: Qt.LeftButton | Qt.RightButton
tooltip: modelData
- onClicked: {
+ onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton)
root.selectedColor = colorRectangle.color
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPicker.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPicker.qml
index e1296123483..07fc29a64d3 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPicker.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorPicker.qml
@@ -206,7 +206,7 @@ Column {
preventStealing: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
- onPositionChanged: {
+ onPositionChanged: function(mouse) {
if (pressed && mouse.buttons === Qt.LeftButton) {
var xx = Math.max(0, Math.min(mouse.x, parent.width))
var yy = Math.max(0, Math.min(mouse.y, parent.height))
@@ -215,15 +215,15 @@ Column {
root.saturation = xx / parent.width
}
}
- onPressed: {
+ onPressed: function(mouse) {
if (mouse.button === Qt.LeftButton)
positionChanged(mouse)
}
- onReleased: {
+ onReleased: function(mouse) {
if (mouse.button === Qt.LeftButton)
root.updateColor()
}
- onClicked: {
+ onClicked: function(mouse) {
if (mouse.button === Qt.RightButton)
root.rightMouseButtonClicked()
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml
index 982651a11ad..87e9a7e3c02 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExpressionTextField.qml
@@ -159,7 +159,7 @@ StudioControls.TextField {
onPressed: listView.model = null
Keys.priority: Keys.BeforeItem
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
var text = textField.text
var pos = textField.cursorPosition
var explicitComplete = true
@@ -220,7 +220,7 @@ StudioControls.TextField {
listView.model = list
}
- Keys.onSpacePressed: {
+ Keys.onSpacePressed: function(event) {
if (event.modifiers & Qt.ControlModifier) {
var list = autoComplete(textField.text, textField.cursorPosition, true, textField.completeOnlyTypes)
textField.prefix = textField.text.substring(0, textField.cursorPosition)
@@ -236,7 +236,7 @@ StudioControls.TextField {
}
}
- Keys.onReturnPressed: {
+ Keys.onReturnPressed: function(event) {
event.accepted = false
if (textField.completionActive) {
textField.commitCompletion()
@@ -244,7 +244,7 @@ StudioControls.TextField {
}
}
- Keys.onEscapePressed: {
+ Keys.onEscapePressed: function(event) {
event.accepted = true
if (textField.completionActive) {
listView.model = null
@@ -253,12 +253,12 @@ StudioControls.TextField {
}
}
- Keys.onUpPressed: {
+ Keys.onUpPressed: function(event) {
listView.decrementCurrentIndex()
event.accepted = false
}
- Keys.onDownPressed: {
+ Keys.onDownPressed: function(event) {
listView.incrementCurrentIndex()
event.accepted = false
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
index 3cd452b1db4..94308e63b3b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ExtendedFunctionLogic.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,7 +23,7 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0
@@ -70,17 +70,9 @@ Item {
}
}
- onBackendValueChanged: {
- setIcon()
- }
-
- onIsBoundBackendChanged: {
- setIcon()
- }
-
- onBackendExpressionChanged: {
- setIcon()
- }
+ onBackendValueChanged: setIcon()
+ onIsBoundBackendChanged: setIcon()
+ onBackendExpressionChanged: setIcon()
Loader {
id: menuLoader
@@ -101,15 +93,11 @@ Item {
exportMenuItem.enabled = !backendValue.isAttachedProperty()
extendedFunctionButton.menuVisible = true
}
- onAboutToHide: {
- extendedFunctionButton.menuVisible = false
- }
+ onAboutToHide: extendedFunctionButton.menuVisible = false
Connections {
target: modelNodeBackend
- onSelectionChanged: {
- menu.close()
- }
+ onSelectionChanged: menu.close()
}
StudioControls.MenuItem {
@@ -121,20 +109,22 @@ Item {
extendedFunctionButton.reseted()
}
}
+
StudioControls.MenuItem {
text: qsTr("Set Binding")
onTriggered: expressionDialogLoader.show()
}
+
StudioControls.MenuItem {
id: exportMenuItem
text: qsTr("Export Property as Alias")
+ checkable: true
onTriggered: {
if (checked)
backendValue.exportPopertyAsAlias()
else
backendValue.removeAliasExport()
}
- checkable: true
}
StudioControls.MenuItem {
@@ -150,13 +140,13 @@ Item {
id: expressionDialogLoader
parent: itemPane
anchors.fill: parent
-
visible: false
active: visible
function show() {
expressionDialogLoader.visible = true
}
+
sourceComponent: Item {
id: bindingEditorParent
@@ -176,6 +166,7 @@ Item {
hideWidget()
expressionDialogLoader.visible = false
}
+
onAccepted: {
backendValue.expression = bindingEditor.text.trim()
hideWidget()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml
index 8221c57b2f7..8294068ccfd 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/FontComboBox.qml
@@ -34,6 +34,7 @@ StudioControls.ComboBox {
property variant backendValue
property color textColor: colorLogic.textColor
property string fontFilter: "*.ttf *.otf"
+ property bool showExtendedFunctionButton: true
labelColor: colorLogic.textColor
editable: true
@@ -63,9 +64,7 @@ StudioControls.ComboBox {
comboBox.model = familyNames
}
- onModelChanged: {
- editText = comboBox.backendValue.valueToString
- }
+ onModelChanged: editText = comboBox.backendValue.valueToString
ExtendedFunctionLogic {
id: extFuncLogic
@@ -76,18 +75,13 @@ StudioControls.ComboBox {
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
-
- property bool showExtendedFunctionButton: true
-
- actionIndicator.visible: showExtendedFunctionButton
+ actionIndicator.visible: comboBox.showExtendedFunctionButton
ColorLogic {
id: colorLogic
- backendValue: comboBox.backendValue
property string textValue: comboBox.backendValue.valueToString
- onTextValueChanged: {
- comboBox.editText = textValue
- }
+ backendValue: comboBox.backendValue
+ onTextValueChanged: comboBox.editText = colorLogic.textValue
}
onAccepted: {
@@ -124,7 +118,7 @@ StudioControls.ComboBox {
Component.onCompleted: {
setupModel()
- //Hack to style the text input
+ // Hack to style the text input
for (var i = 0; i < comboBox.children.length; i++) {
if (comboBox.children[i].text !== undefined) {
comboBox.children[i].color = comboBox.textColor
@@ -135,7 +129,7 @@ StudioControls.ComboBox {
}
function setColor() {
- //Hack to style the text input
+ // Hack to style the text input
for (var i = 0; i < comboBox.children.length; i++) {
if (comboBox.children[i].text !== undefined) {
comboBox.children[i].color = comboBox.textColor
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml
deleted file mode 100644
index dae40f85343..00000000000
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientDialogPopup.qml
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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.
-**
-****************************************************************************/
-
-import QtQuick 2.1
-import QtQuick.Layouts 1.0
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
-import QtQuickDesignerTheme 1.0
-
-Loader {
- id: gradientDialogLoader
- parent: itemPane
- anchors.fill: parent
-
- visible: false
- active: visible
-
- function toggle() {
- gradientDialogLoader.visible = !gradientDialogLoader.visible
- }
-
- property Component content
-
- property int dialogHeight: 240
- property int dialogWidth: 400
-
- sourceComponent: Component {
- FocusScope {
- id: popup
-
- Keys.onEscapePressed: {
- event.accepted = true
- gradientDialogLoader.visible = false
- }
-
- Component.onCompleted: {
- popup.forceActiveFocus()
- }
-
- Rectangle {
- anchors.fill: parent
- color: StudioTheme.Values.themePopupOverlayColor
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked: gradientDialogLoader.visible = false
- preventStealing: true
- hoverEnabled: true
- }
- Rectangle {
- id: background
-
- property int xOffset: itemPane.width - gradientDialogLoader.dialogWidth
- x: 4 + xOffset
- Component.onCompleted: {
- var pos = itemPane.mapFromItem(buttonRow.parent, 0, 0)
- y = pos.y + 32
- }
-
- width: parent.width - 8 - xOffset
- height: gradientDialogLoader.dialogHeight
-
- color: StudioTheme.Values.themePanelBackground
- border.color: StudioTheme.Values.themeControlOutline
-
- Label {
- id: title
- x: 8
- y: 6
- font.bold: true
- text: qsTr("Gradient Properties")
- }
-
- StudioControls.AbstractButton {
- width: 16
- height: 16
- buttonIcon: StudioTheme.Constants.closeCross
- onClicked: gradientDialogLoader.visible = false
- backgroundRadius: 2
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: 4
- }
-
- Loader {
- anchors.top: title.bottom
- anchors.topMargin: 8
- anchors.left: parent.left
- anchors.leftMargin: 8
- sourceComponent: gradientDialogLoader.content
- }
- }
- }
- }
-}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPopupIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPopupIndicator.qml
index 1f617e44377..4212bfa2483 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPopupIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPopupIndicator.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,8 +23,8 @@
**
****************************************************************************/
-import QtQuick 2.1
-import QtQuick.Layouts 1.0
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
Image {
id: root
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
index f997329b036..72446ff5600 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetList.qml
@@ -79,15 +79,10 @@ HelperWindow {
StudioControls.TabBar {
id: presetTabBar
- anchors.left: parent.left
- anchors.right: parent.right
+ Layout.fillWidth: true
- StudioControls.TabButton {
- text: qsTr("System Presets")
- }
- StudioControls.TabButton {
- text: qsTr("User Presets")
- }
+ StudioControls.TabButton { text: qsTr("System Presets") }
+ StudioControls.TabButton { text: qsTr("User Presets") }
}
StackLayout {
@@ -104,11 +99,13 @@ HelperWindow {
id: customTabContent
viewModel: customPresetListModel
editableName: true
- onPresetNameChanged: customPresetListModel.changePresetName(id, name)
+ onPresetNameChanged: function(id, name) {
+ customPresetListModel.changePresetName(id, name)
+ }
property int deleteId
- onDeleteButtonClicked: {
+ onDeleteButtonClicked: function(id) {
deleteId = id
deleteDialog.open()
}
@@ -117,7 +114,7 @@ HelperWindow {
id: deleteDialog
visible: false
modality: Qt.WindowModal
- buttons: StandardButton.No | StandardButton.Yes
+ buttons: StandardButton.No | StandardButton.Yes
title: qsTr("Delete preset?")
text: qsTr("Are you sure you want to delete this preset?")
onAccepted: customPresetListModel.deletePreset(customTabContent.deleteId)
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
index 94e83a905c2..b87b3703db4 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/GradientPresetTabContent.qml
@@ -33,10 +33,9 @@ import StudioTheme 1.0 as StudioTheme
Rectangle {
id: tabBackground
- width: parent.width
- height: parent.height
color: StudioTheme.Values.themeControlBackground
- anchors.fill: parent
+ Layout.fillWidth: true
+ Layout.fillHeight: true
property alias viewModel: gradientTable.model
property bool editableName: false
@@ -172,12 +171,12 @@ Rectangle {
}
Component.onCompleted: {
- var stopsAmount = stopListSize;
- var newStops = [];
- for (var i = 0; i < stopsAmount; i++) {
- newStops.push( stopComponent.createObject(showGr, { "position": stopsPosList[i], "color": stopsColorList[i] }) );
- }
- showGr.stops = newStops;
+ var stopsAmount = stopListSize
+ var newStops = []
+ for (var i = 0; i < stopsAmount; i++)
+ newStops.push( stopComponent.createObject(showGr, { "position": stopsPosList[i], "color": stopsColorList[i] }) )
+
+ showGr.stops = newStops
}
AbstractButton {
@@ -268,7 +267,7 @@ Rectangle {
presetNameBox.edit = false
}
- Keys.onPressed: {
+ Keys.onPressed:function(event) {
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
event.accepted = true
nameInput.editingFinished()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml
index de73742af0e..50c930d64b5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/HueSlider.qml
@@ -23,7 +23,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
import StudioTheme 1.0 as StudioTheme
Item {
@@ -105,9 +105,8 @@ Item {
onPressed: calculateValue()
onReleased: root.clicked()
onPositionChanged: {
- if (pressed) {
+ if (pressed)
calculateValue()
- }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconIndicator.qml
index ee1fccdaa0d..4a1487f4eaa 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/IconIndicator.qml
@@ -68,7 +68,7 @@ Rectangle {
states: [
State {
name: "default"
- when: !toolTipArea.containsMouse
+ when: !toolTipArea.containsMouse && root.enabled
PropertyChanges {
target: indicatorIcon
color: StudioTheme.Values.themeLinkIndicatorColor
@@ -76,11 +76,19 @@ Rectangle {
},
State {
name: "hover"
- when: toolTipArea.containsMouse
+ when: toolTipArea.containsMouse && root.enabled
PropertyChanges {
target: indicatorIcon
color: StudioTheme.Values.themeLinkIndicatorColorHover
}
+ },
+ State {
+ name: "disable"
+ when: !root.enabled
+ PropertyChanges {
+ target: indicatorIcon
+ color: StudioTheme.Values.themeLinkIndicatorColorDisabled
+ }
}
]
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ImagePreviewTooltipArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ImagePreviewTooltipArea.qml
index 0f2f5b69b9e..f8331acd4da 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ImagePreviewTooltipArea.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ImagePreviewTooltipArea.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,9 +23,9 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
import HelperWidgets 2.0
-import QtQuick.Layouts 1.0
MouseArea {
id: mouseArea
@@ -35,7 +35,7 @@ MouseArea {
onExited: tooltipBackend.hideTooltip()
onCanceled: tooltipBackend.hideTooltip()
onPositionChanged: tooltipBackend.reposition()
- onClicked: {
+ onClicked: function(mouse) {
forceActiveFocus()
if (mouse.button === Qt.RightButton)
showContextMenu()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ItemFilterComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ItemFilterComboBox.qml
index b55a276d5b5..aa8eaa74456 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ItemFilterComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ItemFilterComboBox.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
@@ -27,7 +27,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
import HelperWidgets 2.0 as HelperWidgets
HelperWidgets.ComboBox {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
index aa7ba8c97db..4e2b1a2c1af 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/LineEdit.qml
@@ -138,7 +138,7 @@ StudioControls.TextField {
var textValue = lineEdit.text
lineEdit.backendValue.value = textValue
}
- colorLogic.evaluate();
+ colorLogic.evaluate()
}
property variant backendValueValueInternal: backendValue === undefined ? 0 : backendValue.value
@@ -157,13 +157,13 @@ StudioControls.TextField {
}
function escapeString(string) {
- var str = string;
- str = str.replace(/\\/g, "\\\\");
- str.replace(/\"/g, "\\\"");
- str = str.replace(/\t/g, "\\t");
- str = str.replace(/\r/g, "\\r");
- str = str.replace(/\n/g, '\\n');
- return str;
+ var str = string
+ str = str.replace(/\\/g, "\\\\")
+ str.replace(/\"/g, "\\\"")
+ str = str.replace(/\t/g, "\\t")
+ str = str.replace(/\r/g, "\\r")
+ str = str.replace(/\n/g, '\\n')
+ return str
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml
index d1daa7baf8a..c79b6e01500 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ListViewComboBox.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
@@ -27,7 +27,7 @@
**
****************************************************************************/
-import QtQuick 2.12
+import QtQuick 2.15
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OpacitySlider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OpacitySlider.qml
index 68d0c225cd9..cf1fea7d07b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OpacitySlider.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OpacitySlider.qml
@@ -108,9 +108,8 @@ Item {
onPressed: calculateValue()
onReleased: root.clicked()
onPositionChanged: {
- if (pressed) {
+ if (pressed)
calculateValue()
- }
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml
index 7929d2a0538..4cb33e4b3c2 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml
@@ -34,7 +34,7 @@ Row {
property alias origin: myButton.origin
property variant backendValue
- onOriginSelectorClicked: {
+ onOriginSelectorClicked: function(value) {
if (root.enabled)
root.backendValue.setEnumeration("Item", value)
}
@@ -78,7 +78,7 @@ Row {
property string origin: "Center"
// This property is used to indicate the global hover state
- property bool hover: myButton.hovered
+ property bool hover: myButton.hovered && root.enabled
property alias backgroundVisible: buttonBackground.visible
property alias backgroundRadius: buttonBackground.radius
@@ -162,10 +162,8 @@ Row {
border.width: StudioTheme.Values.border
}
- enter: Transition {
- }
- exit: Transition {
- }
+ enter: Transition {}
+ exit: Transition {}
}
states: [
@@ -185,6 +183,7 @@ Row {
State {
name: "globalHover"
when: actionIndicator.hover && !myButton.pressed && !originPopup.opened
+ && root.enabled
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundGlobalHover
@@ -194,7 +193,7 @@ Row {
State {
name: "hover"
when: myButton.hover && !actionIndicator.hover && !myButton.pressed
- && !originPopup.opened
+ && !originPopup.opened && root.enabled
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundHover
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginSelector.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginSelector.qml
index e42aff045b4..4511d7291f5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginSelector.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginSelector.qml
@@ -42,7 +42,7 @@ Rectangle {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
- onClicked: myControl.originSelectorClicked(value)
+ onClicked: myControl.originSelectorClicked(root.value)
}
states: [
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml
index f3b34c9e8b0..3a80e7a9a2d 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/RoundedPanel.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,8 +23,8 @@
**
****************************************************************************/
-import QtQuick 2.1
-import QtQuick.Layouts 1.0
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
import QtQuickDesignerTheme 1.0
import StudioTheme 1.0 as StudioTheme
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml
index 7ddc82ebd5f..f3d9964dacc 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ScrollView.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
index 25216142e75..7e761fd8224 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Section.qml
@@ -54,11 +54,6 @@ Item {
property bool addTopPadding: true
property bool addBottomPadding: true
- onHideHeaderChanged: {
- header.visible = !hideHeader
- header.height = hideHeader ? 0 : 20
- }
-
clip: true
signal showContextMenu()
@@ -66,10 +61,11 @@ Item {
Rectangle {
id: header
- height: StudioTheme.Values.sectionHeadHeight
+ height: hideHeader ? 0 : StudioTheme.Values.sectionHeadHeight
+ visible: !hideHeader
anchors.left: parent.left
anchors.right: parent.right
- color: Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0 + (0.2 * level))
+ color: Qt.lighter(StudioTheme.Values.themeSectionHeadBackground, 1.0 + (0.2 * section.level))
Image {
id: arrow
@@ -77,7 +73,7 @@ Item {
height: 4
source: "image://icons/down-arrow"
anchors.left: parent.left
- anchors.leftMargin: 4 + (level * levelShift)
+ anchors.leftMargin: 4 + (section.level * section.levelShift)
anchors.verticalCenter: parent.verticalCenter
}
@@ -85,7 +81,7 @@ Item {
id: label
anchors.verticalCenter: parent.verticalCenter
color: StudioTheme.Values.themeTextColor
- x: 22 + (level * levelShift)
+ x: 22 + (section.level * section.levelShift)
font.pixelSize: StudioTheme.Values.myFontSize
font.capitalization: Font.AllUppercase
}
@@ -94,7 +90,7 @@ Item {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
- onClicked: {
+ onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton) {
trans.enabled = true
if (expandOnClick)
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml
deleted file mode 100644
index 33473c6eb44..00000000000
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/SimpleColorPalette.qml
+++ /dev/null
@@ -1,130 +0,0 @@
-/****************************************************************************
-**
-** 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.
-**
-****************************************************************************/
-
-import QtQuick 2.15
-import HelperWidgets 2.0
-import StudioControls 1.0 as StudioControls
-import StudioTheme 1.0 as StudioTheme
-
-Item {
- id: root
-
- property color selectedColor
- property bool clickable: true
- property color oldColor
-
- width: 200
- height: 40
- enabled: clickable
-
- function addColorToPalette(colorCode) {
- paletteModel.addItem(colorCode)
- }
-
- function showColorDialog(color) {
- root.oldColor = color
- paletteModel.showDialog(color)
- }
-
- signal dialogColorChanged
-
- Component {
- id: colorItemDelegate
-
- Rectangle {
- id: backgroundColor
-
- property var favorite: isFavorite
-
- height: 27
- width: 27
- border.color: backgroundColor.favorite ? "#ffd700" : "#555555"
- border.width: backgroundColor.favorite ? 2 : 1
- color: "white"
- radius: 0
-
- Rectangle {
- id: colorRectangle
- width: 25
- height: 25
- anchors.centerIn: parent
- color: colorCode
- border.color: StudioTheme.Values.themeControlOutline
- border.width: StudioTheme.Values.border
- }
-
- ToolTipArea {
- anchors.fill: parent
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- tooltip: colorCode
-
- onClicked: {
- if (mouse.button === Qt.LeftButton && clickable)
- root.selectedColor = colorRectangle.color
- }
- onPressed: {
- if (mouse.button === Qt.RightButton)
- contextMenu.popup()
- }
- }
-
- StudioControls.Menu {
- id: contextMenu
-
- StudioControls.MenuItem {
- text: backgroundColor.favorite ? qsTr("Remove from Favorites")
- : qsTr("Add to Favorites")
- onTriggered: paletteModel.toggleFavorite(index)
- }
- }
- }
- }
-
- SimpleColorPaletteModel {
- id: paletteModel
-
- onCurrentColorChanged: {
- root.selectedColor = color
- dialogColorChanged()
- }
-
- onColorDialogRejected: {
- root.selectedColor = root.oldColor
- dialogColorChanged()
- }
- }
-
- ListView {
- id: colorPaletteView
- model: paletteModel
- delegate: colorItemDelegate
- orientation: Qt.Horizontal
- anchors.fill: parent
- clip: true
- interactive: false
- spacing: 2
- }
-}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Spacer.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Spacer.qml
index 21f84a86fce..f4f694ea28c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Spacer.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Spacer.qml
@@ -23,8 +23,8 @@
**
****************************************************************************/
-import QtQuick 2.12
-import QtQuick.Layouts 1.12
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
Item {
height: 4
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml
index d89ec297477..abf18d0a377 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ToolTipArea.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,16 +23,14 @@
**
****************************************************************************/
-import QtQuick 2.1
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
import HelperWidgets 2.0
-import QtQuick.Layouts 1.0
MouseArea {
id: mouseArea
- Tooltip {
- id: myTooltip
- }
+ Tooltip { id: myTooltip }
onExited: myTooltip.hideText()
onCanceled: myTooltip.hideText()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
index b7bc955873f..919b337670b 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml
@@ -24,12 +24,12 @@
****************************************************************************/
import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Controls 2.15
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import QtQuickDesignerTheme 1.0
-import QtQuick.Layouts 1.0
-import QtQuick.Controls 2.5
Row {
id: urlChooser
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
index 9d7c2cae5d6..13e7de2f885 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/qmldir
@@ -29,7 +29,6 @@ FontComboBox 2.0 FontComboBox.qml
FontExtrasSection 2.0 FontExtrasSection.qml
FontSection 2.0 FontSection.qml
FontStyleButtons 2.0 FontStyleButtons.qml
-GradientDialogPopup 2.0 GradientDialogPopup.qml
GradientLine 2.0 GradientLine.qml
GradientPopupIndicator 2.0 GradientPopupIndicator.qml
GradientPresetList 2.0 GradientPresetList.qml
@@ -59,7 +58,6 @@ ScrollView 2.0 ScrollView.qml
SecondColumnLayout 2.0 SecondColumnLayout.qml
Section 2.0 Section.qml
SectionLayout 2.0 SectionLayout.qml
-SimpleColorPalette 2.0 SimpleColorPalette.qml
Spacer 2.0 Spacer.qml
SpinBox 2.0 SpinBox.qml
StandardTextSection 2.0 StandardTextSection.qml
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml
index 1a60dac1cd7..8be58b7904a 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/AbstractButton.qml
@@ -52,7 +52,7 @@ T.AbstractButton {
activeFocusOnTab: false
onHoveredChanged: {
- if (parent !== undefined && parent.hoverCallback !== undefined)
+ if (parent !== undefined && parent.hoverCallback !== undefined && myButton.enabled)
parent.hoverCallback()
}
@@ -132,7 +132,7 @@ T.AbstractButton {
},
State {
name: "globalHover"
- when: myButton.globalHover && !myButton.hovered && !myButton.pressed
+ when: myButton.globalHover && !myButton.hovered && !myButton.pressed && myButton.enabled
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundGlobalHover
@@ -140,7 +140,7 @@ T.AbstractButton {
},
State {
name: "hover"
- when: myButton.hovered && !myButton.pressed
+ when: myButton.hovered && !myButton.pressed && myButton.enabled
PropertyChanges {
target: buttonBackground
color: StudioTheme.Values.themeControlBackgroundHover
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml
index 71fc2ec9016..77f43cb6975 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ButtonRow.qml
@@ -31,7 +31,7 @@ import StudioTheme 1.0 as StudioTheme
Row {
id: myButtonRow
- property bool hover: actionIndicator.hover || myButtonRow.childHover
+ property bool hover: (actionIndicator.hover || myButtonRow.childHover) && myButtonRow.enabled
property bool childHover: false
property alias actionIndicator: actionIndicator
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml
index bc5f23f905b..e94098dbf94 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckBox.qml
@@ -33,7 +33,7 @@ T.CheckBox {
property alias actionIndicator: actionIndicator
// This property is used to indicate the global hover state
- property bool hover: myCheckBox.hovered
+ property bool hover: myCheckBox.hovered && myCheckBox.enabled
property bool edit: false
property alias actionIndicatorVisible: actionIndicator.visible
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml
index 57dbc5e8f4f..8083c3d376e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/CheckIndicator.qml
@@ -33,7 +33,7 @@ Rectangle {
property T.Control myControl
property T.Popup myPopup
- property bool hover: checkIndicatorMouseArea.containsMouse
+ property bool hover: checkIndicatorMouseArea.containsMouse && checkIndicator.enabled
property bool pressed: checkIndicatorMouseArea.containsPress
property bool checked: false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml
index 071772d0f1b..982023636b7 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBox.qml
@@ -35,7 +35,8 @@ T.ComboBox {
property alias labelColor: comboBoxInput.color
// This property is used to indicate the global hover state
- property bool hover: comboBoxInput.hover || actionIndicator.hover || popupIndicator.hover
+ property bool hover: (comboBoxInput.hover || actionIndicator.hover || popupIndicator.hover)
+ && myComboBox.enabled
property bool edit: myComboBox.activeFocus && myComboBox.editable
property bool open: comboBoxPopup.opened
@@ -217,10 +218,8 @@ T.ComboBox {
border.width: 0
}
- enter: Transition {
- }
- exit: Transition {
- }
+ enter: Transition {}
+ exit: Transition {}
}
states: [
@@ -307,7 +306,7 @@ T.ComboBox {
}
]
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape)
myComboBox.focus = false
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml
index ae995e6dbcd..663e7993f1e 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ComboBoxInput.qml
@@ -33,7 +33,7 @@ TextInput {
property T.Control myControl
property bool edit: textInput.activeFocus
- property bool hover: mouseArea.containsMouse
+ property bool hover: mouseArea.containsMouse && textInput.enabled
z: 2
font: myControl.font
@@ -91,7 +91,7 @@ TextInput {
propagateComposedEvents: true
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
- onPressed: mouse.accepted = false
+ onPressed: function(mouse) { mouse.accepted = false }
}
states: [
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml
index 9f11b0d972c..3d430420add 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBox.qml
@@ -51,7 +51,7 @@ T.SpinBox {
property bool edit: spinBoxInput.activeFocus
// This property is used to indicate the global hover state
- property bool hover: mySpinBox.hovered || actionIndicator.hover
+ property bool hover: (mySpinBox.hovered || actionIndicator.hover) && mySpinBox.enabled
property bool drag: false
property bool sliderDrag: sliderPopup.drag
@@ -199,10 +199,8 @@ T.SpinBox {
width: mySpinBox.width - actionIndicator.width - (StudioTheme.Values.border * 2)
height: StudioTheme.Values.sliderHeight
- enter: Transition {
- }
- exit: Transition {
- }
+ enter: Transition {}
+ exit: Transition {}
}
textFromValue: function (value, locale) {
@@ -304,7 +302,7 @@ T.SpinBox {
spinBoxInput.selectAll()
}
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) {
event.accepted = true
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml
index a721b8271ae..9ca34c16802 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxIndicator.qml
@@ -32,7 +32,7 @@ Rectangle {
property T.Control myControl
- property bool hover: spinBoxIndicatorMouseArea.containsMouse
+ property bool hover: spinBoxIndicatorMouseArea.containsMouse && spinBoxIndicator.enabled
property bool pressed: spinBoxIndicatorMouseArea.containsPress
property bool released: false
property bool realEnabled: true
@@ -79,7 +79,7 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
pressAndHoldInterval: 500
- onPressed: {
+ onPressed: function(mouse) {
if (myControl.activeFocus)
spinBoxIndicator.forceActiveFocus()
@@ -90,7 +90,7 @@ Rectangle {
pressAndHoldTimer.restart()
pressedAndHeld = true
}
- onReleased: {
+ onReleased: function(mouse) {
// Only trigger real released when pressAndHold isn't active
if (!pressAndHoldTimer.running && containsMouse)
spinBoxIndicator.realReleased()
@@ -222,7 +222,7 @@ Rectangle {
}
PropertyChanges {
target: spinBoxIndicator
- color: "#2aafd3" // TODO
+ color: StudioTheme.Values.themeInteraction
}
},
State {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml
index a47f1f708a7..8d92d9c94af 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/RealSpinBoxInput.qml
@@ -34,7 +34,7 @@ TextInput {
property bool edit: textInput.activeFocus
property bool drag: false
- property bool hover: mouseArea.containsMouse
+ property bool hover: mouseArea.containsMouse && textInput.enabled
z: 2
font: myControl.font
@@ -57,7 +57,7 @@ TextInput {
// TextInput focus needs to be set to activeFocus whenever it changes,
// otherwise TextInput will get activeFocus whenever the parent SpinBox gets
// activeFocus. This will lead to weird side effects.
- onActiveFocusChanged: textInput.focus = activeFocus
+ onActiveFocusChanged: textInput.focus = textInput.activeFocus
Rectangle {
id: textInputBackground
@@ -72,7 +72,7 @@ TextInput {
Item {
id: dragModifierWorkaround
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
event.accepted = true
if (event.modifiers & Qt.ControlModifier) {
@@ -85,7 +85,7 @@ TextInput {
mouseArea.calcValue(myControl.realValueModified)
}
}
- Keys.onReleased: {
+ Keys.onReleased: function(event) {
event.accepted = true
mouseArea.stepSize = myControl.realStepSize
mouseArea.calcValue(myControl.realValueModified)
@@ -93,7 +93,7 @@ TextInput {
}
// Ensure that we get Up and Down key press events first
- Keys.onShortcutOverride: {
+ Keys.onShortcutOverride: function(event) {
event.accepted = (event.key === Qt.Key_Up || event.key === Qt.Key_Down)
}
@@ -119,7 +119,7 @@ TextInput {
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
- onPositionChanged: {
+ onPositionChanged: function(mouse) {
if (!mouseArea.dragging
&& !myControl.edit
&& Math.abs(mouseArea.pressStartX - mouse.x) > StudioTheme.Values.dragThreshold
@@ -149,7 +149,7 @@ TextInput {
onCanceled: mouseArea.endDrag()
- onClicked: {
+ onClicked: function(mouse) {
if (textInput.edit)
mouse.accepted = false
@@ -162,7 +162,7 @@ TextInput {
textInput.deselect() // QTBUG-75862
}
- onPressed: {
+ onPressed: function(mouse) {
if (textInput.edit)
mouse.accepted = false
@@ -170,7 +170,7 @@ TextInput {
mouseArea.pressStartX = mouseArea.mouseX
}
- onReleased: {
+ onReleased: function(mouse) {
if (textInput.edit)
mouse.accepted = false
@@ -213,7 +213,7 @@ TextInput {
callback()
}
- onWheel: {
+ onWheel: function(wheel) {
if (!myControl.__wheelEnabled)
return
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml
index 2178baddf69..23ee5615700 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Section.qml
@@ -33,20 +33,16 @@ Item {
property int leftPadding: 8
property int topPadding: 4
property int rightPadding: 0
-
property int animationDuration: 120
-
property bool expanded: true
clip: true
Rectangle {
id: header
- height: StudioTheme.Values.sectionHeadHeight
-
anchors.left: parent.left
anchors.right: parent.right
-
+ height: StudioTheme.Values.sectionHeadHeight
color: StudioTheme.Values.themeSectionHeadBackground
SectionLabel {
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml
index ddb6c165c61..dde7dcebff1 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/Slider.qml
@@ -217,8 +217,8 @@ T.Slider {
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
// Sets the global hover
- onContainsMouseChanged: slider.hover = containsMouse
- onPressed: mouse.accepted = false
+ onContainsMouseChanged: slider.hover = mouseArea.containsMouse
+ onPressed: function(mouse) { mouse.accepted = false }
}
states: [
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml
index 98f20c303a5..4c32353697c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBox.qml
@@ -41,7 +41,7 @@ T.SpinBox {
property bool edit: spinBoxInput.activeFocus
// This property is used to indicate the global hover state
- property bool hover: mySpinBox.hovered || actionIndicator.hover
+ property bool hover: (mySpinBox.hovered || actionIndicator.hover) && mySpinBox.enabled
property bool drag: false
property bool sliderDrag: sliderPopup.drag
@@ -164,10 +164,8 @@ T.SpinBox {
width: mySpinBox.width - actionIndicator.width - (StudioTheme.Values.border * 2)
height: StudioTheme.Values.sliderHeight
- enter: Transition {
- }
- exit: Transition {
- }
+ enter: Transition {}
+ exit: Transition {}
}
textFromValue: function (value, locale) {
@@ -256,7 +254,7 @@ T.SpinBox {
sliderPopup.close()
}
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) {
event.accepted = true
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml
index 17d7ac7eb34..7bb78311a6c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxIndicator.qml
@@ -32,7 +32,7 @@ Rectangle {
property T.Control myControl
- property bool hover: spinBoxIndicatorMouseArea.containsMouse
+ property bool hover: spinBoxIndicatorMouseArea.containsMouse && spinBoxIndicator.enabled
property bool pressed: spinBoxIndicatorMouseArea.containsPress
property alias iconFlip: spinBoxIndicatorIconScale.yScale
@@ -46,7 +46,7 @@ Rectangle {
id: spinBoxIndicatorMouseArea
anchors.fill: parent
hoverEnabled: true
- onPressed: {
+ onPressed: function(mouse) {
if (myControl.activeFocus)
spinBoxIndicator.forceActiveFocus()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml
index 4d0432d3f38..855cc220fa5 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/SpinBoxInput.qml
@@ -34,7 +34,7 @@ TextInput {
property bool edit: textInput.activeFocus
property bool drag: false
- property bool hover: mouseArea.containsMouse
+ property bool hover: mouseArea.containsMouse && textInput.enabled
z: 2
font: myControl.font
@@ -57,7 +57,7 @@ TextInput {
// TextInput focus needs to be set to activeFocus whenever it changes,
// otherwise TextInput will get activeFocus whenever the parent SpinBox gets
// activeFocus. This will lead to weird side effects.
- onActiveFocusChanged: textInput.focus = activeFocus
+ onActiveFocusChanged: textInput.focus = textInput.activeFocus
Rectangle {
id: textInputBackground
@@ -115,8 +115,8 @@ TextInput {
propagateComposedEvents: true
acceptedButtons: Qt.LeftButton
cursorShape: Qt.PointingHandCursor
- onPressed: mouse.accepted = false
- onWheel: {
+ onPressed: function(mouse) { mouse.accepted = false }
+ onWheel: function(wheel) {
if (!myControl.__wheelEnabled)
return
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml
index 62881454189..677e8b60539 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextArea.qml
@@ -127,7 +127,7 @@ TextField {
myTextField.text = txtStorage.slice(0, sliceAt).padEnd(sliceAt + 3, '.')
}
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape)
popup.opened ? popup.close() : myTextField.focus = false
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml
index 17fbe899c42..ea58bd71958 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TextField.qml
@@ -34,8 +34,8 @@ T.TextField {
property alias translationIndicator: translationIndicator
// This property is used to indicate the global hover state
- property bool hover: actionIndicator.hover || mouseArea.containsMouse
- || translationIndicator.hover
+ property bool hover: (actionIndicator.hover || mouseArea.containsMouse
+ || translationIndicator.hover) && myTextField.enabled
property bool edit: myTextField.activeFocus
property alias actionIndicatorVisible: actionIndicator.visible
@@ -75,7 +75,7 @@ T.TextField {
propagateComposedEvents: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor
- onPressed: {
+ onPressed: function(mouse) {
if (mouse.button === Qt.RightButton)
contextMenu.popup(myTextField)
@@ -147,6 +147,7 @@ T.TextField {
State {
name: "globalHover"
when: (actionIndicator.hover || translationIndicator.hover) && !myTextField.edit
+ && myTextField.enabled
PropertyChanges {
target: textFieldBackground
color: StudioTheme.Values.themeControlBackgroundGlobalHover
@@ -160,7 +161,7 @@ T.TextField {
State {
name: "hover"
when: mouseArea.containsMouse && !actionIndicator.hover && !translationIndicator.hover
- && !myTextField.edit
+ && !myTextField.edit && myTextField.enabled
PropertyChanges {
target: textFieldBackground
color: StudioTheme.Values.themeControlBackgroundHover
@@ -203,7 +204,7 @@ T.TextField {
}
]
- Keys.onPressed: {
+ Keys.onPressed: function(event) {
if (event.key === Qt.Key_Escape)
myTextField.focus = false
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml
index 2d7ca74f16c..3b56d0a9807 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/TranslationIndicator.qml
@@ -32,7 +32,7 @@ Item {
property Item myControl
- property bool hover: translationIndicatorMouseArea.containsMouse
+ property bool hover: translationIndicatorMouseArea.containsMouse && translationIndicator.enabled
property bool pressed: translationIndicatorMouseArea.pressed
property bool checked: false
@@ -62,7 +62,7 @@ Item {
id: translationIndicatorMouseArea
anchors.fill: parent
hoverEnabled: true
- onPressed: mouse.accepted = true // TODO
+ onPressed: function(mouse) { mouse.accepted = true }
onClicked: {
translationIndicator.checked = !translationIndicator.checked
translationIndicator.clicked()
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
index cbba4a8f3ab..c3e91a6584c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml
@@ -110,6 +110,8 @@ QtObject {
property real infinityControlWidth: values.iconAreaWidth
property real infinityControlHeight: values.height
+ property real transform3DSectionSpacing: 15
+
// Control sizes
property real defaultControlWidth: values.squareComponentWidth * 5
@@ -200,6 +202,8 @@ QtObject {
property string themeError: Theme.color(Theme.DSerrorColor)
property string themeDisabled: Theme.color(Theme.DSdisabledColor)
+ property string themeAliasIconChecked: Theme.color(Theme.DSnavigatorAliasIconChecked)
+
// Control colors
property string themeControlBackground: Theme.color(Theme.DScontrolBackground)
property string themeControlBackgroundInteraction: Theme.color(Theme.DScontrolBackgroundInteraction)
diff --git a/share/qtcreator/styles/inkpot.xml b/share/qtcreator/styles/inkpot.xml
index e5183fe9ba4..780be74d46d 100644
--- a/share/qtcreator/styles/inkpot.xml
+++ b/share/qtcreator/styles/inkpot.xml
@@ -27,6 +27,7 @@
+
diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
index 8752c9062c0..bf9cb86daa0 100644
--- a/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/stack/wizard.json
@@ -132,7 +132,7 @@
"QtQuickControlsVersion": "2.5",
"QtQuickVirtualKeyboardImport": "QtQuick.VirtualKeyboard 2.4"
}
- },
+ }
]
}
},
diff --git a/src/app/main.cpp b/src/app/main.cpp
index b10eea891c5..77c08cbd088 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -567,7 +567,7 @@ int main(int argc, char **argv)
temporaryCleanSettingsDir.reset(new Utils::TemporaryDirectory("qtc-test-settings"));
if (!temporaryCleanSettingsDir->isValid())
return 1;
- options.settingsPath = temporaryCleanSettingsDir->path();
+ options.settingsPath = temporaryCleanSettingsDir->path().path();
}
if (!options.settingsPath.isEmpty())
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, options.settingsPath);
diff --git a/src/libs/extensionsystem/optionsparser.cpp b/src/libs/extensionsystem/optionsparser.cpp
index 5ad79b1f0a1..164dd9f9932 100644
--- a/src/libs/extensionsystem/optionsparser.cpp
+++ b/src/libs/extensionsystem/optionsparser.cpp
@@ -177,7 +177,7 @@ bool OptionsParser::checkForScenarioOption()
if (!m_pmPrivate->m_requestedScenario.isEmpty()) {
if (m_errorString) {
*m_errorString = QCoreApplication::translate("PluginManager",
- "Can't request scenario \"%1\" as the scenario \"%1\" was already requested.")
+ "Cannot request scenario \"%1\" as the scenario \"%1\" was already requested.")
.arg(m_currentArg, m_pmPrivate->m_requestedScenario);
}
m_hasError = true;
diff --git a/src/libs/languageserverprotocol/jsonrpcmessages.h b/src/libs/languageserverprotocol/jsonrpcmessages.h
index f0247e3c56b..7a7ab2df89a 100644
--- a/src/libs/languageserverprotocol/jsonrpcmessages.h
+++ b/src/libs/languageserverprotocol/jsonrpcmessages.h
@@ -241,7 +241,7 @@ public:
return Utils::nullopt;
return Utils::make_optional(Result(result));
}
- void setResult(const Result &result) { m_jsonObject.insert(resultKey, result); }
+ void setResult(const Result &result) { m_jsonObject.insert(resultKey, QJsonValue(result)); }
void clearResult() { m_jsonObject.remove(resultKey); }
using Error = ResponseError;
diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h
index 3231f010a29..4348e4fd19d 100644
--- a/src/libs/languageserverprotocol/lsptypes.h
+++ b/src/libs/languageserverprotocol/lsptypes.h
@@ -40,6 +40,8 @@
#include
#include
+#include
+
namespace LanguageServerProtocol {
class LANGUAGESERVERPROTOCOL_EXPORT DocumentUri : public QUrl
@@ -560,6 +562,7 @@ enum class SymbolKind {
TypeParameter = 26,
LastSymbolKind = TypeParameter,
};
+using SymbolStringifier = std::function;
namespace CompletionItemKind {
enum Kind {
diff --git a/src/libs/languageserverprotocol/semantictokens.cpp b/src/libs/languageserverprotocol/semantictokens.cpp
index 2182aa466dd..d827136a414 100644
--- a/src/libs/languageserverprotocol/semantictokens.cpp
+++ b/src/libs/languageserverprotocol/semantictokens.cpp
@@ -104,8 +104,10 @@ QList SemanticTokens::toTokens(const QList &tokenTypes,
token.deltaLine = *(it);
token.deltaStart = *(it + 1);
token.length = *(it + 2);
- token.tokenType = tokenTypes.value(*(it + 3), -1);
- token.tokenModifiers = convertModifiers(*(it + 4), tokenModifiers);
+ token.tokenIndex = *(it + 3);
+ token.tokenType = tokenTypes.value(token.tokenIndex, -1);
+ token.rawTokenModifiers = *(it + 4);
+ token.tokenModifiers = convertModifiers(token.rawTokenModifiers, tokenModifiers);
tokens << token;
}
return tokens;
diff --git a/src/libs/languageserverprotocol/semantictokens.h b/src/libs/languageserverprotocol/semantictokens.h
index 8d23e31154d..fccfd29dcb4 100644
--- a/src/libs/languageserverprotocol/semantictokens.h
+++ b/src/libs/languageserverprotocol/semantictokens.h
@@ -38,7 +38,9 @@ struct LANGUAGESERVERPROTOCOL_EXPORT SemanticToken
int deltaLine = 0;
int deltaStart = 0;
int length = 0;
+ int tokenIndex = 0;
int tokenType = 0;
+ int rawTokenModifiers = 0;
int tokenModifiers = 0;
};
diff --git a/src/libs/tracing/CMakeLists.txt b/src/libs/tracing/CMakeLists.txt
index 8d445df2bff..cb46eb21b03 100644
--- a/src/libs/tracing/CMakeLists.txt
+++ b/src/libs/tracing/CMakeLists.txt
@@ -2,6 +2,8 @@ if (WITH_TESTS)
set(TEST_SOURCES
runscenegraphtest.cpp runscenegraphtest.h
)
+else()
+ set(TEST_SOURCES "")
endif()
set(TRACING_CPP_SOURCES
@@ -45,6 +47,10 @@ if(${Qt5_VERSION} VERSION_LESS "6.2.0")
qml/tracing.qrc
)
else() # < Qt 6.2
+ if (NOT TARGET Tracing)
+ return()
+ endif()
+
set(TRACING_QML_FILES
qml/ButtonsBar.qml
qml/CategoryLabel.qml
diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp
index d1ad77e54ba..7a2f504af3d 100644
--- a/src/libs/utils/buildablehelperlibrary.cpp
+++ b/src/libs/utils/buildablehelperlibrary.cpp
@@ -36,68 +36,68 @@
namespace Utils {
-bool BuildableHelperLibrary::isQtChooser(const QFileInfo &info)
+bool BuildableHelperLibrary::isQtChooser(const FilePath &filePath)
{
- return info.isSymLink() && info.symLinkTarget().endsWith(QLatin1String("/qtchooser"));
+ return filePath.symLinkTarget().endsWith("/qtchooser");
}
-QString BuildableHelperLibrary::qtChooserToQmakePath(const QString &path)
+FilePath BuildableHelperLibrary::qtChooserToQmakePath(const FilePath &qtChooser)
{
const QString toolDir = QLatin1String("QTTOOLDIR=\"");
QtcProcess proc;
proc.setTimeoutS(1);
- proc.setCommand({path, {"-print-env"}});
+ proc.setCommand({qtChooser, {"-print-env"}});
proc.runBlocking();
if (proc.result() != QtcProcess::FinishedWithSuccess)
- return QString();
+ return {};
const QString output = proc.stdOut();
int pos = output.indexOf(toolDir);
if (pos == -1)
- return QString();
+ return {};
pos += toolDir.count();
int end = output.indexOf('\"', pos);
if (end == -1)
- return QString();
+ return {};
- return output.mid(pos, end - pos) + QLatin1String("/qmake");
+ FilePath qmake = qtChooser;
+ qmake.setPath(output.mid(pos, end - pos) + "/qmake");
+ return qmake;
}
-static bool isQmake(const QString &path)
+static bool isQmake(FilePath path)
{
if (path.isEmpty())
return false;
- QFileInfo fi(path);
- if (BuildableHelperLibrary::isQtChooser(fi))
- fi.setFile(BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget()));
- if (!fi.exists() || fi.isDir())
+ if (BuildableHelperLibrary::isQtChooser(path))
+ path = BuildableHelperLibrary::qtChooserToQmakePath(path.symLinkTarget());
+ if (!path.exists())
return false;
- return !BuildableHelperLibrary::qtVersionForQMake(fi.absoluteFilePath()).isEmpty();
+ return !BuildableHelperLibrary::qtVersionForQMake(path).isEmpty();
}
-static FilePath findQmakeInDir(const FilePath &path)
+static FilePath findQmakeInDir(const FilePath &dir)
{
- if (path.isEmpty())
- return FilePath();
+ if (dir.isEmpty())
+ return {};
- const QString qmake = HostOsInfo::withExecutableSuffix("qmake");
- QDir dir(path.toString());
- if (dir.exists(qmake)) {
- const QString qmakePath = dir.absoluteFilePath(qmake);
+ FilePath qmakePath = dir.pathAppended("qmake").withExecutableSuffix();
+ if (qmakePath.exists()) {
if (isQmake(qmakePath))
- return FilePath::fromString(qmakePath);
+ return qmakePath;
}
// Prefer qmake-qt5 to qmake-qt4 by sorting the filenames in reverse order.
- const QFileInfoList candidates = dir.entryInfoList(
+ const FilePaths candidates = dir.dirEntries(
BuildableHelperLibrary::possibleQMakeCommands(),
- QDir::Files, QDir::Name | QDir::Reversed);
- for (const QFileInfo &fi : candidates) {
- if (fi.fileName() == qmake)
+ QDir::Files,
+ QDir::Name | QDir::Reversed);
+ for (const FilePath &candidate : candidates) {
+ if (candidate == qmakePath)
continue;
- if (isQmake(fi.absoluteFilePath()))
- return FilePath::fromFileInfo(fi);
+ if (isQmake(candidate))
+ return candidate;
}
- return FilePath();
+ return {};
}
FilePath BuildableHelperLibrary::findSystemQt(const Environment &env)
@@ -124,7 +124,7 @@ FilePaths BuildableHelperLibrary::findQtsInEnvironment(const Environment &env, i
return qmakeList;
}
-QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath)
+QString BuildableHelperLibrary::qtVersionForQMake(const FilePath &qmakePath)
{
if (qmakePath.isEmpty())
return QString();
@@ -197,7 +197,7 @@ bool BuildableHelperLibrary::copyFiles(const QString &sourcePath,
QString *errorMessage)
{
// try remove the directory
- if (!FileUtils::removeRecursively(FilePath::fromString(targetDirectory), errorMessage))
+ if (!FilePath::fromString(targetDirectory).removeRecursively(errorMessage))
return false;
if (!QDir().mkpath(targetDirectory)) {
*errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The target directory %1 could not be created.").arg(targetDirectory);
diff --git a/src/libs/utils/buildablehelperlibrary.h b/src/libs/utils/buildablehelperlibrary.h
index 4cca2ccd9ce..67d543f5071 100644
--- a/src/libs/utils/buildablehelperlibrary.h
+++ b/src/libs/utils/buildablehelperlibrary.h
@@ -39,10 +39,10 @@ public:
// at least version 2.0.0 and thus is a qt4 qmake
static FilePath findSystemQt(const Environment &env);
static FilePaths findQtsInEnvironment(const Environment &env, int maxCount = -1);
- static bool isQtChooser(const QFileInfo &info);
- static QString qtChooserToQmakePath(const QString &path);
+ static bool isQtChooser(const FilePath &filePath);
+ static FilePath qtChooserToQmakePath(const FilePath &path);
// return true if the qmake at qmakePath is a Qt (used by QtVersion)
- static QString qtVersionForQMake(const QString &qmakePath);
+ static QString qtVersionForQMake(const FilePath &qmakePath);
// returns something like qmake4, qmake, qmake-qt4 or whatever distributions have chosen (used by QtVersion)
static QStringList possibleQMakeCommands();
static QString filterForQmakeFileDialog();
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index fe1769daffa..87c17b6b560 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -183,7 +183,7 @@ bool Environment::isSameExecutable(const QString &exe1, const QString &exe2) con
const FilePath f2 = FilePath::fromString(i2);
if (f1 == f2)
return true;
- if (FileUtils::resolveSymlinks(f1) == FileUtils::resolveSymlinks(f2))
+ if (f1.resolveSymlinks() == f2.resolveSymlinks())
return true;
if (FileUtils::fileId(f1) == FileUtils::fileId(f2))
return true;
diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp
index 46395830f33..e44faa5e087 100644
--- a/src/libs/utils/fileutils.cpp
+++ b/src/libs/utils/fileutils.cpp
@@ -29,6 +29,7 @@
#include "algorithm.h"
#include "commandline.h"
#include "environment.h"
+#include "hostosinfo.h"
#include "qtcassert.h"
#include
@@ -75,15 +76,9 @@ static DeviceFileHooks s_deviceHooks;
*/
-/*!
- Removes the directory \a filePath and its subdirectories recursively.
-
- \note The \a error parameter is optional.
-
- Returns whether the operation succeeded.
-*/
-bool FileUtils::removeRecursively(const FilePath &filePath, QString *error)
+static bool removeRecursivelyLocal(const FilePath &filePath, QString *error)
{
+ QTC_ASSERT(!filePath.needsDevice(), return false);
QFileInfo fileInfo = filePath.toFileInfo();
if (!fileInfo.exists() && !fileInfo.isSymLink())
return true;
@@ -109,7 +104,7 @@ bool FileUtils::removeRecursively(const FilePath &filePath, QString *error)
const QStringList fileNames = dir.entryList(
QDir::Files | QDir::Hidden | QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
for (const QString &fileName : fileNames) {
- if (!removeRecursively(filePath / fileName, error))
+ if (!removeRecursivelyLocal(filePath / fileName, error))
return false;
}
if (!QDir::root().rmdir(dir.path())) {
@@ -204,14 +199,12 @@ bool FileUtils::copyIfDifferent(const FilePath &srcFilePath, const FilePath &tgt
*/
bool FilePath::isNewerThan(const QDateTime &timeStamp) const
{
- const QFileInfo fileInfo = toFileInfo();
- if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp)
+ if (!exists() || lastModified() >= timeStamp)
return true;
- if (fileInfo.isDir()) {
- const QStringList dirContents = QDir(toString())
- .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
- for (const QString &curFileName : dirContents) {
- if (pathAppended(curFileName).isNewerThan(timeStamp))
+ if (isDir()) {
+ const FilePaths dirContents = dirEntries(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+ for (const FilePath &entry : dirContents) {
+ if (entry.isNewerThan(timeStamp))
return true;
}
}
@@ -231,7 +224,7 @@ Qt::CaseSensitivity FilePath::caseSensitivity() const
}
/*!
- Recursively resolves symlinks if \a filePath is a symlink.
+ Recursively resolves symlinks if this is a symlink.
To resolve symlinks anywhere in the path, see canonicalPath.
Unlike QFileInfo::canonicalFilePath(), this function will still return the expected deepest
target file even if the symlink is dangling.
@@ -240,15 +233,17 @@ Qt::CaseSensitivity FilePath::caseSensitivity() const
Returns the symlink target file path.
*/
-FilePath FileUtils::resolveSymlinks(const FilePath &path)
+FilePath FilePath::resolveSymlinks() const
{
- QFileInfo f = path.toFileInfo();
+ FilePath current = *this;
int links = 16;
- while (links-- && f.isSymLink())
- f.setFile(f.dir(), f.symLinkTarget());
- if (links <= 0)
- return FilePath();
- return FilePath::fromString(f.filePath());
+ while (links--) {
+ const FilePath target = current.symLinkTarget();
+ if (target.isEmpty())
+ return current;
+ current = target;
+ }
+ return current;
}
/*!
@@ -365,22 +360,32 @@ QString FileUtils::normalizePathName(const QString &name)
#endif
}
-bool FileUtils::isRelativePath(const QString &path)
+static bool isRelativePathHelper(const QString &path, OsType osType)
{
- if (path.startsWith(QLatin1Char('/')))
+ if (path.startsWith('/'))
return false;
- if (HostOsInfo::isWindowsHost()) {
- if (path.startsWith(QLatin1Char('\\')))
+ if (osType == OsType::OsTypeWindows) {
+ if (path.startsWith('\\'))
return false;
// Unlike QFileInfo, this won't accept a relative path with a drive letter.
// Such paths result in a royal mess anyway ...
- if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter()
- && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\')))
+ if (path.length() >= 3 && path.at(1) == ':' && path.at(0).isLetter()
+ && (path.at(2) == '/' || path.at(2) == '\\'))
return false;
}
return true;
}
+bool FileUtils::isRelativePath(const QString &path)
+{
+ return isRelativePathHelper(path, HostOsInfo::hostOs());
+}
+
+bool FilePath::isRelativePath() const
+{
+ return isRelativePathHelper(m_data, osType());
+}
+
FilePath FilePath::resolvePath(const QString &fileName) const
{
if (fileName.isEmpty())
@@ -390,13 +395,6 @@ FilePath FilePath::resolvePath(const QString &fileName) const
return FilePath::fromString(QDir::cleanPath(toString() + QLatin1Char('/') + fileName));
}
-FilePath FilePath::resolveSymlinkTarget() const
-{
- // FIXME: implement
- QTC_CHECK(false);
- return *this;
-}
-
FilePath FilePath::cleanPath() const
{
FilePath result = *this;
@@ -897,6 +895,20 @@ bool FilePath::ensureWritableDir() const
return QDir().mkpath(m_data);
}
+bool FilePath::ensureExistingFile() const
+{
+ if (needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.ensureExistingFile, return false);
+ return s_deviceHooks.ensureExistingFile(*this);
+ }
+ QFile f(m_data);
+ if (f.exists())
+ return true;
+ f.open(QFile::WriteOnly);
+ f.close();
+ return f.exists();
+}
+
bool FilePath::isExecutableFile() const
{
if (needsDevice()) {
@@ -937,14 +949,16 @@ bool FilePath::createDir() const
return dir.mkpath(dir.absolutePath());
}
-QList FilePath::dirEntries(const QStringList &nameFilters, QDir::Filters filters) const
+QList FilePath::dirEntries(const QStringList &nameFilters,
+ QDir::Filters filters,
+ QDir::SortFlags sort) const
{
if (needsDevice()) {
QTC_ASSERT(s_deviceHooks.dirEntries, return {});
- return s_deviceHooks.dirEntries(*this, nameFilters, filters);
+ return s_deviceHooks.dirEntries(*this, nameFilters, filters, sort);
}
- const QFileInfoList entryInfoList = QDir(toString()).entryInfoList(nameFilters, filters);
+ const QFileInfoList entryInfoList = QDir(m_data).entryInfoList(nameFilters, filters, sort);
return Utils::transform(entryInfoList, &FilePath::fromFileInfo);
}
@@ -992,6 +1006,25 @@ bool FilePath::needsDevice() const
return !m_scheme.isEmpty();
}
+/// \returns an empty FilePath if this is not a symbolic linl
+FilePath FilePath::symLinkTarget() const
+{
+ if (needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.symLinkTarget, return {});
+ return s_deviceHooks.symLinkTarget(*this);
+ }
+ const QFileInfo info(m_data);
+ if (!info.isSymLink())
+ return {};
+ return FilePath::fromString(info.symLinkTarget());
+}
+
+FilePath FilePath::withExecutableSuffix() const
+{
+ FilePath res = *this;
+ res.setPath(OsSpecificAspects::withExecutableSuffix(osType(), m_data));
+ return res;
+}
/// Find the parent directory of a given directory.
@@ -1034,7 +1067,7 @@ FilePath FilePath::absoluteFilePath() const
FilePath FilePath::absoluteFilePath(const FilePath &tail) const
{
- if (FileUtils::isRelativePath(tail.m_data))
+ if (isRelativePathHelper(tail.m_data, osType()))
return pathAppended(tail.m_data);
return tail;
}
@@ -1397,6 +1430,15 @@ QFile::Permissions FilePath::permissions() const
return toFileInfo().permissions();
}
+OsType FilePath::osType() const
+{
+ if (needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.osType, return {});
+ return s_deviceHooks.osType(*this);
+ }
+ return HostOsInfo::hostOs();
+}
+
bool FilePath::removeFile() const
{
if (needsDevice()) {
@@ -1406,6 +1448,22 @@ bool FilePath::removeFile() const
return QFile::remove(path());
}
+/*!
+ Removes the directory this filePath refers too and its subdirectories recursively.
+
+ \note The \a error parameter is optional.
+
+ Returns whether the operation succeeded.
+*/
+bool FilePath::removeRecursively(QString *error) const
+{
+ if (needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.removeRecursively, return false);
+ return s_deviceHooks.removeRecursively(*this);
+ }
+ return removeRecursivelyLocal(*this, error);
+}
+
bool FilePath::copyFile(const FilePath &target) const
{
if (needsDevice()) {
@@ -1415,6 +1473,15 @@ bool FilePath::copyFile(const FilePath &target) const
return QFile::copy(path(), target.path());
}
+bool FilePath::renameFile(const FilePath &target) const
+{
+ if (needsDevice()) {
+ QTC_ASSERT(s_deviceHooks.renameFile, return false);
+ return s_deviceHooks.renameFile(*this, target);
+ }
+ return QFile::rename(path(), target.path());
+}
+
QTextStream &operator<<(QTextStream &s, const FilePath &fn)
{
return s << fn.toString();
diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h
index b02b7f095f9..0d8d48d0285 100644
--- a/src/libs/utils/fileutils.h
+++ b/src/libs/utils/fileutils.h
@@ -75,16 +75,22 @@ public:
std::function isWritableDir;
std::function isWritableFile;
std::function ensureWritableDir;
+ std::function ensureExistingFile;
std::function createDir;
std::function exists;
std::function removeFile;
+ std::function removeRecursively;
std::function copyFile;
+ std::function renameFile;
std::function searchInPath;
- std::function(const FilePath &, const QStringList &, QDir::Filters)> dirEntries;
+ std::function symLinkTarget;
+ std::function(const FilePath &, const QStringList &,
+ QDir::Filters, QDir::SortFlags)> dirEntries;
std::function fileContents;
std::function writeFileContents;
std::function lastModified;
std::function permissions;
+ std::function osType;
};
class QTCREATOR_UTILS_EXPORT FilePath
@@ -133,11 +139,17 @@ public:
bool isWritableDir() const;
bool isWritableFile() const;
bool ensureWritableDir() const;
+ bool ensureExistingFile() const;
bool isExecutableFile() const;
bool isReadableFile() const;
bool isReadableDir() const;
+ bool isRelativePath() const;
+ bool isAbsolutePath() const { return !isRelativePath(); }
+
bool createDir() const;
- QList dirEntries(const QStringList &nameFilters, QDir::Filters filters) const;
+ QList dirEntries(const QStringList &nameFilters,
+ QDir::Filters filters,
+ QDir::SortFlags sort = QDir::NoSort) const;
QList dirEntries(QDir::Filters filters) const;
QByteArray fileContents(int maxSize = -1) const;
bool writeFileContents(const QByteArray &data) const;
@@ -165,8 +177,11 @@ public:
bool isNewerThan(const QDateTime &timeStamp) const;
QDateTime lastModified() const;
QFile::Permissions permissions() const;
+ OsType osType() const;
bool removeFile() const;
+ bool removeRecursively(QString *error = nullptr) const;
bool copyFile(const FilePath &target) const;
+ bool renameFile(const FilePath &target) const;
Qt::CaseSensitivity caseSensitivity() const;
@@ -179,6 +194,9 @@ public:
FilePath cleanPath() const;
FilePath canonicalPath() const;
+ FilePath symLinkTarget() const;
+ FilePath resolveSymlinks() const;
+ FilePath withExecutableSuffix() const;
FilePath operator/(const QString &str) const;
@@ -229,7 +247,6 @@ public:
};
#endif // QT_GUI_LIB
- static bool removeRecursively(const FilePath &filePath, QString *error = nullptr);
static bool copyRecursively(const FilePath &srcFilePath,
const FilePath &tgtFilePath,
QString *error = nullptr);
@@ -240,7 +257,6 @@ public:
T &©Helper);
static bool copyIfDifferent(const FilePath &srcFilePath,
const FilePath &tgtFilePath);
- static FilePath resolveSymlinks(const FilePath &path);
static QString fileSystemFriendlyName(const QString &name);
static int indexOfQmakeUnfriendly(const QString &name, int startpos = 0);
static QString qmakeFriendlyName(const QString &name);
diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp
index 8aa0099ca85..94c23921bd7 100644
--- a/src/libs/utils/qtcprocess.cpp
+++ b/src/libs/utils/qtcprocess.cpp
@@ -71,7 +71,7 @@ enum { syncDebug = 0 };
enum { defaultMaxHangTimerCount = 10 };
-static Q_LOGGING_CATEGORY(processLog, "qtc.utils.synchronousprocess", QtWarningMsg);
+static Q_LOGGING_CATEGORY(processLog, "qtc.utils.qtcprocess", QtWarningMsg)
static DeviceProcessHooks s_deviceHooks;
@@ -325,6 +325,11 @@ void QtcProcess::start()
return;
}
+ if (processLog().isDebugEnabled()) {
+ static int n = 0;
+ qCDebug(processLog) << "STARTING PROCESS: " << ++n << " " << d->m_commandLine.toUserOutput();
+ }
+
Environment env;
const OsType osType = HostOsInfo::hostOs();
if (d->m_haveEnv) {
@@ -444,6 +449,11 @@ bool QtcProcess::keepsWriteChannelOpen() const
return d->m_process->m_keepStdInOpen;
}
+void QtcProcess::setStandardInputFile(const QString &inputFile)
+{
+ d->m_process->setStandardInputFile(inputFile);
+}
+
void QtcProcess::setRemoteProcessHooks(const DeviceProcessHooks &hooks)
{
s_deviceHooks = hooks;
diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h
index 3f82d70687e..95fe4d22563 100644
--- a/src/libs/utils/qtcprocess.h
+++ b/src/libs/utils/qtcprocess.h
@@ -182,6 +182,8 @@ public:
void setKeepWriteChannelOpen();
bool keepsWriteChannelOpen() const;
+ void setStandardInputFile(const QString &inputFile);
+
signals:
void started();
void finished();
diff --git a/src/libs/utils/savefile.cpp b/src/libs/utils/savefile.cpp
index e96845e74bf..721a87217ea 100644
--- a/src/libs/utils/savefile.cpp
+++ b/src/libs/utils/savefile.cpp
@@ -118,8 +118,7 @@ bool SaveFile::commit()
return false;
}
- QString finalFileName
- = FileUtils::resolveSymlinks(FilePath::fromString(m_finalFileName)).toString();
+ QString finalFileName = FilePath::fromString(m_finalFileName).resolveSymlinks().toString();
#ifdef Q_OS_WIN
// Release the file lock
diff --git a/src/libs/utils/temporarydirectory.cpp b/src/libs/utils/temporarydirectory.cpp
index da539919e42..2c30606e9b0 100644
--- a/src/libs/utils/temporarydirectory.cpp
+++ b/src/libs/utils/temporarydirectory.cpp
@@ -25,6 +25,8 @@
#include "temporarydirectory.h"
+#include "fileutils.h"
+
#include
#include "qtcassert.h"
@@ -64,4 +66,14 @@ QString TemporaryDirectory::masterDirectoryPath()
return m_masterTemporaryDir->path();
}
+FilePath TemporaryDirectory::path() const
+{
+ return FilePath::fromString(QTemporaryDir::path());
+}
+
+FilePath TemporaryDirectory::filePath(const QString &fileName) const
+{
+ return FilePath::fromString(QTemporaryDir::filePath(fileName));
+}
+
} // namespace Utils
diff --git a/src/libs/utils/temporarydirectory.h b/src/libs/utils/temporarydirectory.h
index 853474c24bd..42390a9a0f2 100644
--- a/src/libs/utils/temporarydirectory.h
+++ b/src/libs/utils/temporarydirectory.h
@@ -31,6 +31,8 @@
namespace Utils {
+class FilePath;
+
class QTCREATOR_UTILS_EXPORT TemporaryDirectory : public QTemporaryDir
{
public:
@@ -39,6 +41,9 @@ public:
static QTemporaryDir *masterTemporaryDirectory();
static void setMasterTemporaryDirectory(const QString &pattern);
static QString masterDirectoryPath();
+
+ FilePath path() const;
+ FilePath filePath(const QString &fileName) const;
};
} // namespace Utils
diff --git a/src/plugins/android/addnewavddialog.ui b/src/plugins/android/addnewavddialog.ui
index c60b43fdb3e..f0736429a0c 100644
--- a/src/plugins/android/addnewavddialog.ui
+++ b/src/plugins/android/addnewavddialog.ui
@@ -6,22 +6,9 @@
0
0
- 600
- 243
+ 800
-
-
- 600
- 0
-
-
-
-
- 1024
- 16777215
-
-
Create new AVD
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index d149b2033ca..1e895311724 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -748,28 +748,54 @@ void AndroidBuildApkStep::doRun()
auto setup = [this] {
const auto androidAbis = AndroidManager::applicationAbis(target());
+ const QString buildKey = target()->activeBuildKey();
+
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
+ if (!version)
+ return false;
+
for (const auto &abi : androidAbis) {
FilePath androidLibsDir = buildDirectory() / "android-build/libs" / abi;
- if (!androidLibsDir.exists() && !QDir{buildDirectory().toString()}.mkpath(androidLibsDir.toString()))
- return false;
- }
+ if (!androidLibsDir.exists()) {
+ if (!QDir{buildDirectory().toString()}.mkpath(androidLibsDir.toString())) {
+ const QString error = tr("The Android build folder %1 wasn't found and "
+ "couldn't be created.").arg(androidLibsDir.toString());
+ emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
+ TaskHub::addTask(BuildSystemTask(Task::Error, error));
+ return false;
+ } else if (version->qtVersion() >= QtSupport::QtVersionNumber{6, 0, 0}
+ && version->qtVersion() <= QtSupport::QtVersionNumber{6, 1, 1}) {
+ // 6.0.x <= Qt <= 6.1.1 used to need a manaul call to _prepare_apk_dir target,
+ // and now it's made directly with ALL target, so this code below ensures
+ // these versions are not broken.
+ const QString fileName = QString("lib%1_%2.so").arg(buildKey, abi);
+ const FilePath from = buildDirectory() / fileName;
+ const FilePath to = androidLibsDir / fileName;
+ if (!from.exists() || to.exists())
+ continue;
- const QString buildKey = target()->activeBuildKey();
- BuildSystem *bs = buildSystem();
+ if (!QFile::copy(from.toString(), to.toString())) {
+ const QString error = tr("Couldn't copy the target's lib file %1 to the "
+ "Android build folder %2.")
+ .arg(fileName, androidLibsDir.toString());
+ emit addOutput(error, BuildStep::OutputFormat::ErrorMessage);
+ TaskHub::addTask(BuildSystemTask(Task::Error, error));
+ return false;
+ }
+ }
+ }
+
+ }
bool inputExists = QFile::exists(m_inputFile);
if (inputExists && !AndroidManager::isQtCreatorGenerated(FilePath::fromString(m_inputFile)))
return true; // use the generated file if it was not generated by qtcreator
+ BuildSystem *bs = buildSystem();
auto targets = bs->extraData(buildKey, Android::Constants::AndroidTargets).toStringList();
if (targets.isEmpty())
return inputExists; // qmake does this job for us
-
- QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit());
- if (!version)
- return false;
-
QJsonObject deploySettings = Android::AndroidManager::deploymentSettings(target());
QString applicationBinary;
if (!version->supportsMultipleQtAbis()) {
diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp
index 159fd00f9e6..db74a953970 100644
--- a/src/plugins/android/androidmanifesteditorwidget.cpp
+++ b/src/plugins/android/androidmanifesteditorwidget.cpp
@@ -404,12 +404,6 @@ QGroupBox *Android::Internal::AndroidManifestEditorWidget::createApplicationGrou
m_activityNameLineEdit = new QLineEdit(applicationGroupBox);
formLayout->addRow(tr("Activity name:"), m_activityNameLineEdit);
- m_targetLineEdit = new QComboBox(applicationGroupBox);
- m_targetLineEdit->setEditable(true);
- m_targetLineEdit->setDuplicatesEnabled(true);
- m_targetLineEdit->installEventFilter(this);
- formLayout->addRow(tr("Run:"), m_targetLineEdit);
-
m_styleExtractMethod = new QComboBox(applicationGroupBox);
formLayout->addRow(tr("Style extraction:"), m_styleExtractMethod);
const QList styleMethodsMap = {
@@ -467,8 +461,6 @@ QGroupBox *Android::Internal::AndroidManifestEditorWidget::createApplicationGrou
this, [this]() { setDirty(); });
connect(m_activityNameLineEdit, &QLineEdit::textEdited,
this, [this]() { setDirty(); });
- connect(m_targetLineEdit, &QComboBox::currentTextChanged,
- this, [this]() { setDirty(); });
connect(m_styleExtractMethod,
QOverload::of(&QComboBox::currentIndexChanged),
this, [this]() { setDirty(); });
@@ -532,16 +524,6 @@ void AndroidManifestEditorWidget::initializePage()
insertWidget(Source, m_textEditorWidget);
}
-bool AndroidManifestEditorWidget::eventFilter(QObject *obj, QEvent *event)
-{
- if (obj == m_targetLineEdit) {
- if (event->type() == QEvent::FocusIn)
- QTimer::singleShot(0, this, &AndroidManifestEditorWidget::updateTargetComboBox);
- }
-
- return QWidget::eventFilter(obj, event);
-}
-
void AndroidManifestEditorWidget::focusInEvent(QFocusEvent *event)
{
if (currentWidget()) {
@@ -552,30 +534,6 @@ void AndroidManifestEditorWidget::focusInEvent(QFocusEvent *event)
}
}
-void AndroidManifestEditorWidget::updateTargetComboBox()
-{
- QStringList items;
- if (Target *target = androidTarget(m_textEditorWidget->textDocument()->filePath())) {
- ProjectNode *root = target->project()->rootProjectNode();
- root->forEachProjectNode([&items](const ProjectNode *projectNode) {
- items << projectNode->targetApplications();
- });
- items.sort();
- }
-
- // QComboBox randomly resets what the user has entered
- // if all rows are removed, thus we ensure that the current text
- // is not removed by first adding it and then removing all old rows
- // and then adding the new rows
- QString text = m_targetLineEdit->currentText();
- m_targetLineEdit->addItem(text);
- while (m_targetLineEdit->count() > 1)
- m_targetLineEdit->removeItem(0);
- items.removeDuplicates();
- items.removeAll(text);
- m_targetLineEdit->addItems(items);
-}
-
void AndroidManifestEditorWidget::updateAfterFileLoad()
{
QString error;
@@ -877,11 +835,7 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc)
enum SplashImageParseGuard {splashNone = 0, splash = 1, portraitSplash = 2, landscapeSplash = 4, splashDone = 8};
int splashParseGuard = SplashImageParseGuard::splashNone;
while (!metadataElem.isNull()) {
- if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")
- && !(activityParseGuard & ActivityParseGuard::libName)) {
- m_targetLineEdit->setEditText(metadataElem.attribute(QLatin1String("android:value")));
- activityParseGuard |= ActivityParseGuard::libName;
- } else if (metadataElem.attribute(QLatin1String("android:name"))
+ if (metadataElem.attribute(QLatin1String("android:name"))
== QLatin1String("android.app.extract_android_style")
&& !(activityParseGuard & ActivityParseGuard::styleExtract)) {
m_styleExtractMethod->setCurrentText(
@@ -1392,13 +1346,6 @@ void AndroidManifestEditorWidget::parseActivity(QXmlStreamReader &reader, QXmlSt
while (!reader.atEnd()) {
if (reader.isEndElement()) {
parseSplashScreen(writer);
- if (!found) {
- writer.writeEmptyElement(QLatin1String("meta-data"));
- writer.writeAttribute(QLatin1String("android:name"),
- QLatin1String("android.app.lib_name"));
- writer.writeAttribute(QLatin1String("android:value"),
- m_targetLineEdit->currentText());
- }
writer.writeCurrentToken(reader);
return;
} else if (reader.isStartElement()) {
@@ -1429,12 +1376,7 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt
QStringList keys;
QStringList values;
- if (attributes.value(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) {
- keys = QStringList("android:value");
- values = QStringList(m_targetLineEdit->currentText());
- result = modifyXmlStreamAttributes(attributes, keys, values);
- found = true;
- } else if (attributes.value(QLatin1String("android:name"))
+ if (attributes.value(QLatin1String("android:name"))
== QLatin1String("android.app.extract_android_style")) {
keys = QStringList("android:value");
values = QStringList(m_styleExtractMethod->currentText());
diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h
index 23f97fd0000..1dd134b08c2 100644
--- a/src/plugins/android/androidmanifesteditorwidget.h
+++ b/src/plugins/android/androidmanifesteditorwidget.h
@@ -115,7 +115,6 @@ signals:
void guiChanged();
protected:
- bool eventFilter(QObject *obj, QEvent *event) override;
void focusInEvent(QFocusEvent *event) override;
private:
@@ -142,8 +141,6 @@ private:
void setInvalidServiceInfo();
void clearInvalidServiceInfo();
- void updateTargetComboBox();
-
void parseManifest(QXmlStreamReader &reader, QXmlStreamWriter &writer);
void parseApplication(QXmlStreamReader &reader, QXmlStreamWriter &writer);
void parseSplashScreen(QXmlStreamWriter &writer);
@@ -181,7 +178,6 @@ private:
// Application
QLineEdit *m_appNameLineEdit;
QLineEdit *m_activityNameLineEdit;
- QComboBox *m_targetLineEdit;
QComboBox *m_styleExtractMethod;
QComboBox *m_screenOrientation;
AndroidManifestEditorIconContainerWidget *m_iconButtons;
diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp
index bb196834dd3..d8247de83c5 100644
--- a/src/plugins/android/androidpackageinstallationstep.cpp
+++ b/src/plugins/android/androidpackageinstallationstep.cpp
@@ -137,7 +137,7 @@ void AndroidPackageInstallationStep::doRun()
FilePath androidDir = FilePath::fromString(dir);
if (!dir.isEmpty() && androidDir.exists()) {
emit addOutput(tr("Removing directory %1").arg(dir), OutputFormat::NormalMessage);
- if (!FileUtils::removeRecursively(androidDir, &error)) {
+ if (!androidDir.removeRecursively(&error)) {
emit addOutput(error, OutputFormat::Stderr);
TaskHub::addTask(BuildSystemTask(Task::Error, error));
emit finished(false);
diff --git a/src/plugins/android/javalanguageserver.cpp b/src/plugins/android/javalanguageserver.cpp
index 73de7c0bac2..c7c093f53c3 100644
--- a/src/plugins/android/javalanguageserver.cpp
+++ b/src/plugins/android/javalanguageserver.cpp
@@ -183,7 +183,7 @@ class JLSInterface : public LanguageClient::StdIOClientInterface
public:
JLSInterface() = default;
- QString workspaceDir() const { return m_workspaceDir.path(); }
+ QString workspaceDir() const { return m_workspaceDir.path().path(); }
private:
TemporaryDirectory m_workspaceDir = TemporaryDirectory("QtCreator-jls-XXXXXX");
diff --git a/src/plugins/autotest/ctest/ctestoutputreader.cpp b/src/plugins/autotest/ctest/ctestoutputreader.cpp
index be20942da5e..31b41b41349 100644
--- a/src/plugins/autotest/ctest/ctestoutputreader.cpp
+++ b/src/plugins/autotest/ctest/ctestoutputreader.cpp
@@ -84,6 +84,8 @@ void CTestOutputReader::processOutputLine(const QByteArray &outputLine)
static const QRegularExpression testResult("^\\s*\\d+/\\d+ Test\\s+#\\d+: (.*) (\\.+)\\s*"
"(Passed|\\*\\*\\*Failed|\\*\\*\\*Not Run|"
".*\\*\\*\\*Exception:.*)\\s+(.*) sec$");
+ static const QRegularExpression testCrash("^\\s*\\d+/\\d+ Test\\s+#\\d+: (.*) (\\.+)\\s*"
+ "Exit code .*$");
static const QRegularExpression summary("^\\d+% tests passed, (\\d+) tests failed "
"out of (\\d+)");
static const QRegularExpression summaryTime("^Total Test time .* =\\s+(.*) sec$");
@@ -137,10 +139,19 @@ void CTestOutputReader::processOutputLine(const QByteArray &outputLine)
testResult->setResult(ResultType::TestEnd);
testResult->setDescription(match.captured());
reportResult(testResult);
+ } else if (ExactMatch match = testCrash.match(line)) {
+ m_description = match.captured();
+ m_testName = match.captured(1);
+ m_result = ResultType::Fail;
+ m_expectExceptionFromCrash = true;
} else {
if (!m_description.isEmpty())
m_description.append('\n');
m_description.append(line);
+ if (m_expectExceptionFromCrash) {
+ if (QTC_GUARD(line.startsWith("***Exception:")))
+ m_expectExceptionFromCrash = false;
+ }
}
}
diff --git a/src/plugins/autotest/ctest/ctestoutputreader.h b/src/plugins/autotest/ctest/ctestoutputreader.h
index b5baaaf96c5..baff9a9ca17 100644
--- a/src/plugins/autotest/ctest/ctestoutputreader.h
+++ b/src/plugins/autotest/ctest/ctestoutputreader.h
@@ -46,6 +46,7 @@ protected:
QString m_testName;
QString m_description;
ResultType m_result = ResultType::Invalid;
+ bool m_expectExceptionFromCrash = false;
};
} // namespace Internal
diff --git a/src/plugins/autotest/ctest/ctesttreeitem.cpp b/src/plugins/autotest/ctest/ctesttreeitem.cpp
index 25e7ad44f14..382241b8805 100644
--- a/src/plugins/autotest/ctest/ctesttreeitem.cpp
+++ b/src/plugins/autotest/ctest/ctesttreeitem.cpp
@@ -32,6 +32,7 @@
#include "../testsettings.h"
#include
+#include
#include
#include
#include
@@ -115,13 +116,17 @@ QList CTestTreeItem::testConfigurationsFor(const QStringLi
CTestConfiguration *config = new CTestConfiguration(testBase());
config->setProject(project);
config->setCommandLine(command);
- const QList buildConfigs = target->buildConfigurations();
- if (QTC_GUARD(!buildConfigs.isEmpty())) {
- config->setEnvironment(buildConfigs.first()->environment());
- config->setWorkingDirectory(buildConfigs.first()->buildDirectory().toString());
- } else {
- config->setEnvironment(Utils::Environment::systemEnvironment());
+ const ProjectExplorer::RunConfiguration *runConfig = target->activeRunConfiguration();
+ if (QTC_GUARD(runConfig)) {
+ if (auto envAspect = runConfig->aspect())
+ config->setEnvironment(envAspect->environment());
+ else
+ config->setEnvironment(Utils::Environment::systemEnvironment());
}
+ const ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration();
+ if (QTC_GUARD(buildConfig))
+ config->setWorkingDirectory(buildConfig->buildDirectory().toString());
+
if (selected.isEmpty())
config->setTestCaseCount(testBase()->asTestTool()->rootNode()->childCount());
else
diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp
index f2fc52778de..82675cd8305 100644
--- a/src/plugins/autotest/testcodeparser.cpp
+++ b/src/plugins/autotest/testcodeparser.cpp
@@ -97,10 +97,10 @@ void TestCodeParser::setState(State state)
m_parserState = state;
if (m_parserState == Idle && SessionManager::startupProject()) {
- if (m_fullUpdatePostponed || m_dirty) {
+ if (m_postponedUpdateType == UpdateType::FullUpdate || m_dirty) {
emitUpdateTestTree();
- } else if (m_partialUpdatePostponed) {
- m_partialUpdatePostponed = false;
+ } else if (m_postponedUpdateType == UpdateType::PartialUpdate) {
+ m_postponedUpdateType = UpdateType::NoUpdate;
qCDebug(LOG) << "calling scanForTests with postponed files (setState)";
if (!m_reparseTimer.isActive())
scanForTests(Utils::toList(m_postponedFiles));
@@ -112,7 +112,7 @@ void TestCodeParser::syncTestFrameworks(const QList &parsers)
{
if (m_parserState != Idle) {
// there's a running parse
- m_fullUpdatePostponed = m_partialUpdatePostponed = false;
+ m_postponedUpdateType = UpdateType::NoUpdate;
m_postponedFiles.clear();
Core::ProgressManager::cancelTasks(Constants::TASK_PARSE);
}
@@ -142,8 +142,7 @@ void TestCodeParser::updateTestTree(const QSet &parsers)
{
m_singleShotScheduled = false;
if (m_codeModelParsing) {
- m_fullUpdatePostponed = true;
- m_partialUpdatePostponed = false;
+ m_postponedUpdateType = UpdateType::FullUpdate;
m_postponedFiles.clear();
if (parsers.isEmpty()) {
m_updateParsers.clear();
@@ -157,7 +156,7 @@ void TestCodeParser::updateTestTree(const QSet &parsers)
if (!SessionManager::startupProject())
return;
- m_fullUpdatePostponed = false;
+ m_postponedUpdateType = UpdateType::NoUpdate;
qCDebug(LOG) << "calling scanForTests (updateTestTree)";
QList sortedParsers = Utils::toList(parsers);
Utils::sort(sortedParsers, [](const ITestParser *lhs, const ITestParser *rhs) {
@@ -170,7 +169,7 @@ void TestCodeParser::updateTestTree(const QSet &parsers)
void TestCodeParser::onDocumentUpdated(const Utils::FilePath &fileName, bool isQmlFile)
{
- if (m_codeModelParsing || m_fullUpdatePostponed)
+ if (m_codeModelParsing || m_postponedUpdateType == UpdateType::FullUpdate)
return;
Project *project = SessionManager::startupProject();
@@ -211,7 +210,7 @@ void TestCodeParser::onProjectPartsUpdated(Project *project)
if (project != SessionManager::startupProject())
return;
if (m_codeModelParsing)
- m_fullUpdatePostponed = true;
+ m_postponedUpdateType = UpdateType::FullUpdate;
else
emitUpdateTestTree();
}
@@ -260,19 +259,18 @@ bool TestCodeParser::postponed(const Utils::FilePaths &fileList)
case FullParse:
// parse is running, postponing a full parse
if (fileList.isEmpty()) {
- m_partialUpdatePostponed = false;
m_postponedFiles.clear();
- m_fullUpdatePostponed = true;
+ m_postponedUpdateType = UpdateType::FullUpdate;
qCDebug(LOG) << "Canceling scanForTest (full parse triggered while running a scan)";
Core::ProgressManager::cancelTasks(Constants::TASK_PARSE);
} else {
// partial parse triggered, but full parse is postponed already, ignoring this
- if (m_fullUpdatePostponed)
+ if (m_postponedUpdateType == UpdateType::FullUpdate)
return true;
// partial parse triggered, postpone or add current files to already postponed partial
for (const Utils::FilePath &file : fileList)
m_postponedFiles.insert(file);
- m_partialUpdatePostponed = true;
+ m_postponedUpdateType = UpdateType::PartialUpdate;
}
return true;
case Shutdown:
@@ -378,8 +376,8 @@ void TestCodeParser::onTaskStarted(Utils::Id type)
if (type == CppTools::Constants::TASK_INDEX) {
m_codeModelParsing = true;
if (m_parserState == FullParse || m_parserState == PartialParse) {
- m_fullUpdatePostponed = m_parserState == FullParse;
- m_partialUpdatePostponed = !m_fullUpdatePostponed;
+ m_postponedUpdateType = m_parserState == FullParse
+ ? UpdateType::FullUpdate : UpdateType::PartialUpdate;
qCDebug(LOG) << "Canceling scan for test (CppModelParsing started)";
m_parsingHasFailed = true;
Core::ProgressManager::cancelTasks(Constants::TASK_PARSE);
@@ -417,7 +415,7 @@ void TestCodeParser::onFinished()
qCDebug(LOG) << "setting state to Idle (onFinished, FullParse)";
m_parserState = Idle;
m_dirty = m_parsingHasFailed;
- if (m_partialUpdatePostponed || m_fullUpdatePostponed || m_parsingHasFailed) {
+ if (m_postponedUpdateType != UpdateType::NoUpdate || m_parsingHasFailed) {
onPartialParsingFinished();
} else {
qCDebug(LOG) << "emitting parsingFinished"
@@ -439,19 +437,19 @@ void TestCodeParser::onFinished()
void TestCodeParser::onPartialParsingFinished()
{
- QTC_ASSERT(m_fullUpdatePostponed != m_partialUpdatePostponed
- || ((m_fullUpdatePostponed || m_partialUpdatePostponed) == false),
- m_partialUpdatePostponed = false;m_postponedFiles.clear(););
- if (m_fullUpdatePostponed) {
- m_fullUpdatePostponed = false;
+ const UpdateType oldType = m_postponedUpdateType;
+ m_postponedUpdateType = UpdateType::NoUpdate;
+ switch (oldType) {
+ case UpdateType::FullUpdate:
qCDebug(LOG) << "calling updateTestTree (onPartialParsingFinished)";
updateTestTree(m_updateParsers);
- } else if (m_partialUpdatePostponed) {
- m_partialUpdatePostponed = false;
+ break;
+ case UpdateType::PartialUpdate:
qCDebug(LOG) << "calling scanForTests with postponed files (onPartialParsingFinished)";
if (!m_reparseTimer.isActive())
scanForTests(Utils::toList(m_postponedFiles));
- } else {
+ break;
+ case UpdateType::NoUpdate:
m_dirty |= m_codeModelParsing;
if (m_dirty) {
emit parsingFailed();
@@ -466,6 +464,7 @@ void TestCodeParser::onPartialParsingFinished()
qCDebug(LOG) << "not emitting parsingFinished"
<< "(on PartialParsingFinished, singleshot scheduled)";
}
+ break;
}
}
diff --git a/src/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h
index 85e6f505fec..7027103d277 100644
--- a/src/plugins/autotest/testcodeparser.h
+++ b/src/plugins/autotest/testcodeparser.h
@@ -65,7 +65,7 @@ public:
void syncTestFrameworks(const QList &parsers);
#ifdef WITH_TESTS
bool furtherParsingExpected() const
- { return m_singleShotScheduled || m_fullUpdatePostponed || m_partialUpdatePostponed; }
+ { return m_singleShotScheduled || m_postponedUpdateType != UpdateType::NoUpdate; }
#endif
signals:
@@ -105,8 +105,11 @@ private:
bool m_parsingHasFailed = false;
bool m_codeModelParsing = false;
- bool m_fullUpdatePostponed = false;
- bool m_partialUpdatePostponed = false;
+ enum class UpdateType {
+ NoUpdate,
+ PartialUpdate,
+ FullUpdate
+ } m_postponedUpdateType = UpdateType::NoUpdate;
bool m_dirty = false;
bool m_singleShotScheduled = false;
bool m_reparseTimerTimedOut = false;
diff --git a/src/plugins/clangcodemodel/CMakeLists.txt b/src/plugins/clangcodemodel/CMakeLists.txt
index 4176bfd1e9f..51c89160480 100644
--- a/src/plugins/clangcodemodel/CMakeLists.txt
+++ b/src/plugins/clangcodemodel/CMakeLists.txt
@@ -6,8 +6,8 @@ endif()
add_qtc_plugin(ClangCodeModel
CONDITION TARGET libclang
DEPENDS ClangSupport CPlusPlus
- PLUGIN_DEPENDS Core CppTools LanguageClient ${TEST_LINK_DEPENDS} TextEditor
- PLUGIN_TEST_DEPENDS CppEditor QmakeProjectManager
+ PLUGIN_DEPENDS Core CppEditor CppTools LanguageClient ${TEST_LINK_DEPENDS} TextEditor
+ PLUGIN_TEST_DEPENDS QmakeProjectManager
SOURCES
clangactivationsequencecontextprocessor.cpp clangactivationsequencecontextprocessor.h
clangactivationsequenceprocessor.cpp clangactivationsequenceprocessor.h
@@ -24,11 +24,12 @@ add_qtc_plugin(ClangCodeModel
clangcompletionchunkstotextconverter.cpp clangcompletionchunkstotextconverter.h
clangcompletioncontextanalyzer.cpp clangcompletioncontextanalyzer.h
clangconstants.h
- clangdclient.cpp clangdclient.h
clangcurrentdocumentfilter.cpp clangcurrentdocumentfilter.h
+ clangdclient.cpp clangdclient.h
clangdiagnosticfilter.cpp clangdiagnosticfilter.h
clangdiagnosticmanager.cpp clangdiagnosticmanager.h
clangdiagnostictooltipwidget.cpp clangdiagnostictooltipwidget.h
+ clangdquickfixfactory.cpp clangdquickfixfactory.h
clangeditordocumentparser.cpp clangeditordocumentparser.h
clangeditordocumentprocessor.cpp clangeditordocumentprocessor.h
clangfixitoperation.cpp clangfixitoperation.h
diff --git a/src/plugins/clangcodemodel/clangbackendreceiver.cpp b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
index f9cf7badeaf..181a7f51028 100644
--- a/src/plugins/clangcodemodel/clangbackendreceiver.cpp
+++ b/src/plugins/clangcodemodel/clangbackendreceiver.cpp
@@ -41,8 +41,6 @@
#define qCDebugIpc() qCDebug(ipcLog) << "<===="
-using namespace ClangBackEnd;
-
namespace ClangCodeModel {
namespace Internal {
@@ -189,12 +187,12 @@ void BackendReceiver::alive()
m_aliveHandler();
}
-void BackendReceiver::echo(const EchoMessage &message)
+void BackendReceiver::echo(const ClangBackEnd::EchoMessage &message)
{
qCDebugIpc() << message;
}
-void BackendReceiver::completions(const CompletionsMessage &message)
+void BackendReceiver::completions(const ClangBackEnd::CompletionsMessage &message)
{
qCDebugIpc() << "CompletionsMessage with" << message.codeCompletions.size()
<< "items";
@@ -204,7 +202,7 @@ void BackendReceiver::completions(const CompletionsMessage &message)
processor->handleAvailableCompletions(message.codeCompletions);
}
-void BackendReceiver::annotations(const AnnotationsMessage &message)
+void BackendReceiver::annotations(const ClangBackEnd::AnnotationsMessage &message)
{
qCDebugIpc() << "AnnotationsMessage"
<< "for" << QFileInfo(message.fileContainer.filePath).fileName() << "with"
@@ -230,10 +228,10 @@ void BackendReceiver::annotations(const AnnotationsMessage &message)
}
static
-CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &sourceRange)
+CppTools::CursorInfo::Range toCursorInfoRange(const ClangBackEnd::SourceRangeContainer &sourceRange)
{
- const SourceLocationContainer &start = sourceRange.start;
- const SourceLocationContainer &end = sourceRange.end;
+ const ClangBackEnd::SourceLocationContainer &start = sourceRange.start;
+ const ClangBackEnd::SourceLocationContainer &end = sourceRange.end;
const int length = end.column - start.column;
return {start.line, start.column, length};
@@ -241,13 +239,13 @@ CppTools::CursorInfo::Range toCursorInfoRange(const SourceRangeContainer &source
static
CppTools::CursorInfo toCursorInfo(const CppTools::SemanticInfo::LocalUseMap &localUses,
- const ReferencesMessage &message)
+ const ClangBackEnd::ReferencesMessage &message)
{
CppTools::CursorInfo result;
- const QVector &references = message.references;
+ const QVector &references = message.references;
result.areUseRangesForLocalVariable = message.isLocalVariable;
- for (const SourceRangeContainer &reference : references)
+ for (const ClangBackEnd::SourceRangeContainer &reference : references)
result.useRanges.append(toCursorInfoRange(reference));
result.useRanges.reserve(references.size());
@@ -257,13 +255,13 @@ CppTools::CursorInfo toCursorInfo(const CppTools::SemanticInfo::LocalUseMap &loc
}
static
-CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
+CppTools::SymbolInfo toSymbolInfo(const ClangBackEnd::FollowSymbolMessage &message)
{
CppTools::SymbolInfo result;
- const SourceRangeContainer &range = message.result.range;
+ const ClangBackEnd::SourceRangeContainer &range = message.result.range;
- const SourceLocationContainer &start = range.start;
- const SourceLocationContainer &end = range.end;
+ const ClangBackEnd::SourceLocationContainer &start = range.start;
+ const ClangBackEnd::SourceLocationContainer &end = range.end;
result.startLine = start.line;
result.startColumn = start.column;
result.endLine = end.line;
@@ -275,7 +273,7 @@ CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
return result;
}
-void BackendReceiver::references(const ReferencesMessage &message)
+void BackendReceiver::references(const ClangBackEnd::ReferencesMessage &message)
{
qCDebugIpc() << "ReferencesMessage with"
<< message.references.size() << "references";
@@ -292,22 +290,22 @@ void BackendReceiver::references(const ReferencesMessage &message)
futureInterface.reportFinished();
}
-static Core::HelpItem::Category toHelpItemCategory(ToolTipInfo::QdocCategory category)
+static Core::HelpItem::Category toHelpItemCategory(ClangBackEnd::ToolTipInfo::QdocCategory category)
{
switch (category) {
- case ToolTipInfo::Unknown:
+ case ClangBackEnd::ToolTipInfo::Unknown:
return Core::HelpItem::Unknown;
- case ToolTipInfo::ClassOrNamespace:
+ case ClangBackEnd::ToolTipInfo::ClassOrNamespace:
return Core::HelpItem::ClassOrNamespace;
- case ToolTipInfo::Enum:
+ case ClangBackEnd::ToolTipInfo::Enum:
return Core::HelpItem::Enum;
- case ToolTipInfo::Typedef:
+ case ClangBackEnd::ToolTipInfo::Typedef:
return Core::HelpItem::Typedef;
- case ToolTipInfo::Macro:
+ case ClangBackEnd::ToolTipInfo::Macro:
return Core::HelpItem::Macro;
- case ToolTipInfo::Brief:
+ case ClangBackEnd::ToolTipInfo::Brief:
return Core::HelpItem::Brief;
- case ToolTipInfo::Function:
+ case ClangBackEnd::ToolTipInfo::Function:
return Core::HelpItem::Function;
}
@@ -325,11 +323,11 @@ static QStringList toStringList(const Utf8StringVector &utf8StringVector)
return list;
}
-static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message)
+static CppTools::ToolTipInfo toToolTipInfo(const ClangBackEnd::ToolTipMessage &message)
{
CppTools::ToolTipInfo info;
- const ToolTipInfo &backendInfo = message.toolTipInfo;
+ const ClangBackEnd::ToolTipInfo &backendInfo = message.toolTipInfo;
info.text = backendInfo.text;
info.briefComment = backendInfo.briefComment;
@@ -343,7 +341,7 @@ static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message)
return info;
}
-void BackendReceiver::tooltip(const ToolTipMessage &message)
+void BackendReceiver::tooltip(const ClangBackEnd::ToolTipMessage &message)
{
qCDebugIpc() << "ToolTipMessage" << message.toolTipInfo.text;
diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index f6d7b79071d..57eeb22d870 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -42,7 +42,8 @@ SOURCES += \
clangutils.cpp \
clangoverviewmodel.cpp \
clangdclient.cpp \
- clanggloballocatorfilters.cpp
+ clangdquickfixfactory.cpp \
+ clanggloballocatorfilters.cpp \
HEADERS += \
clangactivationsequencecontextprocessor.h \
@@ -83,7 +84,8 @@ HEADERS += \
clangutils.h \
clangoverviewmodel.h \
clangdclient.h \
- clanggloballocatorfilters.h
+ clangdquickfixfactory.h \
+ clanggloballocatorfilters.h \
FORMS += clangprojectsettingswidget.ui
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index d16c11f7326..18e42a0f04e 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -13,12 +13,12 @@ QtcPlugin {
Depends { name: "Utils" }
Depends { name: "ClangSupport" }
Depends { name: "LanguageClient" }
+ Depends { name: "CppEditor" }
Depends { name: "libclang"; required: false }
Depends { name: "clang_defines" }
pluginTestDepends: [
- "CppEditor",
"QmakeProjectManager",
]
@@ -64,6 +64,8 @@ QtcPlugin {
"clangdiagnosticmanager.h",
"clangdiagnostictooltipwidget.cpp",
"clangdiagnostictooltipwidget.h",
+ "clangdquickfixfactory.cpp",
+ "clangdquickfixfactory.h",
"clangeditordocumentparser.cpp",
"clangeditordocumentparser.h",
"clangeditordocumentprocessor.cpp",
diff --git a/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri b/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri
index f32eaa4c4f4..f333b4dda14 100644
--- a/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri
+++ b/src/plugins/clangcodemodel/clangcodemodel_dependencies.pri
@@ -4,11 +4,11 @@ QTC_LIB_DEPENDS += \
clangsupport
QTC_PLUGIN_DEPENDS += \
coreplugin \
+ cppeditor \
cpptools \
languageclient \
texteditor
QTC_TEST_DEPENDS += \
- cppeditor \
qmakeprojectmanager
equals(TEST, 1): QTC_PLUGIN_DEPENDS += qtsupport
diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
index 2886f637cb3..bc92b1bbab7 100644
--- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
+++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp
@@ -207,7 +207,9 @@ QVector ClangCodeModelPlugin::createTestObjects() const
new Tests::ClangCodeCompletionTest,
new Tests::ClangdTestFindReferences,
new Tests::ClangdTestFollowSymbol,
+ new Tests::ClangdTestHighlighting,
new Tests::ClangdTestLocalReferences,
+ new Tests::ClangdTestTooltips,
};
}
#endif
diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp
index da875481714..a427006d05a 100644
--- a/src/plugins/clangcodemodel/clangdclient.cpp
+++ b/src/plugins/clangcodemodel/clangdclient.cpp
@@ -25,18 +25,22 @@
#include "clangdclient.h"
+#include "clangdiagnosticmanager.h"
+#include "clangtextmark.h"
+
#include
#include
#include
#include
#include
-#include
#include
#include
#include
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -46,6 +50,7 @@
#include
#include
#include
+#include
#include
#include
@@ -55,6 +60,7 @@
#include
#include
+#include
using namespace CPlusPlus;
using namespace Core;
@@ -172,18 +178,50 @@ public:
return true;
}
+ bool isNamespace() const { return role() == "declaration" && kind() == "Namespace"; }
+
QString type() const
{
const Utils::optional arcanaString = arcana();
if (!arcanaString)
return {};
- const int quote1Offset = arcanaString->indexOf('\'');
+ return typeFromPos(*arcanaString, 0);
+ }
+
+ QString typeFromPos(const QString &s, int pos) const
+ {
+ const int quote1Offset = s.indexOf('\'', pos);
if (quote1Offset == -1)
return {};
- const int quote2Offset = arcanaString->indexOf('\'', quote1Offset + 1);
+ const int quote2Offset = s.indexOf('\'', quote1Offset + 1);
if (quote2Offset == -1)
return {};
- return arcanaString->mid(quote1Offset + 1, quote2Offset - quote1Offset - 1);
+ if (s.mid(quote2Offset + 1, 2) == ":'")
+ return typeFromPos(s, quote2Offset + 2);
+ return s.mid(quote1Offset + 1, quote2Offset - quote1Offset - 1);
+ }
+
+ HelpItem::Category qdocCategoryForDeclaration(HelpItem::Category fallback)
+ {
+ const auto childList = children();
+ if (!childList || childList->size() < 2)
+ return fallback;
+ const AstNode c1 = childList->first();
+ if (c1.role() != "type" || c1.kind() != "Auto")
+ return fallback;
+ QList typeCandidates = {childList->at(1)};
+ while (!typeCandidates.isEmpty()) {
+ const AstNode n = typeCandidates.takeFirst();
+ if (n.role() == "type") {
+ if (n.kind() == "Enum")
+ return HelpItem::Enum;
+ if (n.kind() == "Record")
+ return HelpItem::ClassOrNamespace;
+ return fallback;
+ }
+ typeCandidates << n.children().value_or(QList());
+ }
+ return fallback;
}
// Returns true <=> the type is "recursively const".
@@ -196,10 +234,12 @@ public:
QString theType = type();
if (theType.endsWith("const"))
theType.chop(5);
- const int ptrRefCount = theType.count('*') + theType.count('&');
+ const int xrefCount = theType.count("&&");
+ const int refCount = theType.count('&') - 2 * xrefCount;
+ const int ptrRefCount = theType.count('*') + refCount;
const int constCount = theType.count("const");
if (ptrRefCount == 0)
- return constCount > 0 || detailIs("LValueToRValue");
+ return constCount > 0 || detailIs("LValueToRValue") || arcanaContains("xvalue");
return ptrRefCount <= constCount;
}
@@ -210,6 +250,13 @@ public:
&& childList->at(index).range().contains(range);
}
+ bool hasChildWithRole(const QString &role) const
+ {
+ return Utils::contains(children().value_or(QList()), [&role](const AstNode &c) {
+ return c.role() == role;
+ });
+ }
+
QString operatorString() const
{
if (kind() == "BinaryOperator")
@@ -380,10 +427,15 @@ public:
: Request("textDocument/symbolInfo", params) {}
};
-static BaseClientInterface *clientInterface(const Utils::FilePath &jsonDbDir)
+static BaseClientInterface *clientInterface(Project *project, const Utils::FilePath &jsonDbDir)
{
- Utils::CommandLine cmd{CppTools::codeModelSettings()->clangdFilePath(),
- {"--background-index", "--limit-results=0"}};
+ QString indexingOption = "--background-index";
+ const CppTools::ClangdSettings settings(CppTools::ClangdProjectSettings(project).settings());
+ if (!settings.indexingEnabled())
+ indexingOption += "=0";
+ Utils::CommandLine cmd{settings.clangdFilePath(), {indexingOption, "--limit-results=0"}};
+ if (settings.workerThreadLimit() != 0)
+ cmd.addArg("-j=" + QString::number(settings.workerThreadLimit()));
if (!jsonDbDir.isEmpty())
cmd.addArg("--compile-commands-dir=" + jsonDbDir.toString());
if (clangdLog().isDebugEnabled())
@@ -517,7 +569,7 @@ public:
Utils::Link defLink;
QList allLinks;
QHash declDefMap;
- AstNode cursorNode;
+ Utils::optional cursorNode;
AstNode defLinkNode;
SymbolDataList symbolsToDisplay;
std::set openedFiles;
@@ -599,11 +651,29 @@ public:
const int revision;
};
+class DiagnosticsCapabilities : public JsonObject
+{
+public:
+ using JsonObject::JsonObject;
+ void enableCategorySupport() { insert("categorySupport", true); }
+ void enableCodeActionsInline() {insert("codeActionsInline", true);}
+};
+
+class ClangdTextDocumentClientCapabilities : public TextDocumentClientCapabilities
+{
+public:
+ using TextDocumentClientCapabilities::TextDocumentClientCapabilities;
+
+
+ void setPublishDiagnostics(const DiagnosticsCapabilities &caps)
+ { insert("publishDiagnostics", caps); }
+};
class ClangdClient::Private
{
public:
- Private(ClangdClient *q) : q(q) {}
+ Private(ClangdClient *q, Project *project)
+ : q(q), settings(CppTools::ClangdProjectSettings(project).settings()) {}
void handleFindUsagesResult(quint64 key, const QList &locations);
static void handleRenameRequest(const SearchResult *search,
@@ -626,31 +696,93 @@ public:
QString searchTermFromCursor(const QTextCursor &cursor) const;
+ void setHelpItemForTooltip(const MessageId &token, const QString &fqn = {},
+ HelpItem::Category category = HelpItem::Unknown,
+ const QString &type = {});
+
+ void handleSemanticTokens(TextEditor::TextDocument *doc,
+ const QList &tokens);
+
ClangdClient * const q;
+ const CppTools::ClangdSettings::Data settings;
QHash runningFindUsages;
Utils::optional followSymbolData;
Utils::optional switchDeclDefData;
Utils::optional localRefsData;
Utils::optional versionNumber;
+ std::unordered_map highlighters;
quint64 nextJobId = 0;
bool isFullyIndexed = false;
bool isTesting = false;
};
ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
- : Client(clientInterface(jsonDbDir)), d(new Private(this))
+ : Client(clientInterface(project, jsonDbDir)), d(new Private(this, project))
{
setName(tr("clangd"));
LanguageFilter langFilter;
langFilter.mimeTypes = QStringList{"text/x-chdr", "text/x-csrc",
"text/x-c++hdr", "text/x-c++src", "text/x-objc++src", "text/x-objcsrc"};
setSupportedLanguage(langFilter);
- LanguageServerProtocol::ClientCapabilities caps = Client::defaultClientCapabilities();
+ setActivateDocumentAutomatically(true);
+ ClientCapabilities caps = Client::defaultClientCapabilities();
+ Utils::optional textCaps = caps.textDocument();
+ if (textCaps) {
+ ClangdTextDocumentClientCapabilities clangdTextCaps(*textCaps);
+ clangdTextCaps.clearCompletion();
+ clangdTextCaps.clearDocumentHighlight();
+ DiagnosticsCapabilities diagnostics;
+ diagnostics.enableCategorySupport();
+ diagnostics.enableCodeActionsInline();
+ clangdTextCaps.setPublishDiagnostics(diagnostics);
+ caps.setTextDocument(clangdTextCaps);
+ }
caps.clearExperimental();
setClientCapabilities(caps);
setLocatorsEnabled(false);
setProgressTitleForToken(indexingToken(), tr("Parsing C/C++ Files (clangd)"));
setCurrentProject(project);
+
+ const auto textMarkCreator = [this](const Utils::FilePath &filePath,
+ const Diagnostic &diag) { return new ClangdTextMark(filePath, diag, this); };
+ const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); };
+ setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler);
+
+ static const auto symbolStringifier = [](SymbolKind kind, const QString &name,
+ const QString &detail) -> QString
+ {
+ switch (kind) {
+ case LanguageServerProtocol::SymbolKind::Constructor:
+ return name + detail;
+ case LanguageServerProtocol::SymbolKind::Method:
+ case LanguageServerProtocol::SymbolKind::Function: {
+ const int parenOffset = detail.indexOf(" (");
+ if (parenOffset == -1)
+ return name;
+ return name + detail.mid(parenOffset + 1) + " -> " + detail.mid(0, parenOffset);
+ }
+ case LanguageServerProtocol::SymbolKind::Variable:
+ case LanguageServerProtocol::SymbolKind::Field:
+ case LanguageServerProtocol::SymbolKind::Constant:
+ if (detail.isEmpty())
+ return name;
+ return name + " -> " + detail;
+ default:
+ return name;
+ }
+ };
+ setSymbolStringifier(symbolStringifier);
+
+ setSemanticTokensHandler([this](TextEditor::TextDocument *doc,
+ const QList &tokens) {
+ d->handleSemanticTokens(doc, tokens);
+ });
+
+ hoverHandler()->setHelpItemProvider([this](const HoverRequest::Response &response,
+ const DocumentUri &uri) {
+ gatherHelpItemForTooltip(response, uri);
+ });
+
connect(this, &Client::workDone, this, [this, project](const ProgressToken &token) {
const QString * const val = Utils::get_if(&token);
if (val && *val == indexingToken()) {
@@ -786,6 +918,22 @@ void ClangdClient::findUsages(TextEditor::TextDocument *document, const QTextCur
void ClangdClient::enableTesting() { d->isTesting = true; }
+void ClangdClient::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
+{
+ const DocumentUri &uri = params.uri();
+ Client::handleDiagnostics(params);
+ for (const Diagnostic &diagnostic : params.diagnostics()) {
+ const ClangdDiagnostic clangdDiagnostic(diagnostic);
+ for (const CodeAction &action : clangdDiagnostic.codeActions().value_or(QList{}))
+ LanguageClient::updateCodeActionRefactoringMarker(this, action, uri);
+ }
+}
+
+void ClangdClient::handleDocumentClosed(TextEditor::TextDocument *doc)
+{
+ d->highlighters.erase(doc);
+}
+
QVersionNumber ClangdClient::versionNumber() const
{
if (d->versionNumber)
@@ -804,6 +952,8 @@ QVersionNumber ClangdClient::versionNumber() const
return d->versionNumber.value();
}
+CppTools::ClangdSettings::Data ClangdClient::settingsData() const { return d->settings; }
+
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList &locations)
{
const auto refData = runningFindUsages.find(key);
@@ -1019,11 +1169,16 @@ void ClangdClient::followSymbol(
if (!d->followSymbolData || id != d->followSymbolData->id)
return;
d->followSymbolData->defLink = link;
- if (d->followSymbolData->cursorNode.isValid())
+ if (d->followSymbolData->cursorNode)
d->handleGotoDefinitionResult();
};
symbolSupport().findLinkAt(document, cursor, std::move(gotoDefCallback), true);
+ if (versionNumber() < QVersionNumber(12)) {
+ d->followSymbolData->cursorNode.emplace(AstNode());
+ return;
+ }
+
AstRequest astRequest(AstParams(TextDocumentIdentifier(d->followSymbolData->uri),
Range(cursor)));
astRequest.setResponseCallback([this, id = d->followSymbolData->id](
@@ -1032,11 +1187,10 @@ void ClangdClient::followSymbol(
if (!d->followSymbolData || d->followSymbolData->id != id)
return;
const auto result = response.result();
- if (!result) {
- d->followSymbolData.reset();
- return;
- }
- d->followSymbolData->cursorNode = *result;
+ if (result)
+ d->followSymbolData->cursorNode = *result;
+ else
+ d->followSymbolData->cursorNode.emplace(AstNode());
if (d->followSymbolData->defLink.hasValidTarget())
d->handleGotoDefinitionResult();
});
@@ -1167,6 +1321,154 @@ void ClangdClient::findLocalUsages(TextEditor::TextDocument *document, const QTe
symbolSupport().findLinkAt(document, cursor, std::move(gotoDefCallback), true);
}
+void ClangdClient::gatherHelpItemForTooltip(const HoverRequest::Response &hoverResponse,
+ const DocumentUri &uri)
+{
+ // Macros aren't locatable via the AST, so parse the formatted string.
+ if (const Utils::optional result = hoverResponse.result()) {
+ const HoverContent content = result->content();
+ const MarkupContent * const markup = Utils::get_if(&content);
+ if (markup) {
+ const QString markupString = markup->content();
+ static const QString magicMacroPrefix = "### macro `";
+ if (markupString.startsWith(magicMacroPrefix)) {
+ const int nameStart = magicMacroPrefix.length();
+ const int closingQuoteIndex = markupString.indexOf('`', nameStart);
+ if (closingQuoteIndex != -1) {
+ const QString macroName = markupString.mid(nameStart,
+ closingQuoteIndex - nameStart);
+ d->setHelpItemForTooltip(hoverResponse.id(), macroName, HelpItem::Macro);
+ return;
+ }
+ }
+ }
+ }
+
+ AstRequest req((AstParams(TextDocumentIdentifier(uri))));
+ req.setResponseCallback([this, uri, hoverResponse](const AstRequest::Response &response) {
+ const MessageId id = hoverResponse.id();
+ const AstNode ast = response.result().value_or(AstNode());
+ const Range range = hoverResponse.result()->range().value_or(Range());
+ const QList path = getAstPath(ast, range);
+ if (path.isEmpty()) {
+ d->setHelpItemForTooltip(id);
+ return;
+ }
+ AstNode node = path.last();
+ if (node.role() == "expression" && node.kind() == "ImplicitCast") {
+ const Utils::optional> children = node.children();
+ if (children && !children->isEmpty())
+ node = children->first();
+ }
+ while (node.kind() == "Qualified") {
+ const Utils::optional> children = node.children();
+ if (children && !children->isEmpty())
+ node = children->first();
+ }
+ if (clangdLog().isDebugEnabled())
+ node.print(0);
+
+ QString type = node.type();
+ const auto stripTemplatePartOffType = [&type] {
+ const int angleBracketIndex = type.indexOf('<');
+ if (angleBracketIndex != -1)
+ type = type.left(angleBracketIndex);
+ };
+
+ const bool isMemberFunction = node.role() == "expression" && node.kind() == "Member"
+ && (node.arcanaContains("member function") || type.contains('('));
+ const bool isFunction = node.role() == "expression" && node.kind() == "DeclRef"
+ && type.contains('(');
+ if (isMemberFunction || isFunction) {
+ const TextDocumentPositionParams params(TextDocumentIdentifier(uri), range.start());
+ SymbolInfoRequest symReq(params);
+ symReq.setResponseCallback([this, id, type, isFunction]
+ (const SymbolInfoRequest::Response &response) {
+ qCDebug(clangdLog) << "handling symbol info reply";
+ QString fqn;
+ if (const auto result = response.result()) {
+ if (const auto list = Utils::get_if>(&result.value())) {
+ if (!list->isEmpty()) {
+ const SymbolDetails &sd = list->first();
+ fqn = sd.containerName() + sd.name();
+ }
+ }
+ }
+
+ // Unfortunately, the arcana string contains the signature only for
+ // free functions, so we can't distinguish member function overloads.
+ // But since HtmlDocExtractor::getFunctionDescription() is always called
+ // with mainOverload = true, such information would get ignored anyway.
+ d->setHelpItemForTooltip(id, fqn, HelpItem::Function, isFunction ? type : "()");
+ });
+ sendContent(symReq);
+ return;
+ }
+ if ((node.role() == "expression" && node.kind() == "DeclRef")
+ || (node.role() == "declaration"
+ && (node.kind() == "Var" || node.kind() == "ParmVar"
+ || node.kind() == "Field"))) {
+ if (node.arcanaContains("EnumConstant")) {
+ d->setHelpItemForTooltip(id, node.detail().value_or(QString()),
+ HelpItem::Enum, type);
+ return;
+ }
+ stripTemplatePartOffType();
+ type.remove("&").remove("*").remove("const ").remove(" const")
+ .remove("volatile ").remove(" volatile");
+ type = type.simplified();
+ if (type != "int" && !type.contains(" int")
+ && type != "char" && !type.contains(" char")
+ && type != "double" && !type.contains(" double")
+ && type != "float" && type != "bool") {
+ d->setHelpItemForTooltip(id, type, node.qdocCategoryForDeclaration(
+ HelpItem::ClassOrNamespace));
+ } else {
+ d->setHelpItemForTooltip(id);
+ }
+ return;
+ }
+ if (node.isNamespace()) {
+ QString ns = node.detail().value_or(QString());
+ for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
+ if (it->isNamespace()) {
+ const QString name = it->detail().value_or(QString());
+ if (!name.isEmpty())
+ ns.prepend("::").prepend(name);
+ }
+ }
+ d->setHelpItemForTooltip(hoverResponse.id(), ns, HelpItem::ClassOrNamespace);
+ return;
+ }
+ if (node.role() == "type") {
+ if (node.kind() == "Enum") {
+ d->setHelpItemForTooltip(id, node.detail().value_or(QString()), HelpItem::Enum);
+ } else if (node.kind() == "Record" || node.kind() == "TemplateSpecialization") {
+ stripTemplatePartOffType();
+ d->setHelpItemForTooltip(id, type, HelpItem::ClassOrNamespace);
+ } else if (node.kind() == "Typedef") {
+ d->setHelpItemForTooltip(id, type, HelpItem::Typedef);
+ } else {
+ d->setHelpItemForTooltip(id);
+ }
+ return;
+ }
+ if (node.role() == "expression" && node.kind() == "CXXConstruct") {
+ const QString name = node.detail().value_or(QString());
+ if (!name.isEmpty())
+ type = name;
+ d->setHelpItemForTooltip(id, type, HelpItem::ClassOrNamespace);
+ }
+ if (node.role() == "specifier" && node.kind() == "NamespaceAlias") {
+ d->setHelpItemForTooltip(id, node.detail().value_or(QString()).chopped(2),
+ HelpItem::ClassOrNamespace);
+ return;
+ }
+ d->setHelpItemForTooltip(id);
+ });
+ sendContent(req);
+}
+
void ClangdClient::Private::handleGotoDefinitionResult()
{
QTC_ASSERT(followSymbolData->defLink.hasValidTarget(), return);
@@ -1174,8 +1476,8 @@ void ClangdClient::Private::handleGotoDefinitionResult()
qCDebug(clangdLog) << "handling go to definition result";
// No dis-ambiguation necessary. Call back with the link and finish.
- if (!followSymbolData->cursorNode.mightBeAmbiguousVirtualCall()
- && !followSymbolData->cursorNode.isPureVirtualDeclaration()) {
+ if (!followSymbolData->cursorNode->mightBeAmbiguousVirtualCall()
+ && !followSymbolData->cursorNode->isPureVirtualDeclaration()) {
followSymbolData->callback(followSymbolData->defLink);
followSymbolData.reset();
return;
@@ -1190,6 +1492,10 @@ void ClangdClient::Private::handleGotoDefinitionResult()
void ClangdClient::Private::sendGotoImplementationRequest(const Utils::Link &link)
{
+ if (!q->documentForFilePath(link.targetFilePath)
+ && followSymbolData->openedFiles.insert(link.targetFilePath).second) {
+ q->openExtraFile(link.targetFilePath);
+ }
const Position position(link.targetLine - 1, link.targetColumn);
const TextDocumentIdentifier documentId(DocumentUri::fromFilePath(link.targetFilePath));
GotoImplementationRequest req(TextDocumentPositionParams(documentId, position));
@@ -1405,6 +1711,683 @@ QString ClangdClient::Private::searchTermFromCursor(const QTextCursor &cursor) c
return termCursor.selectedText();
}
+void ClangdClient::Private::setHelpItemForTooltip(const MessageId &token, const QString &fqn,
+ HelpItem::Category category,
+ const QString &type)
+{
+ QStringList helpIds;
+ QString mark;
+ if (!fqn.isEmpty()) {
+ helpIds << fqn;
+ int sepSearchStart = 0;
+ while (true) {
+ sepSearchStart = fqn.indexOf("::", sepSearchStart);
+ if (sepSearchStart == -1)
+ break;
+ sepSearchStart += 2;
+ helpIds << fqn.mid(sepSearchStart);
+ }
+ mark = helpIds.last();
+ if (category == HelpItem::Function)
+ mark += type.mid(type.indexOf('('));
+ }
+ if (category == HelpItem::Enum && !type.isEmpty())
+ mark = type;
+
+ HelpItem helpItem(helpIds, mark, category);
+ if (isTesting)
+ emit q->helpItemGathered(helpItem);
+ else
+ q->hoverHandler()->setHelpItem(token, helpItem);
+}
+
+static void collectExtraResults(QFutureInterface &future,
+ TextEditor::HighlightingResults &results, const AstNode &ast,
+ QTextDocument *doc, const QString &docContent)
+{
+ if (!ast.isValid())
+ return;
+
+ static const auto lessThan = [](const TextEditor::HighlightingResult &r1,
+ const TextEditor::HighlightingResult &r2) {
+ return r1.line < r2.line || (r1.line == r2.line && r1.column < r2.column)
+ || (r1.line == r2.line && r1.column == r2.column && r1.length < r2.length);
+ };
+ const auto insert = [&](const TextEditor::HighlightingResult &result) {
+ if (!result.isValid()) // Some nodes don't have a range.
+ return;
+ const auto it = std::lower_bound(results.begin(), results.end(), result, lessThan);
+ if (it == results.end() || *it != result) {
+ qCDebug(clangdLog) << "adding additional highlighting result"
+ << result.line << result.column << result.length;
+ results.insert(it, result);
+ return;
+ }
+
+ // This is for conversion operators, whose type part is only reported as a type by clangd.
+ if ((it->textStyles.mainStyle == TextEditor::C_TYPE
+ || it->textStyles.mainStyle == TextEditor::C_PRIMITIVE_TYPE)
+ && !result.textStyles.mixinStyles.empty()
+ && result.textStyles.mixinStyles.at(0) == TextEditor::C_OPERATOR) {
+ it->textStyles.mixinStyles = result.textStyles.mixinStyles;
+ }
+ };
+ const auto setFromRange = [doc](TextEditor::HighlightingResult &result, const Range &range) {
+ if (!range.isValid())
+ return;
+ const Position startPos = range.start();
+ const Position endPos = range.end();
+ result.line = startPos.line() + 1;
+ result.column = startPos.character() + 1;
+ result.length = endPos.toPositionInDocument(doc) - startPos.toPositionInDocument(doc);
+ };
+ static const auto onlyIndexOf = [](const QStringView &view, const QStringView &s,
+ int from = 0) {
+ const int firstIndex = view.indexOf(s, from);
+ if (firstIndex == -1)
+ return -1;
+ const int nextIndex = view.indexOf(s, firstIndex + 1);
+
+ // The second condion deals with the off-by-one error in TemplateSpecialization nodes;
+ // see below.
+ return nextIndex == -1 || nextIndex == firstIndex + 1 ? firstIndex : -1;
+ };
+
+ QList nodes = {ast};
+ while (!nodes.isEmpty()) {
+ if (future.isCanceled())
+ return;
+ const AstNode node = nodes.takeFirst();
+ const QList children = node.children().value_or(QList());
+ nodes << children;
+
+ if (node.kind().endsWith("Literal")) {
+ TextEditor::HighlightingResult result;
+ result.useTextSyles = true;
+ const bool isStringLike = node.kind().startsWith("String")
+ || node.kind().startsWith("Character");
+ result.textStyles.mainStyle = isStringLike
+ ? TextEditor::C_STRING : TextEditor::C_NUMBER;
+ setFromRange(result, node.range());
+ insert(result);
+ continue;
+ }
+ if (node.role() == "type" && node.kind() == "Builtin") {
+ TextEditor::HighlightingResult result;
+ result.useTextSyles = true;
+ result.textStyles.mainStyle = TextEditor::C_PRIMITIVE_TYPE;
+ setFromRange(result, node.range());
+ insert(result);
+ continue;
+ }
+
+ const bool isExpression = node.role() == "expression";
+ const bool isDeclaration = node.role() == "declaration";
+
+ // Unfortunately, the exact position of a specific token is usually not
+ // recorded in the AST, so if we need that, we have to search for it textually.
+ // In corner cases, this might get sabotaged by e.g. comments, in which case we give up.
+ const auto posForNodeStart = [doc](const AstNode &node) {
+ return Utils::Text::positionInText(doc, node.range().start().line() + 1,
+ node.range().start().character() + 1);
+ };
+ const auto posForNodeEnd = [doc](const AstNode &node) {
+ return Utils::Text::positionInText(doc, node.range().end().line() + 1,
+ node.range().end().character() + 1);
+ };
+ const int nodeStartPos = posForNodeStart(node);
+ const int nodeEndPos = posForNodeEnd(node);
+
+ // Match question mark and colon in ternary operators.
+ if (isExpression && node.kind() == "ConditionalOperator") {
+ if (children.size() != 3)
+ continue;
+
+ // The question mark is between sub-expressions 1 and 2, the colon is between
+ // sub-expressions 2 and 3.
+ const int searchStartPosQuestionMark = posForNodeEnd(children.first());
+ const int searchEndPosQuestionMark = posForNodeStart(children.at(1));
+ QStringView content = QStringView(docContent).mid(searchStartPosQuestionMark,
+ searchEndPosQuestionMark - searchStartPosQuestionMark);
+ const int questionMarkPos = onlyIndexOf(content, QStringView(QStringLiteral("?")));
+ if (questionMarkPos == -1)
+ continue;
+ const int searchStartPosColon = posForNodeEnd(children.at(1));
+ const int searchEndPosColon = posForNodeStart(children.at(2));
+ content = QStringView(docContent).mid(searchStartPosColon,
+ searchEndPosColon - searchStartPosColon);
+ const int colonPos = onlyIndexOf(content, QStringView(QStringLiteral(":")));
+ if (colonPos == -1)
+ continue;
+
+ const int absQuestionMarkPos = searchStartPosQuestionMark + questionMarkPos;
+ const int absColonPos = searchStartPosColon + colonPos;
+ if (absQuestionMarkPos > absColonPos)
+ continue;
+
+ TextEditor::HighlightingResult result;
+ result.useTextSyles = true;
+ result.textStyles.mainStyle = TextEditor::C_PUNCTUATION;
+ result.textStyles.mixinStyles.push_back(TextEditor::C_OPERATOR);
+ Utils::Text::convertPosition(doc, absQuestionMarkPos, &result.line, &result.column);
+ result.length = 1;
+ result.kind = CppTools::SemanticHighlighter::TernaryIf;
+ insert(result);
+ Utils::Text::convertPosition(doc, absColonPos, &result.line, &result.column);
+ result.kind = CppTools::SemanticHighlighter::TernaryElse;
+ insert(result);
+ continue;
+ }
+
+ // The following functions are for matching the "<" and ">" brackets of template
+ // declarations, specializations and instantiations.
+ const auto insertAngleBracketInfo = [&docContent, doc, &insert](
+ int searchStart1, int searchEnd1, int searchStart2, int searchEnd2) {
+ const int openingAngleBracketPos = onlyIndexOf(
+ QStringView(docContent).mid(searchStart1, searchEnd1 - searchStart1),
+ QStringView(QStringLiteral("<")));
+ if (openingAngleBracketPos == -1)
+ return;
+ const int absOpeningAngleBracketPos = searchStart1 + openingAngleBracketPos;
+ if (absOpeningAngleBracketPos > searchStart2)
+ searchStart2 = absOpeningAngleBracketPos + 1;
+ if (searchStart2 >= searchEnd2)
+ return;
+ const int closingAngleBracketPos = onlyIndexOf(
+ QStringView(docContent).mid(searchStart2, searchEnd2 - searchStart2),
+ QStringView(QStringLiteral(">")));
+ if (closingAngleBracketPos == -1)
+ return;
+
+ const int absClosingAngleBracketPos = searchStart2 + closingAngleBracketPos;
+ if (absOpeningAngleBracketPos > absClosingAngleBracketPos)
+ return;
+
+ TextEditor::HighlightingResult result;
+ result.useTextSyles = true;
+ result.textStyles.mainStyle = TextEditor::C_PUNCTUATION;
+ Utils::Text::convertPosition(doc, absOpeningAngleBracketPos,
+ &result.line, &result.column);
+ result.length = 1;
+ result.kind = CppTools::SemanticHighlighter::AngleBracketOpen;
+ insert(result);
+ Utils::Text::convertPosition(doc, absClosingAngleBracketPos,
+ &result.line, &result.column);
+ result.kind = CppTools::SemanticHighlighter::AngleBracketClose;
+ insert(result);
+ };
+
+ if (isDeclaration && (node.kind() == "FunctionTemplate"
+ || node.kind() == "ClassTemplate")) {
+ // The child nodes are the template parameters and and the function or class.
+ // The opening angle bracket is before the first child node, the closing angle
+ // bracket is before the function child node and after the last param node.
+ const QString classOrFunctionKind = QLatin1String(node.kind() == "FunctionTemplate"
+ ? "Function" : "CXXRecord");
+ const auto functionOrClassIt = std::find_if(children.begin(), children.end(),
+ [&classOrFunctionKind](const AstNode &n) {
+ return n.role() == "declaration" && n.kind() == classOrFunctionKind;
+ });
+ if (functionOrClassIt == children.end() || functionOrClassIt == children.begin())
+ continue;
+ const int firstTemplateParamStartPos = posForNodeStart(children.first());
+ const int lastTemplateParamEndPos = posForNodeEnd(*(functionOrClassIt - 1));
+ const int functionOrClassStartPos = posForNodeStart(*functionOrClassIt);
+ insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
+ lastTemplateParamEndPos, functionOrClassStartPos);
+ continue;
+ }
+
+ static const auto findTemplateParam = [](const AstNode &n) {
+ return n.role() == "declaration" && (n.kind() == "TemplateTypeParm"
+ || n.kind() == "NonTypeTemplateParm");
+ };
+
+ if (isDeclaration && node.kind() == "TypeAliasTemplate") {
+ // Children are one node of type TypeAlias and the template parameters.
+ // The opening angle bracket is before the first parameter and the closing
+ // angle bracket is after the last parameter.
+ // The TypeAlias node seems to appear first in the AST, even though lexically
+ // is comes after the parameters. We don't rely on the order here.
+ // Note that there is a second pair of angle brackets. That one is part of
+ // a TemplateSpecialization, which is handled further below.
+ const auto firstTemplateParam = std::find_if(children.begin(), children.end(),
+ findTemplateParam);
+ if (firstTemplateParam == children.end())
+ continue;
+ const auto lastTemplateParam = std::find_if(children.rbegin(), children.rend(),
+ findTemplateParam);
+ QTC_ASSERT(lastTemplateParam != children.rend(), continue);
+ const auto typeAlias = std::find_if(children.begin(), children.end(),
+ [](const AstNode &n) { return n.kind() == "TypeAlias"; });
+ if (typeAlias == children.end())
+ continue;
+
+ const int firstTemplateParamStartPos = posForNodeStart(*firstTemplateParam);
+ const int lastTemplateParamEndPos = posForNodeEnd(*lastTemplateParam);
+ const int searchEndPos = posForNodeStart(*typeAlias);
+ insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
+ lastTemplateParamEndPos, searchEndPos);
+ continue;
+ }
+
+ if (isDeclaration && node.kind() == "ClassTemplateSpecialization") {
+ // There is one child of kind TemplateSpecialization. The first pair
+ // of angle brackets comes before that.
+ if (children.size() == 1) {
+ const int childNodePos = posForNodeStart(children.first());
+ insertAngleBracketInfo(nodeStartPos, childNodePos, nodeStartPos, childNodePos);
+ }
+ continue;
+ }
+
+ if (isDeclaration && node.kind() == "TemplateTemplateParm") {
+ // The child nodes are template arguments and template parameters.
+ // Arguments seem to appear before parameters in the AST, even though they
+ // come after them in the source code. We don't rely on the order here.
+ const auto firstTemplateParam = std::find_if(children.begin(), children.end(),
+ findTemplateParam);
+ if (firstTemplateParam == children.end())
+ continue;
+ const auto lastTemplateParam = std::find_if(children.rbegin(), children.rend(),
+ findTemplateParam);
+ QTC_ASSERT(lastTemplateParam != children.rend(), continue);
+ const auto templateArg = std::find_if(children.begin(), children.end(),
+ [](const AstNode &n) { return n.role() == "template argument"; });
+
+ const int firstTemplateParamStartPos = posForNodeStart(*firstTemplateParam);
+ const int lastTemplateParamEndPos = posForNodeEnd(*lastTemplateParam);
+ const int searchEndPos = templateArg == children.end()
+ ? nodeEndPos : posForNodeStart(*templateArg);
+ insertAngleBracketInfo(nodeStartPos, firstTemplateParamStartPos,
+ lastTemplateParamEndPos, searchEndPos);
+ continue;
+ }
+
+ // {static,dynamic,reinterpret}_cast<>().
+ if (isExpression && node.kind().startsWith("CXX") && node.kind().endsWith("Cast")) {
+ // First child is type, second child is expression.
+ // The opening angle bracket is before the first child, the closing angle bracket
+ // is between the two children.
+ if (children.size() == 2) {
+ insertAngleBracketInfo(nodeStartPos, posForNodeStart(children.first()),
+ posForNodeEnd(children.first()),
+ posForNodeStart(children.last()));
+ }
+ continue;
+ }
+
+ if (node.kind() == "TemplateSpecialization") {
+ // First comes the template type, then the template arguments.
+ // The opening angle bracket is before the first template argument,
+ // the closing angle bracket is after the last template argument.
+ // The first child node has no range, so we start searching at the parent node.
+ if (children.size() >= 2) {
+ int searchStart2 = posForNodeEnd(children.last());
+ int searchEnd2 = nodeEndPos;
+
+ // There is a weird off-by-one error on the clang side: If there is a
+ // nested template instantiation *and* there is no space between
+ // the closing angle brackets, then the inner TemplateSpecialization node's range
+ // will extend one character too far, covering the outer's closing angle bracket.
+ // This is what we are correcting for here.
+ // TODO: Can we fix this in clang?
+ if (searchStart2 == searchEnd2)
+ --searchStart2;
+ insertAngleBracketInfo(nodeStartPos, posForNodeStart(children.at(1)),
+ searchStart2, searchEnd2);
+ }
+ continue;
+ }
+
+ if (!isExpression && !isDeclaration)
+ continue;
+
+ // Operators, overloaded ones in particular.
+ static const QString operatorPrefix = "operator";
+ QString detail = node.detail().value_or(QString());
+ const bool isCallToNew = node.kind() == "CXXNew";
+ const bool isCallToDelete = node.kind() == "CXXDelete";
+ if (!isCallToNew && !isCallToDelete
+ && (!detail.startsWith(operatorPrefix) || detail == operatorPrefix)) {
+ continue;
+ }
+
+ if (!isCallToNew && !isCallToDelete)
+ detail.remove(0, operatorPrefix.length());
+
+ TextEditor::HighlightingResult result;
+ result.useTextSyles = true;
+ const bool isConversionOp = node.kind() == "CXXConversion";
+ const bool isOverloaded = !isConversionOp
+ && (isDeclaration || ((!isCallToNew && !isCallToDelete)
+ || node.arcanaContains("CXXMethod")));
+ result.textStyles.mainStyle = isConversionOp
+ ? TextEditor::C_PRIMITIVE_TYPE
+ : isCallToNew || isCallToDelete || detail.at(0).isSpace()
+ ? TextEditor::C_KEYWORD : TextEditor::C_PUNCTUATION;
+ result.textStyles.mixinStyles.push_back(TextEditor::C_OPERATOR);
+ if (isOverloaded)
+ result.textStyles.mixinStyles.push_back(TextEditor::C_OVERLOADED_OPERATOR);
+ if (isDeclaration)
+ result.textStyles.mixinStyles.push_back(TextEditor::C_DECLARATION);
+
+ const QStringView nodeText = QStringView(docContent)
+ .mid(nodeStartPos, nodeEndPos - nodeStartPos);
+
+ if (isCallToNew || isCallToDelete) {
+ result.line = node.range().start().line() + 1;
+ result.column = node.range().start().character() + 1;
+ result.length = isCallToNew ? 3 : 6;
+ insert(result);
+ if (node.arcanaContains("array")) {
+ const int openingBracketOffset = nodeText.indexOf('[');
+ if (openingBracketOffset == -1)
+ continue;
+ const int closingBracketOffset = nodeText.lastIndexOf(']');
+ if (closingBracketOffset == -1 || closingBracketOffset < openingBracketOffset)
+ continue;
+
+ result.textStyles.mainStyle = TextEditor::C_PUNCTUATION;
+ result.length = 1;
+ Utils::Text::convertPosition(doc,
+ nodeStartPos + openingBracketOffset,
+ &result.line, &result.column);
+ insert(result);
+ Utils::Text::convertPosition(doc,
+ nodeStartPos + closingBracketOffset,
+ &result.line, &result.column);
+ insert(result);
+ }
+ continue;
+ }
+
+ if (isExpression && (detail == QLatin1String("()") || detail == QLatin1String("[]"))) {
+ result.line = node.range().start().line() + 1;
+ result.column = node.range().start().character() + 1;
+ result.length = 1;
+ insert(result);
+ result.line = node.range().end().line() + 1;
+ result.column = node.range().end().character();
+ insert(result);
+ continue;
+ }
+
+ const int opStringLen = detail.at(0).isSpace() ? detail.length() - 1 : detail.length();
+
+ // The simple case: Call to operator+, +=, * etc.
+ if (nodeEndPos - nodeStartPos == opStringLen) {
+ setFromRange(result, node.range());
+ insert(result);
+ continue;
+ }
+
+ const int prefixOffset = nodeText.indexOf(operatorPrefix);
+ if (prefixOffset == -1)
+ continue;
+
+ const bool isArray = detail == "[]";
+ const bool isCall = detail == "()";
+ const bool isArrayNew = detail == " new[]";
+ const bool isArrayDelete = detail == " delete[]";
+ const QStringView searchTerm = isArray || isCall
+ ? QStringView(detail).chopped(1) : isArrayNew || isArrayDelete
+ ? QStringView(detail).chopped(2) : detail;
+ const int opStringOffset = nodeText.indexOf(searchTerm, prefixOffset
+ + operatorPrefix.length());
+ if (opStringOffset == -1 || nodeText.indexOf(operatorPrefix, opStringOffset) != -1)
+ continue;
+
+ const int opStringOffsetInDoc = nodeStartPos + opStringOffset
+ + detail.length() - opStringLen;
+ Utils::Text::convertPosition(doc, opStringOffsetInDoc, &result.line, &result.column);
+ result.length = opStringLen;
+ if (isArray || isCall)
+ result.length = 1;
+ else if (isArrayNew || isArrayDelete)
+ result.length -= 2;
+ if (!isArray && !isCall)
+ insert(result);
+ if (!isArray && !isCall && !isArrayNew && !isArrayDelete)
+ continue;
+
+ result.textStyles.mainStyle = TextEditor::C_PUNCTUATION;
+ result.length = 1;
+ const int openingParenOffset = nodeText.indexOf(
+ isCall ? '(' : '[', prefixOffset + operatorPrefix.length());
+ if (openingParenOffset == -1)
+ continue;
+ const int closingParenOffset = nodeText.indexOf(isCall ? ')' : ']', openingParenOffset + 1);
+ if (closingParenOffset == -1 || closingParenOffset < openingParenOffset)
+ continue;
+ Utils::Text::convertPosition(doc, nodeStartPos + openingParenOffset,
+ &result.line, &result.column);
+ insert(result);
+ Utils::Text::convertPosition(doc, nodeStartPos + closingParenOffset,
+ &result.line, &result.column);
+ insert(result);
+ }
+}
+
+// clangd reports also the #ifs, #elses and #endifs around the disabled code as disabled,
+// and not even in a consistent manner. We don't want this, so we have to clean up here.
+// TODO: Fix in clangd?
+static void cleanupDisabledCode(TextEditor::HighlightingResults &results, QTextDocument *doc,
+ const QString &docContent)
+{
+ bool inDisabled = false;
+ for (auto it = results.begin(); it != results.end();) {
+ const bool wasInDisabled = inDisabled;
+ if (it->textStyles.mainStyle != TextEditor::C_DISABLED_CODE) {
+ inDisabled = false;
+ ++it;
+ continue;
+ }
+
+ inDisabled = true;
+ const int pos = Utils::Text::positionInText(doc, it->line, it->column);
+ const QStringView content(QStringView(docContent).mid(pos, it->length).trimmed());
+ if (!content.startsWith(QLatin1String("#if"))
+ && !content.startsWith(QLatin1String("#elif"))
+ && !content.startsWith(QLatin1String("#else"))
+ && !content.startsWith(QLatin1String("#endif"))) {
+ ++it;
+ continue;
+ }
+
+ if (!wasInDisabled) {
+ // The #if or #else that starts disabled code should not be disabled.
+ it = results.erase(it);
+ continue;
+ }
+
+ if (wasInDisabled && (it == results.end()
+ || (it + 1)->textStyles.mainStyle != TextEditor::C_DISABLED_CODE)) {
+ // The #else or #endif that ends disabled code should not be disabled.
+ it = results.erase(it);
+ continue;
+ }
+ ++it;
+ }
+}
+
+static void semanticHighlighter(QFutureInterface &future,
+ const QList &tokens,
+ const QString &docContents, const AstNode &ast)
+{
+ if (future.isCanceled()) {
+ future.reportFinished();
+ return;
+ }
+
+ QTextDocument doc(docContents);
+ const auto isOutputParameter = [&ast](const ExpandedSemanticToken &token) {
+ if (token.type != "variable" && token.type != "property" && token.type != "parameter")
+ return false;
+ const Position pos(token.line - 1, token.column - 1);
+ const QList path = getAstPath(ast, Range(pos, pos));
+ if (path.size() < 2)
+ return false;
+ if (path.last().hasConstType())
+ return false;
+ for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
+ if (it->kind() == "Call" || it->kind() == "CXXConstruct"
+ || it->kind() == "MemberInitializer") {
+ return true;
+ }
+ if (it->kind().endsWith("Cast") && it->hasConstType())
+ return false;
+ }
+ return false;
+ };
+
+ const auto toResult = [&ast, &isOutputParameter](const ExpandedSemanticToken &token) {
+ TextEditor::TextStyles styles;
+ if (token.type == "variable") {
+ if (token.modifiers.contains("functionScope")) {
+ styles.mainStyle = TextEditor::C_LOCAL;
+ } else if (token.modifiers.contains("classScope")) {
+ styles.mainStyle = TextEditor::C_FIELD;
+ } else if (token.modifiers.contains("fileScope")
+ || token.modifiers.contains("globalScope")) {
+ styles.mainStyle = TextEditor::C_GLOBAL;
+ }
+ } else if (token.type == "function" || token.type == "method") {
+ styles.mainStyle = TextEditor::C_FUNCTION;
+ if (ast.isValid()) {
+ const Position pos(token.line - 1, token.column - 1);
+ const QList path = getAstPath(ast, Range(pos, pos));
+ if (path.length() > 1) {
+ const AstNode declNode = path.at(path.length() - 2);
+ if (declNode.kind() == "Function" || declNode.kind() == "CXXMethod") {
+ if (declNode.arcanaContains("' virtual"))
+ styles.mainStyle = TextEditor::C_VIRTUAL_METHOD;
+ if (declNode.hasChildWithRole("statement"))
+ styles.mixinStyles.push_back(TextEditor::C_FUNCTION_DEFINITION);
+ }
+ }
+ }
+ } else if (token.type == "class") {
+ styles.mainStyle = TextEditor::C_TYPE;
+
+ // clang hardly ever differentiates between constructors and the associated class,
+ // whereas we highlight constructors as functions.
+ if (ast.isValid()) {
+ const Position pos(token.line - 1, token.column - 1);
+ const QList path = getAstPath(ast, Range(pos, pos));
+ if (!path.isEmpty()) {
+ if (path.last().kind() == "CXXConstructor") {
+ if (!path.last().arcanaContains("implicit"))
+ styles.mainStyle = TextEditor::C_FUNCTION;
+ } else if (path.last().kind() == "Record" && path.length() > 1) {
+ const AstNode node = path.at(path.length() - 2);
+ if (node.kind() == "CXXDestructor" && !node.arcanaContains("implicit")) {
+ styles.mainStyle = TextEditor::C_FUNCTION;
+ // TODO: "declaration" modifier is missing for destructors; fix in clangd
+ // (the scope is also wrong)
+ if (node.role() == "declaration")
+ styles.mixinStyles.push_back(TextEditor::C_DECLARATION);
+ }
+ }
+ }
+ }
+ } else if (token.type == "comment") { // "comment" means code disabled via the preprocessor
+ styles.mainStyle = TextEditor::C_DISABLED_CODE;
+ } else if (token.type == "namespace") {
+ styles.mainStyle = TextEditor::C_TYPE;
+ } else if (token.type == "property") {
+ styles.mainStyle = TextEditor::C_FIELD;
+ } else if (token.type == "enum") {
+ styles.mainStyle = TextEditor::C_TYPE;
+ styles.mixinStyles.push_back(TextEditor::C_ENUMERATION);
+ } else if (token.type == "enumMember") {
+ styles.mainStyle = TextEditor::C_ENUMERATION;
+ } else if (token.type == "parameter") {
+ styles.mainStyle = TextEditor::C_PARAMETER;
+ } else if (token.type == "macro") {
+ styles.mainStyle = TextEditor::C_PREPROCESSOR;
+ } else if (token.type == "type") {
+ styles.mainStyle = TextEditor::C_TYPE;
+ } else if (token.type == "typeParameter") {
+ styles.mainStyle = TextEditor::C_TYPE;
+ }
+ if (token.modifiers.contains("declaration"))
+ styles.mixinStyles.push_back(TextEditor::C_DECLARATION);
+ if (isOutputParameter(token))
+ styles.mixinStyles.push_back(TextEditor::C_OUTPUT_ARGUMENT);
+ qCDebug(clangdLog) << "adding highlighting result"
+ << token.line << token.column << token.length << int(styles.mainStyle);
+ return TextEditor::HighlightingResult(token.line, token.column, token.length, styles);
+ };
+
+ TextEditor::HighlightingResults results = Utils::transform(tokens, toResult);
+ cleanupDisabledCode(results, &doc, docContents);
+ collectExtraResults(future, results, ast, &doc, docContents);
+ if (!future.isCanceled()) {
+ qCDebug(clangdLog) << "reporting" << results.size() << "highlighting results";
+ future.reportResults(QVector(results.cbegin(),
+ results.cend()));
+ }
+ future.reportFinished();
+}
+
+// Unfortunately, clangd ignores almost everything except symbols when sending
+// semantic token info, so we need to consult the AST for additional information.
+// In particular, we inspect the following constructs:
+// - Raw string literals, because our built-in lexer does not parse them properly.
+// While we're at it, we also handle other types of literals.
+// - Ternary expressions (for the matching of "?" and ":").
+// - Template declarations and instantiations (for the matching of "<" and ">").
+// - Function declarations, to find out whether a declaration is also a definition.
+// - Function arguments, to find out whether they correspond to output parameters.
+// - We consider most other tokens to be simple enough to be handled by the built-in code model.
+// Sometimes we have no choice, as for #include directives, which appear neither
+// in the semantic tokens nor in the AST.
+void ClangdClient::Private::handleSemanticTokens(TextEditor::TextDocument *doc,
+ const QList &tokens)
+{
+ qCDebug(clangdLog()) << "handling LSP tokens" << tokens.size();
+ for (const ExpandedSemanticToken &t : tokens)
+ qCDebug(clangdLog) << '\t' << t.line << t.column << t.length << t.type << t.modifiers;
+
+ // TODO: Cache ASTs
+ AstParams params(TextDocumentIdentifier(DocumentUri::fromFilePath(doc->filePath())));
+ AstRequest astReq(params);
+ astReq.setResponseCallback([this, tokens, doc](const AstRequest::Response &response) {
+ if (!q->documentOpen(doc))
+ return;
+ const Utils::optional ast = response.result();
+ if (ast && clangdLog().isDebugEnabled())
+ ast->print();
+
+ const auto runner = [tokens, text = doc->document()->toPlainText(),
+ theAst = ast ? *ast : AstNode()] {
+ return Utils::runAsync(semanticHighlighter, tokens, text, theAst);
+ };
+
+ if (isTesting) {
+ const auto watcher = new QFutureWatcher(q);
+ connect(watcher, &QFutureWatcher::finished,
+ q, [this, watcher] {
+ emit q->highlightingResultsReady(watcher->future().results());
+ watcher->deleteLater();
+ });
+ watcher->setFuture(runner());
+ return;
+ }
+
+ auto it = highlighters.find(doc);
+ if (it == highlighters.end()) {
+ it = highlighters.emplace(doc, doc).first;
+ } else {
+ it->second.updateFormatMapFromFontSettings();
+ }
+ it->second.setHighlightingRunner(runner);
+ it->second.run();
+ });
+ q->sendContent(astReq);
+}
+
void ClangdClient::VirtualFunctionAssistProcessor::cancel()
{
resetData();
@@ -1501,6 +2484,16 @@ TextEditor::IAssistProcessor *ClangdClient::VirtualFunctionAssistProvider::creat
= new VirtualFunctionAssistProcessor(m_data);
}
+Utils::optional > ClangdDiagnostic::codeActions() const
+{
+ return optionalArray("codeActions");
+}
+
+QString ClangdDiagnostic::category() const
+{
+ return typedValue("category");
+}
+
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h
index b07de7e95ce..af1870ad550 100644
--- a/src/plugins/clangcodemodel/clangdclient.h
+++ b/src/plugins/clangcodemodel/clangdclient.h
@@ -25,6 +25,7 @@
#pragma once
+#include
#include
#include
#include
@@ -49,6 +50,7 @@ public:
bool isFullyIndexed() const;
QVersionNumber versionNumber() const;
+ CppTools::ClangdSettings::Data settingsData() const;
void openExtraFile(const Utils::FilePath &filePath, const QString &content = {});
void closeExtraFile(const Utils::FilePath &filePath);
@@ -70,14 +72,23 @@ public:
void findLocalUsages(TextEditor::TextDocument *document, const QTextCursor &cursor,
CppTools::RefactoringEngineInterface::RenameCallback &&callback);
+ void gatherHelpItemForTooltip(
+ const LanguageServerProtocol::HoverRequest::Response &hoverResponse,
+ const LanguageServerProtocol::DocumentUri &uri);
+
void enableTesting();
signals:
void indexingFinished();
void foundReferences(const QList &items);
void findUsagesDone();
+ void helpItemGathered(const Core::HelpItem &helpItem);
+ void highlightingResultsReady(const TextEditor::HighlightingResults &results);
private:
+ void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams ¶ms) override;
+ void handleDocumentClosed(TextEditor::TextDocument *doc) override;
+
class Private;
class FollowSymbolData;
class VirtualFunctionAssistProcessor;
@@ -85,5 +96,13 @@ private:
Private * const d;
};
+class ClangdDiagnostic : public LanguageServerProtocol::Diagnostic
+{
+public:
+ using Diagnostic::Diagnostic;
+ Utils::optional> codeActions() const;
+ QString category() const;
+};
+
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
index 666282d8fda..ee7b787118e 100644
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
+++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp
@@ -298,7 +298,8 @@ void ClangDiagnosticManager::generateFixItAvailableMarkers()
addFixItAvailableMarker(m_errorDiagnostics, lineNumbersWithFixItMarker);
}
-static void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic, bool isChild = false)
+void ClangDiagnosticManager::addTask(const ClangBackEnd::DiagnosticContainer &diagnostic,
+ bool isChild)
{
using namespace ProjectExplorer;
using ::Utils::FilePath;
diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h
index 9d5b7a6571c..5c2ed3c8db4 100644
--- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h
+++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.h
@@ -66,6 +66,8 @@ public:
static void clearTaskHubIssues();
void generateTaskHubIssues();
+ static void addTask(const ClangBackEnd::DiagnosticContainer &diagnostic, bool isChild = false);
+
private:
void cleanMarks();
QString filePath() const;
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
index 499ae623f6b..326dfee0ef9 100644
--- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
+++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.cpp
@@ -104,7 +104,7 @@ public:
}
QWidget *createWidget(const QVector &diagnostics,
- const ClangDiagnosticManager *diagMgr)
+ const std::function &canApplyFixIt)
{
const QString text = htmlText(diagnostics);
@@ -133,7 +133,7 @@ public:
const TargetIdToDiagnosticTable table = m_targetIdsToDiagnostics;
const bool hideToolTipAfterLinkActivation = m_displayHints.hideTooltipAfterLinkActivation;
QObject::connect(label, &QLabel::linkActivated, [table, hideToolTipAfterLinkActivation,
- diagMgr](const QString &action) {
+ canApplyFixIt](const QString &action) {
const ClangBackEnd::DiagnosticContainer diagnostic = table.value(action);
if (diagnostic == ClangBackEnd::DiagnosticContainer())
@@ -141,10 +141,8 @@ public:
else if (action.startsWith(LINK_ACTION_GOTO_LOCATION)) {
openEditorAt(diagnostic);
} else if (action.startsWith(LINK_ACTION_APPLY_FIX)) {
- if (diagMgr && !diagMgr->diagnosticsInvalidated()
- && diagMgr->diagnosticsWithFixIts().contains(diagnostic)) {
+ if (canApplyFixIt && canApplyFixIt())
applyFixit(diagnostic);
- }
} else {
QTC_CHECK(!"Link target cannot be handled.");
}
@@ -218,40 +216,6 @@ private:
return text;
}
- static QString documentationUrlForOption(const Utf8String &optionAsUtf8String)
- {
- if (optionAsUtf8String.isEmpty())
- return QString();
-
- QString option = optionAsUtf8String.toString();
-
- // Clazy
- if (DiagnosticTextInfo::isClazyOption(option)) {
- option = optionAsUtf8String.mid(8); // Remove "-Wclazy-" prefix.
- return QString::fromUtf8(CppTools::Constants::CLAZY_DOCUMENTATION_URL_TEMPLATE)
- .arg(option);
- }
-
- // Clang itself
- if (option.startsWith("-W"))
- return QString();
-
- // Clang-Tidy
- return QString::fromUtf8(CppTools::Constants::TIDY_DOCUMENTATION_URL_TEMPLATE).arg(option);
- }
-
- static QString maybeClickableOption(const Utf8String &option)
- {
- if (option.isEmpty())
- return option;
-
- const QString link = documentationUrlForOption(option);
- if (link.isEmpty())
- return option;
-
- return wrapInLink(option.toString(), link);
- }
-
static QString diagnosticCategoryAndEnableOptionRow(
const ClangBackEnd::DiagnosticContainer &diagnostic)
{
@@ -260,7 +224,7 @@ private:
" %1 | "
" %2 | "
" ")
- .arg(diagnostic.category, maybeClickableOption(diagnostic.enableOption));
+ .arg(diagnostic.category, diagnostic.enableOption);
return text;
}
@@ -402,14 +366,14 @@ private:
};
WidgetFromDiagnostics::DisplayHints toHints(const ClangDiagnosticWidget::Destination &destination,
- const ClangDiagnosticManager *diagMgr = nullptr)
+ const std::function &canApplyFixIt)
{
WidgetFromDiagnostics::DisplayHints hints;
if (destination == ClangDiagnosticWidget::ToolTip) {
hints.showCategoryAndEnableOption = true;
hints.showFileNameInMainDiagnostic = false;
- hints.enableClickableFixits = diagMgr && !diagMgr->diagnosticsInvalidated();
+ hints.enableClickableFixits = canApplyFixIt && canApplyFixIt();
hints.limitWidth = true;
hints.hideTooltipAfterLinkActivation = true;
hints.allowTextSelection = false;
@@ -432,7 +396,7 @@ QString ClangDiagnosticWidget::createText(
const QVector &diagnostics,
const ClangDiagnosticWidget::Destination &destination)
{
- const QString htmlText = WidgetFromDiagnostics(toHints(destination)).htmlText(diagnostics);
+ const QString htmlText = WidgetFromDiagnostics(toHints(destination, {})).htmlText(diagnostics);
QTextDocument document;
document.setHtml(htmlText);
@@ -447,9 +411,10 @@ QString ClangDiagnosticWidget::createText(
}
QWidget *ClangDiagnosticWidget::createWidget(const QVector &diagnostics,
- const Destination &destination, const ClangDiagnosticManager *diagMgr)
+ const Destination &destination, const std::function &canApplyFixIt)
{
- return WidgetFromDiagnostics(toHints(destination, diagMgr)).createWidget(diagnostics, diagMgr);
+ return WidgetFromDiagnostics(toHints(destination, canApplyFixIt))
+ .createWidget(diagnostics, canApplyFixIt);
}
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
index 48fa0726952..afe35812ae0 100644
--- a/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
+++ b/src/plugins/clangcodemodel/clangdiagnostictooltipwidget.h
@@ -27,6 +27,8 @@
#include
+#include
+
QT_BEGIN_NAMESPACE
class QLayout;
class QWidget;
@@ -43,9 +45,10 @@ public:
static QString createText(const QVector &diagnostics,
const Destination &destination);
+
static QWidget *createWidget(const QVector &diagnostics,
const Destination &destination,
- const ClangDiagnosticManager *diagMgr = nullptr);
+ const std::function &canApplyFixIt);
};
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangdquickfixfactory.cpp b/src/plugins/clangcodemodel/clangdquickfixfactory.cpp
new file mode 100644
index 00000000000..5146df8bc5b
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdquickfixfactory.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#include "clangdquickfixfactory.h"
+
+#include "clangdclient.h"
+#include "clangmodelmanagersupport.h"
+
+#include
+
+using namespace LanguageServerProtocol;
+
+namespace ClangCodeModel {
+namespace Internal {
+
+ClangdQuickFixFactory::ClangdQuickFixFactory() = default;
+
+void ClangdQuickFixFactory::match(const CppEditor::Internal::CppQuickFixInterface &interface,
+ QuickFixOperations &result)
+{
+ const auto client = ClangModelManagerSupport::instance()->clientForFile(interface.filePath());
+ if (!client)
+ return;
+
+ const auto uri = DocumentUri::fromFilePath(interface.filePath());
+ QTextCursor cursor(interface.textDocument());
+ cursor.setPosition(interface.position());
+ cursor.select(QTextCursor::LineUnderCursor);
+ const QList &diagnostics = client->diagnosticsAt(uri, cursor);
+ for (const Diagnostic &diagnostic : diagnostics) {
+ ClangdDiagnostic clangdDiagnostic(diagnostic);
+ if (const auto actions = clangdDiagnostic.codeActions()) {
+ for (const CodeAction &action : *actions)
+ result << new LanguageClient::CodeActionQuickFixOperation(action, client);
+ }
+ }
+}
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangdquickfixfactory.h b/src/plugins/clangcodemodel/clangdquickfixfactory.h
new file mode 100644
index 00000000000..022b6033407
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangdquickfixfactory.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** 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.
+**
+****************************************************************************/
+
+#pragma once
+
+#include
+
+namespace ClangCodeModel {
+namespace Internal {
+
+class ClangdQuickFixFactory : public CppEditor::CppQuickFixFactory
+{
+public:
+ ClangdQuickFixFactory();
+
+ void match(const CppEditor::Internal::CppQuickFixInterface &interface,
+ QuickFixOperations &result) override;
+};
+
+} // namespace Internal
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index 58eae03422d..8e4a83c7be7 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -137,6 +137,8 @@ void ClangEditorDocumentProcessor::semanticRehighlight()
};
if (!Utils::contains(Core::EditorManager::visibleEditors(), matchesEditor))
return;
+ if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
+ return;
m_semanticHighlighter.updateFormatMapFromFontSettings();
if (m_projectPart)
@@ -188,6 +190,9 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
uint documentRevision)
{
+ if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
+ return;
+
if (documentRevision == revision()) {
if (m_invalidationState == InvalidationState::Scheduled)
m_invalidationState = InvalidationState::Canceled;
@@ -251,6 +256,8 @@ void ClangEditorDocumentProcessor::updateHighlighting(
const QVector &skippedPreprocessorRanges,
uint documentRevision)
{
+ if (ClangModelManagerSupport::instance()->clientForFile(m_document.filePath()))
+ return;
if (documentRevision == revision()) {
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
@@ -489,7 +496,7 @@ ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
vbox->setSpacing(2);
vbox->addWidget(ClangDiagnosticWidget::createWidget({firstHeaderErrorDiagnostic},
- ClangDiagnosticWidget::InfoBar));
+ ClangDiagnosticWidget::InfoBar, {}));
auto widget = new QWidget;
widget->setLayout(vbox);
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp
index 3d8d6648d98..250f2886b3d 100644
--- a/src/plugins/clangcodemodel/clanghoverhandler.cpp
+++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp
@@ -26,6 +26,7 @@
#include "clanghoverhandler.h"
#include "clangeditordocumentprocessor.h"
+#include "clangmodelmanagersupport.h"
#include
#include
@@ -97,6 +98,12 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
int pos,
BaseHoverHandler::ReportPriority report)
{
+ if (ClangModelManagerSupport::instance()
+ ->clientForFile(editorWidget->textDocument()->filePath())) {
+ report(Priority_None);
+ return;
+ }
+
// Reset
m_futureWatcher.reset();
m_cursorPosition = -1;
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
index d2fb17d64de..90be3893dfc 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp
@@ -26,16 +26,17 @@
#include "clangmodelmanagersupport.h"
#include "clangconstants.h"
+#include "clangcurrentdocumentfilter.h"
#include "clangdclient.h"
+#include "clangdquickfixfactory.h"
#include "clangeditordocumentprocessor.h"
-#include "clangutils.h"
#include "clangfollowsymbol.h"
+#include "clanggloballocatorfilters.h"
#include "clanghoverhandler.h"
+#include "clangoverviewmodel.h"
#include "clangprojectsettings.h"
#include "clangrefactoringengine.h"
-#include "clangcurrentdocumentfilter.h"
-#include "clanggloballocatorfilters.h"
-#include "clangoverviewmodel.h"
+#include "clangutils.h"
#include
#include
@@ -119,8 +120,10 @@ ClangModelManagerSupport::ClangModelManagerSupport()
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
this, &ClangModelManagerSupport::onAboutToRemoveProject);
- CppTools::CppCodeModelSettings::setDefaultClangdPath(Utils::FilePath::fromString(
+ CppTools::ClangdSettings::setDefaultClangdPath(Utils::FilePath::fromString(
Core::ICore::clangdExecutable(CLANG_BINDIR)));
+ connect(&CppTools::ClangdSettings::instance(), &CppTools::ClangdSettings::changed,
+ this, &ClangModelManagerSupport::onClangdSettingsChanged);
CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings();
connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated,
this, &ClangModelManagerSupport::onDiagnosticConfigsInvalidated);
@@ -128,6 +131,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
// TODO: Enable this once we do document-level stuff with clangd (highlighting etc)
// createClient(nullptr, {});
m_generatorSynchronizer.setCancelOnWait(true);
+ new ClangdQuickFixFactory(); // memory managed by CppEditor::g_cppQuickFixFactories
}
ClangModelManagerSupport::~ClangModelManagerSupport()
@@ -167,6 +171,11 @@ std::unique_ptr ClangModelManagerSupport::creat
return std::make_unique();
}
+bool ClangModelManagerSupport::supportsOutline(const TextEditor::TextDocument *document) const
+{
+ return !clientForFile(document->filePath());
+}
+
CppTools::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
@@ -245,7 +254,7 @@ void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget
void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *project,
const CppTools::ProjectInfo &projectInfo)
{
- if (!CppTools::codeModelSettings()->useClangd())
+ if (!CppTools::ClangdProjectSettings(project).settings().useClangd)
return;
const auto getJsonDbDir = [project] {
if (const ProjectExplorer::Target * const target = project->activeTarget()) {
@@ -264,10 +273,10 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr
connect(generatorWatcher, &QFutureWatcher::finished,
[this, project, projectInfo, getJsonDbDir, jsonDbDir, generatorWatcher] {
generatorWatcher->deleteLater();
- if (!CppTools::codeModelSettings()->useClangd())
- return;
if (!ProjectExplorer::SessionManager::hasProject(project))
return;
+ if (!CppTools::ClangdProjectSettings(project).settings().useClangd)
+ return;
if (cppModelManager()->projectInfo(project) != projectInfo)
return;
if (getJsonDbDir() != jsonDbDir)
@@ -284,10 +293,10 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr
ClangdClient * const client = createClient(project, jsonDbDir);
connect(client, &Client::initialized, this, [client, project, projectInfo, jsonDbDir] {
using namespace ProjectExplorer;
- if (!CppTools::codeModelSettings()->useClangd())
- return;
if (!SessionManager::hasProject(project))
return;
+ if (!CppTools::ClangdProjectSettings(project).settings().useClangd)
+ return;
if (cppModelManager()->projectInfo(project) != projectInfo)
return;
@@ -340,7 +349,7 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr
}
ClangdClient *ClangModelManagerSupport::clientForProject(
- const ProjectExplorer::Project *project)
+ const ProjectExplorer::Project *project) const
{
const QList clients = Utils::filtered(
LanguageClientManager::clientsForProject(project),
@@ -353,7 +362,7 @@ ClangdClient *ClangModelManagerSupport::clientForProject(
return clients.empty() ? nullptr : qobject_cast(clients.first());
}
-ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file)
+ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file) const
{
return clientForProject(ProjectExplorer::SessionManager::projectForFile(file));
}
@@ -585,6 +594,27 @@ void ClangModelManagerSupport::onProjectPartsRemoved(const QStringList &projectP
reinitializeBackendDocuments(projectPartIds);
}
+void ClangModelManagerSupport::onClangdSettingsChanged()
+{
+ // TODO: Handle also project-less client
+ for (ProjectExplorer::Project * const project : ProjectExplorer::SessionManager::projects()) {
+ const CppTools::ClangdSettings settings(
+ CppTools::ClangdProjectSettings(project).settings());
+ ClangdClient * const client = clientForProject(project);
+ if (!client) {
+ if (settings.useClangd())
+ updateLanguageClient(project, cppModelManager()->projectInfo(project));
+ continue;
+ }
+ if (!settings.useClangd()) {
+ LanguageClientManager::shutdownClient(client);
+ continue;
+ }
+ if (client->settingsData() != settings.data())
+ updateLanguageClient(project, cppModelManager()->projectInfo(project));
+ }
+}
+
static ClangEditorDocumentProcessors clangProcessorsWithDiagnosticConfig(
const QVector<::Utils::Id> &configIds)
{
diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
index 1c7724b5d50..97a0bfaf275 100644
--- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h
+++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h
@@ -72,6 +72,7 @@ public:
CppTools::FollowSymbolInterface &followSymbolInterface() override;
CppTools::RefactoringEngineInterface &refactoringEngineInterface() override;
std::unique_ptr createOverviewModel() override;
+ bool supportsOutline(const TextEditor::TextDocument *document) const override;
BackendCommunicator &communicator();
QString dummyUiHeaderOnDiskDirPath() const;
@@ -79,8 +80,8 @@ public:
ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
- ClangdClient *clientForProject(const ProjectExplorer::Project *project);
- ClangdClient *clientForFile(const Utils::FilePath &file);
+ ClangdClient *clientForProject(const ProjectExplorer::Project *project) const;
+ ClangdClient *clientForFile(const Utils::FilePath &file) const;
static ClangModelManagerSupport *instance();
@@ -114,6 +115,7 @@ private:
void onProjectPartsUpdated(ProjectExplorer::Project *project);
void onProjectPartsRemoved(const QStringList &projectPartIds);
+ void onClangdSettingsChanged();
void onDiagnosticConfigsInvalidated(const QVector<::Utils::Id> &configIds);
diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp
index 188e0de08d5..77ed1f2fa36 100644
--- a/src/plugins/clangcodemodel/clangtextmark.cpp
+++ b/src/plugins/clangcodemodel/clangtextmark.cpp
@@ -26,6 +26,7 @@
#include "clangtextmark.h"
#include "clangconstants.h"
+#include "clangdclient.h"
#include "clangdiagnostictooltipwidget.h"
#include "clangeditordocumentprocessor.h"
#include "clangmodelmanagersupport.h"
@@ -51,6 +52,8 @@
using namespace CppTools;
using namespace ClangCodeModel::Internal;
+using namespace LanguageClient;
+using namespace LanguageServerProtocol;
using namespace Utils;
namespace ClangCodeModel {
@@ -272,10 +275,13 @@ void ClangTextMark::updateIcon(bool valid)
bool ClangTextMark::addToolTipContent(QLayout *target) const
{
-
+ const auto canApplyFixIt = [diag = m_diagnostic, diagMgr = m_diagMgr, c = color()] {
+ return c != Utils::Theme::Color::IconsDisabledColor
+ && !diagMgr->diagnosticsInvalidated()
+ && diagMgr->diagnosticsWithFixIts().contains(diag);
+ };
QWidget *widget = ClangDiagnosticWidget::createWidget(
- {m_diagnostic}, ClangDiagnosticWidget::ToolTip,
- color() == Utils::Theme::Color::IconsDisabledColor ? nullptr : m_diagMgr);
+ {m_diagnostic}, ClangDiagnosticWidget::ToolTip, canApplyFixIt);
target->addWidget(widget);
return true;
@@ -287,5 +293,113 @@ void ClangTextMark::removedFromEditor()
m_removedFromEditorHandler(this);
}
+ClangBackEnd::DiagnosticSeverity convertSeverity(DiagnosticSeverity src)
+{
+ if (src == DiagnosticSeverity::Error)
+ return ClangBackEnd::DiagnosticSeverity::Error;
+ if (src == DiagnosticSeverity::Warning)
+ return ClangBackEnd::DiagnosticSeverity::Warning;
+ return ClangBackEnd::DiagnosticSeverity::Note;
+}
+
+ClangBackEnd::SourceRangeContainer convertRange(const FilePath &filePath, const Range &src)
+{
+ const ClangBackEnd::SourceLocationContainer start(filePath.toString(), src.start().line() + 1,
+ src.start().character() + 1);
+ const ClangBackEnd::SourceLocationContainer end(filePath.toString(), src.end().line() + 1,
+ src.end().character() + 1);
+ return ClangBackEnd::SourceRangeContainer(start, end);
+}
+
+ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
+ const FilePath &filePath)
+{
+ ClangBackEnd::DiagnosticContainer target;
+ target.ranges.append(convertRange(filePath, src.range()));
+ target.location = target.ranges.first().start;
+ target.text = src.message();
+ target.category = src.category();
+ if (src.severity())
+ target.severity = convertSeverity(*src.severity());
+ const Diagnostic::Code code = src.code().value_or(Diagnostic::Code());
+ const QString * const codeString = Utils::get_if(&code);
+ if (codeString && codeString->startsWith("-W"))
+ target.enableOption = *codeString;
+ for (const CodeAction &codeAction : src.codeActions().value_or(QList())) {
+ const Utils::optional edit = codeAction.edit();
+ if (!edit)
+ continue;
+ const Utils::optional changes = edit->changes();
+ if (!changes)
+ continue;
+ for (auto it = changes->cbegin(); it != changes->cend(); ++it) {
+ for (const TextEdit &textEdit : it.value()) {
+ target.fixIts << ClangBackEnd::FixItContainer(textEdit.newText(),
+ convertRange(it.key().toFilePath(), textEdit.range()));
+ }
+ }
+ }
+ return target;
+}
+
+ClangdTextMark::ClangdTextMark(const FilePath &filePath,
+ const Diagnostic &diagnostic,
+ const Client *client)
+ : TextEditor::TextMark(filePath, int(diagnostic.range().start().line() + 1), client->id())
+ , m_lspDiagnostic(diagnostic)
+ , m_diagnostic(convertDiagnostic(ClangdDiagnostic(diagnostic), filePath))
+ , m_client(client)
+{
+ setSettingsPage(CppTools::Constants::CPP_CODE_MODEL_SETTINGS_ID);
+
+ const bool isError = diagnostic.severity()
+ && *diagnostic.severity() == DiagnosticSeverity::Error;
+ setDefaultToolTip(isError ? tr("Code Model Error") : tr("Code Model Warning"));
+ setPriority(isError ? TextEditor::TextMark::HighPriority
+ : TextEditor::TextMark::NormalPriority);
+ setIcon(isError ? Icons::CODEMODEL_ERROR.icon() : Icons::CODEMODEL_WARNING.icon());
+ setLineAnnotation(diagnostic.message());
+ setColor(isError ? Theme::CodeModel_Error_TextMarkColor
+ : Theme::CodeModel_Warning_TextMarkColor);
+
+ // Copy to clipboard action
+ QVector actions;
+ QAction *action = new QAction();
+ action->setIcon(QIcon::fromTheme("edit-copy", Icons::COPY.icon()));
+ action->setToolTip(tr("Clang Code Model Marks", "Copy to Clipboard"));
+ QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
+ const QString text = ClangDiagnosticWidget::createText({diag},
+ ClangDiagnosticWidget::InfoBar);
+ QApplication::clipboard()->setText(text, QClipboard::Clipboard);
+ });
+ actions << action;
+
+ // Remove diagnostic warning action
+ ProjectExplorer::Project *project = projectForCurrentEditor();
+ if (project && isDiagnosticConfigChangable(project, m_diagnostic)) {
+ action = new QAction();
+ action->setIcon(Icons::BROKEN.icon());
+ action->setToolTip(tr("Disable Diagnostic in Current Project"));
+ QObject::connect(action, &QAction::triggered, [diag = m_diagnostic]() {
+ disableDiagnosticInCurrentProjectConfig(diag);
+ });
+ actions << action;
+ }
+
+ setActions(actions);
+
+ ClangDiagnosticManager::addTask(m_diagnostic);
+}
+
+bool ClangdTextMark::addToolTipContent(QLayout *target) const
+{
+ const auto canApplyFixIt = [c = m_client, diag = m_lspDiagnostic, fp = fileName()] {
+ return c && c->reachable() && c->hasDiagnostic(DocumentUri::fromFilePath(fp), diag);
+ };
+ target->addWidget(ClangDiagnosticWidget::createWidget({m_diagnostic},
+ ClangDiagnosticWidget::ToolTip, canApplyFixIt));
+ return true;
+}
+
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangtextmark.h b/src/plugins/clangcodemodel/clangtextmark.h
index a7fbdc65268..15b97ab32f1 100644
--- a/src/plugins/clangcodemodel/clangtextmark.h
+++ b/src/plugins/clangcodemodel/clangtextmark.h
@@ -28,10 +28,16 @@
#include
#include
+#include
+
#include
+#include
+
#include
+namespace LanguageClient { class Client; }
+
namespace ClangCodeModel {
namespace Internal {
class ClangDiagnosticManager;
@@ -60,5 +66,21 @@ private:
const ClangDiagnosticManager * const m_diagMgr;
};
+class ClangdTextMark : public TextEditor::TextMark
+{
+ Q_DECLARE_TR_FUNCTIONS(ClangdTextMark)
+public:
+ ClangdTextMark(const ::Utils::FilePath &filePath,
+ const LanguageServerProtocol::Diagnostic &diagnostic,
+ const LanguageClient::Client *client);
+
+private:
+ bool addToolTipContent(QLayout *target) const override;
+
+ const LanguageServerProtocol::Diagnostic m_lspDiagnostic;
+ const ClangBackEnd::DiagnosticContainer m_diagnostic;
+ const QPointer m_client;
+};
+
} // namespace Internal
} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp b/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp
index d17f69ed50a..696ced1c6f7 100644
--- a/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp
+++ b/src/plugins/clangcodemodel/clanguiheaderondiskmanager.cpp
@@ -28,6 +28,7 @@
#include
#include
+#include
#include
namespace ClangCodeModel {
@@ -62,7 +63,7 @@ QString UiHeaderOnDiskManager::remove(const QString &filePath)
QString UiHeaderOnDiskManager::directoryPath() const
{
- return m_temporaryDir.path();
+ return m_temporaryDir.path().path();
}
QString UiHeaderOnDiskManager::mapPath(const QString &filePath) const
diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp
index 95b9364e0c3..6ea7875cab8 100644
--- a/src/plugins/clangcodemodel/clangutils.cpp
+++ b/src/plugins/clangcodemodel/clangutils.cpp
@@ -100,8 +100,10 @@ private:
void addDummyUiHeaderOnDiskIncludePath()
{
const QString path = ClangModelManagerSupport::instance()->dummyUiHeaderOnDiskDirPath();
- if (!path.isEmpty())
- add({"-I", QDir::toNativeSeparators(path)});
+ if (!path.isEmpty()) {
+ prepend(QDir::toNativeSeparators(path));
+ prepend("-I");
+ }
}
};
diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
index a0d8aef4639..36db72ff58a 100644
--- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
+++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp
@@ -52,7 +52,6 @@
#include
#include
-using namespace ClangBackEnd;
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp
index fcc43db4ca3..1e3b55d0c36 100644
--- a/src/plugins/clangcodemodel/test/clangdtests.cpp
+++ b/src/plugins/clangcodemodel/test/clangdtests.cpp
@@ -35,12 +35,14 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
@@ -54,6 +56,7 @@ using namespace CPlusPlus;
using namespace Core;
using namespace CppTools::Tests;
using namespace ProjectExplorer;
+using namespace TextEditor;
namespace ClangCodeModel {
namespace Internal {
@@ -85,14 +88,13 @@ Utils::FilePath ClangdTest::filePath(const QString &fileName) const
void ClangdTest::initTestCase()
{
- const auto settings = CppTools::codeModelSettings();
const QString clangdFromEnv = qEnvironmentVariable("QTC_CLANGD");
if (!clangdFromEnv.isEmpty())
- settings->setClangdFilePath(Utils::FilePath::fromString(clangdFromEnv));
- const auto clangd = settings->clangdFilePath();
+ CppTools::ClangdSettings::setClangdFilePath(Utils::FilePath::fromString(clangdFromEnv));
+ const auto clangd = CppTools::ClangdSettings::instance().clangdFilePath();
if (clangd.isEmpty() || !clangd.exists())
QSKIP("clangd binary not found");
- settings->setUseClangd(true);
+ CppTools::ClangdSettings::setUseClangd(true);
// Find suitable kit.
m_kit = Utils::findOr(KitManager::kits(), nullptr, [](const Kit *k) {
@@ -493,6 +495,830 @@ void ClangdTestLocalReferences::test()
QCOMPARE(actualRanges, expectedRanges);
}
+
+// This tests our help item construction, not the actual tooltip contents. Those come
+// pre-formatted from clangd.
+ClangdTestTooltips::ClangdTestTooltips()
+{
+ setProjectFileName("tooltips.pro");
+ setSourceFileNames({"tooltips.cpp"});
+ setMinimumVersion(13);
+}
+
+void ClangdTestTooltips::test_data()
+{
+ QTest::addColumn("line");
+ QTest::addColumn