mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-23 03:58:56 -04:00
Merge pull request #963 from kiwix/moveToTrash
Deleting files move them to trash
This commit is contained in:
commit
1ad4a72d0c
@ -57,3 +57,15 @@ QPushButton:hover {
|
||||
min-width: 14px;
|
||||
font: bold;
|
||||
}
|
||||
|
||||
QCheckBox::indicator {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid black;
|
||||
border-radius: 5px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked {
|
||||
image: url(:/icons/check-solid.svg);
|
||||
}
|
||||
|
@ -151,5 +151,8 @@
|
||||
"resume-download": "Resume download",
|
||||
"open-folder": "Open folder",
|
||||
"couldnt-open-location": "Couldn't open location",
|
||||
"couldnt-open-location-text": "Kiwix is not able to open folder {{FOLDER}}"
|
||||
"couldnt-open-location-text": "Kiwix is not able to open folder {{FOLDER}}",
|
||||
"move-files-to-trash": "Move deleted files to trash",
|
||||
"move-files-to-trash-text": "This action will move the file to trash.",
|
||||
"perma-delete-files-text": "This action will permanently delete the file."
|
||||
}
|
||||
|
1
resources/icons/check-solid.svg
Normal file
1
resources/icons/check-solid.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>
|
After Width: | Height: | Size: 428 B |
@ -60,5 +60,6 @@
|
||||
<file>icons/caret-right-solid.svg</file>
|
||||
<file>icons/caret-up-solid.svg</file>
|
||||
<file>icons/kiwix-logo.svg</file>
|
||||
<file>icons/check-solid.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -473,20 +473,43 @@ QString ContentManager::downloadBook(const QString &id)
|
||||
return QString::fromStdString(download->getDid());
|
||||
}
|
||||
|
||||
void ContentManager::eraseBookFilesFromComputer(const QString dirPath, const QString fileName)
|
||||
void ContentManager::eraseBookFilesFromComputer(const QString dirPath, const QString fileName, const bool moveToTrash)
|
||||
{
|
||||
if (fileName == "*") {
|
||||
return;
|
||||
}
|
||||
QDir dir(dirPath, fileName);
|
||||
for(const QString& file: dir.entryList()) {
|
||||
dir.remove(file);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
if (moveToTrash)
|
||||
QFile::moveToTrash(dir.filePath(file));
|
||||
else
|
||||
#endif
|
||||
dir.remove(file); // moveToTrash will always be false here, no check required.
|
||||
}
|
||||
}
|
||||
|
||||
QString formatText(QString text)
|
||||
{
|
||||
QString finalText = "<br><br><i>";
|
||||
finalText += text;
|
||||
finalText += "</i>";
|
||||
return finalText;
|
||||
}
|
||||
|
||||
void ContentManager::eraseBook(const QString& id)
|
||||
{
|
||||
auto text = gt("delete-book-text");
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
const auto moveToTrash = KiwixApp::instance()->getSettingsManager()->getMoveToTrash();
|
||||
#else
|
||||
const auto moveToTrash = false; // we do not support move to trash functionality for qt versions below 5.15
|
||||
#endif
|
||||
if (moveToTrash) {
|
||||
text += formatText(gt("move-files-to-trash-text"));
|
||||
} else {
|
||||
text += formatText(gt("perma-delete-files-text"));
|
||||
}
|
||||
text = text.replace("{{ZIM}}", QString::fromStdString(mp_library->getBookById(id).getTitle()));
|
||||
KiwixConfirmBox *dialog = new KiwixConfirmBox(gt("delete-book"), text, false, mp_view);
|
||||
dialog->show();
|
||||
@ -496,7 +519,7 @@ void ContentManager::eraseBook(const QString& id)
|
||||
kiwix::Book book = mp_library->getBookById(id);
|
||||
QString dirPath = QString::fromStdString(kiwix::removeLastPathElement(book.getPath()));
|
||||
QString fileName = QString::fromStdString(kiwix::getLastPathElement(book.getPath())) + "*";
|
||||
eraseBookFilesFromComputer(dirPath, fileName);
|
||||
eraseBookFilesFromComputer(dirPath, fileName, moveToTrash);
|
||||
mp_library->removeBookFromLibraryById(id);
|
||||
mp_library->save();
|
||||
emit mp_library->bookmarksChanged();
|
||||
@ -576,7 +599,8 @@ void ContentManager::cancelBook(const QString& id)
|
||||
}
|
||||
QString dirPath = QString::fromStdString(kiwix::removeLastPathElement(download->getPath()));
|
||||
QString filename = QString::fromStdString(kiwix::getLastPathElement(download->getPath())) + "*";
|
||||
eraseBookFilesFromComputer(dirPath, filename);
|
||||
// incompleted downloaded file should be perma deleted
|
||||
eraseBookFilesFromComputer(dirPath, filename, false);
|
||||
mp_library->removeBookFromLibraryById(id);
|
||||
mp_library->save();
|
||||
emit(oneBookChanged(id));
|
||||
|
@ -49,7 +49,7 @@ private:
|
||||
QStringList m_categories;
|
||||
|
||||
QStringList getBookIds();
|
||||
void eraseBookFilesFromComputer(const QString dirPath, const QString filename);
|
||||
void eraseBookFilesFromComputer(const QString dirPath, const QString filename, const bool moveToTrash);
|
||||
QList<QMap<QString, QVariant>> getBooksList();
|
||||
ContentManagerModel *managerModel;
|
||||
QMutex remoteLibraryLocker;
|
||||
|
@ -99,13 +99,17 @@ void KiwixApp::init()
|
||||
}
|
||||
});
|
||||
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, [=](QString monitorDir) {
|
||||
m_library.asyncLoadMonitorDir(monitorDir);
|
||||
m_library.asyncUpdateFromDir(monitorDir);
|
||||
});
|
||||
QString monitorDir = m_settingsManager.getMonitorDir();
|
||||
if (monitorDir != "") {
|
||||
m_library.setMonitorDirZims(m_library.getLibraryZimsFromDir(monitorDir));
|
||||
m_watcher.addPath(monitorDir);
|
||||
m_library.asyncLoadMonitorDir(monitorDir);
|
||||
QString downloadDir = m_settingsManager.getDownloadDir();
|
||||
auto dirList = QSet<QString>({monitorDir, downloadDir});
|
||||
for (auto dir : dirList) {
|
||||
if (dir != "") {
|
||||
m_library.setMonitorDirZims(dir, m_library.getLibraryZimsFromDir(dir));
|
||||
m_watcher.addPath(dir);
|
||||
m_library.asyncUpdateFromDir(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,13 +288,14 @@ bool KiwixApp::isCurrentArticleBookmarked()
|
||||
|
||||
void KiwixApp::setMonitorDir(const QString &dir) {
|
||||
m_settingsManager.setMonitorDir(dir);
|
||||
m_library.setMonitorDirZims(QStringList());
|
||||
m_library.setMonitorDirZims(dir, QStringList());
|
||||
for (auto path : m_watcher.directories()) {
|
||||
m_watcher.removePath(path);
|
||||
}
|
||||
if (dir != "") {
|
||||
m_watcher.addPath(dir);
|
||||
m_library.asyncLoadMonitorDir(dir);
|
||||
m_watcher.addPath(m_settingsManager.getDownloadDir());
|
||||
m_library.asyncUpdateFromDir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,9 +115,9 @@ void Library::save()
|
||||
m_library.writeBookmarksToFile(kiwix::appendToDirectory(m_libraryDirectory.toStdString(), "library.bookmarks.xml"));
|
||||
}
|
||||
|
||||
void Library::setMonitorDirZims(QStringList zimList)
|
||||
void Library::setMonitorDirZims(QString monitorDir, QStringList zimList)
|
||||
{
|
||||
m_monitorDirZims = zimList;
|
||||
m_knownZimsInDir[monitorDir] = zimList;
|
||||
}
|
||||
|
||||
QStringList Library::getLibraryZimsFromDir(QString dir) const
|
||||
@ -133,13 +133,12 @@ QStringList Library::getLibraryZimsFromDir(QString dir) const
|
||||
return zimsInDir;
|
||||
}
|
||||
|
||||
void Library::loadMonitorDir(QString monitorDir)
|
||||
void Library::updateFromDir(QString monitorDir)
|
||||
{
|
||||
QMutex mutex;
|
||||
QMutexLocker locker(&mutex);
|
||||
QMutexLocker locker(&m_updateFromDirMutex);
|
||||
const QDir dir(monitorDir);
|
||||
QStringList newDirEntries = dir.entryList({"*.zim"});
|
||||
QStringList oldDirEntries = m_monitorDirZims;
|
||||
QStringList oldDirEntries = m_knownZimsInDir[monitorDir];
|
||||
for (auto &str : newDirEntries) {
|
||||
str = QDir::toNativeSeparators(monitorDir + "/" + str);
|
||||
}
|
||||
@ -160,18 +159,20 @@ void Library::loadMonitorDir(QString monitorDir)
|
||||
needsRefresh |= manager.addBookFromPath(book.toStdString());
|
||||
}
|
||||
for (auto bookPath : removedZims) {
|
||||
removeBookFromLibraryById(QString::fromStdString(m_library.getBookByPath(bookPath.toStdString()).getId()));
|
||||
try {
|
||||
removeBookFromLibraryById(QString::fromStdString(m_library.getBookByPath(bookPath.toStdString()).getId()));
|
||||
} catch (...) {}
|
||||
}
|
||||
if (needsRefresh) {
|
||||
setMonitorDirZims(newDir.values());
|
||||
emit(booksChanged());
|
||||
setMonitorDirZims(monitorDir, newDir.values());
|
||||
}
|
||||
}
|
||||
|
||||
void Library::asyncLoadMonitorDir(QString dir)
|
||||
void Library::asyncUpdateFromDir(QString dir)
|
||||
{
|
||||
QtConcurrent::run( [=]() {
|
||||
loadMonitorDir(dir);
|
||||
updateFromDir(dir);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
||||
#define TQS(v) (QString::fromStdString(v))
|
||||
#define FORWARD_GETTER(METH) QString METH() const { return TQS(mp_book->METH()); }
|
||||
@ -34,14 +35,14 @@ public:
|
||||
QStringList listBookIds(const kiwix::Filter& filter, kiwix::supportedListSortBy sortBy, bool ascending) const;
|
||||
const std::vector<kiwix::Bookmark> getBookmarks(bool onlyValidBookmarks = false) const { return m_library.getBookmarks(onlyValidBookmarks); }
|
||||
QStringList getLibraryZimsFromDir(QString dir) const;
|
||||
void setMonitorDirZims(QStringList zimList);
|
||||
void setMonitorDirZims(QString monitorDir, QStringList zimList);
|
||||
void addBookToLibrary(kiwix::Book& book);
|
||||
void removeBookFromLibraryById(const QString& id);
|
||||
void addBookmark(kiwix::Bookmark& bookmark);
|
||||
void removeBookmark(const QString& zimId, const QString& url);
|
||||
void save();
|
||||
void loadMonitorDir(QString dir);
|
||||
void asyncLoadMonitorDir(QString dir);
|
||||
void updateFromDir(QString dir);
|
||||
void asyncUpdateFromDir(QString dir);
|
||||
kiwix::Library& getKiwixLibrary() { return m_library; }
|
||||
public slots:
|
||||
const kiwix::Book& getBookById(QString id) const;
|
||||
@ -51,9 +52,10 @@ signals:
|
||||
void bookmarksChanged();
|
||||
|
||||
private:
|
||||
QMutex m_updateFromDirMutex;
|
||||
kiwix::Library m_library;
|
||||
QString m_libraryDirectory;
|
||||
QStringList m_monitorDirZims;
|
||||
QMap<QString, QStringList> m_knownZimsInDir;
|
||||
friend class LibraryManipulator;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ SettingsView* SettingsManager::getView()
|
||||
{
|
||||
if (m_view == nullptr) {
|
||||
auto view = new SettingsView();
|
||||
view->init(m_zoomFactor * 100, m_downloadDir, m_monitorDir);
|
||||
view->init(m_zoomFactor * 100, m_downloadDir, m_monitorDir, m_moveToTrash);
|
||||
connect(view, &QObject::destroyed, this, [=]() { m_view = nullptr; });
|
||||
m_view = view;
|
||||
}
|
||||
@ -89,6 +89,13 @@ void SettingsManager::setMonitorDir(QString monitorDir)
|
||||
emit(monitorDirChanged(monitorDir));
|
||||
}
|
||||
|
||||
void SettingsManager::setMoveToTrash(bool moveToTrash)
|
||||
{
|
||||
m_moveToTrash = moveToTrash;
|
||||
setSettings("moveToTrash", m_moveToTrash);
|
||||
emit(moveToTrashChanged(m_moveToTrash));
|
||||
}
|
||||
|
||||
void SettingsManager::initSettings()
|
||||
{
|
||||
m_kiwixServerPort = m_settings.value("localKiwixServer/port", 8080).toInt();
|
||||
@ -96,4 +103,5 @@ void SettingsManager::initSettings()
|
||||
m_downloadDir = m_settings.value("download/dir", QString::fromStdString(kiwix::getDataDirectory())).toString();
|
||||
m_kiwixServerIpAddress = m_settings.value("localKiwixServer/ipAddress", QString("0.0.0.0")).toString();
|
||||
m_monitorDir = m_settings.value("monitor/dir", QString("")).toString();
|
||||
m_moveToTrash = m_settings.value("moveToTrash", true).toBool();
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
qreal getZoomFactor() const { return m_zoomFactor; }
|
||||
QString getDownloadDir() const { return m_downloadDir; }
|
||||
QString getMonitorDir() const { return m_monitorDir; }
|
||||
bool getMoveToTrash() const { return m_moveToTrash; }
|
||||
|
||||
public slots:
|
||||
void setKiwixServerPort(int port);
|
||||
@ -34,6 +35,7 @@ public slots:
|
||||
void setZoomFactor(qreal zoomFactor);
|
||||
void setDownloadDir(QString downloadDir);
|
||||
void setMonitorDir(QString monitorDir);
|
||||
void setMoveToTrash(bool moveToTrash);
|
||||
private:
|
||||
void initSettings();
|
||||
|
||||
@ -42,6 +44,7 @@ signals:
|
||||
void zoomChanged(qreal zoomFactor);
|
||||
void downloadDirChanged(QString downloadDir);
|
||||
void monitorDirChanged(QString monitorDir);
|
||||
void moveToTrashChanged(bool moveToTrash);
|
||||
|
||||
private:
|
||||
QSettings m_settings;
|
||||
@ -51,6 +54,7 @@ private:
|
||||
qreal m_zoomFactor;
|
||||
QString m_downloadDir;
|
||||
QString m_monitorDir;
|
||||
bool m_moveToTrash;
|
||||
};
|
||||
|
||||
#endif // SETTINGSMANAGER_H
|
||||
|
@ -14,6 +14,7 @@ SettingsView::SettingsView(QWidget *parent)
|
||||
QString styleSheet = QString(file.readAll());
|
||||
ui->widget->setStyleSheet(styleSheet);
|
||||
connect(ui->zoomPercentSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsView::setZoom);
|
||||
connect(ui->moveToTrashToggle, &QCheckBox::clicked, this, &SettingsView::setMoveToTrash);
|
||||
connect(ui->browseButton, &QPushButton::clicked, this, &SettingsView::browseDownloadDir);
|
||||
connect(ui->resetButton, &QPushButton::clicked, this, &SettingsView::resetDownloadDir);
|
||||
connect(ui->monitorBrowse, &QPushButton::clicked, this, &SettingsView::browseMonitorDir);
|
||||
@ -21,6 +22,7 @@ SettingsView::SettingsView(QWidget *parent)
|
||||
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::downloadDirChanged, this, &SettingsView::onDownloadDirChanged);
|
||||
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::monitorDirChanged, this, &SettingsView::onMonitorDirChanged);
|
||||
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::zoomChanged, this, &SettingsView::onZoomChanged);
|
||||
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::moveToTrashChanged, this, &SettingsView::onMoveToTrashChanged);
|
||||
ui->settingsLabel->setText(gt("settings"));
|
||||
ui->zoomPercentLabel->setText(gt("zoom-level-setting"));
|
||||
ui->downloadDirLabel->setText(gt("download-directory-setting"));
|
||||
@ -31,9 +33,15 @@ SettingsView::SettingsView(QWidget *parent)
|
||||
ui->monitorBrowse->setText(gt("browse"));
|
||||
ui->monitorHelp->setText("<b>?</b>");
|
||||
ui->monitorHelp->setToolTip(gt("monitor-directory-tooltip"));
|
||||
ui->moveToTrashLabel->setText(gt("move-files-to-trash"));
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
ui->moveToTrashLabel->hide();
|
||||
ui->moveToTrashToggle->hide();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SettingsView::init(int zoomPercent, const QString &downloadDir, const QString &monitorDir)
|
||||
void SettingsView::init(int zoomPercent, const QString &downloadDir, const QString &monitorDir, const bool moveToTrash)
|
||||
{
|
||||
ui->zoomPercentSpinBox->setValue(zoomPercent);
|
||||
ui->downloadDirPath->setText(downloadDir);
|
||||
@ -41,6 +49,7 @@ void SettingsView::init(int zoomPercent, const QString &downloadDir, const QStri
|
||||
ui->monitorClear->hide();
|
||||
}
|
||||
ui->monitorDirPath->setText(monitorDir);
|
||||
ui->moveToTrashToggle->setChecked(moveToTrash);
|
||||
}
|
||||
bool SettingsView::confirmDialog( QString messageText, QString messageTitle)
|
||||
{
|
||||
@ -131,6 +140,11 @@ void SettingsView::setZoom(int zoomPercent)
|
||||
KiwixApp::instance()->getSettingsManager()->setZoomFactor(zoomFactor);
|
||||
}
|
||||
|
||||
void SettingsView::setMoveToTrash(bool moveToTrash)
|
||||
{
|
||||
KiwixApp::instance()->getSettingsManager()->setMoveToTrash(moveToTrash);
|
||||
}
|
||||
|
||||
void SettingsView::onDownloadDirChanged(const QString &dir)
|
||||
{
|
||||
ui->downloadDirPath->setText(dir);
|
||||
@ -151,3 +165,8 @@ void SettingsView::onZoomChanged(qreal zoomFactor)
|
||||
qreal zoomPercent = zoomFactor * 100;
|
||||
ui->zoomPercentSpinBox->setValue(zoomPercent);
|
||||
}
|
||||
|
||||
void SettingsView::onMoveToTrashChanged(bool moveToTrash)
|
||||
{
|
||||
ui->moveToTrashToggle->setChecked(moveToTrash);
|
||||
}
|
||||
|
@ -11,16 +11,18 @@ class SettingsView : public QWidget
|
||||
public:
|
||||
SettingsView(QWidget *parent = nullptr);
|
||||
~SettingsView(){};
|
||||
void init(int zoomPercent, const QString &downloadDir, const QString &monitorDir);
|
||||
void init(int zoomPercent, const QString &downloadDir, const QString &monitorDir, const bool moveToTrash);
|
||||
public Q_SLOTS:
|
||||
void resetDownloadDir();
|
||||
void browseDownloadDir();
|
||||
void browseMonitorDir();
|
||||
void clearMonitorDir();
|
||||
void setZoom(int zoomPercent);
|
||||
void setMoveToTrash(bool moveToTrash);
|
||||
void onDownloadDirChanged(const QString &dir);
|
||||
void onMonitorDirChanged(const QString &dir);
|
||||
void onZoomChanged(qreal zoomFactor);
|
||||
void onMoveToTrashChanged(bool moveToTrash);
|
||||
private:
|
||||
bool confirmDialogDownloadDir(const QString& dir);
|
||||
bool confirmDialog(QString messageText, QString messageTitle);
|
||||
|
@ -284,6 +284,50 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="moveToTrashLabel">
|
||||
<property name="text">
|
||||
<string>Move deleted files to trash</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="moveToTrashToggle">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
Loading…
x
Reference in New Issue
Block a user