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) if (newX < 0)
newX = 0 newX = 0
if (newX > mainWindow.width - bubble.width) if (newX > page1.mainWindow.width - bubble.width)
newX = mainWindow.width - bubble.width newX = page1.mainWindow.width - bubble.width
if (newY < 18) if (newY < 18)
newY = 18 newY = 18
if (newY > mainWindow.height - bubble.height) if (newY > page1.mainWindow.height - bubble.height)
newY = mainWindow.height - bubble.height newY = page1.mainWindow.height - bubble.height
bubble.x = newX bubble.x = newX
bubble.y = newY 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. need a fake Qt installation.
The bare metal device type accepts custom GDB commands that you specify in 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 device options. You can specify the commands to execute when connecting
the commands to execute when connecting to OpenOCD or ST-LINK Utility. 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 \list 1
\li Select \uicontrol Help > \uicontrol {About Plugins} > \li Select \uicontrol Help > \uicontrol {About Plugins} >
\uicontrol {Device Support} > \uicontrol {Bare Metal} to enable the \uicontrol {Device Support} > \uicontrol {Bare Metal}.
Bare Metal Device plugin.
\li Select \uicontrol {Restart Now} to restart \QC and load the plugin. \li Select \uicontrol {Restart Now} to restart \QC and load the plugin.
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices > \endlist
\uicontrol {Bare Metal} > \uicontrol Add > \uicontrol Default,
\uicontrol OpenOCD, or \uicontrol {ST-LINK Utility} to specify
connections to GDB servers or hardware debuggers:
\image creator-baremetal-device.png "Bare Metal options" \section1 Specifying Settings for Debug Server Providers
\list 1 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.
\li In the \uicontrol {Startup mode} field, select the mode to \section2 EBlink
start the GDB server or debugger in. The available modes
depend on the server or debugger.
\li In the \uicontrol Host field, select the host name and port \l{https://github.com/EmBitz/EBlink}{EBlink} is an ARM Cortex-M debug tool
number to connect to the GDB server or hardware debugger. that supports squirrel scripting, live variables, and hot-plugging.
\li In the \uicontrol {Init commands} field, enter the commands \image qtcreator-baremetal-eblink.png "Bare metal device options for EBlink"
to execute when initializing the connection.
\li In the \uicontrol {Reset commands} field, enter the commands To specify settings for \EBlink:
to execute when resetting the connection.
\li Select \uicontrol Apply to add the GDB server or debugger. \list 1
\endlist \include creator-baremetal-settings.qdocinc baremetal-common
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Devices > \li In the \uicontrol {Script file} field, enter the path
\uicontrol Add > \uicontrol {Bare Metal Device} > to a device script file.
\uicontrol {Start Wizard}:
\list 1 \li In the \uicontrol {Verbosity level} field, enter the level of
verbose logging.
\li In the \uicontrol {GDB server provider} field, select a \li Select the \uicontrol {Connect under reset} check box to use
GDB server or hardware debugger. the ST-Link interface. Deselect the check box for hot-plugging.
\li Select \uicontrol Apply to add the device. \li In the \uicontrol Type field, select the interface type.
\endlist \li In the \uicontrol Speed field, enter the interface speed between
120 and 8000 kiloherz (kHz).
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits > \li Select the \uicontrol {Disable cache} check box to disable the
\uicontrol Add to add a kit for building applications and running \EBlink flash cache.
them on bare metal devices:
\image creator-baremetal-kits.png "Bare Metal Device kits" \li Select the \uicontrol {Auto shutdown} check box to automatically
shut down the \EBlink server after disconnecting.
\list 1 \include creator-baremetal-settings.qdocinc baremetal-init-reset
\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 \endlist
\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
\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
\section1 Building for and Running on Bare Metal Devices
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}.
\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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** 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 You can add paths to other CMake executables and use them in different
build and run \l{glossary-buildandrun-kit}{kits}. 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 \QC automatically runs CMake to refresh project information when you edit
a \c CMakeLists.txt configuration file in a project. Project information is a \c CMakeLists.txt configuration file in a project. Project information is
also automatically refreshed when you build the project. also automatically refreshed when you build the project.
@@ -79,6 +83,9 @@
\li In the \uicontrol Path field, specify the path to the CMake \li In the \uicontrol Path field, specify the path to the CMake
executable. 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 \li Select the \uicontrol {Auto-create build directories} check box to
automatically create build directories for CMake projects. automatically create build directories for CMake projects.

View File

@@ -50,6 +50,9 @@
\list \list
\li In the \uicontrol Interpreter field, specify the path to the \li In the \uicontrol Interpreter field, specify the path to the
Python executable. 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 \li In the \uicontrol Script field, you can see the path to the
main file of the project that will be run. main file of the project that will be run.
\li In the \uicontrol {Command line arguments} field, specify \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> <string>qml2puppet</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>org.qt-project.qtcreator.qml2puppet</string> <string>org.qt-project.qtcreator.qml2puppet</string>
<key>LSUIElement</key>
<string>1</string>
</dict> </dict>
</plist> </plist>

View File

