diff --git a/src/app/GUI/mainwindow.h b/src/app/GUI/mainwindow.h index cc5b50fe5..4c8b4f549 100644 --- a/src/app/GUI/mainwindow.h +++ b/src/app/GUI/mainwindow.h @@ -59,6 +59,10 @@ #include "widgets/uilayout.h" #include "widgets/toolbox.h" +#ifndef Q_OS_MAC +#include "widgets/persistentmenu.h" +#endif + class VideoEncoder; class RenderWidget; class ActionButton; @@ -280,7 +284,11 @@ class MainWindow : public QMainWindow QMenu *mPathMenu; QMenu *mEffectsMenu; QMenu *mSceneMenu; +#ifndef Q_OS_MAC + Friction::Ui::PersistentMenu *mViewMenu; +#else QMenu *mViewMenu; +#endif QMenu *mPanelsMenu; QMenu *mRenderMenu; diff --git a/src/app/GUI/menu.cpp b/src/app/GUI/menu.cpp index eb7c6efd2..48506ff25 100644 --- a/src/app/GUI/menu.cpp +++ b/src/app/GUI/menu.cpp @@ -333,7 +333,13 @@ void MainWindow::setupMenuBar() }); cmdAddAction(clearRecentAct); +#ifndef Q_OS_MAC + mViewMenu = new Ui::PersistentMenu(tr("View", "MenuBar"), this); + mViewMenu->setOnlyCheckable(true); + mMenuBar->addMenu(mViewMenu); +#else mViewMenu = mMenuBar->addMenu(tr("View", "MenuBar")); +#endif mObjectMenu = mMenuBar->addMenu(tr("Object", "MenuBar")); @@ -505,7 +511,13 @@ void MainWindow::setupMenuBar() mEffectsMenu->setEnabled(false); setupMenuEffects(); - const auto zoomMenu = mViewMenu->addMenu(QIcon::fromTheme("zoom"), tr("Zoom","MenuBar_View")); +#ifndef Q_OS_MAC + const auto zoomMenu = mViewMenu->addPersistentMenu(QIcon::fromTheme("zoom"), + tr("Zoom","MenuBar_View")); +#else + const auto zoomMenu = mViewMenu->addMenu(QIcon::fromTheme("zoom"), + tr("Zoom","MenuBar_View")); +#endif mZoomInAction = zoomMenu->addAction(tr("Zoom In", "MenuBar_View_Zoom")); mZoomInAction->setIcon(QIcon::fromTheme("zoom_in")); @@ -566,8 +578,13 @@ void MainWindow::setupMenuBar() }); cmdAddAction(mResetZoomAction); +#ifndef Q_OS_MAC + const auto filteringMenu = mViewMenu->addPersistentMenu(QIcon::fromTheme("user-desktop"), + tr("Filtering", "MenuBar_View")); +#else const auto filteringMenu = mViewMenu->addMenu(QIcon::fromTheme("user-desktop"), tr("Filtering", "MenuBar_View")); +#endif mNoneQuality = filteringMenu->addAction( tr("None", "MenuBar_View_Filtering"), [this]() { diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 50a00572f..c35a3d353 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -171,6 +171,7 @@ set( widgets/labeledslider.h widgets/markereditor.h widgets/performancesettingswidget.h + widgets/persistentmenu.h widgets/presetsettingswidget.h widgets/qdoubleslider.h widgets/qrealanimatorvalueslider.h diff --git a/src/ui/widgets/persistentmenu.h b/src/ui/widgets/persistentmenu.h new file mode 100644 index 000000000..72e79ffe2 --- /dev/null +++ b/src/ui/widgets/persistentmenu.h @@ -0,0 +1,79 @@ +/* +# +# Friction - https://friction.graphics +# +# Copyright (c) Ole-André Rodlie and contributors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# See 'README.md' for more information. +# +*/ + +#ifndef FRICTION_PERSISTENTMENU_H +#define FRICTION_PERSISTENTMENU_H + +#include "ui_global.h" + +#include +#include +#include + +namespace Friction +{ + namespace Ui + { + class UI_EXPORT PersistentMenu : public QMenu + { + Q_OBJECT + public: + using QMenu::QMenu; + + PersistentMenu* addPersistentMenu(const QIcon &icon, + const QString &title, + const bool onlyCheckable = false) + { + PersistentMenu *subMenu = new PersistentMenu(title, this); + subMenu->setOnlyCheckable(onlyCheckable); + subMenu->setIcon(icon); + this->addMenu(subMenu); + return subMenu; + } + void setOnlyCheckable(const bool checked) + { + mOnlyCheckable = checked; + } + + private: + bool mOnlyCheckable = false; + + protected: + void mouseReleaseEvent(QMouseEvent *event) override + { + QAction *action = actionAt(event->pos()); + if (action && action->menu()) { + QMenu::mouseReleaseEvent(event); + return; + } + if ((action && !mOnlyCheckable) || + (action && mOnlyCheckable && action->isCheckable())) { + action->activate(QAction::Trigger); + } else { + QMenu::mouseReleaseEvent(event); + } + } + }; + } +} + +#endif // FRICTION_PERSISTENTMENU_H diff --git a/src/ui/widgets/toolinteract.cpp b/src/ui/widgets/toolinteract.cpp index ba9910a09..df5d26fc6 100644 --- a/src/ui/widgets/toolinteract.cpp +++ b/src/ui/widgets/toolinteract.cpp @@ -24,6 +24,7 @@ #include "Private/document.h" #include "GUI/coloranimatorbutton.h" +#include "widgets/persistentmenu.h" #include #include @@ -50,7 +51,7 @@ ToolInteract::ToolInteract(QWidget *parent) void ToolInteract::setupGizmoButton() { const auto button = new QToolButton(this); - const auto menu = new QMenu(button); + const auto menu = new PersistentMenu(button); button->setObjectName("ToolBoxGizmo"); button->setPopupMode(QToolButton::MenuButtonPopup); @@ -155,7 +156,7 @@ void ToolInteract::setupSnapButton() { const auto grid = Document::sInstance->getGrid(); const auto button = new QToolButton(this); - const auto menu = new QMenu(button); + const auto menu = new PersistentMenu(button); button->setObjectName("ToolBoxGizmo"); button->setPopupMode(QToolButton::MenuButtonPopup); @@ -309,7 +310,7 @@ void ToolInteract::setupGridButton() { const auto grid = Document::sInstance->getGrid(); const auto button = new QToolButton(this); - const auto menu = new QMenu(button); + const auto menu = new PersistentMenu(button); button->setObjectName("ToolBoxGizmo"); button->setPopupMode(QToolButton::MenuButtonPopup); @@ -362,8 +363,8 @@ void ToolInteract::setupGridButton() } menu->addSeparator(); - const auto optMenu = menu->addMenu(QIcon::fromTheme("preferences"), - tr("Settings")); + const auto optMenu = menu->addPersistentMenu(QIcon::fromTheme("preferences"), + tr("Settings")); menu->addSeparator(); setupGridAction(button, Core::Grid::Option::SizeX);