git repos / SagoImageBrowser

commit 09130ab9

Poul Sander · 2026-02-22 22:19
09130ab9bc9b07df0d254786902c0d94fdc1b1d2 patch · browse files
parent fc5f2e276b0ec387eb0e54a2d83f6022edcc8910

Draw all folders including parrent folder ("..") so we can quickly navigate with the keyboard

Changed files

M imagemodel.cpp before
M imagemodel.h before
M mainwindow.cpp before
diff --git a/imagemodel.cpp b/imagemodel.cpp index 5c58083..3288ae0 100644 --- a/imagemodel.cpp +++ b/imagemodel.cpp
@@ -4,6 +4,7 @@
#include <QDir>
#include <QImageReader>
#include <QFileInfo>
+#include <QFileIconProvider>
ImageModel::ImageModel(QObject *parent)
: QAbstractListModel(parent)
@@ -12,6 +13,9 @@ ImageModel::ImageModel(QObject *parent)
m_placeholder = QPixmap(128, 128);
m_placeholder.fill(Qt::lightGray);
+
+ QFileIconProvider iconProvider;
+ m_folderIcon = iconProvider.icon(QFileIconProvider::Folder);
}
ImageModel::~ImageModel()
@@ -29,8 +33,22 @@ void ImageModel::setDirectory(const QString &path)
beginResetModel();
m_items.clear();
m_pendingRows.clear();
+ m_currentDir = path;
QDir dir(path);
+
+ // Add subdirectories first
+ dir.setFilter(QDir::AllDirs | QDir::NoDot);
+ dir.setSorting(QDir::Name);
+ const auto dirs = dir.entryInfoList();
+ QPixmap folderPixmap = m_folderIcon.pixmap(128, 128);
+ for (const QFileInfo &d : dirs)
+ {
+ QString name = d.fileName(); // preserves ".." for the parent entry
+ m_items.append({d.absoluteFilePath(), name, folderPixmap, true, true});
+ }
+
+ // Then add image files
QStringList filters;
const auto formats = QImageReader::supportedImageFormats();
@@ -39,12 +57,13 @@ void ImageModel::setDirectory(const QString &path)
dir.setNameFilters(filters);
dir.setFilter(QDir::Files);
+ dir.setSorting(QDir::Name);
const auto files = dir.entryInfoList();
for (const QFileInfo &file : files)
{
- m_items.append({file.absoluteFilePath(), m_placeholder, false});
+ m_items.append({file.absoluteFilePath(), file.fileName(), m_placeholder, false, false});
}
endResetModel();
@@ -60,18 +79,18 @@ void ImageModel::requestThumbnails(int firstRow, int lastRow)
for (int row = firstRow; row <= lastRow; ++row)
{
- if (!m_items[row].loaded)
+ if (!m_items[row].loaded && !m_items[row].isFolder)
queueRow(row);
}
// Optional: preload nearby rows
int buffer = 20;
for (int row = firstRow - buffer; row < firstRow; ++row)
- if (row >= 0 && !m_items[row].loaded)
+ if (row >= 0 && !m_items[row].loaded && !m_items[row].isFolder)
queueRow(row);
for (int row = lastRow + 1; row <= lastRow + buffer; ++row)
- if (row < m_items.size() && !m_items[row].loaded)
+ if (row < m_items.size() && !m_items[row].loaded && !m_items[row].isFolder)
queueRow(row);
}
@@ -102,6 +121,18 @@ QString ImageModel::filePath(const QModelIndex &index) const
return m_items[index.row()].path;
}
+bool ImageModel::isFolder(const QModelIndex &index) const
+{
+ if (!index.isValid() || index.row() >= m_items.size())
+ return false;
+ return m_items[index.row()].isFolder;
+}
+
+QString ImageModel::currentDirectory() const
+{
+ return m_currentDir;
+}
+
int ImageModel::rowCount(const QModelIndex &) const
{
return m_items.size();
@@ -118,7 +149,7 @@ QVariant ImageModel::data(const QModelIndex &index, int role) const
return item.thumbnail;
if (role == Qt::DisplayRole)
- return QFileInfo(item.path).fileName();
+ return item.displayName;
return {};
}
diff --git a/imagemodel.h b/imagemodel.h index c124ae6..7586159 100644 --- a/imagemodel.h +++ b/imagemodel.h
@@ -6,6 +6,7 @@
#include <QThreadPool>
#include <QSet>
#include <atomic>
+#include <QIcon>
class ThumbnailWorker;
@@ -19,6 +20,8 @@ public:
void setDirectory(const QString &path);
QString filePath(const QModelIndex &index) const;
+ bool isFolder(const QModelIndex &index) const;
+ QString currentDirectory() const;
void requestThumbnails(int firstRow, int lastRow);
@@ -31,8 +34,10 @@ private:
struct Item
{
QString path;
+ QString displayName;
QPixmap thumbnail;
bool loaded = false;
+ bool isFolder = false;
};
void queueRow(int row);
@@ -43,4 +48,6 @@ private:
QSet<int> m_pendingRows;
std::atomic_bool m_cancelFlag{false};
+ QIcon m_folderIcon;
+ QString m_currentDir;
};
diff --git a/mainwindow.cpp b/mainwindow.cpp index 0dc9252..aa686c6 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp
@@ -125,7 +125,19 @@ void MainWindow::setupConnections()
this, [this](const QModelIndex &current) { showPreview(current); });
connect(m_listView, &QListView::doubleClicked, this,
- [this](const QModelIndex &index) { enterSingleImageMode(index); });
+ [this](const QModelIndex &index) {
+ if (m_imageModel->isFolder(index)) {
+ QString path = m_imageModel->filePath(index);
+ m_imageModel->setDirectory(path);
+ // Update tree view selection to match
+ QModelIndex dirIdx = m_dirModel->index(path);
+ if (dirIdx.isValid())
+ m_treeView->setCurrentIndex(dirIdx);
+ QTimer::singleShot(0, this, &MainWindow::loadVisibleThumbnails);
+ } else {
+ enterSingleImageMode(index);
+ }
+ });
connect(m_imageView, &ImageViewWidget::closeRequested,
this, &MainWindow::leaveSingleImageMode);
@@ -133,6 +145,8 @@ void MainWindow::setupConnections()
connect(m_imageView, &ImageViewWidget::nextRequested, this, [this]() {
QModelIndex cur = m_listView->currentIndex();
int next = cur.isValid() ? cur.row() + 1 : 0;
+ while (next < m_imageModel->rowCount() && m_imageModel->isFolder(m_imageModel->index(next)))
+ ++next;
if (next < m_imageModel->rowCount())
{
QModelIndex idx = m_imageModel->index(next);
@@ -144,6 +158,8 @@ void MainWindow::setupConnections()
connect(m_imageView, &ImageViewWidget::previousRequested, this, [this]() {
QModelIndex cur = m_listView->currentIndex();
int prev = cur.isValid() ? cur.row() - 1 : 0;
+ while (prev >= 0 && m_imageModel->isFolder(m_imageModel->index(prev)))
+ --prev;
if (prev >= 0)
{
QModelIndex idx = m_imageModel->index(prev);
@@ -245,7 +261,16 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
QModelIndex current = m_listView->currentIndex();
if (current.isValid())
{
- enterSingleImageMode(current);
+ if (m_imageModel->isFolder(current)) {
+ QString path = m_imageModel->filePath(current);
+ m_imageModel->setDirectory(path);
+ QModelIndex dirIdx = m_dirModel->index(path);
+ if (dirIdx.isValid())
+ m_treeView->setCurrentIndex(dirIdx);
+ QTimer::singleShot(0, this, &MainWindow::loadVisibleThumbnails);
+ } else {
+ enterSingleImageMode(current);
+ }
event->accept();
return;
}