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

This commit is contained in:
The Qt Project
2023-09-14 15:41:22 +00:00
616 changed files with 29309 additions and 14257 deletions

View File

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

View File

@@ -36,8 +36,6 @@ qtc_link_with_qt()
option(WITH_TESTS "Build Tests" ${ENV_QTC_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(SHOW_BUILD_DATE "Show build date in about dialog" 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}
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
if (TARGET Qt6::Core5CompatPrivate)
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
features if they are available.
https://github.com/tcbrindle/span
https://github.com/martinmoene/span-lite
QtCreator/src/libs/3rdparty/span
Copyright Tristan Brindle, 2018
Copyright 2018-2021 Martin Moene
Distributed under the Boost Software License, Version 1.0.
(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)
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"
"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})
@@ -198,7 +198,9 @@ function(add_qtc_library name)
SOURCES_PREFIX ${_arg_SOURCES_PREFIX}
SOURCES ${_arg_SOURCES}
INCLUDES ${_arg_INCLUDES}
SYSTEM_INCLUDES ${_arg_SYTEM_INCLUDES}
PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES}
PUBLIC_SYSTEM_INCLUDES ${_arg_PUBLIC_SYSTEM_INCLUDES}
DEFINES ${default_defines_copy} ${_arg_DEFINES} ${TEST_DEFINES}
PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES}
DEPENDS ${_arg_DEPENDS} ${IMPLICIT_DEPENDS}
@@ -322,7 +324,7 @@ function(add_qtc_plugin target_name)
cmake_parse_arguments(_arg
"SKIP_INSTALL;INTERNAL_ONLY;SKIP_TRANSLATION;EXPORT;SKIP_PCH"
"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}
)
@@ -465,7 +467,9 @@ function(add_qtc_plugin target_name)
extend_qtc_target(${target_name}
INCLUDES ${_arg_INCLUDES}
SYSTEM_INCLUDES ${_arg_SYSTEM_INCLUDES}
PUBLIC_INCLUDES ${_arg_PUBLIC_INCLUDES}
PUBLIC_SYSTEM_INCLUDES ${_arg_PUBLIC_SYSTEM_INCLUDES}
DEFINES ${DEFAULT_DEFINES} ${_arg_DEFINES} ${TEST_DEFINES}
PUBLIC_DEFINES ${_arg_PUBLIC_DEFINES}
DEPENDS ${_arg_DEPENDS} ${_DEP_PLUGINS} ${IMPLICIT_DEPENDS}

View File

@@ -244,13 +244,13 @@ function(update_resource_files_list sources)
endforeach()
endfunction()
function(set_public_includes target includes)
function(set_public_includes target includes system)
foreach(inc_dir IN LISTS includes)
if (NOT IS_ABSOLUTE ${inc_dir})
set(inc_dir "${CMAKE_CURRENT_SOURCE_DIR}/${inc_dir}")
endif()
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}>
$<INSTALL_INTERFACE:${_IDE_HEADER_INSTALL_PATH}/${include_dir_relative_path}>
)
@@ -463,7 +463,7 @@ function(extend_qtc_target target_name)
cmake_parse_arguments(_arg
""
"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}
)
@@ -504,8 +504,10 @@ function(extend_qtc_target target_name)
PUBLIC ${_arg_PUBLIC_DEFINES}
)
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)
foreach(source IN LISTS _arg_SOURCES)

View File

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

View File

@@ -31,7 +31,7 @@
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.
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
\c {choco install conan} or \c {pip install conan} command.

View File

@@ -169,7 +169,7 @@
\section2 Debugging Tools for Windows
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
installation packages.

View File

@@ -102,21 +102,13 @@
\e{Windows}
Check whether \QC has been compiled with OpenGL/Desktop, or ANGLE as
a backend. The official binaries are always built with ANGLE (a library that
maps OpenGL ES API to DirectX).
By default Qt Quick uses Direct3D 11. 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.
\list
\li ANGLE backend: This requires a Windows version newer than Windows XP.
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
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}
for details.
\e{Unix}

View File

@@ -83,7 +83,7 @@
The data is transmitted to the backend storage using an encrypted
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

View File

@@ -22,10 +22,10 @@
\endlist
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
\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.
You can connect embedded devices to the development PC to run, debug, and

View File

@@ -54,7 +54,7 @@
\section2 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.
\section2 Specifying MCU Settings

View File

