diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml index 84a689184c1..7d09f49f526 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml @@ -87,7 +87,19 @@ StudioControls.Menu { text: qsTr("Delete File") visible: root._fileIndex height: deleteFileItem.visible ? deleteFileItem.implicitHeight : 0 - onTriggered: assetsModel.deleteFiles(root._selectedAssetPathsList) + onTriggered: { + let deleted = assetsModel.requestDeleteFiles(root._selectedAssetPathsList) + if (!deleted) + confirmDeleteFiles.open() + } + + ConfirmDeleteFilesDialog { + id: confirmDeleteFiles + parent: root.assetsView + files: root._selectedAssetPathsList + + onAccepted: root.assetsView.selectedAssets = {} + } } StudioControls.MenuSeparator { diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/ConfirmDeleteFilesDialog.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ConfirmDeleteFilesDialog.qml new file mode 100644 index 00000000000..57253864eba --- /dev/null +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/ConfirmDeleteFilesDialog.qml @@ -0,0 +1,107 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +import QtQuick +import QtQuick.Controls +import HelperWidgets as HelperWidgets +import StudioTheme as StudioTheme +import StudioControls as StudioControls + +Dialog { + id: root + title: qsTr("Confirm Delete Files") + anchors.centerIn: parent + closePolicy: Popup.CloseOnEscape + implicitWidth: 350 + modal: true + + required property var files + + contentItem: Column { + spacing: 20 + width: parent.width + + Text { + id: confirmDeleteText + + text: root.files && root.files.length + ? qsTr("Some files might be in use. Delete anyway?") + : "" + color: StudioTheme.Values.themeTextColor + wrapMode: Text.WordWrap + width: root.width + leftPadding: 10 + rightPadding: 10 + + Keys.onEnterPressed: btnDelete.onClicked() + Keys.onReturnPressed: btnDelete.onClicked() + } + + Loader { + id: fileListLoader + sourceComponent: null + width: parent.width - 20 + x: 10 + height: 50 + } + + StudioControls.CheckBox { + id: dontAskAgain + text: qsTr("Do not ask this again") + actionIndicatorVisible: false + width: parent.width + x: 10 + } + + Row { + anchors.right: parent.right + + HelperWidgets.Button { + id: btnDelete + + text: qsTr("Delete") + onClicked: { + assetsModel.deleteFiles(root.files, dontAskAgain.checked) + root.accept() + } + } + + HelperWidgets.Button { + text: qsTr("Cancel") + onClicked: root.reject() + } + } + } + + onOpened: { + fileListLoader.sourceComponent = null + fileListLoader.sourceComponent = fileListComponent + + confirmDeleteText.forceActiveFocus() + } + + onClosed: fileListLoader.sourceComponent = null + + Component { + id: fileListComponent + + ListView { + id: filesListView + model: root.files + boundsBehavior: Flickable.StopAtBounds + clip: true + + ScrollBar.vertical: HelperWidgets.VerticalScrollBar { + id: verticalScrollBar + scrollBarVisible: filesListView.contentHeight > filesListView.height + } + + delegate: Text { + elide: Text.ElideLeft + text: model.modelData.replace(assetsModel.currentProjectDirPath(), "") + color: StudioTheme.Values.themeTextColor + width: parent.width - (verticalScrollBar.scrollBarVisible ? verticalScrollBar.width : 0) + } + } // ListView + } // Component +} diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp index d1b93448b7e..0ea4aa816f2 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp @@ -36,9 +36,10 @@ void AssetsLibraryModel::createBackendModel() QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this, &AssetsLibraryModel::directoryLoaded); QObject::connect(m_sourceFsModel, &QFileSystemModel::dataChanged, this, &AssetsLibraryModel::onDataChanged); - QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this, [this](const QString &dir) { - syncHaveFiles(); - }); + QObject::connect(m_sourceFsModel, &QFileSystemModel::directoryLoaded, this, + [this]([[maybe_unused]] const QString &dir) { + syncHaveFiles(); + }); } bool AssetsLibraryModel::isEffectQmlExist(const QString &effectName) @@ -49,7 +50,7 @@ bool AssetsLibraryModel::isEffectQmlExist(const QString &effectName) } void AssetsLibraryModel::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, - const QList &roles) + [[maybe_unused]] const QList &roles) { for (int i = topLeft.row(); i <= bottomRight.row(); ++i) { QModelIndex index = m_sourceFsModel->index(i, 0, topLeft.parent()); @@ -94,43 +95,34 @@ QList AssetsLibraryModel::parentIndices(const QModelIndex &index) c return result; } -void AssetsLibraryModel::deleteFiles(const QStringList &filePaths) +QString AssetsLibraryModel::currentProjectDirPath() const +{ + return DocumentManager::currentProjectDirPath().toString().append('/'); +} + +bool AssetsLibraryModel::requestDeleteFiles(const QStringList &filePaths) { bool askBeforeDelete = QmlDesignerPlugin::settings() .value(DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET) .toBool(); - bool assetDelete = true; - if (askBeforeDelete) { - QMessageBox msg(QMessageBox::Question, tr("Confirm Delete File"), - tr("File%1 might be in use. Delete anyway?\n\n%2") - .arg(filePaths.size() > 1 ? QChar('s') : QChar()) - .arg(filePaths.join('\n').remove(DocumentManager::currentProjectDirPath() - .toString().append('/'))), - QMessageBox::No | QMessageBox::Yes); - QCheckBox cb; - cb.setText(tr("Do not ask this again")); - msg.setCheckBox(&cb); - int ret = msg.exec(); + if (askBeforeDelete) + return false; - if (ret == QMessageBox::No) - assetDelete = false; + deleteFiles(filePaths, false); + return true; +} - if (cb.isChecked()) - QmlDesignerPlugin::settings().insert(DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, false); - } +void AssetsLibraryModel::deleteFiles(const QStringList &filePaths, bool dontAskAgain) +{ + if (dontAskAgain) + QmlDesignerPlugin::settings().insert(DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, false); - if (assetDelete) { - for (const QString &filePath : filePaths) { - if (!QFile::exists(filePath)) { - QMessageBox::warning(Core::ICore::dialogParent(), - tr("Failed to Locate File"), - tr("Could not find \"%1\".").arg(filePath)); - } else if (!QFile::remove(filePath)) { - QMessageBox::warning(Core::ICore::dialogParent(), - tr("Failed to Delete File"), - tr("Could not delete \"%1\".").arg(filePath)); - } + for (const QString &filePath : filePaths) { + if (QFile::exists(filePath) && !QFile::remove(filePath)) { + QMessageBox::warning(Core::ICore::dialogParent(), + tr("Failed to Delete File"), + tr("Could not delete \"%1\".").arg(filePath)); } } } diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h index 6e555f07e23..b4010497b51 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h @@ -38,7 +38,9 @@ public: Q_INVOKABLE QList parentIndices(const QModelIndex &index) const; Q_INVOKABLE bool indexIsValid(const QModelIndex &index) const; - Q_INVOKABLE void deleteFiles(const QStringList &filePaths); + Q_INVOKABLE QString currentProjectDirPath() const; + Q_INVOKABLE bool requestDeleteFiles(const QStringList &filePaths); + Q_INVOKABLE void deleteFiles(const QStringList &filePaths, bool dontAskAgain); Q_INVOKABLE bool renameFolder(const QString &folderPath, const QString &newName); Q_INVOKABLE bool addNewFolder(const QString &folderPath); Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex);