25 Commits
0.2.1 ... 0.3.1

Author SHA1 Message Date
9f67be61fb fix: cannot load images under WSL2 network location
workaround resolve GH-7
2020-08-28 15:25:07 +08:00
761f5e064c feat(i18n): add zh_CN translation for .desktop file 2020-08-26 19:06:41 +08:00
84e100c174 Update README.md 2020-08-23 23:46:12 +08:00
d64e9cf276 build(ci): deb package for ubuntu 20.04 2020-08-13 19:45:38 +08:00
dc82115e1f fix: don't show what's this button from setting dialog. 2020-08-11 09:08:31 +08:00
3b94eecde2 chore: only enable portable mode support for windows 2020-08-10 23:41:59 +08:00
f3b3ad7b8a Correct a typo in PineapplePictures.pro 2020-08-06 19:40:44 +08:00
1a511ddb02 CI: for windows build, also copy LICENSE file to binary dir 2020-08-04 19:15:10 +08:00
1cb67b48f4 fix: cannot minimize window by clicking taskbar icon 2020-08-04 19:10:02 +08:00
90d0869b5e doc: prepare for repo url change 2020-07-29 13:26:54 +08:00
7004e74165 i18n: update translations for new strings 2020-07-29 13:23:31 +08:00
a2adb0e1d4 feat: simple config dialog 2020-07-29 00:57:43 +08:00
6709c21d70 config file support 2020-07-28 21:29:37 +08:00
31fae2cc8c misc: lower minimum window size limit 2020-07-27 20:47:54 +08:00
20be5e6f4f fix: windows icon size not correct in explorer 2020-07-22 19:02:23 +08:00
6009c2682e ci(windows): build with karchive to support kra and ora formats 2020-07-22 13:46:21 +08:00
92ded932ec feat: add version info datat for windows, and application display name 2020-07-21 20:47:06 +08:00
cd942b4fcc fix: try to fix icon resolution issue under windows 2020-07-21 14:01:27 +08:00
6fc1b2e7c8 Merge pull request #5 from Lovelyblack/master
new icon :)
2020-07-21 13:44:35 +08:00
278988b628 Add files via upload 2020-07-21 13:36:47 +08:00
9b19d13ee2 New Ico 2020-07-21 13:35:57 +08:00
c271fde194 chore: stop using QWheelEvent::delta() 2020-07-12 23:46:00 +08:00
fb24e54579 feat: add prev and next button 2020-07-04 13:49:12 +08:00
3b1af64397 fix(CI): since KDE are using their new GitLab instance 2020-06-18 23:13:39 +08:00
4dbfb2f881 CI: add GitHub Action ubuntu build 2020-06-18 23:06:15 +08:00
26 changed files with 1284 additions and 198 deletions

View File

@ -1,4 +1,4 @@
name: MyCi_MacOS name: macOS CI
on: [push] on: [push]

24
.github/workflows/ubuntu.yml vendored Normal file
View File