@@ -133,19 +133,7 @@ int main(int argc, char *argv[])
// subpixel antialiasing and instead use gray. // subpixel antialiasing and instead use gray.
qputenv("QSG_DISTANCEFIELD_ANTIALIASING", "gray"); qputenv("QSG_DISTANCEFIELD_ANTIALIASING", "gray");
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
if (!qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE")) { qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "true");
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 #endif
//If a style different from Desktop is set we have to use QGuiApplication //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.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show() actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
actionIndicator.visible: true actionIndicator.visible: true
labelColor: horizontalAlignmentComboBox.currentIndex === 0 ? colorLogic.__defaultTextColor : colorLogic.__changedTextColor labelColor: horizontalAlignmentComboBox.currentIndex === 0 ? colorLogic.__defaultTextColor : colorLogic.__changedTextColor
@@ -176,7 +176,7 @@ SectionLayout {
actionIndicator.icon.color: extFuncLogic.color actionIndicator.icon.color: extFuncLogic.color
actionIndicator.icon.text: extFuncLogic.glyph actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show() actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.forceVisible: extFuncLogic.menuVisible
actionIndicator.visible: true actionIndicator.visible: true
labelColor: verticalAlignmentComboBox.currentIndex === 0 ? colorLogic.__defaultTextColor : colorLogic.__changedTextColor labelColor: verticalAlignmentComboBox.currentIndex === 0 ? colorLogic.__defaultTextColor : colorLogic.__changedTextColor

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -778,7 +778,7 @@ void AndroidSettingsWidget::openNDKDownloadUrl()
void AndroidSettingsWidget::openOpenJDKDownloadUrl() 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) 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 newTestSetStarts("^\\[ RUN \\] (.*)$");
static const QRegularExpression testSetSuccess("^\\[ OK \\] (.*) \\((.*)\\)$"); static const QRegularExpression testSetSuccess("^\\[ OK \\] (.*) \\((.*)\\)$");
static const QRegularExpression testSetFail("^\\[ FAILED \\] (.*) \\((\\d+ ms)\\)$"); 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 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 " static const QRegularExpression iterations("^Repeating all tests "
"\\(iteration (\\d+)\\) \\. \\. \\.$"); "\\(iteration (\\d+)\\) \\. \\. \\.$");
static const QRegularExpression logging("^\\[( FATAL | ERROR |WARNING| INFO )\\] " static const QRegularExpression logging("^\\[( FATAL | ERROR |WARNING| INFO )\\] "
@@ -126,6 +125,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
} }
reportResult(testResult); reportResult(testResult);
} else if (ExactMatch match = newTestSetStarts.match(line)) { } else if (ExactMatch match = newTestSetStarts.match(line)) {
m_testSetStarted = true;
setCurrentTestCase(match.captured(1)); setCurrentTestCase(match.captured(1));
TestResultPtr testResult = TestResultPtr(new GTestResult(QString(), m_projectFile, TestResultPtr testResult = TestResultPtr(new GTestResult(QString(), m_projectFile,
QString())); QString()));
@@ -134,6 +134,7 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
reportResult(testResult); reportResult(testResult);
m_description.clear(); m_description.clear();
} else if (ExactMatch match = testSetSuccess.match(line)) { } else if (ExactMatch match = testSetSuccess.match(line)) {
m_testSetStarted = false;
TestResultPtr testResult = createDefaultResult(); TestResultPtr testResult = createDefaultResult();
testResult->setResult(ResultType::Pass); testResult->setResult(ResultType::Pass);
testResult->setDescription(m_description); testResult->setDescription(m_description);
@@ -145,40 +146,29 @@ void GTestOutputReader::processOutputLine(const QByteArray &outputLine)
reportResult(testResult); reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
} else if (ExactMatch match = testSetFail.match(line)) { } else if (ExactMatch match = testSetFail.match(line)) {
m_testSetStarted = false;
TestResultPtr testResult = createDefaultResult(); TestResultPtr testResult = createDefaultResult();
testResult->setResult(ResultType::Fail); testResult->setResult(ResultType::Fail);
m_description.chop(1); m_description.chop(1);
QStringList resultDescription; handleDescriptionAndReportResult(testResult);
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();
testResult = createDefaultResult(); testResult = createDefaultResult();
testResult->setResult(ResultType::MessageInternal); testResult->setResult(ResultType::MessageInternal);
testResult->setDescription(tr("Execution took %1.").arg(match.captured(2))); testResult->setDescription(tr("Execution took %1.").arg(match.captured(2)));
reportResult(testResult); reportResult(testResult);
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1); 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)) { } else if (ExactMatch match = logging.match(line)) {
const QString severity = match.captured(1).trimmed(); const QString severity = match.captured(1).trimmed();
ResultType type = ResultType::Invalid; ResultType type = ResultType::Invalid;
@@ -232,5 +222,38 @@ void GTestOutputReader::setCurrentTestSuite(const QString &testSuite)
m_currentTestSuite = 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 Internal
} // namespace Autotest } // namespace Autotest

View File

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

View File

@@ -147,7 +147,10 @@ bool BackendReceiver::isExpectingCompletionsMessage() const
void BackendReceiver::reset() void BackendReceiver::reset()
{ {
// Clean up waiting assist processors // 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(); m_assistProcessorsTable.clear();
// Clean up futures for references; TODO: Remove duplication // Clean up futures for references; TODO: Remove duplication

View File

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

View File

@@ -50,20 +50,14 @@
*/ */
/*! /*!
\fn INavigationWidgetFactory::INavigationWidgetFactory() \fn QString Core::INavigationWidgetFactory::displayName() const
Constructs a navigation widget factory.
*/
/*!
\fn QString INavigationWidgetFactory::displayName() const
Returns the display name of the navigation widget, which is shown in the dropdown menu above the Returns the display name of the navigation widget, which is shown in the dropdown menu above the
navigation widget. navigation widget.
*/ */
/*! /*!
\fn int INavigationWidgetFactory::priority() const \fn int Core::INavigationWidgetFactory::priority() const
Determines the position of the navigation widget in the dropdown menu. 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. 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 Returns a \l{Core::NavigationView} containing the widget and the buttons. The ownership is given
to the caller. to the caller.
@@ -88,7 +82,7 @@ using namespace Core;
static QList<INavigationWidgetFactory *> g_navigationWidgetFactories; static QList<INavigationWidgetFactory *> g_navigationWidgetFactories;
/*! /*!
Creates a \l{Core::NavigationViewFactory}. Constructs a navigation widget factory.
*/ */
INavigationWidgetFactory::INavigationWidgetFactory() 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() \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() \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() \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() \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). (the \a position identifies a specific navigation widget).
\sa INavigationWidgetFactory::restoreSettings() \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). factory (the \a position identifies a specific navigation widget).
\sa INavigationWidgetFactory::saveSettings() \sa INavigationWidgetFactory::saveSettings()

