QmlDesigner: Use a vertical scrollbar for "Confirm Delete Files"

Also, replaced the widgets code with QML.

Task-number: QDS-8033
Change-Id: I29f4e0bc02294e839e352096c3d4394a764cfe76
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Samuel Ghinet
2022-10-31 15:24:30 +02:00
parent 6747e666b9
commit afc7cd2c98
4 changed files with 148 additions and 35 deletions

View File

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

View File

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

View File

@@ -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<int> &roles)
[[maybe_unused]] const QList<int> &roles)
{
for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
QModelIndex index = m_sourceFsModel->index(i, 0, topLeft.parent());
@@ -94,43 +95,34 @@ QList<QModelIndex> 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));
}
}
}

View File

@@ -38,7 +38,9 @@ public:
Q_INVOKABLE QList<QModelIndex> 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);