From 330a9e5870f806b843083828eb3e3d84870ca3e0 Mon Sep 17 00:00:00 2001 From: Albert S Date: Tue, 30 Apr 2019 14:13:10 +0200 Subject: [PATCH] gui: stop generating preview images after a memory limit has been reached. --- gui/mainwindow.cpp | 58 ++++++++++++++++++++++----------------------- gui/pdfpreview.h | 5 ++++ gui/pdfworker.cpp | 59 +++++++++++++++++++++++++++++++--------------- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index e48a250..b06da51 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -116,32 +116,35 @@ void MainWindow::tabChanged() void MainWindow::pdfPreviewReceived(PdfPreview preview) { - 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")) + 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, + [=]() { - command = command.replace("%f", preview.documentPath); - command = command.replace("%p", QString::number(preview.page)); - QStringList splitted = command.split(" "); - if(splitted.size() > 1) + QSettings settings; + QString command = settings.value("pdfviewer").toString(); + if(command != "" && command.contains("%p") && command.contains("%f")) { - QString cmd = splitted[0]; - QStringList args = splitted.mid(1); - QProcess::startDetached(cmd, args); + command = command.replace("%f", preview.documentPath); + command = command.replace("%p", QString::number(preview.page)); + QStringList splitted = command.split(" "); + if(splitted.size() > 1) + { + QString cmd = splitted[0]; + QStringList args = splitted.mid(1); + QProcess::startDetached(cmd, args); + } } - } - else - { - QDesktopServices::openUrl(QUrl::fromLocalFile(preview.documentPath)); - } - }); + else + { + QDesktopServices::openUrl(QUrl::fromLocalFile(preview.documentPath)); + } + }); + } } void MainWindow::lineEditReturnPressed() @@ -179,14 +182,9 @@ void MainWindow::handleSearchResults(const QVector &results) item->setText(0, fileName); item->setText(1, result.fileData.absPath); item->setText(2, dt.toString(Qt::ISODate)); - - // TODO: this must be user defined or done more intelligently - if(this->pdfSearchResults.size() < 300) + if(result.fileData.absPath.endsWith(".pdf")) { - if(result.fileData.absPath.endsWith(".pdf")) - { - this->pdfSearchResults.append(result); - } + this->pdfSearchResults.append(result); } } ui->treeResultsList->resizeColumnToContents(0); diff --git a/gui/pdfpreview.h b/gui/pdfpreview.h index 10d2bd3..b04997e 100644 --- a/gui/pdfpreview.h +++ b/gui/pdfpreview.h @@ -9,6 +9,11 @@ class PdfPreview QImage previewImage; QString documentPath; unsigned int page; + + bool hasPreviewImage() + { + return !previewImage.isNull(); + } }; #endif // PDFPREVIEW_H diff --git a/gui/pdfworker.cpp b/gui/pdfworker.cpp index c792fe5..8696be3 100644 --- a/gui/pdfworker.cpp +++ b/gui/pdfworker.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "pdfworker.h" static QMutex cacheMutex; @@ -16,10 +17,22 @@ struct Renderer double scaleX; double scaleY; QHash documentcache; - Renderer(double scaleX, double scaleY) + qsizetype maxTotalPreviewImageMemUsage; + std::atomic currentTotalPreviewImageMemUsage{0}; + + Renderer(double scaleX, double scaleY, qsizetype maxPreviewImageMemUsage) { this->scaleX = scaleX; this->scaleY = scaleY; + this->maxTotalPreviewImageMemUsage = maxPreviewImageMemUsage; + } + + /*we need this one because std::atomic has none, but this is only a functor for + concurrentmap, thus, it's ok for it to be half-broken*/ + Renderer(const Renderer &o) + { + this->scaleX = o.scaleX; + this->scaleY = o.scaleY; } ~Renderer() @@ -35,7 +48,7 @@ struct Renderer Poppler::Document *result = Poppler::Document::load(path); if(result == nullptr) { - // TODO: some kind of user feedback would be nicec + // TODO: some kind of user feedback would be nice return nullptr; } result->setRenderHint(Poppler::Document::TextAntialiasing); @@ -46,23 +59,28 @@ struct Renderer PdfPreview operator()(const PdfPreview &preview) { - Poppler::Document *doc = document(preview.documentPath); - if(doc == nullptr) - { - return preview; - } - if(doc->isLocked()) - { - return preview; - } - int p = (int)preview.page - 1; - if(p < 0) - { - p = 0; - } - Poppler::Page *pdfPage = doc->page(p); PdfPreview result = preview; - result.previewImage = pdfPage->renderToImage(scaleX, scaleY); + if(currentTotalPreviewImageMemUsage.load() < maxTotalPreviewImageMemUsage) + { + Poppler::Document *doc = document(preview.documentPath); + if(doc == nullptr) + { + return preview; + } + if(doc->isLocked()) + { + return preview; + } + int p = (int)preview.page - 1; + if(p < 0) + { + p = 0; + } + Poppler::Page *pdfPage = doc->page(p); + QImage img = pdfPage->renderToImage(scaleX, scaleY); + result.previewImage = img; + currentTotalPreviewImageMemUsage += img.sizeInBytes(); + } return result; } }; @@ -85,5 +103,8 @@ QFuture PdfWorker::generatePreviews(const QVector path double scaleX = QGuiApplication::primaryScreen()->physicalDotsPerInchX() * scalefactor; double scaleY = QGuiApplication::primaryScreen()->physicalDotsPerInchY() * scalefactor; - return QtConcurrent::mapped(previews, Renderer(scaleX, scaleY)); + QSettings setting; + qsizetype maxPreviewImageMemUsage = setting.value("maxpreviewimagesmemory", 1024 * 1024 * 1024).toLongLong(); + + return QtConcurrent::mapped(previews, Renderer(scaleX, scaleY, maxPreviewImageMemUsage)); }