Merge remote-tracking branch 'origin/qds/dev'

Change-Id: Id242ab4ca485527defdcc1555d204e12e50ddb7a
This commit is contained in:
Tim Jenssen
2023-09-14 17:25:47 +02:00
616 changed files with 29309 additions and 14257 deletions

View File

@@ -113,6 +113,6 @@ SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
Standard: c++11 Standard: c++17
TabWidth: 4 TabWidth: 4
UseTab: Never UseTab: Never

View File

@@ -36,8 +36,6 @@ qtc_link_with_qt()
option(WITH_TESTS "Build Tests" ${ENV_QTC_WITH_TESTS}) option(WITH_TESTS "Build Tests" ${ENV_QTC_WITH_TESTS})
add_feature_info("Build tests" ${WITH_TESTS} "") add_feature_info("Build tests" ${WITH_TESTS} "")
option(WITH_QMLDESIGNER "Build QmlDesigner" ${ENV_QTC_WITH_QMLDESIGNER})
add_feature_info("Build QmlDesigner and related code" ${WITH_QMLDESIGNER} "")
option(WITH_DEBUG_CMAKE "Enabled CMake project debugging functionality" OFF) option(WITH_DEBUG_CMAKE "Enabled CMake project debugging functionality" OFF)
option(SHOW_BUILD_DATE "Show build date in about dialog" OFF) option(SHOW_BUILD_DATE "Show build date in about dialog" OFF)
option(WITH_SANITIZE "Build with sanitizer enabled" OFF) option(WITH_SANITIZE "Build with sanitizer enabled" OFF)
@@ -73,6 +71,14 @@ find_package(Qt6
COMPONENTS Concurrent Core Gui Network PrintSupport Qml Sql Widgets Xml Core5Compat ${QT_TEST_COMPONENT} COMPONENTS Concurrent Core Gui Network PrintSupport Qml Sql Widgets Xml Core5Compat ${QT_TEST_COMPONENT}
REQUIRED REQUIRED
) )
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.4.3)
option(WITH_QMLDESIGNER "Build QmlDesigner" ${ENV_QTC_WITH_QMLDESIGNER})
else()
option(WITH_QMLDESIGNER "Build QmlDesigner" OFF)
endif()
add_feature_info("Build QmlDesigner and related code (only if Qt is 6.4.3 or newer)" ${WITH_QMLDESIGNER} "")
# hack for Qbs which still supports Qt5 and Qt6 # hack for Qbs which still supports Qt5 and Qt6
if (TARGET Qt6::Core5CompatPrivate) if (TARGET Qt6::Core5CompatPrivate)
if (CMAKE_VERSION VERSION_LESS 3.18) if (CMAKE_VERSION VERSION_LESS 3.18)

View File

@@ -423,11 +423,11 @@ we thank the authors who made this possible:
committee draft. It is compatible with C++11, but will use newer language committee draft. It is compatible with C++11, but will use newer language
features if they are available. features if they are available.
https://github.com/tcbrindle/span https://github.com/martinmoene/span-lite
QtCreator/src/libs/3rdparty/span QtCreator/src/libs/3rdparty/span
Copyright Tristan Brindle, 2018 Copyright 2018-2021 Martin Moene
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

View File

@@ -125,7 +125,7 @@ endfunction()
function(add_qtc_library name) function(add_qtc_library name)
cmake_parse_arguments(_arg "STATIC;OBJECT;SHARED;SKIP_TRANSLATION;ALLOW_ASCII_CASTS;FEATURE_INFO;SKIP_PCH;EXCLUDE_FROM_INSTALL" cmake_parse_arguments(_arg "STATIC;OBJECT;SHARED;SKIP_TRANSLATION;ALLOW_ASCII_CASTS;FEATURE_INFO;SKIP_PCH;EXCLUDE_FROM_INSTALL"
"DESTINATION;COMPONENT;SOURCES_PREFIX;BUILD_DEFAULT" "DESTINATION;COMPONENT;SOURCES_PREFIX;BUILD_DEFAULT"
"CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES" ${ARGN} "CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;SYSTEM_INCLUDES;PUBLIC_INCLUDES;PUBLIC_SYSTEM_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES" ${ARGN}
) )
get_default_defines(default_defines_copy ${_arg_ALLOW_ASCII_CASTS}) get_default_defines(default_defines_copy ${_arg_ALLOW_ASCII_CASTS})
@@ -198,7 +198,9 @@ function(add_qtc_library name)
SOURCES_PREFIX ${_arg_SOURCES_PREFIX} SOURCES_PREFIX ${_arg_SOURCES_PREFIX}
SOURCES ${_arg_SOURCES} SOURCES ${_arg_SOURCES}
INCLUDES ${_arg_INCLUDES} INCLUDES ${_arg_INCLUDES}
SYSTEM_INCLUDES ${_arg_SYTEM_INCLUDES}
PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES} PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES}
PUBLIC_SYSTEM_INCLUDES ${_arg_PUBLIC_SYSTEM_INCLUDES}
DEFINES ${default_defines_copy} ${_arg_DEFINES} ${TEST_DEFINES} DEFINES ${default_defines_copy} ${_arg_DEFINES} ${TEST_DEFINES}
PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES} PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES}
DEPENDS ${_arg_DEPENDS} ${IMPLICIT_DEPENDS} DEPENDS ${_arg_DEPENDS} ${IMPLICIT_DEPENDS}
@@ -322,7 +324,7 @@ function(add_qtc_plugin target_name)
cmake_parse_arguments(_arg cmake_parse_arguments(_arg
"SKIP_INSTALL;INTERNAL_ONLY;SKIP_TRANSLATION;EXPORT;SKIP_PCH" "SKIP_INSTALL;INTERNAL_ONLY;SKIP_TRANSLATION;EXPORT;SKIP_PCH"
"VERSION;COMPAT_VERSION;PLUGIN_PATH;PLUGIN_NAME;OUTPUT_NAME;BUILD_DEFAULT;PLUGIN_CLASS" "VERSION;COMPAT_VERSION;PLUGIN_PATH;PLUGIN_NAME;OUTPUT_NAME;BUILD_DEFAULT;PLUGIN_CLASS"
"CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PLUGIN_DEPENDS;PLUGIN_RECOMMENDS;PLUGIN_TEST_DEPENDS;PROPERTIES" "CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;SYSTEM_INCLUDES;PUBLIC_INCLUDES;PUBLIC_SYSTEM_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PLUGIN_DEPENDS;PLUGIN_RECOMMENDS;PLUGIN_TEST_DEPENDS;PROPERTIES"
${ARGN} ${ARGN}
) )
@@ -465,7 +467,9 @@ function(add_qtc_plugin target_name)
extend_qtc_target(${target_name} extend_qtc_target(${target_name}
INCLUDES ${_arg_INCLUDES} INCLUDES ${_arg_INCLUDES}
SYSTEM_INCLUDES ${_arg_SYSTEM_INCLUDES}
PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES} PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES}
PUBLIC_SYSTEM_INCLUDES ${_arg_PUBLIC_SYSTEM_INCLUDES}
DEFINES ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES} DEFINES ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES}
PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES} PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES}
DEPENDS ${_arg_DEPENDS} ${_DEP_PLUGINS} ${IMPLICIT_DEPENDS} DEPENDS ${_arg_DEPENDS} ${_DEP_PLUGINS} ${IMPLICIT_DEPENDS}

View File

@@ -244,13 +244,13 @@ function(update_resource_files_list sources)
endforeach() endforeach()
endfunction() endfunction()
function(set_public_includes target includes) function(set_public_includes target includes system)
foreach(inc_dir IN LISTS includes) foreach(inc_dir IN LISTS includes)
if (NOT IS_ABSOLUTE ${inc_dir}) if (NOT IS_ABSOLUTE ${inc_dir})
set(inc_dir "${CMAKE_CURRENT_SOURCE_DIR}/${inc_dir}") set(inc_dir "${CMAKE_CURRENT_SOURCE_DIR}/${inc_dir}")
endif() endif()
file(RELATIVE_PATH include_dir_relative_path ${PROJECT_SOURCE_DIR} ${inc_dir}) file(RELATIVE_PATH include_dir_relative_path ${PROJECT_SOURCE_DIR} ${inc_dir})
target_include_directories(${target} PUBLIC target_include_directories(${target} ${system} PUBLIC
$<BUILD_INTERFACE:${inc_dir}> $<BUILD_INTERFACE:${inc_dir}>
$<INSTALL_INTERFACE:${_IDE_HEADER_INSTALL_PATH}/${include_dir_relative_path}> $<INSTALL_INTERFACE:${_IDE_HEADER_INSTALL_PATH}/${include_dir_relative_path}>
) )
@@ -463,7 +463,7 @@ function(extend_qtc_target target_name)
cmake_parse_arguments(_arg cmake_parse_arguments(_arg
"" ""
"SOURCES_PREFIX;SOURCES_PREFIX_FROM_TARGET;FEATURE_INFO" "SOURCES_PREFIX;SOURCES_PREFIX_FROM_TARGET;FEATURE_INFO"
"CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES;SOURCES_PROPERTIES" "CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;SYSTEM_INCLUDES;PUBLIC_INCLUDES;PUBLIC_SYSTEM_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES;SOURCES_PROPERTIES"
${ARGN} ${ARGN}
) )
@@ -504,8 +504,10 @@ function(extend_qtc_target target_name)
PUBLIC ${_arg_PUBLIC_DEFINES} PUBLIC ${_arg_PUBLIC_DEFINES}
) )
target_include_directories(${target_name} PRIVATE ${_arg_INCLUDES}) target_include_directories(${target_name} PRIVATE ${_arg_INCLUDES})
target_include_directories(${target_name} SYSTEM PRIVATE ${_arg_SYSTEM_INCLUDES})
set_public_includes(${target_name} "${_arg_PUBLIC_INCLUDES}") set_public_includes(${target_name} "${_arg_PUBLIC_INCLUDES}" "")
set_public_includes(${target_name} "${_arg_PUBLIC_SYSTEM_INCLUDES}" "SYSTEM")
if (_arg_SOURCES_PREFIX) if (_arg_SOURCES_PREFIX)
foreach(source IN LISTS _arg_SOURCES) foreach(source IN LISTS _arg_SOURCES)

View File

@@ -35,6 +35,8 @@ macro.QMLD = "Qt Quick Designer"
macro.QQV = "Qt QML Viewer" macro.QQV = "Qt QML Viewer"
macro.QSDK = "Qt" macro.QSDK = "Qt"
macro.QUL = "Qt Quick Ultralite" macro.QUL = "Qt Quick Ultralite"
macro.QOI = "Qt Online Installer"
macro.QMT = "Qt Maintenance Tool"
macro.qtcversion = $QTC_VERSION macro.qtcversion = $QTC_VERSION
macro.param = "\\e" macro.param = "\\e"
macro.raisedaster.HTML = "<sup>*</sup>" macro.raisedaster.HTML = "<sup>*</sup>"

View File

@@ -31,7 +31,7 @@
sources. Because the client has a local cache for package storage, you can sources. Because the client has a local cache for package storage, you can
work offline, as long as no new packages are needed from remote servers. work offline, as long as no new packages are needed from remote servers.
To use Conan, install it by using the Qt installer or the tools that To use Conan, install it by using \QOI or the tools that
your operating system has. For example, on Windows, you can use the your operating system has. For example, on Windows, you can use the
\c {choco install conan} or \c {pip install conan} command. \c {choco install conan} or \c {pip install conan} command.

View File

@@ -169,7 +169,7 @@
\section2 Debugging Tools for Windows \section2 Debugging Tools for Windows
To use the CDB debugger, install the \e {Debugging Tools for Windows} when To use the CDB debugger, install the \e {Debugging Tools for Windows} when
you install \QC either by using the Qt Online Installer (in \uicontrol Qt you install \QC either by using \QOI (in \uicontrol Qt
> \uicontrol Tools > \uicontrol {\QC}) or by using the stand-alone \QC > \uicontrol Tools > \uicontrol {\QC}) or by using the stand-alone \QC
installation packages. installation packages.

View File

@@ -102,21 +102,13 @@
\e{Windows} \e{Windows}
Check whether \QC has been compiled with OpenGL/Desktop, or ANGLE as By default Qt Quick uses Direct3D 11. If you have problems, try updating
a backend. The official binaries are always built with ANGLE (a library that your graphics drivers or update your DirectX version. Run \c dxdiag.exe to
maps OpenGL ES API to DirectX). check whether \e{Direct3D Acceleration} is indeed enabled.
\list You can also try setting the \c QSG_RHI_BACKEND environment variable to
\c vulkan or \c opengl. See \l {Qt for Windows - Graphics Acceleration}
\li ANGLE backend: This requires a Windows version newer than Windows XP. for details.
If you have problems, try updating your graphics drivers or update
your DirectX version. Run \c dxdiag.exe to check whether
\e{Direct3D Acceleration} is indeed enabled.
\li OpenGL backend: Make sure your graphics driver supports OpenGL 2.1 or
newer. Try to update your graphics driver.
\endlist
\e{Unix} \e{Unix}

View File

@@ -83,7 +83,7 @@
The data is transmitted to the backend storage using an encrypted The data is transmitted to the backend storage using an encrypted
connection. The storage is located in the same Heroku backend as the connection. The storage is located in the same Heroku backend as the
Qt installer backend. Physically, data is stored in the Amazon cloud. \QOI backend. Physically, data is stored in the Amazon cloud.
\section1 Specify telemetry settings \section1 Specify telemetry settings

View File

@@ -22,10 +22,10 @@
\endlist \endlist
You must install the tool chain for building applications for the targeted You must install the tool chain for building applications for the targeted
embedded platform on the development PC and use the Qt Maintenance Tool to embedded platform on the development PC and use \QMT to
install Qt libraries that are built for the platform. You can then add a install Qt libraries that are built for the platform. You can then add a
\l{glossary-buildandrun-kit}{kit} with the tool chain and the Qt version \l{glossary-buildandrun-kit}{kit} with the tool chain and the Qt version
for the device's architecture. When possible, the Maintenance Tool creates for the device's architecture. When possible, \QMT creates
suitable kits for you. suitable kits for you.
You can connect embedded devices to the development PC to run, debug, and You can connect embedded devices to the development PC to run, debug, and

View File

@@ -54,7 +54,7 @@
\section2 MCU Plugin \section2 MCU Plugin
To be able to develop applications for MCUs, you need the MCU plugin. To be able to develop applications for MCUs, you need the MCU plugin.
This plugin is enabled automatically by the Qt Installer when you This plugin is enabled automatically by \QOI when you
install \QMCU. install \QMCU.
\section2 Specifying MCU Settings \section2 Specifying MCU Settings

View File

@@ -376,7 +376,7 @@
the C++20 committee draft. It is compatible with C++11, but will use the C++20 committee draft. It is compatible with C++11, but will use
newer language features if they are available. newer language features if they are available.
Copyright Tristan Brindle, 2018 Copyright 2018-2021 Martin Moene
Distributed under the \l {http://boost.org/LICENSE_1_0.txt} Distributed under the \l {http://boost.org/LICENSE_1_0.txt}
{Boost Software License, Version 1.0}. {Boost Software License, Version 1.0}.
@@ -384,7 +384,7 @@
The source code can be found here: The source code can be found here:
\list \list
\li \l{https://github.com/tcbrindle/span} \li \l{https://github.com/martinmoene/span-lite}
\li QtCreator/src/libs/3rdparty/span \li QtCreator/src/libs/3rdparty/span
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/span} \li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/span}
\endlist \endlist
@@ -394,180 +394,6 @@
Roberto Raggi <roberto.raggi@gmail.com>\br Roberto Raggi <roberto.raggi@gmail.com>\br
QtCreator/src/libs/3rdparty/cplusplus\br\br QtCreator/src/libs/3rdparty/cplusplus\br\br
\li \b{ANGLE Library (Windows)}
Used on Windows to implement OpenGL ES on top of DirectX.
The source code of ANGLE is part of the Qt libraries. For more
information about the licenses used in Qt GUI, see
\l{https://doc.qt.io/qt-5.11/licenses-used-in-qt.html#qt-gui}{Qt GUI}.
\l{https://spdx.org/licenses/BSD-3-Clause.html}
{BSD 3-clause "New" or "Revised" License}
\badcode
Copyright (C) 2002-2013 The ANGLE Project Authors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
Ltd., nor the names of their contributors may be used to endorse
or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
\endcode
\li \b{ANGLE Array Bounds Clamper for WebKit (Windows)}
Implements clamping of array indexing expressions during shader
translation.
Used on Windows to implement OpenGL ES on top of DirectX. Configure with
\c {-no-opengl}, or \c {-opengl desktop} to exclude.
The sources can be found in
\c qtbase/src/3rdparty/angle/src/third_party/compiler.
BSD 2-clause "Simplified" License.
\badcode
Copyright (C) 2012 Apple Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\endcode
\li \b{ANGLE: Murmurhash (Windows)}
Used on Windows to implement OpenGL ES on top of DirectX. Configure
with \c {-no-opengl}, or \c {-opengl desktop} to exclude.
The sources can be found in
\c qtbase/src/3rdparty/angle/src/third_party/murmurhash.
\badcode
MurmurHash3 was written by Austin Appleby, and is placed in the public
domain. The author hereby disclaims copyright to this source code.
\endcode
Public Domain.
\li \b{ANGLE: Systeminfo (Windows)}
Used on Windows to implement OpenGL ES on top of DirectX. Configure
with \c {-no-opengl}, or \c {-opengl desktop} to exclude.
The sources can be found in
\c qtbase/src/3rdparty/angle/src/third_party/systeminfo.
BSD 2-clause "Simplified" License.
\badcode
Copyright (C) 2009 Apple Inc. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\endcode
\li \b{ANGLE: trace_event (Windows)}
Used on Windows to implement OpenGL ES on top of DirectX. Configure
with \c {-no-opengl}, or \c {-opengl desktop} to exclude.
The sources can be found in
\c qtbase/src/3rdparty/angle/src/third_party/trace_event.
BSD 3-clause "New" or "Revised" License.
\badcode
Copyright 2013 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\endcode
\li \b{SQLite (version 3.8.10.2)} \li \b{SQLite (version 3.8.10.2)}
SQLite is a C-language library that implements a small, fast, SQLite is a C-language library that implements a small, fast,
@@ -586,14 +412,6 @@
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/sqlite} \li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/sqlite}
\endlist \endlist
\li \b{three.js}
Copyright (C) 2010-2015 three.js authors
MIT License.
share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication
\li \b{OpenSSL} \li \b{OpenSSL}
The OpenSSL toolkit stays under a double license, i.e. both the conditions of The OpenSSL toolkit stays under a double license, i.e. both the conditions of

View File

@@ -34,13 +34,13 @@
\section1 Checking Build and Run Settings \section1 Checking Build and Run Settings
\QC is an integrated development environment (IDE) that you can use to \QC is an integrated development environment (IDE) that you can use to
develop Qt applications. While you can use the Qt Installer to install \QC, develop Qt applications. While you can use \QOI to install \QC,
the stand-alone \QC installer never installs Qt or any Qt tools, such as the stand-alone \QC installer never installs Qt or any Qt tools, such as
qmake. To use \QC for Qt development, you also need to install a Qt version qmake. To use \QC for Qt development, you also need to install a Qt version
and a compiler. If you update the compiler version later, you and a compiler. If you update the compiler version later, you
can register it into \QC. can register it into \QC.
The Qt Installer attempts to auto-detect compilers and Qt versions. If it \QOI attempts to auto-detect compilers and Qt versions. If it
succeeds, the relevant kits will automatically become succeeds, the relevant kits will automatically become
available in \QC. If it does not, you must add the kits yourself to tell available in \QC. If it does not, you must add the kits yourself to tell
\QC where everything is. \QC where everything is.

View File

