Merge remote-tracking branch 'origin/6.0'
Conflicts: cmake/QtCreatorIDEBranding.cmake qbs/modules/qtc/qtc.qbs qtcreator_ide_branding.pri Change-Id: I366a1a0e378811dfc9b4e6f42ec96426dbb15356
2
.github/workflows/build_cmake.yml
vendored
@@ -9,7 +9,7 @@ env:
|
|||||||
CMAKE_VERSION: 3.21.1
|
CMAKE_VERSION: 3.21.1
|
||||||
NINJA_VERSION: 1.10.2
|
NINJA_VERSION: 1.10.2
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
CCACHE_VERSION: 4.4
|
CCACHE_VERSION: 4.5
|
||||||
QT_MIRRORS: download.qt.io;mirrors.ocf.berkeley.edu/qt;ftp.fau.de/qtproject;mirror.bit.edu.cn/qtproject
|
QT_MIRRORS: download.qt.io;mirrors.ocf.berkeley.edu/qt;ftp.fau.de/qtproject;mirror.bit.edu.cn/qtproject
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
BIN
doc/qtcreator/images/qtcreator-autotests-options-ctest.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8.2 KiB |
@@ -38,13 +38,20 @@
|
|||||||
build system and uses it or even the build system as such to execute the
|
build system and uses it or even the build system as such to execute the
|
||||||
respective tests.
|
respective tests.
|
||||||
|
|
||||||
\QC integrates the \l{Qt Test} framework,
|
\QC integrates the following testing frameworks for unit testing
|
||||||
\l{https://github.com/google/googletest}{Google C++ Testing Framework},
|
applications and libraries:
|
||||||
\l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
|
|
||||||
{Boost.Test}, and \l{https://github.com/catchorg/Catch2}
|
\list
|
||||||
{Catch2 test framework} for unit testing applications and libraries.
|
\li \l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
|
||||||
|
{Boost.Test}
|
||||||
|
\li \l{https://github.com/catchorg/Catch2}{Catch2 test framework}
|
||||||
|
\li \l{https://github.com/google/googletest}{Google C++ Testing Framework}
|
||||||
|
\li \l{Qt Test} framework
|
||||||
|
\endlist
|
||||||
|
|
||||||
Additional build system based support is provided for
|
Additional build system based support is provided for
|
||||||
\l{https://cmake.org/cmake/help/latest/manual/ctest.1.html}{CTest}.
|
\l{https://cmake.org/cmake/help/latest/manual/ctest.1.html}{CTest}.
|
||||||
|
|
||||||
You can use \QC to create, build, and run code based tests for your
|
You can use \QC to create, build, and run code based tests for your
|
||||||
projects.
|
projects.
|
||||||
|
|
||||||
@@ -332,16 +339,23 @@
|
|||||||
in the file currently open in the code editor.
|
in the file currently open in the code editor.
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\note By default, \QC builds a project before deploying and running
|
\endlist
|
||||||
it.
|
|
||||||
|
By default, \QC builds a project before deploying and running it.
|
||||||
|
To run all tests without building and deploying them again, select
|
||||||
|
\uicontrol {Run All Tests Without Deployment} in the context menu.
|
||||||
|
To run the selected tests without deployment, select
|
||||||
|
\uicontrol {Run Selected Tests Without Deployment}.
|
||||||
|
|
||||||
|
The functions to run tests are also available in the context menu in the
|
||||||
|
\uicontrol Tests view and in \uicontrol Tools > \uicontrol Tests.
|
||||||
|
|
||||||
\note If you have enabled build system based and code based tests,
|
\note If you have enabled build system based and code based tests,
|
||||||
you may run tests twice when using \uicontrol {Run All Tests} or
|
you may run tests twice when using \uicontrol {Run All Tests} or
|
||||||
\uicontrol {Run Selected Tests}. This happens if the tests can be
|
\uicontrol {Run Selected Tests}. This happens if the tests can be
|
||||||
found by the code based test frameworks and are registered as test
|
found by the code based test frameworks and are registered as test
|
||||||
with the build system.
|
with the build system.
|
||||||
|
|
||||||
\endlist
|
|
||||||
|
|
||||||
If a test takes more than a minute to execute, the default timeout might
|
If a test takes more than a minute to execute, the default timeout might
|
||||||
stop the test execution. To increase the timeout, select \uicontrol Tools >
|
stop the test execution. To increase the timeout, select \uicontrol Tools >
|
||||||
\uicontrol Options > \uicontrol {Testing} > \uicontrol General.
|
\uicontrol Options > \uicontrol {Testing} > \uicontrol General.
|
||||||
@@ -369,7 +383,8 @@
|
|||||||
|
|
||||||
The test cases are listed in alphabetic, case insensitive order. To list
|
The test cases are listed in alphabetic, case insensitive order. To list
|
||||||
them in the order in which they are defined in the source code,
|
them in the order in which they are defined in the source code,
|
||||||
select \inlineimage leafsort.png (\uicontrol {Sort Naturally}).
|
select \inlineimage leafsort.png
|
||||||
|
(\uicontrol {Sort Naturally}).
|
||||||
|
|
||||||
\section2 Running and Debugging Tests from Code Editor
|
\section2 Running and Debugging Tests from Code Editor
|
||||||
|
|
||||||
@@ -511,7 +526,7 @@
|
|||||||
\li To specify settings for running Catch2 tests, select
|
\li To specify settings for running Catch2 tests, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
|
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
|
||||||
\uicontrol {Catch Test}.
|
\uicontrol {Catch Test}.
|
||||||
\image qtcreator-autotests-options-catch2.png
|
\image qtcreator-autotests-options-catch2.png "Catch Test options"
|
||||||
\li Select the \uicontrol {Show success} check box to show succeeding
|
\li Select the \uicontrol {Show success} check box to show succeeding
|
||||||
expressions as well. By default Catch2 will print only fails.
|
expressions as well. By default Catch2 will print only fails.
|
||||||
\li Select the \uicontrol {Break on failure while debugging} check box
|
\li Select the \uicontrol {Break on failure while debugging} check box
|
||||||
@@ -543,7 +558,7 @@
|
|||||||
\li To specify settings for running CTest-based tests, select
|
\li To specify settings for running CTest-based tests, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
|
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
|
||||||
\uicontrol {CTest}.
|
\uicontrol {CTest}.
|
||||||
//! insert image here
|
\image qtcreator-autotests-options-ctest.png "CTest options"
|
||||||
\li Select the \uicontrol {Output on failure} check box to show test
|
\li Select the \uicontrol {Output on failure} check box to show test
|
||||||
specific output if a test fails. Contrary to the CTest default
|
specific output if a test fails. Contrary to the CTest default
|
||||||
this is enabled by default.
|
this is enabled by default.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2020 The Qt Company Ltd.
|
** Copyright (C) 2021 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.
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
|
|
||||||
However, some configuration options are available and you can set them in
|
However, some configuration options are available and you can set them in
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
|
\uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
|
||||||
\uicontrol Common.
|
\uicontrol General.
|
||||||
|
|
||||||
For more information about the supported functions, see
|
For more information about the supported functions, see
|
||||||
\l{Using Version Control Systems}.
|
\l{Using Version Control Systems}.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2019 The Qt Company Ltd.
|
** Copyright (C) 2021 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.
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
\li \b {\l{Designing User Interfaces}}
|
\li \b {\l{Designing User Interfaces}}
|
||||||
|
|
||||||
To create intuitive, modern-looking, fluid user interfaces, you
|
To create intuitive, modern-looking, fluid user interfaces, you
|
||||||
can use \l{Qt Quick} and \QDS.
|
can use \l{Qt Quick} and \l{Qt Design Studio Manual}{\QDS}.
|
||||||
If you need a traditional user interface that is clearly
|
If you need a traditional user interface that is clearly
|
||||||
structured and enforces a platform look and feel, you can use
|
structured and enforces a platform look and feel, you can use
|
||||||
the integrated \QD. For more information, see
|
the integrated \QD. For more information, see
|
||||||
@@ -114,9 +114,10 @@
|
|||||||
execution. In addition, the QML Profiler enables you to profile
|
execution. In addition, the QML Profiler enables you to profile
|
||||||
Qt Quick applications.
|
Qt Quick applications.
|
||||||
|
|
||||||
\QC is integrated to the \l{Qt Test}, Google C++ Testing, and
|
\QC is integrated to the \l{Qt Test}, Boost.Test, Catch 2 test,
|
||||||
Boost.Test frameworks for unit testing applications and
|
and Google C++ Testing frameworks for unit testing applications
|
||||||
libraries. You can use \QC to create, build, and run autotests.
|
and libraries. You can use \QC to create, build, and run
|
||||||
|
autotests.
|
||||||
|
|
||||||
For more information, see \l{Testing}.
|
For more information, see \l{Testing}.
|
||||||
\li \b {Publishing}
|
\li \b {Publishing}
|
||||||
|
@@ -51,7 +51,8 @@
|
|||||||
\l{http://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
|
\l{http://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
If you have \QDS installed, you can open \QDS examples from \QC in \QDS.
|
If you have \l{Qt Design Studio Manual}{\QDS} installed, you can open
|
||||||
|
\QDS examples from \QC in \QDS.
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2020 The Qt Company Ltd.
|
** Copyright (C) 2021 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.
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
\section2 Creating Widget-Based Qt for Python Applications
|
\section2 Creating Widget-Based Qt for Python Applications
|
||||||
|
|
||||||
\l {https://doc.qt.io/qtforpython/index.html}{Qt for Python} enables you
|
\l {https://doc.qt.io/qtforpython/index.html}{Qt for Python} enables you
|
||||||
to use Qt 5 API in Python applications. You can use the PySide2 module to
|
to use Qt 6 API in Python applications. You can use the PySide6 modules
|
||||||
gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI},
|
to gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI},
|
||||||
and \l {Qt Widgets}.
|
and \l {Qt Widgets}.
|
||||||
|
|
||||||
The Qt for Python Application wizards generate a \c {.pyproject} file that
|
The Qt for Python Application wizards generate a \c {.pyproject} file that
|
||||||
@@ -46,7 +46,8 @@
|
|||||||
|
|
||||||
The \uicontrol {Qt for Python - Window (UI file)} wizard enables you to
|
The \uicontrol {Qt for Python - Window (UI file)} wizard enables you to
|
||||||
create a Python project that contains the source file for a class. Specify
|
create a Python project that contains the source file for a class. Specify
|
||||||
the class name, base class, and and source file for the class.
|
the PySide version, class name, base class, and and source file for the
|
||||||
|
class.
|
||||||
|
|
||||||
\image qtcreator-python-wizard-app-window.png "Qt for Python wizard for creating a widget-based UI"
|
\image qtcreator-python-wizard-app-window.png "Qt for Python wizard for creating a widget-based UI"
|
||||||
|
|
||||||
@@ -55,21 +56,22 @@
|
|||||||
Widgets module, and Qt UI tools:
|
Widgets module, and Qt UI tools:
|
||||||
|
|
||||||
\badcode
|
\badcode
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
from PySide2.QtWidgets import QApplication, QWidget
|
from PySide6.QtWidgets import QApplication, QWidget
|
||||||
from PySide2.QtCore import QFile
|
from PySide6.QtCore import QFile
|
||||||
from PySide2.QtUiTools import QUiLoader
|
from PySide6.QtUiTools import QUiLoader
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
The wizard also adds a main class with the specified name that
|
The wizard also adds a main class with the specified name that
|
||||||
inherits from the specified base class:
|
inherits from the specified base class:
|
||||||
|
|
||||||
\badcode
|
\badcode
|
||||||
class MyWidget(QWidget):
|
class Widget(QWidget):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(MyWidget, self).__init__()
|
super(Widget, self).__init__()
|
||||||
self.load_ui()
|
self.load_ui()
|
||||||
...
|
...
|
||||||
\endcode
|
\endcode
|
||||||
@@ -80,7 +82,7 @@
|
|||||||
\badcode
|
\badcode
|
||||||
def load_ui(self):
|
def load_ui(self):
|
||||||
loader = QUiLoader()
|
loader = QUiLoader()
|
||||||
path = os.path.join(os.path.dirname(__file__), "form.ui")
|
path = os.fspath(Path(__file__).resolve().parent / "form.ui")
|
||||||
ui_file = QFile(path)
|
ui_file = QFile(path)
|
||||||
ui_file.open(QFile.ReadOnly)
|
ui_file.open(QFile.ReadOnly)
|
||||||
loader.load(ui_file, self)
|
loader.load(ui_file, self)
|
||||||
@@ -100,8 +102,8 @@
|
|||||||
Next, the wizard instantiates the \c MainWindow class and shows it:
|
Next, the wizard instantiates the \c MainWindow class and shows it:
|
||||||
|
|
||||||
\badcode
|
\badcode
|
||||||
window = MyWidget()
|
widget = Widget()
|
||||||
window.show()
|
widget.show()
|
||||||
...
|
...
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
@@ -153,12 +155,12 @@
|
|||||||
to QGuiApplication and QQmlApplicationEngine:
|
to QGuiApplication and QQmlApplicationEngine:
|
||||||
|
|
||||||
\badcode
|
\badcode
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
from PySide2.QtGui import QGuiApplication
|
from PySide6.QtGui import QGuiApplication
|
||||||
from PySide2.QtQml import QQmlApplicationEngine
|
from PySide6.QtQml import QQmlApplicationEngine
|
||||||
|
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
The wizard also adds a main function, where it creates a QGuiApplication
|
The wizard also adds a main function, where it creates a QGuiApplication
|
||||||
@@ -175,7 +177,7 @@
|
|||||||
|
|
||||||
\badcode
|
\badcode
|
||||||
engine = QQmlApplicationEngine()
|
engine = QQmlApplicationEngine()
|
||||||
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
|
engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Finally, the wizard adds code that checks whether the file was successfully
|
Finally, the wizard adds code that checks whether the file was successfully
|
||||||
@@ -190,7 +192,7 @@
|
|||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
Open the .qml file in the \uicontrol Edit mode to design a Qt Quick UI, or
|
Open the .qml file in the \uicontrol Edit mode to design a Qt Quick UI, or
|
||||||
use \QDS.
|
use \l{Qt Design Studio Manual}{\QDS}.
|
||||||
|
|
||||||
//! [python qml project wizards]
|
//! [python qml project wizards]
|
||||||
*/
|
*/
|
||||||
|
@@ -35,13 +35,8 @@
|
|||||||
\image qtcreator-open-documents-view.png "Open Documents view"
|
\image qtcreator-open-documents-view.png "Open Documents view"
|
||||||
|
|
||||||
You can use the context menu to apply some of the functions also available
|
You can use the context menu to apply some of the functions also available
|
||||||
in the \uicontrol File menu
|
in the \uicontrol File menu and in the \l {File System Context Menu}
|
||||||
\if defined(qtcreator)
|
{File System} view to the file that is selected in the view.
|
||||||
.
|
|
||||||
\else
|
|
||||||
and in the \l {File System Context Menu} {File System} view to the file
|
|
||||||
that is selected in the view.
|
|
||||||
\endif
|
|
||||||
|
|
||||||
In addition, you can:
|
In addition, you can:
|
||||||
|
|
||||||
|
@@ -293,6 +293,7 @@
|
|||||||
style.
|
style.
|
||||||
\endif
|
\endif
|
||||||
|
|
||||||
|
|
||||||
You can use \QC in the following modes:
|
You can use \QC in the following modes:
|
||||||
|
|
||||||
\list
|
\list
|
||||||
@@ -487,8 +488,8 @@
|
|||||||
|
|
||||||
The pane filters out irrelevant output from the build tools and presents the
|
The pane filters out irrelevant output from the build tools and presents the
|
||||||
issues in an organized way. To further filter the output by type, select
|
issues in an organized way. To further filter the output by type, select
|
||||||
\uicontrol {Filter Tree}
|
\inlineimage filtericon.png
|
||||||
and then select a filter.
|
(\uicontrol {Filter Tree}) and then select a filter.
|
||||||
|
|
||||||
\image qtcreator-issues.png "Issues output pane"
|
\image qtcreator-issues.png "Issues output pane"
|
||||||
|
|
||||||
@@ -550,9 +551,10 @@
|
|||||||
|
|
||||||
To specify settings for displaying application output, select
|
To specify settings for displaying application output, select
|
||||||
\uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
|
\uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
|
||||||
\uicontrol {Application Output}, or click the \uicontrol {Open Settings Page}
|
\uicontrol {Application Output}, or click the \inlineimage settings.png
|
||||||
button. You can select whether to open the \uicontrol{Application Output} pane
|
(\uicontrol {Open Settings Page}) button. You can select whether to open
|
||||||
on output when running or debugging applications, to clear old output on a new run,
|
the \uicontrol{Application Output} pane on output when running or debugging
|
||||||
|
applications, to clear old output on a new run,
|
||||||
to word-wrap output, and to limit output to the specified number of lines.
|
to word-wrap output, and to limit output to the specified number of lines.
|
||||||
|
|
||||||
\section1 Compile Output
|
\section1 Compile Output
|
||||||
@@ -575,8 +577,8 @@
|
|||||||
In the \uicontrol {Limit output to} field, you can specify the maximum
|
In the \uicontrol {Limit output to} field, you can specify the maximum
|
||||||
amount of build output lines to display in the pane.
|
amount of build output lines to display in the pane.
|
||||||
|
|
||||||
You can also reach the options page by clicking the \uicontrol {Open Settings Page}
|
You can also reach the options page by clicking \inlineimage settings.png
|
||||||
button.
|
(\uicontrol {Open Settings Page}).
|
||||||
|
|
||||||
To copy the output from the pane to the clipboard, select
|
To copy the output from the pane to the clipboard, select
|
||||||
\uicontrol {Select All} in the context menu, and then select
|
\uicontrol {Select All} in the context menu, and then select
|
||||||
|
@@ -97,12 +97,14 @@
|
|||||||
|
|
||||||
\list
|
\list
|
||||||
\li To see a complete list of all bindings, select
|
\li To see a complete list of all bindings, select
|
||||||
\uicontrol {Filter Tree} > \uicontrol {Show All Bindings}.
|
\inlineimage filtericon.png
|
||||||
|
(\uicontrol {Filter Tree}) > \uicontrol {Show All Bindings}.
|
||||||
\li To sort types or symbols alphabetically, select
|
\li To sort types or symbols alphabetically, select
|
||||||
\inlineimage sort_alphabetically.png
|
\inlineimage sort_alphabetically.png
|
||||||
(\uicontrol {Sort Alphabetically}).
|
(\uicontrol {Sort Alphabetically}).
|
||||||
\li To stop the synchronization with the type or symbol selected in the
|
\li To stop the synchronization with the type or symbol selected in the
|
||||||
editor, deselect \uicontrol {Synchronize with Editor}.
|
editor, deselect \inlineimage linkicon.png
|
||||||
|
(\uicontrol {Synchronize with Editor}).
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\section1 Viewing the Class Hierarchy
|
\section1 Viewing the Class Hierarchy
|
||||||
@@ -144,5 +146,6 @@
|
|||||||
\image qtcreator-include-hierarchy-view.png "Include Hierarchy view"
|
\image qtcreator-include-hierarchy-view.png "Include Hierarchy view"
|
||||||
|
|
||||||
To keep the view synchronized with the file currently opened in the editor,
|
To keep the view synchronized with the file currently opened in the editor,
|
||||||
select \uicontrol {Synchronize with Editor}.
|
select \inlineimage linkicon.png
|
||||||
|
(\uicontrol {Synchronize with Editor}).
|
||||||
*/
|
*/
|
||||||
|
@@ -25,10 +25,11 @@
|
|||||||
|
|
||||||
#include "qmlstatenodeinstance.h"
|
#include "qmlstatenodeinstance.h"
|
||||||
|
|
||||||
#include <qmlprivategate.h>
|
|
||||||
|
|
||||||
#include "qmlpropertychangesnodeinstance.h"
|
#include "qmlpropertychangesnodeinstance.h"
|
||||||
|
|
||||||
|
#include <qmlprivategate.h>
|
||||||
|
#include <designersupportdelegate.h>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -53,12 +54,28 @@ QmlStateNodeInstance::Pointer
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAllNodesDirtyRecursive(QQuickItem *parentItem)
|
||||||
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
Q_UNUSED(parentItem)
|
||||||
|
#else
|
||||||
|
if (!parentItem)
|
||||||
|
return;
|
||||||
|
const QList<QQuickItem *> children = parentItem->childItems();
|
||||||
|
for (QQuickItem *childItem : children)
|
||||||
|
setAllNodesDirtyRecursive(childItem);
|
||||||
|
DesignerSupport::addDirty(parentItem, QQuickDesignerSupport::Content);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void QmlStateNodeInstance::activateState()
|
void QmlStateNodeInstance::activateState()
|
||||||
{
|
{
|
||||||
if (!QmlPrivateGate::States::isStateActive(object(), context())
|
if (!QmlPrivateGate::States::isStateActive(object(), context())
|
||||||
&& nodeInstanceServer()->hasInstanceForObject(object())) {
|
&& nodeInstanceServer()->hasInstanceForObject(object())) {
|
||||||
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
|
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
|
||||||
QmlPrivateGate::States::activateState(object(), context());
|
QmlPrivateGate::States::activateState(object(), context());
|
||||||
|
|
||||||
|
setAllNodesDirtyRecursive(nodeInstanceServer()->rootItem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1858,7 +1858,11 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
|
|||||||
#ifdef QUICK3D_MODULE
|
#ifdef QUICK3D_MODULE
|
||||||
if (qobject_cast<QQuick3DModel *>(object)
|
if (qobject_cast<QQuick3DModel *>(object)
|
||||||
|| qobject_cast<QQuick3DCamera *>(object)
|
|| qobject_cast<QQuick3DCamera *>(object)
|
||||||
|| qobject_cast<QQuick3DAbstractLight *>(object)) {
|
|| qobject_cast<QQuick3DAbstractLight *>(object)
|
||||||
|
#ifdef QUICK3D_PARTICLES_MODULE
|
||||||
|
|| qobject_cast<QQuick3DParticleSystem *>(object)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Node is a component if it has node children that have no instances
|
// Node is a component if it has node children that have no instances
|
||||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 892 B |
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 8.3 KiB |
@@ -202,8 +202,8 @@ Item {
|
|||||||
dialogBox.setScreenSizeIndex(index);
|
dialogBox.setScreenSizeIndex(index);
|
||||||
|
|
||||||
var r = screenSizeModel.screenSizes(index);
|
var r = screenSizeModel.screenSizes(index);
|
||||||
widthTextField.text = r.width;
|
widthField.realValue = r.width;
|
||||||
heightTextField.text = r.height;
|
heightField.realValue = r.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -252,19 +252,20 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// content items
|
// content items
|
||||||
SC.TextField {
|
SC.RealSpinBox {
|
||||||
id: widthTextField
|
id: widthField
|
||||||
actionIndicatorVisible: false
|
actionIndicatorVisible: false
|
||||||
translationIndicatorVisible: false
|
implicitWidth: 70
|
||||||
implicitWidth: 50
|
labelColor: DialogValues.textColor
|
||||||
color: DialogValues.textColor
|
realFrom: 100
|
||||||
selectByMouse: true
|
realTo: 100000
|
||||||
validator: IntValidator { bottom: 1; top: 100000; }
|
realValue: 100
|
||||||
|
realStepSize: 10
|
||||||
font.pixelSize: DialogValues.defaultPixelSize
|
font.pixelSize: DialogValues.defaultPixelSize
|
||||||
|
|
||||||
onTextChanged: {
|
onRealValueChanged: {
|
||||||
var height = heightTextField.text ? parseInt(heightTextField.text) : 0
|
var height = heightField.realValue
|
||||||
var width = text ? parseInt(text) : 0
|
var width = realValue
|
||||||
|
|
||||||
if (width >= height)
|
if (width >= height)
|
||||||
orientationButton.setHorizontal()
|
orientationButton.setHorizontal()
|
||||||
@@ -276,22 +277,23 @@ Item {
|
|||||||
Binding {
|
Binding {
|
||||||
target: dialogBox
|
target: dialogBox
|
||||||
property: "customWidth"
|
property: "customWidth"
|
||||||
value: widthTextField.text
|
value: widthField.realValue
|
||||||
}
|
}
|
||||||
|
|
||||||
SC.TextField {
|
SC.RealSpinBox {
|
||||||
id: heightTextField
|
id: heightField
|
||||||
actionIndicatorVisible: false
|
actionIndicatorVisible: false
|
||||||
translationIndicatorVisible: false
|
implicitWidth: 70
|
||||||
implicitWidth: 50
|
labelColor: DialogValues.textColor
|
||||||
color: DialogValues.textColor
|
realFrom: 100
|
||||||
selectByMouse: true
|
realTo: 100000
|
||||||
validator: IntValidator { bottom: 1; top: 100000; }
|
realValue: 100
|
||||||
|
realStepSize: 10
|
||||||
font.pixelSize: DialogValues.defaultPixelSize
|
font.pixelSize: DialogValues.defaultPixelSize
|
||||||
|
|
||||||
onTextChanged: {
|
onRealValueChanged: {
|
||||||
var height = text ? parseInt(text) : 0
|
var height = realValue
|
||||||
var width = widthTextField.text ? parseInt(widthTextField.text) : 0
|
var width = widthField.realValue
|
||||||
|
|
||||||
if (width >= height)
|
if (width >= height)
|
||||||
orientationButton.setHorizontal()
|
orientationButton.setHorizontal()
|
||||||
@@ -303,7 +305,7 @@ Item {
|
|||||||
Binding {
|
Binding {
|
||||||
target: dialogBox
|
target: dialogBox
|
||||||
property: "customHeight"
|
property: "customHeight"
|
||||||
value: heightTextField.text
|
value: heightField.realValue
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
@@ -348,9 +350,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (widthTextField.text && heightTextField.text) {
|
if (widthField.realValue && heightField.realValue) {
|
||||||
[widthTextField.text, heightTextField.text] = [heightTextField.text, widthTextField.text];
|
[widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue];
|
||||||
|
|
||||||
checked = !checked
|
checked = !checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ import QtQuick.Controls
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
import newprojectdialog
|
import NewProjectDialog
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@@ -158,16 +158,15 @@ QtObject {
|
|||||||
readonly property string transparent: "\u0099"
|
readonly property string transparent: "\u0099"
|
||||||
readonly property string triState: "\u009A"
|
readonly property string triState: "\u009A"
|
||||||
readonly property string triangleArcA: "\u009B"
|
readonly property string triangleArcA: "\u009B"
|
||||||
readonly property string triangleArcB: "\u009C"
|
readonly property string triangleArcB: "\u009D"
|
||||||
readonly property string triangleCornerA: "\u009D"
|
readonly property string triangleCornerA: "\u009E"
|
||||||
readonly property string triangleCornerB: "\u009E"
|
readonly property string triangleCornerB: "\u009F"
|
||||||
readonly property string unLinked: "\u009F"
|
readonly property string unLinked: "\u00A0"
|
||||||
readonly property string undo: "\u00A0"
|
readonly property string undo: "\u00A1"
|
||||||
readonly property string unpin: "\u00A1"
|
readonly property string unpin: "\u00A2"
|
||||||
readonly property string upDownIcon: "\u00A2"
|
readonly property string upDownIcon: "\u00A3"
|
||||||
readonly property string upDownSquare2: "\u00A3"
|
readonly property string upDownSquare2: "\u00A4"
|
||||||
readonly property string visibilityOffBroken: "\u00A4" // visibilityOff
|
readonly property string visibilityOff: "\u00A5"
|
||||||
readonly property string visibilityOff: "\u00A5" // visibilityOff2
|
|
||||||
readonly property string visibilityOn: "\u00A6"
|
readonly property string visibilityOn: "\u00A6"
|
||||||
readonly property string wildcard: "\u00A7"
|
readonly property string wildcard: "\u00A7"
|
||||||
readonly property string wizardsAutomotive: "\u00A8"
|
readonly property string wizardsAutomotive: "\u00A8"
|
||||||
@@ -175,12 +174,12 @@ QtObject {
|
|||||||
readonly property string wizardsGeneric: "\u00AA"
|
readonly property string wizardsGeneric: "\u00AA"
|
||||||
readonly property string wizardsMcuEmpty: "\u00AB"
|
readonly property string wizardsMcuEmpty: "\u00AB"
|
||||||
readonly property string wizardsMcuGraph: "\u00AC"
|
readonly property string wizardsMcuGraph: "\u00AC"
|
||||||
readonly property string wizardsMobile: "\u00AD"
|
readonly property string wizardsMobile: "\u00AE"
|
||||||
readonly property string wizardsUnknown: "\u00AE"
|
readonly property string wizardsUnknown: "\u00AF"
|
||||||
readonly property string zoomAll: "\u00AF"
|
readonly property string zoomAll: "\u00B0"
|
||||||
readonly property string zoomIn: "\u00B0"
|
readonly property string zoomIn: "\u00B1"
|
||||||
readonly property string zoomOut: "\u00B1"
|
readonly property string zoomOut: "\u00B2"
|
||||||
readonly property string zoomSelection: "\u00B2"
|
readonly property string zoomSelection: "\u00B3"
|
||||||
|
|
||||||
readonly property font iconFont: Qt.font({
|
readonly property font iconFont: Qt.font({
|
||||||
"family": controlIcons.name,
|
"family": controlIcons.name,
|
||||||
|
@@ -794,8 +794,10 @@ bool Check::visit(UiObjectInitializer *)
|
|||||||
UiQualifiedId *qualifiedTypeId = qualifiedTypeNameId(parent());
|
UiQualifiedId *qualifiedTypeId = qualifiedTypeNameId(parent());
|
||||||
if (qualifiedTypeId) {
|
if (qualifiedTypeId) {
|
||||||
typeName = qualifiedTypeId->name.toString();
|
typeName = qualifiedTypeId->name.toString();
|
||||||
if (typeName == "Component")
|
if (typeName == "Component") {
|
||||||
m_idStack.push(StringSet());
|
m_idStack.push(StringSet());
|
||||||
|
_componentChildCount = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_typeStack.push(typeName);
|
m_typeStack.push(typeName);
|
||||||
@@ -806,10 +808,23 @@ bool Check::visit(UiObjectInitializer *)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Check::endVisit(UiObjectInitializer *)
|
void Check::endVisit(UiObjectInitializer *uiObjectInitializer)
|
||||||
{
|
{
|
||||||
m_propertyStack.pop();
|
m_propertyStack.pop();
|
||||||
m_typeStack.pop();
|
|
||||||
|
const QString type = m_typeStack.pop();
|
||||||
|
|
||||||
|
if (type == "Component" && _componentChildCount == 0) {
|
||||||
|
SourceLocation loc;
|
||||||
|
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
|
||||||
|
if (objectDefinition)
|
||||||
|
loc = objectDefinition->qualifiedTypeNameId->identifierToken;
|
||||||
|
UiObjectBinding *objectBinding = cast<UiObjectBinding *>(parent());
|
||||||
|
if (objectBinding)
|
||||||
|
loc = objectBinding->qualifiedTypeNameId->identifierToken;
|
||||||
|
addMessage(WarnComponentRequiresChildren, loc);
|
||||||
|
}
|
||||||
|
|
||||||
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
|
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
|
||||||
if (objectDefinition && objectDefinition->qualifiedTypeNameId->name == QLatin1String("Component"))
|
if (objectDefinition && objectDefinition->qualifiedTypeNameId->name == QLatin1String("Component"))
|
||||||
m_idStack.pop();
|
m_idStack.pop();
|
||||||
@@ -962,6 +977,12 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
|
|||||||
addMessage(ErrUnsupportedRootTypeInQmlUi,
|
addMessage(ErrUnsupportedRootTypeInQmlUi,
|
||||||
locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()), typeName);
|
locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()), typeName);
|
||||||
|
|
||||||
|
if (!m_typeStack.isEmpty() && m_typeStack.last() == "Component") {
|
||||||
|
_componentChildCount++;
|
||||||
|
if (_componentChildCount > 1)
|
||||||
|
addMessage(ErrToManyComponentChildren, typeErrorLocation);
|
||||||
|
}
|
||||||
|
|
||||||
bool typeError = false;
|
bool typeError = false;
|
||||||
if (_importsOk) {
|
if (_importsOk) {
|
||||||
const ObjectValue *prototype = _context->lookupType(_doc.data(), typeId);
|
const ObjectValue *prototype = _context->lookupType(_doc.data(), typeId);
|
||||||
|
@@ -158,6 +158,7 @@ private:
|
|||||||
|
|
||||||
bool _importsOk;
|
bool _importsOk;
|
||||||
bool _inStatementBinding;
|
bool _inStatementBinding;
|
||||||
|
int _componentChildCount = 0;
|
||||||
const Imports *_imports;
|
const Imports *_imports;
|
||||||
TranslationFunction lastTransLationfunction = noTranslationfunction;
|
TranslationFunction lastTransLationfunction = noTranslationfunction;
|
||||||
};
|
};
|
||||||
|
@@ -251,6 +251,10 @@ StaticAnalysisMessages::StaticAnalysisMessages()
|
|||||||
tr("Type cannot be instantiated recursively (%1)."), 1);
|
tr("Type cannot be instantiated recursively (%1)."), 1);
|
||||||
newMsg(WarnLogicalValueDoesNotDependOnValues, Warning,
|
newMsg(WarnLogicalValueDoesNotDependOnValues, Warning,
|
||||||
tr("Logical value does not depend on actual values"));
|
tr("Logical value does not depend on actual values"));
|
||||||
|
newMsg(ErrToManyComponentChildren, Error,
|
||||||
|
tr("Components are only allowed to have a single child element."));
|
||||||
|
newMsg(WarnComponentRequiresChildren, Warning,
|
||||||
|
tr("Components require a child element."));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@@ -132,6 +132,8 @@ enum Type {
|
|||||||
ErrInvalidArrayValueLength = 323,
|
ErrInvalidArrayValueLength = 323,
|
||||||
ErrHitMaximumRecursion = 324,
|
ErrHitMaximumRecursion = 324,
|
||||||
WarnLogicalValueDoesNotDependOnValues = 325,
|
WarnLogicalValueDoesNotDependOnValues = 325,
|
||||||
|
ErrToManyComponentChildren = 326,
|
||||||
|
WarnComponentRequiresChildren = 327,
|
||||||
WarnDuplicateImport = 400
|
WarnDuplicateImport = 400
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -37,7 +37,10 @@
|
|||||||
|
|
||||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||||
#include <projectexplorer/devicesupport/idevicewidget.h>
|
#include <projectexplorer/devicesupport/idevicewidget.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include <projectexplorer/runconfiguration.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
@@ -418,11 +421,19 @@ QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
|
|||||||
|
|
||||||
void AndroidDeviceManager::updateDevicesList()
|
void AndroidDeviceManager::updateDevicesList()
|
||||||
{
|
{
|
||||||
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
|
// If a non-Android Kit is currently active, skip the device list update
|
||||||
|
const Target *startupTarget = SessionManager::startupTarget();
|
||||||
|
if (!startupTarget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Kit *kit = startupTarget->kit();
|
||||||
|
if (!kit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (DeviceTypeKitAspect::deviceTypeId(kit) != Constants::ANDROID_DEVICE_TYPE)
|
||||||
|
return;
|
||||||
|
|
||||||
updateDevicesListOnce();
|
updateDevicesListOnce();
|
||||||
});
|
|
||||||
updateDevicesListOnce();
|
|
||||||
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidDeviceManager::updateDevicesListOnce()
|
void AndroidDeviceManager::updateDevicesListOnce()
|
||||||
@@ -537,11 +548,17 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
|
|||||||
|
|
||||||
void AndroidDeviceManager::setupDevicesWatcher()
|
void AndroidDeviceManager::setupDevicesWatcher()
|
||||||
{
|
{
|
||||||
|
if (!m_devicesUpdaterTimer.isActive()) {
|
||||||
// The call to avdmanager is always slower than the call to adb devices,
|
// The call to avdmanager is always slower than the call to adb devices,
|
||||||
// so connecting the slot to the slower call should be enough.
|
// so connecting the slot to the slower call should be enough.
|
||||||
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
|
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
|
||||||
this, &AndroidDeviceManager::devicesListUpdated);
|
this, &AndroidDeviceManager::devicesListUpdated);
|
||||||
|
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
|
||||||
updateDevicesList();
|
updateDevicesList();
|
||||||
|
});
|
||||||
|
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
|
||||||
|
}
|
||||||
|
updateDevicesListOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidDeviceManager::devicesListUpdated()
|
void AndroidDeviceManager::devicesListUpdated()
|
||||||
|
@@ -83,21 +83,9 @@ FilePath ITestConfiguration::executableFilePath() const
|
|||||||
if (!hasExecutable())
|
if (!hasExecutable())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (m_runnable.command.executable().isExecutableFile() && m_runnable.command.executable().path() != ".") {
|
const Environment env = m_runnable.environment.size() == 0 ? Environment::systemEnvironment()
|
||||||
return m_runnable.command.executable().absoluteFilePath();
|
: m_runnable.environment;
|
||||||
} else if (m_runnable.command.executable().path() == "."){
|
return env.searchInPath(m_runnable.command.executable().path());
|
||||||
QString fullCommandFileName = m_runnable.command.executable().toString();
|
|
||||||
// TODO: check if we can use searchInPath() from Utils::Environment
|
|
||||||
const QStringList &pathList = m_runnable.environment.toProcessEnvironment().value("PATH")
|
|
||||||
.split(HostOsInfo::pathListSeparator());
|
|
||||||
|
|
||||||
for (const QString &path : pathList) {
|
|
||||||
QString filePath(path + QDir::separator() + fullCommandFileName);
|
|
||||||
if (QFileInfo(filePath).isExecutable())
|
|
||||||
return m_runnable.command.executable().absoluteFilePath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment ITestConfiguration::filteredEnvironment(const Environment &original) const
|
Environment ITestConfiguration::filteredEnvironment(const Environment &original) const
|
||||||
|
@@ -338,7 +338,9 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
|
|||||||
return createProposal();
|
return createProposal();
|
||||||
break;
|
break;
|
||||||
case ClangCompletionContextAnalyzer::CompleteIncludePath:
|
case ClangCompletionContextAnalyzer::CompleteIncludePath:
|
||||||
if (completeInclude(analyzer.positionEndOfExpression()))
|
m_completions = completeInclude(analyzer.positionEndOfExpression(), m_completionOperator,
|
||||||
|
m_interface.data(), m_interface->headerPaths());
|
||||||
|
if (!m_completions.isEmpty())
|
||||||
return createProposal();
|
return createProposal();
|
||||||
break;
|
break;
|
||||||
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
|
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
|
||||||
@@ -441,38 +443,46 @@ bool ClangCompletionAssistProcessor::accepts() const
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates completion proposals for #include and given cursor
|
* @brief Creates completion proposals for #include and given cursor
|
||||||
* @param cursor - cursor placed after opening bracked or quote
|
* @param position - cursor placed after opening bracked or quote
|
||||||
* @return false if completions list is empty
|
* @param completionOperator - the type of token
|
||||||
|
* @param interface - relevant document data
|
||||||
|
* @param headerPaths - the include paths
|
||||||
|
* @return the list of completion items
|
||||||
*/
|
*/
|
||||||
bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
|
QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::completeInclude(
|
||||||
|
int position, unsigned completionOperator, const TextEditor::AssistInterface *interface,
|
||||||
|
const ProjectExplorer::HeaderPaths &headerPaths)
|
||||||
{
|
{
|
||||||
|
QTextCursor cursor(interface->textDocument());
|
||||||
|
cursor.setPosition(position);
|
||||||
QString directoryPrefix;
|
QString directoryPrefix;
|
||||||
if (m_completionOperator == T_SLASH) {
|
if (completionOperator == T_SLASH) {
|
||||||
QTextCursor c = cursor;
|
QTextCursor c = cursor;
|
||||||
c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
|
c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
|
||||||
QString sel = c.selectedText();
|
QString sel = c.selectedText();
|
||||||
int startCharPos = sel.indexOf(QLatin1Char('"'));
|
int startCharPos = sel.indexOf(QLatin1Char('"'));
|
||||||
if (startCharPos == -1) {
|
if (startCharPos == -1) {
|
||||||
startCharPos = sel.indexOf(QLatin1Char('<'));
|
startCharPos = sel.indexOf(QLatin1Char('<'));
|
||||||
m_completionOperator = T_ANGLE_STRING_LITERAL;
|
completionOperator = T_ANGLE_STRING_LITERAL;
|
||||||
} else {
|
} else {
|
||||||
m_completionOperator = T_STRING_LITERAL;
|
completionOperator = T_STRING_LITERAL;
|
||||||
}
|
}
|
||||||
if (startCharPos != -1)
|
if (startCharPos != -1)
|
||||||
directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1);
|
directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make completion for all relevant includes
|
// Make completion for all relevant includes
|
||||||
ProjectExplorer::HeaderPaths headerPaths = m_interface->headerPaths();
|
ProjectExplorer::HeaderPaths allHeaderPaths = headerPaths;
|
||||||
const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
|
const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
|
||||||
m_interface->filePath().toFileInfo().path());
|
interface->filePath().toFileInfo().path());
|
||||||
if (!headerPaths.contains(currentFilePath))
|
if (!allHeaderPaths.contains(currentFilePath))
|
||||||
headerPaths.append(currentFilePath);
|
allHeaderPaths.append(currentFilePath);
|
||||||
|
|
||||||
const ::Utils::MimeType mimeType = ::Utils::mimeTypeForName("text/x-c++hdr");
|
const ::Utils::MimeType mimeType = ::Utils::mimeTypeForName("text/x-c++hdr");
|
||||||
const QStringList suffixes = mimeType.suffixes();
|
const QStringList suffixes = mimeType.suffixes();
|
||||||
|
|
||||||
foreach (const ProjectExplorer::HeaderPath &headerPath, headerPaths) {
|
QList<AssistProposalItemInterface *> completions;
|
||||||
|
foreach (const ProjectExplorer::HeaderPath &headerPath, allHeaderPaths) {
|
||||||
QString realPath = headerPath.path;
|
QString realPath = headerPath.path;
|
||||||
if (!directoryPrefix.isEmpty()) {
|
if (!directoryPrefix.isEmpty()) {
|
||||||
realPath += QLatin1Char('/');
|
realPath += QLatin1Char('/');
|
||||||
@@ -480,11 +490,11 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
|
|||||||
if (headerPath.type == ProjectExplorer::HeaderPathType::Framework)
|
if (headerPath.type == ProjectExplorer::HeaderPathType::Framework)
|
||||||
realPath += QLatin1String(".framework/Headers");
|
realPath += QLatin1String(".framework/Headers");
|
||||||
}
|
}
|
||||||
completeIncludePath(realPath, suffixes);
|
completions << completeIncludePath(realPath, suffixes, completionOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QPair<AssistProposalItemInterface *, QString>> completionsForSorting;
|
QList<QPair<AssistProposalItemInterface *, QString>> completionsForSorting;
|
||||||
for (AssistProposalItemInterface * const item : qAsConst(m_completions)) {
|
for (AssistProposalItemInterface * const item : qAsConst(completions)) {
|
||||||
QString s = item->text();
|
QString s = item->text();
|
||||||
s.replace('/', QChar(0)); // The dir separator should compare less than anything else.
|
s.replace('/', QChar(0)); // The dir separator should compare less than anything else.
|
||||||
completionsForSorting << qMakePair(item, s);
|
completionsForSorting << qMakePair(item, s);
|
||||||
@@ -493,26 +503,21 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
|
|||||||
return left.second < right.second;
|
return left.second < right.second;
|
||||||
});
|
});
|
||||||
for (int i = 0; i < completionsForSorting.count(); ++i)
|
for (int i = 0; i < completionsForSorting.count(); ++i)
|
||||||
m_completions[i] = completionsForSorting[i].first;
|
completions[i] = completionsForSorting[i].first;
|
||||||
|
|
||||||
return !m_completions.isEmpty();
|
return completions;
|
||||||
}
|
|
||||||
|
|
||||||
bool ClangCompletionAssistProcessor::completeInclude(int position)
|
|
||||||
{
|
|
||||||
QTextCursor textCursor(m_interface->textDocument()); // TODO: Simplify, move into function
|
|
||||||
textCursor.setPosition(position);
|
|
||||||
return completeInclude(textCursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds #include completion proposals using given include path
|
* @brief Finds #include completion proposals using given include path
|
||||||
* @param realPath - one of directories where compiler searches includes
|
* @param realPath - one of directories where compiler searches includes
|
||||||
* @param suffixes - file suffixes for C/C++ header files
|
* @param suffixes - file suffixes for C/C++ header files
|
||||||
|
* @return a list of matching completion items
|
||||||
*/
|
*/
|
||||||
void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath,
|
QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::completeIncludePath(
|
||||||
const QStringList &suffixes)
|
const QString &realPath, const QStringList &suffixes, unsigned completionOperator)
|
||||||
{
|
{
|
||||||
|
QList<AssistProposalItemInterface *> completions;
|
||||||
QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
//: Parent folder for proposed #include completion
|
//: Parent folder for proposed #include completion
|
||||||
const QString hint = tr("Location: %1").arg(QDir::toNativeSeparators(QDir::cleanPath(realPath)));
|
const QString hint = tr("Location: %1").arg(QDir::toNativeSeparators(QDir::cleanPath(realPath)));
|
||||||
@@ -529,10 +534,11 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
|
|||||||
item->setText(text);
|
item->setText(text);
|
||||||
item->setDetail(hint);
|
item->setDetail(hint);
|
||||||
item->setIcon(CPlusPlus::Icons::keywordIcon());
|
item->setIcon(CPlusPlus::Icons::keywordIcon());
|
||||||
item->setCompletionOperator(m_completionOperator);
|
item->setCompletionOperator(completionOperator);
|
||||||
m_completions.append(item);
|
completions.append(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return completions;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
|
bool ClangCompletionAssistProcessor::completePreprocessorDirectives()
|
||||||
|
@@ -34,6 +34,11 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
|
|
||||||
|
namespace TextEditor {
|
||||||
|
class AssistInterface;
|
||||||
|
class AssistProposalItemInterface;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ClangCodeModel {
|
namespace ClangCodeModel {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -48,6 +53,11 @@ public:
|
|||||||
ClangCompletionAssistProcessor();
|
ClangCompletionAssistProcessor();
|
||||||
~ClangCompletionAssistProcessor() override;
|
~ClangCompletionAssistProcessor() override;
|
||||||
|
|
||||||
|
static QList<TextEditor::AssistProposalItemInterface *> completeInclude(
|
||||||
|
int position, unsigned completionOperator,
|
||||||
|
const TextEditor::AssistInterface *interface,
|
||||||
|
const ProjectExplorer::HeaderPaths &headerPaths);
|
||||||
|
|
||||||
TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
|
TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
|
||||||
|
|
||||||
void handleAvailableCompletions(const CodeCompletions &completions);
|
void handleAvailableCompletions(const CodeCompletions &completions);
|
||||||
@@ -65,12 +75,10 @@ private:
|
|||||||
TextEditor::IAssistProposal *createProposal();
|
TextEditor::IAssistProposal *createProposal();
|
||||||
TextEditor::IAssistProposal *createFunctionHintProposal(
|
TextEditor::IAssistProposal *createFunctionHintProposal(
|
||||||
const CodeCompletions &completions);
|
const CodeCompletions &completions);
|
||||||
|
|
||||||
QList<TextEditor::AssistProposalItemInterface *> toAssistProposalItems(
|
QList<TextEditor::AssistProposalItemInterface *> toAssistProposalItems(
|
||||||
const CodeCompletions &completions) const;
|
const CodeCompletions &completions) const;
|
||||||
bool completeInclude(const QTextCursor &cursor);
|
static QList<TextEditor::AssistProposalItemInterface *> completeIncludePath(
|
||||||
bool completeInclude(int position);
|
const QString &realPath, const QStringList &suffixes, unsigned completionOperator);
|
||||||
void completeIncludePath(const QString &realPath, const QStringList &suffixes);
|
|
||||||
bool completePreprocessorDirectives();
|
bool completePreprocessorDirectives();
|
||||||
bool completeDoxygenKeywords();
|
bool completeDoxygenKeywords();
|
||||||
void addCompletionItem(const QString &text,
|
void addCompletionItem(const QString &text,
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "clangdclient.h"
|
#include "clangdclient.h"
|
||||||
|
|
||||||
|
#include "clangcompletionassistprocessor.h"
|
||||||
#include "clangcompletioncontextanalyzer.h"
|
#include "clangcompletioncontextanalyzer.h"
|
||||||
#include "clangdiagnosticmanager.h"
|
#include "clangdiagnosticmanager.h"
|
||||||
#include "clangmodelmanagersupport.h"
|
#include "clangmodelmanagersupport.h"
|
||||||
@@ -66,6 +67,7 @@
|
|||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -810,14 +812,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum class CustomAssistMode { Doxygen, Preprocessor };
|
enum class CustomAssistMode { Doxygen, Preprocessor, IncludePath };
|
||||||
class CustomAssistProcessor : public IAssistProcessor
|
class CustomAssistProcessor : public IAssistProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CustomAssistProcessor(ClangdClient *client, int position, unsigned completionOperator,
|
CustomAssistProcessor(ClangdClient *client, int position, int endPos,
|
||||||
CustomAssistMode mode)
|
unsigned completionOperator, CustomAssistMode mode)
|
||||||
: m_client(client)
|
: m_client(client)
|
||||||
, m_position(position)
|
, m_position(position)
|
||||||
|
, m_endPos(endPos)
|
||||||
, m_completionOperator(completionOperator)
|
, m_completionOperator(completionOperator)
|
||||||
, m_mode(mode)
|
, m_mode(mode)
|
||||||
{}
|
{}
|
||||||
@@ -833,7 +836,7 @@ private:
|
|||||||
CPlusPlus::Icons::keywordIcon());
|
CPlusPlus::Icons::keywordIcon());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CustomAssistMode::Preprocessor:
|
case CustomAssistMode::Preprocessor: {
|
||||||
static QIcon macroIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro);
|
static QIcon macroIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro);
|
||||||
for (const QString &completion
|
for (const QString &completion
|
||||||
: CppEditor::CppCompletionAssistProcessor::preprocessorCompletions()) {
|
: CppEditor::CppCompletionAssistProcessor::preprocessorCompletions()) {
|
||||||
@@ -843,6 +846,17 @@ private:
|
|||||||
completions << createItem("import", macroIcon);
|
completions << createItem("import", macroIcon);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ClangCodeModel::Internal::CustomAssistMode::IncludePath: {
|
||||||
|
HeaderPaths headerPaths;
|
||||||
|
const CppEditor::ProjectPart::ConstPtr projectPart
|
||||||
|
= projectPartForFile(interface->filePath().toString());
|
||||||
|
if (projectPart)
|
||||||
|
headerPaths = projectPart->headerPaths;
|
||||||
|
completions = ClangCompletionAssistProcessor::completeInclude(
|
||||||
|
m_endPos, m_completionOperator, interface, headerPaths);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
GenericProposalModelPtr model(new GenericProposalModel);
|
GenericProposalModelPtr model(new GenericProposalModel);
|
||||||
model->loadContent(completions);
|
model->loadContent(completions);
|
||||||
const auto proposal = new GenericProposal(m_position, model);
|
const auto proposal = new GenericProposal(m_position, model);
|
||||||
@@ -864,6 +878,7 @@ private:
|
|||||||
|
|
||||||
ClangdClient * const m_client;
|
ClangdClient * const m_client;
|
||||||
const int m_position;
|
const int m_position;
|
||||||
|
const int m_endPos;
|
||||||
const unsigned m_completionOperator;
|
const unsigned m_completionOperator;
|
||||||
const CustomAssistMode m_mode;
|
const CustomAssistMode m_mode;
|
||||||
};
|
};
|
||||||
@@ -1110,6 +1125,12 @@ public:
|
|||||||
using LanguageClientCompletionItem::LanguageClientCompletionItem;
|
using LanguageClientCompletionItem::LanguageClientCompletionItem;
|
||||||
void apply(TextDocumentManipulatorInterface &manipulator,
|
void apply(TextDocumentManipulatorInterface &manipulator,
|
||||||
int basePosition) const override;
|
int basePosition) const override;
|
||||||
|
|
||||||
|
enum class SpecialQtType { Signal, Slot, None };
|
||||||
|
static SpecialQtType getQtType(const CompletionItem &item);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QIcon icon() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
|
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
|
||||||
@@ -1155,15 +1176,7 @@ ClangdClient::ClangdCompletionAssistProcessor::generateCompletionItems(
|
|||||||
// whether the cursor was on the second argument of a (dis)connect() call.
|
// whether the cursor was on the second argument of a (dis)connect() call.
|
||||||
// If so, we offer only signals, as nothing else makes sense in that context.
|
// If so, we offer only signals, as nothing else makes sense in that context.
|
||||||
static const auto criterion = [](const CompletionItem &ci) {
|
static const auto criterion = [](const CompletionItem &ci) {
|
||||||
const Utils::optional<MarkupOrString> doc = ci.documentation();
|
return ClangdCompletionItem::getQtType(ci) == ClangdCompletionItem::SpecialQtType::Signal;
|
||||||
if (!doc)
|
|
||||||
return false;
|
|
||||||
QString docText;
|
|
||||||
if (Utils::holds_alternative<QString>(*doc))
|
|
||||||
docText = Utils::get<QString>(*doc);
|
|
||||||
else if (Utils::holds_alternative<MarkupContent>(*doc))
|
|
||||||
docText = Utils::get<MarkupContent>(*doc).content();
|
|
||||||
return docText.contains("Annotation: qt_signal");
|
|
||||||
};
|
};
|
||||||
const QTextDocument *doc = document();
|
const QTextDocument *doc = document();
|
||||||
const int pos = basePos();
|
const int pos = basePos();
|
||||||
@@ -1526,6 +1539,30 @@ QString ClangdClient::displayNameFromDocumentSymbol(SymbolKind kind, const QStri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force re-parse of all open files that include the changed ui header.
|
||||||
|
// Otherwise, we potentially have stale diagnostics.
|
||||||
|
void ClangdClient::handleUiHeaderChange(const QString &fileName)
|
||||||
|
{
|
||||||
|
const QRegularExpression includeRex("#include.*" + fileName + R"([>"])");
|
||||||
|
const QVector<Client *> &allClients = LanguageClientManager::clients();
|
||||||
|
for (Client * const client : allClients) {
|
||||||
|
if (!client->reachable() || !qobject_cast<ClangdClient *>(client))
|
||||||
|
continue;
|
||||||
|
for (IDocument * const doc : DocumentModel::openedDocuments()) {
|
||||||
|
const auto textDoc = qobject_cast<TextDocument *>(doc);
|
||||||
|
if (!textDoc || !client->documentOpen(textDoc))
|
||||||
|
continue;
|
||||||
|
const QTextCursor includePos = textDoc->document()->find(includeRex);
|
||||||
|
if (includePos.isNull())
|
||||||
|
continue;
|
||||||
|
qCDebug(clangdLog) << "updating" << textDoc->filePath() << "due to change in UI header"
|
||||||
|
<< fileName;
|
||||||
|
client->documentContentsChanged(textDoc, 0, 0, 0);
|
||||||
|
break; // No sane project includes the same UI header twice.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
|
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
|
||||||
{
|
{
|
||||||
const auto refData = runningFindUsages.find(key);
|
const auto refData = runningFindUsages.find(key);
|
||||||
@@ -2817,14 +2854,26 @@ IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor(
|
|||||||
qCDebug(clangdLogCompletion) << "creating doxygen processor";
|
qCDebug(clangdLogCompletion) << "creating doxygen processor";
|
||||||
return new CustomAssistProcessor(m_client,
|
return new CustomAssistProcessor(m_client,
|
||||||
contextAnalyzer.positionForProposal(),
|
contextAnalyzer.positionForProposal(),
|
||||||
|
contextAnalyzer.positionEndOfExpression(),
|
||||||
contextAnalyzer.completionOperator(),
|
contextAnalyzer.completionOperator(),
|
||||||
CustomAssistMode::Doxygen);
|
CustomAssistMode::Doxygen);
|
||||||
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
|
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
|
||||||
qCDebug(clangdLogCompletion) << "creating macro processor";
|
qCDebug(clangdLogCompletion) << "creating macro processor";
|
||||||
return new CustomAssistProcessor(m_client,
|
return new CustomAssistProcessor(m_client,
|
||||||
contextAnalyzer.positionForProposal(),
|
contextAnalyzer.positionForProposal(),
|
||||||
|
contextAnalyzer.positionEndOfExpression(),
|
||||||
contextAnalyzer.completionOperator(),
|
contextAnalyzer.completionOperator(),
|
||||||
CustomAssistMode::Preprocessor);
|
CustomAssistMode::Preprocessor);
|
||||||
|
case ClangCompletionContextAnalyzer::CompleteIncludePath:
|
||||||
|
if (m_client->versionNumber() < QVersionNumber(14)) { // https://reviews.llvm.org/D112996
|
||||||
|
qCDebug(clangdLogCompletion) << "creating include processor";
|
||||||
|
return new CustomAssistProcessor(m_client,
|
||||||
|
contextAnalyzer.positionForProposal(),
|
||||||
|
contextAnalyzer.positionEndOfExpression(),
|
||||||
|
contextAnalyzer.completionOperator(),
|
||||||
|
CustomAssistMode::IncludePath);
|
||||||
|
}
|
||||||
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3009,6 +3058,38 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClangdCompletionItem::SpecialQtType ClangdCompletionItem::getQtType(const CompletionItem &item)
|
||||||
|
{
|
||||||
|
const Utils::optional<MarkupOrString> doc = item.documentation();
|
||||||
|
if (!doc)
|
||||||
|
return SpecialQtType::None;
|
||||||
|
QString docText;
|
||||||
|
if (Utils::holds_alternative<QString>(*doc))
|
||||||
|
docText = Utils::get<QString>(*doc);
|
||||||
|
else if (Utils::holds_alternative<MarkupContent>(*doc))
|
||||||
|
docText = Utils::get<MarkupContent>(*doc).content();
|
||||||
|
if (docText.contains("Annotation: qt_signal"))
|
||||||
|
return SpecialQtType::Signal;
|
||||||
|
if (docText.contains("Annotation: qt_slot"))
|
||||||
|
return SpecialQtType::Slot;
|
||||||
|
return SpecialQtType::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon ClangdCompletionItem::icon() const
|
||||||
|
{
|
||||||
|
const SpecialQtType qtType = getQtType(item());
|
||||||
|
switch (qtType) {
|
||||||
|
case SpecialQtType::Signal:
|
||||||
|
return Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Signal);
|
||||||
|
case SpecialQtType::Slot:
|
||||||
|
// FIXME: Add visibility info to completion item tags in clangd?
|
||||||
|
return Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::SlotPublic);
|
||||||
|
case SpecialQtType::None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return LanguageClientCompletionItem::icon();
|
||||||
|
}
|
||||||
|
|
||||||
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
|
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
|
||||||
const AstHandler &astHandler,
|
const AstHandler &astHandler,
|
||||||
AstCallbackMode callbackMode, const Range &range)
|
AstCallbackMode callbackMode, const Range &range)
|
||||||
|
@@ -86,6 +86,8 @@ public:
|
|||||||
static QString displayNameFromDocumentSymbol(LanguageServerProtocol::SymbolKind kind,
|
static QString displayNameFromDocumentSymbol(LanguageServerProtocol::SymbolKind kind,
|
||||||
const QString &name, const QString &detail);
|
const QString &name, const QString &detail);
|
||||||
|
|
||||||
|
static void handleUiHeaderChange(const QString &fileName);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void indexingFinished();
|
void indexingFinished();
|
||||||
void foundReferences(const QList<Core::SearchResultItem> &items);
|
void foundReferences(const QList<Core::SearchResultItem> &items);
|
||||||
|
@@ -155,7 +155,8 @@ static ::Utils::ProcessLinkCallback extendedCallback(::Utils::ProcessLinkCallbac
|
|||||||
// If globalFollowSymbol finds nothing follow to the declaration.
|
// If globalFollowSymbol finds nothing follow to the declaration.
|
||||||
return [original_callback = std::move(callback), result](const ::Utils::Link &link) {
|
return [original_callback = std::move(callback), result](const ::Utils::Link &link) {
|
||||||
if (link.linkTextStart < 0 && result.isResultOnlyForFallBack) {
|
if (link.linkTextStart < 0 && result.isResultOnlyForFallBack) {
|
||||||
return original_callback(::Utils::Link(::Utils::FilePath::fromString(result.fileName),
|
return original_callback(Utils::Link(
|
||||||
|
Utils::FilePath::fromString(result.fileName).cleanPath(),
|
||||||
result.startLine,
|
result.startLine,
|
||||||
result.startColumn - 1));
|
result.startColumn - 1));
|
||||||
}
|
}
|
||||||
@@ -242,7 +243,7 @@ void ClangFollowSymbol::findLink(const CppEditor::CursorInEditor &data,
|
|||||||
symbolFinder,
|
symbolFinder,
|
||||||
inNextSplit);
|
inNextSplit);
|
||||||
} else {
|
} else {
|
||||||
callback(Link(Utils::FilePath::fromString(result.fileName),
|
callback(Link(Utils::FilePath::fromString(result.fileName).cleanPath(),
|
||||||
result.startLine,
|
result.startLine,
|
||||||
result.startColumn - 1));
|
result.startColumn - 1));
|
||||||
}
|
}
|
||||||
|
@@ -608,6 +608,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QStr
|
|||||||
|
|
||||||
const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content);
|
const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content);
|
||||||
m_communicator.unsavedFilesUpdated(mappedPath, content, 0);
|
m_communicator.unsavedFilesUpdated(mappedPath, content, 0);
|
||||||
|
ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath)
|
void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath)
|
||||||
@@ -618,6 +619,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &fil
|
|||||||
const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath);
|
const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath);
|
||||||
const QString projectPartId = projectPartIdForFile(filePath);
|
const QString projectPartId = projectPartIdForFile(filePath);
|
||||||
m_communicator.unsavedFilesRemoved({{mappedPath, projectPartId}});
|
m_communicator.unsavedFilesRemoved({{mappedPath, projectPartId}});
|
||||||
|
ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1488,9 +1488,15 @@ void ClangdTestCompletion::testCompleteIncludeDirective()
|
|||||||
getProposal("includeDirectiveCompletion.cpp", proposal);
|
getProposal("includeDirectiveCompletion.cpp", proposal);
|
||||||
|
|
||||||
QVERIFY(proposal);
|
QVERIFY(proposal);
|
||||||
|
if (client()->versionNumber() < QVersionNumber(14)) {
|
||||||
|
QVERIFY(hasItem(proposal, "file.h"));
|
||||||
|
QVERIFY(hasItem(proposal, "otherFile.h"));
|
||||||
|
QVERIFY(hasItem(proposal, "mylib/"));
|
||||||
|
} else {
|
||||||
QVERIFY(hasItem(proposal, " file.h>"));
|
QVERIFY(hasItem(proposal, " file.h>"));
|
||||||
QVERIFY(hasItem(proposal, " otherFile.h>"));
|
QVERIFY(hasItem(proposal, " otherFile.h>"));
|
||||||
QVERIFY(hasItem(proposal, " mylib/"));
|
QVERIFY(hasItem(proposal, " mylib/"));
|
||||||
|
}
|
||||||
QVERIFY(!hasSnippet(proposal, "class "));
|
QVERIFY(!hasSnippet(proposal, "class "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ public:
|
|||||||
Utils::Id id() const { return m_id; }
|
Utils::Id id() const { return m_id; }
|
||||||
WizardKind kind() const { return m_supportedProjectTypes.isEmpty() ? FileWizard : ProjectWizard; }
|
WizardKind kind() const { return m_supportedProjectTypes.isEmpty() ? FileWizard : ProjectWizard; }
|
||||||
QIcon icon() const { return m_icon; }
|
QIcon icon() const { return m_icon; }
|
||||||
QString fontIcondCode() const { return m_fontIconCode; }
|
QString fontIconName() const { return m_fontIconName; }
|
||||||
QString description() const { return m_description; }
|
QString description() const { return m_description; }
|
||||||
QString displayName() const { return m_displayName; }
|
QString displayName() const { return m_displayName; }
|
||||||
QString category() const { return m_category; }
|
QString category() const { return m_category; }
|
||||||
@@ -79,7 +79,7 @@ public:
|
|||||||
void setId(const Utils::Id id) { m_id = id; }
|
void setId(const Utils::Id id) { m_id = id; }
|
||||||
void setSupportedProjectTypes(const QSet<Utils::Id> &projectTypes) { m_supportedProjectTypes = projectTypes; }
|
void setSupportedProjectTypes(const QSet<Utils::Id> &projectTypes) { m_supportedProjectTypes = projectTypes; }
|
||||||
void setIcon(const QIcon &icon, const QString &iconText = {});
|
void setIcon(const QIcon &icon, const QString &iconText = {});
|
||||||
void setFontIconCode(const QString &code) { m_fontIconCode = code; }
|
void setFontIconName(const QString &code) { m_fontIconName = code; }
|
||||||
void setDescription(const QString &description) { m_description = description; }
|
void setDescription(const QString &description) { m_description = description; }
|
||||||
void setDisplayName(const QString &displayName) { m_displayName = displayName; }
|
void setDisplayName(const QString &displayName) { m_displayName = displayName; }
|
||||||
void setCategory(const QString &category) { m_category = category; }
|
void setCategory(const QString &category) { m_category = category; }
|
||||||
@@ -137,7 +137,7 @@ private:
|
|||||||
|
|
||||||
QAction *m_action = nullptr;
|
QAction *m_action = nullptr;
|
||||||
QIcon m_icon;
|
QIcon m_icon;
|
||||||
QString m_fontIconCode;
|
QString m_fontIconName;
|
||||||
QString m_description;
|
QString m_description;
|
||||||
QString m_displayName;
|
QString m_displayName;
|
||||||
QString m_category;
|
QString m_category;
|
||||||
|
@@ -57,7 +57,7 @@ QString ProjectPart::projectFileLocation() const
|
|||||||
|
|
||||||
bool ProjectPart::belongsToProject(const ProjectExplorer::Project *project) const
|
bool ProjectPart::belongsToProject(const ProjectExplorer::Project *project) const
|
||||||
{
|
{
|
||||||
return project && topLevelProject == project->projectFilePath();
|
return project ? topLevelProject == project->projectFilePath() : !hasProject();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ProjectPart::readProjectConfigFile(const QString &projectConfigFile)
|
QByteArray ProjectPart::readProjectConfigFile(const QString &projectConfigFile)
|
||||||
|
@@ -258,7 +258,7 @@ void McuPackage::setRelativePathModifier(const QString &path)
|
|||||||
m_relativePathModifier = path;
|
m_relativePathModifier = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void McuPackage::setVersions(const QVector<QString> &versions)
|
void McuPackage::setVersions(const QStringList &versions)
|
||||||
{
|
{
|
||||||
m_versions = versions;
|
m_versions = versions;
|
||||||
}
|
}
|
||||||
@@ -312,13 +312,14 @@ void McuPackage::updateStatusUi()
|
|||||||
QString McuPackage::statusText() const
|
QString McuPackage::statusText() const
|
||||||
{
|
{
|
||||||
const QString displayPackagePath = m_path.toUserOutput();
|
const QString displayPackagePath = m_path.toUserOutput();
|
||||||
const QString displayVersions = QStringList(m_versions.toList()).join(" or ");
|
const QString displayVersions = m_versions.join(" or ");
|
||||||
const QString displayRequiredPath = QString("%1 %2").arg(
|
const QString outDetectionPath = FilePath::fromString(m_detectionPath).toUserOutput();
|
||||||
FilePath::fromString(m_detectionPath).toUserOutput(),
|
const QString displayRequiredPath = m_versions.empty() ?
|
||||||
displayVersions);
|
outDetectionPath :
|
||||||
const QString displayDetectedPath = QString("%1 %2").arg(
|
QString("%1 %2").arg(outDetectionPath, displayVersions);
|
||||||
FilePath::fromString(m_detectionPath).toUserOutput(),
|
const QString displayDetectedPath = m_versions.empty() ?
|
||||||
m_detectedVersion);
|
outDetectionPath :
|
||||||
|
QString("%1 %2").arg(outDetectionPath, m_detectedVersion);
|
||||||
|
|
||||||
QString response;
|
QString response;
|
||||||
switch (m_status) {
|
switch (m_status) {
|
||||||
|
@@ -88,7 +88,7 @@ public:
|
|||||||
void writeGeneralSettings() const;
|
void writeGeneralSettings() const;
|
||||||
bool writeToSettings() const;
|
bool writeToSettings() const;
|
||||||
void setRelativePathModifier(const QString &path);
|
void setRelativePathModifier(const QString &path);
|
||||||
void setVersions(const QVector<QString> &versions);
|
void setVersions(const QStringList &versions);
|
||||||
|
|
||||||
bool automaticKitCreationEnabled() const;
|
bool automaticKitCreationEnabled() const;
|
||||||
void setAutomaticKitCreationEnabled(const bool enabled);
|
void setAutomaticKitCreationEnabled(const bool enabled);
|
||||||
@@ -118,7 +118,7 @@ private:
|
|||||||
Utils::FilePath m_path;
|
Utils::FilePath m_path;
|
||||||
QString m_relativePathModifier; // relative path to m_path to be returned by path()
|
QString m_relativePathModifier; // relative path to m_path to be returned by path()
|
||||||
QString m_detectedVersion;
|
QString m_detectedVersion;
|
||||||
QVector<QString> m_versions;
|
QStringList m_versions;
|
||||||
QString m_downloadUrl;
|
QString m_downloadUrl;
|
||||||
QString m_environmentVariableName;
|
QString m_environmentVariableName;
|
||||||
bool m_addToPath = false;
|
bool m_addToPath = false;
|
||||||
|
@@ -341,13 +341,13 @@ struct McuTargetDescription
|
|||||||
} platform;
|
} platform;
|
||||||
struct {
|
struct {
|
||||||
QString id;
|
QString id;
|
||||||
QVector<QString> versions;
|
QStringList versions;
|
||||||
} toolchain;
|
} toolchain;
|
||||||
struct {
|
struct {
|
||||||
QString name;
|
QString name;
|
||||||
QString defaultPath;
|
QString defaultPath;
|
||||||
QString envVar;
|
QString envVar;
|
||||||
QVector<QString> versions;
|
QStringList versions;
|
||||||
} boardSdk;
|
} boardSdk;
|
||||||
struct {
|
struct {
|
||||||
QString envVar;
|
QString envVar;
|
||||||
@@ -658,10 +658,10 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion
|
|||||||
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
|
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
|
||||||
|
|
||||||
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
|
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
|
||||||
const auto toolchainVersionsVector = Utils::transform<QVector<QString> >(
|
const auto toolchainVersionsList = Utils::transform<QStringList>(
|
||||||
toolchainVersions, [&](const QVariant &version) { return version.toString(); });
|
toolchainVersions, [&](const QVariant &version) { return version.toString(); });
|
||||||
const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList();
|
const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList();
|
||||||
const auto boardSdkVersionsVector = Utils::transform<QVector<QString> >(
|
const auto boardSdkVersionsList = Utils::transform<QStringList>(
|
||||||
boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
|
boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -670,13 +670,13 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion
|
|||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
toolchain.value("id").toString(),
|
toolchain.value("id").toString(),
|
||||||
toolchainVersionsVector,
|
toolchainVersionsList,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
boardSdk.value("name").toString(),
|
boardSdk.value("name").toString(),
|
||||||
boardSdk.value("defaultPath").toString(),
|
boardSdk.value("defaultPath").toString(),
|
||||||
boardSdk.value("envVar").toString(),
|
boardSdk.value("envVar").toString(),
|
||||||
boardSdkVersionsVector,
|
boardSdkVersionsList,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
freeRTOS.value("envVar").toString(),
|
freeRTOS.value("envVar").toString(),
|
||||||
|
@@ -72,7 +72,7 @@ const char CATEGORY_NAME_KEY[] = "trDisplayCategory";
|
|||||||
const char DISPLAY_NAME_KEY[] = "trDisplayName";
|
const char DISPLAY_NAME_KEY[] = "trDisplayName";
|
||||||
const char ICON_KEY[] = "icon";
|
const char ICON_KEY[] = "icon";
|
||||||
const char ICON_TEXT_KEY[] = "iconText";
|
const char ICON_TEXT_KEY[] = "iconText";
|
||||||
const char FONT_ICON_CODE_KEY[] = "fontIconCode";
|
const char FONT_ICON_NAME_KEY[] = "fontIconName";
|
||||||
const char IMAGE_KEY[] = "image";
|
const char IMAGE_KEY[] = "image";
|
||||||
const char ICON_KIND_KEY[] = "iconKind";
|
const char ICON_KIND_KEY[] = "iconKind";
|
||||||
const char DESCRIPTION_KEY[] = "trDescription";
|
const char DESCRIPTION_KEY[] = "trDescription";
|
||||||
@@ -743,8 +743,8 @@ bool JsonWizardFactory::initialize(const QVariantMap &data, const FilePath &base
|
|||||||
: QIcon(iconPath.toString()),
|
: QIcon(iconPath.toString()),
|
||||||
iconText);
|
iconText);
|
||||||
|
|
||||||
const QString fontIconCode = data.value(QLatin1String(FONT_ICON_CODE_KEY)).toString();
|
const QString fontIconName = data.value(QLatin1String(FONT_ICON_NAME_KEY)).toString();
|
||||||
setFontIconCode(fontIconCode);
|
setFontIconName(fontIconName);
|
||||||
|
|
||||||
strVal = data.value(QLatin1String(IMAGE_KEY)).toString();
|
strVal = data.value(QLatin1String(IMAGE_KEY)).toString();
|
||||||
if (!strVal.isEmpty()) {
|
if (!strVal.isEmpty()) {
|
||||||
|
@@ -1,5 +1,10 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/boilerplatetemplates">
|
<qresource prefix="/boilerplatetemplates">
|
||||||
<file>qmlprojectmaincpp.tpl</file>
|
<file>qmlprojectmaincpp.tpl</file>
|
||||||
|
<file>qmlprojectmaincppheader.tpl</file>
|
||||||
|
<file>qmlprojectmodules.tpl</file>
|
||||||
|
<file>qmlprojectmaincmakelists.tpl</file>
|
||||||
|
<file>qmlprojectmodulecmakelists.tpl</file>
|
||||||
|
<file>qmlprojectmainqml.tpl</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -186,6 +186,11 @@ QString Theme::getIconUnicode(Theme::Icon i)
|
|||||||
return instance()->m_constants->property(e.valueToKey(i)).toString();
|
return instance()->m_constants->property(e.valueToKey(i)).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Theme::getIconUnicode(const QString &name)
|
||||||
|
{
|
||||||
|
return instance()->m_constants->property(name.toStdString().data()).toString();
|
||||||
|
}
|
||||||
|
|
||||||
QColor Theme::qmlDesignerBackgroundColorDarker() const
|
QColor Theme::qmlDesignerBackgroundColorDarker() const
|
||||||
{
|
{
|
||||||
return getColor(QmlDesigner_BackgroundColorDarker);
|
return getColor(QmlDesigner_BackgroundColorDarker);
|
||||||
|
@@ -174,8 +174,7 @@ public:
|
|||||||
unpin,
|
unpin,
|
||||||
upDownIcon,
|
upDownIcon,
|
||||||
upDownSquare2,
|
upDownSquare2,
|
||||||
visibilityOffBroken, // visibilityOff
|
visibilityOff,
|
||||||
visibilityOff, // visibilityOff2
|
|
||||||
visibilityOn,
|
visibilityOn,
|
||||||
wildcard,
|
wildcard,
|
||||||
wizardsAutomotive,
|
wizardsAutomotive,
|
||||||
@@ -198,6 +197,7 @@ public:
|
|||||||
static QColor getColor(Color role);
|
static QColor getColor(Color role);
|
||||||
static QPixmap getPixmap(const QString &id);
|
static QPixmap getPixmap(const QString &id);
|
||||||
static QString getIconUnicode(Theme::Icon i);
|
static QString getIconUnicode(Theme::Icon i);
|
||||||
|
static QString getIconUnicode(const QString &name);
|
||||||
|
|
||||||
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarker() const;
|
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarker() const;
|
||||||
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarkAlternate() const;
|
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarkAlternate() const;
|
||||||
|
@@ -279,6 +279,7 @@ bool DesignDocument::isDocumentLoaded() const
|
|||||||
|
|
||||||
void DesignDocument::resetToDocumentModel()
|
void DesignDocument::resetToDocumentModel()
|
||||||
{
|
{
|
||||||
|
plainTextEdit()->document()->clearUndoRedoStacks();
|
||||||
m_inFileComponentModel.reset();
|
m_inFileComponentModel.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,6 +311,8 @@ void DesignDocument::changeToDocumentModel()
|
|||||||
viewManager().detachRewriterView();
|
viewManager().detachRewriterView();
|
||||||
viewManager().detachViewsExceptRewriterAndComponetView();
|
viewManager().detachViewsExceptRewriterAndComponetView();
|
||||||
|
|
||||||
|
plainTextEdit()->document()->clearUndoRedoStacks();
|
||||||
|
|
||||||
m_inFileComponentModel.reset();
|
m_inFileComponentModel.reset();
|
||||||
m_inFileComponentTextModifier.reset();
|
m_inFileComponentTextModifier.reset();
|
||||||
|
|
||||||
@@ -345,6 +348,8 @@ void DesignDocument::changeToInFileComponentModel(ComponentTextModifier *textMod
|
|||||||
viewManager().detachRewriterView();
|
viewManager().detachRewriterView();
|
||||||
viewManager().detachViewsExceptRewriterAndComponetView();
|
viewManager().detachViewsExceptRewriterAndComponetView();
|
||||||
|
|
||||||
|
plainTextEdit()->document()->clearUndoRedoStacks();
|
||||||
|
|
||||||
m_inFileComponentModel.reset(createInFileComponentModel());
|
m_inFileComponentModel.reset(createInFileComponentModel());
|
||||||
m_inFileComponentModel->setTextModifier(m_inFileComponentTextModifier.data());
|
m_inFileComponentModel->setTextModifier(m_inFileComponentTextModifier.data());
|
||||||
|
|
||||||
|
@@ -160,19 +160,28 @@ void ComponentTextModifier::handleOriginalTextChanged()
|
|||||||
|
|
||||||
const QString currentText = m_originalModifier->text();
|
const QString currentText = m_originalModifier->text();
|
||||||
|
|
||||||
// Adjust for removal/addition of whitespace in the document
|
|
||||||
// Check that non-whitespace portion of the text is the same and count the whitespace diff
|
|
||||||
const int oldLen = m_originalText.size();
|
const int oldLen = m_originalText.size();
|
||||||
const int newLen = currentText.size();
|
const int newLen = currentText.size();
|
||||||
|
|
||||||
|
if (oldLen != newLen) {
|
||||||
int newSpace = 0;
|
int newSpace = 0;
|
||||||
int oldSpace = 0;
|
int oldSpace = 0;
|
||||||
int newIdx = 0;
|
int newIdx = 0;
|
||||||
|
int nonWhiteSpaceChangeIdx = -1;
|
||||||
|
int newStartOffset = m_componentStartOffset;
|
||||||
|
|
||||||
|
// Adjust for removal/addition of whitespace in the document.
|
||||||
|
// Whitespace changes that happen when document is saved can be spread around throughout
|
||||||
|
// the entire document in multiple places.
|
||||||
|
// Check that non-whitespace portion of the text is the same and count the whitespace diff
|
||||||
for (int oldIdx = 0; oldIdx < oldLen; ++oldIdx) {
|
for (int oldIdx = 0; oldIdx < oldLen; ++oldIdx) {
|
||||||
const QChar oldChar = m_originalText[oldIdx];
|
const QChar oldChar = m_originalText[oldIdx];
|
||||||
if (oldIdx == m_componentStartOffset)
|
if (oldIdx == m_componentStartOffset)
|
||||||
m_componentStartOffset += newSpace - oldSpace;
|
newStartOffset += newSpace - oldSpace;
|
||||||
if (oldIdx == m_componentEndOffset) {
|
if (oldIdx == m_componentEndOffset) {
|
||||||
m_componentEndOffset += newSpace - oldSpace;
|
m_componentEndOffset += newSpace - oldSpace;
|
||||||
|
m_componentStartOffset = newStartOffset;
|
||||||
|
m_originalText = currentText;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,13 +196,29 @@ void ComponentTextModifier::handleOriginalTextChanged()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentText[newIdx] != oldChar) {
|
if (currentText[newIdx] != oldChar) {
|
||||||
// Non-whitespace difference, we can't determine a valid offset in this case
|
nonWhiteSpaceChangeIdx = oldIdx;
|
||||||
// TODO: Needs proper handling to deal with undo/redo/arbitrary edits somehow (QDS-5392)
|
// A non-whitespace change is a result of manual text edit or undo/redo operation.
|
||||||
|
// Assumption is that separate whitespace changes and a non-whitespace change can't
|
||||||
|
// both happen simultaneously, so break out of whitespace check loop.
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
++newIdx;
|
++newIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nonWhiteSpaceChangeIdx >= 0) {
|
||||||
|
// For non-whitespace change, we assume the whole change is either before the component
|
||||||
|
// or inside the component. If the change spans both, it's likely the change is
|
||||||
|
// invalid anyway, and we don't care about trying to keep offsets up to date.
|
||||||
|
int diff = newLen - oldLen;
|
||||||
|
if (nonWhiteSpaceChangeIdx < m_componentEndOffset)
|
||||||
|
m_componentEndOffset += diff;
|
||||||
|
if (nonWhiteSpaceChangeIdx < m_componentStartOffset)
|
||||||
|
m_componentStartOffset += diff;
|
||||||
m_originalText = currentText;
|
m_originalText = currentText;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
emit textChanged();
|
emit textChanged();
|
||||||
}
|
}
|
||||||
|
@@ -66,6 +66,7 @@ const char NAVIGATOR_REVERSE_ITEM_ORDER[] = "NavigatorReverseItemOrder";
|
|||||||
const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */
|
const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */
|
||||||
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
|
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
|
||||||
const char STANDALONE_MODE[] = "StandAloneMode";
|
const char STANDALONE_MODE[] = "StandAloneMode";
|
||||||
|
const char SHOW_DEBUG_SETTINGS[] = "ShowDebugSettings";
|
||||||
const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView";
|
const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView";
|
||||||
const char COLOR_PALETTE_RECENT[] = "ColorPaletteRecent";
|
const char COLOR_PALETTE_RECENT[] = "ColorPaletteRecent";
|
||||||
const char COLOR_PALETTE_FAVORITE[] = "ColorPaletteFavorite";
|
const char COLOR_PALETTE_FAVORITE[] = "ColorPaletteFavorite";
|
||||||
|
@@ -78,7 +78,7 @@ void onGenerateCmakeLists()
|
|||||||
{
|
{
|
||||||
queuedFiles.clear();
|
queuedFiles.clear();
|
||||||
FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
|
FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
|
||||||
GenerateCmakeLists::generateMainCmake(rootDir);
|
GenerateCmakeLists::generateCmakes(rootDir);
|
||||||
GenerateEntryPoints::generateMainCpp(rootDir);
|
GenerateEntryPoints::generateMainCpp(rootDir);
|
||||||
GenerateEntryPoints::generateMainQml(rootDir);
|
GenerateEntryPoints::generateMainQml(rootDir);
|
||||||
if (showConfirmationDialog(rootDir))
|
if (showConfirmationDialog(rootDir))
|
||||||
@@ -139,138 +139,125 @@ bool writeFile(const GeneratableFile &file)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString readTemplate(const QString &templatePath)
|
||||||
|
{
|
||||||
|
QFile templatefile(templatePath);
|
||||||
|
templatefile.open(QIODevice::ReadOnly);
|
||||||
|
QTextStream stream(&templatefile);
|
||||||
|
QString content = stream.readAll();
|
||||||
|
templatefile.close();
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace GenerateCmakeLists {
|
namespace GenerateCmakeLists {
|
||||||
|
|
||||||
|
QStringList moduleNames;
|
||||||
|
|
||||||
const QDir::Filters FILES_ONLY = QDir::Files;
|
const QDir::Filters FILES_ONLY = QDir::Files;
|
||||||
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
|
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
|
||||||
|
|
||||||
const char CMAKEFILENAME[] = "CMakeLists.txt";
|
const char CMAKEFILENAME[] = "CMakeLists.txt";
|
||||||
const char QMLDIRFILENAME[] = "qmldir";
|
const char QMLDIRFILENAME[] = "qmldir";
|
||||||
|
const char MODULEFILENAME[] = "qmlmodules";
|
||||||
|
|
||||||
QStringList processDirectory(const FilePath &dir)
|
bool generateCmakes(const FilePath &rootDir)
|
||||||
{
|
{
|
||||||
QStringList moduleNames;
|
moduleNames.clear();
|
||||||
|
|
||||||
FilePaths files = dir.dirEntries(FILES_ONLY);
|
FilePath contentDir = rootDir.pathAppended("content");
|
||||||
for (FilePath &file : files) {
|
FilePath importDir = rootDir.pathAppended("imports");
|
||||||
if (!file.fileName().compare(CMAKEFILENAME))
|
|
||||||
files.removeAll(file);
|
generateModuleCmake(contentDir);
|
||||||
|
generateImportCmake(importDir);
|
||||||
|
generateMainCmake(rootDir);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.isEmpty()) {
|
const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
|
||||||
generateSubdirCmake(dir);
|
const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
|
||||||
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
|
|
||||||
for (FilePath &subDir : subDirs) {
|
|
||||||
QStringList subDirModules = processDirectory(subDir);
|
|
||||||
moduleNames.append(subDirModules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QString moduleName = generateModuleCmake(dir);
|
|
||||||
if (!moduleName.isEmpty()) {
|
|
||||||
moduleNames.append(moduleName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return moduleNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char MAINFILE_REQUIRED_VERSION[] = "cmake_minimum_required(VERSION 3.18)\n\n";
|
|
||||||
const char MAINFILE_PROJECT[] = "project(%1 LANGUAGES CXX)\n\n";
|
|
||||||
const char MAINFILE_CMAKE_OPTIONS[] = "set(CMAKE_INCLUDE_CURRENT_DIR ON)\nset(CMAKE_AUTOMOC ON)\n\n";
|
|
||||||
const char MAINFILE_PACKAGES[] = "find_package(Qt6 COMPONENTS Gui Qml Quick)\n";
|
|
||||||
const char MAINFILE_LIBRARIES[] = "set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)\n\n";
|
|
||||||
const char MAINFILE_CPP[] = "add_executable(%1 main.cpp)\n\n";
|
|
||||||
const char MAINFILE_MAINMODULE[] = "qt6_add_qml_module(%1\n\tURI \"Main\"\n\tVERSION 1.0\n\tNO_PLUGIN\n\tQML_FILES main.qml\n)\n\n";
|
|
||||||
const char MAINFILE_LINK_LIBRARIES[] = "target_link_libraries(%1 PRIVATE\n\tQt${QT_VERSION_MAJOR}::Core\n\tQt${QT_VERSION_MAJOR}::Gui\n\tQt${QT_VERSION_MAJOR}::Quick\n\tQt${QT_VERSION_MAJOR}::Qml\n)\n\n";
|
|
||||||
|
|
||||||
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
|
|
||||||
|
|
||||||
void generateMainCmake(const FilePath &rootDir)
|
void generateMainCmake(const FilePath &rootDir)
|
||||||
{
|
{
|
||||||
//TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
|
//TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
|
||||||
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
|
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
|
||||||
|
QString appName = projectName + "App";
|
||||||
|
|
||||||
FilePaths subDirs = rootDir.dirEntries(DIRS_ONLY);
|
QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName);
|
||||||
|
queueCmakeFile(rootDir, cmakeFileContent);
|
||||||
|
|
||||||
QString fileContent;
|
QString modulesAsPlugins;
|
||||||
fileContent.append(MAINFILE_REQUIRED_VERSION);
|
for (const QString &moduleName : moduleNames)
|
||||||
fileContent.append(QString(MAINFILE_PROJECT).arg(projectName));
|
modulesAsPlugins.append(" " + moduleName + "plugin\n");
|
||||||
fileContent.append(MAINFILE_CMAKE_OPTIONS);
|
|
||||||
fileContent.append(MAINFILE_PACKAGES);
|
|
||||||
fileContent.append(QString(MAINFILE_CPP).arg(projectName));
|
|
||||||
fileContent.append(QString(MAINFILE_MAINMODULE).arg(projectName));
|
|
||||||
fileContent.append(MAINFILE_LIBRARIES);
|
|
||||||
|
|
||||||
for (FilePath &subDir : subDirs) {
|
QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH).arg(appName).arg(modulesAsPlugins);
|
||||||
QStringList subDirModules = processDirectory(subDir);
|
GenerateCmake::queueFile(rootDir.pathAppended(MODULEFILENAME), moduleFileContent);
|
||||||
if (!subDirModules.isEmpty())
|
|
||||||
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
|
|
||||||
}
|
}
|
||||||
fileContent.append("\n");
|
|
||||||
|
|
||||||
fileContent.append(QString(MAINFILE_LINK_LIBRARIES).arg(projectName));
|
const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
|
||||||
|
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
|
||||||
|
|
||||||
createCmakeFile(rootDir, fileContent);
|
void generateImportCmake(const FilePath &dir)
|
||||||
|
{
|
||||||
|
QString fileContent;
|
||||||
|
|
||||||
|
fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
|
||||||
|
|
||||||
|
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
|
||||||
|
for (FilePath &subDir : subDirs) {
|
||||||
|
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
|
||||||
|
generateModuleCmake(subDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
queueCmakeFile(dir, fileContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
|
const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
|
||||||
const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n\tPROPERTIES\n\t\t%2 %3\n)\n\n";
|
const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
|
||||||
const char MODULEFILE_CREATE_MODULE[] = "qt6_add_qml_module(%1\n\tURI \"%1\"\n\tVERSION 1.0\n%2)\n\n";
|
const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
|
||||||
|
|
||||||
|
void generateModuleCmake(const FilePath &dir)
|
||||||
QString generateModuleCmake(const FilePath &dir)
|
|
||||||
{
|
{
|
||||||
QString fileContent;
|
QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
|
||||||
const QStringList qmldirFilesOnly(QMLDIRFILENAME);
|
const QStringList qmldirFilesOnly(QMLDIRFILENAME);
|
||||||
|
|
||||||
|
QString singletonContent;
|
||||||
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
|
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
|
||||||
if (!qmldirFileList.isEmpty()) {
|
if (!qmldirFileList.isEmpty()) {
|
||||||
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
|
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
|
||||||
for (QString &singleton : singletons) {
|
for (QString &singleton : singletons) {
|
||||||
fileContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
|
singletonContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList qmlFileList = getDirectoryTreeQmls(dir);
|
QStringList qmlFileList = getDirectoryTreeQmls(dir);
|
||||||
QString qmlFiles;
|
QString qmlFiles;
|
||||||
for (QString &qmlFile : qmlFileList)
|
for (QString &qmlFile : qmlFileList)
|
||||||
qmlFiles.append(QString("\t\t%1\n").arg(qmlFile));
|
qmlFiles.append(QString(" %1\n").arg(qmlFile));
|
||||||
|
|
||||||
QStringList resourceFileList = getDirectoryTreeResources(dir);
|
QStringList resourceFileList = getDirectoryTreeResources(dir);
|
||||||
QString resourceFiles;
|
QString resourceFiles;
|
||||||
for (QString &resourceFile : resourceFileList)
|
for (QString &resourceFile : resourceFileList)
|
||||||
resourceFiles.append(QString("\t\t%1\n").arg(resourceFile));
|
resourceFiles.append(QString(" %1\n").arg(resourceFile));
|
||||||
|
|
||||||
QString moduleContent;
|
QString moduleContent;
|
||||||
if (!qmlFiles.isEmpty()) {
|
if (!qmlFiles.isEmpty()) {
|
||||||
moduleContent.append(QString("\tQML_FILES\n%1").arg(qmlFiles));
|
moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
|
||||||
}
|
}
|
||||||
if (!resourceFiles.isEmpty()) {
|
if (!resourceFiles.isEmpty()) {
|
||||||
moduleContent.append(QString("\tRESOURCES\n%1").arg(resourceFiles));
|
moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString moduleName = dir.fileName();
|
QString moduleName = dir.fileName();
|
||||||
|
|
||||||
fileContent.append(QString(MODULEFILE_CREATE_MODULE).arg(moduleName).arg(moduleContent));
|
moduleNames.append(moduleName);
|
||||||
|
|
||||||
createCmakeFile(dir, fileContent);
|
|
||||||
|
|
||||||
return moduleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void generateSubdirCmake(const FilePath &dir)
|
|
||||||
{
|
|
||||||
QString fileContent;
|
QString fileContent;
|
||||||
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
|
fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent));
|
||||||
|
queueCmakeFile(dir, fileContent);
|
||||||
for (FilePath &subDir : subDirs) {
|
|
||||||
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
createCmakeFile(dir, fileContent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
|
QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
|
||||||
@@ -347,7 +334,7 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
|
|||||||
return resourceFileList;
|
return resourceFileList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createCmakeFile(const FilePath &dir, const QString &content)
|
void queueCmakeFile(const FilePath &dir, const QString &content)
|
||||||
{
|
{
|
||||||
FilePath filePath = dir.pathAppended(CMAKEFILENAME);
|
FilePath filePath = dir.pathAppended(CMAKEFILENAME);
|
||||||
GenerateCmake::queueFile(filePath, content);
|
GenerateCmake::queueFile(filePath, content);
|
||||||
@@ -370,35 +357,42 @@ bool generateEntryPointFiles(const FilePath &dir)
|
|||||||
return cppOk && qmlOk;
|
return cppOk && qmlOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char MAIN_CPPFILE_CONTENT[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
|
const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
|
||||||
|
const char MAIN_CPPFILE_DIR[] = "src";
|
||||||
const char MAIN_CPPFILE_NAME[] = "main.cpp";
|
const char MAIN_CPPFILE_NAME[] = "main.cpp";
|
||||||
|
const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
|
||||||
|
const char MAIN_CPPFILE_HEADER_NAME[] = "import_qml_plugins.h";
|
||||||
|
const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
|
||||||
|
|
||||||
bool generateMainCpp(const FilePath &dir)
|
bool generateMainCpp(const FilePath &dir)
|
||||||
{
|
{
|
||||||
QFile templatefile(MAIN_CPPFILE_CONTENT);
|
FilePath srcDir = dir.pathAppended(MAIN_CPPFILE_DIR);
|
||||||
templatefile.open(QIODevice::ReadOnly);
|
|
||||||
QTextStream stream(&templatefile);
|
|
||||||
QString content = stream.readAll();
|
|
||||||
templatefile.close();
|
|
||||||
|
|
||||||
FilePath filePath = dir.pathAppended(MAIN_CPPFILE_NAME);
|
QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
|
||||||
return GenerateCmake::queueFile(filePath, content);
|
FilePath cppFilePath = srcDir.pathAppended(MAIN_CPPFILE_NAME);
|
||||||
|
bool cppOk = GenerateCmake::queueFile(cppFilePath, cppContent);
|
||||||
|
|
||||||
|
QString modulesAsPlugins;
|
||||||
|
for (const QString &moduleName : GenerateCmakeLists::moduleNames)
|
||||||
|
modulesAsPlugins.append(
|
||||||
|
QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "plugin"));
|
||||||
|
|
||||||
|
QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH)
|
||||||
|
.arg(modulesAsPlugins);
|
||||||
|
FilePath headerFilePath = srcDir.pathAppended(MAIN_CPPFILE_HEADER_NAME);
|
||||||
|
bool headerOk = GenerateCmake::queueFile(headerFilePath, headerContent);
|
||||||
|
|
||||||
|
return cppOk && headerOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char MAIN_QMLFILE_CONTENT[] = "import %1Qml\n\n%2 {\n}\n";
|
const char MAIN_QMLFILE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
|
||||||
const char MAIN_QMLFILE_NAME[] = "main.qml";
|
const char MAIN_QMLFILE_NAME[] = "main.qml";
|
||||||
|
|
||||||
bool generateMainQml(const FilePath &dir)
|
bool generateMainQml(const FilePath &dir)
|
||||||
{
|
{
|
||||||
|
QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_PATH);
|
||||||
FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME);
|
FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME);
|
||||||
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
|
return GenerateCmake::queueFile(filePath, content);
|
||||||
ProjectExplorer::RunConfiguration *runConfiguration = ProjectExplorer::SessionManager::startupRunConfiguration();
|
|
||||||
QString mainClass;
|
|
||||||
|
|
||||||
if (const auto aspect = runConfiguration->aspect<QmlProjectManager::QmlMainFileAspect>())
|
|
||||||
mainClass = FilePath::fromString(aspect->mainScript()).baseName();
|
|
||||||
|
|
||||||
return GenerateCmake::queueFile(filePath, QString(MAIN_QMLFILE_CONTENT).arg(projectName).arg(mainClass));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -45,16 +45,17 @@ bool showConfirmationDialog(const Utils::FilePath &rootDir);
|
|||||||
bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
|
bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
|
||||||
bool writeFile(const GeneratableFile &file);
|
bool writeFile(const GeneratableFile &file);
|
||||||
bool writeQueuedFiles();
|
bool writeQueuedFiles();
|
||||||
|
QString readTemplate(const QString &templatePath);
|
||||||
}
|
}
|
||||||
namespace GenerateCmakeLists {
|
namespace GenerateCmakeLists {
|
||||||
|
bool generateCmakes(const Utils::FilePath &rootDir);
|
||||||
void generateMainCmake(const Utils::FilePath &rootDir);
|
void generateMainCmake(const Utils::FilePath &rootDir);
|
||||||
void generateSubdirCmake(const Utils::FilePath &dir);
|
void generateImportCmake(const Utils::FilePath &dir);
|
||||||
QString generateModuleCmake(const Utils::FilePath &dir);
|
void generateModuleCmake(const Utils::FilePath &dir);
|
||||||
QStringList processDirectory(const Utils::FilePath &dir);
|
|
||||||
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
|
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
|
||||||
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
|
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
|
||||||
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
|
QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
|
||||||
void createCmakeFile(const Utils::FilePath &filePath, const QString &content);
|
void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
|
||||||
bool isFileBlacklisted(const QString &fileName);
|
bool isFileBlacklisted(const QString &fileName);
|
||||||
}
|
}
|
||||||
namespace GenerateEntryPoints {
|
namespace GenerateEntryPoints {
|
||||||
|
19
src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.18)
|
||||||
|
|
||||||
|
project(%1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
find_package(Qt6 COMPONENTS Gui Qml Quick)
|
||||||
|
add_executable(%1 src/main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(%1 PRIVATE
|
||||||
|
Qt${QT_VERSION_MAJOR}::Core
|
||||||
|
Qt${QT_VERSION_MAJOR}::Gui
|
||||||
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
|
Qt${QT_VERSION_MAJOR}::Qml
|
||||||
|
)
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)
|
||||||
|
|
8
src/plugins/qmldesigner/qmlprojectmaincppheader.tpl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* This file is automatically generated by Qt Design Studio.
|
||||||
|
* Do not change.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QtQml/qqmlextensionplugin.h>
|
||||||
|
|
||||||
|
%1
|
6
src/plugins/qmldesigner/qmlprojectmainqml.tpl
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import QtQuick
|
||||||
|
import content
|
||||||
|
|
||||||
|
App {
|
||||||
|
}
|
||||||
|
|
11
src/plugins/qmldesigner/qmlprojectmodulecmakelists.tpl
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
### This file is automatically generated by Qt Design Studio.
|
||||||
|
### Do not change
|
||||||
|
|
||||||
|
%1
|
||||||
|
|
||||||
|
qt_add_library(%2 STATIC)
|
||||||
|
qt6_add_qml_module(%2
|
||||||
|
URI "%2"
|
||||||
|
VERSION 1.0
|
||||||
|
%3
|
||||||
|
)
|
16
src/plugins/qmldesigner/qmlprojectmodules.tpl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
### This file is automatically generated by Qt Design Studio.
|
||||||
|
### Do not change
|
||||||
|
|
||||||
|
qt6_add_qml_module(%1
|
||||||
|
URI "Main"
|
||||||
|
VERSION 1.0
|
||||||
|
NO_PLUGIN
|
||||||
|
QML_FILES main.qml
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(content)
|
||||||
|
add_subdirectory(imports)
|
||||||
|
|
||||||
|
target_link_libraries(%1 PRIVATE
|
||||||
|
%2
|
||||||
|
)
|
@@ -252,10 +252,14 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings)
|
|||||||
m_ui.askBeforeDeletingAssetCheckBox->setChecked(settings.value(
|
m_ui.askBeforeDeletingAssetCheckBox->setChecked(settings.value(
|
||||||
DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool());
|
DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool());
|
||||||
|
|
||||||
if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) {
|
const auto standaloneMode = settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool();
|
||||||
m_ui.debugGroupBox->hide();
|
#ifdef QT_DEBUG
|
||||||
m_ui.featureTimelineEditorCheckBox->hide();
|
const auto showDebugSettings = true;
|
||||||
}
|
#else
|
||||||
|
const auto showDebugSettings = settings.value(DesignerSettingsKey::SHOW_DEBUG_SETTINGS).toBool();
|
||||||
|
#endif
|
||||||
|
m_ui.debugGroupBox->setVisible(!standaloneMode || showDebugSettings);
|
||||||
|
m_ui.featureTimelineEditorCheckBox->setVisible(standaloneMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsPageWidget::apply()
|
void SettingsPageWidget::apply()
|
||||||
|
@@ -199,7 +199,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
|
|||||||
info(openInQDSAppSetting,
|
info(openInQDSAppSetting,
|
||||||
description + tr(" Learn more about Qt Design Studio here: ")
|
description + tr(" Learn more about Qt Design Studio here: ")
|
||||||
+ "<a href='https://www.qt.io/product/ui-design-tools'>Qt Design Studio</a>",
|
+ "<a href='https://www.qt.io/product/ui-design-tools'>Qt Design Studio</a>",
|
||||||
Utils::InfoBarEntry::GlobalSuppression::Enabled);
|
Utils::InfoBarEntry::GlobalSuppression::Disabled);
|
||||||
Core::ICore::infoBar()->addInfo(info);
|
Core::ICore::infoBar()->addInfo(info);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -209,7 +209,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
|
|||||||
Utils::InfoBarEntry
|
Utils::InfoBarEntry
|
||||||
info(openInQDSAppSetting,
|
info(openInQDSAppSetting,
|
||||||
description + "\n" + tr("Do you want to open this file in Qt Design Studio?"),
|
description + "\n" + tr("Do you want to open this file in Qt Design Studio?"),
|
||||||
Utils::InfoBarEntry::GlobalSuppression::Enabled);
|
Utils::InfoBarEntry::GlobalSuppression::Disabled);
|
||||||
info.setCustomButtonInfo(tr("Open in Qt Design Studio"), [filePath] {
|
info.setCustomButtonInfo(tr("Open in Qt Design Studio"), [filePath] {
|
||||||
Core::ICore::infoBar()->removeInfo(openInQDSAppSetting);
|
Core::ICore::infoBar()->removeInfo(openInQDSAppSetting);
|
||||||
|
|
||||||
|
@@ -353,6 +353,10 @@ bool StudioWelcomePlugin::initialize(const QStringList &arguments, QString *erro
|
|||||||
void StudioWelcomePlugin::extensionsInitialized()
|
void StudioWelcomePlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
Core::ModeManager::activateMode(m_welcomeMode->id());
|
Core::ModeManager::activateMode(m_welcomeMode->id());
|
||||||
|
|
||||||
|
// Enable QDS new project dialog
|
||||||
|
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
|
||||||
|
|
||||||
if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
|
if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
|
||||||
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
|
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
|
||||||
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
|
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
|
||||||
@@ -370,8 +374,6 @@ void StudioWelcomePlugin::extensionsInitialized()
|
|||||||
s_view->setSource(QUrl("qrc:/qml/splashscreen/main.qml"));
|
s_view->setSource(QUrl("qrc:/qml/splashscreen/main.qml"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// disabled by default
|
|
||||||
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
|
|
||||||
|
|
||||||
QTC_ASSERT(s_view->rootObject(),
|
QTC_ASSERT(s_view->rootObject(),
|
||||||
qWarning() << "The StudioWelcomePlugin has a runtime depdendency on "
|
qWarning() << "The StudioWelcomePlugin has a runtime depdendency on "
|
||||||
|
@@ -28,11 +28,7 @@
|
|||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
#include "wizardfactories.h"
|
#include "wizardfactories.h"
|
||||||
|
#include <qmldesigner/components/componentcore/theme.h>
|
||||||
namespace {
|
|
||||||
// TODO: should be extern, check coreplugin/dialogs/newdialogwidget.cpp
|
|
||||||
const char BLACKLISTED_CATEGORIES_KEY[] = "Core/NewDialog/BlacklistedCategories";
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace StudioWelcome;
|
using namespace StudioWelcome;
|
||||||
|
|
||||||
@@ -41,9 +37,6 @@ WizardFactories::WizardFactories(QList<Core::IWizardFactory *> &factories, QWidg
|
|||||||
, m_platform{platform}
|
, m_platform{platform}
|
||||||
, m_factories{factories}
|
, m_factories{factories}
|
||||||
{
|
{
|
||||||
QVariant value = Core::ICore::settings()->value(BLACKLISTED_CATEGORIES_KEY);
|
|
||||||
m_blacklist = Utils::Id::fromStringList(value.toStringList());
|
|
||||||
|
|
||||||
sortByCategoryAndId();
|
sortByCategoryAndId();
|
||||||
filter();
|
filter();
|
||||||
m_projectItems = makeProjectItemsGroupedByCategory();
|
m_projectItems = makeProjectItemsGroupedByCategory();
|
||||||
@@ -67,7 +60,7 @@ void WizardFactories::filter()
|
|||||||
[&](auto *wizard) {
|
[&](auto *wizard) {
|
||||||
return wizard->isAvailable(m_platform)
|
return wizard->isAvailable(m_platform)
|
||||||
&& wizard->kind() == Core::IWizardFactory::ProjectWizard
|
&& wizard->kind() == Core::IWizardFactory::ProjectWizard
|
||||||
&& !m_blacklist.contains(Utils::Id::fromString(wizard->category()));
|
&& wizard->requiredFeatures().contains("QtStudio");
|
||||||
});
|
});
|
||||||
|
|
||||||
m_factories = acceptedFactories;
|
m_factories = acceptedFactories;
|
||||||
@@ -83,7 +76,7 @@ ProjectItem WizardFactories::makeProjectItem(Core::IWizardFactory *f, QWidget *p
|
|||||||
/*.categoryId =*/f->category(),
|
/*.categoryId =*/f->category(),
|
||||||
/*. description =*/f->description(),
|
/*. description =*/f->description(),
|
||||||
/*.qmlPath =*/f->detailsPageQmlPath(),
|
/*.qmlPath =*/f->detailsPageQmlPath(),
|
||||||
/*.fontIconCode =*/f->fontIcondCode(),
|
/*.fontIconCode =*/QmlDesigner::Theme::getIconUnicode(f->fontIconName()),
|
||||||
/*.create =*/ std::bind(&Core::IWizardFactory::runWizard, f, _1, parent, platform,
|
/*.create =*/ std::bind(&Core::IWizardFactory::runWizard, f, _1, parent, platform,
|
||||||
QVariantMap(), false),
|
QVariantMap(), false),
|
||||||
};
|
};
|
||||||
|
@@ -55,7 +55,6 @@ private:
|
|||||||
std::map<QString, ProjectCategory> makeProjectItemsGroupedByCategory();
|
std::map<QString, ProjectCategory> makeProjectItemsGroupedByCategory();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSet<Utils::Id> m_blacklist;
|
|
||||||
QWidget *m_wizardParent;
|
QWidget *m_wizardParent;
|
||||||
Utils::Id m_platform;
|
Utils::Id m_platform;
|
||||||
|
|
||||||
|
@@ -651,7 +651,7 @@ void TextDocument::setFilePath(const Utils::FilePath &newName)
|
|||||||
{
|
{
|
||||||
if (newName == filePath())
|
if (newName == filePath())
|
||||||
return;
|
return;
|
||||||
IDocument::setFilePath(newName.absoluteFilePath());
|
IDocument::setFilePath(newName.absoluteFilePath().cleanPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
IDocument::ReloadBehavior TextDocument::reloadBehavior(ChangeTrigger state, ChangeType type) const
|
IDocument::ReloadBehavior TextDocument::reloadBehavior(ChangeTrigger state, ChangeType type) const
|
||||||
|
@@ -189,14 +189,14 @@ public:
|
|||||||
// Navigation
|
// Navigation
|
||||||
QAction *m_goBack = nullptr;
|
QAction *m_goBack = nullptr;
|
||||||
QAction *m_goNext = nullptr;
|
QAction *m_goNext = nullptr;
|
||||||
QLineEdit *m_searchFilter = nullptr;
|
QPointer<QLineEdit> m_searchFilter = nullptr;
|
||||||
|
|
||||||
// Cost formatting
|
// Cost formatting
|
||||||
QAction *m_filterProjectCosts = nullptr;
|
QAction *m_filterProjectCosts = nullptr;
|
||||||
QAction *m_costAbsolute = nullptr;
|
QAction *m_costAbsolute = nullptr;
|
||||||
QAction *m_costRelative = nullptr;
|
QAction *m_costRelative = nullptr;
|
||||||
QAction *m_costRelativeToParent = nullptr;
|
QAction *m_costRelativeToParent = nullptr;
|
||||||
QComboBox *m_eventCombo = nullptr;
|
QPointer<QComboBox> m_eventCombo;
|
||||||
|
|
||||||
QTimer m_updateTimer;
|
QTimer m_updateTimer;
|
||||||
|
|
||||||
@@ -546,7 +546,9 @@ void CallgrindToolPrivate::setBusyCursor(bool busy)
|
|||||||
void CallgrindToolPrivate::selectFunction(const Function *func)
|
void CallgrindToolPrivate::selectFunction(const Function *func)
|
||||||
{
|
{
|
||||||
if (!func) {
|
if (!func) {
|
||||||
|
if (m_flatView)
|
||||||
m_flatView->clearSelection();
|
m_flatView->clearSelection();
|
||||||
|
if (m_visualization)
|
||||||
m_visualization->setFunction(nullptr);
|
m_visualization->setFunction(nullptr);
|
||||||
m_callersModel.clear();
|
m_callersModel.clear();
|
||||||
m_calleesModel.clear();
|
m_calleesModel.clear();
|
||||||
@@ -555,14 +557,17 @@ void CallgrindToolPrivate::selectFunction(const Function *func)
|
|||||||
|
|
||||||
const QModelIndex index = m_dataModel.indexForObject(func);
|
const QModelIndex index = m_dataModel.indexForObject(func);
|
||||||
const QModelIndex proxyIndex = m_proxyModel.mapFromSource(index);
|
const QModelIndex proxyIndex = m_proxyModel.mapFromSource(index);
|
||||||
|
if (m_flatView) {
|
||||||
m_flatView->selectionModel()->clearSelection();
|
m_flatView->selectionModel()->clearSelection();
|
||||||
m_flatView->selectionModel()->setCurrentIndex(proxyIndex,
|
m_flatView->selectionModel()->setCurrentIndex(proxyIndex,
|
||||||
QItemSelectionModel::ClearAndSelect |
|
QItemSelectionModel::ClearAndSelect |
|
||||||
QItemSelectionModel::Rows);
|
QItemSelectionModel::Rows);
|
||||||
m_flatView->scrollTo(proxyIndex);
|
m_flatView->scrollTo(proxyIndex);
|
||||||
|
}
|
||||||
|
|
||||||
m_callersModel.setCalls(func->incomingCalls(), func);
|
m_callersModel.setCalls(func->incomingCalls(), func);
|
||||||
m_calleesModel.setCalls(func->outgoingCalls(), func);
|
m_calleesModel.setCalls(func->outgoingCalls(), func);
|
||||||
|
if (m_visualization)
|
||||||
m_visualization->setFunction(func);
|
m_visualization->setFunction(func);
|
||||||
|
|
||||||
const Function *item = m_stackBrowser.current();
|
const Function *item = m_stackBrowser.current();
|
||||||
@@ -689,6 +694,7 @@ void CallgrindToolPrivate::visualisationFunctionSelected(const Function *functio
|
|||||||
void CallgrindToolPrivate::setParseData(ParseData *data)
|
void CallgrindToolPrivate::setParseData(ParseData *data)
|
||||||
{
|
{
|
||||||
// we have new parse data, invalidate filters in the proxy model
|
// we have new parse data, invalidate filters in the proxy model
|
||||||
|
if (m_visualization)
|
||||||
m_visualization->setFunction(nullptr);
|
m_visualization->setFunction(nullptr);
|
||||||
|
|
||||||
// invalidate parse data in the data model
|
// invalidate parse data in the data model
|
||||||
@@ -705,6 +711,7 @@ void CallgrindToolPrivate::setParseData(ParseData *data)
|
|||||||
m_calleesModel.setParseData(data);
|
m_calleesModel.setParseData(data);
|
||||||
m_callersModel.setParseData(data);
|
m_callersModel.setParseData(data);
|
||||||
|
|
||||||
|
if (m_eventCombo)
|
||||||
updateEventCombo();
|
updateEventCombo();
|
||||||
|
|
||||||
// clear history for new data
|
// clear history for new data
|
||||||
|