Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
90d0869b5e | |||
7004e74165 | |||
a2adb0e1d4 | |||
6709c21d70 | |||
31fae2cc8c | |||
20be5e6f4f | |||
6009c2682e |
@ -19,6 +19,8 @@ set (PPIC_CPP_FILES
|
||||
navigatorview.cpp
|
||||
opacityhelper.cpp
|
||||
toolbutton.cpp
|
||||
settings.cpp
|
||||
settingsdialog.cpp
|
||||
)
|
||||
|
||||
set (PPIC_HEADER_FILES
|
||||
@ -29,6 +31,8 @@ set (PPIC_HEADER_FILES
|
||||
navigatorview.h
|
||||
opacityhelper.h
|
||||
toolbutton.h
|
||||
settings.h
|
||||
settingsdialog.h
|
||||
)
|
||||
|
||||
set (PPIC_QRC_FILES
|
||||
|
@ -32,7 +32,9 @@ SOURCES += \
|
||||
graphicsscene.cpp \
|
||||
navigatorview.cpp \
|
||||
opacityhelper.cpp \
|
||||
toolbutton.cpp
|
||||
toolbutton.cpp \
|
||||
settings.cpp \
|
||||
settingsdialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@ -41,7 +43,9 @@ HEADERS += \
|
||||
graphicsscene.h \
|
||||
navigatorview.h \
|
||||
opacityhelper.h \
|
||||
toolbutton.h
|
||||
toolbutton.h \
|
||||
settings.h \
|
||||
settingsdialog.h
|
||||
|
||||
TRANSLATIONS = \
|
||||
languages/PineapplePictures.ts \
|
||||
@ -56,5 +60,5 @@ RESOURCES += \
|
||||
resources.qrc
|
||||
|
||||
# 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
|
||||
|
@ -3,14 +3,14 @@ Yet another image viewer.
|
||||
|CI|Build Status|
|
||||
|---|---|
|
||||
|Windows Build|[](https://ci.appveyor.com/project/BLumia/pineapplepictures/branch/master)|
|
||||
|macOS Build||
|
||||
|Ubuntu 20.04 Build||
|
||||
|macOS Build||
|
||||
|Ubuntu 20.04 Build||
|
||||
|
||||

|
||||
|
||||
## 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/)
|
||||
|
||||
## Help Translation!
|
||||
|
19
appveyor.yml
19
appveyor.yml
@ -1,5 +1,6 @@
|
||||
environment:
|
||||
CMAKE_INSTALL_ROOT: C:\projects\cmake
|
||||
ZLIB_ROOT: C:\projects\zlib
|
||||
matrix:
|
||||
- build_name: mingw73_32_qt5_12_6
|
||||
QTPATH: C:\Qt\5.12.6\mingw73_32
|
||||
@ -7,6 +8,7 @@ environment:
|
||||
|
||||
install:
|
||||
- mkdir %CMAKE_INSTALL_ROOT%
|
||||
- mkdir %ZLIB_ROOT%
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- git submodule update --init --recursive
|
||||
- set PATH=%PATH%;%CMAKE_INSTALL_ROOT%;%QTPATH%\bin;%MINGW32%\bin
|
||||
@ -23,6 +25,22 @@ build_script:
|
||||
- cmake --build .
|
||||
- cmake --build . --target install
|
||||
- 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
|
||||
- cd 3rdparty
|
||||
- git clone -q https://invent.kde.org/frameworks/kimageformats.git
|
||||
@ -41,6 +59,7 @@ build_script:
|
||||
- mingw32-make install
|
||||
# fixme: I don't know how to NOT make the binary installed to the ./bin/ folder...
|
||||
- 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
|
||||
# for debug..
|
||||
- tree /f
|
||||
|
@ -142,12 +142,16 @@ void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadio
|
||||
applyTransformationModeByScaleFactor();
|
||||
}
|
||||
|
||||
void GraphicsView::checkAndDoFitInView()
|
||||
void GraphicsView::checkAndDoFitInView(bool markItOnAnyway)
|
||||
{
|
||||
if (!isThingSmallerThanWindowWith(transform())) {
|
||||
m_enableFitInView = true;
|
||||
fitInView(sceneRect(), Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
if (markItOnAnyway) {
|
||||
m_enableFitInView = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsView::toggleCheckerboard()
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
void rotateView(qreal rotateAngel);
|
||||
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio);
|
||||
|
||||
void checkAndDoFitInView();
|
||||
void checkAndDoFitInView(bool markItOnAnyway = true);
|
||||
|
||||
signals:
|
||||
void navigatorViewRequired(bool required, qreal angle);
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 212 KiB |
@ -12,7 +12,7 @@
|
||||
<context>
|
||||
<name>GraphicsView</name>
|
||||
<message>
|
||||
<location filename="../graphicsview.cpp" line="243"/>
|
||||
<location filename="../graphicsview.cpp" line="247"/>
|
||||
<source>File url list is empty</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -22,12 +22,12 @@
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsview.cpp" line="251"/>
|
||||
<location filename="../graphicsview.cpp" line="255"/>
|
||||
<source>Image data is invalid</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsview.cpp" line="258"/>
|
||||
<location filename="../graphicsview.cpp" line="262"/>
|
||||
<source>Not supported mimedata: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -35,78 +35,111 @@
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="173"/>
|
||||
<location filename="../mainwindow.cpp" line="174"/>
|
||||
<source>File url list is empty</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="382"/>
|
||||
<location filename="../mainwindow.cpp" line="396"/>
|
||||
<source>&Copy</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="403"/>
|
||||
<location filename="../mainwindow.cpp" line="417"/>
|
||||
<source>Copy P&ixmap</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="408"/>
|
||||
<location filename="../mainwindow.cpp" line="422"/>
|
||||
<source>Copy &File Path</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="418"/>
|
||||
<location filename="../mainwindow.cpp" line="432"/>
|
||||
<source>&Paste Image</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="424"/>
|
||||
<location filename="../mainwindow.cpp" line="438"/>
|
||||
<source>&Paste Image File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="429"/>
|
||||
<location filename="../mainwindow.cpp" line="448"/>
|
||||
<location filename="../mainwindow.cpp" line="443"/>
|
||||
<location filename="../mainwindow.cpp" line="471"/>
|
||||
<source>Stay on top</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="435"/>
|
||||
<location filename="../mainwindow.cpp" line="449"/>
|
||||
<location filename="../mainwindow.cpp" line="450"/>
|
||||
<location filename="../mainwindow.cpp" line="472"/>
|
||||
<source>Protected mode</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="447"/>
|
||||
<location filename="../mainwindow.cpp" line="470"/>
|
||||
<source>Context menu option explanation:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>main</name>
|
||||
<message>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<context>
|
||||
<name>GraphicsView</name>
|
||||
<message>
|
||||
<location filename="../graphicsview.cpp" line="243"/>
|
||||
<location filename="../graphicsview.cpp" line="247"/>
|
||||
<source>File url list is empty</source>
|
||||
<translation>文件 URL 列表为空</translation>
|
||||
</message>
|
||||
@ -22,12 +22,12 @@
|
||||
<translation>文件不是有效的图片文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsview.cpp" line="251"/>
|
||||
<location filename="../graphicsview.cpp" line="255"/>
|
||||
<source>Image data is invalid</source>
|
||||
<translation>图片数据无效</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsview.cpp" line="258"/>
|
||||
<location filename="../graphicsview.cpp" line="262"/>
|
||||
<source>Not supported mimedata: %1</source>
|
||||
<translation>不受支持的 MimeData 格式:%1</translation>
|
||||
</message>
|
||||
@ -35,12 +35,12 @@
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="173"/>
|
||||
<location filename="../mainwindow.cpp" line="174"/>
|
||||
<source>File url list is empty</source>
|
||||
<translation>文件 URL 列表为空</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="382"/>
|
||||
<location filename="../mainwindow.cpp" line="396"/>
|
||||
<source>&Copy</source>
|
||||
<translation>复制(&C)</translation>
|
||||
</message>
|
||||
@ -49,68 +49,101 @@
|
||||
<translation type="vanished">复制位图(&P)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="403"/>
|
||||
<location filename="../mainwindow.cpp" line="417"/>
|
||||
<source>Copy P&ixmap</source>
|
||||
<translation>复制位图(&I)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="408"/>
|
||||
<location filename="../mainwindow.cpp" line="422"/>
|
||||
<source>Copy &File Path</source>
|
||||
<translation>复制文件路径(&F)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="418"/>
|
||||
<location filename="../mainwindow.cpp" line="432"/>
|
||||
<source>&Paste Image</source>
|
||||
<translation>粘贴图像(&P)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="424"/>
|
||||
<location filename="../mainwindow.cpp" line="438"/>
|
||||
<source>&Paste Image File</source>
|
||||
<translation>粘贴图像文件(&P)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="429"/>
|
||||
<location filename="../mainwindow.cpp" line="448"/>
|
||||
<location filename="../mainwindow.cpp" line="443"/>
|
||||
<location filename="../mainwindow.cpp" line="471"/>
|
||||
<source>Stay on top</source>
|
||||
<translation>总在最前</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="435"/>
|
||||
<location filename="../mainwindow.cpp" line="449"/>
|
||||
<location filename="../mainwindow.cpp" line="450"/>
|
||||
<location filename="../mainwindow.cpp" line="472"/>
|
||||
<source>Protected mode</source>
|
||||
<translation>保护模式</translation>
|
||||
</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>
|
||||
<translation>帮助</translation>
|
||||
</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>
|
||||
<translation>以图片文件的路径作为参数运行程序即可直接打开图片文件。</translation>
|
||||
</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>
|
||||
<translation>也支持拖放图片文件到窗口内来加载图片。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.cpp" line="447"/>
|
||||
<location filename="../mainwindow.cpp" line="470"/>
|
||||
<source>Context menu option explanation:</source>
|
||||
<translation>菜单项说明:</translation>
|
||||
</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>
|
||||
<translation>使窗口始终至于其它非置顶窗口上方。</translation>
|
||||
</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>
|
||||
<translation>避免窗口意外关闭。(如:不小心双击了窗口触发了关闭窗口行为)</translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>main</name>
|
||||
<message>
|
||||
|
@ -1,10 +1,12 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "toolbutton.h"
|
||||
#include "bottombuttongroup.h"
|
||||
#include "graphicsview.h"
|
||||
#include "navigatorview.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "settingsdialog.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QMovie>
|
||||
@ -27,9 +29,14 @@
|
||||
MainWindow::MainWindow(QWidget *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->setMinimumSize(710, 530);
|
||||
this->setMinimumSize(350, 350);
|
||||
this->setWindowIcon(QIcon(":/icons/app-icon.svg"));
|
||||
this->setMouseTracking(true);
|
||||
|
||||
@ -101,13 +108,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(m_bottomButtonGroup, &BottomButtonGroup::resetToOriginalBtnClicked,
|
||||
this, [ = ](){ m_graphicsView->resetScale(); });
|
||||
connect(m_bottomButtonGroup, &BottomButtonGroup::toggleWindowMaximum,
|
||||
this, [ = ](){
|
||||
if (isMaximized()) {
|
||||
showNormal();
|
||||
} else {
|
||||
showMaximized();
|
||||
}
|
||||
});
|
||||
this, &MainWindow::toggleMaximize);
|
||||
connect(m_bottomButtonGroup, &BottomButtonGroup::zoomInBtnClicked,
|
||||
this, [ = ](){ m_graphicsView->zoomView(1.25); });
|
||||
connect(m_bottomButtonGroup, &BottomButtonGroup::zoomOutBtnClicked,
|
||||
@ -187,11 +188,11 @@ void MainWindow::adjustWindowSizeBySceneRect()
|
||||
QSize screenSize = qApp->screenAt(QCursor::pos())->availableSize();
|
||||
if (screenSize.expandedTo(sceneSize) == screenSize) {
|
||||
// we can show the picture by increase the window size.
|
||||
if (screenSize.expandedTo(sceneSizeWithMargins) == screenSize) {
|
||||
this->resize(sceneSizeWithMargins);
|
||||
} else {
|
||||
this->resize(screenSize);
|
||||
}
|
||||
QSize finalSize = (screenSize.expandedTo(sceneSizeWithMargins) == screenSize) ?
|
||||
sceneSizeWithMargins : screenSize;
|
||||
// We have a very reasonable sizeHint() value ;P
|
||||
this->resize(finalSize.expandedTo(this->sizeHint()));
|
||||
|
||||
// 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
|
||||
// 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)
|
||||
{
|
||||
if (event->buttons() & Qt::LeftButton && m_clickedOnWindow) {
|
||||
if (event->buttons() & Qt::LeftButton && m_clickedOnWindow && !isMaximized()) {
|
||||
move(event->globalPos() - m_oldMousePos);
|
||||
event->accept();
|
||||
}
|
||||
@ -342,9 +343,22 @@ void MainWindow::mouseReleaseEvent(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)
|
||||
@ -432,12 +446,21 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
||||
});
|
||||
stayOnTopMode->setCheckable(true);
|
||||
stayOnTopMode->setChecked(stayOnTop());
|
||||
|
||||
QAction * protectedMode = new QAction(tr("Protected mode"));
|
||||
connect(protectedMode, &QAction::triggered, this, [ = ](){
|
||||
toggleProtectedMode();
|
||||
});
|
||||
protectedMode->setCheckable(true);
|
||||
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"));
|
||||
connect(helpAction, &QAction::triggered, this, [ = ](){
|
||||
QStringList sl {
|
||||
@ -465,6 +488,7 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
||||
menu->addAction(stayOnTopMode);
|
||||
menu->addAction(protectedMode);
|
||||
menu->addSeparator();
|
||||
menu->addAction(toggleSettings);
|
||||
menu->addAction(helpAction);
|
||||
menu->exec(mapToGlobal(event->pos()));
|
||||
menu->deleteLater();
|
||||
@ -559,6 +583,11 @@ bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *r
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
QSize MainWindow::sizeHint() const
|
||||
{
|
||||
return QSize(710, 530);
|
||||
}
|
||||
|
||||
void MainWindow::centerWindow()
|
||||
{
|
||||
this->setGeometry(
|
||||
@ -626,3 +655,12 @@ void MainWindow::toggleFullscreen()
|
||||
showFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::toggleMaximize()
|
||||
{
|
||||
if (isMaximized()) {
|
||||
showNormal();
|
||||
} else {
|
||||
showMaximized();
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ protected slots:
|
||||
|
||||
bool nativeEvent(const QByteArray& eventType, void* message, long* result) override;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
void centerWindow();
|
||||
void closeWindow();
|
||||
void updateWidgetsPosition();
|
||||
@ -58,6 +60,7 @@ protected slots:
|
||||
bool stayOnTop();
|
||||
void quitAppAction(bool force = false);
|
||||
void toggleFullscreen();
|
||||
void toggleMaximize();
|
||||
|
||||
private:
|
||||
QPoint m_oldMousePos;
|
||||
|
84
settings.cpp
Normal file
84
settings.cpp
Normal 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
41
settings.h
Normal 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
50
settingsdialog.cpp
Normal 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
26
settingsdialog.h
Normal 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
|
Reference in New Issue
Block a user