git repos / SagoImageBrowser

blame: src/imageviewwidget.h

normal view · raw

14cf904f Poul Sander 2026-06-22 18:18 1
/*
14cf904f Poul Sander 2026-06-22 18:18 2
MIT License
14cf904f Poul Sander 2026-06-22 18:18 3
14cf904f Poul Sander 2026-06-22 18:18 4
Copyright (c) 2026 Poul Sander
14cf904f Poul Sander 2026-06-22 18:18 5
14cf904f Poul Sander 2026-06-22 18:18 6
Permission is hereby granted, free of charge, to any person obtaining a copy
14cf904f Poul Sander 2026-06-22 18:18 7
of this software and associated documentation files (the "Software"), to deal
14cf904f Poul Sander 2026-06-22 18:18 8
in the Software without restriction, including without limitation the rights
14cf904f Poul Sander 2026-06-22 18:18 9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14cf904f Poul Sander 2026-06-22 18:18 10
copies of the Software, and to permit persons to whom the Software is
14cf904f Poul Sander 2026-06-22 18:18 11
furnished to do so, subject to the following conditions:
14cf904f Poul Sander 2026-06-22 18:18 12
14cf904f Poul Sander 2026-06-22 18:18 13
The above copyright notice and this permission notice shall be included in all
14cf904f Poul Sander 2026-06-22 18:18 14
copies or substantial portions of the Software.
14cf904f Poul Sander 2026-06-22 18:18 15
14cf904f Poul Sander 2026-06-22 18:18 16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14cf904f Poul Sander 2026-06-22 18:18 17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14cf904f Poul Sander 2026-06-22 18:18 18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14cf904f Poul Sander 2026-06-22 18:18 19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14cf904f Poul Sander 2026-06-22 18:18 20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14cf904f Poul Sander 2026-06-22 18:18 21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
14cf904f Poul Sander 2026-06-22 18:18 22
SOFTWARE.
14cf904f Poul Sander 2026-06-22 18:18 23
14cf904f Poul Sander 2026-06-22 18:18 24
*/
14cf904f Poul Sander 2026-06-22 18:18 25
61136b77 Poul Sander 2026-02-20 22:45 26
#pragma once
61136b77 Poul Sander 2026-02-20 22:45 27
61136b77 Poul Sander 2026-02-20 22:45 28
#include <QWidget>
61136b77 Poul Sander 2026-02-20 22:45 29
#include <QImage>
61136b77 Poul Sander 2026-02-20 22:45 30
#include <QPixmap>
80a9926d Poul Sander 2026-05-19 20:28 31
#include <QByteArray>
80a9926d Poul Sander 2026-05-19 20:28 32
#include <QList>
58103277 Poul Sander 2026-03-01 22:53 33
#include <QMap>
80a9926d Poul Sander 2026-05-19 20:28 34
#include <QSet>
58103277 Poul Sander 2026-03-01 22:53 35
#include <QThread>
53fdab93 Poul Sander 2026-05-18 18:45 36
#include "exifreader.h"
58103277 Poul Sander 2026-03-01 22:53 37
58103277 Poul Sander 2026-03-01 22:53 38
class ImageLoadWorker : public QThread
58103277 Poul Sander 2026-03-01 22:53 39
{
58103277 Poul Sander 2026-03-01 22:53 40
    Q_OBJECT
58103277 Poul Sander 2026-03-01 22:53 41
public:
80a9926d Poul Sander 2026-05-19 20:28 42
    explicit ImageLoadWorker(const QByteArray &path, QObject *parent = nullptr);
58103277 Poul Sander 2026-03-01 22:53 43
    void run() override;
58103277 Poul Sander 2026-03-01 22:53 44
signals:
80a9926d Poul Sander 2026-05-19 20:28 45
    void imageLoaded(const QByteArray &path, const QPixmap &pixmap);
58103277 Poul Sander 2026-03-01 22:53 46
private:
80a9926d Poul Sander 2026-05-19 20:28 47
    QByteArray m_path;
58103277 Poul Sander 2026-03-01 22:53 48
};
61136b77 Poul Sander 2026-02-20 22:45 49
61136b77 Poul Sander 2026-02-20 22:45 50
class ImageViewWidget : public QWidget
61136b77 Poul Sander 2026-02-20 22:45 51
{
61136b77 Poul Sander 2026-02-20 22:45 52
    Q_OBJECT
61136b77 Poul Sander 2026-02-20 22:45 53
61136b77 Poul Sander 2026-02-20 22:45 54
public:
58103277 Poul Sander 2026-03-01 22:53 55
    // Number of images to read ahead and keep behind the current image
58103277 Poul Sander 2026-03-01 22:53 56
    static constexpr int CacheReadAhead = 2;
58103277 Poul Sander 2026-03-01 22:53 57
    static constexpr int CacheKeepBehind = 2;
58103277 Poul Sander 2026-03-01 22:53 58
c58dbdb7 Poul Sander 2026-02-22 17:49 59
    enum ZoomMode { FitToScreen, OriginalSize, CustomZoom };
c58dbdb7 Poul Sander 2026-02-22 17:49 60
61136b77 Poul Sander 2026-02-20 22:45 61
    explicit ImageViewWidget(QWidget *parent = nullptr);
61136b77 Poul Sander 2026-02-20 22:45 62
80a9926d Poul Sander 2026-05-19 20:28 63
    void setImage(const QByteArray &path);
f61bf886 Poul Sander 2026-02-23 19:27 64
    void setBackgroundColor(const QString &color);
c58dbdb7 Poul Sander 2026-02-22 17:49 65
    void zoomIn();
c58dbdb7 Poul Sander 2026-02-22 17:49 66
    void zoomOut();
c58dbdb7 Poul Sander 2026-02-22 17:49 67
    void zoomOriginal();
c58dbdb7 Poul Sander 2026-02-22 17:49 68
    void zoomFitToScreen();
61136b77 Poul Sander 2026-02-20 22:45 69
80a9926d Poul Sander 2026-05-19 20:28 70
    void prefetchImage(const QByteArray &path);
80a9926d Poul Sander 2026-05-19 20:28 71
    void setNeighborPaths(const QList<QByteArray> &paths);
58103277 Poul Sander 2026-03-01 22:53 72
    void clearCache();
48534775 Poul Sander 2026-06-08 18:57 73
    // Drop any cached pixmap for path so it is re-decoded from disk next time.
48534775 Poul Sander 2026-06-08 18:57 74
    void invalidateCache(const QByteArray &path);
58103277 Poul Sander 2026-03-01 22:53 75
53fdab93 Poul Sander 2026-05-18 18:45 76
    void setExifData(const ExifData &data);
53fdab93 Poul Sander 2026-05-18 18:45 77
    void toggleExifOverlay();
beb4a823 Poul Sander 2026-05-19 21:53 78
    QByteArray currentPath() const;
53fdab93 Poul Sander 2026-05-18 18:45 79
61136b77 Poul Sander 2026-02-20 22:45 80
signals:
61136b77 Poul Sander 2026-02-20 22:45 81
    void closeRequested();
1ffc1962 Poul Sander 2026-02-20 23:41 82
    void nextRequested();
1ffc1962 Poul Sander 2026-02-20 23:41 83
    void previousRequested();
beb4a823 Poul Sander 2026-05-19 21:53 84
    void editCaptionRequested();
61136b77 Poul Sander 2026-02-20 22:45 85
61136b77 Poul Sander 2026-02-20 22:45 86
protected:
61136b77 Poul Sander 2026-02-20 22:45 87
    void paintEvent(QPaintEvent *event) override;
61136b77 Poul Sander 2026-02-20 22:45 88
    void keyPressEvent(QKeyEvent *event) override;
c8ae2669 Poul Sander 2026-02-22 17:52 89
    void mousePressEvent(QMouseEvent *event) override;
c8ae2669 Poul Sander 2026-02-22 17:52 90
    void mouseMoveEvent(QMouseEvent *event) override;
c8ae2669 Poul Sander 2026-02-22 17:52 91
    void mouseReleaseEvent(QMouseEvent *event) override;
1035a476 Poul Sander 2026-02-23 19:30 92
    void mouseDoubleClickEvent(QMouseEvent *event) override;
61136b77 Poul Sander 2026-02-20 22:45 93
61136b77 Poul Sander 2026-02-20 22:45 94
private:
c8ae2669 Poul Sander 2026-02-22 17:52 95
    void clampOffset(int imgW, int imgH);
80a9926d Poul Sander 2026-05-19 20:28 96
    QPixmap loadImageFromDisk(const QByteArray &path);
80a9926d Poul Sander 2026-05-19 20:28 97
    void onImageLoaded(const QByteArray &path, const QPixmap &pixmap);
c8ae2669 Poul Sander 2026-02-22 17:52 98
61136b77 Poul Sander 2026-02-20 22:45 99
    QPixmap m_pixmap;
c58dbdb7 Poul Sander 2026-02-22 17:49 100
    ZoomMode m_zoomMode = FitToScreen;
c58dbdb7 Poul Sander 2026-02-22 17:49 101
    double m_zoomFactor = 1.0;
f61bf886 Poul Sander 2026-02-23 19:27 102
    QString m_backgroundColor = "black";
80a9926d Poul Sander 2026-05-19 20:28 103
    QByteArray m_currentPath;
58103277 Poul Sander 2026-03-01 22:53 104
58103277 Poul Sander 2026-03-01 22:53 105
    // Image cache: path -> pixmap
80a9926d Poul Sander 2026-05-19 20:28 106
    QMap<QByteArray, QPixmap> m_cache;
80a9926d Poul Sander 2026-05-19 20:28 107
    QList<QByteArray> m_neighborPaths;    // ordered list of paths around current image
80a9926d Poul Sander 2026-05-19 20:28 108
    QSet<QByteArray> m_pendingLoads;      // paths currently being loaded in background
c8ae2669 Poul Sander 2026-02-22 17:52 109
c8ae2669 Poul Sander 2026-02-22 17:52 110
    // Panning state
c8ae2669 Poul Sander 2026-02-22 17:52 111
    QPoint m_offset;        // current pan offset (pixels)
c8ae2669 Poul Sander 2026-02-22 17:52 112
    bool   m_dragging = false;
c8ae2669 Poul Sander 2026-02-22 17:52 113
    QPoint m_dragStart;
c8ae2669 Poul Sander 2026-02-22 17:52 114
    QPoint m_offsetAtDragStart;
53fdab93 Poul Sander 2026-05-18 18:45 115
53fdab93 Poul Sander 2026-05-18 18:45 116
    // EXIF overlay
53fdab93 Poul Sander 2026-05-18 18:45 117
    ExifData m_exifData;
53fdab93 Poul Sander 2026-05-18 18:45 118
    bool m_showExifOverlay = false;
4db3041a Poul Sander 2026-05-26 22:01 119
4db3041a Poul Sander 2026-05-26 22:01 120
    // Help overlay
4db3041a Poul Sander 2026-05-26 22:01 121
    bool m_showHelpOverlay = false;
cdae9502 Poul Sander 2026-06-09 20:04 122
cdae9502 Poul Sander 2026-06-09 20:04 123
    // Clickable link areas
cdae9502 Poul Sander 2026-06-09 20:04 124
    QRect m_osmLinkRect;
61136b77 Poul Sander 2026-02-20 22:45 125
};
1970-01-01 00:00 126