View File

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

View File

@@ -37,6 +37,7 @@
/*! /*!
\class Core::IVersionControl::TopicCache \class Core::IVersionControl::TopicCache
\inmodule QtCreator
\brief The TopicCache class stores a cache which maps a directory to a topic. \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 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 Autodetects file format and reads the text file specified by \a fileName
into a list of strings specified by \a plainTextList. 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. error details.
Returns whether the operation was successful. 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 Autodetects file format and reads the text file specified by \a fileName
into \a plainText. 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. error details.
Returns whether the operation was successful. Returns whether the operation was successful.

View File

@@ -339,6 +339,7 @@ using namespace Internal;
/*! /*!
* \class Core::VariableChooser * \class Core::VariableChooser
* \inmodule QtCreator
* \brief The VariableChooser class is used to add a tool window for selecting \QC variables * \brief The VariableChooser class is used to add a tool window for selecting \QC variables
* to line edits, text edits or plain text edits. * 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" * \image variablechooser.png "External Tools Preferences with Variable Chooser"
* *
* The variable chooser monitors focus changes of all children of its parent widget. * 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, * 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, * If the control supports variables,
* a tool button which opens the variable chooser is shown in it while it has focus. * a tool button which opens the variable chooser is shown in it while it has focus.
* *
* Supported text controls are QLineEdit, QTextEdit and QPlainTextEdit. * 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. * Property name that is checked for deciding if a widget supports \QC variables.
* Can be manually set with * Can be manually set with
* \c{textcontrol->setProperty(VariableChooser::kVariableSupportProperty, true)} * \c{textcontrol->setProperty(VariableChooser::kVariableSupportProperty, true)}
* \sa addVariableSupport()
*/ */
const char kVariableSupportProperty[] = "QtCreator.VariableSupport"; const char kVariableSupportProperty[] = "QtCreator.VariableSupport";
const char kVariableNameProperty[] = "QtCreator.VariableName"; 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. * Creates a variable chooser that tracks all children of \a parent for variable support.
* Ownership is also transferred to \a parent. * Ownership is also transferred to \a parent.
* \sa addVariableSupport()
*/ */
VariableChooser::VariableChooser(QWidget *parent) : VariableChooser::VariableChooser(QWidget *parent) :
QWidget(parent), QWidget(parent),
@@ -406,6 +405,9 @@ VariableChooser::~VariableChooser()
delete d; delete d;
} }
/*!
Adds the macro expander provider \a provider.
*/
void VariableChooser::addMacroExpanderProvider(const MacroExpanderProvider &provider) void VariableChooser::addMacroExpanderProvider(const MacroExpanderProvider &provider)
{ {
auto item = new VariableGroupItem; auto item = new VariableGroupItem;
@@ -415,8 +417,11 @@ void VariableChooser::addMacroExpanderProvider(const MacroExpanderProvider &prov
} }
/*! /*!
* Marks the control as supporting variables. * Marks the control \a textcontrol as supporting variables.
* \sa kVariableSupportProperty *
* 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) 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>())); .value_or(QList<QString>()));
} }
if (auto functionHintAssistProvider = qobject_cast<FunctionHintAssistProvider *>( if (auto functionHintAssistProvider = qobject_cast<FunctionHintAssistProvider *>(
m_clientProviders.completionAssistProvider)) { m_clientProviders.functionHintProvider)) {
functionHintAssistProvider->setTriggerCharacters( functionHintAssistProvider->setTriggerCharacters(
m_serverCapabilities.signatureHelpProvider() m_serverCapabilities.signatureHelpProvider()
.value_or(ServerCapabilities::SignatureHelpOptions()) .value_or(ServerCapabilities::SignatureHelpOptions())

View File

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

View File

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

View File

@@ -37,6 +37,7 @@ const char KIT_MCUTARGET_MODEL_KEY[] = "McuSupport.McuTargetModel";
const char SETTINGS_GROUP[] = "McuSupport"; const char SETTINGS_GROUP[] = "McuSupport";
const char SETTINGS_KEY_PACKAGE_PREFIX[] = "Package_"; 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 McuSupport
} // namespace Constants } // namespace Constants

View File

@@ -28,6 +28,7 @@
#include "mcusupportsdk.h" #include "mcusupportsdk.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/helpmanager.h>
#include <cmakeprojectmanager/cmakekitinformation.h> #include <cmakeprojectmanager/cmakekitinformation.h>
#include <debugger/debuggeritem.h> #include <debugger/debuggeritem.h>
#include <debugger/debuggeritemmanager.h> #include <debugger/debuggeritemmanager.h>
@@ -56,6 +57,16 @@
namespace McuSupport { namespace McuSupport {
namespace Internal { 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, McuPackage::McuPackage(const QString &label, const QString &defaultPath,
const QString &detectionPath, const QString &settingsKey) const QString &detectionPath, const QString &settingsKey)
: m_label(label) : m_label(label)
@@ -63,11 +74,7 @@ McuPackage::McuPackage(const QString &label, const QString &defaultPath,
, m_detectionPath(detectionPath) , m_detectionPath(detectionPath)
, m_settingsKey(settingsKey) , m_settingsKey(settingsKey)
{ {
QSettings *s = Core::ICore::settings(); m_path = packagePathFromSettings(settingsKey, defaultPath);
s->beginGroup(Constants::SETTINGS_GROUP);
m_path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey,
m_defaultPath).toString();
s->endGroup();
} }
QString McuPackage::path() const QString McuPackage::path() const
@@ -349,6 +356,22 @@ void McuSupportOptions::populatePackagesAndTargets()
setQulDir(Utils::FilePath::fromUserInput(qtForMCUsSdkPackage->path())); 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() void McuSupportOptions::deletePackagesAndTargets()
{ {
qDeleteAll(packages); qDeleteAll(packages);
@@ -370,6 +393,12 @@ void McuSupportOptions::setQulDir(const Utils::FilePath &dir)
emit changed(); 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) static bool mcuTargetIsDesktop(const McuTarget* mcuTarget)
{ {
return mcuTarget->qulPlatform() == "Qt"; return mcuTarget->qulPlatform() == "Qt";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -66,10 +66,27 @@ void ZoomAction::resetZoomLevel()
void ZoomAction::setZoomLevel(float zoomLevel) 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); 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) QWidget *ZoomAction::createWidget(QWidget *parent)
{ {
auto comboBox = new QComboBox(parent); auto comboBox = new QComboBox(parent);
@@ -79,28 +96,10 @@ QWidget *ZoomAction::createWidget(QWidget *parent)
*/ */
if (m_comboBoxModel.isNull()) { if (m_comboBoxModel.isNull()) {
m_comboBoxModel = comboBox->model(); m_comboBoxModel = comboBox->model();
comboBox->addItem(QLatin1String("1 %"), 0.01); for (float z : s_zoomFactors) {
comboBox->addItem(QLatin1String("2 %"), 0.02); const QString name = QString::number(z * 100, 'g', 4) + " %";
comboBox->addItem(QLatin1String("5 %"), 0.05); comboBox->addItem(name, z);
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);
} else { } else {
comboBox->setModel(m_comboBoxModel.data()); comboBox->setModel(m_comboBoxModel.data());
} }
@@ -126,6 +125,12 @@ QWidget *ZoomAction::createWidget(QWidget *parent)
connect(this, &ZoomAction::indexChanged, comboBox, &QComboBox::setCurrentIndex); 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->setProperty("hideborder", true);
comboBox->setMaximumWidth(qMax(comboBox->view()->sizeHintForColumn(0) / 2, 16)); comboBox->setMaximumWidth(qMax(comboBox->view()->sizeHintForColumn(0) / 2, 16));
return comboBox; return comboBox;

View File

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

View File

@@ -103,6 +103,15 @@ bool AnimationCurve::isFromData() const
return m_fromData; return m_fromData;
} }
bool AnimationCurve::hasUnified() const
{
for (auto &&frame : m_frames) {
if (frame.isUnified())
return true;
}
return false;
}
double AnimationCurve::minimumTime() const double AnimationCurve::minimumTime() const
{ {
if (!m_frames.empty()) if (!m_frames.empty())
@@ -144,6 +153,18 @@ std::string AnimationCurve::string() const
return sstream.str(); 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 AnimationCurve::segment(double time) const
{ {
CurveSegment seg; CurveSegment seg;

View File

@@ -50,6 +50,8 @@ public:
bool isFromData() const; bool isFromData() const;
bool hasUnified() const;
double minimumTime() const; double minimumTime() const;
double maximumTime() const; double maximumTime() const;
@@ -60,6 +62,8 @@ public:
std::string string() const; std::string string() const;
QString unifyString() const;
CurveSegment segment(double time) const; CurveSegment segment(double time) const;
std::vector<CurveSegment> segments() 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 *tangentStepAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsStepIcon.png"), "Step");
QAction *tangentSplineAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsSplineIcon.png"), "Spline"); QAction *tangentSplineAction = bar->addAction(QIcon(":/curveeditor/images/tangetToolsSplineIcon.png"), "Spline");
QAction *tangentDefaultAction = bar->addAction("Set Default"); QAction *tangentDefaultAction = bar->addAction("Set Default");
QAction *tangentUnifyAction = bar->addAction("Unify");
auto setLinearInterpolation = [this]() { auto setLinearInterpolation = [this]() {
m_view->setInterpolation(Keyframe::Interpolation::Linear); m_view->setInterpolation(Keyframe::Interpolation::Linear);
@@ -97,9 +98,12 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
m_view->setInterpolation(Keyframe::Interpolation::Bezier); m_view->setInterpolation(Keyframe::Interpolation::Bezier);
}; };
auto toggleUnifyKeyframe = [this]() { m_view->toggleUnified(); };
connect(tangentLinearAction, &QAction::triggered, setLinearInterpolation); connect(tangentLinearAction, &QAction::triggered, setLinearInterpolation);
connect(tangentStepAction, &QAction::triggered, setStepInterpolation); connect(tangentStepAction, &QAction::triggered, setStepInterpolation);
connect(tangentSplineAction, &QAction::triggered, setSplineInterpolation); connect(tangentSplineAction, &QAction::triggered, setSplineInterpolation);
connect(tangentUnifyAction, &QAction::triggered, toggleUnifyKeyframe);
Q_UNUSED(tangentLinearAction); Q_UNUSED(tangentLinearAction);
Q_UNUSED(tangentSplineAction); Q_UNUSED(tangentSplineAction);

View File

@@ -62,6 +62,9 @@ struct KeyframeItemStyleOption
double size = 10.0; double size = 10.0;
QColor color = QColor(200, 200, 0); QColor color = QColor(200, 200, 0);
QColor selectionColor = QColor(200, 200, 200); 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 struct CurveItemStyleOption

View File

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

View File

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

View File

@@ -27,6 +27,7 @@
#include "curveeditorstyle.h" #include "curveeditorstyle.h"
#include "curvesegment.h" #include "curvesegment.h"
#include "handleitem.h"
#include "keyframe.h" #include "keyframe.h"
#include "selectableitem.h" #include "selectableitem.h"
#include "treeitem.h" #include "treeitem.h"
@@ -47,6 +48,10 @@ class CurveItem : public CurveEditorItem
signals: signals:
void curveChanged(unsigned int id, const AnimationCurve &curve); 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: public:
CurveItem(QGraphicsItem *parent = nullptr); CurveItem(QGraphicsItem *parent = nullptr);
@@ -100,6 +105,8 @@ public:
void setInterpolation(Keyframe::Interpolation interpolation); void setInterpolation(Keyframe::Interpolation interpolation);
void toggleUnified();
void connect(GraphicsScene *scene); void connect(GraphicsScene *scene);
void insertKeyframeByTime(double time); void insertKeyframeByTime(double time);

View File

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

View File

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

View File

@@ -275,6 +275,18 @@ void GraphicsView::setInterpolation(Keyframe::Interpolation interpol)
viewport()->update(); 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) void GraphicsView::resizeEvent(QResizeEvent *event)
{ {
QGraphicsView::resizeEvent(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) void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
{ {
m_scene.doNotMoveItems(true);
QPointF pivotRaster(globalToRaster(pivot)); QPointF pivotRaster(globalToRaster(pivot));
m_zoomX = clamp(x, 0.0, 1.0); 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); QPointF deltaTransformed = pivotRaster - globalToRaster(pivot);
scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y())); scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
} }
m_scene.doNotMoveItems(false);
} }
void GraphicsView::insertKeyframe(double time, bool allVisibleCurves) void GraphicsView::insertKeyframe(double time, bool allVisibleCurves)

