Merge remote-tracking branch 'origin/4.12'

Conflicts:
	src/plugins/coreplugin/dialogs/shortcutsettings.cpp

Change-Id: I1f21845350bb69268ca51bc77167a8244adce22a
This commit is contained in:
Eike Ziller
2020-03-26 15:26:27 +01:00
96 changed files with 1068 additions and 263 deletions

View File

@@ -118,14 +118,14 @@ ApplicationWindow {
if (newX < 0)
newX = 0
if (newX > mainWindow.width - bubble.width)
newX = mainWindow.width - bubble.width
if (newX > page1.mainWindow.width - bubble.width)
newX = page1.mainWindow.width - bubble.width
if (newY < 18)
newY = 18
if (newY > mainWindow.height - bubble.height)
newY = mainWindow.height - bubble.height
if (newY > page1.mainWindow.height - bubble.height)
newY = page1.mainWindow.height - bubble.height
bubble.x = newX
bubble.y = newY

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
doc/qtcreator/images/qtcreator-cmakeexecutable.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -39,90 +39,233 @@
need a fake Qt installation.
The bare metal device type accepts custom GDB commands that you specify in
the device options. You can specify the commands to execute by default or
the commands to execute when connecting to OpenOCD or ST-LINK Utility.
the device options. You can specify the commands to execute when connecting
using a particular debug server provider.
To connect bare metal devices:
The following debug server providers are supported:
\list
\li \l EBlink
\li \l J-Link
\li \l OpenOCD
\li \l ST-LINK
\li \l {uVision IDE}
\endlist
\section1 Enabling the Bare Metal Device Plugin
To enable the Bare Metal Device plugin:
\list 1
\li Select \uicontrol Help > \uicontrol {About Plugins} >
\uicontrol {Device Support} > \uicontrol {Bare Metal} to enable the
Bare Metal Device plugin.
\uicontrol {Device Support} > \uicontrol {Bare Metal}.
\li Select \uicontrol {Restart Now} to restart \QC and load the plugin.
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
\uicontrol {Bare Metal} > \uicontrol Add > \uicontrol Default,
\uicontrol OpenOCD, or \uicontrol {ST-LINK Utility} to specify
connections to GDB servers or hardware debuggers:
\endlist
\image creator-baremetal-device.png "Bare Metal options"
\section1 Specifying Settings for Debug Server Providers
To create connections to bare metal devices using a debug server provider,
select \uicontrol Tools > \uicontrol Options > \uicontrol Devices
> \uicontrol {Bare Metal} > \uicontrol Add > \uicontrol Default.
The available settings depend on the debug server provider.
\section2 EBlink
\l{https://github.com/EmBitz/EBlink}{EBlink} is an ARM Cortex-M debug tool
that supports squirrel scripting, live variables, and hot-plugging.
\image qtcreator-baremetal-eblink.png "Bare metal device options for EBlink"
To specify settings for \EBlink:
\list 1
\li In the \uicontrol {Startup mode} field, select the mode to
start the GDB server or debugger in. The available modes
depend on the server or debugger.
\include creator-baremetal-settings.qdocinc baremetal-common
\li In the \uicontrol Host field, select the host name and port
number to connect to the GDB server or hardware debugger.
\li In the \uicontrol {Script file} field, enter the path
to a device script file.
\li In the \uicontrol {Init commands} field, enter the commands
to execute when initializing the connection.
\li In the \uicontrol {Verbosity level} field, enter the level of
verbose logging.
\li In the \uicontrol {Reset commands} field, enter the commands
to execute when resetting the connection.
\li Select the \uicontrol {Connect under reset} check box to use
the ST-Link interface. Deselect the check box for hot-plugging.
\li Select \uicontrol Apply to add the GDB server or debugger.
\li In the \uicontrol Type field, select the interface type.
\li In the \uicontrol Speed field, enter the interface speed between
120 and 8000 kiloherz (kHz).
\li Select the \uicontrol {Disable cache} check box to disable the
\EBlink flash cache.
\li Select the \uicontrol {Auto shutdown} check box to automatically
shut down the \EBlink server after disconnecting.
\include creator-baremetal-settings.qdocinc baremetal-init-reset
\endlist
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices >
\uicontrol Add > \uicontrol {Bare Metal Device} >
\uicontrol {Start Wizard}:
\section2 J-Link
\l{https://www.segger.com/products/debug-probes/j-link/}{J-Link} is a line
of debug probes by Segger.
\image qtcreator-baremetal-jlink.png "Bare metal device options for J-Link"
To specify settings for J-Link debug probes:
\list 1
\li In the \uicontrol {GDB server provider} field, select a
GDB server or hardware debugger.
\include creator-baremetal-settings.qdocinc baremetal-common
\li In the \uicontrol {Host interface} field, select the connection
type, IP or USB, or use the default connection.
\li In the \uicontrol {Target interface} field, select the target
interface type.
\li In the \uicontrol Speed field, enter the interface speed in kHz.
\li In the \uicontrol Device field, select the device to connect to.
\li In the \uicontrol {Additional arguments} field, enter
arguments for the commands.
\include creator-baremetal-settings.qdocinc baremetal-init-reset
\endlist
\section2 OpenOCD
\l{http://openocd.org}{OpenOCD} (Open On-Chip Debugger) is an on-chip debug
solution for targets based on the ARM7 and ARM9 family with Embedded-ICE
(JTAG) facility. It enables source level debugging with the GDB compiled
for the ARM architecture.
\image qtcreator-baremetal-openocd.png "Bare metal device options for OpenOCD"
To specify settings for \OpenOCD:
\list 1
\include creator-baremetal-settings.qdocinc baremetal-common
\li In the \uicontrol {Root scripts directory} field, enter the
path to the directory that contains configuration scripts.
\li In the \uicontrol {Configuration file} field, enter the path
to the device configuration file.
\li In the \uicontrol {Additional arguments} field, enter
arguments for the commands.
\include creator-baremetal-settings.qdocinc baremetal-init-reset
\endlist
\section2 St-Link
\l{https://www.st.com/en/development-tools/stm32-programmers.html#products}
{ST-LINK Utility} is used for programming STM32 microcontrollers.
\image qtcreator-baremetal-stlink.png "Bare metal device options for St-Link"
To specify settings for St-Link:
\list 1
\include creator-baremetal-settings.qdocinc baremetal-common
\li In the \uicontrol {Verbosity level} field, enter the level of
verbose logging.
\li Select the \uicontrol {Extended mode} check box to continue
listening for connection requests after after the connection
is closed.
\li Select the \uicontrol {Reset on connection} check box to
reset the board when the connection is created.
\li In the \uicontrol Version field, select the transport
layer type supported by the device.
\include creator-baremetal-settings.qdocinc baremetal-init-reset
\endlist
\section2 uVision IDE
\l{http://www.keil.com/support/man/docs/uv4/uv4_overview.htm}{uVision} is
an IDE for developing applications for embedded devices. Applications can
be debugged by using uVision Simulator or directly on hardware by using
St-Link.
\section3 uVision Simulator
\image qtcreator-baremetal-uvision-simulator.png "Bare metal device options for uVision Simulator"
To specify settings for uVision Simulator or uVision St-Link Debugger:
\list 1
\include creator-baremetal-settings.qdocinc uvision-common
\li Select the \uicontrol {Limit speed to real-time} check box to limit
the connection speed.
\li Select \uicontrol Apply to add the debug server provider.
\endlist
\section3 uVision St-Link Debugger
\image qtcreator-baremetal-uvision-st-link.png "Bare metal device options for uVision St-Link"
To specify settings for uVision St-Link Debugger:
\list 1
\include creator-baremetal-settings.qdocinc uvision-common
\li In the \uicontrol {Adapter options} field specify the adapter
interface type and speed in MHz.
\li Select \uicontrol Apply to add the debug server provider.
\endlist
\section1 Adding Bare Metal Devices
\image qtcreator-baremetal-devices.png "Bare Metal device options"
To add a bare metal device:
\list 1
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices
> \uicontrol Add > \uicontrol {Bare Metal Device} >
\uicontrol {Start Wizard}.
\li In the \uicontrol {Debug server provider} field, select a debug
server provider.
\li Select \uicontrol Apply to add the device.
\endlist
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits >
\uicontrol Add to add a kit for building applications and running
them on bare metal devices:
\section1 Building for and Running on Bare Metal Devices
\image creator-baremetal-kits.png "Bare Metal Device kits"
To add a kit for building applications and running them on bare metal
devices, select \uicontrol Tools > \uicontrol Options > \uicontrol Kits
> \uicontrol Add. For more information, see \l{Adding Kits}.
\list 1
\li In the \uicontrol Name field, specify a name for the kit.
\li In the \uicontrol {Device type} field, select
\uicontrol {Bare Metal Device}.
\li In the \uicontrol Device field, select the bare metal device
for the kit.
\li Select \uicontrol Apply to add the kit.
\endlist
\li Open a project for an application you want to develop for the
device.
\li Select \uicontrol Projects > \uicontrol {Build & Run}, and then
select the kit for building the application and running it on the bare
metal device specified in the kit.
\image creator-baremetal-kit-for-project.png "Adding a bare metal kit for a project"
\li Select \uicontrol Run to specify run settings.
Usually, you can use the default settings.
\endlist
\image qtcreator-baremetal-kit.png "Kit options for Bare Metal"
You can build applications for and run them on bare metal devices
in the same way as for and on the desktop. For more information, see
\l{Building for Multiple Platforms} and \l{Running on Multiple Platforms}.
*/

View File

@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
**
****************************************************************************/
//! [baremetal-common]
\li In the \uicontrol Name field, enter a name for the connection.
\li In the \uicontrol {Startup mode} field, select the mode to start
the debug server provider in.
\li In the \uicontrol Host field, select the host name and port number
to connect to the debug server provider.
\li In the \uicontrol {Executable file} field, enter the path to the
debug server provider executable.
//! [baremetal-common]
//! [baremetal-init-reset]
\li In the \uicontrol {Init commands} field, enter the commands
to execute when initializing the connection.
\li In the \uicontrol {Reset commands} field, enter the commands
to execute when resetting the connection.
\li Select \uicontrol Apply to add the debug server provider.
//! [baremetal-init-reset]
//! [uvision-common]
\li In the \uicontrol Name field, enter a name for the connection.
\li In the \uicontrol Host field, select the host name and port
number to connect to the debug server provider.
\li In the \uicontrol {Tools file path} field, enter the path to
the Keil toolset configuration file.
\li In the \uicontrol {Target device} field, select the device to
debug.
\li In the \uicontrol {Target driver} field, select the driver for
connecting to the target device.
//! [uvision-common]

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -50,6 +50,10 @@
You can add paths to other CMake executables and use them in different
build and run \l{glossary-buildandrun-kit}{kits}.
CMake documentation is installed in Qt help file format (.qch) when you
install CMake. It is automatically registered by \QC, and you can view it
in the Help mode.
\QC automatically runs CMake to refresh project information when you edit
a \c CMakeLists.txt configuration file in a project. Project information is
also automatically refreshed when you build the project.
@@ -79,6 +83,9 @@
\li In the \uicontrol Path field, specify the path to the CMake
executable.
\li In the \uicontrol {Help file} field, specify the path to the
CMake help file (.qch) provided by and installed with CMake.
\li Select the \uicontrol {Auto-create build directories} check box to
automatically create build directories for CMake projects.

View File

@@ -50,6 +50,9 @@
\list
\li In the \uicontrol Interpreter field, specify the path to the
Python executable.
\li Select the \uicontrol {Buffered output} check box to buffer the
output. This improves output performance, but causes delays in
output.
\li In the \uicontrol Script field, you can see the path to the
main file of the project that will be run.
\li In the \uicontrol {Command line arguments} field, specify

View File

@@ -28,5 +28,7 @@ be met: https://www.gnu.org/licenses/gpl-3.0.html.</string>
<string>qml2puppet</string>
<key>CFBundleIdentifier</key>
<string>org.qt-project.qtcreator.qml2puppet</string>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>

View File

@@ -133,19 +133,7 @@ int main(int argc, char *argv[])
// subpixel antialiasing and instead use gray.
qputenv("QSG_DISTANCEFIELD_ANTIALIASING", "gray");
#ifdef Q_OS_MACOS
if (!qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE")) {
qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "true");
} else {
// We have to parse the arguments before Q[Gui]Application creation
// Since the Qt arguments are not filtered out, yet we do not know the position of the argument
for (int i = 0; i < argc; ++i) {
const char *arg = argv[i];
//In previewmode and rendermode we hide the process
if (!qstrcmp(arg, "previewmode") || !qstrcmp(arg, "rendermode"))
qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "true");
// This keeps qml2puppet from stealing focus
}
}
#endif
//If a style different from Desktop is set we have to use QGuiApplication

View File

@@ -140,7 +140,7 @@ SectionLayout {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
actionIndicator.visible: true
labelColor: horizontalAlignmentComboBox.currentIndex === 0 ? colorLogic.__defaultTextColor : colorLogic.__changedTextColor
@@ -176,7 +176,7 @@ SectionLayout {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
actionIndicator.visible: true
labelColor: verticalAlignmentComboBox.currentIndex === 0 ? colorLogic.__defaultTextColor : colorLogic.__changedTextColor

View File

@@ -93,6 +93,7 @@ Row {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
StudioControls.ButtonGroup {
id: group

View File

@@ -93,6 +93,7 @@ Row {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
StudioControls.ButtonGroup {
id: group

View File

@@ -87,4 +87,5 @@ StudioControls.Button {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
}

View File

@@ -40,6 +40,7 @@ StudioControls.CheckBox {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
labelColor: colorLogic.textColor
ColorLogic {

View File

@@ -57,6 +57,7 @@ StudioControls.ComboBox {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
actionIndicator.visible: comboBox.showExtendedFunctionButton

View File

@@ -42,6 +42,8 @@ Item {
signal reseted
property bool menuVisible: false
function show() {
menuLoader.show()
}
@@ -97,6 +99,10 @@ Item {
onAboutToShow: {
exportMenuItem.checked = backendValue.hasPropertyAlias()
exportMenuItem.enabled = !backendValue.isAttachedProperty()
extendedFunctionButton.menuVisible = true
}
onAboutToHide: {
extendedFunctionButton.menuVisible = false
}
StudioControls.MenuItem {

View File

@@ -81,6 +81,7 @@ StudioControls.ComboBox {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
property bool showExtendedFunctionButton: true

View File

@@ -70,6 +70,7 @@ StudioControls.TextField {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
ColorLogic {
id: colorLogic

View File

@@ -84,6 +84,8 @@ Item {
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
ColorLogic {
id: colorLogic
backendValue: spinBox.backendValue

View File

@@ -53,6 +53,7 @@ RowLayout {
actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
ExtendedFunctionLogic {
id: extFuncLogic

View File

@@ -37,6 +37,7 @@ Rectangle {
property bool hover: false
property bool pressed: false
property bool forceVisible: false
color: actionIndicator.showBackground ? StudioTheme.Values.themeControlBackground : "transparent"
border.color: actionIndicator.showBackground ? StudioTheme.Values.themeControlOutline : "transparent"
@@ -50,6 +51,7 @@ Rectangle {
id: actionIndicatorIcon
anchors.fill: parent
text: StudioTheme.Constants.actionIcon
visible: text != StudioTheme.Constants.actionIcon || actionIndicator.forceVisible
color: StudioTheme.Values.themeTextColor
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: StudioTheme.Values.myIconFontSize
@@ -65,6 +67,7 @@ Rectangle {
PropertyChanges {
target: actionIndicatorIcon
scale: 1.2
visible: true
}
},
State {

View File

@@ -778,7 +778,7 @@ void AndroidSettingsWidget::openNDKDownloadUrl()
void AndroidSettingsWidget::openOpenJDKDownloadUrl()
{
QDesktopServices::openUrl(QUrl::fromUserInput("http://www.oracle.com/technetwork/java/javase/downloads/"));
QDesktopServices::openUrl(QUrl::fromUserInput("https://www.oracle.com/java/technologies/javase-jdk8-downloads.html"));
}
void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)

View File

@@ -68,9 +68,8 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
static const QRegularExpression newTestSetStarts("^\\[ RUN \\] (.*)$");
static const QRegularExpression testSetSuccess("^\\[ OK \\] (.*) \\((.*)\\)$");
static const QRegularExpression testSetFail("^\\[ FAILED \\] (.*) \\((\\d+ ms)\\)$");
static const QRegularExpression testSetSkipped("^\\[ SKIPPED \\] (.*) \\((\\d+ ms)\\)$");
static const QRegularExpression disabledTests("^ YOU HAVE (\\d+) DISABLED TESTS?$");
static const QRegularExpression failureLocation("^(.*):(\\d+): Failure$");
static const QRegularExpression errorLocation("^(.*)\\((\\d+)\\): error:.*$");
static const QRegularExpression iterations("^Repeating all tests "
"\\(iteration (\\d+)\\) \\. \\. \\.$");
static const QRegularExpression logging("^\\[( FATAL | ERROR |WARNING| INFO )\\] "
@@ -126,6 +125,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
}
reportResult(testResult);
} else if (ExactMatch match = newTestSetStarts.match(line)) {
m_testSetStarted = true;
setCurrentTestCase(match.captured(1));
TestResultPtr testResult = TestResultPtr(new GTestResult(QString(), m_projectFile,
QString()));
@@ -134,6 +134,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
reportResult(testResult);
m_description.clear();
} else if (ExactMatch match = testSetSuccess.match(line)) {
m_testSetStarted = false;
TestResultPtr testResult = createDefaultResult();
testResult->setResult(ResultType::Pass);
testResult->setDescription(m_description);
@@ -145,40 +146,29 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
} else if (ExactMatch match = testSetFail.match(line)) {
m_testSetStarted = false;
TestResultPtr testResult = createDefaultResult();
testResult->setResult(ResultType::Fail);
m_description.chop(1);
QStringList resultDescription;
for (const QString &output : m_description.split('\n')) {
QRegularExpressionMatch innerMatch = failureLocation.match(output);
if (!innerMatch.hasMatch()) {
innerMatch = errorLocation.match(output);
if (!innerMatch.hasMatch()) {
resultDescription << output;
continue;
}
}
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult);
resultDescription.clear();
testResult = createDefaultResult();
testResult->setResult(ResultType::MessageLocation);
testResult->setLine(innerMatch.captured(2).toInt());
QString file = constructSourceFilePath(m_buildDir, innerMatch.captured(1));
if (!file.isEmpty())
testResult->setFileName(file);
resultDescription << output;
}
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult);
m_description.clear();
handleDescriptionAndReportResult(testResult);
testResult = createDefaultResult();
testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(match.captured(2)));
reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
} else if (ExactMatch match = testSetSkipped.match(line)) {
if (!m_testSetStarted) // ignore SKIPPED at summary
return;
m_testSetStarted = false;
TestResultPtr testResult = createDefaultResult();
testResult->setResult(ResultType::Skip);
m_description.chop(1);
m_description.prepend(match.captured(1) + '\n');
handleDescriptionAndReportResult(testResult);
testResult = createDefaultResult();
testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(match.captured(2)));
reportResult(testResult);
} else if (ExactMatch match = logging.match(line)) {
const QString severity = match.captured(1).trimmed();
ResultType type = ResultType::Invalid;
@@ -232,5 +222,38 @@ void GTestOutputReader::setCurrentTestSuite(const QString &testSuite)
m_currentTestSuite = testSuite;
}
void GTestOutputReader::handleDescriptionAndReportResult(TestResultPtr testResult)
{
static const QRegularExpression failureLocation("^(.*):(\\d+): Failure$");
static const QRegularExpression skipOrErrorLocation("^(.*)\\((\\d+)\\): (Skipped|error:.*)$");
QStringList resultDescription;
for (const QString &output : m_description.split('\n')) {
QRegularExpressionMatch innerMatch = failureLocation.match(output);
if (!innerMatch.hasMatch()) {
innerMatch = skipOrErrorLocation.match(output);
if (!innerMatch.hasMatch()) {
resultDescription << output;
continue;
}
}
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult);
resultDescription.clear();
testResult = createDefaultResult();
testResult->setResult(ResultType::MessageLocation);
testResult->setLine(innerMatch.captured(2).toInt());
QString file = constructSourceFilePath(m_buildDir, innerMatch.captured(1));
if (!file.isEmpty())
testResult->setFileName(file);
resultDescription << output;
}
testResult->setDescription(resultDescription.join('\n'));
reportResult(testResult);
m_description.clear();
}
} // namespace Internal
} // namespace Autotest

View File

@@ -50,12 +50,14 @@ protected:
private:
void setCurrentTestCase(const QString &testCase);
void setCurrentTestSuite(const QString &testSuite);
void handleDescriptionAndReportResult(TestResultPtr testResult);
QString m_projectFile;
QString m_currentTestSuite;
QString m_currentTestCase;
QString m_description;
int m_iteration = 1;
bool m_testSetStarted = false;
};
} // namespace Internal

View File

@@ -147,7 +147,10 @@ bool BackendReceiver::isExpectingCompletionsMessage() const
void BackendReceiver::reset()
{
// Clean up waiting assist processors
qDeleteAll(m_assistProcessorsTable.begin(), m_assistProcessorsTable.end());
for (ClangCompletionAssistProcessor *processor : m_assistProcessorsTable) {
processor->setAsyncProposalAvailable(nullptr);
delete processor;
}
m_assistProcessorsTable.clear();
// Clean up futures for references; TODO: Remove duplication

View File

@@ -137,16 +137,14 @@ static bool keySequenceIsValid(const QKeySequence &sequence)
return true;
}
static bool textKeySequence(const QKeySequence &sequence)
static bool isTextKeySequence(const QKeySequence &sequence)
{
if (sequence.isEmpty())
return false;
for (int i = 0; i < sequence.count(); ++i) {
int key = sequence[i];
int key = sequence[0];
key &= ~(Qt::ShiftModifier | Qt::KeypadModifier);
if (key < Qt::Key_Escape)
return true;
}
return false;
}
@@ -422,7 +420,7 @@ static bool checkValidity(const QList<ParsedKey> &keys, QString *warningMessage)
}
}
for (const ParsedKey &k : keys) {
if (textKeySequence(k.key)) {
if (isTextKeySequence(k.key)) {
*warningMessage = ShortcutSettingsWidget::tr(
"Key sequence \"%1\" will not work in editor.")
.arg(k.text);

View File

@@ -50,20 +50,14 @@
*/
/*!
\fn INavigationWidgetFactory::INavigationWidgetFactory()
Constructs a navigation widget factory.
*/
/*!
\fn QString INavigationWidgetFactory::displayName() const
\fn QString Core::INavigationWidgetFactory::displayName() const
Returns the display name of the navigation widget, which is shown in the dropdown menu above the
navigation widget.
*/
/*!
\fn int INavigationWidgetFactory::priority() const
\fn int Core::INavigationWidgetFactory::priority() const
Determines the position of the navigation widget in the dropdown menu.
@@ -71,13 +65,13 @@
*/
/*!
\fn Id INavigationWidgetFactory::id() const
\fn Id Core::INavigationWidgetFactory::id() const
Returns a unique identifier for referencing the navigation widget factory.
*/
/*!
\fn NavigationView INavigationWidgetFactory::createWidget()
\fn Core::NavigationView Core::INavigationWidgetFactory::createWidget()
Returns a \l{Core::NavigationView} containing the widget and the buttons. The ownership is given
to the caller.
@@ -88,7 +82,7 @@ using namespace Core;
static QList<INavigationWidgetFactory *> g_navigationWidgetFactories;
/*!
Creates a \l{Core::NavigationViewFactory}.
Constructs a navigation widget factory.
*/
INavigationWidgetFactory::INavigationWidgetFactory()
{
@@ -106,7 +100,7 @@ const QList<INavigationWidgetFactory *> INavigationWidgetFactory::allNavigationF
}
/*!
Sets the display name for the factory.
Sets the display name for the factory to \a displayName.
\sa displayName()
*/
@@ -116,7 +110,7 @@ void INavigationWidgetFactory::setDisplayName(const QString &displayName)
}
/*!
Sets the priority for the factory.
Sets the \a priority for the factory.
\sa priority()
*/
@@ -126,7 +120,7 @@ void INavigationWidgetFactory::setPriority(int priority)
}
/*!
Sets the id for the factory.
Sets the \a id for the factory.
\sa id()
*/
@@ -136,7 +130,7 @@ void INavigationWidgetFactory::setId(Id id)
}
/*!
Sets the keyboard activation sequence for the factory.
Sets the keyboard activation sequence for the factory to \a keys.
\sa activationSequence()
*/
@@ -154,7 +148,7 @@ QKeySequence INavigationWidgetFactory::activationSequence() const
}
/*!
Stores the settings for the \a widget at \a position that was created by this factory
Stores the \a settings for the \a widget at \a position that was created by this factory
(the \a position identifies a specific navigation widget).
\sa INavigationWidgetFactory::restoreSettings()
@@ -164,7 +158,7 @@ void INavigationWidgetFactory::saveSettings(QSettings * /* settings */, int /* p
}
/*!
Reads and restores the settings for the \a widget at \a position that was created by this
Reads and restores the \a settings for the \a widget at \a position that was created by this
factory (the \a position identifies a specific navigation widget).
\sa INavigationWidgetFactory::saveSettings()

View File

@@ -27,6 +27,8 @@
#include "ioutputpane.h"
namespace Core {
/*!
\class Core::IOutputPane
\brief The IOutputPane class is an interface for providing \uicontrol Output panes.
@@ -258,3 +260,5 @@
Displays \a number in the status bar button belonging to the output pane
(for example, number of issues on building).
*/
} // namespace Core

View File

@@ -37,6 +37,7 @@
/*!
\class Core::IVersionControl::TopicCache
\inmodule QtCreator
\brief The TopicCache class stores a cache which maps a directory to a topic.
A VCS topic is typically the current active branch name, but it can also have other

View File

@@ -125,7 +125,7 @@ void BaseTextDocument::setLineTerminationMode(Utils::TextFileFormat::LineTermina
Autodetects file format and reads the text file specified by \a fileName
into a list of strings specified by \a plainTextList.
If an error occurs while writing the file, \a errorMessage is set to the
If an error occurs while writing the file, \a errorString is set to the
error details.
Returns whether the operation was successful.
@@ -143,7 +143,7 @@ BaseTextDocument::ReadResult BaseTextDocument::read(const QString &fileName, QSt
Autodetects file format and reads the text file specified by \a fileName
into \a plainText.
If an error occurs while writing the file, \a errorMessage is set to the
If an error occurs while writing the file, \a errorString is set to the
error details.
Returns whether the operation was successful.

View File

@@ -339,6 +339,7 @@ using namespace Internal;
/*!
* \class Core::VariableChooser
* \inmodule QtCreator
* \brief The VariableChooser class is used to add a tool window for selecting \QC variables
* to line edits, text edits or plain text edits.
*
@@ -351,8 +352,8 @@ using namespace Internal;
* \image variablechooser.png "External Tools Preferences with Variable Chooser"
*
* The variable chooser monitors focus changes of all children of its parent widget.
* When a text control gets focus, the variable chooser checks if it has variable support set,
* either through the addVariableSupport() function. If the control supports variables,
* When a text control gets focus, the variable chooser checks if it has variable support set.
* If the control supports variables,
* a tool button which opens the variable chooser is shown in it while it has focus.
*
* Supported text controls are QLineEdit, QTextEdit and QPlainTextEdit.
@@ -375,7 +376,6 @@ using namespace Internal;
* Property name that is checked for deciding if a widget supports \QC variables.
* Can be manually set with
* \c{textcontrol->setProperty(VariableChooser::kVariableSupportProperty, true)}
* \sa addVariableSupport()
*/
const char kVariableSupportProperty[] = "QtCreator.VariableSupport";
const char kVariableNameProperty[] = "QtCreator.VariableName";
@@ -383,7 +383,6 @@ const char kVariableNameProperty[] = "QtCreator.VariableName";
/*!
* Creates a variable chooser that tracks all children of \a parent for variable support.
* Ownership is also transferred to \a parent.
* \sa addVariableSupport()
*/
VariableChooser::VariableChooser(QWidget *parent) :
QWidget(parent),
@@ -406,6 +405,9 @@ VariableChooser::~VariableChooser()
delete d;
}
/*!
Adds the macro expander provider \a provider.
*/
void VariableChooser::addMacroExpanderProvider(const MacroExpanderProvider &provider)
{
auto item = new VariableGroupItem;
@@ -415,8 +417,11 @@ void VariableChooser::addMacroExpanderProvider(const MacroExpanderProvider &prov
}
/*!
* Marks the control as supporting variables.
* \sa kVariableSupportProperty
* Marks the control \a textcontrol as supporting variables.
*
* If the control provides a variable to the macro expander itself, set
* \a ownName to the variable name to prevent the user from choosing the
* variable, which would lead to endless recursion.
*/
void VariableChooser::addSupportedWidget(QWidget *textcontrol, const QByteArray &ownName)
{

View File

@@ -1244,7 +1244,7 @@ void Client::initializeCallback(const InitializeRequest::Response &initResponse)
.value_or(QList<QString>()));
}
if (auto functionHintAssistProvider = qobject_cast<FunctionHintAssistProvider *>(
m_clientProviders.completionAssistProvider)) {
m_clientProviders.functionHintProvider)) {
functionHintAssistProvider->setTriggerCharacters(
m_serverCapabilities.signatureHelpProvider()
.value_or(ServerCapabilities::SignatureHelpOptions())

View File

@@ -25,6 +25,7 @@
#include "languageclientformatter.h"
#include "client.h"
#include "languageclientutils.h"
#include <texteditor/tabsettings.h>

View File

@@ -25,13 +25,16 @@
#pragma once
#include "client.h"
#include <languageserverprotocol/icontent.h>
#include <languageserverprotocol/languagefeatures.h>
#include <texteditor/formatter.h>
namespace TextEditor { class TextDocument; }
namespace LanguageClient {
class Client;
class LanguageClientFormatter : public TextEditor::Formatter
{
public:

View File

@@ -37,6 +37,7 @@ const char KIT_MCUTARGET_MODEL_KEY[] = "McuSupport.McuTargetModel";
const char SETTINGS_GROUP[] = "McuSupport";
const char SETTINGS_KEY_PACKAGE_PREFIX[] = "Package_";
const char SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK[] = "QtForMCUsSdk"; // Key known by SDK installer
} // namespace McuSupport
} // namespace Constants

View File

@@ -28,6 +28,7 @@
#include "mcusupportsdk.h"
#include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <debugger/debuggeritem.h>
#include <debugger/debuggeritemmanager.h>
@@ -56,6 +57,16 @@
namespace McuSupport {
namespace Internal {
static QString packagePathFromSettings(const QString &settingsKey, const QString &defaultPath = {})
{
QSettings *s = Core::ICore::settings();
s->beginGroup(Constants::SETTINGS_GROUP);
const QString path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX)
+ settingsKey, defaultPath).toString();
s->endGroup();
return path;
}
McuPackage::McuPackage(const QString &label, const QString &defaultPath,
const QString &detectionPath, const QString &settingsKey)
: m_label(label)
@@ -63,11 +74,7 @@ McuPackage::McuPackage(const QString &label, const QString &defaultPath,
, m_detectionPath(detectionPath)
, m_settingsKey(settingsKey)
{
QSettings *s = Core::ICore::settings();
s->beginGroup(Constants::SETTINGS_GROUP);
m_path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey,
m_defaultPath).toString();
s->endGroup();
m_path = packagePathFromSettings(settingsKey, defaultPath);
}
QString McuPackage::path() const
@@ -349,6 +356,22 @@ void McuSupportOptions::populatePackagesAndTargets()
setQulDir(Utils::FilePath::fromUserInput(qtForMCUsSdkPackage->path()));
}
void McuSupportOptions::registerQchFiles()
{
const QString qulDir = qulDirFromSettings().toString();
if (qulDir.isEmpty() || !QFileInfo::exists(qulDir))
return;
const QString docsPath = qulDir + "/docs/";
const QStringList qchFiles = {
docsPath + "quickultralite.qch",
docsPath + "quickultralitecmake.qch"
};
Core::HelpManager::registerDocumentation(
Utils::filtered(qchFiles,
[](const QString &file) { return QFileInfo::exists(file); }));
}
void McuSupportOptions::deletePackagesAndTargets()
{
qDeleteAll(packages);
@@ -370,6 +393,12 @@ void McuSupportOptions::setQulDir(const Utils::FilePath &dir)
emit changed();
}
Utils::FilePath McuSupportOptions::qulDirFromSettings()
{
return Utils::FilePath::fromUserInput(
packagePathFromSettings(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK));
}
static bool mcuTargetIsDesktop(const McuTarget* mcuTarget)
{
return mcuTarget->qulPlatform() == "Qt";

View File

@@ -160,12 +160,14 @@ public:
McuPackage *qtForMCUsSdkPackage = nullptr;
void setQulDir(const Utils::FilePath &dir);
static Utils::FilePath qulDirFromSettings();
QString kitName(const McuTarget* mcuTarget) const;
QList<ProjectExplorer::Kit *> existingKits(const McuTarget *mcuTargt);
ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget);
void populatePackagesAndTargets();
static void registerQchFiles();
private:
void deletePackagesAndTargets();

View File

@@ -223,14 +223,15 @@ void McuSupportOptionsWidget::showEvent(QShowEvent *event)
void McuSupportOptionsWidget::apply()
{
m_options.qtForMCUsSdkPackage->writeToSettings();
for (auto package : m_options.packages)
package->writeToSettings();
QTC_ASSERT(m_options.qtForMCUsSdkPackage, return);
if (!isVisible())
return;
McuSupportOptions::registerQchFiles();
const McuTarget *mcuTarget = currentMcuTarget();
if (!mcuTarget)
return;

View File

@@ -26,6 +26,7 @@
#include "mcusupportplugin.h"
#include "mcusupportconstants.h"
#include "mcusupportdevice.h"
#include "mcusupportoptions.h"
#include "mcusupportoptionspage.h"
#include "mcusupportrunconfiguration.h"
@@ -74,6 +75,7 @@ bool McuSupportPlugin::initialize(const QStringList& arguments, QString* errorSt
dd = new McuSupportPluginPrivate;
McuSupportOptions::registerQchFiles();
ProjectExplorer::JsonWizardFactory::addWizardPath(
Utils::FilePath::fromString(":/mcusupport/wizards/"));

View File

@@ -55,7 +55,7 @@ McuPackage *createQtForMCUsPackage()
McuPackage::tr("Qt for MCUs SDK"),
QDir::homePath(),
Utils::HostOsInfo::withExecutableSuffix("bin/qmltocpp"),
"QtForMCUsSdk");
Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK);
result->setEnvironmentVariableName("Qul_DIR");
return result;
}

View File

@@ -112,6 +112,7 @@ bool QmakeBuildSystem::supportsAction(Node *context, ProjectAction action, const
}
QTC_ASSERT(proFileNode, return false);
pro = proFileNode->proFile();
QTC_ASSERT(pro, return false);
t = pro->projectType();
}

View File

@@ -66,10 +66,27 @@ void ZoomAction::resetZoomLevel()
void ZoomAction::setZoomLevel(float zoomLevel)
{
m_zoomLevel = qBound(0.1f, zoomLevel, 16.0f);
if (qFuzzyCompare(m_zoomLevel, zoomLevel))
return;
m_zoomLevel = qBound(0.01f, zoomLevel, 16.0f);
emit zoomLevelChanged(m_zoomLevel);
}
//initial m_zoomLevel and m_currentComboBoxIndex
const QVector<float> s_zoomFactors = {0.01f, 0.02f, 0.05f, 0.0625f, 0.125f, 0.25f,
0.33f, 0.5f, 0.66f, 0.75f, 0.9f, 1.0f, 1.25f,
1.5f, 1.75f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 16.0f };
int getZoomIndex(float zoom)
{
for (int i = 0; i < s_zoomFactors.length(); i++) {
if (qFuzzyCompare(s_zoomFactors.at(i), zoom))
return i;
}
return -1;
}
QWidget *ZoomAction::createWidget(QWidget *parent)
{
auto comboBox = new QComboBox(parent);
@@ -79,28 +96,10 @@ QWidget *ZoomAction::createWidget(QWidget *parent)
*/
if (m_comboBoxModel.isNull()) {
m_comboBoxModel = comboBox->model();
comboBox->addItem(QLatin1String("1 %"), 0.01);
comboBox->addItem(QLatin1String("2 %"), 0.02);
comboBox->addItem(QLatin1String("5 %"), 0.05);
comboBox->addItem(QLatin1String("6.25 %"), 0.0625);
comboBox->addItem(QLatin1String("12.5 %"), 0.125);
comboBox->addItem(QLatin1String("25 %"), 0.25);
comboBox->addItem(QLatin1String("33 %"), 0.33);
comboBox->addItem(QLatin1String("50 %"), 0.5);
comboBox->addItem(QLatin1String("66 %"), 0.66);
comboBox->addItem(QLatin1String("75 %"), 0.75);
comboBox->addItem(QLatin1String("90 %"), 0.90);
comboBox->addItem(QLatin1String("100 %"), 1.0); // initial m_zoomLevel and m_currentComboBoxIndex
comboBox->addItem(QLatin1String("125 %"), 1.25);
comboBox->addItem(QLatin1String("150 %"), 1.5);
comboBox->addItem(QLatin1String("175 %"), 1.75);
comboBox->addItem(QLatin1String("200 %"), 2.0);
comboBox->addItem(QLatin1String("300 %"), 3.0);
comboBox->addItem(QLatin1String("400 %"), 4.0);
comboBox->addItem(QLatin1String("600 %"), 6.0);
comboBox->addItem(QLatin1String("800 %"), 8.0);
comboBox->addItem(QLatin1String("1000 %"), 10.0);
comboBox->addItem(QLatin1String("1600 %"), 16.0);
for (float z : s_zoomFactors) {
const QString name = QString::number(z * 100, 'g', 4) + " %";
comboBox->addItem(name, z);
}
} else {
comboBox->setModel(m_comboBoxModel.data());
}
@@ -126,6 +125,12 @@ QWidget *ZoomAction::createWidget(QWidget *parent)
connect(this, &ZoomAction::indexChanged, comboBox, &QComboBox::setCurrentIndex);
connect(this, &ZoomAction::zoomLevelChanged, comboBox, [comboBox](double zoom){
const int index = getZoomIndex(zoom);
if (comboBox->currentIndex() != index)
comboBox->setCurrentIndex(index);
});
comboBox->setProperty("hideborder", true);
comboBox->setMaximumWidth(qMax(comboBox->view()->sizeHintForColumn(0) / 2, 16));
return comboBox;

View File

@@ -47,10 +47,10 @@ public:
void zoomIn();
void zoomOut();
void resetZoomLevel();
void setZoomLevel(float zoomLevel);
protected:
QWidget *createWidget(QWidget *parent) override;
void setZoomLevel(float zoomLevel);
signals:
void zoomLevelChanged(float zoom);
void indexChanged(int);

View File

@@ -103,6 +103,15 @@ bool AnimationCurve::isFromData() const
return m_fromData;
}
bool AnimationCurve::hasUnified() const
{
for (auto &&frame : m_frames) {
if (frame.isUnified())
return true;
}
return false;
}
double AnimationCurve::minimumTime() const
{
if (!m_frames.empty())
@@ -144,6 +153,18 @@ std::string AnimationCurve::string() const
return sstream.str();
}
QString AnimationCurve::unifyString() const
{
QString out;
for (auto &&frame : m_frames) {
if (frame.isUnified())
out.append("1");
else
out.append("0");
}
return out;
}
CurveSegment AnimationCurve::segment(double time) const
{
CurveSegment seg;

View File

@@ -50,6 +50,8 @@ public:
bool isFromData() const;
bool hasUnified() const;
double minimumTime() const;
double maximumTime() const;
@@ -60,6 +62,8 @@ public:
std::string string() const;
QString unifyString() const;
CurveSegment segment(double time) const;
std::vector<CurveSegment> segments() const;

View File

@@ -86,6 +86,7 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
QAction *tangentStepAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsStepIcon.png"), "Step");
QAction *tangentSplineAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsSplineIcon.png"), "Spline");
QAction *tangentDefaultAction = bar->addAction("Set Default");
QAction *tangentUnifyAction = bar->addAction("Unify");
auto setLinearInterpolation = [this]() {
m_view->setInterpolation(Keyframe::Interpolation::Linear);
@@ -97,9 +98,12 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
m_view->setInterpolation(Keyframe::Interpolation::Bezier);
};
auto toggleUnifyKeyframe = [this]() { m_view->toggleUnified(); };
connect(tangentLinearAction, &QAction::triggered, setLinearInterpolation);
connect(tangentStepAction, &QAction::triggered, setStepInterpolation);
connect(tangentSplineAction, &QAction::triggered, setSplineInterpolation);
connect(tangentUnifyAction, &QAction::triggered, toggleUnifyKeyframe);
Q_UNUSED(tangentLinearAction);
Q_UNUSED(tangentSplineAction);

View File

@@ -62,6 +62,9 @@ struct KeyframeItemStyleOption
double size = 10.0;
QColor color = QColor(200, 200, 0);
QColor selectionColor = QColor(200, 200, 200);
QColor lockedColor = QColor(50, 50, 50);
QColor unifiedColor = QColor(250, 50, 250);
QColor splitColor = QColor(0, 250, 0);
};
struct CurveItemStyleOption

View File

@@ -447,9 +447,11 @@ std::array<Keyframe, 3> CurveSegment::splitAt(double time)
out[0].setInterpolation(left().interpolation());
out[0].setData(left().data());
out[0].setUnified(left().isUnified());
out[2].setInterpolation(right().interpolation());
out[2].setData(right().data());
out[2].setUnified(right().isUnified());
return out;
}
}

View File

@@ -297,6 +297,8 @@ void CurveItem::setCurve(const AnimationCurve &curve)
item->setComponentTransform(m_transform);
m_keyframes.push_back(item);
QObject::connect(item, &KeyframeItem::redrawCurve, this, &CurveItem::emitCurveChanged);
QObject::connect(item, &KeyframeItem::keyframeMoved, this, &CurveItem::keyframeMoved);
QObject::connect(item, &KeyframeItem::handleMoved, this, &CurveItem::handleMoved);
}
emitCurveChanged();
@@ -344,14 +346,24 @@ void CurveItem::setInterpolation(Keyframe::Interpolation interpolation)
emit curveChanged(id(), curve());
}
void CurveItem::toggleUnified()
{
if (m_keyframes.empty())
return;
for (auto *frame : m_keyframes) {
if (frame->selected())
frame->toggleUnified();
}
emit curveChanged(id(), curve());
}
void CurveItem::connect(GraphicsScene *scene)
{
QObject::connect(this, &CurveItem::curveChanged, scene, &GraphicsScene::curveChanged);
for (auto *frame : m_keyframes) {
QObject::connect(frame, &KeyframeItem::keyframeMoved, scene, &GraphicsScene::keyframeMoved);
QObject::connect(frame, &KeyframeItem::handleMoved, scene, &GraphicsScene::handleMoved);
}
QObject::connect(this, &CurveItem::keyframeMoved, scene, &GraphicsScene::keyframeMoved);
QObject::connect(this, &CurveItem::handleMoved, scene, &GraphicsScene::handleMoved);
}
void CurveItem::insertKeyframeByTime(double time)

View File

@@ -27,6 +27,7 @@
#include "curveeditorstyle.h"
#include "curvesegment.h"
#include "handleitem.h"
#include "keyframe.h"
#include "selectableitem.h"
#include "treeitem.h"
@@ -47,6 +48,10 @@ class CurveItem : public CurveEditorItem
signals:
void curveChanged(unsigned int id, const AnimationCurve &curve);
void keyframeMoved(KeyframeItem *item, const QPointF &direction);
void handleMoved(KeyframeItem *frame, HandleItem::Slot slot, double angle, double deltaLength);
public:
CurveItem(QGraphicsItem *parent = nullptr);
@@ -100,6 +105,8 @@ public:
void setInterpolation(Keyframe::Interpolation interpolation);
void toggleUnified();
void connect(GraphicsScene *scene);
void insertKeyframeByTime(double time);

View File

@@ -37,6 +37,7 @@ GraphicsScene::GraphicsScene(QObject *parent)
: QGraphicsScene(parent)
, m_dirty(true)
, m_limits()
, m_doNotMoveItems(false)
{}
bool GraphicsScene::empty() const
@@ -64,6 +65,11 @@ double GraphicsScene::maximumValue() const
return limits().top();
}
void GraphicsScene::doNotMoveItems(bool val)
{
m_doNotMoveItems = val;
}
void GraphicsScene::addCurveItem(CurveItem *item)
{
m_dirty = true;
@@ -111,10 +117,9 @@ void GraphicsScene::handleUnderMouse(HandleItem *handle)
if (item == handle)
continue;
if (auto *handleItem = qgraphicsitem_cast<HandleItem *>(item)) {
if (handleItem->selected()) {
if (handleItem->slot() == handle->slot())
handleItem->setActivated(handle->isUnderMouse());
if (auto *keyItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
if (keyItem->selected()) {
keyItem->setActivated(handle->isUnderMouse(), handle->slot());
}
}
}
@@ -125,14 +130,29 @@ void GraphicsScene::handleMoved(KeyframeItem *frame,
double angle,
double deltaLength)
{
if (m_doNotMoveItems)
return;
auto moveUnified = [handle, angle, deltaLength](KeyframeItem *key) {
if (key->isUnified()) {
if (handle == HandleItem::Slot::Left)
key->moveHandle(HandleItem::Slot::Right, angle, deltaLength);
else
key->moveHandle(HandleItem::Slot::Left, angle, deltaLength);
}
};
const auto itemList = items();
for (auto *item : itemList) {
if (item == frame)
continue;
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
if (frameItem->selected())
if (item == frame) {
moveUnified(frameItem);
continue;
}
if (frameItem->selected()) {
frameItem->moveHandle(handle, angle, deltaLength);
moveUnified(frameItem);
}
}
}
}

View File

@@ -61,6 +61,8 @@ public:
double maximumValue() const;
void doNotMoveItems(bool tmp);
void addCurveItem(CurveItem *item);
void setComponentTransform(const QTransform &transform);
@@ -90,6 +92,8 @@ private:
mutable bool m_dirty;
mutable QRectF m_limits;
bool m_doNotMoveItems;
};
} // End namespace DesignTools.

View File

@@ -275,6 +275,18 @@ void GraphicsView::setInterpolation(Keyframe::Interpolation interpol)
viewport()->update();
}
void GraphicsView::toggleUnified()
{
const auto itemList = items();
for (auto *item : itemList) {
if (auto *citem = qgraphicsitem_cast<CurveItem *>(item)) {
if (citem->hasSelection())
citem->toggleUnified();
}
}
viewport()->update();
}
void GraphicsView::resizeEvent(QResizeEvent *event)
{
QGraphicsView::resizeEvent(event);
@@ -433,6 +445,8 @@ QPointF GraphicsView::globalToRaster(const QPoint &point) const
void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
{
m_scene.doNotMoveItems(true);
QPointF pivotRaster(globalToRaster(pivot));
m_zoomX = clamp(x, 0.0, 1.0);
@@ -471,6 +485,8 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
QPointF deltaTransformed = pivotRaster - globalToRaster(pivot);
scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
}
m_scene.doNotMoveItems(false);
}
void GraphicsView::insertKeyframe(double time, bool allVisibleCurves)

View File

@@ -112,6 +112,8 @@ public:
void setInterpolation(Keyframe::Interpolation interpol);
void toggleUnified();
protected:
void resizeEvent(QResizeEvent *event) override;

View File

@@ -130,7 +130,7 @@ void HandleItem::setStyle(const CurveEditorStyle &style)
QVariant HandleItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemPositionChange) {
if (KeyframeItem *parent = qgraphicsitem_cast<KeyframeItem *>(parentItem())) {
if (qgraphicsitem_cast<KeyframeItem *>(parentItem())) {
QPointF pos = value.toPointF();
if (m_slot == HandleItem::Slot::Left) {
if (pos.x() > 0.0)

View File

@@ -64,14 +64,22 @@ void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
Q_UNUSED(option)
Q_UNUSED(widget)
QColor mainColor = selected() ? m_style.selectionColor : m_style.color;
QColor borderColor = isUnified() ? m_style.unifiedColor : m_style.splitColor;
if (locked()) {
mainColor = m_style.lockedColor;
borderColor = m_style.lockedColor;
}
QPen pen = painter->pen();
pen.setColor(Qt::black);
pen.setWidthF(1.);
pen.setColor(borderColor);
painter->save();
painter->setPen(pen);
painter->setBrush(locked() ? Qt::black : (selected() ? Qt::red : m_style.color));
painter->setBrush(mainColor);
painter->drawEllipse(boundingRect());
painter->restore();
}
@@ -93,6 +101,11 @@ Keyframe KeyframeItem::keyframe() const
return m_frame;
}
bool KeyframeItem::isUnified() const
{
return m_frame.isUnified();
}
bool KeyframeItem::hasLeftHandle() const
{
return m_frame.hasLeftHandle();
@@ -108,11 +121,6 @@ QTransform KeyframeItem::transform() const
return m_transform;
}
bool KeyframeItem::contains(HandleItem *handle, const QPointF &point) const
{
return false;
}
void KeyframeItem::setHandleVisibility(bool visible)
{
m_visibleOverride = visible;
@@ -195,6 +203,31 @@ void KeyframeItem::setKeyframe(const Keyframe &keyframe)
setPos(m_transform.map(m_frame.position()));
}
void KeyframeItem::toggleUnified()
{
if (!m_left || !m_right)
return;
if (m_frame.isUnified())
m_frame.setUnified(false);
else
m_frame.setUnified(true);
}
void KeyframeItem::setActivated(bool active, HandleItem::Slot slot)
{
if (isUnified() && m_left && m_right) {
m_left->setActivated(active);
m_right->setActivated(active);
return;
}
if (slot == HandleItem::Slot::Left && m_left)
m_left->setActivated(active);
else if (slot == HandleItem::Slot::Right && m_right)
m_right->setActivated(active);
}
void KeyframeItem::setInterpolation(Keyframe::Interpolation interpolation)
{
m_frame.setInterpolation(interpolation);

View File

@@ -66,14 +66,14 @@ public:
Keyframe keyframe() const;
bool isUnified() const;
bool hasLeftHandle() const;
bool hasRightHandle() const;
QTransform transform() const;
bool contains(HandleItem *handle, const QPointF &point) const;
void setHandleVisibility(bool visible);
void setComponentTransform(const QTransform &transform);
@@ -82,6 +82,10 @@ public:
void setKeyframe(const Keyframe &keyframe);
void toggleUnified();
void setActivated(bool active, HandleItem::Slot slot);
void setInterpolation(Keyframe::Interpolation interpolation);
void setLeftHandle(const QPointF &pos);

View File

@@ -31,6 +31,7 @@ namespace DesignTools {
Keyframe::Keyframe()
: m_interpolation(Interpolation::Undefined)
, m_unified(false)
, m_position()
, m_leftHandle()
, m_rightHandle()
@@ -39,6 +40,7 @@ Keyframe::Keyframe()
Keyframe::Keyframe(const QPointF &position)
: m_interpolation(Interpolation::Linear)
, m_unified(false)
, m_position(position)
, m_leftHandle()
, m_rightHandle()
@@ -47,6 +49,7 @@ Keyframe::Keyframe(const QPointF &position)
Keyframe::Keyframe(const QPointF &position, const QVariant &data)
: m_interpolation(Interpolation::Undefined)
, m_unified(false)
, m_position(position)
, m_leftHandle()
, m_rightHandle()
@@ -57,6 +60,7 @@ Keyframe::Keyframe(const QPointF &position, const QVariant &data)
Keyframe::Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle)
: m_interpolation(Interpolation::Bezier)
, m_unified(false)
, m_position(position)
, m_leftHandle(leftHandle)
, m_rightHandle(rightHandle)
@@ -73,6 +77,11 @@ bool Keyframe::hasData() const
return m_data.isValid();
}
bool Keyframe::isUnified() const
{
return m_unified;
}
bool Keyframe::hasLeftHandle() const
{
return !m_leftHandle.isNull();
@@ -143,6 +152,11 @@ void Keyframe::setPosition(const QPointF &pos)
m_position = pos;
}
void Keyframe::setUnified(bool unified)
{
m_unified = unified;
}
void Keyframe::setLeftHandle(const QPointF &pos)
{
m_leftHandle = pos;

View File

@@ -47,6 +47,8 @@ public:
bool hasData() const;
bool isUnified() const;
bool hasLeftHandle() const;
bool hasRightHandle() const;
@@ -63,6 +65,8 @@ public:
Interpolation interpolation() const;
void setUnified(bool unified);
void setPosition(const QPointF &pos);
void setLeftHandle(const QPointF &pos);
@@ -76,6 +80,8 @@ public:
private:
Interpolation m_interpolation = Interpolation::Undefined;
bool m_unified;
QPointF m_position;
QPointF m_leftHandle;

View File

@@ -311,6 +311,16 @@ AnimationCurve PropertyTreeItem::curve() const
return m_curve;
}
bool PropertyTreeItem::hasUnified() const
{
return m_curve.hasUnified();
}
QString PropertyTreeItem::unifyString() const
{
return m_curve.unifyString();
}
void PropertyTreeItem::setCurve(const AnimationCurve &curve)
{
m_curve = curve;

View File

@@ -155,6 +155,10 @@ public:
AnimationCurve curve() const;
bool hasUnified() const;
QString unifyString() const;
void setCurve(const AnimationCurve &curve);
void setComponent(const Component &comp);

View File

@@ -35,6 +35,13 @@ BackgroundAction::BackgroundAction(QObject *parent) :
{
}
void BackgroundAction::setColor(const QColor &color)
{
if (m_comboBox)
m_comboBox->setCurrentIndex(colors().indexOf(color));
}
QIcon iconForColor(const QColor &color) {
const int size = 16;
QImage image(size, size, QImage::Format_ARGB32);
@@ -69,6 +76,7 @@ QWidget *BackgroundAction::createWidget(QWidget *parent)
comboBox->setProperty("hideborder", true);
comboBox->setToolTip(tr("Set the color of the canvas."));
m_comboBox = comboBox;
return comboBox;
}
@@ -83,6 +91,7 @@ QList<QColor> BackgroundAction::colors()
static QColor alphaZero(Qt::transparent);
static QList<QColor> colorList = {alphaZero,
QColor(Qt::black),
QColor("#4c4e50"),
QColor(Qt::darkGray),
QColor(Qt::lightGray),
QColor(Qt::white)};

View File

@@ -25,6 +25,9 @@
#pragma once
#include <QWidgetAction>
#include <QPointer>
QT_FORWARD_DECLARE_CLASS(QComboBox)
namespace QmlDesigner {
@@ -39,6 +42,7 @@ class BackgroundAction : public QWidgetAction
Q_OBJECT
public:
explicit BackgroundAction(QObject *parent);
void setColor(const QColor &color);
signals:
void backgroundChanged(const QColor &color);
@@ -51,6 +55,7 @@ private:
private:
static QList<QColor> colors();
QPointer<QComboBox> m_comboBox;
};
} // namespace QmlDesigner

View File

@@ -754,7 +754,12 @@ static void paintConnection(QPainter *painter,
const bool boolExitRight = from.right() < to.center().x();
const bool boolExitBottom = from.bottom() < to.center().y();
bool horizontalFirst = horizontalOverlap(from, to) && !verticalOverlap(from, to);
bool horizontalFirst = true;
/*
if (verticalOverlap(from, to) && !horizontalOverlap(from, to))
horizontalFirst = false;
*/
const qreal middleFactor = breakOffset / 100.0;
@@ -766,12 +771,18 @@ static void paintConnection(QPainter *painter,
if (to.center().x() > from.left() && to.center().x() < from.right()) {
horizontalFirst = false;
extraLine = true;
} else if (verticalOverlap(from, to)) {
horizontalFirst = true;
extraLine = true;
}
} else {
if (to.center().y() > from.top() && to.center().y() < from.bottom()) {
horizontalFirst = true;
extraLine = true;
} else if (horizontalOverlap(from, to)) {
horizontalFirst = false;
extraLine = true;
}
}
@@ -913,35 +924,84 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
return;
if (!(qmlItemNode().modelNode().hasBindingProperty("from")
&& qmlItemNode().modelNode().hasBindingProperty("from")))
&& qmlItemNode().modelNode().hasBindingProperty("to")))
return;
painter->save();
const QmlFlowItemNode from = qmlItemNode().modelNode().bindingProperty("from").resolveToModelNode();
QmlFlowItemNode from = qmlItemNode().modelNode().bindingProperty("from").resolveToModelNode();
const QmlFlowItemNode to = qmlItemNode().modelNode().bindingProperty("to").resolveToModelNode();
QmlFlowActionAreaNode areaNode = ModelNode();
if (from.isValid() && to.isValid())
bool joinConnection = false;
bool isStartLine = false;
bool isWildcardLine = false;
if (from.isValid()) {
for (const QmlFlowActionAreaNode &area : from.flowActionAreas()) {
if (area.targetTransition() == qmlItemNode().modelNode())
ModelNode target = area.targetTransition();
if (target == qmlItemNode().modelNode()) {
areaNode = area;
} else {
const ModelNode decisionNode = area.decisionNodeForTransition(qmlItemNode().modelNode());
if (decisionNode.isValid()) {
from = decisionNode;
areaNode = ModelNode();
}
}
}
if (from.modelNode().hasAuxiliaryData("joinConnection"))
joinConnection = from.modelNode().auxiliaryData("joinConnection").toBool();
} else {
if (from == qmlItemNode().rootModelNode()) {
isStartLine = true;
} else {
for (const ModelNode wildcard : QmlFlowViewNode(qmlItemNode().rootModelNode()).wildcards()) {
if (wildcard.bindingProperty("target").resolveToModelNode() == qmlItemNode().modelNode()) {
from = wildcard;
isWildcardLine = true;
}
}
}
}
if (!from.modelNode().isValid())
return;
QRectF fromRect = QmlItemNode(from).instanceBoundingRect();
if (QmlItemNode(from).isFlowDecision())
fromRect = QRectF(0,0,200,200);
if (QmlItemNode(from).isFlowWildcard())
fromRect = QRectF(0,0,200,200);
fromRect.translate(QmlItemNode(from).flowPosition());
if (isStartLine) {
fromRect = QRectF(0,0,100,100);
fromRect.translate(QmlItemNode(to).flowPosition()- QPoint(200, 0));
}
if (areaNode.isValid()) {
if (!joinConnection && areaNode.isValid()) {
fromRect = QmlItemNode(areaNode).instanceBoundingRect();
fromRect.translate(QmlItemNode(from).flowPosition());
fromRect.translate(areaNode.instancePosition());
}
QRectF toRect = QmlItemNode(to).instanceBoundingRect();
if (QmlItemNode(to).isFlowDecision())
toRect = QRectF(0,0,200,200);
toRect.translate(QmlItemNode(to).flowPosition());
if (isStartLine) {
fromRect = QRectF(0,0,50,50);
fromRect.translate(QmlItemNode(to).flowPosition() + QPoint(-120, toRect.height() / 2 - 25));
}
toRect.translate(-pos());
fromRect.translate(-pos());
@@ -961,6 +1021,9 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
QColor color = "#e71919";
if (isStartLine)
color = "blue";
bool dash = false;
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
@@ -985,6 +1048,23 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
paintConnection(painter, fromRect, toRect, width, adjustedWidth ,color, dash, outOffset, inOffset, breakOffset);
if (isStartLine) {
QPen pen;
pen.setCosmetic(true);
pen.setColor(color);
painter->setPen(pen);
painter->drawRect(fromRect);
if (scaleFactor > 0.4) {
painter->drawLine(fromRect.topRight() + QPoint(20,10), fromRect.bottomRight() + QPoint(20,-10));
painter->drawLine(fromRect.topRight() + QPoint(25,12), fromRect.bottomRight() + QPoint(25,-12));
painter->drawLine(fromRect.topRight() + QPoint(30,15), fromRect.bottomRight() + QPoint(30,-15));
painter->drawLine(fromRect.topRight() + QPoint(35,17), fromRect.bottomRight() + QPoint(35,-17));
painter->drawLine(fromRect.topRight() + QPoint(40,20), fromRect.bottomRight() + QPoint(40,-20));
}
}
painter->restore();
}
@@ -1011,4 +1091,83 @@ QTransform FormEditorItem::viewportTransform() const
return scene()->views().first()->viewportTransform();
}
void FormEditorFlowDecisionItem::updateGeometry()
{
prepareGeometryChange();
m_selectionBoundingRect = QRectF(0,0, 200, 200);
m_paintedBoundingRect = m_selectionBoundingRect;
m_boundingRect = m_paintedBoundingRect;
setTransform(qmlItemNode().instanceTransformWithContentTransform());
const QPointF pos = qmlItemNode().flowPosition();
setTransform(QTransform::fromTranslate(pos.x(), pos.y()));
}
void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
if (!painter->isActive())
return;
painter->save();
QPen pen;
pen.setJoinStyle(Qt::MiterJoin);
pen.setCosmetic(true);
QColor flowColor = "#e71919";
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
flowColor = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
const qreal scaleFactor = viewportTransform().m11();
qreal width = 2;
if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
width = qmlItemNode().modelNode().auxiliaryData("width").toInt();
bool dash = false;
if (qmlItemNode().modelNode().hasAuxiliaryData("dash"))
dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool();
pen.setColor(flowColor);
if (dash)
pen.setStyle(Qt::DashLine);
else
pen.setStyle(Qt::SolidLine);
pen.setWidthF(width);
pen.setCosmetic(true);
painter->setPen(pen);
if (qmlItemNode().modelNode().hasAuxiliaryData("fillColor")) {
const QColor fillColor = qmlItemNode().modelNode().auxiliaryData("fillColor").value<QColor>();
painter->fillRect(boundingRect(), fillColor);
}
painter->drawLine(boundingRect().left(), boundingRect().center().y(),
boundingRect().center().x(), boundingRect().top());
painter->drawLine(boundingRect().center().x(), boundingRect().top(),
boundingRect().right(), boundingRect().center().y());
painter->drawLine(boundingRect().right(), boundingRect().center().y(),
boundingRect().center().x(), boundingRect().bottom());
painter->drawLine(boundingRect().center().x(), boundingRect().bottom(),
boundingRect().left(), boundingRect().center().y());
painter->restore();
}
bool FormEditorFlowDecisionItem::flowHitTest(const QPointF &point) const
{
return true;
}
void FormEditorFlowWildcardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
FormEditorFlowDecisionItem::paint(painter, option, widget);
}
} //QmlDesigner