@@ -46,8 +46,8 @@
\row \row
\li \b {\l{Building and Running an Example}} \li \b {\l{Building and Running an Example}}
To check that the \l{https://www.qt.io/download-qt-installer} To check that \l{https://www.qt.io/download-qt-installer}
{Qt Online Installer} created \l{glossary-buildandrun-kit} {\QOI} created \l{glossary-buildandrun-kit}
{build and run kits}, open an example application and run it. {build and run kits}, open an example application and run it.
If you have not done so before, go to If you have not done so before, go to
\l{Building and Running an Example}. \l{Building and Running an Example}.

View File

@@ -19,10 +19,10 @@
\endlist \endlist
You must install the tool chain for building applications for the targeted You must install the tool chain for building applications for the targeted
mobile platform on the development PC and use the Qt Maintenance Tool to mobile platform on the development PC and use \QMT to
install Qt libraries that are built for the platform. You can then add a install Qt libraries that are built for the platform. You can then add a
\l{glossary-buildandrun-kit}{kit} with the tool chain and the Qt version \l{glossary-buildandrun-kit}{kit} with the tool chain and the Qt version
for the device's architecture. When possible, the Maintenance Tool creates for the device's architecture. When possible, \QMT creates
suitable kits for you. suitable kits for you.
You can connect mobile devices to the development PC and select the You can connect mobile devices to the development PC and select the

View File

@@ -20,7 +20,7 @@
specifies the compiler and other necessary tools for building an application specifies the compiler and other necessary tools for building an application
for and running it on a particular platform. for and running it on a particular platform.
\QC automatically detects the compilers that your system or the Qt Installer \QC automatically detects the compilers that your system or \QOI
registers and lists them in \uicontrol Edit > \uicontrol Preferences > registers and lists them in \uicontrol Edit > \uicontrol Preferences >
\uicontrol Kits > \uicontrol Compilers. \uicontrol Kits > \uicontrol Compilers.

View File

@@ -28,7 +28,7 @@
To remove invalid Qt versions, select \uicontrol {Clean Up}. To remove invalid Qt versions, select \uicontrol {Clean Up}.
You can link to a Qt that the Qt Installer installed to You can link to a Qt that \QOI installed to
automatically detect the installed Qt versions. However, you cannot link automatically detect the installed Qt versions. However, you cannot link
to a Qt that the system installed with some other package to a Qt that the system installed with some other package
manager, such as your Linux distribution, brew on \macos, or Chocolatey on manager, such as your Linux distribution, brew on \macos, or Chocolatey on
@@ -112,7 +112,7 @@
output exist. When \QC complains about the installation of a self-built Qt output exist. When \QC complains about the installation of a self-built Qt
version, try running \c {make install} in the build directory to actually version, try running \c {make install} in the build directory to actually
install Qt into the configured location. If you installed Qt using the Qt install Qt into the configured location. If you installed Qt using the Qt
Installer, run the Qt maintenance tool to check for updates or to reinstall Installer, run \QMT to check for updates or to reinstall
the Qt version. the Qt version.
\section1 Minimum Requirements \section1 Minimum Requirements

View File

@@ -14,8 +14,8 @@
\title Configuring Projects \title Configuring Projects
When you install Qt for a target platform, such as Android or QNX, the When you install Qt for a target platform, such as Android or QNX,
\l{https://www.qt.io/download-qt-installer}{Qt Online Installer} \l{https://www.qt.io/download-qt-installer}{\QOI}
creates \l{glossary-buildandrun-kit}{kits} for the development creates \l{glossary-buildandrun-kit}{kits} for the development
targets. targets.

View File

@@ -83,8 +83,8 @@
\note If you have not installed the Qt Virtual Keyboard module when \note If you have not installed the Qt Virtual Keyboard module when
you installed Qt, an error message will appear when you try to open you installed Qt, an error message will appear when you try to open
\e Main.qml for editing. You can use the \l {Installing Qt} \e Main.qml for editing. You can use \l {Installing Qt}
{Qt Maintenance Tool} to install Qt Virtual Keyboard. {\QMT} to install Qt Virtual Keyboard.
\li Select \uicontrol Next to open the \uicontrol {Kit Selection} \li Select \uicontrol Next to open the \uicontrol {Kit Selection}
dialog. dialog.

View File

@@ -119,6 +119,9 @@
name of the main QML file in the Qt Quick UI project. name of the main QML file in the Qt Quick UI project.
\li Select \uicontrol Build > \uicontrol Run to build and run your \li Select \uicontrol Build > \uicontrol Run to build and run your
project. project.
\note If you get error messages related to modules, perfom the steps
described in \l{Adding Qt Quick Designer Components to Qt Installations}.
\endlist \endlist
For example, if you copy the source files of the \e ProgressBar For example, if you copy the source files of the \e ProgressBar

View File

@@ -30,6 +30,11 @@
You can use the \l{http://code.google.com/p/gerrit/}{Gerrit} code review You can use the \l{http://code.google.com/p/gerrit/}{Gerrit} code review
tool for projects that use Git. tool for projects that use Git.
\if defined(qtdesignstudio)
\include creator-vcs-options.qdocinc vcs options
\endif
\if defined(qtcreator)
\section1 Using Git for Windows \section1 Using Git for Windows
If you configure Git for use with \c {git bash}, only, and use SSH If you configure Git for use with \c {git bash}, only, and use SSH
@@ -48,6 +53,16 @@
authorization works as it would with \c {git bash}. authorization works as it would with \c {git bash}.
\image qtcreator-preferences-vcs-git.webp {Git preferences} \image qtcreator-preferences-vcs-git.webp {Git preferences}
\endif
\section1 Initializing Git Repositories
To start controlling a project directory that is currently not under
version control, select \uicontrol Tools > \uicontrol Git >
\uicontrol {Create Repository}. \QC creates a new subdirectory named .git
that has all the necessary repository files. However, Git does not track
anything in the project yet, so you will need to create an initial commit to
start tracking the project files.
\section1 Working with the Current File \section1 Working with the Current File
@@ -183,7 +198,7 @@
\section2 Cleaning Projects \section2 Cleaning Projects
To clean the working directory, select \uicontrol {Build Project} > \uicontrol {Clean}. To clean the working directory, select \uicontrol {Clean Project}.
All files that are not under version control are displayed in All files that are not under version control are displayed in
the \uicontrol {Clean Repository} dialog. Ignored files are deselected by the \uicontrol {Clean Repository} dialog. Ignored files are deselected by
default. Select the files to delete, and then select \uicontrol Delete. default. Select the files to delete, and then select \uicontrol Delete.
@@ -465,15 +480,6 @@
\li Show the commit in the diff editor. \li Show the commit in the diff editor.
\endtable \endtable
\section1 Initializing Git Repositories
To start controlling a project directory that is currently not under
version control, select \uicontrol Tools > \uicontrol Git >
\uicontrol {Create Repository}. \QC creates a new subdirectory named .git
that has all the necessary repository files. However, Git does not track
anything in the project yet, so you will need to create an initial commit to
start tracking the project files.
\section1 Working with Remote Repositories \section1 Working with Remote Repositories
To work with remote repositories, select the commands in \uicontrol Tools > To work with remote repositories, select the commands in \uicontrol Tools >

View File

@@ -39,7 +39,7 @@
\section1 Setting Up the Development Environment \section1 Setting Up the Development Environment
You need to install and configure Qt for WebAssembly and the tool chain for You need to install and configure Qt for WebAssembly and the tool chain for
compiling to WebAssembly. The Qt Installer automatically adds a build and compiling to WebAssembly. \QOI automatically adds a build and
run kit to \QC. run kit to \QC.
\section2 Setting Up Qt for WebAssembly \section2 Setting Up Qt for WebAssembly
@@ -47,7 +47,7 @@
To set up Qt for WebAssembly: To set up Qt for WebAssembly:
\list 1 \list 1
\li Use the Qt maintenance tool to install Qt for WebAssembly and, on \li Use \QMT to install Qt for WebAssembly and, on
Windows, \MinGW (found in \uicontrol {Developer and Designer Tools}). Windows, \MinGW (found in \uicontrol {Developer and Designer Tools}).
\li Check out a known-good Emscripten version supported by the Qt for \li Check out a known-good Emscripten version supported by the Qt for
WebAssembly version that you installed, and install and activate WebAssembly version that you installed, and install and activate

View File

@@ -44,9 +44,9 @@
When developing your plugin, point the \c {CMAKE_PREFIX_PATH} to the When developing your plugin, point the \c {CMAKE_PREFIX_PATH} to the
installation location of \QC, or the \QC app on macOS. installation location of \QC, or the \QC app on macOS.
Get prebuilt packages either from the Get prebuilt packages either from
\l{https://download.qt.io/official_releases/online_installers/} \l{https://download.qt.io/official_releases/online_installers/}
{Qt online installer}, or a standalone \QC installer either for a {\QOI}, or a standalone \QC installer either for a
\l{https://download.qt.io/official_releases/qtcreator/} \l{https://download.qt.io/official_releases/qtcreator/}
{released \QC version} or a \l{https://download.qt.io/snapshots/qtcreator/} {released \QC version} or a \l{https://download.qt.io/snapshots/qtcreator/}
{development snapshot}. {development snapshot}.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -107,8 +107,6 @@
> \uicontrol {My Components}, and you can use instances of them to build > \uicontrol {My Components}, and you can use instances of them to build
more components. more components.
\include qtquick-mcu-support.qdocinc mcu qtquick components
\section1 Merging Files with Templates \section1 Merging Files with Templates
You can merge the current component file against an existing second You can merge the current component file against an existing second

View File

@@ -1,27 +0,0 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
//! [mcu qtquick components]
\section1 Creating UIs for MCUs
\l{\QMCU} enables you to use subsets of components to create UIs for
devices that are powered by microcontroller units (MCU). The subset of
supported components depends on the \QMCU version that you use for
development. In this manual, we indicate which components are supported at
the time of writing.
To develop for MCUs, \l{Creating a Project}{create an MCU project}. Only
the components available on MCUs are displayed in \l Components. Only a
subset of properties is supported for the supported components. The
properties that are not available on MCUs are marked in the \l Properties
view with strikethrough text.
\image qmldesigner-mcu-support.png "Components and Text properties supported for MCUs"
For more information about the supported components and their properties,
see \l{\QMCU - All QML Types}.
//! [mcu qtquick components]
*/

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! /*!
\previouspage studio-on-mcus.html \previouspage studio-mcu-framework.html
\page studio-compatibility-with-mcu-sdks.html \page studio-compatibility-with-mcu-sdks.html
\nextpage studio-features-on-mcu-projects.html \nextpage studio-features-on-mcu-projects.html

View File

@@ -0,0 +1,30 @@
/ Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page studio-connecting-mcus-with-creator.html
\previouspage studio-developing-apps-for-mcus.html
\nextpage studio-help.html
\title Connecting MCUs with Qt Creator
\l {Connecting MCUs} {Connect MCU boards} to a development host to
build applications for them using the GNU Arm Embedded GCC compiler, libraries,
and other GNU tools necessary for BareMetal software development on devices
based on the Arm Cortex-M processors. Deploy the applications on MCUs to run
and debug them using Qt Creator.
The toolchains are available for cross-compilation on Microsoft Windows,
Linux, and macOS. However, the \QMCU SDK is currently only available for
Windows and Linux.
For more information on how to manage the complete cycle of developing \QMCU
applications using Qt tools, see:
\list
\li \l {Infineon Traveo II quick start guide}
\li \l {NXP i.MX RT1170 quick start guide}
\li \l {Renesas EK-RA6M3G quick start guide}
\li \l {Renesas RH850-D1M1A quick start guide}
\endlist
*/

View File

@@ -0,0 +1,148 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\previouspage studio-features-on-mcu-projects.html
\page studio-projects-for-mcus.html
\nextpage studio-creating-uis-for-mcus.html
\title Creating Projects for MCUs
Use the \uicontrol {\QMCU} preset in the \QDS wizard to set up a new \QMCU
project. When you create a project with the wizard, all the necessary files
are created, you can adjust the project settings, and save custom presets.
\image studio-preset-for-mcus.png
Using the \uicontrol {\QMCU} preset creates an application that uses a subset
of the default components that you can deploy, run, and debug on MCU boards.
\note For more information on the default components available for MCU
projects, see \l {Qt Design Studio Features on MCU Projects}.
\section1 Creating an MCU Project
To create an MCU project:
\list 1
\li Select \uicontrol {File} > \uicontrol {New Project}.
\li In the \uicontrol {Presets} tab, select the \uicontrol {\QMCU} preset.
\li In the \uicontrol {Details} tab:
\list
\li Select the path for the project files. You can move the project
folders later.
\li Set the screen size to match the device screen, which also enables
previewing on the desktop. You can change the screen size later in
\l {Properties}.
\endlist
\li Select \uicontrol {Create} to create the project.
\endlist
\QDS creates the following files and folders:
\list
\li .qmlproject project file defines that all component and image files
in the project folder belong to the project. All files are added
automatically to their respective Files node based on their
type.
\note \QMCU does not recommend using the directory property to
individually list the files in the project.
\li .qml files define the functionality and appearance of application
components.
\li \e Screen01.ui.qml defines a custom component that you can edit in
the \l {2D} view. For more information, see \l {UI Files}.
While the custom component is a good starting point for new users,
you don't have to use it. Specifically, if you export and import
designs using \QB, your file is most likely called something
else. For more information, see \l {Exporting from Design Tools}.
\note For MCU projects you can only import 2D assets.
\li \e CMakeLists.txt project configuration file allowing you to
share your project as a fully working C++ application with
developers.
\li qtquickcontrols2.conf file specifies the preferred style and some
style-specific arguments.
\li \e fonts folder contains font files that you have added in
\uicontrol Assets.
\li \e imports folder contains a \e {Constants.qml} file that specifies
a font loader for the Arial font and the screen resolution. The size
of the default Screen.ui.qml \l{basic-rectangle}{Rectangle} should
be set as \c {width: Constants.width} & \c {height: Constants.height}
so that it inherits the global resolution saved here.
\li \e MCUDefaultStyle folder contains the default UI images and
components available for the MCU project.
\endlist
To use image files in the UI, select \uicontrol Assets > \inlineimage icons/plus.png
.
\sa {Using Custom Presets}
\section1 Adding Files to MCU Projects
You can use wizard templates to add individual files to projects.
The wizard templates in the \uicontrol {Qt Quick Controls} category create
stylable versions of the components in the \uicontrol {Qt Quick Controls}
module. For more information, see \l{Creating Custom Controls}.
You can create the following types of files:
\table
\header
\li Category
\li Wizard Template
\li Purpose
\row
\li {1,5} Qt Quick Files
\row
\li Qt Quick File
\li Generates a component with one of the following default components
or \l{Using Positioners}{positioners} as the root component:
\l {basic-item}{Item}, \l {basic-rectangle}{Rectangle}, \l {Images}
{Image}, \l {Border Image}, \l Flickable, Row, Column, Flow, or
Grid.
\row
\li Qt Quick UI File
\li Generates a UI file with one of the above components as the root
component.
\row
\li Qt Quick Views
\li Generates a List View. For more information, see
\l{List and Grid Views}.
\row
\li Qt Quick UI Form
\li Creates a UI file along with a matching QML file for
implementation purposes.
\row
\li {1,8} Qt Quick Controls
\li Custom Button
\li Creates a \l {Button}{push button} with a text label.
\row
\li Custom \CheckBox
\li Creates a \l {Check Box}{check box}.
\row
\li Custom Dial
\li Creates a \l {Slider and Dial}{dial}.
\row
\li Custom Slider
\li Creates a \l {Slider and Dial}{slider}.
\row
\li Custom \SpinBox
\li Creates a \l {Spin Box}{spin box}.
\row
\li Custom Switch
\li Creates a \l {Switch}{switch} with on and off states.
\row
\li \l Pane
\li Provides a background that matches the UI style and theme.
\row
\li SwipeView
\li Enables users to navigate pages by swiping sideways.
\row
\li QML Files
\li ListModel
\li Adds a \l{Editing List Models}{list model} to the project.
\endtable
*/

View File

@@ -0,0 +1,52 @@
/ Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page studio-creating-uis-for-mcus.html
\previouspage studio-projects-for-mcus.html
\nextpage studio-developing-apps-for-mcus.html
\title Creating UIs for MCUs
As a technical artist or a designer, you can use specialized UI design tools,
such as Adobe Photoshop, Sketch, Figma, Blender, or Maya, to create the
original UI design files for your MCU application. After the initial design
work, export your design from the design tools, and import your 2D and 3D UI
design assets into \QDS, which can convert them into code for developers.
For more information on managing the original assets created with
specialized UI design tools, see \l {Asset Creation with Other Tools}.
Once your UI design assets are in \QDS, use it to \l {Wireframing} {wireframe}
your MCU application, to visualize its structure. To modify the look and feel
of your UI further, utilize the preset UI components available in \QDS.
\section1 Using MCU Components
With \QDS, you can use subsets of components to create UIs for
devices that are powered by microcontroller units (MCU). The subset of
supported components depends on the \QMCU version that you use for
development.
To develop for MCUs, \l{Creating Projects for MCUs}{create an MCU project}.
Only the components available on MCUs are displayed in \l Components. Also,
only a subset of properties is supported for the supported components. The
properties that are not available on MCUs are marked in the \l Properties
view with strikethrough text.
\image studio-mcu-components-and-properties.webp "Components and Text properties supported for MCUs"
For more information on the supported views and features, see \l{\QDS Features on MCU Projects}.
For an example on how to create a UI that runs both on the desktop and
on MCUs, see \l {Washing Machine UI}. For step-by-step instructions on how
to use \QDS to design a UI for a specific MCU target device, see:
\list
\li \l {Designing a UI for Infineon Traveo II}
\li \l {Designing a UI for NXP i.MX RT1170}
\li \l {Designing a UI for Renesas RA6M3G}
\li \l {Designing a UI for Renesas RH850-D1M1A}
\endlist
\sa {Specifying Component Properties}
*/

View File

@@ -0,0 +1,28 @@
/ Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page studio-developing-apps-for-mcus.html
\previouspage studio-creating-uis-for-mcus.html
\nextpage studio-connecting-mcus-with-creator.html
\title Developing Applications for MCUs
As a GUI/application developer, use \QDS to bring your designs to life. Add
further functionality to your applications and utilize the \l {Prototyping}
{prototyping} features of \QDS to simulate and validate interactions and
their dynamic behavior.
You can also test, preview, and fine-tune your designs to pixel-perfection
live on the desktop or on an actual MCU target device. For more information,
see \l {Validating with Target Hardware}.
\image qds-mcu-target-deployment.png
With \QDS, designers and developers can work together on common projects to
develop applications. As a designer you can use the views in the \e Design
mode to modify UI files (.ui.qml). As a developer you can use Qt Creator to
work on the Qt Quick (.qml) and other files that are needed to implement the
application logic and to prepare the application for production. For more
information, see \l {Implementing Applications}.
*/

View File

@@ -4,7 +4,7 @@
/*! /*!
\previouspage studio-compatibility-with-mcu-sdks.html \previouspage studio-compatibility-with-mcu-sdks.html
\page studio-features-on-mcu-projects.html \page studio-features-on-mcu-projects.html
\nextpage studio-help.html \nextpage studio-projects-for-mcus.html
\title \QDS Features on MCU Projects \title \QDS Features on MCU Projects

View File

@@ -0,0 +1,27 @@
/ Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page studio-mcu-framework.html
\previouspage studio-on-mcus.html
\nextpage studio-compatibility-with-mcu-sdks.html
\title \QMCU Framework
\QMCU is a comprehensive framework that supports various hardware ecosystems
and platforms. One of the most important libraries provided by the \QMCU
framework is \QUL (QUL), a lightweight implementation of the Qt Quick
framework. \QUL provides a QML API and an efficient graphics rendering engine
that has a low memory footprint and is optimized for MCUs and other
resource-constrained devices.
In addition to a lightweight graphics framework, \QMCU offers a toolkit that
enables you to design, develop, and deploy graphical user interfaces (GUI)
on microcontrollers (MCU). Also, it lets you run the applications either
on BareMetal or a real-time operating system (RTOS).
\note In addition to BareMetal and RTOS, you can use the desktop kit to run
and test the application on desktop without flashing it each time.
For more information on \QMCU, see \l {\QMCU documentation}.
*/

View File

@@ -4,89 +4,49 @@
/*! /*!
\previouspage creator-editor-external.html \previouspage creator-editor-external.html
\page studio-on-mcus.html \page studio-on-mcus.html
\nextpage studio-compatibility-with-mcu-sdks.html \nextpage studio-mcu-framework.html
\title \QDS on MCUs \title \QDS on MCUs
\QMCU is a comprehensive framework that supports various hardware ecosystems \table
and platforms. One of the most important libraries provided by the \QMCU \row
framework is \QUL (QUL), a lightweight implementation of the Qt Quick \li \image qds-front-gs.png
framework. \QUL provides a QML API and an efficient graphics rendering engine \li With \QDS, you can use subsets of components to create UIs
that has a low memory footprint and is optimized for MCUs and other for devices that are powered by microcontroller units (MCU). Use
resource-constrained devices. the \uicontrol {\QMCU} preset in the \QDS wizard to set up a new
\QMCU project. Using the \uicontrol {\QMCU} preset creates an
In addition to a lightweight graphics framework, \QMCU offers a toolkit that application that utilizes a subset of the default components that
enables you to design, develop, and deploy graphical user interfaces (GUI) you can deploy, run, and debug on MCU boards.
on microcontrollers (MCU). Also, it lets you run the applications either \endtable
on BareMetal or a real-time operating system (RTOS).
For more information on \QMCU, see \l {\QMCU documentation}.
\section1 Designing application UIs for MCU devices with \QDS
As a technical artist or a designer you can use specialized UI design tools,
such as Adobe Photoshop, Sketch, Figma, Blender, or Maya to create the
original UI design files for your MCU application. After the initial design
work, export your design from the design tools, and import your 2D and 3D UI
design assets into \QDS, which can convert them into code for developers.
For more information on managing the original assets created with
specialized UI design tools, see \l {Asset Creation with Other Tools}.
Once your UI design assets are in \QDS, use it to \l {Wireframing} {wireframe}
your MCU application, to visualize its structure. To modify the look and feel
of your UI further, utilize the preset UI components available in \QDS.
For an example on how to create a UI that runs both on the desktop and
on MCUs, see \l {Washing Machine UI}. For step-by-step instructions on how
to use \QDS to design a UI for a specific MCU target device, see:
\list \list
\li \l {Designing a UI for Infineon Traveo II} \li \l {\QMCU Framework}
\li \l {Designing a UI for NXP i.MX RT1170}
\li \l {Designing a UI for Renesas RA6M3G}
\li \l {Designing a UI for Renesas RH850-D1M1A}
\endlist
\section1 Developing applications for MCU devices with \QDS Provides an overview of the \QMCU framework.
\li \l {\QDS Version Compatibility with \QMCU SDKs}
As a GUI/application developer, use \QDS to bring your designs to life. Add Lists how the \QDS versions match with particular \QMCU SDKs.
further functionality to your applications and utilize the \l {Prototyping} \li \l {\QDS Features on MCU Projects}
{prototyping} features of \QDS to simulate and validate interactions and
their dynamic behavior.
You can also test, preview, and fine-tune your designs to pixel-perfection Specifies how the \QDS features are supported for developing MCU projects.
live on the desktop or on an actual MCU target device. For more information, \li \l {Creating Projects for MCUs}
see \l {Validating with Target Hardware}.
\image qds-mcu-target-deployment.png Describes how to use the \QDS wizard and \uicontrol {\QMCU} preset
to set up a new \QMCU project.
\li \l {Creating UIs for MCUs}
\QDS enables designers and developers to work together on common projects to Provides an overview of how to create UIs for MCUs from a technical
develop applications. Designers can use the views in the Design mode to modify artist/designer perspective. Also, offers links to detailed instructions
UI files (.ui.qml), whereas developers can use Qt Creator to work on the Qt for designing UIs for specific MCU target devices.
Quick (.qml) and other files that are needed to implement the application \li \l {Developing applications for MCUs}
logic and to prepare the application for production. For more information,
see \l {Implementing Applications}.
\section1 Connecting MCUs with Qt Creator Provides an overview of how to develop, prototype, validate, and
implement applications for MCUs from a GUI/application developer
\l {Connecting MCUs} {Connect MCU boards} to a development host to perspective.
build applications for them using the GNU Arm Embedded GCC compiler, libraries, \li \l {Connecting MCUs with Qt Creator}
and other GNU tools necessary for BareMetal software development on devices
based on the Arm Cortex-M processors. Deploy the applications on MCUs to run
and debug them using Qt Creator.
The toolchains are available for cross-compilation on Microsoft Windows,
Linux, and macOS. However, the \QMCU SDK is currently only available for
Windows and Linux.
For more information on how to manage the complete cycle of developing \QMCU
applications using Qt tools, see:
\list
\li \l {Infineon Traveo II quick start guide}
\li \l {NXP i.MX RT1170 quick start guide}
\li \l {Renesas EK-RA6M3G quick start guide}
\li \l {Renesas RH850-D1M1A quick start guide}
\endlist
Describes how to connect MCUs with Qt Creator. Also, offers links to
detailed instructions on how to manage the complete cycle of developing
\QMCU applications using Qt tools.
\endlist
*/ */

View File

@@ -170,6 +170,36 @@
\c {QtQuick.Studio.Components 1.0}. You can add components from all \c {QtQuick.Studio.Components 1.0}. You can add components from all
the available modules in \QDS later. You can also import a module as the available modules in \QDS later. You can also import a module as
an \e alias. an \e alias.
\row
\li \uicontrol {Properties}
\li Specify new properties or assign values to the existing properties of
the component. You can also add and modify properties in \QDS.
The following are a few examples of the properties:
\code
property int counter: 5
property string label: "ok"
antialiasing : true
width: parent.width / 2
\endcode
To remove a property, write a "dash" (-) followed by the "property name".
For example:
\code
- width
\endcode
will remove the property \e width from the generated code.
\row
\li \uicontrol {Snippet}
\li Specify component to be added as child under this component.
Following example adds a Connection component:
\code
Connections {
target: myItem
onVisibleChanged: console.log(original_Text.visible)
}
\endcode
\note The code must have a scope of a component(e.g. Item, MouseArea,
Connections etc.) with a valid syntax for \l {UI Files}.
\note Add respective imports for your snippet in \uicontrol {Imports}.
\row \row
\li \uicontrol Alias \li \uicontrol Alias
\li Exports the component generated from this layer as an alias in the \li Exports the component generated from this layer as an alias in the

View File

@@ -21,7 +21,7 @@
\section1 2D Assets \section1 2D Assets
You can use the Qt Installer to install \QB if you have a You can use \QOI to install \QB if you have a
\QDS enterprise license. \QDS enterprise license.
\table \table

View File

@@ -10,7 +10,7 @@
\QBPS is included in the \QBPS is included in the
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}. \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
You can use the Qt Installer to have the \QBPS plugin package copied to the You can use \QOI to have the \QBPS plugin package copied to the
following path in your Qt installation folder: following path in your Qt installation folder:
\list \list

View File

@@ -187,8 +187,22 @@
Components 1.0, you need the import statement Components 1.0, you need the import statement
\c {QtQuick.Studio.Components 1.0}. You can also import a module \c {QtQuick.Studio.Components 1.0}. You can also import a module
as an alias. as an alias.
\li In the \uicontrol {Properties} field, specify properties for \li In the \uicontrol {Properties} field, specify new properties or assign
the component. You can add and modify properties in \QDS. values to the existing properties of the component. You can also add and modify
properties in \QDS.
The following are a few examples of the properties:
\code
property int counter: 5
property string label: "ok"
antialiasing : true
width: parent.width / 2
\endcode
To remove a property, write a "dash" (-) followed by the "property name".
For example:
\code
- width
\endcode
will remove the property \e width from the generated code.
\li Select the \uicontrol {Clip Contents} check box to enable clipping \li Select the \uicontrol {Clip Contents} check box to enable clipping
in the type generated from the layer. The generated type will clip in the type generated from the layer. The generated type will clip
its own painting, as well as the painting of its children, to its its own painting, as well as the painting of its children, to its

View File

@@ -10,7 +10,7 @@
\QBSK is included in the \QBSK is included in the
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}. \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
You can use the Qt Installer to have the \QBSK plugin package copied to the You can use \QOI to have the \QBSK plugin package copied to the
following path in your Qt installation folder: following path in your Qt installation folder:
\list \list

View File

@@ -209,8 +209,22 @@
\c {QtQuick.Controls 2.3} and to use Qt Quick Studio Components 1.0, \c {QtQuick.Controls 2.3} and to use Qt Quick Studio Components 1.0,
you need the import statement \c {QtQuick.Studio.Components 1.0}. you need the import statement \c {QtQuick.Studio.Components 1.0}.
You can also import a module as an alias. You can also import a module as an alias.
\li In the \uicontrol {Properties} field, specify properties for the \li In the \uicontrol {Properties} field, specify new properties or assign
component. You can add and modify properties in \QDS. values to the existing properties of the component. You can also add and modify
properties in \QDS.
The following are a few examples of the properties:
\code
property int counter: 5
property string label: "ok"
antialiasing : true
width: parent.width / 2
\endcode
To remove a property, write a "dash" (-) followed by the "property name".
For example:
\code
- width
\endcode
will remove the property \e width from the generated code.
\li Select the \uicontrol Alias check box to export the item generated \li Select the \uicontrol Alias check box to export the item generated
from this layer as an alias in the parent component. from this layer as an alias in the parent component.
\li Select the \uicontrol Clip check box to enable clipping in the \li Select the \uicontrol Clip check box to enable clipping in the

View File

@@ -10,7 +10,7 @@
\QBXD is included in the \QBXD is included in the
\l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}. \l{https://www.qt.io/pricing}{Qt Design Studio Enterprise license}.
You can use the Qt Installer to have the \QBXD plugin package copied to the You can use \QOI to have the \QBXD plugin package copied to the
following path in your Qt installation folder: following path in your Qt installation folder:
\list \list

View File

@@ -114,15 +114,21 @@
you need the import statement \c {QtQuick.Studio.Components 1.0}. you need the import statement \c {QtQuick.Studio.Components 1.0}.
You can also import a module as an alias. You can also import a module as an alias.
\li In the \uicontrol {Properties} field, specify new properties or assign \li In the \uicontrol {Properties} field, specify new properties or assign
value to the existing properties of the component. You can also add and modify values to the existing properties of the component. You can also add and modify
properties in \QDS. properties in \QDS.
Following are few examples of properties: The following are a few examples of the properties:
\code \code
property int counter: 5 property int counter: 5
property string label: "ok" property string label: "ok"
antialiasing : true antialiasing : true
width: parent.width / 2 width: parent.width / 2
\endcode \endcode
To remove a property, write a "dash" (-) followed by the "property name".
For example:
\code
- width
\endcode
will remove the property \e width from the generated code.
\li In the \uicontrol {Snippet} field, specify component to be added as child under this \li In the \uicontrol {Snippet} field, specify component to be added as child under this
component. component.
Following example adds a Connection component: Following example adds a Connection component:
@@ -134,6 +140,7 @@
\endcode \endcode
\note The code must have a scope of a component(e.g. Item, MouseArea, Connections etc.) \note The code must have a scope of a component(e.g. Item, MouseArea, Connections etc.)
with a valid syntax for \l {UI Files}. with a valid syntax for \l {UI Files}.
\note Add respective imports for your snippet in \uicontrol Imports.
\li Select the \uicontrol Clip check box to enable clipping in the \li Select the \uicontrol Clip check box to enable clipping in the
component generated from the layer. The generated component will clip component generated from the layer. The generated component will clip
its own painting, as well as the painting of its children, to its its own painting, as well as the painting of its children, to its

View File

@@ -24,7 +24,7 @@
\li \l {Installation} \li \l {Installation}
\QDS is available either as a standalone installation package or \QDS is available either as a standalone installation package or
as an option in the Qt online installer. as an option in \QOI.
\li \l {Tutorials} \li \l {Tutorials}
Follow a set of hands-on tutorials that illustrate how to use the Follow a set of hands-on tutorials that illustrate how to use the

View File

@@ -3,7 +3,7 @@
/*! /*!
\page studio-help.html \page studio-help.html
\previouspage studio-features-on-mcu-projects.html \previouspage studio-connecting-mcus-with-creator.html
\nextpage creator-how-to-get-help.html \nextpage creator-how-to-get-help.html
\title Help \title Help

View File

@@ -8,15 +8,15 @@
\title Installation \title Installation
You can install \QDS either using a stand-alone installation package or the You can install \QDS either using a stand-alone installation package or \QOI.
Qt online installer. The installers copy all the modules and tools you need The installers copy all the modules and tools you need
to design UIs and preview them on the desktop to your computer and configure to design UIs and preview them on the desktop to your computer and configure
them for you. \QDS is available for Linux, \macOS, and Windows operating them for you. \QDS is available for Linux, \macOS, and Windows operating
systems. For more information, see \l{Supported Platforms}. systems. For more information, see \l{Supported Platforms}.
To begin, create a \l{Qt Account}. This account gives you access to a web To begin, create a \l{Qt Account}. This account gives you access to a web
portal to manage your licenses and download the standalone \QDS package or portal to manage your licenses and download the standalone \QDS package or
the Qt online installer. Alternatively, you can download an evaluation \QOI. Alternatively, you can download an evaluation
package \l{https://www.qt.io/product/ui-design-tools}{here}. package \l{https://www.qt.io/product/ui-design-tools}{here}.
After the installation, you can start exploring \QDS by following After the installation, you can start exploring \QDS by following
@@ -31,15 +31,15 @@
would for any other software, and follow the instructions of the would for any other software, and follow the instructions of the
installer to complete it. installer to complete it.
\section1 Using Qt Online Installer \section1 Using \QOI
You can download the Qt online installer for your operating system You can download \QOI for your operating system
from your Qt Account. from your Qt Account.
\list 1 \list 1
\li Start the Qt online installer. \li Start \QOI.
\li Select \uicontrol {Design Tools}. \li Select \uicontrol {Design Tools}.
\image studio-installation.png "Design Tools selected in Qt online installer" \image studio-installation.png "Design Tools selected in Qt Online Installer"
\li Select \uicontrol Next and follow the instructions of the \li Select \uicontrol Next and follow the instructions of the
installer to complete the installation. installer to complete the installation.
\endlist \endlist

View File

@@ -51,7 +51,7 @@
\li MCU \li MCU
\li Creates an application that uses a subset of default components \li Creates an application that uses a subset of default components
(as supported by \QMCU) that you can deploy, run, and debug (as supported by \QMCU) that you can deploy, run, and debug
on MCU boards. on MCU boards. For more information, see \l {Creating Projects for MCUs}.
\row \row
\li {1,3} Mobile \li {1,3} Mobile
\li Scroll \li Scroll

View File

@@ -33,6 +33,7 @@
\li \l{Open Documents} \li \l{Open Documents}
\li \l{Content Library} \li \l{Content Library}
\li \l{Texture Editor} \li \l{Texture Editor}
\li \l{Qt Insight}
\endlist \endlist
\li \l{Managing Workspaces} \li \l{Managing Workspaces}
\li \l{Managing Sessions} \li \l{Managing Sessions}
@@ -254,8 +255,13 @@
\li \l{Use external tools} \li \l{Use external tools}
\li \l{\QDS on MCUs} \li \l{\QDS on MCUs}
\list \list
\li \l {\QMCU Framework}
\li \l {\QDS Version Compatibility with \QMCU SDKs} \li \l {\QDS Version Compatibility with \QMCU SDKs}
\li \l {\QDS Features on MCU Projects} \li \l {\QDS Features on MCU Projects}
\li \l {Creating Projects for MCUs}
\li \l {Creating UIs for MCUs}
\li \l {Developing Applications for MCUs}
\li \l {Connecting MCUs with Qt Creator}
\endlist \endlist
\endlist \endlist
\li \l Help \li \l Help

View File

@@ -183,7 +183,7 @@
and drag the component along the axis. and drag the component along the axis.
\li To move components on a plane, click the plane handle and drag the \li To move components on a plane, click the plane handle and drag the
component on the plane. component on the plane.
\li To move an component freely in the 3D view, click and drag the gray \li To move components freely in the 3D view, click and drag the gray
handle at the center of the move gizmo. handle at the center of the move gizmo.
\endlist \endlist
@@ -221,6 +221,35 @@
gray handle at the center of the component. gray handle at the center of the component.
\endlist \endlist
\section1 Snapping
With snapping turned on, the objects in the \uicontrol 3D view snap to certain
intervals during transformation (move, rotate, scale).
You can toggle snapping in the following ways:
\list
\li Select \inlineimage icons/snapping-3d.png
in the \uicontrol 3D view toolbar.
\li Hold down the \key Ctrl key.
\endlist
With snapping turned on, you can press and hold \key Shift to snap objects to one tenth of
the specified snap interval.
\section2 Configuring Snapping
To edit snapping settings, select \inlineimage icons/snapping-3d-conf.png
in the \uicontrol 3D view toolbar.
In the configure dialog, you can do the following:
\list
\li Turn on and off snapping separately for the different transformations
(move, rotate, scale).
\li Set snap intervals.
\li Toggle if the position snaps to absolute or relative values.
\endlist
\section1 Aligning Views and Cameras \section1 Aligning Views and Cameras
To align a camera to the \uicontrol{3D} view: To align a camera to the \uicontrol{3D} view:
@@ -375,6 +404,16 @@
\li Toggle Edit Light On/Off \li Toggle Edit Light On/Off
\li \key U \li \key U
\li \l{Using Edit Light} \li \l{Using Edit Light}
\row
\li \inlineimage icons/snapping-3d.png
\li Toggle Snapping During Node Drag
\li \key Shift + \key Tab
\li \l{Snapping}
\row
\li \inlineimage icons/snapping-3d-conf.png
\li Open Snap Configuration Dialog
\li
\li \l{Configuring Snapping}
\row \row
\li \inlineimage icons/align-camera-on.png \li \inlineimage icons/align-camera-on.png
\li Align Selected Cameras to View \li Align Selected Cameras to View

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page studio-qt-insight.html
\previouspage studio-texture-editor.html
\nextpage creator-project-managing-workspaces.html
\title Qt Insight
In the \uicontrol {Qt Insight} view, you manage your Qt Insight.
Qt Insight is an analytics solution that provides real user insights on the usage of Qt
applications. It shows, for example, an applications performance, usage, and user data.
For more information, see the
\l{https://www.qt.io/product/insight/onboarding-instructions}{Getting Started with Qt Insight}
documentation.
\image qt-insight-view.png
In \QDS, you can do the following with Qt Insight:
\list
\li Turn on and off tracking
\li Set send cadence
\li Manage categories
\endlist
*/

View File

@@ -4,7 +4,7 @@
/*! /*!
\page studio-texture-editor.html \page studio-texture-editor.html
\previouspage studio-content-library.html \previouspage studio-content-library.html
\nextpage creator-project-managing-workspaces.html \nextpage studio-qt-insight.html
\title Texture Editor \title Texture Editor

View File

@@ -3,7 +3,7 @@
/*! /*!
\page creator-project-managing-workspaces.html \page creator-project-managing-workspaces.html
\previouspage studio-texture-editor.html \previouspage studio-qt-insight.html
\nextpage creator-project-managing-sessions.html \nextpage creator-project-managing-sessions.html
\title Managing Workspaces \title Managing Workspaces

View File

@@ -156,7 +156,7 @@ TreeViewDelegate {
mouseArea.allowTooltip = true mouseArea.allowTooltip = true
} }
onPositionChanged: tooltipBackend.reposition() onPositionChanged: AssetsLibraryBackend.tooltipBackend.reposition()
onPressed: (mouse) => { onPressed: (mouse) => {
mouseArea.forceActiveFocus() mouseArea.forceActiveFocus()

View File

@@ -145,11 +145,11 @@ Item {
Column { Column {
id: toolbarColumn id: toolbarColumn
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 6 anchors.topMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.bottomMargin: 6 anchors.bottomMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.leftMargin: 10 anchors.leftMargin: StudioTheme.Values.toolbarHorizontalMargin
anchors.rightMargin: 10 anchors.rightMargin: StudioTheme.Values.toolbarHorizontalMargin
spacing: 12 spacing: StudioTheme.Values.toolbarColumnSpacing
StudioControls.SearchBox { StudioControls.SearchBox {
id: searchBox id: searchBox
@@ -260,10 +260,13 @@ Item {
AssetsView { AssetsView {
id: assetsView id: assetsView
assetsRoot: root
contextMenu: contextMenu
width: parent.width width: parent.width
height: parent.height - assetsView.y height: parent.height - assetsView.y
assetsRoot: root
contextMenu: contextMenu
focus: true
} }
} }
} }

View File

@@ -15,6 +15,11 @@ TreeView {
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
rowSpacing: 5 rowSpacing: 5
property bool adsFocus: false
// objectName is used by the dock widget to find this particular ScrollView
// and set the ads focus on it.
objectName: "__mainSrollView"
property var assetsModel: AssetsLibraryBackend.assetsModel property var assetsModel: AssetsLibraryBackend.assetsModel
property var rootView: AssetsLibraryBackend.rootView property var rootView: AssetsLibraryBackend.rootView
property var tooltipBackend: AssetsLibraryBackend.tooltipBackend property var tooltipBackend: AssetsLibraryBackend.tooltipBackend
@@ -46,9 +51,18 @@ TreeView {
return -1 return -1
} }
ScrollBar.vertical: HelperWidgets.VerticalScrollBar { HoverHandler { id: hoverHandler }
ScrollBar.vertical: HelperWidgets.ScrollBar {
id: verticalScrollBar id: verticalScrollBar
scrollBarVisible: root.contentHeight > root.height parent: root
x: root.width - verticalScrollBar.width
y: 0
height: root.availableHeight
orientation: Qt.Vertical
show: (hoverHandler.hovered || root.adsFocus || verticalScrollBar.inUse)
&& verticalScrollBar.isNeeded
} }
model: assetsModel model: assetsModel
@@ -348,22 +362,21 @@ TreeView {
root.currentFilePath = filePath root.currentFilePath = filePath
} }
Keys.enabled: true function moveSelection(amount)
{
Keys.onUpPressed: { if (!assetsModel.haveFiles || !amount)
if (!root.currentFilePath)
return return
let index = assetsModel.indexForPath(root.currentFilePath) let index = root.currentFilePath ? assetsModel.indexForPath(root.currentFilePath)
: root.__modelIndex(root.firstRow)
let row = root.rowAtIndex(index) let row = root.rowAtIndex(index)
let nextRow = row let nextRow = row
let nextIndex = index let nextIndex = index
do { do {
if (nextRow <= root.firstRow) nextRow = nextRow + amount
return // don't select hidden rows if ((amount < 0 && nextRow < root.firstRow) || (amount > 0 && nextRow > root.lastRow))
return
nextRow--
nextIndex = root.__modelIndex(nextRow) nextIndex = root.__modelIndex(nextRow)
} while (assetsModel.isDirectory(nextIndex)) } while (assetsModel.isDirectory(nextIndex))
@@ -371,26 +384,14 @@ TreeView {
root.positionViewAtRow(nextRow, TableView.Contain) root.positionViewAtRow(nextRow, TableView.Contain)
} }
Keys.enabled: true
Keys.onUpPressed: {
moveSelection(-1)
}
Keys.onDownPressed: { Keys.onDownPressed: {
if (!root.currentFilePath) moveSelection(1)
return
let index = assetsModel.indexForPath(root.currentFilePath)
let row = root.rowAtIndex(index)
let nextRow = row
let nextIndex = index
do {
if (nextRow >= root.lastRow)
return // don't select hidden rows
nextRow++
nextIndex = root.__modelIndex(nextRow)
} while (assetsModel.isDirectory(nextIndex))
root.__selectRow(nextRow)
root.positionViewAtRow(nextRow, TableView.Contain)
} }
ConfirmDeleteFilesDialog { ConfirmDeleteFilesDialog {

View File

@@ -0,0 +1,288 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import Qt.labs.platform as PlatformWidgets
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
Item {
id: root
implicitWidth: 300
implicitHeight: innerRect.height + 6
property color textColor
signal selectItem(int itemIndex)
signal deleteItem()
Item {
id: boundingRect
anchors.centerIn: root
width: root.width - 24
height: nameHolder.height
clip: true
MouseArea {
id: itemMouse
anchors.fill: parent
acceptedButtons: Qt.LeftButton
propagateComposedEvents: true
hoverEnabled: true
onClicked: (event) => {
if (!collectionIsSelected) {
collectionIsSelected = true
event.accepted = true
}
}
}
Rectangle {
id: innerRect
anchors.fill: parent
}
Row {
width: parent.width - threeDots.width
leftPadding: 20
Text {
id: moveTool
property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
width: moveTool.style.squareControlSize.width
height: nameHolder.height
text: StudioTheme.Constants.dragmarks
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: moveTool.style.baseIconFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Text {
id: nameHolder
text: collectionName
font.pixelSize: StudioTheme.Values.baseFontSize
color: textColor
leftPadding: 5
topPadding: 8
rightPadding: 8
bottomPadding: 8
elide: Text.ElideMiddle
verticalAlignment: Text.AlignVCenter
}
}
Text {
id: threeDots
text: "..."
font.pixelSize: StudioTheme.Values.baseFontSize
color: textColor
anchors.right: boundingRect.right
anchors.verticalCenter: parent.verticalCenter
rightPadding: 12
topPadding: nameHolder.topPadding
bottomPadding: nameHolder.bottomPadding
verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton + Qt.LeftButton
onClicked: (event) => {
collectionMenu.open()
event.accepted = true
}
}
}
}
PlatformWidgets.Menu {
id: collectionMenu
PlatformWidgets.MenuItem {
text: qsTr("Delete")
shortcut: StandardKey.Delete
onTriggered: deleteDialog.open()
}
PlatformWidgets.MenuItem {
text: qsTr("Rename")
shortcut: StandardKey.Replace
onTriggered: renameDialog.open()
}
}
StudioControls.Dialog {
id: deleteDialog
title: qsTr("Deleting whole collection")
contentItem: Column {
spacing: 2
Text {
text: qsTr("Are you sure that you want to delete collection \"" + collectionName + "\"?")
color: StudioTheme.Values.themeTextColor
}
Item { // spacer
width: 1
height: 20
}
Row {
anchors.right: parent.right
spacing: 10
HelperWidgets.Button {
id: btnDelete
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Delete")
onClicked: root.deleteItem(index)
}
HelperWidgets.Button {
text: qsTr("Cancel")
anchors.verticalCenter: parent.verticalCenter
onClicked: deleteDialog.reject()
}
}
}
}
StudioControls.Dialog {
id: renameDialog
title: qsTr("Rename collection")
onAccepted: {
if (newNameField.text !== "")
collectionName = newNameField.text
}
onOpened: {
newNameField.text = collectionName
}
contentItem: Column {
spacing: 2
Text {
text: qsTr("Previous name: " + collectionName)
color: StudioTheme.Values.themeTextColor
}
Row {
spacing: 10
Text {
text: qsTr("New name:")
color: StudioTheme.Values.themeTextColor
}
StudioControls.TextField {
id: newNameField
anchors.verticalCenter: parent.verticalCenter
actionIndicator.visible: false
translationIndicator.visible: false
validator: newNameValidator
Keys.onEnterPressed: renameDialog.accept()
Keys.onReturnPressed: renameDialog.accept()
Keys.onEscapePressed: renameDialog.reject()
onTextChanged: {
btnRename.enabled = newNameField.text !== ""
}
}
}
Item { // spacer
width: 1
height: 20
}
Row {
anchors.right: parent.right
spacing: 10
HelperWidgets.Button {
id: btnRename
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Rename")
onClicked: renameDialog.accept()
}
HelperWidgets.Button {
text: qsTr("Cancel")
anchors.verticalCenter: parent.verticalCenter
onClicked: renameDialog.reject()
}
}
}
}
HelperWidgets.RegExpValidator {
id: newNameValidator
regExp: /^\w+$/
}
states: [
State {
name: "default"
when: !collectionIsSelected && !itemMouse.containsMouse
PropertyChanges {
target: innerRect
opacity: 0.6
color: StudioTheme.Values.themeControlBackground
}
PropertyChanges {
target: root
textColor: StudioTheme.Values.themeTextColor
}
},
State {
name: "hovered"
when: !collectionIsSelected && itemMouse.containsMouse
PropertyChanges {
target: innerRect
opacity: 0.8
color: StudioTheme.Values.themeControlBackgroundHover
}
PropertyChanges {
target: root
textColor: StudioTheme.Values.themeTextColor
}
},
State {
name: "selected"
when: collectionIsSelected
PropertyChanges {
target: innerRect
opacity: 1
color: StudioTheme.Values.themeControlBackgroundInteraction
}
PropertyChanges {
target: root
textColor: StudioTheme.Values.themeIconColorSelected
}
}
]
}

View File

@@ -0,0 +1,154 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0 as HelperWidgets
import StudioTheme 1.0 as StudioTheme
import CollectionEditorBackend
Item {
id: root
focus: true
property var rootView: CollectionEditorBackend.rootView
property var model: CollectionEditorBackend.model
property var singleCollectionModel: CollectionEditorBackend.singleCollectionModel
function showWarning(title, message) {
warningDialog.title = title
warningDialog.message = message
warningDialog.open()
}
JsonImport {
id: jsonImporter
backendValue: root.rootView
anchors.centerIn: parent
}
CsvImport {
id: csvImporter
backendValue: root.rootView
anchors.centerIn: parent
}
NewCollectionDialog {
id: newCollection
backendValue: root.rootView
anchors.centerIn: parent
}
Message {
id: warningDialog
title: ""
message: ""
}
Rectangle {
id: collectionsRect
color: StudioTheme.Values.themeToolbarBackground
width: 300
height: root.height
Column {
width: parent.width
Rectangle {
width: parent.width
height: StudioTheme.Values.height + 5
color: StudioTheme.Values.themeToolbarBackground
Text {
id: collectionText
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Collections")
font.pixelSize: StudioTheme.Values.mediumIconFont
color: StudioTheme.Values.themeTextColor
leftPadding: 15
}
Row {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
rightPadding: 12
spacing: 2
HelperWidgets.IconButton {
icon: StudioTheme.Constants.translationImport
tooltip: qsTr("Import Json")
onClicked: jsonImporter.open()
}
HelperWidgets.IconButton {
icon: StudioTheme.Constants.translationImport
tooltip: qsTr("Import CSV")
onClicked: csvImporter.open()
}
}
}
Rectangle { // Collections
width: parent.width
color: StudioTheme.Values.themeBackgroundColorNormal
height: 330
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: (event) => {
root.model.deselect()
event.accepted = true
}
}
ListView {
id: collectionListView
width: parent.width
height: contentHeight
model: root.model
delegate: CollectionItem {
onDeleteItem: root.model.removeRow(index)
}
}
}
Rectangle {
width: parent.width
height: addCollectionButton.height
color: StudioTheme.Values.themeBackgroundColorNormal
IconTextButton {
id: addCollectionButton
anchors.centerIn: parent
text: qsTr("Add new collection")
icon: StudioTheme.Constants.create_medium
onClicked: newCollection.open()
}
}
}
}
SingleCollectionView {
model: root.singleCollectionModel
anchors {
left: collectionsRect.right
right: parent.right
top: parent.top
bottom: parent.bottom
}
}
}

View File

@@ -0,0 +1,188 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuickDesignerTheme 1.0
import Qt.labs.platform as PlatformWidgets
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
StudioControls.Dialog {
id: root
title: qsTr("Import A CSV File")
anchors.centerIn: parent
closePolicy: Popup.CloseOnEscape
modal: true
required property var backendValue
property bool fileExists: false
onOpened: {
collectionName.text = "Collection_"
fileName.text = qsTr("New CSV File")
fileName.selectAll()
fileName.forceActiveFocus()
}
onRejected: {
fileName.text = ""
}
HelperWidgets.RegExpValidator {
id: fileNameValidator
regExp: /^(\w[^*><?|]*)[^/\\:*><?|]$/
}
PlatformWidgets.FileDialog {
id: fileDialog
onAccepted: fileName.text = fileDialog.file
}
Message {
id: creationFailedDialog
title: qsTr("Could not load the file")
message: qsTr("An error occurred while trying to load the file.")
onClosed: root.reject()
}
contentItem: Column {
spacing: 10
Row {
spacing: 10
Text {
text: qsTr("File name: ")
anchors.verticalCenter: parent.verticalCenter
color: StudioTheme.Values.themeTextColor
}
StudioControls.TextField {
id: fileName
anchors.verticalCenter: parent.verticalCenter
actionIndicator.visible: false
translationIndicator.visible: false
validator: fileNameValidator
Keys.onEnterPressed: btnCreate.onClicked()
Keys.onReturnPressed: btnCreate.onClicked()
Keys.onEscapePressed: root.reject()
onTextChanged: {
root.fileExists = root.backendValue.isCsvFile(fileName.text)
}
}
HelperWidgets.Button {
id: fileDialogButton
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Open")
onClicked: fileDialog.open()
}
}
Row {
spacing: 10
Text {
text: qsTr("Collection name: ")
anchors.verticalCenter: parent.verticalCenter
color: StudioTheme.Values.themeTextColor
}
StudioControls.TextField {
id: collectionName
anchors.verticalCenter: parent.verticalCenter
actionIndicator.visible: false
translationIndicator.visible: false
validator: HelperWidgets.RegExpValidator {
regExp: /^\w+$/
}
Keys.onEnterPressed: btnCreate.onClicked()
Keys.onReturnPressed: btnCreate.onClicked()
Keys.onEscapePressed: root.reject()
}
}
Text {
id: fieldErrorText
color: StudioTheme.Values.themeTextColor
anchors.right: parent.right
states: [
State {
name: "default"
when: fileName.text !== "" && collectionName.text !== ""
PropertyChanges {
target: fieldErrorText
text: ""
visible: false
}
},
State {
name: "fileError"
when: fileName.text === ""
PropertyChanges {
target: fieldErrorText
text: qsTr("File name can not be empty")
visible: true
}
},
State {
name: "collectionNameError"
when: collectionName.text === ""
PropertyChanges {
target: fieldErrorText
text: qsTr("Collection name can not be empty")
visible: true
}
}
]
}
Item { // spacer
width: 1
height: 20
}
Row {
anchors.right: parent.right
spacing: 10
HelperWidgets.Button {
id: btnCreate
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Import")
enabled: root.fileExists && collectionName.text !== ""
onClicked: {
let csvLoaded = root.backendValue.loadCsvFile(collectionName.text, fileName.text)
if (csvLoaded)
root.accept()
else
creationFailedDialog.open()
}
}
HelperWidgets.Button {
text: qsTr("Cancel")
anchors.verticalCenter: parent.verticalCenter
onClicked: root.reject()
}
}
}
}

View File

@@ -0,0 +1,85 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import StudioTheme as StudioTheme
Rectangle {
id: root
required property string text
required property string icon
property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
implicitHeight: style.squareControlSize.height
implicitWidth: rowAlign.width
signal clicked()
Row {
id: rowAlign
spacing: 0
leftPadding: StudioTheme.Values.inputHorizontalPadding
rightPadding: StudioTheme.Values.inputHorizontalPadding
Text {
id: iconItem
width: root.style.squareControlSize.width
height: root.height
anchors.verticalCenter: parent.verticalCenter
text: root.icon
color: StudioTheme.Values.themeTextColor
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: root.style.baseIconFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Text {
id: textItem
height: root.height
anchors.verticalCenter: parent.verticalCenter
text: root.text
color: StudioTheme.Values.themeTextColor
font.family: StudioTheme.Constants.font.family
font.pixelSize: root.style.baseIconFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: root.clicked()
}
states: [
State {
name: "default"
when: !mouseArea.pressed && !mouseArea.containsMouse
PropertyChanges {
target: root
color: StudioTheme.Values.themeBackgroundColorNormal
}
},
State {
name: "Pressed"
when: mouseArea.pressed
PropertyChanges {
target: root
color: StudioTheme.Values.themeControlBackgroundInteraction
}
},
State {
name: "Hovered"
when: !mouseArea.pressed && mouseArea.containsMouse
PropertyChanges {
target: root
color: StudioTheme.Values.themeControlBackgroundHover
}
}
]
}

View File

@@ -0,0 +1,127 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuickDesignerTheme 1.0
import Qt.labs.platform as PlatformWidgets
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
StudioControls.Dialog {
id: root
title: qsTr("Import Collections")
anchors.centerIn: parent
closePolicy: Popup.CloseOnEscape
modal: true
required property var backendValue
property bool fileExists: false
onOpened: {
fileName.text = qsTr("New Json File")
fileName.selectAll()
fileName.forceActiveFocus()
}
onRejected: {
fileName.text = ""
}
HelperWidgets.RegExpValidator {
id: fileNameValidator
regExp: /^(\w[^*><?|]*)[^/\\:*><?|]$/
}
PlatformWidgets.FileDialog {
id: fileDialog
onAccepted: fileName.text = fileDialog.file
}
Message {
id: creationFailedDialog
title: qsTr("Could not load the file")
message: qsTr("An error occurred while trying to load the file.")
onClosed: root.reject()
}
contentItem: Column {
spacing: 2
Row {
spacing: 10
Text {
text: qsTr("File name: ")
anchors.verticalCenter: parent.verticalCenter
color: StudioTheme.Values.themeTextColor
}
StudioControls.TextField {
id: fileName
anchors.verticalCenter: parent.verticalCenter
actionIndicator.visible: false
translationIndicator.visible: false
validator: fileNameValidator
Keys.onEnterPressed: btnCreate.onClicked()
Keys.onReturnPressed: btnCreate.onClicked()
Keys.onEscapePressed: root.reject()
onTextChanged: {
root.fileExists = root.backendValue.isJsonFile(fileName.text)
}
}
HelperWidgets.Button {
id: fileDialogButton
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Open")
onClicked: fileDialog.open()
}
}
Text {
text: qsTr("File name cannot be empty.")
color: StudioTheme.Values.themeTextColor
anchors.right: parent.right
visible: fileName.text === ""
}
Item { // spacer
width: 1
height: 20
}
Row {
anchors.right: parent.right
spacing: 10
HelperWidgets.Button {
id: btnCreate
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Import")
enabled: root.fileExists
onClicked: {
let jsonLoaded = root.backendValue.loadJsonFile(fileName.text)
if (jsonLoaded)
root.accept()
else
creationFailedDialog.open()
}
}
HelperWidgets.Button {
text: qsTr("Cancel")
anchors.verticalCenter: parent.verticalCenter
onClicked: root.reject()
}
}
}
}

View File

@@ -0,0 +1,41 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
StudioControls.Dialog {
id: root
required property string message
anchors.centerIn: parent
closePolicy: Popup.CloseOnEscape
implicitWidth: 300
modal: true
contentItem: Column {
spacing: 20
width: parent.width
Text {
text: root.message
color: StudioTheme.Values.themeTextColor
wrapMode: Text.WordWrap
width: root.width
leftPadding: 10
rightPadding: 10
}
HelperWidgets.Button {
text: qsTr("Close")
anchors.right: parent.right
onClicked: root.reject()
}
}
onOpened: root.forceActiveFocus()
}

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
StudioControls.Dialog {
id: root
title: qsTr("Add a new Collection")
anchors.centerIn: parent
closePolicy: Popup.CloseOnEscape
modal: true
required property var backendValue
onOpened: {
collectionName.text = "Collection"
}
onRejected: {
collectionName.text = ""
}
onAccepted: {
if (collectionName.text !== "")
root.backendValue.addCollection(collectionName.text)
}
contentItem: Column {
spacing: 10
Row {
spacing: 10
Text {
text: qsTr("Collection name: ")
anchors.verticalCenter: parent.verticalCenter
color: StudioTheme.Values.themeTextColor
}
StudioControls.TextField {
id: collectionName
anchors.verticalCenter: parent.verticalCenter
actionIndicator.visible: false
translationIndicator.visible: false
validator: HelperWidgets.RegExpValidator {
regExp: /^\w+$/
}
Keys.onEnterPressed: btnCreate.onClicked()
Keys.onReturnPressed: btnCreate.onClicked()
Keys.onEscapePressed: root.reject()
}
}
Text {
id: fieldErrorText
color: StudioTheme.Values.themeTextColor
anchors.right: parent.right
text: qsTr("Collection name can not be empty")
visible: collectionName.text === ""
}
Item { // spacer
width: 1
height: 20
}
Row {
anchors.right: parent.right
spacing: 10
HelperWidgets.Button {
id: btnCreate
anchors.verticalCenter: parent.verticalCenter
text: qsTr("Create")
enabled: collectionName.text !== ""
onClicked: root.accept()
}
HelperWidgets.Button {
text: qsTr("Cancel")
anchors.verticalCenter: parent.verticalCenter
onClicked: root.reject()
}
}
}
}

View File

@@ -0,0 +1,134 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import StudioTheme 1.0 as StudioTheme
Rectangle {
id: root
required property var model
property alias leftPadding: topRow.leftPadding
property real rightPadding: topRow.rightPadding
color: StudioTheme.Values.themeBackgroundColorAlternate
Column {
id: topRow
spacing: 0
width: parent.width
leftPadding: 20
rightPadding: 0
topPadding: 5
Text {
id: collectionNameText
leftPadding: 8
rightPadding: 8
topPadding: 3
bottomPadding: 3
color: StudioTheme.Values.themeTextColor
text: root.model.collectionName
font.pixelSize: StudioTheme.Values.mediumIconFont
elide: Text.ElideRight
Rectangle {
anchors.fill: parent
z: parent.z - 1
color: StudioTheme.Values.themeBackgroundColorNormal
}
}
Item { // spacer
width: 1
height: 10
}
HorizontalHeaderView {
id: headerView
property real topPadding: 5
property real bottomPadding: 5
height: headerMetrics.height + topPadding + bottomPadding
syncView: tableView
clip: true
delegate: Rectangle {
implicitWidth: 100
implicitHeight: headerText.height
color: StudioTheme.Values.themeControlBackground
border.width: 2
border.color: StudioTheme.Values.themeControlOutline
clip: true
Text {
id: headerText
topPadding: headerView.topPadding
bottomPadding: headerView.bottomPadding
leftPadding: 5
rightPadding: 5
text: display
font.pixelSize: headerMetrics.font
color: StudioTheme.Values.themeIdleGreen
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.centerIn: parent
elide: Text.ElideRight
}
}
TextMetrics {
id: headerMetrics
font.pixelSize: StudioTheme.Values.baseFontSize
text: "Xq"
}
}
}
TableView {
id: tableView
anchors {
top: topRow.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
leftMargin: root.leftPadding
rightMargin: root.rightPadding
}
model: root.model
delegate: Rectangle {
implicitWidth: 100
implicitHeight: itemText.height
color: StudioTheme.Values.themeControlBackground
border.width: 1
border.color: StudioTheme.Values.themeControlOutline
Text {
id: itemText
text: display
width: parent.width
leftPadding: 5
topPadding: 3
bottomPadding: 3
font.pixelSize: StudioTheme.Values.baseFontSize
color: StudioTheme.Values.themeTextColor
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
}
}

View File

@@ -2,12 +2,39 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import StudioTheme 1.0 as StudioTheme
import HelperWidgets as HelperWidgets
PopupDialog { PopupDialog {
property alias backend: form.backend property alias backend: form.backend
titleBar: Row {
spacing: 30 // TODO
anchors.fill: parent
Text {
color: StudioTheme.Values.themeTextColor
text: qsTr("Owner")
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
HelperWidgets.ToolTipArea {
anchors.fill: parent
tooltip: qsTr("The owner of the property")
}
}
Text {
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
text: form.backend.targetNode
}
}
BindingsDialogForm { BindingsDialogForm {
id: form id: form
y: 32 y: 32
height: 160
} }
} }

View File

@@ -3,99 +3,77 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme
Rectangle { Column {
width: 400 id: root
height: 800
color: "#1b1b1b" readonly property real horizontalSpacing: 10
readonly property real verticalSpacing: 16
readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
property var backend property var backend
Text { y: StudioTheme.Values.popupMargin
id: text1 width: parent.width
x: 10 spacing: root.verticalSpacing
y: 25
color: "#ffffff" Row {
text: qsTr("Target") spacing: root.horizontalSpacing
font.pixelSize: 15
PopupLabel { text: qsTr("From") ; tooltip: qsTr("The Property to assign from.")}
PopupLabel { text: qsTr("To"); tooltip: qsTr("The Property to assign to.") }
} }
Text { Row {
id: text111 spacing: root.horizontalSpacing
x: 80
y: 25 StudioControls.TopLevelComboBox {
color: "red" id: sourceNode
text: backend.targetNode style: StudioTheme.Values.connectionPopupControlStyle
font.pixelSize: 15 width: root.columnWidth
model: backend.sourceNode.model ?? []
onModelChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex
onActivated: backend.sourceNode.activateIndex(sourceNode.currentIndex)
property int currentTypeIndex: backend.sourceNode.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex
}
PopupLabel {
width: root.columnWidth
text: backend.targetNode
}
} }
TopLevelComboBox { Row {
id: target spacing: root.horizontalSpacing
x: 101
width: 210
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -335
model: backend.property.model ?? []
enabled: false
//I see no use case to actually change the property name
//onActivated: backend.targetNode.activateIndex(target.currentIndex)
property int currentTypeIndex: backend.property.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex
}
Text { StudioControls.TopLevelComboBox {
id: text2 id: sourceProperty
x: 13 style: StudioTheme.Values.connectionPopupControlStyle
y: 111 width: root.columnWidth
color: "#ffffff"
text: qsTr("Source Propety")
font.pixelSize: 15
}
TopLevelComboBox { model: backend.sourceProperty.model ?? []
id: sourceNode onModelChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
x: 135 onActivated: backend.sourceProperty.activateIndex(
y: 98 sourceProperty.currentIndex)
width: 156 property int currentTypeIndex: backend.sourceProperty.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
}
model: backend.sourceNode.model ?? [] StudioControls.TopLevelComboBox {
id: name
width: root.columnWidth
style: StudioTheme.Values.connectionPopupControlStyle
onModelChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex model: backend.property.model ?? []
onActivated: backend.sourceNode.activateIndex(sourceNode.currentIndex) onActivated: backend.property.activateIndex(name.currentIndex)
property int currentTypeIndex: backend.sourceNode.currentIndex ?? 0 property int currentTypeIndex: backend.property.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex onCurrentTypeIndexChanged: name.currentIndex = name.currentTypeIndex
} }
Text {
x: 13
y: 88
color: "#ffffff"
text: qsTr("Source Node")
font.pixelSize: 15
}
TopLevelComboBox {
id: sourceProperty
x: 140
y: 121
width: 156
model: backend.sourceProperty.model ?? []
onModelChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
onActivated: backend.sourceProperty.activateIndex(
sourceProperty.currentIndex)
property int currentTypeIndex: backend.sourceProperty.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
}
Text {
id: text3
x: 10
y: 55
color: "#ffffff"
text: qsTr("Property")
font.pixelSize: 15
} }
} }

View File

@@ -3,121 +3,188 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend import ConnectionsEditorEditorBackend
ListView { ListView {
id: listView id: root
width: 606
height: 160 property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
interactive: false
property bool adsFocus: false
clip: true
interactive: true
highlightMoveDuration: 0 highlightMoveDuration: 0
highlightResizeDuration: 0
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds
HoverHandler { id: hoverHandler }
ScrollBar.vertical: HelperWidgets.ScrollBar {
id: verticalScrollBar
parent: root
x: root.width - verticalScrollBar.width
y: 0
height: root.availableHeight
orientation: Qt.Vertical
show: (hoverHandler.hovered || root.focus || verticalScrollBar.inUse || root.adsFocus)
&& verticalScrollBar.isNeeded
}
onVisibleChanged: { onVisibleChanged: {
dialog.hide() dialog.hide()
} }
property int modelCurrentIndex: listView.model.currentIndex ?? 0 property int modelCurrentIndex: root.model.currentIndex ?? 0
// Something weird with currentIndex happens when items are removed added.
// listView.model.currentIndex contains the persistent index.
/* Something weird with currentIndex happens when items are removed added.
listView.model.currentIndex contains the persistent index.
*/
onModelCurrentIndexChanged: { onModelCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex root.currentIndex = root.model.currentIndex
} }
onCurrentIndexChanged: { onCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex root.currentIndex = root.model.currentIndex
dialog.backend.currentRow = listView.currentIndex
} }
// Number of columns
readonly property int numColumns: 4
// Proper row width calculation
readonly property int rowSpacing: StudioTheme.Values.toolbarHorizontalMargin
readonly property int rowSpace: root.width - (root.rowSpacing * (root.numColumns + 1))
- root.style.squareControlSize.width
property int rowWidth: root.rowSpace / root.numColumns
property int rowRest: root.rowSpace % root.numColumns
data: [ data: [
BindingsDialog { BindingsDialog {
id: dialog id: dialog
visible: false visible: false
backend: listView.model.delegate backend: root.model.delegate
} }
] ]
delegate: Item {
width: 600 delegate: Rectangle {
height: 18 id: itemDelegate
required property int index
required property string target
required property string targetProperty
required property string source
required property string sourceProperty
width: ListView.view.width
height: root.style.squareControlSize.height
color: mouseArea.containsMouse ?
itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
: root.style.background.hover
: "transparent"
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
onClicked: { onClicked: {
listView.model.currentIndex = index root.model.currentIndex = itemDelegate.index
listView.currentIndex = index root.currentIndex = itemDelegate.index
dialog.backend.currentRow = index
dialog.popup(mouseArea) dialog.popup(mouseArea)
} }
property int currentIndex: listView.currentIndex
} }
Row { Row {
id: row1 id: row
x: 0
y: 0 property color textColor: itemDelegate.ListView.isCurrentItem ? root.style.text.selectedText
width: 600 : root.style.icon.idle
height: 16
spacing: 10 height: itemDelegate.height
spacing: root.rowSpacing
Text { Text {
width: 120 width: root.rowWidth + root.rowRest
color: "#ffffff" height: itemDelegate.height
text: target ?? "" color: row.textColor
anchors.verticalCenter: parent.verticalCenter text: itemDelegate.target ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
leftPadding: root.rowSpacing
} }
Text { Text {
width: 120 width: root.rowWidth
text: targetProperty ?? "" height: itemDelegate.height
color: "#ffffff" text: itemDelegate.targetProperty ?? ""
anchors.verticalCenter: parent.verticalCenter color: row.textColor
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Text {
width: 120 width: root.rowWidth
text: source ?? "" height: itemDelegate.height
anchors.verticalCenter: parent.verticalCenter text: itemDelegate.source ?? ""
color: "#ffffff" verticalAlignment: Text.AlignVCenter
color: row.textColor
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Text {
width: 120 width: root.rowWidth
text: sourceProperty ?? "" height: itemDelegate.height
anchors.verticalCenter: parent.verticalCenter text: itemDelegate.sourceProperty ?? ""
color: "#ffffff" verticalAlignment: Text.AlignVCenter
color: row.textColor
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Rectangle {
width: 120 width: root.style.squareControlSize.width
height: root.style.squareControlSize.height
text: "-" color: toolTipArea.containsMouse ?
anchors.verticalCenter: parent.verticalCenter itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
horizontalAlignment: Text.AlignRight : root.style.background.hover
font.pointSize: 14 : "transparent"
color: "#ffffff"
font.bold: true Text {
MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: listView.model.remove(index)
text: StudioTheme.Constants.remove_medium
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: root.style.baseIconFontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: row.textColor
renderType: Text.QtRendering
}
HelperWidgets.ToolTipArea {
id: toolTipArea
tooltip: qsTr("This is a test.")
anchors.fill: parent
onClicked: root.model.remove(itemDelegate.index)
} }
} }
} }
} }
highlight: Rectangle { highlight: Rectangle {
color: "#2a5593" color: root.style.interaction
width: 600 width: 600
} }
} }

