diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 42c65a7..f969aaf 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -17,260 +17,277 @@ #include "../shared/sqlitesearch.h" #include "../shared/qssgeneralexception.h" MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow) + QMainWindow(parent), + ui(new Ui::MainWindow) { - ui->setupUi(this); + ui->setupUi(this); + QSettings settings; - db = QSqlDatabase::addDatabase("QSQLITE"); - db.setDatabaseName(QSettings().value("dbpath").toString()); - if(!db.open()) - { - qDebug() << "failed to open database"; - throw std::runtime_error("Failed to open database"); - } - connectSignals(); - ui->treeResultsList->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); - ui->tabWidget->setCurrentIndex(0); - ui->statusBar->addWidget(ui->lblSearchResults); - ui->statusBar->addWidget(ui->pdfProcessBar); - ui->pdfProcessBar->hide(); - QSettings settings; - ui->comboScale->setCurrentText(settings.value("currentScale").toString()); + db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName(settings.value("dbpath").toString()); + if(!db.open()) + { + qDebug() << "failed to open database"; + throw std::runtime_error("Failed to open database"); + } + connectSignals(); + ui->treeResultsList->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu); + ui->tabWidget->setCurrentIndex(0); + ui->statusBar->addWidget(ui->lblSearchResults); + ui->statusBar->addWidget(ui->pdfProcessBar); + ui->pdfProcessBar->hide(); + ui->comboScale->setCurrentText(settings.value("currentScale").toString()); + pdfPreviewsPerPage = settings.value("pdfPreviewsPerPage", 20).toInt(); + ui->spinPdfPreviewPage->setMinimum(1); } void MainWindow::connectSignals() { - connect(ui->txtSearch, &QLineEdit::returnPressed, this, &MainWindow::lineEditReturnPressed); - connect(&searchWatcher, &QFutureWatcher::finished, this, [&]{ - try - { - auto results = searchWatcher.future().result(); - handleSearchResults(results); - } - catch(QSSGeneralException &e) - { - handleSearchError(e.message); - } + connect(ui->txtSearch, &QLineEdit::returnPressed, this, &MainWindow::lineEditReturnPressed); + connect(&searchWatcher, &QFutureWatcher::finished, this, [&]{ + try + { + auto results = searchWatcher.future().result(); + handleSearchResults(results); + } + catch(QSSGeneralException &e) + { + handleSearchError(e.message); + } - }); + }); - connect(&pdfWorkerWatcher, &QFutureWatcher::resultReadyAt, this, [&](int index) { - pdfPreviewReceived(pdfWorkerWatcher.resultAt(index)); - }); - connect(&pdfWorkerWatcher, &QFutureWatcher::progressValueChanged, ui->pdfProcessBar, &QProgressBar::setValue); - connect(ui->treeResultsList, &QTreeWidget::itemActivated, this, &MainWindow::treeSearchItemActivated); - connect(ui->treeResultsList, &QTreeWidget::customContextMenuRequested, this, &MainWindow::showSearchResultsContextMenu); - connect(ui->tabWidget, &QTabWidget::currentChanged, this, &MainWindow::tabChanged); - connect(ui->comboScale, qOverload(&QComboBox::currentIndexChanged), this, &MainWindow::comboScaleChanged); + connect(&pdfWorkerWatcher, &QFutureWatcher::resultReadyAt, this, [&](int index) { + pdfPreviewReceived(pdfWorkerWatcher.resultAt(index)); + }); + connect(&pdfWorkerWatcher, &QFutureWatcher::progressValueChanged, ui->pdfProcessBar, &QProgressBar::setValue); + connect(ui->treeResultsList, &QTreeWidget::itemActivated, this, &MainWindow::treeSearchItemActivated); + connect(ui->treeResultsList, &QTreeWidget::customContextMenuRequested, this, &MainWindow::showSearchResultsContextMenu); + connect(ui->tabWidget, &QTabWidget::currentChanged, this, &MainWindow::tabChanged); + connect(ui->comboScale, qOverload(&QComboBox::currentIndexChanged), this, &MainWindow::comboScaleChanged); + connect(ui->spinPdfPreviewPage, qOverload(&QSpinBox::valueChanged), this, &MainWindow::spinPdfPreviewPageValueChanged); + +} + +void MainWindow::spinPdfPreviewPageValueChanged(int val) +{ + makePdfPreview(val); } void MainWindow::comboScaleChanged(QString text) { - QSettings scaleSetting; - scaleSetting.setValue("currentScale", ui->comboScale->currentText()); - makePdfPreview(); + QSettings scaleSetting; + scaleSetting.setValue("currentScale", ui->comboScale->currentText()); + makePdfPreview(ui->spinPdfPreviewPage->value()); } bool MainWindow::pdfTabActive() { - return ui->tabWidget->currentIndex() == 1; + return ui->tabWidget->currentIndex() == 1; } void MainWindow::keyPressEvent(QKeyEvent *event) { - bool quit = ((event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Q) || event->key() == Qt::Key_Escape); - if(quit) - { - qApp->quit(); - } + bool quit = ((event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_Q) || event->key() == Qt::Key_Escape); + if(quit) + { + qApp->quit(); + } - if(event->modifiers() & Qt::ControlModifier) - { + if(event->modifiers() & Qt::ControlModifier) + { - if(event->key() == Qt::Key_L) - { - ui->txtSearch->setFocus(); - ui->txtSearch->selectAll(); - } - } - QWidget::keyPressEvent(event); + if(event->key() == Qt::Key_L) + { + ui->txtSearch->setFocus(); + ui->txtSearch->selectAll(); + } + } + QWidget::keyPressEvent(event); } void MainWindow::tabChanged() { - if(pdfTabActive()) - { - if(pdfDirty) - { - makePdfPreview(); - } - ui->pdfProcessBar->show(); - } - else - { - ui->pdfProcessBar->hide(); - } + if(pdfTabActive()) + { + if(pdfDirty) + { + makePdfPreview(ui->spinPdfPreviewPage->value()); + } + ui->pdfProcessBar->show(); + } + else + { + ui->pdfProcessBar->hide(); + } } void MainWindow::pdfPreviewReceived(PdfPreview preview) { - if(preview.hasPreviewImage()) - { - ClickLabel *label = new ClickLabel(); - label->setPixmap(QPixmap::fromImage(preview.previewImage)); - label->setToolTip(preview.documentPath); - ui->scrollAreaWidgetContents->layout()->addWidget(label); - connect(label, &ClickLabel::leftClick, [=]() { - QSettings settings; - QString command = settings.value("pdfviewer").toString(); - if(command != "" && command.contains("%p") && command.contains("%f")) - { - QStringList splitted = command.split(" "); - if(splitted.size() > 1) - { - QString cmd = splitted[0]; - QStringList args = splitted.mid(1); - args.replaceInStrings("%f", preview.documentPath); - args.replaceInStrings("%p", QString::number(preview.page)); + if(preview.hasPreviewImage()) + { + ClickLabel *label = new ClickLabel(); + label->setPixmap(QPixmap::fromImage(preview.previewImage)); + label->setToolTip(preview.documentPath); + ui->scrollAreaWidgetContents->layout()->addWidget(label); + connect(label, &ClickLabel::leftClick, [=]() { + QSettings settings; + QString command = settings.value("pdfviewer").toString(); + if(command != "" && command.contains("%p") && command.contains("%f")) + { + QStringList splitted = command.split(" "); + if(splitted.size() > 1) + { + QString cmd = splitted[0]; + QStringList args = splitted.mid(1); + args.replaceInStrings("%f", preview.documentPath); + args.replaceInStrings("%p", QString::number(preview.page)); - QProcess::startDetached(cmd, args); - } - } - else - { - QDesktopServices::openUrl(QUrl::fromLocalFile(preview.documentPath)); - } - }); - } + QProcess::startDetached(cmd, args); + } + } + else + { + QDesktopServices::openUrl(QUrl::fromLocalFile(preview.documentPath)); + } + }); + } } void MainWindow::lineEditReturnPressed() { - QString q = ui->txtSearch->text(); - if(!QSSQuery::checkParanthesis(q)) - { - ui->lblSearchResults->setText("Invalid paranthesis"); - return; - } - //TODO: validate q; - ui->lblSearchResults->setText("Searching..."); - searchWatcher.cancel(); - searchWatcher.waitForFinished(); - QFuture> searchFuture = QtConcurrent::run([&, q]() { - SqliteSearch searcher(db); - this->currentQuery = QSSQuery::build(q); - return searcher.search(this->currentQuery); - }); - searchWatcher.setFuture(searchFuture); + QString q = ui->txtSearch->text(); + if(!QSSQuery::checkParanthesis(q)) + { + ui->lblSearchResults->setText("Invalid paranthesis"); + return; + } + //TODO: validate q; + ui->lblSearchResults->setText("Searching..."); + searchWatcher.cancel(); + searchWatcher.waitForFinished(); + QFuture> searchFuture = QtConcurrent::run([&, q]() { + SqliteSearch searcher(db); + this->currentQuery = QSSQuery::build(q); + return searcher.search(this->currentQuery); + }); + searchWatcher.setFuture(searchFuture); } void MainWindow::handleSearchResults(const QVector &results) { - this->pdfSearchResults.clear(); - ui->treeResultsList->clear(); - ui->lblSearchResults->setText("Results: " + QString::number(results.size())); - for(const SearchResult &result : results) - { - QFileInfo pathInfo(result.fileData.absPath); - QString fileName =pathInfo.fileName(); - QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeResultsList); + this->pdfSearchResults.clear(); + ui->treeResultsList->clear(); + ui->lblSearchResults->setText("Results: " + QString::number(results.size())); + for(const SearchResult &result : results) + { + QFileInfo pathInfo(result.fileData.absPath); + QString fileName =pathInfo.fileName(); + QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeResultsList); - QDateTime dt = QDateTime::fromSecsSinceEpoch(result.fileData.mtime); - item->setIcon(0, iconProvider.icon(pathInfo)); - item->setText(0, fileName); - item->setText(1, result.fileData.absPath); - item->setText(2, dt.toString(Qt::ISODate)); - item->setText(3, this->locale().formattedDataSize(result.fileData.size)); - if(result.fileData.absPath.endsWith(".pdf")) - { - this->pdfSearchResults.append(result); - } - } - ui->treeResultsList->resizeColumnToContents(0); - ui->treeResultsList->resizeColumnToContents(1); - pdfDirty = ! this->pdfSearchResults.empty(); - if(pdfTabActive() && pdfDirty) - { - makePdfPreview(); - } + QDateTime dt = QDateTime::fromSecsSinceEpoch(result.fileData.mtime); + item->setIcon(0, iconProvider.icon(pathInfo)); + item->setText(0, fileName); + item->setText(1, result.fileData.absPath); + item->setText(2, dt.toString(Qt::ISODate)); + item->setText(3, this->locale().formattedDataSize(result.fileData.size)); + if(result.fileData.absPath.endsWith(".pdf")) + { + this->pdfSearchResults.append(result); + } + } + ui->treeResultsList->resizeColumnToContents(0); + ui->treeResultsList->resizeColumnToContents(1); + pdfDirty = ! this->pdfSearchResults.empty(); + + int numpages = ceil(static_cast(this->pdfSearchResults.size()) / pdfPreviewsPerPage); + ui->spinPdfPreviewPage->setMinimum(1); + ui->spinPdfPreviewPage->setMaximum(numpages); + ui->spinPdfPreviewPage->setValue(1); + if(pdfTabActive() && pdfDirty) + { + makePdfPreview(1); + } } -void MainWindow::makePdfPreview() +void MainWindow::makePdfPreview(int page) { - this->pdfWorkerWatcher.cancel(); - this->pdfWorkerWatcher.waitForFinished(); + this->pdfWorkerWatcher.cancel(); + this->pdfWorkerWatcher.waitForFinished(); - QCoreApplication::processEvents(); //Maybe not necessary anymore, depends on whether it's possible that a slot is still to be fired. - qDeleteAll(ui->scrollAreaWidgetContents->children()); + QCoreApplication::processEvents(); //Maybe not necessary anymore, depends on whether it's possible that a slot is still to be fired. + qDeleteAll(ui->scrollAreaWidgetContents->children()); - ui->scrollAreaWidgetContents->setLayout(new QHBoxLayout()); - ui->pdfProcessBar->setMaximum(this->pdfSearchResults.size()); - processedPdfPreviews = 0; - QString scaleText = ui->comboScale->currentText(); - scaleText.chop(1); + ui->scrollAreaWidgetContents->setLayout(new QHBoxLayout()); + ui->pdfProcessBar->setMaximum(this->pdfSearchResults.size()); + processedPdfPreviews = 0; + QString scaleText = ui->comboScale->currentText(); + scaleText.chop(1); - QVector wordsToHighlight; - QRegularExpression extractor(R"#("([^"]*)"|(\w+))#"); - for(const Token &token : this->currentQuery.getTokens()) - { - if(token.type == FILTER_CONTENT_CONTAINS) - { - QRegularExpressionMatchIterator i = extractor.globalMatch(token.value); - while(i.hasNext()) - { - QRegularExpressionMatch m = i.next(); - QString value = m.captured(1); - if(value.isEmpty()) - { - value = m.captured(2); - } - wordsToHighlight.append(value); + QVector wordsToHighlight; + QRegularExpression extractor(R"#("([^"]*)"|(\w+))#"); + for(const Token &token : this->currentQuery.getTokens()) + { + if(token.type == FILTER_CONTENT_CONTAINS) + { + QRegularExpressionMatchIterator i = extractor.globalMatch(token.value); + while(i.hasNext()) + { + QRegularExpressionMatch m = i.next(); + QString value = m.captured(1); + if(value.isEmpty()) + { + value = m.captured(2); + } + wordsToHighlight.append(value); - } - } - } - PdfWorker worker; - this->pdfWorkerWatcher.setFuture(worker.generatePreviews(this->pdfSearchResults, wordsToHighlight, scaleText.toInt() / 100.)); - ui->pdfProcessBar->setMaximum(this->pdfWorkerWatcher.progressMaximum()); - ui->pdfProcessBar->setMinimum(this->pdfWorkerWatcher.progressMinimum()); + } + } + } + PdfWorker worker; + int end = pdfPreviewsPerPage; + int begin = page * pdfPreviewsPerPage - pdfPreviewsPerPage; + this->pdfWorkerWatcher.setFuture(worker.generatePreviews(this->pdfSearchResults.mid(begin, end), wordsToHighlight, scaleText.toInt() / 100.)); + ui->pdfProcessBar->setMaximum(this->pdfWorkerWatcher.progressMaximum()); + ui->pdfProcessBar->setMinimum(this->pdfWorkerWatcher.progressMinimum()); } void MainWindow::handleSearchError(QString error) { - ui->lblSearchResults->setText("Error:" + error); + ui->lblSearchResults->setText("Error:" + error); } void MainWindow::treeSearchItemActivated(QTreeWidgetItem *item, int i) { - QDesktopServices::openUrl(QUrl::fromLocalFile(item->text(1))); + QDesktopServices::openUrl(QUrl::fromLocalFile(item->text(1))); } void MainWindow::showSearchResultsContextMenu(const QPoint &point) { - QTreeWidgetItem *item = ui->treeResultsList->itemAt(point); - if(item == nullptr) - { - return; - } - QMenu menu("SearchResult", this); - menu.addAction("Copy filename to clipboard", [&] { QGuiApplication::clipboard()->setText(item->text(0));}); - menu.addAction("Copy full path to clipboard", [&] { QGuiApplication::clipboard()->setText(item->text(1)); }); - menu.addAction("Open containing folder", [&] { - QFileInfo pathinfo(item->text(1)); - QString dir = pathinfo.absolutePath(); - QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); + QTreeWidgetItem *item = ui->treeResultsList->itemAt(point); + if(item == nullptr) + { + return; + } + QMenu menu("SearchResult", this); + menu.addAction("Copy filename to clipboard", [&] { QGuiApplication::clipboard()->setText(item->text(0));}); + menu.addAction("Copy full path to clipboard", [&] { QGuiApplication::clipboard()->setText(item->text(1)); }); + menu.addAction("Open containing folder", [&] { + QFileInfo pathinfo(item->text(1)); + QString dir = pathinfo.absolutePath(); + QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); - }); - menu.exec(QCursor::pos()); + }); + menu.exec(QCursor::pos()); } MainWindow::~MainWindow() { - delete ui; + delete ui; } + diff --git a/gui/mainwindow.h b/gui/mainwindow.h index dbb7ae2..ae5b5aa 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -34,13 +34,14 @@ private: void add(QString path, unsigned int page); QVector pdfSearchResults; void connectSignals(); - void makePdfPreview(); + void makePdfPreview(int page); bool pdfTabActive(); void keyPressEvent(QKeyEvent *event) override; unsigned int processedPdfPreviews; void handleSearchResults(const QVector &results); void handleSearchError(QString error); QSSQuery currentQuery; + int pdfPreviewsPerPage; private slots: void lineEditReturnPressed(); void treeSearchItemActivated(QTreeWidgetItem *item, int i); @@ -48,7 +49,7 @@ private slots: void tabChanged(); void pdfPreviewReceived(PdfPreview preview); void comboScaleChanged(QString text); - + void spinPdfPreviewPageValueChanged(int val); }; #endif // MAINWINDOW_H diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index 8de1fd7..3cf967d 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -148,6 +148,26 @@ + + + + Page: + + + + + + + QAbstractSpinBox::PlusMinus + + + false + + + false + + +