summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <am@disconnect.de>2010-11-06 13:44:10 +0100
committerArno <am@disconnect.de>2010-11-06 13:44:10 +0100
commitb62368501e5b37aea3d8d5feac884a254c71380d (patch)
treed618dcf351ddb374f47019299af8eca9a696e277
parent8230ea0228bd300316529c852858f7105ee75a3d (diff)
downloadSheMov-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.
-rw-r--r--consistencycheck.cpp192
-rw-r--r--consistencycheck.h26
2 files changed, 182 insertions, 36 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);
diff --git a/consistencycheck.h b/consistencycheck.h
index 2f934fc..f5470e3 100644
--- a/consistencycheck.h
+++ b/consistencycheck.h
@@ -12,12 +12,15 @@
#include <QThread>
#include <QSqlDatabase>
#include <QMutex>
+#include <QStringList>
+#include <QList>
class QPushButton;
class QPlainTextEdit;
class QLabel;
class QString;
-class QCheckBox;
+class QSqlQuery;
+class QFileInfo;
class ConsistencyChecker;
class ConsistencyCheck : public QDialog {
@@ -32,15 +35,16 @@ class ConsistencyCheck : public QDialog {
void checkerStarted();
void checkerFinished();
void cancelChecker();
- void showErrorsChanged(int state);
+ void cleanup();
private:
+ void moveFiles(const QStringList &files);
QPushButton *mCancelExit;
QPushButton *mCheckDb;
QPushButton *mCheckFs;
- QPlainTextEdit *mDisplay;
- QLabel *mCheckLabel;
- QCheckBox *mErrorsOnly;
+ QPushButton *mCleanup;
+ QPlainTextEdit *mOkDisplay;
+ QPlainTextEdit *mErrorDisplay;
ConsistencyChecker *mChecker;
};
@@ -55,12 +59,18 @@ class ConsistencyChecker : public QThread {
int status() const { return mStatus; }
void setStatus(int status) { mStatus = status; }
void check();
+ const QStringList strayFiles();
+ void clearStrayFiles();
+ const QList<int> strayIds();
+ void clearStrayIds();
public slots:
void setCancel(bool cancel);
+ void deleteIds(const QList<int> &ids);
private slots:
void dbCheck();
+ void fsCheck();
signals:
void consistencyMsg(const QString &msg);
@@ -70,11 +80,17 @@ class ConsistencyChecker : public QThread {
private:
QString archivePath(const QString &fileName, const QString &md5sum) const;
+ void doFsCheck(const QFileInfo &start);
bool mCanceled;
int mMode;
int mStatus;
QSqlDatabase mDb;
+ QSqlQuery *mFileQuery;
QMutex mCancelMutex;
+ QMutex mStrayFilesMutex;
+ QMutex mStrayIdsMutex;
+ QStringList mStrayFiles;
+ QList<int> mStrayIds;
};
#endif // CONSISTENCYCHECK_H