View File

@@ -2,9 +2,44 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import HelperWidgets 2.0 as HelperWidgets
PopupDialog { PopupDialog {
property alias backend: form.backend
titleBar: Row {
spacing: 30 // TODO
anchors.fill: parent
Text {
color: StudioTheme.Values.themeTextColor
text: qsTr("Target")
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
HelperWidgets.ToolTipArea {
anchors.fill: parent
tooltip: qsTr("Choose the target for the signal.")
}
}
StudioControls.TopLevelComboBox {
id: target
style: StudioTheme.Values.connectionPopupControlStyle
width: 180
anchors.verticalCenter: parent.verticalCenter
model: backend.signal.id.model ?? 0
onActivated: backend.signal.id.activateIndex(target.currentIndex)
property int currentTypeIndex: backend.signal.id.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex
}
}
ConnectionsDialogForm { ConnectionsDialogForm {
y: 32 id: form
} }
} }

View File

@@ -1,242 +1,207 @@
// Copyright (C) 2023 The Qt Company Ltd. // Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import StudioControls import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
Rectangle { Column {
width: 400 id: root
height: 800
color: "#1b1b1b"
Text { readonly property real horizontalSpacing: 10
id: text1 readonly property real verticalSpacing: 16
x: 10 readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
y: 25
color: "#ffffff" property var backend
text: qsTr("Target:")
font.pixelSize: 15 y: StudioTheme.Values.popupMargin
width: parent.width
spacing: root.verticalSpacing
TapHandler {
onTapped: root.forceActiveFocus()
} }
TopLevelComboBox { Row {
id: target spacing: root.horizontalSpacing
x: 95
width: 210 PopupLabel { text: qsTr("Signal"); tooltip: qsTr("The name of the signal.") }
anchors.verticalCenter: parent.verticalCenter PopupLabel { text: qsTr("Action"); tooltip: qsTr("The type of the action.") }
anchors.verticalCenterOffset: -367
model: ["mySpinbox", "foo", "backendObject"]
} }
Text { Row {
id: text2 spacing: root.horizontalSpacing
x: 10
y: 131
color: "#ffffff"
text: qsTr("Signal")
font.pixelSize: 15
}
TopLevelComboBox { StudioControls.TopLevelComboBox {
id: signal id: signal
x: 10 style: StudioTheme.Values.connectionPopupControlStyle
y: 7 width: root.columnWidth
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -207
model: ["onClicked", "onPressed", "onReleased"]
}
TopLevelComboBox { model: backend.signal.name.model ?? 0
id: action
x: 207
y: 7
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -207
model: ["Call Function", "Assign", "ChnageState"]
}
Text { onActivated: backend.signal.name.activateIndex(signal.currentIndex)
id: text3 property int currentTypeIndex: backend.signal.name.currentIndex ?? 0
x: 207 onCurrentTypeIndexChanged: signal.currentIndex = signal.currentTypeIndex
y: 131
color: "#ffffff"
text: qsTr("Action")
font.pixelSize: 15
}
Item {
id: functionGroup
x: 0
y: 276
width: 400
height: 176
Text {
id: text4
x: 17
y: -11
color: "#ffffff"
text: qsTr("Target")
font.pixelSize: 15
} }
TopLevelComboBox { StudioControls.TopLevelComboBox {
id: functionTarget id: action
x: 10 style: StudioTheme.Values.connectionPopupControlStyle
y: 7 width: root.columnWidth
width: 156 textRole: "text"
anchors.verticalCenter: parent.verticalCenter valueRole: "value"
anchors.verticalCenterOffset: -48 ///model.getData(currentIndex, "role")
model: ["mySpinBox", "backendObject", "someButton"] property int indexFromBackend: indexOfValue(backend.actionType)
} onIndexFromBackendChanged: action.currentIndex = action.indexFromBackend
onActivated: backend.changeActionType(action.currentValue)
TopLevelComboBox { model: [
id: functionName { value: ConnectionModelStatementDelegate.CallFunction, text: qsTr("Call Function") },
x: 203 { value: ConnectionModelStatementDelegate.Assign, text: qsTr("Assign") },
y: 7 { value: ConnectionModelStatementDelegate.ChangeState, text: qsTr("Change State") },
width: 156 { value: ConnectionModelStatementDelegate.SetProperty, text: qsTr("Set Property") },
anchors.verticalCenter: parent.verticalCenter { value: ConnectionModelStatementDelegate.PrintMessage, text: qsTr("Print Message") },
anchors.verticalCenterOffset: -48 { value: ConnectionModelStatementDelegate.Custom, text: qsTr("Unknown") }
model: ["start", "trigger", "stop"] ]
}
Text {
id: text5
x: 203
y: -11
color: "#ffffff"
text: qsTr("Function")
font.pixelSize: 15
} }
} }
Item { StatementEditor {
id: statesGroup actionType: action.currentValue ?? ConnectionModelStatementDelegate.Custom
x: 0 horizontalSpacing: root.horizontalSpacing
y: 383 columnWidth: root.columnWidth
width: 400 statement: backend.okStatement
height: 106 spacing: root.verticalSpacing
Text { }
id: text6
x: 17 HelperWidgets.AbstractButton {
y: -11 style: StudioTheme.Values.connectionPopupButtonStyle
color: "#ffffff" width: 160
text: qsTr("State Group") buttonIcon: qsTr("Add Condition")
font.pixelSize: 15 iconSize: StudioTheme.Values.baseFontSize
iconFont: StudioTheme.Constants.font
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom && !backend.hasCondition
onClicked: backend.addCondition()
}
HelperWidgets.AbstractButton {
style: StudioTheme.Values.connectionPopupButtonStyle
width: 160
buttonIcon: qsTr("Remove Condition")
iconSize: StudioTheme.Values.baseFontSize
iconFont: StudioTheme.Constants.font
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom && backend.hasCondition
onClicked: backend.removeCondition()
}
ExpressionBuilder {
style: StudioTheme.Values.connectionPopupControlStyle
width: root.width
visible: backend.hasCondition
model: backend.conditionListModel
onRemove: function(index) {
//console.log("remove", index)
backend.conditionListModel.removeToken(index)
} }
TopLevelComboBox { onUpdate: function(index, value) {
id: stateGroup //console.log("update", index, value)
x: 10 backend.conditionListModel.updateToken(index, value)
y: 7
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -12
model: ["default", "State Group 01", "State Group 02"]
} }
TopLevelComboBox { onAdd: function(value) {
id: stateName //console.log("add", value)
x: 209 backend.conditionListModel.appendToken(value)
y: 7
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -12
model: ["State 01", "State 02", "State 03"]
} }
Text { onInsert: function(index, value, type) {
id: text7 //console.log("insert", index, value, type)
x: 209 if (type === ConditionListModel.Intermediate)
y: -11 backend.conditionListModel.insertIntermediateToken(index, value)
color: "#ffffff" else if (type === ConditionListModel.Shadow)
text: qsTr("State") backend.conditionListModel.insertShadowToken(index, value)
font.pixelSize: 15 else
backend.conditionListModel.insertToken(index, value)
}
onSetValue: function(index, value) {
//console.log("setValue", index, value)
backend.conditionListModel.setShadowToken(index, value)
} }
} }
Item { HelperWidgets.AbstractButton {
id: assignment style: StudioTheme.Values.connectionPopupButtonStyle
x: 10 width: 160
y: 505 buttonIcon: qsTr("Add Else Statement")
width: 400 iconSize: StudioTheme.Values.baseFontSize
height: 106 iconFont: StudioTheme.Constants.font
Text { anchors.horizontalCenter: parent.horizontalCenter
id: text8 visible: action.currentValue !== ConnectionModelStatementDelegate.Custom
x: 17 && backend.hasCondition && !backend.hasElse
y: -11
color: "#ffffff"
text: qsTr("target")
font.pixelSize: 15
}
TopLevelComboBox { onClicked: backend.addElse()
id: valueTarget }
x: 10
y: 7
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -12
model: ["mySpinBox", "myButton", "backendObject"]
}
TopLevelComboBox { HelperWidgets.AbstractButton {
id: valueSource style: StudioTheme.Values.connectionPopupButtonStyle
x: 209 width: 160
y: 7 buttonIcon: qsTr("Remove Else Statement")
width: 156 iconSize: StudioTheme.Values.baseFontSize
anchors.verticalCenter: parent.verticalCenter iconFont: StudioTheme.Constants.font
anchors.verticalCenterOffset: -12 anchors.horizontalCenter: parent.horizontalCenter
model: ["mySpinBox", "myButton", "backendObject"] visible: action.currentValue !== ConnectionModelStatementDelegate.Custom
} && backend.hasCondition && backend.hasElse
onClicked: backend.removeElse()
}
//Else Statement
StatementEditor {
actionType: action.currentValue ?? ConnectionModelStatementDelegate.Custom
horizontalSpacing: root.horizontalSpacing
columnWidth: root.columnWidth
statement: backend.koStatement
spacing: root.verticalSpacing
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom
&& backend.hasCondition && backend.hasElse
}
// Editor
Rectangle {
id: editor
width: parent.width
height: 150
color: StudioTheme.Values.themeToolbarBackground
Text { Text {
id: text9 width: parent.width - 8 // twice the editor button margins
x: 209 anchors.centerIn: parent
y: -11 text: backend.source
color: "#ffffff" color: StudioTheme.Values.themeTextColor
text: qsTr("source") font.pixelSize: StudioTheme.Values.myFontSize
font.pixelSize: 15 wrapMode: Text.WordWrap
} }
Text { HelperWidgets.AbstractButton {
id: text10 id: editorButton
x: 17
y: 76
color: "#ffffff"
text: qsTr("value")
font.pixelSize: 15
}
TopLevelComboBox { anchors.top: parent.top
id: valueOut anchors.right: parent.right
x: 10 anchors.margins: 4
y: -2
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 84
model: ["width", "height", "opacity"]
}
TopLevelComboBox { style: StudioTheme.Values.viewBarButtonStyle
id: valueIn buttonIcon: StudioTheme.Constants.edit_medium
x: 209 tooltip: qsTr("Add something.")
y: -2 onClicked: console.log("OPEN EDITOR")
width: 156
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 84
model: ["width", "height", "x", "y"]
}
Text {
id: text11
x: 209
y: 76
color: "#ffffff"
text: qsTr("value")
font.pixelSize: 15
} }
} }
} }