View File

@@ -1,3 +1,4 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
@@ -196,6 +197,33 @@ private:
mutable bool m_hitTest = false;
};
class FormEditorFlowDecisionItem : FormEditorFlowItem
{
friend class QmlDesigner::FormEditorScene;
public:
void updateGeometry() override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
bool flowHitTest(const QPointF &point) const override;
protected:
FormEditorFlowDecisionItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
: FormEditorFlowItem(qmlItemNode, scene)
{}
};
class FormEditorFlowWildcardItem : FormEditorFlowDecisionItem
{
friend class QmlDesigner::FormEditorScene;
public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
protected:
FormEditorFlowWildcardItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
: FormEditorFlowDecisionItem(qmlItemNode, scene)
{}
};
inline int FormEditorItem::type() const
{

View File

@@ -178,6 +178,10 @@ FormEditorItem *FormEditorScene::addFormEditorItem(const QmlItemNode &qmlItemNod
formEditorItem = new FormEditorFlowActionItem(qmlItemNode, this);
else if (type == FlowTransition)
formEditorItem = new FormEditorTransitionItem(qmlItemNode, this);
else if (type == FlowDecision)
formEditorItem = new FormEditorFlowDecisionItem(qmlItemNode, this);
else if (type == FlowWildcard)
formEditorItem = new FormEditorFlowWildcardItem(qmlItemNode, this);
else
formEditorItem = new FormEditorItem(qmlItemNode, this);

View File

@@ -55,7 +55,9 @@ public:
Default,
Flow,
FlowAction,
FlowTransition
FlowTransition,
FlowDecision,
FlowWildcard
};
FormEditorScene(FormEditorWidget *widget, FormEditorView *editorView);

View File

@@ -105,6 +105,16 @@ void FormEditorView::setupFormEditorItemTree(const QmlItemNode &qmlItemNode)
if (qmlItemNode.hasNodeParent())
m_scene->reparentItem(qmlItemNode, qmlItemNode.modelParentItem());
m_scene->synchronizeTransformation(m_scene->itemForQmlItemNode(qmlItemNode));
} else if (qmlItemNode.isFlowDecision()) {
m_scene->addFormEditorItem(qmlItemNode, FormEditorScene::FlowDecision);
if (qmlItemNode.hasNodeParent())
m_scene->reparentItem(qmlItemNode, qmlItemNode.modelParentItem());
m_scene->synchronizeTransformation(m_scene->itemForQmlItemNode(qmlItemNode));
} else if (qmlItemNode.isFlowWildcard()) {
m_scene->addFormEditorItem(qmlItemNode, FormEditorScene::FlowWildcard);
if (qmlItemNode.hasNodeParent())
m_scene->reparentItem(qmlItemNode, qmlItemNode.modelParentItem());
m_scene->synchronizeTransformation(m_scene->itemForQmlItemNode(qmlItemNode));
} else if (qmlItemNode.isFlowActionArea()) {
m_scene->addFormEditorItem(qmlItemNode.toQmlItemNode(), FormEditorScene::FlowAction);
m_scene->synchronizeParent(qmlItemNode.toQmlItemNode());
@@ -134,6 +144,10 @@ void FormEditorView::setupFormEditorItemTree(const QmlItemNode &qmlItemNode)
for (const QmlObjectNode &nextNode : qmlItemNode.allDirectSubNodes()) {
if (QmlVisualNode::isValidQmlVisualNode(nextNode) && nextNode.toQmlVisualNode().isFlowTransition()) {
setupFormEditorItemTree(nextNode.toQmlItemNode());
} else if (QmlVisualNode::isValidQmlVisualNode(nextNode) && nextNode.toQmlVisualNode().isFlowDecision()) {
setupFormEditorItemTree(nextNode.toQmlItemNode());
} else if (QmlVisualNode::isValidQmlVisualNode(nextNode) && nextNode.toQmlVisualNode().isFlowWildcard()) {
setupFormEditorItemTree(nextNode.toQmlItemNode());
}
}
} else {

View File

@@ -195,10 +195,14 @@ void FormEditorWidget::changeRootItemHeight(const QString &heighText)
void FormEditorWidget::changeBackgound(const QColor &color)
{
if (color.alpha() == 0)
if (color.alpha() == 0) {
m_graphicsView->activateCheckboardBackground();
else
if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorColor"))
m_formEditorView->rootModelNode().setAuxiliaryData("formeditorColor", {});
} else {
m_graphicsView->activateColoredBackground(color);
m_formEditorView->rootModelNode().setAuxiliaryData("formeditorColor", color);
}
}
void FormEditorWidget::registerActionAsCommand(QAction *action, Core::Id id, const QKeySequence &keysequence)
@@ -236,6 +240,17 @@ void FormEditorWidget::updateActions()
m_rootHeightAction->setLineEditText(m_formEditorView->rootModelNode().auxiliaryData("height").toString());
else
m_rootHeightAction->clearLineEditText();
if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorColor"))
m_backgroundAction->setColor(m_formEditorView->rootModelNode().auxiliaryData("formeditorColor").value<QColor>());
else
m_backgroundAction->setColor(Qt::transparent);
if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorZoom"))
m_zoomAction->setZoomLevel(m_formEditorView->rootModelNode().auxiliaryData("formeditorZoom").toDouble());
else
m_zoomAction->setZoomLevel(1.0);
} else {
m_rootWidthAction->clearLineEditText();
m_rootHeightAction->clearLineEditText();
@@ -314,6 +329,13 @@ void FormEditorWidget::setZoomLevel(double zoomLevel)
m_graphicsView->resetTransform();
m_graphicsView->scale(zoomLevel, zoomLevel);
if (zoomLevel == 1.0) {
if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorZoom"))
m_formEditorView->rootModelNode().setAuxiliaryData("formeditorZoom", {});
} else {
m_formEditorView->rootModelNode().setAuxiliaryData("formeditorZoom", zoomLevel);
}
}
void FormEditorWidget::setScene(FormEditorScene *scene)

