/** * @brief MainWindow::startFileHasher */ void MainWindow::startFileHasher() { if (!filelist->writeLock(true)) { return; } if (filelist->isHashCompleted()) { QMessageBox msgBox(QMessageBox::Question, "Hasher", "All listed files have already been scanned. Erase all old hashed values?"); msgBox.addButton(tr("Erase and rescan"), QMessageBox::ActionRole); QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort); msgBox.exec(); if (msgBox.clickedButton() == abortButton) { filelist->writeLock(false); return; } filelist->removeHashes(); verifyFilesButton->setVisible(false); } else if (filelist->isHashPartiallyCompleted()) { QMessageBox msgBox(QMessageBox::Question, "Hasher", "Some of the listed files have already been scanned. How to proceed?"); msgBox.addButton(tr("Scan only unscanned files."), QMessageBox::ActionRole); QPushButton *clearButton = msgBox.addButton(tr("Erase all old values and rescan"), QMessageBox::ActionRole); QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort); msgBox.exec(); if (msgBox.clickedButton() == clearButton) { filelist->removeHashes(); } else if (msgBox.clickedButton() == abortButton) { filelist->writeLock(false); return; } } startProcessWork(); progressbar->setMaximum(filelist->rowCount()); emit processWorkStarted(); emit hashFiles(mainproject, false, mainproject->getSourceDirectory()->getPath()); }
/** * @brief FileDrop::dropEvent * * Called by the window manager when the files have been dropped on the widget. * Will create File nodes for all files and add them to the project file list. */ void FileDrop::dropEvent(QDropEvent *event) { if (hasWriteLock) { filelist->writeLock(false); QList<QUrl> urlList; if (event->mimeData()->hasUrls()) { urlList = event->mimeData()->urls(); } if ((urlList.size() == 1) && (QFileInfo(urlList.first().path()).isDir())) { emit directoryDropped(urlList.first().path()); emit startProcessWork(); } } clear(); event->acceptProposedAction(); }
/** * @brief MainWindow::startFileFinder * Removes all list entries and starts scanning with the file finder thread. * If the list isn't empty, a confirmation dialog will be displayed. */ void MainWindow::startFileFinder() { if (!filelist->writeLock(true)) { return; } if (!filelist->isEmpty()) { QMessageBox msgBox(QMessageBox::Warning, "File Finder", "The list of files will be cleared and the scan will start from the beginning. Proceed?"); msgBox.addButton(QMessageBox::Ok); QPushButton *abortButton = msgBox.addButton(QMessageBox::Cancel); msgBox.exec(); if (msgBox.clickedButton() == abortButton) { filelist->writeLock(false); return; } } filelist->clearContents(); startProcessWork(); emit processWorkStarted(); emit findFiles(mainproject); }
/** * @brief MainWindow::startVerifyFiles */ void MainWindow::startVerifyFiles() { if (!filelist->writeLock(true)) { return; } if (!filelist->isHashPartiallyCompleted()) { filelist->writeLock(false); return; } if (filelist->isVerficationCompleted()) { QMessageBox msgBox(QMessageBox::Question, "Verifier", "All listed files have already been verified. Redo everyting?"); msgBox.addButton(tr("Verify everything again."), QMessageBox::ActionRole); QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort); msgBox.exec(); if (msgBox.clickedButton() == abortButton) { filelist->writeLock(false); return; } filelist->removeVerifications(); } else if (filelist->isVerificationPartiallyCompleted()) { QMessageBox msgBox(QMessageBox::Question, "Verifier", "Some of the listed files have already been verified. Redo everyting?"); msgBox.addButton(tr("Scan only the unverified files."), QMessageBox::ActionRole); QPushButton *clearButton = msgBox.addButton(tr("Erase all old values and verify again."), QMessageBox::ActionRole); QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort); msgBox.exec(); if (msgBox.clickedButton() == clearButton) { filelist->removeVerifications(); } else if (msgBox.clickedButton() == abortButton) { filelist->writeLock(false); return; } } startProcessWork(); progressbar->setMaximum(filelist->rowCount()); emit processWorkStarted(); emit hashFiles(mainproject, true, mainproject->getVerifyDirectory()->getPath()); }
/** * @brief MainWindow::createWorkerThreads * * Creates the objects with the processing algorithms that are to be run i separate threads. * As of now they are one instance of Hasher and one instad of FileFinder. * Each instance is put in a QThread. * * To prevent race conditions, before doing any processing (calling a slot in the threads) * a call to processWorkStarted() must be made. When the threads are finished with the actions, * they will announce this with a signal to MainWindow::actionStopped. */ void MainWindow::createWorkerThreads() { hasher = new Hasher; filefinder = new FileFinder; hasherthread = new QThread; filefinderthread = new QThread; filefinder->moveToThread(filefinderthread); hasher->moveToThread(hasherthread); filefinderthread->start(); hasherthread->start(); connect(this, SIGNAL(findFiles(HashProject*)), filefinder, SLOT(scanProject(HashProject*))); connect(this, SIGNAL(hashFiles(HashProject*, bool, QString)), hasher, SLOT(hashProject(HashProject*, bool, QString))); connect(filefinder, SIGNAL(fileFound(HashProject::File, bool)), filelist, SLOT(addFile(HashProject::File, bool))); connect(filelist, SIGNAL(hashFile(int, QString, HashProject::File, QString)), hasher, SLOT(hashFile(int, QString, HashProject::File, QString))); connect(hasher, SIGNAL(fileHashCalculated(int, QString, QString, bool)), filelist, SLOT(fileHashCalculated(int, QString, QString, bool))); /** * Signal path between the three threads when announcing that they are finished: * Example, scanning for files using filefinder: * filefinder.scanFinished -> filelist.fileAdditionFinished -> hasher.scanFinished -> filelist.processingDone -> mainwindow.actionStopped * Example, hashing files after dropping them: * filelist.fileAdditionFinished -> hasher.scanFinished -> filelist.processingDone -> mainwindow.actionStopped * Example, hashing a project: * hasher.hashproject -> hasher.scanFinished -> filelist.processingDone -> mainwindow.actionStopped */ connect(this, SIGNAL(processWorkStarted()), hasher, SLOT(startProcessWork())); connect(filefinder, SIGNAL(scanFinished()), filelist, SLOT(fileAdditionFinished())); connect(filelist, SIGNAL(noMoreFileJobs()), hasher, SLOT(noMoreFiles())); connect(hasher, SIGNAL(scanFinished()), filelist, SLOT(hashingFinished())); connect(filelist, SIGNAL(processingDone()), this, SLOT(actionStopped())); connect(hasher, SIGNAL(progressstatus(int)), progressbar, SLOT(setValue(int))); }
/** * @brief MainWindow::MainWindow * @param parent */ MainWindow::MainWindow(HashCalcApplication* parent) : QMainWindow() { setWindowTitle(tr("File Hash Calculator")); setAttribute(Qt::WA_DeleteOnClose, true); setWindowIcon(QIcon(":/mainicon.icns")); isOpeningNewProject = false; parentapp = parent; mainproject = new HashProject; filelist = mainproject->getDataTable(); createActionButtonBox(); createDirectoryBoxes(); createOptionsBox(); createWorkerThreads(); createFileDisplayBox(); statusBox = new StatusBoxWidget; filedrop = new FileDrop(filelist); connect(filedrop, SIGNAL(startProcessWork()), this, SLOT(startFileFinder())); connect(filedrop, SIGNAL(directoryDropped(QString)), mainproject->getSourceDirectory(), SLOT(setPath(QString))); QVBoxLayout* controlLayout = new QVBoxLayout; controlLayout->addWidget(sourceDirectoryBox); controlLayout->addWidget(verifyDirectoryBox); controlLayout->addWidget(optionsBox); controlLayout->addWidget(statusBox); controlLayout->addWidget(actionButtonBox); controlLayout->addWidget(filedrop); controlLayout->setAlignment(displayFileBox, Qt::AlignTop); controlLayout->setContentsMargins(0, 0, 0, 0); optionsBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); actionButtonBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); statusBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); filedrop->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); controlWidgets = new QWidget; controlWidgets->setLayout(controlLayout); QVBoxLayout* rightLayout = new QVBoxLayout; rightLayout->addWidget(displayFileBox); rightLayout->addWidget(filelist); QWidget *rightWidget = new QWidget; rightLayout->setContentsMargins(0, 0, 0, 0); rightWidget->setLayout(rightLayout); mainWidget = new QSplitter(this); mainWidget->addWidget(controlWidgets); mainWidget->addWidget(rightWidget); mainWidget->setMinimumSize(1000, 750); mainWidget->setChildrenCollapsible(false); mainWidget->setCollapsible(0, false); mainWidget->setCollapsible(1, false); mainWidget->setStretchFactor(0, 0); mainWidget->setStretchFactor(1, 100); setCentralWidget(mainWidget); actions = new MenuActions(this); actions->createMenus(); QSettings settings; algorithmComboBox->setCurrentText(settings.value("selectedalgorithm", "CRC32").toString()); calcHashSumWhenFoundCheckbox->setChecked(settings.value("calchashsumwhenfound", false).toBool()); if (!calcHashSumWhenFoundCheckbox->isChecked()) { hashCalculationOwnThreadCheckbox->setEnabled(false); } hashCalculationOwnThreadCheckbox->setChecked(settings.value("hashcalculationownthread", true).toBool()); mainWidget->restoreState(settings.value("splittersizes").toByteArray()); connect(filelist, SIGNAL(displayFile(QString,QString)), this, SLOT(updateFileDisplay(QString,QString))); connect(filelist, SIGNAL(fileListSizeChanged(int, int, int, int)), statusBox, SLOT(updateStatusBox(int, int, int, int))); connect(filelist, SIGNAL(fileListSizeChanged(int, int, int, int)), actions, SLOT(filelistChanged(int, int, int, int))); }