diff options
author | Arno <am@disconnect.de> | 2010-11-06 13:44:10 +0100 |
---|---|---|
committer | Arno <am@disconnect.de> | 2010-11-06 13:44:10 +0100 |
commit | b62368501e5b37aea3d8d5feac884a254c71380d (patch) | |
tree | d618dcf351ddb374f47019299af8eca9a696e277 /consistencycheck.cpp | |
parent | 8230ea0228bd300316529c852858f7105ee75a3d (diff) | |
download | SheMov-b62368501e5b37aea3d8d5feac884a254c71380d.tar.gz SheMov-b62368501e5b37aea3d8d5feac884a254c71380d.tar.bz2 SheMov-b62368501e5b37aea3d8d5feac884a254c71380d.zip |
Finish ConsistencyChecker
This commit reverts the previous one. You don't need a QTimer to start a
QThread member function in a separate thread. Calling start() creates a
new thread.
Implemented filesystem check and polished the dialog.
Diffstat (limited to 'consistencycheck.cpp')
-rw-r--r-- | consistencycheck.cpp | 192 |
1 files changed, 161 insertions, 31 deletions
diff --git a/consistencycheck.cpp b/consistencycheck.cpp index 7e02304..1d5114c 100644 --- a/consistencycheck.cpp +++ b/consistencycheck.cpp @@ -20,24 +20,34 @@ #include <QBrush> #include <QTextBlock> #include <QCheckBox> -#include <QTimer> +#include <QSettings> +#include <QDir> +#include <QFileDialog> +#include <QMessageBox> #include "consistencycheck.h" #include "helper.h" ConsistencyCheck::ConsistencyCheck(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), mChecker(0){ // setup widget - mCheckLabel = new QLabel(tr("Checking database consistency")); - mDisplay = new QPlainTextEdit; - mDisplay->setReadOnly(true); + QLabel *okLabel = new QLabel(tr("Ok")); + mOkDisplay = new QPlainTextEdit; + mOkDisplay->setReadOnly(true); + mOkDisplay->setLineWrapMode(QPlainTextEdit::NoWrap); + QLabel *errorLabel = new QLabel(tr("Errors")); + mErrorDisplay = new QPlainTextEdit; + mErrorDisplay->setReadOnly(true); + mErrorDisplay->setLineWrapMode(QPlainTextEdit::NoWrap); mCancelExit = new QPushButton(tr("Close")); mCheckDb = new QPushButton(tr("Check database")); mCheckFs = new QPushButton(tr("Check Filesystem")); - mErrorsOnly = new QCheckBox(tr("Show only errors")); - connect(mErrorsOnly, SIGNAL(stateChanged(int)), this, SLOT(showErrorsChanged(int))); + mCleanup = new QPushButton(tr("Cleanup...")); + connect(mCleanup, SIGNAL(clicked()), this, SLOT(cleanup())); + mCleanup->setEnabled(false); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addWidget(mCheckDb); buttonLayout->addWidget(mCheckFs); + buttonLayout->addWidget(mCleanup); buttonLayout->addStretch(); buttonLayout->addWidget(mCancelExit); connect(mCancelExit, SIGNAL(clicked()), this, SLOT(accept())); @@ -54,41 +64,48 @@ ConsistencyCheck::ConsistencyCheck(QWidget *parent, Qt::WindowFlags f) : QDialog mChecker = new ConsistencyChecker(this); connect(mChecker, SIGNAL(started()), this, SLOT(checkerStarted())); connect(mChecker, SIGNAL(finished()), this, SLOT(checkerFinished())); + connect(mChecker, SIGNAL(consistencyMsg(QString)), this, SLOT(addMessage(QString))); // main layout QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(mCheckLabel); - mainLayout->addWidget(mDisplay); - mainLayout->addWidget(mErrorsOnly); + mainLayout->addWidget(okLabel); + mainLayout->addWidget(mOkDisplay); + mainLayout->addWidget(errorLabel); + mainLayout->addWidget(mErrorDisplay); mainLayout->addLayout(buttonLayout); setWindowTitle(tr("Checking consistency")); setLayout(mainLayout); + setMinimumWidth(600); } void ConsistencyCheck::startChecker(int checkerType){ if(mChecker->status() == ConsistencyChecker::Fail){ return; } + mOkDisplay->clear(); + mErrorDisplay->clear(); switch(checkerType){ case DbCheck: mChecker->setMode(ConsistencyCheck::DbCheck); break; case FsCheck: + mChecker->setMode(ConsistencyCheck::FsCheck); ; break; default: ; } - connect(mChecker, SIGNAL(consistencyMsg(QString)), this, SLOT(addMessage(QString))); mChecker->check(); } void ConsistencyCheck::addMessage(const QString &message){ - QTextCursor cursor(mDisplay->textCursor()); + QTextCursor cursor; QTextCharFormat fmt; if(message.startsWith("OK")){ + cursor = QTextCursor(mOkDisplay->textCursor()); fmt.setForeground(QBrush(Qt::green)); }else{ + cursor = QTextCursor(mErrorDisplay->textCursor()); fmt.setForeground(QBrush(Qt::red)); } QTextBlock curBlock = cursor.block(); @@ -114,24 +131,53 @@ void ConsistencyCheck::checkerFinished(){ mCancelExit->disconnect(); connect(mCancelExit, SIGNAL(clicked()), this, SLOT(accept())); mChecker->setCancel(false); + if(!mChecker->strayFiles().isEmpty() || !mChecker->strayIds().isEmpty()){ + mCleanup->setEnabled(true); + } } void ConsistencyCheck::cancelChecker(){ mChecker->setCancel(true); } -void ConsistencyCheck::showErrorsChanged(int state){ - QTextDocument *doc = mDisplay->document(); - for(QTextBlock it = doc->begin(); it != doc->end(); it = it.next()){ - if(it.text().startsWith("OK")){ - if(state == Qt::Checked){ - it.setVisible(false); - }else{ - it.setVisible(true); +void ConsistencyCheck::cleanup(){ + QStringList strayFiles = mChecker->strayFiles(); + moveFiles(strayFiles); + if(mChecker->mode() == DbCheck){ + QList<int> fileIds = mChecker->strayIds(); + if(!fileIds.isEmpty()){ + QString msg = QString(tr("Really delete %1 entries from database?")).arg(QString::number(fileIds.count())); + int retval = QMessageBox::critical(this, tr("Delete from database"), msg, QMessageBox::Yes | QMessageBox::No); + if(retval == QMessageBox::Yes){ + mChecker->deleteIds(fileIds); + } + } + } + mCleanup->setEnabled(false); +} + +void ConsistencyCheck::moveFiles(const QStringList &files){ + if(files.isEmpty()){ + return; + } + QSettings s; + QString startDir = s.value("paths/selecteddir").toString(); + QString targetDir = QFileDialog::getExistingDirectory(this, tr("Move stray files to..."), startDir); + if(!targetDir.isEmpty()){ + foreach(QString file, files){ + QFileInfo fi(file); + QString tgt = QString("%1%2%3").arg(targetDir).arg(QDir::separator()).arg(fi.fileName()); + QFileInfo tfi(tgt); + if(tfi.exists()){ + QString msg = QString(tr("Target %1 exists. Overwrite?")).arg(tfi.absoluteFilePath()); + int retval = QMessageBox::critical(this, tr("File exists"), msg, QMessageBox::Yes | QMessageBox::No); + if(retval == QMessageBox::No){ + continue; + } } + QFile::rename(file, tgt); } } - mDisplay->viewport()->update(); } ConsistencyChecker::ConsistencyChecker(QObject *parent) : QThread(parent), mCanceled(false), mMode(-1), mStatus(Ok){ @@ -139,6 +185,13 @@ ConsistencyChecker::ConsistencyChecker(QObject *parent) : QThread(parent), mCanc if(!mDb.open()){ mStatus = Fail; } + mFileQuery = new QSqlQuery(mDb); + mFileQuery->prepare("SELECT COUNT(*) FROM files where cmd5sum = :md5"); +} + +ConsistencyChecker::~ConsistencyChecker(){ + delete mFileQuery; + mDb.close(); } void ConsistencyChecker::check(){ @@ -147,41 +200,72 @@ void ConsistencyChecker::check(){ } } +const QStringList ConsistencyChecker::strayFiles(){ + QMutexLocker locker(&mStrayFilesMutex); + return mStrayFiles; +} + +void ConsistencyChecker::clearStrayFiles(){ + QMutexLocker locker(&mStrayFilesMutex); + mStrayFiles.clear(); +} + +const QList<int> ConsistencyChecker::strayIds(){ + QMutexLocker locker(&mStrayIdsMutex); + return mStrayIds; +} + +void ConsistencyChecker::clearStrayIds(){ + QMutexLocker locker(&mStrayIdsMutex); + mStrayIds.clear(); +} + void ConsistencyChecker::setCancel(bool cancel){ QMutexLocker locker(&mCancelMutex); mCanceled = cancel; } -ConsistencyChecker::~ConsistencyChecker(){ - mDb.close(); +void ConsistencyChecker::deleteIds(const QList<int> &ids){ + QSqlQuery idQuery(mDb); + idQuery.prepare("DELETE FROM files WHERE ifiles_id = :id"); + foreach(int id, ids){ + idQuery.bindValue(":id", id); + idQuery.exec(); + } } void ConsistencyChecker::run(){ - switch(mMode){ - case ConsistencyCheck::DbCheck: - QTimer::singleShot(0, this, SLOT(dbCheck())); - exec(); - break; - default: - ; + clearStrayFiles(); + clearStrayIds(); + if(mMode == ConsistencyCheck::FsCheck){ + fsCheck(); + } + if(mMode == ConsistencyCheck::DbCheck){ + dbCheck(); } } void ConsistencyChecker::dbCheck(){ - QSqlQuery fileDbQuery = QSqlQuery("SELECT tfilename, cmd5sum, idvd FROM files ORDER BY tfilename", mDb); + QSqlQuery fileDbQuery = QSqlQuery("SELECT tfilename, cmd5sum, idvd, ifiles_id FROM files ORDER BY tfilename", mDb); while(fileDbQuery.next()){ QMutexLocker locker(&mCancelMutex); if(mCanceled){ - return; + quit(); + }else{ + locker.unlock(); } QString fileName = fileDbQuery.value(0).toString(); QString md5sum = fileDbQuery.value(1).toString(); int dvdNo = fileDbQuery.value(2).toInt(); + int fileId = fileDbQuery.value(3).toInt(); QString fullPath = archivePath(fileName, md5sum); if(fullPath.isEmpty()){ if(dvdNo != -1){ emit consistencyMsg(QString(tr("OK: %1")).arg(fileName)); }else{ + mStrayIdsMutex.lock(); + mStrayIds << fileId; + mStrayIdsMutex.unlock(); emit consistencyMsg(QString(tr("NOT FOUND: %1")).arg(fileName)); } }else{ @@ -192,6 +276,9 @@ void ConsistencyChecker::dbCheck(){ if(mimeType.startsWith("image")){ emit consistencyMsg(QString(tr("OK: %1")).arg(fileName)); }else{ + mStrayFilesMutex.lock(); + mStrayFiles << fullPath; + mStrayFilesMutex.unlock(); QString msg = QString(tr("FOUND: %1 (DVD: %2)")).arg(fullPath).arg(dvdNo); emit consistencyMsg(msg); } @@ -201,6 +288,49 @@ void ConsistencyChecker::dbCheck(){ quit(); } +void ConsistencyChecker::fsCheck(){ + mStrayFilesMutex.lock(); + mStrayFiles.clear(); + mStrayFilesMutex.unlock(); + QSettings s; + QString startDir = s.value("paths/archivedir").toString(); + QFileInfo startFi(startDir); + doFsCheck(startFi); + quit(); +} + +void ConsistencyChecker::doFsCheck(const QFileInfo &start){ + if(start.isDir()){ + QMutexLocker locker(&mCancelMutex); + if(mCanceled){ + quit(); + }else{ + locker.unlock(); + } + QDir curDir(start.absoluteFilePath()); + foreach(QFileInfo fi, curDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)){ + if(fi.isDir()){ + doFsCheck(fi); + }else{ + QString md5sum = Helper::md5Sum(fi.absoluteFilePath()); + mFileQuery->bindValue(":md5sum", md5sum); + mFileQuery->exec(); + while(mFileQuery->next()){ + int count = mFileQuery->value(0).toInt(); + if(count > 0){ + emit consistencyMsg(QString(tr("OK: %1 -> %2")).arg(fi.fileName()).arg(md5sum)); + }else{ + mStrayFilesMutex.lock(); + mStrayFiles << fi.absoluteFilePath(); + mStrayFilesMutex.unlock(); + emit consistencyMsg(QString(tr("NOT FOUND: %1 -> %2")).arg(fi.fileName()).arg(md5sum)); + } + } + } + } + } +} + QString ConsistencyChecker::archivePath(const QString &fileName, const QString &md5sum) const { QString filePath = Helper::createArchivePath(fileName, md5sum); QFileInfo fi(filePath); |