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:
Mahmoud Badri
2024-02-20 14:07:44 +02:00
committed by Ali Kianian
parent e79cab5d99
commit 23e8be1ef4
8 changed files with 194 additions and 134 deletions

View File

@@ -98,7 +98,7 @@ Item {
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton | Qt.LeftButton
onClicked: contextMenuRequested()
onClicked: root.contextMenuRequested()
}
}
}

View File

@@ -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
}
}

View File

@@ -25,7 +25,7 @@ Item {
// called from C++ when using the delete key
function deleteSelectedCollection() {
print("TODO: deleteSelectedCollection")
collectionListView.deleteCurrentCollection()
}
function closeDialogs() {

View File

@@ -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()
}
}
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}
}

View File

@@ -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);

View File

@@ -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;