git repos / SagoImageBrowser

blame: mainwindow.cpp

normal view · raw

032aa1e1 Poul Sander 2026-02-19 18:55 1
#include "mainwindow.h"
032aa1e1 Poul Sander 2026-02-19 18:55 2
#include "imagemodel.h"
61136b77 Poul Sander 2026-02-20 22:45 3
#include "imageviewwidget.h"
032aa1e1 Poul Sander 2026-02-19 18:55 4
032aa1e1 Poul Sander 2026-02-19 18:55 5
#include <QFileSystemModel>
032aa1e1 Poul Sander 2026-02-19 18:55 6
#include <QTreeView>
032aa1e1 Poul Sander 2026-02-19 18:55 7
#include <QListView>
032aa1e1 Poul Sander 2026-02-19 18:55 8
#include <QLabel>
032aa1e1 Poul Sander 2026-02-19 18:55 9
#include <QSplitter>
61136b77 Poul Sander 2026-02-20 22:45 10
#include <QStackedWidget>
032aa1e1 Poul Sander 2026-02-19 18:55 11
#include <QDir>
032aa1e1 Poul Sander 2026-02-19 18:55 12
#include <QImageReader>
032aa1e1 Poul Sander 2026-02-19 18:55 13
#include <QHeaderView>
6fcd6c90 Poul Sander 2026-02-19 21:12 14
#include <QScrollBar>
6fcd6c90 Poul Sander 2026-02-19 21:12 15
#include <QTimer>
6fcd6c90 Poul Sander 2026-02-19 21:12 16
#include <QEvent>
61136b77 Poul Sander 2026-02-20 22:45 17
#include <QKeyEvent>
cfe4a67b Poul Sander 2026-02-19 23:06 18
#include <QItemSelectionModel>
6fcd6c90 Poul Sander 2026-02-19 21:12 19
#include <iostream>
032aa1e1 Poul Sander 2026-02-19 18:55 20
032aa1e1 Poul Sander 2026-02-19 18:55 21
MainWindow::MainWindow(QWidget *parent)
032aa1e1 Poul Sander 2026-02-19 18:55 22
    : QMainWindow(parent)
