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
6fcd6c90 Poul Sander 2026-02-19 21:12 110
    connect(m_listView->verticalScrollBar(), &QScrollBar::valueChanged,
6fcd6c90 Poul Sander 2026-02-19 21:12 111
            this, [this]()
6fcd6c90 Poul Sander 2026-02-19 21:12 112
            { loadVisibleThumbnails(); });
6fcd6c90 Poul Sander 2026-02-19 21:12 113
6fcd6c90 Poul Sander 2026-02-19 21:12 114
    // Also catch resize — visible range changes when the viewport is resized
6fcd6c90 Poul Sander 2026-02-19 21:12 115
    m_listView->viewport()->installEventFilter(this);
6fcd6c90 Poul Sander 2026-02-19 21:12 116
}
6fcd6c90 Poul Sander 2026-02-19 21:12 117
6fcd6c90 Poul Sander 2026-02-19 21:12 118
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
6fcd6c90 Poul Sander 2026-02-19 21:12 119
{
6fcd6c90 Poul Sander 2026-02-19 21:12 120
    if (obj == m_listView->viewport() && event->type() == QEvent::Resize)
6fcd6c90 Poul Sander 2026-02-19 21:12 121
        QTimer::singleShot(0, this, &MainWindow::loadVisibleThumbnails);
6fcd6c90 Poul Sander 2026-02-19 21:12 122
6fcd6c90 Poul Sander 2026-02-19 21:12 123
    return QMainWindow::eventFilter(obj, event);
6fcd6c90 Poul Sander 2026-02-19 21:12 124
}
6fcd6c90 Poul Sander 2026-02-19 21:12 125
6fcd6c90 Poul Sander 2026-02-19 21:12 126
void MainWindow::loadVisibleThumbnails()
6fcd6c90 Poul Sander 2026-02-19 21:12 127
{
6fcd6c90 Poul Sander 2026-02-19 21:12 128
    QModelIndex topLeft = m_listView->indexAt(QPoint(0, 0));
6fcd6c90 Poul Sander 2026-02-19 21:12 129
    QModelIndex bottomRight = m_listView->indexAt(
6fcd6c90 Poul Sander 2026-02-19 21:12 130
        QPoint(m_listView->viewport()->width() - 1,
6fcd6c90 Poul Sander 2026-02-19 21:12 131
               m_listView->viewport()->height() - 1));
6fcd6c90 Poul Sander 2026-02-19 21:12 132
6fcd6c90 Poul Sander 2026-02-19 21:12 133
    int first = topLeft.isValid() ? topLeft.row() : 0;
6fcd6c90 Poul Sander 2026-02-19 21:12 134
    int last = bottomRight.isValid() ? bottomRight.row()
6fcd6c90 Poul Sander 2026-02-19 21:12 135
                                     : m_imageModel->rowCount() - 1;
6fcd6c90 Poul Sander 2026-02-19 21:12 136
6fcd6c90 Poul Sander 2026-02-19 21:12 137
    if (last < 0)
6fcd6c90 Poul Sander 2026-02-19 21:12 138
        return;
6fcd6c90 Poul Sander 2026-02-19 21:12 139
6fcd6c90 Poul Sander 2026-02-19 21:12 140
    std::cout << "loadVisibleThumbnails: " << first << " - " << last << "\n";
6fcd6c90 Poul Sander 2026-02-19 21:12 141
    m_imageModel->requestThumbnails(first, last);
032aa1e1 Poul Sander 2026-02-19 18:55 142
}
cfe4a67b Poul Sander 2026-02-19 23:06 143
cfe4a67b Poul Sander 2026-02-19 23:06 144
void MainWindow::showPreview(const QModelIndex &index)
cfe4a67b Poul Sander 2026-02-19 23:06 145
{
cfe4a67b Poul Sander 2026-02-19 23:06 146
    if (!index.isValid())
cfe4a67b Poul Sander 2026-02-19 23:06 147
        return;
cfe4a67b Poul Sander 2026-02-19 23:06 148
cfe4a67b Poul Sander 2026-02-19 23:06 149
    QString path = m_imageModel->filePath(index);
cfe4a67b Poul Sander 2026-02-19 23:06 150
cfe4a67b Poul Sander 2026-02-19 23:06 151
    QImageReader reader(path);
cfe4a67b Poul Sander 2026-02-19 23:06 152
    reader.setAutoTransform(true);
cfe4a67b Poul Sander 2026-02-19 23:06 153
    QImage image = reader.read();
cfe4a67b Poul Sander 2026-02-19 23:06 154
cfe4a67b Poul Sander 2026-02-19 23:06 155
    m_previewLabel->setPixmap(
cfe4a67b Poul Sander 2026-02-19 23:06 156
        QPixmap::fromImage(image).scaled(
cfe4a67b Poul Sander 2026-02-19 23:06 157
            m_previewLabel->size(),
cfe4a67b Poul Sander 2026-02-19 23:06 158
            Qt::KeepAspectRatio,
cfe4a67b Poul Sander 2026-02-19 23:06 159
            Qt::SmoothTransformation));
cfe4a67b Poul Sander 2026-02-19 23:06 160
}
61136b77 Poul Sander 2026-02-20 22:45 161
61136b77 Poul Sander 2026-02-20 22:45 162
void MainWindow::enterSingleImageMode(const QModelIndex &index)
61136b77 Poul Sander 2026-02-20 22:45 163
{
61136b77 Poul Sander 2026-02-20 22:45 164
    if (!index.isValid())
61136b77 Poul Sander 2026-02-20 22:45 165
        return;
61136b77 Poul Sander 2026-02-20 22:45 166
61136b77 Poul Sander 2026-02-20 22:45 167
    QString path = m_imageModel->filePath(index);
61136b77 Poul Sander 2026-02-20 22:45 168
    m_imageView->setImage(path);
61136b77 Poul Sander 2026-02-20 22:45 169
    m_stack->setCurrentWidget(m_imageView);
61136b77 Poul Sander 2026-02-20 22:45 170
    m_imageView->setFocus();
61136b77 Poul Sander 2026-02-20 22:45 171
}
61136b77 Poul Sander 2026-02-20 22:45 172
61136b77 Poul Sander 2026-02-20 22:45 173
void MainWindow::leaveSingleImageMode()
61136b77 Poul Sander 2026-02-20 22:45 174
{
61136b77 Poul Sander 2026-02-20 22:45 175
    if (isFullScreen())
61136b77 Poul Sander 2026-02-20 22:45 176
    {
61136b77 Poul Sander 2026-02-20 22:45 177
        if (m_wasFullScreen)
61136b77 Poul Sander 2026-02-20 22:45 178
            showFullScreen();
61136b77 Poul Sander 2026-02-20 22:45 179
        else
61136b77 Poul Sander 2026-02-20 22:45 180
            showNormal();
61136b77 Poul Sander 2026-02-20 22:45 181
    }
61136b77 Poul Sander 2026-02-20 22:45 182
    m_stack->setCurrentWidget(m_browserPage);
61136b77 Poul Sander 2026-02-20 22:45 183
    m_listView->setFocus();
61136b77 Poul Sander 2026-02-20 22:45 184
}
61136b77 Poul Sander 2026-02-20 22:45 185
61136b77 Poul Sander 2026-02-20 22:45 186
void MainWindow::keyPressEvent(QKeyEvent *event)
61136b77 Poul Sander 2026-02-20 22:45 187
{
61136b77 Poul Sander 2026-02-20 22:45 188
    if (event->key() == Qt::Key_F11 && m_stack->currentWidget() == m_imageView)
61136b77 Poul Sander 2026-02-20 22:45 189
    {
61136b77 Poul Sander 2026-02-20 22:45 190
        if (isFullScreen())
61136b77 Poul Sander 2026-02-20 22:45 191
            showNormal();
61136b77 Poul Sander 2026-02-20 22:45 192
        else
61136b77 Poul Sander 2026-02-20 22:45 193
            showFullScreen();
61136b77 Poul Sander 2026-02-20 22:45 194
        event->accept();
61136b77 Poul Sander 2026-02-20 22:45 195
        return;
61136b77 Poul Sander 2026-02-20 22:45 196
    }
61136b77 Poul Sander 2026-02-20 22:45 197
61136b77 Poul Sander 2026-02-20 22:45 198
    if (event->key() == Qt::Key_Return && m_stack->currentWidget() == m_browserPage)
61136b77 Poul Sander 2026-02-20 22:45 199
    {
61136b77 Poul Sander 2026-02-20 22:45 200
        QModelIndex current = m_listView->currentIndex();
61136b77 Poul Sander 2026-02-20 22:45 201
        if (current.isValid())
61136b77 Poul Sander 2026-02-20 22:45 202
        {
61136b77 Poul Sander 2026-02-20 22:45 203
            enterSingleImageMode(current);
61136b77 Poul Sander 2026-02-20 22:45 204
            event->accept();
61136b77 Poul Sander 2026-02-20 22:45 205
            return;
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
61136b77 Poul Sander 2026-02-20 22:45 209
    QMainWindow::keyPressEvent(event);
61136b77 Poul Sander 2026-02-20 22:45 210
}
1970-01-01 00:00 211