pineapple-pictures/app/mainwindow.cpp

752 lines
22 KiB
C++
Raw Normal View History

// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
2019-09-28 01:18:08 +08:00
#include "mainwindow.h"
2020-07-28 21:14:38 +08:00
#include "settings.h"
2019-10-06 14:12:52 +08:00
#include "toolbutton.h"
2019-09-29 01:40:19 +08:00
#include "bottombuttongroup.h"
2019-09-28 01:18:08 +08:00
#include "graphicsview.h"
2019-10-03 17:57:14 +08:00
#include "navigatorview.h"
2019-09-29 15:52:35 +08:00
#include "graphicsscene.h"
2020-07-29 00:57:43 +08:00
#include "settingsdialog.h"
2020-09-28 20:10:33 +08:00
#include "aboutdialog.h"
2020-10-30 13:06:46 +08:00
#include "metadatamodel.h"
#include "metadatadialog.h"
#include "actionmanager.h"
#include "playlistmanager.h"
2019-09-28 01:18:08 +08:00
#include <QMouseEvent>
#include <QMovie>
#include <QDebug>
#include <QGraphicsTextItem>
2019-09-29 01:40:19 +08:00
#include <QApplication>
2019-09-29 15:52:35 +08:00
#include <QStyle>
#include <QScreen>
2019-10-05 13:21:49 +08:00
#include <QMenu>
2019-11-03 17:15:50 +08:00
#include <QShortcut>
#include <QClipboard>
#include <QMimeData>
#include <QWindow>
2021-10-02 19:57:42 +08:00
#include <QFile>
#include <QTimer>
#include <QFileDialog>
#include <QStandardPaths>
2022-01-21 16:48:43 +08:00
#include <QProcess>
#include <QDesktopServices>
2019-09-29 01:40:19 +08:00
MainWindow::MainWindow(QWidget *parent)
: FramelessWindow(parent)
, m_am(new ActionManager)
, m_pm(new PlaylistManager(PlaylistManager::PL_SAMEFOLDER, this))
2019-09-28 01:18:08 +08:00
{
2020-07-29 00:57:43 +08:00
if (Settings::instance()->stayOnTop()) {
this->setWindowFlag(Qt::WindowStaysOnTopHint);
2020-07-28 21:14:38 +08:00
}
2019-09-28 01:18:08 +08:00
this->setAttribute(Qt::WA_TranslucentBackground, true);
this->setMinimumSize(350, 330);
2019-10-01 11:44:35 +08:00
this->setWindowIcon(QIcon(":/icons/app-icon.svg"));
2020-07-04 13:49:12 +08:00
this->setMouseTracking(true);
2019-09-28 01:18:08 +08:00
m_pm->setAutoLoadFilterSuffix({"*.jpg", "*.jpeg", "*.jfif", "*.png", "*.gif", "*.svg", "*.bmp", "*.webp"});
2019-09-28 01:18:08 +08:00
m_fadeOutAnimation = new QPropertyAnimation(this, "windowOpacity");
m_fadeOutAnimation->setDuration(300);
m_fadeOutAnimation->setStartValue(1);
m_fadeOutAnimation->setEndValue(0);
m_floatUpAnimation = new QPropertyAnimation(this, "geometry");
m_floatUpAnimation->setDuration(300);
m_floatUpAnimation->setEasingCurve(QEasingCurve::OutCirc);
m_exitAnimationGroup = new QParallelAnimationGroup(this);
2019-09-28 01:18:08 +08:00
m_exitAnimationGroup->addAnimation(m_fadeOutAnimation);
m_exitAnimationGroup->addAnimation(m_floatUpAnimation);
connect(m_exitAnimationGroup, &QParallelAnimationGroup::finished,
this, &QWidget::close);
2019-09-28 01:18:08 +08:00
2019-09-29 15:52:35 +08:00
GraphicsScene * scene = new GraphicsScene(this);
2019-09-28 01:18:08 +08:00
m_graphicsView = new GraphicsView(this);
m_graphicsView->setScene(scene);
this->setCentralWidget(m_graphicsView);
2019-09-28 01:18:08 +08:00
2019-10-03 17:57:14 +08:00
m_gv = new NavigatorView(this);
2019-10-04 21:34:20 +08:00
m_gv->setFixedSize(220, 160);
2019-10-03 17:57:14 +08:00
m_gv->setScene(scene);
2019-10-04 09:54:13 +08:00
m_gv->setMainView(m_graphicsView);
2019-10-03 17:57:14 +08:00
m_gv->fitInView(m_gv->sceneRect(), Qt::KeepAspectRatio);
connect(m_graphicsView, &GraphicsView::navigatorViewRequired,
this, [ = ](bool required, const QTransform & tf){
m_gv->setTransform(GraphicsView::resetScale(tf));
2019-10-03 17:57:14 +08:00
m_gv->fitInView(m_gv->sceneRect(), Qt::KeepAspectRatio);
m_gv->setVisible(required);
m_gv->updateMainViewportRegion();
2019-10-03 17:57:14 +08:00
});
2019-10-04 09:54:13 +08:00
connect(m_graphicsView, &GraphicsView::viewportRectChanged,
m_gv, &NavigatorView::updateMainViewportRegion);
connect(m_graphicsView, &GraphicsView::requestGallery,
this, &MainWindow::loadGalleryBySingleLocalFile);
2020-07-04 13:49:12 +08:00
m_closeButton = new ToolButton(true, m_graphicsView);
2019-10-06 14:12:52 +08:00
m_closeButton->setIcon(QIcon(":/icons/window-close"));
m_closeButton->setIconSize(QSize(50, 50));
2019-09-28 01:18:08 +08:00
connect(m_closeButton, &QAbstractButton::clicked,
this, &MainWindow::closeWindow);
2019-09-29 01:40:19 +08:00
2020-07-04 13:49:12 +08:00
m_prevButton = new ToolButton(false, m_graphicsView);
m_prevButton->setIcon(QIcon(":/icons/go-previous"));
m_prevButton->setIconSize(QSize(75, 75));
m_prevButton->setVisible(false);
m_prevButton->setOpacity(0, false);
m_nextButton = new ToolButton(false, m_graphicsView);
m_nextButton->setIcon(QIcon(":/icons/go-next"));
m_nextButton->setIconSize(QSize(75, 75));
m_nextButton->setVisible(false);
m_nextButton->setOpacity(0, false);
connect(m_prevButton, &QAbstractButton::clicked,
this, &MainWindow::galleryPrev);
connect(m_nextButton, &QAbstractButton::clicked,
this, &MainWindow::galleryNext);
m_am->setupAction(this);
m_bottomButtonGroup = new BottomButtonGroup({
m_am->actionActualSize,
m_am->actionToggleMaximize,
m_am->actionZoomIn,
m_am->actionZoomOut,
m_am->actionToggleCheckerboard,
m_am->actionRotateClockwise
}, this);
2019-09-30 23:02:44 +08:00
2019-10-06 14:58:01 +08:00
m_bottomButtonGroup->setOpacity(0, false);
m_gv->setOpacity(0, false);
m_closeButton->setOpacity(0, false);
2019-10-03 11:00:28 +08:00
connect(m_pm, &PlaylistManager::loaded, this, [this](int galleryFileCount) {
m_prevButton->setVisible(galleryFileCount > 1);
m_nextButton->setVisible(galleryFileCount > 1);
2020-07-04 13:49:12 +08:00
});
2020-05-19 14:08:29 +08:00
QShortcut * fullscreenShorucut = new QShortcut(QKeySequence(QKeySequence::FullScreen), this);
connect(fullscreenShorucut, &QShortcut::activated,
this, &MainWindow::toggleFullscreen);
2019-10-01 11:44:35 +08:00
centerWindow();
QTimer::singleShot(0, this, [this](){
m_am->setupShortcuts();
});
2019-09-28 01:18:08 +08:00
}
MainWindow::~MainWindow()
{
}
void MainWindow::showUrls(const QList<QUrl> &urls)
{
if (!urls.isEmpty()) {
if (urls.count() == 1) {
m_graphicsView->showFileFromPath(urls.first().toLocalFile(), true);
} else {
m_graphicsView->showFileFromPath(urls.first().toLocalFile(), false);
m_pm->setPlaylist(urls);
m_pm->setCurrentIndex(0);
}
} else {
m_graphicsView->showText(tr("File url list is empty"));
return;
}
2019-10-03 17:57:14 +08:00
m_gv->fitInView(m_gv->sceneRect(), Qt::KeepAspectRatio);
}
void MainWindow::initWindowSize()
{
switch (Settings::instance()->initWindowSizeBehavior()) {
2022-03-12 10:35:23 +08:00
case Settings::WindowSizeBehavior::Auto:
adjustWindowSizeBySceneRect();
break;
2022-03-12 10:35:23 +08:00
case Settings::WindowSizeBehavior::Maximized:
showMaximized();
break;
2022-03-12 10:35:23 +08:00
default:
adjustWindowSizeBySceneRect();
break;
}
}
2019-10-01 11:44:35 +08:00
void MainWindow::adjustWindowSizeBySceneRect()
{
if (m_pm->count() < 1) return;
QSize sceneSize = m_graphicsView->sceneRect().toRect().size();
QSize sceneSizeWithMargins = sceneSize + QSize(130, 125);
if (m_graphicsView->scaleFactor() < 1 || size().expandedTo(sceneSizeWithMargins) != size()) {
2019-10-01 11:44:35 +08:00
// if it scaled down by the resize policy:
QSize screenSize = qApp->screenAt(QCursor::pos())->availableSize();
if (screenSize.expandedTo(sceneSize) == screenSize) {
// we can show the picture by increase the window size.
2020-07-27 20:47:54 +08:00
QSize finalSize = (screenSize.expandedTo(sceneSizeWithMargins) == screenSize) ?
sceneSizeWithMargins : screenSize;
// We have a very reasonable sizeHint() value ;P
this->resize(finalSize.expandedTo(this->sizeHint()));
2019-10-05 12:55:09 +08:00
// We're sure the window can display the whole thing with 1:1 scale.
// The old window size may cause fitInView call from resize() and the
// above resize() call won't reset the scale back to 1:1, so we
// just call resetScale() here to ensure the thing is no longer scaled.
m_graphicsView->resetScale();
2019-10-01 11:44:35 +08:00
centerWindow();
} else {
// toggle maximum
showMaximized();
}
}
}
// can be empty if it is NOT from a local file.
QUrl MainWindow::currentImageFileUrl() const
{
QUrl url;
std::tie(std::ignore, url) = m_pm->currentFileUrl();
return url;
}
void MainWindow::clearGallery()
{
m_pm->clear();
}
void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
{
m_pm->setCurrentFile(path);
}
void MainWindow::galleryPrev()
{
int index;
QString filePath;
std::tie(index, filePath) = m_pm->previousFile();
if (index >= 0) {
m_graphicsView->showFileFromPath(filePath, false);
m_pm->setCurrentIndex(index);
}
}
void MainWindow::galleryNext()
{
int index;
QString filePath;
std::tie(index, filePath) = m_pm->nextFile();
if (index >= 0) {
m_graphicsView->showFileFromPath(filePath, false);
m_pm->setCurrentIndex(index);
2020-07-04 13:49:12 +08:00
}
}
2019-09-29 01:40:19 +08:00
void MainWindow::showEvent(QShowEvent *event)
{
updateWidgetsPosition();
return FramelessWindow::showEvent(event);
2019-09-29 01:40:19 +08:00
}
2021-10-02 19:57:42 +08:00
void MainWindow::enterEvent(QT_ENTER_EVENT *event)
2019-10-03 11:00:28 +08:00
{
2019-10-06 14:58:01 +08:00
m_bottomButtonGroup->setOpacity(1);
m_gv->setOpacity(1);
2019-10-03 11:00:28 +08:00
2019-10-06 14:58:01 +08:00
m_closeButton->setOpacity(1);
2020-07-04 13:49:12 +08:00
m_prevButton->setOpacity(1);
m_nextButton->setOpacity(1);
2019-10-06 14:12:52 +08:00
return FramelessWindow::enterEvent(event);
2019-10-03 11:00:28 +08:00
}
void MainWindow::leaveEvent(QEvent *event)
{
2019-10-06 14:58:01 +08:00
m_bottomButtonGroup->setOpacity(0);
m_gv->setOpacity(0);
2019-10-03 11:00:28 +08:00
2019-10-06 14:58:01 +08:00
m_closeButton->setOpacity(0);
2020-07-04 13:49:12 +08:00
m_prevButton->setOpacity(0);
m_nextButton->setOpacity(0);
2019-10-06 14:12:52 +08:00
return FramelessWindow::leaveEvent(event);
2019-10-03 11:00:28 +08:00
}
2019-09-28 01:18:08 +08:00
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton && !isMaximized()) {
2019-09-28 01:18:08 +08:00
m_clickedOnWindow = true;
m_oldMousePos = event->pos();
// qDebug() << m_oldMousePos << m_graphicsView->transform().m11()
// << m_graphicsView->transform().m22() << m_graphicsView->matrix().m12();
2019-09-28 01:18:08 +08:00
event->accept();
}
return FramelessWindow::mousePressEvent(event);
2019-09-28 01:18:08 +08:00
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
2020-07-28 21:14:38 +08:00
if (event->buttons() & Qt::LeftButton && m_clickedOnWindow && !isMaximized()) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
if (!window()->windowHandle()->startSystemMove()) {
move(event->globalPos() - m_oldMousePos);
}
#else
2019-09-28 01:18:08 +08:00
move(event->globalPos() - m_oldMousePos);
#endif // QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
2019-09-28 01:18:08 +08:00
event->accept();
}
return FramelessWindow::mouseMoveEvent(event);
2019-09-28 01:18:08 +08:00
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
m_clickedOnWindow = false;
// It seems the forward/back mouse button won't generate a key event [1] so we can't use
// QShortcut or QKeySequence to indicate these shortcuts, so we do it here.
// Reference:
// [1]: https://codereview.qt-project.org/c/qt/qtbase/+/177475
if (event->button() == Qt::ForwardButton || event->button() == Qt::BackButton) {
event->button() == Qt::BackButton ? galleryPrev() : galleryNext();
event->accept();
}
return FramelessWindow::mouseReleaseEvent(event);
2019-09-28 01:18:08 +08:00
}
void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
// The forward/back mouse button can also used to trigger a mouse double-click event
// Since we use that for gallery navigation so we ignore these two buttons.
if (event->buttons() & Qt::ForwardButton || event->buttons() & Qt::BackButton) {
return;
}
2020-07-28 21:14:38 +08:00
switch (Settings::instance()->doubleClickBehavior()) {
2022-03-12 10:35:23 +08:00
case Settings::DoubleClickBehavior::Close:
2020-07-28 21:14:38 +08:00
quitAppAction();
event->accept();
break;
2022-03-12 10:35:23 +08:00
case Settings::DoubleClickBehavior::Maximize:
2020-07-28 21:14:38 +08:00
toggleMaximize();
event->accept();
break;
2022-03-12 10:35:23 +08:00
case Settings::DoubleClickBehavior::Ignore:
2020-07-28 21:14:38 +08:00
break;
}
2019-09-28 01:18:08 +08:00
2020-07-28 21:14:38 +08:00
// blumia: don't call parent constructor here, seems it will cause mouse move
// event get called even if we set event->accept();
// return QMainWindow::mouseDoubleClickEvent(event);
2019-09-28 01:18:08 +08:00
}
2019-10-04 09:54:13 +08:00
void MainWindow::wheelEvent(QWheelEvent *event)
{
2020-07-12 23:45:49 +08:00
QPoint numDegrees = event->angleDelta() / 8;
bool needWeelEvent = false, wheelUp = false;
bool actionIsZoom = event->modifiers().testFlag(Qt::ControlModifier)
2022-03-12 10:35:23 +08:00
|| Settings::instance()->mouseWheelBehavior() == Settings::MouseWheelBehavior::Zoom;
2020-07-12 23:45:49 +08:00
// NOTE: Only checking angleDelta since the QWheelEvent::pixelDelta() doc says
// pixelDelta() value is driver specific and unreliable on X11...
// We are not scrolling the canvas, just zoom in or out, so it probably
// doesn't matter here.
if (!numDegrees.isNull() && numDegrees.y() != 0) {
needWeelEvent = true;
wheelUp = numDegrees.y() > 0;
2020-07-12 23:45:49 +08:00
}
if (needWeelEvent) {
if (actionIsZoom) {
if (wheelUp) {
on_actionZoomIn_triggered();
} else {
on_actionZoomOut_triggered();
}
} else {
if (wheelUp) {
galleryPrev();
} else {
galleryNext();
}
}
2020-07-12 23:45:49 +08:00
event->accept();
2019-10-04 09:54:13 +08:00
} else {
FramelessWindow::wheelEvent(event);
2019-10-04 09:54:13 +08:00
}
}
2019-09-28 01:18:08 +08:00
void MainWindow::resizeEvent(QResizeEvent *event)
{
2019-09-29 01:40:19 +08:00
updateWidgetsPosition();
2019-09-28 01:18:08 +08:00
return FramelessWindow::resizeEvent(event);
2019-09-28 01:18:08 +08:00
}
2019-10-05 13:21:49 +08:00
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
QMenu * menu = new QMenu;
QMenu * copyMenu = new QMenu(tr("&Copy"));
QUrl currentFileUrl = currentImageFileUrl();
QImage clipboardImage;
QUrl clipboardFileUrl;
QAction * copyPixmap = m_am->actionCopyPixmap;
QAction * copyFilePath = m_am->actionCopyFilePath;
copyMenu->addAction(copyPixmap);
if (currentFileUrl.isValid()) {
copyMenu->addAction(copyFilePath);
}
QAction * paste = m_am->actionPaste;
QAction * stayOnTopMode = m_am->actionToggleStayOnTop;
2019-10-06 12:57:38 +08:00
stayOnTopMode->setCheckable(true);
stayOnTopMode->setChecked(stayOnTop());
2020-07-29 00:57:43 +08:00
QAction * protectedMode = m_am->actionToggleProtectMode;
2019-10-05 13:21:49 +08:00
protectedMode->setCheckable(true);
protectedMode->setChecked(m_protectedMode);
2020-07-29 00:57:43 +08:00
QAction * toggleSettings = m_am->actionSettings;
QAction * helpAction = m_am->actionHelp;
QAction * propertiesAction = m_am->actionProperties;
2020-10-30 13:06:46 +08:00
#if 0
menu->addAction(m_am->actionOpen);
#endif // 0
if (copyMenu->actions().count() == 1) {
menu->addActions(copyMenu->actions());
} else {
menu->addMenu(copyMenu);
}
if (canPaste()) {
menu->addAction(paste);
}
2021-03-19 23:11:06 +08:00
menu->addSeparator();
menu->addAction(m_am->actionHorizontalFlip);
#if 0
2021-06-04 13:53:47 +08:00
menu->addAction(m_am->actionFitInView);
menu->addAction(m_am->actionFitByWidth);
#endif // 0
menu->addSeparator();
2019-10-06 12:57:38 +08:00
menu->addAction(stayOnTopMode);
2019-10-05 13:21:49 +08:00
menu->addAction(protectedMode);
menu->addSeparator();
2020-07-29 00:57:43 +08:00
menu->addAction(toggleSettings);
menu->addAction(helpAction);
2020-10-30 13:06:46 +08:00
if (currentFileUrl.isValid()) {
menu->addSeparator();
2022-01-21 16:48:43 +08:00
if (currentFileUrl.isLocalFile()) {
menu->addAction(m_am->actionLocateInFileManager);
}
2020-10-30 13:06:46 +08:00
menu->addAction(propertiesAction);
}
2019-10-05 13:21:49 +08:00
menu->exec(mapToGlobal(event->pos()));
menu->deleteLater();
copyMenu->deleteLater();
2019-10-05 13:21:49 +08:00
return FramelessWindow::contextMenuEvent(event);
2019-10-05 13:21:49 +08:00
}
2019-10-01 11:44:35 +08:00
void MainWindow::centerWindow()
{
this->setGeometry(
QStyle::alignedRect(
Qt::LeftToRight,
Qt::AlignCenter,
this->size(),
qApp->screenAt(QCursor::pos())->geometry()
)
);
}
2019-09-28 01:18:08 +08:00
void MainWindow::closeWindow()
{
QRect windowRect(this->geometry());
m_floatUpAnimation->setStartValue(windowRect);
m_floatUpAnimation->setEndValue(windowRect.adjusted(0, -80, 0, 0));
m_floatUpAnimation->setStartValue(QRect(this->geometry().x(), this->geometry().y(), this->geometry().width(), this->geometry().height()));
m_floatUpAnimation->setEndValue(QRect(this->geometry().x(), this->geometry().y()-80, this->geometry().width(), this->geometry().height()));
m_exitAnimationGroup->start();
}
2019-09-29 01:40:19 +08:00
void MainWindow::updateWidgetsPosition()
{
m_closeButton->move(width() - m_closeButton->width(), 0);
m_prevButton->move(25, (height() - m_prevButton->sizeHint().height()) / 2);
m_nextButton->move(width() - m_nextButton->sizeHint().width() - 25,
(height() - m_prevButton->sizeHint().height()) / 2);
2019-09-29 01:40:19 +08:00
m_bottomButtonGroup->move((width() - m_bottomButtonGroup->width()) / 2,
height() - m_bottomButtonGroup->height());
2019-10-03 17:57:14 +08:00
m_gv->move(width() - m_gv->width(), height() - m_gv->height());
2019-09-29 01:40:19 +08:00
}
2019-10-05 13:21:49 +08:00
void MainWindow::toggleProtectedMode()
{
m_protectedMode = !m_protectedMode;
m_closeButton->setVisible(!m_protectedMode);
2020-07-04 13:49:12 +08:00
m_prevButton->setVisible(!m_protectedMode);
m_nextButton->setVisible(!m_protectedMode);
2019-10-05 13:21:49 +08:00
}
2019-10-06 12:57:38 +08:00
void MainWindow::toggleStayOnTop()
{
setWindowFlag(Qt::WindowStaysOnTopHint, !stayOnTop());
show();
2019-10-06 12:57:38 +08:00
}
bool MainWindow::stayOnTop() const
2019-10-06 12:57:38 +08:00
{
return windowFlags().testFlag(Qt::WindowStaysOnTopHint);
}
2019-11-03 17:15:50 +08:00
bool MainWindow::canPaste() const
{
const QMimeData * clipboardData = QApplication::clipboard()->mimeData();
if (clipboardData->hasImage()) {
return true;
} else if (clipboardData->hasText()) {
QString clipboardText(clipboardData->text());
if (clipboardText.startsWith("PICTURE:")) {
QString maybeFilename(clipboardText.mid(8));
if (QFile::exists(maybeFilename)) {
return true;
}
}
}
return false;
}
2019-11-03 17:15:50 +08:00
void MainWindow::quitAppAction(bool force)
{
if (!m_protectedMode || force) {
closeWindow();
}
}
2020-05-19 14:08:29 +08:00
void MainWindow::toggleFullscreen()
{
if (isFullScreen()) {
showNormal();
} else {
showFullScreen();
}
}
2020-07-28 21:14:38 +08:00
void MainWindow::toggleMaximize()
{
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
}
2021-01-10 14:57:01 +08:00
QSize MainWindow::sizeHint() const
{
return QSize(710, 530);
}
void MainWindow::on_actionOpen_triggered()
{
QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
QUrl pictureUrl = picturesLocations.isEmpty() ? QUrl::fromLocalFile(picturesLocations.first())
: QUrl::fromLocalFile(QDir::homePath());
QList<QUrl> urls(QFileDialog::getOpenFileUrls(this, QString(), pictureUrl));
if (!urls.isEmpty()) {
showUrls(urls);
}
}
void MainWindow::on_actionActualSize_triggered()
{
m_graphicsView->resetScale();
m_graphicsView->setEnableAutoFitInView(false);
}
void MainWindow::on_actionToggleMaximize_triggered()
{
toggleMaximize();
}
void MainWindow::on_actionZoomIn_triggered()
{
if (m_graphicsView->scaleFactor() < 1000) {
m_graphicsView->zoomView(1.25);
}
}
void MainWindow::on_actionZoomOut_triggered()
{
m_graphicsView->zoomView(0.8);
}
2021-03-19 23:11:06 +08:00
void MainWindow::on_actionHorizontalFlip_triggered()
{
m_graphicsView->flipView();
}
2021-06-04 13:53:47 +08:00
void MainWindow::on_actionFitInView_triggered()
{
m_graphicsView->fitInView(m_gv->sceneRect(), Qt::KeepAspectRatio);
m_graphicsView->setEnableAutoFitInView(m_graphicsView->scaleFactor() <= 1);
2021-06-04 13:53:47 +08:00
}
void MainWindow::on_actionFitByWidth_triggered()
{
m_graphicsView->fitByOrientation();
}
void MainWindow::on_actionCopyPixmap_triggered()
{
QClipboard *cb = QApplication::clipboard();
cb->setPixmap(m_graphicsView->scene()->renderToPixmap());
}
void MainWindow::on_actionCopyFilePath_triggered()
{
QUrl currentFileUrl(currentImageFileUrl());
if (currentFileUrl.isValid()) {
QClipboard *cb = QApplication::clipboard();
cb->setText(currentFileUrl.toLocalFile());
}
}
void MainWindow::on_actionPaste_triggered()
{
QImage clipboardImage;
QUrl clipboardFileUrl;
const QMimeData * clipboardData = QApplication::clipboard()->mimeData();
if (clipboardData->hasImage()) {
QVariant imageVariant(clipboardData->imageData());
if (imageVariant.isValid()) {
clipboardImage = qvariant_cast<QImage>(imageVariant);
}
} else if (clipboardData->hasText()) {
QString clipboardText(clipboardData->text());
if (clipboardText.startsWith("PICTURE:")) {
QString maybeFilename(clipboardText.mid(8));
if (QFile::exists(maybeFilename)) {
clipboardFileUrl = QUrl::fromLocalFile(maybeFilename);
}
}
}
if (!clipboardImage.isNull()) {
m_graphicsView->showImage(clipboardImage);
clearGallery();
} else if (clipboardFileUrl.isValid()) {
QString localFile(clipboardFileUrl.toLocalFile());
m_graphicsView->showFileFromPath(localFile, true);
m_pm->setCurrentFile(localFile);
}
}
void MainWindow::on_actionToggleCheckerboard_triggered()
{
// TODO: is that okay to do this since we plan to support custom shortcuts?
m_graphicsView->toggleCheckerboard(QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier));
}
void MainWindow::on_actionRotateClockwise_triggered()
{
m_graphicsView->rotateView();
m_graphicsView->displayScene();
m_gv->setVisible(false);
}
void MainWindow::on_actionPrevPicture_triggered()
{
galleryPrev();
}
void MainWindow::on_actionNextPicture_triggered()
{
galleryNext();
}
void MainWindow::on_actionToggleStayOnTop_triggered()
{
toggleStayOnTop();
}
void MainWindow::on_actionToggleProtectMode_triggered()
{
toggleProtectedMode();
}
void MainWindow::on_actionSettings_triggered()
{
SettingsDialog * sd = new SettingsDialog(this);
sd->exec();
sd->deleteLater();
}
void MainWindow::on_actionHelp_triggered()
{
AboutDialog * ad = new AboutDialog(this);
ad->exec();
ad->deleteLater();
}
void MainWindow::on_actionProperties_triggered()
{
QUrl currentFileUrl = currentImageFileUrl();
if (!currentFileUrl.isValid()) return;
MetadataModel * md = new MetadataModel();
md->setFile(currentFileUrl.toLocalFile());
MetadataDialog * ad = new MetadataDialog(this);
ad->setMetadataModel(md);
ad->exec();
ad->deleteLater();
}
2022-01-21 16:48:43 +08:00
void MainWindow::on_actionLocateInFileManager_triggered()
{
QUrl currentFileUrl = currentImageFileUrl();
if (!currentFileUrl.isValid()) return;
QFileInfo fileInfo(currentFileUrl.toLocalFile());
if (!fileInfo.exists()) return;
#ifdef Q_OS_WIN
QProcess::startDetached("explorer", QStringList() << "/select," << QDir::toNativeSeparators(fileInfo.absoluteFilePath()));
#else
// maybe use https://www.freedesktop.org/wiki/Specifications/file-manager-interface/ for linux?
QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absolutePath()));
#endif // Q_OS_WIN
}
void MainWindow::on_actionQuitApp_triggered()
{
quitAppAction(false);
}