View File

@@ -186,12 +186,6 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
qCInfo(itemlibraryPopulate) << "required import: " << entry.requiredImport() << entryToImport(entry).toImportString();
if (!isItem && valid) {
qDebug() << Q_FUNC_INFO;
qDebug() << metaInfo.typeName() << "is not a QtQuick.Item";
qDebug() << Utils::transform(metaInfo.superClasses(), &NodeMetaInfo::typeName);
}
bool forceVisiblity = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary();
if (m_flowMode) {

View File

@@ -185,6 +185,9 @@ void GradientModel::setColor(int index, const QColor &color)
if (locked())
return;
if (!m_itemNode.isValid())
return;
if (!m_itemNode.modelNode().isSelected())
return;

View File

@@ -161,6 +161,8 @@ QVariant properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode,
return 50;
else if (propertyName == "customId")
return QString();
else if (propertyName == "joinConnection")
return false;
return {};
}
@@ -228,7 +230,7 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml
if (itemNode.isFlowTransition()) {
propertyNames.append({"color", "width", "inOffset", "outOffset", "dash", "breakPoint"});
} else if (itemNode.isFlowItem()) {
propertyNames.append({"color", "width", "inOffset", "outOffset"});
propertyNames.append({"color", "width", "inOffset", "outOffset", "joinConnection"});
} else if (itemNode.isFlowActionArea()) {
propertyNames.append({"color", "width", "fillColor", "outOffset", "dash"});
}