@@ -376,7 +376,7 @@
the C++20 committee draft. It is compatible with C++11, but will use
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}
{Boost Software License, Version 1.0}.
@@ -384,7 +384,7 @@
The source code can be found here:
\list
\li \l{https://github.com/tcbrindle/span}
\li \l{https://github.com/martinmoene/span-lite}
\li QtCreator/src/libs/3rdparty/span
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/span}
\endlist
@@ -394,180 +394,6 @@
Roberto Raggi <roberto.raggi@gmail.com>\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)}
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}
\endlist
\li \b{three.js}
Copyright (C) 2010-2015 three.js authors
MIT License.
share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication
\li \b{OpenSSL}
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
\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
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
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
available in \QC. If it does not, you must add the kits yourself to tell
\QC where everything is.

View File

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

View File

@@ -19,10 +19,10 @@
\endlist
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
\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.
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
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 >
\uicontrol Kits > \uicontrol Compilers.

View File

@@ -28,7 +28,7 @@
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
to a Qt that the system installed with some other package
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
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
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.
\section1 Minimum Requirements

View File

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

View File

@@ -83,8 +83,8 @@
\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
\e Main.qml for editing. You can use the \l {Installing Qt}
{Qt Maintenance Tool} to install Qt Virtual Keyboard.
\e Main.qml for editing. You can use \l {Installing Qt}
{\QMT} to install Qt Virtual Keyboard.
\li Select \uicontrol Next to open the \uicontrol {Kit Selection}
dialog.

View File

@@ -119,6 +119,9 @@
name of the main QML file in the Qt Quick UI project.
\li Select \uicontrol Build > \uicontrol Run to build and run your
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
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
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
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}.
\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
@@ -183,7 +198,7 @@
\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
the \uicontrol {Clean Repository} dialog. Ignored files are deselected by
default. Select the files to delete, and then select \uicontrol Delete.
@@ -465,15 +480,6 @@
\li Show the commit in the diff editor.
\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
To work with remote repositories, select the commands in \uicontrol Tools >

View File

