Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: add delete confirmation dialog #176

Merged
merged 1 commit into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/deepin-image-viewer.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@
<file>qml/Utils/FloatingNotice.qml</file>
<file>qml/Utils/ImageInputHandler.qml</file>
<file>qml/Utils/RightMenuItem.qml</file>
<file>qml/Dialog/RemoveDialog.qml</file>
</qresource>
</RCC>
3 changes: 3 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "src/imagedata/imageinfo.h"
#include "src/imagedata/imagesourcemodel.h"
#include "src/imagedata/imageprovider.h"
#include "src/utils/filetrashhelper.h"
#include "config.h"

#include <DApplication>
Expand Down Expand Up @@ -57,6 +58,8 @@ int main(int argc, char *argv[])
qmlRegisterType<ImageSourceModel>(uri.toUtf8().data(), 1, 0, "ImageSourceModel");
qmlRegisterType<MouseTrackItem>(uri.toUtf8().data(), 1, 0, "MouseTrackItem");
qmlRegisterUncreatableType<Types>(uri.toUtf8().data(), 1, 0, "Types", "Types only use for define");
// 文件回收站处理
qmlRegisterType<FileTrashHelper>(uri.toUtf8().data(), 1, 0, "FileTrashHelper");

// QML全局单例
GlobalControl control;
Expand Down
120 changes: 120 additions & 0 deletions src/qml/Dialog/RemoveDialog.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick 2.11
import QtQuick.Layouts 1.11
import org.deepin.dtk 1.0

