From 285cc2befa6a02a7c7402dcb5f85ec8d015874fa Mon Sep 17 00:00:00 2001 From: fkubicek <66724409+fkubicek@users.noreply.github.com> Date: Sun, 3 Dec 2023 19:47:24 +0100 Subject: [PATCH 1/3] Change error emitting flow Simplify how error signals are emitted and make more data about errors available to MainWindow. --- src/mainwindow.cpp | 9 ++++--- src/qvgraphicsview.cpp | 11 -------- src/qvgraphicsview.h | 2 -- src/qvimagecore.cpp | 57 +++++++++++++++++++++++++++++++----------- src/qvimagecore.h | 15 +++++++++-- 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e6969546..1e6d5dbd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -449,9 +449,12 @@ void MainWindow::buildWindowTitle() newString = QString::number(getCurrentFileDetails().loadedIndexInFolder+1); newString += "/" + QString::number(getCurrentFileDetails().folderFileInfoList.count()); newString += " - " + getCurrentFileDetails().fileInfo.fileName(); - newString += " - " + QString::number(getCurrentFileDetails().baseImageSize.width()); - newString += "x" + QString::number(getCurrentFileDetails().baseImageSize.height()); - newString += " - " + QVInfoDialog::formatBytes(getCurrentFileDetails().fileInfo.size()); + if (!getCurrentFileDetails().errorData.hasError) + { + newString += " - " + QString::number(getCurrentFileDetails().baseImageSize.width()); + newString += "x" + QString::number(getCurrentFileDetails().baseImageSize.height()); + newString += " - " + QVInfoDialog::formatBytes(getCurrentFileDetails().fileInfo.size()); + } newString += " - qView"; break; } diff --git a/src/qvgraphicsview.cpp b/src/qvgraphicsview.cpp index b5c604f9..d2b54334 100644 --- a/src/qvgraphicsview.cpp +++ b/src/qvgraphicsview.cpp @@ -53,7 +53,6 @@ QVGraphicsView::QVGraphicsView(QWidget *parent) : QGraphicsView(parent) connect(&imageCore, &QVImageCore::animatedFrameChanged, this, &QVGraphicsView::animatedFrameChanged); connect(&imageCore, &QVImageCore::fileChanged, this, &QVGraphicsView::postLoad); connect(&imageCore, &QVImageCore::updateLoadedPixmapItem, this, &QVGraphicsView::updateLoadedPixmapItem); - connect(&imageCore, &QVImageCore::readError, this, &QVGraphicsView::error); // Should replace the other timer eventually expensiveScaleTimerNew = new QTimer(this); @@ -681,16 +680,6 @@ void QVGraphicsView::centerOn(const QGraphicsItem *item) centerOn(item->sceneBoundingRect().center()); } -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(); diff --git a/src/qvgraphicsview.h b/src/qvgraphicsview.h index d2fb8624..9cb65e2a 100644 --- a/src/qvgraphicsview.h +++ b/src/qvgraphicsview.h @@ -113,8 +113,6 @@ private slots: void updateLoadedPixmapItem(); - void error(int errorNum, const QString &errorString, const QString &fileName); - private: diff --git a/src/qvimagecore.cpp b/src/qvimagecore.cpp index 0fecd73b..d70b3f7c 100644 --- a/src/qvimagecore.cpp +++ b/src/qvimagecore.cpp @@ -115,14 +115,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); @@ -164,12 +164,17 @@ 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 = { + true, + imageReader.error(), + imageReader.errorString() + }; } return readData; @@ -177,6 +182,16 @@ QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, const QColo void QVImageCore::loadPixmap(const ReadData &readData) { + if (readData.errorData.hasError) + { + 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(); @@ -186,8 +201,11 @@ void QVImageCore::loadPixmap(const ReadData &readData) // Reset mechanism to avoid stalling while loading waitingOnLoad = false; - if (readData.pixmap.isNull()) + if (currentFileDetails.errorData.hasError) + { + loadEmptyPixmap(); return; + } loadedPixmap = matchCurrentRotation(readData.pixmap); @@ -232,11 +250,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, @@ -245,10 +275,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 @@ -479,9 +508,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 } diff --git a/src/qvimagecore.h b/src/qvimagecore.h index 20e5f0fd..960dc031 100644 --- a/src/qvimagecore.h +++ b/src/qvimagecore.h @@ -34,6 +34,13 @@ class QVImageCore : public QObject QString mimeType; }; + struct ErrorData + { + bool hasError; + int errorNum; + QString errorString; + }; + struct FileDetails { QFileInfo fileInfo; @@ -45,6 +52,7 @@ class QVImageCore : public QObject QSize baseImageSize; QSize loadedPixmapSize; QElapsedTimer timeSinceLoaded; + ErrorData errorData; void updateLoadedIndexInFolder(); }; @@ -56,12 +64,13 @@ class QVImageCore : public QObject qint64 fileSize; QSize imageSize; QColorSpace targetColorSpace; + 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 getCompatibleFiles(const QString &dirPath) const; @@ -99,7 +108,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; From 0a415559071b2efb0fb93055b61e719a62ea0300 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Sun, 9 Jun 2024 13:04:23 -0400 Subject: [PATCH 2/3] Handle our own background painting --- src/mainwindow.cpp | 17 +++++++++++++++++ src/mainwindow.h | 4 ++++ src/qvgraphicsview.cpp | 16 +--------------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1e6d5dbd..ddf49717 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -39,6 +39,7 @@ MainWindow::MainWindow(QWidget *parent) : { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_OpaquePaintEvent); // Initialize variables justLaunchedWithImage = false; @@ -266,6 +267,16 @@ void MainWindow::mouseDoubleClickEvent(QMouseEvent *event) QMainWindow::mouseDoubleClickEvent(event); } +void MainWindow::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + QPainter painter(this); + + const QColor &backgroundColor = customBackgroundColor.isValid() ? customBackgroundColor : painter.background().color(); + painter.fillRect(rect(), backgroundColor); +} + void MainWindow::openFile(const QString &fileName) { graphicsView->loadFile(fileName); @@ -278,6 +289,9 @@ void MainWindow::settingsUpdated() buildWindowTitle(); + //bgcolor + customBackgroundColor = settingsManager.getBoolean("bgcolorenabled") ? QColor(settingsManager.getString("bgcolor")) : QColor(); + // menubarenabled bool menuBarEnabled = settingsManager.getBoolean("menubarenabled"); #ifdef Q_OS_MACOS @@ -300,6 +314,9 @@ void MainWindow::settingsUpdated() ui->fullscreenLabel->setVisible(qvApp->getSettingsManager().getBoolean("fullscreendetails") && (windowState() == Qt::WindowFullScreen)); setWindowSize(); + + // repaint in case background color changed + update(); } void MainWindow::shortcutsUpdated() diff --git a/src/mainwindow.h b/src/mainwindow.h index ba1676c1..a50f753f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -141,6 +141,8 @@ public slots: void mouseDoubleClickEvent(QMouseEvent *event) override; + void paintEvent(QPaintEvent *event) override; + protected slots: void settingsUpdated(); void shortcutsUpdated(); @@ -158,6 +160,8 @@ protected slots: QVInfoDialog *info; + QColor customBackgroundColor; + bool justLaunchedWithImage; Qt::WindowStates storedWindowState; diff --git a/src/qvgraphicsview.cpp b/src/qvgraphicsview.cpp index d2b54334..cebcc24a 100644 --- a/src/qvgraphicsview.cpp +++ b/src/qvgraphicsview.cpp @@ -20,6 +20,7 @@ QVGraphicsView::QVGraphicsView(QWidget *parent) : QGraphicsView(parent) setDragMode(QGraphicsView::ScrollHandDrag); setFrameShape(QFrame::NoFrame); setTransformationAnchor(QGraphicsView::NoAnchor); + viewport()->setAutoFillBackground(false); // part of a pathetic attempt at gesture support grabGesture(Qt::PinchGesture); @@ -684,21 +685,6 @@ void QVGraphicsView::settingsUpdated() { auto &settingsManager = qvApp->getSettingsManager(); - //bgcolor - QBrush newBrush; - newBrush.setStyle(Qt::SolidPattern); - if (!settingsManager.getBoolean("bgcolorenabled")) - { - newBrush.setColor(QColor(0, 0, 0, 0)); - } - else - { - QColor newColor; - newColor.setNamedColor(settingsManager.getString("bgcolor")); - newBrush.setColor(newColor); - } - setBackgroundBrush(newBrush); - //filtering if (settingsManager.getBoolean("filteringenabled")) loadedPixmapItem->setTransformationMode(Qt::SmoothTransformation); From 0df0c118e37cbcfc9785cc20ca054acaf4dca40a Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Sun, 9 Jun 2024 13:20:41 -0400 Subject: [PATCH 3/3] Draw error message inside viewport --- src/mainwindow.cpp | 31 ++++++++++++++++++++++++++----- src/mainwindow.h | 2 ++ src/qvapplication.cpp | 5 +++++ src/qvapplication.h | 2 ++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ddf49717..73896c03 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -273,8 +273,20 @@ void MainWindow::paintEvent(QPaintEvent *event) QPainter painter(this); + const int viewportY = qMax(getTitlebarOverlap(), graphicsView->mapTo(this, QPoint()).y()); + const QRect viewportRect = rect().adjusted(0, viewportY, 0, 0); + const QColor &backgroundColor = customBackgroundColor.isValid() ? customBackgroundColor : painter.background().color(); painter.fillRect(rect(), backgroundColor); + + if (getCurrentFileDetails().errorData.hasError && viewportRect.isValid()) + { + const QVImageCore::ErrorData &errorData = getCurrentFileDetails().errorData; + 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(QVApplication::getPerceivedBrightness(backgroundColor) > 0.5 ? Qt::black : Qt::white); + painter.drawText(viewportRect, errorMessage, QTextOption(Qt::AlignCenter)); + } } void MainWindow::openFile(const QString &fileName) @@ -350,6 +362,9 @@ void MainWindow::fileChanged() if (info->isVisible()) refreshProperties(); buildWindowTitle(); + + // repaint to handle error message + update(); } void MainWindow::disableActions() @@ -531,11 +546,7 @@ void MainWindow::setWindowSize() if (menuBar()->isVisible()) extraWidgetsSize.rheight() += menuBar()->height(); - int titlebarOverlap = 0; -#ifdef COCOA_LOADED - // To account for fullsizecontentview on mac - titlebarOverlap = QVCocoaFunctions::getObscuredHeight(window()->windowHandle()); -#endif + const int titlebarOverlap = getTitlebarOverlap(); if (titlebarOverlap != 0) extraWidgetsSize.rheight() += titlebarOverlap; @@ -1155,3 +1166,13 @@ void MainWindow::toggleFullScreen() showFullScreen(); } } + +int MainWindow::getTitlebarOverlap() const +{ +#ifdef COCOA_LOADED + // To account for fullsizecontentview on mac + return QVCocoaFunctions::getObscuredHeight(window()->windowHandle()); +#endif + + return 0; +} diff --git a/src/mainwindow.h b/src/mainwindow.h index a50f753f..8870f369 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -111,6 +111,8 @@ class MainWindow : public QMainWindow void toggleFullScreen(); + int getTitlebarOverlap() const; + const QVImageCore::FileDetails& getCurrentFileDetails() const { return graphicsView->getCurrentFileDetails(); } public slots: diff --git a/src/qvapplication.cpp b/src/qvapplication.cpp index ba62ea3f..db3c7eb0 100644 --- a/src/qvapplication.cpp +++ b/src/qvapplication.cpp @@ -390,3 +390,8 @@ void QVApplication::defineFilterLists() nameFilterList << filterString; nameFilterList << tr("All Files") + " (*)"; } + +qreal QVApplication::getPerceivedBrightness(const QColor &color) +{ + return (color.red() * 0.299 + color.green() * 0.587 + color.blue() * 0.114) / 255.0; +} diff --git a/src/qvapplication.h b/src/qvapplication.h index 55b9bd74..4d19143a 100644 --- a/src/qvapplication.h +++ b/src/qvapplication.h @@ -77,6 +77,8 @@ class QVApplication : public QApplication ActionManager &getActionManager() { return actionManager; } + static qreal getPerceivedBrightness(const QColor &color); + private: QList lastActiveWindows;