View File

@@ -230,6 +230,19 @@ DesignTools::AnimationCurve AnimationCurveEditorModel::createDoubleCurve(
{
std::vector<DesignTools::Keyframe> keyframes = createKeyframes(group.keyframePositions());
keyframes = resolveSmallCurves(keyframes);
QString str;
ModelNode target = group.modelNode();
if (target.hasAuxiliaryData("unified"))
str = target.auxiliaryData("unified").toString();
if (str.size() == static_cast<int>(keyframes.size())) {
for (int i = 0; i < str.size(); ++i) {
if (str.at(i) == '1')
keyframes[i].setUnified(true);
}
}
return DesignTools::AnimationCurve(keyframes);
}

View File

@@ -253,11 +253,6 @@ void TimelineToolBar::openAnimationCurveEditor()
m_dialog->show();
}
void TimelineToolBar::updateCurve(DesignTools::PropertyTreeItem *item)
{
DesignTools::AnimationCurve curve = item->curve();
}
void TimelineToolBar::createLeftControls()
{
auto addActionToGroup = [&](QAction *action) {

View File

@@ -91,8 +91,6 @@ public:
void openAnimationCurveEditor();
void updateCurve(DesignTools::PropertyTreeItem *item);
protected:
void resizeEvent(QResizeEvent *event) override;

View File

@@ -340,6 +340,11 @@ void TimelineWidget::updateAnimationCurve(DesignTools::PropertyTreeItem *item)
groupNode.setAuxiliaryData("pinned", true);
else
groupNode.removeAuxiliaryData("pinned");
if (item->hasUnified())
groupNode.setAuxiliaryData("unified", item->unifyString());
else
groupNode.removeAuxiliaryData("unified");
}
auto replaceKeyframes = [&group, item, this]() {

View File

@@ -126,6 +126,7 @@ public:
bool isFlowView() const;
bool isFlowItem() const;
bool isFlowActionArea() const;
ModelNode rootModelNode() const;
};
class QmlFlowItemNode;
@@ -141,6 +142,7 @@ public:
void assignTargetFlowItem(const QmlFlowItemNode &flowItem);
QmlFlowItemNode flowItemParent() const;
void destroyTarget();
ModelNode decisionNodeForTransition(const ModelNode &transition) const;
};
class QMLDESIGNERCORE_EXPORT QmlFlowItemNode : public QmlItemNode
@@ -161,7 +163,8 @@ public:
static bool isValidQmlFlowViewNode(const ModelNode &modelNode);
QList<QmlFlowItemNode> flowItems() const;
ModelNode addTransition(const QmlFlowItemNode &from, const QmlFlowItemNode &to);
QList<ModelNode> transitions() const;
const QList<ModelNode> transitions() const;
const QList<ModelNode> wildcards() const;
};