DialogWindow {
id: dialog

property alias fileName: textMetics.text
property int nameMaxWidth: 200

// 操作结束 true: 允许删除 false: 取消
signal finished(bool ret)

flags: Qt.Window | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint
height: 180
maximumHeight: 180
maximumWidth: 400
minimumHeight: 180
minimumWidth: 400
modality: Qt.WindowModal
visible: false
width: 400

header: DialogTitleBar {
enableInWindowBlendBlur: true

// 仅保留默认状态,否则 hover 上会有变化效果
icon {
mode: DTK.NormalState
name: "user-trash-full-opened"
}
}

Component.onCompleted: {
setX(window.x + window.width / 2 - width / 2);
setY(window.y + window.height / 2 - height / 2);
show();
}
onClosing: {
finished(false);
}

ColumnLayout {
height: parent.height
width: parent.width

ColumnLayout {
Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
Layout.maximumHeight: 80
Layout.minimumHeight: 80
Layout.preferredHeight: 80

Label {
id: notifyText

property Palette textColor: Palette {
normal: ("black")
normalDark: ("white")
}

Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true
color: ColorSelector.textColor
font: DTK.fontManager.t5
horizontalAlignment: Text.AlignHCenter
text: qsTr("Cannot move \"%1\" to the trash. Do you want to permanently delete it?").arg(textMetics.elidedText)
wrapMode: Text.Wrap

TextMetrics {
id: textMetics

elide: Text.ElideMiddle
elideWidth: nameMaxWidth
font: notifyText.font
}
}

Label {
id: messageText

Layout.alignment: Qt.AlignHCenter
Layout.fillHeight: true
font: DTK.fontManager.t6
text: qsTr("This action cannot be undone")
width: dialog.width
}
}

Row {
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.fillHeight: true
spacing: 10

Button {
height: 36
text: qsTr("Cancel")
width: 185

onClicked: {
finished(false);
}
}

RecommandButton {
height: 36
text: qsTr("Confirm")
width: 185

onClicked: {
finished(true);
}
}
}
}
}
1 change: 0 additions & 1 deletion src/qml/ImageDelegate/DamagedImageDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ BaseImageDelegate {
anchors.centerIn: parent
height: 151
name: "photo_breach"
palette: DTK.makeIconPalette(parent.palette)
theme: DTK.DTK.themeType
width: 151
}
Expand Down
3 changes: 1 addition & 2 deletions src/qml/ReName.qml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ DialogWindow {
regExp: /^[^ \\.\\\\/\':\\*\\?\"<>|%&][^\\\\/\':\\*\\?\"<>|%&]*/
}

Keys.onPressed: event => {
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Return:
case Qt.Key_Enter:
Expand All @@ -117,7 +117,6 @@ DialogWindow {
Button {
id: cancelbtn

font.pixelSize: 16
height: 36
text: qsTr("Cancel")
width: 185
Expand Down
55 changes: 51 additions & 4 deletions src/qml/ThumbnailListView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import QtQuick.Layouts 1.11
import QtGraphicalEffects 1.0
import org.deepin.dtk 1.0
import org.deepin.image.viewer 1.0 as IV
import "./Dialog"

Item {
id: thumbnailView
Expand All @@ -21,11 +22,31 @@ Item {
property Image targetImage

function deleteCurrentImage() {
if (!IV.FileControl.deleteImagePath(IV.GControl.currentSource)) {
// 取消删除文件
return;
var trashFile = IV.GControl.currentSource;
if (!fileTrashHelper.fileCanTrash(trashFile)) {
// 无法移动到回收站,显示删除提示对话框
removeDialogLoader.active = true;
} else {
deleteCurrentImageImpl(false);
}
IV.GControl.removeImage(IV.GControl.currentSource);
}

// 实际移除文件操作, directDelete:是否直接删除文件而不是移动到回收站(部分文件系统不支持)
function deleteCurrentImageImpl(directDelete) {
var trashFile = IV.GControl.currentSource;
if (directDelete) {
if (!fileTrashHelper.removeFile(trashFile)) {
return;
}
} else {
// 移动文件到回收站
if (!fileTrashHelper.moveFileToTrash(trashFile)) {
return;
}
}
IV.GControl.removeImage(trashFile);

// 删除最后图片,恢复到初始界面
if (0 === IV.GControl.imageCount) {
stackView.switchOpenImage();
}
Expand All @@ -45,6 +66,32 @@ Item {
IV.GStatus.viewInteractive = true;
}

// 用于文件移动至回收站/删除的辅助类
IV.FileTrashHelper {
id: fileTrashHelper

}

// 删除确认对话框加载器
Loader {
id: removeDialogLoader

active: false
asynchronous: true

sourceComponent: RemoveDialog {
fileName: IV.FileControl.slotGetFileNameSuffix(IV.GControl.currentSource)

onFinished: {
if (ret) {
thumbnailView.deleteCurrentImageImpl(true);
}
// 使用后释放对话框
removeDialogLoader.active = false;
}
}
}

Binding {
delayed: true
property: "thumbnailVaildWidth"
Expand Down
2 changes: 1 addition & 1 deletion src/src/filecontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ FileControl::FileControl(QObject *parent)
m_ocrInterface = new OcrInterface("com.deepin.Ocr", "/com/deepin/Ocr", QDBusConnection::sessionBus(), this);
m_shortcutViewProcess = new QProcess(this);
m_config = LibConfigSetter::instance();
imageFileWatcher = new ImageFileWatcher(this);
imageFileWatcher = ImageFileWatcher::instance();

QObject::connect(imageFileWatcher, &ImageFileWatcher::imageFileChanged, this, &FileControl::imageFileChanged);

Expand Down
11 changes: 8 additions & 3 deletions src/src/imagedata/imagefilewatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@
#include <QFileSystemWatcher>

ImageFileWatcher::ImageFileWatcher(QObject *parent)
: QObject(parent)
, fileWatcher(new QFileSystemWatcher(this))
: QObject(parent), fileWatcher(new QFileSystemWatcher(this))
{
connect(fileWatcher, &QFileSystemWatcher::fileChanged, this, &ImageFileWatcher::onImageFileChanged);
connect(fileWatcher, &QFileSystemWatcher::directoryChanged, this, &ImageFileWatcher::onImageDirChanged);
}

ImageFileWatcher::~ImageFileWatcher() {}
ImageFileWatcher::~ImageFileWatcher() { }

ImageFileWatcher *ImageFileWatcher::instance()
{
static ImageFileWatcher ins;
return &ins;
}

/**
@brief 重置监控文件列表为 \a filePaths , 若监控的文件路重复,则不执行重置
Expand Down
16 changes: 10 additions & 6 deletions src/src/imagedata/imagefilewatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class ImageFileWatcher : public QObject
{
Q_OBJECT
public:
explicit ImageFileWatcher(QObject *parent = nullptr);
~ImageFileWatcher() override;
static ImageFileWatcher *instance();

void resetImageFiles(const QStringList &filePaths);
void fileRename(const QString &oldPath, const QString &newPath);
Expand All @@ -30,12 +29,17 @@ class ImageFileWatcher : public QObject
// 当处理的图片文件夹变更(新增图片等)
Q_SLOT void onImageDirChanged(const QString &dir);

explicit ImageFileWatcher(QObject *parent = nullptr);
~ImageFileWatcher() override;

private:
QHash<QString, QUrl> cacheFileInfo; ///< 缓存的图片信息,用于判断图片信息是否变更 QHash<完整路径, url信息>
QHash<QString, QUrl> removedFile; ///< 缓存被移除的文件信息(FileWatcher在文件删除/移动后将不会继续观察)
QFileSystemWatcher *fileWatcher = nullptr; ///< 文件观察类,用于提示文件变更
QHash<QString, QUrl> cacheFileInfo; ///< 缓存的图片信息,用于判断图片信息是否变更 QHash<完整路径, url信息>
QHash<QString, QUrl> removedFile; ///< 缓存被移除的文件信息(FileWatcher在文件删除/移动后将不会继续观察)
QFileSystemWatcher *fileWatcher = nullptr; ///< 文件观察类,用于提示文件变更

QString rotateImagePath;

Q_DISABLE_COPY(ImageFileWatcher)
};

#endif // IMAGEFILEWATCHER_H
#endif // IMAGEFILEWATCHER_H
Loading
Loading