/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team 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, either version 3 of the License, or (at your option) any later version. 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 . ***/ #ifndef WIDGETMENU_H #define WIDGETMENU_H #include #include #include #include "common/define.h" namespace olive { /** * @brief A menu widget for context menus and menu bars * * A QMenu subclass with functions for creating menus and menu items that conform to Olive's menu and keyboard shortcut * system. * * In Olive, menu items in the menu bar are also responsible for keyboard shortcuts throughout the application. To allow * these to be configurable and these configurations saveable, every item needs a unique ID. This ID gets linked to the * keyboard shortcuts in config files. The ID doesn't get translated so it can also persist through language changes. * * The ID gets stored in the QAction's "id" property. If a keyboard shortcut is provided, it gets stored in the * QAction's "keydefault" property. * * It is always recommended to use this over QMenu in any situation. */ class Menu : public QMenu { public: Menu(QMenuBar* bar); template /** * @brief Construct a Menu and add it to a QMenuBar * * This Menu can be connected to a slot that's triggered when the Menu is "about to show". Use `receiver` and * `member` to connect this (same syntax as QObject::connect) or leave as nullptr to not. */ Menu(QMenuBar* bar, const typename QtPrivate::FunctionPointer::Object *receiver, Func member) { bar->addMenu(this); Init(); ConnectAboutToShow(receiver, member); } Menu(Menu* menu); template /** * @brief Construct a Menu and add it as a submenu to another Menu * * This Menu can be connected to a slot that's triggered when the Menu is "about to show". Use `receiver` and * `member` to connect this (same syntax as QObject::connect) or leave as nullptr to not. */ Menu(Menu* menu, const typename QtPrivate::FunctionPointer::Object *receiver, Func member) { menu->addMenu(this); Init(); ConnectAboutToShow(receiver, member); } /** * @brief Construct a popup menu */ Menu(QWidget* parent = nullptr); /** * @brief Construct a popup menu */ Menu(const QString& s, QWidget* parent = nullptr); template /** * @brief Create a menu item and add it to this menu * * @param id * * The action's unique ID * * @param receiver * * The QObject to receive the signal when this item is triggered * * @param member * * The QObject slot to connect this action's triggered signal to * * @param key * * Default keyboard sequence * * @return * * The QAction that was created and added to this Menu */ QAction* AddItem(const QString& id, const typename QtPrivate::FunctionPointer::Object *receiver, Func member, const QKeySequence &key = QKeySequence()) { QAction* a = CreateItem(this, id, receiver, member, key); addAction(a); return a; } QAction* AddActionWithData(const QString& text, const QVariant& d, const QVariant& compare); QAction *InsertAlphabetically(const QString& s); void InsertAlphabetically(QAction* entry); void InsertAlphabetically(Menu* menu); template /** * @brief Create a menu item * * @param parent * * The QAction's parent * * @param id * * The action's unique ID * * @param receiver * * The QObject to receive the signal when this item is triggered * * @param member * * The QObject slot to connect this action's triggered signal to * * @param key * * Default keyboard sequence * * @return * * The QAction that was created and added to this Menu */ static QAction* CreateItem(QObject* parent, const QString& id, const typename QtPrivate::FunctionPointer::Object *receiver, Func member, const QKeySequence &key = QKeySequence()) { QAction* a = new QAction(parent); ConformItem(a, id, receiver, member, key); return a; } template /** * @brief Conform a QAction to Olive's ID/keydefault system * * If a QAction was created elsewhere (e.g. through QUndoStack::createUndoAction()), this function will give it * properties conforming it to Olive's menu item system * * @param a * * The QAction's to conform * * @param id * * The action's unique ID * * @param receiver * * The QObject to receive the signal when this item is triggered * * @param member * * The QObject slot to connect this action's triggered signal to * * @param key * * Default keyboard sequence */ static void ConformItem(QAction *a, const QString& id, const typename QtPrivate::FunctionPointer::Object *receiver, Func member, const QKeySequence &key = QKeySequence()) { ConformItem(a, id, key); connect(a, &QAction::triggered, receiver, member); } static void ConformItem(QAction *a, const QString& id, const QKeySequence &key = QKeySequence()); private: void Init(); template void ConnectAboutToShow(const typename QtPrivate::FunctionPointer::Object *receiver, Func member) { connect(this, &Menu::aboutToShow, receiver, member); } }; } #endif // WIDGETMENU_H