Skip to content

Commit

Permalink
Display error message inside viewport instead of as a modal dialog
Browse files Browse the repository at this point in the history
Thanks to @fkubicek for some of the ideas that made this possible
  • Loading branch information
jdpurcell committed Dec 28, 2023
1 parent 75a10be commit 819d75c
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 41 deletions.
35 changes: 23 additions & 12 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,19 @@ void MainWindow::paintEvent(QPaintEvent *event)
}
}
}
else if (customBackgroundColor.isValid())
{
painter.fillRect(viewportRect, customBackgroundColor);
}
else
{
painter.eraseRect(viewportRect);
const QColor &backgroundColor = customBackgroundColor.isValid() ? customBackgroundColor : painter.background().color();
painter.fillRect(viewportRect, backgroundColor);

if (getCurrentFileDetails().errorData.has_value())
{
const QVImageCore::ErrorData &errorData = getCurrentFileDetails().errorData.value();
const QString errorMessage = tr("Error occurred opening\n%3\n%2 (Error %1)").arg(QString::number(errorData.errorNum), errorData.errorString, getCurrentFileDetails().fileInfo.fileName());
painter.setFont(font());
painter.setPen(Qv::getPerceivedBrightness(backgroundColor) > 0.5 ? QColorConstants::Black : QColorConstants::White);
painter.drawText(viewportRect, errorMessage, QTextOption(Qt::AlignCenter));
}
}
}
}
Expand Down Expand Up @@ -399,6 +405,9 @@ void MainWindow::fileChanged(const bool isRestoringState)
updateWindowFilePath();
if (!isRestoringState)
setWindowSize();

// full repaint to handle error message
update();
}

