Merge remote-tracking branch 'origin/6.0'
Change-Id: Ia208fc746333e3d36868c580aa7794da9627c3e0
82
dist/changes-6.0.2.md
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
Qt Creator 6.0.2
|
||||||
|
================
|
||||||
|
|
||||||
|
Qt Creator version 6.0.2 contains bug fixes.
|
||||||
|
|
||||||
|
The most important changes are listed in this document. For a complete list of
|
||||||
|
changes, see the Git log for the Qt Creator sources that you can check out from
|
||||||
|
the public Git repository. For example:
|
||||||
|
|
||||||
|
git clone git://code.qt.io/qt-creator/qt-creator.git
|
||||||
|
git log --cherry-pick --pretty=oneline origin/v6.0.1..v6.0.2
|
||||||
|
|
||||||
|
General
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed crash in process launcher (QTCREATORBUG-26726)
|
||||||
|
|
||||||
|
Editing
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fixed that `Select All` scrolled to bottom (QTCREATORBUG-26736)
|
||||||
|
* Fixed copying with block selection (QTCREATORBUG-26761)
|
||||||
|
|
||||||
|
### C++
|
||||||
|
|
||||||
|
* ClangCodeModel
|
||||||
|
* Fixed performance regression of code completion on Windows and macOS
|
||||||
|
(QTCREATORBUG-26754)
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
* Fixed working directory for `REPL`
|
||||||
|
|
||||||
|
### Modeling
|
||||||
|
|
||||||
|
* Fixed missing options in property editor (QTCREATORBUG-26760)
|
||||||
|
|
||||||
|
Projects
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Fixed that closing application in `Application Output` pane killed process
|
||||||
|
even if `Keep Running` was selected
|
||||||
|
* Fixed filtering in target setup page (QTCREATORBUG-26779)
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
* Fixed that GUI project wizards did not create GUI applications on Windows and
|
||||||
|
app bundles on macOS
|
||||||
|
|
||||||
|
Platforms
|
||||||
|
---------
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
* Fixed that commercial plugins linked to libGLX and libOpenGL
|
||||||
|
(QTCREATORBUG-26744)
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
* Fixed crash when switching screen configuration (QTCREATORBUG-26019)
|
||||||
|
|
||||||
|
Credits for these changes go to:
|
||||||
|
--------------------------------
|
||||||
|
Allan Sandfeld Jensen
|
||||||
|
André Pönitz
|
||||||
|
Antti Määttä
|
||||||
|
Christiaan Janssen
|
||||||
|
Christian Kandeler
|
||||||
|
Christian Stenger
|
||||||
|
Cristian Adam
|
||||||
|
David Schulz
|
||||||
|
Eike Ziller
|
||||||
|
Henning Gruendl
|
||||||
|
Jaroslaw Kobus
|
||||||
|
Knud Dollereder
|
||||||
|
Leena Miettinen
|
||||||
|
Marco Bubke
|
||||||
|
Mats Honkamaa
|
||||||
|
Samuel Ghinet
|
||||||
|
Tapani Mattila
|
||||||
|
Thomas Hartmann
|
||||||
|
Tuomo Pelkonen
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,106 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2017 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the Qt Creator documentation.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU Free Documentation License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU Free
|
|
||||||
** Documentation License version 1.3 as published by the Free Software
|
|
||||||
** Foundation and appearing in the file included in the packaging of
|
|
||||||
** this file. Please review the following information to ensure
|
|
||||||
** the GNU Free Documentation License version 1.3 requirements
|
|
||||||
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
// **********************************************************************
|
|
||||||
// NOTE: the sections are not ordered by their logical order to avoid
|
|
||||||
// reshuffling the file each time the index order changes (i.e., often).
|
|
||||||
// Run the fixnavi.pl script to adjust the links to the index order.
|
|
||||||
// **********************************************************************
|
|
||||||
|
|
||||||
/*!
|
|
||||||
//! [cmake deploying embedded]
|
|
||||||
|
|
||||||
\section1 Deploying CMake Projects to Generic Remote Linux Devices
|
|
||||||
|
|
||||||
\QC cannot directly extract files to be installed from a CMake project.
|
|
||||||
Therefore, a special deploy step is created that installs the project into
|
|
||||||
a local directory. The files in that directory are then deployed to the
|
|
||||||
remote device.
|
|
||||||
Alternatively, you can provide a \c {QtCreatorDeployment.txt} file in which
|
|
||||||
you must specify all files to be deployed which are not executables or
|
|
||||||
libraries. You place this file in either the root directory of the CMake
|
|
||||||
project or the build directory of the active build configuration.
|
|
||||||
Currently, \QC first checks the root directory and only if no
|
|
||||||
\c {QtCreatorDeployment.txt} exists it checks the active build directory.
|
|
||||||
|
|
||||||
Use the following syntax in the file:
|
|
||||||
|
|
||||||
\code
|
|
||||||
<deployment/prefix>
|
|
||||||
<relative/source/file1>:<relative/destination/dir1>
|
|
||||||
...
|
|
||||||
<relative/source/filen>:<relative/destination/dirn>
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
Where:
|
|
||||||
|
|
||||||
\list
|
|
||||||
|
|
||||||
\li \c {<deployment/prefix>} is the (absolute) path prefix to where
|
|
||||||
files are copied on the remote machine.
|
|
||||||
|
|
||||||
\li \c {<relative/source/file>} is the file path relative to the CMake
|
|
||||||
project root. No directories or wildcards are allowed in this
|
|
||||||
value.
|
|
||||||
|
|
||||||
\li \c {<relative/destination/dir>} is the destination directory path
|
|
||||||
relative to \c {deployment/prefix}.
|
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
To automate the creation of \c {QtCreatorDeployment.txt} file:
|
|
||||||
|
|
||||||
\list 1
|
|
||||||
|
|
||||||
\li Define the following macros in the top level \c {CMakeLists.txt}
|
|
||||||
file:
|
|
||||||
|
|
||||||
\code
|
|
||||||
file(WRITE "${CMAKE_SOURCE_DIR}/QtCreatorDeployment.txt" "<deployment/prefix>\n")
|
|
||||||
|
|
||||||
macro(add_deployment_file SRC DEST)
|
|
||||||
file(RELATIVE_PATH path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
file(APPEND "${CMAKE_SOURCE_DIR}/QtCreatorDeployment.txt" "${path}/${SRC}:${DEST}\n")
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(add_deployment_directory SRC DEST)
|
|
||||||
file(GLOB_RECURSE files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${SRC}/*")
|
|
||||||
foreach(filename ${files})
|
|
||||||
get_filename_component(path ${filename} PATH)
|
|
||||||
add_deployment_file("${filename}" "${DEST}/${path}")
|
|
||||||
endforeach(filename)
|
|
||||||
endmacro()
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\li Use \c {add_deployment_file(<file/name>)} to add files and
|
|
||||||
\c {add_deployment_directory(<folder/name>)} to add directories
|
|
||||||
(including subdirectories) to the \c QtCreatorDeployment.txt file.
|
|
||||||
|
|
||||||
\li Re-run \c cmake after you add or remove files using the macros.
|
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
//! [cmake deploying embedded]
|
|
||||||
*/
|
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2021 The Qt Company Ltd.
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -42,8 +42,9 @@
|
|||||||
native build configurations and workspaces that you can use in the compiler
|
native build configurations and workspaces that you can use in the compiler
|
||||||
environment of your choice.
|
environment of your choice.
|
||||||
|
|
||||||
You can use CMake from \QC to build applications for the desktop and
|
You can use CMake from \QC to build applications for the desktop, as well
|
||||||
Android devices. You can also build single files to test your changes.
|
as mobile and embedded devices. You can also build single files to test
|
||||||
|
your changes.
|
||||||
|
|
||||||
\QC automatically detects the CMake executable specified in the \c PATH.
|
\QC automatically detects the CMake executable specified in the \c PATH.
|
||||||
You can add paths to other CMake executables and use them in different
|
You can add paths to other CMake executables and use them in different
|
||||||
@@ -168,6 +169,6 @@
|
|||||||
\li \l {Opening Projects}
|
\li \l {Opening Projects}
|
||||||
\li \l {CMake Build Configuration}
|
\li \l {CMake Build Configuration}
|
||||||
\li \l {Specifying Run Settings}
|
\li \l {Specifying Run Settings}
|
||||||
\li \l {Deploying CMake Projects to Generic Remote Linux Devices}
|
\li \l {Deploying Applications to Generic Remote Linux Devices}
|
||||||
\endlist
|
\endlist
|
||||||
*/
|
*/
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2021 The Qt Company Ltd.
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -30,13 +30,18 @@
|
|||||||
|
|
||||||
\title Deploying Applications to Boot2Qt Devices
|
\title Deploying Applications to Boot2Qt Devices
|
||||||
|
|
||||||
You can specify the generic deployment steps for remote Linux devices also
|
You can specify settings for deploying applications to \l{Boot2Qt} devices
|
||||||
for \l{Boot2Qt} devices.
|
in the project configuration file and in \uicontrol Projects >
|
||||||
|
\uicontrol {Run Settings} > \uicontrol Deployment.
|
||||||
|
|
||||||
\image qtcreator-boot2qt-deployment-steps.png "Boot2Qt deployment steps"
|
\image qtcreator-boot2qt-deployment-steps.png "Boot2Qt deployment steps"
|
||||||
|
|
||||||
For more information, see \l{Generic Deployment Steps}.
|
The deployment process is described in more detail in
|
||||||
|
\l{Deploying Applications to Generic Remote Linux Devices}.
|
||||||
|
|
||||||
|
\section1 Launching Applications on Boot
|
||||||
|
|
||||||
In addition, to have your application launch on boot, select
|
In addition, to have your application launch on boot, select
|
||||||
\uicontrol {Add Deploy Step} > \uicontrol {Change Default Application}.
|
\uicontrol {Add Deploy Step} > \uicontrol {Change default application}
|
||||||
|
> \uicontrol {Set this application to start by default}.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2020 The Qt Company Ltd.
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -41,58 +41,70 @@
|
|||||||
\title Deploying Applications to Generic Remote Linux Devices
|
\title Deploying Applications to Generic Remote Linux Devices
|
||||||
|
|
||||||
You can specify settings for deploying applications to generic remote
|
You can specify settings for deploying applications to generic remote
|
||||||
Linux devices in the project .pro file. You can view the settings in
|
Linux devices in the project configuration file and in the
|
||||||
the \uicontrol Projects mode, in \uicontrol {Run Settings}.
|
\uicontrol Projects mode, in \uicontrol {Run Settings}.
|
||||||
|
|
||||||
\image qtcreator-embedded-linux-deployment-overview.png "Deploy to device"
|
\image qtcreator-embedded-linux-deployment-details.png "Deploy to embedded Linux"
|
||||||
|
|
||||||
The files to be installed are listed in the \uicontrol {Deployment} step,
|
The files to be installed are listed in the \uicontrol {Deployment} step,
|
||||||
the \uicontrol {Files to deploy} field. The \uicontrol {Local File Path}
|
the \uicontrol {Files to deploy} field. The \uicontrol {Local File Path}
|
||||||
field displays the location of the file on the development PC. The
|
field displays the location of the file on the development PC. The
|
||||||
\uicontrol {Remote Directory} field displays the folder where the file is
|
\uicontrol {Remote Directory} field displays the directory where the file is
|
||||||
installed on the device. Text in red color indicates that the information is
|
installed on the device. Text in red color indicates that the information is
|
||||||
missing. Edit the qmake \l{Variables#installs} {INSTALLS variable} in the
|
missing.
|
||||||
project \c .pro file to add the missing files.
|
|
||||||
|
\section1 Adding Missing Files
|
||||||
|
|
||||||
|
The process to add files to deploy depends on the build system you use.
|
||||||
|
|
||||||
|
\section2 CMake
|
||||||
|
|
||||||
|
When using CMake as the build system, use the \l{CMake: install command}
|
||||||
|
{install} command in the CMakeLists.txt file to add the missing files.
|
||||||
|
|
||||||
|
For example, add the following lines to the CMakeLists.txt file to install
|
||||||
|
the binary of your project to the \c /opt directory on the remote device:
|
||||||
|
|
||||||
|
\badcode
|
||||||
|
set(INSTALL_DESTDIR "/opt")
|
||||||
|
|
||||||
|
install(TARGETS <target>
|
||||||
|
RUNTIME DESTINATION "${INSTALL_DESTDIR}"
|
||||||
|
BUNDLE DESTINATION "${INSTALL_DESTDIR}"
|
||||||
|
LIBRARY DESTINATION "${INSTALL_DESTDIR}"
|
||||||
|
)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\section2 qmake
|
||||||
|
|
||||||
|
When using qmake, edit the \l{Variables#installs}{INSTALLS variable} in
|
||||||
|
the project \c .pro file.
|
||||||
|
|
||||||
When you run the application, \QC copies the necessary files to the device
|
When you run the application, \QC copies the necessary files to the device
|
||||||
and starts the application on it.
|
and starts the application on it.
|
||||||
|
|
||||||
For example, adding
|
For example, add the following lines to the \c .pro file to copy the binary
|
||||||
|
of your project to the \c /opt directory on the remote device:
|
||||||
|
|
||||||
\code
|
\code
|
||||||
target.path = /root
|
target.path = /opt
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
to the project .pro file will copy the binary of your project to \c /root
|
To deploy additional files, add them to further targets that you also add
|
||||||
on the remote device. Additional files can be deployed by adding them to
|
to \c INSTALLS.
|
||||||
further targets and adding those to \c INSTALLS as well.
|
|
||||||
|
|
||||||
\section1 Generic Deployment Steps
|
\section1 Deploy Steps
|
||||||
|
|
||||||
\image qtcreator-embedded-linux-deployment-details.png "Deploy to embedded Linux"
|
When you run the application on the device, \QC first uploads the
|
||||||
|
necessary files to it, as specified by the deploy steps.
|
||||||
|
|
||||||
When you run the application on the device, \QC
|
\section2 Finding Configured Devices
|
||||||
deploys the application as specified by the deploy steps. By default, \QC
|
|
||||||
copies the application files to the device by using the SSH file transfer
|
|
||||||
protocol (SFTP), as specified by the \uicontrol {Upload files via SFTP}
|
|
||||||
step.
|
|
||||||
|
|
||||||
If you have a lot of data to copy, select \uicontrol Details in the
|
The \uicontrol {Check for a configured device} step looks for a device that
|
||||||
\uicontrol {Upload Files via SFTP} step, and then select the
|
is ready for deployment.
|
||||||
\uicontrol {Incremental deployment} check box. \QC takes note of the
|
|
||||||
deployment time and only copies files that have changed since the last
|
|
||||||
deployment. However, when you make major changes on the device, such as
|
|
||||||
removing files from the device manually or flashing a new disk image, or
|
|
||||||
when you use another device with the same IP address, deselect the check box
|
|
||||||
once, to have \QC deploy all files again.
|
|
||||||
|
|
||||||
To only create a tarball and not copy the files to the device, select
|
\section2 Checking for Free Disk Space
|
||||||
\uicontrol {Add Deploy Step} > \uicontrol {Create tarball}. Then remove all
|
|
||||||
other deploy steps.
|
|
||||||
|
|
||||||
The \uicontrol {Deploy tarball via SFTP upload} step specifies that \QC
|
|
||||||
uploads the tarball to the device and extracts it.
|
|
||||||
|
|
||||||
The \uicontrol {Check for free disk space} step is by default the first
|
The \uicontrol {Check for free disk space} step is by default the first
|
||||||
deploy step. Use it to find out whether the remote file system has enough
|
deploy step. Use it to find out whether the remote file system has enough
|
||||||
@@ -104,7 +116,27 @@
|
|||||||
support will crash when an SFTP upload is being attempted. This is not a bug
|
support will crash when an SFTP upload is being attempted. This is not a bug
|
||||||
in \QC.
|
in \QC.
|
||||||
|
|
||||||
\if defined(qtcreator)
|
\section2 Uploading Files
|
||||||
\include creator-projects-cmake-deploying.qdocinc cmake deploying embedded
|
|
||||||
\endif
|
By default, \QC copies the application files to the device by
|
||||||
|
using the SSH file transfer protocol (SFTP), as specified by
|
||||||
|
the \uicontrol {Upload files via SFTP} step.
|
||||||
|
|
||||||
|
If you have a lot of data to copy, select \uicontrol Details in the
|
||||||
|
\uicontrol {Upload Files via SFTP} step, and then select the
|
||||||
|
\uicontrol {Incremental deployment} check box. \QC takes note of the
|
||||||
|
deployment time and only copies files that have changed since the last
|
||||||
|
deployment. However, when you make major changes on the device, such as
|
||||||
|
removing files from the device manually or flashing a new disk image, or
|
||||||
|
when you use another device with the same IP address, deselect the check box
|
||||||
|
once, to have \QC deploy all files again.
|
||||||
|
|
||||||
|
\section2 Creating a Tarball
|
||||||
|
|
||||||
|
To only create a tarball and not copy the files to the device, select
|
||||||
|
\uicontrol {Add Deploy Step} > \uicontrol {Create tarball}. Then remove all
|
||||||
|
other deploy steps.
|
||||||
|
|
||||||
|
The \uicontrol {Deploy tarball via SFTP upload} step specifies that \QC
|
||||||
|
uploads the tarball to the device and extracts it.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2019 The Qt Company Ltd.
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the Qt Creator documentation.
|
** This file is part of the Qt Creator documentation.
|
||||||
@@ -144,8 +144,8 @@
|
|||||||
If you want to run your application on a generic remote Linux device,
|
If you want to run your application on a generic remote Linux device,
|
||||||
you first need to deploy your executable and possibly other files.
|
you first need to deploy your executable and possibly other files.
|
||||||
\QC does that for you automatically if you provide the necessary
|
\QC does that for you automatically if you provide the necessary
|
||||||
information. This works the same way as explained for CMake
|
information. This works the same way as explained for CMake in
|
||||||
\l {Deploying CMake Projects to Generic Remote Linux Devices}{here},
|
\l {Deploying Applications to Generic Remote Linux Devices},
|
||||||
except that you also need to include your application binary in the list.
|
except that you also need to include your application binary in the list.
|
||||||
|
|
||||||
\section1 Creating a Run Configuration
|
\section1 Creating a Run Configuration
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018 Blackberry
|
** Copyright (C) 2018 Blackberry
|
||||||
**
|
|
||||||
** Contact: Blackberry (qt@blackberry.com)
|
** Contact: Blackberry (qt@blackberry.com)
|
||||||
** Contact: KDAB (info@kdab.com)
|
** Contact: KDAB (info@kdab.com)
|
||||||
**
|
**
|
||||||
** This file is part of the documentation of the Qt Toolkit.
|
** Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Creator documentation.
|
||||||
**
|
**
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
@@ -40,19 +40,12 @@
|
|||||||
|
|
||||||
\title Deploying Applications to QNX Neutrino Devices
|
\title Deploying Applications to QNX Neutrino Devices
|
||||||
|
|
||||||
You can deploy applications to QNX Neutrino devices in the way that is
|
You can specify settings for deploying applications to QNX Neutrino
|
||||||
described in \l{Deploying Applications to Generic Remote Linux Devices}.
|
devices in the project configuration file and in \uicontrol Projects
|
||||||
|
> \uicontrol {Run Settings} > \uicontrol Deployment.
|
||||||
|
|
||||||
\image qtcreator-qnx-deployment.png "Deploy to device"
|
\image qtcreator-qnx-deployment.png "Deploy to device"
|
||||||
|
|
||||||
The files to be installed are listed in the \uicontrol {Deployment} step,
|
The deployment process is described in more detail in
|
||||||
the \uicontrol {Files to deploy} field. The
|
\l{Deploying Applications to Generic Remote Linux Devices}.
|
||||||
\uicontrol {Local File Path} field displays the location of the file on the
|
|
||||||
development PC. The \uicontrol {Remote Directory} field displays the folder
|
|
||||||
where the file is installed on the device. Text in red color indicates that
|
|
||||||
the information is missing. Edit the qmake \l{Variables#installs}
|
|
||||||
{INSTALLS variable} in the project \c .pro file to add the missing files.
|
|
||||||
|
|
||||||
When you run the application, \QC copies the necessary files to the device
|
|
||||||
and starts the application on it.
|
|
||||||
*/
|
*/
|
||||||
|
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 9.8 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 18 KiB |
BIN
doc/qtdesignstudio/examples/doc/images/snow-particles.png
Normal file
After Width: | Height: | Size: 35 KiB |
198
doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Studio documentation.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Free Documentation License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Free
|
||||||
|
** Documentation License version 1.3 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file included in the packaging of
|
||||||
|
** this file. Please review the following information to ensure
|
||||||
|
** the GNU Free Documentation License version 1.3 requirements
|
||||||
|
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\page rain-snow-particle-effect.html
|
||||||
|
\ingroup gstutorials
|
||||||
|
|
||||||
|
\title Rain and Snow Effect
|
||||||
|
\brief Illustrates how to create a rain and snow effect with the \QDS
|
||||||
|
particle system.
|
||||||
|
|
||||||
|
\image snow-particles.png
|
||||||
|
|
||||||
|
The \e{Rain and Snow Effect} tutorial illustrates how you can add a rain and
|
||||||
|
a snow effect to your
|
||||||
|
scene using the \QDS particle system.
|
||||||
|
|
||||||
|
You need to download the starting project for this tutorial from
|
||||||
|
\l{https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/
|
||||||
|
tutorial%20projects/rain-snow-particles/Start}{here} before you start.
|
||||||
|
|
||||||
|
Download the project and open the \e faceparticles.qmlproject file in \QDS
|
||||||
|
to get started.
|
||||||
|
|
||||||
|
\image rain-snow-tutorial-start.png
|
||||||
|
\section1 Creating a Rain Effect
|
||||||
|
|
||||||
|
\section2 Adding a Particle System to Your Scene
|
||||||
|
|
||||||
|
To add a particle system, you first need to import the QtQuick3D.Particles3D
|
||||||
|
module to your project:
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li In the \uicontrol Library view, select
|
||||||
|
\inlineimage icons/plus.png
|
||||||
|
next to \uicontrol Components.
|
||||||
|
\li Find QtQuick3D.Particles3D and select it to add it to your project.
|
||||||
|
\li From \uicontrol Library > \uicontrol Components, drag a
|
||||||
|
\uicontrol{Particle System} to \uicontrol scene in \uicontrol Navigator.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
Now you have added a particle system to your scene.
|
||||||
|
|
||||||
|
\image rain-snow-tutorial-particle-system
|
||||||
|
|
||||||
|
\section2 Adjusting the Behavior and Apperance of the Particle System
|
||||||
|
Next, you adjust the position, behavior, and apperance of the particle
|
||||||
|
system to create a simple rain effect:
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li Adjust the position of the particle system to align with the sphere.
|
||||||
|
In \uicontrol Navigator, select \e particleSystem and in
|
||||||
|
\uicontrol Properties, set \uicontrol Translation > \uicontrol Y to 193.
|
||||||
|
\li Set the \e rain-drop-white-square.png as texture for the particles.
|
||||||
|
From \uicontrol Library > \uicontrol Components, drag a \uicontrol Texture
|
||||||
|
to \e spriteParticle.
|
||||||
|
\li In \uicontrol Navigator, select \uicontrol texture1 and in \uicontrol
|
||||||
|
Properties, set \uicontrol Source to \e rain-drop-white-square.png.
|
||||||
|
\li In \uicontrol Navigator, select \uicontrol spriteParticle and in the
|
||||||
|
\uicontrol Properties, set \uicontrol Sprite to texture.
|
||||||
|
\li Adjust the apperance and behavior of the sprite further. In \uicontrol
|
||||||
|
Properties, set:
|
||||||
|
\list
|
||||||
|
\li \uicontrol{Particle Scale} to 10.
|
||||||
|
\li \uicontrol{Max Amount} to 1000.
|
||||||
|
\li \uicontrol Color to #91ffffff.
|
||||||
|
\li \uicontrol{Fade In Effect} to FadeNone.
|
||||||
|
\li \uicontrol{Fade Out Effect} to FadeNone.
|
||||||
|
\endlist
|
||||||
|
\li Now you have set the apperance of the particles. Next, adjust
|
||||||
|
the particle emitter. In \uicontrol Navigator, select \uicontrol
|
||||||
|
particleEmitter, and in \uicontrol Properties set:
|
||||||
|
\list
|
||||||
|
\li \uicontrol System to particleSystem.
|
||||||
|
\li \uicontrol{Emit Rate} to 1500.
|
||||||
|
\li \uicontrol{Life Span} to 100.
|
||||||
|
\li \uicontrol{Life Span Variation} to 0.
|
||||||
|
\li \uicontrol{Particle End Scale} to 1.
|
||||||
|
\li \uicontrol{Particle Scale Variation} to 0,5.
|
||||||
|
\li \uicontrol{Particle End Scale Variation} to 0,5.
|
||||||
|
\li \uicontrol{Particle Rotation} > \uicontrol Variation >
|
||||||
|
\uicontrol X, \uicontrol Y,
|
||||||
|
and \uicontrol Z to 0.
|
||||||
|
\li \uicontrol{Particle Rotation} > \uicontrol{Velocity Variation} >
|
||||||
|
\uicontrol X,
|
||||||
|
\uicontrol Y, and \uicontrol Z to 0.
|
||||||
|
\li \uicontrol Transform > \uicontrol Translation \uicontrol Y to -69.
|
||||||
|
\endlist
|
||||||
|
\li Finally, you set the direction of the particles. In \uicontrol
|
||||||
|
Navigator, select \uicontrol dir3d and in \uicontrol
|
||||||
|
Properties set:
|
||||||
|
\list
|
||||||
|
\li \uicontrol Direction > \uicontrol Y to -500.
|
||||||
|
\li \uicontrol Direction > \uicontrol Z to 0.
|
||||||
|
\li \uicontrol{Direction Variation} > \uicontrol X, \uicontrol Y, and
|
||||||
|
\uicontrol Z to 0.
|
||||||
|
\endlist
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\section2 Adjusting the Size of the Emitting Area
|
||||||
|
|
||||||
|
By default, the \uicontrol {Particle Emitter} emits particles from one
|
||||||
|
point in the scene. In this scene you want to emit particles from a bigger
|
||||||
|
area matching the size of the sphere. To do this, you need to add
|
||||||
|
a \uicontrol{Particle Shape} component:
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li From \uicontrol Components, drag a \uicontrol{Particle Shape}
|
||||||
|
component to \uicontrol{particleSystem} in \uicontrol Navigator.
|
||||||
|
\li In \uicontrol Navigator, select \uicontrol particleShape, and in
|
||||||
|
\uicontrol Properties set:
|
||||||
|
\list
|
||||||
|
\li \uicontrol Type to \uicontrol Sphere.
|
||||||
|
\li \uicontrol Extends \uicontrol X to 85.
|
||||||
|
\li \uicontrol Extends \uicontrol Y to 85.
|
||||||
|
\li \uicontrol Extends \uicontrol Z to 85.
|
||||||
|
\endlist
|
||||||
|
\li In \uicontrol Navigator, select \uicontrol particleEmitter, and in
|
||||||
|
\uicontrol Particle set
|
||||||
|
\uicontrol Shape to \uicontrol particleShape.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image rain-snow-tutorial-navigator.png
|
||||||
|
|
||||||
|
Now, the rain effect is ready. Press \key Alt+P to see it in the live
|
||||||
|
preview.
|
||||||
|
|
||||||
|
\section1 Creating a Snow Effect
|
||||||
|
|
||||||
|
To make it easy, you can duplicate the particle system you created for the
|
||||||
|
rain effect and adjust the properties to create a snow effect. To do this,
|
||||||
|
first create a new state for the snow effect:
|
||||||
|
|
||||||
|
\list
|
||||||
|
\li In \uicontrol{States}, select \uicontrol{Create New State}.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image rain-snow-tutorial-states.png
|
||||||
|
|
||||||
|
\section2 Turning the Rain into Snow
|
||||||
|
|
||||||
|
\list 1
|
||||||
|
\li With the new state that you just created selected in
|
||||||
|
\uicontrol{States}, in \uicontrol{Navigator}, select \uicontrol
|
||||||
|
spriteParticle and set \uicontrol Color to #ffffff.
|
||||||
|
\li In \uicontrol{Navigator}, select \uicontrol texture1 and set
|
||||||
|
\uicontrol Source to \e{snowflake.png}.
|
||||||
|
\li In \uicontrol{Navigator}, select \uicontrol particleEmitter and set:
|
||||||
|
\list
|
||||||
|
\li \uicontrol{Emit Rate} to 250.
|
||||||
|
\li \uicontrol{Life Span} to 450.
|
||||||
|
\li \uicontrol{Particle Rotation} > \uicontrol Variation >
|
||||||
|
\uicontrol{X}, \uicontrol{Y}, and \uicontrol Z to 180.
|
||||||
|
\li \uicontrol{Particle Rotation} > \uicontrol{Velocity Variation} >
|
||||||
|
\uicontrol{X}, \uicontrol{Y}, and \uicontrol Z to 200.
|
||||||
|
\endlist
|
||||||
|
\li In \uicontrol{Navigator}, select \uicontrol particleEmitter
|
||||||
|
> \uicontrol dir3d and set:
|
||||||
|
\list
|
||||||
|
\li \uicontrol Direction > \uicontrol Y to -100.
|
||||||
|
\li \uicontrol{Direction Variation} \uicontrol{X}, \uicontrol{Y},
|
||||||
|
and \uicontrol Z
|
||||||
|
to 10.
|
||||||
|
\endlist
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
Now you can run the snow effect in the live preview:
|
||||||
|
\list 1
|
||||||
|
\li In \uicontrol{States} next to \uicontrol State1 select
|
||||||
|
\inlineimage icons/action-icon.png
|
||||||
|
and select \uicontrol{Set as Default}.
|
||||||
|
\li Press \key{Alt+P}.
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\image rain-snow-tutorial-default-state.png
|
||||||
|
*/
|
Before Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 109 KiB |
@@ -48,95 +48,83 @@
|
|||||||
prompt you to enter the settings needed for a particular type of project
|
prompt you to enter the settings needed for a particular type of project
|
||||||
and create the necessary files for you.
|
and create the necessary files for you.
|
||||||
|
|
||||||
\QDS projects are useful for creating UIs. You cannot use them for
|
To test how well your designs work, you can preview the
|
||||||
application development, because they do not contain:
|
UIs on the desktop, embedded Linux devices, or Android devices. For more
|
||||||
|
|
||||||
\list
|
|
||||||
\li C++ code
|
|
||||||
\li Resource files (.qrc)
|
|
||||||
\li Code needed for deploying applications to devices.
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
Because the projects do not contain any C++ code, you do not need
|
|
||||||
to build them. To test how well your designs work, you can preview the
|
|
||||||
UIs on the desktop or embedded Linux devices. For more
|
|
||||||
information, see \l{Validating with Target Hardware}.
|
information, see \l{Validating with Target Hardware}.
|
||||||
|
|
||||||
\image studio-project-wizards.png "A list of project wizards"
|
\image studio-project-wizards.png "A list of project wizards"
|
||||||
|
|
||||||
You can export designs from other design tools and import them to projects
|
You can export designs from other design tools and import them to projects
|
||||||
or create them from scratch using the following wizard templates:
|
or create them from scratch using the following wizard presets:
|
||||||
|
|
||||||
\table
|
\table
|
||||||
\header
|
\header
|
||||||
\li Category
|
\li Category
|
||||||
\li Wizard Template
|
\li Wizard Preset
|
||||||
\li Purpose
|
\li Purpose
|
||||||
\row
|
\row
|
||||||
\li {1,2} General
|
\li {1,2} General
|
||||||
\li Qt Quick Application - Empty
|
\li Empty
|
||||||
\li Creates a project that uses default components and preset UI
|
\li Creates a project that uses default components such as rectangles,
|
||||||
controls and can be run on all target platforms.
|
images, and text. You can run the application on all target
|
||||||
|
platforms.
|
||||||
\row
|
\row
|
||||||
\li Qt Quick 3D Application
|
\li 3D
|
||||||
\li Creates a project that uses default components, UI controls, and
|
\li Creates a project that uses default and 3D components such as
|
||||||
3D components.
|
cameras, lights, 3D models, and materials.
|
||||||
\row
|
\row
|
||||||
\li Qt for MCUs
|
\li Qt for MCUs
|
||||||
\li Qt for MCUs Application
|
\li MCU
|
||||||
\li Creates an application that uses a subset of preset components
|
\li Creates an application that uses a subset of default components
|
||||||
(as supported by Qt for MCUs) that you can deploy, run, and debug
|
(as supported by Qt for MCUs) that you can deploy, run, and debug
|
||||||
on MCU boards.
|
on MCU boards.
|
||||||
\row
|
\row
|
||||||
\li {1,2} Mobile
|
\li {1,3} Mobile
|
||||||
\li Qt Quick Application - Scroll
|
\li Scroll
|
||||||
\li Creates an application that uses UI controls to implement a
|
\li Creates an application that uses Qt Quick controls to implement a
|
||||||
scrollable list.
|
scrollable list.
|
||||||
\row
|
\row
|
||||||
\li Qt Quick Application - Stack
|
\li Stack
|
||||||
\li Creates an application that uses UI controls to implement a
|
\li Creates an application that uses Qt Quick controls to implement a
|
||||||
set of pages with a stack-based navigation model.
|
set of pages with a stack-based navigation model.
|
||||||
|
\row
|
||||||
|
\li Swipe
|
||||||
|
\li Creates an application that uses Qt Quick controls to implement a
|
||||||
|
swipable screen.
|
||||||
\row
|
\row
|
||||||
\li Desktop
|
\li Desktop
|
||||||
\li Qt Quick Application - Launcher
|
\li Launcher
|
||||||
\li Creates a project that uses default components and UI controls and
|
\li Creates a project that uses default components such as rectangles,
|
||||||
defines a launcher application.
|
images, and text, and defines a launcher application.
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
For an example of creating a \uicontrol {Qt Quick 3D Application} project,
|
|
||||||
watch the following video:
|
|
||||||
|
|
||||||
\youtube 9ihYeC0YJ0M
|
|
||||||
|
|
||||||
\section1 Using Project Wizards
|
\section1 Using Project Wizards
|
||||||
|
|
||||||
|
To create a new project:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li Select \uicontrol File > \uicontrol {New Project}.
|
\li Select \uicontrol File > \uicontrol {New Project}.
|
||||||
\li Select a wizard template, and then select \uicontrol Choose.
|
\li In the \uicontrol Presets tab, select a wizard preset.
|
||||||
\li In the \uicontrol Name field, enter a name for the project.
|
\li In the \uicontrol Details tab:
|
||||||
Keep in mind that projects cannot be easily renamed later.
|
\list
|
||||||
\image studio-project-location.png "Project Location dialog"
|
\li Enter a name for the project. Keep in mind that projects
|
||||||
\li In the \uicontrol {Create in} field, enter the path for the project
|
cannot be easily renamed later.
|
||||||
files. You can move project folders later without problems.
|
\li Select the path for the project files. You can move project
|
||||||
\li Select \uicontrol Next (or \uicontrol Continue on \macos).
|
folders later.
|
||||||
\li In the \uicontrol {Screen resolution} field, select the screen
|
\li Set the screen resolution for previewing the UI on the
|
||||||
resolution for previewing the UI on the desktop or on a device.
|
desktop or on a device. This determines the screen size. You can
|
||||||
This determines the screen size.
|
change the screen size later in \l Properties.
|
||||||
\image studio-project-custom-screen-size.png "Define Project Details dialog"
|
\li Select \uicontrol {Use Qt Virtual Keyboard} to
|
||||||
\li To use a custom screen size, specify the width and height of the
|
enable users to enter text using a virtual keyboard.
|
||||||
screen in the \uicontrol {Custom screen width} and
|
\li In \uicontrol {Target Qt Version}, select the Qt
|
||||||
\uicontrol {Custom screen height} fields.
|
version to use for developing the application. While you can
|
||||||
You can easily change the screen size later in \l Properties.
|
change the Qt version later in the \uicontrol {Run Settings}
|
||||||
\li In the \uicontrol {Qt Quick Controls Style} field, select one of
|
of the project, keep in mind that the two versions are not fully
|
||||||
|
compatible.
|
||||||
|
\endlist
|
||||||
|
\li In the \uicontrol {Style} tab, select one of
|
||||||
the predefined \l{Styling Qt Quick Controls}{UI styles} to use.
|
the predefined \l{Styling Qt Quick Controls}{UI styles} to use.
|
||||||
\li Select the \uicontrol {Use Qt Virtual Keyboard} check box to enable
|
\li Select \uicontrol Create to create the project.
|
||||||
users to enter text using a virtual keyboard.
|
|
||||||
\li In the \uicontrol {Target Qt Version} field, select the Qt version
|
|
||||||
to use for developing the application. While you can change the
|
|
||||||
Qt version later in the \uicontrol {Run Settings} of the project,
|
|
||||||
keep in mind that the two versions are not fully compatible.
|
|
||||||
\li Select \uicontrol Finish (or \uicontrol Done on \macos) to create
|
|
||||||
the project.
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\QDS creates the following files and folders:
|
\QDS creates the following files and folders:
|
||||||
@@ -155,6 +143,9 @@
|
|||||||
Specifically, if you export and import designs using \QB, your main
|
Specifically, if you export and import designs using \QB, your main
|
||||||
file is most likely called something else. For more information,
|
file is most likely called something else. For more information,
|
||||||
see \l {Exporting from Design Tools}.
|
see \l {Exporting from Design Tools}.
|
||||||
|
\li \e CMakeLists.txt project configuration file allowing you to
|
||||||
|
share your project as a fully working C++ application with
|
||||||
|
developers.
|
||||||
\li qtquickcontrols2.conf file specifies the preferred style and some
|
\li qtquickcontrols2.conf file specifies the preferred style and some
|
||||||
style-specific arguments.
|
style-specific arguments.
|
||||||
\li \e fonts folder contains font files that you have added in
|
\li \e fonts folder contains font files that you have added in
|
||||||
|
@@ -237,7 +237,7 @@
|
|||||||
"enabled": "%{IsTopLevelProject}",
|
"enabled": "%{IsTopLevelProject}",
|
||||||
"data": {
|
"data": {
|
||||||
"projectFilePath": "%{ProjectFilePath}",
|
"projectFilePath": "%{ProjectFilePath}",
|
||||||
"requiredFeatures": [ "%{JS: (value('TestFrameWork') === 'QtQuickTest' ? 'QtSupport.Wizards.FeatureQt.5' : ((value('BuildSystem') === 'qmake' || value('TestFrameWork') === 'QtTest') ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' )) }" ]
|
"requiredFeatures": [ "%{JS: (value('TestFrameWork') === 'QtQuickTest' ? 'QtSupport.Wizards.FeatureQtQuick.2' : ((value('BuildSystem') === 'qmake' || value('TestFrameWork') === 'QtTest') ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' )) }" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/optional.h>
|
||||||
#include <utils/smallstringview.h>
|
#include <utils/smallstringview.h>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -62,7 +63,7 @@ void insertUpdateDelete(SqliteRange &&sqliteRange,
|
|||||||
auto endSqliteIterator = sqliteRange.end();
|
auto endSqliteIterator = sqliteRange.end();
|
||||||
auto currentValueIterator = values.begin();
|
auto currentValueIterator = values.begin();
|
||||||
auto endValueIterator = values.end();
|
auto endValueIterator = values.end();
|
||||||
std::optional<std::decay_t<decltype(*currentValueIterator)>> lastValue;
|
Utils::optional<std::decay_t<decltype(*currentValueIterator)>> lastValue;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
bool hasMoreValues = currentValueIterator != endValueIterator;
|
bool hasMoreValues = currentValueIterator != endValueIterator;
|
||||||
|
@@ -41,6 +41,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(TimeStamp first, TimeStamp second) { return !(first == second); }
|
friend bool operator!=(TimeStamp first, TimeStamp second) { return !(first == second); }
|
||||||
|
friend bool operator<(TimeStamp first, TimeStamp second) { return first.value < second.value; }
|
||||||
|
|
||||||
|
friend TimeStamp operator+(TimeStamp first, TimeStamp second)
|
||||||
|
{
|
||||||
|
return first.value + second.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend TimeStamp operator-(TimeStamp first, TimeStamp second)
|
||||||
|
{
|
||||||
|
return first.value - second.value;
|
||||||
|
}
|
||||||
|
|
||||||
bool isValid() const { return value >= 0; }
|
bool isValid() const { return value >= 0; }
|
||||||
|
|
||||||
|
@@ -408,7 +408,10 @@ QFuture<ResultType> runAsync_internal(QThreadPool *pool,
|
|||||||
QFuture<ResultType> future = job->future();
|
QFuture<ResultType> future = job->future();
|
||||||
if (pool) {
|
if (pool) {
|
||||||
job->setThreadPool(pool);
|
job->setThreadPool(pool);
|
||||||
|
if (QThread::currentThread() == pool->thread())
|
||||||
pool->start(job);
|
pool->start(job);
|
||||||
|
else
|
||||||
|
QMetaObject::invokeMethod(pool, [pool, job]() { pool->start(job); }, Qt::QueuedConnection);
|
||||||
} else {
|
} else {
|
||||||
auto thread = new Internal::RunnableThread(job);
|
auto thread = new Internal::RunnableThread(job);
|
||||||
if (stackSize)
|
if (stackSize)
|
||||||
|
@@ -138,11 +138,10 @@ void DPasteDotComProtocol::paste(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DPasteDotComProtocol::checkConfiguration(QString *errorMessage)
|
bool DPasteDotComProtocol::checkConfiguration(QString * /*errorMessage*/)
|
||||||
{
|
{
|
||||||
if (!m_hostKnownOk)
|
// we need a 1s gap between requests, so skip status check to avoid failing
|
||||||
m_hostKnownOk = httpStatus(baseUrl(), errorMessage);
|
return true;
|
||||||
return m_hostKnownOk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DPasteDotComProtocol::reportError(const QString &message)
|
void DPasteDotComProtocol::reportError(const QString &message)
|
||||||
|
@@ -50,8 +50,6 @@ private:
|
|||||||
bool checkConfiguration(QString *errorMessage) override;
|
bool checkConfiguration(QString *errorMessage) override;
|
||||||
|
|
||||||
static void reportError(const QString &message);
|
static void reportError(const QString &message);
|
||||||
|
|
||||||
bool m_hostKnownOk = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CodePaster
|
} // namespace CodePaster
|
||||||
|
@@ -1572,6 +1572,8 @@ static const MsvcToolChain *selectMsvcToolChain(const QString &displayedVarsBat,
|
|||||||
QTC_CHECK(displayedVarsBat.isEmpty());
|
QTC_CHECK(displayedVarsBat.isEmpty());
|
||||||
const QVersionNumber version = clangClVersion(clangClPath);
|
const QVersionNumber version = clangClVersion(clangClPath);
|
||||||
if (version.majorVersion() >= 6) {
|
if (version.majorVersion() >= 6) {
|
||||||
|
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2022Flavor);
|
||||||
|
if (!toolChain)
|
||||||
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2019Flavor);
|
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2019Flavor);
|
||||||
if (!toolChain)
|
if (!toolChain)
|
||||||
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2017Flavor);
|
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2017Flavor);
|
||||||
|
@@ -185,7 +185,7 @@ void CMakeGeneratorDialogTreeModel::createNodes(const FilePaths &candidates, QSt
|
|||||||
|
|
||||||
const CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::constNodeForIndex(const QModelIndex &index) const
|
const CheckableFileTreeItem* CMakeGeneratorDialogTreeModel::constNodeForIndex(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
const QStandardItem *parent = static_cast<const QStandardItem*>(index.constInternalPointer());
|
const QStandardItem *parent = static_cast<const QStandardItem*>(index.internalPointer());
|
||||||
const QStandardItem *item = parent->child(index.row(), index.column());
|
const QStandardItem *item = parent->child(index.row(), index.column());
|
||||||
return static_cast<const CheckableFileTreeItem*>(item);
|
return static_cast<const CheckableFileTreeItem*>(item);
|
||||||
}
|
}
|
||||||
|
@@ -1050,15 +1050,16 @@ static QString getAssetDefaultDirectory(const QString &assetDir, const QString &
|
|||||||
{
|
{
|
||||||
QString adjustedDefaultDirectory = defaultDirectory;
|
QString adjustedDefaultDirectory = defaultDirectory;
|
||||||
|
|
||||||
Utils::FilePath assetPath = projectFilePath();
|
Utils::FilePath contentPath = projectFilePath();
|
||||||
if (assetPath.pathAppended("content").exists())
|
|
||||||
assetPath= assetPath.pathAppended("content");
|
|
||||||
|
|
||||||
assetPath = assetPath.pathAppended(assetDir);
|
if (contentPath.pathAppended("content").exists())
|
||||||
|
contentPath = contentPath.pathAppended("content");
|
||||||
|
|
||||||
|
Utils::FilePath assetPath = contentPath.pathAppended(assetDir);
|
||||||
|
|
||||||
if (!assetPath.exists()) {
|
if (!assetPath.exists()) {
|
||||||
// Create the default asset type directory if it doesn't exist
|
// Create the default asset type directory if it doesn't exist
|
||||||
QDir dir(projectFilePath().toString());
|
QDir dir(contentPath.toString());
|
||||||
dir.mkpath(assetDir);
|
dir.mkpath(assetDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,18 +25,19 @@
|
|||||||
|
|
||||||
#include "asynchronousimagefactory.h"
|
#include "asynchronousimagefactory.h"
|
||||||
|
|
||||||
|
#include "imagecachecollector.h"
|
||||||
#include "imagecachegenerator.h"
|
#include "imagecachegenerator.h"
|
||||||
#include "imagecachestorage.h"
|
#include "imagecachestorage.h"
|
||||||
#include "timestampprovider.h"
|
#include "timestampproviderinterface.h"
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
AsynchronousImageFactory::AsynchronousImageFactory(ImageCacheStorageInterface &storage,
|
AsynchronousImageFactory::AsynchronousImageFactory(ImageCacheStorageInterface &storage,
|
||||||
ImageCacheGeneratorInterface &generator,
|
TimeStampProviderInterface &timeStampProvider,
|
||||||
TimeStampProviderInterface &timeStampProvider)
|
ImageCacheCollectorInterface &collector)
|
||||||
: m_storage(storage)
|
: m_storage(storage)
|
||||||
, m_generator(generator)
|
|
||||||
, m_timeStampProvider(timeStampProvider)
|
, m_timeStampProvider(timeStampProvider)
|
||||||
|
, m_collector(collector)
|
||||||
{
|
{
|
||||||
m_backgroundThread = std::thread{[this] {
|
m_backgroundThread = std::thread{[this] {
|
||||||
while (isRunning()) {
|
while (isRunning()) {
|
||||||
@@ -45,8 +46,8 @@ AsynchronousImageFactory::AsynchronousImageFactory(ImageCacheStorageInterface &s
|
|||||||
entry->extraId,
|
entry->extraId,
|
||||||
std::move(entry->auxiliaryData),
|
std::move(entry->auxiliaryData),
|
||||||
m_storage,
|
m_storage,
|
||||||
m_generator,
|
m_timeStampProvider,
|
||||||
m_timeStampProvider);
|
m_collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForEntries();
|
waitForEntries();
|
||||||
@@ -107,30 +108,33 @@ void AsynchronousImageFactory::request(Utils::SmallStringView name,
|
|||||||
Utils::SmallStringView extraId,
|
Utils::SmallStringView extraId,
|
||||||
ImageCache::AuxiliaryData auxiliaryData,
|
ImageCache::AuxiliaryData auxiliaryData,
|
||||||
ImageCacheStorageInterface &storage,
|
ImageCacheStorageInterface &storage,
|
||||||
ImageCacheGeneratorInterface &generator,
|
TimeStampProviderInterface &timeStampProvider,
|
||||||
TimeStampProviderInterface &timeStampProvider)
|
ImageCacheCollectorInterface &collector)
|
||||||
{
|
{
|
||||||
const auto id = extraId.empty() ? Utils::PathString{name}
|
const auto id = extraId.empty() ? Utils::PathString{name}
|
||||||
: Utils::PathString::join({name, "+", extraId});
|
: Utils::PathString::join({name, "+", extraId});
|
||||||
|
|
||||||
const auto currentModifiedTime = timeStampProvider.timeStamp(name);
|
const auto currentModifiedTime = timeStampProvider.timeStamp(name);
|
||||||
const auto storageModifiedTime = storage.fetchModifiedImageTime(id);
|
const auto storageModifiedTime = storage.fetchModifiedImageTime(id);
|
||||||
|
const auto pause = timeStampProvider.pause();
|
||||||
|
|
||||||
if (currentModifiedTime == storageModifiedTime && storage.fetchHasImage(id))
|
if (currentModifiedTime < (storageModifiedTime + pause))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
generator.generateImage(name,
|
auto capture = [=](const QImage &image, const QImage &smallImage) {
|
||||||
|
m_storage.storeImage(id, currentModifiedTime, image, smallImage);
|
||||||
|
};
|
||||||
|
|
||||||
|
collector.start(name,
|
||||||
extraId,
|
extraId,
|
||||||
currentModifiedTime,
|
std::move(auxiliaryData),
|
||||||
ImageCache::CaptureImageWithSmallImageCallback{},
|
std::move(capture),
|
||||||
ImageCache::AbortCallback{},
|
ImageCache::AbortCallback{});
|
||||||
std::move(auxiliaryData));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsynchronousImageFactory::clean()
|
void AsynchronousImageFactory::clean()
|
||||||
{
|
{
|
||||||
clearEntries();
|
clearEntries();
|
||||||
m_generator.clean();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsynchronousImageFactory::wait()
|
void AsynchronousImageFactory::wait()
|
||||||
|
@@ -39,15 +39,14 @@ namespace QmlDesigner {
|
|||||||
|
|
||||||
class TimeStampProviderInterface;
|
class TimeStampProviderInterface;
|
||||||
class ImageCacheStorageInterface;
|
class ImageCacheStorageInterface;
|
||||||
class ImageCacheGeneratorInterface;
|
|
||||||
class ImageCacheCollectorInterface;
|
class ImageCacheCollectorInterface;
|
||||||
|
|
||||||
class AsynchronousImageFactory
|
class AsynchronousImageFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AsynchronousImageFactory(ImageCacheStorageInterface &storage,
|
AsynchronousImageFactory(ImageCacheStorageInterface &storage,
|
||||||
ImageCacheGeneratorInterface &generator,
|
TimeStampProviderInterface &timeStampProvider,
|
||||||
TimeStampProviderInterface &timeStampProvider);
|
ImageCacheCollectorInterface &collector);
|
||||||
|
|
||||||
~AsynchronousImageFactory();
|
~AsynchronousImageFactory();
|
||||||
|
|
||||||
@@ -83,8 +82,8 @@ private:
|
|||||||
Utils::SmallStringView extraId,
|
Utils::SmallStringView extraId,
|
||||||
ImageCache::AuxiliaryData auxiliaryData,
|
ImageCache::AuxiliaryData auxiliaryData,
|
||||||
ImageCacheStorageInterface &storage,
|
ImageCacheStorageInterface &storage,
|
||||||
ImageCacheGeneratorInterface &generator,
|
TimeStampProviderInterface &timeStampProvider,
|
||||||
TimeStampProviderInterface &timeStampProvider);
|
ImageCacheCollectorInterface &collector);
|
||||||
void wait();
|
void wait();
|
||||||
void clearEntries();
|
void clearEntries();
|
||||||
void stopThread();
|
void stopThread();
|
||||||
@@ -95,8 +94,8 @@ private:
|
|||||||
std::condition_variable m_condition;
|
std::condition_variable m_condition;
|
||||||
std::thread m_backgroundThread;
|
std::thread m_backgroundThread;
|
||||||
ImageCacheStorageInterface &m_storage;
|
ImageCacheStorageInterface &m_storage;
|
||||||
ImageCacheGeneratorInterface &m_generator;
|
|
||||||
TimeStampProviderInterface &m_timeStampProvider;
|
TimeStampProviderInterface &m_timeStampProvider;
|
||||||
|
ImageCacheCollectorInterface &m_collector;
|
||||||
bool m_finishing{false};
|
bool m_finishing{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -60,8 +60,10 @@ QString fileToString(const QString &filename)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ImageCacheCollector::ImageCacheCollector(ImageCacheConnectionManager &connectionManager)
|
ImageCacheCollector::ImageCacheCollector(ImageCacheConnectionManager &connectionManager,
|
||||||
|
ImageCacheCollectorNullImageHandling nullImageHandling)
|
||||||
: m_connectionManager{connectionManager}
|
: m_connectionManager{connectionManager}
|
||||||
|
, nullImageHandling{nullImageHandling}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ImageCacheCollector::~ImageCacheCollector() = default;
|
ImageCacheCollector::~ImageCacheCollector() = default;
|
||||||
@@ -89,6 +91,7 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
|
|||||||
model->setRewriterView(&rewriterView);
|
model->setRewriterView(&rewriterView);
|
||||||
|
|
||||||
if (rewriterView.inErrorState() || !rewriterView.rootModelNode().metaInfo().isGraphicalItem()) {
|
if (rewriterView.inErrorState() || !rewriterView.rootModelNode().metaInfo().isGraphicalItem()) {
|
||||||
|
if (abortCallback)
|
||||||
abortCallback(ImageCache::AbortReason::Failed);
|
abortCallback(ImageCache::AbortReason::Failed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -98,12 +101,14 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
|
|||||||
if (stateNode.isValid())
|
if (stateNode.isValid())
|
||||||
rewriterView.setCurrentStateNode(stateNode);
|
rewriterView.setCurrentStateNode(stateNode);
|
||||||
|
|
||||||
auto callback = [captureCallback = std::move(captureCallback)](const QImage &image) {
|
auto callback = [=, captureCallback = std::move(captureCallback)](const QImage &image) {
|
||||||
|
if (nullImageHandling == ImageCacheCollectorNullImageHandling::CaptureNullImage
|
||||||
|
|| !image.isNull()) {
|
||||||
QSize smallImageSize = image.size().scaled(QSize{96, 96}.boundedTo(image.size()),
|
QSize smallImageSize = image.size().scaled(QSize{96, 96}.boundedTo(image.size()),
|
||||||
Qt::KeepAspectRatio);
|
Qt::KeepAspectRatio);
|
||||||
QImage smallImage = image.isNull() ? QImage{} : image.scaled(smallImageSize);
|
QImage smallImage = image.isNull() ? QImage{} : image.scaled(smallImageSize);
|
||||||
|
|
||||||
captureCallback(image, smallImage);
|
captureCallback(image, smallImage);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!m_target)
|
if (!m_target)
|
||||||
@@ -122,29 +127,21 @@ void ImageCacheCollector::start(Utils::SmallStringView name,
|
|||||||
model->setNodeInstanceView({});
|
model->setNodeInstanceView({});
|
||||||
model->setRewriterView({});
|
model->setRewriterView({});
|
||||||
|
|
||||||
if (!capturedDataArrived)
|
if (!capturedDataArrived && abortCallback)
|
||||||
abortCallback(ImageCache::AbortReason::Failed);
|
abortCallback(ImageCache::AbortReason::Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<QImage, QImage> ImageCacheCollector::createImage(Utils::SmallStringView filePath,
|
std::pair<QImage, QImage> ImageCacheCollector::createImage(Utils::SmallStringView,
|
||||||
Utils::SmallStringView state,
|
Utils::SmallStringView,
|
||||||
const ImageCache::AuxiliaryData &auxiliaryData)
|
const ImageCache::AuxiliaryData &)
|
||||||
{
|
{
|
||||||
Q_UNUSED(filePath)
|
|
||||||
Q_UNUSED(state)
|
|
||||||
Q_UNUSED(auxiliaryData)
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon ImageCacheCollector::createIcon(Utils::SmallStringView filePath,
|
QIcon ImageCacheCollector::createIcon(Utils::SmallStringView,
|
||||||
Utils::SmallStringView state,
|
Utils::SmallStringView,
|
||||||
const ImageCache::AuxiliaryData &auxiliaryData)
|
const ImageCache::AuxiliaryData &)
|
||||||
{
|
{
|
||||||
Q_UNUSED(filePath)
|
|
||||||
Q_UNUSED(state)
|
|
||||||
Q_UNUSED(auxiliaryData)
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,10 +45,13 @@ class ImageCacheConnectionManager;
|
|||||||
class RewriterView;
|
class RewriterView;
|
||||||
class NodeInstanceView;
|
class NodeInstanceView;
|
||||||
|
|
||||||
|
enum class ImageCacheCollectorNullImageHandling { CaptureNullImage, DontCaptureNullImage };
|
||||||
|
|
||||||
class ImageCacheCollector final : public ImageCacheCollectorInterface
|
class ImageCacheCollector final : public ImageCacheCollectorInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageCacheCollector(ImageCacheConnectionManager &connectionManager);
|
ImageCacheCollector(ImageCacheConnectionManager &connectionManager,
|
||||||
|
ImageCacheCollectorNullImageHandling nullImageHandling = {});
|
||||||
|
|
||||||
~ImageCacheCollector();
|
~ImageCacheCollector();
|
||||||
|
|
||||||
@@ -72,6 +75,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
ImageCacheConnectionManager &m_connectionManager;
|
ImageCacheConnectionManager &m_connectionManager;
|
||||||
QPointer<ProjectExplorer::Target> m_target;
|
QPointer<ProjectExplorer::Target> m_target;
|
||||||
|
ImageCacheCollectorNullImageHandling nullImageHandling{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -33,6 +33,7 @@ class TimeStampProvider : public TimeStampProviderInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sqlite::TimeStamp timeStamp(Utils::SmallStringView name) const override;
|
Sqlite::TimeStamp timeStamp(Utils::SmallStringView name) const override;
|
||||||
|
Sqlite::TimeStamp pause() const override { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -36,6 +36,7 @@ class TimeStampProviderInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Sqlite::TimeStamp timeStamp(Utils::SmallStringView name) const = 0;
|
virtual Sqlite::TimeStamp timeStamp(Utils::SmallStringView name) const = 0;
|
||||||
|
virtual Sqlite::TimeStamp pause() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~TimeStampProviderInterface() = default;
|
~TimeStampProviderInterface() = default;
|
||||||
|
@@ -137,6 +137,7 @@ void BaseConnectionManager::callCrashCallback()
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock{m_callbackMutex};
|
std::lock_guard<std::mutex> lock{m_callbackMutex};
|
||||||
|
|
||||||
|
if (m_crashCallback)
|
||||||
m_crashCallback();
|
m_crashCallback();
|
||||||
}
|
}
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -50,7 +50,7 @@
|
|||||||
#include <imagecache/imagecacheconnectionmanager.h>
|
#include <imagecache/imagecacheconnectionmanager.h>
|
||||||
#include <imagecache/imagecachegenerator.h>
|
#include <imagecache/imagecachegenerator.h>
|
||||||
#include <imagecache/imagecachestorage.h>
|
#include <imagecache/imagecachestorage.h>
|
||||||
#include <imagecache/timestampprovider.h>
|
#include <imagecache/timestampproviderinterface.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
@@ -70,6 +70,23 @@ QString defaultImagePath()
|
|||||||
return qobject_cast<::QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
|
return qobject_cast<::QmlProjectManager::QmlBuildSystem *>(target->buildSystem());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TimeStampProvider : public TimeStampProviderInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sqlite::TimeStamp timeStamp(Utils::SmallStringView) const override
|
||||||
|
{
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
return std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
Sqlite::TimeStamp pause() const override
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
return std::chrono::duration_cast<std::chrono::seconds>(1h).count();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class PreviewImageCacheData
|
class PreviewImageCacheData
|
||||||
@@ -81,11 +98,11 @@ public:
|
|||||||
Sqlite::LockingMode::Normal};
|
Sqlite::LockingMode::Normal};
|
||||||
ImageCacheStorage<Sqlite::Database> storage{database};
|
ImageCacheStorage<Sqlite::Database> storage{database};
|
||||||
ImageCacheConnectionManager connectionManager;
|
ImageCacheConnectionManager connectionManager;
|
||||||
ImageCacheCollector collector{connectionManager};
|
ImageCacheCollector collector{connectionManager,
|
||||||
ImageCacheGenerator generator{collector, storage};
|
ImageCacheCollectorNullImageHandling::DontCaptureNullImage};
|
||||||
TimeStampProvider timeStampProvider;
|
TimeStampProvider timeStampProvider;
|
||||||
AsynchronousExplicitImageCache cache{storage};
|
AsynchronousExplicitImageCache cache{storage};
|
||||||
AsynchronousImageFactory factory{storage, generator, timeStampProvider};
|
AsynchronousImageFactory factory{storage, timeStampProvider, collector};
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlDesignerProjectManagerProjectData
|
class QmlDesignerProjectManagerProjectData
|
||||||
@@ -155,8 +172,10 @@ void QmlDesignerProjectManager::projectAdded(::ProjectExplorer::Project *project
|
|||||||
|
|
||||||
void QmlDesignerProjectManager::aboutToRemoveProject(::ProjectExplorer::Project *)
|
void QmlDesignerProjectManager::aboutToRemoveProject(::ProjectExplorer::Project *)
|
||||||
{
|
{
|
||||||
|
if (m_projectData) {
|
||||||
m_imageCacheData->collector.setTarget(m_projectData->activeTarget);
|
m_imageCacheData->collector.setTarget(m_projectData->activeTarget);
|
||||||
m_projectData.reset();
|
m_projectData.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesignerProjectManager::projectRemoved(::ProjectExplorer::Project *) {}
|
void QmlDesignerProjectManager::projectRemoved(::ProjectExplorer::Project *) {}
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include "qdsnewdialog.h"
|
#include "qdsnewdialog.h"
|
||||||
|
|
||||||
|
#include <app/app_version.h>
|
||||||
|
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/dialogs/restartdialog.h>
|
#include <coreplugin/dialogs/restartdialog.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -268,6 +270,24 @@ int ProjectModel::rowCount(const QModelIndex &) const
|
|||||||
return ProjectExplorer::ProjectExplorerPlugin::recentProjects().count();
|
return ProjectExplorer::ProjectExplorerPlugin::recentProjects().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString getQDSVersion(const QString &projectFilePath)
|
||||||
|
{
|
||||||
|
const QString defaultReturn = "";
|
||||||
|
Utils::FileReader reader;
|
||||||
|
if (!reader.fetch(Utils::FilePath::fromString(projectFilePath)))
|
||||||
|
return defaultReturn;
|
||||||
|
|
||||||
|
const QByteArray data = reader.data();
|
||||||
|
|
||||||
|
QRegularExpression regexp(R"x(qdsVersion: "(.*)")x");
|
||||||
|
QRegularExpressionMatch match = regexp.match(QString::fromUtf8(data));
|
||||||
|
|
||||||
|
if (!match.hasMatch())
|
||||||
|
return defaultReturn;
|
||||||
|
|
||||||
|
return ProjectModel::tr("Created with Qt Design Studio version: %1").arg(match.captured(1));
|
||||||
|
}
|
||||||
|
|
||||||
QString getMainQmlFile(const QString &projectFilePath)
|
QString getMainQmlFile(const QString &projectFilePath)
|
||||||
{
|
{
|
||||||
const QString defaultReturn = "content/App.qml";
|
const QString defaultReturn = "content/App.qml";
|
||||||
@@ -293,8 +313,8 @@ QString appQmlFile(const QString &projectFilePath)
|
|||||||
|
|
||||||
static QString fromCamelCase(const QString &s) {
|
static QString fromCamelCase(const QString &s) {
|
||||||
|
|
||||||
static QRegularExpression regExp1 {"(.)([A-Z][a-z]+)"};
|
const QRegularExpression regExp1 {"(.)([A-Z][a-z]+)"};
|
||||||
static QRegularExpression regExp2 {"([a-z0-9])([A-Z])"};
|
const QRegularExpression regExp2 {"([a-z0-9])([A-Z])"};
|
||||||
QString result = s;
|
QString result = s;
|
||||||
result.replace(regExp1, "\\1 \\2");
|
result.replace(regExp1, "\\1 \\2");
|
||||||
result.replace(regExp2, "\\1 \\2");
|
result.replace(regExp2, "\\1 \\2");
|
||||||
@@ -302,15 +322,49 @@ static QString fromCamelCase(const QString &s) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString resolutionFromConstants(const QString &projectFilePath)
|
||||||
|
{
|
||||||
|
const QFileInfo fileInfo(projectFilePath);
|
||||||
|
const QString fileName = fileInfo.dir().absolutePath()
|
||||||
|
+ "/" + "imports" + "/" + fileInfo.baseName() + "/Constants.qml";
|
||||||
|
|
||||||
|
Utils::FileReader reader;
|
||||||
|
if (!reader.fetch(Utils::FilePath::fromString(fileName)))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const QByteArray data = reader.data();
|
||||||
|
|
||||||
|
const QRegularExpression regexpWidth(R"x(readonly\s+property\s+int\s+width:\s+(\d*))x");
|
||||||
|
const QRegularExpression regexpHeight(R"x(readonly\s+property\s+int\s+height:\s+(\d*))x");
|
||||||
|
|
||||||
|
int width = -1;
|
||||||
|
int height = -1;
|
||||||
|
|
||||||
|
QRegularExpressionMatch match = regexpHeight.match(QString::fromUtf8(data));
|
||||||
|
if (match.hasMatch())
|
||||||
|
height = match.captured(1).toInt();
|
||||||
|
|
||||||
|
match = regexpWidth.match(QString::fromUtf8(data));
|
||||||
|
if (match.hasMatch())
|
||||||
|
width = match.captured(1).toInt();
|
||||||
|
|
||||||
|
if (width > 0 && height > 0)
|
||||||
|
return ProjectModel::tr("Resolution: %1x%2").arg(width).arg(height);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static QString description(const QString &projectFilePath)
|
static QString description(const QString &projectFilePath)
|
||||||
{
|
{
|
||||||
|
|
||||||
const QString created = "Created: " +
|
const QString created = ProjectModel::tr("Created: %1").arg(
|
||||||
QFileInfo(projectFilePath).fileTime(QFileDevice::FileBirthTime).toString();
|
QFileInfo(projectFilePath).fileTime(QFileDevice::FileBirthTime).toString());
|
||||||
const QString lastEdited = "Last Edited: " +
|
const QString lastEdited = ProjectModel::tr("Last Edited: %1").arg(
|
||||||
QFileInfo(projectFilePath).fileTime(QFileDevice::FileModificationTime).toString();
|
QFileInfo(projectFilePath).fileTime(QFileDevice::FileModificationTime).toString());
|
||||||
|
|
||||||
return fromCamelCase(QFileInfo(projectFilePath).baseName()) + "\n" + created + "\n" + lastEdited;
|
return fromCamelCase(QFileInfo(projectFilePath).baseName()) + "\n\n" + created + "\n" + lastEdited
|
||||||
|
+ "\n" + resolutionFromConstants(projectFilePath)
|
||||||
|
+ "\n" + getQDSVersion(projectFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString tags(const QString &projectFilePath)
|
static QString tags(const QString &projectFilePath)
|
||||||
@@ -438,6 +492,26 @@ bool StudioWelcomePlugin::initialize(const QStringList &arguments, QString *erro
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool showSplashScreen()
|
||||||
|
{
|
||||||
|
const QString lastQDSVersionEntry = "QML/Designer/lastQDSVersion";
|
||||||
|
|
||||||
|
QSettings *settings = Core::ICore::settings();
|
||||||
|
|
||||||
|
const QString lastQDSVersion = settings->value(lastQDSVersionEntry).toString();
|
||||||
|
|
||||||
|
|
||||||
|
const QString currentVersion = Core::Constants::IDE_VERSION_DISPLAY;
|
||||||
|
|
||||||
|
if (currentVersion != lastQDSVersion) {
|
||||||
|
settings->setValue(lastQDSVersionEntry, currentVersion);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
|
||||||
|
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
void StudioWelcomePlugin::extensionsInitialized()
|
void StudioWelcomePlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
Core::ModeManager::activateMode(m_welcomeMode->id());
|
Core::ModeManager::activateMode(m_welcomeMode->id());
|
||||||
@@ -445,8 +519,7 @@ void StudioWelcomePlugin::extensionsInitialized()
|
|||||||
// Enable QDS new project dialog
|
// Enable QDS new project dialog
|
||||||
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
|
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
|
||||||
|
|
||||||
if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
|
if (showSplashScreen()) {
|
||||||
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
|
|
||||||
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
|
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
|
||||||
s_view = new QQuickWidget(Core::ICore::dialogParent());
|
s_view = new QQuickWidget(Core::ICore::dialogParent());
|
||||||
s_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
s_view->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||||
@@ -532,6 +605,8 @@ WelcomeMode::WelcomeMode()
|
|||||||
setContextHelp("Qt Design Studio Manual");
|
setContextHelp("Qt Design Studio Manual");
|
||||||
setContext(Core::Context(Core::Constants::C_WELCOME_MODE));
|
setContext(Core::Context(Core::Constants::C_WELCOME_MODE));
|
||||||
|
|
||||||
|
QFontDatabase::addApplicationFont(":/studiofonts/TitilliumWeb-Regular.ttf");
|
||||||
|
|
||||||
m_modeWidget = new QQuickWidget;
|
m_modeWidget = new QQuickWidget;
|
||||||
m_modeWidget->setMinimumSize(1024, 768);
|
m_modeWidget->setMinimumSize(1024, 768);
|
||||||
m_modeWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
m_modeWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "googletest.h"
|
#include "googletest.h"
|
||||||
|
|
||||||
|
#include "imagecachecollectormock.h"
|
||||||
#include "mockimagecachegenerator.h"
|
#include "mockimagecachegenerator.h"
|
||||||
#include "mockimagecachestorage.h"
|
#include "mockimagecachestorage.h"
|
||||||
#include "mocktimestampprovider.h"
|
#include "mocktimestampprovider.h"
|
||||||
@@ -41,67 +42,64 @@ class AsynchronousImageFactory : public testing::Test
|
|||||||
protected:
|
protected:
|
||||||
AsynchronousImageFactory()
|
AsynchronousImageFactory()
|
||||||
{
|
{
|
||||||
ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
ON_CALL(timeStampProviderMock, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
.WillByDefault(Return(Sqlite::TimeStamp{123}));
|
.WillByDefault(Return(Sqlite::TimeStamp{123}));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Notification notification;
|
Notification notification;
|
||||||
Notification waitInThread;
|
Notification waitInThread;
|
||||||
NiceMock<MockImageCacheStorage> mockStorage;
|
NiceMock<MockImageCacheStorage> storageMock;
|
||||||
NiceMock<MockImageCacheGenerator> mockGenerator;
|
NiceMock<ImageCacheCollectorMock> collectorMock;
|
||||||
NiceMock<MockTimeStampProvider> mockTimeStampProvider;
|
NiceMock<MockTimeStampProvider> timeStampProviderMock;
|
||||||
QmlDesigner::AsynchronousImageFactory factory{mockStorage, mockGenerator, mockTimeStampProvider};
|
QmlDesigner::AsynchronousImageFactory factory{storageMock, timeStampProviderMock, collectorMock};
|
||||||
QImage image1{10, 10, QImage::Format_ARGB32};
|
QImage image1{10, 10, QImage::Format_ARGB32};
|
||||||
QImage smallImage1{1, 1, QImage::Format_ARGB32};
|
QImage smallImage1{1, 1, QImage::Format_ARGB32};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, RequestImageRequestImageFromGenerator)
|
TEST_F(AsynchronousImageFactory, RequestImageRequestImageFromCollector)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockGenerator,
|
EXPECT_CALL(collectorMock,
|
||||||
generateImage(Eq("/path/to/Component.qml"),
|
start(Eq("/path/to/Component.qml"),
|
||||||
IsEmpty(),
|
IsEmpty(),
|
||||||
Eq(Sqlite::TimeStamp{123}),
|
VariantWith<Utils::monostate>(Utils::monostate{}),
|
||||||
_,
|
_,
|
||||||
_,
|
_))
|
||||||
VariantWith<Utils::monostate>(Utils::monostate{})))
|
.WillRepeatedly([&](auto, auto, auto, auto, auto) { notification.notify(); });
|
||||||
.WillRepeatedly([&](auto, auto, auto, auto, auto, auto) { notification.notify(); });
|
|
||||||
|
|
||||||
factory.generate("/path/to/Component.qml");
|
factory.generate("/path/to/Component.qml");
|
||||||
notification.wait();
|
notification.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, RequestImageWithExtraIdRequestImageFromGenerator)
|
TEST_F(AsynchronousImageFactory, RequestImageWithExtraIdRequestImageFromCollector)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockGenerator,
|
EXPECT_CALL(collectorMock,
|
||||||
generateImage(Eq("/path/to/Component.qml"),
|
start(Eq("/path/to/Component.qml"),
|
||||||
Eq("foo"),
|
Eq("foo"),
|
||||||
Eq(Sqlite::TimeStamp{123}),
|
VariantWith<Utils::monostate>(Utils::monostate{}),
|
||||||
_,
|
_,
|
||||||
_,
|
_))
|
||||||
VariantWith<Utils::monostate>(Utils::monostate{})))
|
.WillRepeatedly([&](auto, auto, auto, auto, auto) { notification.notify(); });
|
||||||
.WillRepeatedly([&](auto, auto, auto, auto, auto, auto) { notification.notify(); });
|
|
||||||
|
|
||||||
factory.generate("/path/to/Component.qml", "foo");
|
factory.generate("/path/to/Component.qml", "foo");
|
||||||
notification.wait();
|
notification.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, RequestImageWithAuxiliaryDataRequestImageFromGenerator)
|
TEST_F(AsynchronousImageFactory, RequestImageWithAuxiliaryDataRequestImageFromCollector)
|
||||||
{
|
{
|
||||||
std::vector<QSize> sizes{{20, 11}};
|
std::vector<QSize> sizes{{20, 11}};
|
||||||
|
|
||||||
EXPECT_CALL(mockGenerator,
|
EXPECT_CALL(collectorMock,
|
||||||
generateImage(Eq("/path/to/Component.qml"),
|
start(Eq("/path/to/Component.qml"),
|
||||||
Eq("foo"),
|
Eq("foo"),
|
||||||
Eq(Sqlite::TimeStamp{123}),
|
VariantWith<FontCollectorSizesAuxiliaryData>(
|
||||||
_,
|
AllOf(Field(&FontCollectorSizesAuxiliaryData::sizes,
|
||||||
_,
|
|
||||||
VariantWith<FontCollectorSizesAuxiliaryData>(AllOf(
|
|
||||||
Field(&FontCollectorSizesAuxiliaryData::sizes,
|
|
||||||
ElementsAre(QSize{20, 11})),
|
ElementsAre(QSize{20, 11})),
|
||||||
Field(&FontCollectorSizesAuxiliaryData::colorName, Eq(u"color")),
|
Field(&FontCollectorSizesAuxiliaryData::colorName, Eq(u"color")),
|
||||||
Field(&FontCollectorSizesAuxiliaryData::text, Eq(u"some text"))))))
|
Field(&FontCollectorSizesAuxiliaryData::text, Eq(u"some text")))),
|
||||||
.WillRepeatedly([&](auto, auto, auto, auto, auto, auto) { notification.notify(); });
|
_,
|
||||||
|
_))
|
||||||
|
.WillRepeatedly([&](auto, auto, auto, auto, auto) { notification.notify(); });
|
||||||
|
|
||||||
factory.generate("/path/to/Component.qml",
|
factory.generate("/path/to/Component.qml",
|
||||||
"foo",
|
"foo",
|
||||||
@@ -111,40 +109,34 @@ TEST_F(AsynchronousImageFactory, RequestImageWithAuxiliaryDataRequestImageFromGe
|
|||||||
notification.wait();
|
notification.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, DontRequestImageRequestImageFromGeneratorIfFileWasNotUpdated)
|
TEST_F(AsynchronousImageFactory, DontRequestImageRequestImageFromCollectorIfFileWasUpdatedRecently)
|
||||||
{
|
{
|
||||||
ON_CALL(mockStorage, fetchHasImage(Eq("/path/to/Component.qml"))).WillByDefault([&](auto) {
|
ON_CALL(storageMock, fetchModifiedImageTime(Eq("/path/to/Component.qml"))).WillByDefault([&](auto) {
|
||||||
notification.notify();
|
notification.notify();
|
||||||
return true;
|
return Sqlite::TimeStamp{124};
|
||||||
});
|
});
|
||||||
ON_CALL(mockStorage, fetchModifiedImageTime(Eq("/path/to/Component.qml")))
|
ON_CALL(timeStampProviderMock, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
.WillByDefault(Return(Sqlite::TimeStamp{124}));
|
.WillByDefault(Return(Sqlite::TimeStamp{125}));
|
||||||
ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
ON_CALL(timeStampProviderMock, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
.WillByDefault(Return(Sqlite::TimeStamp{124}));
|
.WillByDefault(Return(Sqlite::TimeStamp{1}));
|
||||||
|
|
||||||
EXPECT_CALL(mockGenerator, generateImage(_, _, _, _, _, _)).Times(0);
|
EXPECT_CALL(collectorMock, start(_, _, _, _, _)).Times(0);
|
||||||
|
|
||||||
factory.generate("/path/to/Component.qml");
|
factory.generate("/path/to/Component.qml");
|
||||||
notification.wait();
|
notification.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory,
|
TEST_F(AsynchronousImageFactory, RequestImageRequestImageFromCollectorIfFileWasNotUpdatedRecently)
|
||||||
RequestImageRequestImageFromGeneratorIfFileWasNotUpdatedButTheImageIsNull)
|
|
||||||
{
|
{
|
||||||
ON_CALL(mockStorage, fetchHasImage(Eq("/path/to/Component.qml"))).WillByDefault(Return(false));
|
ON_CALL(storageMock, fetchModifiedImageTime(Eq("/path/to/Component.qml")))
|
||||||
ON_CALL(mockStorage, fetchModifiedImageTime(Eq("/path/to/Component.qml")))
|
.WillByDefault(Return(Sqlite::TimeStamp{123}));
|
||||||
.WillByDefault(Return(Sqlite::TimeStamp{124}));
|
ON_CALL(timeStampProviderMock, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
.WillByDefault(Return(Sqlite::TimeStamp{125}));
|
||||||
.WillByDefault(Return(Sqlite::TimeStamp{124}));
|
ON_CALL(timeStampProviderMock, pause()).WillByDefault(Return(Sqlite::TimeStamp{1}));
|
||||||
|
|
||||||
EXPECT_CALL(mockGenerator,
|
EXPECT_CALL(collectorMock, start(_, _, _, _, _)).WillOnce([&](auto, auto, auto, auto, auto) {
|
||||||
generateImage(Eq("/path/to/Component.qml"),
|
notification.notify();
|
||||||
IsEmpty(),
|
});
|
||||||
Eq(Sqlite::TimeStamp{124}),
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
VariantWith<Utils::monostate>(Utils::monostate{})))
|
|
||||||
.WillRepeatedly([&](auto, auto, auto, auto, auto, auto) { notification.notify(); });
|
|
||||||
|
|
||||||
factory.generate("/path/to/Component.qml");
|
factory.generate("/path/to/Component.qml");
|
||||||
notification.wait();
|
notification.wait();
|
||||||
@@ -152,39 +144,57 @@ TEST_F(AsynchronousImageFactory,
|
|||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, CleanRemovesEntries)
|
TEST_F(AsynchronousImageFactory, CleanRemovesEntries)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component1.qml"), _, _, _, _, _))
|
EXPECT_CALL(collectorMock, start(Eq("/path/to/Component1.qml"), _, _, _, _))
|
||||||
.WillRepeatedly([&](auto, auto, auto, auto, auto, auto) { waitInThread.wait(); });
|
.WillRepeatedly([&](auto, auto, auto, auto, auto) { waitInThread.wait(); });
|
||||||
factory.generate("/path/to/Component1.qml");
|
factory.generate("/path/to/Component1.qml");
|
||||||
|
|
||||||
EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component3.qml"), _, _, _, _, _)).Times(0);
|
EXPECT_CALL(collectorMock, start(Eq("/path/to/Component3.qml"), _, _, _, _)).Times(0);
|
||||||
|
|
||||||
factory.generate("/path/to/Component3.qml");
|
factory.generate("/path/to/Component3.qml");
|
||||||
factory.clean();
|
factory.clean();
|
||||||
waitInThread.notify();
|
waitInThread.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, CleanCallsGeneratorClean)
|
|
||||||
{
|
|
||||||
EXPECT_CALL(mockGenerator, clean()).Times(AtLeast(1));
|
|
||||||
|
|
||||||
factory.clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(AsynchronousImageFactory, AfterCleanNewJobsWorks)
|
TEST_F(AsynchronousImageFactory, AfterCleanNewJobsWorks)
|
||||||
{
|
{
|
||||||
factory.clean();
|
factory.clean();
|
||||||
|
|
||||||
EXPECT_CALL(mockGenerator,
|
EXPECT_CALL(collectorMock,
|
||||||
generateImage(Eq("/path/to/Component.qml"),
|
start(Eq("/path/to/Component.qml"),
|
||||||
IsEmpty(),
|
IsEmpty(),
|
||||||
Eq(Sqlite::TimeStamp{123}),
|
VariantWith<Utils::monostate>(Utils::monostate{}),
|
||||||
_,
|
_,
|
||||||
_,
|
_))
|
||||||
VariantWith<Utils::monostate>(Utils::monostate{})))
|
.WillRepeatedly([&](auto, auto, auto, auto, auto) { notification.notify(); });
|
||||||
.WillRepeatedly([&](auto, auto, auto, auto, auto, auto) { notification.notify(); });
|
|
||||||
|
|
||||||
factory.generate("/path/to/Component.qml");
|
factory.generate("/path/to/Component.qml");
|
||||||
notification.wait();
|
notification.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(AsynchronousImageFactory, CaptureImageCallbackStoresImage)
|
||||||
|
{
|
||||||
|
ON_CALL(storageMock, fetchModifiedImageTime(Eq("/path/to/Component.qml")))
|
||||||
|
.WillByDefault(Return(Sqlite::TimeStamp{123}));
|
||||||
|
ON_CALL(timeStampProviderMock, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
|
.WillByDefault(Return(Sqlite::TimeStamp{125}));
|
||||||
|
ON_CALL(timeStampProviderMock, pause()).WillByDefault(Return(Sqlite::TimeStamp{1}));
|
||||||
|
ON_CALL(collectorMock,
|
||||||
|
start(Eq("/path/to/Component.qml"),
|
||||||
|
Eq("id"),
|
||||||
|
VariantWith<Utils::monostate>(Utils::monostate{}),
|
||||||
|
_,
|
||||||
|
_))
|
||||||
|
.WillByDefault([&](auto, auto, auto, auto capture, auto) { capture(image1, smallImage1); });
|
||||||
|
|
||||||
|
EXPECT_CALL(storageMock,
|
||||||
|
storeImage(Eq("/path/to/Component.qml+id"),
|
||||||
|
Sqlite::TimeStamp{125},
|
||||||
|
Eq(image1),
|
||||||
|
Eq(smallImage1)))
|
||||||
|
.WillOnce([&](auto, auto, auto, auto) { notification.notify(); });
|
||||||
|
|
||||||
|
factory.generate("/path/to/Component.qml", "id");
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@@ -33,4 +33,5 @@ class MockTimeStampProvider : public QmlDesigner::TimeStampProviderInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(Sqlite::TimeStamp, timeStamp, (Utils::SmallStringView name), (const, override));
|
MOCK_METHOD(Sqlite::TimeStamp, timeStamp, (Utils::SmallStringView name), (const, override));
|
||||||
|
MOCK_METHOD(Sqlite::TimeStamp, pause, (), (const, override));
|
||||||
};
|
};
|
||||||
|