@@ -39,7 +39,7 @@
\section1 Setting Up the Development Environment
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.
\section2 Setting Up Qt for WebAssembly
@@ -47,7 +47,7 @@
To set up Qt for WebAssembly:
\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}).
\li Check out a known-good Emscripten version supported by the Qt for
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
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/}
{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/}
{released \QC version} or a \l{https://download.qt.io/snapshots/qtcreator/}
{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
more components.
\include qtquick-mcu-support.qdocinc mcu qtquick components
\section1 Merging Files with Templates
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
/*!
\previouspage studio-on-mcus.html
\previouspage studio-mcu-framework.html
\page studio-compatibility-with-mcu-sdks.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
\page studio-features-on-mcu-projects.html
\nextpage studio-help.html
\nextpage studio-projects-for-mcus.html
\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
\page studio-on-mcus.html
\nextpage studio-compatibility-with-mcu-sdks.html
\nextpage studio-mcu-framework.html
\title \QDS on MCUs
\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).
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:
\table
\row
\li \image qds-front-gs.png
\li With \QDS, you can use subsets of components to create UIs
for devices that are powered by microcontroller units (MCU). Use
the \uicontrol {\QMCU} preset in the \QDS wizard to set up a new
\QMCU project. Using the \uicontrol {\QMCU} preset creates an
application that utilizes a subset of the default components that
you can deploy, run, and debug on MCU boards.
\endtable
\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
\li \l {\QMCU Framework}
\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
further functionality to your applications and utilize the \l {Prototyping}
{prototyping} features of \QDS to simulate and validate interactions and
their dynamic behavior.
Lists how the \QDS versions match with particular \QMCU SDKs.
\li \l {\QDS Features on MCU Projects}
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}.
Specifies how the \QDS features are supported for developing MCU projects.
\li \l {Creating Projects for MCUs}
\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
develop applications. Designers can use the views in the Design mode to modify
UI files (.ui.qml), whereas developers 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}.
Provides an overview of how to create UIs for MCUs from a technical
artist/designer perspective. Also, offers links to detailed instructions
for designing UIs for specific MCU target devices.
\li \l {Developing applications for MCUs}
\section1 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
Provides an overview of how to develop, prototype, validate, and
implement applications for MCUs from a GUI/application developer
perspective.
\li \l {Connecting MCUs with Qt Creator}
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
the available modules in \QDS later. You can also import a module as
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
\li \uicontrol Alias
\li Exports the component generated from this layer as an alias in the

View File

@@ -21,7 +21,7 @@
\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.
\table

View File

@@ -10,7 +10,7 @@
\QBPS is included in the
\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:
\list

View File

@@ -187,8 +187,22 @@
Components 1.0, you need the import statement
\c {QtQuick.Studio.Components 1.0}. You can also import a module
as an alias.
\li In the \uicontrol {Properties} field, specify properties for
the component. You can add and modify properties in \QDS.
\li In the \uicontrol {Properties} field, 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.
\li Select the \uicontrol {Clip Contents} check box to enable clipping
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

View File

@@ -10,7 +10,7 @@
\QBSK is included in the
\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:
\list

View File

@@ -209,8 +209,22 @@
\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 can also import a module as an alias.
\li In the \uicontrol {Properties} field, specify properties for the
component. You can add and modify properties in \QDS.
\li In the \uicontrol {Properties} field, 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.
\li Select the \uicontrol Alias check box to export the item generated
from this layer as an alias in the parent component.
\li Select the \uicontrol Clip check box to enable clipping in the

View File

@@ -10,7 +10,7 @@
\QBXD is included in the
\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:
\list

View File

@@ -114,15 +114,21 @@
you need the import statement \c {QtQuick.Studio.Components 1.0}.
You can also import a module as an alias.
\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.
Following are few examples of properties:
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 In the \uicontrol {Snippet} field, specify component to be added as child under this
component.
Following example adds a Connection component:
@@ -134,6 +140,7 @@
\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.
\li Select the \uicontrol Clip check box to enable clipping in the
component generated from the layer. The generated component will clip
its own painting, as well as the painting of its children, to its

View File

@@ -24,7 +24,7 @@
\li \l {Installation}
\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}
Follow a set of hands-on tutorials that illustrate how to use the

View File

@@ -3,7 +3,7 @@
/*!
\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
\title Help

View File

@@ -8,15 +8,15 @@
\title Installation
You can install \QDS either using a stand-alone installation package or the
Qt online installer. The installers copy all the modules and tools you need
You can install \QDS either using a stand-alone installation package or \QOI.
The installers copy all the modules and tools you need
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
systems. For more information, see \l{Supported Platforms}.
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
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}.
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
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.
\list 1
\li Start the Qt online installer.
\li Start \QOI.
\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
installer to complete the installation.
\endlist

View File

@@ -51,7 +51,7 @@
\li MCU
\li Creates an application that uses a subset of default components
(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
\li {1,3} Mobile
\li Scroll

View File

@@ -33,6 +33,7 @@
\li \l{Open Documents}
\li \l{Content Library}
\li \l{Texture Editor}
\li \l{Qt Insight}
\endlist
\li \l{Managing Workspaces}
\li \l{Managing Sessions}
@@ -254,8 +255,13 @@
\li \l{Use external tools}
\li \l{\QDS on MCUs}
\list
\li \l {\QMCU Framework}
\li \l {\QDS Version Compatibility with \QMCU SDKs}
\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
\li \l Help

View File

@@ -183,7 +183,7 @@
and drag the component along the axis.
\li To move components on a plane, click the plane handle and drag the
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.
\endlist
@@ -221,6 +221,35 @@
gray handle at the center of the component.
\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
To align a camera to the \uicontrol{3D} view:
@@ -375,6 +404,16 @@
\li Toggle Edit Light On/Off
\li \key U
\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
\li \inlineimage icons/align-camera-on.png
\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
\previouspage studio-content-library.html
\nextpage creator-project-managing-workspaces.html
\nextpage studio-qt-insight.html
\title Texture Editor

View File

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

View File

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

View File

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

View File

@@ -15,6 +15,11 @@ TreeView {
boundsBehavior: Flickable.StopAtBounds
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 rootView: AssetsLibraryBackend.rootView
property var tooltipBackend: AssetsLibraryBackend.tooltipBackend
@@ -46,9 +51,18 @@ TreeView {
return -1
}
ScrollBar.vertical: HelperWidgets.VerticalScrollBar {
HoverHandler { id: hoverHandler }
ScrollBar.vertical: HelperWidgets.ScrollBar {
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
@@ -348,22 +362,21 @@ TreeView {
root.currentFilePath = filePath
}
Keys.enabled: true
Keys.onUpPressed: {
if (!root.currentFilePath)
function moveSelection(amount)
{
if (!assetsModel.haveFiles || !amount)
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 nextRow = row
let nextIndex = index
do {
if (nextRow <= root.firstRow)
return // don't select hidden rows
nextRow--
nextRow = nextRow + amount
if ((amount < 0 && nextRow < root.firstRow) || (amount > 0 && nextRow > root.lastRow))
return
nextIndex = root.__modelIndex(nextRow)
} while (assetsModel.isDirectory(nextIndex))
@@ -371,26 +384,14 @@ TreeView {
root.positionViewAtRow(nextRow, TableView.Contain)
}
Keys.enabled: true
Keys.onUpPressed: {
moveSelection(-1)
}
Keys.onDownPressed: {
if (!root.currentFilePath)
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)
moveSelection(1)
}
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
import QtQuick
import StudioTheme 1.0 as StudioTheme
import HelperWidgets as HelperWidgets
PopupDialog {
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 {
id: form
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
import QtQuick
import QtQuick.Controls
import StudioControls
import StudioControls as StudioControls
import StudioTheme as StudioTheme
Rectangle {
width: 400
height: 800
color: "#1b1b1b"
Column {
id: root
readonly property real horizontalSpacing: 10
readonly property real verticalSpacing: 16
readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
property var backend
Text {
id: text1
x: 10
y: 25
color: "#ffffff"
text: qsTr("Target")
font.pixelSize: 15
y: StudioTheme.Values.popupMargin
width: parent.width
spacing: root.verticalSpacing
Row {
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.") }
}
Text {
id: text111
x: 80
y: 25
color: "red"
text: backend.targetNode
font.pixelSize: 15
Row {
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: sourceNode
style: StudioTheme.Values.connectionPopupControlStyle
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 {
id: target
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
}
Row {
spacing: root.horizontalSpacing
Text {
id: text2
x: 13
y: 111
color: "#ffffff"
text: qsTr("Source Propety")
font.pixelSize: 15
}
StudioControls.TopLevelComboBox {
id: sourceProperty
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
TopLevelComboBox {
id: sourceNode
x: 135
y: 98
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
}
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)
property int currentTypeIndex: backend.sourceNode.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceNode.currentIndex = sourceNode.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
onActivated: backend.property.activateIndex(name.currentIndex)
property int currentTypeIndex: backend.property.currentIndex ?? 0
onCurrentTypeIndexChanged: name.currentIndex = name.currentTypeIndex
}
}
}

View File

@@ -3,121 +3,188 @@
import QtQuick
import QtQuick.Controls
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend
ListView {
id: listView
width: 606
height: 160
interactive: false
id: root
property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
property bool adsFocus: false
clip: true
interactive: true
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: {
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: {
listView.currentIndex = listView.model.currentIndex
root.currentIndex = root.model.currentIndex
}
onCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex
dialog.backend.currentRow = listView.currentIndex
root.currentIndex = root.model.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: [
BindingsDialog {
id: dialog
visible: false
backend: listView.model.delegate
backend: root.model.delegate
}
]
delegate: Item {
width: 600
height: 18
delegate: Rectangle {
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 {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
listView.model.currentIndex = index
listView.currentIndex = index
dialog.backend.currentRow = index
root.model.currentIndex = itemDelegate.index
root.currentIndex = itemDelegate.index
dialog.popup(mouseArea)
}
property int currentIndex: listView.currentIndex
}
Row {
id: row1
x: 0
y: 0
width: 600
height: 16
spacing: 10
id: row
property color textColor: itemDelegate.ListView.isCurrentItem ? root.style.text.selectedText
: root.style.icon.idle
height: itemDelegate.height
spacing: root.rowSpacing
Text {
width: 120
color: "#ffffff"
text: target ?? ""
anchors.verticalCenter: parent.verticalCenter
width: root.rowWidth + root.rowRest
height: itemDelegate.height
color: row.textColor
text: itemDelegate.target ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
leftPadding: root.rowSpacing
}
Text {
width: 120
text: targetProperty ?? ""
color: "#ffffff"
anchors.verticalCenter: parent.verticalCenter
width: root.rowWidth
height: itemDelegate.height
text: itemDelegate.targetProperty ?? ""
color: row.textColor
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
text: source ?? ""
anchors.verticalCenter: parent.verticalCenter
color: "#ffffff"
width: root.rowWidth
height: itemDelegate.height
text: itemDelegate.source ?? ""
verticalAlignment: Text.AlignVCenter
color: row.textColor
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
text: sourceProperty ?? ""
anchors.verticalCenter: parent.verticalCenter
color: "#ffffff"
width: root.rowWidth
height: itemDelegate.height
text: itemDelegate.sourceProperty ?? ""
verticalAlignment: Text.AlignVCenter
color: row.textColor
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
Rectangle {
width: root.style.squareControlSize.width
height: root.style.squareControlSize.height
text: "-"
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
font.pointSize: 14
color: "#ffffff"
font.bold: true
MouseArea {
color: toolTipArea.containsMouse ?
itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
: root.style.background.hover
: "transparent"
Text {
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 {
color: "#2a5593"
color: root.style.interaction
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
import QtQuick
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
import HelperWidgets 2.0 as HelperWidgets
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 {
y: 32
id: form
}
}

View File

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

View File

@@ -3,113 +3,178 @@
import QtQuick
import QtQuick.Controls
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend
ListView {
id: listView
width: 606
height: 160
interactive: false
id: root
property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
property bool adsFocus: false
clip: true
interactive: true
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: {
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: {
listView.currentIndex = listView.model.currentIndex
root.currentIndex = root.model.currentIndex
}
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: [
ConnectionsDialog {
id: dialog
visible: false
backend: root.model.delegate
}
]
delegate: Item {
delegate: Rectangle {
id: itemDelegate
width: 600
height: 18
required property int index
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 {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
listView.model.currentIndex = index
listView.currentIndex = index
root.model.currentIndex = itemDelegate.index
root.currentIndex = itemDelegate.index
dialog.backend.currentRow = itemDelegate.index
dialog.popup(mouseArea)
}
property int currentIndex: listView.currentIndex
}
Row {
id: row1
x: 0
y: 0
width: 600
height: 16
spacing: 10
id: row
property color textColor: itemDelegate.ListView.isCurrentItem ? root.style.text.selectedText
: root.style.icon.idle
height: itemDelegate.height
spacing: root.rowSpacing
Text {
width: 120
color: "#ffffff"
text: target
anchors.verticalCenter: parent.verticalCenter
width: root.rowWidth + root.rowRest
height: itemDelegate.height
color: row.textColor
text: itemDelegate.target
verticalAlignment: Text.AlignVCenter
font.bold: false
leftPadding: root.rowSpacing
elide: Text.ElideMiddle
}
Text {
width: 120
text: signal
color: "#ffffff"
anchors.verticalCenter: parent.verticalCenter
width: root.rowWidth
height: itemDelegate.height
text: itemDelegate.signal
color: row.textColor
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
text: action
anchors.verticalCenter: parent.verticalCenter
color: "#ffffff"
width: root.rowWidth
height: itemDelegate.height
text: itemDelegate.action
verticalAlignment: Text.AlignVCenter
color: row.textColor
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
Rectangle {
width: root.style.squareControlSize.width
height: root.style.squareControlSize.height
text: "-"
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
font.pointSize: 14
color: "#ffffff"
font.bold: true
MouseArea {
color: toolTipArea.containsMouse ?
itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
: root.style.background.hover
: "transparent"
Text {
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 {
color: "#2a5593"
width: 600
color: root.style.interaction
}
}

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.Controls
import QtQuick.Layouts
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend
Rectangle {
width: 640
height: 1080
color: "#232222"
id: root
Rectangle {
id: rectangle
x: 10
y: 10
width: 620
height: 97
color: "#333333"
color: StudioTheme.Values.themePanelBackground
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"
Column {
id: column
anchors.fill: parent
spacing: 8 // TODO
Rectangle {
id: rectangle1
x: 10
y: 10
width: 600
height: 34
color: "#00ffffff"
border.width: 1
id: toolbar
width: parent.width
height: StudioTheme.Values.doubleToolbarHeight
color: StudioTheme.Values.themeToolbarBackground
Text {
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 {
Column {
anchors.fill: parent
onClicked: {
print(ConnectionsEditorEditorBackend.dynamicPropertiesModel.delegate)
print(ConnectionsEditorEditorBackend.dynamicPropertiesModel.delegate.type)
print(ConnectionsEditorEditorBackend.dynamicPropertiesModel.delegate.type.model)
anchors.topMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.bottomMargin: StudioTheme.Values.toolbarVerticalMargin
anchors.leftMargin: StudioTheme.Values.toolbarHorizontalMargin
anchors.rightMargin: StudioTheme.Values.toolbarHorizontalMargin
spacing: StudioTheme.Values.toolbarColumnSpacing
if (connections.checked)
ConnectionsEditorEditorBackend.connectionModel.add()
else if (bindings.checked)
ConnectionsEditorEditorBackend.bindingModel.add()
else if (properties.checked)
ConnectionsEditorEditorBackend.dynamicPropertiesModel.add()
StudioControls.SearchBox {
id: searchBox
width: parent.width
style: StudioTheme.Values.searchControlStyle
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 {
visible: connections.checked
x: 17
y: 124
model: ConnectionsEditorEditorBackend.connectionModel
}
ConnectionsListView {
visible: connections.checked
width: parent.width
height: parent.height - toolbar.height - column.spacing
model: ConnectionsEditorEditorBackend.connectionModel
adsFocus: root.adsFocus
}
BindingsListView {
visible: bindings.checked
x: 17
y: 124
model: ConnectionsEditorEditorBackend.bindingModel
}
BindingsListView {
visible: bindings.checked
width: parent.width
height: parent.height - toolbar.height - column.spacing
model: ConnectionsEditorEditorBackend.bindingModel
adsFocus: root.adsFocus
}
PropertiesListView {
visible: properties.checked
x: 17
y: 124
model: ConnectionsEditorEditorBackend.dynamicPropertiesModel
PropertiesListView {
visible: properties.checked
width: parent.width
height: parent.height - toolbar.height - column.spacing
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.Controls
import HelperWidgets 2.0 as HelperWidgets
import StudioTheme 1.0 as StudioTheme
import ConnectionsEditorEditorBackend
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
flags: Qt.FramelessWindowHint || Qt.Dialog
flags: Qt.FramelessWindowHint | Qt.Dialog
color: StudioTheme.Values.themePopoutBackground
color: Qt.transparent
property int bw: 5
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()
function ensureVerticalPosition() {
if ((window.y + window.height) > (Screen.height - window.style.dialogScreenMargin)) {
window.y = (Screen.height - window.height - window.style.dialogScreenMargin)
}
}
Rectangle {
id: rectangle1
color: "#d7d7d7"
border.color: "#232323"
onHeightChanged: window.ensureVerticalPosition()
function popup(item) {
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
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 {
grabPermissions: TapHandler.CanTakeOverFromAnything
onActiveChanged: if (active) { window.startSystemMove(); }
id: dragHandler
target: null
grabPermissions: PointerHandler.CanTakeOverFromAnything
onActiveChanged: {
if (dragHandler.active)
window.startSystemMove() // QTBUG-102488
}
}
Rectangle {
id: rectangle2
x: 329
width: 16
height: 16
color: "#ffffff"
radius: 4
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 6
Row {
id: row
anchors.fill: parent
anchors.leftMargin: StudioTheme.Values.popupMargin
anchors.rightMargin: StudioTheme.Values.popupMargin
spacing: 0
MouseArea {
id: mouseArea
anchors.fill: parent
Item {
id: titleBarContent
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()
}
}
}
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
import QtQuick
import StudioTheme 1.0 as StudioTheme
import HelperWidgets as HelperWidgets
PopupDialog {
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 {
id: form
y: 32
height: 180
}
}

View File

@@ -1,76 +1,73 @@
// 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 2.15
import QtQuick.Controls 2.15
import QtQuick
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
Text {
id: text1
x: 10
y: 25
color: "#ffffff"
text: qsTr("Type:")
font.pixelSize: 15
}
y: StudioTheme.Values.popupMargin
width: parent.width
spacing: root.verticalSpacing
PopupLabel {
text: qsTr("Type")
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 ?? []
onActivated: backend.type.activateIndex(target.currentIndex)
onActivated: backend.type.activateIndex(type.currentIndex)
property int currentTypeIndex: backend.type.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex
onCurrentTypeIndexChanged: type.currentIndex = type.currentTypeIndex
}
Text {
id: text2
x: 10
y: 131
color: "#ffffff"
text: qsTr("Name")
font.pixelSize: 15
Row {
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("Name") ; tooltip: qsTr("The name of the property.")}
PopupLabel { text: qsTr("Value"); tooltip: qsTr("The value of the property.") }
}
TextInput {
id: name
x: 70
y: 131
color: "white"
width: 156
text: backend.name.text ?? ""
onEditingFinished: {
backend.name.activateText(name.text)
Row {
spacing: root.horizontalSpacing
StudioControls.TextField {
id: name
width: root.columnWidth
actionIndicatorVisible: false
translationIndicatorVisible: false
text: backend.name.text ?? ""
onEditingFinished: {
backend.name.activateText(name.text)
}
}
}
StudioControls.TextField {
id: value
Text {
x: 10
y: 81
color: "#ffffff"
text: qsTr("Value")
font.pixelSize: 15
}
width: root.columnWidth
actionIndicatorVisible: false
translationIndicatorVisible: false
TextInput {
id: value
color: "red"
x: 70
y: 81
width: 156
text: backend.value.text ?? ""
onEditingFinished: {
backend.value.activateText(value.text)
text: backend.value.text ?? ""
onEditingFinished: {
backend.value.activateText(value.text)
}
}
}
}

View File

@@ -3,126 +3,191 @@
import QtQuick
import QtQuick.Controls
import ConnectionsEditor
import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls
import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend
ListView {
id: listView
width: 606
height: 160
interactive: false
id: root
property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
property bool adsFocus: false
clip: true
interactive: true
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: {
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: {
listView.currentIndex = listView.model.currentIndex
root.currentIndex = root.model.currentIndex
}
onCurrentIndexChanged: {
listView.currentIndex = listView.model.currentIndex
dialog.backend.currentRow = listView.currentIndex
root.currentIndex = root.model.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: [
PropertiesDialog {
id: dialog
visible: false
backend: listView.model.delegate
backend: root.model.delegate
}
]
delegate: Item {
delegate: Rectangle {
id: itemDelegate
width: 600
height: 18
required property int index
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 {
id: mouseArea
anchors.fill: parent
property int currentIndex: listView.currentIndex
property int currentIndex: root.currentIndex
Connections {
target: mouseArea
function onClicked() {
listView.model.currentIndex = index
listView.currentIndex = index
dialog.backend.currentRow = index
root.model.currentIndex = itemDelegate.index
root.currentIndex = itemDelegate.index
dialog.popup(mouseArea)
}
}
}
Row {
id: row1
x: 0
y: 0
width: 600
height: 16
spacing: 10
id: row
height: itemDelegate.height
spacing: root.rowSpacing
property color textColor: itemDelegate.ListView.isCurrentItem ? root.style.text.selectedText
: root.style.icon.idle
Text {
width: 120
color: "#ffffff"
text: target ?? ""
anchors.verticalCenter: parent.verticalCenter
width: root.rowWidth + root.rowRest
height: itemDelegate.height
color: row.textColor
text: itemDelegate.target ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
leftPadding: root.rowSpacing
}
Text {
width: 120
text: name ?? ""
color: "#ffffff"
anchors.verticalCenter: parent.verticalCenter
width: root.rowWidth
height: itemDelegate.height
color: row.textColor
text: itemDelegate.name ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
text: type ?? ""
anchors.verticalCenter: parent.verticalCenter
color: "#ffffff"
width: root.rowWidth + root.rowRest
height: itemDelegate.height
color: row.textColor
text: itemDelegate.type ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
text: value ?? ""
anchors.verticalCenter: parent.verticalCenter
color: "#ffffff"
width: root.rowWidth + root.rowRest
height: itemDelegate.height
color: row.textColor
text: itemDelegate.value ?? ""
verticalAlignment: Text.AlignVCenter
font.bold: false
elide: Text.ElideMiddle
}
Text {
width: 120
Rectangle {
width: root.style.squareControlSize.width
height: root.style.squareControlSize.height
text: "-"
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignRight
font.pointSize: 14
color: "#ffffff"
font.bold: true
MouseArea {
color: toolTipArea.containsMouse ?
itemDelegate.ListView.isCurrentItem ? root.style.interactionHover
: root.style.background.hover
: "transparent"
Text {
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 {
color: "#2a5593"
color: root.style.interaction
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
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
implicitWidth: Math.max(
buttonBackground ? buttonBackground.implicitWidth : 0,
textItem.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(
buttonBackground ? buttonBackground.implicitHeight : 0,
textItem.implicitHeight + topPadding + bottomPadding)
leftPadding: 4
rightPadding: 4
property StudioTheme.ControlStyle style: StudioTheme.Values.viewBarButtonStyle
text: "My Button"
property alias tooltip: toolTipArea.tooltip
property alias buttonIcon: buttonIcon.text
background: buttonBackground
Rectangle {
id: buttonBackground
color: "#047eff"
implicitWidth: 100
implicitHeight: 40
opacity: enabled ? 1 : 0.3
radius: 12
border.color: "#047eff"
width: control.style.squareControlSize.width + buttonLabel.implicitWidth
+ buttonLabel.leftPadding + buttonLabel.rightPadding
height: control.style.squareControlSize.height
contentItem: Row {
spacing: 0
Text {
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
Text {
id: textItem
text: control.text
background: Rectangle {
id: controlBackground
color: control.style.background.idle
border.color: control.style.border.idle
border.width: control.style.borderWidth
radius: StudioTheme.Values.smallRadius //control.style.radius
}
opacity: enabled ? 1.0 : 0.3
color: "#ffffff"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
HelperWidgets.ToolTipArea {
id: toolTipArea
anchors.fill: parent
// Without setting the acceptedButtons property the clicked event won't
// reach the AbstractButton, it will be consumed by the ToolTipArea
acceptedButtons: Qt.NoButton
}
states: [
State {
name: "normal"
when: !control.down && !control.checked
name: "default"
when: control.enabled && !control.hovered && !control.pressed && !control.checked
PropertyChanges {
target: buttonBackground
visible: false
color: "#00000000"
border.color: "#047eff"
target: controlBackground
color: control.style.background.idle
border.color: control.style.border.idle
}
PropertyChanges {
target: textItem
color: "#ffffff"
target: buttonIcon
color: control.style.icon.idle
}
PropertyChanges {
target: buttonLabel
color: control.style.icon.idle
}
},
State {
name: "down"
when: control.down && !control.checked
name: "hover"
when: control.enabled && control.hovered && !control.pressed && !control.checked
PropertyChanges {
target: textItem
color: "#ffffff"
target: controlBackground
color: control.style.background.hover
border.color: control.style.border.hover
}
PropertyChanges {
target: buttonBackground
color: "#047eff"
border.color: "#00000000"
target: buttonIcon
color: control.style.icon.hover
}
PropertyChanges {
target: buttonLabel
color: control.style.icon.hover
}
},
State {
name: "down1"
when: control.checked
extend: "down"
name: "hoverCheck"
when: control.enabled && control.hovered && !control.pressed && control.checked
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 {
text: qsTr("Add an instance")
enabled: root.targetAvailable
enabled: root.targetAvailable && ContentLibraryBackend.rootView.hasActive3DScene
onTriggered: ContentLibraryBackend.effectsModel.addInstance(root.targetItem)
}

View File

@@ -1,186 +1,284 @@
{
"ContextMenuArea": {
"size": "28x28",
"Off": {
"Disabled": { "color": "DStextColorDisabled" },
"Hovered": { "color": "DSpanelBackground" },
"Normal": { "color": "DStextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
[
{
"ContextMenuArea": {
"size": "28x28",
"Off": {
"Disabled": { "color": "DStextColorDisabled" },
"Hovered": { "color": "DSpanelBackground" },
"Normal": { "color": "DStextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
},
"On": {
"Disabled": { "color": "DStextColorDisabled" },
"Hovered": { "color": "DSsubPanelBackground" },
"Normal": { "color": "DStextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
}
},
"On": {
"Disabled": { "color": "DStextColorDisabled" },
"Hovered": { "color": "DSsubPanelBackground" },
"Normal": { "color": "DStextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
"AddMouseAreaIcon": {
"iconName": "mouseArea_small"
},
"AlignCameraToViewIcon": {
"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"
},
"AlignCameraToViewIcon": {
"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"
{
"ToolbarArea": {
"size": "32x32",
"Off": {
"Disabled": { "color": "DStoolbarIcon_blocked" },
"Hovered": { "color": "DSiconColor" },
"Normal": { "color": "DSiconColor" },
"Selected": { "color": "DStextSelectedTextColor" }
},
"On": {
"Disabled": { "color": "DStoolbarIcon_blocked" },
"Hovered": { "color": "DStextSelectedTextColor" },
"Normal": { "color": "DStextSelectedTextColor" },
"Selected": { "color": "DStextSelectedTextColor" }
}
},
"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"
"AlignCameraToViewIcon": {
"iconName": "alignToCam_medium"
},
"On": {
"iconName": "visibilityOn"
}
},
"SnappingIcon": {
"iconName": "snapping_small"
},
"SimpleCheckIcon": {
"Off": {
"iconName": "transparent"
"AlignViewToCameraIcon": {
"iconName": "alignToView_medium"
},
"On": {
"iconName": "tickMark_small"
}
},
"TimelineIcon": {
"iconName": "timeline_small"
},
"ToggleGroupIcon": {
"Off": {
"iconName": "selectOutline_medium"
"CameraIcon": {
"Off": {
"iconName": "orthCam_small"
},
"On": {
"iconName": "perspectiveCam_small"
}
},
"On": {
"iconName": "selectFill_medium"
}
},
"VisibilityIcon": {
"Off": {
"iconName": "visibilityOff"
"EditColorIcon": {
"iconName": "colorSelection_medium"
},
"On": {
"iconName": "visibilityOn"
"EditLightIcon": {
"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