@ -0,0 +1,24 @@
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
cpack -G DEB
- uses: actions/upload-artifact@v2
with:
name: ubuntu-20.04-deb-package
path: build/*.deb

View File

@ -3,6 +3,7 @@ project (pineapple-pictures)
cmake_minimum_required (VERSION 3.9.5) cmake_minimum_required (VERSION 3.9.5)
include (GNUInstallDirs) include (GNUInstallDirs)
include (FeatureSummary)
set (CMAKE_AUTOMOC ON) set (CMAKE_AUTOMOC ON)
set (CMAKE_AUTORCC ON) set (CMAKE_AUTORCC ON)
@ -19,6 +20,8 @@ set (PPIC_CPP_FILES
navigatorview.cpp navigatorview.cpp
opacityhelper.cpp opacityhelper.cpp
toolbutton.cpp toolbutton.cpp
settings.cpp
settingsdialog.cpp
) )
set (PPIC_HEADER_FILES set (PPIC_HEADER_FILES
@ -29,6 +32,8 @@ set (PPIC_HEADER_FILES
navigatorview.h navigatorview.h
opacityhelper.h opacityhelper.h
toolbutton.h toolbutton.h
settings.h
settingsdialog.h
) )
set (PPIC_QRC_FILES set (PPIC_QRC_FILES
@ -67,6 +72,49 @@ if (WIN32)
TARGET ${EXE_NAME} TARGET ${EXE_NAME}
PROPERTY WIN32_EXECUTABLE true PROPERTY WIN32_EXECUTABLE true
) )
target_compile_definitions(${EXE_NAME} PRIVATE
FLAG_PORTABLE_MODE_SUPPORT=1
)
endif ()
# Helper macros for parsing and setting project version from `git describe --long` result
macro (ppic_set_version_via_describe _describe_long)
string (
REGEX REPLACE
"^([0-9a-z.]*)-[0-9]+-g[0-9a-f]*$"
"\\1"
_tag_parts
"${_describe_long}"
)
list (GET _tag_parts 0 _matched_tag_version)
if ("${_matched_tag_version}" MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+$")
string (
REGEX REPLACE
"^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$"
"\\1;\\2;\\3"
_ver_parts
"${_matched_tag_version}"
)
list (GET _ver_parts 0 CPACK_PACKAGE_VERSION_MAJOR)
list (GET _ver_parts 1 CPACK_PACKAGE_VERSION_MINOR)
list (GET _ver_parts 2 CPACK_PACKAGE_VERSION_PATCH)
endif ()
endmacro ()
# Version setup
if (EXISTS "${CMAKE_SOURCE_DIR}/.git")
find_package(Git)
set_package_properties(Git PROPERTIES TYPE OPTIONAL PURPOSE "Determine exact build version.")
if (GIT_FOUND)
execute_process (
COMMAND ${GIT_EXECUTABLE} describe --tags --always --long
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE _git_describe_long
)
string (REGEX REPLACE "\n" "" _git_describe_long "${_git_describe_long}")
ppic_set_version_via_describe(${_git_describe_long})
endif ()
endif () endif ()
# Helper macros for install settings # Helper macros for install settings

View File

@ -32,7 +32,9 @@ SOURCES += \
graphicsscene.cpp \ graphicsscene.cpp \
navigatorview.cpp \ navigatorview.cpp \
opacityhelper.cpp \ opacityhelper.cpp \
toolbutton.cpp toolbutton.cpp \
settings.cpp \
settingsdialog.cpp
HEADERS += \ HEADERS += \
mainwindow.h \ mainwindow.h \
@ -41,7 +43,9 @@ HEADERS += \
graphicsscene.h \ graphicsscene.h \
navigatorview.h \ navigatorview.h \
opacityhelper.h \ opacityhelper.h \
toolbutton.h toolbutton.h \
settings.h \
settingsdialog.h
TRANSLATIONS = \ TRANSLATIONS = \
languages/PineapplePictures.ts \ languages/PineapplePictures.ts \
@ -55,6 +59,6 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
RESOURCES += \ RESOURCES += \
resources.qrc resources.qrc
# Generate fron svg: # Generate from svg:
# magick convert -background none ./app-icon.svg -define icon:auto-resize=64,48,32,16 app-icon.ico # magick convert -background none app-icon.svg -define icon:auto-resize="16,32,48,64,128,256" app-icon.ico
RC_ICONS = icons/app-icon.ico RC_ICONS = icons/app-icon.ico

View File

@ -3,26 +3,64 @@ Yet another image viewer.
|CI|Build Status| |CI|Build Status|
|---|---| |---|---|
|Windows Build|[![Windows build status](https://ci.appveyor.com/api/projects/status/dbd8clww3cit6oa0/branch/master?svg=true)](https://ci.appveyor.com/project/BLumia/pineapplepictures/branch/master)| |Windows Build|[![Windows build status](https://ci.appveyor.com/api/projects/status/dbd8clww3cit6oa0/branch/master?svg=true)](https://ci.appveyor.com/project/BLumia/pineapplepictures/branch/master)|
|macOS Build|![macOS CI](https://github.com/BLumia/pineapple-pictures/workflows/macOS%20CI/badge.svg)|
|Ubuntu 20.04 Build|![Ubuntu 20.04 CI](https://github.com/BLumia/pineapple-pictures/workflows/Ubuntu%2020.04%20CI/badge.svg)|
![Pineapple Pictures - Main Window](https://repository-images.githubusercontent.com/211888654/21fb6300-269f-11ea-8e85-953e5d57da44) ![Pineapple Pictures - Main Window](https://repository-images.githubusercontent.com/211888654/21fb6300-269f-11ea-8e85-953e5d57da44)
## Get it! ## Get it!
- [GitHub Release Page](https://github.com/BLumia/PineapplePictures/releases) - [GitHub Release Page](https://github.com/BLumia/pineapple-pictures/releases)
- Archlinux AUR: [pineapple-pictures-git](https://aur.archlinux.org/packages/pineapple-pictures-git/) - Archlinux AUR: [pineapple-pictures-git](https://aur.archlinux.org/packages/pineapple-pictures-git/)
## Build it manually:
Current state, we need:
- `cmake`: as the build system.
- `qt5` with `qt5-svg` and `qt5-tools`: since the app is using Qt.
Then we can build it with any proper c++ compiler like g++ or msvc.
Building it just requires normal cmake building steps:
``` bash
$ mkdir build && cd build
$ cmake ..
$ cmake --build . # or simply using `make` if you are using Makefile as the cmake generator.
```
After that, a `ppic` executable file will be available to use. You can also optionally install it by using the target `install` (or simply `make install` in case you are using Makefile). After the build process, you can also use `cpack` to make a package.
Image formats supports rely on Qt's imageformats plugins, just get the plugins you need from your distro's package manager will be fine. For Windows user, you may need build and install the imageformats plugin manually, read the content below.
### Linux
Just normal build process as other program will be fine. Nothing special ;)
For Archlinux there are also a [PKGBUILD](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=pineapple-pictures-git) you can use.
For packaging to debian-based distro, the `CMakeLists.txt` provides some cpack configurations for generating a `.deb` package. After the build process, use `cpack -G DEB` to generate the package. You can also take `.github/workflows/ubuntu.yml` as a reference.
For this project, `DEB` is the only supported cpack generator in current state, feel free to submit a PR if you like improving `cpack` support for this project.
### Windows
The normal build steps for Linux is also applied to Windows, but since Windows doesn't have a decent package manager, so if you need any other image formats support other than the supported formats which Qt provided, you need to get and build these imageformats plugins manually and vendor it. It's optional and can be skipped if you don't need extra image formats support.
For the Windows binary I provided, kimageformats plugin is used (for formats like kra, xcf, psd and etc.). You can take `appveyor.yml` as a reference to learn what I did when building the Windows binary.
[KDE Craft](https://community.kde.org/Craft) environment also can be used to build and package this program. I did also created a blueprint for building this project, but since I don't have a CI to run KDE Craft build, the blueprint repo are not provided here. Maybe sometimes later.
### macOS
I don't have a mac, so no support at all. There is also a GitHub Action (see `.github/workflows/macos.yml`) running macOS build though so at least it can build. Feel free to submit a PR if you would like to give some love to the macOS build ;P
## Help Translation! ## Help Translation!
[Translate this project on Transifex!](https://www.transifex.com/blumia/pineapple-pictures/) [Translate this project on Transifex!](https://www.transifex.com/blumia/pineapple-pictures/)
Feel free to open up an issue to request an new language to translate. Feel free to open up an issue to request a new language to translate.
## Uncleaned shits inside(TM):
- Mixed `CR LF` and `LF`.
- Ugly action icons.
- 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).
## License ## License

View File

@ -1,5 +1,6 @@
environment: environment:
CMAKE_INSTALL_ROOT: C:\projects\cmake CMAKE_INSTALL_ROOT: C:\projects\cmake
ZLIB_ROOT: C:\projects\zlib
matrix: matrix:
- build_name: mingw73_32_qt5_12_6 - build_name: mingw73_32_qt5_12_6
QTPATH: C:\Qt\5.12.6\mingw73_32 QTPATH: C:\Qt\5.12.6\mingw73_32
@ -7,6 +8,7 @@ environment:
install: install:
- mkdir %CMAKE_INSTALL_ROOT% - mkdir %CMAKE_INSTALL_ROOT%
- mkdir %ZLIB_ROOT%
- cd %APPVEYOR_BUILD_FOLDER% - cd %APPVEYOR_BUILD_FOLDER%
- git submodule update --init --recursive - git submodule update --init --recursive
- set PATH=%PATH%;%CMAKE_INSTALL_ROOT%;%QTPATH%\bin;%MINGW32%\bin - set PATH=%PATH%;%CMAKE_INSTALL_ROOT%;%QTPATH%\bin;%MINGW32%\bin
@ -17,15 +19,31 @@ build_script:
- cinst ninja - cinst ninja
# install ECM so we can build KImageFormats # install ECM so we can build KImageFormats
- cd 3rdparty - cd 3rdparty
- git clone -q git://anongit.kde.org/extra-cmake-modules.git - git clone -q https://invent.kde.org/frameworks/extra-cmake-modules.git
- cd extra-cmake-modules - cd extra-cmake-modules
- cmake -G "Ninja" . -DCMAKE_INSTALL_PREFIX=%CMAKE_INSTALL_ROOT% - cmake -G "Ninja" . -DCMAKE_INSTALL_PREFIX=%CMAKE_INSTALL_ROOT%
- cmake --build . - cmake --build .
- cmake --build . --target install - cmake --build . --target install
- cd %APPVEYOR_BUILD_FOLDER% - cd %APPVEYOR_BUILD_FOLDER%
# download and install zlib for KArchive
- cd %ZLIB_ROOT%
- curl -fsS -o zlib128-dll.zip http://zlib.net/zlib128-dll.zip
- 7z e zlib128-dll.zip
- cd %APPVEYOR_BUILD_FOLDER%
# install KArchive for kra format support of KImageFormats
- cd 3rdparty
- git clone -q https://invent.kde.org/frameworks/karchive.git
- cd karchive
- mkdir build
- cd build
- cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=%CMAKE_INSTALL_ROOT% -DCMAKE_CXX_FLAGS_RELEASE="-s" -DCMAKE_MAKE_PROGRAM=mingw32-make -DZLIB_ROOT=%ZLIB_ROOT%
# -DCMAKE_PREFIX_PATH=%CMAKE_INSTALL_ROOT%
- cmake --build . --config Release
- cmake --build . --config Release --target install
- cd %APPVEYOR_BUILD_FOLDER%
# install KImageFormats # install KImageFormats
- cd 3rdparty - cd 3rdparty
- git clone git://anongit.kde.org/kimageformats.git - git clone -q https://invent.kde.org/frameworks/kimageformats.git
- cd kimageformats - cd kimageformats
- mkdir build - mkdir build
- cd build - cd build
@ -41,6 +59,8 @@ build_script:
- 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
- copy %APPVEYOR_BUILD_FOLDER%\LICENSE .
- copy C:\projects\cmake\bin\libKF5Archive.dll .
- windeployqt --verbose=2 --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
# for debug.. # for debug..
- tree /f - tree /f

View File

@ -31,6 +31,17 @@ void GraphicsView::showFileFromUrl(const QUrl &url, bool doRequestGallery)
QString filePath(url.toLocalFile()); QString filePath(url.toLocalFile());
#ifdef Q_OS_WIN
// TODO: remove this workaround when M$ change the "wsl$" hostname.
if (Q_UNLIKELY(url.scheme() == QStringLiteral("qtbug-86277"))) {
filePath = url.path();
// Qt's QUrl won't work with such hostname anyway so the urls will
// still be the wrong one when requesting gallery. So we just don't
// request gallery here...
doRequestGallery = false;
}
#endif // Q_OS_WIN
if (filePath.endsWith(".svg")) { if (filePath.endsWith(".svg")) {
showSvg(filePath); showSvg(filePath);
} else if (filePath.endsWith(".gif")) { } else if (filePath.endsWith(".gif")) {
@ -142,12 +153,16 @@ void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadio
applyTransformationModeByScaleFactor(); applyTransformationModeByScaleFactor();
} }
void GraphicsView::checkAndDoFitInView() void GraphicsView::checkAndDoFitInView(bool markItOnAnyway)
{ {
if (!isThingSmallerThanWindowWith(transform())) { if (!isThingSmallerThanWindowWith(transform())) {
m_enableFitInView = true; m_enableFitInView = true;
fitInView(sceneRect(), Qt::KeepAspectRatio); fitInView(sceneRect(), Qt::KeepAspectRatio);
} }
if (markItOnAnyway) {
m_enableFitInView = true;
}
} }
void GraphicsView::toggleCheckerboard() void GraphicsView::toggleCheckerboard()
@ -242,7 +257,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());

View File

@ -30,7 +30,7 @@ public:
void rotateView(qreal rotateAngel); void rotateView(qreal rotateAngel);
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio); void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio);
void checkAndDoFitInView(); void checkAndDoFitInView(bool markItOnAnyway = true);
signals: signals:
void navigatorViewRequired(bool required, qreal angle); void navigatorViewRequired(bool required, qreal angle);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -1,102 +1,469 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Creator: CorelDRAW 2018 (评估版) -->
<svg <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="86.6986mm" height="86.6986mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 8669.86 8669.86"
xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" <defs>
xmlns:svg="http://www.w3.org/2000/svg" <style type="text/css">
xmlns="http://www.w3.org/2000/svg" <![CDATA[
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" .str0 {stroke:#332C2B;stroke-width:20;stroke-miterlimit:22.9256}
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" .fil124 {fill:#FEFEFE}
width="32" .fil118 {fill:#F6CAA9}
height="32" .fil117 {fill:#F7CAA8}
viewBox="0 0 8.4666665 8.4666669" .fil116 {fill:#F6CAA8}
version="1.1" .fil115 {fill:#F6CAA7}
id="svg8" .fil114 {fill:#F6C9A7}
inkscape:version="0.92.4 (5da689c313, 2019-01-14)" .fil113 {fill:#F6C9A6}
sodipodi:docname="view-fullscreen - 副本.svg"> .fil112 {fill:#F6C8A5}
<defs .fil111 {fill:#F6C7A4}
id="defs2" /> .fil110 {fill:#F6C7A3}
<sodipodi:namedview .fil109 {fill:#F6C6A3}
id="base" .fil108 {fill:#F6C6A2}
pagecolor="#000000" .fil107 {fill:#F5C6A2}
bordercolor="#666666" .fil106 {fill:#F5C5A2}
borderopacity="1.0" .fil105 {fill:#F5C5A1}
inkscape:pageopacity="0.69803922" .fil104 {fill:#F5C5A1}
inkscape:pageshadow="2" .fil103 {fill:#F5C5A0}
inkscape:zoom="22.4" .fil102 {fill:#F5C49F}
inkscape:cx="11.283707" .fil101 {fill:#F5C49E}
inkscape:cy="14.931415" .fil100 {fill:#F5C39E}
inkscape:document-units="px" .fil99 {fill:#F5C39D}
inkscape:current-layer="layer1" .fil98 {fill:#F5C29D}
showgrid="false" .fil97 {fill:#F5C29C}
units="px" .fil96 {fill:#F5C19B}
inkscape:pagecheckerboard="true" .fil95 {fill:#F5C19B}
inkscape:window-width="1920" .fil94 {fill:#F5C19A}
inkscape:window-height="1001" .fil93 {fill:#F5C19A}
inkscape:window-x="-9" .fil92 {fill:#F5C099}
inkscape:window-y="-9" .fil91 {fill:#F5C098}
inkscape:window-maximized="1" /> .fil90 {fill:#F4BF98}
<metadata .fil89 {fill:#F4BF97}
id="metadata5"> .fil88 {fill:#F4BE97}
<rdf:RDF> .fil87 {fill:#F4BE96}
<cc:Work .fil1 {fill:#F4BD95}
rdf:about=""> .fil2 {fill:#F4BD95}
<dc:format>image/svg+xml</dc:format> .fil3 {fill:#F4BD94}
<dc:type .fil4 {fill:#F4BD94}
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> .fil5 {fill:#F4BC93}
<dc:title /> .fil6 {fill:#F4BC93}
</cc:Work> .fil7 {fill:#F4BB92}
</rdf:RDF> .fil8 {fill:#F4BB91}
</metadata> .fil9 {fill:#F4BA90}
<g .fil10 {fill:#F4B98F}
inkscape:label="Layer 1" .fil11 {fill:#F4B98F}
inkscape:groupmode="layer" .fil12 {fill:#F4B98E}
id="layer1" .fil13 {fill:#F3B88E}
transform="translate(0,-288.5333)"> .fil14 {fill:#F3B88D}
<path .fil15 {fill:#F3B78C}
style="fill:none;stroke:#ffffff;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" .fil16 {fill:#F3B78B}
d="M 1.6393869,293.16031 1.615848,290.14918 H 3.6380209" .fil17 {fill:#F3B68B}
id="path837" .fil18 {fill:#F3B68A}
inkscape:connector-curvature="0" .fil19 {fill:#F3B589}
sodipodi:nodetypes="ccc" /> .fil20 {fill:#F2B488}
<path .fil21 {fill:#F2B487}
style="fill:none;stroke:#ffffff;stroke-width:0.26531255px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" .fil22 {fill:#F2B386}
d="m 6.9097992,291.96816 0.014252,-1.85441 -3.2860303,0.0354" .fil23 {fill:#F2B385}
id="path837-6" .fil24 {fill:#F2B285}
inkscape:connector-curvature="0" .fil25 {fill:#F2B284}
sodipodi:nodetypes="ccc" /> .fil26 {fill:#F2B183}
<path .fil27 {fill:#F2B082}
style="fill:none;stroke:#ffffff;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" .fil28 {fill:#F2B081}
d="m 6.9097992,291.96816 0.035006,3.10579 H 4.9226322" .fil29 {fill:#F2B081}
id="path837-9" .fil30 {fill:#F2B080}
inkscape:connector-curvature="0" .fil31 {fill:#F2AF7F}
sodipodi:nodetypes="ccc" /> .fil32 {fill:#F2AE7F}
<path .fil33 {fill:#F2AE7E}
style="fill:none;stroke:#ffffff;stroke-width:0.26531255px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" .fil34 {fill:#F2AD7D}
d="m 1.6393869,293.16031 -0.00244,1.90166 3.2856855,0.012" .fil35 {fill:#F2AD7D}
id="path837-6-4" .fil36 {fill:#F1AC7D}
inkscape:connector-curvature="0" .fil37 {fill:#F1AC7C}
sodipodi:nodetypes="ccc" /> .fil38 {fill:#F1AC7C}
<path .fil39 {fill:#F1AC7B}
style="fill:none;stroke:#ffffff;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" .fil40 {fill:#F1AB7B}
d="m 1.6418341,292.9131 0.8740699,-0.51972 c 0,0 0.4960938,-0.29529 0.8622581,-0.11812 0.3661646,0.17718 0.094494,0.0236 0.3661646,0.17718 0.2716702,0.15355 0.2716702,0.16537 0.2716702,0.16537 l 0.5669645,0.60239 c 0,0 0.9921875,1.16937 1.1339284,1.37017 l 0.1299292,0.21261 0.1417411,0.30711" .fil41 {fill:#F1AA7A}
id="path819" .fil42 {fill:#F0AA79}
inkscape:connector-curvature="0" .fil43 {fill:#F0AA78}
sodipodi:nodetypes="ccccccscc" /> .fil44 {fill:#F0A978}
<path .fil45 {fill:#F0A977}
style="fill:none;stroke:#ffffff;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" .fil46 {fill:#F0A877}
d="m 5.1144902,293.84623 0.4488469,-0.62603 c 0,0 0.3071055,-0.22442 0.5669642,-0.2008 l 0.2598587,0.0236 0.3425409,0.12993 v 0 l 0.2480469,0.14174" .fil47 {fill:#F0A876}
id="path821" .fil48 {fill:#F0A776}
inkscape:connector-curvature="0" .fil49 {fill:#F0A775}
sodipodi:nodetypes="ccccccc" /> .fil50 {fill:#F0A674}
<ellipse .fil51 {fill:#F0A674}
style="fill:#ffffff;fill-opacity:0.87058824;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" .fil52 {fill:#F0A673}
id="path823" .fil53 {fill:#F0A673}
cx="5.0849609" .fil54 {fill:#F0A572}
cy="291.8028" .fil55 {fill:#F0A572}
rx="0.86816406" .fil56 {fill:#F0A471}
ry="0.8976934" /> .fil57 {fill:#F0A470}
</g> .fil58 {fill:#F0A370}
</svg> .fil59 {fill:#F0A36F}
.fil60 {fill:#F0A36F}
.fil61 {fill:#F0A26E}
.fil62 {fill:#EFA26E}
.fil63 {fill:#EFA26D}
.fil64 {fill:#EFA16C}
.fil65 {fill:#EFA06B}
.fil66 {fill:#EFA06B}
.fil67 {fill:#EF9F6A}
.fil68 {fill:#EF9F6A}
.fil69 {fill:#EF9E69}
.fil70 {fill:#EF9E69}
.fil71 {fill:#EF9E68}
.fil72 {fill:#EE9D68}
.fil73 {fill:#EE9D67}
.fil74 {fill:#EE9D67}
.fil75 {fill:#EE9C66}
.fil76 {fill:#EE9C65}
.fil77 {fill:#EE9B65}
.fil78 {fill:#EE9B64}
.fil79 {fill:#EE9A63}
.fil80 {fill:#EE9963}
.fil81 {fill:#EE9962}
.fil82 {fill:#EE9962}
.fil83 {fill:#EE9961}
.fil84 {fill:#ED9860}
.fil85 {fill:#ED975F}
.fil120 {fill:#7789A4}
.fil122 {fill:#664840}
.fil123 {fill:#9A8276}
.fil86 {fill:#EC9760}
.fil0 {fill:url(#id1)}
.fil119 {fill:url(#id2)}
.fil121 {fill:url(#id3)}
]]>
</style>
<clipPath id="id0">
<path d="M3369.27 5277.36l110.2 -99.02c247.94,-533.39 647.21,-1047.01 1246.8,-1534.38 399.32,-324.56 1700.72,1992.38 1629.16,2055.54 -1059.82,254.09 -2048.61,72.9 -2986.16,-422.14z"/>
</clipPath>
<linearGradient id="id1" gradientUnits="userSpaceOnUse" x1="768.62" y1="3552.57" x2="7059.64" y2="3552.57">
<stop offset="0" style="stop-opacity:1; stop-color:#28AFEA"/>
<stop offset="0.192157" style="stop-opacity:1; stop-color:#46A5E8"/>
<stop offset="0.368627" style="stop-opacity:1; stop-color:#28AFEA"/>
<stop offset="1" style="stop-opacity:1; stop-color:#649AE6"/>
</linearGradient>
<linearGradient id="id2" gradientUnits="userSpaceOnUse" x1="3022.74" y1="6181.99" x2="3647.6" y2="2505.13">
<stop offset="0" style="stop-opacity:1; stop-color:#664840"/>
<stop offset="0.870588" style="stop-opacity:1; stop-color:#B2A39F"/>
<stop offset="1" style="stop-opacity:1; stop-color:#FEFEFE"/>
</linearGradient>
<radialGradient id="id3" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.999999 -0 -0 0.999999 0 0)" cx="3914.13" cy="3552.57" r="3081.87" fx="3914.13" fy="3552.57">
<stop offset="0" style="stop-opacity:1; stop-color:#FEFEFE"/>
<stop offset="0.368627" style="stop-opacity:1; stop-color:#BAC3D1"/>
<stop offset="1" style="stop-opacity:1; stop-color:#7789A4"/>
</radialGradient>
</defs>
<g id="图层_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<circle class="fil0 str0" cx="3914.13" cy="3552.57" r="3145.51"/>
<g>
<g style="clip-path:url(#id0)">
<polygon class="fil1" points="4049.35,6758.42 4047.39,6754.15 6436.52,5657.1 6438.48,5661.36 "/>
<polygon id="1" class="fil1" points="4049.31,6758.34 4043.55,6745.78 6432.68,5648.73 6438.44,5661.28 "/>
<polygon id="2" class="fil2" points="4045.47,6749.97 4039.71,6737.41 6428.84,5640.36 6434.6,5652.91 "/>
<polygon id="3" class="fil3" points="4041.63,6741.6 4035.86,6729.05 6424.99,5631.99 6430.76,5644.54 "/>
<polygon id="4" class="fil4" points="4037.79,6733.23 4032.02,6720.68 6421.15,5623.62 6426.91,5636.18 "/>
<polygon id="5" class="fil5" points="4033.94,6724.86 4028.18,6712.31 6417.31,5615.25 6423.07,5627.81 "/>
<polygon id="6" class="fil6" points="4030.1,6716.49 4024.34,6703.94 6413.46,5606.89 6419.23,5619.44 "/>
<polygon id="7" class="fil6" points="4026.26,6708.12 4020.49,6695.57 6409.62,5598.52 6415.39,5611.07 "/>
<polygon id="8" class="fil7" points="4022.41,6699.76 4016.65,6687.2 6405.78,5590.15 6411.54,5602.7 "/>
<polygon id="9" class="fil7" points="4018.57,6691.39 4012.81,6678.83 6401.94,5581.78 6407.7,5594.33 "/>
<polygon id="10" class="fil8" points="4014.73,6683.02 4008.97,6670.47 6398.09,5573.41 6403.86,5585.96 "/>
<polygon id="11" class="fil9" points="4010.89,6674.65 4005.12,6662.1 6394.25,5565.04 6400.02,5577.6 "/>
<polygon id="12" class="fil9" points="4007.04,6666.28 4001.28,6653.73 6390.41,5556.67 6396.17,5569.23 "/>
<polygon id="13" class="fil10" points="4003.2,6657.91 3997.44,6645.36 6386.57,5548.31 6392.33,5560.86 "/>
<polygon id="14" class="fil10" points="3999.36,6649.55 3993.59,6636.99 6382.72,5539.94 6388.49,5552.49 "/>
<polygon id="15" class="fil11" points="3995.52,6641.18 3989.75,6628.62 6378.88,5531.57 6384.64,5544.12 "/>
<polygon id="16" class="fil12" points="3991.67,6632.81 3985.91,6620.26 6375.04,5523.2 6380.8,5535.75 "/>
<polygon id="17" class="fil13" points="3987.83,6624.44 3982.07,6611.89 6371.2,5514.83 6376.96,5527.38 "/>
<polygon id="18" class="fil13" points="3983.99,6616.07 3978.22,6603.52 6367.35,5506.46 6373.12,5519.02 "/>
<polygon id="19" class="fil14" points="3980.14,6607.7 3974.38,6595.15 6363.51,5498.09 6369.27,5510.65 "/>
<polygon id="20" class="fil14" points="3976.3,6599.33 3970.54,6586.78 6359.67,5489.73 6365.43,5502.28 "/>
<polygon id="21" class="fil15" points="3972.46,6590.97 3966.7,6578.41 6355.82,5481.36 6361.59,5493.91 "/>
<polygon id="22" class="fil15" points="3968.62,6582.6 3962.85,6570.04 6351.98,5472.99 6357.75,5485.54 "/>
<polygon id="23" class="fil16" points="3964.77,6574.23 3959.01,6561.68 6348.14,5464.62 6353.9,5477.17 "/>
<polygon id="24" class="fil17" points="3960.93,6565.86 3955.17,6553.31 6344.3,5456.25 6350.06,5468.81 "/>
<polygon id="25" class="fil18" points="3957.09,6557.49 3951.32,6544.94 6340.45,5447.88 6346.22,5460.44 "/>
<polygon id="26" class="fil18" points="3953.25,6549.12 3947.48,6536.57 6336.61,5439.52 6342.37,5452.07 "/>
<polygon id="27" class="fil19" points="3949.4,6540.75 3943.64,6528.2 6332.77,5431.15 6338.53,5443.7 "/>
<polygon id="28" class="fil19" points="3945.56,6532.39 3939.8,6519.83 6328.93,5422.78 6334.69,5435.33 "/>
<polygon id="29" class="fil20" points="3941.72,6524.02 3935.95,6511.46 6325.08,5414.41 6330.85,5426.96 "/>
<polygon id="30" class="fil20" points="3937.88,6515.65 3932.11,6503.1 6321.24,5406.04 6327,5418.59 "/>
<polygon id="31" class="fil20" points="3934.03,6507.28 3928.27,6494.73 6317.4,5397.67 6323.16,5410.23 "/>
<polygon id="32" class="fil21" points="3930.19,6498.91 3924.43,6486.36 6313.55,5389.3 6319.32,5401.86 "/>
<polygon id="33" class="fil21" points="3926.35,6490.54 3920.58,6477.99 6309.71,5380.94 6315.48,5393.49 "/>
<polygon id="34" class="fil22" points="3922.5,6482.18 3916.74,6469.62 6305.87,5372.57 6311.63,5385.12 "/>
<polygon id="35" class="fil22" points="3918.66,6473.81 3912.9,6461.25 6302.03,5364.2 6307.79,5376.75 "/>
<polygon id="36" class="fil23" points="3914.82,6465.44 3909.05,6452.89 6298.18,5355.83 6303.95,5368.38 "/>
<polygon id="37" class="fil24" points="3910.98,6457.07 3905.21,6444.52 6294.34,5347.46 6300.11,5360.01 "/>
<polygon id="38" class="fil25" points="3907.13,6448.7 3901.37,6436.15 6290.5,5339.09 6296.26,5351.65 "/>
<polygon id="39" class="fil25" points="3903.29,6440.33 3897.53,6427.78 6286.66,5330.73 6292.42,5343.28 "/>
<polygon id="40" class="fil26" points="3899.45,6431.96 3893.68,6419.41 6282.81,5322.36 6288.58,5334.91 "/>
<polygon id="41" class="fil26" points="3895.61,6423.6 3889.84,6411.04 6278.97,5313.99 6284.73,5326.54 "/>
<polygon id="42" class="fil27" points="3891.76,6415.23 3886,6402.67 6275.13,5305.62 6280.89,5318.17 "/>
<polygon id="43" class="fil27" points="3887.92,6406.86 3882.16,6394.31 6271.29,5297.25 6277.05,5309.8 "/>
<polygon id="44" class="fil28" points="3884.08,6398.49 3878.31,6385.94 6267.44,5288.88 6273.21,5301.44 "/>
<polygon id="45" class="fil29" points="3880.23,6390.12 3874.47,6377.57 6263.6,5280.51 6269.36,5293.07 "/>
<polygon id="46" class="fil30" points="3876.39,6381.75 3870.63,6369.2 6259.76,5272.15 6265.52,5284.7 "/>
<polygon id="47" class="fil30" points="3872.55,6373.38 3866.79,6360.83 6255.91,5263.78 6261.68,5276.33 "/>
<polygon id="48" class="fil31" points="3868.71,6365.02 3862.94,6352.46 6252.07,5255.41 6257.84,5267.96 "/>
<polygon id="49" class="fil31" points="3864.86,6356.65 3859.1,6344.09 6248.23,5247.04 6253.99,5259.59 "/>
<polygon id="50" class="fil32" points="3861.02,6348.28 3855.26,6335.73 6244.39,5238.67 6250.15,5251.22 "/>
<polygon id="51" class="fil33" points="3857.18,6339.91 3851.41,6327.36 6240.54,5230.3 6246.31,5242.86 "/>
<polygon id="52" class="fil33" points="3853.34,6331.54 3847.57,6318.99 6236.7,5221.93 6242.46,5234.49 "/>
<polygon id="53" class="fil34" points="3849.49,6323.17 3843.73,6310.62 6232.86,5213.57 6238.62,5226.12 "/>
<polygon id="54" class="fil34" points="3845.65,6314.81 3839.89,6302.25 6229.02,5205.2 6234.78,5217.75 "/>
<polygon id="55" class="fil35" points="3841.81,6306.44 3836.04,6293.88 6225.17,5196.83 6230.94,5209.38 "/>
<polygon id="56" class="fil36" points="3837.97,6298.07 3832.2,6285.52 6221.33,5188.46 6227.09,5201.01 "/>
<polygon id="57" class="fil37" points="3834.12,6289.7 3828.36,6277.15 6217.49,5180.09 6223.25,5192.64 "/>
<polygon id="58" class="fil38" points="3830.28,6281.33 3824.52,6268.78 6213.64,5171.72 6219.41,5184.28 "/>
<polygon id="59" class="fil39" points="3826.44,6272.96 3820.67,6260.41 6209.8,5163.36 6215.57,5175.91 "/>
<polygon id="60" class="fil40" points="3822.59,6264.59 3816.83,6252.04 6205.96,5154.99 6211.72,5167.54 "/>
<polygon id="61" class="fil41" points="3818.75,6256.23 3812.99,6243.67 6202.12,5146.62 6207.88,5159.17 "/>
<polygon id="62" class="fil41" points="3814.91,6247.86 3809.14,6235.3 6198.27,5138.25 6204.04,5150.8 "/>
<polygon id="63" class="fil42" points="3811.07,6239.49 3805.3,6226.94 6194.43,5129.88 6200.2,5142.43 "/>
<polygon id="64" class="fil42" points="3807.22,6231.12 3801.46,6218.57 6190.59,5121.51 6196.35,5134.07 "/>
<polygon id="65" class="fil43" points="3803.38,6222.75 3797.62,6210.2 6186.75,5113.14 6192.51,5125.7 "/>
<polygon id="66" class="fil44" points="3799.54,6214.38 3793.77,6201.83 6182.9,5104.78 6188.67,5117.33 "/>
<polygon id="67" class="fil45" points="3795.7,6206.01 3789.93,6193.46 6179.06,5096.41 6184.82,5108.96 "/>
<polygon id="68" class="fil45" points="3791.85,6197.65 3786.09,6185.09 6175.22,5088.04 6180.98,5100.59 "/>
<polygon id="69" class="fil46" points="3788.01,6189.28 3782.25,6176.73 6171.37,5079.67 6177.14,5092.22 "/>
<polygon id="70" class="fil47" points="3784.17,6180.91 3778.4,6168.36 6167.53,5071.3 6173.3,5083.85 "/>
<polygon id="71" class="fil48" points="3780.32,6172.54 3774.56,6159.99 6163.69,5062.93 6169.45,5075.49 "/>
<polygon id="72" class="fil49" points="3776.48,6164.17 3770.72,6151.62 6159.85,5054.56 6165.61,5067.12 "/>
<polygon id="73" class="fil49" points="3772.64,6155.8 3766.88,6143.25 6156,5046.2 6161.77,5058.75 "/>
<polygon id="74" class="fil50" points="3768.8,6147.44 3763.03,6134.88 6152.16,5037.83 6157.93,5050.38 "/>
<polygon id="75" class="fil50" points="3764.95,6139.07 3759.19,6126.51 6148.32,5029.46 6154.08,5042.01 "/>
<polygon id="76" class="fil51" points="3761.11,6130.7 3755.35,6118.15 6144.48,5021.09 6150.24,5033.64 "/>
<polygon id="77" class="fil52" points="3757.27,6122.33 3751.5,6109.78 6140.63,5012.72 6146.4,5025.27 "/>
<polygon id="78" class="fil53" points="3753.43,6113.96 3747.66,6101.41 6136.79,5004.35 6142.55,5016.91 "/>
<polygon id="79" class="fil54" points="3749.58,6105.59 3743.82,6093.04 6132.95,4995.99 6138.71,5008.54 "/>
<polygon id="80" class="fil55" points="3745.74,6097.22 3739.98,6084.67 6129.11,4987.62 6134.87,5000.17 "/>
<polygon id="81" class="fil55" points="3741.9,6088.86 3736.13,6076.3 6125.26,4979.25 6131.03,4991.8 "/>
<polygon id="82" class="fil56" points="3738.05,6080.49 3732.29,6067.93 6121.42,4970.88 6127.18,4983.43 "/>
<polygon id="83" class="fil56" points="3734.21,6072.12 3728.45,6059.57 6117.58,4962.51 6123.34,4975.06 "/>
<polygon id="84" class="fil57" points="3730.37,6063.75 3724.61,6051.2 6113.73,4954.14 6119.5,4966.7 "/>
<polygon id="85" class="fil58" points="3726.53,6055.38 3720.76,6042.83 6109.89,4945.77 6115.66,4958.33 "/>
<polygon id="86" class="fil59" points="3722.68,6047.01 3716.92,6034.46 6106.05,4937.41 6111.81,4949.96 "/>
<polygon id="87" class="fil60" points="3718.84,6038.64 3713.08,6026.09 6102.21,4929.04 6107.97,4941.59 "/>
<polygon id="88" class="fil60" points="3715,6030.28 3709.23,6017.72 6098.36,4920.67 6104.13,4933.22 "/>
<polygon id="89" class="fil61" points="3711.16,6021.91 3705.39,6009.36 6094.52,4912.3 6100.29,4924.85 "/>
<polygon id="90" class="fil62" points="3707.31,6013.54 3701.55,6000.99 6090.68,4903.93 6096.44,4916.48 "/>
<polygon id="91" class="fil63" points="3703.47,6005.17 3697.71,5992.62 6086.84,4895.56 6092.6,4908.12 "/>
<polygon id="92" class="fil63" points="3699.63,5996.8 3693.86,5984.25 6082.99,4887.19 6088.76,4899.75 "/>
<polygon id="93" class="fil64" points="3695.79,5988.43 3690.02,5975.88 6079.15,4878.83 6084.91,4891.38 "/>
<polygon id="94" class="fil64" points="3691.94,5980.07 3686.18,5967.51 6075.31,4870.46 6081.07,4883.01 "/>
<polygon id="95" class="fil65" points="3688.1,5971.7 3682.34,5959.14 6071.46,4862.09 6077.23,4874.64 "/>
<polygon id="96" class="fil65" points="3684.26,5963.33 3678.49,5950.78 6067.62,4853.72 6073.39,4866.27 "/>
<polygon id="97" class="fil66" points="3680.41,5954.96 3674.65,5942.41 6063.78,4845.35 6069.54,4857.91 "/>
<polygon id="98" class="fil67" points="3676.57,5946.59 3670.81,5934.04 6059.94,4836.98 6065.7,4849.54 "/>
<polygon id="99" class="fil68" points="3672.73,5938.22 3666.97,5925.67 6056.09,4828.62 6061.86,4841.17 "/>
<polygon id="100" class="fil69" points="3668.89,5929.85 3663.12,5917.3 6052.25,4820.25 6058.02,4832.8 "/>
<polygon id="101" class="fil70" points="3665.04,5921.49 3659.28,5908.93 6048.41,4811.88 6054.17,4824.43 "/>
<polygon id="102" class="fil70" points="3661.2,5913.12 3655.44,5900.56 6044.57,4803.51 6050.33,4816.06 "/>
<polygon id="103" class="fil71" points="3657.36,5904.75 3651.59,5892.2 6040.72,4795.14 6046.49,4807.69 "/>
<polygon id="104" class="fil72" points="3653.52,5896.38 3647.75,5883.83 6036.88,4786.77 6042.64,4799.33 "/>
<polygon id="105" class="fil73" points="3649.67,5888.01 3643.91,5875.46 6033.04,4778.4 6038.8,4790.96 "/>
<polygon id="106" class="fil74" points="3645.83,5879.64 3640.07,5867.09 6029.2,4770.04 6034.96,4782.59 "/>
<polygon id="107" class="fil74" points="3641.99,5871.27 3636.22,5858.72 6025.35,4761.67 6031.12,4774.22 "/>
<polygon id="108" class="fil75" points="3638.14,5862.91 3632.38,5850.35 6021.51,4753.3 6027.27,4765.85 "/>
<polygon id="109" class="fil75" points="3634.3,5854.54 3628.54,5841.99 6017.67,4744.93 6023.43,4757.48 "/>
<polygon id="110" class="fil76" points="3630.46,5846.17 3624.7,5833.62 6013.82,4736.56 6019.59,4749.11 "/>
<polygon id="111" class="fil77" points="3626.62,5837.8 3620.85,5825.25 6009.98,4728.19 6015.75,4740.75 "/>
<polygon id="112" class="fil78" points="3622.77,5829.43 3617.01,5816.88 6006.14,4719.82 6011.9,4732.38 "/>
<polygon id="113" class="fil78" points="3618.93,5821.06 3613.17,5808.51 6002.3,4711.46 6008.06,4724.01 "/>
<polygon id="114" class="fil79" points="3615.09,5812.7 3609.32,5800.14 5998.45,4703.09 6004.22,4715.64 "/>
<polygon id="115" class="fil79" points="3611.25,5804.33 3605.48,5791.77 5994.61,4694.72 6000.37,4707.27 "/>
<polygon id="116" class="fil80" points="3607.4,5795.96 3601.64,5783.41 5990.77,4686.35 5996.53,4698.9 "/>
<polygon id="117" class="fil80" points="3603.56,5787.59 3597.8,5775.04 5986.93,4677.98 5992.69,4690.54 "/>
<polygon id="118" class="fil81" points="3599.72,5779.22 3593.95,5766.67 5983.08,4669.61 5988.85,4682.17 "/>
<polygon id="119" class="fil82" points="3595.88,5770.85 3590.11,5758.3 5979.24,4661.25 5985,4673.8 "/>
<polygon id="120" class="fil83" points="3592.03,5762.48 3586.27,5749.93 5975.4,4652.88 5981.16,4665.43 "/>
<polygon id="121" class="fil83" points="3588.19,5754.12 3582.43,5741.56 5971.55,4644.51 5977.32,4657.06 "/>
<polygon id="122" class="fil84" points="3584.35,5745.75 3578.58,5733.19 5967.71,4636.14 5973.48,4648.69 "/>
<polygon id="123" class="fil84" points="3580.5,5737.38 3574.74,5724.83 5963.87,4627.77 5969.63,4640.32 "/>
<polygon id="124" class="fil85" points="3576.66,5729.01 3570.9,5716.46 5960.03,4619.4 5965.79,4631.96 "/>
<polygon id="125" class="fil86" points="3572.82,5720.64 3567.05,5708.09 5956.18,4611.03 5961.95,4623.59 "/>
<polygon id="126" class="fil85" points="3568.98,5712.27 3563.21,5699.72 5952.34,4602.67 5958.11,4615.22 "/>
<polygon id="127" class="fil84" points="3565.13,5703.91 3559.37,5691.35 5948.5,4594.3 5954.26,4606.85 "/>
<polygon id="128" class="fil84" points="3561.29,5695.54 3555.53,5682.98 5944.66,4585.93 5950.42,4598.48 "/>
<polygon id="129" class="fil83" points="3557.45,5687.17 3551.68,5674.62 5940.81,4577.56 5946.58,4590.11 "/>
<polygon id="130" class="fil83" points="3553.61,5678.8 3547.84,5666.25 5936.97,4569.19 5942.73,4581.74 "/>
<polygon id="131" class="fil82" points="3549.76,5670.43 3544,5657.88 5933.13,4560.82 5938.89,4573.38 "/>
<polygon id="132" class="fil81" points="3545.92,5662.06 3540.16,5649.51 5929.29,4552.45 5935.05,4565.01 "/>
<polygon id="133" class="fil80" points="3542.08,5653.69 3536.31,5641.14 5925.44,4544.09 5931.21,4556.64 "/>
<polygon id="134" class="fil80" points="3538.23,5645.33 3532.47,5632.77 5921.6,4535.72 5927.36,4548.27 "/>
<polygon id="135" class="fil79" points="3534.39,5636.96 3528.63,5624.4 5917.76,4527.35 5923.52,4539.9 "/>
<polygon id="136" class="fil79" points="3530.55,5628.59 3524.79,5616.04 5913.91,4518.98 5919.68,4531.53 "/>
<polygon id="137" class="fil78" points="3526.71,5620.22 3520.94,5607.67 5910.07,4510.61 5915.84,4523.17 "/>
<polygon id="138" class="fil78" points="3522.86,5611.85 3517.1,5599.3 5906.23,4502.24 5911.99,4514.8 "/>
<polygon id="139" class="fil77" points="3519.02,5603.48 3513.26,5590.93 5902.39,4493.88 5908.15,4506.43 "/>
<polygon id="140" class="fil76" points="3515.18,5595.11 3509.41,5582.56 5898.54,4485.51 5904.31,4498.06 "/>
<polygon id="141" class="fil75" points="3511.34,5586.75 3505.57,5574.19 5894.7,4477.14 5900.46,4489.69 "/>
<polygon id="142" class="fil75" points="3507.49,5578.38 3501.73,5565.82 5890.86,4468.77 5896.62,4481.32 "/>
<polygon id="143" class="fil74" points="3503.65,5570.01 3497.89,5557.46 5887.02,4460.4 5892.78,4472.95 "/>
<polygon id="144" class="fil74" points="3499.81,5561.64 3494.04,5549.09 5883.17,4452.03 5888.94,4464.59 "/>
<polygon id="145" class="fil73" points="3495.97,5553.27 3490.2,5540.72 5879.33,4443.66 5885.09,4456.22 "/>
<polygon id="146" class="fil72" points="3492.12,5544.9 3486.36,5532.35 5875.49,4435.3 5881.25,4447.85 "/>
<polygon id="147" class="fil71" points="3488.28,5536.54 3482.52,5523.98 5871.64,4426.93 5877.41,4439.48 "/>
<polygon id="148" class="fil70" points="3484.44,5528.17 3478.67,5515.61 5867.8,4418.56 5873.57,4431.11 "/>
<polygon id="149" class="fil70" points="3480.59,5519.8 3474.83,5507.25 5863.96,4410.19 5869.72,4422.74 "/>
<polygon id="150" class="fil69" points="3476.75,5511.43 3470.99,5498.88 5860.12,4401.82 5865.88,4414.37 "/>
<polygon id="151" class="fil68" points="3472.91,5503.06 3467.14,5490.51 5856.27,4393.45 5862.04,4406.01 "/>
<polygon id="152" class="fil67" points="3469.07,5494.69 3463.3,5482.14 5852.43,4385.09 5858.2,4397.64 "/>
<polygon id="153" class="fil66" points="3465.22,5486.32 3459.46,5473.77 5848.59,4376.72 5854.35,4389.27 "/>
<polygon id="154" class="fil65" points="3461.38,5477.96 3455.62,5465.4 5844.75,4368.35 5850.51,4380.9 "/>
<polygon id="155" class="fil65" points="3457.54,5469.59 3451.77,5457.03 5840.9,4359.98 5846.67,4372.53 "/>
<polygon id="156" class="fil64" points="3453.7,5461.22 3447.93,5448.67 5837.06,4351.61 5842.82,4364.16 "/>
<polygon id="157" class="fil64" points="3449.85,5452.85 3444.09,5440.3 5833.22,4343.24 5838.98,4355.8 "/>
<polygon id="158" class="fil63" points="3446.01,5444.48 3440.25,5431.93 5829.37,4334.87 5835.14,4347.43 "/>
<polygon id="159" class="fil63" points="3442.17,5436.11 3436.4,5423.56 5825.53,4326.51 5831.3,4339.06 "/>
<polygon id="160" class="fil62" points="3438.32,5427.74 3432.56,5415.19 5821.69,4318.14 5827.45,4330.69 "/>
<polygon id="161" class="fil61" points="3434.48,5419.38 3428.72,5406.82 5817.85,4309.77 5823.61,4322.32 "/>
<polygon id="162" class="fil60" points="3430.64,5411.01 3424.88,5398.45 5814,4301.4 5819.77,4313.95 "/>
<polygon id="163" class="fil60" points="3426.8,5402.64 3421.03,5390.09 5810.16,4293.03 5815.93,4305.58 "/>
<polygon id="164" class="fil59" points="3422.95,5394.27 3417.19,5381.72 5806.32,4284.66 5812.08,4297.22 "/>
<polygon id="165" class="fil58" points="3419.11,5385.9 3413.35,5373.35 5802.48,4276.29 5808.24,4288.85 "/>
<polygon id="166" class="fil57" points="3415.27,5377.53 3409.5,5364.98 5798.63,4267.93 5804.4,4280.48 "/>
<polygon id="167" class="fil56" points="3411.43,5369.17 3405.66,5356.61 5794.79,4259.56 5800.55,4272.11 "/>
<polygon id="168" class="fil56" points="3407.58,5360.8 3401.82,5348.24 5790.95,4251.19 5796.71,4263.74 "/>
<polygon id="169" class="fil55" points="3403.74,5352.43 3397.98,5339.88 5787.11,4242.82 5792.87,4255.37 "/>
<polygon id="170" class="fil55" points="3399.9,5344.06 3394.13,5331.51 5783.26,4234.45 5789.03,4247 "/>
<polygon id="171" class="fil54" points="3396.05,5335.69 3390.29,5323.14 5779.42,4226.08 5785.18,4238.64 "/>
<polygon id="172" class="fil53" points="3392.21,5327.32 3386.45,5314.77 5775.58,4217.72 5781.34,4230.27 "/>
<polygon id="173" class="fil52" points="3388.37,5318.95 3382.61,5306.4 5771.73,4209.35 5777.5,4221.9 "/>
<polygon id="174" class="fil51" points="3384.53,5310.59 3378.76,5298.03 5767.89,4200.98 5773.66,4213.53 "/>
<polygon id="175" class="fil50" points="3380.68,5302.22 3374.92,5289.66 5764.05,4192.61 5769.81,4205.16 "/>
<polygon id="176" class="fil50" points="3376.84,5293.85 3371.08,5281.3 5760.21,4184.24 5765.97,4196.79 "/>
<polygon id="177" class="fil49" points="3373,5285.48 3367.23,5272.93 5756.36,4175.87 5762.13,4188.43 "/>
<polygon id="178" class="fil49" points="3369.16,5277.11 3363.39,5264.56 5752.52,4167.5 5758.28,4180.06 "/>
<polygon id="179" class="fil48" points="3365.31,5268.74 3359.55,5256.19 5748.68,4159.14 5754.44,4171.69 "/>
<polygon id="180" class="fil47" points="3361.47,5260.37 3355.71,5247.82 5744.84,4150.77 5750.6,4163.32 "/>
<polygon id="181" class="fil46" points="3357.63,5252.01 3351.86,5239.45 5740.99,4142.4 5746.76,4154.95 "/>
<polygon id="182" class="fil45" points="3353.79,5243.64 3348.02,5231.09 5737.15,4134.03 5742.91,4146.58 "/>
<polygon id="183" class="fil45" points="3349.94,5235.27 3344.18,5222.72 5733.31,4125.66 5739.07,4138.21 "/>
<polygon id="184" class="fil44" points="3346.1,5226.9 3340.34,5214.35 5729.46,4117.29 5735.23,4129.85 "/>
<polygon id="185" class="fil43" points="3342.26,5218.53 3336.49,5205.98 5725.62,4108.92 5731.39,4121.48 "/>
<polygon id="186" class="fil42" points="3338.41,5210.16 3332.65,5197.61 5721.78,4100.56 5727.54,4113.11 "/>
<polygon id="187" class="fil42" points="3334.57,5201.8 3328.81,5189.24 5717.94,4092.19 5723.7,4104.74 "/>
<polygon id="188" class="fil41" points="3330.73,5193.43 3324.96,5180.87 5714.09,4083.82 5719.86,4096.37 "/>
<polygon id="189" class="fil41" points="3326.89,5185.06 3321.12,5172.51 5710.25,4075.45 5716.02,4088 "/>
<polygon id="190" class="fil40" points="3323.04,5176.69 3317.28,5164.14 5706.41,4067.08 5712.17,4079.63 "/>
<polygon id="191" class="fil39" points="3319.2,5168.32 3313.44,5155.77 5702.57,4058.71 5708.33,4071.27 "/>
<polygon id="192" class="fil38" points="3315.36,5159.95 3309.59,5147.4 5698.72,4050.35 5704.49,4062.9 "/>
<polygon id="193" class="fil37" points="3311.52,5151.58 3305.75,5139.03 5694.88,4041.98 5700.64,4054.53 "/>
<polygon id="194" class="fil36" points="3307.67,5143.22 3301.91,5130.66 5691.04,4033.61 5696.8,4046.16 "/>
<polygon id="195" class="fil35" points="3303.83,5134.85 3298.07,5122.29 5687.2,4025.24 5692.96,4037.79 "/>
<polygon id="196" class="fil34" points="3299.99,5126.48 3294.22,5113.93 5683.35,4016.87 5689.12,4029.42 "/>
<polygon id="197" class="fil34" points="3296.14,5118.11 3290.38,5105.56 5679.51,4008.5 5685.27,4021.06 "/>
<polygon id="198" class="fil33" points="3292.3,5109.74 3286.54,5097.19 5675.67,4000.13 5681.43,4012.69 "/>
<polygon id="199" class="fil33" points="3288.46,5101.37 3282.7,5088.82 5671.82,3991.77 5677.59,4004.32 "/>
<polygon id="200" class="fil32" points="3284.62,5093 3278.85,5080.45 5667.98,3983.4 5673.75,3995.95 "/>
<polygon id="201" class="fil31" points="3280.77,5084.64 3275.01,5072.08 5664.14,3975.03 5669.9,3987.58 "/>
<polygon id="202" class="fil31" points="3276.93,5076.27 3271.17,5063.72 5660.3,3966.66 5666.06,3979.21 "/>
<polygon id="203" class="fil30" points="3273.09,5067.9 3267.32,5055.35 5656.45,3958.29 5662.22,3970.84 "/>
<polygon id="204" class="fil30" points="3269.25,5059.53 3263.48,5046.98 5652.61,3949.92 5658.37,3962.48 "/>
<polygon id="205" class="fil29" points="3265.4,5051.16 3259.64,5038.61 5648.77,3941.55 5654.53,3954.11 "/>
<polygon id="206" class="fil28" points="3261.56,5042.79 3255.8,5030.24 5644.93,3933.19 5650.69,3945.74 "/>
<polygon id="207" class="fil27" points="3257.72,5034.43 3251.95,5021.87 5641.08,3924.82 5646.85,3937.37 "/>
<polygon id="208" class="fil27" points="3253.88,5026.06 3248.11,5013.5 5637.24,3916.45 5643,3929 "/>
<polygon id="209" class="fil26" points="3250.03,5017.69 3244.27,5005.14 5633.4,3908.08 5639.16,3920.63 "/>
<polygon id="210" class="fil26" points="3246.19,5009.32 3240.43,4996.77 5629.55,3899.71 5635.32,3912.27 "/>
<polygon id="211" class="fil25" points="3242.35,5000.95 3236.58,4988.4 5625.71,3891.34 5631.48,3903.9 "/>
<polygon id="212" class="fil25" points="3238.5,4992.58 3232.74,4980.03 5621.87,3882.98 5627.63,3895.53 "/>
<polygon id="213" class="fil24" points="3234.66,4984.21 3228.9,4971.66 5618.03,3874.61 5623.79,3887.16 "/>
<polygon id="214" class="fil23" points="3230.82,4975.85 3225.05,4963.29 5614.18,3866.24 5619.95,3878.79 "/>
<polygon id="215" class="fil22" points="3226.98,4967.48 3221.21,4954.92 5610.34,3857.87 5616.11,3870.42 "/>
<polygon id="216" class="fil22" points="3223.13,4959.11 3217.37,4946.56 5606.5,3849.5 5612.26,3862.05 "/>
<polygon id="217" class="fil21" points="3219.29,4950.74 3213.53,4938.19 5602.66,3841.13 5608.42,3853.69 "/>
<polygon id="218" class="fil21" points="3215.45,4942.37 3209.68,4929.82 5598.81,3832.76 5604.58,3845.32 "/>
<polygon id="219" class="fil20" points="3211.61,4934 3205.84,4921.45 5594.97,3824.4 5600.73,3836.95 "/>
<polygon id="220" class="fil20" points="3207.76,4925.63 3202,4913.08 5591.13,3816.03 5596.89,3828.58 "/>
<polygon id="221" class="fil20" points="3203.92,4917.27 3198.16,4904.71 5587.28,3807.66 5593.05,3820.21 "/>
<polygon id="222" class="fil19" points="3200.08,4908.9 3194.31,4896.35 5583.44,3799.29 5589.21,3811.84 "/>
<polygon id="223" class="fil19" points="3196.23,4900.53 3190.47,4887.98 5579.6,3790.92 5585.36,3803.47 "/>
<polygon id="224" class="fil18" points="3192.39,4892.16 3186.63,4879.61 5575.76,3782.55 5581.52,3795.11 "/>
<polygon id="225" class="fil18" points="3188.55,4883.79 3182.79,4871.24 5571.91,3774.18 5577.68,3786.74 "/>
<polygon id="226" class="fil17" points="3184.71,4875.42 3178.94,4862.87 5568.07,3765.82 5573.84,3778.37 "/>
<polygon id="227" class="fil16" points="3180.86,4867.06 3175.1,4854.5 5564.23,3757.45 5569.99,3770 "/>
<polygon id="228" class="fil15" points="3177.02,4858.69 3171.26,4846.13 5560.39,3749.08 5566.15,3761.63 "/>
<polygon id="229" class="fil15" points="3173.18,4850.32 3167.41,4837.77 5556.54,3740.71 5562.31,3753.26 "/>
<polygon id="230" class="fil14" points="3169.34,4841.95 3163.57,4829.4 5552.7,3732.34 5558.46,3744.9 "/>
<polygon id="231" class="fil14" points="3165.49,4833.58 3159.73,4821.03 5548.86,3723.97 5554.62,3736.53 "/>
<polygon id="232" class="fil13" points="3161.65,4825.21 3155.89,4812.66 5545.02,3715.61 5550.78,3728.16 "/>
<polygon id="233" class="fil13" points="3157.81,4816.84 3152.04,4804.29 5541.17,3707.24 5546.94,3719.79 "/>
<polygon id="234" class="fil12" points="3153.96,4808.48 3148.2,4795.92 5537.33,3698.87 5543.09,3711.42 "/>
<polygon id="235" class="fil11" points="3150.12,4800.11 3144.36,4787.55 5533.49,3690.5 5539.25,3703.05 "/>
<polygon id="236" class="fil10" points="3146.28,4791.74 3140.52,4779.19 5529.64,3682.13 5535.41,3694.68 "/>
<polygon id="237" class="fil10" points="3142.44,4783.37 3136.67,4770.82 5525.8,3673.76 5531.57,3686.32 "/>
<polygon id="238" class="fil9" points="3138.59,4775 3132.83,4762.45 5521.96,3665.39 5527.72,3677.95 "/>
<polygon id="239" class="fil9" points="3134.75,4766.63 3128.99,4754.08 5518.12,3657.03 5523.88,3669.58 "/>
<polygon id="240" class="fil8" points="3130.91,4758.27 3125.14,4745.71 5514.27,3648.66 5520.04,3661.21 "/>
<polygon id="241" class="fil7" points="3127.07,4749.9 3121.3,4737.34 5510.43,3640.29 5516.2,3652.84 "/>
<polygon id="242" class="fil7" points="3123.22,4741.53 3117.46,4728.98 5506.59,3631.92 5512.35,3644.47 "/>
<polygon id="243" class="fil6" points="3119.38,4733.16 3113.62,4720.61 5502.75,3623.55 5508.51,3636.1 "/>
<polygon id="244" class="fil6" points="3115.54,4724.79 3109.77,4712.24 5498.9,3615.18 5504.67,3627.74 "/>
<polygon id="245" class="fil5" points="3111.7,4716.42 3105.93,4703.87 5495.06,3606.81 5500.82,3619.37 "/>
<polygon id="246" class="fil4" points="3107.85,4708.05 3102.09,4695.5 5491.22,3598.45 5496.98,3611 "/>
<polygon id="247" class="fil3" points="3104.01,4699.69 3098.25,4687.13 5487.37,3590.08 5493.14,3602.63 "/>
<polygon id="248" class="fil2" points="3100.17,4691.32 3094.4,4678.76 5483.53,3581.71 5489.3,3594.26 "/>
<polygon id="249" class="fil1" points="3096.32,4682.95 3090.56,4670.4 5479.69,3573.34 5485.45,3585.89 "/>
<polygon id="250" class="fil1" points="3092.48,4674.58 3086.72,4662.03 5475.85,3564.97 5481.61,3577.53 "/>
<polygon id="251" class="fil87" points="3088.64,4666.21 3082.88,4653.66 5472,3556.6 5477.77,3569.16 "/>
<polygon id="252" class="fil87" points="3084.8,4657.84 3079.03,4645.29 5468.16,3548.24 5473.93,3560.79 "/>
<polygon id="253" class="fil88" points="3080.95,4649.47 3075.19,4636.92 5464.32,3539.87 5470.08,3552.42 "/>
<polygon id="254" class="fil89" points="3077.11,4641.11 3071.35,4628.55 5460.48,3531.5 5466.24,3544.05 "/>
<polygon id="255" class="fil90" points="3073.27,4632.74 3067.5,4620.18 5456.63,3523.13 5462.4,3535.68 "/>
<polygon id="256" class="fil91" points="3069.43,4624.37 3063.66,4611.82 5452.79,3514.76 5458.55,3527.31 "/>
<polygon id="257" class="fil92" points="3065.58,4616 3059.82,4603.45 5448.95,3506.39 5454.71,3518.95 "/>
<polygon id="258" class="fil92" points="3061.74,4607.63 3055.98,4595.08 5445.11,3498.02 5450.87,3510.58 "/>
<polygon id="259" class="fil93" points="3057.9,4599.26 3052.13,4586.71 5441.26,3489.66 5447.03,3502.21 "/>
<polygon id="260" class="fil94" points="3054.05,4590.9 3048.29,4578.34 5437.42,3481.29 5443.18,3493.84 "/>
<polygon id="261" class="fil95" points="3050.21,4582.53 3044.45,4569.97 5433.58,3472.92 5439.34,3485.47 "/>
<polygon id="262" class="fil96" points="3046.37,4574.16 3040.61,4561.61 5429.73,3464.55 5435.5,3477.1 "/>
<polygon id="263" class="fil96" points="3042.53,4565.79 3036.76,4553.24 5425.89,3456.18 5431.66,3468.73 "/>
<polygon id="264" class="fil97" points="3038.68,4557.42 3032.92,4544.87 5422.05,3447.81 5427.81,3460.37 "/>
<polygon id="265" class="fil97" points="3034.84,4549.05 3029.08,4536.5 5418.21,3439.45 5423.97,3452 "/>
<polygon id="266" class="fil98" points="3031,4540.68 3025.23,4528.13 5414.36,3431.08 5420.13,3443.63 "/>
<polygon id="267" class="fil99" points="3027.16,4532.32 3021.39,4519.76 5410.52,3422.71 5416.28,3435.26 "/>
<polygon id="268" class="fil100" points="3023.31,4523.95 3017.55,4511.39 5406.68,3414.34 5412.44,3426.89 "/>
<polygon id="269" class="fil101" points="3019.47,4515.58 3013.71,4503.03 5402.84,3405.97 5408.6,3418.52 "/>
<polygon id="270" class="fil102" points="3015.63,4507.21 3009.86,4494.66 5398.99,3397.6 5404.76,3410.16 "/>
<polygon id="271" class="fil102" points="3011.79,4498.84 3006.02,4486.29 5395.15,3389.23 5400.91,3401.79 "/>
<polygon id="272" class="fil103" points="3007.94,4490.47 3002.18,4477.92 5391.31,3380.87 5397.07,3393.42 "/>
<polygon id="273" class="fil103" points="3004.1,4482.1 2998.34,4469.55 5387.46,3372.5 5393.23,3385.05 "/>
<polygon id="274" class="fil104" points="3000.26,4473.74 2994.49,4461.18 5383.62,3364.13 5389.39,3376.68 "/>
<polygon id="275" class="fil105" points="2996.41,4465.37 2990.65,4452.81 5379.78,3355.76 5385.54,3368.31 "/>
<polygon id="276" class="fil106" points="2992.57,4457 2986.81,4444.45 5375.94,3347.39 5381.7,3359.94 "/>
<polygon id="277" class="fil107" points="2988.73,4448.63 2982.96,4436.08 5372.09,3339.02 5377.86,3351.58 "/>
<polygon id="278" class="fil108" points="2984.89,4440.26 2979.12,4427.71 5368.25,3330.65 5374.02,3343.21 "/>
<polygon id="279" class="fil109" points="2981.04,4431.89 2975.28,4419.34 5364.41,3322.29 5370.17,3334.84 "/>
<polygon id="280" class="fil110" points="2977.2,4423.53 2971.44,4410.97 5360.57,3313.92 5366.33,3326.47 "/>
<polygon id="281" class="fil111" points="2973.36,4415.16 2967.59,4402.6 5356.72,3305.55 5362.49,3318.1 "/>
<polygon id="282" class="fil111" points="2969.52,4406.79 2963.75,4394.24 5352.88,3297.18 5358.64,3309.73 "/>
<polygon id="283" class="fil112" points="2965.67,4398.42 2959.91,4385.87 5349.04,3288.81 5354.8,3301.36 "/>
<polygon id="284" class="fil112" points="2961.83,4390.05 2956.07,4377.5 5345.2,3280.44 5350.96,3293 "/>
<polygon id="285" class="fil113" points="2957.99,4381.68 2952.22,4369.13 5341.35,3272.08 5347.12,3284.63 "/>
<polygon id="286" class="fil113" points="2954.14,4373.31 2948.38,4360.76 5337.51,3263.71 5343.27,3276.26 "/>
<polygon id="287" class="fil114" points="2950.3,4364.95 2944.54,4352.39 5333.67,3255.34 5339.43,3267.89 "/>
<polygon id="288" class="fil115" points="2946.46,4356.58 2940.7,4344.02 5329.82,3246.97 5335.59,3259.52 "/>
<polygon id="289" class="fil116" points="2942.62,4348.21 2936.85,4335.66 5325.98,3238.6 5331.75,3251.15 "/>
<polygon id="290" class="fil117" points="2938.77,4339.84 2933.01,4327.29 5322.14,3230.23 5327.9,3242.79 "/>
<polygon id="291" class="fil118" points="2934.93,4331.47 2929.17,4318.92 5318.3,3221.86 5324.06,3234.42 "/>
<polygon id="292" class="fil118" points="2931.09,4323.1 2932.6,4326.39 5321.73,3229.34 5320.22,3226.05 "/>
</g>
</g>
<path class="fil119" d="M1339.29 5096.79l147.16 -132.24c331.13,-712.35 864.35,-1398.28 1665.1,-2049.16 533.28,-433.45 2271.3,2660.8 2175.74,2745.15 -1415.39,339.35 -2735.92,97.36 -3988,-563.75z"/>
<path class="fil120" d="M5777.71 5348.83l1969.84 2220.65c479.99,541.1 -404.26,1279.68 -856.98,769.31l-1969.83 -2220.66c-266.41,-300.32 569.96,-1092.85 856.97,-769.3z"/>
<path class="fil121" d="M3914.13 251.11c1823.36,0 3301.46,1478.1 3301.46,3301.46 0,1823.35 -1478.1,3301.46 -3301.46,3301.46 -1823.35,0 -3301.46,-1478.11 -3301.46,-3301.46 0,-1823.36 1478.11,-3301.46 3301.46,-3301.46zm0 1233.51c1142.11,0 2067.95,925.84 2067.95,2067.95 0,1142.1 -925.84,2067.94 -2067.95,2067.94 -1142.1,0 -2067.94,-925.84 -2067.94,-2067.94 0,-1142.11 925.84,-2067.95 2067.94,-2067.95z"/>
<path class="fil122" d="M5216.44 5089.76c-705.89,-446.6 -1224.17,-746.12 -2074.57,-200.94 -105.07,67.36 -339.17,246.82 -378.72,340.57 1315.26,-254.1 1488.29,846.64 2369.25,1306.63l175.15 82.52c2.14,1.03 5.14,2.45 7.28,3.48 2.13,1.02 5.16,2.42 7.29,3.44 191.64,92.05 571.91,156.13 782,138.63 292.82,-24.4 537.94,-70.37 803.82,-204.52 1278.38,-645.04 1437.6,-2188.86 503.59,-3180.72 -112.81,-119.83 -302.36,-249.02 -451.7,-328.53l-78.33 -40.45c-54.75,44.07 -331.37,352.18 -350.07,446.51 468.29,-198.36 -35.84,2442.68 -1314.99,1633.38z"/>
<path class="fil122" d="M6228.5 4045.78c0.78,53.81 -23.23,88.5 -46.67,141.03 -16.11,36.13 -12.77,29.87 -40.67,72.34 -132.98,202.44 -305.91,160.42 -494.69,182.97 -91.79,10.96 -158.44,-22.84 -213.41,-135.29 -138.4,-283.06 50.54,-483.16 286.65,-369.98 101.89,43.62 100.38,54 226.66,82.9l282.13 26.03z"/>
<path class="fil122" d="M5418.96 2298.56l-188.14 182.21 -225.43 236.76c531.39,179.74 805.77,453.61 1395.48,979.08 376.13,-340.71 826.26,-819.43 1384.13,-972.25 -96.28,-158.86 -236.47,-283.8 -400.75,-390.14 -21.71,-295.47 -93.01,-560.02 -202.94,-800.48 -210.83,155.54 -376.53,320.82 -496.06,496.07 -200.75,-39.41 -386.95,-31.78 -561.04,14.8 -117.53,-193.54 -294.47,-352.08 -496.07,-496.08 -138.4,234.36 -205.41,485.01 -209.18,750.03z"/>
<path class="fil123" d="M5296.62 2417.04l-65.8 63.73 -225.43 236.76c531.39,179.74 805.77,453.61 1395.48,979.08 192.15,-492.44 527.57,-929.99 1109.2,-1273.12 110.05,86.07 204.31,184.35 274.93,300.87 -557.87,152.82 -1008,631.54 -1384.13,972.25 -411.25,-601.43 -781.81,-1037.87 -1104.25,-1279.57z"/>
<path class="fil86" d="M6018.42 1885.17c-207.79,29.82 -420.94,313.33 -599.46,413.39 -7.67,-192.25 68.85,-593.17 211.14,-757.55 115.67,91.61 242.75,198.57 388.32,344.16z"/>
<path class="fil86" d="M7399.24 2344.03c-199.67,-64.85 -424.66,-438.85 -629,-427.72 106.24,-155.58 243.18,-274.57 411.07,-382.57 102.23,128.45 189.13,612.09 217.93,810.29z"/>
<circle class="fil124" cx="4355.68" cy="2693.31" r="315.68"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 40 KiB

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

@ -12,22 +12,22 @@
<context> <context>
<name>GraphicsView</name> <name>GraphicsView</name>
<message> <message>
<location filename="../graphicsview.cpp" line="239"/> <location filename="../graphicsview.cpp" line="247"/>
<source>File url list is empty</source> <source>File url list is empty</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="44"/> <location filename="../graphicsview.cpp" line="46"/>
<source>File is not a valid image</source> <source>File is not a valid image</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="247"/> <location filename="../graphicsview.cpp" line="255"/>
<source>Image data is invalid</source> <source>Image data is invalid</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="254"/> <location filename="../graphicsview.cpp" line="262"/>
<source>Not supported mimedata: %1</source> <source>Not supported mimedata: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -35,82 +35,120 @@
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../mainwindow.cpp" line="143"/> <location filename="../mainwindow.cpp" line="174"/>
<source>File url list is empty</source> <source>File url list is empty</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="322"/> <location filename="../mainwindow.cpp" line="396"/>
<source>&amp;Copy</source> <source>&amp;Copy</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="343"/> <location filename="../mainwindow.cpp" line="417"/>
<source>Copy P&amp;ixmap</source> <source>Copy P&amp;ixmap</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="348"/> <location filename="../mainwindow.cpp" line="422"/>
<source>Copy &amp;File Path</source> <source>Copy &amp;File Path</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="358"/> <location filename="../mainwindow.cpp" line="432"/>
<source>&amp;Paste Image</source> <source>&amp;Paste Image</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="363"/> <location filename="../mainwindow.cpp" line="438"/>
<source>&amp;Paste Image File</source> <source>&amp;Paste Image File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="368"/> <location filename="../mainwindow.cpp" line="443"/>
<location filename="../mainwindow.cpp" line="387"/> <location filename="../mainwindow.cpp" line="471"/>
<source>Stay on top</source> <source>Stay on top</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="374"/> <location filename="../mainwindow.cpp" line="450"/>
<location filename="../mainwindow.cpp" line="388"/> <location filename="../mainwindow.cpp" line="472"/>
<source>Protected mode</source> <source>Protected mode</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="380"/> <location filename="../mainwindow.cpp" line="457"/>
<source>Configure...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="464"/>
<source>Help</source> <source>Help</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="383"/> <location filename="../mainwindow.cpp" line="467"/>
<source>Launch application with image file path as argument to load the file.</source> <source>Launch application with image file path as argument to load the file.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="384"/> <location filename="../mainwindow.cpp" line="468"/>
<source>Drag and drop image file onto the window is also supported.</source> <source>Drag and drop image file onto the window is also supported.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="386"/> <location filename="../mainwindow.cpp" line="470"/>
<source>Context menu option explanation:</source> <source>Context menu option explanation:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="387"/> <location filename="../mainwindow.cpp" line="471"/>
<source>Make window stay on top of all other windows.</source> <source>Make window stay on top of all other windows.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="388"/> <location filename="../mainwindow.cpp" line="472"/>
<source>Avoid close window accidentally. (eg. by double clicking the window)</source> <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="18"/>
<source>Do nothing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="19"/>
<source>Close the window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="20"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="28"/>
<source>Stay on top when start-up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="29"/>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../main.cpp" line="24"/> <location filename="../main.cpp" line="27"/>
<source>Pineapple Pictures</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../main.cpp" line="31"/>
<source>File list.</source> <source>File list.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -12,22 +12,22 @@
<context> <context>
<name>GraphicsView</name> <name>GraphicsView</name>
<message> <message>
<location filename="../graphicsview.cpp" line="239"/> <location filename="../graphicsview.cpp" line="247"/>
<source>File url list is empty</source> <source>File url list is empty</source>
<translation> URL </translation> <translation> URL </translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="44"/> <location filename="../graphicsview.cpp" line="46"/>
<source>File is not a valid image</source> <source>File is not a valid image</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="247"/> <location filename="../graphicsview.cpp" line="255"/>
<source>Image data is invalid</source> <source>Image data is invalid</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="254"/> <location filename="../graphicsview.cpp" line="262"/>
<source>Not supported mimedata: %1</source> <source>Not supported mimedata: %1</source>
<translation> MimeData %1</translation> <translation> MimeData %1</translation>
</message> </message>
@ -35,12 +35,12 @@
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../mainwindow.cpp" line="143"/> <location filename="../mainwindow.cpp" line="174"/>
<source>File url list is empty</source> <source>File url list is empty</source>
<translation> URL </translation> <translation> URL </translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="322"/> <location filename="../mainwindow.cpp" line="396"/>
<source>&amp;Copy</source> <source>&amp;Copy</source>
<translation>(&amp;C)</translation> <translation>(&amp;C)</translation>
</message> </message>
@ -49,72 +49,110 @@
<translation type="vanished">(&amp;P)</translation> <translation type="vanished">(&amp;P)</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="343"/> <location filename="../mainwindow.cpp" line="417"/>
<source>Copy P&amp;ixmap</source> <source>Copy P&amp;ixmap</source>
<translation>(&amp;I)</translation> <translation>(&amp;I)</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="348"/> <location filename="../mainwindow.cpp" line="422"/>
<source>Copy &amp;File Path</source> <source>Copy &amp;File Path</source>
<translation>(&amp;F)</translation> <translation>(&amp;F)</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="358"/> <location filename="../mainwindow.cpp" line="432"/>
<source>&amp;Paste Image</source> <source>&amp;Paste Image</source>
<translation>(&amp;P)</translation> <translation>(&amp;P)</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="363"/> <location filename="../mainwindow.cpp" line="438"/>
<source>&amp;Paste Image File</source> <source>&amp;Paste Image File</source>
<translation>(&amp;P)</translation> <translation>(&amp;P)</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="368"/> <location filename="../mainwindow.cpp" line="443"/>
<location filename="../mainwindow.cpp" line="387"/> <location filename="../mainwindow.cpp" line="471"/>
<source>Stay on top</source> <source>Stay on top</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="374"/> <location filename="../mainwindow.cpp" line="450"/>
<location filename="../mainwindow.cpp" line="388"/> <location filename="../mainwindow.cpp" line="472"/>
<source>Protected mode</source> <source>Protected mode</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="380"/> <location filename="../mainwindow.cpp" line="457"/>
<source>Configure...</source>
<translation>...</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="464"/>
<source>Help</source> <source>Help</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="383"/> <location filename="../mainwindow.cpp" line="467"/>
<source>Launch application with image file path as argument to load the file.</source> <source>Launch application with image file path as argument to load the file.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="384"/> <location filename="../mainwindow.cpp" line="468"/>
<source>Drag and drop image file onto the window is also supported.</source> <source>Drag and drop image file onto the window is also supported.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="386"/> <location filename="../mainwindow.cpp" line="470"/>
<source>Context menu option explanation:</source> <source>Context menu option explanation:</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="387"/> <location filename="../mainwindow.cpp" line="471"/>
<source>Make window stay on top of all other windows.</source> <source>Make window stay on top of all other windows.</source>
<translation>使</translation> <translation>使</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="388"/> <location filename="../mainwindow.cpp" line="472"/>
<source>Avoid close window accidentally. (eg. by double clicking the window)</source> <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="18"/>
<source>Do nothing</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="19"/>
<source>Close the window</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="20"/>
<source>Toggle maximize</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="28"/>
<source>Stay on top when start-up</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="29"/>
<source>Double-click behavior</source>
<translation></translation>
</message>
</context>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../main.cpp" line="24"/> <location filename="../main.cpp" line="27"/>
<source>Pineapple Pictures</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="31"/>
<source>File list.</source> <source>File list.</source>
<translation></translation> <translation></translation>
</message> </message>

View File

@ -23,6 +23,8 @@ int main(int argc, char *argv[])
#endif #endif
translator.load(QString("PineapplePictures_%1").arg(QLocale::system().name()), qmDir); translator.load(QString("PineapplePictures_%1").arg(QLocale::system().name()), qmDir);
a.installTranslator(&translator); a.installTranslator(&translator);
a.setApplicationName("Pineapple Pictures");
a.setApplicationDisplayName(QCoreApplication::translate("main", "Pineapple Pictures"));
// parse commandline arguments // parse commandline arguments
QCommandLineParser parser; QCommandLineParser parser;
@ -35,6 +37,14 @@ int main(int argc, char *argv[])
QList<QUrl> urlList; QList<QUrl> urlList;
for (const QString & str : urlStrList) { for (const QString & str : urlStrList) {
QUrl url = QUrl::fromLocalFile(str); QUrl url = QUrl::fromLocalFile(str);
#ifdef Q_OS_WIN
// TODO: remove this workaround when M$ change the "wsl$" hostname.
if (Q_UNLIKELY(str.startsWith(R"(\\wsl$\)"))) {
url.clear();
url.setScheme(QStringLiteral("qtbug-86277"));
url.setPath(str);
}
#endif // Q_OS_WIN
if (url.isValid()) { if (url.isValid()) {
urlList.append(url); urlList.append(url);
} }

View File

@ -1,10 +1,12 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "settings.h"
#include "toolbutton.h" #include "toolbutton.h"
#include "bottombuttongroup.h" #include "bottombuttongroup.h"
#include "graphicsview.h" #include "graphicsview.h"
#include "navigatorview.h" #include "navigatorview.h"
#include "graphicsscene.h" #include "graphicsscene.h"
#include "settingsdialog.h"
#include <QMouseEvent> #include <QMouseEvent>
#include <QMovie> #include <QMovie>
@ -27,10 +29,16 @@
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent) QMainWindow(parent)
{ {
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); if (Settings::instance()->stayOnTop()) {
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowStaysOnTopHint);
} else {
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
}
this->setAttribute(Qt::WA_TranslucentBackground, true); this->setAttribute(Qt::WA_TranslucentBackground, true);
this->setMinimumSize(710, 530); this->setMinimumSize(350, 350);
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,25 +80,35 @@ 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,
this, [ = ](){ m_graphicsView->resetScale(); }); this, [ = ](){ m_graphicsView->resetScale(); });
connect(m_bottomButtonGroup, &BottomButtonGroup::toggleWindowMaximum, connect(m_bottomButtonGroup, &BottomButtonGroup::toggleWindowMaximum,
this, [ = ](){ this, &MainWindow::toggleMaximize);
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
});
connect(m_bottomButtonGroup, &BottomButtonGroup::zoomInBtnClicked, connect(m_bottomButtonGroup, &BottomButtonGroup::zoomInBtnClicked,
this, [ = ](){ m_graphicsView->zoomView(1.25); }); this, [ = ](){ m_graphicsView->zoomView(1.25); });
connect(m_bottomButtonGroup, &BottomButtonGroup::zoomOutBtnClicked, connect(m_bottomButtonGroup, &BottomButtonGroup::zoomOutBtnClicked,
@ -109,6 +127,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));
@ -165,11 +188,11 @@ void MainWindow::adjustWindowSizeBySceneRect()
QSize screenSize = qApp->screenAt(QCursor::pos())->availableSize(); QSize screenSize = qApp->screenAt(QCursor::pos())->availableSize();
if (screenSize.expandedTo(sceneSize) == screenSize) { if (screenSize.expandedTo(sceneSize) == screenSize) {
// we can show the picture by increase the window size. // we can show the picture by increase the window size.
if (screenSize.expandedTo(sceneSizeWithMargins) == screenSize) { QSize finalSize = (screenSize.expandedTo(sceneSizeWithMargins) == screenSize) ?
this->resize(sceneSizeWithMargins); sceneSizeWithMargins : screenSize;
} else { // We have a very reasonable sizeHint() value ;P
this->resize(screenSize); this->resize(finalSize.expandedTo(this->sizeHint()));
}
// We're sure the window can display the whole thing with 1:1 scale. // We're sure the window can display the whole thing with 1:1 scale.
// The old window size may cause fitInView call from resize() and the // The old window size may cause fitInView call from resize() and the
// above resize() call won't reset the scale back to 1:1, so we // above resize() call won't reset the scale back to 1:1, so we
@ -222,13 +245,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 +263,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 +272,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 +293,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 +305,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);
} }
@ -291,7 +326,7 @@ void MainWindow::mousePressEvent(QMouseEvent *event)
void MainWindow::mouseMoveEvent(QMouseEvent *event) void MainWindow::mouseMoveEvent(QMouseEvent *event)
{ {
if (event->buttons() & Qt::LeftButton && m_clickedOnWindow) { if (event->buttons() & Qt::LeftButton && m_clickedOnWindow && !isMaximized()) {
move(event->globalPos() - m_oldMousePos); move(event->globalPos() - m_oldMousePos);
event->accept(); event->accept();
} }
@ -308,17 +343,43 @@ void MainWindow::mouseReleaseEvent(QMouseEvent *event)
void MainWindow::mouseDoubleClickEvent(QMouseEvent *event) void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{ {
quitAppAction(); switch (Settings::instance()->doubleClickBehavior()) {
case ActionCloseWindow:
quitAppAction();
event->accept();
break;
case ActionMaximizeWindow:
toggleMaximize();
event->accept();
break;
case ActionDoNothing:
break;
}
return QMainWindow::mouseDoubleClickEvent(event); // blumia: don't call parent constructor here, seems it will cause mouse move
// event get called even if we set event->accept();
// return QMainWindow::mouseDoubleClickEvent(event);
} }
void MainWindow::wheelEvent(QWheelEvent *event) void MainWindow::wheelEvent(QWheelEvent *event)
{ {
if (event->delta() > 0) { QPoint numDegrees = event->angleDelta() / 8;
m_graphicsView->zoomView(1.25); bool needZoom = false, zoomIn = false;
// NOTE: Only checking angleDelta since the QWheelEvent::pixelDelta() doc says
// pixelDelta() value is driver specific and unreliable on X11...
// We are not scrolling the canvas, just zoom in or out, so it probably
// doesn't matter here.
if (!numDegrees.isNull() && numDegrees.y() != 0) {
needZoom = true;
zoomIn = numDegrees.y() > 0;
}
if (needZoom) {
m_graphicsView->zoomView(zoomIn ? 1.25 : 0.8);
event->accept();
} else { } else {
m_graphicsView->zoomView(0.8); QMainWindow::wheelEvent(event);
} }
} }
@ -385,12 +446,21 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
}); });
stayOnTopMode->setCheckable(true); stayOnTopMode->setCheckable(true);
stayOnTopMode->setChecked(stayOnTop()); stayOnTopMode->setChecked(stayOnTop());
QAction * protectedMode = new QAction(tr("Protected mode")); QAction * protectedMode = new QAction(tr("Protected mode"));
connect(protectedMode, &QAction::triggered, this, [ = ](){ connect(protectedMode, &QAction::triggered, this, [ = ](){
toggleProtectedMode(); toggleProtectedMode();
}); });
protectedMode->setCheckable(true); protectedMode->setCheckable(true);
protectedMode->setChecked(m_protectedMode); protectedMode->setChecked(m_protectedMode);
QAction * toggleSettings = new QAction(tr("Configure..."));
connect(toggleSettings, &QAction::triggered, this, [ = ](){
SettingsDialog * sd = new SettingsDialog(this);
sd->exec();
sd->deleteLater();
});
QAction * helpAction = new QAction(tr("Help")); QAction * helpAction = new QAction(tr("Help"));
connect(helpAction, &QAction::triggered, this, [ = ](){ connect(helpAction, &QAction::triggered, this, [ = ](){
QStringList sl { QStringList sl {
@ -418,6 +488,7 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
menu->addAction(stayOnTopMode); menu->addAction(stayOnTopMode);
menu->addAction(protectedMode); menu->addAction(protectedMode);
menu->addSeparator(); menu->addSeparator();
menu->addAction(toggleSettings);
menu->addAction(helpAction); menu->addAction(helpAction);
menu->exec(mapToGlobal(event->pos())); menu->exec(mapToGlobal(event->pos()));
menu->deleteLater(); menu->deleteLater();
@ -512,6 +583,11 @@ bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *r
#endif // _WIN32 #endif // _WIN32
} }
QSize MainWindow::sizeHint() const
{
return QSize(710, 530);
}
void MainWindow::centerWindow() void MainWindow::centerWindow()
{ {
this->setGeometry( this->setGeometry(
@ -537,6 +613,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 +625,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()
@ -574,3 +655,12 @@ void MainWindow::toggleFullscreen()
showFullScreen(); showFullScreen();
} }
} }
void MainWindow::toggleMaximize()
{
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
}

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;
@ -46,6 +50,8 @@ protected slots:
bool nativeEvent(const QByteArray& eventType, void* message, long* result) override; bool nativeEvent(const QByteArray& eventType, void* message, long* result) override;
QSize sizeHint() const override;
void centerWindow(); void centerWindow();
void closeWindow(); void closeWindow();
void updateWidgetsPosition(); void updateWidgetsPosition();
@ -54,6 +60,7 @@ protected slots:
bool stayOnTop(); bool stayOnTop();
void quitAppAction(bool force = false); void quitAppAction(bool force = false);
void toggleFullscreen(); void toggleFullscreen();
void toggleMaximize();
private: private:
QPoint m_oldMousePos; QPoint m_oldMousePos;
@ -61,6 +68,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

@ -1,12 +1,15 @@
[Desktop Entry] [Desktop Entry]
Categories=Graphics; Categories=Graphics;
Comment=Pineapple Pictures Image Viewer. Comment=Pineapple Pictures is a lightweight image viewer
Comment[zh_CN]=菠萝看图是一个轻量级的图像查看器
Exec=ppic %F Exec=ppic %F
GenericName=Pictures GenericName=Image Viewer
GenericName[zh_CN]=图像查看器
Icon=pineapple-pictures Icon=pineapple-pictures
Keywords=Picture;Image;Viewer;Jpg;Jpeg;Png; Keywords=Picture;Image;Viewer;Jpg;Jpeg;Png;
MimeType=image/bmp;image/bmp24;image/jpg;image/jpe;image/jpeg;image/jpeg24;image/jng;image/pcd;image/pcx;image/png;image/tif;image/tiff;image/tiff24;image/dds;image/gif;image/sgi;image/j2k;image/jp2;image/pct;image/wdp;image/arw;image/icb;image/dng;image/vda;image/vst;image/svg;image/ptif;image/mef;image/xbm;image/svg+xml; MimeType=image/bmp;image/bmp24;image/jpg;image/jpe;image/jpeg;image/jpeg24;image/jng;image/pcd;image/pcx;image/png;image/tif;image/tiff;image/tiff24;image/dds;image/gif;image/sgi;image/j2k;image/jp2;image/pct;image/wdp;image/arw;image/icb;image/dng;image/vda;image/vst;image/svg;image/ptif;image/mef;image/xbm;image/svg+xml;
Name=Pineapple Pictures Name=Pineapple Pictures
Name[zh_CN]=菠萝看图
StartupNotify=false StartupNotify=false
Type=Application Type=Application
Terminal=false Terminal=false

View File

@ -1 +1,17 @@
IDI_ICON1 ICON DISCARDABLE "icons/app-icon.ico" IDI_ICON1 ICON DISCARDABLE "icons/app-icon.ico"
1 VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription", "Pineapple Pictures - Image Viewer"
VALUE "LegalCopyright", "MIT/Expat License - Copyright (C) 2020 Gary Wang"
VALUE "ProductName", "Pineapple Pictures"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

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>

86
settings.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "settings.h"
#include <QApplication>
#include <QStandardPaths>
#include <QDebug>
#include <QDir>
Settings *Settings::m_settings_instance = nullptr;
Settings *Settings::instance()
{
if (!m_settings_instance) {
m_settings_instance = new Settings;
}
return m_settings_instance;
}
bool Settings::stayOnTop()
{
return m_qsettings->value("stay_on_top", true).toBool();
}
DoubleClickBehavior Settings::doubleClickBehavior()
{
QString result = m_qsettings->value("double_click_behavior", "close").toString().toLower();
return stringToDoubleClickBehavior(result);
}
void Settings::setStayOnTop(bool on)
{
m_qsettings->setValue("stay_on_top", on);
m_qsettings->sync();
}
void Settings::setDoubleClickBehavior(DoubleClickBehavior dcb)
{
m_qsettings->setValue("double_click_behavior", doubleClickBehaviorToString(dcb));
m_qsettings->sync();
}
QString Settings::doubleClickBehaviorToString(DoubleClickBehavior dcb)
{
static QMap<DoubleClickBehavior, QString> _map {
{ActionCloseWindow, "close"},
{ActionMaximizeWindow, "maximize"},
{ActionDoNothing, "ignore"}
};
return _map.value(dcb, "close");
}
DoubleClickBehavior Settings::stringToDoubleClickBehavior(QString str)
{
static QMap<QString, DoubleClickBehavior> _map {
{"close", ActionCloseWindow},
{"maximize", ActionMaximizeWindow},
{"ignore", ActionDoNothing}
};
return _map.value(str, ActionCloseWindow);
}
Settings::Settings()
: QObject(qApp)
{
QString configPath;
#ifdef FLAG_PORTABLE_MODE_SUPPORT
QString portableConfigDirPath = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("data");
QFileInfo portableConfigDirInfo(portableConfigDirPath);
if (portableConfigDirInfo.exists() && portableConfigDirInfo.isDir() && portableConfigDirInfo.isWritable()) {
// we can use it.
configPath = portableConfigDirPath;
}
#endif // FLAG_PORTABLE_MODE_SUPPORT
// %LOCALAPPDATA% under Windows.
if (configPath.isEmpty()) {
configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
}
m_qsettings = new QSettings(QDir(configPath).absoluteFilePath("config.ini"), QSettings::IniFormat, this);
}

41
settings.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include <QObject>
#include <QSettings>
enum DoubleClickBehavior {
ActionDoNothing,
ActionCloseWindow,
ActionMaximizeWindow,
ActionStart = ActionDoNothing,
ActionEnd = ActionMaximizeWindow
};
class Settings : public QObject
{
Q_OBJECT
public:
static Settings *instance();
bool stayOnTop();
DoubleClickBehavior doubleClickBehavior();
void setStayOnTop(bool on);
void setDoubleClickBehavior(DoubleClickBehavior dcb);
static QString doubleClickBehaviorToString(DoubleClickBehavior dcb);
static DoubleClickBehavior stringToDoubleClickBehavior(QString str);
private:
Settings();
static Settings *m_settings_instance;
QSettings *m_qsettings;
signals:
public slots:
};

51
settingsdialog.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "settingsdialog.h"
#include "settings.h"
#include <QCheckBox>
#include <QComboBox>
#include <QFormLayout>
#include <QStringListModel>
SettingsDialog::SettingsDialog(QWidget *parent)
: QDialog(parent)
, m_stayOnTop(new QCheckBox)
, m_doubleClickBehavior(new QComboBox)
{
QFormLayout * settingsForm = new QFormLayout(this);
static QMap<DoubleClickBehavior, QString> _map {
{ ActionDoNothing, tr("Do nothing") },
{ ActionCloseWindow, tr("Close the window") },
{ ActionMaximizeWindow, tr("Toggle maximize") }
};
QStringList dropDown;
for (int dcb = ActionStart; dcb <= ActionEnd; dcb++) {
dropDown.append(_map.value(static_cast<DoubleClickBehavior>(dcb)));
}
settingsForm->addRow(tr("Stay on top when start-up"), m_stayOnTop);
settingsForm->addRow(tr("Double-click behavior"), m_doubleClickBehavior);
m_stayOnTop->setChecked(Settings::instance()->stayOnTop());
m_doubleClickBehavior->setModel(new QStringListModel(dropDown));
DoubleClickBehavior dcb = Settings::instance()->doubleClickBehavior();
m_doubleClickBehavior->setCurrentIndex(static_cast<int>(dcb));
connect(m_stayOnTop, &QCheckBox::stateChanged, this, [ = ](int state){
Settings::instance()->setStayOnTop(state == Qt::Checked);
});
connect(m_doubleClickBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setDoubleClickBehavior(static_cast<DoubleClickBehavior>(index));
});
this->setMinimumSize(300, 61); // not sure why it complain "Unable to set geometry"
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
}
SettingsDialog::~SettingsDialog()
{
}

26
settingsdialog.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include <QObject>
#include <QWidget>
#include <QDialog>
class QCheckBox;
class QComboBox;
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget *parent = nullptr);
~SettingsDialog();
signals:
public slots:
private:
QCheckBox * m_stayOnTop = nullptr;
QComboBox * m_doubleClickBehavior = nullptr;
};
#endif // SETTINGSDIALOG_H

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);