View File

@@ -109,8 +109,12 @@ public:
static NodeListProperty findSceneNodeProperty(AbstractView *view, qint32 sceneRootId);
static bool isFlowTransition(const ModelNode &node);
static bool isFlowDecision(const ModelNode &node);
static bool isFlowWildcard(const ModelNode &node);
bool isFlowTransition() const;
bool isFlowDecision() const;
bool isFlowWildcard() const;
private:
void setDoubleProperty(const PropertyName &name, double value);

View File

@@ -886,6 +886,9 @@ void ModelPrivate::notifyPropertiesAboutToBeRemoved(const QList<InternalProperty
void ModelPrivate::setAuxiliaryData(const InternalNode::Pointer& node, const PropertyName &name, const QVariant &data)
{
if (node->auxiliaryData(name) == data)
return;
if (data.isValid())
node->setAuxiliaryData(name, data);
else

View File

@@ -53,6 +53,12 @@ bool QmlItemNode::isItemOrWindow(const ModelNode &modelNode)
if (modelNode.metaInfo().isSubclassOf("QtQuick.Item"))
return true;
if (modelNode.metaInfo().isSubclassOf("FlowView.FlowDecision"))
return true;
if (modelNode.metaInfo().isSubclassOf("FlowView.FlowWildcard"))
return true;
if (modelNode.metaInfo().isGraphicalItem() && modelNode.isRootNode())
return true;
@@ -214,6 +220,12 @@ bool QmlItemNode::instanceIsAnchoredByChildren() const
bool QmlItemNode::instanceIsMovable() const
{
if (modelNode().metaInfo().isValid()
&& (modelNode().metaInfo().isSubclassOf("FlowView.FlowDecision")
|| modelNode().metaInfo().isSubclassOf("FlowView.FlowWildcard")
))
return true;
return nodeInstance().isMovable();
}
@@ -498,6 +510,13 @@ bool QmlItemNode::isFlowActionArea() const
return modelNode().metaInfo().isSubclassOf("FlowView.FlowActionArea");
}
ModelNode QmlItemNode::rootModelNode() const
{
if (view())
return view()->rootModelNode();
return {};
}
void QmlItemNode::setSize(const QSizeF &size)
{
if (!hasBindingProperty("width") && !(anchors().instanceHasAnchor(AnchorLineRight)
@@ -590,6 +609,24 @@ void QmlFlowActionAreaNode::destroyTarget()
}
}
ModelNode QmlFlowActionAreaNode::decisionNodeForTransition(const ModelNode &transition) const
{
ModelNode target = targetTransition();
if (target.isValid() && target.hasMetaInfo() && QmlVisualNode::isFlowTransition(target)) {
ModelNode finalTarget = target.bindingProperty("to").resolveToModelNode();
if (finalTarget.isValid() && finalTarget.hasMetaInfo() && QmlVisualNode::isFlowDecision(finalTarget)) {
if (finalTarget.hasBindingProperty("targets")
&& finalTarget.bindingProperty("targets").resolveToModelNodeList().contains(transition))
return finalTarget;
}
}
return {};
}
bool QmlFlowViewNode::isValid() const
{
return isValidQmlFlowViewNode(modelNode());
@@ -626,7 +663,7 @@ ModelNode QmlFlowViewNode::addTransition(const QmlFlowItemNode &from, const QmlF
return transition;
}
QList<ModelNode> QmlFlowViewNode::transitions() const
const QList<ModelNode> QmlFlowViewNode::transitions() const
{
if (modelNode().nodeListProperty("flowTransitions").isValid())
return modelNode().nodeListProperty("flowTransitions").toModelNodeList();
@@ -636,4 +673,12 @@ QList<ModelNode> QmlFlowViewNode::transitions() const
}
const QList<ModelNode> QmlFlowViewNode::wildcards() const
{
if (modelNode().nodeListProperty("flowWildcards").isValid())
return modelNode().nodeListProperty("flowWildcards").toModelNodeList();
return {};
}
} //QmlDesigner

View File

@@ -71,7 +71,9 @@ bool QmlVisualNode::isValidQmlVisualNode(const ModelNode &modelNode)
{
return isValidQmlObjectNode(modelNode)
&& modelNode.metaInfo().isValid()
&& (isItemOr3DNode(modelNode) || modelNode.metaInfo().isSubclassOf("FlowView.FlowTransition"));
&& (isItemOr3DNode(modelNode) || modelNode.metaInfo().isSubclassOf("FlowView.FlowTransition")
|| modelNode.metaInfo().isSubclassOf("FlowView.FlowDecision")
|| modelNode.metaInfo().isSubclassOf("FlowView.FlowWildcard"));
}
bool QmlVisualNode::isRootNode() const
@@ -322,11 +324,31 @@ bool QmlVisualNode::isFlowTransition(const ModelNode &node)
return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowTransition");
}
bool QmlVisualNode::isFlowDecision(const ModelNode &node)
{
return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowDecision");
}
bool QmlVisualNode::isFlowWildcard(const ModelNode &node)
{
return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowWildcard");
}
bool QmlVisualNode::isFlowTransition() const
{
return isFlowTransition(modelNode());
}
bool QmlVisualNode::isFlowDecision() const
{
return isFlowDecision(modelNode());
}
bool QmlVisualNode::isFlowWildcard() const
{
return isFlowWildcard(modelNode());
}
QList<ModelNode> toModelNodeList(const QList<QmlVisualNode> &qmlVisualNodeList)
{
QList<ModelNode> modelNodeList;

View File

@@ -780,7 +780,7 @@ void RewriterView::setupCanonicalHashes() const
for (const ModelNode &node : allModelNodes()) {
int offset = nodeOffset(node);
QTC_ASSERT(offset > 0, qDebug() << Q_FUNC_INFO << "no offset" << node; return);
if (offset > 0)
data.emplace_back(std::make_pair(node, offset));
}
@@ -1106,8 +1106,11 @@ void checkNode(const QmlJS::SimpleReaderNode::Ptr &node, RewriterView *view)
auto properties = node->properties();
for (auto i = properties.begin(); i != properties.end(); ++i) {
if (i.key() != "i")
modelNode.setAuxiliaryData(fixUpIllegalChars(i.key()).toUtf8(), i.value());
if (i.key() != "i") {
const PropertyName name = fixUpIllegalChars(i.key()).toUtf8();
if (!modelNode.hasAuxiliaryData(name))
modelNode.setAuxiliaryData(name, i.value());
}
}
checkChildNodes(node, view);
@@ -1121,7 +1124,8 @@ void RewriterView::restoreAuxiliaryData()
setupCanonicalHashes();
QTC_ASSERT(!m_canonicalIntModelNode.isEmpty(), return);
if (m_canonicalIntModelNode.isEmpty())
return;
const QString text = m_textModifier->text();

View File

@@ -62,6 +62,13 @@
\" <comment>Javascript module</comment>\",
\" <glob pattern=\'*.mjs\' weight=\'70\'/>\",
\" </mime-type>\",
\" <mime-type type=\'text/x-qtscript\'>\",
\" <alias type=\'application/x-qtscript\'/>\",
\" <sub-class-of type=\'application/javascript\'/>\",
\" <comment>Qt Script file</comment>\",
\" <glob pattern=\'*.qs\' weight=\'70\'/>\",
\" </mime-type>\",
\"</mime-info>\"
]
}

