diff --git a/src/core/notebookmgr.cpp b/src/core/notebookmgr.cpp index d6e1243c..bf301dab 100644 --- a/src/core/notebookmgr.cpp +++ b/src/core/notebookmgr.cpp @@ -21,6 +21,12 @@ NotebookMgr::NotebookMgr(QObject *p_parent) { } +void NotebookMgr::close() +{ + m_notebooks.clear(); + m_currentNotebookId = -1; +} + void NotebookMgr::init() { initVersionControllerServer(); diff --git a/src/core/notebookmgr.h b/src/core/notebookmgr.h index bbb2f202..77186dc4 100644 --- a/src/core/notebookmgr.h +++ b/src/core/notebookmgr.h @@ -32,6 +32,8 @@ namespace vnotex void init(); + void close(); + QSharedPointer getBundleNotebookFactory() const; QList> getAllNotebookFactories() const; diff --git a/src/widgets/framelessmainwindow/framelessmainwindow.cpp b/src/widgets/framelessmainwindow/framelessmainwindow.cpp index b1d07dd0..ac81806a 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindow.cpp +++ b/src/widgets/framelessmainwindow/framelessmainwindow.cpp @@ -10,8 +10,6 @@ FramelessMainWindow::FramelessMainWindow(bool p_frameless, QWidget *p_parent) m_defaultFlags(windowFlags()) { if (m_frameless) { - m_resizeAreaWidth *= devicePixelRatio(); - setWindowFlags(m_defaultFlags | Qt::FramelessWindowHint); } } @@ -27,7 +25,6 @@ void FramelessMainWindow::setTitleBar(QWidget *p_titleBar) Q_ASSERT(!m_titleBar && m_frameless); m_titleBar = p_titleBar; - m_titleBar->installEventFilter(this); } void FramelessMainWindow::changeEvent(QEvent *p_event) @@ -36,7 +33,8 @@ void FramelessMainWindow::changeEvent(QEvent *p_event) if (p_event->type() == QEvent::WindowStateChange) { m_windowStates = windowState(); - m_resizable = m_movable = m_windowStates == Qt::WindowNoState; + m_resizable = m_windowStates == Qt::WindowNoState; + m_movable = m_windowStates == Qt::WindowNoState; emit windowStateChanged(m_windowStates); } } diff --git a/src/widgets/framelessmainwindow/framelessmainwindow.h b/src/widgets/framelessmainwindow/framelessmainwindow.h index 0a8ad5e4..aa48edd1 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindow.h +++ b/src/widgets/framelessmainwindow/framelessmainwindow.h @@ -13,11 +13,11 @@ namespace vnotex { Q_OBJECT public: - FramelessMainWindow(bool p_frameless, QWidget *p_parent); + FramelessMainWindow(bool p_frameless, QWidget *p_parent = nullptr); bool isFrameless() const; - void setTitleBar(QWidget *p_titleBar); + virtual void setTitleBar(QWidget *p_titleBar); signals: void windowStateChanged(Qt::WindowStates p_state); @@ -30,8 +30,6 @@ namespace vnotex const bool m_frameless = true; - int m_resizeAreaWidth = 5; - bool m_movable = true; bool m_resizable = true; diff --git a/src/widgets/framelessmainwindow/framelessmainwindowimpl.h b/src/widgets/framelessmainwindow/framelessmainwindowimpl.h index 93ad51b7..21075984 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowimpl.h +++ b/src/widgets/framelessmainwindow/framelessmainwindowimpl.h @@ -2,13 +2,14 @@ #define FRAMELESSMAINWINDOWIMPL_H #include "framelessmainwindowwin.h" +#include "framelessmainwindowlinux.h" namespace vnotex { #ifdef Q_OS_WIN typedef FramelessMainWindowWin FramelessMainWindowImpl; #else - typedef FramelessMainWindow FramelessMainWindowImpl; + typedef FramelessMainWindowLinux FramelessMainWindowImpl; #endif } diff --git a/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp b/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp new file mode 100644 index 00000000..17a06a6f --- /dev/null +++ b/src/widgets/framelessmainwindow/framelessmainwindowlinux.cpp @@ -0,0 +1,233 @@ +#include "framelessmainwindowlinux.h" + +#ifndef Q_OS_WIN + +#include +#include +#include +#include +#include + +using namespace vnotex; + +FramelessMainWindowLinux::FramelessMainWindowLinux(bool p_frameless, QWidget *p_parent) + : FramelessMainWindow(p_frameless, p_parent) +{ + if (m_frameless) { + // installEventFilter(this); + } +} + +bool FramelessMainWindowLinux::eventFilter(QObject *p_obj, QEvent *p_event) +{ + if (!m_frameless) { + return FramelessMainWindow::eventFilter(p_obj, p_event); + } + + if (p_obj == m_titleBar) { + const auto type = p_event->type(); + if (type == QEvent::MouseButtonDblClick + || type == QEvent::NonClientAreaMouseButtonDblClick) { + if (!(m_windowStates & Qt::WindowFullScreen)) { + if (m_windowStates & Qt::WindowMaximized) { + showNormal(); + } else { + showMaximized(); + } + } + } + } else if (p_obj == this) { + doResize(p_event); + } + + return FramelessMainWindow::eventFilter(p_obj, p_event); +} + +void FramelessMainWindowLinux::setTitleBar(QWidget *p_titleBar) +{ + FramelessMainWindow::setTitleBar(p_titleBar); + + m_titleBar->installEventFilter(this); +} + +void FramelessMainWindowLinux::mousePressEvent(QMouseEvent *p_event) +{ + FramelessMainWindow::mousePressEvent(p_event); + + if (m_frameless) { + recordMousePress(p_event->pos()); + } +} + +void FramelessMainWindowLinux::recordMousePress(const QPoint &p_pos) +{ + m_mousePressed = true; + m_mousePressPoint = p_pos; + m_rectOnMousePress = geometry(); + m_mousePressArea = hitArea(m_mousePressPoint); +} + +void FramelessMainWindowLinux::mouseReleaseEvent(QMouseEvent *p_event) +{ + FramelessMainWindow::mouseReleaseEvent(p_event); + + if (m_frameless) { + // setCursor(Qt::ArrowCursor); + m_mousePressed = false; + } +} + +void FramelessMainWindowLinux::mouseMoveEvent(QMouseEvent *p_event) +{ + FramelessMainWindow::mouseMoveEvent(p_event); + + if (m_frameless) { + Q_ASSERT(m_mousePressed); + if (m_movable && m_mousePressArea == Area::Caption) { + const auto delta = p_event->pos() - m_mousePressPoint; + move(pos() + delta); + } + } +} + +void FramelessMainWindowLinux::doResize(QEvent *p_event) +{ + Q_UNUSED(p_event); +#if 0 + static bool needResetCursor = false; + + switch (p_event->type()) { + case QEvent::HoverMove: + { + if (!m_resizable) { + return; + } + + auto eve = static_cast(p_event); + const auto evePos = eve->pos(); + const auto area = hitArea(evePos); + if (!m_mousePressed && area != Area::None && area != Area::Caption) { + // Mouse press event may be blocked by the children of QMainWindow. + if (QGuiApplication::mouseButtons() != Qt::NoButton) { + recordMousePress(evePos); + return; + } + } + + if (m_mousePressed) { + const auto delta = evePos - m_mousePressPoint; + switch (m_mousePressArea) { + case Area::Left: + { + int newWidth = m_rectOnMousePress.width() - delta.x(); + qDebug() << newWidth << minimumWidth(); + if (minimumWidth() <= newWidth) { + setGeometry(m_rectOnMousePress.x() + delta.x(), + m_rectOnMousePress.y(), + newWidth, + m_rectOnMousePress.height()); + } + break; + } + + default: + break; + } + } else { + switch (area) { + case Area::Left: + Q_FALLTHROUGH(); + case Area::Right: + needResetCursor = true; + setCursor(Qt::SizeHorCursor); + break; + + case Area::Top: + Q_FALLTHROUGH(); + case Area::Bottom: + needResetCursor = true; + setCursor(Qt::SizeVerCursor); + break; + + case Area::TopLeft: + Q_FALLTHROUGH(); + case Area::BottomRight: + needResetCursor = true; + setCursor(Qt::SizeFDiagCursor); + break; + + case Area::TopRight: + Q_FALLTHROUGH(); + case Area::BottomLeft: + needResetCursor = true; + setCursor(Qt::SizeBDiagCursor); + break; + + default: + if (needResetCursor) { + needResetCursor = false; + setCursor(Qt::ArrowCursor); + } + break; + } + } + + return; + } + + default: + break; + } +#endif +} + +FramelessMainWindowLinux::Area FramelessMainWindowLinux::hitArea(const QPoint &p_pos) const +{ + const int x = p_pos.x(); + const int y = p_pos.y(); + Area area = Area::None; + if (x < m_resizeAreaWidth) { + // Left. + if (y < m_resizeAreaWidth) { + // Top. + area = Area::TopLeft; + } else if (y > height() - m_resizeAreaWidth) { + // Bottom. + area = Area::BottomLeft; + } else { + area = Area::Left; + } + } else if (x > width() - m_resizeAreaWidth) { + // Right. + if (y < m_resizeAreaWidth) { + // Top. + area = Area::TopRight; + } else if (y > height() - m_resizeAreaWidth) { + // Bottom. + area = Area::BottomRight; + } else { + area = Area::Right; + } + } else if (y < m_resizeAreaWidth) { + // Top. + area = Area::Top; + } else if (y > height() - m_resizeAreaWidth) { + // Bottom. + area = Area::Bottom; + } else if (y < m_titleBarHeight) { + area = Area::Caption; + } + + return area; +} + +void FramelessMainWindowLinux::showEvent(QShowEvent *p_event) +{ + FramelessMainWindow::showEvent(p_event); + + if (m_frameless && m_titleBarHeight == 0 && m_titleBar) { + m_titleBarHeight = m_titleBar->height(); + } +} + +#endif diff --git a/src/widgets/framelessmainwindow/framelessmainwindowlinux.h b/src/widgets/framelessmainwindow/framelessmainwindowlinux.h new file mode 100644 index 00000000..059c8184 --- /dev/null +++ b/src/widgets/framelessmainwindow/framelessmainwindowlinux.h @@ -0,0 +1,71 @@ +#ifndef FRAMELESSMAINWINDOWLINUX_H +#define FRAMELESSMAINWINDOWLINUX_H + +#include "framelessmainwindow.h" + +#include +#include + +namespace vnotex +{ +#ifndef Q_OS_WIN + class FramelessMainWindowLinux : public FramelessMainWindow + { + Q_OBJECT + public: + FramelessMainWindowLinux(bool p_frameless, QWidget *p_parent = nullptr); + + void setTitleBar(QWidget *p_titleBar) Q_DECL_OVERRIDE; + + protected: + bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE; + + void mousePressEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + + void mouseReleaseEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + + void mouseMoveEvent(QMouseEvent *p_event) Q_DECL_OVERRIDE; + + void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE; + + private: + enum Area + { + Left = 0, + TopLeft, + Top, + TopRight, + Right, + BottomRight, + Bottom, + BottomLeft, + Caption, + None + }; + + Area hitArea(const QPoint &p_pos) const; + + void doResize(QEvent *p_event); + + void recordMousePress(const QPoint &p_pos); + + const int m_resizeAreaWidth = 6; + + int m_titleBarHeight = 0; + + Area m_mousePressArea = Area::None; + + QPoint m_mousePressPoint; + + bool m_mousePressed = false; + + QRect m_rectOnMousePress; + }; +#else + class FramelessMainWindowLinuxDummy + { + }; +#endif +} + +#endif // FRAMELESSMAINWINDOWLINUX_H diff --git a/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp b/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp index 8236c346..29a5a54c 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp +++ b/src/widgets/framelessmainwindow/framelessmainwindowwin.cpp @@ -18,6 +18,8 @@ FramelessMainWindowWin::FramelessMainWindowWin(bool p_frameless, QWidget *p_pare : FramelessMainWindow(p_frameless, p_parent) { if (m_frameless) { + m_resizeAreaWidth *= devicePixelRatio(); + m_redrawTimer = new QTimer(this); m_redrawTimer->setSingleShot(true); m_redrawTimer->setInterval(500); @@ -68,31 +70,36 @@ bool FramelessMainWindowWin::nativeEvent(const QByteArray &p_eventType, void *p_ ::GetWindowRect(msg->hwnd, &windowRect); // x and y could not be compared with width() and height() in hidpi case. - int x = static_cast(GET_X_LPARAM(msg->lParam) - windowRect.left); - int y = static_cast(GET_Y_LPARAM(msg->lParam) - windowRect.top); - - bool onLeft = x < m_resizeAreaWidth; - bool onRight = x > windowRect.right - windowRect.left - m_resizeAreaWidth; - bool onTop = y < m_resizeAreaWidth; - bool onBottom = y > windowRect.bottom - windowRect.top - m_resizeAreaWidth; + const int x = static_cast(GET_X_LPARAM(msg->lParam) - windowRect.left); + const int y = static_cast(GET_Y_LPARAM(msg->lParam) - windowRect.top); *p_result = 0; if (m_resizable) { - if (onLeft && onTop) { - *p_result = HTTOPLEFT; - } else if (onLeft && onBottom) { - *p_result = HTBOTTOMLEFT; - } else if (onRight && onTop) { - *p_result = HTTOPRIGHT; - } else if (onRight && onBottom) { - *p_result = HTBOTTOMRIGHT; - } else if (onLeft) { - *p_result = HTLEFT; - } else if (onRight) { - *p_result = HTRIGHT; - } else if (onTop) { + if (x < m_resizeAreaWidth) { + // Left. + if (y < m_resizeAreaWidth) { + // Top. + *p_result = HTTOPLEFT; + } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { + // Bottom. + *p_result = HTBOTTOMLEFT; + } else { + *p_result = HTLEFT; + } + } else if (x > windowRect.right - windowRect.left - m_resizeAreaWidth) { + // Right. + if (y < m_resizeAreaWidth) { + // Top. + *p_result = HTTOPRIGHT; + } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { + // Bottom. + *p_result = HTBOTTOMRIGHT; + } else { + *p_result = HTRIGHT; + } + } else if (y < m_resizeAreaWidth) { *p_result = HTTOP; - } else if (onBottom) { + } else if (y > windowRect.bottom - windowRect.top - m_resizeAreaWidth) { *p_result = HTBOTTOM; } } diff --git a/src/widgets/framelessmainwindow/framelessmainwindowwin.h b/src/widgets/framelessmainwindow/framelessmainwindowwin.h index d4f04e80..7f5e8c14 100644 --- a/src/widgets/framelessmainwindow/framelessmainwindowwin.h +++ b/src/widgets/framelessmainwindow/framelessmainwindowwin.h @@ -10,7 +10,7 @@ namespace vnotex { Q_OBJECT public: - FramelessMainWindowWin(bool p_frameless = true, QWidget *p_parent = nullptr); + FramelessMainWindowWin(bool p_frameless, QWidget *p_parent = nullptr); protected: #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) @@ -27,6 +27,8 @@ namespace vnotex void updateMargins(); + int m_resizeAreaWidth = 6; + QTimer *m_redrawTimer = nullptr; QSize m_sizeBeforeMove; @@ -35,6 +37,10 @@ namespace vnotex int m_titleBarHeight = 0; }; +#else + class FramelessMainWindowWinDummy + { + }; #endif } diff --git a/src/widgets/mainwindow.cpp b/src/widgets/mainwindow.cpp index 8eff33a9..8b8d65fc 100644 --- a/src/widgets/mainwindow.cpp +++ b/src/widgets/mainwindow.cpp @@ -547,6 +547,8 @@ void MainWindow::closeOnQuit() { // No user interaction is available. emit mainWindowClosedOnQuit(); + + VNoteX::getInst().getNotebookMgr().close(); } void MainWindow::setupShortcuts() diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index 7f60c4fb..cf3c53d6 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -59,6 +59,7 @@ SOURCES += \ $$PWD/findandreplacewidget.cpp \ $$PWD/floatingwidget.cpp \ $$PWD/framelessmainwindow/framelessmainwindow.cpp \ + $$PWD/framelessmainwindow/framelessmainwindowlinux.cpp \ $$PWD/framelessmainwindow/framelessmainwindowwin.cpp \ $$PWD/fullscreentoggleaction.cpp \ $$PWD/historypanel.cpp \ @@ -185,6 +186,7 @@ HEADERS += \ $$PWD/floatingwidget.h \ $$PWD/framelessmainwindow/framelessmainwindow.h \ $$PWD/framelessmainwindow/framelessmainwindowimpl.h \ + $$PWD/framelessmainwindow/framelessmainwindowlinux.h \ $$PWD/framelessmainwindow/framelessmainwindowwin.h \ $$PWD/fullscreentoggleaction.h \ $$PWD/historypanel.h \