diff --git a/src/deepin-image-viewer.qrc b/src/deepin-image-viewer.qrc
index bf63ea6e..0f1353e4 100644
--- a/src/deepin-image-viewer.qrc
+++ b/src/deepin-image-viewer.qrc
@@ -34,5 +34,6 @@
qml/Utils/FloatingNotice.qml
qml/Utils/ImageInputHandler.qml
qml/Utils/RightMenuItem.qml
+ qml/Dialog/RemoveDialog.qml
diff --git a/src/main.cpp b/src/main.cpp
index bc72a4d6..fb6439d7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -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
@@ -57,6 +58,8 @@ int main(int argc, char *argv[])
qmlRegisterType(uri.toUtf8().data(), 1, 0, "ImageSourceModel");
qmlRegisterType(uri.toUtf8().data(), 1, 0, "MouseTrackItem");
qmlRegisterUncreatableType(uri.toUtf8().data(), 1, 0, "Types", "Types only use for define");
+ // 文件回收站处理
+ qmlRegisterType(uri.toUtf8().data(), 1, 0, "FileTrashHelper");
// QML全局单例
GlobalControl control;
diff --git a/src/qml/Dialog/RemoveDialog.qml b/src/qml/Dialog/RemoveDialog.qml
new file mode 100644
index 00000000..d93e5df3
--- /dev/null
+++ b/src/qml/Dialog/RemoveDialog.qml
@@ -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);
+ }
+ }
+ }
+ }
+}
diff --git a/src/qml/ImageDelegate/DamagedImageDelegate.qml b/src/qml/ImageDelegate/DamagedImageDelegate.qml
index 376a33e1..bd2b5c83 100644
--- a/src/qml/ImageDelegate/DamagedImageDelegate.qml
+++ b/src/qml/ImageDelegate/DamagedImageDelegate.qml
@@ -14,7 +14,6 @@ BaseImageDelegate {
anchors.centerIn: parent
height: 151
name: "photo_breach"
- palette: DTK.makeIconPalette(parent.palette)
theme: DTK.DTK.themeType
width: 151
}
diff --git a/src/qml/ReName.qml b/src/qml/ReName.qml
index ba30de15..bdf4d721 100644
--- a/src/qml/ReName.qml
+++ b/src/qml/ReName.qml
@@ -94,7 +94,7 @@ DialogWindow {
regExp: /^[^ \\.\\\\/\':\\*\\?\"<>|%&][^\\\\/\':\\*\\?\"<>|%&]*/
}
- Keys.onPressed: event => {
+ Keys.onPressed: {
switch (event.key) {
case Qt.Key_Return:
case Qt.Key_Enter:
@@ -117,7 +117,6 @@ DialogWindow {
Button {
id: cancelbtn
- font.pixelSize: 16
height: 36
text: qsTr("Cancel")
width: 185
diff --git a/src/qml/ThumbnailListView.qml b/src/qml/ThumbnailListView.qml
index 6d3a74f2..ca62e48b 100644
--- a/src/qml/ThumbnailListView.qml
+++ b/src/qml/ThumbnailListView.qml
@@ -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
@@ -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();
}
@@ -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"
diff --git a/src/src/filecontrol.cpp b/src/src/filecontrol.cpp
index d8d9089b..f62d006c 100644
--- a/src/src/filecontrol.cpp
+++ b/src/src/filecontrol.cpp
@@ -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);
diff --git a/src/src/imagedata/imagefilewatcher.cpp b/src/src/imagedata/imagefilewatcher.cpp
index 24c09bce..6cb6f794 100644
--- a/src/src/imagedata/imagefilewatcher.cpp
+++ b/src/src/imagedata/imagefilewatcher.cpp
@@ -10,14 +10,19 @@
#include
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 , 若监控的文件路重复,则不执行重置
diff --git a/src/src/imagedata/imagefilewatcher.h b/src/src/imagedata/imagefilewatcher.h
index 85653f3c..1ae6b1aa 100644
--- a/src/src/imagedata/imagefilewatcher.h
+++ b/src/src/imagedata/imagefilewatcher.h
@@ -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);
@@ -30,12 +29,17 @@ class ImageFileWatcher : public QObject
// 当处理的图片文件夹变更(新增图片等)
Q_SLOT void onImageDirChanged(const QString &dir);
+ explicit ImageFileWatcher(QObject *parent = nullptr);
+ ~ImageFileWatcher() override;
+
private:
- QHash cacheFileInfo; ///< 缓存的图片信息,用于判断图片信息是否变更 QHash<完整路径, url信息>
- QHash removedFile; ///< 缓存被移除的文件信息(FileWatcher在文件删除/移动后将不会继续观察)
- QFileSystemWatcher *fileWatcher = nullptr; ///< 文件观察类,用于提示文件变更
+ QHash cacheFileInfo; ///< 缓存的图片信息,用于判断图片信息是否变更 QHash<完整路径, url信息>
+ QHash removedFile; ///< 缓存被移除的文件信息(FileWatcher在文件删除/移动后将不会继续观察)
+ QFileSystemWatcher *fileWatcher = nullptr; ///< 文件观察类,用于提示文件变更
QString rotateImagePath;
+
+ Q_DISABLE_COPY(ImageFileWatcher)
};
-#endif // IMAGEFILEWATCHER_H
+#endif // IMAGEFILEWATCHER_H
diff --git a/src/src/utils/filetrashhelper.cpp b/src/src/utils/filetrashhelper.cpp
new file mode 100644
index 00000000..e92e36a3
--- /dev/null
+++ b/src/src/utils/filetrashhelper.cpp
@@ -0,0 +1,241 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "filetrashhelper.h"
+#include "imagedata/imagefilewatcher.h"
+#include "unionimage/baseutils.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*!
+ \brief 拷贝自 dde-file-manager 代码,看图中仅使用 kRemovable 访问可能被卸载的设备
+ */
+enum DeviceQueryOption {
+ kNoCondition = 0,
+ kMountable = 1,
+ kMounted = 1 << 1,
+ kRemovable = 1 << 2,
+ kNotIgnored = 1 << 3,
+ kNotMounted = 1 << 4,
+ kOptical = 1 << 5,
+ kSystem = 1 << 6,
+ kLoop = 1 << 7,
+};
+
+/*!
+ \class FileTrashHelper::FileTrashHelper
+ \brief 文件回收站辅助类
+ \details 用于判断文件是否可被移动到回收站中,以及移动文件到回收站
+ \note 强关联文管DBus接口,需注意对应接口更新
+ */
+FileTrashHelper::FileTrashHelper(QObject *parent)
+ : QObject(parent)
+{
+ // DFM 设备管理接口,访问文件挂载信息
+ dfmDeviceManager.reset(new QDBusInterface(QStringLiteral("org.deepin.filemanager.server"),
+ QStringLiteral("/org/deepin/filemanager/server/DeviceManager"),
+ QStringLiteral("org.deepin.filemanager.server.DeviceManager")));
+}
+
+/*!
+ \return 返回文件 \a url 是否可被移动到回收站中
+ */
+bool FileTrashHelper::fileCanTrash(const QUrl &url)
+{
+ // 检测当前文件和上次是否相同
+ QDir currentDir(url.path());
+ if (lastDir != currentDir) {
+ lastDir = currentDir;
+ resetMountInfo();
+ }
+
+ queryMountInfo();
+
+ if (isGvfsFile(url)) {
+ return false;
+ }
+
+ if (isExternalDevice(url.path())) {
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \return 移动文件 \a url 到回收站
+ */
+bool FileTrashHelper::moveFileToTrash(const QUrl &url)
+{
+ // 优先采用文管后端 DBus 服务
+ bool ret = moveFileToTrashWithDBus(url);
+
+ if (!ret) {
+ qInfo() << qPrintable("Move file to trash DBus interface failed! Rollback to v20 version");
+ // 备用 V20 接口
+ ret = Libutils::base::trashFile(url.path());
+ }
+
+ if (!ret) {
+ qWarning() << qPrintable("Move file to trash failed:");
+ }
+
+ return ret;
+}
+
+/*!
+ \return 返回删除文件 \a url 的结果
+ */
+bool FileTrashHelper::removeFile(const QUrl &url)
+{
+ QFile file(url.path());
+ bool ret = file.remove();
+ if (!ret) {
+ qWarning() << qPrintable("Remove file failed:") << file.errorString();
+ }
+
+ return ret;
+}
+
+/*!
+ \brief 重置文件挂载信息,仅在需要获取时重新取得挂载数据
+ 对于看图应用的特殊处理,在打开新的图片后,仅需在首次触发查询挂载设备信息时查询,
+ 对于中途取消挂载的设备,文件监控会提示文件不存在,因此无需处理;
+ 同时,看图只会访问同一目录内容,挂载信息仅需查询单次,无需重复查询或监控设备
+ */
+void FileTrashHelper::resetMountInfo()
+{
+ initData = false;
+ mountDevices.clear();
+}
+
+/*!
+ \brief 查询当前挂载设备信息
+ \note 注意依赖文官接口的变动
+ */
+void FileTrashHelper::queryMountInfo()
+{
+ if (initData) {
+ return;
+ }
+
+ initData = true;
+
+ // 调用 DBus 接口查询可被卸载设备信息
+ // GetBlockDevicesIdList(int opts)
+ QDBusReply deviceListReply = dfmDeviceManager->call("GetBlockDevicesIdList", kRemovable);
+ if (!deviceListReply.isValid()) {
+ qWarning() << qPrintable("DBus call GetBlockDevicesIdList failed") << deviceListReply.error().message();
+ return;
+ }
+
+ for (const QString &id : deviceListReply.value()) {
+ // QueryBlockDeviceInfo(const QString &id, bool reload)
+ QDBusReply deviceReply = dfmDeviceManager->call("QueryBlockDeviceInfo", id, false);
+ if (!deviceReply.isValid()) {
+ qWarning() << qPrintable("DBus call QueryBlockDeviceInfo failed") << deviceReply.error().message();
+ continue;
+ }
+
+ const QVariantMap deviceInfo = deviceReply.value();
+ if (QString("usb") == deviceInfo.value("ConnectionBus").toString()) {
+ const QStringList mountPaths = deviceInfo.value("MountPoints").toStringList();
+ if (mountPaths.isEmpty()) {
+ const QString mountPath = deviceInfo.value("MountPoint").toString();
+
+ if (!mountPath.isEmpty()) {
+ mountDevices.insert(id, mountPath);
+ }
+ } else {
+ for (const QString &mount : mountPaths) {
+ mountDevices.insert(id, mount);
+ }
+ }
+ }
+ }
+}
+
+/*!
+ \return 返回文件路径 \a path 是否指向外部设备
+ */
+bool FileTrashHelper::isExternalDevice(const QString &path)
+{
+ for (auto itr = mountDevices.begin(); itr != mountDevices.end(); ++itr) {
+ if (path.startsWith(itr.value())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*!
+ \return 判断 \a url 是否为远程挂载路径,此路径下同样无法恢复文件
+ */
+bool FileTrashHelper::isGvfsFile(const QUrl &url) const
+{
+ if (!url.isValid())
+ return false;
+
+ const QString &path = url.toLocalFile();
+ static const QString gvfsMatch { "(^/run/user/\\d+/gvfs/|^/root/.gvfs/|^/media/[\\s\\S]*/smbmounts)" };
+ QRegularExpression re { gvfsMatch };
+ QRegularExpressionMatch match { re.match(path) };
+ return match.hasMatch();
+}
+
+/*!
+ \brief 通过后端文管接口将文件 \a url 移动到回收站
+ 注意文管接口是异步接口且没有返回值,此处通过文件变更信号判断文件是否被移动。
+ \return 移动文件到回收站是否成功
+ */
+bool FileTrashHelper::moveFileToTrashWithDBus(const QUrl &url)
+{
+ if (!url.isValid()) {
+ return false;
+ }
+
+ QStringList list;
+ list << url.toString();
+ // 优先采用文管后端的DBus服务
+ QDBusInterface interface(QStringLiteral("org.freedesktop.FileManager1"),
+ QStringLiteral("/org/freedesktop/FileManager1"),
+ QStringLiteral("org.freedesktop.FileManager1"));
+ // 默认超时时间大约25s, 修改为最大限制
+ interface.setTimeout(INT_MAX);
+ auto pendingCall = interface.asyncCall("Trash", list);
+
+ QEventLoop loop;
+ bool waitRet = false;
+ // 等待文件变更
+ QString filePath = url.path();
+ auto conn = QObject::connect(ImageFileWatcher::instance(),
+ &ImageFileWatcher::imageFileChanged,
+ this,
+ [&filePath, &loop, &waitRet](const QString &imagePath) {
+ // 删除信息未通过 DBus 返回,直接判断文件是否已被删除
+ if ((imagePath == filePath) && !QFile::exists(filePath)) {
+ waitRet = true;
+ loop.quit();
+ };
+ });
+
+ // 等待最多200ms超时
+ static const int overTime = 200;
+ QTimer::singleShot(overTime, &loop, &QEventLoop::quit);
+ loop.exec();
+
+ if (pendingCall.isError()) {
+ auto error = pendingCall.error();
+ qWarning() << "Delete image by dbus error:" << error.name() << error.message();
+ }
+
+ QObject::disconnect(conn);
+ return waitRet;
+}
diff --git a/src/src/utils/filetrashhelper.h b/src/src/utils/filetrashhelper.h
new file mode 100644
index 00000000..60532544
--- /dev/null
+++ b/src/src/utils/filetrashhelper.h
@@ -0,0 +1,42 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef FILETRASHHELPER_H
+#define FILETRASHHELPER_H
+
+#include
+#include
+#include
+#include
+
+// 文件移动至回收站 辅助类
+class FileTrashHelper : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit FileTrashHelper(QObject *parent = nullptr);
+
+ Q_INVOKABLE bool fileCanTrash(const QUrl &url);
+ Q_INVOKABLE bool moveFileToTrash(const QUrl &url);
+ Q_INVOKABLE bool removeFile(const QUrl &url);
+
+ Q_INVOKABLE void resetMountInfo();
+
+private:
+ void queryMountInfo();
+ bool isExternalDevice(const QString &path);
+ bool isGvfsFile(const QUrl &url) const;
+
+ bool moveFileToTrashWithDBus(const QUrl &url);
+
+private:
+ QScopedPointer dfmDeviceManager;
+
+ bool initData { false }; // 挂载数据是否被初始化
+ QDir lastDir; // 上一次访问的文件目录
+ QMultiHash mountDevices; // 当前挂载设备信息
+};
+
+#endif // FILETRASHHELPER_H
diff --git a/src/translations/deepin-image-viewer.ts b/src/translations/deepin-image-viewer.ts
index 6e14d0b4..2e792924 100644
--- a/src/translations/deepin-image-viewer.ts
+++ b/src/translations/deepin-image-viewer.ts
@@ -264,6 +264,25 @@
Confirm
+
+ RemoveDialog
+
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+
+
+ This action cannot be undone
+ This action cannot be undone
+
+
+ Cancel
+ Cancel
+
+
+ Confirm
+ Confirm
+
+
SliderShow
@@ -393,11 +412,11 @@
Version
- Version
+ Version
%1 is released under %2
- %1 is released under %2
+ %1 is released under %2
Open image
diff --git a/src/translations/deepin-image-viewer_bo.ts b/src/translations/deepin-image-viewer_bo.ts
index 6b6983a8..35920089 100644
--- a/src/translations/deepin-image-viewer_bo.ts
+++ b/src/translations/deepin-image-viewer_bo.ts
@@ -262,6 +262,25 @@
གཏན་འཁེལ།
+
+ RemoveDialog
+
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+ “%1”ནང་དོན་སྙིགས་སྣོད་སུ་འཇོག་ཐབས་མེད་པས། ཁྱེད་ཀྱིས་རྦད་དེ་བསུབ་བམ།
+
+
+ This action cannot be undone
+ བཀོལ་སྤྱོད་འདི་བྱས་ཚེ་སོར་ཆུད་མི་ཐུབ།
+
+
+ Cancel
+ འདོར་བ།
+
+
+ Confirm
+ གཏན་འཁེལ།
+
+
SliderShow
@@ -391,11 +410,11 @@
Version
- པར་གཞི།
+ པར་གཞི།
%1 is released under %2
- %1བརྩི་སྲུང་། %2ཆིངས་ཡིག་ཁྱབ་བསྒྲགས།
+ %1བརྩི་སྲུང་། %2ཆིངས་ཡིག་ཁྱབ་བསྒྲགས།
Open image
diff --git a/src/translations/deepin-image-viewer_ug.ts b/src/translations/deepin-image-viewer_ug.ts
index 5df73d39..c178a8ab 100644
--- a/src/translations/deepin-image-viewer_ug.ts
+++ b/src/translations/deepin-image-viewer_ug.ts
@@ -262,6 +262,25 @@
جەزملەش
+
+ RemoveDialog
+
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+ «%1» نى ئەخلەت ساندۇقىغا قويغىلى بولمىدى، تەلتۆكۈس ئۆچۈرەمسىز؟
+
+
+ This action cannot be undone
+ بۇ مەشغۇلاتنى ئەسلىگە قايتۇرغىلى بولمايدۇ
+
+
+ Cancel
+ بىكار قىلىش
+
+
+ Confirm
+ جەزملەش
+
+
SliderShow
@@ -391,11 +410,11 @@
Version
- نەشرى
+ نەشرى
%1 is released under %2
- %1 كېلىشىم %2 گە ئەمەل قىلغان ئاساستا ئېلان قىلىندى
+ %1 كېلىشىم %2 گە ئەمەل قىلغان ئاساستا ئېلان قىلىندى
Open image
diff --git a/src/translations/deepin-image-viewer_zh_CN.ts b/src/translations/deepin-image-viewer_zh_CN.ts
index acd79b55..587715fb 100644
--- a/src/translations/deepin-image-viewer_zh_CN.ts
+++ b/src/translations/deepin-image-viewer_zh_CN.ts
@@ -262,6 +262,25 @@
确定
+
+ RemoveDialog
+
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+ 无法将“%1”放到回收站,您要彻底删除吗?
+
+
+ This action cannot be undone
+ 此操作不可以恢复
+
+
+ Cancel
+ 取消
+
+
+ Confirm
+ 确定
+
+
SliderShow
@@ -391,11 +410,11 @@
Version
- 版本
+ 版本
%1 is released under %2
- %1遵循%2协议发布
+ %1遵循%2协议发布
Open image
diff --git a/src/translations/deepin-image-viewer_zh_HK.ts b/src/translations/deepin-image-viewer_zh_HK.ts
index 9cab323a..bb268471 100644
--- a/src/translations/deepin-image-viewer_zh_HK.ts
+++ b/src/translations/deepin-image-viewer_zh_HK.ts
@@ -262,6 +262,25 @@
確定
+
+ RemoveDialog
+
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+ 無法將“%1”放到回收站,您要徹底刪除嗎?
+
+
+ This action cannot be undone
+ 此操作不可以恢復
+
+
+ Cancel
+ 取消
+
+
+ Confirm
+ 確定
+
+
SliderShow
@@ -391,11 +410,11 @@
Version
- 版本
+ 版本
%1 is released under %2
- %1遵循%2協議發佈
+ %1遵循%2協議發佈
Open image
diff --git a/src/translations/deepin-image-viewer_zh_TW.ts b/src/translations/deepin-image-viewer_zh_TW.ts
index 8b25df97..2f7c9420 100644
--- a/src/translations/deepin-image-viewer_zh_TW.ts
+++ b/src/translations/deepin-image-viewer_zh_TW.ts
@@ -262,6 +262,25 @@
確定
+
+ RemoveDialog
+
+ Cannot move "%1" to the trash. Do you want to permanently delete it?
+ 無法將“%1”放到回收站,您要徹底刪除嗎?
+
+
+ This action cannot be undone
+ 此操作不可以復原
+
+
+ Cancel
+ 取消
+
+
+ Confirm
+ 確定
+
+
SliderShow
@@ -391,11 +410,11 @@
Version
- 版本
+ 版本
%1 is released under %2
- %1遵循%2協議發布
+ %1遵循%2協議發布
Open image