View File

@@ -3,113 +3,178 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend import ConnectionsEditorEditorBackend
ListView { ListView {
id: listView id: root
width: 606
height: 160 property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
interactive: false
property bool adsFocus: false
clip: true
interactive: true
highlightMoveDuration: 0 highlightMoveDuration: 0
highlightResizeDuration: 0
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds
HoverHandler { id: hoverHandler }
ScrollBar.vertical: HelperWidgets.ScrollBar {
id: verticalScrollBar
parent: root
x: root.width - verticalScrollBar.width
y: 0
height: root.availableHeight
orientation: Qt.Vertical
show: (hoverHandler.hovered || root.focus || verticalScrollBar.inUse || root.adsFocus)
&& verticalScrollBar.isNeeded
}
onVisibleChanged: { onVisibleChanged: {
dialog.hide() dialog.hide()
} }
property int modelCurrentIndex: listView.model.currentIndex ?? 0 property int modelCurrentIndex: root.model.currentIndex ?? 0
// Something weird with currentIndex happens when items are removed added.
// listView.model.currentIndex contains the persistent index.
/*
Something weird with currentIndex happens when items are removed added.
listView.model.currentIndex contains the persistent index.
*/
onModelCurrentIndexChanged: { onModelCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex root.currentIndex = root.model.currentIndex
} }
onCurrentIndexChanged: { onCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex root.currentIndex = root.model.currentIndex
dialog.backend.currentRow = root.currentIndex
} }
// Number of columns
readonly property int numColumns: 3
// Proper row width calculation
readonly property int rowSpacing: StudioTheme.Values.toolbarHorizontalMargin
readonly property int rowSpace: root.width - (root.rowSpacing * (root.numColumns + 1))
- root.style.squareControlSize.width
property int rowWidth: root.rowSpace / root.numColumns
property int rowRest: root.rowSpace % root.numColumns
data: [ data: [
ConnectionsDialog { ConnectionsDialog {
id: dialog id: dialog
visible: false visible: false
backend: root.model.delegate
} }
] ]
delegate: Item { delegate: Rectangle {
id: itemDelegate
width: 600 required property int index
height: 18
required property string signal
required property string target
required property string action
width: ListView.view.width
height: root.style.squareControlSize.height
color: mouseArea.containsMouse ?
itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
: root.style.background.hover
: "transparent"
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
onClicked: { onClicked: {
listView.model.currentIndex = index root.model.currentIndex = itemDelegate.index
listView.currentIndex = index root.currentIndex = itemDelegate.index
dialog.backend.currentRow = itemDelegate.index
dialog.popup(mouseArea) dialog.popup(mouseArea)
} }
property int currentIndex: listView.currentIndex
} }
Row { Row {
id: row1 id: row
x: 0
y: 0 property color textColor: itemDelegate.ListView.isCurrentItem ? root.style.text.selectedText
width: 600 : root.style.icon.idle
height: 16
spacing: 10 height: itemDelegate.height
spacing: root.rowSpacing
Text { Text {
width: 120 width: root.rowWidth + root.rowRest
color: "#ffffff" height: itemDelegate.height
text: target color: row.textColor
anchors.verticalCenter: parent.verticalCenter text: itemDelegate.target
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
leftPadding: root.rowSpacing
elide: Text.ElideMiddle
} }
Text { Text {
width: 120 width: root.rowWidth
text: signal height: itemDelegate.height
color: "#ffffff" text: itemDelegate.signal
anchors.verticalCenter: parent.verticalCenter color: row.textColor
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Text {
width: 120 width: root.rowWidth
height: itemDelegate.height
text: action text: itemDelegate.action
anchors.verticalCenter: parent.verticalCenter verticalAlignment: Text.AlignVCenter
color: "#ffffff" color: row.textColor
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Rectangle {
width: 120 width: root.style.squareControlSize.width
height: root.style.squareControlSize.height
text: "-" color: toolTipArea.containsMouse ?
anchors.verticalCenter: parent.verticalCenter itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
horizontalAlignment: Text.AlignRight : root.style.background.hover
font.pointSize: 14 : "transparent"
color: "#ffffff"
font.bold: true Text {
MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: listView.model.remove(index)
text: StudioTheme.Constants.remove_medium
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: root.style.baseIconFontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: row.textColor
renderType: Text.QtRendering
}
HelperWidgets.ToolTipArea {
id: toolTipArea
tooltip: qsTr("This is a test.")
anchors.fill: parent
onClicked: root.model.remove(itemDelegate.index)
} }
} }
} }
} }
highlight: Rectangle { highlight: Rectangle {
color: "#2a5593" color: root.style.interaction
width: 600
} }
} }

