gui: stop generating preview images after a memory limit has been reached.

This commit is contained in:
Albert S. 2019-04-30 14:13:10 +02:00
parent 5deb64cd28
commit 330a9e5870
3 changed files with 73 additions and 49 deletions

View File

@ -116,32 +116,35 @@ void MainWindow::tabChanged()
void MainWindow::pdfPreviewReceived(PdfPreview preview) void MainWindow::pdfPreviewReceived(PdfPreview preview)
{ {
ClickLabel *label = new ClickLabel(); if(preview.hasPreviewImage())
label->setPixmap(QPixmap::fromImage(preview.previewImage)); {
label->setToolTip(preview.documentPath); ClickLabel *label = new ClickLabel();
ui->scrollAreaWidgetContents->layout()->addWidget(label); label->setPixmap(QPixmap::fromImage(preview.previewImage));
connect(label, &ClickLabel::leftClick, 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"))
{ {
command = command.replace("%f", preview.documentPath); QSettings settings;
command = command.replace("%p", QString::number(preview.page)); QString command = settings.value("pdfviewer").toString();
QStringList splitted = command.split(" "); if(command != "" && command.contains("%p") && command.contains("%f"))
if(splitted.size() > 1)
{ {
QString cmd = splitted[0]; command = command.replace("%f", preview.documentPath);
QStringList args = splitted.mid(1); command = command.replace("%p", QString::number(preview.page));
QProcess::startDetached(cmd, args); QStringList splitted = command.split(" ");
if(splitted.size() > 1)
{
QString cmd = splitted[0];
QStringList args = splitted.mid(1);
QProcess::startDetached(cmd, args);
}
} }
} else
else {
{ QDesktopServices::openUrl(QUrl::fromLocalFile(preview.documentPath));
QDesktopServices::openUrl(QUrl::fromLocalFile(preview.documentPath)); }
} });
}); }
} }
void MainWindow::lineEditReturnPressed() void MainWindow::lineEditReturnPressed()
@ -179,14 +182,9 @@ void MainWindow::handleSearchResults(const QVector<SearchResult> &results)
item->setText(0, fileName); item->setText(0, fileName);
item->setText(1, result.fileData.absPath); item->setText(1, result.fileData.absPath);
item->setText(2, dt.toString(Qt::ISODate)); item->setText(2, dt.toString(Qt::ISODate));
if(result.fileData.absPath.endsWith(".pdf"))
// TODO: this must be user defined or done more intelligently
if(this->pdfSearchResults.size() < 300)
{ {
if(result.fileData.absPath.endsWith(".pdf")) this->pdfSearchResults.append(result);
{
this->pdfSearchResults.append(result);
}
} }
} }
ui->treeResultsList->resizeColumnToContents(0); ui->treeResultsList->resizeColumnToContents(0);

View File

@ -9,6 +9,11 @@ class PdfPreview
QImage previewImage; QImage previewImage;
QString documentPath; QString documentPath;
unsigned int page; unsigned int page;
bool hasPreviewImage()
{
return !previewImage.isNull();
}
}; };
#endif // PDFPREVIEW_H #endif // PDFPREVIEW_H

View File

@ -6,6 +6,7 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include <QtConcurrent/QtConcurrentMap> #include <QtConcurrent/QtConcurrentMap>
#include <atomic>
#include "pdfworker.h" #include "pdfworker.h"
static QMutex cacheMutex; static QMutex cacheMutex;
@ -16,10 +17,22 @@ struct Renderer
double scaleX; double scaleX;
double scaleY; double scaleY;
QHash<QString, Poppler::Document *> documentcache; QHash<QString, Poppler::Document *> documentcache;
Renderer(double scaleX, double scaleY) qsizetype maxTotalPreviewImageMemUsage;
std::atomic<qsizetype> currentTotalPreviewImageMemUsage{0};
Renderer(double scaleX, double scaleY, qsizetype maxPreviewImageMemUsage)
{ {
this->scaleX = scaleX; this->scaleX = scaleX;
this->scaleY = scaleY; 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() ~Renderer()
@ -35,7 +48,7 @@ struct Renderer
Poppler::Document *result = Poppler::Document::load(path); Poppler::Document *result = Poppler::Document::load(path);
if(result == nullptr) if(result == nullptr)
{ {
// TODO: some kind of user feedback would be nicec // TODO: some kind of user feedback would be nice
return nullptr; return nullptr;
} }
result->setRenderHint(Poppler::Document::TextAntialiasing); result->setRenderHint(Poppler::Document::TextAntialiasing);
@ -46,23 +59,28 @@ struct Renderer
PdfPreview operator()(const PdfPreview &preview) 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; 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; return result;
} }
}; };
@ -85,5 +103,8 @@ QFuture<PdfPreview> PdfWorker::generatePreviews(const QVector<SearchResult> path
double scaleX = QGuiApplication::primaryScreen()->physicalDotsPerInchX() * scalefactor; double scaleX = QGuiApplication::primaryScreen()->physicalDotsPerInchX() * scalefactor;
double scaleY = QGuiApplication::primaryScreen()->physicalDotsPerInchY() * 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));
} }