forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/7.0'
Conflicts: src/plugins/qmlprojectmanager/qmlprojectplugin.cpp Change-Id: I14030f58303839e706af892dd12a67566e3bed68
This commit is contained in:
2
.github/workflows/build_cmake.yml
vendored
2
.github/workflows/build_cmake.yml
vendored
@ -8,7 +8,7 @@ on:
|
||||
|
||||
env:
|
||||
QT_VERSION: 6.2.3
|
||||
CLANG_VERSION: 14.0.0
|
||||
CLANG_VERSION: 14.0.3
|
||||
ELFUTILS_VERSION: 0.175
|
||||
CMAKE_VERSION: 3.21.1
|
||||
NINJA_VERSION: 1.10.2
|
||||
|
@ -107,7 +107,7 @@ set(CRASHPAD_BACKEND_URL "" CACHE STRING "Crashpad backend URL")
|
||||
set(BUILD_WITH_CRASHPAD OFF)
|
||||
# Linux is not supported for now
|
||||
# x86_64;arm64 is not supported for now
|
||||
if(CRASHPAD_BACKEND_URL AND (WIN32 OR (APPLE AND NOT "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64;arm64")))
|
||||
if(CRASHPAD_BACKEND_URL AND (WIN32 OR APPLE)) # Linux is not supported for now
|
||||
find_package(Crashpad QUIET)
|
||||
if(TARGET Crashpad::Crashpad)
|
||||
set(BUILD_WITH_CRASHPAD ON)
|
||||
|
@ -57,25 +57,9 @@ find_path(CRASHPAD_GEN_DIR
|
||||
"${CMAKE_PREFIX_PATH}"
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
find_path(CRASHPAD_OBJ_DIR
|
||||
NAMES mig_output.child_portServer.o
|
||||
PATH_SUFFIXES gen/util/mach
|
||||
HINTS
|
||||
"${CRASHPAD_OBJECT_DIR}"
|
||||
"${CRASHPAD_LIB_DIR}/out/Default"
|
||||
"${CMAKE_PREFIX_PATH}"
|
||||
)
|
||||
set(CRASHPAD_APPLE_VARS CRASHPAD_OBJ_DIR CRASHPAD_GEN_DIR)
|
||||
find_library(FWbsm bsm)
|
||||
find_library(FWAppKit AppKit)
|
||||
find_library(FWIOKit IOKit)
|
||||
find_library(FWSecurity Security)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Crashpad DEFAULT_MSG
|
||||
CRASHPAD_BIN_DIR CRASHPAD_INCLUDE_DIR CRASHPAD_LIB_DIR ${CRASHPAD_APPLE_VARS}
|
||||
CRASHPAD_BIN_DIR CRASHPAD_INCLUDE_DIR CRASHPAD_LIB_DIR
|
||||
)
|
||||
|
||||
if(Crashpad_FOUND)
|
||||
@ -93,18 +77,16 @@ if(Crashpad_FOUND)
|
||||
set_target_properties(Crashpad::Crashpad PROPERTIES
|
||||
IMPORTED_LOCATION "${CRASHPAD_LIB_DIR}/client/client.lib")
|
||||
elseif(APPLE)
|
||||
find_library(FWbsm bsm)
|
||||
find_library(FWAppKit AppKit)
|
||||
find_library(FWIOKit IOKit)
|
||||
find_library(FWSecurity Security)
|
||||
target_link_libraries(Crashpad::Crashpad INTERFACE
|
||||
"${CRASHPAD_LIB_DIR}/third_party/mini_chromium/mini_chromium/base/libbase.a"
|
||||
"${CRASHPAD_LIB_DIR}/util/libutil.a"
|
||||
"${CRASHPAD_LIB_DIR}/util/libmig_output.a"
|
||||
"${CRASHPAD_LIB_DIR}/client/libclient.a"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.child_portServer.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.child_portUser.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.excServer.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.excUser.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.mach_excServer.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.mach_excUser.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.notifyServer.o"
|
||||
"${CRASHPAD_OBJ_DIR}/mig_output.notifyUser.o"
|
||||
"${CRASHPAD_LIB_DIR}/client/libcommon.a"
|
||||
${FWbsm} ${FWAppKit} ${FWIOKit} ${FWSecurity})
|
||||
set_target_properties(Crashpad::Crashpad PROPERTIES
|
||||
IMPORTED_LOCATION "${CRASHPAD_LIB_DIR}/client/libclient.a")
|
||||
|
@ -335,6 +335,10 @@ function(find_dependent_plugins varName)
|
||||
set(_RESULT ${ARGN})
|
||||
|
||||
foreach(i ${ARGN})
|
||||
if(NOT TARGET ${i})
|
||||
continue()
|
||||
endif()
|
||||
set(_dep)
|
||||
get_property(_dep TARGET "${i}" PROPERTY _arg_DEPENDS)
|
||||
if (_dep)
|
||||
find_dependent_plugins(_REC ${_dep})
|
||||
|
@ -7,7 +7,7 @@ instructions:
|
||||
variableValue: "RelWithDebInfo"
|
||||
- type: EnvironmentVariable
|
||||
variableName: LLVM_BASE_URL
|
||||
variableValue: http://master.qt.io/development_releases/prebuilt/libclang/libclang-release_14.0.0-based
|
||||
variableValue: http://master.qt.io/development_releases/prebuilt/libclang/libclang-release_14.0.3-based
|
||||
|
||||
- type: Group
|
||||
instructions:
|
||||
|
83
dist/changes-7.0.2.md
vendored
Normal file
83
dist/changes-7.0.2.md
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
Qt Creator 7.0.2
|
||||
================
|
||||
|
||||
Qt Creator version 7.0.2 contains bug fixes.
|
||||
|
||||
The most important changes are listed in this document. For a complete list of
|
||||
changes, see the Git log for the Qt Creator sources that you can check out from
|
||||
the public Git repository. For example:
|
||||
|
||||
git clone git://code.qt.io/qt-creator/qt-creator.git
|
||||
git log --cherry-pick --pretty=oneline origin/v7.0.1..v7.0.2
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
### Locator
|
||||
|
||||
* Fixed saving of command history of `Execute` filter
|
||||
|
||||
Editing
|
||||
-------
|
||||
|
||||
* Fixed that actions could be applied to wrong editor after switching split
|
||||
(QTCREATORBUG-27479)
|
||||
|
||||
### C++
|
||||
|
||||
* Fixed wrong `__cplusplus` value for older GCC versions
|
||||
* ClangFormat
|
||||
* Fixed disappearing settings drop down (QTCREATORBUG-26948)
|
||||
|
||||
### Language Client
|
||||
|
||||
* Fixed crash with function argument and quick fix hints (QTCREATORBUG-27404)
|
||||
* Fixed selection in `Outline` view
|
||||
* Fixed `Sort Alphabetically` for outline dropdown
|
||||
|
||||
Projects
|
||||
--------
|
||||
|
||||
* Fixed crash with `Recent Projects` (QTCREATORBUG-27399)
|
||||
* Fixed that `-include` flags were ignored by code model (QTCREATORBUG-27450)
|
||||
|
||||
### CMake
|
||||
|
||||
* Fixed crash when cancelling progress indicator (QTCREATORBUG-27499)
|
||||
* Fixed application of build directory after `Browse` (QTCREATORBUG-27407)
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
* Fixed pretty printer for `QFile` in Qt 6.3
|
||||
|
||||
Platforms
|
||||
---------
|
||||
|
||||
### macOS
|
||||
|
||||
* Fixed compilier identification of `cc` and `c++` (QTCREATORBUG-27523)
|
||||
|
||||
Credits for these changes go to:
|
||||
--------------------------------
|
||||
Alessandro Portale
|
||||
Artem Sokolovskii
|
||||
Brook Cronin
|
||||
Christian Kandeler
|
||||
Christian Stenger
|
||||
Cristian Adam
|
||||
David Schulz
|
||||
Eike Ziller
|
||||
Henning Gruendl
|
||||
Jaroslaw Kobus
|
||||
Kai Uwe Broulik
|
||||
Knud Dollereder
|
||||
Leena Miettinen
|
||||
Mahmoud Badri
|
||||
Mats Honkamaa
|
||||
Miikka Heikkinen
|
||||
Orgad Shaneh
|
||||
Robert Löhning
|
||||
Thomas Hartmann
|
||||
Tim Jenssen
|
||||
Vikas Pachdha
|
@ -41,16 +41,14 @@
|
||||
|
||||
\title Using QML Modules with Plugins
|
||||
|
||||
QML modules may use plugins to expose components defined in C++ to QML
|
||||
applications. \QC cannot load the plugins to determine the details of
|
||||
the contained components, and therefore, the modules must provide extra type
|
||||
information for code completion and the semantic checks to work correctly.
|
||||
\l{Defining a QML Module}{QML modules} may use \l{Creating C++ Plugins for QML}
|
||||
{C++ plugins} to expose components defined in C++ to QML applications.
|
||||
|
||||
To create a QML module
|
||||
To create a QML
|
||||
\if defined(qtdesignstudio)
|
||||
and make it appear in the \l Components view:
|
||||
module and make it appear in the \l Components view:
|
||||
\else
|
||||
:
|
||||
module:
|
||||
\endif
|
||||
|
||||
\list 1
|
||||
@ -97,26 +95,13 @@
|
||||
\c .metainfo file is in place.
|
||||
\endif
|
||||
|
||||
\if defined(qtcreator)
|
||||
\section1 Registering QML Types
|
||||
|
||||
When you write a QML module or use QML from a C++ application, and the C++
|
||||
is a part of your qmake project, you typically register new types with the
|
||||
\c qmlRegisterType() function or expose some class instances with
|
||||
\l{QQmlContext::setContextProperty()}. The \QC C++ code model now scans for
|
||||
these calls and tells the QML code model about them. This means that properties
|
||||
are displayed during code completion and the JavaScript code checker does not
|
||||
complain about unknown types. However, this works only when the source code
|
||||
is available, and therefore, you must explicitly generate type information
|
||||
for QML modules with plugins before distributing them.
|
||||
\endif
|
||||
|
||||
\section1 Generating Type Description Files
|
||||
|
||||
Ideally, QML modules have a \c{plugins.qmltypes} file in the same directory
|
||||
as the \c qmldir file. The \c qmltypes file contains a description of the
|
||||
components exported by the module's plugins and is loaded by \QC when the
|
||||
module is imported.
|
||||
When \l{Defining QML Types from C++}{registering QML types}, make sure that
|
||||
the QML module has a \c{plugins.qmltypes} file. Ideally, it should be located
|
||||
in the same directory as the \c qmldir file. The \c qmltypes file contains a
|
||||
description of the components exported by the module's plugins and is loaded
|
||||
by \QC when the module is imported.
|
||||
|
||||
For more information, see \l{Type Description Files}.
|
||||
|
||||
@ -127,7 +112,6 @@
|
||||
However, this automatic dumping is a fallback mechanism with many points of
|
||||
failure and you cannot rely upon it.
|
||||
|
||||
\if defined(qtcreator)
|
||||
\section1 Importing QML Modules
|
||||
|
||||
By default, \QC will look in the QML import path of Qt for QML modules.
|
||||
@ -145,7 +129,7 @@
|
||||
|
||||
The import path affects all the targets built by the CMake project.
|
||||
|
||||
\else
|
||||
\if defined(qtdesignstudio)
|
||||
\section1 Running QML Modules in Design Mode
|
||||
|
||||
A QML emulation layer (also called QML Puppet) is used in the
|
||||
@ -169,7 +153,7 @@
|
||||
by an application or edited in the \uicontrol Design mode.
|
||||
|
||||
If you want to use a different module in the \uicontrol Design mode
|
||||
than in your actual application for example to mockup C++ items,
|
||||
than in your actual application for example to mockup C++ items,
|
||||
you can use \c{QML_DESIGNER_IMPORT_PATH}
|
||||
in the \c{.pro} file (for qmake projects), or declare and set the property
|
||||
\c qmlDesignerImportPaths in your product (for Qbs projects).
|
||||
|
BIN
doc/qtdesignstudio/images/studio-asset-import.png
Normal file
BIN
doc/qtdesignstudio/images/studio-asset-import.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
Before Width: | Height: | Size: 17 KiB |
Binary file not shown.
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 51 KiB |
@ -32,8 +32,8 @@
|
||||
|
||||
\title Exporting Designs from Figma
|
||||
|
||||
You can use \QBF to export designs from Figma to \e {.metadata}
|
||||
format that you can \l{Importing 2D Assets}{import} to projects in \QDS.
|
||||
You can use \QBF to export designs from Figma to a \e {.qtbridge}
|
||||
archive that you can \l{Importing 2D Assets}{import} to projects in \QDS.
|
||||
|
||||
\image studio-figma-export.png
|
||||
|
||||
|
@ -128,9 +128,8 @@
|
||||
\li When the exporting is done, select \uicontrol OK.
|
||||
\endlist
|
||||
|
||||
\QBF exports everything into a single archive. Before importing the design
|
||||
into \QDS, you have to manually extract the archive. Then you can import the
|
||||
\e .metainfo into a project in \QDS, as described in \l{Importing 2D Assets}.
|
||||
\QBF exports everything into a .qtbridge archive. You can import the archive
|
||||
into a project in \QDS, as described in \l{Importing 2D Assets}.
|
||||
|
||||
\section1 Export Settings
|
||||
|
||||
|
@ -55,48 +55,47 @@
|
||||
\image studio-imported-assets.png "UI imported into Qt Design Studio"
|
||||
|
||||
\QB enables you to export assets and then import them to a \QDS project
|
||||
as image and QML files for editing in \l {Form Editor}. If you make changes
|
||||
as images and QML files for editing in \l {Form Editor}. If you make changes
|
||||
to your design in the design tool that you originally used to create it,
|
||||
you can merge the changes into existing QML files without overwriting the
|
||||
changes you have made in \QDS. For more information, see
|
||||
\l {Exporting from Design Tools}.
|
||||
|
||||
\note Attempting to import assets exported on another system might fail.
|
||||
\QB exports the designs either as an archive(.qtbridge) or as images with
|
||||
a .metadata file. \QDS support both formats.
|
||||
|
||||
The following instructions use an empty project as an example. For more
|
||||
information about the options you have, see
|
||||
\l {Creating Projects}.
|
||||
|
||||
To import assets exported in \QB to \QDS projects:
|
||||
To import the exported assets to \QDS projects:
|
||||
|
||||
\list 1
|
||||
\li Select \uicontrol File > \uicontrol {New Project} >
|
||||
\uicontrol General > \uicontrol {Qt Quick Application - Empty} >
|
||||
\uicontrol Choose, and follow the instructions of the wizard to
|
||||
create an empty project.
|
||||
\uicontrol General > \uicontrol {Empty}. Add \uicontrol {Details} about
|
||||
the project and select \uicontrol Create.
|
||||
\li In \uicontrol Projects, double-click \e Screen01.ui.qml to move to
|
||||
the Design mode.
|
||||
\li Select \uicontrol Assets > \inlineimage icons/plus.png
|
||||
.
|
||||
\li Select the folder where you exported the assets.
|
||||
\li Select \uicontrol {Exported Assets (*.metadata)} in the dropdown
|
||||
menu to filter \e .metadata files.
|
||||
\li Select a \e .metadata file to import, and then select
|
||||
\uicontrol Open.
|
||||
\li Select \uicontrol {Compressed Metadata (*.qtbridge)} or
|
||||
\uicontrol {Exported Metadata (*.metadata)} in the dropdown menu to
|
||||
filter the exported files.
|
||||
\li Select a the file to import and then select \uicontrol Open.
|
||||
\li Select \uicontrol Details next to the
|
||||
\uicontrol {Metadata Import Paths} field to display the path where
|
||||
the metadata is imported from.
|
||||
\image studio-import-metadata.png "Asset Import dialog"
|
||||
\uicontrol {Import Paths} field to display the path where the exported
|
||||
assets are imported from.
|
||||
\image studio-asset-import.png "Asset Import dialog"
|
||||
\li Select \uicontrol Details next to the
|
||||
\uicontrol {QML/Asset Export Paths} field to display the paths to
|
||||
\uicontrol {Export Paths} field to display the paths to
|
||||
copy the assets to.
|
||||
\li In the \uicontrol QML field, you can change the folder to copy the
|
||||
QML files to.
|
||||
\li In the \uicontrol Assets field, you can change the folder to copy
|
||||
the image files to.
|
||||
\li Select the \uicontrol {Create sub directory for each metadata}
|
||||
check box to copy the directory structure from the metadata file
|
||||
to \QDS.
|
||||
\li Select the \uicontrol {Create sub directory} check box to import the
|
||||
assets in a sub directory inside \uicontrol {Export Paths}.
|
||||
\li Deselect the \uicontrol {Import assets} check box if you only want
|
||||
to create QML files.
|
||||
\li Deselect the \uicontrol {Generate QML} check box if you only
|
||||
@ -104,26 +103,21 @@
|
||||
\li Select the \uicontrol {Merge QML} check box if you have imported the
|
||||
assets before and want to merge the changes into existing QML files
|
||||
instead of overwriting the existing files. See \l {Merging QML Files}.
|
||||
\li Select the \uicontrol {Round off coordinates} check box to round off
|
||||
the position and dimension values to integers in the generated QML files.
|
||||
\li Select the \uicontrol {Save Logs} check box to write the export logs
|
||||
to a text file inside the directory selected in \uicontrol QML export path.
|
||||
\li Select \uicontrol Import to import the QML files and assets. This
|
||||
might take a little while for complex projects.
|
||||
\endlist
|
||||
|
||||
The imported assets are displayed in \uicontrol Assets
|
||||
as PNG images. The components that you specified in the design tool are
|
||||
displayed in \uicontrol Components > \uicontrol {My Components} as well as
|
||||
in the \uicontrol Projects view as separate QML files. To start using them,
|
||||
The imported assets are displayed in \uicontrol Assets as images.
|
||||
The components that you specified in the design tool are displayed in
|
||||
\uicontrol Components > \uicontrol {My Components} as well as in the
|
||||
\uicontrol Projects view as separate QML files. To use them,
|
||||
drag-and-drop them from \uicontrol Components to \uicontrol {Form Editor} or
|
||||
\l Navigator.
|
||||
|
||||
\note The layer that was the bottom layer in the design tool becames the top
|
||||
layer in \uicontrol Navigator to reflect the QML code model. You
|
||||
can view the QML code in \l{Text Editor}.
|
||||
|
||||
After importing the metadata files, wait a few moments to allow all
|
||||
imported assets to appear in your project files before selecting your
|
||||
metadata filename from \uicontrol Assets > \inlineimage icons/plus.png
|
||||
.
|
||||
|
||||
If asset importer conflicts, warnings, and errors are displayed in the
|
||||
\uicontrol {Asset Import} dialog while importing, fix the issues in
|
||||
design tool and export the assets again.
|
||||
|
@ -263,32 +263,44 @@ def qdump__Utils__Environment(d, value):
|
||||
qdump__Utils__NameValueDictionary(d, value)
|
||||
|
||||
|
||||
def qdump__Utils__DictKey(d, value):
|
||||
d.putStringValue(value["name"])
|
||||
|
||||
|
||||
def qdump__Utils__NameValueDictionary(d, value):
|
||||
dptr = d.extractPointer(value["m_values"])
|
||||
(ref, n) = d.split('ii', dptr)
|
||||
d.check(0 <= n and n <= 100 * 1000 * 1000)
|
||||
d.check(-1 <= ref and ref < 100000)
|
||||
dptr = d.extractPointer(value)
|
||||
if d.qtVersion() >= 0x60000:
|
||||
if dptr == 0:
|
||||
d.putItemCount(0)
|
||||
return
|
||||
m = value['d']['d']['m']
|
||||
d.putItem(m)
|
||||
d.putBetterType('Utils::NameValueDictionary')
|
||||
else: # Qt5
|
||||
(ref, n) = d.split('ii', dptr)
|
||||
d.check(0 <= n and n <= 100 * 1000 * 1000)
|
||||
d.check(-1 <= ref and ref < 100000)
|
||||
|
||||
d.putItemCount(n)
|
||||
if d.isExpanded():
|
||||
if n > 10000:
|
||||
n = 10000
|
||||
d.putItemCount(n)
|
||||
if d.isExpanded():
|
||||
if n > 10000:
|
||||
n = 10000
|
||||
|
||||
typeCode = 'ppp@{%s}@{%s}' % ("Utils::DictKey", "QString")
|
||||
typeCode = 'ppp@{%s}@{%s}' % ("Utils::DictKey", "@QPair<@QString,bool>")
|
||||
|
||||
def helper(node):
|
||||
(p, left, right, padding1, key, padding2, value) = d.split(typeCode, node)
|
||||
if left:
|
||||
for res in helper(left):
|
||||
yield res
|
||||
yield (key["name"], value)
|
||||
if right:
|
||||
for res in helper(right):
|
||||
yield res
|
||||
def helper(node):
|
||||
(p, left, right, padding1, key, padding2, value) = d.split(typeCode, node)
|
||||
if left:
|
||||
for res in helper(left):
|
||||
yield res
|
||||
yield (key["name"], value)
|
||||
if right:
|
||||
for res in helper(right):
|
||||
yield res
|
||||
|
||||
with Children(d, n):
|
||||
for (pair, i) in zip(helper(dptr + 8), range(n)):
|
||||
d.putPairItem(i, pair, 'key', 'value')
|
||||
with Children(d, n):
|
||||
for (pair, i) in zip(helper(dptr + 8), range(n)):
|
||||
d.putPairItem(i, pair, 'key', 'value')
|
||||
|
||||
|
||||
def qdump__Utf8String(d, value):
|
||||
|
@ -39,6 +39,8 @@ Node {
|
||||
// Note: Only one instance of HelperGrid is supported, as the geometry names are fixed
|
||||
|
||||
Model { // Main grid lines
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
geometry: GridGeometry {
|
||||
id: gridGeometry
|
||||
name: "3D Edit View Helper Grid"
|
||||
@ -55,6 +57,8 @@ Node {
|
||||
}
|
||||
|
||||
Model { // Subdivision lines
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
geometry: GridGeometry {
|
||||
lines: gridGeometry.lines
|
||||
step: gridGeometry.step
|
||||
@ -73,6 +77,8 @@ Node {
|
||||
}
|
||||
|
||||
Model { // Z Axis
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
geometry: GridGeometry {
|
||||
lines: gridGeometry.lines
|
||||
step: gridGeometry.step
|
||||
@ -89,6 +95,8 @@ Node {
|
||||
]
|
||||
}
|
||||
Model { // X Axis
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
eulerRotation.z: 90
|
||||
geometry: GridGeometry {
|
||||
lines: gridGeometry.lines
|
||||
|
@ -54,6 +54,9 @@ Node {
|
||||
|
||||
visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty
|
||||
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
|
||||
materials: [
|
||||
DefaultMaterial {
|
||||
diffuseColor: "#fff600"
|
||||
|
@ -40,6 +40,8 @@ Node {
|
||||
|
||||
Model { // Main grid lines
|
||||
readonly property bool _edit3dLocked: true // Make this non-pickable
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
geometry: GridGeometry {
|
||||
id: gridGeometry
|
||||
name: "3D Edit View Helper Grid"
|
||||
@ -57,6 +59,8 @@ Node {
|
||||
|
||||
Model { // Subdivision lines
|
||||
readonly property bool _edit3dLocked: true // Make this non-pickable
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
geometry: GridGeometry {
|
||||
lines: gridGeometry.lines
|
||||
step: gridGeometry.step
|
||||
@ -76,6 +80,8 @@ Node {
|
||||
|
||||
Model { // Z Axis
|
||||
readonly property bool _edit3dLocked: true // Make this non-pickable
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
geometry: GridGeometry {
|
||||
lines: gridGeometry.lines
|
||||
step: gridGeometry.step
|
||||
@ -93,6 +99,8 @@ Node {
|
||||
}
|
||||
Model { // X Axis
|
||||
readonly property bool _edit3dLocked: true // Make this non-pickable
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
eulerRotation.z: 90
|
||||
geometry: GridGeometry {
|
||||
lines: gridGeometry.lines
|
||||
|
@ -55,6 +55,9 @@ Node {
|
||||
|
||||
visible: selectionBox.targetNode && !selectionBoxGeometry.isEmpty
|
||||
|
||||
castsShadows: false
|
||||
receivesShadows: false
|
||||
|
||||
materials: [
|
||||
DefaultMaterial {
|
||||
diffuseColor: "#fff600"
|
||||
|
@ -1610,7 +1610,7 @@ void NodeInstanceServer::addAnimation(QQuickAbstractAnimation *animation)
|
||||
m_animations.push_back(animation);
|
||||
|
||||
QQuickPropertyAnimation *panim = qobject_cast<QQuickPropertyAnimation *>(animation);
|
||||
if (panim) {
|
||||
if (panim && panim->target()) {
|
||||
QObject *target = panim->target();
|
||||
QString property = panim->property();
|
||||
QVariant value = target->property(qPrintable(baseProperty(property)));
|
||||
|
@ -534,7 +534,7 @@ void Qt5InformationNodeInstanceServer::handleParticleSystemDeselected()
|
||||
for (auto a : anim) {
|
||||
a->stop();
|
||||
QQuickPropertyAnimation *panim = qobject_cast<QQuickPropertyAnimation *>(a);
|
||||
if (panim)
|
||||
if (panim && panim->target())
|
||||
panim->target()->setProperty(qPrintable(baseProperty(panim->property())), animationDefaultValue(i));
|
||||
i++;
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
|
||||
if (rootNodeInstance().isSubclassOf("QQuick3DNode") && rootNodeInstance().contentItem()
|
||||
&& DesignerSupport::isDirty(rootNodeInstance().contentItem(),
|
||||
DesignerSupport::ContentUpdateMask)
|
||||
DesignerSupport::AllMask)
|
||||
&& nodeInstanceClient()->bytesToWrite() < 10000) {
|
||||
Internal::QuickItemNodeInstance::updateDirtyNode(rootNodeInstance().contentItem());
|
||||
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()}));
|
||||
|
@ -59,9 +59,6 @@ Item {
|
||||
var complexSuffixes = rootView.supportedAssetSuffixes(true);
|
||||
for (const u of drag.urls) {
|
||||
var url = u.toString();
|
||||
if (url.startsWith("file:///")) // remove file scheme (happens on Windows)
|
||||
url = url.substr(8)
|
||||
|
||||
var ext = '*.' + url.slice(url.lastIndexOf('.') + 1).toLowerCase()
|
||||
if (simpleSuffixes.includes(ext))
|
||||
root.dropSimpleExtFiles.push(url)
|
||||
|
@ -143,7 +143,8 @@ Section {
|
||||
PropertyLabel {
|
||||
text: qsTr("Style name")
|
||||
tooltip: qsTr("Font's style.")
|
||||
blockedByTemplate: !styleNameComboBox.enabled
|
||||
enabled: styleNameComboBox.model.length
|
||||
blockedByTemplate: !backendValue.isAvailable
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
@ -156,7 +157,7 @@ Section {
|
||||
backendValue: getBackendValue("styleName")
|
||||
model: styleNamesForFamily(fontComboBox.familyName)
|
||||
valueType: ComboBox.String
|
||||
enabled: backendValue.isAvailable
|
||||
enabled: backendValue.isAvailable && styleNameComboBox.model.length
|
||||
}
|
||||
|
||||
ExpandingSpacer {}
|
||||
|
@ -92,7 +92,6 @@ StudioControls.ComboBox {
|
||||
onValueFromBackendChanged: colorLogic.invalidate()
|
||||
|
||||
function invalidate() {
|
||||
|
||||
if (comboBox.block)
|
||||
return
|
||||
|
||||
@ -140,6 +139,21 @@ StudioControls.ComboBox {
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (!comboBox.__isCompleted)
|
||||
return
|
||||
|
||||
let inputValue = comboBox.editText
|
||||
|
||||
let index = comboBox.find(inputValue)
|
||||
if (index !== -1)
|
||||
inputValue = comboBox.textAt(index)
|
||||
|
||||
comboBox.backendValue.value = inputValue
|
||||
|
||||
comboBox.dirty = false
|
||||
}
|
||||
|
||||
onCompressedActivated: {
|
||||
if (!comboBox.__isCompleted)
|
||||
return
|
||||
|
@ -131,7 +131,7 @@ Item {
|
||||
checkable: true
|
||||
onTriggered: {
|
||||
if (checked)
|
||||
backendValue.exportPopertyAsAlias()
|
||||
backendValue.exportPropertyAsAlias()
|
||||
else
|
||||
backendValue.removeAliasExport()
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import HelperWidgets 2.0
|
||||
import StudioControls 1.0 as StudioControls
|
||||
|
||||
StudioControls.ComboBox {
|
||||
id: comboBox
|
||||
id: root
|
||||
|
||||
property variant backendValue
|
||||
property color textColor: colorLogic.textColor
|
||||
@ -39,17 +39,17 @@ StudioControls.ComboBox {
|
||||
labelColor: colorLogic.textColor
|
||||
editable: true
|
||||
|
||||
onTextColorChanged: setColor()
|
||||
onTextColorChanged: root.setColor()
|
||||
|
||||
FileResourcesModel {
|
||||
id: fileModel
|
||||
modelNodeBackendProperty: modelNodeBackend
|
||||
filter: comboBox.fontFilter
|
||||
filter: root.fontFilter
|
||||
}
|
||||
|
||||
function createFontLoader(fontUrl) {
|
||||
return Qt.createQmlObject('import QtQuick 2.0; FontLoader { source: "' + fontUrl + '"; }',
|
||||
comboBox, "dynamicFontLoader")
|
||||
root, "dynamicFontLoader")
|
||||
}
|
||||
|
||||
function setupModel() {
|
||||
@ -63,80 +63,83 @@ StudioControls.ComboBox {
|
||||
// Remove duplicate family names
|
||||
familyNames = [...new Set(familyNames)]
|
||||
familyNames.sort()
|
||||
comboBox.model = familyNames
|
||||
root.model = familyNames
|
||||
root.currentIndex = root.find(root.backendValue.value)
|
||||
}
|
||||
|
||||
onModelChanged: editText = comboBox.backendValue.valueToString
|
||||
function setColor() {
|
||||
// Hack to style the text input
|
||||
for (var i = 0; i < root.children.length; i++) {
|
||||
if (root.children[i].text !== undefined) {
|
||||
root.children[i].color = root.textColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onModelChanged: root.editText = root.backendValue.valueToString
|
||||
|
||||
ExtendedFunctionLogic {
|
||||
id: extFuncLogic
|
||||
backendValue: comboBox.backendValue
|
||||
backendValue: root.backendValue
|
||||
}
|
||||
|
||||
actionIndicator.icon.color: extFuncLogic.color
|
||||
actionIndicator.icon.text: extFuncLogic.glyph
|
||||
actionIndicator.onClicked: extFuncLogic.show()
|
||||
actionIndicator.forceVisible: extFuncLogic.menuVisible
|
||||
actionIndicator.visible: comboBox.showExtendedFunctionButton
|
||||
actionIndicator.visible: root.showExtendedFunctionButton
|
||||
|
||||
ColorLogic {
|
||||
id: colorLogic
|
||||
property string textValue: comboBox.backendValue.valueToString
|
||||
backendValue: comboBox.backendValue
|
||||
onTextValueChanged: comboBox.editText = colorLogic.textValue
|
||||
property string textValue: root.backendValue.valueToString
|
||||
backendValue: root.backendValue
|
||||
onTextValueChanged: root.editText = colorLogic.textValue
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (backendValue === undefined)
|
||||
if (root.backendValue === undefined)
|
||||
return
|
||||
|
||||
if (editText === "")
|
||||
if (root.editText === "")
|
||||
return
|
||||
|
||||
if (backendValue.value !== editText)
|
||||
backendValue.value = editText;
|
||||
if (root.backendValue.value !== root.editText)
|
||||
root.backendValue.value = root.editText
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
if (backendValue === undefined)
|
||||
onCompressedActivated: function(index, reason) { root.handleActivate(index) }
|
||||
|
||||
function handleActivate(index)
|
||||
{
|
||||
if (root.backendValue === undefined)
|
||||
return
|
||||
|
||||
if (editText === "")
|
||||
if (root.editText === "")
|
||||
return
|
||||
|
||||
var indexText = comboBox.textAt(index)
|
||||
var indexText = root.textAt(index)
|
||||
|
||||
if (backendValue.value !== indexText)
|
||||
backendValue.value = indexText
|
||||
if (root.backendValue.value !== indexText)
|
||||
root.backendValue.value = indexText
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: modelNodeBackend
|
||||
function onSelectionChanged() {
|
||||
comboBox.editText = backendValue.value
|
||||
setupModel()
|
||||
root.editText = root.backendValue.value
|
||||
root.setupModel()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
setupModel()
|
||||
root.setupModel()
|
||||
// Hack to style the text input
|
||||
for (var i = 0; i < comboBox.children.length; i++) {
|
||||
if (comboBox.children[i].text !== undefined) {
|
||||
comboBox.children[i].color = comboBox.textColor
|
||||
comboBox.children[i].anchors.rightMargin = 34
|
||||
comboBox.children[i].anchors.leftMargin = 18
|
||||
for (var i = 0; i < root.children.length; i++) {
|
||||
if (root.children[i].text !== undefined) {
|
||||
root.children[i].color = root.textColor
|
||||
root.children[i].anchors.rightMargin = 34
|
||||
root.children[i].anchors.leftMargin = 18
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setColor() {
|
||||
// Hack to style the text input
|
||||
for (var i = 0; i < comboBox.children.length; i++) {
|
||||
if (comboBox.children[i].text !== undefined) {
|
||||
comboBox.children[i].color = comboBox.textColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,36 +32,43 @@ StudioControls.TextField {
|
||||
id: lineEdit
|
||||
|
||||
property variant backendValue
|
||||
property color borderColor: "#222"
|
||||
property color highlightColor: "orange"
|
||||
color: lineEdit.edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
|
||||
|
||||
property bool showTranslateCheckBox: true
|
||||
translationIndicatorVisible: showTranslateCheckBox
|
||||
|
||||
property bool writeValueManually: false
|
||||
property bool writeAsExpression: false
|
||||
|
||||
property bool __dirty: false
|
||||
|
||||
property bool showTranslateCheckBox: true
|
||||
property bool showExtendedFunctionButton: true
|
||||
property string context
|
||||
|
||||
actionIndicator.visible: showExtendedFunctionButton
|
||||
property bool __dirty: false
|
||||
|
||||
signal commitData
|
||||
|
||||
property string context
|
||||
color: lineEdit.edit ? StudioTheme.Values.themeTextColor : colorLogic.textColor
|
||||
actionIndicator.visible: lineEdit.showExtendedFunctionButton
|
||||
translationIndicatorVisible: lineEdit.showTranslateCheckBox
|
||||
|
||||
function setTranslateExpression() {
|
||||
if (translateFunction() === "qsTranslate") {
|
||||
backendValue.expression = translateFunction()
|
||||
+ "(\"" + backendValue.getTranslationContext()
|
||||
+ "\", " + "\"" + escapeString(text) + "\")"
|
||||
lineEdit.backendValue.expression = translateFunction()
|
||||
+ "(\"" + lineEdit.backendValue.getTranslationContext()
|
||||
+ "\", " + "\"" + lineEdit.escapeString(lineEdit.text) + "\")"
|
||||
} else {
|
||||
backendValue.expression = translateFunction() + "(\"" + escapeString(text) + "\")"
|
||||
lineEdit.backendValue.expression = translateFunction()
|
||||
+ "(\"" + lineEdit.escapeString(lineEdit.text) + "\")"
|
||||
}
|
||||
}
|
||||
|
||||
function escapeString(string) {
|
||||
var str = string
|
||||
str = str.replace(/\\/g, "\\\\")
|
||||
str.replace(/\"/g, "\\\"")
|
||||
str = str.replace(/\t/g, "\\t")
|
||||
str = str.replace(/\r/g, "\\r")
|
||||
str = str.replace(/\n/g, '\\n')
|
||||
return str
|
||||
}
|
||||
|
||||
ExtendedFunctionLogic {
|
||||
id: extFuncLogic
|
||||
backendValue: lineEdit.backendValue
|
||||
@ -79,60 +86,58 @@ StudioControls.TextField {
|
||||
if (colorLogic.valueFromBackend === undefined) {
|
||||
lineEdit.text = ""
|
||||
} else {
|
||||
if (writeValueManually)
|
||||
if (lineEdit.writeValueManually)
|
||||
lineEdit.text = convertColorToString(colorLogic.valueFromBackend)
|
||||
else
|
||||
lineEdit.text = colorLogic.valueFromBackend
|
||||
}
|
||||
__dirty = false
|
||||
lineEdit.__dirty = false
|
||||
}
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
__dirty = true
|
||||
}
|
||||
onTextChanged: lineEdit.__dirty = true
|
||||
|
||||
Connections {
|
||||
target: modelNodeBackend
|
||||
function onSelectionToBeChanged() {
|
||||
if (__dirty && !writeValueManually) {
|
||||
if (writeAsExpression)
|
||||
lineEdit.backendValue.expression = text
|
||||
if (lineEdit.__dirty && !lineEdit.writeValueManually) {
|
||||
if (lineEdit.writeAsExpression)
|
||||
lineEdit.backendValue.expression = lineEdit.text
|
||||
else
|
||||
lineEdit.backendValue.value = text
|
||||
} else if (__dirty) {
|
||||
lineEdit.backendValue.value = lineEdit.text
|
||||
} else if (lineEdit.__dirty) {
|
||||
commitData()
|
||||
}
|
||||
|
||||
__dirty = false
|
||||
lineEdit.__dirty = false
|
||||
}
|
||||
}
|
||||
|
||||
onEditingFinished: {
|
||||
if (writeValueManually)
|
||||
if (lineEdit.writeValueManually)
|
||||
return
|
||||
|
||||
if (!__dirty)
|
||||
if (!lineEdit.__dirty)
|
||||
return
|
||||
|
||||
if (backendValue.isTranslated) {
|
||||
setTranslateExpression()
|
||||
if (lineEdit.backendValue.isTranslated) {
|
||||
lineEdit.setTranslateExpression()
|
||||
} else {
|
||||
if (writeAsExpression) {
|
||||
if (lineEdit.backendValue.expression !== text)
|
||||
lineEdit.backendValue.expression = text
|
||||
} else if (lineEdit.backendValue.value !== text) {
|
||||
lineEdit.backendValue.value = text
|
||||
if (lineEdit.writeAsExpression) {
|
||||
if (lineEdit.backendValue.expression !== lineEdit.text)
|
||||
lineEdit.backendValue.expression = lineEdit.text
|
||||
} else if (lineEdit.backendValue.value !== lineEdit.text) {
|
||||
lineEdit.backendValue.value = lineEdit.text
|
||||
}
|
||||
}
|
||||
__dirty = false
|
||||
lineEdit.__dirty = false
|
||||
}
|
||||
|
||||
property bool isTranslated: colorLogic.backendValue === undefined ? false
|
||||
: colorLogic.backendValue.isTranslated
|
||||
|
||||
translationIndicator.onClicked: {
|
||||
if (translationIndicator.checked) {
|
||||
if (lineEdit.translationIndicator.checked) {
|
||||
setTranslateExpression()
|
||||
} else {
|
||||
var textValue = lineEdit.text
|
||||
@ -141,7 +146,8 @@ StudioControls.TextField {
|
||||
colorLogic.evaluate()
|
||||
}
|
||||
|
||||
property variant backendValueValueInternal: backendValue === undefined ? 0 : backendValue.value
|
||||
property variant backendValueValueInternal: lineEdit.backendValue === undefined ? 0
|
||||
: lineEdit.backendValue.value
|
||||
onBackendValueValueInternalChanged: {
|
||||
if (lineEdit.backendValue === undefined)
|
||||
lineEdit.translationIndicator.checked = false
|
||||
@ -155,15 +161,4 @@ StudioControls.TextField {
|
||||
else
|
||||
lineEdit.translationIndicator.checked = lineEdit.backendValue.isTranslated
|
||||
}
|
||||
|
||||
function escapeString(string) {
|
||||
var str = string
|
||||
str = str.replace(/\\/g, "\\\\")
|
||||
str.replace(/\"/g, "\\\"")
|
||||
str = str.replace(/\t/g, "\\t")
|
||||
str = str.replace(/\r/g, "\\r")
|
||||
str = str.replace(/\n/g, '\\n')
|
||||
return str
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import StudioTheme 1.0 as StudioTheme
|
||||
import QtQuickDesignerTheme 1.0
|
||||
|
||||
Row {
|
||||
id: urlChooser
|
||||
id: root
|
||||
|
||||
property variant backendValue
|
||||
property color textColor: colorLogic.highlight ? colorLogic.textColor
|
||||
@ -47,22 +47,24 @@ Row {
|
||||
FileResourcesModel {
|
||||
id: fileModel
|
||||
modelNodeBackendProperty: modelNodeBackend
|
||||
filter: urlChooser.filter
|
||||
filter: root.filter
|
||||
}
|
||||
|
||||
ColorLogic {
|
||||
id: colorLogic
|
||||
backendValue: urlChooser.backendValue
|
||||
backendValue: root.backendValue
|
||||
}
|
||||
|
||||
StudioControls.ComboBox {
|
||||
StudioControls.FilterComboBox {
|
||||
id: comboBox
|
||||
|
||||
property ListModel items: ListModel {}
|
||||
property ListModel listModel: ListModel {}
|
||||
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
+ StudioTheme.Values.actionIndicatorWidth
|
||||
width: implicitWidth
|
||||
allowUserInput: true
|
||||
|
||||
// Note: highlightedIndex property isn't used because it has no setter and it doesn't reset
|
||||
// when the combobox is closed by focusing on some other control.
|
||||
property int hoverIndex: -1
|
||||
@ -70,7 +72,7 @@ Row {
|
||||
ToolTip {
|
||||
id: toolTip
|
||||
visible: comboBox.hover && toolTip.text !== ""
|
||||
text: urlChooser.backendValue.valueToString
|
||||
text: root.backendValue.valueToString
|
||||
delay: StudioTheme.Values.toolTipDelay
|
||||
height: StudioTheme.Values.toolTipHeight
|
||||
background: Rectangle {
|
||||
@ -88,27 +90,39 @@ Row {
|
||||
delegate: ItemDelegate {
|
||||
required property string fullPath
|
||||
required property string name
|
||||
required property int group
|
||||
required property int index
|
||||
|
||||
id: delegateItem
|
||||
width: parent.width
|
||||
id: delegateRoot
|
||||
width: comboBox.popup.width - comboBox.popup.leftPadding - comboBox.popup.rightPadding
|
||||
- (comboBox.popupScrollBar.visible ? comboBox.popupScrollBar.contentItem.implicitWidth + 2
|
||||
: 0) // TODO Magic number
|
||||
height: StudioTheme.Values.height - 2 * StudioTheme.Values.border
|
||||
padding: 0
|
||||
highlighted: comboBox.highlightedIndex === index
|
||||
hoverEnabled: true
|
||||
highlighted: comboBox.highlightedIndex === delegateRoot.DelegateModel.itemsIndex
|
||||
|
||||
onHoveredChanged: {
|
||||
if (delegateRoot.hovered && !comboBox.popupMouseArea.active)
|
||||
comboBox.setHighlightedIndexItems(delegateRoot.DelegateModel.itemsIndex)
|
||||
}
|
||||
|
||||
onClicked: comboBox.selectItem(delegateRoot.DelegateModel.itemsIndex)
|
||||
|
||||
indicator: Item {
|
||||
id: itemDelegateIconArea
|
||||
width: delegateItem.height
|
||||
height: delegateItem.height
|
||||
width: delegateRoot.height
|
||||
height: delegateRoot.height
|
||||
|
||||
Label {
|
||||
id: itemDelegateIcon
|
||||
text: StudioTheme.Constants.tickIcon
|
||||
color: delegateItem.highlighted ? StudioTheme.Values.themeTextSelectedTextColor
|
||||
color: delegateRoot.highlighted ? StudioTheme.Values.themeTextSelectedTextColor
|
||||
: StudioTheme.Values.themeTextColor
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti
|
||||
visible: comboBox.currentIndex === index ? true : false
|
||||
visible: comboBox.currentIndex === delegateRoot.DelegateModel.itemsIndex ? true
|
||||
: false
|
||||
anchors.fill: parent
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@ -119,7 +133,7 @@ Row {
|
||||
contentItem: Text {
|
||||
leftPadding: itemDelegateIconArea.width
|
||||
text: name
|
||||
color: delegateItem.highlighted ? StudioTheme.Values.themeTextSelectedTextColor
|
||||
color: delegateRoot.highlighted ? StudioTheme.Values.themeTextSelectedTextColor
|
||||
: StudioTheme.Values.themeTextColor
|
||||
font: comboBox.font
|
||||
elide: Text.ElideRight
|
||||
@ -127,17 +141,17 @@ Row {
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: itemDelegateBackground
|
||||
x: 0
|
||||
y: 0
|
||||
width: delegateItem.width
|
||||
height: delegateItem.height
|
||||
color: delegateItem.highlighted ? StudioTheme.Values.themeInteraction : "transparent"
|
||||
width: delegateRoot.width
|
||||
height: delegateRoot.height
|
||||
color: delegateRoot.highlighted ? StudioTheme.Values.themeInteraction
|
||||
: "transparent"
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
id: itemToolTip
|
||||
visible: delegateItem.hovered && comboBox.highlightedIndex === index
|
||||
visible: delegateRoot.hovered && comboBox.highlightedIndex === index
|
||||
text: fullPath
|
||||
delay: StudioTheme.Values.toolTipDelay
|
||||
height: StudioTheme.Values.toolTipHeight
|
||||
@ -161,7 +175,7 @@ Row {
|
||||
|
||||
ExtendedFunctionLogic {
|
||||
id: extFuncLogic
|
||||
backendValue: urlChooser.backendValue
|
||||
backendValue: root.backendValue
|
||||
onReseted: comboBox.editText = ""
|
||||
}
|
||||
|
||||
@ -181,20 +195,15 @@ Row {
|
||||
|
||||
// Takes into account applied bindings
|
||||
property string textValue: {
|
||||
if (urlChooser.backendValue.isBound)
|
||||
return urlChooser.backendValue.expression
|
||||
if (root.backendValue.isBound)
|
||||
return root.backendValue.expression
|
||||
|
||||
var fullPath = urlChooser.backendValue.valueToString
|
||||
var fullPath = root.backendValue.valueToString
|
||||
return fullPath.substr(fullPath.lastIndexOf('/') + 1)
|
||||
}
|
||||
|
||||
onTextValueChanged: comboBox.setCurrentText(comboBox.textValue)
|
||||
|
||||
editable: true
|
||||
textRole: "name"
|
||||
valueRole: "fullPath"
|
||||
model: comboBox.items
|
||||
|
||||
onModelChanged: {
|
||||
if (!comboBox.isComplete)
|
||||
return
|
||||
@ -206,20 +215,14 @@ Row {
|
||||
if (!comboBox.isComplete)
|
||||
return
|
||||
|
||||
var inputValue = comboBox.editText
|
||||
let inputValue = comboBox.editText
|
||||
|
||||
// Check if value set by user matches with a name in the model then pick the full path
|
||||
var index = comboBox.find(inputValue)
|
||||
let index = comboBox.find(inputValue)
|
||||
if (index !== -1)
|
||||
inputValue = comboBox.items.get(index).fullPath
|
||||
inputValue = comboBox.items.get(index).model.fullPath
|
||||
|
||||
// Get the currently assigned backend value, extract its file name and compare it to the
|
||||
// input value. If they differ the new value needs to be set.
|
||||
var currentValue = urlChooser.backendValue.value
|
||||
var fileName = currentValue.substr(currentValue.lastIndexOf('/') + 1);
|
||||
|
||||
if (fileName !== inputValue)
|
||||
urlChooser.backendValue.value = inputValue
|
||||
root.backendValue.value = inputValue
|
||||
|
||||
comboBox.dirty = false
|
||||
}
|
||||
@ -234,14 +237,16 @@ Row {
|
||||
}
|
||||
|
||||
function handleActivate(index) {
|
||||
if (urlChooser.backendValue === undefined || !comboBox.isComplete)
|
||||
if (root.backendValue === undefined || !comboBox.isComplete)
|
||||
return
|
||||
|
||||
if (index === -1) // select first item if index is invalid
|
||||
index = 0
|
||||
let inputValue = comboBox.editText
|
||||
|
||||
if (urlChooser.backendValue.value !== comboBox.items.get(index).fullPath)
|
||||
urlChooser.backendValue.value = comboBox.items.get(index).fullPath
|
||||
if (index >= 0)
|
||||
inputValue = comboBox.items.get(index).model.fullPath
|
||||
|
||||
if (root.backendValue.value !== inputValue)
|
||||
root.backendValue.value = inputValue
|
||||
|
||||
comboBox.dirty = false
|
||||
}
|
||||
@ -250,7 +255,7 @@ Row {
|
||||
// Hack to style the text input
|
||||
for (var i = 0; i < comboBox.children.length; i++) {
|
||||
if (comboBox.children[i].text !== undefined) {
|
||||
comboBox.children[i].color = urlChooser.textColor
|
||||
comboBox.children[i].color = root.textColor
|
||||
comboBox.children[i].anchors.rightMargin = 34
|
||||
}
|
||||
}
|
||||
@ -261,36 +266,44 @@ Row {
|
||||
|
||||
function createModel() {
|
||||
// Build the combobox model
|
||||
comboBox.items.clear()
|
||||
comboBox.listModel.clear()
|
||||
// While adding items to the model this binding needs to be interrupted, otherwise the
|
||||
// update function of the SortFilterModel is triggered every time on append() which makes
|
||||
// QtDS very slow. This will happen when selecting different items in the scene.
|
||||
comboBox.model = {}
|
||||
|
||||
if (urlChooser.defaultItems !== undefined) {
|
||||
for (var i = 0; i < urlChooser.defaultItems.length; ++i) {
|
||||
comboBox.items.append({
|
||||
fullPath: urlChooser.defaultItems[i],
|
||||
name: urlChooser.defaultItems[i]
|
||||
if (root.defaultItems !== undefined) {
|
||||
for (var i = 0; i < root.defaultItems.length; ++i) {
|
||||
comboBox.listModel.append({
|
||||
fullPath: root.defaultItems[i],
|
||||
name: root.defaultItems[i],
|
||||
group: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = 0; j < fileModel.fullPathModel.length; ++j) {
|
||||
comboBox.items.append({
|
||||
comboBox.listModel.append({
|
||||
fullPath: fileModel.fullPathModel[j],
|
||||
name: fileModel.fileNameModel[j]
|
||||
name: fileModel.fileNameModel[j],
|
||||
group: 1
|
||||
})
|
||||
}
|
||||
|
||||
comboBox.model = Qt.binding(function() { return comboBox.listModel })
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: fileModel
|
||||
function onFullPathModelChanged() {
|
||||
urlChooser.createModel()
|
||||
root.createModel()
|
||||
comboBox.setCurrentText(comboBox.textValue)
|
||||
}
|
||||
}
|
||||
|
||||
onDefaultItemsChanged: urlChooser.createModel()
|
||||
onDefaultItemsChanged: root.createModel()
|
||||
|
||||
Component.onCompleted: urlChooser.createModel()
|
||||
Component.onCompleted: root.createModel()
|
||||
|
||||
function indexOf(model, criteria) {
|
||||
for (var i = 0; i < model.count; ++i) {
|
||||
@ -305,16 +318,16 @@ Row {
|
||||
function onStateChanged(state) {
|
||||
// update currentIndex when the popup opens to override the default behavior in super classes
|
||||
// that selects currentIndex based on values in the combo box.
|
||||
if (comboBox.popup.opened && !urlChooser.backendValue.isBound) {
|
||||
var index = urlChooser.indexOf(comboBox.items,
|
||||
if (comboBox.popup.opened && !root.backendValue.isBound) {
|
||||
var index = root.indexOf(comboBox.items,
|
||||
function(item) {
|
||||
return item.fullPath === urlChooser.backendValue.value
|
||||
return item.fullPath === root.backendValue.value
|
||||
})
|
||||
|
||||
if (index !== -1) {
|
||||
comboBox.currentIndex = index
|
||||
comboBox.hoverIndex = index
|
||||
comboBox.editText = comboBox.items.get(index).name
|
||||
comboBox.editText = comboBox.items.get(index).model.name
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,11 +337,11 @@ Row {
|
||||
|
||||
IconIndicator {
|
||||
icon: StudioTheme.Constants.addFile
|
||||
iconColor: urlChooser.textColor
|
||||
iconColor: root.textColor
|
||||
onClicked: {
|
||||
fileModel.openFileDialog()
|
||||
if (fileModel.fileName !== "")
|
||||
urlChooser.backendValue.value = fileModel.fileName
|
||||
root.backendValue.value = fileModel.fileName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,16 +50,16 @@ Rectangle {
|
||||
id: checkIndicatorMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onPressed: {
|
||||
onClicked: {
|
||||
if (myControl.activeFocus)
|
||||
myControl.focus = false
|
||||
|
||||
if (myPopup.opened) {
|
||||
myPopup.close()
|
||||
} else {
|
||||
myPopup.open()
|
||||
myPopup.forceActiveFocus()
|
||||
}
|
||||
|
||||
if (myControl.activeFocus)
|
||||
myControl.focus = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,11 @@ T.ComboBox {
|
||||
comboBoxPopup.close()
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (myComboBox.activeFocus)
|
||||
comboBoxInput.preFocusText = myComboBox.editText
|
||||
}
|
||||
|
||||
ActionIndicator {
|
||||
id: actionIndicator
|
||||
myControl: myComboBox
|
||||
@ -76,19 +81,22 @@ T.ComboBox {
|
||||
|
||||
contentItem: ComboBoxInput {
|
||||
id: comboBoxInput
|
||||
|
||||
property string preFocusText: ""
|
||||
|
||||
myControl: myComboBox
|
||||
text: myComboBox.editText
|
||||
|
||||
onEditingFinished: {
|
||||
comboBoxInput.deselect()
|
||||
comboBoxInput.focus = false
|
||||
myComboBox.focus = false
|
||||
|
||||
// Only trigger the signal, if the value was modified
|
||||
if (myComboBox.dirty) {
|
||||
myTimer.stop()
|
||||
myComboBox.dirty = false
|
||||
myComboBox.compressedActivated(myComboBox.find(myComboBox.editText),
|
||||
ComboBox.ActivatedReason.EditingFinished)
|
||||
myComboBox.accepted()
|
||||
}
|
||||
}
|
||||
onTextEdited: myComboBox.dirty = true
|
||||
@ -276,7 +284,7 @@ T.ComboBox {
|
||||
PropertyChanges {
|
||||
target: comboBoxBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundInteraction
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
border.color: StudioTheme.Values.themeControlOutlineInteraction
|
||||
}
|
||||
StateChangeScript {
|
||||
script: comboBoxPopup.close()
|
||||
@ -312,7 +320,10 @@ T.ComboBox {
|
||||
]
|
||||
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape)
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
myComboBox.editText = comboBoxInput.preFocusText
|
||||
myComboBox.dirty = true
|
||||
myComboBox.focus = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,13 +73,13 @@ TextInput {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: function(mouse) {
|
||||
if (textInput.readOnly) {
|
||||
if (!textInput.myControl.editable) {
|
||||
if (myControl.popup.opened) {
|
||||
myControl.popup.close()
|
||||
myControl.focus = false
|
||||
} else {
|
||||
myControl.forceActiveFocus()
|
||||
myControl.popup.open()
|
||||
myControl.forceActiveFocus()
|
||||
}
|
||||
} else {
|
||||
textInput.forceActiveFocus()
|
||||
|
@ -0,0 +1,752 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Quick 3D.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 or (at your option) any later version
|
||||
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Templates as T
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
enum Interaction { None, TextEdit, Key }
|
||||
|
||||
property int currentInteraction: FilterComboBox.Interaction.None
|
||||
|
||||
property alias model: sortFilterModel.model
|
||||
property alias items: sortFilterModel.items
|
||||
property alias delegate: sortFilterModel.delegate
|
||||
|
||||
property alias font: textInput.font
|
||||
|
||||
// This indicates if the value was committed or the user is still editing
|
||||
property bool editing: false
|
||||
|
||||
// This is the actual filter that is applied on the model
|
||||
property string filter: ""
|
||||
property bool filterActive: root.filter !== ""
|
||||
|
||||
// Accept arbitrary input or only items from the model
|
||||
property bool allowUserInput: false
|
||||
|
||||
property alias editText: textInput.text
|
||||
property int highlightedIndex: -1 // items index
|
||||
property int currentIndex: -1 // items index
|
||||
|
||||
property string autocompleteString: ""
|
||||
|
||||
property bool __isCompleted: false
|
||||
|
||||
property alias actionIndicator: actionIndicator
|
||||
|
||||
// This property is used to indicate the global hover state
|
||||
property bool hover: actionIndicator.hover || textInput.hover || checkIndicator.hover
|
||||
property alias edit: textInput.edit
|
||||
property alias open: popup.visible
|
||||
|
||||
property alias actionIndicatorVisible: actionIndicator.visible
|
||||
property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth
|
||||
property real __actionIndicatorHeight: StudioTheme.Values.actionIndicatorHeight
|
||||
|
||||
property bool dirty: false // user modification flag
|
||||
|
||||
property bool escapePressed: false
|
||||
|
||||
signal accepted()
|
||||
signal activated(int index)
|
||||
signal compressedActivated(int index, int reason)
|
||||
|
||||
enum ActivatedReason { EditingFinished, Other }
|
||||
|
||||
property alias popup: popup
|
||||
property alias popupScrollBar: popupScrollBar
|
||||
property alias popupMouseArea: popupMouseArea
|
||||
|
||||
width: StudioTheme.Values.defaultControlWidth
|
||||
height: StudioTheme.Values.defaultControlHeight
|
||||
implicitHeight: StudioTheme.Values.defaultControlHeight
|
||||
|
||||
function selectItem(itemsIndex) {
|
||||
textInput.text = sortFilterModel.items.get(itemsIndex).model.name
|
||||
root.currentIndex = itemsIndex
|
||||
root.finishEditing()
|
||||
root.activated(itemsIndex)
|
||||
}
|
||||
|
||||
function submitValue() {
|
||||
if (!root.allowUserInput) {
|
||||
// If input isn't according to any item in the model, don't finish editing
|
||||
if (root.highlightedIndex === -1)
|
||||
return
|
||||
|
||||
root.selectItem(root.highlightedIndex)
|
||||
} else {
|
||||
root.currentIndex = -1
|
||||
|
||||
// Only trigger the signal, if the value was modified
|
||||
if (root.dirty) {
|
||||
myTimer.stop()
|
||||
root.dirty = false
|
||||
root.editText = root.editText.trim()
|
||||
}
|
||||
|
||||
root.finishEditing()
|
||||
root.accepted()
|
||||
}
|
||||
}
|
||||
|
||||
function finishEditing() {
|
||||
root.editing = false
|
||||
root.filter = ""
|
||||
root.autocompleteString = ""
|
||||
textInput.focus = false // Remove focus from text field
|
||||
popup.close()
|
||||
}
|
||||
|
||||
function increaseVisibleIndex() {
|
||||
let numItems = sortFilterModel.visibleGroup.count
|
||||
if (!numItems)
|
||||
return
|
||||
|
||||
if (root.highlightedIndex === -1) // Nothing is selected
|
||||
root.setHighlightedIndexVisible(0)
|
||||
else {
|
||||
let currentVisibleIndex = sortFilterModel.items.get(root.highlightedIndex).visibleIndex
|
||||
++currentVisibleIndex
|
||||
|
||||
if (currentVisibleIndex > numItems - 1)
|
||||
currentVisibleIndex = 0
|
||||
|
||||
root.setHighlightedIndexVisible(currentVisibleIndex)
|
||||
}
|
||||
}
|
||||
|
||||
function decreaseVisibleIndex() {
|
||||
let numItems = sortFilterModel.visibleGroup.count
|
||||
if (!numItems)
|
||||
return
|
||||
|
||||
if (root.highlightedIndex === -1) // Nothing is selected
|
||||
root.setHighlightedIndexVisible(numItems - 1)
|
||||
else {
|
||||
let currentVisibleIndex = sortFilterModel.items.get(root.highlightedIndex).visibleIndex
|
||||
--currentVisibleIndex
|
||||
|
||||
if (currentVisibleIndex < 0)
|
||||
currentVisibleIndex = numItems - 1
|
||||
|
||||
root.setHighlightedIndexVisible(currentVisibleIndex)
|
||||
}
|
||||
}
|
||||
|
||||
function updateHighlightedIndex() {
|
||||
// Check if current index is still part of the filtered list, if not set it to 0
|
||||
if (root.highlightedIndex !== -1 && !sortFilterModel.items.get(root.highlightedIndex).inVisible) {
|
||||
root.setHighlightedIndexVisible(0)
|
||||
} else {
|
||||
// Needs to be set in order for ListView to keep its currenIndex up to date, so
|
||||
// scroll position gets updated according to the higlighted item
|
||||
root.setHighlightedIndexItems(root.highlightedIndex)
|
||||
}
|
||||
}
|
||||
|
||||
function setHighlightedIndexItems(itemsIndex) { // items group index
|
||||
root.highlightedIndex = itemsIndex
|
||||
|
||||
if (itemsIndex === -1)
|
||||
listView.currentIndex = -1
|
||||
else
|
||||
listView.currentIndex = sortFilterModel.items.get(itemsIndex).visibleIndex
|
||||
}
|
||||
|
||||
function setHighlightedIndexVisible(visibleIndex) { // visible group index
|
||||
if (visibleIndex === -1)
|
||||
root.highlightedIndex = -1
|
||||
else
|
||||
root.highlightedIndex = sortFilterModel.visibleGroup.get(visibleIndex).itemsIndex
|
||||
|
||||
listView.currentIndex = visibleIndex
|
||||
}
|
||||
|
||||
function updateAutocomplete() {
|
||||
if (root.highlightedIndex === -1)
|
||||
root.autocompleteString = ""
|
||||
else {
|
||||
let suggestion = sortFilterModel.items.get(root.highlightedIndex).model.name
|
||||
root.autocompleteString = suggestion.substring(textInput.text.length)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO is this already case insensitiv?!
|
||||
function find(text) {
|
||||
for (let i = 0; i < sortFilterModel.items.count; ++i)
|
||||
if (sortFilterModel.items.get(i).model.name === text)
|
||||
return i
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: myTimer
|
||||
property int activatedIndex
|
||||
repeat: false
|
||||
running: false
|
||||
interval: 100
|
||||
onTriggered: root.compressedActivated(myTimer.activatedIndex,
|
||||
ComboBox.ActivatedReason.Other)
|
||||
}
|
||||
|
||||
onActivated: function(index) {
|
||||
myTimer.activatedIndex = index
|
||||
myTimer.restart()
|
||||
}
|
||||
|
||||
onHighlightedIndexChanged: {
|
||||
if (root.editing || (root.editText === "" && root.allowUserInput))
|
||||
root.updateAutocomplete()
|
||||
}
|
||||
|
||||
DelegateModel {
|
||||
id: noMatchesModel
|
||||
|
||||
model: ListModel {
|
||||
ListElement { name: "No matches" }
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: noMatchesDelegate
|
||||
width: popup.width - popup.leftPadding - popup.rightPadding
|
||||
- (popupScrollBar.visible ? popupScrollBar.contentItem.implicitWidth + 2
|
||||
: 0) // TODO Magic number
|
||||
height: StudioTheme.Values.height - 2 * StudioTheme.Values.border
|
||||
padding: 0
|
||||
|
||||
contentItem: Text {
|
||||
leftPadding: StudioTheme.Values.inputHorizontalPadding
|
||||
text: name
|
||||
font.italic: true
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
x: 0
|
||||
y: 0
|
||||
width: noMatchesDelegate.width
|
||||
height: noMatchesDelegate.height
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SortFilterModel {
|
||||
id: sortFilterModel
|
||||
|
||||
filterAcceptsItem: function(item) {
|
||||
return item.name.toLowerCase().startsWith(root.filter.toLowerCase())
|
||||
}
|
||||
|
||||
lessThan: function(left, right) {
|
||||
if (left.group === right.group) {
|
||||
return left.name.toLowerCase().localeCompare(right.name.toLowerCase())
|
||||
}
|
||||
|
||||
return left.group - right.group
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: delegateRoot
|
||||
width: popup.width - popup.leftPadding - popup.rightPadding
|
||||
- (popupScrollBar.visible ? popupScrollBar.contentItem.implicitWidth + 2
|
||||
: 0) // TODO Magic number
|
||||
height: StudioTheme.Values.height - 2 * StudioTheme.Values.border
|
||||
padding: 0
|
||||
hoverEnabled: true
|
||||
highlighted: root.highlightedIndex === delegateRoot.DelegateModel.itemsIndex
|
||||
|
||||
onHoveredChanged: {
|
||||
if (delegateRoot.hovered && !popupMouseArea.active)
|
||||
root.setHighlightedIndexItems(delegateRoot.DelegateModel.itemsIndex)
|
||||
}
|
||||
|
||||
onClicked: root.selectItem(delegateRoot.DelegateModel.itemsIndex)
|
||||
|
||||
indicator: Item {
|
||||
id: itemDelegateIconArea
|
||||
width: delegateRoot.height
|
||||
height: delegateRoot.height
|
||||
|
||||
T.Label {
|
||||
id: itemDelegateIcon
|
||||
text: StudioTheme.Constants.tickIcon
|
||||
color: delegateRoot.highlighted ? StudioTheme.Values.themeTextSelectedTextColor
|
||||
: StudioTheme.Values.themeTextColor
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti
|
||||
visible: root.currentIndex === delegateRoot.DelegateModel.itemsIndex ? true
|
||||
: false
|
||||
anchors.fill: parent
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
leftPadding: itemDelegateIconArea.width
|
||||
text: name
|
||||
color: delegateRoot.highlighted ? StudioTheme.Values.themeTextSelectedTextColor
|
||||
: StudioTheme.Values.themeTextColor
|
||||
font: textInput.font
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
x: 0
|
||||
y: 0
|
||||
width: delegateRoot.width
|
||||
height: delegateRoot.height
|
||||
color: delegateRoot.highlighted ? StudioTheme.Values.themeInteraction
|
||||
: "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
onUpdated: {
|
||||
if (!root.__isCompleted)
|
||||
return
|
||||
|
||||
if (sortFilterModel.count === 0)
|
||||
root.setHighlightedIndexVisible(-1)
|
||||
else {
|
||||
if (root.highlightedIndex === -1 && !root.allowUserInput)
|
||||
root.setHighlightedIndexVisible(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
ActionIndicator {
|
||||
id: actionIndicator
|
||||
myControl: root
|
||||
x: 0
|
||||
y: 0
|
||||
width: actionIndicator.visible ? root.__actionIndicatorWidth : 0
|
||||
height: actionIndicator.visible ? root.__actionIndicatorHeight : 0
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: textInput
|
||||
|
||||
property bool hover: textInputMouseArea.containsMouse && textInput.enabled
|
||||
property bool edit: textInput.activeFocus
|
||||
property string preFocusText: ""
|
||||
|
||||
x: 0
|
||||
y: 0
|
||||
z: 2
|
||||
width: root.width - actionIndicator.width
|
||||
height: root.height
|
||||
leftPadding: StudioTheme.Values.inputHorizontalPadding
|
||||
rightPadding: StudioTheme.Values.inputHorizontalPadding + checkIndicator.width
|
||||
+ StudioTheme.Values.border
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
selectionColor: StudioTheme.Values.themeTextSelectionColor
|
||||
selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
|
||||
selectByMouse: true
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
id: textInputBackground
|
||||
z: -1
|
||||
width: textInput.width
|
||||
height: textInput.height
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
border.width: StudioTheme.Values.border
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: textInputMouseArea
|
||||
anchors.fill: parent
|
||||
enabled: true
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
acceptedButtons: Qt.LeftButton
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: function(mouse) {
|
||||
textInput.forceActiveFocus()
|
||||
mouse.accepted = false
|
||||
}
|
||||
|
||||
// Stop scrollable views from scrolling while ComboBox is in edit mode and the mouse
|
||||
// pointer is on top of it. We might add wheel selection in the future.
|
||||
onWheel: function(wheel) {
|
||||
wheel.accepted = root.edit
|
||||
}
|
||||
}
|
||||
|
||||
onEditingFinished: {
|
||||
if (root.escapePressed) {
|
||||
root.escapePressed = false
|
||||
root.editText = textInput.preFocusText
|
||||
} else {
|
||||
if (root.currentInteraction === FilterComboBox.Interaction.TextEdit) {
|
||||
if (root.dirty)
|
||||
root.submitValue()
|
||||
} else if (root.currentInteraction === FilterComboBox.Interaction.Key) {
|
||||
root.selectItem(root.highlightedIndex)
|
||||
}
|
||||
}
|
||||
|
||||
sortFilterModel.update()
|
||||
}
|
||||
|
||||
onTextEdited: {
|
||||
root.currentInteraction = FilterComboBox.Interaction.TextEdit
|
||||
root.editing = true
|
||||
popupMouseArea.active = true
|
||||
root.dirty = true
|
||||
|
||||
if (textInput.text !== "")
|
||||
root.filter = textInput.text
|
||||
else {
|
||||
root.filter = ""
|
||||
root.autocompleteString = ""
|
||||
}
|
||||
|
||||
if (!popup.visible)
|
||||
popup.open()
|
||||
|
||||
sortFilterModel.update()
|
||||
|
||||
if (!root.allowUserInput)
|
||||
root.updateHighlightedIndex()
|
||||
else
|
||||
root.setHighlightedIndexVisible(-1)
|
||||
|
||||
root.updateAutocomplete()
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (textInput.activeFocus) {
|
||||
popup.open()
|
||||
textInput.preFocusText = textInput.text
|
||||
} else
|
||||
popup.close()
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "default"
|
||||
when: root.enabled && !textInput.edit && !root.hover && !root.open
|
||||
PropertyChanges {
|
||||
target: textInputBackground
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
}
|
||||
PropertyChanges {
|
||||
target: textInputMouseArea
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "globalHover"
|
||||
when: root.hover && !textInput.hover && !textInput.edit && !root.open
|
||||
PropertyChanges {
|
||||
target: textInputBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundGlobalHover
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "hover"
|
||||
when: textInput.hover && root.hover && !textInput.edit
|
||||
PropertyChanges {
|
||||
target: textInputBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundHover
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "edit"
|
||||
when: root.edit
|
||||
PropertyChanges {
|
||||
target: textInputBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundInteraction
|
||||
border.color: StudioTheme.Values.themeControlOutlineInteraction
|
||||
}
|
||||
PropertyChanges {
|
||||
target: textInputMouseArea
|
||||
cursorShape: Qt.IBeamCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "disable"
|
||||
when: !root.enabled
|
||||
PropertyChanges {
|
||||
target: textInputBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundDisabled
|
||||
}
|
||||
PropertyChanges {
|
||||
target: textInput
|
||||
color: StudioTheme.Values.themeTextColorDisabled
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Text {
|
||||
visible: root.autocompleteString !== ""
|
||||
text: root.autocompleteString
|
||||
x: textInput.leftPadding + textMetrics.advanceWidth
|
||||
y: (textInput.height - Math.ceil(textMetrics.height)) / 2
|
||||
color: "gray" // TODO proper color value
|
||||
font: textInput.font
|
||||
renderType: textInput.renderType
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: textMetrics
|
||||
font: textInput.font
|
||||
text: textInput.text
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: checkIndicator
|
||||
|
||||
property bool hover: checkIndicatorMouseArea.containsMouse && checkIndicator.enabled
|
||||
property bool pressed: checkIndicatorMouseArea.containsPress
|
||||
property bool checked: popup.visible
|
||||
|
||||
x: textInput.width - checkIndicator.width - StudioTheme.Values.border
|
||||
y: StudioTheme.Values.border
|
||||
width: StudioTheme.Values.height - StudioTheme.Values.border
|
||||
height: textInput.height - (StudioTheme.Values.border * 2)
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
border.width: 0
|
||||
|
||||
MouseArea {
|
||||
id: checkIndicatorMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
if (popup.visible)
|
||||
popup.close()
|
||||
else
|
||||
popup.open()
|
||||
|
||||
if (!textInput.activeFocus) {
|
||||
textInput.forceActiveFocus()
|
||||
textInput.selectAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T.Label {
|
||||
id: checkIndicatorIcon
|
||||
anchors.fill: parent
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
text: StudioTheme.Constants.upDownSquare2
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: StudioTheme.Values.sliderControlSizeMulti
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "default"
|
||||
when: root.enabled && checkIndicator.enabled && !root.edit
|
||||
&& !checkIndicator.hover && !root.hover
|
||||
&& !checkIndicator.checked
|
||||
PropertyChanges {
|
||||
target: checkIndicator
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "globalHover"
|
||||
when: root.enabled && checkIndicator.enabled
|
||||
&& !checkIndicator.hover && root.hover && !root.edit
|
||||
&& !checkIndicator.checked
|
||||
PropertyChanges {
|
||||
target: checkIndicator
|
||||
color: StudioTheme.Values.themeControlBackgroundGlobalHover
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "hover"
|
||||
when: root.enabled && checkIndicator.enabled
|
||||
&& checkIndicator.hover && root.hover && !checkIndicator.pressed
|
||||
&& !checkIndicator.checked
|
||||
PropertyChanges {
|
||||
target: checkIndicator
|
||||
color: StudioTheme.Values.themeControlBackgroundHover
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "check"
|
||||
when: checkIndicator.checked
|
||||
PropertyChanges {
|
||||
target: checkIndicatorIcon
|
||||
color: StudioTheme.Values.themeIconColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: checkIndicator
|
||||
color: StudioTheme.Values.themeInteraction
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "press"
|
||||
when: root.enabled && checkIndicator.enabled
|
||||
&& checkIndicator.pressed
|
||||
PropertyChanges {
|
||||
target: checkIndicatorIcon
|
||||
color: StudioTheme.Values.themeIconColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: checkIndicator
|
||||
color: StudioTheme.Values.themeInteraction
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "disable"
|
||||
when: !root.enabled
|
||||
PropertyChanges {
|
||||
target: checkIndicator
|
||||
color: StudioTheme.Values.themeControlBackgroundDisabled
|
||||
}
|
||||
PropertyChanges {
|
||||
target: checkIndicatorIcon
|
||||
color: StudioTheme.Values.themeTextColorDisabled
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T.Popup {
|
||||
id: popup
|
||||
x: textInput.x + StudioTheme.Values.border
|
||||
y: textInput.height
|
||||
width: textInput.width - (StudioTheme.Values.border * 2)
|
||||
height: Math.min(popup.contentItem.implicitHeight + popup.topPadding + popup.bottomPadding,
|
||||
root.Window.height - popup.topMargin - popup.bottomMargin,
|
||||
StudioTheme.Values.maxComboBoxPopupHeight)
|
||||
padding: StudioTheme.Values.border
|
||||
margins: 0 // If not defined margin will be -1
|
||||
closePolicy: T.Popup.NoAutoClose
|
||||
|
||||
contentItem: ListView {
|
||||
id: listView
|
||||
clip: true
|
||||
implicitHeight: listView.contentHeight
|
||||
highlightMoveVelocity: -1
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
flickDeceleration: 10000
|
||||
|
||||
model: {
|
||||
if (popup.visible)
|
||||
return sortFilterModel.count ? sortFilterModel : noMatchesModel
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
id: popupScrollBar
|
||||
visible: listView.height < listView.contentHeight
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: StudioTheme.Values.themePopupBackground
|
||||
border.width: 0
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
// Reset the highlightedIndex of ListView as binding with condition didn't work
|
||||
if (root.highlightedIndex !== -1)
|
||||
root.setHighlightedIndexItems(root.highlightedIndex)
|
||||
}
|
||||
|
||||
onAboutToShow: {
|
||||
// Select first item in list
|
||||
if (root.highlightedIndex === -1 && sortFilterModel.count && !root.allowUserInput)
|
||||
root.setHighlightedIndexVisible(0)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
// This is MouseArea is intended to block the hovered property of an ItemDelegate
|
||||
// when the ListView changes due to Key interaction.
|
||||
|
||||
id: popupMouseArea
|
||||
property bool active: true
|
||||
|
||||
anchors.fill: parent
|
||||
enabled: popup.visible && popupMouseArea.active
|
||||
hoverEnabled: true
|
||||
onPositionChanged: { popupMouseArea.active = false }
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onDownPressed: {
|
||||
if (!sortFilterModel.visibleGroup.count)
|
||||
return
|
||||
|
||||
root.currentInteraction = FilterComboBox.Interaction.Key
|
||||
root.increaseVisibleIndex()
|
||||
|
||||
popupMouseArea.active = true
|
||||
}
|
||||
|
||||
Keys.onUpPressed: {
|
||||
if (!sortFilterModel.visibleGroup.count)
|
||||
return
|
||||
|
||||
root.currentInteraction = FilterComboBox.Interaction.Key
|
||||
root.decreaseVisibleIndex()
|
||||
|
||||
popupMouseArea.active = true
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
root.escapePressed = true
|
||||
root.finishEditing()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
let index = root.find(root.editText)
|
||||
root.currentIndex = index
|
||||
root.highlightedIndex = index // TODO might not be intended
|
||||
|
||||
root.__isCompleted = true
|
||||
}
|
||||
}
|
@ -79,6 +79,8 @@ T.SpinBox {
|
||||
|
||||
property alias compressedValueTimer: myTimer
|
||||
|
||||
property string preFocusText: ""
|
||||
|
||||
signal realValueModified
|
||||
signal compressedRealValueModified
|
||||
signal dragStarted
|
||||
@ -162,6 +164,8 @@ T.SpinBox {
|
||||
validator: doubleValidator
|
||||
|
||||
function handleEditingFinished() {
|
||||
mySpinBox.focus = false
|
||||
|
||||
// Keep the dirty state before calling setValueFromInput(),
|
||||
// it will be set to false (cleared) internally
|
||||
var valueModified = mySpinBox.dirty
|
||||
@ -174,7 +178,7 @@ T.SpinBox {
|
||||
mySpinBox.compressedRealValueModified()
|
||||
}
|
||||
|
||||
onEditingFinished: handleEditingFinished()
|
||||
onEditingFinished: spinBoxInput.handleEditingFinished()
|
||||
onTextEdited: mySpinBox.dirty = true
|
||||
}
|
||||
|
||||
@ -281,7 +285,7 @@ T.SpinBox {
|
||||
id: myTimer
|
||||
repeat: false
|
||||
running: false
|
||||
interval: 200
|
||||
interval: 400
|
||||
onTriggered: mySpinBox.compressedRealValueModified()
|
||||
}
|
||||
|
||||
@ -306,8 +310,10 @@ T.SpinBox {
|
||||
}
|
||||
onDisplayTextChanged: spinBoxInput.text = mySpinBox.displayText
|
||||
onActiveFocusChanged: {
|
||||
if (mySpinBox.activeFocus) // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason)
|
||||
if (mySpinBox.activeFocus) { // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason)
|
||||
mySpinBox.preFocusText = spinBoxInput.text
|
||||
spinBoxInput.selectAll()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: function(event) {
|
||||
@ -333,8 +339,11 @@ T.SpinBox {
|
||||
mySpinBox.realStepSize = currStepSize
|
||||
}
|
||||
|
||||
if (event.key === Qt.Key_Escape)
|
||||
mySpinBox.focus = false
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
spinBoxInput.text = mySpinBox.preFocusText
|
||||
mySpinBox.dirty = true
|
||||
spinBoxInput.handleEditingFinished()
|
||||
}
|
||||
}
|
||||
|
||||
function clamp(v, lo, hi) {
|
||||
|
@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Quick 3D.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 or (at your option) any later version
|
||||
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
||||
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick
|
||||
import QtQml.Models
|
||||
|
||||
DelegateModel {
|
||||
id: delegateModel
|
||||
|
||||
property var visibleGroup: visibleItems
|
||||
|
||||
property var lessThan: function(left, right) { return true }
|
||||
property var filterAcceptsItem: function(item) { return true }
|
||||
|
||||
signal updated()
|
||||
|
||||
function update() {
|
||||
if (delegateModel.items.count > 0) {
|
||||
delegateModel.items.setGroups(0, delegateModel.items.count, "items")
|
||||
}
|
||||
|
||||
// Filter items
|
||||
var visible = []
|
||||
for (var i = 0; i < delegateModel.items.count; ++i) {
|
||||
var item = delegateModel.items.get(i)
|
||||
if (delegateModel.filterAcceptsItem(item.model)) {
|
||||
visible.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the list of visible items
|
||||
visible.sort(function(a, b) {
|
||||
return delegateModel.lessThan(a.model, b.model);
|
||||
});
|
||||
|
||||
// Add all items to the visible group
|
||||
for (i = 0; i < visible.length; ++i) {
|
||||
item = visible[i]
|
||||
item.inVisible = true
|
||||
if (item.visibleIndex !== i) {
|
||||
visibleItems.move(item.visibleIndex, i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
delegateModel.updated()
|
||||
}
|
||||
|
||||
items.onChanged: delegateModel.update()
|
||||
onLessThanChanged: delegateModel.update()
|
||||
onFilterAcceptsItemChanged: delegateModel.update()
|
||||
|
||||
groups: DelegateModelGroup {
|
||||
id: visibleItems
|
||||
|
||||
name: "visible"
|
||||
includeByDefault: false
|
||||
}
|
||||
|
||||
filterOnGroup: "visible"
|
||||
}
|
@ -28,15 +28,15 @@ import QtQuick.Templates 2.15 as T
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
T.TextField {
|
||||
id: myTextField
|
||||
id: root
|
||||
|
||||
property alias actionIndicator: actionIndicator
|
||||
property alias translationIndicator: translationIndicator
|
||||
|
||||
// This property is used to indicate the global hover state
|
||||
property bool hover: (actionIndicator.hover || mouseArea.containsMouse
|
||||
|| translationIndicator.hover) && myTextField.enabled
|
||||
property bool edit: myTextField.activeFocus
|
||||
|| translationIndicator.hover) && root.enabled
|
||||
property bool edit: root.activeFocus
|
||||
|
||||
property alias actionIndicatorVisible: actionIndicator.visible
|
||||
property real __actionIndicatorWidth: StudioTheme.Values.actionIndicatorWidth
|
||||
@ -46,6 +46,8 @@ T.TextField {
|
||||
property real __translationIndicatorWidth: StudioTheme.Values.translationIndicatorWidth
|
||||
property real __translationIndicatorHeight: StudioTheme.Values.translationIndicatorHeight
|
||||
|
||||
property string preFocusText: ""
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
|
||||
@ -78,7 +80,7 @@ T.TextField {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: function(mouse) {
|
||||
if (mouse.button === Qt.RightButton)
|
||||
contextMenu.popup(myTextField)
|
||||
contextMenu.popup(root)
|
||||
|
||||
mouse.accepted = false
|
||||
}
|
||||
@ -86,43 +88,50 @@ T.TextField {
|
||||
|
||||
onPersistentSelectionChanged: {
|
||||
if (!persistentSelection)
|
||||
myTextField.deselect()
|
||||
root.deselect()
|
||||
}
|
||||
|
||||
ContextMenu {
|
||||
id: contextMenu
|
||||
myTextEdit: myTextField
|
||||
myTextEdit: root
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (root.activeFocus)
|
||||
root.preFocusText = root.text
|
||||
}
|
||||
|
||||
onEditChanged: {
|
||||
if (myTextField.edit)
|
||||
if (root.edit)
|
||||
contextMenu.close()
|
||||
}
|
||||
|
||||
onEditingFinished: root.focus = false
|
||||
|
||||
ActionIndicator {
|
||||
id: actionIndicator
|
||||
myControl: myTextField
|
||||
myControl: root
|
||||
x: 0
|
||||
y: 0
|
||||
width: actionIndicator.visible ? myTextField.__actionIndicatorWidth : 0
|
||||
height: actionIndicator.visible ? myTextField.__actionIndicatorHeight : 0
|
||||
width: actionIndicator.visible ? root.__actionIndicatorWidth : 0
|
||||
height: actionIndicator.visible ? root.__actionIndicatorHeight : 0
|
||||
}
|
||||
|
||||
Text {
|
||||
id: placeholder
|
||||
x: myTextField.leftPadding
|
||||
y: myTextField.topPadding
|
||||
width: myTextField.width - (myTextField.leftPadding + myTextField.rightPadding)
|
||||
height: myTextField.height - (myTextField.topPadding + myTextField.bottomPadding)
|
||||
x: root.leftPadding
|
||||
y: root.topPadding
|
||||
width: root.width - (root.leftPadding + root.rightPadding)
|
||||
height: root.height - (root.topPadding + root.bottomPadding)
|
||||
|
||||
text: myTextField.placeholderText
|
||||
font: myTextField.font
|
||||
color: myTextField.placeholderTextColor
|
||||
verticalAlignment: myTextField.verticalAlignment
|
||||
visible: !myTextField.length && !myTextField.preeditText
|
||||
&& (!myTextField.activeFocus || myTextField.horizontalAlignment !== Qt.AlignHCenter)
|
||||
text: root.placeholderText
|
||||
font: root.font
|
||||
color: root.placeholderTextColor
|
||||
verticalAlignment: root.verticalAlignment
|
||||
visible: !root.length && !root.preeditText
|
||||
&& (!root.activeFocus || root.horizontalAlignment !== Qt.AlignHCenter)
|
||||
elide: Text.ElideRight
|
||||
renderType: myTextField.renderType
|
||||
renderType: root.renderType
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
@ -131,14 +140,14 @@ T.TextField {
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
border.width: StudioTheme.Values.border
|
||||
x: actionIndicator.width
|
||||
width: myTextField.width - actionIndicator.width
|
||||
height: myTextField.height
|
||||
width: root.width - actionIndicator.width
|
||||
height: root.height
|
||||
}
|
||||
|
||||
TranslationIndicator {
|
||||
id: translationIndicator
|
||||
myControl: myTextField
|
||||
x: myTextField.width - translationIndicator.width
|
||||
myControl: root
|
||||
x: root.width - translationIndicator.width
|
||||
width: translationIndicator.visible ? __translationIndicatorWidth : 0
|
||||
height: translationIndicator.visible ? __translationIndicatorHeight : 0
|
||||
}
|
||||
@ -146,15 +155,14 @@ T.TextField {
|
||||
states: [
|
||||
State {
|
||||
name: "default"
|
||||
when: myTextField.enabled && !myTextField.hover
|
||||
&& !myTextField.edit
|
||||
when: root.enabled && !root.hover && !root.edit
|
||||
PropertyChanges {
|
||||
target: textFieldBackground
|
||||
color: StudioTheme.Values.themeControlBackground
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
}
|
||||
PropertyChanges {
|
||||
target: myTextField
|
||||
target: root
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
placeholderTextColor: StudioTheme.Values.themePlaceholderTextColor
|
||||
}
|
||||
@ -165,15 +173,15 @@ T.TextField {
|
||||
},
|
||||
State {
|
||||
name: "globalHover"
|
||||
when: (actionIndicator.hover || translationIndicator.hover) && !myTextField.edit
|
||||
&& myTextField.enabled
|
||||
when: (actionIndicator.hover || translationIndicator.hover) && !root.edit
|
||||
&& root.enabled
|
||||
PropertyChanges {
|
||||
target: textFieldBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundGlobalHover
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
}
|
||||
PropertyChanges {
|
||||
target: myTextField
|
||||
target: root
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
placeholderTextColor: StudioTheme.Values.themePlaceholderTextColor
|
||||
}
|
||||
@ -181,28 +189,28 @@ T.TextField {
|
||||
State {
|
||||
name: "hover"
|
||||
when: mouseArea.containsMouse && !actionIndicator.hover && !translationIndicator.hover
|
||||
&& !myTextField.edit && myTextField.enabled
|
||||
&& !root.edit && root.enabled
|
||||
PropertyChanges {
|
||||
target: textFieldBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundHover
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
}
|
||||
PropertyChanges {
|
||||
target: myTextField
|
||||
target: root
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
placeholderTextColor: StudioTheme.Values.themePlaceholderTextColor
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "edit"
|
||||
when: myTextField.edit
|
||||
when: root.edit
|
||||
PropertyChanges {
|
||||
target: textFieldBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundInteraction
|
||||
border.color: StudioTheme.Values.themeControlOutlineInteraction
|
||||
}
|
||||
PropertyChanges {
|
||||
target: myTextField
|
||||
target: root
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
placeholderTextColor: StudioTheme.Values.themePlaceholderTextColorInteraction
|
||||
}
|
||||
@ -213,14 +221,14 @@ T.TextField {
|
||||
},
|
||||
State {
|
||||
name: "disable"
|
||||
when: !myTextField.enabled
|
||||
when: !root.enabled
|
||||
PropertyChanges {
|
||||
target: textFieldBackground
|
||||
color: StudioTheme.Values.themeControlBackgroundDisabled
|
||||
border.color: StudioTheme.Values.themeControlOutlineDisabled
|
||||
}
|
||||
PropertyChanges {
|
||||
target: myTextField
|
||||
target: root
|
||||
color: StudioTheme.Values.themeTextColorDisabled
|
||||
placeholderTextColor: StudioTheme.Values.themeTextColorDisabled
|
||||
}
|
||||
@ -228,7 +236,9 @@ T.TextField {
|
||||
]
|
||||
|
||||
Keys.onPressed: function(event) {
|
||||
if (event.key === Qt.Key_Escape)
|
||||
myTextField.focus = false
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
root.text = root.preFocusText
|
||||
root.focus = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ CheckIndicator 1.0 CheckIndicator.qml
|
||||
ComboBox 1.0 ComboBox.qml
|
||||
ComboBoxInput 1.0 ComboBoxInput.qml
|
||||
ContextMenu 1.0 ContextMenu.qml
|
||||
FilterComboBox 1.0 FilterComboBox.qml
|
||||
InfinityLoopIndicator 1.0 InfinityLoopIndicator.qml
|
||||
ItemDelegate 1.0 ItemDelegate.qml
|
||||
LinkIndicator2D 1.0 LinkIndicator2D.qml
|
||||
@ -30,6 +31,7 @@ SectionLabel 1.0 SectionLabel.qml
|
||||
SectionLayout 1.0 SectionLayout.qml
|
||||
Slider 1.0 Slider.qml
|
||||
SliderPopup 1.0 SliderPopup.qml
|
||||
SortFilterModel 1.0 SortFilterModel.qml
|
||||
SpinBox 1.0 SpinBox.qml
|
||||
SpinBoxIndicator 1.0 SpinBoxIndicator.qml
|
||||
SpinBoxInput 1.0 SpinBoxInput.qml
|
||||
|
@ -406,11 +406,6 @@ QStringList lastSessionArgument()
|
||||
#ifdef ENABLE_CRASHPAD
|
||||
bool startCrashpad(const QString &libexecPath, bool crashReportingEnabled)
|
||||
{
|
||||
if (QSysInfo::currentCpuArchitecture() == "arm64") {
|
||||
qDebug() << "The crashpad_handler binary does not work on arm64 properly. So it is disabled for now.";
|
||||
return false;
|
||||
}
|
||||
|
||||
using namespace crashpad;
|
||||
|
||||
// Cache directory that will store crashpad information and minidumps
|
||||
|
@ -702,7 +702,8 @@ void CMakeBuildSystem::updateFileSystemNodes()
|
||||
addCMakeLists(newRoot.get(), std::move(fileNodes));
|
||||
}
|
||||
|
||||
addFileSystemNodes(newRoot.get(), m_allFiles);
|
||||
if (m_allFiles)
|
||||
addFileSystemNodes(newRoot.get(), m_allFiles);
|
||||
setRootProjectNode(std::move(newRoot));
|
||||
|
||||
m_reader.resetData();
|
||||
|
@ -436,6 +436,13 @@ static bool hideAnalyzeMenu()
|
||||
.toBool();
|
||||
}
|
||||
|
||||
static bool hideDebugMenu()
|
||||
{
|
||||
return Core::ICore::settings()
|
||||
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG, false)
|
||||
.toBool();
|
||||
}
|
||||
|
||||
QAction *addAction(const QObject *parent, QMenu *menu, const QString &display, bool on,
|
||||
const std::function<void()> &onTriggered)
|
||||
{
|
||||
@ -922,7 +929,9 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
|
||||
m_visibleStartAction.setAction(&m_startAction);
|
||||
|
||||
m_visibleStartAction.setObjectName("Debug"); // used for UI introduction
|
||||
ModeManager::addAction(&m_visibleStartAction, /*priority*/ 90);
|
||||
|
||||
if (!hideDebugMenu())
|
||||
ModeManager::addAction(&m_visibleStartAction, /*priority*/ 90);
|
||||
|
||||
m_undisturbableAction.setIcon(interruptIcon(false));
|
||||
m_undisturbableAction.setEnabled(false);
|
||||
|
@ -95,6 +95,7 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInte
|
||||
handleCodeActionResponse(response);
|
||||
});
|
||||
|
||||
m_client->addAssistProcessor(this);
|
||||
m_client->requestCodeActions(request);
|
||||
m_currentRequest = request.id();
|
||||
return nullptr;
|
||||
|
@ -280,10 +280,15 @@ void MacroManager::startMacro()
|
||||
foreach (IMacroHandler *handler, d->handlers)
|
||||
handler->startRecording(d->currentMacro);
|
||||
|
||||
QString endShortcut = Core::ActionManager::command(Constants::END_MACRO)->keySequence().toString();
|
||||
QString executeShortcut = Core::ActionManager::command(Constants::EXECUTE_LAST_MACRO)->keySequence().toString();
|
||||
QString help = tr("Macro mode. Type \"%1\" to stop recording and \"%2\" to play the macro.")
|
||||
.arg(endShortcut).arg(executeShortcut);
|
||||
const QString endShortcut = Core::ActionManager::command(Constants::END_MACRO)
|
||||
->keySequence()
|
||||
.toString(QKeySequence::NativeText);
|
||||
const QString executeShortcut = Core::ActionManager::command(Constants::EXECUTE_LAST_MACRO)
|
||||
->keySequence()
|
||||
.toString(QKeySequence::NativeText);
|
||||
const QString help
|
||||
= tr("Macro mode. Type \"%1\" to stop recording and \"%2\" to play the macro.")
|
||||
.arg(endShortcut, executeShortcut);
|
||||
Core::EditorManager::showEditorStatusBar(Constants::M_STATUS_BUFFER, help,
|
||||
tr("Stop Recording Macro"),
|
||||
this, [this] { endMacro(); });
|
||||
|
@ -96,8 +96,10 @@ void MacroOptionsWidget::createTable()
|
||||
|
||||
Core::Command *command =
|
||||
Core::ActionManager::command(base.withSuffix(macro->displayName()));
|
||||
if (command && command->action())
|
||||
macroItem->setText(2, command->action()->shortcut().toString());
|
||||
if (command && command->action()) {
|
||||
macroItem->setText(2,
|
||||
command->action()->shortcut().toString(QKeySequence::NativeText));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1079,12 +1079,19 @@ Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) co
|
||||
Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
||||
{
|
||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
||||
if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|
||||
|| fileName.endsWith("gcc")
|
||||
|| fileName == "cc"))
|
||||
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|
||||
|| fileName.endsWith("g++")
|
||||
|| fileName == "c++"))) {
|
||||
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
|
||||
|
||||
const bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
||||
&& (fileName.startsWith("gcc")
|
||||
|| fileName.endsWith("gcc")
|
||||
|| (fileName == "cc" && !resolvedSymlinksFileName.contains("clang")));
|
||||
|
||||
const bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
||||
&& (fileName.startsWith("g++")
|
||||
|| fileName.endsWith("g++")
|
||||
|| (fileName == "c++" && !resolvedSymlinksFileName.contains("clang")));
|
||||
|
||||
if (isCCompiler || isCxxCompiler) {
|
||||
return autoDetectToolChain(tcd, [](const ToolChain *tc) {
|
||||
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
|
||||
});
|
||||
@ -1765,9 +1772,18 @@ Toolchains ClangToolChainFactory::autoDetect(const ToolchainDetector &detector)
|
||||
|
||||
Toolchains ClangToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
||||
{
|
||||
const QString fileName = tcd.compilerPath.toString();
|
||||
if ((tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|
||||
|| (tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("clang++"))) {
|
||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
||||
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
|
||||
|
||||
const bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
|
||||
&& ((fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|
||||
|| (fileName == "cc" && resolvedSymlinksFileName.contains("clang")));
|
||||
|
||||
const bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
|
||||
&& (fileName.startsWith("clang++")
|
||||
|| (fileName == "c++" && resolvedSymlinksFileName.contains("clang")));
|
||||
|
||||
if (isCCompiler || isCxxCompiler) {
|
||||
return autoDetectToolChain(tcd);
|
||||
}
|
||||
return {};
|
||||
@ -2023,7 +2039,7 @@ Toolchains LinuxIccToolChainFactory::autoDetect(const ToolchainDetector &detecto
|
||||
|
||||
Toolchains LinuxIccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
|
||||
{
|
||||
const QString fileName = tcd.compilerPath.toString();
|
||||
const QString fileName = tcd.compilerPath.completeBaseName();
|
||||
if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
|
||||
(tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) {
|
||||
return autoDetectToolChain(tcd);
|
||||
|
@ -1340,7 +1340,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
||||
dd->m_modeBarBuildAction->initialize(cmd->action());
|
||||
dd->m_modeBarBuildAction->setAttribute(ProxyAction::UpdateText);
|
||||
dd->m_modeBarBuildAction->setAction(cmd->action());
|
||||
ModeManager::addAction(dd->m_modeBarBuildAction, Constants::P_ACTION_BUILDPROJECT);
|
||||
if (!hideBuildMenu())
|
||||
ModeManager::addAction(dd->m_modeBarBuildAction, Constants::P_ACTION_BUILDPROJECT);
|
||||
|
||||
// build for run config
|
||||
dd->m_buildForRunConfigAction = new ParameterAction(
|
||||
|
@ -36,19 +36,24 @@
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <utils/filesystemwatcher.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QElapsedTimer>
|
||||
#include <QFont>
|
||||
#include <QImageReader>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMessageBox>
|
||||
#include <QMetaProperty>
|
||||
#include <QPainter>
|
||||
#include <QRawFont>
|
||||
#include <QRegularExpression>
|
||||
#include <QMessageBox>
|
||||
#include <QCheckBox>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/filesystemwatcher.h>
|
||||
|
||||
static Q_LOGGING_CATEGORY(assetsLibraryBenchmark, "qtc.assetsLibrary.setRoot", QtWarningMsg)
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@ -298,6 +303,12 @@ void AssetsLibraryModel::refresh()
|
||||
|
||||
void AssetsLibraryModel::setRootPath(const QString &path)
|
||||
{
|
||||
QElapsedTimer time;
|
||||
if (assetsLibraryBenchmark().isInfoEnabled())
|
||||
time.start();
|
||||
|
||||
qCInfo(assetsLibraryBenchmark) << "start:" << time.elapsed();
|
||||
|
||||
static const QStringList ignoredTopLevelDirs {"imports", "asset_imports"};
|
||||
|
||||
m_fileSystemWatcher->clear();
|
||||
@ -345,6 +356,8 @@ void AssetsLibraryModel::setRootPath(const QString &path)
|
||||
return isEmpty;
|
||||
};
|
||||
|
||||
qCInfo(assetsLibraryBenchmark) << "directories parsed:" << time.elapsed();
|
||||
|
||||
if (m_assetsDir)
|
||||
delete m_assetsDir;
|
||||
|
||||
@ -360,6 +373,8 @@ void AssetsLibraryModel::setRootPath(const QString &path)
|
||||
|
||||
m_assetsDir->setDirVisible(!noAssets); // if there are no assets, hide all empty asset folders
|
||||
endResetModel();
|
||||
|
||||
qCInfo(assetsLibraryBenchmark) << "model reset:" << time.elapsed();
|
||||
}
|
||||
|
||||
void AssetsLibraryModel::setSearchText(const QString &searchText)
|
||||
|
@ -87,7 +87,7 @@ bool AssetsLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
auto drag = new QDrag(this);
|
||||
drag->setPixmap(m_assetsIconProvider->requestPixmap(m_assetsToDrag[0], nullptr, {128, 128}));
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData("application/vnd.bauhaus.libraryresource", m_assetsToDrag.join(',').toUtf8());
|
||||
mimeData->setData(Constants::MIME_TYPE_ASSETS, m_assetsToDrag.join(',').toUtf8());
|
||||
drag->setMimeData(mimeData);
|
||||
drag->exec();
|
||||
drag->deleteLater();
|
||||
@ -213,26 +213,32 @@ void AssetsLibraryWidget::handleAddAsset()
|
||||
addResources({});
|
||||
}
|
||||
|
||||
void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &simpleFilesPaths,
|
||||
const QStringList &complexFilesPaths,
|
||||
void AssetsLibraryWidget::handleExtFilesDrop(const QList<QUrl> &simpleFilePaths,
|
||||
const QList<QUrl> &complexFilePaths,
|
||||
const QString &targetDirPath)
|
||||
{
|
||||
if (!simpleFilesPaths.isEmpty()) {
|
||||
auto toLocalFile = [](const QUrl &url) { return url.toLocalFile(); };
|
||||
|
||||
QStringList simpleFilePathStrings = Utils::transform<QStringList>(simpleFilePaths, toLocalFile);
|
||||
QStringList complexFilePathStrings = Utils::transform<QStringList>(complexFilePaths,
|
||||
toLocalFile);
|
||||
|
||||
if (!simpleFilePathStrings.isEmpty()) {
|
||||
if (targetDirPath.isEmpty()) {
|
||||
addResources(simpleFilesPaths);
|
||||
addResources(simpleFilePathStrings);
|
||||
} else {
|
||||
AddFilesResult result = ModelNodeOperations::addFilesToProject(simpleFilesPaths,
|
||||
AddFilesResult result = ModelNodeOperations::addFilesToProject(simpleFilePathStrings,
|
||||
targetDirPath);
|
||||
if (result == AddFilesResult::Failed) {
|
||||
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
||||
tr("Could not add %1 to project.")
|
||||
.arg(simpleFilesPaths.join(' ')));
|
||||
.arg(simpleFilePathStrings.join(' ')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!complexFilesPaths.empty())
|
||||
addResources(complexFilesPaths);
|
||||
if (!complexFilePathStrings.empty())
|
||||
addResources(complexFilePathStrings);
|
||||
}
|
||||
|
||||
QSet<QString> AssetsLibraryWidget::supportedAssetSuffixes(bool complex)
|
||||
@ -301,25 +307,25 @@ QPair<QString, QByteArray> AssetsLibraryWidget::getAssetTypeAndData(const QStrin
|
||||
if (!suffix.isEmpty()) {
|
||||
if (AssetsLibraryModel::supportedImageSuffixes().contains(suffix)) {
|
||||
// Data: Image format (suffix)
|
||||
return {"application/vnd.bauhaus.libraryresource.image", suffix.toUtf8()};
|
||||
return {Constants::MIME_TYPE_ASSET_IMAGE, suffix.toUtf8()};
|
||||
} else if (AssetsLibraryModel::supportedFontSuffixes().contains(suffix)) {
|
||||
// Data: Font family name
|
||||
QRawFont font(assetPath, 10);
|
||||
QString fontFamily = font.isValid() ? font.familyName() : "";
|
||||
return {"application/vnd.bauhaus.libraryresource.font", fontFamily.toUtf8()};
|
||||
return {Constants::MIME_TYPE_ASSET_FONT, fontFamily.toUtf8()};
|
||||
} else if (AssetsLibraryModel::supportedShaderSuffixes().contains(suffix)) {
|
||||
// Data: shader type, frament (f) or vertex (v)
|
||||
return {"application/vnd.bauhaus.libraryresource.shader",
|
||||
return {Constants::MIME_TYPE_ASSET_SHADER,
|
||||
AssetsLibraryModel::supportedFragmentShaderSuffixes().contains(suffix) ? "f" : "v"};
|
||||
} else if (AssetsLibraryModel::supportedAudioSuffixes().contains(suffix)) {
|
||||
// No extra data for sounds
|
||||
return {"application/vnd.bauhaus.libraryresource.sound", {}};
|
||||
return {Constants::MIME_TYPE_ASSET_SOUND, {}};
|
||||
} else if (AssetsLibraryModel::supportedVideoSuffixes().contains(suffix)) {
|
||||
// No extra data for videos
|
||||
return {"application/vnd.bauhaus.libraryresource.video", {}};
|
||||
return {Constants::MIME_TYPE_ASSET_VIDEO, {}};
|
||||
} else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) {
|
||||
// Data: Image format (suffix)
|
||||
return {"application/vnd.bauhaus.libraryresource.texture3d", suffix.toUtf8()};
|
||||
return {Constants::MIME_TYPE_ASSET_TEXTURE3D, suffix.toUtf8()};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@ -79,8 +79,8 @@ public:
|
||||
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
|
||||
Q_INVOKABLE void handleAddAsset();
|
||||
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
||||
Q_INVOKABLE void handleExtFilesDrop(const QStringList &simpleFilesPaths,
|
||||
const QStringList &complexFilesPaths,
|
||||
Q_INVOKABLE void handleExtFilesDrop(const QList<QUrl> &simpleFilePaths,
|
||||
const QList<QUrl> &complexFilePaths,
|
||||
const QString &targetDirPath = {});
|
||||
Q_INVOKABLE QSet<QString> supportedAssetSuffixes(bool complex);
|
||||
|
||||
|
@ -214,10 +214,9 @@ QmlTimeline CurveEditorView::activeTimeline() const
|
||||
if (node.hasVariantProperty("enabled")
|
||||
&& node.variantProperty("enabled").value().toBool())
|
||||
return QmlTimeline(node);
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const ModelNode &node : allModelNodesOfType("QtQuick.Timeline.Timeline")) {
|
||||
@ -226,8 +225,9 @@ QmlTimeline CurveEditorView::activeTimeline() const
|
||||
if (!propertyChanges.isValid())
|
||||
continue;
|
||||
|
||||
if (node.hasVariantProperty("enabled") && node.variantProperty("enabled").value().toBool())
|
||||
return QmlTimeline(node);
|
||||
if (propertyChanges.modelNode().hasProperty("enabled") &&
|
||||
propertyChanges.modelNode().variantProperty("enabled").value().toBool())
|
||||
return QmlTimeline(node);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@ -169,7 +169,7 @@ void Edit3DCanvas::dragEnterEvent(QDragEnterEvent *e)
|
||||
// Allow drop when there is no valid active scene, as the drop goes under the root node of
|
||||
// the document in that case.
|
||||
if (!node.isValid() || !ModelNode::isThisOrAncestorLocked(node)) {
|
||||
QByteArray data = e->mimeData()->data(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
|
||||
QByteArray data = e->mimeData()->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
|
||||
if (!data.isEmpty()) {
|
||||
QDataStream stream(data);
|
||||
stream >> m_itemLibraryEntry;
|
||||
|
@ -24,12 +24,12 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "abstractformeditortool.h"
|
||||
#include "assetslibrarywidget.h"
|
||||
#include "formeditorscene.h"
|
||||
#include "formeditorview.h"
|
||||
#include "formeditorwidget.h"
|
||||
#include "formeditorscene.h"
|
||||
#include "assetslibrarywidget.h"
|
||||
|
||||
#include <modelnodecontextmenu.h>
|
||||
#include "modelnodecontextmenu.h"
|
||||
#include "qmldesignerconstants.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGraphicsSceneDragDropEvent>
|
||||
@ -236,20 +236,20 @@ void AbstractFormEditorTool::dropEvent(const QList<QGraphicsItem*> &/*itemList*/
|
||||
void AbstractFormEditorTool::dragEnterEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneDragDropEvent *event)
|
||||
{
|
||||
bool hasValidAssets = false;
|
||||
if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
|
||||
if (event->mimeData()->hasFormat(Constants::MIME_TYPE_ASSETS)) {
|
||||
const QStringList assetPaths = QString::fromUtf8(event->mimeData()
|
||||
->data("application/vnd.bauhaus.libraryresource")).split(",");
|
||||
->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
||||
for (const QString &assetPath : assetPaths) {
|
||||
QString assetType = AssetsLibraryWidget::getAssetTypeAndData(assetPath).first;
|
||||
if (assetType == "application/vnd.bauhaus.libraryresource.image"
|
||||
|| assetType == "application/vnd.bauhaus.libraryresource.font") {
|
||||
if (assetType == Constants::MIME_TYPE_ASSET_IMAGE
|
||||
|| assetType == Constants::MIME_TYPE_ASSET_FONT) {
|
||||
hasValidAssets = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo")) || hasValidAssets) {
|
||||
if (event->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO) || hasValidAssets) {
|
||||
event->accept();
|
||||
view()->changeToDragTool();
|
||||
view()->currentTool()->dragEnterEvent(itemList, event);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <metainfo.h>
|
||||
#include <nodehints.h>
|
||||
#include <rewritingexception.h>
|
||||
#include "qmldesignerconstants.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
@ -219,9 +220,7 @@ void DragTool::abort()
|
||||
|
||||
static ItemLibraryEntry itemLibraryEntryFromMimeData(const QMimeData *mimeData)
|
||||
{
|
||||
QByteArray data = mimeData->data(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
|
||||
|
||||
QDataStream stream(data);
|
||||
QDataStream stream(mimeData->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO));
|
||||
|
||||
ItemLibraryEntry itemLibraryEntry;
|
||||
stream >> itemLibraryEntry;
|
||||
@ -236,7 +235,7 @@ static bool canBeDropped(const QMimeData *mimeData)
|
||||
|
||||
static bool hasItemLibraryInfo(const QMimeData *mimeData)
|
||||
{
|
||||
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
|
||||
return mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
|
||||
}
|
||||
|
||||
void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
|
||||
@ -326,12 +325,12 @@ void DragTool::createDragNodes(const QMimeData *mimeData, const QPointF &scenePo
|
||||
scenePosition);
|
||||
} else {
|
||||
const QStringList assetPaths = QString::fromUtf8(mimeData
|
||||
->data("application/vnd.bauhaus.libraryresource")).split(",");
|
||||
->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
||||
for (const QString &assetPath : assetPaths) {
|
||||
QString assetType = AssetsLibraryWidget::getAssetTypeAndData(assetPath).first;
|
||||
if (assetType == "application/vnd.bauhaus.libraryresource.image")
|
||||
if (assetType == Constants::MIME_TYPE_ASSET_IMAGE)
|
||||
createQmlItemNodeFromImage(assetPath, targetContainerQmlItemNode, scenePosition);
|
||||
else if (assetType == "application/vnd.bauhaus.libraryresource.font")
|
||||
else if (assetType == Constants::MIME_TYPE_ASSET_FONT)
|
||||
createQmlItemNodeFromFont(assetPath, targetContainerQmlItemNode, scenePosition);
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nodemetainfo.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include "qmldesignerconstants.h"
|
||||
#include "qmldesignerplugin.h"
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@ -515,9 +516,9 @@ QMimeData *ItemLibraryModel::getMimeData(const ItemLibraryEntry &itemLibraryEntr
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << itemLibraryEntry;
|
||||
mimeData->setData(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"), data);
|
||||
mimeData->setData(Constants::MIME_TYPE_ITEM_LIBRARY_INFO, data);
|
||||
|
||||
mimeData->removeFormat(QStringLiteral("text/plain"));
|
||||
mimeData->removeFormat("text/plain");
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "modelnodeoperations.h"
|
||||
#include <metainfo.h>
|
||||
#include <model.h>
|
||||
#include <navigatorwidget.h>
|
||||
#include <rewritingexception.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
@ -89,6 +88,9 @@ static QString propertyEditorResourcesPath()
|
||||
|
||||
bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
Model *model = document ? document->documentModel() : nullptr;
|
||||
|
||||
if (event->type() == QEvent::FocusOut) {
|
||||
if (obj == m_itemsWidget.data())
|
||||
QMetaObject::invokeMethod(m_itemsWidget->rootObject(), "closeContextMenu");
|
||||
@ -115,33 +117,19 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
}
|
||||
}
|
||||
}
|
||||
QWidget *view = QmlDesignerPlugin::instance()->viewManager().widget("Navigator");
|
||||
if (view) {
|
||||
NavigatorWidget *navView = qobject_cast<NavigatorWidget *>(view);
|
||||
if (navView) {
|
||||
navView->setDragType(entry.typeName());
|
||||
navView->update();
|
||||
}
|
||||
|
||||
if (model) {
|
||||
model->startDrag(m_itemLibraryModel->getMimeData(entry),
|
||||
Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
|
||||
}
|
||||
auto drag = new QDrag(this);
|
||||
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
|
||||
drag->setMimeData(m_itemLibraryModel->getMimeData(entry));
|
||||
drag->exec();
|
||||
drag->deleteLater();
|
||||
|
||||
m_itemToDrag = {};
|
||||
}
|
||||
}
|
||||
} else if (event->type() == QMouseEvent::MouseButtonRelease) {
|
||||
m_itemToDrag = {};
|
||||
QWidget *view = QmlDesignerPlugin::instance()->viewManager().widget("Navigator");
|
||||
if (view) {
|
||||
NavigatorWidget *navView = qobject_cast<NavigatorWidget *>(view);
|
||||
if (navView) {
|
||||
navView->setDragType("");
|
||||
navView->update();
|
||||
}
|
||||
}
|
||||
if (model)
|
||||
model->endDrag();
|
||||
}
|
||||
|
||||
return QObject::eventFilter(obj, event);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "navigatorview.h"
|
||||
#include "navigatorwidget.h"
|
||||
#include "choosefrompropertylistdialog.h"
|
||||
#include "qmldesignerconstants.h"
|
||||
#include "qmldesignerplugin.h"
|
||||
#include "assetslibrarywidget.h"
|
||||
|
||||
@ -71,7 +72,7 @@ namespace QmlDesigner {
|
||||
|
||||
static QList<ModelNode> modelNodesFromMimeData(const QMimeData *mineData, AbstractView *view)
|
||||
{
|
||||
QByteArray encodedModelNodeData = mineData->data(QLatin1String("application/vnd.modelnode.list"));
|
||||
QByteArray encodedModelNodeData = mineData->data(Constants::MIME_TYPE_MODELNODE_LIST);
|
||||
QDataStream modelNodeStream(&encodedModelNodeData, QIODevice::ReadOnly);
|
||||
|
||||
QList<ModelNode> modelNodeList;
|
||||
@ -465,9 +466,9 @@ void NavigatorTreeModel::setView(NavigatorView *view)
|
||||
|
||||
QStringList NavigatorTreeModel::mimeTypes() const
|
||||
{
|
||||
const static QStringList types({"application/vnd.modelnode.list",
|
||||
"application/vnd.bauhaus.itemlibraryinfo",
|
||||
"application/vnd.bauhaus.libraryresource"});
|
||||
const static QStringList types({Constants::MIME_TYPE_MODELNODE_LIST,
|
||||
Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
|
||||
Constants::MIME_TYPE_ASSETS});
|
||||
|
||||
return types;
|
||||
}
|
||||
@ -490,7 +491,7 @@ QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &modelIndexList) c
|
||||
}
|
||||
}
|
||||
|
||||
mimeData->setData("application/vnd.modelnode.list", encodedModelNodeData);
|
||||
mimeData->setData(Constants::MIME_TYPE_MODELNODE_LIST, encodedModelNodeData);
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
@ -560,10 +561,10 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
||||
widget->setDragType("");
|
||||
|
||||
if (dropModelIndex.model() == this) {
|
||||
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
|
||||
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
|
||||
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
||||
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource")) {
|
||||
const QStringList assetsPaths = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")).split(",");
|
||||
} else if (mimeData->hasFormat(Constants::MIME_TYPE_ASSETS)) {
|
||||
const QStringList assetsPaths = QString::fromUtf8(mimeData->data(Constants::MIME_TYPE_ASSETS)).split(',');
|
||||
NodeAbstractProperty targetProperty;
|
||||
|
||||
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
||||
@ -579,9 +580,9 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
||||
QSet<QString> neededImports;
|
||||
for (const QString &assetPath : assetsPaths) {
|
||||
QString assetType = AssetsLibraryWidget::getAssetTypeAndData(assetPath).first;
|
||||
if (assetType == "application/vnd.bauhaus.libraryresource.shader")
|
||||
if (assetType == Constants::MIME_TYPE_ASSET_SHADER)
|
||||
neededImports.insert("QtQuick3D");
|
||||
else if (assetType == "application/vnd.bauhaus.libraryresource.sound")
|
||||
else if (assetType == Constants::MIME_TYPE_ASSET_SOUND)
|
||||
neededImports.insert("QtMultimedia");
|
||||
|
||||
if (neededImports.size() == 2)
|
||||
@ -598,20 +599,20 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
||||
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetPath);
|
||||
QString assetType = assetTypeAndData.first;
|
||||
QString assetData = QString::fromUtf8(assetTypeAndData.second);
|
||||
if (assetType == "application/vnd.bauhaus.libraryresource.image") {
|
||||
if (assetType == Constants::MIME_TYPE_ASSET_IMAGE) {
|
||||
currNode = handleItemLibraryImageDrop(assetPath, targetProperty,
|
||||
rowModelIndex, moveNodesAfter);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.font") {
|
||||
} else if (assetType == Constants::MIME_TYPE_ASSET_FONT) {
|
||||
currNode = handleItemLibraryFontDrop(assetData, // assetData is fontFamily
|
||||
targetProperty, rowModelIndex);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.shader") {
|
||||
} else if (assetType == Constants::MIME_TYPE_ASSET_SHADER) {
|
||||
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f",
|
||||
targetProperty, rowModelIndex,
|
||||
moveNodesAfter);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.sound") {
|
||||
} else if (assetType == Constants::MIME_TYPE_ASSET_SOUND) {
|
||||
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty,
|
||||
rowModelIndex);
|
||||
} else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d") {
|
||||
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
|
||||
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
|
||||
rowModelIndex, moveNodesAfter);
|
||||
}
|
||||
@ -627,7 +628,7 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
||||
m_view->setSelectedModelNodes(addedNodes);
|
||||
}
|
||||
}
|
||||
} else if (mimeData->hasFormat("application/vnd.modelnode.list")) {
|
||||
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MODELNODE_LIST)) {
|
||||
handleInternalDrop(mimeData, rowNumber, dropModelIndex);
|
||||
}
|
||||
}
|
||||
@ -673,7 +674,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
||||
NodeAbstractProperty targetProperty;
|
||||
|
||||
const ItemLibraryEntry itemLibraryEntry =
|
||||
createItemLibraryEntryFromMimeData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo"));
|
||||
createItemLibraryEntryFromMimeData(mimeData->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO));
|
||||
|
||||
const NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry);
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <bindingproperty.h>
|
||||
#include <designmodecontext.h>
|
||||
#include <designersettings.h>
|
||||
#include <itemlibraryinfo.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <nodelistproperty.h>
|
||||
#include <variantproperty.h>
|
||||
@ -57,8 +58,9 @@
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QTimer>
|
||||
#include <QMimeData>
|
||||
#include <QPixmap>
|
||||
#include <QTimer>
|
||||
|
||||
static inline void setScenePos(const QmlDesigner::ModelNode &modelNode,const QPointF &pos)
|
||||
{
|
||||
@ -263,6 +265,25 @@ void NavigatorView::bindingPropertiesChanged(const QList<BindingProperty> & prop
|
||||
}
|
||||
}
|
||||
|
||||
void NavigatorView::dragStarted(QMimeData *mimeData)
|
||||
{
|
||||
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
|
||||
QByteArray data = mimeData->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
|
||||
QDataStream stream(data);
|
||||
ItemLibraryEntry itemLibraryEntry;
|
||||
stream >> itemLibraryEntry;
|
||||
|
||||
m_widget->setDragType(itemLibraryEntry.typeName());
|
||||
m_widget->update();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigatorView::dragEnded()
|
||||
{
|
||||
m_widget->setDragType("");
|
||||
m_widget->update();
|
||||
}
|
||||
|
||||
void NavigatorView::customNotification(const AbstractView *view, const QString &identifier,
|
||||
const QList<ModelNode> &nodeList, const QList<QVariant> &data)
|
||||
{
|
||||
|
@ -92,6 +92,9 @@ public:
|
||||
|
||||
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags) override;
|
||||
|
||||
void dragStarted(QMimeData *mimeData) override;
|
||||
void dragEnded() override;
|
||||
|
||||
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
|
||||
|
||||
void handleChangedExport(const ModelNode &modelNode, bool exported);
|
||||
|
@ -294,7 +294,7 @@ void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qm
|
||||
valueObject = new PropertyEditorValue(&backendValuesPropertyMap());
|
||||
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged);
|
||||
QObject::connect(valueObject, &PropertyEditorValue::expressionChanged, propertyEditor, &PropertyEditorView::changeExpression);
|
||||
QObject::connect(valueObject, &PropertyEditorValue::exportPopertyAsAliasRequested, propertyEditor, &PropertyEditorView::exportPopertyAsAlias);
|
||||
QObject::connect(valueObject, &PropertyEditorValue::exportPropertyAsAliasRequested, propertyEditor, &PropertyEditorView::exportPropertyAsAlias);
|
||||
QObject::connect(valueObject, &PropertyEditorValue::removeAliasExportRequested, propertyEditor, &PropertyEditorView::removeAliasExport);
|
||||
backendValuesPropertyMap().insert(QString::fromUtf8(propertyName), QVariant::fromValue(valueObject));
|
||||
}
|
||||
|
@ -367,9 +367,9 @@ void PropertyEditorValue::setEnumeration(const QString &scope, const QString &na
|
||||
setValueWithEmit(QVariant::fromValue(newEnumeration));
|
||||
}
|
||||
|
||||
void PropertyEditorValue::exportPopertyAsAlias()
|
||||
void PropertyEditorValue::exportPropertyAsAlias()
|
||||
{
|
||||
emit exportPopertyAsAliasRequested(nameAsQString());
|
||||
emit exportPropertyAsAliasRequested(nameAsQString());
|
||||
}
|
||||
|
||||
bool PropertyEditorValue::hasPropertyAlias() const
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
|
||||
static void registerDeclarativeTypes();
|
||||
|
||||
Q_INVOKABLE void exportPopertyAsAlias();
|
||||
Q_INVOKABLE void exportPropertyAsAlias();
|
||||
Q_INVOKABLE bool hasPropertyAlias() const;
|
||||
Q_INVOKABLE bool isAttachedProperty() const;
|
||||
Q_INVOKABLE void removeAliasExport();
|
||||
@ -153,7 +153,7 @@ signals:
|
||||
void valueChangedQml();
|
||||
|
||||
void expressionChanged(const QString &name);
|
||||
void exportPopertyAsAliasRequested(const QString &name);
|
||||
void exportPropertyAsAliasRequested(const QString &name);
|
||||
void removeAliasExportRequested(const QString &name);
|
||||
|
||||
void modelStateChanged();
|
||||
|
@ -256,6 +256,9 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
|
||||
if (noValidSelection())
|
||||
return;
|
||||
|
||||
QScopeGuard unlock([&](){ m_locked = false; });
|
||||
m_locked = true;
|
||||
|
||||
executeInTransaction("PropertyEditorView::changeExpression", [this, name](){
|
||||
PropertyName underscoreName(name);
|
||||
underscoreName.replace('.', '_');
|
||||
@ -317,13 +320,13 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
|
||||
return;
|
||||
}
|
||||
|
||||
if (qmlObjectNode->expression(name) != value->expression() || !qmlObjectNode->propertyAffectedByCurrentState(name))
|
||||
if (qmlObjectNode->expression(name) != value->expression()
|
||||
|| !qmlObjectNode->propertyAffectedByCurrentState(name))
|
||||
qmlObjectNode->setBindingProperty(name, value->expression());
|
||||
|
||||
}); /* end of transaction */
|
||||
}
|
||||
|
||||
void PropertyEditorView::exportPopertyAsAlias(const QString &name)
|
||||
void PropertyEditorView::exportPropertyAsAlias(const QString &name)
|
||||
{
|
||||
if (name.isNull())
|
||||
return;
|
||||
@ -334,7 +337,7 @@ void PropertyEditorView::exportPopertyAsAlias(const QString &name)
|
||||
if (noValidSelection())
|
||||
return;
|
||||
|
||||
executeInTransaction("PropertyEditorView::exportPopertyAsAlias", [this, name](){
|
||||
executeInTransaction("PropertyEditorView::exportPropertyAsAlias", [this, name](){
|
||||
const QString id = m_selectedNode.validId();
|
||||
QString upperCasePropertyName = name;
|
||||
upperCasePropertyName.replace(0, 1, upperCasePropertyName.at(0).toUpper());
|
||||
@ -362,7 +365,7 @@ void PropertyEditorView::removeAliasExport(const QString &name)
|
||||
if (noValidSelection())
|
||||
return;
|
||||
|
||||
executeInTransaction("PropertyEditorView::exportPopertyAsAlias", [this, name](){
|
||||
executeInTransaction("PropertyEditorView::exportPropertyAsAlias", [this, name](){
|
||||
const QString id = m_selectedNode.validId();
|
||||
|
||||
for (const BindingProperty &property : rootModelNode().bindingProperties())
|
||||
@ -692,6 +695,9 @@ void PropertyEditorView::variantPropertiesChanged(const QList<VariantProperty>&
|
||||
|
||||
void PropertyEditorView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
|
||||
{
|
||||
if (locked())
|
||||
return;
|
||||
|
||||
if (noValidSelection())
|
||||
return;
|
||||
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
|
||||
void changeValue(const QString &name);
|
||||
void changeExpression(const QString &name);
|
||||
void exportPopertyAsAlias(const QString &name);
|
||||
void exportPropertyAsAlias(const QString &name);
|
||||
void removeAliasExport(const QString &name);
|
||||
|
||||
bool locked() const;
|
||||
|
@ -229,6 +229,9 @@ public:
|
||||
virtual void updateImport3DSupport(const QVariantMap &supportMap);
|
||||
virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
||||
|
||||
virtual void dragStarted(QMimeData *mimeData);
|
||||
virtual void dragEnded();
|
||||
|
||||
void changeRootNodeType(const TypeName &type, int majorVersion, int minorVersion);
|
||||
|
||||
NodeInstanceView *nodeInstanceView() const;
|
||||
|
@ -129,6 +129,9 @@ public:
|
||||
QString generateNewId(const QString &prefixName) const;
|
||||
QString generateNewId(const QString &prefixName, const QString &fallbackPrefix) const;
|
||||
|
||||
void startDrag(QMimeData *mimeData, const QString iconPath = {});
|
||||
void endDrag();
|
||||
|
||||
protected:
|
||||
Model();
|
||||
|
||||
|
@ -396,6 +396,9 @@ void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, con
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractView::dragStarted(QMimeData * /*mimeData*/) {}
|
||||
void AbstractView::dragEnded() {}
|
||||
|
||||
QList<ModelNode> AbstractView::toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList) const
|
||||
{
|
||||
return QmlDesigner::toModelNodeList(nodeList, const_cast<AbstractView*>(this));
|
||||
|
@ -67,6 +67,7 @@
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QDrag>
|
||||
#include <QRegularExpression>
|
||||
|
||||
/*!
|
||||
@ -588,6 +589,16 @@ void ModelPrivate::notifyImport3DSupportChanged(const QVariantMap &supportMap)
|
||||
notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); });
|
||||
}
|
||||
|
||||
void ModelPrivate::notifyDragStarted(QMimeData *mimeData)
|
||||
{
|
||||
notifyInstanceChanges([&](AbstractView *view) { view->dragStarted(mimeData); });
|
||||
}
|
||||
|
||||
void ModelPrivate::notifyDragEnded()
|
||||
{
|
||||
notifyInstanceChanges([&](AbstractView *view) { view->dragEnded(); });
|
||||
}
|
||||
|
||||
void ModelPrivate::notifyRewriterBeginTransaction()
|
||||
{
|
||||
notifyNodeInstanceViewLast([&](AbstractView *view) { view->rewriterBeginTransaction(); });
|
||||
@ -1492,6 +1503,22 @@ QString Model::generateNewId(const QString &prefixName, const QString &fallbackP
|
||||
return newId;
|
||||
}
|
||||
|
||||
void Model::startDrag(QMimeData *mimeData, const QString iconPath)
|
||||
{
|
||||
d->notifyDragStarted(mimeData);
|
||||
|
||||
auto drag = new QDrag(this);
|
||||
drag->setPixmap(iconPath);
|
||||
drag->setMimeData(mimeData);
|
||||
drag->exec();
|
||||
drag->deleteLater();
|
||||
}
|
||||
|
||||
void Model::endDrag()
|
||||
{
|
||||
d->notifyDragEnded();
|
||||
}
|
||||
|
||||
QString Model::generateNewId(const QString &prefixName) const
|
||||
{
|
||||
return generateNewId(prefixName, QStringLiteral("element"));
|
||||
|
@ -183,6 +183,9 @@ public:
|
||||
void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap);
|
||||
void notifyImport3DSupportChanged(const QVariantMap &supportMap);
|
||||
|
||||
void notifyDragStarted(QMimeData *mimeData);
|
||||
void notifyDragEnded();
|
||||
|
||||
void setDocumentMessages(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings);
|
||||
|
||||
void notifyRewriterBeginTransaction();
|
||||
|
@ -85,6 +85,16 @@ const char QUICK_3D_ASSET_IMPORT_DATA_OPTIONS_KEY[] = "import_options";
|
||||
const char QUICK_3D_ASSET_IMPORT_DATA_SOURCE_KEY[] = "source_scene";
|
||||
const char DEFAULT_ASSET_IMPORT_FOLDER[] = "/asset_imports";
|
||||
|
||||
const char MIME_TYPE_ITEM_LIBRARY_INFO[] = "application/vnd.qtdesignstudio.itemlibraryinfo";
|
||||
const char MIME_TYPE_ASSETS[] = "application/vnd.qtdesignstudio.assets";
|
||||
const char MIME_TYPE_ASSET_IMAGE[] = "application/vnd.qtdesignstudio.asset.image";
|
||||
const char MIME_TYPE_ASSET_FONT[] = "application/vnd.qtdesignstudio.asset.font";
|
||||
const char MIME_TYPE_ASSET_SHADER[] = "application/vnd.qtdesignstudio.asset.shader";
|
||||
const char MIME_TYPE_ASSET_SOUND[] = "application/vnd.qtdesignstudio.asset.sound";
|
||||
const char MIME_TYPE_ASSET_VIDEO[] = "application/vnd.qtdesignstudio.asset.video";
|
||||
const char MIME_TYPE_ASSET_TEXTURE3D[] = "application/vnd.qtdesignstudio.asset.texture3d";
|
||||
const char MIME_TYPE_MODELNODE_LIST[] = "application/vnd.qtdesignstudio.modelnode.list";
|
||||
|
||||
// Menus
|
||||
const char M_VIEW_WORKSPACES[] = "QmlDesigner.Menu.View.Workspaces";
|
||||
|
||||
|
@ -91,6 +91,10 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
|
||||
if (mainFileProperty.isValid())
|
||||
projectItem->setMainFile(mainFileProperty.value.toString());
|
||||
|
||||
const auto mainUiFileProperty = rootNode->property(QLatin1String("mainUiFile"));
|
||||
if (mainUiFileProperty.isValid())
|
||||
projectItem->setMainUiFile(mainUiFileProperty.value.toString());
|
||||
|
||||
const auto importPathsProperty = rootNode->property(QLatin1String("importPaths"));
|
||||
if (importPathsProperty.isValid()) {
|
||||
QStringList list = importPathsProperty.value.toStringList();
|
||||
|
@ -81,6 +81,9 @@ public:
|
||||
QString mainFile() const { return m_mainFile; }
|
||||
void setMainFile(const QString &mainFilePath) { m_mainFile = mainFilePath; }
|
||||
|
||||
QString mainUiFile() const { return m_mainUiFile; }
|
||||
void setMainUiFile(const QString &mainUiFilePath) { m_mainUiFile = mainUiFilePath; }
|
||||
|
||||
bool widgetApp() const { return m_widgetApp; }
|
||||
void setWidgetApp(bool widgetApp) { m_widgetApp = widgetApp; }
|
||||
|
||||
@ -107,6 +110,7 @@ protected:
|
||||
QStringList m_supportedLanguages;
|
||||
QString m_primaryLanguage;
|
||||
QString m_mainFile;
|
||||
QString m_mainUiFile;
|
||||
Utils::EnvironmentItems m_environment;
|
||||
QVector<QmlProjectContentItem *> m_content; // content property
|
||||
bool m_forceFreeType = false;
|
||||
|
@ -118,21 +118,38 @@ QmlProject::QmlProject(const Utils::FilePath &fileName)
|
||||
disconnect(m_openFileConnection);
|
||||
|
||||
if (target && success) {
|
||||
Utils::FilePaths uiFiles = getUiQmlFilesForFolder(projectDirectory()
|
||||
+ "/content");
|
||||
if (uiFiles.isEmpty())
|
||||
uiFiles = getUiQmlFilesForFolder(projectDirectory());
|
||||
|
||||
if (!uiFiles.isEmpty()) {
|
||||
Utils::FilePath currentFile;
|
||||
if (auto cd = Core::EditorManager::currentDocument())
|
||||
currentFile = cd->filePath();
|
||||
auto target = activeTarget();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (currentFile.isEmpty() || !isKnownFile(currentFile))
|
||||
QTimer::singleShot(1000, [uiFiles]() {
|
||||
Core::EditorManager::openEditor(uiFiles.first(),
|
||||
auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
|
||||
target->buildSystem());
|
||||
|
||||
const Utils::FilePath mainUiFile = qmlBuildSystem->mainUiFilePath();
|
||||
|
||||
if (mainUiFile.completeSuffix() == "qi.qml" && mainUiFile.exists()) {
|
||||
QTimer::singleShot(1000, [mainUiFile]() {
|
||||
Core::EditorManager::openEditor(mainUiFile,
|
||||
Utils::Id());
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Utils::FilePaths uiFiles = getUiQmlFilesForFolder(projectDirectory()
|
||||
+ "/content");
|
||||
if (uiFiles.isEmpty())
|
||||
uiFiles = getUiQmlFilesForFolder(projectDirectory());
|
||||
|
||||
if (!uiFiles.isEmpty()) {
|
||||
Utils::FilePath currentFile;
|
||||
if (auto cd = Core::EditorManager::currentDocument())
|
||||
currentFile = cd->filePath();
|
||||
|
||||
if (currentFile.isEmpty() || !isKnownFile(currentFile))
|
||||
QTimer::singleShot(1000, [uiFiles]() {
|
||||
Core::EditorManager::openEditor(uiFiles.first(),
|
||||
Utils::Id());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -236,6 +253,58 @@ void QmlBuildSystem::parseProject(RefreshOptions options)
|
||||
}
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting, const Utils::FilePath &mainFilePath, const QString &oldFile)
|
||||
{
|
||||
// make sure to change it also in the qmlproject file
|
||||
const Utils::FilePath qmlProjectFilePath = project()->projectFilePath();
|
||||
Core::FileChangeBlocker fileChangeBlocker(qmlProjectFilePath);
|
||||
const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForFilePath(qmlProjectFilePath);
|
||||
TextEditor::TextDocument *document = nullptr;
|
||||
if (!editors.isEmpty()) {
|
||||
document = qobject_cast<TextEditor::TextDocument*>(editors.first()->document());
|
||||
if (document && document->isModified())
|
||||
if (!Core::DocumentManager::saveDocument(document))
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fileContent;
|
||||
QString error;
|
||||
Utils::TextFileFormat textFileFormat;
|
||||
const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8
|
||||
if (Utils::TextFileFormat::readFile(qmlProjectFilePath, codec, &fileContent, &textFileFormat, &error)
|
||||
!= Utils::TextFileFormat::ReadSuccess) {
|
||||
qWarning() << "Failed to read file" << qmlProjectFilePath << ":" << error;
|
||||
}
|
||||
|
||||
const QString settingQmlCode = setting + ":";
|
||||
|
||||
QDir projectDir = project()->projectFilePath().toDir();
|
||||
projectDir.cdUp();
|
||||
const QString relativePath = projectDir.relativeFilePath(mainFilePath.toString());
|
||||
|
||||
if (fileContent.indexOf(settingQmlCode) < 0) {
|
||||
QString addedText = QString("\n %1 \"%2\"\n").arg(settingQmlCode).arg(relativePath);
|
||||
auto index = fileContent.lastIndexOf("}");
|
||||
fileContent.insert(index, addedText);
|
||||
} else {
|
||||
QString originalFileName = oldFile;
|
||||
originalFileName.replace(".", "\\.");
|
||||
const QRegularExpression expression(QString("%1\\s*\"(%2)\"").arg(settingQmlCode).arg(originalFileName));
|
||||
|
||||
const QRegularExpressionMatch match = expression.match(fileContent);
|
||||
|
||||
fileContent.replace(match.capturedStart(1),
|
||||
match.capturedLength(1),
|
||||
relativePath);
|
||||
}
|
||||
|
||||
if (!textFileFormat.writeFile(qmlProjectFilePath, fileContent, &error))
|
||||
qWarning() << "Failed to write file" << qmlProjectFilePath << ":" << error;
|
||||
|
||||
refresh(Everything);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QmlBuildSystem::refresh(RefreshOptions options)
|
||||
{
|
||||
ParseGuard guard = guardParsingRun();
|
||||
@ -266,11 +335,68 @@ QString QmlBuildSystem::mainFile() const
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString QmlBuildSystem::mainUiFile() const
|
||||
{
|
||||
if (m_projectItem)
|
||||
return m_projectItem->mainUiFile();
|
||||
return QString();
|
||||
}
|
||||
|
||||
Utils::FilePath QmlBuildSystem::mainFilePath() const
|
||||
{
|
||||
return projectDirectory().pathAppended(mainFile());
|
||||
}
|
||||
|
||||
Utils::FilePath QmlBuildSystem::mainUiFilePath() const
|
||||
{
|
||||
return projectDirectory().pathAppended(mainUiFile());
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::setMainFileInProjectFile(const Utils::FilePath &newMainFilePath)
|
||||
{
|
||||
|
||||
return setFileSettingInProjectFile("mainFile", newMainFilePath, mainFile());
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::setMainUiFileInProjectFile(const Utils::FilePath &newMainUiFilePath)
|
||||
{
|
||||
return setMainUiFileInMainFile(newMainUiFilePath)
|
||||
&& setFileSettingInProjectFile("mainUiFile", newMainUiFilePath, mainUiFile());
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::setMainUiFileInMainFile(const Utils::FilePath &newMainUiFilePath)
|
||||
{
|
||||
Core::FileChangeBlocker fileChangeBlocker(mainFilePath());
|
||||
const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForFilePath(mainFilePath());
|
||||
TextEditor::TextDocument *document = nullptr;
|
||||
if (!editors.isEmpty()) {
|
||||
document = qobject_cast<TextEditor::TextDocument*>(editors.first()->document());
|
||||
if (document && document->isModified())
|
||||
if (!Core::DocumentManager::saveDocument(document))
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fileContent;
|
||||
QString error;
|
||||
Utils::TextFileFormat textFileFormat;
|
||||
const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8
|
||||
if (Utils::TextFileFormat::readFile(mainFilePath(), codec, &fileContent, &textFileFormat, &error)
|
||||
!= Utils::TextFileFormat::ReadSuccess) {
|
||||
qWarning() << "Failed to read file" << mainFilePath() << ":" << error;
|
||||
}
|
||||
|
||||
const QString currentMain = QString("%1 {").arg(mainUiFilePath().baseName());
|
||||
const QString newMain = QString("%1 {").arg(newMainUiFilePath.baseName());
|
||||
|
||||
if (fileContent.contains(currentMain))
|
||||
fileContent.replace(currentMain, newMain);
|
||||
|
||||
if (!textFileFormat.writeFile(mainFilePath(), fileContent, &error))
|
||||
qWarning() << "Failed to write file" << mainFilePath() << ":" << error;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::qtForMCUs() const
|
||||
{
|
||||
if (m_projectItem)
|
||||
@ -646,43 +772,10 @@ bool QmlBuildSystem::deleteFiles(Node *context, const FilePaths &filePaths)
|
||||
bool QmlBuildSystem::renameFile(Node * context, const FilePath &oldFilePath, const FilePath &newFilePath)
|
||||
{
|
||||
if (dynamic_cast<QmlProjectNode *>(context)) {
|
||||
if (oldFilePath.endsWith(mainFile())) {
|
||||
setMainFile(newFilePath.toString());
|
||||
|
||||
// make sure to change it also in the qmlproject file
|
||||
const Utils::FilePath qmlProjectFilePath = project()->projectFilePath();
|
||||
Core::FileChangeBlocker fileChangeBlocker(qmlProjectFilePath);
|
||||
const QList<Core::IEditor *> editors = Core::DocumentModel::editorsForFilePath(qmlProjectFilePath);
|
||||
TextEditor::TextDocument *document = nullptr;
|
||||
if (!editors.isEmpty()) {
|
||||
document = qobject_cast<TextEditor::TextDocument*>(editors.first()->document());
|
||||
if (document && document->isModified())
|
||||
if (!Core::DocumentManager::saveDocument(document))
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fileContent;
|
||||
QString error;
|
||||
Utils::TextFileFormat textFileFormat;
|
||||
const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8
|
||||
if (Utils::TextFileFormat::readFile(qmlProjectFilePath, codec, &fileContent, &textFileFormat, &error)
|
||||
!= Utils::TextFileFormat::ReadSuccess) {
|
||||
qWarning() << "Failed to read file" << qmlProjectFilePath << ":" << error;
|
||||
}
|
||||
|
||||
// find the mainFile and do the file name with brackets in a capture group and mask the . with \.
|
||||
QString originalFileName = oldFilePath.fileName();
|
||||
originalFileName.replace(".", "\\.");
|
||||
const QRegularExpression expression(QString("mainFile:\\s*\"(%1)\"").arg(originalFileName));
|
||||
const QRegularExpressionMatch match = expression.match(fileContent);
|
||||
|
||||
fileContent.replace(match.capturedStart(1), match.capturedLength(1), newFilePath.fileName());
|
||||
|
||||
if (!textFileFormat.writeFile(qmlProjectFilePath, fileContent, &error))
|
||||
qWarning() << "Failed to write file" << qmlProjectFilePath << ":" << error;
|
||||
|
||||
refresh(Everything);
|
||||
}
|
||||
if (oldFilePath.endsWith(mainFile()))
|
||||
return setMainFileInProjectFile(newFilePath);
|
||||
if (oldFilePath.endsWith(mainUiFile()))
|
||||
return setMainUiFileInProjectFile(newFilePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -77,7 +77,13 @@ public:
|
||||
|
||||
Utils::FilePath canonicalProjectDir() const;
|
||||
QString mainFile() const;
|
||||
QString mainUiFile() const;
|
||||
Utils::FilePath mainFilePath() const;
|
||||
Utils::FilePath mainUiFilePath() const;
|
||||
|
||||
bool setMainFileInProjectFile(const Utils::FilePath &newMainFilePath);
|
||||
bool setMainUiFileInProjectFile(const Utils::FilePath &newMainUiFilePath);
|
||||
bool setMainUiFileInMainFile(const Utils::FilePath &newMainUiFilePath);
|
||||
|
||||
bool qtForMCUs() const;
|
||||
bool qt6Project() const;
|
||||
@ -116,6 +122,10 @@ public:
|
||||
void parseProject(RefreshOptions options);
|
||||
|
||||
private:
|
||||
bool setFileSettingInProjectFile(const QString &setting,
|
||||
const Utils::FilePath &mainFilePath,
|
||||
const QString &oldFile);
|
||||
|
||||
std::unique_ptr<QmlProjectItem> m_projectItem;
|
||||
Utils::FilePath m_canonicalProjectDir;
|
||||
bool m_blockFilesUpdate = false;
|
||||
|
@ -30,16 +30,23 @@
|
||||
#include "qmlprojectrunconfiguration.h"
|
||||
#include "projectfilecontenttools.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/designmode.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/fileiconprovider.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagebox.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <projectexplorer/runcontrol.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||
|
||||
@ -54,11 +61,12 @@
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QPointer>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <QPointer>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
@ -230,19 +238,124 @@ void QmlProjectPlugin::openInQDSWithProject(const Utils::FilePath &filePath)
|
||||
}
|
||||
}
|
||||
|
||||
static QmlBuildSystem *qmlBuildSystemforFileNode(const FileNode *fileNode)
|
||||
{
|
||||
if (!fileNode)
|
||||
return nullptr;
|
||||
|
||||
if (QmlProject *qmlProject = qobject_cast<QmlProject*>(fileNode->getProject())) {
|
||||
auto target = qmlProject->activeTarget();
|
||||
if (!target)
|
||||
return nullptr;
|
||||
|
||||
return qobject_cast<QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
|
||||
{
|
||||
Q_UNUSED(errorMessage)
|
||||
|
||||
d = new QmlProjectPluginPrivate;
|
||||
|
||||
if (!qmlDesignerEnabled()) {
|
||||
if (!qmlDesignerEnabled())
|
||||
initializeQmlLandingPage();
|
||||
}
|
||||
|
||||
ProjectManager::registerProjectType<QmlProject>(QmlJSTools::Constants::QMLPROJECT_MIMETYPE);
|
||||
Core::FileIconProvider::registerIconOverlayForSuffix(":/qmlproject/images/qmlproject.png",
|
||||
"qmlproject");
|
||||
|
||||
if (QmlProject::isQtDesignStudio()) {
|
||||
Core::ActionContainer *menu = Core::ActionManager::actionContainer(
|
||||
ProjectExplorer::Constants::M_FILECONTEXT);
|
||||
QAction *mainfileAction = new QAction(tr("Set as main .qml file"), this);
|
||||
mainfileAction->setEnabled(false);
|
||||
|
||||
connect(mainfileAction, &QAction::triggered, this, []() {
|
||||
const Node *currentNode = ProjectTree::currentNode();
|
||||
if (!currentNode || !currentNode->asFileNode()
|
||||
|| currentNode->asFileNode()->fileType() != FileType::QML)
|
||||
return;
|
||||
|
||||
const Utils::FilePath file = currentNode->filePath();
|
||||
|
||||
QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(currentNode->asFileNode());
|
||||
if (buildSystem)
|
||||
buildSystem->setMainFileInProjectFile(file);
|
||||
});
|
||||
|
||||
menu->addAction(Core::ActionManager::registerAction(
|
||||
mainfileAction,
|
||||
"QmlProject.setMainFile",
|
||||
Core::Context(ProjectExplorer::Constants::C_PROJECT_TREE)),
|
||||
ProjectExplorer::Constants::G_FILE_OTHER);
|
||||
mainfileAction->setVisible(false);
|
||||
connect(ProjectTree::instance(),
|
||||
&ProjectTree::currentNodeChanged,
|
||||
mainfileAction,
|
||||
[mainfileAction](Node *node) {
|
||||
const FileNode *fileNode = node ? node->asFileNode() : nullptr;
|
||||
|
||||
const bool isVisible = fileNode && fileNode->fileType() == FileType::QML
|
||||
&& fileNode->filePath().completeSuffix() == "qml";
|
||||
|
||||
mainfileAction->setVisible(isVisible);
|
||||
|
||||
if (!isVisible)
|
||||
return;
|
||||
|
||||
QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(fileNode);
|
||||
|
||||
if (buildSystem)
|
||||
mainfileAction->setEnabled(buildSystem->mainFilePath()
|
||||
!= fileNode->filePath());
|
||||
});
|
||||
|
||||
QAction *mainUifileAction = new QAction(tr("Set as main .ui.qml file"), this);
|
||||
mainUifileAction->setEnabled(false);
|
||||
|
||||
connect(mainUifileAction, &QAction::triggered, this, []() {
|
||||
const Node *currentNode = ProjectTree::currentNode();
|
||||
if (!currentNode || !currentNode->asFileNode()
|
||||
|| currentNode->asFileNode()->fileType() != FileType::QML)
|
||||
return;
|
||||
|
||||
const Utils::FilePath file = currentNode->filePath();
|
||||
|
||||
QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(currentNode->asFileNode());
|
||||
if (buildSystem)
|
||||
buildSystem->setMainUiFileInProjectFile(file);
|
||||
});
|
||||
|
||||
menu->addAction(Core::ActionManager::registerAction(
|
||||
mainUifileAction,
|
||||
"QmlProject.setMainUIFile",
|
||||
Core::Context(ProjectExplorer::Constants::C_PROJECT_TREE)),
|
||||
ProjectExplorer::Constants::G_FILE_OTHER);
|
||||
mainUifileAction->setVisible(false);
|
||||
connect(ProjectTree::instance(),
|
||||
&ProjectTree::currentNodeChanged,
|
||||
mainUifileAction,
|
||||
[mainUifileAction](Node *node) {
|
||||
const FileNode *fileNode = node ? node->asFileNode() : nullptr;
|
||||
const bool isVisible = fileNode && fileNode->fileType() == FileType::QML
|
||||
&& fileNode->filePath().completeSuffix() == "ui.qml";
|
||||
|
||||
mainUifileAction->setVisible(isVisible);
|
||||
|
||||
if (!isVisible)
|
||||
return;
|
||||
|
||||
QmlBuildSystem *buildSystem = qmlBuildSystemforFileNode(fileNode);
|
||||
if (buildSystem)
|
||||
mainUifileAction->setEnabled(buildSystem->mainUiFilePath()
|
||||
!= fileNode->filePath());
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -196,17 +196,6 @@ void FileDownloader::probeUrl()
|
||||
});
|
||||
|
||||
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
QQmlData *data = QQmlData::get(this, false);
|
||||
if (!data) {
|
||||
qDebug() << Q_FUNC_INFO << "FileDownloader is nullptr.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (QQmlData::wasDeleted(this)) {
|
||||
qDebug() << Q_FUNC_INFO << "FileDownloader was deleted.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->error())
|
||||
return;
|
||||
|
||||
@ -383,7 +372,6 @@ void FileExtractor::extract()
|
||||
|
||||
Utils::Archive *archive = new Utils::Archive(m_sourceFile, m_targetPath);
|
||||
QTC_ASSERT(archive->isValid(), delete archive; return);
|
||||
archive->setParent(this);
|
||||
|
||||
m_timer.start();
|
||||
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||
@ -423,7 +411,8 @@ void FileExtractor::extract()
|
||||
emit detailedTextChanged();
|
||||
});
|
||||
|
||||
QObject::connect(archive, &Utils::Archive::finished, this, [this](bool ret) {
|
||||
QObject::connect(archive, &Utils::Archive::finished, this, [this, archive](bool ret) {
|
||||
delete archive;
|
||||
m_finished = ret;
|
||||
m_timer.stop();
|
||||
|
||||
@ -436,3 +425,76 @@ void FileExtractor::extract()
|
||||
});
|
||||
archive->unarchive();
|
||||
}
|
||||
|
||||
static Utils::FilePath tempFilePath()
|
||||
{
|
||||
QStandardPaths::StandardLocation location = QStandardPaths::CacheLocation;
|
||||
|
||||
return Utils::FilePath::fromString(QStandardPaths::writableLocation(location))
|
||||
.pathAppended("QtDesignStudio");
|
||||
}
|
||||
|
||||
DataModelDownloader::DataModelDownloader(QObject * /* parent */)
|
||||
{
|
||||
auto fileInfo = targetFolder().toFileInfo();
|
||||
m_birthTime = fileInfo.birthTime();
|
||||
m_exists = fileInfo.exists();
|
||||
}
|
||||
|
||||
void DataModelDownloader::start()
|
||||
{
|
||||
m_fileDownloader.setUrl(QUrl::fromUserInput(
|
||||
"https://download.qt.io/learning/examples/qtdesignstudio/dataImports.zip"));
|
||||
|
||||
connect(&m_fileDownloader, &FileDownloader::availableChanged, this, [this]() {
|
||||
|
||||
m_available = m_fileDownloader.available();
|
||||
|
||||
emit availableChanged();
|
||||
|
||||
if (!m_available) {
|
||||
qWarning() << m_fileDownloader.url() << "failed to download";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_forceDownload && m_fileDownloader.lastModified() < m_birthTime)
|
||||
return;
|
||||
|
||||
m_fileDownloader.start();
|
||||
connect(&m_fileDownloader, &FileDownloader::finishedChanged, this, [this]() {
|
||||
if (m_fileDownloader.finished()) {
|
||||
const Utils::FilePath archiveFile = Utils::FilePath::fromString(
|
||||
m_fileDownloader.tempFile());
|
||||
QTC_ASSERT(Utils::Archive::supportsFile(archiveFile), return );
|
||||
auto archive = new Utils::Archive(archiveFile, tempFilePath());
|
||||
QTC_ASSERT(archive->isValid(), delete archive; return );
|
||||
QObject::connect(archive, &Utils::Archive::finished, this, [this, archive](bool ret) {
|
||||
QTC_CHECK(ret);
|
||||
delete archive;
|
||||
emit finished();
|
||||
});
|
||||
archive->unarchive();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool DataModelDownloader::exists() const
|
||||
{
|
||||
return m_exists;
|
||||
}
|
||||
|
||||
bool DataModelDownloader::available() const
|
||||
{
|
||||
return m_available;
|
||||
}
|
||||
|
||||
Utils::FilePath DataModelDownloader::targetFolder() const
|
||||
{
|
||||
return Utils::FilePath::fromUserInput(tempFilePath().toString() + "/" + "dataImports");
|
||||
}
|
||||
|
||||
void DataModelDownloader::setForceDownload(bool b)
|
||||
{
|
||||
m_forceDownload = b;
|
||||
}
|
||||
|
@ -154,5 +154,29 @@ private:
|
||||
int m_progress = 0;
|
||||
QFile m_tempFile;
|
||||
QDateTime m_lastModified;
|
||||
bool m_available;
|
||||
bool m_available = false;
|
||||
};
|
||||
|
||||
class DataModelDownloader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DataModelDownloader(QObject *parent = nullptr);
|
||||
void start();
|
||||
bool exists() const;
|
||||
bool available() const;
|
||||
Utils::FilePath targetFolder() const;
|
||||
void setForceDownload(bool b);
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
void availableChanged();
|
||||
|
||||
private:
|
||||
FileDownloader m_fileDownloader;
|
||||
QDateTime m_birthTime;
|
||||
bool m_exists = false;
|
||||
bool m_available = false;
|
||||
bool m_forceDownload = false;
|
||||
};
|
||||
|
@ -447,6 +447,7 @@ public:
|
||||
|
||||
private:
|
||||
QQuickWidget *m_modeWidget = nullptr;
|
||||
DataModelDownloader *m_dataModelDownloader = nullptr;
|
||||
};
|
||||
|
||||
void StudioWelcomePlugin::closeSplashScreen()
|
||||
@ -596,6 +597,28 @@ WelcomeMode::WelcomeMode()
|
||||
{
|
||||
setDisplayName(tr("Welcome"));
|
||||
|
||||
const QString welcomePagePath = Core::ICore::resourcePath("qmldesigner/welcomepage").toString();
|
||||
|
||||
m_dataModelDownloader = new DataModelDownloader(this);
|
||||
if (!m_dataModelDownloader->exists()) { //Fallback if data cannot be downloaded
|
||||
Utils::FileUtils::copyRecursively(Utils::FilePath::fromUserInput(welcomePagePath
|
||||
+ "/dataImports"),
|
||||
m_dataModelDownloader->targetFolder());
|
||||
m_dataModelDownloader->setForceDownload(true);
|
||||
}
|
||||
Utils::FilePath readme = Utils::FilePath::fromUserInput(welcomePagePath
|
||||
+ "/dataImports/readme.txt");
|
||||
|
||||
if (!readme.exists()) // Only downloads contain the readme
|
||||
m_dataModelDownloader->setForceDownload(true);
|
||||
|
||||
m_dataModelDownloader->start();
|
||||
|
||||
connect(m_dataModelDownloader, &DataModelDownloader::finished, this, [this](){
|
||||
auto source = m_modeWidget->source();
|
||||
m_modeWidget->engine()->clearComponentCache();
|
||||
m_modeWidget->setSource(source);
|
||||
});
|
||||
const Utils::Icon FLAT({{":/studiowelcome/images/mode_welcome_mask.png",
|
||||
Utils::Theme::IconsBaseColor}});
|
||||
const Utils::Icon FLAT_ACTIVE({{":/studiowelcome/images/mode_welcome_mask.png",
|
||||
@ -640,8 +663,8 @@ WelcomeMode::WelcomeMode()
|
||||
|
||||
m_modeWidget->engine()->addImportPath(Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources/imports").toString());
|
||||
|
||||
const QString welcomePagePath = Core::ICore::resourcePath("qmldesigner/welcomepage").toString();
|
||||
m_modeWidget->engine()->addImportPath(welcomePagePath + "/imports");
|
||||
m_modeWidget->engine()->addImportPath(m_dataModelDownloader->targetFolder().toString());
|
||||
m_modeWidget->setSource(QUrl::fromLocalFile(welcomePagePath + "/main.qml"));
|
||||
|
||||
QShortcut *updateShortcut = nullptr;
|
||||
|
@ -4,29 +4,7 @@ Squish tests inside this folder have several prerequisites to get them running.
|
||||
|
||||
First - and most important - you have to own a valid Squish license. At least Squish 6.0 is required.
|
||||
|
||||
Second - some of the test suites/test cases expect a build of Qt 4.8.7 to be available:
|
||||
[ this is optional and if Qt4 is not available some Qt5 will be tried to use instead ]
|
||||
1. Download the source code from:
|
||||
* Windows: https://download.qt.io/archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.zip
|
||||
* Other: https://download.qt.io/archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.tar.gz
|
||||
2. Extract the contents of the archive's directory qt-everywhere-opensource-src-4.8.7 to:
|
||||
* Windows: C:\Qt\Qt4.8.7
|
||||
* Other: $HOME/Qt4.8.7
|
||||
3. Apply the changes from patch.txt next to this README.
|
||||
4. In the directory you extracted the sources to, configure Qt:
|
||||
* Windows (MSVC2013 32 bit):
|
||||
.\configure.exe -opensource -developer-build -confirm-license -debug-and-release -nomake tests -nomake examples -nomake demos -no-webkit -no-phonon
|
||||
* Linux (gcc < 6):
|
||||
./configure -opensource -developer-build -confirm-license -debug-and-release -nomake tests -nomake examples -nomake demos -no-webkit -no-phonon
|
||||
* macOS:
|
||||
./configure -opensource -developer-build -confirm-license -debug-and-release -nomake tests -nomake examples -nomake demos -no-webkit -no-phonon -sdk <PATH_TO_INSTALLED_MACOSX_SDK>
|
||||
5. Make:
|
||||
* Windows (do not use jom):
|
||||
nmake
|
||||
* Other:
|
||||
make -j<number of available cores>
|
||||
|
||||
Third - some of the test suites/test cases expect Qt versions to be installed in their default
|
||||
Second - some of the test suites/test cases expect Qt versions to be installed in their default
|
||||
locations. On Linux/macOS this is ~/Qt5.x.1 and on Windows this is C:\Qt\Qt5.x.1. It's easiest to
|
||||
use installations of the official opensource Qt packages. Just install the Qt version for the
|
||||
respective toolchain with the components (if available):
|
||||
@ -50,7 +28,7 @@ Qt 5.4.1 (gcc)
|
||||
Qt 5.10.1 (MSVC2015, 32 bit)
|
||||
Qt 5.14.1 (MSVC2017, 64 bit)
|
||||
|
||||
Fourth - you'll have to provide some additional repositories.
|
||||
Third - you'll have to provide some additional repositories.
|
||||
These additional repositories are located inside ~/squish-data or C:\Users\<user>\squish-data (depending on the OS you're on).
|
||||
You can also just provide them inside a different folder and specify the folder with the environment variable SYSTEST_SRCPATH.
|
||||
This folder must contain the following:
|
||||
@ -58,12 +36,12 @@ This folder must contain the following:
|
||||
* a subfolder called 'creator-test-data'
|
||||
* a speedcrunch 0.11 repository (or source copy) inside 'creator-test-data' named 'speedcrunch'
|
||||
|
||||
Fifth - you'll have to make sure that some needed tools are available (no matter on which OS you're on).
|
||||
Fourth - you'll have to make sure that some needed tools are available (no matter on which OS you're on).
|
||||
* cmake 3.14 or newer
|
||||
* wget or curl, capable of HTTPS
|
||||
Normally it should be okay to just install them as usual and add their executables' path(s) to the PATH variable.
|
||||
|
||||
Sixth - Qt Creator must be built on a Qt without Qt WebEngine or Qt WebKit.
|
||||
Fifth - Qt Creator must be built on a Qt without Qt WebEngine or Qt WebKit.
|
||||
|
||||
On macOS make sure you are using the correct keyboard layout to avoid problems when using keyboard interaction. Tested and known to be
|
||||
working would be 'U.S. International - PC', while pure 'U.S.' had problems.
|
||||
|
@ -4,31 +4,6 @@
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>Profile.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.Data">
|
||||
<value type="QString" key="Android.GdbServer.Information"></value>
|
||||
<value type="QString" key="Debugger.Information">{70e26273-2c0b-4534-bbc0-eb6ca670821a}</value>
|
||||
<value type="QString" key="PE.Profile.Device">{7c5a3673-e300-4286-9666-0f86d3e3dc38}</value>
|
||||
<value type="QByteArray" key="PE.Profile.DeviceType">GenericLinuxOsType</value>
|
||||
<value type="QString" key="PE.Profile.SysRoot"></value>
|
||||
<value type="QString" key="PE.Profile.ToolChain">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.ToolChains">
|
||||
<value type="QByteArray" key="C">{461bb8dc-22ff-461f-82fe-ebe8b21b697f}</value>
|
||||
<value type="QString" key="Cxx">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="QtPM4.mkSpecInformation"></value>
|
||||
<value type="int" key="QtSupport.QtInformation">2</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="PE.Profile.Icon">:///DESKTOP///</value>
|
||||
<value type="QString" key="PE.Profile.Id">{f16848fc-b615-43b5-b0cc-16a9f57fb573}</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.MutableInfo"/>
|
||||
<value type="QString" key="PE.Profile.Name">Embedded Linux</value>
|
||||
<value type="bool" key="PE.Profile.SDK">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -55,32 +30,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.Data">
|
||||
<value type="QString" key="Android.GdbServer.Information"></value>
|
||||
<value type="QString" key="Debugger.Information">{2f514661-b9f7-4f83-8822-a9a9d0699600}</value>
|
||||
<value type="QString" key="PE.Profile.Device">Desktop Device</value>
|
||||
<value type="QByteArray" key="PE.Profile.DeviceType">Desktop</value>
|
||||
<value type="QString" key="PE.Profile.SysRoot"></value>
|
||||
<value type="QString" key="PE.Profile.ToolChain">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.ToolChains">
|
||||
<value type="QByteArray" key="C">{461bb8dc-22ff-461f-82fe-ebe8b21b697f}</value>
|
||||
<value type="QString" key="Cxx">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="QtPM4.mkSpecInformation"></value>
|
||||
<value type="int" key="QtSupport.QtInformation">2</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="PE.Profile.Icon">:///DESKTOP///</value>
|
||||
<value type="QString" key="PE.Profile.Id">{1dcb5509-1670-470d-80a5-8a988f36e4e2}</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.MutableInfo"/>
|
||||
<value type="QString" key="PE.Profile.Name">Desktop 4.8.7 default</value>
|
||||
<value type="bool" key="PE.Profile.SDK">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.3</variable>
|
||||
<variable>Profile.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -108,7 +58,7 @@
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.Count</variable>
|
||||
<value type="int">4</value>
|
||||
<value type="int">2</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.Default</variable>
|
||||
|
@ -4,16 +4,6 @@
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>QtVersion.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">2</value>
|
||||
<value type="QString" key="Name">Desktop Qt 4.8 for GCC</value>
|
||||
<value type="QString" key="QMakePath">~/Qt4.8.7/bin/qmake</value>
|
||||
<value type="QString" key="QtVersion.Type">Qt4ProjectManager.QtVersion.Desktop</value>
|
||||
<value type="bool" key="isAutodetected">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">9</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (SQUISH_DEFAULT_COMPILER)</value>
|
||||
@ -23,7 +13,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.2</variable>
|
||||
<variable>QtVersion.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">11</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (SQUISH_DEFAULT_COMPILER)</value>
|
||||
|
@ -4,52 +4,6 @@
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>Profile.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.Data">
|
||||
<value type="QString" key="Android.GdbServer.Information"></value>
|
||||
<value type="QString" key="Debugger.Information">{70e26273-2c0b-4534-bbc0-eb6ca670821a}</value>
|
||||
<value type="QString" key="PE.Profile.Device">{7c5a3673-e300-4286-9666-0f86d3e3dc38}</value>
|
||||
<value type="QByteArray" key="PE.Profile.DeviceType">GenericLinuxOsType</value>
|
||||
<value type="QString" key="PE.Profile.SysRoot"></value>
|
||||
<value type="QString" key="PE.Profile.ToolChain">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.ToolChains">
|
||||
<value type="QByteArray" key="C">{7bfd4fd4-e64a-417f-b10f-20602e1719d1}</value>
|
||||
<value type="QString" key="Cxx">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="QtPM4.mkSpecInformation"></value>
|
||||
<value type="int" key="QtSupport.QtInformation">2</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="PE.Profile.Icon">:///DESKTOP///</value>
|
||||
<value type="QString" key="PE.Profile.Id">{f16848fc-b615-43b5-b0cc-16a9f57fb573}</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.MutableInfo"/>
|
||||
<value type="QString" key="PE.Profile.Name">Embedded Linux</value>
|
||||
<value type="bool" key="PE.Profile.SDK">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.Data">
|
||||
<value type="QString" key="Android.GdbServer.Information"></value>
|
||||
<value type="QString" key="Debugger.Information">{70e26273-2c0b-4534-bbc0-eb6ca670821a}</value>
|
||||
<value type="QString" key="PE.Profile.Device">Desktop Device</value>
|
||||
<value type="QByteArray" key="PE.Profile.DeviceType">Desktop</value>
|
||||
<value type="QString" key="PE.Profile.SysRoot"></value>
|
||||
<value type="QString" key="PE.Profile.ToolChain">ProjectExplorer.ToolChain.Gcc:{c3f59b87-6997-4bd8-8067-ee04dc536371}</value>
|
||||
<value type="QString" key="QtPM4.mkSpecInformation"></value>
|
||||
<value type="int" key="QtSupport.QtInformation">2</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="PE.Profile.Icon">:///DESKTOP///</value>
|
||||
<value type="QString" key="PE.Profile.Id">{1dcb5509-1670-470d-80a5-8a988f36e4e2}</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.MutableInfo"/>
|
||||
<value type="QString" key="PE.Profile.Name">Desktop 4.8.7 default</value>
|
||||
<value type="bool" key="PE.Profile.SDK">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -73,7 +27,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.3</variable>
|
||||
<variable>Profile.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -97,7 +51,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.4</variable>
|
||||
<variable>Profile.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -126,7 +80,7 @@
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.Count</variable>
|
||||
<value type="int">5</value>
|
||||
<value type="int">3</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.Default</variable>
|
||||
|
@ -4,16 +4,6 @@
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>QtVersion.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">2</value>
|
||||
<value type="QString" key="Name">Desktop Qt 4.8 for GCC</value>
|
||||
<value type="QString" key="QMakePath">~/Qt4.8.7/bin/qmake</value>
|
||||
<value type="QString" key="QtVersion.Type">Qt4ProjectManager.QtVersion.Desktop</value>
|
||||
<value type="bool" key="isAutodetected">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">13</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (SQUISH_DEFAULT_COMPILER)</value>
|
||||
@ -23,7 +13,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.2</variable>
|
||||
<variable>QtVersion.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">15</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (SQUISH_DEFAULT_COMPILER)</value>
|
||||
@ -33,7 +23,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.3</variable>
|
||||
<variable>QtVersion.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">17</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (SQUISH_DEFAULT_COMPILER)</value>
|
||||
|
@ -4,34 +4,6 @@
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>Profile.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.Data">
|
||||
<value type="QString" key="Android.GdbServer.Information"></value>
|
||||
<value type="QString" key="Debugger.Information">{1b25f20a-d584-4fb7-85b3-74dd15b82f6f}</value>
|
||||
<value type="QString" key="PE.Profile.Device">Desktop Device</value>
|
||||
<value type="QByteArray" key="PE.Profile.DeviceType">Desktop</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.Environment"/>
|
||||
<value type="QString" key="PE.Profile.SysRoot"></value>
|
||||
<value type="QString" key="PE.Profile.ToolChain">{7ca0887f-a9a5-4251-aba6-560a15595d20}</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.ToolChains">
|
||||
<value type="QByteArray" key="C">{d35e7a1a-5ab8-4fd6-8a2c-634846c669bb}</value>
|
||||
<value type="QString" key="Cxx">{7ca0887f-a9a5-4251-aba6-560a15595d20}</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="QtPM4.mkSpecInformation"></value>
|
||||
<value type="int" key="QtSupport.QtInformation">2</value>
|
||||
</valuemap>
|
||||
<value type="QString" key="PE.Profile.Icon">:///DESKTOP///</value>
|
||||
<value type="QString" key="PE.Profile.Id">{9b35bbe6-25a7-4cce-ba07-487c795f5265}</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.MutableInfo"/>
|
||||
<value type="QString" key="PE.Profile.Name">Desktop 4.8.7 default</value>
|
||||
<value type="bool" key="PE.Profile.SDK">false</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.StickyInfo"/>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -59,7 +31,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.2</variable>
|
||||
<variable>Profile.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -70,8 +42,7 @@
|
||||
<value type="QByteArray" key="PE.Profile.DeviceType">Desktop</value>
|
||||
<valuelist type="QVariantList" key="PE.Profile.Environment"/>
|
||||
<value type="QString" key="PE.Profile.SysRoot"></value>
|
||||
<value type="QString" key="PE.Profile.ToolChain">{7ca0887f-a9a5-4251-aba6-560a15595d20}</value>
|
||||
<valuemap type="QVariantMap" key="PE.Profile.ToolChains">
|
||||
<valuemap type="QVariantMap" key="PE.Profile.ToolChainsV3">
|
||||
<value type="QByteArray" key="C">{ce3a8004-e9ae-46f2-b62d-d7daf69435ca}</value>
|
||||
<value type="QByteArray" key="Cxx">{3df7c776-a480-4a04-9099-6c75adac2dca}</value>
|
||||
</valuemap>
|
||||
@ -87,7 +58,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.3</variable>
|
||||
<variable>Profile.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="PE.Profile.AutoDetected">false</value>
|
||||
<value type="QString" key="PE.Profile.AutoDetectionSource"></value>
|
||||
@ -116,7 +87,7 @@
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.Count</variable>
|
||||
<value type="int">4</value>
|
||||
<value type="int">3</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Profile.Default</variable>
|
||||
|
@ -4,16 +4,6 @@
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>QtVersion.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">2</value>
|
||||
<value type="QString" key="Name">Qt 4.8 for Desktop - MSVC2013</value>
|
||||
<value type="QString" key="QMakePath">C:/Qt/Qt4.8.7/bin/qmake.exe</value>
|
||||
<value type="QString" key="QtVersion.Type">Qt4ProjectManager.QtVersion.Desktop</value>
|
||||
<value type="bool" key="isAutodetected">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">22</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (mingw491_32)</value>
|
||||
@ -23,7 +13,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.2</variable>
|
||||
<variable>QtVersion.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">24</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (msvc2017_64)</value>
|
||||
@ -33,7 +23,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>QtVersion.3</variable>
|
||||
<variable>QtVersion.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="int" key="Id">26</value>
|
||||
<value type="QString" key="Name">Qt %{Qt:Version} (msvc2015)</value>
|
||||
|
@ -19,18 +19,6 @@
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.1</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.SupportedAbi">x86-windows-msvc2013-pe-32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBat">C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/vcvarsall.bat</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBatArg">x86</value>
|
||||
<value type="bool" key="ProjectExplorer.ToolChain.Autodetect">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.DisplayName">Microsoft Visual C++ Compiler 12.0 (x86)</value>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.Id">ProjectExplorer.ToolChain.Msvc:{d35e7a1a-5ab8-4fd6-8a2c-634846c669bb}</value>
|
||||
<value type="int" key="ProjectExplorer.ToolChain.Language">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.GccToolChain.OriginalTargetTriple">i686-w64-mingw32</value>
|
||||
<value type="QString" key="ProjectExplorer.GccToolChain.Path">C:/Qt/Qt5.4.1/Tools/mingw491_32/bin/gcc.exe</value>
|
||||
@ -47,12 +35,18 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.3</variable>
|
||||
<variable>ToolChain.2</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.SupportedAbi">x86-windows-msvc2017-pe-64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBat">C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBatArg">amd64</value>
|
||||
<value type="bool" key="ProjectExplorer.ToolChain.Autodetect">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.MsvcToolChain.environmentModifications">
|
||||
<valuelist type="QVariantList">
|
||||
<value type="QString">PATH</value>
|
||||
<value type="int">0</value>
|
||||
<value type="QString">SQUISH_MSVC2017_PATH</value>
|
||||
</valuelist>
|
||||
</valuelist>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.DisplayName">MSVC2017 (amd64)</value>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.Id">ProjectExplorer.ToolChain.Msvc:{ce3a8004-e9ae-46f2-b62d-d7daf69435ca}</value>
|
||||
<value type="int" key="ProjectExplorer.ToolChain.Language">1</value>
|
||||
@ -60,7 +54,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.4</variable>
|
||||
<variable>ToolChain.3</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.SupportedAbi">x86-windows-msvc2015-pe-32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBat">C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat</value>
|
||||
@ -73,7 +67,7 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.5</variable>
|
||||
<variable>ToolChain.4</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.SupportedAbi">x86-windows-msvc2015-pe-32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBat">C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat</value>
|
||||
@ -86,23 +80,18 @@
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.6</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.SupportedAbi">x86-windows-msvc2013-pe-32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBat">C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/vcvarsall.bat</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBatArg">x86</value>
|
||||
<value type="bool" key="ProjectExplorer.ToolChain.Autodetect">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.DisplayName">Microsoft Visual C++ Compiler 12.0 (x86)</value>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.Id">ProjectExplorer.ToolChain.Msvc:{7ca0887f-a9a5-4251-aba6-560a15595d20}</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.7</variable>
|
||||
<variable>ToolChain.5</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.SupportedAbi">x86-windows-msvc2017-pe-64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBat">C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat</value>
|
||||
<value type="QString" key="ProjectExplorer.MsvcToolChain.VarsBatArg">amd64</value>
|
||||
<value type="bool" key="ProjectExplorer.ToolChain.Autodetect">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.MsvcToolChain.environmentModifications">
|
||||
<valuelist type="QVariantList">
|
||||
<value type="QString">PATH</value>
|
||||
<value type="int">0</value>
|
||||
<value type="QString">SQUISH_MSVC2017_PATH</value>
|
||||
</valuelist>
|
||||
</valuelist>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.DisplayName">MSVC2017 (amd64)</value>
|
||||
<value type="QString" key="ProjectExplorer.ToolChain.Id">ProjectExplorer.ToolChain.Msvc:{3df7c776-a480-4a04-9099-6c75adac2dca}</value>
|
||||
<value type="int" key="ProjectExplorer.ToolChain.Language">2</value>
|
||||
@ -111,7 +100,7 @@
|
||||
</data>
|
||||
<data>
|
||||
<variable>ToolChain.Count</variable>
|
||||
<value type="int">8</value>
|
||||
<value type="int">6</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
|
@ -190,13 +190,12 @@ def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShad
|
||||
# it will wait here until compilation of the debug libraries has finished.
|
||||
runCMakeButton = ("{type='QPushButton' text='Run CMake' unnamed='1' "
|
||||
"window=':Qt Creator_Core::Internal::MainWindow'}")
|
||||
if currentTarget not in (Targets.DESKTOP_4_8_7_DEFAULT, Targets.EMBEDDED_LINUX):
|
||||
qmlDebuggingCombo = findObject(':Qt Creator.QML debugging and profiling:_QComboBox')
|
||||
if selectFromCombo(qmlDebuggingCombo, 'Enable'):
|
||||
if buildSystem is None or buildSystem == "CMake": # re-run cmake to apply
|
||||
clickButton(waitForObject(runCMakeButton))
|
||||
elif buildSystem == "qmake": # Don't rebuild now
|
||||
clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000))
|
||||
qmlDebuggingCombo = findObject(':Qt Creator.QML debugging and profiling:_QComboBox')
|
||||
if selectFromCombo(qmlDebuggingCombo, 'Enable'):
|
||||
if buildSystem is None or buildSystem == "CMake": # re-run cmake to apply
|
||||
clickButton(waitForObject(runCMakeButton))
|
||||
elif buildSystem == "qmake": # Don't rebuild now
|
||||
clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000))
|
||||
try:
|
||||
problemFound = waitForObject("{window=':Qt Creator_Core::Internal::MainWindow' "
|
||||
"type='QLabel' name='problemLabel' visible='1'}", 1000)
|
||||
@ -205,14 +204,13 @@ def verifyBuildConfig(currentTarget, configName, shouldBeDebug=False, enableShad
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
if currentTarget not in (Targets.DESKTOP_4_8_7_DEFAULT, Targets.EMBEDDED_LINUX):
|
||||
qmlDebuggingCombo = findObject(':Qt Creator.QML debugging and profiling:_QComboBox')
|
||||
if selectFromCombo(qmlDebuggingCombo, "Disable"):
|
||||
test.log("Qml debugging libraries are available - unchecked qml debugging.")
|
||||
if buildSystem is None or buildSystem == "CMake": # re-run cmake to apply
|
||||
clickButton(waitForObject(runCMakeButton))
|
||||
elif buildSystem == "qmake": # Don't rebuild now
|
||||
clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000))
|
||||
qmlDebuggingCombo = findObject(':Qt Creator.QML debugging and profiling:_QComboBox')
|
||||
if selectFromCombo(qmlDebuggingCombo, "Disable"):
|
||||
test.log("Qml debugging libraries are available - unchecked qml debugging.")
|
||||
if buildSystem is None or buildSystem == "CMake": # re-run cmake to apply
|
||||
clickButton(waitForObject(runCMakeButton))
|
||||
elif buildSystem == "qmake": # Don't rebuild now
|
||||
clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000))
|
||||
clickButton(waitForObject(":scrollArea.Details_Utils::DetailsButton"))
|
||||
switchViewTo(ViewConstants.EDIT)
|
||||
|
||||
|
@ -30,37 +30,27 @@ except ImportError:
|
||||
|
||||
# for easier re-usage (because Python hasn't an enum type)
|
||||
class Targets:
|
||||
ALL_TARGETS = tuple(range(5))
|
||||
ALL_TARGETS = tuple(range(3))
|
||||
|
||||
(DESKTOP_4_8_7_DEFAULT,
|
||||
EMBEDDED_LINUX,
|
||||
DESKTOP_5_4_1_GCC,
|
||||
(DESKTOP_5_4_1_GCC,
|
||||
DESKTOP_5_10_1_DEFAULT,
|
||||
DESKTOP_5_14_1_DEFAULT) = ALL_TARGETS
|
||||
|
||||
__TARGET_NAME_DICT__ = dict(zip(ALL_TARGETS,
|
||||
["Desktop 4.8.7 default",
|
||||
"Embedded Linux",
|
||||
"Desktop 5.4.1 GCC",
|
||||
["Desktop 5.4.1 GCC",
|
||||
"Desktop 5.10.1 default",
|
||||
"Desktop 5.14.1 default"]))
|
||||
|
||||
@staticmethod
|
||||
def availableTargetClasses(ignoreValidity=False):
|
||||
availableTargets = set(Targets.ALL_TARGETS)
|
||||
if not qt4Available and not ignoreValidity:
|
||||
availableTargets.remove(Targets.DESKTOP_4_8_7_DEFAULT)
|
||||
if not (qt4Available or ignoreValidity) or platform.system() in ('Windows', 'Microsoft'):
|
||||
availableTargets.remove(Targets.EMBEDDED_LINUX)
|
||||
elif platform.system() == 'Darwin':
|
||||
if platform.system() == 'Darwin':
|
||||
availableTargets.remove(Targets.DESKTOP_5_4_1_GCC)
|
||||
return availableTargets
|
||||
|
||||
@staticmethod
|
||||
def desktopTargetClasses():
|
||||
desktopTargets = Targets.availableTargetClasses()
|
||||
desktopTargets.discard(Targets.EMBEDDED_LINUX)
|
||||
return desktopTargets
|
||||
return Targets.availableTargetClasses()
|
||||
|
||||
@staticmethod
|
||||
def getStringForTarget(target):
|
||||
|
@ -161,11 +161,8 @@ def __createProjectHandleQtQuickSelection__(minimumQtVersion):
|
||||
# param buildSystem is a string holding the build system selected for the project
|
||||
# param checks turns tests in the function on if set to True
|
||||
# param available a list holding the available targets
|
||||
# withoutQt4 if True Qt4 will get unchecked / not selected while checking the targets
|
||||
def __selectQtVersionDesktop__(buildSystem, checks, available=None, withoutQt4=False):
|
||||
def __selectQtVersionDesktop__(buildSystem, checks, available=None):
|
||||
wanted = Targets.desktopTargetClasses()
|
||||
if withoutQt4:
|
||||
wanted.discard(Targets.DESKTOP_4_8_7_DEFAULT)
|
||||
checkedTargets = __chooseTargets__(wanted, available)
|
||||
if checks:
|
||||
for target in checkedTargets:
|
||||
@ -183,9 +180,8 @@ def __selectQtVersionDesktop__(buildSystem, checks, available=None, withoutQt4=F
|
||||
objectMap.realName(detailsWidget)))
|
||||
verifyChecked(cbObject % ("Minimum Size Release",
|
||||
objectMap.realName(detailsWidget)))
|
||||
elif (buildSystem == "qmake"
|
||||
and target not in (Targets.DESKTOP_4_8_7_DEFAULT, Targets.EMBEDDED_LINUX)):
|
||||
verifyChecked(cbObject % ("Profile", objectMap.realName(detailsWidget)))
|
||||
elif buildSystem == "qmake":
|
||||
verifyChecked(cbObject % ("Profile", objectMap.realName(detailsWidget)))
|
||||
clickButton(detailsButton)
|
||||
clickButton(waitForObject(":Next_QPushButton"))
|
||||
|
||||
@ -207,11 +203,6 @@ def __verifyFileCreation__(path, expectedFiles):
|
||||
def __modifyAvailableTargets__(available, requiredQt, asStrings=False):
|
||||
versionFinder = re.compile("^Desktop (\\d{1}\.\\d{1,2}\.\\d{1,2}).*$")
|
||||
tmp = list(available) # we need a deep copy
|
||||
if Qt5Path.toVersionTuple(requiredQt) > (4,8,7) and qt4Available:
|
||||
toBeRemoved = Targets.EMBEDDED_LINUX
|
||||
if asStrings:
|
||||
toBeRemoved = Targets.getStringForTarget(toBeRemoved)
|
||||
available.discard(toBeRemoved)
|
||||
for currentItem in tmp:
|
||||
if asStrings:
|
||||
item = currentItem
|
||||
@ -260,7 +251,7 @@ def createProject_Qt_GUI(path, projectName, checks=True, addToVersionControl="<N
|
||||
|
||||
clickButton(waitForObject(":Next_QPushButton"))
|
||||
__createProjectHandleTranslationSelection__()
|
||||
__selectQtVersionDesktop__(buildSystem, checks, available, True)
|
||||
__selectQtVersionDesktop__(buildSystem, checks, available)
|
||||
|
||||
expectedFiles = []
|
||||
if checks:
|
||||
@ -540,12 +531,6 @@ def __getSupportedPlatforms__(text, templateName, getAsStrings=False, ignoreVali
|
||||
supports = text[text.find('Supported Platforms'):].split(":")[1].strip().split("\n")
|
||||
result = set()
|
||||
if 'Desktop' in supports:
|
||||
if (version == None or version < "5.0") and not templateName.startswith("Qt Quick"):
|
||||
neverIgnoreValidity = templateName in ("Qt Custom Designer Widget", "Code Snippet", "Subdirs Project")
|
||||
if qt4Available or ignoreValidity and not neverIgnoreValidity:
|
||||
result.add(Targets.DESKTOP_4_8_7_DEFAULT)
|
||||
if platform.system() in ("Linux", "Darwin"):
|
||||
result.add(Targets.EMBEDDED_LINUX)
|
||||
result = result.union(set([Targets.DESKTOP_5_10_1_DEFAULT, Targets.DESKTOP_5_14_1_DEFAULT]))
|
||||
if platform.system() != 'Darwin':
|
||||
result.add(Targets.DESKTOP_5_4_1_GCC)
|
||||
|
@ -40,12 +40,6 @@ except ImportError:
|
||||
import builtins as __builtin__ # Python 3
|
||||
|
||||
|
||||
# ensure global variables are defined before including shared scripts
|
||||
qt4Path = os.path.expanduser("~/Qt4.8.7")
|
||||
if platform.system() in ('Windows', 'Microsoft'):
|
||||
qt4Path = "C:\\Qt\\Qt4.8.7"
|
||||
|
||||
qt4Available = os.path.exists(qt4Path)
|
||||
srcPath = ''
|
||||
SettingsPath = []
|
||||
tmpSettingsDir = ''
|
||||
@ -237,6 +231,23 @@ def substituteCdb(settingsDir):
|
||||
__substitute__(debuggers, "SQUISH_DEBUGGER_BITNESS", bitness)
|
||||
test.log("Injected architecture '%s' and bitness '%s' in cdb path..." % (architecture, bitness))
|
||||
|
||||
|
||||
def substituteMsvcPaths(settingsDir):
|
||||
for msvcFlavor in ["Community", "BuildTools"]:
|
||||
try:
|
||||
msvc2017Path = os.path.join("C:\\Program Files (x86)", "Microsoft Visual Studio",
|
||||
"2017", msvcFlavor, "VC", "Tools", "MSVC")
|
||||
msvc2017Path = os.path.join(msvc2017Path, os.listdir(msvc2017Path)[0], "bin",
|
||||
"HostX64", "x64")
|
||||
__substitute__(os.path.join(settingsDir, "QtProject", 'qtcreator', 'toolchains.xml'),
|
||||
"SQUISH_MSVC2017_PATH", msvc2017Path)
|
||||
return
|
||||
except:
|
||||
continue
|
||||
test.warning("PATH variable for MSVC2017 could not be set, some tests will fail.",
|
||||
"Please make sure that MSVC2017 is installed correctly.")
|
||||
|
||||
|
||||
def __guessABI__(supportedABIs, use64Bit):
|
||||
if platform.system() == 'Linux':
|
||||
supportedABIs = filter(lambda x: 'linux' in x, supportedABIs)
|
||||
@ -331,6 +342,7 @@ def copySettingsToTmpDir(destination=None, omitFiles=[]):
|
||||
substituteDefaultCompiler(tmpSettingsDir)
|
||||
elif platform.system() in ('Windows', 'Microsoft'):
|
||||
substituteCdb(tmpSettingsDir)
|
||||
substituteMsvcPaths(tmpSettingsDir)
|
||||
substituteUnchosenTargetABIs(tmpSettingsDir)
|
||||
SettingsPath = ['-settingspath', '"%s"' % tmpSettingsDir]
|
||||
|
||||
|
@ -41,7 +41,6 @@ def main():
|
||||
return
|
||||
# open example project, supports only Qt 5
|
||||
targets = Targets.desktopTargetClasses()
|
||||
targets.discard(Targets.DESKTOP_4_8_7_DEFAULT)
|
||||
targets.discard(Targets.DESKTOP_5_4_1_GCC)
|
||||
openQmakeProject(examplePath, targets)
|
||||
# build and wait until finished - on all build configurations
|
||||
|
@ -47,7 +47,6 @@ def main():
|
||||
if not startCreatorVerifyingClang(useClang):
|
||||
continue
|
||||
createProject_Qt_Console(tempDir(), "SquishProject")
|
||||
# by default Qt4 is selected, use a Qt5 kit instead
|
||||
selectBuildConfig(Targets.DESKTOP_5_10_1_DEFAULT, "Debug")
|
||||
checkCodeModelSettings(useClang)
|
||||
selectFromLocator("main.cpp")
|
||||
|
Reference in New Issue
Block a user