032aa1e1 Poul Sander 2026-02-19 18:55 23
{
032aa1e1 Poul Sander 2026-02-19 18:55 24
    setupUi();
032aa1e1 Poul Sander 2026-02-19 18:55 25
    setupConnections();
032aa1e1 Poul Sander 2026-02-19 18:55 26
}
032aa1e1 Poul Sander 2026-02-19 18:55 27
032aa1e1 Poul Sander 2026-02-19 18:55 28
void MainWindow::setupUi()
032aa1e1 Poul Sander 2026-02-19 18:55 29
{
032aa1e1 Poul Sander 2026-02-19 18:55 30
    // Folder model (left pane)
032aa1e1 Poul Sander 2026-02-19 18:55 31
    m_dirModel = new QFileSystemModel(this);
032aa1e1 Poul Sander 2026-02-19 18:55 32
    m_dirModel->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
032aa1e1 Poul Sander 2026-02-19 18:55 33
    m_dirModel->setRootPath(QDir::homePath());
032aa1e1 Poul Sander 2026-02-19 18:55 34
032aa1e1 Poul Sander 2026-02-19 18:55 35
    m_treeView = new QTreeView;
032aa1e1 Poul Sander 2026-02-19 18:55 36
    m_treeView->setModel(m_dirModel);
032aa1e1 Poul Sander 2026-02-19 18:55 37
    m_treeView->setRootIndex(m_dirModel->index(QDir::homePath()));
032aa1e1 Poul Sander 2026-02-19 18:55 38
    m_treeView->header()->hide();
032aa1e1 Poul Sander 2026-02-19 18:55 39
    m_treeView->setColumnHidden(1, true);
032aa1e1 Poul Sander 2026-02-19 18:55 40
    m_treeView->setColumnHidden(2, true);
032aa1e1 Poul Sander 2026-02-19 18:55 41
    m_treeView->setColumnHidden(3, true);
032aa1e1 Poul Sander 2026-02-19 18:55 42
032aa1e1 Poul Sander 2026-02-19 18:55 43
    // Thumbnail model (center pane)
032aa1e1 Poul Sander 2026-02-19 18:55 44
    m_imageModel = new ImageModel(this);
032aa1e1 Poul Sander 2026-02-19 18:55 45
032aa1e1 Poul Sander 2026-02-19 18:55 46
    m_listView = new QListView;
032aa1e1 Poul Sander 2026-02-19 18:55 47
    m_listView->setModel(m_imageModel);
032aa1e1 Poul Sander 2026-02-19 18:55 48
    m_listView->setViewMode(QListView::IconMode);
032aa1e1 Poul Sander 2026-02-19 18:55 49
    m_listView->setIconSize(QSize(128, 128));
b614a581 Poul Sander 2026-02-19 21:18 50
    m_listView->setGridSize(QSize(148, 168));
032aa1e1 Poul Sander 2026-02-19 18:55 51
    m_listView->setResizeMode(QListView::Adjust);
032aa1e1 Poul Sander 2026-02-19 18:55 52
    m_listView->setSelectionMode(QAbstractItemView::SingleSelection);
b614a581 Poul Sander 2026-02-19 21:18 53
    m_listView->setSpacing(4);
b614a581 Poul Sander 2026-02-19 21:18 54
    m_listView->setWordWrap(true);
b614a581 Poul Sander 2026-02-19 21:18 55
    m_listView->setTextElideMode(Qt::ElideRight);
032aa1e1 Poul Sander 2026-02-19 18:55 56
032aa1e1 Poul Sander 2026-02-19 18:55 57
    // Preview pane (right)
032aa1e1 Poul Sander 2026-02-19 18:55 58
    m_previewLabel = new QLabel;
032aa1e1 Poul Sander 2026-02-19 18:55 59
    m_previewLabel->setAlignment(Qt::AlignCenter);
032aa1e1 Poul Sander 2026-02-19 18:55 60
    m_previewLabel->setMinimumWidth(300);
032aa1e1 Poul Sander 2026-02-19 18:55 61
032aa1e1 Poul Sander 2026-02-19 18:55 62
    // Layout
032aa1e1 Poul Sander 2026-02-19 18:55 63
    QSplitter *rightSplitter = new QSplitter(Qt::Horizontal);
032aa1e1 Poul Sander 2026-02-19 18:55 64
    rightSplitter->addWidget(m_listView);
032aa1e1 Poul Sander 2026-02-19 18:55 65
    rightSplitter->addWidget(m_previewLabel);
032aa1e1 Poul Sander 2026-02-19 18:55 66
    rightSplitter->setStretchFactor(0, 3);
032aa1e1 Poul Sander 2026-02-19 18:55 67
    rightSplitter->setStretchFactor(1, 2);
032aa1e1 Poul Sander 2026-02-19 18:55 68
032aa1e1 Poul Sander 2026-02-19 18:55 69
    QSplitter *mainSplitter = new QSplitter(Qt::Horizontal);
032aa1e1 Poul Sander 2026-02-19 18:55 70
    mainSplitter->addWidget(m_treeView);
032aa1e1 Poul Sander 2026-02-19 18:55 71
    mainSplitter->addWidget(rightSplitter);
032aa1e1 Poul Sander 2026-02-19 18:55 72
    mainSplitter->setStretchFactor(1, 1);
032aa1e1 Poul Sander 2026-02-19 18:55 73
61136b77 Poul Sander 2026-02-20 22:45 74
    m_browserPage = mainSplitter;
61136b77 Poul Sander 2026-02-20 22:45 75
61136b77 Poul Sander 2026-02-20 22:45 76
    // Single image view
61136b77 Poul Sander 2026-02-20 22:45 77
    m_imageView = new ImageViewWidget;
61136b77 Poul Sander 2026-02-20 22:45 78
61136b77 Poul Sander 2026-02-20 22:45 79
    // Stack to switch between browser and single image
61136b77 Poul Sander 2026-02-20 22:45 80
    m_stack = new QStackedWidget;
61136b77 Poul Sander 2026-02-20 22:45 81
    m_stack->addWidget(m_browserPage);
61136b77 Poul Sander 2026-02-20 22:45 82
    m_stack->addWidget(m_imageView);
61136b77 Poul Sander 2026-02-20 22:45 83
61136b77 Poul Sander 2026-02-20 22:45 84
    setCentralWidget(m_stack);
032aa1e1 Poul Sander 2026-02-19 18:55 85
}
032aa1e1 Poul Sander 2026-02-19 18:55 86
032aa1e1 Poul Sander 2026-02-19 18:55 87
void MainWindow::setupConnections()
032aa1e1 Poul Sander 2026-02-19 18:55 88
{
032aa1e1 Poul Sander 2026-02-19 18:55 89
    connect(m_treeView, &QTreeView::clicked, this,
032aa1e1 Poul Sander 2026-02-19 18:55 90
            [this](const QModelIndex &index)
6fcd6c90 Poul Sander 2026-02-19 21:12 91
            {
6fcd6c90 Poul Sander 2026-02-19 21:12 92
                QString path = m_dirModel->filePath(index);
6fcd6c90 Poul Sander 2026-02-19 21:12 93
                m_imageModel->setDirectory(path);
6fcd6c90 Poul Sander 2026-02-19 21:12 94
                // Defer thumbnail load so the view has time to lay out items
6fcd6c90 Poul Sander 2026-02-19 21:12 95
                QTimer::singleShot(0, this, &MainWindow::loadVisibleThumbnails);
6fcd6c90 Poul Sander 2026-02-19 21:12 96
            });
032aa1e1 Poul Sander 2026-02-19 18:55 97
032aa1e1 Poul Sander 2026-02-19 18:55 98
    connect(m_listView, &QListView::clicked, this,
cfe4a67b Poul Sander 2026-02-19 23:06 99
            [this](const QModelIndex &index) { showPreview(index); });
6fcd6c90 Poul Sander 2026-02-19 21:12 100
cfe4a67b Poul Sander 2026-02-19 23:06 101
    connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged,
cfe4a67b Poul Sander 2026-02-19 23:06 102
            this, [this](const QModelIndex &current) { showPreview(current); });
