1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
#include "./direrrorsdialog.h"
#include <syncthingconnector/syncthingconnection.h>
#include <syncthingconnector/syncthingdir.h>
#include <syncthingconnector/utils.h>
#include <QDir>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QStringBuilder>
#include <QTextBrowser>
#include <QVBoxLayout>
#include <algorithm>
#include <iostream>
#include <limits>
#include <utility>
using namespace std;
using namespace CppUtilities;
using namespace Data;
namespace QtGui {
DirectoryErrorsDialog::DirectoryErrorsDialog(const Data::SyncthingConnection &connection, const Data::SyncthingDir &dir, QWidget *parent)
: TextViewDialog(tr("Errors for folder %1").arg(dir.displayName()), parent)
, m_connection(connection)
, m_dirId(dir.id)
{
// add layout to show status and additional buttons
auto *const buttonLayout = new QHBoxLayout;
buttonLayout->setContentsMargins(0, 0, 0, 0);
layout()->addLayout(buttonLayout);
// add label for overall status
m_statusLabel = new QLabel(this);
QFont boldFont(m_statusLabel->font());
boldFont.setBold(true);
m_statusLabel->setFont(boldFont);
buttonLayout->addWidget(m_statusLabel);
// add a button for removing all non-empty directories
m_rmNonEmptyDirsButton = new QPushButton(this);
m_rmNonEmptyDirsButton->setText(tr("Remove non-empty directories"));
m_rmNonEmptyDirsButton->setIcon(QIcon::fromTheme(QStringLiteral("remove")));
buttonLayout->setContentsMargins(0, 0, 0, 0);
buttonLayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
buttonLayout->addWidget(m_rmNonEmptyDirsButton);
// connect signals and slots
connect(&connection, &SyncthingConnection::dirStatusChanged, this, &DirectoryErrorsDialog::handleDirStatusChanged);
connect(&connection, &SyncthingConnection::newDirs, this, &DirectoryErrorsDialog::handleNewDirs);
connect(m_rmNonEmptyDirsButton, &QPushButton::clicked, this, &DirectoryErrorsDialog::removeNonEmptyDirs);
// populate initially available errors
updateErrors(dir);
}
DirectoryErrorsDialog::~DirectoryErrorsDialog()
{
}
void DirectoryErrorsDialog::handleDirStatusChanged(const SyncthingDir &dir)
{
if (dir.id == m_dirId) {
updateErrors(dir);
}
}
void DirectoryErrorsDialog::handleNewDirs()
{
auto index = int();
if (const auto *const dir = m_connection.findDirInfo(m_dirId, index)) {
updateErrors(*dir);
}
}
void DirectoryErrorsDialog::updateErrors(const Data::SyncthingDir &dir)
{
// update status
m_statusLabel->setText(tr("%1 item(s) out-of-sync", nullptr, trQuandity(dir.pullErrorCount)).arg(dir.pullErrorCount));
m_rmNonEmptyDirsButton->setHidden(m_nonEmptyDirs.empty());
// clear previous errors
auto *const textBrowser = browser();
textBrowser->clear();
m_nonEmptyDirs.clear();
// add item errors to textBrowser
for (const SyncthingItemError &error : dir.itemErrors) {
textBrowser->append(error.path % QChar(':') % QChar('\n') % error.message % QChar('\n'));
if (error.message.endsWith(QStringLiteral("directory not empty"))) {
m_nonEmptyDirs << dir.path + error.path;
}
}
}
QString printDirectories(const QString &message, const QStringList &dirs)
{
return QStringLiteral("<p>") % message % QStringLiteral("</p><ul><li>") % dirs.join(QStringLiteral("</li><li>")) % QStringLiteral("</ul>");
}
void DirectoryErrorsDialog::removeNonEmptyDirs()
{
auto index = int();
const auto *const dir = m_connection.findDirInfo(m_dirId, index);
if (!dir) {
return;
}
const QString title(tr("Remove non-empty directories for folder \"%1\"").arg(dir->displayName()));
if (QMessageBox::warning(this, title, printDirectories(tr("Do you really want to remove the following directories:"), m_nonEmptyDirs),
QMessageBox::YesToAll | QMessageBox::NoToAll, QMessageBox::NoToAll)
!= QMessageBox::YesToAll) {
return;
}
QStringList removedDirs, failedDirs;
for (const auto &dirPath : std::as_const(m_nonEmptyDirs)) {
auto ok = false;
auto dirObj = QDir(dirPath);
if (!dirObj.exists() || !dirObj.removeRecursively()) {
// check whether dir has already been removed by removing its parent
for (const auto &removedDir : std::as_const(removedDirs)) {
if (dirPath.startsWith(removedDir)) {
ok = true;
break;
}
}
} else {
ok = true;
}
(ok ? removedDirs : failedDirs) << dirPath;
}
if (!failedDirs.isEmpty()) {
QMessageBox::critical(this, title, printDirectories(tr("Unable to remove the following dirs:"), failedDirs));
}
}
} // namespace QtGui
|