feat: add prev and next button

This commit is contained in:
Gary Wang 2020-07-04 13:49:12 +08:00
parent 3b1af64397
commit fb24e54579
9 changed files with 221 additions and 13 deletions

View File

@ -23,6 +23,7 @@ Feel free to open up an issue to request an new language to translate.
- Mixed `CR LF` and `LF`. - Mixed `CR LF` and `LF`.
- Ugly action icons. - Ugly action icons.
- Ugly implementations.
- For windows build, win32 APIs are used. - For windows build, win32 APIs are used.
- No drag-window-border-to-resize support under non-windows platforms (I use <kbd>Meta+Drag</kbd> to resize window under my x11 desktop). - No drag-window-border-to-resize support under non-windows platforms (I use <kbd>Meta+Drag</kbd> to resize window under my x11 desktop).

View File

@ -242,7 +242,7 @@ void GraphicsView::dropEvent(QDropEvent *event)
if (urls.isEmpty()) { if (urls.isEmpty()) {
showText(tr("File url list is empty")); showText(tr("File url list is empty"));
} else { } else {
showFileFromUrl(urls.first()); showFileFromUrl(urls.first(), true);
} }
} else if (mimeData->hasImage()) { } else if (mimeData->hasImage()) {
QImage img = qvariant_cast<QImage>(mimeData->imageData()); QImage img = qvariant_cast<QImage>(mimeData->imageData());

79
icons/go-next.svg Normal file
View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="75"
height="75"
viewBox="0 0 19.84375 19.843751"
version="1.1"
id="svg8"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="go-next.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#282929"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.76862745"
inkscape:pageshadow="2"
inkscape:zoom="16.000001"
inkscape:cx="35.333099"
inkscape:cy="37.582065"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1">
<sodipodi:guide
position="11.453565,9.9198082"
orientation="0,-1"
id="guide857" />
<sodipodi:guide
position="9.9229088,19.564698"
orientation="1,0"
id="guide837" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="图层 1"
inkscape:groupmode="layer"
id="layer1">
<ellipse
style="opacity:1;fill:#000000;fill-opacity:0.15678;stroke:#ffffff;stroke-width:0.396875;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path849"
cx="9.9368067"
cy="9.915391"
rx="8.6764698"
ry="8.9158831" />
<path
style="fill:none;stroke:#ffffff;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 8.3550725,6.9255115 11.353504,9.9239423 8.3550725,12.91402"
id="path867" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

79
icons/go-previous.svg Normal file
View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="go-previous.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
id="svg8"
version="1.1"
viewBox="0 0 19.84375 19.843751"
height="75"
width="75">
<defs
id="defs2" />
<sodipodi:namedview
inkscape:window-maximized="1"
inkscape:window-y="-9"
inkscape:window-x="-9"
inkscape:window-height="1001"
inkscape:window-width="1920"
inkscape:guide-bbox="true"
showguides="true"
inkscape:pagecheckerboard="false"
units="px"
showgrid="false"
inkscape:document-rotation="0"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="45.995918"
inkscape:cx="29.794477"
inkscape:zoom="11.313709"
inkscape:pageshadow="2"
inkscape:pageopacity="0.76862745"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#282929"
id="base">
<sodipodi:guide
id="guide857"
orientation="0,-1"
position="11.453565,9.9198082" />
<sodipodi:guide
id="guide837"
orientation="1,0"
position="9.9229088,19.564698" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="图层 1">
<ellipse
ry="8.9158831"
rx="8.6764698"
cy="9.915391"
cx="9.9368067"
id="path849"
style="opacity:1;fill:#000000;fill-opacity:0.15678;stroke:#ffffff;stroke-width:0.396875;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path867"
d="M 11.494016,6.9255115 8.4955849,9.9239423 11.494016,12.91402"
style="fill:none;stroke:#ffffff;stroke-width:0.396875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -31,6 +31,7 @@ MainWindow::MainWindow(QWidget *parent) :
this->setAttribute(Qt::WA_TranslucentBackground, true); this->setAttribute(Qt::WA_TranslucentBackground, true);
this->setMinimumSize(710, 530); this->setMinimumSize(710, 530);
this->setWindowIcon(QIcon(":/icons/app-icon.svg")); this->setWindowIcon(QIcon(":/icons/app-icon.svg"));
this->setMouseTracking(true);
m_fadeOutAnimation = new QPropertyAnimation(this, "windowOpacity"); m_fadeOutAnimation = new QPropertyAnimation(this, "windowOpacity");
m_fadeOutAnimation->setDuration(300); m_fadeOutAnimation->setDuration(300);
@ -72,13 +73,29 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_graphicsView, &GraphicsView::requestGallery, connect(m_graphicsView, &GraphicsView::requestGallery,
this, &MainWindow::loadGalleryBySingleLocalFile); this, &MainWindow::loadGalleryBySingleLocalFile);
m_closeButton = new ToolButton(m_graphicsView); m_closeButton = new ToolButton(true, m_graphicsView);
m_closeButton->setIcon(QIcon(":/icons/window-close")); m_closeButton->setIcon(QIcon(":/icons/window-close"));
m_closeButton->setIconSize(QSize(50, 50)); m_closeButton->setIconSize(QSize(50, 50));
connect(m_closeButton, &QAbstractButton::clicked, connect(m_closeButton, &QAbstractButton::clicked,
this, &MainWindow::closeWindow); this, &MainWindow::closeWindow);
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_bottomButtonGroup = new BottomButtonGroup(this); m_bottomButtonGroup = new BottomButtonGroup(this);
connect(m_bottomButtonGroup, &BottomButtonGroup::resetToOriginalBtnClicked, connect(m_bottomButtonGroup, &BottomButtonGroup::resetToOriginalBtnClicked,
@ -109,6 +126,11 @@ MainWindow::MainWindow(QWidget *parent) :
m_gv->setOpacity(0, false); m_gv->setOpacity(0, false);
m_closeButton->setOpacity(0, false); m_closeButton->setOpacity(0, false);
connect(this, &MainWindow::galleryLoaded, this, [this]() {
m_prevButton->setVisible(isGalleryAvailable());
m_nextButton->setVisible(isGalleryAvailable());
});
QShortcut * quitAppShorucut = new QShortcut(QKeySequence(Qt::Key_Space), this); QShortcut * quitAppShorucut = new QShortcut(QKeySequence(Qt::Key_Space), this);
connect(quitAppShorucut, &QShortcut::activated, connect(quitAppShorucut, &QShortcut::activated,
std::bind(&MainWindow::quitAppAction, this, false)); std::bind(&MainWindow::quitAppAction, this, false));
@ -222,13 +244,13 @@ void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
} }
} }
// qDebug() << m_files << m_currentFileIndex; emit galleryLoaded();
} }
void MainWindow::galleryPrev() void MainWindow::galleryPrev()
{ {
int count = m_files.count(); int count = m_files.count();
if (m_currentFileIndex < 0 || m_files.isEmpty() || m_currentFileIndex >= m_files.count()) { if (!isGalleryAvailable()) {
return; return;
} }
@ -240,7 +262,7 @@ void MainWindow::galleryPrev()
void MainWindow::galleryNext() void MainWindow::galleryNext()
{ {
int count = m_files.count(); int count = m_files.count();
if (m_currentFileIndex < 0 || m_files.isEmpty() || m_currentFileIndex >= m_files.count()) { if (!isGalleryAvailable()) {
return; return;
} }
@ -249,6 +271,14 @@ void MainWindow::galleryNext()
m_graphicsView->showFileFromUrl(m_files.at(m_currentFileIndex), false); m_graphicsView->showFileFromUrl(m_files.at(m_currentFileIndex), false);
} }
bool MainWindow::isGalleryAvailable()
{
if (m_currentFileIndex < 0 || m_files.isEmpty() || m_currentFileIndex >= m_files.count()) {
return false;
}
return true;
}
void MainWindow::showEvent(QShowEvent *event) void MainWindow::showEvent(QShowEvent *event)
{ {
updateWidgetsPosition(); updateWidgetsPosition();
@ -262,6 +292,8 @@ void MainWindow::enterEvent(QEvent *event)
m_gv->setOpacity(1); m_gv->setOpacity(1);
m_closeButton->setOpacity(1); m_closeButton->setOpacity(1);
m_prevButton->setOpacity(1);
m_nextButton->setOpacity(1);
return QMainWindow::enterEvent(event); return QMainWindow::enterEvent(event);
} }
@ -272,6 +304,8 @@ void MainWindow::leaveEvent(QEvent *event)
m_gv->setOpacity(0); m_gv->setOpacity(0);
m_closeButton->setOpacity(0); m_closeButton->setOpacity(0);
m_prevButton->setOpacity(0);
m_nextButton->setOpacity(0);
return QMainWindow::leaveEvent(event); return QMainWindow::leaveEvent(event);
} }
@ -537,6 +571,9 @@ void MainWindow::closeWindow()
void MainWindow::updateWidgetsPosition() void MainWindow::updateWidgetsPosition()
{ {
m_closeButton->move(width() - m_closeButton->width(), 0); m_closeButton->move(width() - m_closeButton->width(), 0);
m_prevButton->move(25, (height() - m_prevButton->height()) / 2);
m_nextButton->move(width() - m_nextButton->width() - 25,
(height() - m_prevButton->height()) / 2);
m_bottomButtonGroup->move((width() - m_bottomButtonGroup->width()) / 2, m_bottomButtonGroup->move((width() - m_bottomButtonGroup->width()) / 2,
height() - m_bottomButtonGroup->height()); height() - m_bottomButtonGroup->height());
m_gv->move(width() - m_gv->width(), height() - m_gv->height()); m_gv->move(width() - m_gv->width(), height() - m_gv->height());
@ -546,6 +583,8 @@ void MainWindow::toggleProtectedMode()
{ {
m_protectedMode = !m_protectedMode; m_protectedMode = !m_protectedMode;
m_closeButton->setVisible(!m_protectedMode); m_closeButton->setVisible(!m_protectedMode);
m_prevButton->setVisible(!m_protectedMode);
m_nextButton->setVisible(!m_protectedMode);
} }
void MainWindow::toggleStayOnTop() void MainWindow::toggleStayOnTop()

View File

@ -31,6 +31,10 @@ public:
void loadGalleryBySingleLocalFile(const QString &path); void loadGalleryBySingleLocalFile(const QString &path);
void galleryPrev(); void galleryPrev();
void galleryNext(); void galleryNext();
bool isGalleryAvailable();
signals:
void galleryLoaded();
protected slots: protected slots:
void showEvent(QShowEvent *event) override; void showEvent(QShowEvent *event) override;
@ -61,6 +65,8 @@ private:
QPropertyAnimation *m_floatUpAnimation; QPropertyAnimation *m_floatUpAnimation;
QParallelAnimationGroup *m_exitAnimationGroup; QParallelAnimationGroup *m_exitAnimationGroup;
ToolButton *m_closeButton; ToolButton *m_closeButton;
ToolButton *m_prevButton;
ToolButton *m_nextButton;
GraphicsView *m_graphicsView; GraphicsView *m_graphicsView;
NavigatorView *m_gv; NavigatorView *m_gv;
BottomButtonGroup *m_bottomButtonGroup; BottomButtonGroup *m_bottomButtonGroup;

View File

@ -8,5 +8,7 @@
<file>icons/view-background-checkerboard.svg</file> <file>icons/view-background-checkerboard.svg</file>
<file>icons/app-icon.svg</file> <file>icons/app-icon.svg</file>
<file>icons/window-close.svg</file> <file>icons/window-close.svg</file>
<file>icons/go-next.svg</file>
<file>icons/go-previous.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -6,18 +6,20 @@
#include <QGraphicsOpacityEffect> #include <QGraphicsOpacityEffect>
#include <QPropertyAnimation> #include <QPropertyAnimation>
ToolButton::ToolButton(QWidget *parent) ToolButton::ToolButton(bool hoverColor, QWidget *parent)
: QPushButton(parent) : QPushButton(parent)
, m_opacityHelper(new OpacityHelper(this)) , m_opacityHelper(new OpacityHelper(this))
{ {
setFlat(true); setFlat(true);
setFixedSize(50, 50); QString qss = "QPushButton {"
setStyleSheet("QPushButton {"
"background: transparent;" "background: transparent;"
"}" "}";
"QPushButton:hover {" if (hoverColor) {
"background: red;" qss += "QPushButton:hover {"
"}"); "background: red;"
"}";
}
setStyleSheet(qss);
} }
void ToolButton::setOpacity(qreal opacity, bool animated) void ToolButton::setOpacity(qreal opacity, bool animated)

View File

@ -8,7 +8,7 @@ class ToolButton : public QPushButton
{ {
Q_OBJECT Q_OBJECT
public: public:
ToolButton(QWidget * parent = nullptr); ToolButton(bool hoverColor = false, QWidget * parent = nullptr);
public slots: public slots:
void setOpacity(qreal opacity, bool animated = true); void setOpacity(qreal opacity, bool animated = true);