feat: update action manager
- add and delete some actions in action manager. - rename "fit to view" to "fit to screen". - update main window right click menu and toolbar. - use special state update slot in action manager instead of function located in main window.
This commit is contained in:
@@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
#include "actionmanager.h"
|
#include "actionmanager.h"
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "playlistmanager.h"
|
||||||
|
#include "graphicsview.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QSvgRenderer>
|
#include <QSvgRenderer>
|
||||||
@@ -25,6 +29,8 @@ void ActionManager::setupAction(MainWindow *mainWindow)
|
|||||||
{
|
{
|
||||||
// region: Action and Its Icon Creation
|
// region: Action and Its Icon Creation
|
||||||
|
|
||||||
|
// Declare some convenient macros and lambdas.
|
||||||
|
|
||||||
#define ICON_NAME(name)\
|
#define ICON_NAME(name)\
|
||||||
QStringLiteral(":/icons/" #name ".svg")
|
QStringLiteral(":/icons/" #name ".svg")
|
||||||
|
|
||||||
@@ -39,40 +45,51 @@ void ActionManager::setupAction(MainWindow *mainWindow)
|
|||||||
w->addAction(*a);
|
w->addAction(*a);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CREATE_NEW_ICON_ACTION(w, a, i) create_action(w, &a, ICON_NAME(i), ACTION_NAME(a))
|
/// This macro for register normal action.
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionActualSize, zoom-original);
|
#define CREATE_NEW_ACTION(w, a) create_action(w, &a, QString(), ACTION_NAME(a))
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleMaximize, view-fullscreen);
|
/// This macro for register Qt theme action.
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomIn, zoom-in);
|
#define CREATE_NEW_THEMEICON_ACTION(w, a, i) create_action(w, &a, QLatin1String(STRIFY(i)), ACTION_NAME(a), true)
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomOut, zoom-out);
|
/// This macro for register action with our custom icon.
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleCheckerboard, view-background-checkerboard);
|
#define CREATE_NEW_ICON_ACTION(w, a, i) create_action(w, &a, ICON_NAME(i), ACTION_NAME(a), false)
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionRotateClockwise, object-rotate-right);
|
|
||||||
|
// TODO: We may replace all Qt theme icons to our custom icon for visual consistency.
|
||||||
|
// TODO: Some icons are invalid.
|
||||||
|
|
||||||
|
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionCopyPixmap, edit-copy);
|
||||||
|
CREATE_NEW_ACTION(mainWindow, actionCopyFilePath);
|
||||||
|
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionPrevPicture, go-previous);
|
CREATE_NEW_ICON_ACTION(mainWindow, actionPrevPicture, go-previous);
|
||||||
CREATE_NEW_ICON_ACTION(mainWindow, actionNextPicture, go-next);
|
CREATE_NEW_ICON_ACTION(mainWindow, actionNextPicture, go-next);
|
||||||
#undef CREATE_NEW_ICON_ACTION
|
|
||||||
|
|
||||||
#define CREATE_NEW_ACTION(w, a) create_action(w, &a, QString(), ACTION_NAME(a))
|
CREATE_NEW_ICON_ACTION(mainWindow, actionActualSize, zoom-original);
|
||||||
#define CREATE_NEW_THEMEICON_ACTION(w, a, i) create_action(w, &a, QLatin1String(STRIFY(i)), ACTION_NAME(a), true)
|
CREATE_NEW_ICON_ACTION(mainWindow, actionFitToScreen, app-icon);
|
||||||
CREATE_NEW_ACTION(mainWindow, actionRotateCounterClockwise);
|
CREATE_NEW_ICON_ACTION(mainWindow, actionFitByWidth, app-icon);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionFitByHeight, app-icon);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomIn, zoom-in);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomOut, zoom-out);
|
||||||
|
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionFlipHorizontal, app-icon);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionFlipVertical, app-icon);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionRotateClockwise, object-rotate-right);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionRotateCounterClockwise, app-icon);
|
||||||
|
|
||||||
|
CREATE_NEW_ACTION(mainWindow, actionToggleAvoidResetTransform);
|
||||||
|
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleCheckerboard, view-background-checkerboard);
|
||||||
CREATE_NEW_ACTION(mainWindow, actionTogglePauseAnimation);
|
CREATE_NEW_ACTION(mainWindow, actionTogglePauseAnimation);
|
||||||
CREATE_NEW_ACTION(mainWindow, actionAnimationNextFrame);
|
CREATE_NEW_ACTION(mainWindow, actionAnimationNextFrame);
|
||||||
|
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionOpen, document-open);
|
|
||||||
CREATE_NEW_ACTION(mainWindow, actionHorizontalFlip);
|
|
||||||
CREATE_NEW_ACTION(mainWindow, actionFitInView);
|
|
||||||
CREATE_NEW_ACTION(mainWindow, actionFitByWidth);
|
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionCopyPixmap, edit-copy);
|
|
||||||
CREATE_NEW_ACTION(mainWindow, actionCopyFilePath);
|
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionPaste, edit-paste);
|
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionTrash, edit-delete);
|
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionTrash, edit-delete);
|
||||||
CREATE_NEW_ACTION(mainWindow, actionToggleAvoidResetTransform);
|
|
||||||
CREATE_NEW_ACTION(mainWindow, actionSettings);
|
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionHelp, system-help);
|
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionLocateInFileManager, system-file-manager);
|
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionLocateInFileManager, system-file-manager);
|
||||||
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionProperties, document-properties);
|
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionProperties, document-properties);
|
||||||
CREATE_NEW_ACTION(mainWindow, actionQuitApp);
|
|
||||||
#undef CREATE_NEW_ACTION
|
CREATE_NEW_ACTION(mainWindow, actionSettings);
|
||||||
|
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionHelp, system-help);
|
||||||
|
|
||||||
|
// Remove convenient macros
|
||||||
|
|
||||||
|
#undef CREATE_NEW_ICON_ACTION
|
||||||
#undef CREATE_NEW_THEMEICON_ACTION
|
#undef CREATE_NEW_THEMEICON_ACTION
|
||||||
|
#undef CREATE_NEW_ACTION
|
||||||
|
|
||||||
#undef STRIFY
|
#undef STRIFY
|
||||||
#undef ACTION_NAME
|
#undef ACTION_NAME
|
||||||
@@ -80,34 +97,40 @@ void ActionManager::setupAction(MainWindow *mainWindow)
|
|||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
// region: Setup Checkable Action
|
||||||
|
|
||||||
|
actionToggleAvoidResetTransform->setCheckable(true);
|
||||||
|
actionToggleCheckerboard->setCheckable(true);
|
||||||
|
actionTogglePauseAnimation->setCheckable(true);
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
// region: Action Translatable Text Setup
|
// region: Action Translatable Text Setup
|
||||||
|
|
||||||
actionOpen->setText(QCoreApplication::translate("MainWindow", "&Open...", nullptr));
|
actionCopyPixmap->setText(QCoreApplication::translate("MainWindow", "Copy P&ixmap", nullptr));
|
||||||
|
actionCopyFilePath->setText(QCoreApplication::translate("MainWindow", "Copy &File Path", nullptr));
|
||||||
actionActualSize->setText(QCoreApplication::translate("MainWindow", "Actual size", nullptr));
|
|
||||||
actionToggleMaximize->setText(QCoreApplication::translate("MainWindow", "Toggle maximize", nullptr));
|
|
||||||
actionZoomIn->setText(QCoreApplication::translate("MainWindow", "Zoom in", nullptr));
|
|
||||||
actionZoomOut->setText(QCoreApplication::translate("MainWindow", "Zoom out", nullptr));
|
|
||||||
actionToggleCheckerboard->setText(QCoreApplication::translate("MainWindow", "Toggle Checkerboard", nullptr));
|
|
||||||
actionRotateClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate right", nullptr));
|
|
||||||
actionRotateCounterClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate left", nullptr));
|
|
||||||
|
|
||||||
actionPrevPicture->setText(QCoreApplication::translate("MainWindow", "Previous image", nullptr));
|
actionPrevPicture->setText(QCoreApplication::translate("MainWindow", "Previous image", nullptr));
|
||||||
actionNextPicture->setText(QCoreApplication::translate("MainWindow", "Next image", nullptr));
|
actionNextPicture->setText(QCoreApplication::translate("MainWindow", "Next image", nullptr));
|
||||||
|
|
||||||
|
actionActualSize->setText(QCoreApplication::translate("MainWindow", "Actual size", nullptr));
|
||||||
|
actionFitToScreen->setText(QCoreApplication::translate("MainWindow", "Fit to screen", nullptr));
|
||||||
|
actionFitByWidth->setText(QCoreApplication::translate("MainWindow", "Fit by width", nullptr));
|
||||||
|
actionFitByHeight->setText(QCoreApplication::translate("MainWindow", "Fit by height", nullptr));
|
||||||
|
actionZoomIn->setText(QCoreApplication::translate("MainWindow", "Zoom in", nullptr));
|
||||||
|
actionZoomOut->setText(QCoreApplication::translate("MainWindow", "Zoom out", nullptr));
|
||||||
|
|
||||||
|
actionFlipHorizontal->setText(QCoreApplication::translate("MainWindow", "Flip &Horizontally", nullptr));
|
||||||
|
actionFlipVertical->setText(QCoreApplication::translate("MainWindow", "Flip &Vertically", nullptr));
|
||||||
|
actionRotateClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate right", nullptr));
|
||||||
|
actionRotateCounterClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate left", nullptr));
|
||||||
|
|
||||||
|
actionToggleAvoidResetTransform->setText(QCoreApplication::translate("MainWindow", "Keep transformation", "The 'transformation' means the flip/rotation status that currently applied to the image view"));
|
||||||
|
actionToggleCheckerboard->setText(QCoreApplication::translate("MainWindow", "Toggle Checkerboard", nullptr));
|
||||||
actionTogglePauseAnimation->setText(QCoreApplication::translate("MainWindow", "Pause/Resume Animation", nullptr));
|
actionTogglePauseAnimation->setText(QCoreApplication::translate("MainWindow", "Pause/Resume Animation", nullptr));
|
||||||
actionAnimationNextFrame->setText(QCoreApplication::translate("MainWindow", "Animation Go to Next Frame", nullptr));
|
actionAnimationNextFrame->setText(QCoreApplication::translate("MainWindow", "Animation Go to Next Frame", nullptr));
|
||||||
|
|
||||||
actionHorizontalFlip->setText(QCoreApplication::translate("MainWindow", "Flip &Horizontally", nullptr));
|
|
||||||
actionFitInView->setText(QCoreApplication::translate("MainWindow", "Fit to view", nullptr));
|
|
||||||
actionFitByWidth->setText(QCoreApplication::translate("MainWindow", "Fit to width", nullptr));
|
|
||||||
actionCopyPixmap->setText(QCoreApplication::translate("MainWindow", "Copy P&ixmap", nullptr));
|
|
||||||
actionCopyFilePath->setText(QCoreApplication::translate("MainWindow", "Copy &File Path", nullptr));
|
|
||||||
actionPaste->setText(QCoreApplication::translate("MainWindow", "&Paste", nullptr));
|
|
||||||
actionTrash->setText(QCoreApplication::translate("MainWindow", "Move to Trash", nullptr));
|
actionTrash->setText(QCoreApplication::translate("MainWindow", "Move to Trash", nullptr));
|
||||||
actionToggleAvoidResetTransform->setText(QCoreApplication::translate("MainWindow", "Keep transformation", "The 'transformation' means the flip/rotation status that currently applied to the image view"));
|
|
||||||
actionSettings->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr));
|
|
||||||
actionHelp->setText(QCoreApplication::translate("MainWindow", "Help", nullptr));
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
actionLocateInFileManager->setText(
|
actionLocateInFileManager->setText(
|
||||||
QCoreApplication::translate(
|
QCoreApplication::translate(
|
||||||
@@ -119,8 +142,9 @@ void ActionManager::setupAction(MainWindow *mainWindow)
|
|||||||
actionLocateInFileManager->setText(QCoreApplication::translate("MainWindow", "Show in directory", nullptr));
|
actionLocateInFileManager->setText(QCoreApplication::translate("MainWindow", "Show in directory", nullptr));
|
||||||
#endif // Q_OS_WIN
|
#endif // Q_OS_WIN
|
||||||
actionProperties->setText(QCoreApplication::translate("MainWindow", "Properties", nullptr));
|
actionProperties->setText(QCoreApplication::translate("MainWindow", "Properties", nullptr));
|
||||||
actionQuitApp->setText(QCoreApplication::translate("MainWindow", "Quit", nullptr));
|
|
||||||
|
|
||||||
|
actionSettings->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr));
|
||||||
|
actionHelp->setText(QCoreApplication::translate("MainWindow", "Help", nullptr));
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
QMetaObject::connectSlotsByName(mainWindow);
|
QMetaObject::connectSlotsByName(mainWindow);
|
||||||
@@ -128,34 +152,57 @@ void ActionManager::setupAction(MainWindow *mainWindow)
|
|||||||
|
|
||||||
void ActionManager::setupShortcuts()
|
void ActionManager::setupShortcuts()
|
||||||
{
|
{
|
||||||
actionOpen->setShortcut(QKeySequence::Open);
|
actionCopyPixmap->setShortcut(QKeySequence::Copy);
|
||||||
|
|
||||||
|
actionPrevPicture->setShortcuts({
|
||||||
|
QKeySequence(Qt::Key_Left),
|
||||||
|
QKeySequence(Qt::Key_PageUp),
|
||||||
|
});
|
||||||
|
actionNextPicture->setShortcuts({
|
||||||
|
QKeySequence(Qt::Key_Right),
|
||||||
|
QKeySequence(Qt::Key_PageDown),
|
||||||
|
});
|
||||||
|
|
||||||
actionActualSize->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
|
actionActualSize->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
|
||||||
actionZoomIn->setShortcut(QKeySequence::ZoomIn);
|
actionZoomIn->setShortcut(QKeySequence::ZoomIn);
|
||||||
actionZoomOut->setShortcut(QKeySequence::ZoomOut);
|
actionZoomOut->setShortcut(QKeySequence::ZoomOut);
|
||||||
actionPrevPicture->setShortcuts({
|
|
||||||
QKeySequence(Qt::Key_PageUp),
|
|
||||||
QKeySequence(Qt::Key_Left),
|
|
||||||
});
|
|
||||||
actionNextPicture->setShortcuts({
|
|
||||||
QKeySequence(Qt::Key_PageDown),
|
|
||||||
QKeySequence(Qt::Key_Right),
|
|
||||||
});
|
|
||||||
actionHorizontalFlip->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_R));
|
|
||||||
actionCopyPixmap->setShortcut(QKeySequence::Copy);
|
|
||||||
actionPaste->setShortcut(QKeySequence::Paste);
|
|
||||||
actionTrash->setShortcut(QKeySequence::Delete);
|
actionTrash->setShortcut(QKeySequence::Delete);
|
||||||
actionHelp->setShortcut(QKeySequence::HelpContents);
|
|
||||||
actionSettings->setShortcut(QKeySequence::Preferences);
|
|
||||||
actionProperties->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I));
|
actionProperties->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I));
|
||||||
actionQuitApp->setShortcuts({
|
|
||||||
QKeySequence(Qt::Key_Space),
|
actionSettings->setShortcut(QKeySequence::Preferences);
|
||||||
QKeySequence(Qt::Key_Escape)
|
actionHelp->setShortcut(QKeySequence::HelpContents);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionManager::enablePrevNextPictureAction(bool enablePrevPictureAction, bool enableNextPictureAction)
|
void ActionManager::updateActionState(PlaylistManager* pm, GraphicsView* gv)
|
||||||
{
|
{
|
||||||
actionPrevPicture->setEnabled(enablePrevPictureAction);
|
const auto* gs = gv->scene();
|
||||||
actionNextPicture->setEnabled(enableNextPictureAction);
|
const auto* settings = Settings::instance();
|
||||||
|
|
||||||
|
// Update Prev/Next Picture State
|
||||||
|
const int galleryFileCount = pm->totalCount();
|
||||||
|
const bool loopGallery = settings->loopGallery();
|
||||||
|
actionPrevPicture->setEnabled(galleryFileCount > 1 && (loopGallery || !pm->isFirstIndex()));
|
||||||
|
actionNextPicture->setEnabled(galleryFileCount > 1 && (loopGallery || !pm->isLastIndex()));
|
||||||
|
|
||||||
|
// Update Avoid Reset Transform
|
||||||
|
actionToggleAvoidResetTransform->setCheckable(gv->avoidResetTransform());
|
||||||
|
|
||||||
|
// Update Checkerboard
|
||||||
|
actionToggleCheckerboard->setChecked(gv->checkerboard());
|
||||||
|
|
||||||
|
// Update Animation Graphics Action
|
||||||
|
bool canPauseAnimation = gs->canPauseAnimation();
|
||||||
|
actionTogglePauseAnimation->setEnabled(canPauseAnimation);
|
||||||
|
if (canPauseAnimation) {
|
||||||
|
actionTogglePauseAnimation->setChecked(gs->isPauseAnimation());
|
||||||
|
} else {
|
||||||
|
actionTogglePauseAnimation->setChecked(false);
|
||||||
|
}
|
||||||
|
bool canSkipAnimation = gs->canSkipAnimationFrame();
|
||||||
|
actionAnimationNextFrame->setEnabled(canSkipAnimation);
|
||||||
|
|
||||||
|
// TODO: Add more...
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
class PlaylistManager;
|
||||||
|
class GraphicsView;
|
||||||
|
|
||||||
/// Action Manager is separated from Main Window
|
/// Action Manager is separated from Main Window
|
||||||
/// to manage all actions specifically.
|
/// to manage all actions specifically.
|
||||||
@@ -19,38 +21,40 @@ public:
|
|||||||
|
|
||||||
void setupAction(MainWindow * mainWindow);
|
void setupAction(MainWindow * mainWindow);
|
||||||
void setupShortcuts();
|
void setupShortcuts();
|
||||||
void enablePrevNextPictureAction(bool enablePrevPictureAction, bool enableNextPictureAction);
|
|
||||||
|
public slots:
|
||||||
|
void updateActionState(PlaylistManager* pm, GraphicsView* gv);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QAction *actionOpen;
|
QAction *actionCopyPixmap;
|
||||||
|
QAction *actionCopyFilePath;
|
||||||
QAction *actionActualSize;
|
|
||||||
QAction *actionToggleMaximize;
|
|
||||||
QAction *actionZoomIn;
|
|
||||||
QAction *actionZoomOut;
|
|
||||||
QAction *actionToggleCheckerboard;
|
|
||||||
QAction *actionRotateClockwise;
|
|
||||||
QAction *actionRotateCounterClockwise;
|
|
||||||
|
|
||||||
QAction *actionPrevPicture;
|
QAction *actionPrevPicture;
|
||||||
QAction *actionNextPicture;
|
QAction *actionNextPicture;
|
||||||
|
|
||||||
|
QAction *actionActualSize;
|
||||||
|
QAction *actionFitToScreen;
|
||||||
|
QAction *actionFitByWidth;
|
||||||
|
QAction *actionFitByHeight;
|
||||||
|
QAction *actionZoomIn;
|
||||||
|
QAction *actionZoomOut;
|
||||||
|
|
||||||
|
QAction *actionFlipHorizontal;
|
||||||
|
QAction *actionFlipVertical;
|
||||||
|
QAction *actionRotateClockwise;
|
||||||
|
QAction *actionRotateCounterClockwise;
|
||||||
|
|
||||||
|
QAction *actionToggleAvoidResetTransform;
|
||||||
|
QAction *actionToggleCheckerboard;
|
||||||
QAction *actionTogglePauseAnimation;
|
QAction *actionTogglePauseAnimation;
|
||||||
QAction *actionAnimationNextFrame;
|
QAction *actionAnimationNextFrame;
|
||||||
|
|
||||||
QAction *actionHorizontalFlip;
|
|
||||||
QAction *actionFitInView;
|
|
||||||
QAction *actionFitByWidth;
|
|
||||||
QAction *actionCopyPixmap;
|
|
||||||
QAction *actionCopyFilePath;
|
|
||||||
QAction *actionPaste;
|
|
||||||
QAction *actionTrash;
|
QAction *actionTrash;
|
||||||
QAction *actionToggleAvoidResetTransform;
|
|
||||||
QAction *actionSettings;
|
|
||||||
QAction *actionHelp;
|
|
||||||
QAction *actionLocateInFileManager;
|
QAction *actionLocateInFileManager;
|
||||||
QAction *actionProperties;
|
QAction *actionProperties;
|
||||||
QAction *actionQuitApp;
|
|
||||||
|
QAction *actionSettings;
|
||||||
|
QAction *actionHelp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ACTIONMANAGER_H
|
#endif // ACTIONMANAGER_H
|
||||||
|
|||||||
@@ -200,27 +200,57 @@ bool GraphicsScene::trySetTransformationMode(Qt::TransformationMode mode, float
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetch graphics item as our custom animated item.
|
||||||
|
/// Return nullptr means this item is not animated item.
|
||||||
|
static PGraphicsMovieItem* fetchAnimatedItem(QGraphicsItem *item) {
|
||||||
|
return qgraphicsitem_cast<PGraphicsMovieItem *>(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::canPauseAnimation() const {
|
||||||
|
return fetchAnimatedItem(m_theThing) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::isPauseAnimation() const {
|
||||||
|
auto* animatedItem = fetchAnimatedItem(m_theThing);
|
||||||
|
if (animatedItem != nullptr) {
|
||||||
|
return animatedItem->movie()->state() == QMovie::Paused;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool GraphicsScene::togglePauseAnimation()
|
bool GraphicsScene::togglePauseAnimation()
|
||||||
{
|
{
|
||||||
PGraphicsMovieItem * animatedItem = qgraphicsitem_cast<PGraphicsMovieItem *>(m_theThing);
|
auto* animatedItem = fetchAnimatedItem(m_theThing);
|
||||||
if (animatedItem) {
|
if (animatedItem != nullptr) {
|
||||||
animatedItem->movie()->setPaused(animatedItem->movie()->state() != QMovie::Paused);
|
animatedItem->movie()->setPaused(animatedItem->movie()->state() != QMovie::Paused);
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::canSkipAnimationFrame() const {
|
||||||
|
return isPauseAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsScene::skipAnimationFrame(int delta)
|
bool GraphicsScene::skipAnimationFrame(int delta)
|
||||||
{
|
{
|
||||||
PGraphicsMovieItem * animatedItem = qgraphicsitem_cast<PGraphicsMovieItem *>(m_theThing);
|
auto* animatedItem = fetchAnimatedItem(m_theThing);
|
||||||
if (animatedItem) {
|
|
||||||
|
// Only paused animated item can skip frame
|
||||||
|
if (animatedItem == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (animatedItem->movie()->state() != QMovie::Paused) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform skip
|
||||||
const int frameCount = animatedItem->movie()->frameCount();
|
const int frameCount = animatedItem->movie()->frameCount();
|
||||||
const int currentFrame = animatedItem->movie()->currentFrameNumber();
|
const int currentFrame = animatedItem->movie()->currentFrameNumber();
|
||||||
const int targetFrame = (currentFrame + delta) % frameCount;
|
const int targetFrame = (currentFrame + delta) % frameCount;
|
||||||
animatedItem->movie()->setPaused(true);
|
|
||||||
return animatedItem->movie()->jumpToFrame(targetFrame);
|
return animatedItem->movie()->jumpToFrame(targetFrame);
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap GraphicsScene::renderToPixmap()
|
QPixmap GraphicsScene::renderToPixmap()
|
||||||
|
|||||||
@@ -21,7 +21,19 @@ public:
|
|||||||
|
|
||||||
bool trySetTransformationMode(Qt::TransformationMode mode, float scaleHint);
|
bool trySetTransformationMode(Qt::TransformationMode mode, float scaleHint);
|
||||||
|
|
||||||
|
/// Check whether current thing is animation.
|
||||||
|
/// Only animation thing can be paused.
|
||||||
|
bool canPauseAnimation() const;
|
||||||
|
/// Check whether we are pasuing an animation graphics.
|
||||||
|
bool isPauseAnimation() const;
|
||||||
|
/// Toggle animation graphics pause state.
|
||||||
|
/// Return true for successfully toggle, otherwise false.
|
||||||
bool togglePauseAnimation();
|
bool togglePauseAnimation();
|
||||||
|
/// Check whether we can skip animation frame.
|
||||||
|
/// Only paused animation graphics can skip frame.
|
||||||
|
bool canSkipAnimationFrame() const;
|
||||||
|
/// Skip paused animation graphics with given frame.
|
||||||
|
/// Return true for successfully skip, otherwise false.
|
||||||
bool skipAnimationFrame(int delta = 1);
|
bool skipAnimationFrame(int delta = 1);
|
||||||
|
|
||||||
QPixmap renderToPixmap();
|
QPixmap renderToPixmap();
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ void GraphicsView::resetTransform()
|
|||||||
|
|
||||||
void GraphicsView::zoomView(qreal scaleFactor)
|
void GraphicsView::zoomView(qreal scaleFactor)
|
||||||
{
|
{
|
||||||
m_enableFitInView = false;
|
m_enableFitToScreen = false;
|
||||||
scale(scaleFactor, scaleFactor);
|
scale(scaleFactor, scaleFactor);
|
||||||
applyTransformationModeByScaleFactor();
|
applyTransformationModeByScaleFactor();
|
||||||
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
|
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
|
||||||
@@ -224,6 +224,8 @@ void GraphicsView::fitByOrientation(Qt::Orientation ori, bool scaleDownOnly)
|
|||||||
QRectF originalScene = sceneRect();
|
QRectF originalScene = sceneRect();
|
||||||
QTransform currentTransform = transform();
|
QTransform currentTransform = transform();
|
||||||
|
|
||||||
|
// TODO: May be optimized by matrix arithmetic operation?
|
||||||
|
|
||||||
if (ori == Qt::Horizontal) {
|
if (ori == Qt::Horizontal) {
|
||||||
// For horizontal fit (fit by width), position at top (for tall images)
|
// For horizontal fit (fit by width), position at top (for tall images)
|
||||||
// Find the scene point that corresponds to the top-center of the transformed image
|
// Find the scene point that corresponds to the top-center of the transformed image
|
||||||
@@ -276,7 +278,7 @@ void GraphicsView::fitByOrientation(Qt::Orientation ori, bool scaleDownOnly)
|
|||||||
centerOn(sceneLeftCenter);
|
centerOn(sceneLeftCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_enableFitInView = false;
|
m_enableFitToScreen = false;
|
||||||
|
|
||||||
applyTransformationModeByScaleFactor();
|
applyTransformationModeByScaleFactor();
|
||||||
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
|
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
|
||||||
@@ -299,7 +301,7 @@ void GraphicsView::displayScene()
|
|||||||
emit navigatorViewRequired(false, transform());
|
emit navigatorViewRequired(false, transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_enableFitInView = true;
|
m_enableFitToScreen = true;
|
||||||
m_firstUserMediaLoaded = true;
|
m_firstUserMediaLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,9 +315,9 @@ bool GraphicsView::isSceneBiggerThanView() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Automately do fit in view when viewport(window) smaller than image original size.
|
// Automately do fit in view when viewport(window) smaller than image original size.
|
||||||
void GraphicsView::setEnableAutoFitInView(bool enable)
|
void GraphicsView::setEnableAutoFitToScreen(bool enable)
|
||||||
{
|
{
|
||||||
m_enableFitInView = enable;
|
m_enableFitToScreen = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicsView::avoidResetTransform() const
|
bool GraphicsView::avoidResetTransform() const
|
||||||
@@ -328,6 +330,15 @@ void GraphicsView::setAvoidResetTransform(bool avoidReset)
|
|||||||
m_avoidResetTransform = avoidReset;
|
m_avoidResetTransform = avoidReset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsView::checkerboard() const {
|
||||||
|
return m_checkerboardEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::toggleCheckerboard(bool invertCheckerboardColor)
|
||||||
|
{
|
||||||
|
setCheckerboardEnabled(!m_checkerboardEnabled, invertCheckerboardColor);
|
||||||
|
}
|
||||||
|
|
||||||
inline double zeroOrOne(double number)
|
inline double zeroOrOne(double number)
|
||||||
{
|
{
|
||||||
return qFuzzyIsNull(number) ? 0 : (number > 0 ? 1 : -1);
|
return qFuzzyIsNull(number) ? 0 : (number > 0 ? 1 : -1);
|
||||||
@@ -342,11 +353,6 @@ QTransform GraphicsView::resetScale(const QTransform & orig)
|
|||||||
orig.dx(), orig.dy());
|
orig.dx(), orig.dy());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsView::toggleCheckerboard(bool invertCheckerboardColor)
|
|
||||||
{
|
|
||||||
setCheckerboardEnabled(!m_checkerboardEnabled, invertCheckerboardColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsView::updateStyle(Qt::ColorScheme colorScheme) {
|
void GraphicsView::updateStyle(Qt::ColorScheme colorScheme) {
|
||||||
// YYC MARK:
|
// YYC MARK:
|
||||||
// If we are using Windows 10 and lower system or Qt which do not support "Windows 11"
|
// If we are using Windows 10 and lower system or Qt which do not support "Windows 11"
|
||||||
@@ -423,11 +429,11 @@ void GraphicsView::wheelEvent(QWheelEvent *event)
|
|||||||
|
|
||||||
void GraphicsView::resizeEvent(QResizeEvent *event)
|
void GraphicsView::resizeEvent(QResizeEvent *event)
|
||||||
{
|
{
|
||||||
if (m_enableFitInView) {
|
if (m_enableFitToScreen) {
|
||||||
bool originalSizeSmallerThanWindow = isThingSmallerThanWindowWith(resetScale(transform()));
|
bool originalSizeSmallerThanWindow = isThingSmallerThanWindowWith(resetScale(transform()));
|
||||||
if (originalSizeSmallerThanWindow && scaleFactor() >= 1) {
|
if (originalSizeSmallerThanWindow && scaleFactor() >= 1) {
|
||||||
// no longer need to do fitInView()
|
// no longer need to do fitInView()
|
||||||
// but we leave the m_enableFitInView value unchanged in case
|
// but we leave the m_enableToScreen value unchanged in case
|
||||||
// user resize down the window again.
|
// user resize down the window again.
|
||||||
} else if (originalSizeSmallerThanWindow && scaleFactor() < 1) {
|
} else if (originalSizeSmallerThanWindow && scaleFactor() < 1) {
|
||||||
resetScale();
|
resetScale();
|
||||||
|
|||||||
@@ -38,11 +38,14 @@ public:
|
|||||||
|
|
||||||
void displayScene();
|
void displayScene();
|
||||||
bool isSceneBiggerThanView() const;
|
bool isSceneBiggerThanView() const;
|
||||||
void setEnableAutoFitInView(bool enable = true);
|
void setEnableAutoFitToScreen(bool enable = true);
|
||||||
|
|
||||||
bool avoidResetTransform() const;
|
bool avoidResetTransform() const;
|
||||||
void setAvoidResetTransform(bool avoidReset);
|
void setAvoidResetTransform(bool avoidReset);
|
||||||
|
|
||||||
|
bool checkerboard() const;
|
||||||
|
void toggleCheckerboard(bool invertCheckerboardColor = false);
|
||||||
|
|
||||||
static QTransform resetScale(const QTransform & orig);
|
static QTransform resetScale(const QTransform & orig);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -50,7 +53,6 @@ signals:
|
|||||||
void viewportRectChanged();
|
void viewportRectChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleCheckerboard(bool invertCheckerboardColor = false);
|
|
||||||
void updateStyle(Qt::ColorScheme colorScheme);
|
void updateStyle(Qt::ColorScheme colorScheme);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -70,7 +72,7 @@ private:
|
|||||||
// Consider switch to 3 state for "no fit", "always fit" and "fit when view is smaller"?
|
// Consider switch to 3 state for "no fit", "always fit" and "fit when view is smaller"?
|
||||||
// ... or even more? e.g. "fit/snap width" things...
|
// ... or even more? e.g. "fit/snap width" things...
|
||||||
// Currently it's "no fit" when it's false and "fit when view is smaller" when it's true.
|
// Currently it's "no fit" when it's false and "fit when view is smaller" when it's true.
|
||||||
bool m_enableFitInView = false;
|
bool m_enableFitToScreen = false;
|
||||||
bool m_avoidResetTransform = false;
|
bool m_avoidResetTransform = false;
|
||||||
bool m_checkerboardEnabled = false;
|
bool m_checkerboardEnabled = false;
|
||||||
bool m_useLightCheckerboard = false;
|
bool m_useLightCheckerboard = false;
|
||||||
|
|||||||
@@ -92,13 +92,16 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
|
|
||||||
m_bottomButtonGroup = new BottomButtonGroup({
|
m_bottomButtonGroup = new BottomButtonGroup({
|
||||||
m_am->actionActualSize,
|
m_am->actionActualSize,
|
||||||
m_am->actionToggleMaximize,
|
m_am->actionFitToScreen,
|
||||||
m_am->actionZoomIn,
|
m_am->actionZoomIn,
|
||||||
m_am->actionZoomOut,
|
m_am->actionZoomOut,
|
||||||
m_am->actionPrevPicture,
|
m_am->actionPrevPicture,
|
||||||
|
m_am->actionProperties,
|
||||||
m_am->actionNextPicture,
|
m_am->actionNextPicture,
|
||||||
|
m_am->actionRotateCounterClockwise,
|
||||||
|
m_am->actionRotateClockwise,
|
||||||
|
m_am->actionFlipHorizontal,
|
||||||
m_am->actionToggleCheckerboard,
|
m_am->actionToggleCheckerboard,
|
||||||
m_am->actionRotateClockwise
|
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
connect(m_pm, &PlaylistManager::totalCountChanged, this, &MainWindow::updateGalleryButtonsVisibility);
|
connect(m_pm, &PlaylistManager::totalCountChanged, this, &MainWindow::updateGalleryButtonsVisibility);
|
||||||
@@ -358,65 +361,73 @@ void MainWindow::resizeEvent(QResizeEvent *event)
|
|||||||
|
|
||||||
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
||||||
{
|
{
|
||||||
|
// TODO: Update this function.
|
||||||
QMenu * menu = new QMenu;
|
QMenu * menu = new QMenu;
|
||||||
|
|
||||||
|
// TODO: currentImageFileUrl() may be redundant.
|
||||||
QMenu * copyMenu = new QMenu(tr("&Copy"));
|
QMenu * copyMenu = new QMenu(tr("&Copy"));
|
||||||
QUrl currentFileUrl = currentImageFileUrl();
|
QUrl currentFileUrl = currentImageFileUrl();
|
||||||
|
|
||||||
QAction * copyPixmap = m_am->actionCopyPixmap;
|
|
||||||
QAction * copyFilePath = m_am->actionCopyFilePath;
|
|
||||||
|
|
||||||
copyMenu->setIcon(QIcon::fromTheme(u"edit-copy"_s));
|
copyMenu->setIcon(QIcon::fromTheme(u"edit-copy"_s));
|
||||||
copyMenu->addAction(copyPixmap);
|
copyMenu->addAction(m_am->actionCopyPixmap);
|
||||||
if (currentFileUrl.isValid()) {
|
if (currentFileUrl.isValid()) {
|
||||||
copyMenu->addAction(copyFilePath);
|
copyMenu->addAction(m_am->actionCopyFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction * paste = m_am->actionPaste;
|
|
||||||
|
|
||||||
QAction * trash = m_am->actionTrash;
|
|
||||||
|
|
||||||
QAction * avoidResetTransform = m_am->actionToggleAvoidResetTransform;
|
|
||||||
avoidResetTransform->setCheckable(true);
|
|
||||||
avoidResetTransform->setChecked(m_gv->avoidResetTransform());
|
|
||||||
|
|
||||||
QAction * toggleSettings = m_am->actionSettings;
|
|
||||||
QAction * helpAction = m_am->actionHelp;
|
|
||||||
QAction * propertiesAction = m_am->actionProperties;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
menu->addAction(m_am->actionOpen);
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
if (copyMenu->actions().count() == 1) {
|
if (copyMenu->actions().count() == 1) {
|
||||||
menu->addActions(copyMenu->actions());
|
menu->addActions(copyMenu->actions());
|
||||||
} else {
|
} else {
|
||||||
menu->addMenu(copyMenu);
|
menu->addMenu(copyMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canPaste()) {
|
menu->addSeparator();
|
||||||
menu->addAction(paste);
|
|
||||||
}
|
menu->addAction(m_am->actionPrevPicture);
|
||||||
|
menu->addAction(m_am->actionNextPicture);
|
||||||
|
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
|
|
||||||
menu->addAction(m_am->actionHorizontalFlip);
|
menu->addAction(m_am->actionActualSize);
|
||||||
#if 0
|
menu->addAction(m_am->actionFitToScreen);
|
||||||
menu->addAction(m_am->actionFitInView);
|
|
||||||
menu->addAction(m_am->actionFitByWidth);
|
menu->addAction(m_am->actionFitByWidth);
|
||||||
#endif // 0
|
menu->addAction(m_am->actionFitByHeight);
|
||||||
|
menu->addAction(m_am->actionZoomIn);
|
||||||
|
menu->addAction(m_am->actionZoomOut);
|
||||||
|
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
|
|
||||||
|
menu->addAction(m_am->actionFlipHorizontal);
|
||||||
|
menu->addAction(m_am->actionFlipVertical);
|
||||||
|
menu->addAction(m_am->actionRotateClockwise);
|
||||||
|
menu->addAction(m_am->actionRotateCounterClockwise);
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
|
||||||
|
// TODO: Move checked update to action manager.
|
||||||
|
QAction * avoidResetTransform = m_am->actionToggleAvoidResetTransform;
|
||||||
|
avoidResetTransform->setCheckable(true);
|
||||||
|
avoidResetTransform->setChecked(m_gv->avoidResetTransform());
|
||||||
menu->addAction(avoidResetTransform);
|
menu->addAction(avoidResetTransform);
|
||||||
menu->addSeparator();
|
menu->addAction(m_am->actionToggleCheckerboard);
|
||||||
menu->addAction(toggleSettings);
|
QAction * pauseAnimation = m_am->actionTogglePauseAnimation;
|
||||||
menu->addAction(helpAction);
|
pauseAnimation->setCheckable(true);
|
||||||
|
pauseAnimation->setChecked(m_gv->scene()->pauseAnimation());
|
||||||
|
menu->addAction(pauseAnimation);
|
||||||
|
menu->addAction(m_am->actionAnimationNextFrame);
|
||||||
|
|
||||||
if (currentFileUrl.isValid()) {
|
if (currentFileUrl.isValid()) {
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
if (currentFileUrl.isLocalFile()) {
|
if (currentFileUrl.isLocalFile()) {
|
||||||
menu->addAction(trash);
|
menu->addAction(m_am->actionTrash);
|
||||||
menu->addAction(m_am->actionLocateInFileManager);
|
menu->addAction(m_am->actionLocateInFileManager);
|
||||||
}
|
}
|
||||||
menu->addAction(propertiesAction);
|
menu->addAction(m_am->actionProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
|
||||||
|
menu->addAction(m_am->actionSettings);
|
||||||
|
menu->addAction(m_am->actionHelp);
|
||||||
|
|
||||||
menu->exec(mapToGlobal(event->pos()));
|
menu->exec(mapToGlobal(event->pos()));
|
||||||
menu->deleteLater();
|
menu->deleteLater();
|
||||||
copyMenu->deleteLater();
|
copyMenu->deleteLater();
|
||||||
@@ -542,55 +553,7 @@ QSize MainWindow::sizeHint() const
|
|||||||
return QSize(710, 530);
|
return QSize(710, 530);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionOpen_triggered()
|
// region: Action Trigger
|
||||||
{
|
|
||||||
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_gv->resetScale();
|
|
||||||
m_gv->setEnableAutoFitInView(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionToggleMaximize_triggered()
|
|
||||||
{
|
|
||||||
toggleMaximize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionZoomIn_triggered()
|
|
||||||
{
|
|
||||||
if (m_gv->scaleFactor() < 1000) {
|
|
||||||
m_gv->zoomView(1.25);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionZoomOut_triggered()
|
|
||||||
{
|
|
||||||
m_gv->zoomView(0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionHorizontalFlip_triggered()
|
|
||||||
{
|
|
||||||
m_gv->flipView();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionFitInView_triggered()
|
|
||||||
{
|
|
||||||
m_gv->fitInView(m_nav->sceneRect(), Qt::KeepAspectRatio);
|
|
||||||
m_gv->setEnableAutoFitInView(m_gv->scaleFactor() <= 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionFitByWidth_triggered()
|
|
||||||
{
|
|
||||||
m_gv->fitByOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionCopyPixmap_triggered()
|
void MainWindow::on_actionCopyPixmap_triggered()
|
||||||
{
|
{
|
||||||
@@ -607,43 +570,99 @@ void MainWindow::on_actionCopyFilePath_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionPaste_triggered()
|
void MainWindow::on_actionPrevPicture_triggered()
|
||||||
{
|
{
|
||||||
QImage clipboardImage;
|
galleryPrev();
|
||||||
QUrl clipboardFileUrl;
|
}
|
||||||
|
|
||||||
const QMimeData * clipboardData = QApplication::clipboard()->mimeData();
|
void MainWindow::on_actionNextPicture_triggered()
|
||||||
if (clipboardData->hasImage()) {
|
{
|
||||||
QVariant imageVariant(clipboardData->imageData());
|
galleryNext();
|
||||||
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()) {
|
void MainWindow::on_actionActualSize_triggered()
|
||||||
setWindowTitle(tr("Image From Clipboard"));
|
{
|
||||||
m_gv->showImage(clipboardImage);
|
m_gv->resetScale();
|
||||||
clearGallery();
|
m_gv->setEnableAutoFitToScreen(false);
|
||||||
} else if (clipboardFileUrl.isValid()) {
|
}
|
||||||
m_gv->showFileFromPath(clipboardFileUrl.toLocalFile());
|
|
||||||
m_pm->loadPlaylist(clipboardFileUrl);
|
void MainWindow::on_actionFitToScreen_triggered()
|
||||||
|
{
|
||||||
|
m_gv->fitInView(m_nav->sceneRect(), Qt::KeepAspectRatio);
|
||||||
|
m_gv->setEnableAutoFitToScreen(m_gv->scaleFactor() <= 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionFitByWidth_triggered()
|
||||||
|
{
|
||||||
|
m_gv->fitByOrientation(Qt::Orientation::Horizontal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionFitByHeight_triggered()
|
||||||
|
{
|
||||||
|
m_gv->fitByOrientation(Qt::Orientation::Vertical);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionZoomIn_triggered()
|
||||||
|
{
|
||||||
|
if (m_gv->scaleFactor() < 1000) {
|
||||||
|
m_gv->zoomView(1.25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionZoomOut_triggered()
|
||||||
|
{
|
||||||
|
m_gv->zoomView(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionFlipHorizontal_triggered()
|
||||||
|
{
|
||||||
|
m_gv->flipView(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionFlipVertical_triggered()
|
||||||
|
{
|
||||||
|
m_gv->flipView(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionRotateClockwise_triggered()
|
||||||
|
{
|
||||||
|
m_gv->rotateView(true);
|
||||||
|
m_gv->displayScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionRotateCounterClockwise_triggered()
|
||||||
|
{
|
||||||
|
m_gv->rotateView(false);
|
||||||
|
m_gv->displayScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionToggleAvoidResetTransform_triggered()
|
||||||
|
{
|
||||||
|
toggleAvoidResetTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionToggleCheckerboard_triggered()
|
||||||
|
{
|
||||||
|
m_gv->toggleCheckerboard(QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionTogglePauseAnimation_triggered()
|
||||||
|
{
|
||||||
|
m_gv->scene()->togglePauseAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionAnimationNextFrame_triggered()
|
||||||
|
{
|
||||||
|
m_gv->scene()->skipAnimationFrame(1);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionTrash_triggered()
|
void MainWindow::on_actionTrash_triggered()
|
||||||
{
|
{
|
||||||
QModelIndex index = m_pm->curIndex();
|
auto index = m_pm->currentIndex();
|
||||||
if (!m_pm->urlByIndex(index).isLocalFile()) return;
|
if (!index.has_value()) return;
|
||||||
|
if (!m_pm->urlByIndex(*index).isLocalFile()) return;
|
||||||
|
|
||||||
QFile file(m_pm->localFileByIndex(index));
|
QFile file(m_pm->localFileByIndex(*index));
|
||||||
QFileInfo fileInfo(file.fileName());
|
QFileInfo fileInfo(file.fileName());
|
||||||
|
|
||||||
QMessageBox::StandardButton result = QMessageBox::question(this, tr("Move to Trash"),
|
QMessageBox::StandardButton result = QMessageBox::question(this, tr("Move to Trash"),
|
||||||
@@ -660,77 +679,6 @@ void MainWindow::on_actionTrash_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionToggleCheckerboard_triggered()
|
|
||||||
{
|
|
||||||
// TODO: is that okay to do this since we plan to support custom shortcuts?
|
|
||||||
m_gv->toggleCheckerboard(QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionRotateClockwise_triggered()
|
|
||||||
{
|
|
||||||
m_gv->rotateView();
|
|
||||||
m_gv->displayScene();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionRotateCounterClockwise_triggered()
|
|
||||||
{
|
|
||||||
m_gv->rotateView(false);
|
|
||||||
m_gv->displayScene();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionPrevPicture_triggered()
|
|
||||||
{
|
|
||||||
galleryPrev();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionNextPicture_triggered()
|
|
||||||
{
|
|
||||||
galleryNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionTogglePauseAnimation_triggered()
|
|
||||||
{
|
|
||||||
m_gv->scene()->togglePauseAnimation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionAnimationNextFrame_triggered()
|
|
||||||
{
|
|
||||||
m_gv->scene()->skipAnimationFrame(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionToggleAvoidResetTransform_triggered()
|
|
||||||
{
|
|
||||||
toggleAvoidResetTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionLocateInFileManager_triggered()
|
void MainWindow::on_actionLocateInFileManager_triggered()
|
||||||
{
|
{
|
||||||
QUrl currentFileUrl = currentImageFileUrl();
|
QUrl currentFileUrl = currentImageFileUrl();
|
||||||
@@ -766,23 +714,39 @@ void MainWindow::on_actionLocateInFileManager_triggered()
|
|||||||
#endif // Q_OS_WIN
|
#endif // Q_OS_WIN
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionQuitApp_triggered()
|
void MainWindow::on_actionProperties_triggered()
|
||||||
{
|
{
|
||||||
quitAppAction(false);
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
bool MainWindow::updateFileWatcher(const QString &basePath)
|
bool MainWindow::updateFileWatcher(const QString &basePath)
|
||||||
{
|
{
|
||||||
m_fileSystemWatcher->removePaths(m_fileSystemWatcher->files());
|
m_fileSystemWatcher->removePaths(m_fileSystemWatcher->files());
|
||||||
if (!basePath.isEmpty()) return m_fileSystemWatcher->addPath(basePath);
|
if (!basePath.isEmpty()) return m_fileSystemWatcher->addPath(basePath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateGalleryButtonsVisibility()
|
|
||||||
{
|
|
||||||
const int galleryFileCount = m_pm->totalCount();
|
|
||||||
const bool loopGallery = Settings::instance()->loopGallery();
|
|
||||||
m_am->enablePrevNextPictureAction(
|
|
||||||
galleryFileCount > 1 && (loopGallery || !m_pm->isFirstIndex()),
|
|
||||||
galleryFileCount > 1 && (loopGallery || !m_pm->isLastIndex()));
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -66,39 +66,38 @@ protected:
|
|||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_actionOpen_triggered();
|
void on_actionCopyPixmap_triggered();
|
||||||
|
void on_actionCopyFilePath_triggered();
|
||||||
void on_actionActualSize_triggered();
|
|
||||||
void on_actionToggleMaximize_triggered();
|
|
||||||
void on_actionZoomIn_triggered();
|
|
||||||
void on_actionZoomOut_triggered();
|
|
||||||
void on_actionToggleCheckerboard_triggered();
|
|
||||||
void on_actionRotateClockwise_triggered();
|
|
||||||
void on_actionRotateCounterClockwise_triggered();
|
|
||||||
|
|
||||||
void on_actionPrevPicture_triggered();
|
void on_actionPrevPicture_triggered();
|
||||||
void on_actionNextPicture_triggered();
|
void on_actionNextPicture_triggered();
|
||||||
|
|
||||||
|
void on_actionActualSize_triggered();
|
||||||
|
void on_actionFitToScreen_triggered();
|
||||||
|
void on_actionFitByWidth_triggered();
|
||||||
|
void on_actionFitByHeight_triggered();
|
||||||
|
void on_actionZoomIn_triggered();
|
||||||
|
void on_actionZoomOut_triggered();
|
||||||
|
|
||||||
|
void on_actionFlipHorizontal_triggered();
|
||||||
|
void on_actionFlipVertical_triggered();
|
||||||
|
void on_actionRotateClockwise_triggered();
|
||||||
|
void on_actionRotateCounterClockwise_triggered();
|
||||||
|
|
||||||
|
void on_actionToggleAvoidResetTransform_triggered();
|
||||||
|
void on_actionToggleCheckerboard_triggered();
|
||||||
void on_actionTogglePauseAnimation_triggered();
|
void on_actionTogglePauseAnimation_triggered();
|
||||||
void on_actionAnimationNextFrame_triggered();
|
void on_actionAnimationNextFrame_triggered();
|
||||||
|
|
||||||
void on_actionHorizontalFlip_triggered();
|
|
||||||
void on_actionFitInView_triggered();
|
|
||||||
void on_actionFitByWidth_triggered();
|
|
||||||
void on_actionCopyPixmap_triggered();
|
|
||||||
void on_actionCopyFilePath_triggered();
|
|
||||||
void on_actionPaste_triggered();
|
|
||||||
void on_actionTrash_triggered();
|
void on_actionTrash_triggered();
|
||||||
void on_actionToggleAvoidResetTransform_triggered();
|
void on_actionLocateInFileManager_triggered();
|
||||||
|
void on_actionProperties_triggered();
|
||||||
|
|
||||||
void on_actionSettings_triggered();
|
void on_actionSettings_triggered();
|
||||||
void on_actionHelp_triggered();
|
void on_actionHelp_triggered();
|
||||||
void on_actionProperties_triggered();
|
|
||||||
void on_actionLocateInFileManager_triggered();
|
|
||||||
void on_actionQuitApp_triggered();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool updateFileWatcher(const QString & basePath = QString());
|
bool updateFileWatcher(const QString & basePath = QString());
|
||||||
void updateGalleryButtonsVisibility();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ActionManager *m_am;
|
ActionManager *m_am;
|
||||||
|
|||||||
Reference in New Issue
Block a user