/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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); mCancelExit = new QPushButton(tr("Cancel")); 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))); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addWidget(mCheckDb); buttonLayout->addWidget(mCheckFs); buttonLayout->addStretch(); buttonLayout->addWidget(mCancelExit); connect(mCancelExit, SIGNAL(clicked()), this, SLOT(cancelExit())); // signal mapper QSignalMapper *mapper = new QSignalMapper(this); connect(mCheckDb, SIGNAL(clicked()), mapper, SLOT(map())); mapper->setMapping(mCheckDb, ConsistencyCheck::DbCheck); connect(mCheckFs, SIGNAL(clicked()), mapper, SLOT(map())); mapper->setMapping(mCheckFs, ConsistencyCheck::FsCheck); connect(mapper, SIGNAL(mapped(int)), this, SLOT(startChecker(int))); // main layout QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mCheckLabel); mainLayout->addWidget(mDisplay); mainLayout->addWidget(mErrorsOnly); mainLayout->addLayout(buttonLayout); setWindowTitle(tr("Checking consistency")); setLayout(mainLayout); } void ConsistencyCheck::startChecker(int checkerType){ mChecker = new ConsistencyChecker; if(mChecker->status() == ConsistencyChecker::Fail){ return; } switch(checkerType){ case DbCheck: mChecker->setMode(ConsistencyCheck::DbCheck); break; case FsCheck: ; break; default: ; } connect(mChecker, SIGNAL(consistencyMsg(QString)), this, SLOT(addMessage(QString))); mChecker->check(); } void ConsistencyCheck::addMessage(const QString &message){ QTextCursor cursor(mDisplay->textCursor()); QTextCharFormat fmt; if(message.startsWith("OK")){ fmt.setForeground(QBrush(Qt::green)); }else{ fmt.setForeground(QBrush(Qt::red)); } QTextBlock curBlock = cursor.block(); if(!curBlock.text().isEmpty()){ cursor.insertBlock(); } cursor.setCharFormat(fmt); cursor.insertText(message); } void ConsistencyCheck::cancelExit(){ if(mChecker->isRunning()){ mChecker->cancel(true); mCancelExit->setText(tr("Close")); connect(mCancelExit, SIGNAL(clicked()), this, SLOT(accept())); }else{ close(); } } 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){ qDebug() << it.text(); it.setVisible(false); }else{ it.setVisible(true); } } } mDisplay->viewport()->update(); } ConsistencyChecker::ConsistencyChecker(QObject *parent) : QThread(parent), mCanceled(false), mMode(-1), mStatus(Ok){ mDb = QSqlDatabase::cloneDatabase(QSqlDatabase::database("treedb"), "checkerDb"); if(!mDb.open()){ mStatus = Fail; } } void ConsistencyChecker::check(){ if(!isRunning()){ start(); } } void ConsistencyChecker::cancel(bool cancel){ if(!cancel){ return; } QMutexLocker locker(&mCancelMutex); mCanceled = true; } ConsistencyChecker::~ConsistencyChecker(){ mDb.close(); } void ConsistencyChecker::run(){ switch(mMode){ case ConsistencyCheck::DbCheck: dbCheck(); break; default: ; } } void ConsistencyChecker::dbCheck(){ QSqlQuery fileDbQuery = QSqlQuery("SELECT tfilename, cmd5sum, idvd FROM files ORDER BY tfilename", mDb); while(fileDbQuery.next()){ QMutexLocker locker(&mCancelMutex); if(mCanceled){ return; } QString fileName = fileDbQuery.value(0).toString(); QString md5sum = fileDbQuery.value(1).toString(); int dvdNo = fileDbQuery.value(2).toInt(); QString fullPath = archivePath(fileName, md5sum); if(fullPath.isEmpty()){ if(dvdNo != -1){ emit consistencyMsg(QString(tr("OK: %1")).arg(fileName)); }else{ emit consistencyMsg(QString(tr("NOT FOUND: %1")).arg(fileName)); } }else{ if(dvdNo == -1){ emit consistencyMsg(QString(tr("OK: %1")).arg(fileName)); }else{ QString mimeType = Helper::mimeType(fullPath); if(mimeType.startsWith("image")){ emit consistencyMsg(QString(tr("OK: %1")).arg(fileName)); }else{ QString msg = QString(tr("FOUND: %1 (DVD: %2)")).arg(fullPath).arg(dvdNo); emit consistencyMsg(msg); } } } } } QString ConsistencyChecker::archivePath(const QString &fileName, const QString &md5sum) const { QString filePath = Helper::createArchivePath(fileName, md5sum); QFileInfo fi(filePath); if(!fi.exists()){ filePath = Helper::createArchivePath(fileName, md5sum, true); fi = QFileInfo(filePath); if(!fi.exists()){ filePath.clear(); } } return filePath; }