forked from qt-creator/qt-creator
QmlDesigner: Add top level toolbar
* Added Designer\TopToolBar=true to .ini to enable toolbar * Added backend to CrumbleBar * Added crumble bar * Added QML toolbar * Disabled original toolbar in DesignModeWidget * Added callback to DesignerActionManager * Added id to ZoomPreviewAction * Dock Manager is exposed in DesignModeWidget * Added new version of icon font Change-Id: I8c8ad16137c84229854a1d0fa6dfdf498edf4253 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
@@ -307,7 +307,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentStateInternalIdChanged: layoutTimer.start()
|
||||
//onCurrentStateInternalIdChanged: layoutTimer.start()
|
||||
|
||||
StudioControls.Dialog {
|
||||
id: editDialog
|
||||
@@ -573,6 +573,8 @@ Rectangle {
|
||||
y: scrollView.height - height
|
||||
width: scrollView.availableWidth
|
||||
orientation: Qt.Horizontal
|
||||
active: frame.contentHeight > scrollView.height
|
||||
visible: frame.contentHeight > scrollView.height
|
||||
}
|
||||
|
||||
ScrollBar.vertical: StateScrollBar {
|
||||
@@ -582,6 +584,8 @@ Rectangle {
|
||||
y: scrollView.topPadding
|
||||
height: scrollView.availableHeight
|
||||
orientation: Qt.Vertical
|
||||
active: frame.contentWidth > scrollView.width
|
||||
visible: frame.contentWidth > scrollView.width
|
||||
}
|
||||
|
||||
Flickable {
|
||||
|
||||
@@ -45,6 +45,7 @@ T.AbstractButton {
|
||||
color: control.style.background.idle
|
||||
border.color: control.style.border.idle
|
||||
border.width: control.style.borderWidth
|
||||
radius: control.style.radius
|
||||
}
|
||||
|
||||
indicator: Item {
|
||||
@@ -77,7 +78,7 @@ T.AbstractButton {
|
||||
when: control.enabled && control.pressed
|
||||
PropertyChanges {
|
||||
target: buttonIcon
|
||||
color: control.style.icon.idle
|
||||
color: control.style.icon.interaction
|
||||
}
|
||||
},
|
||||
State {
|
||||
|
||||
@@ -93,8 +93,8 @@ T.ComboBox {
|
||||
__parentPopup: control.popup
|
||||
x: comboBoxInput.x + comboBoxInput.width
|
||||
y: control.style.borderWidth
|
||||
width: control.style.baseIconSize.width - control.style.borderWidth
|
||||
height: control.style.baseIconSize.height - control.style.borderWidth * 2
|
||||
width: control.style.squareControlSize.width - control.style.borderWidth
|
||||
height: control.style.squareControlSize.height - control.style.borderWidth * 2
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
@@ -162,7 +162,7 @@ T.ComboBox {
|
||||
: control.style.text.idle
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
font.pixelSize: control.style.smallIconFontSize
|
||||
visible: control.currentIndex === index ? true : false
|
||||
visible: control.currentIndex === index
|
||||
anchors.fill: parent
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@@ -261,8 +261,7 @@ T.ComboBox {
|
||||
// tab focus. It is therefor possible to use the mouse wheel to scroll through the items.
|
||||
State {
|
||||
name: "focus"
|
||||
when: control.enabled && control.activeFocus && !control.editable
|
||||
&& !control.open
|
||||
when: control.enabled && control.activeFocus && !control.editable && !control.open
|
||||
PropertyChanges {
|
||||
target: control
|
||||
wheelEnabled: true
|
||||
|
||||
@@ -87,7 +87,8 @@ TextInput {
|
||||
},
|
||||
State {
|
||||
name: "dragHover"
|
||||
when: control.__parentControl.enabled && control.__parentControl.hasActiveHoverDrag
|
||||
when: control.__parentControl.enabled
|
||||
&& (control.__parentControl.hasActiveHoverDrag ?? false)
|
||||
PropertyChanges {
|
||||
target: background
|
||||
color: control.style.background.interaction
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Templates 2.12 as T
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
T.ComboBox {
|
||||
id: control
|
||||
|
||||
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
|
||||
|
||||
property bool hover: (comboBoxInput.hover || window.visible) && control.enabled
|
||||
property bool edit: false
|
||||
property bool open: window.visible
|
||||
|
||||
editable: false
|
||||
width: control.style.controlSize.width
|
||||
height: control.style.controlSize.height
|
||||
|
||||
leftPadding: control.style.borderWidth
|
||||
rightPadding: popupIndicator.width + control.style.borderWidth
|
||||
font.pixelSize: control.style.baseFontSize
|
||||
|
||||
delegate: ItemDelegate {
|
||||
required property int index
|
||||
required property var modelData
|
||||
|
||||
width: control.width
|
||||
highlighted: control.highlightedIndex === index
|
||||
contentItem: Text {
|
||||
text: modelData
|
||||
color: "#21be2b"
|
||||
font: control.font
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
indicator: CheckIndicator {
|
||||
id: popupIndicator
|
||||
style: control.style
|
||||
__parentControl: control
|
||||
__parentPopup: comboBoxPopup
|
||||
x: comboBoxInput.x + comboBoxInput.width
|
||||
y: control.style.borderWidth
|
||||
width: control.style.squareControlSize.width - control.style.borderWidth
|
||||
height: control.style.squareControlSize.height - control.style.borderWidth * 2
|
||||
}
|
||||
|
||||
contentItem: ComboBoxInput {
|
||||
id: comboBoxInput
|
||||
style: control.style
|
||||
__parentControl: control
|
||||
text: control.editText
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id: comboBoxBackground
|
||||
color: control.style.background.idle
|
||||
border.color: control.style.border.idle
|
||||
border.width: control.style.borderWidth
|
||||
width: control.width
|
||||
height: control.height
|
||||
}
|
||||
|
||||
popup: T.Popup {
|
||||
id: comboBoxPopup
|
||||
width: 0
|
||||
height: 0
|
||||
closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent
|
||||
onAboutToShow: {
|
||||
control.menuDelegate.parent = window.contentItem
|
||||
control.menuDelegate.visible = true
|
||||
|
||||
window.show()
|
||||
window.requestActivate()
|
||||
window.x = control.mapToGlobal(0,0).x
|
||||
window.y = control.mapToGlobal(0,0).y + control.height
|
||||
control.menuDelegate.focus = true
|
||||
}
|
||||
|
||||
onAboutToHide: window.hide()
|
||||
}
|
||||
|
||||
// Close popup when application goes to background
|
||||
Connections {
|
||||
target: Qt.application
|
||||
function onStateChanged() {
|
||||
if (Qt.application.state === Qt.ApplicationInactive)
|
||||
comboBoxPopup.close()
|
||||
}
|
||||
}
|
||||
|
||||
Window {
|
||||
id: window
|
||||
width: control.menuDelegate.implicitWidth
|
||||
height: control.menuDelegate.implicitHeight
|
||||
visible: false
|
||||
flags: Qt.Popup | Qt.NoDropShadowWindowHint
|
||||
modality: Qt.NonModal
|
||||
transientParent: control.Window.window
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
property Menu menuDelegate: Menu {
|
||||
id: textEditMenu
|
||||
y: 0
|
||||
width: control.width
|
||||
overlap: 0
|
||||
|
||||
Repeater {
|
||||
model: control.model
|
||||
|
||||
MenuItem {
|
||||
id: menuItem
|
||||
x: 0
|
||||
text: modelData
|
||||
onTriggered: {
|
||||
control.currentIndex = index
|
||||
comboBoxPopup.close()
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
implicitWidth: textLabel.implicitWidth + menuItem.labelSpacing
|
||||
+ menuItem.leftPadding + menuItem.rightPadding
|
||||
implicitHeight: control.style.controlSize.height
|
||||
x: control.style.borderWidth
|
||||
y: control.style.borderWidth
|
||||
width: menuItem.menu.width - (control.style.borderWidth * 2)
|
||||
height: menuItem.height - (control.style.borderWidth * 2)
|
||||
color: menuItem.highlighted ? control.style.interaction
|
||||
: "transparent"
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
Text {
|
||||
id: textLabel
|
||||
leftPadding: itemDelegateIconArea.width
|
||||
text: menuItem.text
|
||||
font: control.font
|
||||
color: menuItem.highlighted ? control.style.text.selectedText
|
||||
: control.style.text.idle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Item {
|
||||
id: itemDelegateIconArea
|
||||
width: menuItem.height
|
||||
height: menuItem.height
|
||||
|
||||
T.Label {
|
||||
id: itemDelegateIcon
|
||||
text: StudioTheme.Constants.tickIcon
|
||||
color: textLabel.color
|
||||
font.family: StudioTheme.Constants.iconFont.family
|
||||
font.pixelSize: control.style.smallIconFontSize
|
||||
visible: control.currentIndex === index
|
||||
anchors.fill: parent
|
||||
renderType: Text.NativeRendering
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "default"
|
||||
when: control.enabled && !control.hover && !control.edit && !control.open
|
||||
&& !control.activeFocus && !control.hasActiveDrag
|
||||
PropertyChanges {
|
||||
target: control
|
||||
wheelEnabled: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: comboBoxInput
|
||||
selectByMouse: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: comboBoxBackground
|
||||
color: control.style.background.idle
|
||||
}
|
||||
},
|
||||
// This state is intended for ComboBoxes which aren't editable, but have focus e.g. via
|
||||
// tab focus. It is therefor possible to use the mouse wheel to scroll through the items.
|
||||
State {
|
||||
name: "focus"
|
||||
when: control.enabled && control.activeFocus && !control.editable && !control.open
|
||||
PropertyChanges {
|
||||
target: control
|
||||
wheelEnabled: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: comboBoxInput
|
||||
focus: true
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "popup"
|
||||
when: control.enabled && control.open
|
||||
PropertyChanges {
|
||||
target: control
|
||||
wheelEnabled: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: comboBoxInput
|
||||
selectByMouse: false
|
||||
readOnly: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: comboBoxBackground
|
||||
color: control.style.background.interaction
|
||||
border.color: control.style.border.interaction
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "disable"
|
||||
when: !control.enabled
|
||||
PropertyChanges {
|
||||
target: comboBoxBackground
|
||||
color: control.style.background.disabled
|
||||
border.color: control.style.border.disabled
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -49,3 +49,4 @@ TextField 1.0 TextField.qml
|
||||
ToolTip 1.0 ToolTip.qml
|
||||
TranslationIndicator 1.0 TranslationIndicator.qml
|
||||
VerticalScrollBar 1.0 VerticalScrollBar.qml
|
||||
TopLevelComboBox 1.0 TopLevelComboBox.qml
|
||||
|
||||
@@ -17,7 +17,7 @@ QtObject {
|
||||
property real bigIconFontSize: Values.bigIconFontSize
|
||||
|
||||
property real borderWidth: Values.border
|
||||
property real radius: 4
|
||||
property real radius: Values.radius
|
||||
|
||||
property size smallControlSize: Qt.size(Values.smallRectWidth,
|
||||
Values.smallRectWidth)
|
||||
@@ -28,7 +28,6 @@ QtObject {
|
||||
|
||||
property size smallIconSize: Qt.size(Values.spinControlIconSizeMulti,
|
||||
Values.spinControlIconSizeMulti)
|
||||
property size baseIconSize: Qt.size(Values.height, Values.height)
|
||||
|
||||
// TODO only used once
|
||||
property size spinBoxIndicatorSize: Qt.size(Values.spinBoxIndicatorWidth,
|
||||
@@ -92,6 +91,7 @@ QtObject {
|
||||
component BorderColors: QtObject {
|
||||
property color idle: Values.themeControlOutline
|
||||
property color interaction: Values.themeControlOutlineInteraction
|
||||
property color hover: "red"
|
||||
property color disabled: Values.themeControlOutlineDisabled
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import QtQuick
|
||||
|
||||
ControlStyle {
|
||||
background {
|
||||
idle: "red"
|
||||
}
|
||||
controlSize: Qt.size(Values.topLevelComboWidth, Values.topLevelComboHeight)
|
||||
baseIconFontSize: Values.topLevelComboIcon
|
||||
smallIconFontSize: 10
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ QtObject {
|
||||
|
||||
property real baseHeight: 29
|
||||
|
||||
property real topLevelComboWidth: 210
|
||||
property real topLevelComboHeight: 36
|
||||
property real topLevelComboIcon: 20
|
||||
|
||||
property real smallFont: 8
|
||||
property real baseFont: 12
|
||||
property real mediumFont: 14
|
||||
@@ -77,6 +81,7 @@ QtObject {
|
||||
property real marginTopBottom: 4
|
||||
property real border: 1
|
||||
property real borderHover: 3
|
||||
property real radius: 0
|
||||
|
||||
property real maxComboBoxPopupHeight: Math.round(300 * values.scaleFactor)
|
||||
property real maxTextAreaPopupHeight: Math.round(150 * values.scaleFactor)
|
||||
@@ -350,4 +355,24 @@ QtObject {
|
||||
|
||||
property ControlStyle controlStyle: DefaultStyle {}
|
||||
property ControlStyle toolbarStyle: ToolbarStyle {}
|
||||
property ControlStyle primaryToolbarStyle: ToolbarStyle {
|
||||
baseIconFontSize: values.baseFontSize
|
||||
radius: 4
|
||||
|
||||
icon: ControlStyle.IconColors {
|
||||
idle: values.themeTextSelectedTextColor
|
||||
disabled: "#636363"
|
||||
}
|
||||
|
||||
background: ControlStyle.BackgroundColors {
|
||||
idle: values.themeInteraction
|
||||
}
|
||||
|
||||
border: ControlStyle.BorderColors {
|
||||
idle: values.themeInteraction
|
||||
hover: "#000000"
|
||||
interaction: "#DCDADA"
|
||||
disabled: "#636363"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
share/qtcreator/qmldesigner/statusbar/Main.qml
Normal file
21
share/qtcreator/qmldesigner/statusbar/Main.qml
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import StudioControls
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Item {
|
||||
id: toolbarContainer
|
||||
|
||||
height: 24
|
||||
width: 2024
|
||||
|
||||
Rectangle {
|
||||
|
||||
color: "#2d2d2d"
|
||||
anchors.fill: parent
|
||||
|
||||
}
|
||||
}
|
||||
93
share/qtcreator/qmldesigner/toolbar/CrumbleBar.qml
Normal file
93
share/qtcreator/qmldesigner/toolbar/CrumbleBar.qml
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
ListView {
|
||||
id: root
|
||||
|
||||
property real crumbleWidth: 166
|
||||
property real crumbleHeight: 36
|
||||
|
||||
property real inset: 5
|
||||
property real strokeWidth: 1
|
||||
property real textLeftMargin: 18
|
||||
property real textTopMargin: 6
|
||||
property real textRightMargin: 6
|
||||
property real textBottomMargin: 6
|
||||
|
||||
property alias font: fontMetrics.font
|
||||
|
||||
signal clicked(index: int)
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
flickableDirection: Flickable.HorizontalFlick
|
||||
interactive: true
|
||||
|
||||
orientation: ListView.Horizontal
|
||||
clip: true
|
||||
focus: true
|
||||
|
||||
function updateContentX() {
|
||||
root.contentX = (root.contentWidth < root.width) ? 0 : root.contentWidth - root.width
|
||||
}
|
||||
|
||||
onCountChanged: root.updateContentX()
|
||||
onWidthChanged: root.updateContentX()
|
||||
|
||||
visible: root.count > 1 && root.width > (root.crumbleWidth) - 24
|
||||
|
||||
delegate: CrumbleBread {
|
||||
text: fileName
|
||||
tooltip: fileAddress
|
||||
|
||||
width: root.crumbleWidth
|
||||
height: root.crumbleHeight
|
||||
|
||||
inset: root.inset
|
||||
strokeWidth: root.strokeWidth
|
||||
textLeftMargin: root.textLeftMargin
|
||||
textTopMargin: root.textTopMargin
|
||||
textRightMargin: root.textRightMargin
|
||||
textBottomMargin: root.textBottomMargin
|
||||
|
||||
font: root.font
|
||||
|
||||
modelSize: root.count
|
||||
|
||||
onClicked: {
|
||||
if (index + 1 < root.count)
|
||||
root.clicked(index)
|
||||
}
|
||||
}
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1.0
|
||||
duration: 400
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "scale"
|
||||
from: 0
|
||||
to: 1.0
|
||||
duration: 400
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "x"
|
||||
duration: 400
|
||||
easing.type: Easing.OutBack
|
||||
}
|
||||
}
|
||||
|
||||
FontMetrics {
|
||||
id: fontMetrics
|
||||
font.pixelSize: 12
|
||||
font.family: "SF Pro"
|
||||
}
|
||||
}
|
||||
176
share/qtcreator/qmldesigner/toolbar/CrumbleBread.qml
Normal file
176
share/qtcreator/qmldesigner/toolbar/CrumbleBread.qml
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Shapes
|
||||
|
||||
Item {
|
||||
id: root
|
||||
antialiasing: true
|
||||
|
||||
property int modelSize
|
||||
|
||||
/* Colors might come from Theme */
|
||||
property color idleBackgroundColor: "#2e2f30"
|
||||
property color idleStrokeColor: "#1f1f1f"
|
||||
property color idleTextColor: "#ffffff"
|
||||
property color hoverBackgroundColor: "#434343"
|
||||
property color hoverStrokeColor: "#434343"
|
||||
property color activeColor: "#57b9fc"
|
||||
property color activeTextColor: "#1f1f1f"
|
||||
|
||||
property string tooltip
|
||||
|
||||
property alias text: label.text
|
||||
property alias font: label.font
|
||||
property alias inset: backgroundPath.inset
|
||||
property alias strokeWidth: backgroundPath.strokeWidth
|
||||
|
||||
property real textLeftMargin: 18
|
||||
property real textTopMargin: 6
|
||||
property real textRightMargin: 6
|
||||
property real textBottomMargin: 6
|
||||
|
||||
readonly property int itemIndex: index
|
||||
readonly property bool isFirst: itemIndex === 0
|
||||
readonly property bool isLast: (itemIndex + 1) === modelSize
|
||||
|
||||
signal clicked(int callIdx)
|
||||
|
||||
width: 166
|
||||
height: 36
|
||||
|
||||
Shape {
|
||||
id: backgroundShape
|
||||
anchors.fill: root
|
||||
|
||||
antialiasing: root.antialiasing
|
||||
layer.enabled: antialiasing
|
||||
layer.smooth: antialiasing
|
||||
layer.samples: antialiasing ? 4 : 0
|
||||
|
||||
ShapePath {
|
||||
id: backgroundPath
|
||||
|
||||
joinStyle: ShapePath.MiterJoin
|
||||
fillColor: root.idleBackgroundColor
|
||||
strokeColor: root.idleStrokeColor
|
||||
strokeWidth: 1
|
||||
|
||||
property real inset: 5
|
||||
property real rightOut: root.isLast ? 0 : root.inset
|
||||
property real leftIn: root.isFirst ? 0 : root.inset
|
||||
property real strokeOffset: backgroundPath.strokeWidth / 2
|
||||
|
||||
property real topY: backgroundPath.strokeOffset
|
||||
property real bottomY: backgroundShape.height - backgroundPath.strokeOffset
|
||||
property real halfY: (backgroundPath.topY + backgroundPath.bottomY) / 2
|
||||
|
||||
startX: backgroundPath.strokeOffset
|
||||
startY: backgroundPath.topY
|
||||
|
||||
PathLine {
|
||||
x: backgroundShape.width - backgroundPath.strokeOffset - backgroundPath.rightOut
|
||||
y: backgroundPath.topY
|
||||
}
|
||||
PathLine {
|
||||
x: backgroundShape.width - backgroundPath.strokeOffset
|
||||
y: backgroundPath.halfY
|
||||
}
|
||||
PathLine {
|
||||
x: backgroundShape.width - backgroundPath.strokeOffset - backgroundPath.rightOut
|
||||
y: backgroundPath.bottomY
|
||||
}
|
||||
PathLine {
|
||||
x: backgroundPath.strokeOffset
|
||||
y: backgroundPath.bottomY
|
||||
}
|
||||
PathLine {
|
||||
x: backgroundPath.leftIn + backgroundPath.strokeOffset
|
||||
y: backgroundPath.halfY
|
||||
}
|
||||
PathLine {
|
||||
x: backgroundPath.strokeOffset
|
||||
y: backgroundPath.topY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: root.textLeftMargin
|
||||
anchors.topMargin: root.textTopMargin
|
||||
anchors.rightMargin: root.textRightMargin
|
||||
anchors.bottomMargin: root.textBottomMargin
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
color: root.idleTextColor
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
|
||||
text: "Crumble File"
|
||||
font.pixelSize: 12
|
||||
font.family: "SF Pro"
|
||||
|
||||
ToolTip.text: root.tooltip
|
||||
ToolTip.visible: mouseArea.containsMouse
|
||||
ToolTip.delay: 1000
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: root.clicked(root.itemIndex)
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "idle"
|
||||
when: !mouseArea.containsMouse && !mouseArea.pressed && !root.isLast
|
||||
|
||||
PropertyChanges {
|
||||
target: backgroundPath
|
||||
fillColor: root.idleBackgroundColor
|
||||
strokeColor: root.idleStrokeColor
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "active"
|
||||
when: root.isLast
|
||||
extend: "pressed"
|
||||
},
|
||||
State {
|
||||
name: "hover"
|
||||
when: mouseArea.containsMouse && !mouseArea.pressed
|
||||
|
||||
PropertyChanges {
|
||||
target: backgroundPath
|
||||
fillColor: root.hoverBackgroundColor
|
||||
strokeColor: root.hoverStrokeColor
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "pressed"
|
||||
when: mouseArea.pressed
|
||||
|
||||
PropertyChanges {
|
||||
target: backgroundPath
|
||||
strokeColor: root.activeColor
|
||||
fillColor: root.activeColor
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: label
|
||||
color: root.activeTextColor
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
223
share/qtcreator/qmldesigner/toolbar/Main.qml
Normal file
223
share/qtcreator/qmldesigner/toolbar/Main.qml
Normal file
@@ -0,0 +1,223 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import StudioControls
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
import ToolBar 1.0
|
||||
|
||||
Rectangle {
|
||||
id: toolbarContainer
|
||||
color: "#2d2d2d"
|
||||
border.color: "#00000000"
|
||||
|
||||
height: 56
|
||||
width: 2024
|
||||
|
||||
ToolBarBackend {
|
||||
id: backend
|
||||
}
|
||||
|
||||
Item {
|
||||
id: topToolbarOtherMode
|
||||
anchors.fill: parent
|
||||
visible: !backend.isInDesignMode
|
||||
|
||||
ToolbarButton {
|
||||
id: homeOther
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
enabled: backend.isDesignModeEnabled
|
||||
tooltip: qsTr("Switch to Design Mode")
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_designMode
|
||||
|
||||
onClicked: backend.triggerModeChange()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: topToolbar
|
||||
anchors.fill: parent
|
||||
visible: backend.isInDesignMode
|
||||
|
||||
ToolbarButton {
|
||||
id: home
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_home
|
||||
|
||||
onClicked: backend.triggerModeChange()
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: runProject
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: home.right
|
||||
anchors.leftMargin: 10
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_runProject
|
||||
style: StudioTheme.ToolbarStyle {
|
||||
icon: StudioTheme.ControlStyle.IconColors {
|
||||
idle: "#649a5d"
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: backend.runProject()
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: livePreviewButton
|
||||
style: StudioTheme.Values.primaryToolbarStyle
|
||||
width: 96
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: runProject.right
|
||||
anchors.leftMargin: 10
|
||||
iconFont: StudioTheme.Constants.font
|
||||
buttonIcon: qsTr("Live Preview")
|
||||
|
||||
onClicked: livePreview.trigger()
|
||||
|
||||
ActionSubscriber {
|
||||
id: livePreview
|
||||
actionId: "LivePreview"
|
||||
}
|
||||
}
|
||||
|
||||
TopLevelComboBox {
|
||||
id: currentFile
|
||||
style: StudioTheme.Values.toolbarStyle
|
||||
width: 320
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: livePreviewButton.right
|
||||
anchors.leftMargin: 10
|
||||
model: backend.documentModel
|
||||
currentIndex: backend.documentIndex
|
||||
|
||||
onActivated: backend.openFileByIndex(index)
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: backButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: currentFile.right
|
||||
anchors.leftMargin: 10
|
||||
enabled: backend.canGoBack
|
||||
tooltip: qsTr("Go Back")
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_navFile
|
||||
iconRotation: 0
|
||||
|
||||
onClicked: backend.goBackward()
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: forwardButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: backButton.right
|
||||
anchors.leftMargin: 10
|
||||
enabled: backend.canGoForward
|
||||
tooltip: qsTr("Go Forward")
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_navFile
|
||||
iconRotation: 180
|
||||
|
||||
onClicked: backend.goForward()
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: closeButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: forwardButton.right
|
||||
anchors.leftMargin: 10
|
||||
tooltip: qsTr("Close")
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_closeFile
|
||||
|
||||
onClicked: backend.closeCurrentDocument()
|
||||
}
|
||||
|
||||
CrumbleBar {
|
||||
id: flickable
|
||||
height: 36
|
||||
anchors.left: closeButton.right
|
||||
anchors.leftMargin: 10
|
||||
anchors.right: createComponent.left
|
||||
anchors.rightMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
model: CrumbleBarModel {
|
||||
id: crumbleBarModel
|
||||
}
|
||||
|
||||
onClicked: crumbleBarModel.onCrumblePathElementClicked(index)
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: createComponent
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: enterComponent.left
|
||||
anchors.rightMargin: 10
|
||||
enabled: moveToComponentBackend.available
|
||||
tooltip: moveToComponentBackend.tooltip
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_makeComponent
|
||||
|
||||
onClicked: moveToComponentBackend.trigger()
|
||||
|
||||
ActionSubscriber {
|
||||
id: moveToComponentBackend
|
||||
actionId: "MakeComponent"
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: enterComponent
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: workspaces.left
|
||||
anchors.rightMargin: 10
|
||||
enabled: goIntoComponentBackend.available
|
||||
tooltip: goIntoComponentBackend.tooltip
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_enterComponent
|
||||
|
||||
onClicked: goIntoComponentBackend.trigger()
|
||||
|
||||
ActionSubscriber {
|
||||
id: goIntoComponentBackend
|
||||
actionId: "GoIntoComponent"
|
||||
}
|
||||
}
|
||||
|
||||
TopLevelComboBox {
|
||||
id: workspaces
|
||||
style: StudioTheme.Values.toolbarStyle
|
||||
width: 210
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: annotations.left
|
||||
anchors.rightMargin: 10
|
||||
model: backend.workspaces
|
||||
onCurrentTextChanged: backend.setCurrentWorkspace(workspaces.currentText)
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: annotations
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: shareButton.left
|
||||
anchors.rightMargin: 10
|
||||
tooltip: qsTr("Edit Annotations")
|
||||
buttonIcon: StudioTheme.Constants.topToolbar_annotations
|
||||
|
||||
onClicked: backend.editGlobalAnnoation()
|
||||
}
|
||||
|
||||
ToolbarButton {
|
||||
id: shareButton
|
||||
style: StudioTheme.Values.primaryToolbarStyle
|
||||
width: 96
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
iconFont: StudioTheme.Constants.font
|
||||
buttonIcon: qsTr("Share")
|
||||
|
||||
onClicked: backend.shareApplicationOnline()
|
||||
}
|
||||
}
|
||||
}
|
||||
24
share/qtcreator/qmldesigner/toolbar/ToolbarButton.qml
Normal file
24
share/qtcreator/qmldesigner/toolbar/ToolbarButton.qml
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import StudioControls 1.0 as StudioControls
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
import HelperWidgets 2.0
|
||||
|
||||
StudioControls.AbstractButton {
|
||||
id: button
|
||||
|
||||
property alias tooltip: toolTipArea.tooltip
|
||||
|
||||
style: StudioTheme.Values.toolbarStyle
|
||||
hover: toolTipArea.containsMouse
|
||||
|
||||
ToolTipArea {
|
||||
id: toolTipArea
|
||||
anchors.fill: parent
|
||||
// Without setting the acceptedButtons property the clicked event won't
|
||||
// reach the AbstractButton, it will be consumed by the ToolTipArea
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
@@ -1111,6 +1111,15 @@ extend_qtc_plugin(QmlDesigner
|
||||
shortcutwidget.cpp shortcutwidget.h
|
||||
)
|
||||
|
||||
extend_qtc_plugin(QmlDesigner
|
||||
SOURCES_PREFIX components/toolbar
|
||||
SOURCES
|
||||
toolbar.cpp
|
||||
toolbar.h
|
||||
toolbarbackend.cpp
|
||||
toolbarbackend.h
|
||||
)
|
||||
|
||||
extend_qtc_plugin(QmlDesigner
|
||||
CONDITION TARGET Nanotrace
|
||||
DEPENDS Nanotrace
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "qmldesignerplugin.h"
|
||||
|
||||
#include <nodeabstractproperty.h>
|
||||
#include <toolbar.h>
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
@@ -60,6 +61,7 @@ void CrumbleBar::pushFile(const Utils::FilePath &fileName)
|
||||
{
|
||||
if (!m_isInternalCalled) {
|
||||
crumblePath()->clear();
|
||||
m_pathes.clear();
|
||||
} else {
|
||||
// If the path already exists in crumblePath, pop up to first instance of that to avoid
|
||||
// cyclical crumblePath
|
||||
@@ -71,8 +73,10 @@ void CrumbleBar::pushFile(const Utils::FilePath &fileName)
|
||||
}
|
||||
|
||||
if (match != -1) {
|
||||
for (int i = crumblePath()->length() - 1 - match; i > 0; --i)
|
||||
for (int i = crumblePath()->length() - 1 - match; i > 0; --i) {
|
||||
crumblePath()->popElement();
|
||||
m_pathes.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,10 +85,13 @@ void CrumbleBar::pushFile(const Utils::FilePath &fileName)
|
||||
CrumbleBarInfo crumbleBarInfo;
|
||||
crumbleBarInfo.fileName = fileName;
|
||||
crumblePath()->pushElement(fileName.fileName(), QVariant::fromValue(crumbleBarInfo));
|
||||
m_pathes.append({fileName, fileName.fileName(), {}});
|
||||
}
|
||||
|
||||
m_isInternalCalled = false;
|
||||
updateVisibility();
|
||||
|
||||
emit pathChanged();
|
||||
}
|
||||
|
||||
void CrumbleBar::pushInFileComponent(const ModelNode &modelNode)
|
||||
@@ -97,10 +104,13 @@ void CrumbleBar::pushInFileComponent(const ModelNode &modelNode)
|
||||
crumblePath()->popElement();
|
||||
|
||||
crumblePath()->pushElement(crumbleBarInfo.displayName, QVariant::fromValue(crumbleBarInfo));
|
||||
m_pathes.append({{}, crumbleBarInfo.displayName, modelNode});
|
||||
|
||||
m_isInternalCalled = false;
|
||||
|
||||
updateVisibility();
|
||||
|
||||
emit pathChanged();
|
||||
}
|
||||
|
||||
void CrumbleBar::nextFileIsCalledInternally()
|
||||
@@ -120,6 +130,21 @@ Utils::CrumblePath *CrumbleBar::crumblePath()
|
||||
return m_crumblePath;
|
||||
}
|
||||
|
||||
QStringList CrumbleBar::path() const
|
||||
{
|
||||
QStringList list;
|
||||
for (auto &path : m_pathes) {
|
||||
list.append(path.displayName);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<CrumbleBarInfo> CrumbleBar::infos() const
|
||||
{
|
||||
return m_pathes;
|
||||
}
|
||||
|
||||
bool CrumbleBar::showSaveDialog()
|
||||
{
|
||||
bool canceled = false;
|
||||
@@ -151,11 +176,15 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
|
||||
if (!inlineComp && !showSaveDialog())
|
||||
return;
|
||||
|
||||
while (clickedCrumbleBarInfo != crumblePath()->dataForLastIndex().value<CrumbleBarInfo>())
|
||||
while (clickedCrumbleBarInfo != crumblePath()->dataForLastIndex().value<CrumbleBarInfo>()) {
|
||||
crumblePath()->popElement();
|
||||
m_pathes.removeLast();
|
||||
}
|
||||
|
||||
if (crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isValid())
|
||||
if (crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isValid()) {
|
||||
crumblePath()->popElement();
|
||||
m_pathes.removeLast();
|
||||
}
|
||||
|
||||
m_isInternalCalled = true;
|
||||
if (inlineComp) {
|
||||
@@ -164,6 +193,7 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
|
||||
QmlDesignerPlugin::instance()->viewManager().setComponentViewToMaster();
|
||||
} else {
|
||||
crumblePath()->popElement();
|
||||
m_pathes.removeLast();
|
||||
nextFileIsCalledInternally();
|
||||
Core::EditorManager::openEditor(clickedCrumbleBarInfo.fileName,
|
||||
Utils::Id(),
|
||||
@@ -175,11 +205,13 @@ void CrumbleBar::onCrumblePathElementClicked(const QVariant &data)
|
||||
QmlDesignerPlugin::instance()->viewManager().setComponentViewToMaster();
|
||||
}
|
||||
}
|
||||
emit pathChanged();
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
void CrumbleBar::updateVisibility()
|
||||
{
|
||||
if (!ToolBar::isVisible())
|
||||
crumblePath()->setVisible(crumblePath()->length() > 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,24 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class CrumbleBarInfo {
|
||||
public:
|
||||
|
||||
CrumbleBarInfo() = default;
|
||||
|
||||
CrumbleBarInfo(Utils::FilePath f,
|
||||
QString d,
|
||||
ModelNode m) :
|
||||
fileName(f),
|
||||
displayName(d),
|
||||
modelNode(m)
|
||||
{}
|
||||
|
||||
Utils::FilePath fileName;
|
||||
QString displayName;
|
||||
ModelNode modelNode;
|
||||
};
|
||||
|
||||
class CrumbleBar : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -24,21 +42,23 @@ public:
|
||||
|
||||
Utils::CrumblePath *crumblePath();
|
||||
|
||||
private:
|
||||
QStringList path() const;
|
||||
|
||||
QList<CrumbleBarInfo> infos() const;
|
||||
|
||||
void onCrumblePathElementClicked(const QVariant &data);
|
||||
|
||||
signals:
|
||||
void pathChanged();
|
||||
|
||||
private:
|
||||
void updateVisibility();
|
||||
bool showSaveDialog();
|
||||
|
||||
private:
|
||||
bool m_isInternalCalled = false;
|
||||
Utils::CrumblePath *m_crumblePath = nullptr;
|
||||
};
|
||||
|
||||
class CrumbleBarInfo {
|
||||
public:
|
||||
Utils::FilePath fileName;
|
||||
QString displayName;
|
||||
ModelNode modelNode;
|
||||
QList<CrumbleBarInfo> m_pathes;
|
||||
};
|
||||
|
||||
bool operator ==(const CrumbleBarInfo &first, const CrumbleBarInfo &second);
|
||||
|
||||
@@ -293,6 +293,11 @@ QIcon DesignerActionManager::contextIcon(int contextId) const
|
||||
return m_designerIcons->icon(DesignerIcons::IconId(contextId), DesignerIcons::ContextMenuArea);
|
||||
}
|
||||
|
||||
void DesignerActionManager::addAddActionCallback(ActionAddedInterface callback)
|
||||
{
|
||||
m_callBacks.append(callback);
|
||||
}
|
||||
|
||||
class VisiblityModelNodeAction : public ModelNodeContextMenuAction
|
||||
{
|
||||
public:
|
||||
@@ -2051,6 +2056,10 @@ void DesignerActionManager::createDefaultModelNodePreviewImageHandlers()
|
||||
void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
|
||||
{
|
||||
m_designerActions.append(QSharedPointer<ActionInterface>(newAction));
|
||||
|
||||
for (auto callback : m_callBacks) {
|
||||
callback(newAction);
|
||||
}
|
||||
}
|
||||
|
||||
void DesignerActionManager::addCreatorCommand(Core::Command *command, const QByteArray &category, int priority,
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <QToolBar>
|
||||
#include <QImage>
|
||||
|
||||
#include <functional>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QGraphicsItem;
|
||||
class QGraphicsWidget;
|
||||
@@ -27,6 +29,7 @@ class DesignerIcons;
|
||||
|
||||
using AddResourceOperation = std::function<AddFilesResult(const QStringList &, const QString &, bool)>;
|
||||
using ModelNodePreviewImageOperation = std::function<QVariant(const ModelNode &)>;
|
||||
using ActionAddedInterface = std::function<void(ActionInterface*)>;
|
||||
|
||||
struct AddResourceHandler
|
||||
{
|
||||
@@ -121,6 +124,8 @@ public:
|
||||
QHash<QString, QStringList> handleExternalAssetsDrop(const QMimeData *data) const;
|
||||
QIcon contextIcon(int contextId) const;
|
||||
|
||||
void addAddActionCallback(ActionAddedInterface callback);
|
||||
|
||||
private:
|
||||
void addTransitionEffectAction(const TypeName &typeName);
|
||||
void addCustomTransitionEffectAction();
|
||||
@@ -133,6 +138,7 @@ private:
|
||||
QList<ModelNodePreviewImageHandler> m_modelNodePreviewImageHandlers;
|
||||
ExternalDependenciesInterface &m_externalDependencies;
|
||||
QScopedPointer<DesignerIcons> m_designerIcons;
|
||||
QList<ActionAddedInterface> m_callBacks;
|
||||
};
|
||||
|
||||
} //QmlDesigner
|
||||
|
||||
126
src/plugins/qmldesigner/components/toolbar/toolbar.cpp
Normal file
126
src/plugins/qmldesigner/components/toolbar/toolbar.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "toolbar.h"
|
||||
#include "toolbarbackend.h"
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/filepath.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QToolBar>
|
||||
#include <QMainWindow>
|
||||
#include <QQmlEngine>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
QmlDesigner::ToolBar::ToolBar()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static Utils::FilePath propertyEditorResourcesPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
|
||||
return Utils::FilePath::fromString(QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources");
|
||||
#endif
|
||||
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources");
|
||||
}
|
||||
|
||||
Utils::FilePath qmlSourcesStatusBarPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
|
||||
return Utils::FilePath::fromString(QLatin1String(SHARE_QML_PATH) + "/statusbar");
|
||||
#endif
|
||||
return Core::ICore::resourcePath("qmldesigner/statusbar");
|
||||
}
|
||||
|
||||
Utils::FilePath qmlSourcesPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
|
||||
return Utils::FilePath::fromString(QLatin1String(SHARE_QML_PATH) + "/toolbar");
|
||||
#endif
|
||||
return Core::ICore::resourcePath("qmldesigner/toolbar");
|
||||
}
|
||||
|
||||
void ToolBar::create()
|
||||
{
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
||||
ToolBarBackend::registerDeclarativeType();
|
||||
|
||||
auto window = Core::ICore::mainWindow();
|
||||
|
||||
//Core::ICore::statusBar()->hide();
|
||||
|
||||
auto toolBar = new QToolBar;
|
||||
|
||||
toolBar->setFloatable(false);
|
||||
toolBar->setMovable(false);
|
||||
|
||||
auto quickWidget = new QQuickWidget;
|
||||
|
||||
quickWidget->setFixedHeight(48);
|
||||
quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
quickWidget->setMinimumWidth(200);
|
||||
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
||||
quickWidget->engine()->addImportPath(propertyEditorResourcesPath().toString() + "/imports");
|
||||
|
||||
Utils::FilePath qmlFilePath = qmlSourcesPath() / "Main.qml";
|
||||
QTC_ASSERT(qmlFilePath.exists(), return );
|
||||
|
||||
Theme::setupTheme(quickWidget->engine());
|
||||
|
||||
quickWidget->setSource(QUrl::fromLocalFile(qmlFilePath.toFSPathString()));
|
||||
|
||||
toolBar->addWidget(quickWidget);
|
||||
window->addToolBar(toolBar);
|
||||
}
|
||||
|
||||
void ToolBar::createStatusBar()
|
||||
{
|
||||
if (!isVisible())
|
||||
return;
|
||||
|
||||
ToolBarBackend::registerDeclarativeType();
|
||||
|
||||
auto quickWidget = new QQuickWidget;
|
||||
|
||||
quickWidget->setFixedHeight(24);
|
||||
quickWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
quickWidget->setMinimumWidth(200);
|
||||
quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
|
||||
quickWidget->engine()->addImportPath(propertyEditorResourcesPath().toString() + "/imports");
|
||||
|
||||
Utils::FilePath qmlFilePath = qmlSourcesStatusBarPath() + QStringLiteral("/Main.qml");
|
||||
QTC_ASSERT(qmlFilePath.exists(), return );
|
||||
|
||||
Theme::setupTheme(quickWidget->engine());
|
||||
|
||||
quickWidget->setSource(QUrl::fromLocalFile(qmlFilePath.toFSPathString()));
|
||||
|
||||
for (QWidget *w : Core::ICore::statusBar()->findChildren<QWidget *>(Qt::FindDirectChildrenOnly)) {
|
||||
w->hide();
|
||||
}
|
||||
|
||||
Core::ICore::statusBar()->addWidget(quickWidget);
|
||||
}
|
||||
|
||||
bool ToolBar::isVisible()
|
||||
{
|
||||
QSettings *settings = Core::ICore::settings();
|
||||
const QString qdsToolbarEntry = "QML/Designer/TopToolBar";
|
||||
|
||||
return settings->value(qdsToolbarEntry, false).toBool();
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
21
src/plugins/qmldesigner/components/toolbar/toolbar.h
Normal file
21
src/plugins/qmldesigner/components/toolbar/toolbar.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QQuickWidget>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class ToolBar : public QQuickWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ToolBar();
|
||||
static void create();
|
||||
static void createStatusBar();
|
||||
static bool isVisible();
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
409
src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
Normal file
409
src/plugins/qmldesigner/components/toolbar/toolbarbackend.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "toolbarbackend.h"
|
||||
|
||||
#include <crumblebar.h>
|
||||
#include <designeractionmanager.h>
|
||||
#include <designmodewidget.h>
|
||||
#include <viewmanager.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/designmode.h>
|
||||
#include <coreplugin/editormanager/documentmodel.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qmlprojectmanager/qmlproject.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static Internal::DesignModeWidget *designModeWidget()
|
||||
{
|
||||
return QmlDesignerPlugin::instance()->mainWidget();
|
||||
}
|
||||
|
||||
static DesignDocument *currentDesignDocument()
|
||||
{
|
||||
return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument();
|
||||
}
|
||||
|
||||
static CrumbleBar *crumbleBar()
|
||||
{
|
||||
return designModeWidget()->crumbleBar();
|
||||
}
|
||||
|
||||
static Utils::FilePath getMainUiFile()
|
||||
{
|
||||
auto project = ProjectExplorer::SessionManager::startupProject();
|
||||
if (!project)
|
||||
return {};
|
||||
|
||||
if (!project->activeTarget())
|
||||
return {};
|
||||
|
||||
auto qmlBuildSystem = qobject_cast<QmlProjectManager::QmlBuildSystem *>(
|
||||
project->activeTarget()->buildSystem());
|
||||
return qmlBuildSystem->mainUiFilePath();
|
||||
}
|
||||
|
||||
static void openUiFile()
|
||||
{
|
||||
const Utils::FilePath mainUiFile = getMainUiFile();
|
||||
|
||||
if (mainUiFile.completeSuffix() == "ui.qml" && mainUiFile.exists())
|
||||
Core::EditorManager::openEditor(mainUiFile, Utils::Id());
|
||||
}
|
||||
|
||||
void ToolBarBackend::triggerModeChange()
|
||||
{
|
||||
QTimer::singleShot(0, []() { //Do not trigger mode change directly from QML
|
||||
bool qmlFileOpen = false;
|
||||
|
||||
auto document = Core::EditorManager::currentDocument();
|
||||
|
||||
if (document)
|
||||
qmlFileOpen = document->filePath().fileName().endsWith(".qml");
|
||||
|
||||
if (Core::ModeManager::currentModeId() == Core::Constants::MODE_DESIGN)
|
||||
Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
|
||||
else if (qmlFileOpen)
|
||||
Core::ModeManager::activateMode(Core::Constants::MODE_DESIGN);
|
||||
else if (Core::ModeManager::currentModeId() == Core::Constants::MODE_WELCOME)
|
||||
openUiFile();
|
||||
else
|
||||
Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
|
||||
});
|
||||
}
|
||||
|
||||
void ToolBarBackend::runProject()
|
||||
{
|
||||
ProjectExplorer::ProjectExplorerPlugin::runStartupProject(
|
||||
ProjectExplorer::Constants::NORMAL_RUN_MODE);
|
||||
}
|
||||
|
||||
void ToolBarBackend::goForward()
|
||||
{
|
||||
QTC_ASSERT(designModeWidget(), return );
|
||||
designModeWidget()->toolBarOnGoForwardClicked();
|
||||
}
|
||||
|
||||
void ToolBarBackend::goBackward()
|
||||
{
|
||||
QTC_ASSERT(designModeWidget(), return );
|
||||
designModeWidget()->toolBarOnGoBackClicked();
|
||||
}
|
||||
|
||||
void ToolBarBackend::openFileByIndex(int i)
|
||||
{
|
||||
auto fileName = Core::DocumentModel::entries().at(i)->fileName();
|
||||
|
||||
Core::EditorManager::openEditor(fileName, Utils::Id(), Core::EditorManager::DoNotMakeVisible);
|
||||
}
|
||||
|
||||
void ToolBarBackend::closeCurrentDocument()
|
||||
{
|
||||
Core::EditorManager::slotCloseCurrentEditorOrDocument();
|
||||
}
|
||||
|
||||
void ToolBarBackend::shareApplicationOnline()
|
||||
{
|
||||
auto command = Core::ActionManager::command("QmlProject.ShareDesign");
|
||||
if (command)
|
||||
command->action()->trigger();
|
||||
}
|
||||
|
||||
void ToolBarBackend::setCurrentWorkspace(const QString &workspace)
|
||||
{
|
||||
designModeWidget()->dockManager()->openWorkspace(workspace);
|
||||
}
|
||||
|
||||
void ToolBarBackend::editGlobalAnnoation()
|
||||
{
|
||||
ModelNode node = currentDesignDocument()->rewriterView()->rootModelNode();
|
||||
|
||||
if (node.isValid()) {
|
||||
designModeWidget()->globalAnnotationEditor().setModelNode(node);
|
||||
designModeWidget()->globalAnnotationEditor().showWidget();
|
||||
}
|
||||
}
|
||||
|
||||
bool ToolBarBackend::canGoBack() const
|
||||
{
|
||||
QTC_ASSERT(designModeWidget(), return false);
|
||||
return designModeWidget()->canGoBack();
|
||||
}
|
||||
|
||||
bool ToolBarBackend::canGoForward() const
|
||||
{
|
||||
QTC_ASSERT(designModeWidget(), return false);
|
||||
return designModeWidget()->canGoForward();
|
||||
}
|
||||
|
||||
ToolBarBackend::ToolBarBackend(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
ActionAddedInterface callback = [this](ActionInterface *interface) {
|
||||
if (interface->menuId() == "PreviewZoom")
|
||||
m_zoomAction = interface;
|
||||
};
|
||||
|
||||
QmlDesignerPlugin::instance()->viewManager().designerActionManager().addAddActionCallback(callback);
|
||||
|
||||
connect(designModeWidget(),
|
||||
&Internal::DesignModeWidget::navigationHistoryChanged,
|
||||
this,
|
||||
&ToolBarBackend::navigationHistoryChanged);
|
||||
|
||||
connect(Core::DocumentModel::model(),
|
||||
&QAbstractItemModel::rowsInserted,
|
||||
this,
|
||||
&ToolBarBackend::updateDocumentModel);
|
||||
connect(Core::DocumentModel::model(),
|
||||
&QAbstractItemModel::rowsRemoved,
|
||||
this,
|
||||
&ToolBarBackend::updateDocumentModel);
|
||||
connect(Core::DocumentModel::model(),
|
||||
&QAbstractItemModel::dataChanged,
|
||||
this,
|
||||
&ToolBarBackend::updateDocumentModel);
|
||||
connect(Core::DocumentModel::model(),
|
||||
&QAbstractItemModel::modelReset,
|
||||
this,
|
||||
&ToolBarBackend::updateDocumentModel);
|
||||
|
||||
connect(Core::EditorManager::instance(),
|
||||
&Core::EditorManager::currentEditorChanged,
|
||||
this,
|
||||
&ToolBarBackend::documentIndexChanged);
|
||||
|
||||
connect(designModeWidget(), &Internal::DesignModeWidget::initialized, this, [this]() {
|
||||
const auto dockManager = designModeWidget()->dockManager();
|
||||
|
||||
connect(dockManager,
|
||||
&ADS::DockManager::workspaceListChanged,
|
||||
this,
|
||||
&ToolBarBackend::setupWorkspaces);
|
||||
connect(dockManager, &ADS::DockManager::workspaceLoaded, this, [this](const QString &) {
|
||||
emit currentWorkspaceChanged();
|
||||
});
|
||||
|
||||
setupWorkspaces();
|
||||
});
|
||||
|
||||
auto editorManager = Core::EditorManager::instance();
|
||||
|
||||
connect(editorManager, &Core::EditorManager::documentClosed, this, [this]() {
|
||||
if (isInDesignMode() && Core::DocumentModel::entryCount() == 0) {
|
||||
QTimer::singleShot(0, []() { /* The mode change has to happen from event loop.
|
||||
Otherwise we and up in an invalid state */
|
||||
Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
connect(Core::ICore::instance(), &Core::ICore::coreAboutToOpen, this, [this] {
|
||||
connect(Core::DesignMode::instance(), &Core::DesignMode::enabledStateChanged, this, [this] {
|
||||
emit isDesignModeEnabledChanged();
|
||||
});
|
||||
});
|
||||
|
||||
connect(Core::ModeManager::instance(), &Core::ModeManager::currentModeChanged, this, [this]() {
|
||||
emit isInDesignModeChanged();
|
||||
});
|
||||
}
|
||||
|
||||
void ToolBarBackend::registerDeclarativeType()
|
||||
{
|
||||
qmlRegisterType<ToolBarBackend>("ToolBar", 1, 0, "ToolBarBackend");
|
||||
qmlRegisterType<ActionSubscriber>("ToolBar", 1, 0, "ActionSubscriber");
|
||||
qmlRegisterType<CrumbleBarModel>("ToolBar", 1, 0, "CrumbleBarModel");
|
||||
}
|
||||
|
||||
QStringList ToolBarBackend::documentModel() const
|
||||
{
|
||||
return m_openDocuments;
|
||||
}
|
||||
|
||||
void ToolBarBackend::updateDocumentModel()
|
||||
{
|
||||
m_openDocuments.clear();
|
||||
for (auto &entry : Core::DocumentModel::entries())
|
||||
m_openDocuments.append(entry->displayName());
|
||||
|
||||
emit openDocumentsChanged();
|
||||
}
|
||||
|
||||
int ToolBarBackend::documentIndex() const
|
||||
{
|
||||
if (Core::EditorManager::currentDocument())
|
||||
return Core::DocumentModel::indexOfDocument(Core::EditorManager::currentDocument()).value();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString ToolBarBackend::currentWorkspace() const
|
||||
{
|
||||
return designModeWidget()->dockManager()->activeWorkspace();
|
||||
}
|
||||
|
||||
QStringList ToolBarBackend::workspaces() const
|
||||
{
|
||||
return m_workspaces;
|
||||
}
|
||||
|
||||
bool ToolBarBackend::isInDesignMode() const
|
||||
{
|
||||
if (!Core::ModeManager::instance())
|
||||
return false;
|
||||
|
||||
return Core::ModeManager::currentModeId() == Core::Constants::MODE_DESIGN;
|
||||
}
|
||||
|
||||
bool ToolBarBackend::isDesignModeEnabled() const
|
||||
{
|
||||
if (Core::DesignMode::instance())
|
||||
return Core::DesignMode::instance()->isEnabled() || getMainUiFile().exists();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToolBarBackend::setupWorkspaces()
|
||||
{
|
||||
m_workspaces.clear();
|
||||
m_workspaces = designModeWidget()->dockManager()->workspaces();
|
||||
Utils::sort(m_workspaces);
|
||||
emit workspacesChanged();
|
||||
}
|
||||
|
||||
ActionSubscriber::ActionSubscriber(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
ActionAddedInterface callback = [this](ActionInterface *interface) {
|
||||
if (interface->menuId() == m_actionId.toLatin1()) {
|
||||
m_interface = interface;
|
||||
setupNotifier();
|
||||
}
|
||||
};
|
||||
|
||||
QmlDesignerPlugin::instance()->viewManager().designerActionManager().addAddActionCallback(callback);
|
||||
}
|
||||
|
||||
void ActionSubscriber::trigger()
|
||||
{
|
||||
if (m_interface)
|
||||
m_interface->action()->trigger();
|
||||
}
|
||||
|
||||
bool ActionSubscriber::available() const
|
||||
{
|
||||
if (m_interface)
|
||||
return m_interface->action()->isEnabled();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ActionSubscriber::checked() const
|
||||
{
|
||||
if (m_interface)
|
||||
return m_interface->action()->isChecked();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ActionSubscriber::actionId() const
|
||||
{
|
||||
return m_actionId;
|
||||
}
|
||||
|
||||
void ActionSubscriber::setActionId(const QString &id)
|
||||
{
|
||||
if (id == m_actionId)
|
||||
return;
|
||||
|
||||
m_actionId = id;
|
||||
emit actionIdChanged();
|
||||
emit tooltipChanged();
|
||||
}
|
||||
|
||||
QString ActionSubscriber::tooltip() const
|
||||
{
|
||||
if (m_interface)
|
||||
return m_interface->action()->text();
|
||||
return {};
|
||||
}
|
||||
|
||||
void ActionSubscriber::setupNotifier()
|
||||
{
|
||||
if (!m_interface)
|
||||
return;
|
||||
|
||||
connect(m_interface->action(), &QAction::enabledChanged, this, &ActionSubscriber::availableChanged);
|
||||
|
||||
emit tooltipChanged();
|
||||
}
|
||||
|
||||
CrumbleBarModel::CrumbleBarModel(QObject *)
|
||||
{
|
||||
connect(crumbleBar(), &CrumbleBar::pathChanged, this, &CrumbleBarModel::handleCrumblePathChanged);
|
||||
}
|
||||
|
||||
int CrumbleBarModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return crumbleBar()->path().count();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> CrumbleBarModel::roleNames() const
|
||||
{
|
||||
static QHash<int, QByteArray> roleNames{{Qt::UserRole + 1, "fileName"},
|
||||
{Qt::UserRole + 2, "fileAddress"}};
|
||||
|
||||
return roleNames;
|
||||
}
|
||||
|
||||
QVariant CrumbleBarModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.isValid() && index.row() < rowCount()) {
|
||||
auto info = crumbleBar()->infos().at(index.row());
|
||||
|
||||
if (role == Qt::UserRole + 1) {
|
||||
return info.displayName;
|
||||
} else if (role == Qt::UserRole + 2) {
|
||||
return info.fileName.displayName();
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "invalid role";
|
||||
}
|
||||
} else {
|
||||
qWarning() << Q_FUNC_INFO << "invalid index";
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void CrumbleBarModel::handleCrumblePathChanged()
|
||||
{
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void CrumbleBarModel::onCrumblePathElementClicked(int i)
|
||||
{
|
||||
if (i < rowCount()) {
|
||||
auto info = crumbleBar()->infos().at(i);
|
||||
crumbleBar()->onCrumblePathElementClicked(QVariant::fromValue(info));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
129
src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
Normal file
129
src/plugins/qmldesigner/components/toolbar/toolbarbackend.h
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class ActionInterface;
|
||||
|
||||
class CrumbleBarModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CrumbleBarModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void handleCrumblePathChanged();
|
||||
|
||||
Q_INVOKABLE void onCrumblePathElementClicked(int i);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class ActionSubscriber : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ActionSubscriber(QObject *parent = nullptr);
|
||||
|
||||
Q_PROPERTY(QString actionId READ actionId WRITE setActionId NOTIFY actionIdChanged)
|
||||
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
|
||||
Q_PROPERTY(bool checked READ checked NOTIFY checkedChanged)
|
||||
Q_PROPERTY(QString tooltip READ tooltip NOTIFY tooltipChanged)
|
||||
|
||||
Q_INVOKABLE void trigger();
|
||||
|
||||
bool available() const;
|
||||
bool checked() const;
|
||||
|
||||
QString actionId() const;
|
||||
void setActionId(const QString &id);
|
||||
|
||||
QString tooltip() const;
|
||||
|
||||
signals:
|
||||
void actionIdChanged();
|
||||
void availableChanged();
|
||||
void checkedChanged();
|
||||
void tooltipChanged();
|
||||
|
||||
private:
|
||||
void setupNotifier();
|
||||
|
||||
ActionInterface *m_interface = nullptr;
|
||||
QString m_actionId;
|
||||
};
|
||||
|
||||
class ToolBarBackend : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY navigationHistoryChanged)
|
||||
Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY navigationHistoryChanged)
|
||||
Q_PROPERTY(QStringList documentModel READ documentModel NOTIFY openDocumentsChanged)
|
||||
Q_PROPERTY(int documentIndex READ documentIndex NOTIFY documentIndexChanged)
|
||||
Q_PROPERTY(QString currentWorkspace READ currentWorkspace NOTIFY currentWorkspaceChanged)
|
||||
Q_PROPERTY(QStringList workspaces READ workspaces NOTIFY workspacesChanged)
|
||||
Q_PROPERTY(bool isInDesignMode READ isInDesignMode NOTIFY isInDesignModeChanged)
|
||||
Q_PROPERTY(bool isDesignModeEnabled READ isDesignModeEnabled NOTIFY isDesignModeEnabledChanged)
|
||||
|
||||
public:
|
||||
ToolBarBackend(QObject *parent = nullptr);
|
||||
static void registerDeclarativeType();
|
||||
|
||||
Q_INVOKABLE void triggerModeChange();
|
||||
Q_INVOKABLE void runProject();
|
||||
Q_INVOKABLE void goForward();
|
||||
Q_INVOKABLE void goBackward();
|
||||
Q_INVOKABLE void openFileByIndex(int i);
|
||||
Q_INVOKABLE void closeCurrentDocument();
|
||||
Q_INVOKABLE void shareApplicationOnline();
|
||||
Q_INVOKABLE void setCurrentWorkspace(const QString &workspace);
|
||||
Q_INVOKABLE void editGlobalAnnoation();
|
||||
|
||||
bool canGoBack() const;
|
||||
bool canGoForward() const;
|
||||
|
||||
QStringList documentModel() const;
|
||||
|
||||
void updateDocumentModel();
|
||||
int documentIndex() const;
|
||||
|
||||
QString currentWorkspace() const;
|
||||
QStringList workspaces() const;
|
||||
|
||||
bool isInDesignMode() const;
|
||||
bool isDesignModeEnabled() const;
|
||||
|
||||
signals:
|
||||
void navigationHistoryChanged();
|
||||
void openDocumentsChanged();
|
||||
void documentIndexChanged();
|
||||
void currentWorkspaceChanged();
|
||||
void workspacesChanged();
|
||||
void isInDesignModeChanged();
|
||||
void isDesignModeEnabledChanged();
|
||||
|
||||
private:
|
||||
void setupWorkspaces();
|
||||
|
||||
ActionInterface *m_zoomAction;
|
||||
ActionInterface *editAnnotation;
|
||||
ActionInterface *goIntoComponent;
|
||||
ActionInterface *moveToComponent;
|
||||
|
||||
QStringList m_openDocuments;
|
||||
QStringList m_workspaces;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <nodeinstanceview.h>
|
||||
#include <itemlibrarywidget.h>
|
||||
#include <theme.h>
|
||||
#include <toolbar.h>
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
@@ -341,6 +342,7 @@ void DesignModeWidget::setup()
|
||||
mviews->addAction(command);
|
||||
|
||||
// Create toolbars
|
||||
if (!ToolBar::isVisible()) {
|
||||
auto toolBar = new QToolBar();
|
||||
|
||||
toolBar->addAction(viewManager().componentViewAction());
|
||||
@@ -357,40 +359,13 @@ void DesignModeWidget::setup()
|
||||
connect(m_toolBar, &Core::EditorToolBar::goForwardClicked, this, &DesignModeWidget::toolBarOnGoForwardClicked);
|
||||
connect(m_toolBar, &Core::EditorToolBar::goBackClicked, this, &DesignModeWidget::toolBarOnGoBackClicked);
|
||||
|
||||
|
||||
QToolBar* toolBarWrapper = new QToolBar();
|
||||
toolBarWrapper->addWidget(m_toolBar);
|
||||
toolBarWrapper->addWidget(createCrumbleBarFrame());
|
||||
toolBarWrapper->setMovable(false);
|
||||
addToolBar(Qt::TopToolBarArea, toolBarWrapper);
|
||||
|
||||
if (currentDesignDocument())
|
||||
setupNavigatorHistory(currentDesignDocument()->textEditor());
|
||||
|
||||
m_dockManager->initialize();
|
||||
|
||||
// Hide all floating widgets if the initial mode isn't design mode
|
||||
if (Core::ModeManager::instance()->currentModeId() != Core::Constants::MODE_DESIGN) {
|
||||
for (auto &floatingWidget : m_dockManager->floatingWidgets())
|
||||
floatingWidget->hide();
|
||||
}
|
||||
|
||||
connect(Core::ModeManager::instance(),
|
||||
&Core::ModeManager::currentModeChanged,
|
||||
this,
|
||||
[this](Utils::Id mode, Utils::Id previousMode) {
|
||||
if (mode == Core::Constants::MODE_DESIGN) {
|
||||
m_dockManager->reloadActiveWorkspace();
|
||||
m_dockManager->setModeChangeState(false);
|
||||
}
|
||||
|
||||
if (previousMode == Core::Constants::MODE_DESIGN
|
||||
&& mode != Core::Constants::MODE_DESIGN) {
|
||||
m_dockManager->save();
|
||||
m_dockManager->setModeChangeState(true);
|
||||
for (auto &floatingWidget : m_dockManager->floatingWidgets())
|
||||
floatingWidget->hide();
|
||||
}
|
||||
});
|
||||
|
||||
addSpacerToToolBar(toolBar);
|
||||
|
||||
@@ -429,6 +404,37 @@ void DesignModeWidget::setup()
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (currentDesignDocument())
|
||||
setupNavigatorHistory(currentDesignDocument()->textEditor());
|
||||
|
||||
m_dockManager->initialize();
|
||||
|
||||
// Hide all floating widgets if the initial mode isn't design mode
|
||||
if (Core::ModeManager::instance()->currentModeId() != Core::Constants::MODE_DESIGN) {
|
||||
for (auto &floatingWidget : m_dockManager->floatingWidgets())
|
||||
floatingWidget->hide();
|
||||
}
|
||||
|
||||
connect(Core::ModeManager::instance(),
|
||||
&Core::ModeManager::currentModeChanged,
|
||||
this,
|
||||
[this](Utils::Id mode, Utils::Id previousMode) {
|
||||
if (mode == Core::Constants::MODE_DESIGN) {
|
||||
m_dockManager->reloadActiveWorkspace();
|
||||
m_dockManager->setModeChangeState(false);
|
||||
}
|
||||
|
||||
if (previousMode == Core::Constants::MODE_DESIGN
|
||||
&& mode != Core::Constants::MODE_DESIGN) {
|
||||
m_dockManager->save();
|
||||
m_dockManager->setModeChangeState(true);
|
||||
for (auto &floatingWidget : m_dockManager->floatingWidgets())
|
||||
floatingWidget->hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
viewManager().enableWidgets();
|
||||
@@ -500,6 +506,26 @@ void DesignModeWidget::toolBarOnGoForwardClicked()
|
||||
}
|
||||
}
|
||||
|
||||
bool DesignModeWidget::canGoForward()
|
||||
{
|
||||
return m_canGoForward;
|
||||
}
|
||||
|
||||
bool DesignModeWidget::canGoBack()
|
||||
{
|
||||
return m_canGoBack;
|
||||
}
|
||||
|
||||
ADS::DockManager *DesignModeWidget::dockManager() const
|
||||
{
|
||||
return m_dockManager;
|
||||
}
|
||||
|
||||
GlobalAnnotationEditor &DesignModeWidget::globalAnnotationEditor()
|
||||
{
|
||||
return m_globalAnnotationEditor;
|
||||
}
|
||||
|
||||
DesignDocument *DesignModeWidget::currentDesignDocument() const
|
||||
{
|
||||
return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument();
|
||||
@@ -515,11 +541,14 @@ void DesignModeWidget::setupNavigatorHistory(Core::IEditor *editor)
|
||||
if (!m_keepNavigatorHistory)
|
||||
addNavigatorHistoryEntry(editor->document()->filePath());
|
||||
|
||||
const bool canGoBack = m_navigatorHistoryCounter > 0;
|
||||
const bool canGoForward = m_navigatorHistoryCounter < (m_navigatorHistory.size() - 1);
|
||||
m_toolBar->setCanGoBack(canGoBack);
|
||||
m_toolBar->setCanGoForward(canGoForward);
|
||||
m_canGoBack = m_navigatorHistoryCounter > 0;
|
||||
m_canGoForward = m_navigatorHistoryCounter < (m_navigatorHistory.size() - 1);
|
||||
m_toolBar->setCanGoBack(m_canGoBack);
|
||||
m_toolBar->setCanGoForward(m_canGoForward);
|
||||
if (!ToolBar::isVisible())
|
||||
m_toolBar->setCurrentEditor(editor);
|
||||
|
||||
emit navigationHistoryChanged();
|
||||
}
|
||||
|
||||
void DesignModeWidget::addNavigatorHistoryEntry(const Utils::FilePath &fileName)
|
||||
@@ -576,6 +605,8 @@ void DesignModeWidget::initialize()
|
||||
}
|
||||
|
||||
m_initStatus = Initialized;
|
||||
|
||||
emit initialized();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -64,12 +64,23 @@ public:
|
||||
|
||||
static QWidget *createProjectExplorerWidget(QWidget *parent);
|
||||
|
||||
private:
|
||||
enum InitializeStatus { NotInitialized, Initializing, Initialized };
|
||||
|
||||
void toolBarOnGoBackClicked();
|
||||
void toolBarOnGoForwardClicked();
|
||||
|
||||
bool canGoForward();
|
||||
bool canGoBack();
|
||||
|
||||
ADS::DockManager *dockManager() const;
|
||||
|
||||
GlobalAnnotationEditor &globalAnnotationEditor();
|
||||
|
||||
signals:
|
||||
void navigationHistoryChanged();
|
||||
void initialized();
|
||||
|
||||
private:
|
||||
enum InitializeStatus { NotInitialized, Initializing, Initialized };
|
||||
|
||||
void setup();
|
||||
bool isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const;
|
||||
QmlDesigner::ModelNode nodeForPosition(int cursorPos) const;
|
||||
@@ -96,6 +107,9 @@ private:
|
||||
ADS::DockManager *m_dockManager = nullptr;
|
||||
ADS::DockWidget *m_outputPaneDockWidget = nullptr;
|
||||
GlobalAnnotationEditor m_globalAnnotationEditor;
|
||||
|
||||
bool m_canGoForward = false;
|
||||
bool m_canGoBack = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "qmldesignerprojectmanager.h"
|
||||
#include "quick2propertyeditorview.h"
|
||||
#include "settingspage.h"
|
||||
#include <toolbar.h>
|
||||
|
||||
#include <colortool/colortool.h>
|
||||
#include <connectionview.h>
|
||||
@@ -92,7 +93,7 @@ public:
|
||||
return {"QmlDesigner.Wizards.Enterprise"};
|
||||
}
|
||||
QSet<Utils::Id> availablePlatforms() const override { return {}; }
|
||||
QString displayNameForPlatform(Utils::Id id) const override { return {}; }
|
||||
QString displayNameForPlatform(Utils::Id) const override { return {}; }
|
||||
};
|
||||
|
||||
QString normalizeIdentifier(const QString &string)
|
||||
@@ -270,6 +271,11 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
|
||||
Core::AsynchronousMessageBox::warning(composedTitle, description.toString());
|
||||
});
|
||||
|
||||
if (QmlProjectManager::QmlProject::isQtDesignStudio()) {
|
||||
ToolBar::create();
|
||||
ToolBar::createStatusBar();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ QByteArray ZoomPreviewAction::category() const
|
||||
|
||||
QByteArray ZoomPreviewAction::menuId() const
|
||||
{
|
||||
return QByteArray();
|
||||
return "PreviewZoom";
|
||||
}
|
||||
|
||||
int ZoomPreviewAction::priority() const
|
||||
|
||||
Reference in New Issue
Block a user