void MainWindow::zoomLevelChanged()
Expand Down Expand Up @@ -523,13 +532,15 @@ void MainWindow::buildWindowTitle()
QString newString = "qView";
if (getCurrentFileDetails().fileInfo.isFile())
{
auto getFileName = [this]() { return getCurrentFileDetails().fileInfo.fileName(); };
auto getZoomLevel = [this]() { return QString::number(graphicsView->getZoomLevel() * 100.0, 'f', 1) + "%"; };
auto getImageIndex = [this]() { return QString::number(getCurrentFileDetails().loadedIndexInFolder+1); };
auto getImageCount = [this]() { return QString::number(getCurrentFileDetails().folderFileInfoList.count()); };
auto getImageWidth = [this]() { return QString::number(getCurrentFileDetails().baseImageSize.width()); };
auto getImageHeight = [this]() { return QString::number(getCurrentFileDetails().baseImageSize.height()); };
auto getFileSize = [this]() { return QVInfoDialog::formatBytes(getCurrentFileDetails().fileInfo.size()); };
const QVImageCore::FileDetails &fileDetails = getCurrentFileDetails();
const bool hasError = fileDetails.errorData.has_value();
auto getFileName = [&]() { return fileDetails.fileInfo.fileName(); };
auto getZoomLevel = [&]() { return QString::number((hasError ? 1.0 : graphicsView->getZoomLevel()) * 100.0, 'f', 1) + "%"; };
auto getImageIndex = [&]() { return QString::number(fileDetails.loadedIndexInFolder+1); };
auto getImageCount = [&]() { return QString::number(fileDetails.folderFileInfoList.count()); };
auto getImageWidth = [&]() { return QString::number(hasError ? 0 : fileDetails.baseImageSize.width()); };
auto getImageHeight = [&]() { return QString::number(hasError ? 0 : fileDetails.baseImageSize.height()); };
auto getFileSize = [&]() { return QVInfoDialog::formatBytes(hasError ? 0 : fileDetails.fileInfo.size()); };
switch (qvApp->getSettingsManager().getEnum<Qv::TitleBarText>("titlebarmode")) {
case Qv::TitleBarText::Minimal:
{
Expand Down
11 changes: 0 additions & 11 deletions src/qvgraphicsview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ QVGraphicsView::QVGraphicsView(QWidget *parent) : QGraphicsView(parent)

connect(&imageCore, &QVImageCore::animatedFrameChanged, this, &QVGraphicsView::animatedFrameChanged);
connect(&imageCore, &QVImageCore::fileChanged, this, &QVGraphicsView::postLoad);
connect(&imageCore, &QVImageCore::readError, this, &QVGraphicsView::error);

expensiveScaleTimer = new QTimer(this);
expensiveScaleTimer->setSingleShot(true);
Expand Down Expand Up @@ -928,16 +927,6 @@ MainWindow* QVGraphicsView::getMainWindow() const
return qobject_cast<MainWindow*>(window());
}

void QVGraphicsView::error(int errorNum, const QString &errorString, const QString &fileName)
{
if (!errorString.isEmpty())
{
closeImage();
QMessageBox::critical(this, tr("Error"), tr("Error occurred opening \"%3\":\n%2 (Error %1)").arg(QString::number(errorNum), errorString, fileName));
return;
}
}

void QVGraphicsView::settingsUpdated()
{
auto &settingsManager = qvApp->getSettingsManager();
Expand Down
2 changes: 0 additions & 2 deletions src/qvgraphicsview.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ private slots:

void postLoad();

void error(int errorNum, const QString &errorString, const QString &fileName);

private:
QGraphicsPixmapItem *loadedPixmapItem;

Expand Down
56 changes: 42 additions & 14 deletions src/qvimagecore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ void QVImageCore::loadFile(const QString &fileName, bool isReloading)
else
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
loadFutureWatcher.setFuture(QtConcurrent::run(this, &QVImageCore::readFile, sanitaryFileName, targetColorSpace, false));
loadFutureWatcher.setFuture(QtConcurrent::run(this, &QVImageCore::readFile, sanitaryFileName, targetColorSpace));
#else
loadFutureWatcher.setFuture(QtConcurrent::run(&QVImageCore::readFile, this, sanitaryFileName, targetColorSpace, false));
loadFutureWatcher.setFuture(QtConcurrent::run(&QVImageCore::readFile, this, sanitaryFileName, targetColorSpace));
#endif
}
}

QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, const QColorSpace &targetColorSpace, bool forCache)
QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, const QColorSpace &targetColorSpace)
{
QImageReader imageReader;
imageReader.setDecideFormatFromContent(true);
Expand Down Expand Up @@ -155,19 +155,33 @@ QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, const QColo
fileInfo.absoluteFilePath(),
fileInfo.size(),
imageReader.size(),
targetColorSpace
targetColorSpace,
{}
};
// Only error out when not loading for cache
if (readPixmap.isNull() && !forCache)

if (readPixmap.isNull())
{
emit readError(imageReader.error(), imageReader.errorString(), fileInfo.fileName());
readData.errorData = {
imageReader.error(),
imageReader.errorString()
};
}

return readData;
}

void QVImageCore::loadPixmap(const ReadData &readData)
{
if (readData.errorData.has_value())
{
currentFileDetails = getEmptyFileDetails();
currentFileDetails.errorData = readData.errorData;
}
else
{
currentFileDetails.errorData = {};
}

// Do this first so we can keep folder info even when loading errored files
currentFileDetails.fileInfo = QFileInfo(readData.absoluteFilePath);
currentFileDetails.updateLoadedIndexInFolder();
Expand All @@ -177,8 +191,11 @@ void QVImageCore::loadPixmap(const ReadData &readData)
// Reset mechanism to avoid stalling while loading
waitingOnLoad = false;

if (readData.pixmap.isNull())
if (currentFileDetails.errorData.has_value())
{
loadEmptyPixmap();
return;
}

loadedPixmap = readData.pixmap;

Expand Down Expand Up @@ -223,11 +240,23 @@ void QVImageCore::loadPixmap(const ReadData &readData)
}

