Merge "Merge remote-tracking branch 'origin/6.0'"
41
dist/changes-6.0.0.md
vendored
@@ -29,16 +29,24 @@ Editing
|
||||
* Added option for saving open files automatically after refactoring
|
||||
(QTCREATORBUG-25924)
|
||||
* Added information about source to tooltip on diagnostics
|
||||
* Fixed `Insert Definition` for templates with value parameters
|
||||
(QTCREATORBUG-26113)
|
||||
* Added highlighting color option for namespaces (QTCREATORBUG-16580)
|
||||
* Made pure virtual functions optional in `Create implementations for all member
|
||||
functions` (QTCREATORBUG-26468)
|
||||
* Fixed `Insert Definition` for template types (QTCREATORBUG-26113,
|
||||
QTCREATORBUG-26397)
|
||||
* Fixed that `Find References` did not work for some template and namespace
|
||||
combinations (QTCREATORBUG-26520)
|
||||
* Fixed canceling of C++ parsing on configuration change (QTCREATORBUG-24890)
|
||||
* Fixed crash when checking for refactoring actions (QTCREATORBUG-26316)
|
||||
* Fixed wrong target compiler option (QTCREATORBUG-25615)
|
||||
* Fixed parentheses matching (QTCREATORBUG-26400)
|
||||
* Fixed documentation comment generation for template types (QTCREATORBUG-9620)
|
||||
* Clangd
|
||||
* Added warning for older `clangd` versions
|
||||
* Added support for completion and function hint
|
||||
* Added option for `Insert header files on completion`
|
||||
* Improved location of generated `compile_commands.json` (QTCREATORBUG-26431)
|
||||
* Fixed missing reparsing after refactorings (QTCREATORBUG-26523)
|
||||
|
||||
### QML
|
||||
|
||||
@@ -66,6 +74,7 @@ Projects
|
||||
(QTCREATORBUG-26422)
|
||||
* Fixed that re-detecting compilers removed compilers from kits
|
||||
(QTCREATORBUG-25697)
|
||||
* Fixed GitHub action created by Qt Creator plugin wizard for Qt 6
|
||||
|
||||
### CMake
|
||||
|
||||
@@ -79,6 +88,7 @@ Projects
|
||||
QTCREATORBUG-26238, QTCREATORBUG-21452, QTCREATORBUG-25644,
|
||||
QTCREATORBUG-25782)
|
||||
* Fixed that generated files were selected for analyzing (QTCREATORBUG-25125)
|
||||
* Fixed importing of Qt projects (QTCREATORBUG-25767)
|
||||
|
||||
### qmake
|
||||
|
||||
@@ -88,6 +98,11 @@ Projects
|
||||
|
||||
* Fixed that headers were not shown as part of the project (QTCREATORBUG-26356)
|
||||
|
||||
### Conan
|
||||
|
||||
* Added `QT_CREATOR_CONAN_BUILD_POLICY` used for `BUILD` property of
|
||||
`conan_cmake_run`
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
@@ -97,6 +112,11 @@ Debugging
|
||||
* Fixed variable expansion for `Additional Startup Commands`
|
||||
(QTCREATORBUG-26382)
|
||||
|
||||
### CDB
|
||||
|
||||
* Added hint for missing Qt debug information
|
||||
* Improved pretty printing for Qt 6 without debug information
|
||||
|
||||
Version Control Systems
|
||||
-----------------------
|
||||
|
||||
@@ -117,9 +137,16 @@ Test Integration
|
||||
Platforms
|
||||
---------
|
||||
|
||||
### Windows
|
||||
|
||||
* Added support for MSVC 2022
|
||||
|
||||
### macOS
|
||||
|
||||
* Changed prebuilt binaries to universal Intel + ARM
|
||||
* Made dark theme the default in dark system mode
|
||||
* Fixed issues with dark system mode (QTCREATORBUG-21520, QTCREATORBUG-26427,
|
||||
QTCREATORBUG-26428)
|
||||
|
||||
### Android
|
||||
|
||||
@@ -127,11 +154,16 @@ Platforms
|
||||
selector (QTCREATORBUG-23991)
|
||||
* Added details to device settings (QTCREATORBUG-23991)
|
||||
* Added filter field for Android SDK manager
|
||||
* Fixed that NDK 22 and later could not be added
|
||||
|
||||
### WebAssembly
|
||||
|
||||
* Fixed running applications (QTCREATORBUG-25905, QTCREATORBUG-26189)
|
||||
|
||||
### MCU
|
||||
|
||||
* Added preliminary support for SDK 2.0
|
||||
|
||||
### Docker
|
||||
|
||||
* Various improvements
|
||||
@@ -147,6 +179,7 @@ André Pönitz
|
||||
Artem Sokolovskii
|
||||
Artur Shepilko
|
||||
Assam Boudjelthia
|
||||
BogDan Vatra
|
||||
Christiaan Janssen
|
||||
Christian Kandeler
|
||||
Christian Stenger
|
||||
@@ -160,6 +193,7 @@ Ivan Komissarov
|
||||
Jaroslaw Kobus
|
||||
Johanna Vanhatapio
|
||||
Jonas Karlsson
|
||||
Jonas Singe
|
||||
Kai Köhne
|
||||
Kama Wójcik
|
||||
Knud Dollereder
|
||||
@@ -171,9 +205,11 @@ Marco Bubke
|
||||
Martin Kampas
|
||||
Miikka Heikkinen
|
||||
Miina Puuronen
|
||||
Oliver Wolff
|
||||
Orgad Shaneh
|
||||
Petar Perisin
|
||||
Piotr Mikolajczyk
|
||||
Robert Löhning
|
||||
Samuel Ghinet
|
||||
Shantanu Tushar
|
||||
Tapani Mattila
|
||||
@@ -181,6 +217,7 @@ Tasuku Suzuki
|
||||
Thiago Macieira
|
||||
Thomas Hartmann
|
||||
Tim Jenssen
|
||||
Tomi Korpipaa
|
||||
Tony Leinonen
|
||||
Tor Arne Vestbø
|
||||
Tuomo Pelkonen
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 28 KiB |
BIN
doc/qtcreator/images/qtcreator-git-amend.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 16 KiB |
@@ -135,6 +135,9 @@
|
||||
case-sensitivity. Select \uicontrol {Show Non-matching Lines} to
|
||||
hide the lines that match the filter.
|
||||
|
||||
Press \key {Ctrl+F} to \l{Finding and Replacing}{search} for a string from
|
||||
the output.
|
||||
|
||||
To increase or decrease the output text size, select \inlineimage plus.png
|
||||
(\uicontrol {Zoom In}) or \inlineimage minus.png
|
||||
(\uicontrol {Zoom Out}), or press \key Ctrl++ or \key Ctrl+-.
|
||||
@@ -197,5 +200,5 @@
|
||||
\image qtcreator-cmake-clean-steps.png
|
||||
|
||||
The build errors and warnings are parsed and displayed in the
|
||||
\uicontrol Issues output pane.
|
||||
\l Issues output pane.
|
||||
*/
|
||||
|
@@ -57,18 +57,19 @@
|
||||
a \c CMakeLists.txt configuration file in a project. Project information is
|
||||
also automatically refreshed when you build the project.
|
||||
|
||||
The \uicontrol {File System} section in the sidebar \uicontrol Projects view
|
||||
displays information from the file system. \QC cannot determine whether the
|
||||
files are part of the project. For example, header files that \QC finds in
|
||||
the project directories but that are not mentioned in the CMakeLists.txt
|
||||
files are listed here.
|
||||
\image qtcreator-projects-view-edit.png "CMake project in Projects view"
|
||||
|
||||
\image qtcreator-projects-view-cmake.png "File System section in Projects view"
|
||||
If \QC cannot load the CMake project, the \l Projects view shows a
|
||||
\uicontrol {<File System>} project node to avoid scanning the file
|
||||
system and load the project faster. The node shows the same files
|
||||
as the \l {File System} view. Select \uicontrol Build >
|
||||
\uicontrol {Clear CMake Configuration}, and then select \uicontrol Build
|
||||
> \uicontrol {Run CMake} to reconfigure the project.
|
||||
|
||||
\section1 Adding CMake Tools
|
||||
|
||||
\QC requires CMake's \l{https://cmake.org/cmake/help/latest/manual/cmake-file-api.7.html}
|
||||
{file-based API}. Please make sure to use CMake version 3.14, or later.
|
||||
{file-based API}, and therefore you'll need CMake version 3.14, or later.
|
||||
|
||||
To view and specify settings for CMake:
|
||||
|
||||
@@ -144,6 +145,8 @@
|
||||
|
||||
\endlist
|
||||
|
||||
Warnings and errors are displayed in the \l {Issues} output pane.
|
||||
|
||||
\section1 Adding External Libraries to CMake Projects
|
||||
|
||||
Through external libraries, \QC can support code completion and syntax
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -57,7 +57,7 @@
|
||||
applications for multiple desktop and \l{glossary-device}{device}
|
||||
platforms.
|
||||
|
||||
\li \l{Using Other Build Systems}
|
||||
\li \l{Build Systems}
|
||||
|
||||
\QC is integrated with cross-platform systems for build automation:
|
||||
qmake, Qbs, CMake, and Autotools. In addition, you can import
|
||||
|
@@ -515,7 +515,7 @@
|
||||
\li \l{Opening Projects}
|
||||
\li \l{Adding Libraries to Projects}
|
||||
\li \l{Adding New Custom Wizards}
|
||||
\li \l{Using Other Build Systems}
|
||||
\li \l{Build Systems}
|
||||
\endlist
|
||||
|
||||
*/
|
||||
|
@@ -34,7 +34,7 @@
|
||||
\page creator-project-other.html
|
||||
\nextpage creator-project-cmake.html
|
||||
|
||||
\title Using Other Build Systems
|
||||
\title Build Systems
|
||||
|
||||
Most \QC project wizards enable you to choose the build system to use for
|
||||
building the project: qmake, CMake, Meson, or Qbs. qmake is installed and
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -75,7 +75,7 @@
|
||||
\section1 Related Topics
|
||||
|
||||
\list
|
||||
\li \l{Using Other Build Systems}
|
||||
\li \l{Build Systems}
|
||||
\endlist
|
||||
|
||||
*/
|
||||
|
@@ -212,7 +212,7 @@
|
||||
\li \l {Embedded Platforms}
|
||||
\li \l {Mobile Platforms}
|
||||
\endlist
|
||||
\li \l{Using Other Build Systems}
|
||||
\li \l{Build Systems}
|
||||
\list
|
||||
\li \l{Setting Up CMake}
|
||||
\li \l{Setting Up Qbs}
|
||||
|
@@ -113,7 +113,7 @@
|
||||
\li \b {\l{Advanced Use}}
|
||||
\list
|
||||
\li \l{Supported Platforms}
|
||||
\li \l{Using Other Build Systems}
|
||||
\li \l{Build Systems}
|
||||
\li \l{Using Command Line Options}
|
||||
\li \l{Keyboard Shortcuts}
|
||||
\li \l{Using External Tools}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the Qt Creator documentation.
|
||||
@@ -203,7 +203,20 @@
|
||||
commit page containing a text editor where you can enter your commit
|
||||
message and a checkable list of modified files to be included.
|
||||
|
||||
\image qtcreator-vcs-commit.png
|
||||
\image qtcreator-vcs-commit.png "Committing changes with Git"
|
||||
|
||||
\uicontrol {General Information} displays the names of the
|
||||
repository and branch for the commit.
|
||||
|
||||
In \uicontrol {Commit Information}, you can edit information about the
|
||||
author of the commit. To bypass re-commit and commit message hooks,
|
||||
select \uicontrol {Bypass hooks}. If signoffs are used for your project,
|
||||
select \uicontrol {Sign off} to add a \e signed-off-by trailer by the
|
||||
author at the end of the commit log message.
|
||||
|
||||
In \uicontrol Description, edit the commit message.
|
||||
|
||||
In \uicontrol Files, select the files to include in the commit.
|
||||
|
||||
When you have finished filling out the commit page information, click on
|
||||
\uicontrol Commit to start committing.
|
||||
@@ -223,10 +236,22 @@
|
||||
|
||||
\section2 Amending Commits
|
||||
|
||||
To apply latest changes to the last commit, select
|
||||
\uicontrol {Amend Last Commit}. You can also edit the commit message.
|
||||
To apply latest changes to the last commit, select \uicontrol Tools >
|
||||
\uicontrol Git > \uicontrol {Local Repository} >
|
||||
\uicontrol {Amend Last Commit}.
|
||||
|
||||
\image qtcreator-git-amend.png "Amending a Git commit"
|
||||
|
||||
To view the commit in its current form, before amending, select
|
||||
\uicontrol {Show HEAD}.
|
||||
|
||||
To view a diff of the changes in the selected files, select
|
||||
\uicontrol {Diff Selected Files}.
|
||||
|
||||
Select \uicontrol Commit to amend the commit.
|
||||
|
||||
To amend an earlier comment in a series of related commits, select
|
||||
\uicontrol Tools > \uicontrol Git > \uicontrol {Local Repository} >
|
||||
\uicontrol {Fixup Previous Commit}. This operation is done using interactive
|
||||
rebase. In case of conflicts, a merge tool is suggested.
|
||||
|
||||
|
@@ -30,6 +30,28 @@
|
||||
|
||||
\title Importing 2D Assets
|
||||
|
||||
You can import 2D assets, such as images, fonts, and sound files, to \QDS to
|
||||
use them in your projects.
|
||||
|
||||
To import an asset, drag-and-drop the external file containing the asset from,
|
||||
for example, File Explorer on Windows, to \uicontrol {Form Editor},
|
||||
\uicontrol Navigator, or \uicontrol {Text Editor}. Alternatively, select
|
||||
\l Library > \uicontrol Assets > \inlineimage plus.png
|
||||
and follow the instructions in the \uicontrol {Asset Import} dialog. You can
|
||||
also multiselect several external asset files to drag-and-drop them to
|
||||
\QDS simultaneously.
|
||||
|
||||
The imported images will appear in \uicontrol Library > \uicontrol Assets.
|
||||
If you initiate the import by dragging the assets to \uicontrol {Form Editor},
|
||||
they are also added to your projects as image components, and you can view
|
||||
them in \uicontrol {Form Editor} and \uicontrol Navigator. If you drag an
|
||||
external font file to \uicontrol {Form Editor}, it will be added to your
|
||||
project as a text component. Other imported assets, such as sound files,
|
||||
will only appear in \uicontrol Library > \uicontrol Assets, and you can then
|
||||
drag-and-drop them to a suitable view.
|
||||
|
||||
\section1 Importing Designs From Other Design Tools
|
||||
|
||||
\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
|
||||
@@ -45,7 +67,7 @@
|
||||
information about the options you have, see
|
||||
\l {Creating Projects}.
|
||||
|
||||
To import designs to \QDS projects:
|
||||
To import assets exported in \QB to \QDS projects:
|
||||
|
||||
\list 1
|
||||
\li Select \uicontrol File > \uicontrol {New File or Project} >
|
||||
@@ -107,4 +129,5 @@
|
||||
design tool and export the assets again.
|
||||
|
||||
\include qtbridge-tutorial-links.qdocinc qtsketchbridge tutorials
|
||||
|
||||
*/
|
||||
|
@@ -43,17 +43,27 @@
|
||||
For more information about exporting 3D graphics, see
|
||||
\l{Exporting 3D Assets}.
|
||||
|
||||
During the import, you can optimize the files for \QDS. You can remove
|
||||
components from meshes to reduce the cache size, find and fix issues in
|
||||
the files, optimize graphs and meshes, and so on. The available options
|
||||
depend on whether you are importing files that you created with Qt 3D Studio
|
||||
or with other 3D graphics tools. See the tooltips in the options dialog
|
||||
for more information about a particular option.
|
||||
|
||||
\image studio-import-3d.png
|
||||
|
||||
To import 3D assets to \QDS projects:
|
||||
|
||||
\list 1
|
||||
\li Drag-and-drop an external file containing the 3D asset from,
|
||||
for example, File Explorer (on Windows), to \uicontrol {3D Editor}.
|
||||
\li In the \uicontrol {3D Scene Options} tab, select options for
|
||||
importing the file.
|
||||
\li Select \uicontrol Import to import the 3D graphics file.
|
||||
\li When the import is done, select \uicontrol Close.
|
||||
\endlist
|
||||
|
||||
The 3D asset you dragged-and-dropped to \uicontrol {3D Editor} has now
|
||||
been added to your scene, and you can see it in the \uicontrol {3D Editor}
|
||||
view and in \uicontrol Navigator. It is also available in
|
||||
\uicontrol Library > \uicontrol Components > \uicontrol {My 3D Components}.
|
||||
|
||||
Alternatively, you can initiate the import dialog from the
|
||||
\uicontrol Library view:
|
||||
|
||||
\list 1
|
||||
\li In the \l{Design Views}{Design mode}, select \l Library >
|
||||
\uicontrol Assets > \inlineimage plus.png
|
||||
@@ -67,6 +77,17 @@
|
||||
\li When the import is done, select \uicontrol Close.
|
||||
\endlist
|
||||
|
||||
The 3D asset now appears in \uicontrol Library > \uicontrol Components >
|
||||
\uicontrol {My 3D Components}. You can add it to the scene by
|
||||
drag-and-dropping it to \uicontrol {3D Editor}.
|
||||
|
||||
During the import, you can optimize the files for \QDS. You can remove
|
||||
components from meshes to reduce the cache size, find and fix issues in
|
||||
the files, optimize graphs and meshes, and so on. The available options
|
||||
depend on whether you are importing files that you created with Qt 3D Studio
|
||||
or with other 3D graphics tools. See the tooltips in the options dialog
|
||||
for more information about a particular option.
|
||||
|
||||
The 3D asset you added to the project now appears in \uicontrol Library >
|
||||
\uicontrol Components > \uicontrol {My 3D Components}. You can add it to
|
||||
your UI by dragging-and-dropping it to \l {3D Editor}.
|
||||
|
@@ -119,9 +119,13 @@
|
||||
\section1 Assets
|
||||
|
||||
\uicontrol Library > \uicontrol {Assets} displays the images and other files
|
||||
that you add to the project folder by selecting \inlineimage plus.png
|
||||
. To add assets to your UI, drag-and-drop them to \l Navigator or
|
||||
\l {Form Editor}.
|
||||
that you add to the project folder by dragging-and-dropping external asset
|
||||
files to \QDS or by selecting \inlineimage plus.png
|
||||
. For more information about importing assets to \QDS, see
|
||||
\l {Importing 2D Assets} and \l {Importing 3D Assets}.
|
||||
|
||||
To add assets to your UI, drag-and-drop them from \uicontrol Library >
|
||||
\uicontrol Assets to \l Navigator, \l {Form Editor}, or \l {3D Editor}.
|
||||
|
||||
To add multiple assets to your UI simultaneously, multiselect them first by
|
||||
holding \key Ctrl and clicking the asset files you wish to select.
|
||||
|
@@ -252,8 +252,9 @@ class DumperBase():
|
||||
#DumperBase.warn('EXPANDED INAMES: %s' % self.expandedINames)
|
||||
#DumperBase.warn('WATCHERS: %s' % self.watchers)
|
||||
|
||||
def setFallbackQtVersion(self, version):
|
||||
self.warn("got fallback qt version %x" % version)
|
||||
def setFallbackQtVersion(self, args):
|
||||
version = int(args.get('version', self.fallbackQtVersion))
|
||||
DumperBase.warn("got fallback qt version 0x%x" % version)
|
||||
self.fallbackQtVersion = version
|
||||
|
||||
def resetPerStepCaches(self):
|
||||
@@ -1135,12 +1136,18 @@ class DumperBase():
|
||||
if displayFormat != DisplayFormat.Raw and p:
|
||||
if innerType.name in (
|
||||
'char',
|
||||
'int8_t',
|
||||
'qint8',
|
||||
'wchar_t',
|
||||
'unsigned char',
|
||||
'uint8_t',
|
||||
'quint8',
|
||||
'signed char',
|
||||
'CHAR',
|
||||
'WCHAR'
|
||||
'WCHAR',
|
||||
'char8_t',
|
||||
'char16_t',
|
||||
'char32_t'
|
||||
):
|
||||
self.putCharArrayHelper(p, n, innerType, self.currentItemFormat(),
|
||||
makeExpandable=False)
|
||||
@@ -1406,11 +1413,17 @@ class DumperBase():
|
||||
if innerType.name not in (
|
||||
'char',
|
||||
'signed char',
|
||||
'int8_t',
|
||||
'qint8',
|
||||
'unsigned char',
|
||||
'uint8_t',
|
||||
'quint8',
|
||||
'wchar_t',
|
||||
'CHAR',
|
||||
'WCHAR'
|
||||
'WCHAR',
|
||||
'char8_t',
|
||||
'char16_t',
|
||||
'char32_t'
|
||||
):
|
||||
self.putDerefedPointer(value)
|
||||
return
|
||||
@@ -3628,15 +3641,33 @@ class DumperBase():
|
||||
res = {
|
||||
'bool': 'int:1',
|
||||
'char': 'int:1',
|
||||
'int8_t': 'int:1',
|
||||
'qint8': 'int:1',
|
||||
'signed char': 'int:1',
|
||||
'char8_t': 'uint:1',
|
||||
'unsigned char': 'uint:1',
|
||||
'uint8_t': 'uint:1',
|
||||
'quint8': 'uint:1',
|
||||
'short': 'int:2',
|
||||
'int16_t': 'int:2',
|
||||
'qint16': 'int:2',
|
||||
'unsigned short': 'uint:2',
|
||||
'char16_t': 'uint:2',
|
||||
'uint16_t': 'uint:2',
|
||||
'quint16': 'uint:2',
|
||||
'int': 'int:4',
|
||||
'int32_t': 'int:4',
|
||||
'qint32': 'int:4',
|
||||
'unsigned int': 'uint:4',
|
||||
'char32_t': 'uint:4',
|
||||
'uint32_t': 'uint:4',
|
||||
'quint32': 'uint:4',
|
||||
'long long': 'int:8',
|
||||
'int64_t': 'int:8',
|
||||
'qint64': 'int:8',
|
||||
'unsigned long long': 'uint:8',
|
||||
'uint64_t': 'uint:8',
|
||||
'quint64': 'uint:8',
|
||||
'float': 'float:4',
|
||||
'double': 'float:8',
|
||||
'QChar': 'uint:2'
|
||||
|
@@ -1393,14 +1393,19 @@ void NodeInstanceServer::setTranslationLanguage(const QString &language)
|
||||
engine()->setUiLanguage(language);
|
||||
#endif
|
||||
static QPointer<MultiLanguage::Translator> multilanguageTranslator;
|
||||
if (!MultiLanguage::databaseFilePath().isEmpty()) {
|
||||
if (!multilanguageLink) {
|
||||
multilanguageLink = std::make_unique<MultiLanguage::Link>();
|
||||
multilanguageTranslator = multilanguageLink->translator().release();
|
||||
QCoreApplication::installTranslator(multilanguageTranslator);
|
||||
if (!MultiLanguage::databaseFilePath().isEmpty()
|
||||
&& QFileInfo::exists(QString::fromUtf8(MultiLanguage::databaseFilePath()))) {
|
||||
try {
|
||||
if (!multilanguageLink) {
|
||||
multilanguageLink = std::make_unique<MultiLanguage::Link>();
|
||||
multilanguageTranslator = multilanguageLink->translator().release();
|
||||
QCoreApplication::installTranslator(multilanguageTranslator);
|
||||
}
|
||||
if (multilanguageTranslator)
|
||||
multilanguageTranslator->setLanguage(language);
|
||||
} catch (std::exception &e) {
|
||||
qWarning() << "QmlPuppet is unable to initialize MultiLanguage translator:" << e.what();
|
||||
}
|
||||
if (multilanguageTranslator)
|
||||
multilanguageTranslator->setLanguage(language);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -32,6 +32,8 @@ import StudioControls 1.0 as StudioControls
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Item {
|
||||
id: rootItem
|
||||
|
||||
property var selectedAssets: ({})
|
||||
property int allExpandedState: 0
|
||||
property string delFilePath: ""
|
||||
@@ -257,4 +259,52 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder when the assets panel is empty
|
||||
Column {
|
||||
id: colNoAssets
|
||||
visible: assetsModel.isEmpty
|
||||
|
||||
spacing: 20
|
||||
x: 20
|
||||
width: rootItem.width - 2 * x
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Text {
|
||||
text: qsTr("Looks like you don't have any assets yet.")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: 18
|
||||
width: colNoAssets.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Image {
|
||||
source: "image://qmldesigner_assets/browse"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
scale: maBrowse.containsMouse ? 1.2 : 1
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
duration: 300
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: maBrowse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: rootView.handleAddAsset();
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Drag-and-drop your assets here or click the '+' button to browse assets from the file system.")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
font.pixelSize: 18
|
||||
width: colNoAssets.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -105,8 +105,11 @@ Item {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.centerIn: parent
|
||||
color: tabBar.currentIndex === index ? StudioTheme.Values.themeIconColorSelected
|
||||
: StudioTheme.Values.themeIconColor
|
||||
color: !plusButton.enabled
|
||||
? StudioTheme.Values.themeIconColorDisabled
|
||||
: tabBar.currentIndex === index
|
||||
? StudioTheme.Values.themeIconColorSelected
|
||||
: StudioTheme.Values.themeIconColor
|
||||
}
|
||||
|
||||
HelperWidgets.ToolTipArea {
|
||||
|
@@ -0,0 +1,192 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick.Window
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import StudioTheme as StudioTheme
|
||||
import StudioControls as SC
|
||||
|
||||
import NewProjectDialog
|
||||
|
||||
Item {
|
||||
width: DialogValues.dialogWidth
|
||||
height: DialogValues.dialogHeight
|
||||
|
||||
Rectangle { // the main dialog panel
|
||||
anchors.fill: parent
|
||||
color: DialogValues.darkPaneColor
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 0
|
||||
|
||||
Item { // Header Item
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 218
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
|
||||
Item { width: parent.width; height: 74 } // spacer
|
||||
|
||||
Text {
|
||||
text: qsTr("Welcome to Qt Design Studio. Let's Create Something Wonderful!")
|
||||
font.pixelSize: 32
|
||||
width: parent.width
|
||||
height: 47
|
||||
lineHeight: 49
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Item { width: parent.width; height: 11 } // spacer
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
text: qsTr("Get started by selecting from Presets or start from empty screen. You may also include your design file.")
|
||||
color: DialogValues.textColor
|
||||
font.pixelSize: DialogValues.paneTitlePixelSize
|
||||
lineHeight: DialogValues.paneTitleLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
} // Header Item
|
||||
|
||||
Item { // Content Item
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
x: 35
|
||||
width: parent.width - 70
|
||||
height: parent.height
|
||||
spacing: 0
|
||||
|
||||
Rectangle { // Left pane
|
||||
color: DialogValues.lightPaneColor
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.minimumWidth: 379 // figured out this number visually
|
||||
Layout.minimumHeight: 326 // figured out this number visually
|
||||
|
||||
Column {
|
||||
x: DialogValues.defaultPadding // left padding
|
||||
width: parent.width - DialogValues.defaultPadding * 2 // right padding
|
||||
height: parent.height
|
||||
|
||||
Text {
|
||||
text: qsTr("Presets")
|
||||
width: parent.width
|
||||
font.weight: Font.DemiBold
|
||||
font.pixelSize: DialogValues.paneTitlePixelSize
|
||||
lineHeight: DialogValues.paneTitleLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
|
||||
NewProjectView {
|
||||
id: projectViewId
|
||||
x: 10 // left padding
|
||||
width: parent.width - 64 // right padding
|
||||
height: DialogValues.projectViewHeight
|
||||
loader: projectDetailsLoader
|
||||
}
|
||||
|
||||
Item { height: 5; width: parent.width }
|
||||
|
||||
Text {
|
||||
id: descriptionText
|
||||
text: dialogBox.projectDescription
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
leftPadding: 14
|
||||
width: projectViewId.width
|
||||
color: DialogValues.textColor
|
||||
wrapMode: Text.WordWrap
|
||||
maximumLineCount: 4
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
} // Left pane
|
||||
|
||||
Loader {
|
||||
id: projectDetailsLoader
|
||||
// we need to specify width because the loaded item needs to use parent sizes
|
||||
width: DialogValues.loadedPanesWidth
|
||||
Layout.fillHeight: true
|
||||
source: ""
|
||||
}
|
||||
} // RowLayout
|
||||
} //Content Item
|
||||
|
||||
Item { // Footer
|
||||
implicitHeight: DialogValues.footerHeight
|
||||
implicitWidth: parent.width
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
spacing: DialogValues.defaultPadding
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
SC.AbstractButton {
|
||||
implicitWidth: DialogValues.dialogButtonWidth
|
||||
width: DialogValues.dialogButtonWidth
|
||||
visible: true
|
||||
buttonIcon: qsTr("Cancel")
|
||||
iconSize: DialogValues.defaultPixelSize
|
||||
iconFont: StudioTheme.Constants.font
|
||||
|
||||
onClicked: {
|
||||
dialogBox.reject();
|
||||
}
|
||||
}
|
||||
|
||||
SC.AbstractButton {
|
||||
implicitWidth: DialogValues.dialogButtonWidth
|
||||
width: DialogValues.dialogButtonWidth
|
||||
visible: true
|
||||
buttonIcon: qsTr("Create")
|
||||
iconSize: DialogValues.defaultPixelSize
|
||||
enabled: dialogBox.fieldsValid
|
||||
iconFont: StudioTheme.Constants.font
|
||||
|
||||
onClicked: {
|
||||
dialogBox.accept();
|
||||
}
|
||||
}
|
||||
Item { implicitWidth: 35 - DialogValues.defaultPadding }
|
||||
} // RowLayout
|
||||
} // Footer
|
||||
} // ColumnLayout
|
||||
} // Rectangle
|
||||
}
|
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 9.6 KiB |
@@ -0,0 +1,453 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import StudioControls as SC
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
Item {
|
||||
width: DialogValues.detailsPaneWidth
|
||||
|
||||
Component.onCompleted: {
|
||||
dialogBox.detailsLoaded = true;
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
dialogBox.detailsLoaded = false;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: DialogValues.darkPaneColor
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
x: DialogValues.detailsPanePadding // left padding
|
||||
width: parent.width - DialogValues.detailsPanePadding * 2 // right padding
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: DialogValues.defaultPadding
|
||||
|
||||
Text {
|
||||
text: qsTr("Details")
|
||||
width: parent.width;
|
||||
font.weight: Font.DemiBold
|
||||
font.pixelSize: DialogValues.paneTitlePixelSize
|
||||
lineHeight: DialogValues.paneTitleLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
|
||||
SC.TextField {
|
||||
id: projectNameTextField
|
||||
actionIndicatorVisible: false
|
||||
translationIndicatorVisible: false
|
||||
text: dialogBox.projectName
|
||||
width: parent.width
|
||||
color: DialogValues.textColor
|
||||
selectByMouse: true
|
||||
|
||||
font.pixelSize: DialogValues.paneTitlePixelSize
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: dialogBox
|
||||
property: "projectName"
|
||||
value: projectNameTextField.text
|
||||
}
|
||||
|
||||
Item { width: parent.width; height: DialogValues.narrowSpacing(11) }
|
||||
|
||||
RowLayout { // Project location
|
||||
width: parent.width
|
||||
|
||||
SC.TextField {
|
||||
Layout.fillWidth: true
|
||||
id: projectLocationTextField
|
||||
actionIndicatorVisible: false
|
||||
translationIndicatorVisible: false
|
||||
text: dialogBox.projectLocation
|
||||
color: DialogValues.textColor
|
||||
selectByMouse: true
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: dialogBox
|
||||
property: "projectLocation"
|
||||
value: projectLocationTextField.text
|
||||
}
|
||||
|
||||
SC.AbstractButton {
|
||||
implicitWidth: 30
|
||||
iconSize: 20
|
||||
visible: true
|
||||
buttonIcon: "…"
|
||||
iconFont: StudioTheme.Constants.font
|
||||
|
||||
onClicked: {
|
||||
var newLocation = dialogBox.chooseProjectLocation()
|
||||
if (newLocation)
|
||||
projectLocationTextField.text = newLocation
|
||||
}
|
||||
} // SC.AbstractButton
|
||||
} // Project location RowLayout
|
||||
|
||||
Item { width: parent.width; height: DialogValues.narrowSpacing(7) }
|
||||
|
||||
RowLayout { // StatusMessage
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
|
||||
Image {
|
||||
id: statusIcon
|
||||
asynchronous: false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: statusMessage
|
||||
text: dialogBox.statusMessage
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
wrapMode: Text.Wrap
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 3
|
||||
Layout.fillWidth: true
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "warning"
|
||||
when: dialogBox.statusType === "warning"
|
||||
PropertyChanges {
|
||||
target: statusMessage
|
||||
color: DialogValues.textWarning
|
||||
}
|
||||
PropertyChanges {
|
||||
target: statusIcon
|
||||
source: "image://newprojectdialog_library/status-warning"
|
||||
}
|
||||
},
|
||||
|
||||
State {
|
||||
name: "error"
|
||||
when: dialogBox.statusType === "error"
|
||||
PropertyChanges {
|
||||
target: statusMessage
|
||||
color: DialogValues.textError
|
||||
}
|
||||
PropertyChanges {
|
||||
target: statusIcon
|
||||
source: "image://newprojectdialog_library/status-error"
|
||||
}
|
||||
}
|
||||
]
|
||||
} // Text
|
||||
} // RowLayout
|
||||
|
||||
SC.CheckBox {
|
||||
id: defaultLocationCheckbox
|
||||
actionIndicatorVisible: false
|
||||
text: qsTr("Use as default project location")
|
||||
checked: false
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: dialogBox
|
||||
property: "saveAsDefaultLocation"
|
||||
value: defaultLocationCheckbox.checked
|
||||
}
|
||||
|
||||
Rectangle { width: parent.width; height: 1; color: DialogValues.dividerlineColor }
|
||||
|
||||
SC.ComboBox { // Screen Size ComboBox
|
||||
id: screenSizeComboBox
|
||||
actionIndicatorVisible: false
|
||||
currentIndex: 1
|
||||
model: screenSizeModel
|
||||
textRole: "display"
|
||||
width: parent.width
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
|
||||
onActivated: (index) => {
|
||||
// NOTE: item 0 is activated when the screenSizeModel is reset
|
||||
dialogBox.setScreenSizeIndex(index);
|
||||
|
||||
var r = screenSizeModel.screenSizes(index);
|
||||
widthTextField.text = r.width;
|
||||
heightTextField.text = r.height;
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: screenSizeModel
|
||||
function onModelReset() {
|
||||
screenSizeComboBox.activated(screenSizeComboBox.currentIndex)
|
||||
}
|
||||
}
|
||||
} // Screen Size ComboBox
|
||||
|
||||
GridLayout { // orientation + width + height
|
||||
width: parent.width
|
||||
height: 85
|
||||
|
||||
columns: 4
|
||||
rows: 2
|
||||
|
||||
columnSpacing: 10
|
||||
rowSpacing: 10
|
||||
|
||||
// header items
|
||||
Text {
|
||||
text: qsTr("Width")
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Height")
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Text {
|
||||
text: qsTr("Orientation")
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
|
||||
// content items
|
||||
SC.TextField {
|
||||
id: widthTextField
|
||||
actionIndicatorVisible: false
|
||||
translationIndicatorVisible: false
|
||||
implicitWidth: 50
|
||||
color: DialogValues.textColor
|
||||
selectByMouse: true
|
||||
validator: IntValidator { bottom: 1; top: 100000; }
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
|
||||
onTextChanged: {
|
||||
var height = heightTextField.text ? parseInt(heightTextField.text) : 0
|
||||
var width = text ? parseInt(text) : 0
|
||||
|
||||
if (width >= height)
|
||||
orientationButton.setHorizontal()
|
||||
else
|
||||
orientationButton.setVertical()
|
||||
}
|
||||
} // Width Text Field
|
||||
|
||||
Binding {
|
||||
target: dialogBox
|
||||
property: "customWidth"
|
||||
value: widthTextField.text
|
||||
}
|
||||
|
||||
SC.TextField {
|
||||
id: heightTextField
|
||||
actionIndicatorVisible: false
|
||||
translationIndicatorVisible: false
|
||||
implicitWidth: 50
|
||||
color: DialogValues.textColor
|
||||
selectByMouse: true
|
||||
validator: IntValidator { bottom: 1; top: 100000; }
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
|
||||
onTextChanged: {
|
||||
var height = text ? parseInt(text) : 0
|
||||
var width = widthTextField.text ? parseInt(widthTextField.text) : 0
|
||||
|
||||
if (width >= height)
|
||||
orientationButton.setHorizontal()
|
||||
else
|
||||
orientationButton.setVertical()
|
||||
}
|
||||
} // Height Text Field
|
||||
|
||||
Binding {
|
||||
target: dialogBox
|
||||
property: "customHeight"
|
||||
value: heightTextField.text
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Button {
|
||||
id: orientationButton
|
||||
implicitWidth: 100
|
||||
implicitHeight: 50
|
||||
|
||||
checked: false
|
||||
hoverEnabled: false
|
||||
background: Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: "transparent"
|
||||
|
||||
Row {
|
||||
Item {
|
||||
width: orientationButton.width / 2
|
||||
height: orientationButton.height
|
||||
Rectangle {
|
||||
id: horizontalBar
|
||||
color: "white"
|
||||
width: parent.width
|
||||
height: orientationButton.height / 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: orientationButton.width / 4
|
||||
height: orientationButton.height
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: verticalBar
|
||||
width: orientationButton.width / 4
|
||||
height: orientationButton.height
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (widthTextField.text && heightTextField.text) {
|
||||
[widthTextField.text, heightTextField.text] = [heightTextField.text, widthTextField.text];
|
||||
|
||||
checked = !checked
|
||||
}
|
||||
}
|
||||
|
||||
function setHorizontal() {
|
||||
checked = false
|
||||
horizontalBar.color = DialogValues.textColorInteraction
|
||||
verticalBar.color = "white"
|
||||
}
|
||||
|
||||
function setVertical() {
|
||||
checked = true
|
||||
horizontalBar.color = "white"
|
||||
verticalBar.color = DialogValues.textColorInteraction
|
||||
}
|
||||
} // Orientation button
|
||||
|
||||
} // GridLayout: orientation + width + height
|
||||
|
||||
Rectangle { width: parent.width; height: 1; color: DialogValues.dividerlineColor }
|
||||
|
||||
SC.Section {
|
||||
width: parent.width
|
||||
caption: qsTr("Advanced")
|
||||
captionPixelSize: DialogValues.defaultPixelSize
|
||||
captionColor: DialogValues.darkPaneColor
|
||||
captionTextColor: DialogValues.textColor
|
||||
leftPadding: 0
|
||||
expanded: true
|
||||
visible: dialogBox.haveVirtualKeyboard || dialogBox.haveTargetQtVersion
|
||||
|
||||
Column {
|
||||
spacing: DialogValues.defaultPadding
|
||||
width: parent.width
|
||||
|
||||
/* We need a spacer of -10 in order to have actual 18px spacing between
|
||||
* section bottom and the checkbox. Otherwise, with Column spacing set to
|
||||
* 18, without a spacer, the default space to the first item would be 10,
|
||||
* for some reason. */
|
||||
Item { width: parent.width; height: -10 }
|
||||
|
||||
SC.CheckBox {
|
||||
id: useQtVirtualKeyboard
|
||||
actionIndicatorVisible: false
|
||||
text: qsTr("Use Qt Virtual Keyboard")
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
checked: dialogBox.useVirtualKeyboard
|
||||
visible: dialogBox.haveVirtualKeyboard
|
||||
}
|
||||
|
||||
RowLayout { // Target Qt Version
|
||||
width: parent.width
|
||||
visible: dialogBox.haveTargetQtVersion
|
||||
|
||||
Text {
|
||||
text: "Target Qt Version:"
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
|
||||
SC.ComboBox { // Target Qt Version ComboBox
|
||||
id: qtVersionComboBox
|
||||
actionIndicatorVisible: false
|
||||
implicitWidth: 70
|
||||
Layout.alignment: Qt.AlignRight
|
||||
currentIndex: 1
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
name: "Qt 5"
|
||||
}
|
||||
ListElement {
|
||||
name: "Qt 6"
|
||||
}
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
|
||||
onActivated: (index) => {
|
||||
dialogBox.setTargetQtVersion(index)
|
||||
}
|
||||
} // Target Qt Version ComboBox
|
||||
|
||||
} // RowLayout
|
||||
} // Column
|
||||
} // SC.Section
|
||||
|
||||
Binding {
|
||||
target: dialogBox
|
||||
property: "useVirtualKeyboard"
|
||||
value: useQtVirtualKeyboard.checked
|
||||
}
|
||||
|
||||
} // Column
|
||||
} // Item
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
pragma Singleton
|
||||
import QtQml
|
||||
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
QtObject {
|
||||
readonly property int dialogWidth: 1522
|
||||
readonly property int dialogHeight: 994
|
||||
readonly property int projectViewMinimumWidth: 600
|
||||
readonly property int projectViewMinimumHeight: projectViewHeight
|
||||
readonly property int dialogContentHeight: projectViewHeight + 300 // i.e. dialog without header and footer
|
||||
readonly property int loadedPanesWidth: detailsPaneWidth + stylesPaneWidth
|
||||
readonly property int detailsPaneWidth: 330 + detailsPanePadding * 2
|
||||
readonly property int stylesPaneWidth: styleImageWidth + stylesPanePadding * 2 + styleImageBorderWidth * 2 // i.e. 240px
|
||||
readonly property int detailsPanePadding: 18
|
||||
readonly property int stylesPanePadding: 18
|
||||
readonly property int defaultPadding: 18
|
||||
|
||||
readonly property int styleImageWidth: 200
|
||||
readonly property int styleImageBorderWidth: 2
|
||||
readonly property int footerHeight: 73
|
||||
readonly property int projectItemWidth: 144
|
||||
readonly property int projectItemHeight: 144
|
||||
readonly property int projectViewHeight: projectItemHeight * 2 + projectViewHeaderHeight
|
||||
readonly property int projectViewHeaderHeight: 38
|
||||
|
||||
readonly property int dialogButtonWidth: 100
|
||||
|
||||
readonly property int loadedPanesHeight: dialogContentHeight
|
||||
readonly property int detailsPaneHeight: dialogContentHeight
|
||||
|
||||
readonly property string darkPaneColor: StudioTheme.Values.themeBackgroundColorNormal
|
||||
readonly property string lightPaneColor: StudioTheme.Values.themeBackgroundColorAlternate
|
||||
|
||||
readonly property string textColor: StudioTheme.Values.themeTabInactiveText
|
||||
readonly property string textColorInteraction: StudioTheme.Values.themeInteraction
|
||||
readonly property string dividerlineColor: StudioTheme.Values.themeTextColorDisabled
|
||||
readonly property string textError: StudioTheme.Values.themeError
|
||||
readonly property string textWarning: StudioTheme.Values.themeWarning
|
||||
|
||||
readonly property real defaultPixelSize: 14
|
||||
readonly property real defaultLineHeight: 21
|
||||
readonly property real viewHeaderPixelSize: 16
|
||||
readonly property real viewHeaderLineHeight: 24
|
||||
readonly property real paneTitlePixelSize: 18
|
||||
readonly property real paneTitleLineHeight: 27
|
||||
|
||||
// for a spacer item
|
||||
function narrowSpacing(value, layoutSpacing = DialogValues.defaultPadding) {
|
||||
/* e.g. if we want narrow spacing value = 11, then for the spacer item residing inside a
|
||||
layout with spacing set to 18, we need to realize the fact that by adding the spacer
|
||||
item, we already have 18 * 2 spacing added implicitly (i.e. spacing before the spacer
|
||||
item and spacing after it). So we have to subtract 2 x layout spacing before setting
|
||||
our own, narrower, spacing.
|
||||
*/
|
||||
return -layoutSpacing -layoutSpacing + value
|
||||
}
|
||||
}
|
@@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
GridView {
|
||||
id: projectView
|
||||
|
||||
required property Item loader
|
||||
|
||||
header: TabBar {
|
||||
id: tabBar
|
||||
width: parent.width
|
||||
height: DialogValues.projectViewHeaderHeight
|
||||
|
||||
background: Rectangle {
|
||||
color: DialogValues.lightPaneColor
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: categoryModel
|
||||
|
||||
TabButton {
|
||||
padding: 0
|
||||
|
||||
width: headerText.contentWidth + 36
|
||||
|
||||
background: Item { // TabButton background
|
||||
Rectangle { // bottom strip
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: headerText.contentWidth
|
||||
height: 6
|
||||
radius: 10
|
||||
color: tabBar.currentIndex === index ? DialogValues.textColorInteraction
|
||||
: "transparent"
|
||||
}
|
||||
} // TabButton background
|
||||
|
||||
implicitHeight: headerText.height + DialogValues.defaultPadding - 7
|
||||
|
||||
contentItem: Item {
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
|
||||
Text {
|
||||
id: headerText
|
||||
color: tabBar.currentIndex == index ? DialogValues.textColorInteraction
|
||||
: DialogValues.textColor
|
||||
text: name
|
||||
width: parent.width
|
||||
font.weight: Font.DemiBold
|
||||
font.pixelSize: DialogValues.viewHeaderPixelSize
|
||||
lineHeight: DialogValues.viewHeaderLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Item { width: parent.width; height: 11; }
|
||||
} // Column
|
||||
} // Item
|
||||
|
||||
onClicked: {
|
||||
projectModel.setPage(index)
|
||||
projectView.currentIndex = 0
|
||||
projectView.currentIndexChanged()
|
||||
}
|
||||
} // TabButton
|
||||
} // Repeater
|
||||
} // Header - TabBar
|
||||
|
||||
cellWidth: DialogValues.projectItemWidth
|
||||
cellHeight: DialogValues.projectItemHeight
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
children: [
|
||||
Rectangle {
|
||||
color: DialogValues.darkPaneColor
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
}
|
||||
]
|
||||
|
||||
model: projectModel
|
||||
|
||||
// called by onModelReset and when user clicks on an item, or when the header item is changed.
|
||||
onCurrentIndexChanged: {
|
||||
dialogBox.selectedProject = projectView.currentIndex
|
||||
var source = dialogBox.currentProjectQmlPath()
|
||||
loader.source = source
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: projectModel
|
||||
|
||||
// called when data is set (setWizardFactories)
|
||||
function onModelReset() {
|
||||
currentIndex = 0
|
||||
currentIndexChanged()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: delegate
|
||||
|
||||
width: DialogValues.projectItemWidth
|
||||
height: DialogValues.projectItemHeight
|
||||
|
||||
function fontIconCode(index) {
|
||||
var code = projectModel.fontIconCode(index)
|
||||
return code ? code : StudioTheme.Constants.wizardsUnknown
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Label {
|
||||
id: projectTypeIcon
|
||||
text: fontIconCode(index)
|
||||
color: DialogValues.textColor
|
||||
width: parent.width
|
||||
height: DialogValues.projectItemHeight / 2
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignBottom
|
||||
renderType: Text.NativeRendering
|
||||
font.pixelSize: 65
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
}
|
||||
|
||||
Text {
|
||||
id: projectTypeLabel
|
||||
color: DialogValues.textColor
|
||||
|
||||
text: name
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
width: parent.width
|
||||
height: DialogValues.projectItemHeight / 2
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
}
|
||||
} // Column
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
delegate.GridView.view.currentIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
when: delegate.GridView.isCurrentItem
|
||||
PropertyChanges {
|
||||
target: projectTypeLabel
|
||||
color: DialogValues.textColorInteraction
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: projectTypeIcon
|
||||
color: DialogValues.textColorInteraction
|
||||
}
|
||||
} // State
|
||||
]
|
||||
} // ItemDelegate
|
||||
} // GridView
|
@@ -0,0 +1,183 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
import StudioControls as SC
|
||||
|
||||
Item {
|
||||
width: DialogValues.stylesPaneWidth
|
||||
|
||||
Component.onCompleted: {
|
||||
dialogBox.stylesLoaded = true;
|
||||
|
||||
/*
|
||||
* TODO: roleNames is called before the backend model (in the proxy class StyleModel) is
|
||||
* loaded, which may be buggy. But I found no way to force refresh the model, so as to
|
||||
* reload the role names afterwards. setting styleModel.dynamicRoles doesn't appear to do
|
||||
* anything.
|
||||
*/
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
dialogBox.stylesLoaded = false;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: DialogValues.lightPaneColor
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
x: DialogValues.stylesPanePadding // left padding
|
||||
width: parent.width - DialogValues.stylesPanePadding * 2 // right padding
|
||||
height: parent.height
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
Text {
|
||||
id: styleTitleText
|
||||
text: qsTr("Style")
|
||||
width: parent.width;
|
||||
font.weight: Font.DemiBold
|
||||
font.pixelSize: DialogValues.paneTitlePixelSize
|
||||
lineHeight: DialogValues.paneTitleLineHeight
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: DialogValues.textColor
|
||||
|
||||
function refresh() {
|
||||
text = qsTr("Style") + " (" + styleModel.rowCount() + ")"
|
||||
}
|
||||
}
|
||||
|
||||
SC.ComboBox { // Style Filter ComboBox
|
||||
actionIndicatorVisible: false
|
||||
currentIndex: 0
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
|
||||
model: ListModel {
|
||||
ListElement { text: qsTr("All"); value: "all" }
|
||||
ListElement { text: qsTr("Light"); value: "light" }
|
||||
ListElement { text: qsTr("Dark"); value: "dark" }
|
||||
}
|
||||
|
||||
implicitWidth: parent.width
|
||||
|
||||
onActivated: (index) => {
|
||||
styleModel.filter(currentValue.toLowerCase());
|
||||
styleTitleText.refresh();
|
||||
}
|
||||
} // Style Filter ComboBox
|
||||
|
||||
ListView {
|
||||
id: stylesList
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
model: styleModel
|
||||
|
||||
focus: true
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
highlightFollowsCurrentItem: false
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (styleModel.rowCount() > 0)
|
||||
dialogBox.styleIndex = stylesList.currentIndex;
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: delegateId
|
||||
height: styleImage.height + DialogValues.styleImageBorderWidth + styleText.height + 1
|
||||
width: stylesList.width
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: DialogValues.lightPaneColor
|
||||
|
||||
Column {
|
||||
spacing: 0
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
border.color: index == stylesList.currentIndex ? DialogValues.textColorInteraction : "transparent"
|
||||
border.width: index == stylesList.currentIndex ? DialogValues.styleImageBorderWidth : 0
|
||||
color: "transparent"
|
||||
width: parent.width
|
||||
height: parent.height - styleText.height
|
||||
|
||||
Image {
|
||||
id: styleImage
|
||||
asynchronous: false
|
||||
source: "image://newprojectdialog_library/" + styleModel.iconId(model.index)
|
||||
width: 200
|
||||
height: 262
|
||||
x: DialogValues.styleImageBorderWidth
|
||||
y: DialogValues.styleImageBorderWidth
|
||||
}
|
||||
} // Rectangle
|
||||
|
||||
Text {
|
||||
id: styleText
|
||||
text: model.display
|
||||
font.pixelSize: DialogValues.defaultPixelSize
|
||||
lineHeight: DialogValues.defaultLineHeight
|
||||
height: 18
|
||||
lineHeightMode: Text.FixedHeight
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
width: parent.width
|
||||
color: DialogValues.textColor
|
||||
}
|
||||
} // Column
|
||||
} // Rectangle
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
stylesList.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: styleModel
|
||||
function onModelReset() {
|
||||
stylesList.currentIndex = dialogBox.styleIndex;
|
||||
stylesList.currentIndexChanged();
|
||||
styleTitleText.refresh();
|
||||
}
|
||||
}
|
||||
} // ListView
|
||||
} // ColumnLayout
|
||||
} // Parent Item
|
||||
} // Rectangle
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
singleton DialogValues 1.0 DialogValues.qml
|
||||
Details 1.0 Details.qml
|
||||
Styles 1.0 Styles.qml
|
||||
NewProjectView 1.0 NewProjectView.qml
|
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick.Window
|
||||
import QtQuick.Controls
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
import newprojectdialog
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
|
||||
Details {
|
||||
height: parent.height
|
||||
}
|
||||
|
||||
Styles {
|
||||
height: parent.height
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
DefaultProject 1.0 DefaultProject.qml
|
@@ -30,6 +30,9 @@ import StudioTheme 1.0 as StudioTheme
|
||||
Item {
|
||||
id: section
|
||||
property alias caption: label.text
|
||||
property alias captionPixelSize: label.font.pixelSize
|
||||
property alias captionColor: header.color
|
||||
property alias captionTextColor: label.color
|
||||
property int leftPadding: 8
|
||||
property int topPadding: 4
|
||||
property int rightPadding: 0
|
||||
|
@@ -23,7 +23,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick 2.15
|
||||
|
||||
QtObject {
|
||||
readonly property int width: 1920
|
||||
@@ -95,84 +95,92 @@ QtObject {
|
||||
readonly property string distributeSpacingHorizontal: "\u005A"
|
||||
readonly property string distributeSpacingVertical: "\u005B"
|
||||
readonly property string distributeTop: "\u005C"
|
||||
readonly property string edit: "\u005D"
|
||||
readonly property string eyeDropper: "\u005E"
|
||||
readonly property string flowAction: "\u005F"
|
||||
readonly property string flowTransition: "\u0060"
|
||||
readonly property string fontStyleBold: "\u0061"
|
||||
readonly property string fontStyleItalic: "\u0062"
|
||||
readonly property string fontStyleStrikethrough: "\u0063"
|
||||
readonly property string fontStyleUnderline: "\u0064"
|
||||
readonly property string gradient: "\u0065"
|
||||
readonly property string gridView: "\u0066"
|
||||
readonly property string idAliasOff: "\u0067"
|
||||
readonly property string idAliasOn: "\u0068"
|
||||
readonly property string infinity: "\u0069"
|
||||
readonly property string keyframe: "\u006A"
|
||||
readonly property string linkTriangle: "\u006B"
|
||||
readonly property string linked: "\u006C"
|
||||
readonly property string listView: "\u006D"
|
||||
readonly property string lockOff: "\u006E"
|
||||
readonly property string lockOn: "\u006F"
|
||||
readonly property string mergeCells: "\u0070"
|
||||
readonly property string minus: "\u0071"
|
||||
readonly property string mirror: "\u0072"
|
||||
readonly property string orientation: "\u0073"
|
||||
readonly property string paddingEdge: "\u0074"
|
||||
readonly property string paddingFrame: "\u0075"
|
||||
readonly property string pasteStyle: "\u0076"
|
||||
readonly property string pause: "\u0077"
|
||||
readonly property string pin: "\u0078"
|
||||
readonly property string play: "\u0079"
|
||||
readonly property string plus: "\u007A"
|
||||
readonly property string promote: "\u007B"
|
||||
readonly property string readOnly: "\u007C"
|
||||
readonly property string redo: "\u007D"
|
||||
readonly property string rotationFill: "\u007E"
|
||||
readonly property string rotationOutline: "\u007F"
|
||||
readonly property string search: "\u0080"
|
||||
readonly property string sectionToggle: "\u0081"
|
||||
readonly property string splitColumns: "\u0082"
|
||||
readonly property string splitRows: "\u0083"
|
||||
readonly property string startNode: "\u0084"
|
||||
readonly property string testIcon: "\u0085"
|
||||
readonly property string textAlignBottom: "\u0086"
|
||||
readonly property string textAlignCenter: "\u0087"
|
||||
readonly property string textAlignJustified: "\u0088"
|
||||
readonly property string textAlignLeft: "\u0089"
|
||||
readonly property string textAlignMiddle: "\u008A"
|
||||
readonly property string textAlignRight: "\u008B"
|
||||
readonly property string textAlignTop: "\u008C"
|
||||
readonly property string textBulletList: "\u008D"
|
||||
readonly property string textFullJustification: "\u008E"
|
||||
readonly property string textNumberedList: "\u008F"
|
||||
readonly property string tickIcon: "\u0090"
|
||||
readonly property string transparent: "\u0091"
|
||||
readonly property string triState: "\u0092"
|
||||
readonly property string triangleArcA: "\u0093"
|
||||
readonly property string triangleArcB: "\u0094"
|
||||
readonly property string triangleCornerA: "\u0095"
|
||||
readonly property string triangleCornerB: "\u0096"
|
||||
readonly property string unLinked: "\u0097"
|
||||
readonly property string undo: "\u0098"
|
||||
readonly property string unpin: "\u0099"
|
||||
readonly property string upDownIcon: "\u009A"
|
||||
readonly property string upDownSquare2: "\u009B"
|
||||
readonly property string visibilityOffBroken: "\u009C" // visibilityOff
|
||||
readonly property string visibilityOff: "\u009D" // visibilityOff2
|
||||
readonly property string visibilityOn: "\u009E"
|
||||
readonly property string wildcard: "\u009F"
|
||||
readonly property string wizardsAutomotive: "\u00A0"
|
||||
readonly property string wizardsDesktop: "\u00A1"
|
||||
readonly property string wizardsGeneric: "\u00A2"
|
||||
readonly property string wizardsMcuEmpty: "\u00A3"
|
||||
readonly property string wizardsMcuGraph: "\u00A4"
|
||||
readonly property string wizardsMobile: "\u00A5"
|
||||
readonly property string wizardsUnknown: "\u00A6"
|
||||
readonly property string zoomAll: "\u00A7"
|
||||
readonly property string zoomIn: "\u00A8"
|
||||
readonly property string zoomOut: "\u00A9"
|
||||
readonly property string zoomSelection: "\u00AA"
|
||||
readonly property string download: "\u005D"
|
||||
readonly property string edit: "\u005E"
|
||||
readonly property string eyeDropper: "\u005F"
|
||||
readonly property string favorite: "\u0060"
|
||||
readonly property string flowAction: "\u0061"
|
||||
readonly property string flowTransition: "\u0062"
|
||||
readonly property string fontStyleBold: "\u0063"
|
||||
readonly property string fontStyleItalic: "\u0064"
|
||||
readonly property string fontStyleStrikethrough: "\u0065"
|
||||
readonly property string fontStyleUnderline: "\u0066"
|
||||
readonly property string gradient: "\u0067"
|
||||
readonly property string gridView: "\u0068"
|
||||
readonly property string idAliasOff: "\u0069"
|
||||
readonly property string idAliasOn: "\u006A"
|
||||
readonly property string infinity: "\u006B"
|
||||
readonly property string keyframe: "\u006C"
|
||||
readonly property string linkTriangle: "\u006D"
|
||||
readonly property string linked: "\u006E"
|
||||
readonly property string listView: "\u006F"
|
||||
readonly property string lockOff: "\u0070"
|
||||
readonly property string lockOn: "\u0071"
|
||||
readonly property string mergeCells: "\u0072"
|
||||
readonly property string minus: "\u0073"
|
||||
readonly property string mirror: "\u0074"
|
||||
readonly property string orientation: "\u0075"
|
||||
readonly property string paddingEdge: "\u0076"
|
||||
readonly property string paddingFrame: "\u0077"
|
||||
readonly property string pasteStyle: "\u0078"
|
||||
readonly property string pause: "\u0079"
|
||||
readonly property string pin: "\u007A"
|
||||
readonly property string play: "\u007B"
|
||||
readonly property string plus: "\u007C"
|
||||
readonly property string promote: "\u007D"
|
||||
readonly property string readOnly: "\u007E"
|
||||
readonly property string redo: "\u007F"
|
||||
readonly property string rotationFill: "\u0080"
|
||||
readonly property string rotationOutline: "\u0081"
|
||||
readonly property string search: "\u0082"
|
||||
readonly property string sectionToggle: "\u0083"
|
||||
readonly property string splitColumns: "\u0084"
|
||||
readonly property string splitRows: "\u0085"
|
||||
readonly property string startNode: "\u0086"
|
||||
readonly property string testIcon: "\u0087"
|
||||
readonly property string textAlignBottom: "\u0088"
|
||||
readonly property string textAlignCenter: "\u0089"
|
||||
readonly property string textAlignJustified: "\u008A"
|
||||
readonly property string textAlignLeft: "\u008B"
|
||||
readonly property string textAlignMiddle: "\u008C"
|
||||
readonly property string textAlignRight: "\u008D"
|
||||
readonly property string textAlignTop: "\u008E"
|
||||
readonly property string textBulletList: "\u008F"
|
||||
readonly property string textFullJustification: "\u0090"
|
||||
readonly property string textNumberedList: "\u0091"
|
||||
readonly property string tickIcon: "\u0092"
|
||||
readonly property string translationCreateFiles: "\u0093"
|
||||
readonly property string translationCreateReport: "\u0094"
|
||||
readonly property string translationExport: "\u0095"
|
||||
readonly property string translationImport: "\u0096"
|
||||
readonly property string translationSelectLanguages: "\u0097"
|
||||
readonly property string translationTest: "\u0098"
|
||||
readonly property string transparent: "\u0099"
|
||||
readonly property string triState: "\u009A"
|
||||
readonly property string triangleArcA: "\u009B"
|
||||
readonly property string triangleArcB: "\u009C"
|
||||
readonly property string triangleCornerA: "\u009D"
|
||||
readonly property string triangleCornerB: "\u009E"
|
||||
readonly property string unLinked: "\u009F"
|
||||
readonly property string undo: "\u00A0"
|
||||
readonly property string unpin: "\u00A1"
|
||||
readonly property string upDownIcon: "\u00A2"
|
||||
readonly property string upDownSquare2: "\u00A3"
|
||||
readonly property string visibilityOffBroken: "\u00A4" // visibilityOff
|
||||
readonly property string visibilityOff: "\u00A5" // visibilityOff2
|
||||
readonly property string visibilityOn: "\u00A6"
|
||||
readonly property string wildcard: "\u00A7"
|
||||
readonly property string wizardsAutomotive: "\u00A8"
|
||||
readonly property string wizardsDesktop: "\u00A9"
|
||||
readonly property string wizardsGeneric: "\u00AA"
|
||||
readonly property string wizardsMcuEmpty: "\u00AB"
|
||||
readonly property string wizardsMcuGraph: "\u00AC"
|
||||
readonly property string wizardsMobile: "\u00AD"
|
||||
readonly property string wizardsUnknown: "\u00AE"
|
||||
readonly property string zoomAll: "\u00AF"
|
||||
readonly property string zoomIn: "\u00B0"
|
||||
readonly property string zoomOut: "\u00B1"
|
||||
readonly property string zoomSelection: "\u00B2"
|
||||
|
||||
readonly property font iconFont: Qt.font({
|
||||
"family": controlIcons.name,
|
||||
|
2
src/libs/3rdparty/cplusplus/Lexer.cpp
vendored
@@ -1034,7 +1034,7 @@ void Lexer::scanPreprocessorNumber(Token *tok, bool dotAlreadySkipped)
|
||||
yyinp();
|
||||
if (_yychar == '+' || _yychar == '-')
|
||||
yyinp();
|
||||
} else if (std::isalnum(_yychar) || _yychar == '_' || _yychar == '.') {
|
||||
} else if (std::isalnum(_yychar) || (_yychar == '\'') || _yychar == '_' || _yychar == '.') {
|
||||
yyinp();
|
||||
} else {
|
||||
scanOptionalUserDefinedLiteral(tok);
|
||||
|
@@ -910,7 +910,7 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
if (Symbol *declaration = templateTy->declaration()) {
|
||||
if (Function *funTy = declaration->asFunction()) {
|
||||
if (maybeValidPrototype(funTy, actualArgumentCount))
|
||||
addResult(funTy->returnType().simplified(), _scope);
|
||||
addResult(funTy->returnType().simplified(), scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -136,6 +136,7 @@ static Utils::optional<Tool> unzipTool(const FilePath &src, const FilePath &dest
|
||||
const QString destStr = dest.toString();
|
||||
const QString args = result.command.arguments().replace("%{src}", srcStr).replace("%{dest}", destStr);
|
||||
result.command.setArguments(args);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
@@ -41,7 +41,7 @@ namespace Internal {
|
||||
|
||||
bool currentAppearanceMatches(bool dark)
|
||||
{
|
||||
#if __has_builtin(__builtin_available)
|
||||
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
|
||||
if (__builtin_available(macOS 10.14, *)) {
|
||||
auto appearance = [NSApp.effectiveAppearance
|
||||
bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
|
||||
|
@@ -57,7 +57,6 @@ add_subdirectory(scxmleditor)
|
||||
add_subdirectory(subversion)
|
||||
add_subdirectory(compilationdatabaseprojectmanager)
|
||||
add_subdirectory(languageclient)
|
||||
add_subdirectory(studiowelcome)
|
||||
|
||||
# Level 6:
|
||||
add_subdirectory(cmakeprojectmanager)
|
||||
@@ -93,6 +92,7 @@ if (WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(qmldesigner_builddir ${PROJECT_BINARY_DIR}/qmldsgnr)
|
||||
endif()
|
||||
add_subdirectory(qmldesigner ${qmldesigner_builddir})
|
||||
add_subdirectory(studiowelcome)
|
||||
add_subdirectory(qnx)
|
||||
add_subdirectory(webassembly)
|
||||
add_subdirectory(mcusupport)
|
||||
|
@@ -562,6 +562,16 @@ FilePath AndroidConfig::gdbPathFromNdk(const Abi &abi, const FilePath &ndkLocati
|
||||
QString(QTC_HOST_EXE_SUFFIX)));
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::lldbPathFromNdk(const FilePath &ndkLocation) const
|
||||
{
|
||||
const FilePath path = ndkLocation.pathAppended(
|
||||
QString("toolchains/llvm/prebuilt/%1/bin/lldb%2").arg(toolchainHostFromNdk(ndkLocation),
|
||||
QString(QTC_HOST_EXE_SUFFIX)));
|
||||
if (path.exists())
|
||||
return path;
|
||||
return {};
|
||||
}
|
||||
|
||||
FilePath AndroidConfig::makePathFromNdk(const FilePath &ndkLocation) const
|
||||
{
|
||||
return ndkLocation.pathAppended(
|
||||
@@ -1240,39 +1250,79 @@ static QString getMultiOrSingleAbiString(const QStringList &abis)
|
||||
return containsAllAbis(abis) ? "Multi-Abi" : abis.join(",");
|
||||
}
|
||||
|
||||
static const Debugger::DebuggerItem *existingDebugger(const FilePath &command,
|
||||
Debugger::DebuggerEngineType type)
|
||||
{
|
||||
// check if the debugger is already registered, but ignoring the display name
|
||||
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command);
|
||||
|
||||
// Return existing debugger with same command
|
||||
if (existing && existing->engineType() == type && existing->isAutoDetected())
|
||||
return existing;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static QVariant findOrRegisterDebugger(ToolChain *tc,
|
||||
const QStringList &abisList,
|
||||
bool customDebugger = false)
|
||||
{
|
||||
const auto ¤tConfig = AndroidConfigurations::currentConfig();
|
||||
const FilePath ndk = static_cast<AndroidToolChain *>(tc)->ndkLocation();
|
||||
const FilePath command = currentConfig.gdbPathFromNdk(tc->targetAbi(), ndk);
|
||||
const FilePath lldbCommand = currentConfig.lldbPathFromNdk(ndk);
|
||||
const Debugger::DebuggerItem *existingLldb = existingDebugger(lldbCommand,
|
||||
Debugger::LldbEngineType);
|
||||
// Return existing debugger with same command - prefer lldb (limit to sdk/ndk min version?)
|
||||
if (existingLldb)
|
||||
return existingLldb->id();
|
||||
|
||||
const FilePath gdbCommand = currentConfig.gdbPathFromNdk(tc->targetAbi(), ndk);
|
||||
|
||||
// check if the debugger is already registered, but ignoring the display name
|
||||
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command);
|
||||
|
||||
const Debugger::DebuggerItem *existingGdb = existingDebugger(gdbCommand,
|
||||
Debugger::GdbEngineType);
|
||||
// Return existing debugger with same command
|
||||
if (existing && existing->engineType() == Debugger::GdbEngineType
|
||||
&& existing->isAutoDetected()) {
|
||||
return existing->id();
|
||||
if (existingGdb)
|
||||
return existingGdb->id();
|
||||
|
||||
const QString mainName = AndroidConfigurations::tr("Android Debugger (%1, NDK %2)");
|
||||
const QString custom = customDebugger ? QString{"Custom "} : QString{};
|
||||
// debugger not found, register a new one
|
||||
// check lldb
|
||||
QVariant registeredLldb;
|
||||
if (!lldbCommand.isEmpty()) {
|
||||
Debugger::DebuggerItem debugger;
|
||||
debugger.setCommand(lldbCommand);
|
||||
debugger.setEngineType(Debugger::LldbEngineType);
|
||||
debugger.setUnexpandedDisplayName(custom + mainName
|
||||
.arg(getMultiOrSingleAbiString(allSupportedAbis()))
|
||||
.arg(AndroidConfigurations::currentConfig().ndkVersion(ndk).toString())
|
||||
+ ' ' + debugger.engineTypeName());
|
||||
debugger.setAutoDetected(true);
|
||||
debugger.reinitializeFromFile();
|
||||
registeredLldb = Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||
}
|
||||
|
||||
// we always have a value for gdb (but we shouldn't - we currently use a fallback)
|
||||
if (!gdbCommand.exists()) {
|
||||
if (!registeredLldb.isNull())
|
||||
return registeredLldb;
|
||||
return {};
|
||||
}
|
||||
|
||||
// debugger not found, register a new one
|
||||
Debugger::DebuggerItem debugger;
|
||||
debugger.setCommand(command);
|
||||
debugger.setCommand(gdbCommand);
|
||||
debugger.setEngineType(Debugger::GdbEngineType);
|
||||
|
||||
// NDK 10 and older have multiple gdb versions per ABI, so check for that.
|
||||
const bool oldNdkVersion = currentConfig.ndkVersion(ndk) <= QVersionNumber{11};
|
||||
QString mainName = AndroidConfigurations::tr("Android Debugger (%1, NDK %2)");
|
||||
if (customDebugger)
|
||||
mainName.prepend("Custom ");
|
||||
debugger.setUnexpandedDisplayName(mainName
|
||||
debugger.setUnexpandedDisplayName(custom + mainName
|
||||
.arg(getMultiOrSingleAbiString(oldNdkVersion ? abisList : allSupportedAbis()))
|
||||
.arg(AndroidConfigurations::currentConfig().ndkVersion(ndk).toString()));
|
||||
.arg(AndroidConfigurations::currentConfig().ndkVersion(ndk).toString())
|
||||
+ ' ' + debugger.engineTypeName());
|
||||
debugger.setAutoDetected(true);
|
||||
debugger.reinitializeFromFile();
|
||||
return Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||
QVariant registeredGdb = Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||
return registeredLldb.isNull() ? registeredGdb : registeredLldb;
|
||||
}
|
||||
|
||||
void AndroidConfigurations::registerCustomToolChainsAndDebuggers()
|
||||
|
@@ -140,6 +140,7 @@ public:
|
||||
|
||||
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::BaseQtVersion *qtVersion) const;
|
||||
Utils::FilePath gdbPathFromNdk(const ProjectExplorer::Abi &abi, const Utils::FilePath &ndkLocation) const;
|
||||
Utils::FilePath lldbPathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||
Utils::FilePath makePathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||
|
||||
Utils::FilePath keytoolPath() const;
|
||||
|
@@ -428,7 +428,7 @@ void AndroidDeviceManager::updateDevicesList()
|
||||
void AndroidDeviceManager::updateDevicesListOnce()
|
||||
{
|
||||
if (!m_avdsFutureWatcher.isRunning() && m_androidConfig.adbToolPath().exists()) {
|
||||
m_avdsFutureWatcher.setFuture((new AndroidAvdManager)->avdList());
|
||||
m_avdsFutureWatcher.setFuture(m_avdManager.avdList());
|
||||
m_devicesFutureWatcher.setFuture(Utils::runAsync([this]() {
|
||||
return m_androidConfig.connectedDevices();
|
||||
}));
|
||||
|
@@ -246,11 +246,6 @@ bool AndroidManager::isQtCreatorGenerated(const FilePath &deploymentFile)
|
||||
return QJsonDocument::fromJson(f.readAll()).object()["_description"].toString() == qtcSignature;
|
||||
}
|
||||
|
||||
FilePath AndroidManager::dirPath(const Target *target)
|
||||
{
|
||||
return androidBuildDirectory(target);
|
||||
}
|
||||
|
||||
FilePath AndroidManager::androidBuildDirectory(const Target *target)
|
||||
{
|
||||
return buildDirectory(target) / Constants::ANDROID_BUILD_DIRECTORY;
|
||||
|
@@ -95,8 +95,6 @@ public:
|
||||
|
||||
static bool isQt5CmakeProject(const ProjectExplorer::Target *target);
|
||||
|
||||
// TODO: remove this on 6.0 branch, kept here for binary compatibility for 5.0 release.
|
||||
static Utils::FilePath dirPath(const ProjectExplorer::Target *target);
|
||||
static Utils::FilePath androidBuildDirectory(const ProjectExplorer::Target *target);
|
||||
static Utils::FilePath buildDirectory(const ProjectExplorer::Target *target);
|
||||
static Utils::FilePath manifestPath(const ProjectExplorer::Target *target);
|
||||
|
@@ -166,7 +166,7 @@ void AndroidManifestEditorIconWidget::selectIcon()
|
||||
{
|
||||
FilePath file = FileUtils::getOpenFilePath(this, m_iconSelectionText,
|
||||
FileUtils::homePath(),
|
||||
tr("Images (*.png *.jpg *.webp *.svg)"));
|
||||
tr("Images (*.png *.jpg *.jpeg *.webp *.svg)"));
|
||||
if (file.isEmpty())
|
||||
return;
|
||||
setIconFromPath(file);
|
||||
|
@@ -62,7 +62,7 @@ const char splashscreenFileName[] = "logo";
|
||||
const char splashscreenPortraitFileName[] = "logo_port";
|
||||
const char splashscreenLandscapeFileName[] = "logo_land";
|
||||
const char imageSuffix[] = ".png";
|
||||
const QString fileDialogImageFiles = QString(QWidget::tr("Images (*.png *.jpg)"));
|
||||
const QString fileDialogImageFiles = QString(QWidget::tr("Images (*.png *.jpg *.jpeg)"));
|
||||
const QSize lowDpiImageSize{200, 320};
|
||||
const QSize mediumDpiImageSize{320, 480};
|
||||
const QSize highDpiImageSize{480, 800};
|
||||
@@ -608,8 +608,8 @@ void SplashScreenContainerWidget::checkSplashscreenImage(const QString &name)
|
||||
|
||||
for (const QString &path : paths) {
|
||||
const FilePath filePath = baseDir.pathAppended(path + name);
|
||||
if (filePath.stringAppended(".png").exists()
|
||||
|| filePath.stringAppended(".jpg").exists()) {
|
||||
if (filePath.stringAppended(".png").exists() || filePath.stringAppended(".jpg").exists()
|
||||
|| filePath.stringAppended(".jpeg").exists()) {
|
||||
setCurrentIndex(1);
|
||||
break;
|
||||
}
|
||||
|
@@ -189,7 +189,8 @@ void SplashScreenWidget::selectImage()
|
||||
{
|
||||
const FilePath file = FileUtils::getOpenFilePath(this, m_imageSelectionText,
|
||||
FileUtils::homePath(),
|
||||
QStringLiteral("%1 (*.png *.jpg)").arg(tr("Images")));
|
||||
QStringLiteral("%1 (*.png *.jpg *.jpeg)")
|
||||
.arg(tr("Images")));
|
||||
if (file.isEmpty())
|
||||
return;
|
||||
setImageFromPath(file, false);
|
||||
|
@@ -55,6 +55,7 @@ QStringList filterInterfering(const QStringList &provided, QStringList *omitted)
|
||||
"--gtest_stream_result_to=",
|
||||
"--gtest_break_on_failure",
|
||||
"--gtest_throw_on_failure",
|
||||
"--gtest_catch_exceptions=",
|
||||
"--gtest_print_time="
|
||||
};
|
||||
|
||||
@@ -100,6 +101,7 @@ QStringList GTestConfiguration::argumentsForTestRunner(QStringList *omitted) con
|
||||
if (isDebugRunMode()) {
|
||||
if (gSettings->breakOnFailure.value())
|
||||
arguments << "--gtest_break_on_failure";
|
||||
arguments << "--gtest_catch_exceptions=0";
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
@@ -61,3 +61,14 @@ extend_qtc_plugin(ClangCodeModel
|
||||
test/clangdtests.cpp test/clangdtests.h
|
||||
test/data/clangtestdata.qrc
|
||||
)
|
||||
|
||||
if(MINGW)
|
||||
set(big_obj_compile_option "-Wa,-mbig-obj")
|
||||
elseif(MSVC)
|
||||
set(big_obj_compile_option "/bigobj")
|
||||
endif()
|
||||
|
||||
extend_qtc_plugin(ClangCodeModel
|
||||
CONDITION DEFINED big_obj_compile_option
|
||||
PROPERTIES COMPILE_OPTIONS ${big_obj_compile_option}
|
||||
)
|
||||
|
@@ -252,6 +252,16 @@ public:
|
||||
QString theType = type();
|
||||
if (theType.endsWith("const"))
|
||||
theType.chop(5);
|
||||
|
||||
// We don't care about the "inner" type of templates.
|
||||
const int openAngleBracketPos = theType.indexOf('<');
|
||||
if (openAngleBracketPos != -1) {
|
||||
const int closingAngleBracketPos = theType.lastIndexOf('>');
|
||||
if (closingAngleBracketPos > openAngleBracketPos) {
|
||||
theType = theType.left(openAngleBracketPos)
|
||||
+ theType.mid(closingAngleBracketPos + 1);
|
||||
}
|
||||
}
|
||||
const int xrefCount = theType.count("&&");
|
||||
const int refCount = theType.count('&') - 2 * xrefCount;
|
||||
const int ptrRefCount = theType.count('*') + refCount;
|
||||
@@ -2443,6 +2453,8 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (it->kind() == "Lambda")
|
||||
return false;
|
||||
if (it->kind().endsWith("Cast") && it->hasConstType())
|
||||
return false;
|
||||
if (it->kind() == "Member" && it->arcanaContains("(")
|
||||
@@ -3140,6 +3152,18 @@ void ExtraHighlightingResultsCollector::insertResult(const HighlightingResult &r
|
||||
return;
|
||||
const auto it = std::lower_bound(m_results.begin(), m_results.end(), result, lessThan);
|
||||
if (it == m_results.end() || *it != result) {
|
||||
|
||||
// Prevent inserting expansions for function-like macros. For instance:
|
||||
// #define TEST() "blubb"
|
||||
// const char *s = TEST();
|
||||
// The macro name is always shorter than the expansion and starts at the same
|
||||
// location, so it should occur right before the insertion position.
|
||||
if (it > m_results.begin() && (it - 1)->line == result.line
|
||||
&& (it - 1)->column == result.column
|
||||
&& (it - 1)->textStyles.mainStyle == C_PREPROCESSOR) {
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(clangdLogHighlight) << "adding additional highlighting result"
|
||||
<< result.line << result.column << result.length;
|
||||
m_results.insert(it, result);
|
||||
|
@@ -112,6 +112,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
||||
m_instance = this;
|
||||
|
||||
watchForExternalChanges();
|
||||
watchForInternalChanges();
|
||||
cppModelManager()->setCurrentDocumentFilter(std::make_unique<ClangdCurrentDocumentFilter>());
|
||||
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
|
||||
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());
|
||||
@@ -488,6 +489,29 @@ void ClangModelManagerSupport::watchForExternalChanges()
|
||||
});
|
||||
}
|
||||
|
||||
void ClangModelManagerSupport::watchForInternalChanges()
|
||||
{
|
||||
connect(Core::DocumentManager::instance(), &Core::DocumentManager::filesChangedInternally,
|
||||
this, [this](const Utils::FilePaths &filePaths) {
|
||||
for (const Utils::FilePath &fp : filePaths) {
|
||||
ClangdClient * const client = clientForFile(fp);
|
||||
if (!client || client->documentForFilePath(fp))
|
||||
continue;
|
||||
client->openExtraFile(fp);
|
||||
|
||||
// We need to give clangd some time to start re-parsing the file.
|
||||
// Closing right away does not work, and neither does doing it queued.
|
||||
// If it turns out that this delay is not always enough, we'll need to come up
|
||||
// with something more clever.
|
||||
// Ideally, clangd would implement workspace/didChangeWatchedFiles; let's keep
|
||||
// any eye on that.
|
||||
QTimer::singleShot(5000, client, [client, fp] {
|
||||
if (!client->documentForFilePath(fp))
|
||||
client->closeExtraFile(fp); });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
|
||||
{
|
||||
QTC_ASSERT(editor, return);
|
||||
|
@@ -135,8 +135,8 @@ private:
|
||||
ClangdClient *createClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir);
|
||||
void claimNonProjectSources(ClangdClient *fallbackClient);
|
||||
void watchForExternalChanges();
|
||||
void watchForInternalChanges();
|
||||
|
||||
private:
|
||||
UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
|
||||
BackendCommunicator m_communicator;
|
||||
ClangCompletionAssistProvider m_completionAssistProvider;
|
||||
|
@@ -1249,6 +1249,9 @@ void ClangdTestHighlighting::test_data()
|
||||
QTest::newRow("const argument to unnamed lambda") << 830 << 16 << 830 << 19
|
||||
<< QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("simple assignment") << 835 << 5 << 835 << 6 << QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("simple return") << 841 << 12 << 841 << 15 << QList<int>{C_LOCAL} << 0;
|
||||
QTest::newRow("lambda parameter") << 847 << 49 << 847 << 52
|
||||
<< QList<int>{C_PARAMETER, C_DECLARATION} << 0;
|
||||
}
|
||||
|
||||
void ClangdTestHighlighting::test()
|
||||
|
@@ -834,3 +834,15 @@ void assignmentTest() {
|
||||
struct S {} s;
|
||||
s = {};
|
||||
}
|
||||
|
||||
using FooPtrVector = std::vector<Foo *>;
|
||||
FooPtrVector returnTest() {
|
||||
FooPtrVector foo;
|
||||
return foo;
|
||||
}
|
||||
|
||||
template <typename Container, typename Func> inline void useContainer(const Container &, Func) {}
|
||||
void testConstRefAutoLambdaArgs()
|
||||
{
|
||||
useContainer(FooPtrVector(), [](const auto &arg) {});
|
||||
}
|
||||
|
@@ -421,10 +421,13 @@ QTextCursor BaseTextFind::findOne(const QRegularExpression &expr,
|
||||
QTextCursor found = document()->find(expr, from, options);
|
||||
while (!found.isNull() && !inScope(found)) {
|
||||
if (!found.hasSelection()) {
|
||||
from = found;
|
||||
found.movePosition(options & QTextDocument::FindBackward
|
||||
? QTextCursor::PreviousCharacter
|
||||
: QTextCursor::NextCharacter);
|
||||
if (found.movePosition(options & QTextDocument::FindBackward
|
||||
? QTextCursor::PreviousCharacter
|
||||
: QTextCursor::NextCharacter)) {
|
||||
from = found;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
from.setPosition(options & QTextDocument::FindBackward ? found.selectionStart()
|
||||
: found.selectionEnd());
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
@@ -165,9 +166,13 @@ namespace Core {
|
||||
// The Core Singleton
|
||||
static ICore *m_instance = nullptr;
|
||||
static MainWindow *m_mainwindow = nullptr;
|
||||
std::function<NewDialog *(QWidget *)> ICore::m_newDialogFactory = [](QWidget *parent) {
|
||||
|
||||
static NewDialog *defaultDialogFactory(QWidget *parent)
|
||||
{
|
||||
return new NewDialogWidget(parent);
|
||||
};
|
||||
}
|
||||
|
||||
static std::function<NewDialog *(QWidget *)> m_newDialogFactory = defaultDialogFactory;
|
||||
|
||||
/*!
|
||||
Returns the pointer to the instance. Only use for connecting to signals.
|
||||
@@ -253,7 +258,23 @@ void ICore::showNewItemDialog(const QString &title,
|
||||
const QVariantMap &extraVariables)
|
||||
{
|
||||
QTC_ASSERT(!isNewItemDialogRunning(), return);
|
||||
NewDialog *newDialog = ICore::m_newDialogFactory(dialogParent());
|
||||
|
||||
/* This is a workaround for QDS: In QDS, we currently have a "New Project" dialog box but we do
|
||||
* not also have a "New file" dialog box (yet). Therefore, when requested to add a new file, we
|
||||
* need to use QtCreator's dialog box. In QDS, if `factories` contains project wizard factories
|
||||
* (even though it may contain file wizard factories as well), then we consider it to be a
|
||||
* request for "New Project". Otherwise, if we only have file wizard factories, we defer to
|
||||
* QtCreator's dialog and request "New File"
|
||||
*/
|
||||
auto dialogFactory = m_newDialogFactory;
|
||||
bool haveProjectWizards = Utils::anyOf(factories, [](IWizardFactory *f) {
|
||||
return f->kind() == IWizardFactory::ProjectWizard;
|
||||
});
|
||||
|
||||
if (!haveProjectWizards)
|
||||
dialogFactory = defaultDialogFactory;
|
||||
|
||||
NewDialog *newDialog = dialogFactory(dialogParent());
|
||||
connect(newDialog->widget(), &QObject::destroyed, m_instance, &ICore::updateNewItemDialogState);
|
||||
newDialog->setWizardFactories(factories, defaultLocation, extraVariables);
|
||||
newDialog->setWindowTitle(title);
|
||||
|
@@ -180,8 +180,6 @@ public:
|
||||
|
||||
private:
|
||||
static void updateNewItemDialogState();
|
||||
|
||||
static std::function<NewDialog *(QWidget *)> m_newDialogFactory;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
@@ -291,9 +291,10 @@ Wizard *IWizardFactory::runWizard(const FilePath &path, QWidget *parent, Id plat
|
||||
s_reopenData.reopen();
|
||||
});
|
||||
s_inspectWizardAction->setEnabled(true);
|
||||
if (showWizard)
|
||||
if (showWizard) {
|
||||
wizard->show();
|
||||
Core::ICore::registerWindow(wizard, Core::Context("Core.NewWizard"));
|
||||
Core::ICore::registerWindow(wizard, Core::Context("Core.NewWizard"));
|
||||
}
|
||||
} else {
|
||||
s_isWizardRunning = false;
|
||||
ICore::updateNewItemDialogState();
|
||||
|
@@ -92,6 +92,7 @@
|
||||
#include <QStyleFactory>
|
||||
#include <QToolButton>
|
||||
#include <QUrl>
|
||||
#include <QWindow>
|
||||
|
||||
using namespace ExtensionSystem;
|
||||
using namespace Utils;
|
||||
@@ -101,6 +102,14 @@ namespace Internal {
|
||||
|
||||
enum { debugMainWindow = 0 };
|
||||
|
||||
static bool isQtDesignStudio()
|
||||
{
|
||||
QSettings *settings = Core::ICore::settings();
|
||||
const QString qdsStandaloneEntry = "QML/Designer/StandAloneMode"; //entry from qml settings
|
||||
|
||||
return settings->value(qdsStandaloneEntry, false).toBool();
|
||||
}
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: AppMainWindow()
|
||||
, m_coreImpl(new ICore(this))
|
||||
@@ -518,7 +527,8 @@ void MainWindow::registerDefaultActions()
|
||||
|
||||
// New File Action
|
||||
QIcon icon = QIcon::fromTheme(QLatin1String("document-new"), Utils::Icons::NEWFILE.icon());
|
||||
m_newAction = new QAction(icon, tr("&New File or Project..."), this);
|
||||
QString newActionText = isQtDesignStudio() ? tr("&New Project...") : tr("&New File or Project...");
|
||||
m_newAction = new QAction(icon, newActionText, this);
|
||||
cmd = ActionManager::registerAction(m_newAction, Constants::NEW);
|
||||
cmd->setDefaultKeySequence(QKeySequence::New);
|
||||
mfile->addAction(cmd, Constants::G_FILE_NEW);
|
||||
@@ -939,6 +949,20 @@ void MainWindow::setFocusToEditor()
|
||||
EditorManagerPrivate::doEscapeKeyFocusMoveMagic();
|
||||
}
|
||||
|
||||
static void acceptModalDialogs()
|
||||
{
|
||||
const QWidgetList topLevels = QApplication::topLevelWidgets();
|
||||
QList<QDialog *> dialogsToClose;
|
||||
for (QWidget *topLevel : topLevels) {
|
||||
if (auto dialog = qobject_cast<QDialog *>(topLevel)) {
|
||||
if (dialog->isModal())
|
||||
dialogsToClose.append(dialog);
|
||||
}
|
||||
}
|
||||
for (QDialog *dialog : dialogsToClose)
|
||||
dialog->accept();
|
||||
}
|
||||
|
||||
void MainWindow::exit()
|
||||
{
|
||||
// this function is most likely called from a user action
|
||||
@@ -946,7 +970,15 @@ void MainWindow::exit()
|
||||
// since on close we are going to delete everything
|
||||
// so to prevent the deleting of that object we
|
||||
// just append it
|
||||
QMetaObject::invokeMethod(this, &QWidget::close, Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this] {
|
||||
// Modal dialogs block the close event. So close them, in case this was triggered from
|
||||
// a RestartDialog in the settings dialog.
|
||||
acceptModalDialogs();
|
||||
close();
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::openFileWith()
|
||||
|
@@ -36,6 +36,9 @@
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QHash>
|
||||
#include <QPair>
|
||||
#include <QSettings>
|
||||
|
||||
using namespace Utils;
|
||||
@@ -356,11 +359,12 @@ static QVersionNumber getClangdVersion(const FilePath &clangdFilePath)
|
||||
|
||||
QVersionNumber ClangdSettings::clangdVersion(const FilePath &clangdFilePath)
|
||||
{
|
||||
static QHash<Utils::FilePath, QPair<QDateTime, QVersionNumber>> versionCache;
|
||||
const QDateTime timeStamp = clangdFilePath.lastModified();
|
||||
const auto it = m_versionCache.find(clangdFilePath);
|
||||
if (it == m_versionCache.end()) {
|
||||
const auto it = versionCache.find(clangdFilePath);
|
||||
if (it == versionCache.end()) {
|
||||
const QVersionNumber version = getClangdVersion(clangdFilePath);
|
||||
m_versionCache.insert(clangdFilePath, qMakePair(timeStamp, version));
|
||||
versionCache.insert(clangdFilePath, qMakePair(timeStamp, version));
|
||||
return version;
|
||||
}
|
||||
if (it->first != timeStamp) {
|
||||
|
@@ -29,10 +29,7 @@
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QStringList>
|
||||
#include <QVersionNumber>
|
||||
|
||||
@@ -150,7 +147,6 @@ private:
|
||||
void saveSettings();
|
||||
|
||||
Data m_data;
|
||||
static inline QHash<Utils::FilePath, QPair<QDateTime, QVersionNumber>> m_versionCache;
|
||||
};
|
||||
|
||||
inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
|
||||
|
@@ -213,6 +213,7 @@ QuickFixOperationTest::QuickFixOperationTest(const QList<TestDocumentPtr> &testD
|
||||
QuickFixOperations operations;
|
||||
factory->match(quickFixInterface, operations);
|
||||
if (operations.isEmpty()) {
|
||||
QEXPECT_FAIL("CompleteSwitchCaseStatement_QTCREATORBUG-25998", "FIXME", Abort);
|
||||
QVERIFY(testDocuments.first()->m_expectedSource.isEmpty());
|
||||
return;
|
||||
}
|
||||
|
@@ -148,6 +148,7 @@ void SemanticHighlighter::run()
|
||||
connectWatcher();
|
||||
|
||||
m_revision = documentRevision();
|
||||
qCDebug(log) << "starting runner for document revision" << m_revision;
|
||||
m_watcher->setFuture(m_highlightingRunner());
|
||||
}
|
||||
|
||||
@@ -160,12 +161,17 @@ static Parentheses getClearedParentheses(const QTextBlock &block)
|
||||
|
||||
void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
|
||||
{
|
||||
if (documentRevision() != m_revision)
|
||||
return; // outdated
|
||||
if (!m_watcher || m_watcher->isCanceled())
|
||||
return; // aborted
|
||||
|
||||
qCDebug(log) << "onHighlighterResultAvailable()" << from << to;
|
||||
if (documentRevision() != m_revision) {
|
||||
qCDebug(log) << "ignoring results: revision changed from" << m_revision << "to"
|
||||
<< documentRevision();
|
||||
return;
|
||||
}
|
||||
if (!m_watcher || m_watcher->isCanceled()) {
|
||||
qCDebug(log) << "ignoring results: future was canceled";
|
||||
return;
|
||||
}
|
||||
|
||||
QElapsedTimer t;
|
||||
t.start();
|
||||
|
||||
|
@@ -2832,8 +2832,10 @@ void CdbEngine::setupScripting(const DebuggerResponse &response)
|
||||
runCommand({command, ScriptCommand});
|
||||
}
|
||||
|
||||
const QString qtVersion = QString::number(runParameters().fallbackQtVersion, 16);
|
||||
runCommand({"theDumper.setFallbackQtVersion(0x" + qtVersion + ")", ScriptCommand});
|
||||
DebuggerCommand cmd0("theDumper.setFallbackQtVersion", ScriptCommand);
|
||||
cmd0.arg("version", runParameters().fallbackQtVersion);
|
||||
runCommand(cmd0);
|
||||
|
||||
runCommand({"theDumper.loadDumpers(None)", ScriptCommand,
|
||||
[this](const DebuggerResponse &response) {
|
||||
watchHandler()->addDumpers(response.data["result"]["dumpers"]);
|
||||
|
@@ -931,22 +931,27 @@ void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
|
||||
|
||||
void DebuggerEngine::updateLocalsWindow(bool showReturn)
|
||||
{
|
||||
QTC_ASSERT(d->m_returnWindow, return);
|
||||
QTC_ASSERT(d->m_localsView, return);
|
||||
d->m_returnWindow->setVisible(showReturn);
|
||||
d->m_localsView->resizeColumns();
|
||||
}
|
||||
|
||||
bool DebuggerEngine::isRegistersWindowVisible() const
|
||||
{
|
||||
QTC_ASSERT(d->m_registerWindow, return false);
|
||||
return d->m_registerWindow->isVisible();
|
||||
}
|
||||
|
||||
bool DebuggerEngine::isPeripheralRegistersWindowVisible() const
|
||||
{
|
||||
QTC_ASSERT(d->m_peripheralRegisterWindow, return false);
|
||||
return d->m_peripheralRegisterWindow->isVisible();
|
||||
}
|
||||
|
||||
bool DebuggerEngine::isModulesWindowVisible() const
|
||||
{
|
||||
QTC_ASSERT(d->m_modulesWindow, return false);
|
||||
return d->m_modulesWindow->isVisible();
|
||||
}
|
||||
|
||||
|
@@ -165,9 +165,12 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
|
||||
return;
|
||||
}
|
||||
|
||||
Environment env = sysEnv.size() == 0 ? Environment::systemEnvironment() : sysEnv;
|
||||
// Prevent calling lldb on Windows because the lldb from the llvm package is linked against
|
||||
// python but does not contain a python dll.
|
||||
if (HostOsInfo::isWindowsHost() && m_command.fileName().startsWith("lldb")) {
|
||||
const bool isAndroidNdkLldb = DebuggerItem::addAndroidLldbPythonEnv(m_command, env);
|
||||
if (HostOsInfo::isWindowsHost() && m_command.fileName().startsWith("lldb")
|
||||
&& !isAndroidNdkLldb) {
|
||||
QString errorMessage;
|
||||
m_version = winGetDLLVersion(WinDLLFileVersion,
|
||||
m_command.absoluteFilePath().path(),
|
||||
@@ -178,7 +181,7 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
|
||||
}
|
||||
|
||||
QtcProcess proc;
|
||||
proc.setEnvironment(sysEnv);
|
||||
proc.setEnvironment(env);
|
||||
proc.setCommand({m_command, {version}});
|
||||
proc.runBlocking();
|
||||
const QString output = proc.allOutput().trimmed();
|
||||
@@ -262,6 +265,22 @@ void DebuggerItem::reinitializeFromFile(const Environment &sysEnv, QString *erro
|
||||
m_engineType = NoEngineType;
|
||||
}
|
||||
|
||||
bool DebuggerItem::addAndroidLldbPythonEnv(const Utils::FilePath &lldbCmd, Utils::Environment &env)
|
||||
{
|
||||
if (lldbCmd.baseName().contains("lldb") &&
|
||||
(lldbCmd.path().contains("/ndk/") || lldbCmd.path().contains("/ndk-bundle/"))) {
|
||||
const FilePath pythonDir = lldbCmd.parentDir().parentDir().pathAppended("python3");
|
||||
const FilePath pythonBinDir =
|
||||
HostOsInfo::isAnyUnixHost() ? pythonDir.pathAppended("bin") : pythonDir;
|
||||
if (pythonBinDir.exists()) {
|
||||
env.set("PYTHONHOME", pythonDir.toUserOutput());
|
||||
env.prependOrSetPath(pythonBinDir);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString DebuggerItem::engineTypeName() const
|
||||
{
|
||||
switch (m_engineType) {
|
||||
|
@@ -107,6 +107,8 @@ public:
|
||||
QString detectionSource() const { return m_detectionSource; }
|
||||
void setDetectionSource(const QString &source) { m_detectionSource = source; }
|
||||
|
||||
static bool addAndroidLldbPythonEnv(const Utils::FilePath &lldbCmd, Utils::Environment &env);
|
||||
|
||||
private:
|
||||
DebuggerItem(const QVariant &id);
|
||||
void initMacroExpander();
|
||||
|
@@ -4011,7 +4011,10 @@ void GdbEngine::setupEngine()
|
||||
if (!commands.isEmpty())
|
||||
runCommand({commands});
|
||||
|
||||
runCommand({"setFallbackQtVersion(0x" + QString::number(rp.fallbackQtVersion, 16) + ")"});
|
||||
DebuggerCommand cmd1("setFallbackQtVersion");
|
||||
cmd1.arg("version", rp.fallbackQtVersion);
|
||||
runCommand(cmd1);
|
||||
|
||||
runCommand({"loadDumpers", CB(handlePythonSetup)});
|
||||
|
||||
// Reload peripheral register description.
|
||||
|
@@ -213,12 +213,7 @@ void LldbEngine::setupEngine()
|
||||
showMessage("STARTING LLDB: " + lldbCmd.toUserOutput());
|
||||
Environment environment = runParameters().debugger.environment;
|
||||
environment.appendOrSet("PYTHONUNBUFFERED", "1"); // avoid flushing problem on macOS
|
||||
if (lldbCmd.path().contains("/ndk-bundle/")) {
|
||||
FilePath androidPythonDir = lldbCmd.parentDir().parentDir().pathAppended("python3");
|
||||
if (HostOsInfo::isAnyUnixHost())
|
||||
androidPythonDir = androidPythonDir.pathAppended("bin");
|
||||
environment.prependOrSetPath(androidPythonDir);
|
||||
}
|
||||
DebuggerItem::addAndroidLldbPythonEnv(lldbCmd, environment);
|
||||
m_lldbProc.setEnvironment(environment);
|
||||
|
||||
if (runParameters().debugger.workingDirectory.isDir())
|
||||
@@ -269,10 +264,6 @@ void LldbEngine::setupEngine()
|
||||
runCommand(cmd);
|
||||
}
|
||||
|
||||
DebuggerCommand cmd0("setFallbackQtVersion");
|
||||
cmd0.arg("version", "0x" + QString::number(rp.fallbackQtVersion, 16));
|
||||
runCommand(cmd0);
|
||||
|
||||
DebuggerCommand cmd1("loadDumpers");
|
||||
cmd1.callback = [this](const DebuggerResponse &response) {
|
||||
watchHandler()->addDumpers(response.data["dumpers"]);
|
||||
@@ -348,6 +339,10 @@ void LldbEngine::setupEngine()
|
||||
|
||||
cmd2.flags = Silent;
|
||||
runCommand(cmd2);
|
||||
|
||||
DebuggerCommand cmd0("setFallbackQtVersion");
|
||||
cmd0.arg("version", rp.fallbackQtVersion);
|
||||
runCommand(cmd0);
|
||||
}
|
||||
|
||||
void LldbEngine::runEngine()
|
||||
|
@@ -48,7 +48,11 @@ bool isIntType(const QString &type)
|
||||
case 'b':
|
||||
return type == "bool";
|
||||
case 'c':
|
||||
return type == "char";
|
||||
return type.startsWith("char") &&
|
||||
( type == "char"
|
||||
|| type == "char8_t"
|
||||
|| type == "char16_t"
|
||||
|| type == "char32_t" );
|
||||
case 'i':
|
||||
return type.startsWith("int") &&
|
||||
( type == "int"
|
||||
@@ -63,7 +67,8 @@ bool isIntType(const QString &type)
|
||||
case 'p':
|
||||
return type == "ptrdiff_t";
|
||||
case 'q':
|
||||
return type == "qint16" || type == "quint16"
|
||||
return type == "qint8" || type == "quint8"
|
||||
|| type == "qint16" || type == "quint16"
|
||||
|| type == "qint32" || type == "quint32"
|
||||
|| type == "qint64" || type == "quint64"
|
||||
|| type == "qlonglong" || type == "qulonglong";
|
||||
|
@@ -717,22 +717,34 @@ static QString formattedValue(const WatchItem *item)
|
||||
|
||||
// Append quoted, printable character also for decimal.
|
||||
// FIXME: This is unreliable.
|
||||
if (item->type.endsWith("char") || item->type.endsWith("int8_t")) {
|
||||
const QString type = item->type;
|
||||
if (type == "char8_t" || type.endsWith("char") || type.endsWith("int8_t")) {
|
||||
bool ok;
|
||||
const int code = item->value.toInt(&ok);
|
||||
bool isUnsigned = item->type == "unsigned char" || item->type == "uchar" || item->type == "uint8_t";
|
||||
bool isUnsigned = type == "char8_t"
|
||||
|| type == "unsigned char"
|
||||
|| type == "uchar"
|
||||
|| type == "uint8_t";
|
||||
if (ok)
|
||||
return reformatCharacter(code, 1, !isUnsigned);
|
||||
} else if (item->type.endsWith("wchar_t")) {
|
||||
} else if (type == "qint8" || type == "quint8") {
|
||||
bool ok = false;
|
||||
const int code = item->value.toInt(&ok);
|
||||
bool isUnsigned = type == "quint8";
|
||||
if (ok)
|
||||
return reformatCharacter(code, 1, !isUnsigned);
|
||||
} else if (type == "char32_t" || type.endsWith("wchar_t")) {
|
||||
bool ok;
|
||||
const int code = item->value.toInt(&ok);
|
||||
bool isUnsigned = type == "char32_t";
|
||||
if (ok)
|
||||
return reformatCharacter(code, 4, false);
|
||||
} else if (item->type.endsWith("QChar")) {
|
||||
return reformatCharacter(code, 4, !isUnsigned);
|
||||
} else if (type == "char16_t" || type.endsWith("QChar")) {
|
||||
bool ok;
|
||||
const int code = item->value.toInt(&ok);
|
||||
bool isUnsigned = type == "char16_t";
|
||||
if (ok)
|
||||
return reformatCharacter(code, 2, false);
|
||||
return reformatCharacter(code, 2, !isUnsigned);
|
||||
}
|
||||
|
||||
if (format == HexadecimalIntegerFormat
|
||||
|
@@ -937,7 +937,6 @@ void Client::handleCodeActionResponse(const CodeActionRequest::Response &respons
|
||||
|
||||
void Client::executeCommand(const Command &command)
|
||||
{
|
||||
const QString method(ExecuteCommandRequest::methodName);
|
||||
bool serverSupportsExecuteCommand = m_serverCapabilities.executeCommandProvider().has_value();
|
||||
serverSupportsExecuteCommand = m_dynamicCapabilities
|
||||
.isRegistered(ExecuteCommandRequest::methodName)
|
||||
@@ -953,7 +952,18 @@ ProjectExplorer::Project *Client::project() const
|
||||
|
||||
void Client::setCurrentProject(ProjectExplorer::Project *project)
|
||||
{
|
||||
if (m_project == project)
|
||||
return;
|
||||
if (m_project)
|
||||
m_project->disconnect(this);
|
||||
m_project = project;
|
||||
if (m_project) {
|
||||
connect(m_project, &ProjectExplorer::Project::destroyed, this, [this]() {
|
||||
// the project of the client should already be null since we expect the session and
|
||||
// the language client manager to reset it before it gets deleted.
|
||||
QTC_ASSERT(m_project == nullptr, projectClosed(m_project));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Client::projectOpened(ProjectExplorer::Project *project)
|
||||
|
@@ -53,6 +53,8 @@ using namespace LanguageServerProtocol;
|
||||
|
||||
namespace LanguageClient {
|
||||
|
||||
static Q_LOGGING_CATEGORY(Log, "qtc.languageclient.manager", QtWarningMsg)
|
||||
|
||||
static LanguageClientManager *managerInstance = nullptr;
|
||||
|
||||
LanguageClientManager::LanguageClientManager(QObject *parent)
|
||||
@@ -111,6 +113,7 @@ void LanguageClient::LanguageClientManager::addClient(Client *client)
|
||||
if (managerInstance->m_clients.contains(client))
|
||||
return;
|
||||
|
||||
qCDebug(Log) << "add client: " << client->name() << client;
|
||||
managerInstance->m_clients << client;
|
||||
connect(client, &Client::finished, managerInstance, [client]() { clientFinished(client); });
|
||||
connect(client,
|
||||
@@ -130,6 +133,7 @@ void LanguageClient::LanguageClientManager::addClient(Client *client)
|
||||
|
||||
void LanguageClientManager::clientStarted(Client *client)
|
||||
{
|
||||
qCDebug(Log) << "client started: " << client->name() << client;
|
||||
QTC_ASSERT(managerInstance, return);
|
||||
QTC_ASSERT(client, return);
|
||||
if (managerInstance->m_shuttingDown)
|
||||
@@ -150,6 +154,7 @@ void LanguageClientManager::clientFinished(Client *client)
|
||||
const QList<TextEditor::TextDocument *> &clientDocs
|
||||
= managerInstance->m_clientForDocument.keys(client);
|
||||
if (client->reset()) {
|
||||
qCDebug(Log) << "restart unexpectedly finished client: " << client->name() << client;
|
||||
client->disconnect(managerInstance);
|
||||
client->log(
|
||||
tr("Unexpectedly finished. Restarting in %1 seconds.").arg(restartTimeoutS));
|
||||
@@ -158,6 +163,7 @@ void LanguageClientManager::clientFinished(Client *client)
|
||||
client->deactivateDocument(document);
|
||||
return;
|
||||
}
|
||||
qCDebug(Log) << "client finished unexpectedly: " << client->name() << client;
|
||||
client->log(tr("Unexpectedly finished."));
|
||||
for (TextEditor::TextDocument *document : clientDocs)
|
||||
managerInstance->m_clientForDocument.remove(document);
|
||||
@@ -174,6 +180,7 @@ Client *LanguageClientManager::startClient(BaseSettings *setting, ProjectExplore
|
||||
QTC_ASSERT(setting, return nullptr);
|
||||
QTC_ASSERT(setting->isValid(), return nullptr);
|
||||
Client *client = setting->createClient(project);
|
||||
qCDebug(Log) << "start client: " << client->name() << client;
|
||||
QTC_ASSERT(client, return nullptr);
|
||||
client->start();
|
||||
managerInstance->m_clientsForSetting[setting->m_id].append(client);
|
||||
@@ -206,6 +213,7 @@ void LanguageClientManager::shutdownClient(Client *client)
|
||||
{
|
||||
if (!client)
|
||||
return;
|
||||
qCDebug(Log) << "request client shutdown: " << client->name() << client;
|
||||
// reset the documents for that client already when requesting the shutdown so they can get
|
||||
// reassigned to another server right after this request to another server
|
||||
for (TextEditor::TextDocument *document : managerInstance->m_clientForDocument.keys(client))
|
||||
@@ -220,6 +228,7 @@ void LanguageClientManager::deleteClient(Client *client)
|
||||
{
|
||||
QTC_ASSERT(managerInstance, return);
|
||||
QTC_ASSERT(client, return);
|
||||
qCDebug(Log) << "delete client: " << client->name() << client;
|
||||
client->disconnect();
|
||||
managerInstance->m_clients.removeAll(client);
|
||||
for (QVector<Client *> &clients : managerInstance->m_clientsForSetting)
|
||||
@@ -237,6 +246,7 @@ void LanguageClientManager::shutdown()
|
||||
QTC_ASSERT(managerInstance, return);
|
||||
if (managerInstance->m_shuttingDown)
|
||||
return;
|
||||
qCDebug(Log) << "shutdown manager";
|
||||
managerInstance->m_shuttingDown = true;
|
||||
for (Client *client : qAsConst(managerInstance->m_clients))
|
||||
shutdownClient(client);
|
||||
@@ -412,6 +422,7 @@ void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *doc
|
||||
currentClient->deactivateDocument(document);
|
||||
managerInstance->m_clientForDocument[document] = client;
|
||||
if (client) {
|
||||
qCDebug(Log) << "open" << document->filePath() << "with" << client->name() << client;
|
||||
if (!client->documentOpen(document))
|
||||
client->openDocument(document);
|
||||
else
|
||||
|
@@ -25,12 +25,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../projectexplorer_export.h"
|
||||
#include <utils/projectintropage.h>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
// Documentation inside.
|
||||
class JsonProjectPage : public Utils::ProjectIntroPage
|
||||
class PROJECTEXPLORER_EXPORT JsonProjectPage : public Utils::ProjectIntroPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -603,7 +603,7 @@ double round(double value, int decimal_places) {
|
||||
}
|
||||
|
||||
static const std::initializer_list<QStringView> tagAllowList{
|
||||
u"path", u"rect", u"polygon", u"circle", u"ellipse"
|
||||
u"path", u"rect", u"line", u"polygon", u"polyline", u"circle", u"ellipse"
|
||||
};
|
||||
|
||||
// fillOpacity and strokeOpacity aren't actual QML properties, but get mapped anyways
|
||||
@@ -840,6 +840,8 @@ QVariant convertValue(const QByteArray &key, const QString &value)
|
||||
return value.toInt();
|
||||
} else if (key == "opacity") {
|
||||
return value.toFloat();
|
||||
} else if ((key == "fillColor" || key == "strokeColor") && value == "none") {
|
||||
return "transparent";
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -1015,6 +1017,28 @@ PropertyMap generateRectProperties(const QDomElement &e, const CSSRules &cssRule
|
||||
return properties;
|
||||
}
|
||||
|
||||
PropertyMap generateLineProperties(const QDomElement &e, const CSSRules &cssRules)
|
||||
{
|
||||
QLineF line(e.attribute("x1").toFloat(),
|
||||
e.attribute("y1").toFloat(),
|
||||
e.attribute("x2").toFloat(),
|
||||
e.attribute("y2").toFloat());
|
||||
|
||||
QPainterPath path(line.p1());
|
||||
path.lineTo(line.p2());
|
||||
|
||||
PropertyMap properties;
|
||||
QTransform transform;
|
||||
flattenTransformsAndStyles(e, cssRules, transform, properties);
|
||||
|
||||
path = transform.map(path);
|
||||
|
||||
if (!applyMinimumBoundingBox(path, properties))
|
||||
return {};
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
PropertyMap generateEllipseProperties(const QDomElement &e, const CSSRules &cssRules)
|
||||
{
|
||||
const QPointF center(e.attribute("cx").toFloat(), e.attribute("cy").toFloat());
|
||||
@@ -1085,7 +1109,7 @@ PropertyMap generatePolygonProperties(const QDomElement &e, const CSSRules &cssR
|
||||
for (int i = 0; i < pointList.length(); i += 2)
|
||||
polygon.push_back({pointList[i].toFloat(), pointList[i + 1].toFloat()});
|
||||
|
||||
if (!polygon.isClosed() && polygon.size())
|
||||
if (e.tagName() != "polyline" && !polygon.isClosed() && polygon.size())
|
||||
polygon.push_back(polygon.front());
|
||||
|
||||
QPainterPath path;
|
||||
@@ -1178,6 +1202,11 @@ QmlObjectNode SVGPasteAction::createQmlObjectNode(QmlDesigner::ModelNode &target
|
||||
round(tmp[2].toFloat(), 2),
|
||||
round(tmp[3].toFloat(), 2));
|
||||
}
|
||||
|
||||
viewBoxProperties.insert("clip", true);
|
||||
} else {
|
||||
viewBox.setWidth(round(rootElement.attribute("width").toFloat(), 2));
|
||||
viewBox.setHeight(round(rootElement.attribute("height").toFloat(), 2));
|
||||
}
|
||||
|
||||
viewBoxProperties.insert("x", viewBox.x());
|
||||
@@ -1202,8 +1231,6 @@ QmlObjectNode SVGPasteAction::createQmlObjectNode(QmlDesigner::ModelNode &target
|
||||
|
||||
depthFirstTraversal(node, processStyleAndCollectShapes);
|
||||
|
||||
viewBoxProperties.insert("clip", true);
|
||||
|
||||
ModelNode groupNode = createGroupNode(targetNode, viewBoxProperties);
|
||||
|
||||
for (const QDomElement &e : shapeElements) {
|
||||
@@ -1213,7 +1240,9 @@ QmlObjectNode SVGPasteAction::createQmlObjectNode(QmlDesigner::ModelNode &target
|
||||
pathProperties = generatePathProperties(e, cssRules);
|
||||
else if (e.tagName() == "rect")
|
||||
pathProperties = generateRectProperties(e, cssRules);
|
||||
else if (e.tagName() == "polygon")
|
||||
else if (e.tagName() == "line")
|
||||
pathProperties = generateLineProperties(e, cssRules);
|
||||
else if (e.tagName() == "polygon" || e.tagName() == "polyline")
|
||||
pathProperties = generatePolygonProperties(e, cssRules);
|
||||
else if (e.tagName() == "circle" || e.tagName() == "ellipse")
|
||||
pathProperties = generateEllipseProperties(e, cssRules);
|
||||
|
@@ -103,8 +103,10 @@ public:
|
||||
distributeSpacingHorizontal,
|
||||
distributeSpacingVertical,
|
||||
distributeTop,
|
||||
download,
|
||||
edit,
|
||||
eyeDropper,
|
||||
favorite,
|
||||
flowAction,
|
||||
flowTransition,
|
||||
fontStyleBold,
|
||||
@@ -155,6 +157,12 @@ public:
|
||||
textFullJustification,
|
||||
textNumberedList,
|
||||
tickIcon,
|
||||
translationCreateFiles,
|
||||
translationCreateReport,
|
||||
translationExport,
|
||||
translationImport,
|
||||
translationSelectLanguages,
|
||||
translationTest,
|
||||
transparent,
|
||||
triState,
|
||||
triangleArcA,
|
||||
|
@@ -63,7 +63,7 @@ static bool itemIsResizable(const QmlItemNode &qmlItemNode)
|
||||
&& qmlItemNode.instanceIsResizable()
|
||||
&& qmlItemNode.modelIsMovable()
|
||||
&& qmlItemNode.modelIsResizable()
|
||||
&& !qmlItemNode.instanceHasRotationTransform()
|
||||
&& !qmlItemNode.instanceHasScaleOrRotationTransform()
|
||||
&& !qmlItemNode.instanceIsInLayoutable();
|
||||
}
|
||||
|
||||
|
@@ -311,6 +311,7 @@ void DesignDocument::changeToDocumentModel()
|
||||
viewManager().detachViewsExceptRewriterAndComponetView();
|
||||
|
||||
m_inFileComponentModel.reset();
|
||||
m_inFileComponentTextModifier.reset();
|
||||
|
||||
viewManager().attachRewriterView();
|
||||
viewManager().attachViewsExceptRewriterAndComponetView();
|
||||
|
BIN
src/plugins/qmldesigner/components/itemlibrary/images/browse.png
Normal file
After Width: | Height: | Size: 494 B |
After Width: | Height: | Size: 871 B |
@@ -31,5 +31,7 @@
|
||||
<file>images/asset_sound_384.png</file>
|
||||
<file>images/x.png</file>
|
||||
<file>images/x@2x.png</file>
|
||||
<file>images/browse.png</file>
|
||||
<file>images/browse@2x.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -42,16 +42,18 @@ QPixmap ItemLibraryAssetsIconProvider::requestPixmap(const QString &id, QSize *s
|
||||
{
|
||||
QPixmap pixmap;
|
||||
const QString suffix = "*." + id.split('.').last().toLower();
|
||||
if (ItemLibraryAssetsModel::supportedFontSuffixes().contains(suffix))
|
||||
if (id == "browse")
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/browse.png");
|
||||
else if (ItemLibraryAssetsModel::supportedFontSuffixes().contains(suffix))
|
||||
pixmap = generateFontIcons(id);
|
||||
else if (ItemLibraryAssetsModel::supportedImageSuffixes().contains(suffix))
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(id);
|
||||
else if (ItemLibraryAssetsModel::supportedTexture3DSuffixes().contains(suffix))
|
||||
pixmap = HdrImage{id}.toPixmap();
|
||||
else if (ItemLibraryAssetsModel::supportedShaderSuffixes().contains(suffix))
|
||||
pixmap = QPixmap(Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/asset_shader_48.png"));
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/asset_shader_48.png");
|
||||
else if (ItemLibraryAssetsModel::supportedAudioSuffixes().contains(suffix))
|
||||
pixmap = QPixmap(Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/asset_sound_48.png"));
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/asset_sound_48.png");
|
||||
|
||||
if (size) {
|
||||
size->setWidth(pixmap.width());
|
||||
|
@@ -275,7 +275,8 @@ void ItemLibraryAssetsModel::setRootPath(const QString &path)
|
||||
|
||||
beginResetModel();
|
||||
m_assetsDir = new ItemLibraryAssetsDir(path, 0, true, this);
|
||||
parseDirRecursive(m_assetsDir, 1);
|
||||
bool noAssets = parseDirRecursive(m_assetsDir, 1);
|
||||
setIsEmpty(noAssets);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@@ -304,6 +305,19 @@ const QSet<QString> &ItemLibraryAssetsModel::supportedSuffixes() const
|
||||
return allSuffixes;
|
||||
}
|
||||
|
||||
bool ItemLibraryAssetsModel::isEmpty() const
|
||||
{
|
||||
return m_isEmpty;
|
||||
};
|
||||
|
||||
void ItemLibraryAssetsModel::setIsEmpty(bool empty)
|
||||
{
|
||||
if (m_isEmpty != empty) {
|
||||
m_isEmpty = empty;
|
||||
emit isEmptyChanged();
|
||||
}
|
||||
};
|
||||
|
||||
const QSet<QString> &ItemLibraryAssetsModel::previewableSuffixes() const
|
||||
{
|
||||
static QSet<QString> previewableSuffixes;
|
||||
|
@@ -46,13 +46,15 @@ class ItemLibraryAssetsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool isEmpty READ isEmpty WRITE setIsEmpty NOTIFY isEmptyChanged)
|
||||
|
||||
public:
|
||||
ItemLibraryAssetsModel(QmlDesigner::SynchronousImageCache &fontImageCache,
|
||||
Utils::FileSystemWatcher *fileSystemWatcher,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex & parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void refresh();
|
||||
@@ -82,15 +84,22 @@ public:
|
||||
Q_INVOKABLE DirExpandState getAllExpandedState() const;
|
||||
Q_INVOKABLE void removeFile(const QString &filePath);
|
||||
|
||||
signals:
|
||||
void isEmptyChanged();
|
||||
|
||||
private:
|
||||
const QSet<QString> &supportedSuffixes() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
void setIsEmpty(bool empty);
|
||||
|
||||
SynchronousImageCache &m_fontImageCache;
|
||||
QHash<QString, QPair<QDateTime, QIcon>> m_iconCache;
|
||||
|
||||
QString m_searchText;
|
||||
Utils::FileSystemWatcher *m_fileSystemWatcher = nullptr;
|
||||
ItemLibraryAssetsDir *m_assetsDir = nullptr;
|
||||
bool m_isEmpty = true;
|
||||
|
||||
QHash<int, QByteArray> m_roleNames;
|
||||
inline static QHash<QString, bool> m_expandedStateHash; // <assetPath, isExpanded>
|
||||
|
@@ -118,6 +118,8 @@ void ItemLibraryView::modelAttached(Model *model)
|
||||
m_widget->clearSearchFilter();
|
||||
m_widget->setModel(model);
|
||||
updateImports();
|
||||
if (model)
|
||||
m_widget->updatePossibleImports(model->possibleImports());
|
||||
m_hasErrors = !rewriterView()->errors().isEmpty();
|
||||
m_widget->setFlowMode(QmlItemNode(rootModelNode()).isFlowView());
|
||||
setResourcePath(DocumentManager::currentResourcePath().toFileInfo().absoluteFilePath());
|
||||
|
@@ -29,12 +29,12 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
// This dialog displays all given type properties of an object and allows the user to choose one
|
||||
ChooseFromPropertyListDialog::ChooseFromPropertyListDialog(const ModelNode &node, TypeName type, QWidget *parent)
|
||||
// This dialog displays specified properties and allows the user to choose one
|
||||
ChooseFromPropertyListDialog::ChooseFromPropertyListDialog(const QStringList &propNames,
|
||||
QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::ChooseFromPropertyListDialog)
|
||||
{
|
||||
m_propertyTypeName = type;
|
||||
m_ui->setupUi(this);
|
||||
setWindowTitle(tr("Select property"));
|
||||
m_ui->label->setText(tr("Bind to property:"));
|
||||
@@ -50,7 +50,7 @@ ChooseFromPropertyListDialog::ChooseFromPropertyListDialog(const ModelNode &node
|
||||
QDialog::accept();
|
||||
});
|
||||
|
||||
fillList(node);
|
||||
fillList(propNames);
|
||||
}
|
||||
|
||||
ChooseFromPropertyListDialog::~ChooseFromPropertyListDialog()
|
||||
@@ -63,31 +63,80 @@ TypeName ChooseFromPropertyListDialog::selectedProperty() const
|
||||
return m_selectedProperty;
|
||||
}
|
||||
|
||||
void ChooseFromPropertyListDialog::fillList(const ModelNode &node)
|
||||
// Create dialog for selecting any property matching newNode type
|
||||
// Subclass type matches are also valid
|
||||
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
|
||||
const ModelNode &targetNode, const ModelNode &newNode, QWidget *parent)
|
||||
{
|
||||
// Fill the list with all properties of given type
|
||||
const auto metaInfo = node.metaInfo();
|
||||
const auto propNames = metaInfo.propertyNames();
|
||||
const TypeName property(m_propertyTypeName);
|
||||
QStringList nameList;
|
||||
TypeName typeName = newNode.type();
|
||||
|
||||
// Component matches cases where you don't want to insert a plain component,
|
||||
// such as layer.effect. Also, default property is often a Component (typically 'delegate'),
|
||||
// and inserting into such property will silently overwrite implicit component, if any.
|
||||
if (typeName == "QtQml.Component")
|
||||
return nullptr;
|
||||
|
||||
const NodeMetaInfo metaInfo = targetNode.metaInfo();
|
||||
const PropertyNameList propNames = metaInfo.propertyNames();
|
||||
QStringList matchingNames;
|
||||
|
||||
// Common base types cause too many rarely valid matches, so they are ignored
|
||||
const QSet<TypeName> ignoredTypes {"<cpp>.QObject",
|
||||
"<cpp>.QQuickItem",
|
||||
"QtQuick.Item",
|
||||
"QtQuick3D.Object3D",
|
||||
"QtQuick3D.Node"};
|
||||
|
||||
for (const auto &propName : propNames) {
|
||||
if (metaInfo.propertyTypeName(propName) == property)
|
||||
nameList.append(QString::fromLatin1(propName));
|
||||
}
|
||||
|
||||
if (!nameList.isEmpty()) {
|
||||
QString defaultProp = nameList.first();
|
||||
|
||||
nameList.sort();
|
||||
for (const auto &propName : qAsConst(nameList)) {
|
||||
QListWidgetItem *newItem = new QListWidgetItem(propName);
|
||||
m_ui->listProps->addItem(newItem);
|
||||
const TypeName testType = metaInfo.propertyTypeName(propName);
|
||||
if (!ignoredTypes.contains(testType)
|
||||
&& metaInfo.propertyIsWritable(propName)
|
||||
&& (testType == typeName || newNode.isSubclassOf(testType))) {
|
||||
matchingNames.append(QString::fromLatin1(propName));
|
||||
}
|
||||
|
||||
// Select the default prop
|
||||
m_ui->listProps->setCurrentRow(nameList.indexOf(defaultProp));
|
||||
m_selectedProperty = defaultProp.toLatin1();
|
||||
}
|
||||
|
||||
if (!matchingNames.isEmpty())
|
||||
return new ChooseFromPropertyListDialog(matchingNames, parent);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create dialog for selecting writable properties of exact property type
|
||||
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
|
||||
const ModelNode &targetNode, TypeName type, QWidget *parent)
|
||||
{
|
||||
const NodeMetaInfo metaInfo = targetNode.metaInfo();
|
||||
const PropertyNameList propNames = metaInfo.propertyNames();
|
||||
const TypeName property(type);
|
||||
QStringList matchingNames;
|
||||
for (const auto &propName : propNames) {
|
||||
if (metaInfo.propertyTypeName(propName) == property && metaInfo.propertyIsWritable(propName))
|
||||
matchingNames.append(QString::fromLatin1(propName));
|
||||
}
|
||||
|
||||
if (!matchingNames.isEmpty())
|
||||
return new ChooseFromPropertyListDialog(matchingNames, parent);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ChooseFromPropertyListDialog::fillList(const QStringList &propNames)
|
||||
{
|
||||
if (propNames.isEmpty())
|
||||
return;
|
||||
|
||||
QString defaultProp = propNames.first();
|
||||
QStringList sortedNames = propNames;
|
||||
sortedNames.sort();
|
||||
for (const auto &propName : qAsConst(sortedNames)) {
|
||||
QListWidgetItem *newItem = new QListWidgetItem(propName);
|
||||
m_ui->listProps->addItem(newItem);
|
||||
}
|
||||
|
||||
// Select the default prop
|
||||
m_ui->listProps->setCurrentRow(sortedNames.indexOf(defaultProp));
|
||||
m_selectedProperty = defaultProp.toLatin1();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -40,16 +40,22 @@ class ChooseFromPropertyListDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ChooseFromPropertyListDialog(const ModelNode &node, TypeName type, QWidget *parent = 0);
|
||||
~ChooseFromPropertyListDialog();
|
||||
|
||||
TypeName selectedProperty() const;
|
||||
|
||||
static ChooseFromPropertyListDialog *createIfNeeded(const ModelNode &targetNode,
|
||||
const ModelNode &newNode,
|
||||
QWidget *parent = 0);
|
||||
static ChooseFromPropertyListDialog *createIfNeeded(const ModelNode &targetNode,
|
||||
TypeName type,
|
||||
QWidget *parent = 0);
|
||||
|
||||
private:
|
||||
void fillList(const ModelNode &node);
|
||||
explicit ChooseFromPropertyListDialog(const QStringList &propNames, QWidget *parent = 0);
|
||||
void fillList(const QStringList &propNames);
|
||||
|
||||
Ui::ChooseFromPropertyListDialog *m_ui;
|
||||
TypeName m_selectedProperty;
|
||||
TypeName m_propertyTypeName;
|
||||
};
|
||||
}
|
||||
|
@@ -739,25 +739,13 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
||||
}
|
||||
} else {
|
||||
ModelNode targetNode = targetProperty.parentModelNode();
|
||||
NodeMetaInfo metaInfo = targetNode.metaInfo();
|
||||
TypeName typeName = newModelNode.type();
|
||||
|
||||
// Empty components are not supported and having one as property value is generally
|
||||
// unstable, so let's not offer user to put a fresh Component into a property
|
||||
if (typeName != "QtQml.Component") {
|
||||
const PropertyNameList nameList = targetNode.metaInfo().directPropertyNames();
|
||||
for (const auto &propertyName : nameList) {
|
||||
auto testType = metaInfo.propertyTypeName(propertyName);
|
||||
if (testType == typeName || newModelNode.isSubclassOf(testType)) {
|
||||
ChooseFromPropertyListDialog *dialog = nullptr;
|
||||
dialog = new ChooseFromPropertyListDialog(targetNode, testType, Core::ICore::dialogParent());
|
||||
dialog->exec();
|
||||
if (dialog->result() == QDialog::Accepted)
|
||||
targetNode.bindingProperty(dialog->selectedProperty()).setExpression(newModelNode.validId());
|
||||
delete dialog;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ChooseFromPropertyListDialog *dialog = ChooseFromPropertyListDialog::createIfNeeded(
|
||||
targetNode, newModelNode, Core::ICore::dialogParent());
|
||||
if (dialog) {
|
||||
dialog->exec();
|
||||
if (dialog->result() == QDialog::Accepted)
|
||||
targetNode.bindingProperty(dialog->selectedProperty()).setExpression(newModelNode.validId());
|
||||
delete dialog;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1015,10 +1003,13 @@ bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
||||
if (targetNode.isSubclassOf("QtQuick3D.Material")) {
|
||||
// if dropping an image on a default material, create a texture instead of image
|
||||
ChooseFromPropertyListDialog *dialog = nullptr;
|
||||
if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial") || targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
|
||||
if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")
|
||||
|| targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
|
||||
// Show texture property selection dialog
|
||||
dialog = new ChooseFromPropertyListDialog(targetNode, "QtQuick3D.Texture", Core::ICore::dialogParent());
|
||||
dialog->exec();
|
||||
dialog = ChooseFromPropertyListDialog::createIfNeeded(targetNode, "QtQuick3D.Texture",
|
||||
Core::ICore::dialogParent());
|
||||
if (dialog)
|
||||
dialog->exec();
|
||||
}
|
||||
if (!dialog || dialog->result() == QDialog::Accepted) {
|
||||
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
||||
|
@@ -99,7 +99,7 @@ public:
|
||||
bool instanceIsMovable() const;
|
||||
bool instanceIsResizable() const;
|
||||
bool instanceIsInLayoutable() const;
|
||||
bool instanceHasRotationTransform() const;
|
||||
bool instanceHasScaleOrRotationTransform() const;
|
||||
|
||||
bool modelIsMovable() const;
|
||||
bool modelIsResizable() const;
|
||||
|