forked from qt-creator/qt-creator
QmlDesigner: Fix deleting collections using the keyboard delete key
Fixes: QDS-11735 Change-Id: I188856918da6d478e16383017d808205ee20ee8c Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
committed by
Ali Kianian
parent
e79cab5d99
commit
23e8be1ef4
@@ -98,7 +98,7 @@ Item {
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton | Qt.LeftButton
|
||||
onClicked: contextMenuRequested()
|
||||
onClicked: root.contextMenuRequested()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,10 @@ ListView {
|
||||
renameDialog.reject()
|
||||
}
|
||||
|
||||
function deleteCurrentCollection() {
|
||||
deleteDialog.open()
|
||||
}
|
||||
|
||||
delegate: CollectionItem {
|
||||
implicitWidth: root.width
|
||||
onDeleteItem: root.model.removeRow(index)
|
||||
@@ -36,6 +40,10 @@ ListView {
|
||||
readonly property bool selected: item ? item.isSelected : false
|
||||
readonly property int index: item ? item.id : -1
|
||||
|
||||
function updateItem() {
|
||||
currentCollection.item = collectionMenu.clickedItem ?? root.itemAtIndex(root.model.selectedIndex)
|
||||
}
|
||||
|
||||
function rename(newName) {
|
||||
if (item)
|
||||
item.rename(newName)
|
||||
@@ -54,145 +62,56 @@ ListView {
|
||||
StudioControls.Menu {
|
||||
id: collectionMenu
|
||||
|
||||
property CollectionItem clickedItem
|
||||
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
enabled: root.count
|
||||
|
||||
function openMenu(item) {
|
||||
currentCollection.item = item
|
||||
popup()
|
||||
collectionMenu.clickedItem = item
|
||||
currentCollection.updateItem()
|
||||
collectionMenu.popup()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
onClosed: collectionMenu.clickedItem = null
|
||||
|
||||
Action {
|
||||
id: menuDeleteAction
|
||||
|
||||
text: qsTr("Delete")
|
||||
shortcut: StandardKey.Delete
|
||||
onTriggered: deleteDialog.open()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
Action {
|
||||
id: menuRenameAction
|
||||
|
||||
text: qsTr("Rename")
|
||||
shortcut: StandardKey.Replace
|
||||
onTriggered: renameDialog.open()
|
||||
}
|
||||
|
||||
StudioControls.MenuItem {
|
||||
Action {
|
||||
id: menuAssignAction
|
||||
|
||||
text: qsTr("Assign to the selected node")
|
||||
enabled: CollectionEditorBackend.rootView.targetNodeSelected
|
||||
onTriggered: rootView.assignCollectionToSelectedNode(currentCollection.name)
|
||||
}
|
||||
}
|
||||
|
||||
StudioControls.Dialog {
|
||||
ConfirmDeleteCollectionDialog {
|
||||
id: deleteDialog
|
||||
|
||||
title: qsTr("Deleting the model")
|
||||
clip: true
|
||||
|
||||
collectionName: currentCollection.name
|
||||
onAboutToShow: currentCollection.updateItem()
|
||||
onAccepted: currentCollection.deleteItem()
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: deleteDialogContent // Keep the id here even if it's not used, because the dialog might lose implicitSize
|
||||
|
||||
width: 300
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
text: qsTr("Are you sure that you want to delete model \"%1\"?"
|
||||
+ "\nThe model will be deleted permanently.").arg(currentCollection.name)
|
||||
|
||||
}
|
||||
|
||||
Spacer {}
|
||||
|
||||
RowLayout {
|
||||
spacing: StudioTheme.Values.sectionRowSpacing
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Delete")
|
||||
onClicked: deleteDialog.accept()
|
||||
}
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: deleteDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StudioControls.Dialog {
|
||||
RenameCollectionDialog {
|
||||
id: renameDialog
|
||||
|
||||
title: qsTr("Rename model")
|
||||
|
||||
onAccepted: {
|
||||
if (newNameField.text !== "")
|
||||
currentCollection.rename(newNameField.text)
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
newNameField.text = currentCollection.name
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: qsTr("Previous name: " + currentCollection.name)
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
}
|
||||
|
||||
Spacer {}
|
||||
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
text: qsTr("New name:")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
}
|
||||
|
||||
StudioControls.TextField {
|
||||
id: newNameField
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
actionIndicator.visible: false
|
||||
translationIndicator.visible: false
|
||||
validator: newNameValidator
|
||||
|
||||
Keys.onEnterPressed: renameDialog.accept()
|
||||
Keys.onReturnPressed: renameDialog.accept()
|
||||
Keys.onEscapePressed: renameDialog.reject()
|
||||
|
||||
onTextChanged: {
|
||||
btnRename.enabled = newNameField.text !== ""
|
||||
}
|
||||
}
|
||||
|
||||
Spacer {}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
spacing: StudioTheme.Values.sectionRowSpacing
|
||||
|
||||
HelperWidgets.Button {
|
||||
id: btnRename
|
||||
|
||||
text: qsTr("Rename")
|
||||
onClicked: renameDialog.accept()
|
||||
}
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: renameDialog.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
collectionName: currentCollection.name
|
||||
onAboutToShow: currentCollection.updateItem()
|
||||
onAccepted: currentCollection.rename(renameDialog.newCollectionName)
|
||||
}
|
||||
|
||||
Connections {
|
||||
@@ -202,14 +121,4 @@ ListView {
|
||||
root.closeDialogs()
|
||||
}
|
||||
}
|
||||
|
||||
RegularExpressionValidator {
|
||||
id: newNameValidator
|
||||
regularExpression: /^\w+$/
|
||||
}
|
||||
|
||||
component Spacer: Item {
|
||||
implicitWidth: 1
|
||||
implicitHeight: StudioTheme.Values.columnGap
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ Item {
|
||||
|
||||
// called from C++ when using the delete key
|
||||
function deleteSelectedCollection() {
|
||||
print("TODO: deleteSelectedCollection")
|
||||
collectionListView.deleteCurrentCollection()
|
||||
}
|
||||
|
||||
function closeDialogs() {
|
||||
|
@@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import HelperWidgets 2.0 as HelperWidgets
|
||||
import StudioControls 1.0 as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
StudioControls.Dialog {
|
||||
id: root
|
||||
|
||||
required property string collectionName
|
||||
|
||||
title: qsTr("Deleting the model")
|
||||
clip: true
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: deleteDialogContent // Keep the id here even if it's not used, because the dialog might lose implicitSize
|
||||
|
||||
width: 300
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
text: qsTr("Are you sure that you want to delete model \"%1\"?"
|
||||
+ "\nThe model will be deleted permanently.").arg(root.collectionName)
|
||||
|
||||
}
|
||||
|
||||
Item { // spacer
|
||||
implicitWidth: 1
|
||||
implicitHeight: StudioTheme.Values.columnGap
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: StudioTheme.Values.sectionRowSpacing
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Delete")
|
||||
onClicked: root.accept()
|
||||
}
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: root.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import HelperWidgets 2.0 as HelperWidgets
|
||||
import StudioControls 1.0 as StudioControls
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
StudioControls.Dialog {
|
||||
id: root
|
||||
|
||||
required property string collectionName
|
||||
readonly property alias newCollectionName: newNameField.text
|
||||
readonly property bool isValid: newNameField.text !== ""
|
||||
|
||||
title: qsTr("Rename model")
|
||||
|
||||
onOpened: {
|
||||
newNameField.text = root.collectionName
|
||||
newNameField.forceActiveFocus()
|
||||
}
|
||||
|
||||
function acceptIfVerified() {
|
||||
if (root.isValid)
|
||||
root.accept()
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: renameDialogContent
|
||||
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
text: qsTr("Previous name: " + root.collectionName)
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
}
|
||||
|
||||
Spacer {}
|
||||
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
text: qsTr("New name:")
|
||||
color: StudioTheme.Values.themeTextColor
|
||||
}
|
||||
|
||||
StudioControls.TextField {
|
||||
id: newNameField
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
actionIndicator.visible: false
|
||||
translationIndicator.visible: false
|
||||
validator: RegularExpressionValidator {
|
||||
regularExpression: /^\w+$/
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: root.acceptIfVerified()
|
||||
Keys.onReturnPressed: root.acceptIfVerified()
|
||||
Keys.onEscapePressed: root.reject()
|
||||
}
|
||||
|
||||
Spacer {}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
spacing: StudioTheme.Values.sectionRowSpacing
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Rename")
|
||||
enabled: root.isValid
|
||||
onClicked: root.acceptIfVerified()
|
||||
}
|
||||
|
||||
HelperWidgets.Button {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: root.reject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Spacer: Item {
|
||||
implicitWidth: 1
|
||||
implicitHeight: StudioTheme.Values.columnGap
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@ import StudioTheme 1.0 as StudioTheme
|
||||
T.MenuItem {
|
||||
id: control
|
||||
|
||||
property alias shortcut: itemAction.shortcut
|
||||
property alias shortcut: shortcutObserver.shortcutWorkaround
|
||||
|
||||
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
|
||||
|
||||
@@ -24,9 +24,6 @@ T.MenuItem {
|
||||
padding: 0
|
||||
spacing: 0
|
||||
horizontalPadding: control.style.contextMenuHorizontalPadding
|
||||
action: Action {
|
||||
id: itemAction
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
Text {
|
||||
@@ -41,16 +38,23 @@ T.MenuItem {
|
||||
|
||||
Text {
|
||||
id: shortcutLabel
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: shortcutObserver.nativeText
|
||||
? shortcutObserver.nativeText
|
||||
: control.action
|
||||
? control.action.fakeShortcut ? control.action.fakeShortcut : ""
|
||||
: ""
|
||||
font: control.font
|
||||
color: textLabel.color
|
||||
|
||||
Shortcut {
|
||||
id: shortcutObserver
|
||||
property int shortcutWorkaround: control.shortcut ?? 0
|
||||
|
||||
property int shortcutWorkaround: 0
|
||||
sequence: shortcutObserver.shortcutWorkaround
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ QString getPreferredCollectionName(const QUrl &url, const QString &collectionNam
|
||||
} // namespace
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
CollectionWidget::CollectionWidget(CollectionView *view)
|
||||
: m_view(view)
|
||||
, m_listModel(new CollectionListModel)
|
||||
@@ -62,11 +63,11 @@ CollectionWidget::CollectionWidget(CollectionView *view)
|
||||
{
|
||||
setWindowTitle(tr("Model Editor", "Title of model editor widget"));
|
||||
|
||||
Core::IContext *icontext = nullptr;
|
||||
Core::Context context(Constants::C_QMLCOLLECTIONEDITOR);
|
||||
icontext = new Core::IContext(this);
|
||||
icontext->setContext(context);
|
||||
icontext->setWidget(this);
|
||||
m_iContext = new Core::IContext(this);
|
||||
m_iContext->setContext(context);
|
||||
m_iContext->setWidget(this);
|
||||
Core::ICore::addContextObject(m_iContext);
|
||||
|
||||
connect(m_listModel, &CollectionListModel::warning, this, &CollectionWidget::warn);
|
||||
|
||||
|
@@ -71,6 +71,7 @@ private:
|
||||
QPointer<CollectionView> m_view;
|
||||
QPointer<CollectionListModel> m_listModel;
|
||||
QPointer<CollectionDetailsModel> m_collectionDetailsModel;
|
||||
QPointer<Core::IContext> m_iContext;
|
||||
std::unique_ptr<CollectionDetailsSortFilterModel> m_collectionDetailsSortFilterModel;
|
||||
QScopedPointer<StudioQuickWidget> m_quickWidget;
|
||||
bool m_targetNodeSelected = false;
|
||||
|
Reference in New Issue
Block a user