View File

@@ -0,0 +1,495 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
Rectangle {
id: root
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property var conditionListModel: ConnectionsEditorEditorBackend.connectionModel.delegate.conditionListModel
property alias model: repeater.model
property int shadowPillIndex: -1
property bool shadowPillVisible: root.shadowPillIndex !== -1
// Make expression editor at least 20 px high, especially when empty
property int baseHeight: Math.max(20, flow.childrenRect.height)
property int heightBeforeShadowPill: root.baseHeight
property int expressionHeight: {
// If expression is empty or the only item is a shadow pill
if (repeater.count === 0 || (repeater.count === 1 && root.shadowPillVisible))
return root.heightBeforeShadowPill
if (popup.visible)
return root.heightBeforeShadowPill + flow.spacing + 20
return root.heightBeforeShadowPill
}
signal remove(int index)
signal update(int index, var value)
signal add(var value)
signal insert(int index, var value, int type)
signal setValue(int index, var value)
signal setValueType(int index, var value, int type)
width: 400
height: root.expressionHeight + 2 * StudioTheme.Values.flowMargin
color: {
if (focusScope.activeFocus || popup.searchActive)
return root.style.background.interaction
if (mouseArea.containsMouse)
return root.style.background.hover
return root.style.background.idle
}
border {
color: {
if (!root.conditionListModel.valid)
return StudioTheme.Values.themeError
if (focusScope.activeFocus)
return root.style.border.interaction
if (mouseArea.containsMouse)
return root.style.border.hover
return root.style.border.idle
}
width: root.style.borderWidth
}
onVisibleChanged: {
if (!root.visible)
popup.close()
}
// Is text input for creating new items currently used.
function textInputActive() { // TODO Make property
return newTextInput.activeFocus && newTextInput.visible
}
function getMappedItemRect(index: int) : rect {
let item = repeater.itemAt(index)
let itemRect = Qt.rect(item.x, item.y, item.width, item.height)
return flow.mapToItem(root, itemRect)
}
function placeCursor(index: int) : void {
var textInputPosition = Qt.point(0, 0)
if (!repeater.count) { // Empty repeater
let mappedItemRect = flow.mapToItem(root, 0, 0, 0, 0)
textInputPosition = Qt.point(mappedItemRect.x, mappedItemRect.y)
index = 0
} else { // Repeater is not empty
// Clamp index to 0 and num items in repeater
index = Math.min(Math.max(index, 0), repeater.count)
if (index === 0) {
// Needs to be placed in front of first repeater item
let mappedItemRect = root.getMappedItemRect(index)
textInputPosition = Qt.point(mappedItemRect.x - 4, // - 4 due to spacing of flow
mappedItemRect.y)
} else {
let mappedItemRect = root.getMappedItemRect(index - 1)
textInputPosition = Qt.point(mappedItemRect.x + mappedItemRect.width + 3,
mappedItemRect.y)
}
}
// Position text input, make it visible and set focus
newTextInput.x = textInputPosition.x
newTextInput.y = textInputPosition.y
newTextInput.index = index
newTextInput.visible = true
newTextInput.forceActiveFocus()
if (!root.shadowPillVisible)
popup.showOperators = root.conditionListModel.operatorAllowed(index)
// Open suggestion popup
popup.open()
}
ListModel {
id: __operatorModel
function convertValueToName(value) {
for (var i = 0; i < __operatorModel.count; ++i) {
let element = __operatorModel.get(i)
if (element.value === value )
return element.name
}
return value
}
ListElement {
name: "AND"
value: "&&"
tooltip: QT_TR_NOOP("This is AND (&&)")
}
ListElement {
name: "OR"
value: "||"
tooltip: QT_TR_NOOP("This is OR (||)")
}
ListElement {
name: "EQUAL"
value: "==="
tooltip: QT_TR_NOOP("This is EQUAL (===)")
}
ListElement {
name: "NOT EQUAL"
value: "!=="
tooltip: QT_TR_NOOP("This is NOT EQUAL (!==)")
}
ListElement {
name: "GREATER"
value: ">"
tooltip: QT_TR_NOOP("This is GREATER (>)")
}
ListElement {
name: "LESS"
value: "<"
tooltip: QT_TR_NOOP("This is LESS (<)")
}
ListElement {
name: "GREATER OR EQUAL"
value: ">="
tooltip: QT_TR_NOOP("This is GREATER OR EQUAL (>=)")
}
ListElement {
name: "LESS OR EQUAL"
value: "<="
tooltip: QT_TR_NOOP("This is LESS OR EQUAL (<=)")
}
}
StudioControls.ToolTip {
id: toolTip
visible: mouseArea.containsMouse && toolTip.text !== ""
delay: 1000
text: root.conditionListModel.error
}
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.IBeamCursor
hoverEnabled: true
onPressed: function (event) {
// Check if empty
if (!repeater.count) {
root.placeCursor(0)
return
}
// Map to flow item
let point = mouseArea.mapToItem(flow, Qt.point(event.x, event.y))
let horizontalDistance = Number.MAX_VALUE
let verticalDistance = Number.MAX_VALUE
let cursorPosition = 0
for (var i = 0; i < repeater.count; ++i) {
let item = repeater.itemAt(i)
let y = item.y + (item.height / 2)
// Vertical distance
let vDistance = Math.abs(point.y - y)
// Horizontal distance
let hLeftDistance = Math.abs(point.x - item.x)
let hRightDistance = Math.abs(point.x - (item.x + item.width))
// Early return if vertical distance increases
if (vDistance > verticalDistance)
break
if (vDistance <= verticalDistance) {
// Rest horizontal distance if vertical distance is smaller than before
if (vDistance !== verticalDistance)
horizontalDistance = Number.MAX_VALUE
if (hLeftDistance < horizontalDistance) {
horizontalDistance = hLeftDistance
cursorPosition = i
}
if (hRightDistance < horizontalDistance) {
horizontalDistance = hRightDistance
cursorPosition = i + 1
}
verticalDistance = vDistance
}
}
root.placeCursor(cursorPosition)
}
}
Item {
anchors.fill: parent
anchors.margins: StudioTheme.Values.flowMargin
Text {
id: placeholder
height: 20
topPadding: 1
font.pixelSize: root.style.baseFontSize
color: (focusScope.activeFocus || popup.searchActive)
? root.style.text.placeholderInteraction
: root.style.text.placeholder
visible: !repeater.count
text: qsTr("Condition")
}
}
FocusScope {
id: focusScope
anchors.fill: parent
onActiveFocusChanged: {
if (!focusScope.activeFocus && !popup.searchActive)
popup.close()
}
Flow {
id: flow
property int focusIndex: -1
anchors.fill: parent
anchors.margins: StudioTheme.Values.flowMargin
spacing: StudioTheme.Values.flowSpacing
onPositioningComplete: {
if (root.textInputActive())
root.placeCursor(newTextInput.index)
if (!root.shadowPillVisible)
root.heightBeforeShadowPill = root.baseHeight
}
Repeater {
id: repeater
onItemRemoved: function(index, item) {
if (!root.textInputActive())
return
// Udpate the cursor position
if (index < newTextInput.index)
newTextInput.index = newTextInput.index - 1
}
onItemAdded: function(index, item) {
if (!root.textInputActive())
return
if (index >= newTextInput.index)
newTextInput.index = newTextInput.index + 1
}
Pill {
id: pill
operatorModel: __operatorModel
onRemove: function() {
// If pill has focus due to selection or keyboard navigation
if (pill.focus)
root.placeCursor(pill.index)
Qt.callLater(root.remove, pill.index)
}
onUpdate: function(value) {
if (value === "")
Qt.callLater(root.remove, pill.index) // Otherwise crash
else
Qt.callLater(root.update, pill.index, value)
}
onFocusChanged: function() {
if (pill.focus)
flow.focusIndex = pill.index
}
onSubmit: function (cursorPosition) {
let index = pill.index
// If cursor position is 0 the user moved the cursor out to left side,
// so place the cursor before the pill
if (cursorPosition !== 0)
index++
root.placeCursor(index)
}
}
}
}
TextInput {
id: newTextInput
property int index
height: 20
topPadding: 1
font.pixelSize: root.style.baseFontSize
color: root.style.text.idle
visible: false
validator: RegularExpressionValidator { regularExpression: /^\S.+/ }
onTextEdited: {
if (newTextInput.text === "")
return
newTextInput.visible = false
root.insert(newTextInput.index, newTextInput.text, ConditionListModel.Intermediate)
newTextInput.clear()
// Set focus on the newly created item
let newItem = repeater.itemAt(newTextInput.index)
newItem.forceActiveFocus()
}
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Backspace) {
if (root.textInputActive()) {
let previousIndex = newTextInput.index - 1
if (previousIndex < 0)
return
let item = repeater.itemAt(previousIndex)
item.setCursorEnd()
item.forceActiveFocus()
popup.close()
}
}
}
}
}
SuggestionPopup {
id: popup
style: StudioTheme.Values.connectionPopupControlStyle
x: 0
y: root.height
width: root.width
operatorModel: __operatorModel
//onOpened: console.log("POPUP opened")
//onClosed: console.log("POPUP closed")
onAboutToHide: {
newTextInput.visible = false
}
onSelect: function(value) {
newTextInput.visible = true
newTextInput.forceActiveFocus()
if (root.shadowPillVisible) { // Active shadow pill
root.remove(root.shadowPillIndex)
root.shadowPillIndex = -1
}
root.insert(newTextInput.index, value, ConditionListModel.Variable)
// Clear search, reset stack view and tree model
popup.reset()
}
onSearchActiveChanged: {
if (popup.searchActive) {
root.heightBeforeShadowPill = root.baseHeight
root.insert(newTextInput.index, "...", ConditionListModel.Shadow)
root.shadowPillIndex = newTextInput.index
} else {
if (!root.shadowPillVisible)
return
root.remove(root.shadowPillIndex)
root.shadowPillIndex = -1
}
}
onEntered: function(value) {
if (!popup.searchActive) {
if (!root.shadowPillVisible) {
root.heightBeforeShadowPill = root.baseHeight
root.shadowPillIndex = newTextInput.index
root.insert(newTextInput.index, value, ConditionListModel.Shadow)
} else {
root.setValue(root.shadowPillIndex, value)
}
} else {
root.setValue(root.shadowPillIndex, value)
}
}
onExited: function(value) {
let shadowItem = repeater.itemAt(root.shadowPillIndex)
if (!popup.searchActive) {
if (root.shadowPillVisible && shadowItem?.value === value) {
root.remove(root.shadowPillIndex)
root.shadowPillIndex = -1
}
} else {
// Reset to 3 dots if still the same value as the exited item
if (shadowItem?.value === value)
root.setValue(root.shadowPillIndex, "...")
}
}
}
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Left) {
if (root.textInputActive()) {
let previousIndex = newTextInput.index - 1
if (previousIndex < 0)
return
let item = repeater.itemAt(previousIndex)
item.setCursorEnd()
item.forceActiveFocus()
popup.close()
} else {
if (flow.focusIndex < 0)
return
root.placeCursor(flow.focusIndex)
}
} else if (event.key === Qt.Key_Right) {
if (root.textInputActive()) {
let nextIndex = newTextInput.index
if (nextIndex >= repeater.count)
return
let item = repeater.itemAt(nextIndex)
item.setCursorBegin()
item.forceActiveFocus()
popup.close()
} else {
root.placeCursor(flow.focusIndex + 1)
}
}
}
}

