diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a82e3fd..e631c72 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -34,6 +34,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -48,6 +53,19 @@ ThumbnailCache::Size thumbnailSizeFromString(const QString &s) return (s == "large") ? ThumbnailCache::Size::Large : ThumbnailCache::Size::Normal; } + +QString displayPath(const QByteArray &path) +{ + return QString::fromLocal8Bit(path.constData(), path.size()); +} + +QString filenameFromPath(const QByteArray &path) +{ + const std::filesystem::path fsPath(path.toStdString()); + const std::string nativeName = fsPath.filename().native(); + return QString::fromLocal8Bit(nativeName.data(), + static_cast(nativeName.size())); +} } // namespace MainWindow::MainWindow(QWidget *parent) @@ -101,6 +119,7 @@ void MainWindow::setupUi() m_listView->setWordWrap(true); m_listView->setTextElideMode(Qt::ElideRight); m_listView->setItemDelegate(new ThumbnailDelegate(this)); + m_listView->setContextMenuPolicy(Qt::CustomContextMenu); // Preview pane (right) m_previewLabel = new QLabel; @@ -380,6 +399,9 @@ void MainWindow::setupConnections() } }); + connect(m_listView, &QListView::customContextMenuRequested, + this, &MainWindow::showImageContextMenu); + connect(m_imageView, &ImageViewWidget::closeRequested, this, &MainWindow::leaveSingleImageMode); connect(m_imageView, &ImageViewWidget::editCaptionRequested, @@ -550,14 +572,22 @@ void MainWindow::enterSingleImageMode(const QModelIndex &index) void MainWindow::onEditCaption() { - const QByteArray path = m_imageView->currentPath(); + QByteArray path; + if (m_stack->currentWidget() == m_imageView) { + path = m_imageView->currentPath(); + } else { + const QModelIndex index = m_listView->currentIndex(); + if (index.isValid() && !m_imageModel->isFolder(index)) + path = m_imageModel->filePath(index); + } + if (path.isEmpty()) return; if (::access(path.constData(), W_OK) != 0) { QMessageBox::warning(this, tr("Cannot Edit Caption"), tr("The file is write-protected and cannot be edited.\n\n%1") - .arg(QString::fromLocal8Bit(path))); + .arg(displayPath(path))); return; } @@ -583,11 +613,39 @@ void MainWindow::onEditCaption() const QString newCaption = edit->toPlainText(); if (ExifReader::saveCaption(path, newCaption, data)) { ExifData updated = ExifReader::read(path); - m_imageView->setExifData(updated); + if (m_imageView->currentPath() == path) + m_imageView->setExifData(updated); updateExifInfo(path); } } +void MainWindow::showImageContextMenu(const QPoint &pos) +{ + const QModelIndex index = m_listView->indexAt(pos); + if (!index.isValid() || m_imageModel->isFolder(index)) + return; + + m_listView->setCurrentIndex(index); + showPreview(index); + + const QByteArray path = m_imageModel->filePath(index); + + QMenu menu(this); + QAction *copyFilenameAction = menu.addAction(tr("Copy filename")); + QAction *copyFullPathAction = menu.addAction(tr("Copy full path")); + menu.addSeparator(); + QAction *editDescriptionAction = menu.addAction(tr("Edit description")); + + QAction *chosen = menu.exec(m_listView->viewport()->mapToGlobal(pos)); + if (chosen == copyFilenameAction) { + QGuiApplication::clipboard()->setText(filenameFromPath(path)); + } else if (chosen == copyFullPathAction) { + QGuiApplication::clipboard()->setText(displayPath(path)); + } else if (chosen == editDescriptionAction) { + onEditCaption(); + } +} + void MainWindow::leaveSingleImageMode() { if (isFullScreen()) { diff --git a/src/mainwindow.h b/src/mainwindow.h index d597ddb..1e3e8b4 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -15,6 +15,7 @@ class QTableWidget; class QLineEdit; class QPushButton; class QCompleter; +class QPoint; class ImageModel; class ImageViewWidget; class PathCompleterModel; @@ -46,6 +47,7 @@ private: void enterSingleImageMode(const QModelIndex &index); void leaveSingleImageMode(); void onEditCaption(); + void showImageContextMenu(const QPoint &pos); void onPathEntered(); void updatePathField(const QByteArray &path); QList computeNeighborPaths(const QModelIndex &index) const; @@ -93,4 +95,4 @@ private: bool m_lockDockingPreference = false; void applyDockLocking(bool lock); -}; \ No newline at end of file +};