6fcd6c90 Poul Sander 2026-02-19 21:12 103
61136b77 Poul Sander 2026-02-20 22:45 104
    connect(m_listView, &QListView::doubleClicked, this,
61136b77 Poul Sander 2026-02-20 22:45 105
            [this](const QModelIndex &index) { enterSingleImageMode(index); });
61136b77 Poul Sander 2026-02-20 22:45 106
61136b77 Poul Sander 2026-02-20 22:45 107
    connect(m_imageView, &ImageViewWidget::closeRequested,
61136b77 Poul Sander 2026-02-20 22:45 108
            this, &MainWindow::leaveSingleImageMode);
61136b77 Poul Sander 2026-02-20 22:45 109
1ffc1962 Poul Sander 2026-02-20 23:41 110
    connect(m_imageView, &ImageViewWidget::nextRequested, this, [this]() {
1ffc1962 Poul Sander 2026-02-20 23:41 111
        QModelIndex cur = m_listView->currentIndex();
1ffc1962 Poul Sander 2026-02-20 23:41 112
        int next = cur.isValid() ? cur.row() + 1 : 0;
1ffc1962 Poul Sander 2026-02-20 23:41 113
        if (next < m_imageModel->rowCount())
1ffc1962 Poul Sander 2026-02-20 23:41 114
        {
1ffc1962 Poul Sander 2026-02-20 23:41 115
            QModelIndex idx = m_imageModel->index(next);
1ffc1962 Poul Sander 2026-02-20 23:41 116
            m_listView->setCurrentIndex(idx);
1ffc1962 Poul Sander 2026-02-20 23:41 117
            enterSingleImageMode(idx);
1ffc1962 Poul Sander 2026-02-20 23:41 118
        }
1ffc1962 Poul Sander 2026-02-20 23:41 119
    });
1ffc1962 Poul Sander 2026-02-20 23:41 120
1ffc1962 Poul Sander 2026-02-20 23:41 121
    connect(m_imageView, &ImageViewWidget::previousRequested, this, [this]() {
1ffc1962 Poul Sander 2026-02-20 23:41 122
        QModelIndex cur = m_listView->currentIndex();
1ffc1962 Poul Sander 2026-02-20 23:41 123
        int prev = cur.isValid() ? cur.row() - 1 : 0;
1ffc1962 Poul Sander 2026-02-20 23:41 124
        if (prev >= 0)
1ffc1962 Poul Sander 2026-02-20 23:41 125
        {
1ffc1962 Poul Sander 2026-02-20 23:41 126
            QModelIndex idx = m_imageModel->index(prev);
1ffc1962 Poul Sander 2026-02-20 23:41 127
            m_listView->setCurrentIndex(idx);
1ffc1962 Poul Sander 2026-02-20 23:41 128
            enterSingleImageMode(idx);
1ffc1962 Poul Sander 2026-02-20 23:41 129
        }
1ffc1962 Poul Sander 2026-02-20 23:41 130
    });
1ffc1962 Poul Sander 2026-02-20 23:41 131
6fcd6c90 Poul Sander 2026-02-19 21:12 132
    connect(m_listView->verticalScrollBar(), &QScrollBar::valueChanged,
6fcd6c90 Poul Sander 2026-02-19 21:12 133
            this, [this]()
6fcd6c90 Poul Sander 2026-02-19 21:12 134
            { loadVisibleThumbnails(); });