View File

@@ -4,114 +4,129 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import ConnectionsEditor import HelperWidgets as HelperWidgets
import HelperWidgets 2.0 as HelperWidgets import StudioControls as StudioControls
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend import ConnectionsEditorEditorBackend
Rectangle { Rectangle {
width: 640 id: root
height: 1080
color: "#232222"
Rectangle { color: StudioTheme.Values.themePanelBackground
id: rectangle
x: 10 property bool adsFocus: false
y: 10 // objectName is used by the dock widget to find this particular ScrollView
width: 620 // and set the ads focus on it.
height: 97 objectName: "__mainSrollView"
color: "#333333"
Column {
id: column
anchors.fill: parent
spacing: 8 // TODO
Rectangle { Rectangle {
id: rectangle1 id: toolbar
x: 10 width: parent.width
y: 10 height: StudioTheme.Values.doubleToolbarHeight
width: 600 color: StudioTheme.Values.themeToolbarBackground
height: 34
color: "#00ffffff"
border.width: 1
Text { Column {
id: text1
x: 10
y: 10
color: "#b5b2b2"
text: qsTr("Search")
font.pixelSize: 12
}
}
RowLayout {
x: 10
y: 50
TabCheckButton {
id: connections
text: "Connections"
checked: true
autoExclusive: true
checkable: true
}
TabCheckButton {
id: bindings
text: "Bindings"
autoExclusive: true
checkable: true
}
TabCheckButton {
id: properties
text: "Properties"
autoExclusive: true
checkable: true
}
}
Text {
id: text2
x: 577
y: 58
color: "#ffffff"
text: qsTr("+")
font.pixelSize: 18
font.bold: true
MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { anchors.topMargin: StudioTheme.Values.toolbarVerticalMargin
print(ConnectionsEditorEditorBackend.dynamicPropertiesModel.delegate) anchors.bottomMargin: StudioTheme.Values.toolbarVerticalMargin
print(ConnectionsEditorEditorBackend.dynamicPropertiesModel.delegate.type) anchors.leftMargin: StudioTheme.Values.toolbarHorizontalMargin
print(ConnectionsEditorEditorBackend.dynamicPropertiesModel.delegate.type.model) anchors.rightMargin: StudioTheme.Values.toolbarHorizontalMargin
spacing: StudioTheme.Values.toolbarColumnSpacing
if (connections.checked) StudioControls.SearchBox {
ConnectionsEditorEditorBackend.connectionModel.add() id: searchBox
else if (bindings.checked) width: parent.width
ConnectionsEditorEditorBackend.bindingModel.add() style: StudioTheme.Values.searchControlStyle
else if (properties.checked)
ConnectionsEditorEditorBackend.dynamicPropertiesModel.add() onSearchChanged: function(searchText) {}
}
Row {
id: row
width: parent.width
height: StudioTheme.Values.toolbarHeight
spacing: 6
TabCheckButton {
id: connections
buttonIcon: StudioTheme.Constants.connections_medium
text: qsTr("Connections")
tooltip: qsTr("This is a tooltip.")
checked: true
autoExclusive: true
checkable: true
}
TabCheckButton {
id: bindings
buttonIcon: StudioTheme.Constants.binding_medium
text: qsTr("Bindings")
tooltip: qsTr("This is a tooltip.")
autoExclusive: true
checkable: true
}
TabCheckButton {
id: properties
buttonIcon: StudioTheme.Constants.properties_medium
text: qsTr("Properties")
tooltip: qsTr("This is a tooltip.")
autoExclusive: true
checkable: true
}
Item {
id: spacer
width: row.width - connections.width - bindings.width
- properties.width - addButton.width - row.spacing * 4
height: 1
}
HelperWidgets.AbstractButton {
id: addButton
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.add_medium
tooltip: qsTr("Add something.")
onClicked: {
if (connections.checked)
ConnectionsEditorEditorBackend.connectionModel.add()
else if (bindings.checked)
ConnectionsEditorEditorBackend.bindingModel.add()
else if (properties.checked)
ConnectionsEditorEditorBackend.dynamicPropertiesModel.add()
}
}
} }
} }
} }
}
ConnectionsListView { ConnectionsListView {
visible: connections.checked visible: connections.checked
x: 17 width: parent.width
y: 124 height: parent.height - toolbar.height - column.spacing
model: ConnectionsEditorEditorBackend.connectionModel model: ConnectionsEditorEditorBackend.connectionModel
} adsFocus: root.adsFocus
}
BindingsListView { BindingsListView {
visible: bindings.checked visible: bindings.checked
x: 17 width: parent.width
y: 124 height: parent.height - toolbar.height - column.spacing
model: ConnectionsEditorEditorBackend.bindingModel model: ConnectionsEditorEditorBackend.bindingModel
} adsFocus: root.adsFocus
}
PropertiesListView { PropertiesListView {
visible: properties.checked visible: properties.checked
x: 17 width: parent.width
y: 124 height: parent.height - toolbar.height - column.spacing
model: ConnectionsEditorEditorBackend.dynamicPropertiesModel model: ConnectionsEditorEditorBackend.dynamicPropertiesModel
adsFocus: root.adsFocus
}
} }
} }

View File

@@ -0,0 +1,29 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
ItemDelegate {
id: control
hoverEnabled: true
contentItem: Text {
leftPadding: 8
rightPadding: 8
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.hovered ? "#111111" : "white"
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 200
implicitHeight: 30
opacity: enabled ? 1 : 0.3
color: control.hovered ? "#4DBFFF" : "transparent"
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuick.Templates as T
import StudioTheme as StudioTheme
T.TreeViewDelegate {
id: control
hoverEnabled: true
implicitWidth: 200
implicitHeight: 30
indentation: 12
leftPadding: control.leftMargin + control.__contentIndent
readonly property int customDepth: control.depth - 1
readonly property real __contentIndent: !control.isTreeNode ? 0
: (control.customDepth * control.indentation)
+ (control.indicator ? control.indicator.width + control.spacing : 0)
indicator: Item {
x: control.leftMargin + (control.customDepth * control.indentation)
width: 30
height: 30
Text {
id: icon
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: StudioTheme.Values.smallIconFontSize
color: control.hovered ? "#111111" : "white" // TODO colors
text: StudioTheme.Constants.sectionToggle
rotation: control.expanded ? 0 : -90
anchors.centerIn: parent
}
}
background: Rectangle {
implicitWidth: 200
implicitHeight: 30
color: control.hovered ? "#4DBFFF" : "transparent"
}
contentItem: Text {
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: control.hovered ? "#111111" : "white"
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}

View File

@@ -0,0 +1,163 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import StudioControls as StudioControls
import StudioTheme as StudioTheme
FocusScope {
id: root
required property int index
required property string value
required property int type
function setCursorBegin() { textInput.cursorPosition = 0 }
function setCursorEnd() { textInput.cursorPosition = textInput.text.length }
function isEditable() { return root.type === ConditionListModel.Intermediate
|| root.type === ConditionListModel.Literal
|| root.type === ConditionListModel.Invalid }
function isIntermediate() { return root.type === ConditionListModel.Intermediate }
function isLiteral() { return root.type === ConditionListModel.Literal }
function isOperator() { return root.type === ConditionListModel.Operator }
function isProperty() { return root.type === ConditionListModel.Variable }
function isShadow() { return root.type === ConditionListModel.Shadow }
function isInvalid() { return root.type === ConditionListModel.Invalid }
signal remove()
signal update(var value)
signal submit(int cursorPosition)
readonly property int margin: StudioTheme.Values.flowPillMargin
property var operatorModel
width: {
if (root.isEditable()) {
if (root.isInvalid())
return textInput.width + 1 + 2 * root.margin
else
return textInput.width + 1
}
return textItem.contentWidth + icon.width + root.margin
}
height: StudioTheme.Values.flowPillHeight
onActiveFocusChanged: {
if (root.activeFocus && root.isEditable())
textInput.forceActiveFocus()
}
Keys.onPressed: function (event) {
if (root.isEditable())
return
if (event.key === Qt.Key_Backspace || event.key === Qt.Key_Delete)
root.remove()
}
MouseArea {
id: rootMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: root.isEditable() ? Qt.IBeamCursor : Qt.ArrowCursor
onClicked: root.forceActiveFocus()
}
Rectangle {
id: pill
anchors.fill: parent
color: {
if (root.isShadow())
return StudioTheme.Values.themeInteraction
if (root.isEditable())
return "transparent"
return StudioTheme.Values.themePillBackground
}
border.color: root.isInvalid() ? StudioTheme.Values.themeWarning : "white" // TODO colors
border.width: {
if (root.isShadow())
return 0
if (root.isInvalid())
return 1
if (root.isEditable())
return 0
if (rootMouseArea.containsMouse || root.focus)
return 1
return 0
}
radius: StudioTheme.Values.flowPillRadius
Row {
id: row
anchors.left: parent.left
anchors.leftMargin: root.margin
anchors.verticalCenter: parent.verticalCenter
visible: root.isOperator() || root.isProperty() || root.isShadow()
Text {
id: textItem
font.pixelSize: StudioTheme.Values.baseFontSize
color: root.isShadow() ? StudioTheme.Values.themeTextSelectedTextColor
: StudioTheme.Values.themeTextColor
text: root.isOperator() ? root.operatorModel.convertValueToName(root.value)
: root.value
anchors.verticalCenter: parent.verticalCenter
}
Item {
id: icon
width: root.isShadow() ? root.margin : StudioTheme.Values.flowPillHeight
height: StudioTheme.Values.flowPillHeight
visible: !root.isShadow()
Text {
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: StudioTheme.Values.smallIconFontSize
color: StudioTheme.Values.themeIconColor
text: StudioTheme.Constants.close_small
anchors.centerIn: parent
}
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: root.remove()
}
}
}
TextInput {
id: textInput
x: root.isInvalid() ? root.margin : 0
height: StudioTheme.Values.flowPillHeight
topPadding: 1
font.pixelSize: StudioTheme.Values.baseFontSize
color: (rootMouseArea.containsMouse || textInput.activeFocus) ? StudioTheme.Values.themeIconColor
: StudioTheme.Values.themeTextColor
text: root.value
visible: root.isEditable()
enabled: root.isEditable()
//validator: RegularExpressionValidator { regularExpression: /^\S+/ }
onEditingFinished: {
root.update(textInput.text) // emit
root.submit(textInput.cursorPosition) // emit
}
Keys.onPressed: function (event) {
if (event.key === Qt.Key_Backspace) {
if (textInput.text !== "")
return
root.remove() // emit
}
}
}
}
}

View File

@@ -3,70 +3,100 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import HelperWidgets 2.0 as HelperWidgets
import StudioTheme 1.0 as StudioTheme
import ConnectionsEditorEditorBackend
Window { Window {
id: window id: window
width: 400
height: 800 property alias titleBar: titleBarContent.children
default property alias content: mainContent.children
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
width: 320
height: column.implicitHeight
visible: true visible: true
flags: Qt.FramelessWindowHint || Qt.Dialog flags: Qt.FramelessWindowHint | Qt.Dialog
color: StudioTheme.Values.themePopoutBackground
color: Qt.transparent function ensureVerticalPosition() {
if ((window.y + window.height) > (Screen.height - window.style.dialogScreenMargin)) {
property int bw: 5 window.y = (Screen.height - window.height - window.style.dialogScreenMargin)
}
function popup(item) {
print("popup " + item)
var padding = 12
var p = item.mapToGlobal(0, 0)
dialog.x = p.x - dialog.width - padding
if (dialog.x < 0)
dialog.x = p.x + item.width + padding
dialog.y = p.y
dialog.show()
dialog.raise()
} }
Rectangle { onHeightChanged: window.ensureVerticalPosition()
id: rectangle1
color: "#d7d7d7" function popup(item) {
border.color: "#232323" var padding = 12
var p = item.mapToGlobal(0, 0)
window.x = p.x - window.width - padding
if (window.x < 0)
window.x = p.x + item.width + padding
window.y = p.y
window.ensureVerticalPosition()
window.show()
window.raise()
}
Column {
id: column
anchors.fill: parent anchors.fill: parent
Item {
id: titleBarItem
width: parent.width
height: StudioTheme.Values.titleBarHeight
Rectangle {
id: rectangle
height: 32
color: "#797979"
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 0
anchors.leftMargin: 0
anchors.rightMargin: 0
DragHandler { DragHandler {
grabPermissions: TapHandler.CanTakeOverFromAnything id: dragHandler
onActiveChanged: if (active) { window.startSystemMove(); }
target: null
grabPermissions: PointerHandler.CanTakeOverFromAnything
onActiveChanged: {
if (dragHandler.active)
window.startSystemMove() // QTBUG-102488
}
} }
Rectangle { Row {
id: rectangle2 id: row
x: 329 anchors.fill: parent
width: 16 anchors.leftMargin: StudioTheme.Values.popupMargin
height: 16 anchors.rightMargin: StudioTheme.Values.popupMargin
color: "#ffffff" spacing: 0
radius: 4
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 6
MouseArea { Item {
id: mouseArea id: titleBarContent
anchors.fill: parent width: row.width - closeIndicator.width //- row.anchors.leftMargin
height: row.height
}
HelperWidgets.IconIndicator {
id: closeIndicator
anchors.verticalCenter: parent.verticalCenter
icon: StudioTheme.Constants.colorPopupClose
pixelSize: StudioTheme.Values.myIconFontSize// * 1.4
onClicked: window.close() onClicked: window.close()
} }
} }
} }
Rectangle {
width: parent.width - 8
height: 1
anchors.horizontalCenter: parent.horizontalCenter
color: "#636363"
}
Item {
id: mainContent
width: parent.width - 2 * StudioTheme.Values.popupMargin
height: mainContent.childrenRect.height + 2 * StudioTheme.Values.popupMargin
anchors.horizontalCenter: parent.horizontalCenter
}
} }
} }

View File

@@ -0,0 +1,20 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
Text {
width: root.columnWidth
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
property alias tooltip: area.tooltip
HelperWidgets.ToolTipArea {
id: area
anchors.fill: parent
tooltip: qsTr("missing")
}
}

View File

@@ -2,12 +2,39 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import StudioTheme 1.0 as StudioTheme
import HelperWidgets as HelperWidgets
PopupDialog { PopupDialog {
property alias backend: form.backend property alias backend: form.backend
titleBar: Row {
spacing: 30 // TODO
anchors.fill: parent
Text {
color: StudioTheme.Values.themeTextColor
text: qsTr("Owner")
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
HelperWidgets.ToolTipArea {
anchors.fill: parent
tooltip: qsTr("The owner of the property")
}
}
Text {
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
text: form.backend.targetNode
}
}
PropertiesDialogForm { PropertiesDialogForm {
id: form id: form
y: 32 y: 32
height: 180
} }
} }

View File

@@ -1,76 +1,73 @@
// Copyright (C) 2023 The Qt Company Ltd. // Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick 2.15 import QtQuick
import QtQuick.Controls 2.15 import QtQuick.Controls
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import StudioControls Column {
id: root
readonly property real horizontalSpacing: 10
readonly property real verticalSpacing: 16
readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
Rectangle {
width: 400
height: 800
color: "#1b1b1b"
property var backend property var backend
Text { y: StudioTheme.Values.popupMargin
id: text1 width: parent.width
x: 10 spacing: root.verticalSpacing
y: 25
color: "#ffffff" PopupLabel {
text: qsTr("Type:") text: qsTr("Type")
font.pixelSize: 15 tooltip: qsTr("The type of the property")
} }
StudioControls.TopLevelComboBox {
id: type
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//width: root.width
TopLevelComboBox {
id: target
x: 95
width: 210
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -367
model: backend.type.model ?? [] model: backend.type.model ?? []
onActivated: backend.type.activateIndex(target.currentIndex) onActivated: backend.type.activateIndex(type.currentIndex)
property int currentTypeIndex: backend.type.currentIndex ?? 0 property int currentTypeIndex: backend.type.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex onCurrentTypeIndexChanged: type.currentIndex = type.currentTypeIndex
} }
Text { Row {
id: text2 spacing: root.horizontalSpacing
x: 10
y: 131 PopupLabel { text: qsTr("Name") ; tooltip: qsTr("The name of the property.")}
color: "#ffffff" PopupLabel { text: qsTr("Value"); tooltip: qsTr("The value of the property.") }
text: qsTr("Name")
font.pixelSize: 15
} }
TextInput { Row {
id: name spacing: root.horizontalSpacing
x: 70 StudioControls.TextField {
y: 131 id: name
color: "white"
width: 156 width: root.columnWidth
text: backend.name.text ?? "" actionIndicatorVisible: false
onEditingFinished: { translationIndicatorVisible: false
backend.name.activateText(name.text)
text: backend.name.text ?? ""
onEditingFinished: {
backend.name.activateText(name.text)
}
} }
} StudioControls.TextField {
id: value
Text { width: root.columnWidth
x: 10 actionIndicatorVisible: false
y: 81 translationIndicatorVisible: false
color: "#ffffff"
text: qsTr("Value")
font.pixelSize: 15
}
TextInput {
id: value text: backend.value.text ?? ""
color: "red" onEditingFinished: {
x: 70 backend.value.activateText(value.text)
y: 81 }
width: 156
text: backend.value.text ?? ""
onEditingFinished: {
backend.value.activateText(value.text)
} }
} }
} }

View File

@@ -3,126 +3,191 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend import ConnectionsEditorEditorBackend
ListView { ListView {
id: listView id: root
width: 606
height: 160 property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
interactive: false
property bool adsFocus: false
clip: true
interactive: true
highlightMoveDuration: 0 highlightMoveDuration: 0
highlightResizeDuration: 0
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds
HoverHandler { id: hoverHandler }
ScrollBar.vertical: HelperWidgets.ScrollBar {
id: verticalScrollBar
parent: root
x: root.width - verticalScrollBar.width
y: 0
height: root.availableHeight
orientation: Qt.Vertical
show: (hoverHandler.hovered || root.focus || verticalScrollBar.inUse || root.adsFocus)
&& verticalScrollBar.isNeeded
}
onVisibleChanged: { onVisibleChanged: {
dialog.hide() dialog.hide()
} }
property int modelCurrentIndex: listView.model.currentIndex ?? 0 property int modelCurrentIndex: root.model.currentIndex ?? 0
// Something weird with currentIndex happens when items are removed added.
// listView.model.currentIndex contains the persistent index.
/* Something weird with currentIndex happens when items are removed added.
listView.model.currentIndex contains the persistent index.
*/
onModelCurrentIndexChanged: { onModelCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex root.currentIndex = root.model.currentIndex
} }
onCurrentIndexChanged: { onCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex root.currentIndex = root.model.currentIndex
dialog.backend.currentRow = listView.currentIndex
} }
// Number of columns
readonly property int numColumns: 4
// Proper row width calculation
readonly property int rowSpacing: StudioTheme.Values.toolbarHorizontalMargin
readonly property int rowSpace: root.width - (root.rowSpacing * (root.numColumns + 1))
- root.style.squareControlSize.width
property int rowWidth: root.rowSpace / root.numColumns
property int rowRest: root.rowSpace % root.numColumns
data: [ data: [
PropertiesDialog { PropertiesDialog {
id: dialog id: dialog
visible: false visible: false
backend: listView.model.delegate backend: root.model.delegate
} }
] ]
delegate: Item { delegate: Rectangle {
id: itemDelegate
width: 600 required property int index
height: 18
required property string target
required property string name
required property string type
required property string value
width: ListView.view.width
height: root.style.squareControlSize.height
color: mouseArea.containsMouse ?
itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
: root.style.background.hover
: "transparent"
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
property int currentIndex: listView.currentIndex property int currentIndex: root.currentIndex
Connections { Connections {
target: mouseArea target: mouseArea
function onClicked() { function onClicked() {
listView.model.currentIndex = index root.model.currentIndex = itemDelegate.index
listView.currentIndex = index root.currentIndex = itemDelegate.index
dialog.backend.currentRow = index
dialog.popup(mouseArea) dialog.popup(mouseArea)
} }
} }
} }
Row { Row {
id: row1 id: row
x: 0
y: 0
width: 600
height: 16
spacing: 10
height: itemDelegate.height
spacing: root.rowSpacing
property color textColor: itemDelegate.ListView.isCurrentItem ? root.style.text.selectedText
: root.style.icon.idle
Text { Text {
width: 120 width: root.rowWidth + root.rowRest
color: "#ffffff" height: itemDelegate.height
text: target ?? "" color: row.textColor
anchors.verticalCenter: parent.verticalCenter text: itemDelegate.target ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
leftPadding: root.rowSpacing
} }
Text { Text {
width: 120 width: root.rowWidth
text: name ?? "" height: itemDelegate.height
color: "#ffffff" color: row.textColor
anchors.verticalCenter: parent.verticalCenter text: itemDelegate.name ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Text {
width: 120 width: root.rowWidth + root.rowRest
text: type ?? "" height: itemDelegate.height
anchors.verticalCenter: parent.verticalCenter color: row.textColor
color: "#ffffff" text: itemDelegate.type ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Text {
width: 120 width: root.rowWidth + root.rowRest
text: value ?? "" height: itemDelegate.height
anchors.verticalCenter: parent.verticalCenter color: row.textColor
color: "#ffffff" text: itemDelegate.value ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false font.bold: false
elide: Text.ElideMiddle
} }
Text { Rectangle {
width: 120 width: root.style.squareControlSize.width
height: root.style.squareControlSize.height
text: "-" color: toolTipArea.containsMouse ?
anchors.verticalCenter: parent.verticalCenter itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
horizontalAlignment: Text.AlignRight : root.style.background.hover
font.pointSize: 14 : "transparent"
color: "#ffffff"
font.bold: true Text {
MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: listView.model.remove(index)
text: StudioTheme.Constants.remove_medium
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: root.style.baseIconFontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: row.textColor
renderType: Text.QtRendering
}
HelperWidgets.ToolTipArea {
id: toolTipArea
tooltip: qsTr("This is a test.")
anchors.fill: parent
onClicked: root.model.remove(itemDelegate.index)
} }
} }
} }
} }
highlight: Rectangle { highlight: Rectangle {
color: "#2a5593" color: root.style.interaction
width: 600 width: 600
} }
} }