View File

@@ -549,6 +549,7 @@ public:
QTextBlock foldedBlockAt(const QPoint &pos, QRect *box = nullptr) const;
bool isMouseNavigationEvent(QMouseEvent *e) const;
void requestUpdateLink(QMouseEvent *e);
void updateLink();
void showLink(const Utils::Link &);
@@ -5553,7 +5554,7 @@ void TextEditorWidget::mousePressEvent(QMouseEvent *e)
if (refactorMarker.callback)
refactorMarker.callback(this);
} else {
d->m_linkPressed = true;
d->m_linkPressed = d->isMouseNavigationEvent(e);
}
}
} else if (e->button() == Qt::RightButton) {
@@ -5572,13 +5573,7 @@ void TextEditorWidget::mousePressEvent(QMouseEvent *e)
void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
{
if (mouseNavigationEnabled()
&& d->m_linkPressed
&& e->modifiers() & Qt::ControlModifier
&& !(e->modifiers() & Qt::ShiftModifier)
&& e->button() == Qt::LeftButton
) {
if (d->m_linkPressed && d->isMouseNavigationEvent(e) && e->button() == Qt::LeftButton) {
EditorManager::addCurrentPositionToNavigationHistory();
bool inNextSplit = ((e->modifiers() & Qt::AltModifier) && !alwaysOpenLinksInNextSplit())
|| (alwaysOpenLinksInNextSplit() && !(e->modifiers() & Qt::AltModifier));
@@ -6167,11 +6162,16 @@ bool TextEditorWidget::openLink(const Utils::Link &link, bool inNextSplit)
Id(), flags);
}
bool TextEditorWidgetPrivate::isMouseNavigationEvent(QMouseEvent *e) const
{
return q->mouseNavigationEnabled() && e->modifiers() & Qt::ControlModifier
&& !(e->modifiers() & Qt::ShiftModifier);
}
void TextEditorWidgetPrivate::requestUpdateLink(QMouseEvent *e)
{
if (!q->mouseNavigationEnabled())
if (!isMouseNavigationEvent(e))
return;
if (e->modifiers() & Qt::ControlModifier) {
// Link emulation behaviour for 'go to definition'
const QTextCursor cursor = q->cursorForPosition(e->pos());
@@ -6193,7 +6193,6 @@ void TextEditorWidgetPrivate::requestUpdateLink(QMouseEvent *e)
QTimer::singleShot(0, this, &TextEditorWidgetPrivate::updateLink);
return;
}
}
clearLink();
}

View File

@@ -2,7 +2,7 @@
\"Name\" : \"WebAssembly\",
\"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"Experimental\" : true,
\"DisabledByDefault\" : true,
\"Vendor\" : \"The Qt Company Ltd\",
\"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
\"License\" : [ \"Commercial Usage\",