6fcd6c90 Poul Sander 2026-02-19 21:12 135
6fcd6c90 Poul Sander 2026-02-19 21:12 136
    // Also catch resize — visible range changes when the viewport is resized
6fcd6c90 Poul Sander 2026-02-19 21:12 137
    m_listView->viewport()->installEventFilter(this);
6fcd6c90 Poul Sander 2026-02-19 21:12 138
}
6fcd6c90 Poul Sander 2026-02-19 21:12 139
6fcd6c90 Poul Sander 2026-02-19 21:12 140
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
6fcd6c90 Poul Sander 2026-02-19 21:12 141
{
6fcd6c90 Poul Sander 2026-02-19 21:12 142
    if (obj == m_listView->viewport() && event->type() == QEvent::Resize)
6fcd6c90 Poul Sander 2026-02-19 21:12 143
        QTimer::singleShot(0, this, &MainWindow::loadVisibleThumbnails);
6fcd6c90 Poul Sander 2026-02-19 21:12 144
6fcd6c90 Poul Sander 2026-02-19 21:12 145
    return QMainWindow::eventFilter(obj, event);
6fcd6c90 Poul Sander 2026-02-19 21:12 146
}
6fcd6c90 Poul Sander 2026-02-19 21:12 147
6fcd6c90 Poul Sander 2026-02-19 21:12 148
void MainWindow::loadVisibleThumbnails()
6fcd6c90 Poul Sander 2026-02-19 21:12 149
{
6fcd6c90 Poul Sander 2026-02-19 21:12 150
    QModelIndex topLeft = m_listView->indexAt(QPoint(0, 0));
6fcd6c90 Poul Sander 2026-02-19 21:12 151
    QModelIndex bottomRight = m_listView->indexAt(
6fcd6c90 Poul Sander 2026-02-19 21:12 152
        QPoint(m_listView->viewport()->width() - 1,
6fcd6c90 Poul Sander 2026-02-19 21:12 153
               m_listView->viewport()->height() - 1));
6fcd6c90 Poul Sander 2026-02-19 21:12 154
6fcd6c90 Poul Sander 2026-02-19 21:12 155
    int first = topLeft.isValid() ? topLeft.row() : 0;
6fcd6c90 Poul Sander 2026-02-19 21:12 156
    int last = bottomRight.isValid() ? bottomRight.row()
6fcd6c90 Poul Sander 2026-02-19 21:12 157
                                     : m_imageModel->rowCount() - 1;
6fcd6c90 Poul Sander 2026-02-19 21:12 158
6fcd6c90 Poul Sander 2026-02-19 21:12 159
    if (last < 0)
6fcd6c90 Poul Sander 2026-02-19 21:12 160
        return;
6fcd6c90 Poul Sander 2026-02-19 21:12 161
6fcd6c90 Poul Sander 2026-02-19 21:12 162
    std::cout << "loadVisibleThumbnails: " << first << " - " << last << "\n";
6fcd6c90 Poul Sander 2026-02-19 21:12 163
    m_imageModel->requestThumbnails(first, last);
032aa1e1 Poul Sander 2026-02-19 18:55 164
}
cfe4a67b Poul Sander 2026-02-19 23:06 165
cfe4a67b Poul Sander 2026-02-19 23:06 166
void MainWindow::showPreview(const QModelIndex &index)
cfe4a67b Poul Sander 2026-02-19 23:06 167
{
cfe4a67b Poul Sander 2026-02-19 23:06 168
    if (!index.isValid())
cfe4a67b Poul Sander 2026-02-19 23:06 169
        return;
cfe4a67b Poul Sander 2026-02-19 23:06 170
cfe4a67b Poul Sander 2026-02-19 23:06 171
    QString path = m_imageModel->filePath(index);
cfe4a67b Poul Sander 2026-02-19 23:06 172
cfe4a67b Poul Sander 2026-02-19 23:06 173
    QImageReader reader(path);
cfe4a67b Poul Sander 2026-02-19 23:06 174
    reader.setAutoTransform(true);
cfe4a67b Poul Sander 2026-02-19 23:06 175
    QImage image = reader.read();
cfe4a67b Poul Sander 2026-02-19 23:06 176
cfe4a67b Poul Sander 2026-02-19 23:06 177
    m_previewLabel->setPixmap(
cfe4a67b Poul Sander 2026-02-19 23:06 178
        QPixmap::fromImage(image).scaled(
cfe4a67b Poul Sander 2026-02-19 23:06 179
            m_previewLabel->size(),
cfe4a67b Poul Sander 2026-02-19 23:06 180
            Qt::KeepAspectRatio,
cfe4a67b Poul Sander 2026-02-19 23:06 181
            Qt::SmoothTransformation));
cfe4a67b Poul Sander 2026-02-19 23:06 182
}
61136b77 Poul Sander 2026-02-20 22:45 183
61136b77 Poul Sander 2026-02-20 22:45 184
void MainWindow::enterSingleImageMode(const QModelIndex &index)
61136b77 Poul Sander 2026-02-20 22:45 185
{
61136b77 Poul Sander 2026-02-20 22:45 186
    if (!index.isValid())
61136b77 Poul Sander 2026-02-20 22:45 187
        return;
61136b77 Poul Sander 2026-02-20 22:45 188
61136b77 Poul Sander 2026-02-20 22:45 189
    QString path = m_imageModel->filePath(index);
61136b77 Poul Sander 2026-02-20 22:45 190
    m_imageView->setImage(path);
61136b77 Poul Sander 2026-02-20 22:45 191
    m_stack->setCurrentWidget(m_imageView);
61136b77 Poul Sander 2026-02-20 22:45 192
    m_imageView->setFocus();
61136b77 Poul Sander 2026-02-20 22:45 193
}
61136b77 Poul Sander 2026-02-20 22:45 194
61136b77 Poul Sander 2026-02-20 22:45 195
void MainWindow::leaveSingleImageMode()
61136b77 Poul Sander 2026-02-20 22:45 196
{
61136b77 Poul Sander 2026-02-20 22:45 197
    if (isFullScreen())
61136b77 Poul Sander 2026-02-20 22:45 198
    {
61136b77 Poul Sander 2026-02-20 22:45 199
        if (m_wasFullScreen)
61136b77 Poul Sander 2026-02-20 22:45 200
            showFullScreen();
61136b77 Poul Sander 2026-02-20 22:45 201
        else
61136b77 Poul Sander 2026-02-20 22:45 202
            showNormal();
61136b77 Poul Sander 2026-02-20 22:45 203
    }
61136b77 Poul Sander 2026-02-20 22:45 204
    m_stack->setCurrentWidget(m_browserPage);
61136b77 Poul Sander 2026-02-20 22:45 205
    m_listView->setFocus();
61136b77 Poul Sander 2026-02-20 22:45 206
}
61136b77 Poul Sander 2026-02-20 22:45 207
61136b77 Poul Sander 2026-02-20 22:45 208
void MainWindow::keyPressEvent(QKeyEvent *event)
61136b77 Poul Sander 2026-02-20 22:45 209
{
61136b77 Poul Sander 2026-02-20 22:45 210
    if (event->key() == Qt::Key_F11 && m_stack->currentWidget() == m_imageView)
61136b77 Poul Sander 2026-02-20 22:45 211
    {
61136b77 Poul Sander 2026-02-20 22:45 212
        if (isFullScreen())
61136b77 Poul Sander 2026-02-20 22:45 213
            showNormal();
61136b77 Poul Sander 2026-02-20 22:45 214
        else
61136b77 Poul Sander 2026-02-20 22:45 215
            showFullScreen();
61136b77 Poul Sander 2026-02-20 22:45 216
        event->accept();
61136b77 Poul Sander 2026-02-20 22:45 217
        return;
61136b77 Poul Sander 2026-02-20 22:45 218
    }
61136b77 Poul Sander 2026-02-20 22:45 219
61136b77 Poul Sander 2026-02-20 22:45 220
    if (event->key() == Qt::Key_Return && m_stack->currentWidget() == m_browserPage)
61136b77 Poul Sander 2026-02-20 22:45 221
    {
61136b77 Poul Sander 2026-02-20 22:45 222
        QModelIndex current = m_listView->currentIndex();
61136b77 Poul Sander 2026-02-20 22:45 223
        if (current.isValid())
61136b77 Poul Sander 2026-02-20 22:45 224
        {
61136b77 Poul Sander 2026-02-20 22:45 225
            enterSingleImageMode(current);
61136b77 Poul Sander 2026-02-20 22:45 226
            event->accept();
61136b77 Poul Sander 2026-02-20 22:45 227
            return;
61136b77 Poul Sander 2026-02-20 22:45 228
        }
61136b77 Poul Sander 2026-02-20 22:45 229
    }
61136b77 Poul Sander 2026-02-20 22:45 230
61136b77 Poul Sander 2026-02-20 22:45 231
    QMainWindow::keyPressEvent(event);
61136b77 Poul Sander 2026-02-20 22:45 232
}
1970-01-01 00:00 233