View File

@@ -0,0 +1,252 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend
Column {
id: root
property int actionType
property int horizontalSpacing
property int columnWidth
property var statement
//implicitWidth: Math.max(16, container.childrenRect.width + container.childrenRect.x)
//implicitHeight: Math.max(16, container.childrenRect.height + container.childrenRect.y)
// Call Function
Row {
visible: root.actionType === ConnectionModelStatementDelegate.CallFunction
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("Item") ; tooltip: qsTr("The target item of the function.")}
PopupLabel { text: qsTr("Method") ; tooltip: qsTr("The name of the function.")}
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.CallFunction
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: functionId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: root.statement.function.id.model ?? 0
onActivated: backend.okStatement.function.id.activateIndex(functionId.currentIndex)
property int currentTypeIndex: backend.okStatement.function.id.currentIndex ?? 0
onCurrentTypeIndexChanged: functionId.currentIndex = functionId.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: functionName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: root.statement.function.name.model ?? 0
onActivated: root.statement.function.name.activateIndex(functionName.currentIndex)
property int currentTypeIndex: root.statement.function.name.currentIndex ?? 0
onCurrentTypeIndexChanged: functionName.currentIndex = functionName.currentTypeIndex
}
}
// Assign
Row {
visible: root.actionType === ConnectionModelStatementDelegate.Assign
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("From") ; tooltip: qsTr("The Property to assign from.")}
PopupLabel { text: qsTr("To"); tooltip: qsTr("The Property to assign to.") }
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.Assign
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: rhsAssignmentId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//from - rhs - id
model: root.statement.rhsAssignment.id.model ?? 0
onActivated: root.statement.rhsAssignment.id.activateIndex(rhsAssignmentId.currentIndex)
property int currentTypeIndex: root.statement.rhsAssignment.id.currentIndex ?? 0
onCurrentTypeIndexChanged: rhsAssignmentId.currentIndex = rhsAssignmentId.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: lhsAssignmentId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//to lhs - id
model: root.statement.lhs.id.model ?? 0
onActivated: root.statement.lhs.id.activateIndex(lhsAssignmentId.currentIndex)
property int currentTypeIndex: root.statement.lhs.id.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsAssignmentId.currentIndex = lhsAssignmentId.currentTypeIndex
}
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.Assign
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: rhsAssignmentName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//from - rhs - name
model: root.statement.rhsAssignment.name.model ?? 0
onActivated: root.statement.rhsAssignment.name.activateIndex(rhsAssignmentName.currentIndex)
property int currentTypeIndex: root.statement.rhsAssignment.name.currentIndex ?? 0
onCurrentTypeIndexChanged: rhsAssignmentName.currentIndex = rhsAssignmentName.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: lhsAssignmentName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//to lhs - name
model: root.statement.lhs.name.model ?? 0
onActivated: root.statement.lhs.name.activateIndex(lhsAssignmentName.currentIndex)
property int currentTypeIndex: root.statement.lhs.name.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsAssignmentName.currentIndex = lhsAssignmentName.currentTypeIndex
}
}
// Change State
Row {
visible: root.actionType === ConnectionModelStatementDelegate.ChangeState
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("State Group"); tooltip: qsTr("The State Group.") }
PopupLabel { text: qsTr("State"); tooltip: qsTr("The State .") }
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.ChangeState
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: stateGroups
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: root.statement.stateTargets.model ?? 0
onActivated: root.statement.stateTargets.activateIndex(stateGroups.currentIndex)
property int currentTypeIndex: root.statement.stateTargets.currentIndex ?? 0
onCurrentTypeIndexChanged: stateGroups.currentIndex = stateGroups.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: states
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: root.statement.states.model ?? 0
onActivated: root.statement.states.activateIndex(states.currentIndex)
property int currentTypeIndex: root.statement.states.currentIndex ?? 0
onCurrentTypeIndexChanged: states.currentIndex = states.currentTypeIndex
}
}
// Set Property
Row {
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("Item"); tooltip: qsTr("The Item.")}
PopupLabel { text: qsTr("Property"); tooltip: qsTr("The property of the item.")}
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: lhsPropertyId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: root.statement.lhs.id.model ?? 0
onActivated: root.statement.lhs.id.activateIndex(lhsPropertyId.currentIndex)
property int currentTypeIndex: root.statement.lhs.id.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsPropertyId.currentIndex = lhsPropertyId.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: lhsPropertyName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: root.statement.lhs.name.model ?? 0
onActivated: root.statement.lhs.name.activateIndex(lhsPropertyName.currentIndex)
property int currentTypeIndex: root.statement.lhs.name.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsPropertyName.currentIndex = lhsPropertyName.currentTypeIndex
}
}
PopupLabel {
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
text: qsTr("Value")
}
StudioControls.TextField {
id: setPropertyArgument
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
width: root.width
actionIndicatorVisible: false
translationIndicatorVisible: false
text: root.statement.stringArgument.text ?? ""
onEditingFinished: {
root.statement.stringArgument.activateText(setPropertyArgument.text)
}
}
// Print Message
PopupLabel {
visible: root.actionType === ConnectionModelStatementDelegate.PrintMessage
text: qsTr("Message")
tooltip: qsTr("The message that is printed.")
}
StudioControls.TextField {
id: messageString
visible: root.actionType === ConnectionModelStatementDelegate.PrintMessage
width: root.width
actionIndicatorVisible: false
translationIndicatorVisible: false
text: root.statement.stringArgument.text ?? ""
onEditingFinished: {
root.statement.stringArgument.activateText(messageString.text)
}
}
// Custom
PopupLabel {
visible: root.actionType === ConnectionModelStatementDelegate.Custom
text: qsTr("Custom Connections can only be edited with the binding editor")
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 30
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
}

View File

@@ -0,0 +1,303 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls as Controls
import HelperWidgets as HelperWidgets
import StudioTheme as StudioTheme
import StudioControls as StudioControls
import ConnectionsEditorEditorBackend
Controls.Popup {
id: root
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property var listModel: ConnectionsEditorEditorBackend.connectionModel.delegate.propertyListProxyModel
property var treeModel: ConnectionsEditorEditorBackend.connectionModel.delegate.propertyTreeModel
signal select(var value)
signal entered(var value)
signal exited(var value)
property alias searchActive: search.activeFocus
property bool showOperators: false
property alias operatorModel: repeater.model
function reset() {
search.clear()
stack.pop(null, Controls.StackView.Immediate)
root.listModel.reset()
}
closePolicy: Controls.Popup.CloseOnEscape | Controls.Popup.CloseOnPressOutsideParent
padding: 0
focus: search.activeFocus
background: Rectangle {
implicitWidth: root.width
color: root.style.background.idle
border {
color: root.style.border.idle
width: root.style.borderWidth
}
}
contentItem: Column {
StudioControls.SearchBox {
id: search
width: parent.width
visible: !root.showOperators
onSearchChanged: function(value) {
root.treeModel.setFilter(value)
}
}
Controls.StackView {
id: stack
visible: !root.showOperators
width: parent.width
height: currentItem?.implicitHeight
clip: true
initialItem: mainView
}
Component {
id: mainView
Column {
Rectangle {
width: stack.width
height: 30
visible: root.listModel.parentName !== ""
color: backMouseArea.containsMouse ? "#4DBFFF" : "transparent"
MouseArea {
id: backMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
stack.pop(Controls.StackView.Immediate)
root.listModel.goUp() //treeModel.pop()
}
}
Row {
anchors.fill: parent
Item {
width: 30
height: 30
Text {
id: chevronLeft
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: root.style.baseIconFontSize
color: backMouseArea.containsMouse ? "#111111" : "white" // TODO colors
text: StudioTheme.Constants.back_medium
anchors.centerIn: parent
}
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: root.listModel.parentName
color: backMouseArea.containsMouse ? "#111111" : "white" // TODO colors
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
}
}
Rectangle {
width: stack.width - 8
height: 1
visible: root.listModel.parentName !== ""
color: "#3C3C3C"
anchors.horizontalCenter: parent.horizontalCenter
}
ListView {
id: listView
visible: search.empty
width: stack.width
implicitHeight: Math.min(180, childrenRect.height)
clip: true
model: root.listModel
HoverHandler { id: listViewHoverHandler }
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: HelperWidgets.ScrollBar {
id: listScrollBar
parent: listView
x: listView.width - listScrollBar.width
y: 0
height: listView.availableHeight
orientation: Qt.Vertical
show: (listViewHoverHandler.hovered || listView.focus || listScrollBar.inUse)
&& listScrollBar.isNeeded
}
delegate: MyListViewDelegate {
id: listViewDelegate
required property int index
required property string propertyName
required property int childCount
required property string expression
text: listViewDelegate.propertyName
implicitWidth: listView.width
onClicked: {
if (!listViewDelegate.childCount) {
root.select(listViewDelegate.expression)
return
}
stack.push(mainView, Controls.StackView.Immediate)
ListView.view.model.goInto(listViewDelegate.index)
}
onHoveredChanged: {
if (listViewDelegate.childCount)
return
if (listViewDelegate.hovered)
root.entered(listViewDelegate.expression)
else
root.exited(listViewDelegate.expression)
}
}
}
TreeView {
id: treeView
visible: !search.empty
width: stack.width
implicitHeight: Math.min(180, childrenRect.height)
clip: true
model: root.treeModel
HoverHandler { id: treeViewHoverHandler }
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: HelperWidgets.ScrollBar {
id: treeScrollBar
parent: treeView
x: treeView.width - treeScrollBar.width
y: 0
height: treeView.availableHeight
orientation: Qt.Vertical
show: (treeViewHoverHandler.hovered || treeView.focus || treeScrollBar.inUse)
&& treeScrollBar.isNeeded
}
onLayoutChanged: function() {
treeView.expand(0)
}
rowHeightProvider: function(row) {
return (row <= 0) ? 0 : -1
}
delegate: MyTreeViewDelegate {
id: treeViewDelegate
required property int index
required property string propertyName
required property int childCount
required property string expression
text: treeViewDelegate.propertyName
implicitWidth: treeView.width
onClicked: {
if (!treeViewDelegate.childCount)
root.select(treeViewDelegate.expression)
else
treeView.toggleExpanded(treeViewDelegate.index)
}
onHoveredChanged: {
if (treeViewDelegate.childCount)
return
if (treeViewDelegate.hovered)
root.entered(treeViewDelegate.expression)
else
root.exited(treeViewDelegate.expression)
}
}
}
}
}
Item {
visible: root.showOperators
width: stack.width
height: flow.childrenRect.height + 2 * StudioTheme.Values.flowMargin
Flow {
id: flow
anchors.fill: parent
anchors.margins: StudioTheme.Values.flowMargin
spacing: StudioTheme.Values.flowSpacing
Repeater {
id: repeater
Rectangle {
id: delegate
required property int index
required property string name
required property string value
required property string tooltip
width: textItem.contentWidth + 2 * StudioTheme.Values.flowPillMargin
height: StudioTheme.Values.flowPillHeight
color: "#161616"
radius: StudioTheme.Values.flowPillRadius
border {
color: "white"
width: mouseArea.containsMouse ? 1 : 0
}
HelperWidgets.ToolTipArea {
id: mouseArea
hoverEnabled: true
anchors.fill: parent
tooltip: delegate.tooltip
onClicked: root.select(delegate.value)
}
Text {
id: textItem
font.pixelSize: StudioTheme.Values.baseFontSize
color: StudioTheme.Values.themeTextColor
text: delegate.name
anchors.centerIn: parent
}
}
}
}
}
}
}

View File

