Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
fb24e54579 | |||
3b1af64397 | |||
4dbfb2f881 | |||
fe0b36dc34 | |||
1864ff5b7f | |||
fb1ad2ba06 | |||
e3dfc9c673 | |||
eb648e3112 | |||
5495fa06d3 | |||
41e75f10b5 | |||
6b0e4b6767 | |||
f49ed645fc | |||
8fe860e4bf | |||
2d07290fbe |
17
.github/workflows/macos.yml
vendored
Normal file
17
.github/workflows/macos.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: macOS CI
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Install Qt
|
||||||
|
uses: jurplel/install-qt-action@v2.2.1
|
||||||
|
- name: Run a qt project
|
||||||
|
run: |
|
||||||
|
cmake ./
|
||||||
|
make
|
20
.github/workflows/ubuntu.yml
vendored
Normal file
20
.github/workflows/ubuntu.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Ubuntu 20.04 CI
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Get build dept.
|
||||||
|
run: sudo apt install cmake qtbase5-dev libqt5svg5-dev qttools5-dev
|
||||||
|
- name: Build it
|
||||||
|
run: |
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ../
|
||||||
|
make
|
||||||
|
sudo cpack
|
@ -6,7 +6,7 @@ include (GNUInstallDirs)
|
|||||||
|
|
||||||
set (CMAKE_AUTOMOC ON)
|
set (CMAKE_AUTOMOC ON)
|
||||||
set (CMAKE_AUTORCC ON)
|
set (CMAKE_AUTORCC ON)
|
||||||
set (QT_MINIMUM_VERSION "5.7.1")
|
set (QT_MINIMUM_VERSION "5.10")
|
||||||
|
|
||||||
find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets Svg LinguistTools)
|
find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets Svg LinguistTools)
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ install (
|
|||||||
|
|
||||||
# CPACK: General Settings
|
# CPACK: General Settings
|
||||||
set (CPACK_GENERATOR "TBZ2")
|
set (CPACK_GENERATOR "TBZ2")
|
||||||
set (CPACK_PACKAGE_NAME "PineapplePictures")
|
set (CPACK_PACKAGE_NAME "pineapple-pictures")
|
||||||
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Yet another image viewer")
|
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Yet another image viewer")
|
||||||
set (CPACK_PACKAGE_VENDOR "Gary Wang")
|
set (CPACK_PACKAGE_VENDOR "Gary Wang")
|
||||||
set (CPACK_PACKAGE_CONTACT "https://github.com/BLumia/PineapplePictures/issues/")
|
set (CPACK_PACKAGE_CONTACT "https://github.com/BLumia/PineapplePictures/issues/")
|
||||||
@ -143,6 +143,8 @@ elseif (APPLE)
|
|||||||
# ...
|
# ...
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
set (CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
set (CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
set (CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5svg5")
|
||||||
|
set (CPACK_DEBIAN_PACKAGE_RECOMMENDS "kimageformat-plugins")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
@ -3,6 +3,8 @@ Yet another image viewer.
|
|||||||
|CI|Build Status|
|
|CI|Build Status|
|
||||||
|---|---|
|
|---|---|
|
||||||
|Windows Build|[](https://ci.appveyor.com/project/BLumia/pineapplepictures/branch/master)|
|
|Windows Build|[](https://ci.appveyor.com/project/BLumia/pineapplepictures/branch/master)|
|
||||||
|
|macOS Build||
|
||||||
|
|Ubuntu 20.04 Build||
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -21,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).
|
||||||
|
|
||||||
|
40
appveyor.yml
40
appveyor.yml
@ -1,27 +1,49 @@
|
|||||||
environment:
|
environment:
|
||||||
|
CMAKE_INSTALL_ROOT: C:\projects\cmake
|
||||||
matrix:
|
matrix:
|
||||||
- build_name: mingw73_32_qt5_12_5
|
- build_name: mingw73_32_qt5_12_6
|
||||||
QTPATH: C:\Qt\5.12.5\mingw73_32
|
QTPATH: C:\Qt\5.12.6\mingw73_32
|
||||||
MINGW32: C:\Qt\Tools\mingw730_32
|
MINGW32: C:\Qt\Tools\mingw730_32
|
||||||
# - build_name: msvc2017_64
|
|
||||||
# QTPATH: C:\Qt\5.11.2\msvc2017_64
|
|
||||||
# MINGW32: C:\Qt\Tools\mingw530_32
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
- mkdir %CMAKE_INSTALL_ROOT%
|
||||||
- cd %APPVEYOR_BUILD_FOLDER%
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- set PATH=%PATH%;%QTPATH%\bin;%MINGW32%\bin
|
- set PATH=%PATH%;%CMAKE_INSTALL_ROOT%;%QTPATH%\bin;%MINGW32%\bin
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
|
# prepare
|
||||||
|
- mkdir 3rdparty
|
||||||
|
- cinst ninja
|
||||||
|
# install ECM so we can build KImageFormats
|
||||||
|
- cd 3rdparty
|
||||||
|
- git clone -q https://invent.kde.org/frameworks/extra-cmake-modules.git
|
||||||
|
- cd extra-cmake-modules
|
||||||
|
- cmake -G "Ninja" . -DCMAKE_INSTALL_PREFIX=%CMAKE_INSTALL_ROOT%
|
||||||
|
- cmake --build .
|
||||||
|
- cmake --build . --target install
|
||||||
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
# install KImageFormats
|
||||||
|
- cd 3rdparty
|
||||||
|
- git clone -q https://invent.kde.org/frameworks/kimageformats.git
|
||||||
|
- cd kimageformats
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake -G "Unix Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -DCMAKE_INSTALL_PREFIX='%cd%' ..\
|
- cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS_RELEASE="-s" -DCMAKE_MAKE_PROGRAM=mingw32-make -DQT_PLUGIN_INSTALL_DIR=%QTPATH%\plugins
|
||||||
|
- cmake --build . --config Release
|
||||||
|
- cmake --build . --config Release --target install
|
||||||
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
# finally...
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_MAKE_PROGRAM=mingw32-make -DCMAKE_INSTALL_PREFIX='%cd%'
|
||||||
- mingw32-make
|
- mingw32-make
|
||||||
- mingw32-make install
|
- mingw32-make install
|
||||||
# fixme: I don't know how to NOT make the binary installed to the ./bin/ folder...
|
# fixme: I don't know how to NOT make the binary installed to the ./bin/ folder...
|
||||||
- cd bin
|
- cd bin
|
||||||
- windeployqt --no-quick-import --no-translations --no-opengl-sw --no-angle --no-system-d3d-compiler --release .\ppic.exe
|
- windeployqt --verbose=2 --no-quick-import --no-translations --no-opengl-sw --no-angle --no-system-d3d-compiler --release .\ppic.exe
|
||||||
- tree
|
# for debug..
|
||||||
|
- tree /f
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: build\bin
|
- path: build\bin
|
||||||
|
@ -60,6 +60,17 @@ void GraphicsScene::showGif(const QString &filepath)
|
|||||||
this->setSceneRect(m_theThing->boundingRect());
|
this->setSceneRect(m_theThing->boundingRect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::trySetTransformationMode(Qt::TransformationMode mode)
|
||||||
|
{
|
||||||
|
QGraphicsPixmapItem * pixmapItem = qgraphicsitem_cast<QGraphicsPixmapItem *>(m_theThing);
|
||||||
|
if (pixmapItem) {
|
||||||
|
pixmapItem->setTransformationMode(mode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QPixmap GraphicsScene::renderToPixmap()
|
QPixmap GraphicsScene::renderToPixmap()
|
||||||
{
|
{
|
||||||
QPixmap pixmap(sceneRect().toRect().size());
|
QPixmap pixmap(sceneRect().toRect().size());
|
||||||
|
@ -15,6 +15,8 @@ public:
|
|||||||
void showSvg(const QString &filepath);
|
void showSvg(const QString &filepath);
|
||||||
void showGif(const QString &filepath);
|
void showGif(const QString &filepath);
|
||||||
|
|
||||||
|
bool trySetTransformationMode(Qt::TransformationMode mode);
|
||||||
|
|
||||||
QPixmap renderToPixmap();
|
QPixmap renderToPixmap();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -39,8 +39,10 @@ void GraphicsView::showFileFromUrl(const QUrl &url, bool doRequestGallery)
|
|||||||
QImageReader imageReader(filePath);
|
QImageReader imageReader(filePath);
|
||||||
imageReader.setAutoTransform(true);
|
imageReader.setAutoTransform(true);
|
||||||
imageReader.setDecideFormatFromContent(true);
|
imageReader.setDecideFormatFromContent(true);
|
||||||
QImage::Format imageFormat = imageReader.imageFormat();
|
// Since if the image format / plugin does not support this feature, imageFormat() will returns an invalid format.
|
||||||
if (imageFormat == QImage::Format_Invalid) {
|
// So we cannot use imageFormat() and check if it returns QImage::Format_Invalid to detect if we support the file.
|
||||||
|
// QImage::Format imageFormat = imageReader.imageFormat();
|
||||||
|
if (imageReader.format().isEmpty()) {
|
||||||
showText(tr("File is not a valid image"));
|
showText(tr("File is not a valid image"));
|
||||||
} else {
|
} else {
|
||||||
showImage(QPixmap::fromImageReader(&imageReader));
|
showImage(QPixmap::fromImageReader(&imageReader));
|
||||||
@ -117,6 +119,7 @@ void GraphicsView::zoomView(qreal scaleFactor)
|
|||||||
{
|
{
|
||||||
m_enableFitInView = false;
|
m_enableFitInView = false;
|
||||||
scale(scaleFactor, scaleFactor);
|
scale(scaleFactor, scaleFactor);
|
||||||
|
applyTransformationModeByScaleFactor();
|
||||||
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), m_rotateAngle);
|
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), m_rotateAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +139,7 @@ void GraphicsView::rotateView(qreal rotateAngel)
|
|||||||
void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode)
|
void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode)
|
||||||
{
|
{
|
||||||
QGraphicsView::fitInView(rect, aspectRadioMode);
|
QGraphicsView::fitInView(rect, aspectRadioMode);
|
||||||
|
applyTransformationModeByScaleFactor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsView::checkAndDoFitInView()
|
void GraphicsView::checkAndDoFitInView()
|
||||||
@ -213,9 +217,9 @@ void GraphicsView::dragEnterEvent(QDragEnterEvent *event)
|
|||||||
} else {
|
} else {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
qDebug() << event->mimeData() << "Drag Enter Event"
|
// qDebug() << event->mimeData() << "Drag Enter Event"
|
||||||
<< event->mimeData()->hasUrls() << event->mimeData()->hasImage()
|
// << event->mimeData()->hasUrls() << event->mimeData()->hasImage()
|
||||||
<< event->mimeData()->formats() << event->mimeData()->hasFormat("text/uri-list");
|
// << event->mimeData()->formats() << event->mimeData()->hasFormat("text/uri-list");
|
||||||
|
|
||||||
return QGraphicsView::dragEnterEvent(event);
|
return QGraphicsView::dragEnterEvent(event);
|
||||||
}
|
}
|
||||||
@ -238,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());
|
||||||
@ -285,9 +289,9 @@ void GraphicsView::setCheckerboardEnabled(bool enabled)
|
|||||||
if (m_checkerboardEnabled) {
|
if (m_checkerboardEnabled) {
|
||||||
// Prepare background check-board pattern
|
// Prepare background check-board pattern
|
||||||
QPixmap tilePixmap(0x20, 0x20);
|
QPixmap tilePixmap(0x20, 0x20);
|
||||||
tilePixmap.fill(QColor(35, 35, 35, 110));
|
tilePixmap.fill(QColor(35, 35, 35, 170));
|
||||||
QPainter tilePainter(&tilePixmap);
|
QPainter tilePainter(&tilePixmap);
|
||||||
QColor color(40, 40, 40, 110);
|
QColor color(45, 45, 45, 170);
|
||||||
tilePainter.fillRect(0, 0, 0x10, 0x10, color);
|
tilePainter.fillRect(0, 0, 0x10, 0x10, color);
|
||||||
tilePainter.fillRect(0x10, 0x10, 0x10, 0x10, color);
|
tilePainter.fillRect(0x10, 0x10, 0x10, 0x10, color);
|
||||||
tilePainter.end();
|
tilePainter.end();
|
||||||
@ -298,6 +302,15 @@ void GraphicsView::setCheckerboardEnabled(bool enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsView::applyTransformationModeByScaleFactor()
|
||||||
|
{
|
||||||
|
if (this->scaleFactor() < 1) {
|
||||||
|
scene()->trySetTransformationMode(Qt::SmoothTransformation);
|
||||||
|
} else {
|
||||||
|
scene()->trySetTransformationMode(Qt::FastTransformation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsView::resetWithScaleAndRotate(qreal scaleFactor, qreal rotateAngle)
|
void GraphicsView::resetWithScaleAndRotate(qreal scaleFactor, qreal rotateAngle)
|
||||||
{
|
{
|
||||||
QGraphicsView::resetTransform();
|
QGraphicsView::resetTransform();
|
||||||
|
@ -54,6 +54,7 @@ private:
|
|||||||
bool isThingSmallerThanWindowWith(const QTransform &transform) const;
|
bool isThingSmallerThanWindowWith(const QTransform &transform) const;
|
||||||
bool shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const;
|
bool shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const;
|
||||||
void setCheckerboardEnabled(bool enabled);
|
void setCheckerboardEnabled(bool enabled);
|
||||||
|
void applyTransformationModeByScaleFactor();
|
||||||
|
|
||||||
void resetWithScaleAndRotate(qreal scaleFactor, qreal rotateAngle);
|
void resetWithScaleAndRotate(qreal scaleFactor, qreal rotateAngle);
|
||||||
|
|
||||||
|
79
icons/go-next.svg
Normal file
79
icons/go-next.svg
Normal 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
79
icons/go-previous.svg
Normal 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 |
@ -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,10 +126,19 @@ 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));
|
||||||
|
|
||||||
|
QShortcut * quitAppShorucut2 = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
|
connect(quitAppShorucut2, &QShortcut::activated,
|
||||||
|
std::bind(&MainWindow::quitAppAction, this, false));
|
||||||
|
|
||||||
QShortcut * prevPictureShorucut = new QShortcut(QKeySequence(Qt::Key_PageUp), this);
|
QShortcut * prevPictureShorucut = new QShortcut(QKeySequence(Qt::Key_PageUp), this);
|
||||||
connect(prevPictureShorucut, &QShortcut::activated,
|
connect(prevPictureShorucut, &QShortcut::activated,
|
||||||
this, &MainWindow::galleryPrev);
|
this, &MainWindow::galleryPrev);
|
||||||
@ -121,6 +147,10 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
connect(nextPictureShorucut, &QShortcut::activated,
|
connect(nextPictureShorucut, &QShortcut::activated,
|
||||||
this, &MainWindow::galleryNext);
|
this, &MainWindow::galleryNext);
|
||||||
|
|
||||||
|
QShortcut * fullscreenShorucut = new QShortcut(QKeySequence(QKeySequence::FullScreen), this);
|
||||||
|
connect(fullscreenShorucut, &QShortcut::activated,
|
||||||
|
this, &MainWindow::toggleFullscreen);
|
||||||
|
|
||||||
centerWindow();
|
centerWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,12 +215,18 @@ QUrl MainWindow::currentImageFileUrl() const
|
|||||||
return QUrl();
|
return QUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::clearGallery()
|
||||||
|
{
|
||||||
|
m_currentFileIndex = -1;
|
||||||
|
m_files.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
|
void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
|
||||||
{
|
{
|
||||||
QFileInfo info(path);
|
QFileInfo info(path);
|
||||||
QDir dir(info.path());
|
QDir dir(info.path());
|
||||||
QString currentFileName = info.fileName();
|
QString currentFileName = info.fileName();
|
||||||
QStringList entryList = dir.entryList({"*.jpg", "*.jpeg", "*.png", "*.gif", "*.svg", "*.bmp"},
|
QStringList entryList = dir.entryList({"*.jpg", "*.jpeg", "*.jfif", "*.png", "*.gif", "*.svg", "*.bmp"},
|
||||||
QDir::Files | QDir::NoSymLinks, QDir::NoSort);
|
QDir::Files | QDir::NoSymLinks, QDir::NoSort);
|
||||||
|
|
||||||
QCollator collator;
|
QCollator collator;
|
||||||
@ -198,8 +234,7 @@ void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
|
|||||||
|
|
||||||
std::sort(entryList.begin(), entryList.end(), collator);
|
std::sort(entryList.begin(), entryList.end(), collator);
|
||||||
|
|
||||||
m_currentFileIndex = -1;
|
clearGallery();
|
||||||
m_files.clear();
|
|
||||||
|
|
||||||
for (int i = 0; i < entryList.count(); i++) {
|
for (int i = 0; i < entryList.count(); i++) {
|
||||||
const QString & oneEntry = entryList.at(i);
|
const QString & oneEntry = entryList.at(i);
|
||||||
@ -209,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,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();
|
||||||
@ -249,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);
|
||||||
}
|
}
|
||||||
@ -259,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);
|
||||||
}
|
}
|
||||||
@ -268,8 +315,8 @@ void MainWindow::mousePressEvent(QMouseEvent *event)
|
|||||||
if (event->buttons() & Qt::LeftButton && !isMaximized()) {
|
if (event->buttons() & Qt::LeftButton && !isMaximized()) {
|
||||||
m_clickedOnWindow = true;
|
m_clickedOnWindow = true;
|
||||||
m_oldMousePos = event->pos();
|
m_oldMousePos = event->pos();
|
||||||
qDebug() << m_oldMousePos << m_graphicsView->transform().m11()
|
// qDebug() << m_oldMousePos << m_graphicsView->transform().m11()
|
||||||
<< m_graphicsView->transform().m22() << m_graphicsView->matrix().m12();
|
// << m_graphicsView->transform().m22() << m_graphicsView->matrix().m12();
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +404,7 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
|||||||
|
|
||||||
QAction * pasteImage = new QAction(tr("&Paste Image"));
|
QAction * pasteImage = new QAction(tr("&Paste Image"));
|
||||||
connect(pasteImage, &QAction::triggered, this, [ = ](){
|
connect(pasteImage, &QAction::triggered, this, [ = ](){
|
||||||
|
clearGallery();
|
||||||
m_graphicsView->showImage(clipboardImage);
|
m_graphicsView->showImage(clipboardImage);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -523,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());
|
||||||
@ -532,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()
|
||||||
@ -551,3 +604,12 @@ void MainWindow::quitAppAction(bool force)
|
|||||||
closeWindow();
|
closeWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::toggleFullscreen()
|
||||||
|
{
|
||||||
|
if (isFullScreen()) {
|
||||||
|
showNormal();
|
||||||
|
} else {
|
||||||
|
showFullScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,9 +27,14 @@ public:
|
|||||||
void adjustWindowSizeBySceneRect();
|
void adjustWindowSizeBySceneRect();
|
||||||
QUrl currentImageFileUrl() const;
|
QUrl currentImageFileUrl() const;
|
||||||
|
|
||||||
|
void clearGallery();
|
||||||
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;
|
||||||
@ -52,6 +57,7 @@ protected slots:
|
|||||||
void toggleStayOnTop();
|
void toggleStayOnTop();
|
||||||
bool stayOnTop();
|
bool stayOnTop();
|
||||||
void quitAppAction(bool force = false);
|
void quitAppAction(bool force = false);
|
||||||
|
void toggleFullscreen();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPoint m_oldMousePos;
|
QPoint m_oldMousePos;
|
||||||
@ -59,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;
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
qss += "QPushButton:hover {"
|
||||||
"background: red;"
|
"background: red;"
|
||||||
"}");
|
"}";
|
||||||
|
}
|
||||||
|
setStyleSheet(qss);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolButton::setOpacity(qreal opacity, bool animated)
|
void ToolButton::setOpacity(qreal opacity, bool animated)
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user