diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index c5c559d6856b..cb39dd4c40ba 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -1837,7 +1837,7 @@ void Application::checkForPreviousCrashes() tmp.setFilter(QDir::Dirs); QList dirs = tmp.entryInfoList(); if (dirs.isEmpty()) { - // delete the lock file immediately if not transient directories are related + // delete the lock file immediately if no transient directories are related tmp.remove(fn); } else { @@ -1852,7 +1852,7 @@ void Application::checkForPreviousCrashes() if (tmp.rmdir(it->filePath())) countDeletedDocs++; } - // search for the existance of a recovery file + // search for the existence of a recovery file else if (doc_dir.exists(QLatin1String("fc_recovery_file.xml"))) { // store the transient directory in case it's not empty restoreDocFiles << *it; diff --git a/src/Gui/DocumentRecovery.cpp b/src/Gui/DocumentRecovery.cpp index 416151042bc4..4f270f0feefe 100644 --- a/src/Gui/DocumentRecovery.cpp +++ b/src/Gui/DocumentRecovery.cpp @@ -36,6 +36,8 @@ # include # include # include +# include +# include # include # include # include @@ -58,6 +60,7 @@ #include #include +#include using namespace Gui; using namespace Gui::Dialog; @@ -445,4 +448,125 @@ DocumentRecoveryPrivate::XmlConfig DocumentRecoveryPrivate::readXmlFile(const QS return cfg; } +void DocumentRecovery::contextMenuEvent(QContextMenuEvent* ev) +{ + QList items = d_ptr->ui.treeWidget->selectedItems(); + if (!items.isEmpty()) { + QMenu menu; + QAction* rem = menu.addAction(tr("Delete"), this, SLOT(onDeleteSection())); + menu.exec(ev->globalPos()); + } +} + +void DocumentRecovery::onDeleteSection() +{ + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(tr("Cleanup")); + msgBox.setText(tr("Are you sure you want to delete the selected transient directories?")); + msgBox.setInformativeText(tr("When deleting the selected transient directory you won't be able to recover any files afterwards.")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int ret = msgBox.exec(); + if (ret == QMessageBox::No) + return; + + QList items = d_ptr->ui.treeWidget->selectedItems(); + QDir tmp = QString::fromUtf8(App::Application::getTempPath().c_str()); + for (QList::iterator it = items.begin(); it != items.end(); ++it) { + int index = d_ptr->ui.treeWidget->indexOfTopLevelItem(*it); + QTreeWidgetItem* item = d_ptr->ui.treeWidget->takeTopLevelItem(index); + + QString projectFile = item->toolTip(0); + clearDirectory(QFileInfo(tmp.filePath(projectFile))); + tmp.rmdir(projectFile); + delete item; + } + + int numItems = d_ptr->ui.treeWidget->topLevelItemCount(); + if (numItems == 0) { + d_ptr->ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + d_ptr->ui.buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(true); + } +} + +void DocumentRecovery::on_buttonCleanup_clicked() +{ + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(tr("Cleanup")); + msgBox.setText(tr("Are you sure you want to delete all transient directories?")); + msgBox.setInformativeText(tr("When deleting all transient directory you won't be able to recover any files afterwards.")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int ret = msgBox.exec(); + if (ret == QMessageBox::No) + return; + + d_ptr->ui.treeWidget->clear(); + d_ptr->ui.buttonCleanup->setEnabled(false); + d_ptr->ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + d_ptr->ui.buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(true); + + QDir tmp = QString::fromUtf8(App::Application::getTempPath().c_str()); + tmp.setNameFilters(QStringList() << QString::fromLatin1("*.lock")); + tmp.setFilter(QDir::Files); + + QList restoreDocFiles; + QString exeName = QString::fromLatin1(App::GetApplication().getExecutableName()); + QList locks = tmp.entryInfoList(); + for (QList::iterator it = locks.begin(); it != locks.end(); ++it) { + QString bn = it->baseName(); + // ignore the lock file for this instance + QString pid = QString::number(QCoreApplication::applicationPid()); + if (bn.startsWith(exeName) && bn.indexOf(pid) < 0) { + QString fn = it->absoluteFilePath(); + boost::interprocess::file_lock flock((const char*)fn.toLocal8Bit()); + if (flock.try_lock()) { + // OK, this file is a leftover from a previous crash + QString crashed_pid = bn.mid(exeName.length()+1); + // search for transient directories with this PID + QString filter; + QTextStream str(&filter); + str << exeName << "_Doc_*_" << crashed_pid; + tmp.setNameFilters(QStringList() << filter); + tmp.setFilter(QDir::Dirs); + QList dirs = tmp.entryInfoList(); + if (!dirs.isEmpty()) { + for (QList::iterator jt = dirs.begin(); jt != dirs.end(); ++jt) { + clearDirectory(*jt); + tmp.rmdir(jt->fileName()); + } + } + tmp.remove(it->fileName()); + } + } + } + + QMessageBox::information(this, tr("Finished"), tr("Transient directories deleted.")); +} + +void DocumentRecovery::clearDirectory(const QFileInfo& dir) +{ + QDir qThisDir(dir.absoluteFilePath()); + if (!qThisDir.exists()) + return; + + // Remove all files in this directory + qThisDir.setFilter(QDir::Files); + QStringList files = qThisDir.entryList(); + for (QStringList::iterator it = files.begin(); it != files.end(); ++it) { + QString file = *it; + qThisDir.remove(file); + } + + // Clear this directory of any sub-directories + qThisDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + QFileInfoList subdirs = qThisDir.entryInfoList(); + for (QFileInfoList::iterator it = subdirs.begin(); it != subdirs.end(); ++it) { + clearDirectory(*it); + qThisDir.rmdir(it->fileName()); + } +} + #include "moc_DocumentRecovery.cpp" diff --git a/src/Gui/DocumentRecovery.h b/src/Gui/DocumentRecovery.h index 3b8e9aa04b8b..966f551173ae 100644 --- a/src/Gui/DocumentRecovery.h +++ b/src/Gui/DocumentRecovery.h @@ -50,7 +50,13 @@ class DocumentRecovery : public QDialog protected: void closeEvent(QCloseEvent*); + void contextMenuEvent(QContextMenuEvent*); QString createProjectFile(const QString&); + void clearDirectory(const QFileInfo&); + +protected Q_SLOTS: + void on_buttonCleanup_clicked(); + void onDeleteSection(); private: static std::string doctools; diff --git a/src/Gui/DocumentRecovery.ui b/src/Gui/DocumentRecovery.ui index 5b85ab312eb3..37be061479e4 100644 --- a/src/Gui/DocumentRecovery.ui +++ b/src/Gui/DocumentRecovery.ui @@ -14,7 +14,7 @@ Document Recovery - + Qt::Vertical @@ -27,7 +27,7 @@ - + Press 'Start Recovery' to start the recovery process of the doument listed below. @@ -36,7 +36,7 @@ The 'Status' column shows whether the document could be recovered. - + Qt::Vertical @@ -49,15 +49,18 @@ The 'Status' column shows whether the document could be recovered. - + Status of recovered documents: - + + + QAbstractItemView::ExtendedSelection + Document Name @@ -71,6 +74,16 @@ The 'Status' column shows whether the document could be recovered. + + + true + + + Cleanup... + + + + Qt::Horizontal