@@ -2,79 +2,163 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates as T
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
Button { T.TabButton {
id: control id: control
implicitWidth: Math.max( property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
buttonBackground ? buttonBackground.implicitWidth : 0,
textItem.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(
buttonBackground ? buttonBackground.implicitHeight : 0,
textItem.implicitHeight + topPadding + bottomPadding)
leftPadding: 4
rightPadding: 4
text: "My Button" property alias tooltip: toolTipArea.tooltip
property alias buttonIcon: buttonIcon.text
background: buttonBackground width: control.style.squareControlSize.width + buttonLabel.implicitWidth
Rectangle { + buttonLabel.leftPadding + buttonLabel.rightPadding
id: buttonBackground height: control.style.squareControlSize.height
color: "#047eff"
implicitWidth: 100 contentItem: Row {
implicitHeight: 40 spacing: 0
opacity: enabled ? 1 : 0.3
radius: 12 Text {
border.color: "#047eff" id: buttonIcon
width: control.style.squareControlSize.width
height: control.height
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: control.style.baseIconFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Text {
id: buttonLabel
height: control.height
rightPadding: 4
font.pixelSize: control.style.baseFontSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: control.text
}
} }
contentItem: textItem background: Rectangle {
Text { id: controlBackground
id: textItem color: control.style.background.idle
text: control.text border.color: control.style.border.idle
border.width: control.style.borderWidth
radius: StudioTheme.Values.smallRadius //control.style.radius
}
opacity: enabled ? 1.0 : 0.3 HelperWidgets.ToolTipArea {
color: "#ffffff" id: toolTipArea
horizontalAlignment: Text.AlignHCenter anchors.fill: parent
verticalAlignment: Text.AlignVCenter // Without setting the acceptedButtons property the clicked event won't
// reach the AbstractButton, it will be consumed by the ToolTipArea
acceptedButtons: Qt.NoButton
} }
states: [ states: [
State { State {
name: "normal" name: "default"
when: !control.down && !control.checked when: control.enabled && !control.hovered && !control.pressed && !control.checked
PropertyChanges { PropertyChanges {
target: buttonBackground target: controlBackground
visible: false color: control.style.background.idle
color: "#00000000" border.color: control.style.border.idle
border.color: "#047eff"
} }
PropertyChanges { PropertyChanges {
target: textItem target: buttonIcon
color: "#ffffff" color: control.style.icon.idle
}
PropertyChanges {
target: buttonLabel
color: control.style.icon.idle
} }
}, },
State { State {
name: "down" name: "hover"
when: control.down && !control.checked when: control.enabled && control.hovered && !control.pressed && !control.checked
PropertyChanges { PropertyChanges {
target: textItem target: controlBackground
color: "#ffffff" color: control.style.background.hover
border.color: control.style.border.hover
} }
PropertyChanges { PropertyChanges {
target: buttonBackground target: buttonIcon
color: "#047eff" color: control.style.icon.hover
border.color: "#00000000" }
PropertyChanges {
target: buttonLabel
color: control.style.icon.hover
} }
}, },
State { State {
name: "down1" name: "hoverCheck"
when: control.checked when: control.enabled && control.hovered && !control.pressed && control.checked
extend: "down" PropertyChanges {
target: controlBackground
color: control.style.interactionHover
border.color: control.style.interactionHover
}
PropertyChanges {
target: buttonIcon
color: control.style.text.selectedText
}
PropertyChanges {
target: buttonLabel
color: control.style.text.selectedText
}
},
State {
name: "pressed"
when: control.enabled && control.hovered && control.pressed
PropertyChanges {
target: controlBackground
color: control.style.interaction
border.color: control.style.interaction
}
PropertyChanges {
target: buttonIcon
color: control.style.icon.interaction
}
PropertyChanges {
target: buttonLabel
color: control.style.icon.interaction
}
},
State {
name: "check"
when: control.enabled && !control.pressed && control.checked
extend: "hoverCheck"
PropertyChanges {
target: controlBackground
color: control.style.interaction
border.color: control.style.interaction
}
},
State {
name: "pressedButNotHovered"
when: control.enabled && !control.hovered && control.pressed
extend: "hover"
},
State {
name: "disable"
when: !control.enabled
PropertyChanges {
target: controlBackground
color: control.style.background.disabled
border.color: control.style.border.disabled
}
PropertyChanges {
target: buttonIcon
color: control.style.icon.disabled
}
PropertyChanges {
target: buttonLabel
color: control.style.icon.disabled
}
} }
] ]
} }

View File

@@ -26,7 +26,7 @@ StudioControls.Menu {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Add an instance") text: qsTr("Add an instance")
enabled: root.targetAvailable enabled: root.targetAvailable && ContentLibraryBackend.rootView.hasActive3DScene
onTriggered: ContentLibraryBackend.effectsModel.addInstance(root.targetItem) onTriggered: ContentLibraryBackend.effectsModel.addInstance(root.targetItem)
} }

View File

@@ -1,186 +1,284 @@
{ [
"ContextMenuArea": { {
"size": "28x28", "ContextMenuArea": {
"Off": { "size": "28x28",
"Disabled": { "color": "DStextColorDisabled" }, "Off": {
"Hovered": { "color": "DSpanelBackground" }, "Disabled": { "color": "DStextColorDisabled" },
"Normal": { "color": "DStextColor" }, "Hovered": { "color": "DSpanelBackground" },
"Selected": { "color": "DStextSelectedTextColor" } "Normal": { "color": "DStextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
},
"On": {
"Disabled": { "color": "DStextColorDisabled" },
"Hovered": { "color": "DSsubPanelBackground" },
"Normal": { "color": "DStextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
}
}, },
"On": { "AddMouseAreaIcon": {
"Disabled": { "color": "DStextColorDisabled" }, "iconName": "mouseArea_small"
"Hovered": { "color": "DSsubPanelBackground" }, },
"Normal": { "color": "DStextColor" }, "AlignCameraToViewIcon": {
"Selected": { "color": "DStextSelectedTextColor" } "iconName": "alignToCamera_small"
},
"AlignViewToCameraIcon": {
"iconName": "alignToObject_small"
},
"AnchorsIcon": {
"iconName": "anchors_small"
},
"AnnotationIcon": {
"iconName": "annotations_small"
},
"ArrangeIcon": {
"iconName": "arrange_small"
},
"BackspaceIcon": {
"iconName": "backspace_small"
},
"CameraIcon": {
"iconName": "camera_small"
},
"CameraOrthographicIcon": {
"iconName": "orthCam_small"
},
"CameraPerspectiveIcon": {
"iconName": "perspectiveCam_small"
},
"ConnectionsIcon": {
"iconName": "connection_small"
},
"CopyIcon": {
"iconName": "copy_small"
},
"CreateIcon": {
"iconName": "create_small"
},
"DeleteIcon": {
"iconName": "delete_small"
},
"DuplicateIcon": {
"iconName": "duplicate_small"
},
"EditComponentIcon": {
"iconName": "editComponent_small"
},
"EditIcon": {
"iconName": "edit_small"
},
"EnterComponentIcon": {
"iconName": "editComponent_small"
},
"EventListIcon": {
"iconName": "events_small"
},
"FitSelectedIcon": {
"iconName": "fitSelected_small"
},
"GroupSelectionIcon": {
"iconName": "group_small"
},
"ImportedModelsIcon": {
"iconName": "importedModels_small"
},
"LayoutsIcon": {
"iconName": "layouts_small"
},
"LightIcon": {
"Off": {
"iconName": "editLightOff_medium"
},
"On": {
"iconName": "editLightOn_medium"
}
},
"LightDirectionalIcon": {
"iconName": "directionalLight_small"
},
"LightPointIcon": {
"iconName": "pointLight_small"
},
"LightSpotIcon": {
"iconName": "spotLight_small"
},
"MakeComponentIcon": {
"iconName": "createComponent_small"
},
"MaterialIcon": {
"iconName": "material_medium"
},
"MergeWithTemplateIcon": {
"iconName": "merge_small"
},
"MinimalDownArrowIcon" : {
"iconName": "upDownSquare2"
},
"ModelConeIcon": {
"iconName": "cone_small"
},
"ModelCubeIcon": {
"iconName": "cube_small"
},
"ModelCylinderIcon": {
"iconName": "cylinder_small"
},
"ModelPlaneIcon": {
"iconName": "plane_small"
},
"ModelSphereIcon": {
"iconName": "sphere_small"
},
"ParentIcon": {
"iconName": "selectParent_small"
},
"PasteIcon": {
"iconName": "paste_small"
},
"PositionsersIcon": {
"iconName": "positioners_small"
},
"PrimitivesIcon": {
"iconName": "cube_small"
},
"ResetViewIcon": {
"iconName": "reload_medium"
},
"SelecionIcon": {
"iconName": "selection_small"
},
"ShowBoundsIcon": {
"Off": {
"iconName": "visibilityOff"
},
"On": {
"iconName": "visibilityOn"
}
},
"SnappingIcon": {
"iconName": "snapping_small"
},
"SimpleCheckIcon": {
"Off": {
"iconName": "transparent"
},
"On": {
"iconName": "tickMark_small"
}
},
"TimelineIcon": {
"iconName": "timeline_small"
},
"ToggleGroupIcon": {
"Off": {
"iconName": "selectOutline_medium"
},
"On": {
"iconName": "selectFill_medium"
}
},
"VisibilityIcon": {
"Off": {
"iconName": "visibilityOff"
},
"On": {
"iconName": "visibilityOn"
}
} }
}, },
"AddMouseAreaIcon": { {
"iconName": "mouseArea_small" "ToolbarArea": {
}, "size": "32x32",
"AlignCameraToViewIcon": { "Off": {
"iconName": "alignToCamera_small" "Disabled": { "color": "DStoolbarIcon_blocked" },
}, "Hovered": { "color": "DSiconColor" },
"AlignViewToCameraIcon": { "Normal": { "color": "DSiconColor" },
"iconName": "alignToObject_small" "Selected": { "color": "DStextSelectedTextColor" }
}, },
"AnchorsIcon": { "On": {
"iconName": "anchors_small" "Disabled": { "color": "DStoolbarIcon_blocked" },
}, "Hovered": { "color": "DStextSelectedTextColor" },
"AnnotationIcon": { "Normal": { "color": "DStextSelectedTextColor" },
"iconName": "annotations_small" "Selected": { "color": "DStextSelectedTextColor" }
}, }
"ArrangeIcon": {
"iconName": "arrange_small"
},
"BackspaceIcon": {
"iconName": "backspace_small"
},
"CameraIcon": {
"iconName": "camera_small"
},
"CameraOrthographicIcon": {
"iconName": "orthCam_small"
},
"CameraPerspectiveIcon": {
"iconName": "perspectiveCam_small"
},
"ConnectionsIcon": {
"iconName": "connection_small"
},
"CopyIcon": {
"iconName": "copy_small"
},
"CreateIcon": {
"iconName": "create_small"
},
"DeleteIcon": {
"iconName": "delete_small"
},
"DuplicateIcon": {
"iconName": "duplicate_small"
},
"EditComponentIcon": {
"iconName": "editComponent_small"
},
"EditIcon": {
"iconName": "edit_small"
},
"EnterComponentIcon": {
"iconName": "editComponent_small"
},
"EventListIcon": {
"iconName": "events_small"
},
"FitSelectedIcon": {
"iconName": "fitSelected_small"
},
"GroupSelectionIcon": {
"iconName": "group_small"
},
"ImportedModelsIcon": {
"iconName": "importedModels_small"
},
"LayoutsIcon": {
"iconName": "layouts_small"
},
"LightIcon": {
"Off": {
"iconName": "editLightOff_medium"
}, },
"On": { "AlignCameraToViewIcon": {
"iconName": "editLightOn_medium" "iconName": "alignToCam_medium"
}
},
"LightDirectionalIcon": {
"iconName": "directionalLight_small"
},
"LightPointIcon": {
"iconName": "pointLight_small"
},
"LightSpotIcon": {
"iconName": "spotLight_small"
},
"MakeComponentIcon": {
"iconName": "createComponent_small"
},
"MaterialIcon": {
"iconName": "material_medium"
},
"MergeWithTemplateIcon": {
"iconName": "merge_small"
},
"MinimalDownArrowIcon" : {
"iconName": "upDownSquare2"
},
"ModelConeIcon": {
"iconName": "cone_small"
},
"ModelCubeIcon": {
"iconName": "cube_small"
},
"ModelCylinderIcon": {
"iconName": "cylinder_small"
},
"ModelPlaneIcon": {
"iconName": "plane_small"
},
"ModelSphereIcon": {
"iconName": "sphere_small"
},
"ParentIcon": {
"iconName": "selectParent_small"
},
"PasteIcon": {
"iconName": "paste_small"
},
"PositionsersIcon": {
"iconName": "positioners_small"
},
"PrimitivesIcon": {
"iconName": "cube_small"
},
"ResetViewIcon": {
"iconName": "reload_medium"
},
"SelecionIcon": {
"iconName": "selection_small"
},
"ShowBoundsIcon": {
"Off": {
"iconName": "visibilityOff"
}, },
"On": { "AlignViewToCameraIcon": {
"iconName": "visibilityOn" "iconName": "alignToView_medium"
}
},
"SnappingIcon": {
"iconName": "snapping_small"
},
"SimpleCheckIcon": {
"Off": {
"iconName": "transparent"
}, },
"On": { "CameraIcon": {
"iconName": "tickMark_small" "Off": {
} "iconName": "orthCam_small"
}, },
"TimelineIcon": { "On": {
"iconName": "timeline_small" "iconName": "perspectiveCam_small"
}, }
"ToggleGroupIcon": {
"Off": {
"iconName": "selectOutline_medium"
}, },
"On": { "EditColorIcon": {
"iconName": "selectFill_medium" "iconName": "colorSelection_medium"
}
},
"VisibilityIcon": {
"Off": {
"iconName": "visibilityOff"
}, },
"On": { "EditLightIcon": {
"iconName": "visibilityOn" "Off": {
"iconName": "editLightOff_medium"
},
"On": {
"iconName": "editLightOn_medium"
}
},
"FitToViewIcon": {
"iconName": "fitToView_medium"
},
"LocalOrientIcon": {
"iconName": "localOrient_medium"
},
"MoveToolIcon": {
"iconName": "move_medium"
},
"ParticlesAnimationIcon": {
"iconName": "particleAnimation_medium"
},
"ParticlesPlayIcon": {
"Off": {
"iconName": "playOutline_medium"
},
"On": {
"iconName": "pause"
}
},
"ParticlesRestartIcon": {
"iconName": "restartParticles_medium"
},
"ResetViewIcon": {
"iconName": "reload_medium"
},
"RotateToolIcon": {
"iconName": "roatate_medium"
},
"ScaleToolIcon": {
"iconName": "scale_medium"
},
"SnappingIcon": {
"iconName": "snapping_medium"
},
"SnappingConfIcon": {
"iconName": "snapping_conf_medium"
},
"ToggleGroupIcon": {
"Off": {
"iconName": "selectOutline_medium"
},
"On": {
"iconName": "selectFill_medium"
}
},
"VisibilityIcon": {
"Off": {
"iconName": "invisible_medium"
},
"On": {
"iconName": "visible_medium"
}
} }
} }
} ]

View File

@@ -0,0 +1,242 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
Rectangle {
id: root
property int toolTipDelay: 1000
width: 230
height: 270
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
Connections {
target: rootView
// Spinboxes lose the initial binding if the value changes so we need these connections
onPosIntChanged: posIntSpin.realValue = rootView.posInt
onRotIntChanged: rotIntSpin.realValue = rootView.rotInt
onScaleIntChanged: scaleIntSpin.realValue = rootView.scaleInt
}
ColumnLayout {
anchors.fill: parent
spacing: 0
RowLayout {
height: 32
Layout.topMargin: 8
Layout.rightMargin: 8
Layout.leftMargin: 8
Layout.fillWidth: true
spacing: 16
Rectangle {
width: 40
height: 40
radius: 5
Layout.fillHeight: false
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
HelperWidgets.IconIndicator {
anchors.fill: parent
icon: StudioTheme.Constants.snapping_conf_medium
pixelSize: StudioTheme.Values.myIconFontSize * 1.4
iconColor: StudioTheme.Values.themeLinkIndicatorColorHover
enabled: false
states: [] // Disable normal state based coloring
}
}
Text {
text: qsTr("Snap Configuration")
font.pixelSize: 12
horizontalAlignment: Text.AlignLeft
Layout.fillWidth: true
font.bold: true
color: StudioTheme.Values.themeTextColor
}
}
GridLayout {
Layout.margins:10
Layout.fillWidth: true
Layout.fillHeight: true
rowSpacing: 5
columnSpacing: 5
rows: 5
columns: 3
Text {
text: qsTr("Interval")
Layout.column: 1
Layout.row: 0
Layout.leftMargin: 10
font.pixelSize: 12
font.bold: true
color: StudioTheme.Values.themeTextColor
}
StudioControls.CheckBox {
text: qsTr("Position")
Layout.column: 0
Layout.row: 1
Layout.minimumWidth: 100
checked: rootView.posEnabled
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap position.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.posEnabled = checked
}
StudioControls.RealSpinBox {
id: posIntSpin
Layout.fillWidth: true
Layout.column: 1
Layout.row: 1
Layout.leftMargin: 10
realFrom: 1
realTo: 10000
realValue: rootView.posInt
realStepSize: 1
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for move gizmo.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.posInt = realValue
}
StudioControls.CheckBox {
text: qsTr("Rotation")
Layout.column: 0
Layout.row: 2
Layout.minimumWidth: 100
checked: rootView.rotEnabled
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap rotation.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.rotEnabled = checked
}
StudioControls.RealSpinBox {
id: rotIntSpin
Layout.fillWidth: true
Layout.column: 1
Layout.row: 2
Layout.leftMargin: 10
realFrom: 1
realTo: 90
realValue: rootView.rotInt
realStepSize: 1
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval in degrees for rotation gizmo.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.rotInt = realValue
}
StudioControls.CheckBox {
text: qsTr("Scale")
Layout.column: 0
Layout.row: 3
Layout.minimumWidth: 100
checked: rootView.scaleEnabled
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap scale.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.scaleEnabled = checked
}
StudioControls.RealSpinBox {
id: scaleIntSpin
Layout.fillWidth: true
Layout.column: 1
Layout.row: 3
Layout.leftMargin: 10
realFrom: 1
realTo: 100
realValue: rootView.scaleInt
realStepSize: 1
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Snap interval for scale gizmo in percentage of original scale.")
ToolTip.delay: root.toolTipDelay
onRealValueChanged: rootView.scaleInt = realValue
}
StudioControls.CheckBox {
text: qsTr("Absolute Position")
Layout.fillWidth: false
Layout.leftMargin: 0
Layout.column: 0
Layout.row: 4
Layout.columnSpan: 3
checked: rootView.absolute
actionIndicatorVisible: false
hoverEnabled: true
ToolTip.visible: hovered
ToolTip.text: qsTr("Toggles if the position snaps to absolute values or relative to object position.")
ToolTip.delay: root.toolTipDelay
onToggled: rootView.absolute = checked
}
Text {
text: qsTr("deg")
font.pixelSize: 12
Layout.column: 2
Layout.row: 2
color: StudioTheme.Values.themeTextColor
}
Text {
text: qsTr("%")
font.pixelSize: 12
Layout.column: 2
Layout.row: 3
color: StudioTheme.Values.themeTextColor
}
}
HelperWidgets.Button {
text: qsTr("Reset All")
Layout.bottomMargin: 8
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
onClicked: rootView.resetDefaults()
}
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
HelperWidgets.Section {
id: root
// model properties
required property string nodeName
required property bool nodeEnabled
required property var nodeUniformsModel
required property int index
caption: root.nodeName
category: "EffectMaker"
draggable: true
fillBackground: true
showCloseButton: true
closeButtonToolTip: qsTr("Remove")
onCloseButtonClicked: {
EffectMakerBackend.effectMakerModel.removeNode(root.index)
}
showEyeButton: true
eyeEnabled: root.nodeEnabled
eyeButtonToolTip: qsTr("Enable/Disable Node")
onEyeButtonClicked: {
root.nodeEnabled = root.eyeEnabled
}
Column {
spacing: 10
Repeater {
model: root.nodeUniformsModel
EffectCompositionNodeUniform {
width: root.width
}
}
}
}

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Dialogs
import QtQuick.Layouts
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
Item {
id: root
height: layout.implicitHeight
Component.onCompleted: {
if (uniformType === "int")
valueLoader.source = "ValueInt.qml"
else if (uniformType === "vec2")
valueLoader.source = "ValueVec2.qml"
else if (uniformType === "vec3")
valueLoader.source = "ValueVec3.qml"
else if (uniformType === "vec4")
valueLoader.source = "ValueVec4.qml"
else if (uniformType === "bool")
valueLoader.source = "ValueBool.qml"
else if (uniformType === "color")
valueLoader.source = "ValueColor.qml"
else if (uniformType === "image")
valueLoader.source = "ValueImage.qml"
else if (uniformType === "define")
valueLoader.source = "ValueDefine.qml"
else
valueLoader.source = "ValueFloat.qml"
}
RowLayout {
id: layout
spacing: 20
anchors.fill: parent
Text {
text: uniformName
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize
horizontalAlignment: Text.AlignRight
Layout.maximumWidth: 140
Layout.minimumWidth: 140
Layout.preferredWidth: 140
HelperWidgets.ToolTipArea {
anchors.fill: parent
tooltip: uniformDescription
}
}
Loader {
id: valueLoader
Layout.fillWidth: true
}
}
}

View File

@@ -0,0 +1,152 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import EffectMakerBackend
Item {
id: root
property var draggedSec: null
property var secsY: []
property int moveFromIdx: 0
property int moveToIdx: 0
Column {
id: col
anchors.fill: parent
spacing: 1
EffectMakerTopBar {
}
EffectMakerPreview {
}
Rectangle {
width: parent.width
height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
EffectNodesComboBox {
mainRoot: root
anchors.verticalCenter: parent.verticalCenter
}
HelperWidgets.AbstractButton {
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.code
tooltip: qsTr("Open Shader in Code Editor")
onClicked: {} // TODO
}
}
HelperWidgets.ScrollView {
id: scrollView
width: parent.width
height: parent.height - y
clip: true
Column {
width: scrollView.width
spacing: 1
Repeater {
id: repeater
width: root.width
model: EffectMakerBackend.effectMakerModel
onCountChanged: {
HelperWidgets.Controller.setCount("EffectMaker", repeater.count)
}
delegate: EffectCompositionNode {
width: root.width
Behavior on y {
PropertyAnimation {
duration: 300
easing.type: Easing.InOutQuad
}
}
onStartDrag: (section) => {
root.draggedSec = section
root.moveFromIdx = index
highlightBorder = true
root.secsY = []
for (let i = 0; i < repeater.count; ++i)
root.secsY[i] = repeater.itemAt(i).y
}
onStopDrag: {
if (root.moveFromIdx === root.moveToIdx)
root.draggedSec.y = root.secsY[root.moveFromIdx]
else
EffectMakerBackend.effectMakerModel.moveNode(root.moveFromIdx, root.moveToIdx)
highlightBorder = false
root.draggedSec = null
}
}
} // Repeater
Timer {
running: root.draggedSec
interval: 50
repeat: true
onTriggered: {
root.moveToIdx = root.moveFromIdx
for (let i = 0; i < repeater.count; ++i) {
let currItem = repeater.itemAt(i)
if (i > root.moveFromIdx) {
if (root.draggedSec.y > currItem.y + (currItem.height - root.draggedSec.height) * .5) {
currItem.y = root.secsY[i] - root.draggedSec.height
root.moveToIdx = i
} else {
currItem.y = root.secsY[i]
}
} else if (i < root.moveFromIdx) {
if (root.draggedSec.y < currItem.y + (currItem.height - root.draggedSec.height) * .5) {
currItem.y = root.secsY[i] + root.draggedSec.height
root.moveToIdx = Math.min(root.moveToIdx, i)
} else {
currItem.y = root.secsY[i]
}
}
}
}
} // Timer
} // Column
} // ScrollView
}
Text {
id: emptyText
text: qsTr("Add an effect node to start")
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.baseFontSize
x: scrollView.x + (scrollView.width - emptyText.width) * .5
y: scrollView.y + scrollView.height * .5
visible: EffectMakerBackend.effectMakerModel.isEmpty
}
}

View File

@@ -0,0 +1,127 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Layouts
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
Column {
id: root
width: parent.width
Rectangle { // toolbar
width: parent.width
height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
RowLayout {
anchors.fill: parent
spacing: 5
anchors.rightMargin: 5
anchors.leftMargin: 5
Item {
Layout.fillWidth: true
}
HelperWidgets.AbstractButton {
enabled: previewImage.scale > .4
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.zoomOut_medium
tooltip: qsTr("Zoom out")
onClicked: {
previewImage.scale -= .2
}
}
HelperWidgets.AbstractButton {
enabled: previewImage.scale < 2
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.zoomIn_medium
tooltip: qsTr("Zoom In")
onClicked: {
previewImage.scale += .2
}
}
HelperWidgets.AbstractButton {
enabled: previewImage.scale !== 1
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.fitAll_medium
tooltip: qsTr("Zoom Fit")
onClicked: {
previewImage.scale = 1
}
}
Item {
Layout.fillWidth: true
}
Column {
Text {
text: "0.000s"
color: StudioTheme.Values.themeTextColor
font.pixelSize: 10
}
Text {
text: "0000000"
color: StudioTheme.Values.themeTextColor
font.pixelSize: 10
}
}
HelperWidgets.AbstractButton {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.toStartFrame_medium
tooltip: qsTr("Restart Animation")
onClicked: {} // TODO
}
HelperWidgets.AbstractButton {
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.topToolbar_runProject
tooltip: qsTr("Play Animation")
onClicked: {} // TODO
}
}
}
Rectangle { // preview image
id: previewImageBg
color: "#dddddd"
width: parent.width
height: 200
clip: true
Image {
id: previewImage
anchors.margins: 5
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
source: "images/qt_logo.png" // TODO: update image
Behavior on scale {
NumberAnimation {
duration: 200
easing.type: Easing.OutQuad
}
}
}
}
}

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
Rectangle {
id: root
width: parent.width
height: StudioTheme.Values.toolbarHeight
color: StudioTheme.Values.themeToolbarBackground
HelperWidgets.Button {
anchors.verticalCenter: parent.verticalCenter
x: 5
text: qsTr("Save in Library")
onClicked: {
// TODO
}
}
HelperWidgets.AbstractButton {
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 5
anchors.right: parent.right
style: StudioTheme.Values.viewBarButtonStyle
buttonIcon: StudioTheme.Constants.help
tooltip: qsTr("How to use Effect Maker:
1. Click \"+ Add Effect\" to add effect node
2. Adjust the effect nodes properties
3. Change the order of the effects, if you like
4. See the preview
5. Save in the library, if you wish to reuse the effect later") // TODO: revise with doc engineer
}
}

View File

@@ -0,0 +1,55 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Controls
import QtQuickDesignerTheme
import HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
Rectangle {
id: root
width: 140
height: 32
color: mouseArea.containsMouse ? StudioTheme.Values.themeControlBackgroundInteraction
: "transparent"
signal addEffectNode(var nodeQenPath)
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onClicked: {
root.addEffectNode(modelData.nodeQenPath)
}
}
Row {
spacing: 5
IconImage {
id: nodeIcon
width: 32
height: 32
color: StudioTheme.Values.themeTextColor
source: modelData.nodeIcon
}
Text {
text: modelData.nodeName
color: StudioTheme.Values.themeTextColor
font.pointSize: StudioTheme.Values.smallFontSize
anchors.verticalCenter: nodeIcon.verticalCenter
}
}
}

View File

@@ -0,0 +1,113 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
StudioControls.ComboBox {
id: root
actionIndicatorVisible: false
x: 5
width: parent.width - 50
model: [qsTr("+ Add Effect")]
// hide default popup
popup.width: 0
popup.height: 0
required property Item mainRoot
Connections {
target: root.popup
function onAboutToShow() {
var a = mainRoot.mapToGlobal(0, 0)
var b = root.mapToItem(mainRoot, 0, 0)
effectNodesWindow.x = a.x + b.x + root.width - effectNodesWindow.width
effectNodesWindow.y = a.y + b.y + root.height - 1
effectNodesWindow.show()
effectNodesWindow.requestActivate()
}
function onAboutToHide() {
effectNodesWindow.hide()
}
}
Window {
id: effectNodesWindow
width: row.width + 2 // 2: scrollView left and right 1px margins
height: Math.min(800, Math.min(row.height + 2, Screen.height - y - 40)) // 40: some bottom margin to cover OS bottom toolbar
flags: Qt.Popup | Qt.FramelessWindowHint
onActiveChanged: {
if (!active && !root.hover)
root.popup.close()
}
Rectangle {
anchors.fill: parent
color: StudioTheme.Values.themePanelBackground
border.color: StudioTheme.Values.themeInteraction
border.width: 1
HelperWidgets.ScrollView {
anchors.fill: parent
anchors.margins: 1
Row {
id: row
onWidthChanged: {
// Needed to update on first window showing, as row.width only gets
// correct value after the window is shown, so first showing is off
var a = mainRoot.mapToGlobal(0, 0)
var b = root.mapToItem(mainRoot, 0, 0)
effectNodesWindow.x = a.x + b.x + root.width - row.width
}
padding: 10
spacing: 10
Repeater {
model: EffectMakerBackend.effectMakerNodesModel
Column {
spacing: 10
Text {
text: categoryName
color: StudioTheme.Values.themeTextColor
font.pointSize: StudioTheme.Values.baseFontSize
}
Item { width: 1; height: 5 } // spacer
Repeater {
model: categoryNodes
EffectNode {
onAddEffectNode: (nodeQenPath) => {
EffectMakerBackend.rootView.addEffectNode(modelData.nodeQenPath)
root.popup.close()
}
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuickDesignerTheme
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
StudioControls.CheckBox {
actionIndicatorVisible: false
checked: uniformValue
onToggled: uniformValue = checked
}

View File

@@ -0,0 +1,23 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuickDesignerTheme
import HelperWidgets as HelperWidgets
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
Row {
id: itemPane
width: parent.width
spacing: 5
HelperWidgets.ColorEditor {
backendValue: uniformBackendValue
showExtendedFunctionButton: false
onValueChanged: uniformValue = convertColorToString(color)
}
}

View File

@@ -0,0 +1,25 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuickDesignerTheme
import StudioControls as StudioControls
import StudioTheme 1.0 as StudioTheme
import EffectMakerBackend
Row {
width: parent.width
StudioControls.TextField {
id: textField
width: parent.width - 20
actionIndicatorVisible: false
translationIndicatorVisible: false
text: uniformValue
onEditingFinished: uniformValue = text
}
}

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