7 Commits
0.2.3 ... 0.3.0

15 changed files with 402 additions and 63 deletions

View File

@ -19,6 +19,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 +31,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

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 \
@ -56,5 +60,5 @@ RESOURCES += \
resources.qrc resources.qrc
# Generate fron svg: # Generate fron 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,14 +3,14 @@ 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/PineapplePictures/workflows/macOS%20CI/badge.svg)| |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/PineapplePictures/workflows/Ubuntu%2020.04%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/)
## Help Translation! ## Help Translation!

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
@ -23,6 +25,22 @@ build_script:
- 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 -q https://invent.kde.org/frameworks/kimageformats.git - git clone -q https://invent.kde.org/frameworks/kimageformats.git
@ -41,6 +59,7 @@ 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 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

@ -142,12 +142,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()

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: 97 KiB

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -12,7 +12,7 @@
<context> <context>
<name>GraphicsView</name> <name>GraphicsView</name>
<message> <message>
<location filename="../graphicsview.cpp" line="243"/> <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>
@ -22,12 +22,12 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="251"/> <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="258"/> <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,78 +35,111 @@
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
<message> <message>
<location filename="../mainwindow.cpp" line="173"/> <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="382"/> <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="403"/> <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="408"/> <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="418"/> <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="424"/> <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="429"/> <location filename="../mainwindow.cpp" line="443"/>
<location filename="../mainwindow.cpp" line="448"/> <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="435"/> <location filename="../mainwindow.cpp" line="450"/>
<location filename="../mainwindow.cpp" line="449"/> <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="441"/> <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="444"/> <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="445"/> <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="447"/> <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="448"/> <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="449"/> <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>

View File

@ -12,7 +12,7 @@
<context> <context>
<name>GraphicsView</name> <name>GraphicsView</name>
<message> <message>
<location filename="../graphicsview.cpp" line="243"/> <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>
@ -22,12 +22,12 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../graphicsview.cpp" line="251"/> <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="258"/> <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="173"/> <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="382"/> <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,68 +49,101 @@
<translation type="vanished">(&amp;P)</translation> <translation type="vanished">(&amp;P)</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.cpp" line="403"/> <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="408"/> <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="418"/> <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="424"/> <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="429"/> <location filename="../mainwindow.cpp" line="443"/>
<location filename="../mainwindow.cpp" line="448"/> <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="435"/> <location filename="../mainwindow.cpp" line="450"/>
<location filename="../mainwindow.cpp" line="449"/> <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="441"/> <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="444"/> <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="445"/> <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="447"/> <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="448"/> <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="449"/> <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>

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,9 +29,14 @@
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::WindowStaysOnTopHint);
} else {
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
}
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); this->setMouseTracking(true);
@ -101,13 +108,7 @@ MainWindow::MainWindow(QWidget *parent) :
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,
@ -187,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
@ -325,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();
} }
@ -342,9 +343,22 @@ 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)
@ -432,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 {
@ -465,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();
@ -559,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(
@ -626,3 +655,12 @@ void MainWindow::toggleFullscreen()
showFullScreen(); showFullScreen();
} }
} }
void MainWindow::toggleMaximize()
{
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
}

View File

@ -50,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();
@ -58,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;

84
settings.cpp Normal file
View File

@ -0,0 +1,84 @@
#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;
QString portableConfigDirPath = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("data");
QFileInfo portableConfigDirInfo(portableConfigDirPath);
if (portableConfigDirInfo.exists() && portableConfigDirInfo.isDir() && portableConfigDirInfo.isWritable()) {
// we can use it.
configPath = portableConfigDirPath;
}
// %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:
};

50
settingsdialog.cpp Normal file
View File

@ -0,0 +1,50 @@
#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"
}
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