diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eba63e..eb016dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ qt_add_executable(ImageBrowser imagemodel.h thumbnailworker.cpp thumbnailworker.h + imageviewwidget.cpp + imageviewwidget.h ) target_link_libraries(ImageBrowser PRIVATE Qt6::Widgets) \ No newline at end of file diff --git a/imageviewwidget.cpp b/imageviewwidget.cpp new file mode 100644 index 0000000..2ff637b --- /dev/null +++ b/imageviewwidget.cpp @@ -0,0 +1,50 @@ +#include "imageviewwidget.h" + +#include +#include +#include + +ImageViewWidget::ImageViewWidget(QWidget *parent) + : QWidget(parent) +{ + setFocusPolicy(Qt::StrongFocus); + setStyleSheet("background-color: black;"); +} + +void ImageViewWidget::setImage(const QString &path) +{ + QImageReader reader(path); + reader.setAutoTransform(true); + QImage image = reader.read(); + + if (!image.isNull()) + m_pixmap = QPixmap::fromImage(image); + else + m_pixmap = QPixmap(); + + update(); +} + +void ImageViewWidget::paintEvent(QPaintEvent *) +{ + if (m_pixmap.isNull()) + return; + + QPainter painter(this); + QPixmap scaled = m_pixmap.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + int x = (width() - scaled.width()) / 2; + int y = (height() - scaled.height()) / 2; + painter.drawPixmap(x, y, scaled); +} + +void ImageViewWidget::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) + { + emit closeRequested(); + event->accept(); + return; + } + + QWidget::keyPressEvent(event); +} diff --git a/imageviewwidget.h b/imageviewwidget.h new file mode 100644 index 0000000..f10cd29 --- /dev/null +++ b/imageviewwidget.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include + +class ImageViewWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ImageViewWidget(QWidget *parent = nullptr); + + void setImage(const QString &path); + +signals: + void closeRequested(); + +protected: + void paintEvent(QPaintEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + +private: + QPixmap m_pixmap; +}; diff --git a/mainwindow.cpp b/mainwindow.cpp index 2c297e3..504f0b0 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,17 +1,20 @@ #include "mainwindow.h" #include "imagemodel.h" +#include "imageviewwidget.h" #include #include #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -68,7 +71,17 @@ void MainWindow::setupUi() mainSplitter->addWidget(rightSplitter); mainSplitter->setStretchFactor(1, 1); - setCentralWidget(mainSplitter); + m_browserPage = mainSplitter; + + // Single image view + m_imageView = new ImageViewWidget; + + // Stack to switch between browser and single image + m_stack = new QStackedWidget; + m_stack->addWidget(m_browserPage); + m_stack->addWidget(m_imageView); + + setCentralWidget(m_stack); } void MainWindow::setupConnections() @@ -88,6 +101,12 @@ void MainWindow::setupConnections() connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex ¤t) { showPreview(current); }); + connect(m_listView, &QListView::doubleClicked, this, + [this](const QModelIndex &index) { enterSingleImageMode(index); }); + + connect(m_imageView, &ImageViewWidget::closeRequested, + this, &MainWindow::leaveSingleImageMode); + connect(m_listView->verticalScrollBar(), &QScrollBar::valueChanged, this, [this]() { loadVisibleThumbnails(); }); @@ -139,3 +158,53 @@ void MainWindow::showPreview(const QModelIndex &index) Qt::KeepAspectRatio, Qt::SmoothTransformation)); } + +void MainWindow::enterSingleImageMode(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + QString path = m_imageModel->filePath(index); + m_imageView->setImage(path); + m_stack->setCurrentWidget(m_imageView); + m_imageView->setFocus(); +} + +void MainWindow::leaveSingleImageMode() +{ + if (isFullScreen()) + { + if (m_wasFullScreen) + showFullScreen(); + else + showNormal(); + } + m_stack->setCurrentWidget(m_browserPage); + m_listView->setFocus(); +} + +void MainWindow::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_F11 && m_stack->currentWidget() == m_imageView) + { + if (isFullScreen()) + showNormal(); + else + showFullScreen(); + event->accept(); + return; + } + + if (event->key() == Qt::Key_Return && m_stack->currentWidget() == m_browserPage) + { + QModelIndex current = m_listView->currentIndex(); + if (current.isValid()) + { + enterSingleImageMode(current); + event->accept(); + return; + } + } + + QMainWindow::keyPressEvent(event); +} diff --git a/mainwindow.h b/mainwindow.h index 7b01b44..4072447 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -5,8 +5,10 @@ class QTreeView; class QListView; class QLabel; +class QStackedWidget; class QFileSystemModel; class ImageModel; +class ImageViewWidget; class MainWindow : public QMainWindow { @@ -20,7 +22,10 @@ private: void setupConnections(); void loadVisibleThumbnails(); void showPreview(const QModelIndex &index); + void enterSingleImageMode(const QModelIndex &index); + void leaveSingleImageMode(); + void keyPressEvent(QKeyEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override; QFileSystemModel *m_dirModel; @@ -29,4 +34,9 @@ private: QTreeView *m_treeView; QListView *m_listView; QLabel *m_previewLabel; + + QStackedWidget *m_stack; + QWidget *m_browserPage; + ImageViewWidget *m_imageView; + bool m_wasFullScreen = false; };