Skip to content

Commit

Permalink
Merge pull request #5698 from nextcloud/feature/trashfiles
Browse files Browse the repository at this point in the history
Add option to move deleted files to trash instead of permanently deleting them
  • Loading branch information
claucambra authored Jul 20, 2023
2 parents a14f5bc + e54d78a commit b4c9761
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 78 deletions.
73 changes: 5 additions & 68 deletions src/common/filesystembase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,77 +367,14 @@ bool FileSystem::remove(const QString &fileName, QString *errorString)

bool FileSystem::moveToTrash(const QString &fileName, QString *errorString)
{
// TODO: Qt 5.15 bool QFile::moveToTrash()
#if defined Q_OS_UNIX && !defined Q_OS_MAC
QString trashPath, trashFilePath, trashInfoPath;
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
if (xdgDataHome.isEmpty()) {
trashPath = QDir::homePath() + QStringLiteral("/.local/share/Trash/"); // trash path that should exist
} else {
trashPath = xdgDataHome + QStringLiteral("/Trash/");
}

trashFilePath = trashPath + QStringLiteral("files/"); // trash file path contain delete files
trashInfoPath = trashPath + QStringLiteral("info/"); // trash info path contain delete files information

if (!(QDir().mkpath(trashFilePath) && QDir().mkpath(trashInfoPath))) {
*errorString = QCoreApplication::translate("FileSystem", "Could not make directories in trash");
return false; //mkpath will return true if path exists
}

QFileInfo f(fileName);

QDir file;
int suffix_number = 1;
if (file.exists(trashFilePath + f.fileName())) { //file in trash already exists, move to "filename.1"
QString path = trashFilePath + f.fileName() + QLatin1Char('.');
while (file.exists(path + QString::number(suffix_number))) { //or to "filename.2" if "filename.1" exists, etc
suffix_number++;
}
if (!file.rename(f.absoluteFilePath(), path + QString::number(suffix_number))) { // rename(file old path, file trash path)
*errorString = QCoreApplication::translate("FileSystem", R"(Could not move "%1" to "%2")")
.arg(f.absoluteFilePath(), path + QString::number(suffix_number));
return false;
}
} else {
if (!file.rename(f.absoluteFilePath(), trashFilePath + f.fileName())) { // rename(file old path, file trash path)
*errorString = QCoreApplication::translate("FileSystem", R"(Could not move "%1" to "%2")")
.arg(f.absoluteFilePath(), trashFilePath + f.fileName());
return false;
QFile f(fileName);
if (!f.moveToTrash()) {
if (errorString) {
*errorString = f.errorString();
}
return false;
}

// create file format for trash info file----- START
QFile infoFile;
if (file.exists(trashInfoPath + f.fileName() + QStringLiteral(".trashinfo"))) { //TrashInfo file already exists, create "filename.1.trashinfo"
QString filename = trashInfoPath + f.fileName() + QLatin1Char('.') + QString::number(suffix_number) + QStringLiteral(".trashinfo");
infoFile.setFileName(filename); //filename+.trashinfo // create file information file in /.local/share/Trash/info/ folder
} else {
QString filename = trashInfoPath + f.fileName() + QStringLiteral(".trashinfo");
infoFile.setFileName(filename); //filename+.trashinfo // create file information file in /.local/share/Trash/info/ folder
}

infoFile.open(QIODevice::ReadWrite);

QTextStream stream(&infoFile); // for write data on open file

stream << "[Trash Info]\n"
<< "Path="
<< QUrl::toPercentEncoding(f.absoluteFilePath(), "~_-./")
<< "\n"
<< "DeletionDate="
<< QDateTime::currentDateTime().toString(Qt::ISODate)
<< '\n';
infoFile.close();

// create info file format of trash file----- END

return true;
#else
Q_UNUSED(fileName)
*errorString = QCoreApplication::translate("FileSystem", "Moving to the trash is not implemented on this platform");
return false;
#endif
}

bool FileSystem::isFileLocked(const QString &fileName)
Expand Down
25 changes: 16 additions & 9 deletions src/gui/generalsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ GeneralSettings::GeneralSettings(QWidget *parent)
connect(_ui->newFolderLimitCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
connect(_ui->newFolderLimitSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &GeneralSettings::saveMiscSettings);
connect(_ui->newExternalStorage, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);
connect(_ui->moveFilesToTrashCheckBox, &QAbstractButton::toggled, this, &GeneralSettings::saveMiscSettings);

#ifndef WITH_CRASHREPORTER
_ui->crashreporterCheckBox->setVisible(false);
Expand Down Expand Up @@ -246,17 +247,20 @@ void GeneralSettings::loadMiscSettings()
{
QScopedValueRollback<bool> scope(_currentlyLoading, true);
ConfigFile cfgFile;

_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
_ui->serverNotificationsCheckBox->setChecked(cfgFile.optionalServerNotifications());
_ui->callNotificationsCheckBox->setEnabled(_ui->serverNotificationsCheckBox->isEnabled());
_ui->callNotificationsCheckBox->setChecked(cfgFile.showCallNotifications());
_ui->showInExplorerNavigationPaneCheckBox->setChecked(cfgFile.showInExplorerNavigationPane());
_ui->crashreporterCheckBox->setChecked(cfgFile.crashReporter());
_ui->newExternalStorage->setChecked(cfgFile.confirmExternalStorage());
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
_ui->moveFilesToTrashCheckBox->setChecked(cfgFile.moveToTrash());

auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
_ui->newFolderLimitCheckBox->setChecked(newFolderLimit.first);
_ui->newFolderLimitSpinBox->setValue(newFolderLimit.second);
_ui->newExternalStorage->setChecked(cfgFile.confirmExternalStorage());
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());
}

#if defined(BUILD_UPDATER)
Expand Down Expand Up @@ -406,17 +410,20 @@ void GeneralSettings::slotToggleAutoUpdateCheck()

void GeneralSettings::saveMiscSettings()
{
if (_currentlyLoading)
if (_currentlyLoading) {
return;
}

ConfigFile cfgFile;
bool isChecked = _ui->monoIconsCheckBox->isChecked();
cfgFile.setMonoIcons(isChecked);
Theme::instance()->setSystrayUseMonoIcons(isChecked);
cfgFile.setCrashReporter(_ui->crashreporterCheckBox->isChecked());

cfgFile.setNewBigFolderSizeLimit(_ui->newFolderLimitCheckBox->isChecked(),
_ui->newFolderLimitSpinBox->value());
const auto monoIconsChecked = _ui->monoIconsCheckBox->isChecked();
cfgFile.setMonoIcons(monoIconsChecked);
Theme::instance()->setSystrayUseMonoIcons(monoIconsChecked);

cfgFile.setCrashReporter(_ui->crashreporterCheckBox->isChecked());
cfgFile.setNewBigFolderSizeLimit(_ui->newFolderLimitCheckBox->isChecked(), _ui->newFolderLimitSpinBox->value());
cfgFile.setConfirmExternalStorage(_ui->newExternalStorage->isChecked());
cfgFile.setMoveToTrash(_ui->moveFilesToTrashCheckBox->isChecked());
}

void GeneralSettings::slotToggleLaunchOnStartup(bool enable)
Expand Down
13 changes: 12 additions & 1 deletion src/gui/generalsettings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>556</width>
<height>563</height>
<height>613</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -276,6 +276,17 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="moveFilesToTrashCheckBox">
<property name="text">
<string>Move removed files to trash</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
Expand Down

0 comments on commit b4c9761

Please sign in to comment.