void QVImageCore::closeImage()
{
currentFileDetails = getEmptyFileDetails();
loadEmptyPixmap();
}

void QVImageCore::loadEmptyPixmap()
{
loadedPixmap = QPixmap();
loadedMovie.stop();
loadedMovie.setFileName("");
currentFileDetails = {

emit fileChanged();
}

QVImageCore::FileDetails QVImageCore::getEmptyFileDetails()
{
return {
QFileInfo(),
currentFileDetails.folderFileInfoList,
currentFileDetails.loadedIndexInFolder,
Expand All @@ -236,10 +265,9 @@ void QVImageCore::closeImage()
false,
QSize(),
QSize(),
QElapsedTimer()
QElapsedTimer(),
{}
};

emit fileChanged();
}

// All file logic, sorting, etc should be moved to a different class or file
Expand Down Expand Up @@ -459,9 +487,9 @@ void QVImageCore::requestCachingFile(const QString &filePath, const QColorSpace
});

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
cacheFutureWatcher->setFuture(QtConcurrent::run(this, &QVImageCore::readFile, filePath, targetColorSpace, true));
cacheFutureWatcher->setFuture(QtConcurrent::run(this, &QVImageCore::readFile, filePath, targetColorSpace));
#else
cacheFutureWatcher->setFuture(QtConcurrent::run(&QVImageCore::readFile, this, filePath, targetColorSpace, true));
cacheFutureWatcher->setFuture(QtConcurrent::run(&QVImageCore::readFile, this, filePath, targetColorSpace));
#endif
}

Expand Down
15 changes: 13 additions & 2 deletions src/qvimagecore.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define QVIMAGECORE_H

#include "qvnamespace.h"
#include <optional>
#include <QObject>
#include <QImageReader>
#include <QPixmap>
Expand Down Expand Up @@ -35,6 +36,12 @@ class QVImageCore : public QObject
QString mimeType;
};

struct ErrorData
{
int errorNum;
QString errorString;
};

struct FileDetails
{
QFileInfo fileInfo;
Expand All @@ -46,6 +53,7 @@ class QVImageCore : public QObject
QSize baseImageSize;
QSize loadedPixmapSize;
QElapsedTimer timeSinceLoaded;
std::optional<ErrorData> errorData;

void updateLoadedIndexInFolder();
};
Expand All @@ -57,12 +65,13 @@ class QVImageCore : public QObject
qint64 fileSize;
QSize imageSize;
QColorSpace targetColorSpace;
std::optional<ErrorData> errorData;
};

explicit QVImageCore(QObject *parent = nullptr);

void loadFile(const QString &fileName, bool isReloading = false);
ReadData readFile(const QString &fileName, const QColorSpace &targetColorSpace, bool forCache);
ReadData readFile(const QString &fileName, const QColorSpace &targetColorSpace);
void loadPixmap(const ReadData &readData);
void closeImage();
QList<CompatibleFile> getCompatibleFiles(const QString &dirPath);
Expand Down Expand Up @@ -94,7 +103,9 @@ class QVImageCore : public QObject

void fileChanged();

void readError(int errorNum, const QString &errorString, const QString &fileName);
protected:
void loadEmptyPixmap();
FileDetails getEmptyFileDetails();

private:
QPixmap loadedPixmap;
Expand Down
6 changes: 6 additions & 0 deletions src/qvnamespace.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef QVNAMESPACE_H
#define QVNAMESPACE_H

#include <QColor>
#include <QSet>
#include <QString>

Expand Down Expand Up @@ -123,6 +124,11 @@ namespace Qv
action == ViewportScrollAction::None ||
action == ViewportScrollAction::Pan;
}

inline qreal getPerceivedBrightness(const QColor &color)
{
return (color.red() * 0.299 + color.green() * 0.587 + color.blue() * 0.114) / 255.0;
}
}

#endif // QVNAMESPACE_H

0 comments on commit 819d75c

Please sign in to comment.