View File

@@ -112,6 +112,8 @@ public:
void setInterpolation(Keyframe::Interpolation interpol); void setInterpolation(Keyframe::Interpolation interpol);
void toggleUnified();
protected: protected:
void resizeEvent(QResizeEvent *event) override; 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) QVariant HandleItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{ {
if (change == ItemPositionChange) { if (change == ItemPositionChange) {
if (KeyframeItem *parent = qgraphicsitem_cast<KeyframeItem *>(parentItem())) { if (qgraphicsitem_cast<KeyframeItem *>(parentItem())) {
QPointF pos = value.toPointF(); QPointF pos = value.toPointF();
if (m_slot == HandleItem::Slot::Left) { if (m_slot == HandleItem::Slot::Left) {
if (pos.x() > 0.0) if (pos.x() > 0.0)

View File

@@ -64,14 +64,22 @@ void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
Q_UNUSED(option) Q_UNUSED(option)
Q_UNUSED(widget) 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(); QPen pen = painter->pen();
pen.setColor(Qt::black); pen.setWidthF(1.);
pen.setColor(borderColor);
painter->save(); painter->save();
painter->setPen(pen); painter->setPen(pen);
painter->setBrush(locked() ? Qt::black : (selected() ? Qt::red : m_style.color)); painter->setBrush(mainColor);
painter->drawEllipse(boundingRect()); painter->drawEllipse(boundingRect());
painter->restore(); painter->restore();
} }
@@ -93,6 +101,11 @@ Keyframe KeyframeItem::keyframe() const
return m_frame; return m_frame;
} }
bool KeyframeItem::isUnified() const
{
return m_frame.isUnified();
}
bool KeyframeItem::hasLeftHandle() const bool KeyframeItem::hasLeftHandle() const
{ {
return m_frame.hasLeftHandle(); return m_frame.hasLeftHandle();
@@ -108,11 +121,6 @@ QTransform KeyframeItem::transform() const
return m_transform; return m_transform;
} }
bool KeyframeItem::contains(HandleItem *handle, const QPointF &point) const
{
return false;
}
void KeyframeItem::setHandleVisibility(bool visible) void KeyframeItem::setHandleVisibility(bool visible)
{ {
m_visibleOverride = visible; m_visibleOverride = visible;
@@ -195,6 +203,31 @@ void KeyframeItem::setKeyframe(const Keyframe &keyframe)
setPos(m_transform.map(m_frame.position())); 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) void KeyframeItem::setInterpolation(Keyframe::Interpolation interpolation)
{ {
m_frame.setInterpolation(interpolation); m_frame.setInterpolation(interpolation);

View File

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

View File

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

View File

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

View File

@@ -311,6 +311,16 @@ AnimationCurve PropertyTreeItem::curve() const
return m_curve; 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) void PropertyTreeItem::setCurve(const AnimationCurve &curve)
{ {
m_curve = curve; m_curve = curve;

View File

@@ -155,6 +155,10 @@ public:
AnimationCurve curve() const; AnimationCurve curve() const;
bool hasUnified() const;
QString unifyString() const;
void setCurve(const AnimationCurve &curve); void setCurve(const AnimationCurve &curve);
void setComponent(const Component &comp); 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) { QIcon iconForColor(const QColor &color) {
const int size = 16; const int size = 16;
QImage image(size, size, QImage::Format_ARGB32); QImage image(size, size, QImage::Format_ARGB32);
@@ -69,6 +76,7 @@ QWidget *BackgroundAction::createWidget(QWidget *parent)
comboBox->setProperty("hideborder", true); comboBox->setProperty("hideborder", true);
comboBox->setToolTip(tr("Set the color of the canvas.")); comboBox->setToolTip(tr("Set the color of the canvas."));
m_comboBox = comboBox;
return comboBox; return comboBox;
} }
@@ -83,6 +91,7 @@ QList<QColor> BackgroundAction::colors()
static QColor alphaZero(Qt::transparent); static QColor alphaZero(Qt::transparent);
static QList<QColor> colorList = {alphaZero, static QList<QColor> colorList = {alphaZero,
QColor(Qt::black), QColor(Qt::black),
QColor("#4c4e50"),
QColor(Qt::darkGray), QColor(Qt::darkGray),
QColor(Qt::lightGray), QColor(Qt::lightGray),
QColor(Qt::white)}; QColor(Qt::white)};

View File

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

View File

@@ -754,7 +754,12 @@ static void paintConnection(QPainter *painter,
const bool boolExitRight = from.right() < to.center().x(); const bool boolExitRight = from.right() < to.center().x();
const bool boolExitBottom = from.bottom() < to.center().y(); 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; const qreal middleFactor = breakOffset / 100.0;
@@ -764,14 +769,20 @@ static void paintConnection(QPainter *painter,
if (horizontalFirst) { if (horizontalFirst) {
if (to.center().x() > from.left() && to.center().x() < from.right()) { if (to.center().x() > from.left() && to.center().x() < from.right()) {
horizontalFirst = false; horizontalFirst = false;
extraLine = true; extraLine = true;
} } else if (verticalOverlap(from, to)) {
horizontalFirst = true;
extraLine = true;
}
} else { } else {
if (to.center().y() > from.top() && to.center().y() < from.bottom()) { if (to.center().y() > from.top() && to.center().y() < from.bottom()) {
horizontalFirst = true; horizontalFirst = true;
extraLine = true; extraLine = true;
} else if (horizontalOverlap(from, to)) {
horizontalFirst = false;
extraLine = true;
} }
} }
@@ -913,35 +924,84 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
return; return;
if (!(qmlItemNode().modelNode().hasBindingProperty("from") if (!(qmlItemNode().modelNode().hasBindingProperty("from")
&& qmlItemNode().modelNode().hasBindingProperty("from"))) && qmlItemNode().modelNode().hasBindingProperty("to")))
return; return;
painter->save(); 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(); const QmlFlowItemNode to = qmlItemNode().modelNode().bindingProperty("to").resolveToModelNode();
QmlFlowActionAreaNode areaNode = ModelNode(); 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()) { for (const QmlFlowActionAreaNode &area : from.flowActionAreas()) {
if (area.targetTransition() == qmlItemNode().modelNode()) ModelNode target = area.targetTransition();
if (target == qmlItemNode().modelNode()) {
areaNode = area; 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(); 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()); 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 = QmlItemNode(areaNode).instanceBoundingRect();
fromRect.translate(QmlItemNode(from).flowPosition()); fromRect.translate(QmlItemNode(from).flowPosition());
fromRect.translate(areaNode.instancePosition()); fromRect.translate(areaNode.instancePosition());
} }
QRectF toRect = QmlItemNode(to).instanceBoundingRect(); QRectF toRect = QmlItemNode(to).instanceBoundingRect();
if (QmlItemNode(to).isFlowDecision())
toRect = QRectF(0,0,200,200);
toRect.translate(QmlItemNode(to).flowPosition()); 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()); toRect.translate(-pos());
fromRect.translate(-pos()); fromRect.translate(-pos());
@@ -961,6 +1021,9 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
QColor color = "#e71919"; QColor color = "#e71919";
if (isStartLine)
color = "blue";
bool dash = false; bool dash = false;
if (qmlItemNode().modelNode().hasAuxiliaryData("color")) 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); 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(); painter->restore();
} }
@@ -1011,4 +1091,83 @@ QTransform FormEditorItem::viewportTransform() const
return scene()->views().first()->viewportTransform(); 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 } //QmlDesigner

View File

@@ -1,3 +1,4 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 The Qt Company Ltd.
@@ -196,6 +197,33 @@ private:
mutable bool m_hitTest = false; 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 inline int FormEditorItem::type() const
{ {

View File

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

View File

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

View File

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

View File

@@ -195,10 +195,14 @@ void FormEditorWidget::changeRootItemHeight(const QString &heighText)
void FormEditorWidget::changeBackgound(const QColor &color) void FormEditorWidget::changeBackgound(const QColor &color)
{ {
if (color.alpha() == 0) if (color.alpha() == 0) {
m_graphicsView->activateCheckboardBackground(); m_graphicsView->activateCheckboardBackground();
else if (m_formEditorView->rootModelNode().hasAuxiliaryData("formeditorColor"))
m_formEditorView->rootModelNode().setAuxiliaryData("formeditorColor", {});
} else {
m_graphicsView->activateColoredBackground(color); m_graphicsView->activateColoredBackground(color);
m_formEditorView->rootModelNode().setAuxiliaryData("formeditorColor", color);
}
} }
void FormEditorWidget::registerActionAsCommand(QAction *action, Core::Id id, const QKeySequence &keysequence) 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()); m_rootHeightAction->setLineEditText(m_formEditorView->rootModelNode().auxiliaryData("height").toString());
else else
m_rootHeightAction->clearLineEditText(); 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 { } else {
m_rootWidthAction->clearLineEditText(); m_rootWidthAction->clearLineEditText();
m_rootHeightAction->clearLineEditText(); m_rootHeightAction->clearLineEditText();
@@ -314,6 +329,13 @@ void FormEditorWidget::setZoomLevel(double zoomLevel)
m_graphicsView->resetTransform(); m_graphicsView->resetTransform();
m_graphicsView->scale(zoomLevel, zoomLevel); 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) 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(); 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(); bool forceVisiblity = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary();
if (m_flowMode) { if (m_flowMode) {

View File

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

View File

@@ -161,6 +161,8 @@ QVariant properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode,
return 50; return 50;
else if (propertyName == "customId") else if (propertyName == "customId")
return QString(); return QString();
else if (propertyName == "joinConnection")
return false;
return {}; return {};
} }
@@ -228,7 +230,7 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml
if (itemNode.isFlowTransition()) { if (itemNode.isFlowTransition()) {
propertyNames.append({"color", "width", "inOffset", "outOffset", "dash", "breakPoint"}); propertyNames.append({"color", "width", "inOffset", "outOffset", "dash", "breakPoint"});
} else if (itemNode.isFlowItem()) { } else if (itemNode.isFlowItem()) {
propertyNames.append({"color", "width", "inOffset", "outOffset"}); propertyNames.append({"color", "width", "inOffset", "outOffset", "joinConnection"});
} else if (itemNode.isFlowActionArea()) { } else if (itemNode.isFlowActionArea()) {
propertyNames.append({"color", "width", "fillColor", "outOffset", "dash"}); 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()); std::vector<DesignTools::Keyframe> keyframes = createKeyframes(group.keyframePositions());
keyframes = resolveSmallCurves(keyframes); 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); return DesignTools::AnimationCurve(keyframes);
} }

View File

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

View File

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

View File

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

View File

@@ -126,6 +126,7 @@ public:
bool isFlowView() const; bool isFlowView() const;
bool isFlowItem() const; bool isFlowItem() const;
bool isFlowActionArea() const; bool isFlowActionArea() const;
ModelNode rootModelNode() const;
}; };
class QmlFlowItemNode; class QmlFlowItemNode;
@@ -141,6 +142,7 @@ public:
void assignTargetFlowItem(const QmlFlowItemNode &flowItem); void assignTargetFlowItem(const QmlFlowItemNode &flowItem);
QmlFlowItemNode flowItemParent() const; QmlFlowItemNode flowItemParent() const;
void destroyTarget(); void destroyTarget();
ModelNode decisionNodeForTransition(const ModelNode &transition) const;
}; };
class QMLDESIGNERCORE_EXPORT QmlFlowItemNode : public QmlItemNode class QMLDESIGNERCORE_EXPORT QmlFlowItemNode : public QmlItemNode
@@ -161,7 +163,8 @@ public:
static bool isValidQmlFlowViewNode(const ModelNode &modelNode); static bool isValidQmlFlowViewNode(const ModelNode &modelNode);
QList<QmlFlowItemNode> flowItems() const; QList<QmlFlowItemNode> flowItems() const;
ModelNode addTransition(const QmlFlowItemNode &from, const QmlFlowItemNode &to); 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 NodeListProperty findSceneNodeProperty(AbstractView *view, qint32 sceneRootId);
static bool isFlowTransition(const ModelNode &node); static bool isFlowTransition(const ModelNode &node);
static bool isFlowDecision(const ModelNode &node);
static bool isFlowWildcard(const ModelNode &node);
bool isFlowTransition() const; bool isFlowTransition() const;
bool isFlowDecision() const;
bool isFlowWildcard() const;
private: private:
void setDoubleProperty(const PropertyName &name, double value); 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) void ModelPrivate::setAuxiliaryData(const InternalNode::Pointer& node, const PropertyName &name, const QVariant &data)
{ {
if (node->auxiliaryData(name) == data)
return;
if (data.isValid()) if (data.isValid())
node->setAuxiliaryData(name, data); node->setAuxiliaryData(name, data);
else else

View File

@@ -53,6 +53,12 @@ bool QmlItemNode::isItemOrWindow(const ModelNode &modelNode)
if (modelNode.metaInfo().isSubclassOf("QtQuick.Item")) if (modelNode.metaInfo().isSubclassOf("QtQuick.Item"))
return true; return true;
if (modelNode.metaInfo().isSubclassOf("FlowView.FlowDecision"))
return true;
if (modelNode.metaInfo().isSubclassOf("FlowView.FlowWildcard"))
return true;
if (modelNode.metaInfo().isGraphicalItem() && modelNode.isRootNode()) if (modelNode.metaInfo().isGraphicalItem() && modelNode.isRootNode())
return true; return true;
@@ -214,6 +220,12 @@ bool QmlItemNode::instanceIsAnchoredByChildren() const
bool QmlItemNode::instanceIsMovable() const bool QmlItemNode::instanceIsMovable() const
{ {
if (modelNode().metaInfo().isValid()
&& (modelNode().metaInfo().isSubclassOf("FlowView.FlowDecision")
|| modelNode().metaInfo().isSubclassOf("FlowView.FlowWildcard")
))
return true;
return nodeInstance().isMovable(); return nodeInstance().isMovable();
} }
@@ -498,6 +510,13 @@ bool QmlItemNode::isFlowActionArea() const
return modelNode().metaInfo().isSubclassOf("FlowView.FlowActionArea"); return modelNode().metaInfo().isSubclassOf("FlowView.FlowActionArea");
} }
ModelNode QmlItemNode::rootModelNode() const
{
if (view())
return view()->rootModelNode();
return {};
}
void QmlItemNode::setSize(const QSizeF &size) void QmlItemNode::setSize(const QSizeF &size)
{ {
if (!hasBindingProperty("width") && !(anchors().instanceHasAnchor(AnchorLineRight) 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 bool QmlFlowViewNode::isValid() const
{ {
return isValidQmlFlowViewNode(modelNode()); return isValidQmlFlowViewNode(modelNode());
@@ -626,7 +663,7 @@ ModelNode QmlFlowViewNode::addTransition(const QmlFlowItemNode &from, const QmlF
return transition; return transition;
} }
QList<ModelNode> QmlFlowViewNode::transitions() const const QList<ModelNode> QmlFlowViewNode::transitions() const
{ {
if (modelNode().nodeListProperty("flowTransitions").isValid()) if (modelNode().nodeListProperty("flowTransitions").isValid())
return modelNode().nodeListProperty("flowTransitions").toModelNodeList(); 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 } //QmlDesigner

View File

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

View File

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

View File

@@ -62,6 +62,13 @@
\" <comment>Javascript module</comment>\", \" <comment>Javascript module</comment>\",
\" <glob pattern=\'*.mjs\' weight=\'70\'/>\", \" <glob pattern=\'*.mjs\' weight=\'70\'/>\",
\" </mime-type>\", \" </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>\" \"</mime-info>\"
] ]
} }

View File

@@ -549,6 +549,7 @@ public:
QTextBlock foldedBlockAt(const QPoint &pos, QRect *box = nullptr) const; QTextBlock foldedBlockAt(const QPoint &pos, QRect *box = nullptr) const;
bool isMouseNavigationEvent(QMouseEvent *e) const;
void requestUpdateLink(QMouseEvent *e); void requestUpdateLink(QMouseEvent *e);
void updateLink(); void updateLink();
void showLink(const Utils::Link &); void showLink(const Utils::Link &);
@@ -5553,7 +5554,7 @@ void TextEditorWidget::mousePressEvent(QMouseEvent *e)
if (refactorMarker.callback) if (refactorMarker.callback)
refactorMarker.callback(this); refactorMarker.callback(this);
} else { } else {
d->m_linkPressed = true; d->m_linkPressed = d->isMouseNavigationEvent(e);
} }
} }
} else if (e->button() == Qt::RightButton) { } else if (e->button() == Qt::RightButton) {
@@ -5572,13 +5573,7 @@ void TextEditorWidget::mousePressEvent(QMouseEvent *e)
void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e) void TextEditorWidget::mouseReleaseEvent(QMouseEvent *e)
{ {
if (mouseNavigationEnabled() if (d->m_linkPressed && d->isMouseNavigationEvent(e) && e->button() == Qt::LeftButton) {
&& d->m_linkPressed
&& e->modifiers() & Qt::ControlModifier
&& !(e->modifiers() & Qt::ShiftModifier)
&& e->button() == Qt::LeftButton
) {
EditorManager::addCurrentPositionToNavigationHistory(); EditorManager::addCurrentPositionToNavigationHistory();
bool inNextSplit = ((e->modifiers() & Qt::AltModifier) && !alwaysOpenLinksInNextSplit()) bool inNextSplit = ((e->modifiers() & Qt::AltModifier) && !alwaysOpenLinksInNextSplit())
|| (alwaysOpenLinksInNextSplit() && !(e->modifiers() & Qt::AltModifier)); || (alwaysOpenLinksInNextSplit() && !(e->modifiers() & Qt::AltModifier));
@@ -6167,32 +6162,36 @@ bool TextEditorWidget::openLink(const Utils::Link &link, bool inNextSplit)
Id(), flags); Id(), flags);
} }
bool TextEditorWidgetPrivate::isMouseNavigationEvent(QMouseEvent *e) const
{
return q->mouseNavigationEnabled() && e->modifiers() & Qt::ControlModifier
&& !(e->modifiers() & Qt::ShiftModifier);
}
void TextEditorWidgetPrivate::requestUpdateLink(QMouseEvent *e) void TextEditorWidgetPrivate::requestUpdateLink(QMouseEvent *e)
{ {
if (!q->mouseNavigationEnabled()) if (!isMouseNavigationEvent(e))
return; return;
if (e->modifiers() & Qt::ControlModifier) { // Link emulation behaviour for 'go to definition'
// Link emulation behaviour for 'go to definition' const QTextCursor cursor = q->cursorForPosition(e->pos());
const QTextCursor cursor = q->cursorForPosition(e->pos());
// Avoid updating the link we already found // Avoid updating the link we already found
if (cursor.position() >= m_currentLink.linkTextStart if (cursor.position() >= m_currentLink.linkTextStart
&& cursor.position() <= m_currentLink.linkTextEnd) && cursor.position() <= m_currentLink.linkTextEnd)
return; return;
// Check that the mouse was actually on the text somewhere // Check that the mouse was actually on the text somewhere
bool onText = q->cursorRect(cursor).right() >= e->x(); bool onText = q->cursorRect(cursor).right() >= e->x();
if (!onText) { if (!onText) {
QTextCursor nextPos = cursor; QTextCursor nextPos = cursor;
nextPos.movePosition(QTextCursor::Right); nextPos.movePosition(QTextCursor::Right);
onText = q->cursorRect(nextPos).right() >= e->x(); onText = q->cursorRect(nextPos).right() >= e->x();
} }
if (onText) { if (onText) {
m_pendingLinkUpdate = cursor; m_pendingLinkUpdate = cursor;
QTimer::singleShot(0, this, &TextEditorWidgetPrivate::updateLink); QTimer::singleShot(0, this, &TextEditorWidgetPrivate::updateLink);
return; return;
}
} }
clearLink(); clearLink();

View File

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