From: Abdelrazak Younes Date: Wed, 26 Dec 2007 10:55:43 +0000 (+0000) Subject: Simplify MenuBackend and menubar interactions. X-Git-Tag: 1.6.10~6801 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=722329490b835d12e54ac279f8f345a84d60f5b9;p=features.git Simplify MenuBackend and menubar interactions. * GuiMenubar: freed from GuiView and QMenuBar, renamed to 'Menus' * GuiView: just use the standard QMenuBar. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@22308 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/development/scons/scons_manifest.py b/development/scons/scons_manifest.py index 5b8f46aa2d..371d34c6bb 100644 --- a/development/scons/scons_manifest.py +++ b/development/scons/scons_manifest.py @@ -738,7 +738,6 @@ src_frontends_qt4_header_files = Split(''' GuiLog.h GuiMath.h GuiMathMatrix.h - GuiMenubar.h GuiNomencl.h GuiNote.h GuiPainter.h @@ -771,6 +770,7 @@ src_frontends_qt4_header_files = Split(''' LaTeXHighlighter.h LengthCombo.h LyXFileDialog.h + Menus.h PanelStack.h TocModel.h TocWidget.h @@ -826,7 +826,6 @@ src_frontends_qt4_files = Split(''' GuiLog.cpp GuiMath.cpp GuiMathMatrix.cpp - GuiMenubar.cpp GuiNomencl.cpp GuiNote.cpp GuiPainter.cpp @@ -859,6 +858,7 @@ src_frontends_qt4_files = Split(''' LengthCombo.cpp LaTeXHighlighter.cpp LyXFileDialog.cpp + Menus.h PanelStack.cpp TocModel.cpp TocWidget.cpp diff --git a/src/frontends/qt4/GuiApplication.h b/src/frontends/qt4/GuiApplication.h index 851ffbba45..fb8be4a75e 100644 --- a/src/frontends/qt4/GuiApplication.h +++ b/src/frontends/qt4/GuiApplication.h @@ -17,11 +17,10 @@ #include "GuiFontLoader.h" #include "GuiClipboard.h" #include "GuiSelection.h" +#include "Menus.h" #include "frontends/Application.h" -#include "MenuBackend.h" - #include #include #include @@ -64,8 +63,8 @@ public: virtual Clipboard & clipboard(); virtual Selection & selection(); virtual FontLoader & fontLoader() { return font_loader_; } - MenuBackend const & menuBackend() const { return menu_backend_; } - MenuBackend & menuBackend() { return menu_backend_; } + MenuBackend const & menuBackend() const { return menus_; } + MenuBackend & menuBackend() { return menus_; } virtual int exec(); virtual void exit(int status); virtual bool event(QEvent * e); @@ -76,6 +75,8 @@ public: void unregisterSocketCallback(int fd); //@} + Menus const & menus() const { return menus_; } + Menus & menus() { return menus_; } /// Methods inherited from \c QApplication class //@{ bool notify(QObject * receiver, QEvent * event); @@ -140,7 +141,7 @@ private: /// std::map socket_notifiers_; /// - MenuBackend menu_backend_; + Menus menus_; #ifdef Q_WS_X11 public: diff --git a/src/frontends/qt4/GuiMenubar.cpp b/src/frontends/qt4/GuiMenubar.cpp deleted file mode 100644 index 33e7f0b9b7..0000000000 --- a/src/frontends/qt4/GuiMenubar.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/** - * \file qt4/GuiMenubar.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "GuiMenubar.h" - -#include "Action.h" -#include "GuiApplication.h" -#include "GuiPopupMenu.h" -#include "GuiView.h" - -#include "qt_helpers.h" - -#include "MenuBackend.h" - -#include "support/debug.h" - -#include -#include - - -namespace lyx { -namespace frontend { - -// MacOSX specific stuff is at the end. - -GuiMenubar::GuiMenubar(GuiView * view) - : owner_(view) -{ - init(); -} - - -void GuiMenubar::init() -{ - // Clear all menubar contents before filling it. - owner_->menuBar()->clear(); - -#ifdef Q_WS_MACX - // setup special mac specific menu item - macxMenuBarInit(); -#endif - - /// menu controller - MenuBackend & menu_backend = guiApp->menuBackend(); - LYXERR(Debug::GUI, "populating menu bar" << to_utf8(menu_backend.getMenubar().name())); - - if (menu_backend.getMenubar().size() == 0) { - LYXERR(Debug::GUI, "\tERROR: empty menu bar" - << to_utf8(menu_backend.getMenubar().name())); - return; - // continue; - } - else { - LYXERR(Debug::GUI, "menu bar entries " - << menu_backend.getMenubar().size()); - } - - Menu menu; - menu_backend.expand(menu_backend.getMenubar(), menu, owner_->buffer()); - - Menu::const_iterator m = menu.begin(); - Menu::const_iterator end = menu.end(); - - for (; m != end; ++m) { - - if (m->kind() != MenuItem::Submenu) { - LYXERR(Debug::GUI, "\tERROR: not a submenu " << to_utf8(m->label())); - continue; - } - - LYXERR(Debug::GUI, "menu bar item " << to_utf8(m->label()) - << " is a submenu named " << to_utf8(m->submenuname())); - - docstring name = m->submenuname(); - if (!menu_backend.hasMenu(name)) { - LYXERR(Debug::GUI, "\tERROR: " << to_utf8(name) - << " submenu has no menu!"); - continue; - } - - Menu menu; - menu_backend.expand(menu_backend.getMenubar(), menu, owner_->buffer()); - - GuiPopupMenu * qMenu = new GuiPopupMenu(owner_, *m, true); - owner_->menuBar()->addMenu(qMenu); - - name_map_[toqstr(name)] = qMenu; - } -} - - -GuiMenubar::~GuiMenubar() {} - -void GuiMenubar::openByName(QString const & name) -{ - if (QMenu * menu = name_map_.value(name)) - menu->exec(QCursor::pos()); -} - - -/// Some special Qt/Mac support hacks - -/* - Here is what the Qt documentation says about how a menubar is chosen: - - 1) If the window has a QMenuBar then it is used. 2) If the window - is a modal then its menubar is used. If no menubar is specified - then a default menubar is used (as documented below) 3) If the - window has no parent then the default menubar is used (as - documented below). - - The above 3 steps are applied all the way up the parent window - chain until one of the above are satisifed. If all else fails a - default menubar will be created, the default menubar on Qt/Mac is - an empty menubar, however you can create a different default - menubar by creating a parentless QMenuBar, the first one created - will thus be designated the default menubar, and will be used - whenever a default menubar is needed. - - Thus, for Qt/Mac, we add the menus to a free standing menubar, so - that this menubar will be used also when one of LyX' dialogs has - focus. (JMarc) -*/ - -void GuiMenubar::macxMenuBarInit() -{ - /* Since Qt 4.2, the qt/mac menu code has special code for - specifying the role of a menu entry. However, it does not - work very well with our scheme of creating menus on demand, - and therefore we need to put these entries in a special - invisible menu. (JMarc) - */ - - /* The entries of our special mac menu. If we add support for - * special entries in MenuBackend, we could imagine something - * like - * SpecialItem About " "About LyX" "dialog-show aboutlyx" - * and therefore avoid hardcoding. I am not sure it is worth - * the hassle, though. (JMarc) - */ - struct MacMenuEntry { - kb_action action; - char const * arg; - char const * label; - QAction::MenuRole role; - }; - - MacMenuEntry entries[] = { - {LFUN_DIALOG_SHOW, "aboutlyx", "About LyX", - QAction::AboutRole}, - {LFUN_DIALOG_SHOW, "prefs", "Preferences", - QAction::PreferencesRole}, - {LFUN_RECONFIGURE, "", "Reconfigure", - QAction::ApplicationSpecificRole}, - {LFUN_LYX_QUIT, "", "Quit LyX", QAction::QuitRole} - }; - const size_t num_entries = sizeof(entries) / sizeof(MacMenuEntry); - - // the special menu for MenuBackend. - Menu special; - for (size_t i = 0 ; i < num_entries ; ++i) { - FuncRequest const func(entries[i].action, - from_utf8(entries[i].arg)); - special.add(MenuItem(MenuItem::Command, - from_utf8(entries[i].label), - func)); - } - MenuBackend & menu_backend = guiApp->menuBackend(); - menu_backend.specialMenu(special); - - // add the entries to a QMenu that will eventually be empty - // and therefore invisible. - QMenu * qMenu = owner_->menuBar()->addMenu("special"); - - // we do not use 'special' because it is a temporary variable, - // whereas MenuBackend::specialMenu points to a persistent - // copy. - Menu::const_iterator cit = menu_backend.specialMenu().begin(); - Menu::const_iterator end = menu_backend.specialMenu().end(); - for (size_t i = 0 ; cit != end ; ++cit, ++i) { - Action * action = new Action(*owner_, QIcon(), - toqstr(cit->label()), - cit->func(), QString()); - action->setMenuRole(entries[i].role); - qMenu->addAction(action); - - } -} - -} // namespace frontend -} // namespace lyx - -#include "GuiMenubar_moc.cpp" diff --git a/src/frontends/qt4/GuiMenubar.h b/src/frontends/qt4/GuiMenubar.h deleted file mode 100644 index 10acf8e701..0000000000 --- a/src/frontends/qt4/GuiMenubar.h +++ /dev/null @@ -1,64 +0,0 @@ -// -*- C++ -*- -/** - * \file GuiMenubar.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Lars Gullik Bjønnes - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef GUIMENUBAR_H -#define GUIMENUBAR_H - -#include -#include - -class QMenuBar; - -namespace lyx { -namespace frontend { - -class GuiView; -class GuiPopupMenu; -class GuiView; - -class GuiMenubar : public QObject -{ - Q_OBJECT -public: - GuiMenubar(GuiView *); - - ~GuiMenubar(); - - /// - void init(); - - /// opens a top-level submenu given its name - void openByName(QString const & name); - - /// return the owning view - GuiView * view() { return owner_; } - - /// update the state of the menuitems - not needed - void updateView(); - -private: - /// Initialize specific MACOS X menubar - void macxMenuBarInit(); - - /// owning view - GuiView * owner_; - - typedef QHash NameMap; - - /// name to menu for openByName - NameMap name_map_; -}; - -} // namespace frontend -} // namespace lyx - -#endif // GUIMENUBAR_H diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index 4f1b4ce51e..72df7a3e08 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -20,9 +20,9 @@ #include "GuiApplication.h" #include "GuiWorkArea.h" #include "GuiKeySymbol.h" -#include "GuiMenubar.h" #include "GuiToolbar.h" #include "GuiToolbars.h" +#include "Menus.h" #include "qt_helpers.h" @@ -165,7 +165,6 @@ struct GuiView::GuiViewPrivate delete splitter_; delete bg_widget_; delete stack_widget_; - delete menubar_; delete toolbars_; } @@ -242,8 +241,6 @@ public: QSplitter * splitter_; QStackedWidget * stack_widget_; BackgroundWidget * bg_widget_; - /// view's menubar - GuiMenubar * menubar_; /// view's toolbars GuiToolbars * toolbars_; /// The main layout box. @@ -280,9 +277,11 @@ public: GuiView::GuiView(int id) : d(*new GuiViewPrivate), id_(id) { - // GuiToolbars *must* be initialised before GuiMenubar. + // GuiToolbars *must* be initialised before the menu bar. d.toolbars_ = new GuiToolbars(*this); - d.menubar_ = new GuiMenubar(this); + + // Fill up the menu bar. + guiApp->menus().fillMenuBar(this); setCentralWidget(d.stack_widget_); @@ -1366,7 +1365,7 @@ bool GuiView::dispatch(FuncRequest const & cmd) break; case LFUN_MENU_OPEN: - d.menubar_->openByName(toqstr(cmd.argument())); + guiApp->menus().openByName(toqstr(cmd.argument())); break; case LFUN_FILE_INSERT: @@ -1596,7 +1595,7 @@ void GuiView::resetDialogs() // Make sure that no LFUN uses any LyXView. theLyXFunc().setLyXView(0); d.toolbars_->init(); - d.menubar_->init(); + guiApp->menus().fillMenuBar(this); if (d.layout_) d.layout_->updateContents(true); // Now update controls with current buffer. diff --git a/src/frontends/qt4/Makefile.am b/src/frontends/qt4/Makefile.am index ed17a5de39..4aae59b510 100644 --- a/src/frontends/qt4/Makefile.am +++ b/src/frontends/qt4/Makefile.am @@ -94,7 +94,6 @@ SOURCEFILES = \ GuiLog.cpp \ GuiMath.cpp \ GuiMathMatrix.cpp \ - GuiMenubar.cpp \ GuiNomencl.cpp \ GuiNote.cpp \ GuiPainter.cpp \ @@ -127,6 +126,7 @@ SOURCEFILES = \ LengthCombo.cpp \ LyXFileDialog.cpp \ LaTeXHighlighter.cpp \ + Menus.cpp \ PanelStack.cpp \ qt_helpers.cpp \ TocModel.cpp \ @@ -181,7 +181,6 @@ MOCHEADER = \ GuiListings.h \ GuiLog.h \ GuiMathMatrix.h \ - GuiMenubar.h \ GuiNomencl.h \ GuiNote.h \ GuiParagraph.h \ @@ -212,6 +211,7 @@ MOCHEADER = \ LengthCombo.h \ LyXFileDialog.h \ LaTeXHighlighter.h \ + Menus.h \ PanelStack.h \ qlkey.h \ TocModel.h \ diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp new file mode 100644 index 0000000000..f47d94d1aa --- /dev/null +++ b/src/frontends/qt4/Menus.cpp @@ -0,0 +1,187 @@ +/** + * \file qt4/Menus.cpp + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author John Levon + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "Menus.h" + +#include "Action.h" +#include "GuiApplication.h" +#include "GuiPopupMenu.h" +#include "GuiView.h" + +#include "qt_helpers.h" + +#include "support/debug.h" + +#include +#include + + +namespace lyx { +namespace frontend { + +// MacOSX specific stuff is at the end. + +void Menus::fillMenuBar(GuiView * view) +{ + // Clear all menubar contents before filling it. + view->menuBar()->clear(); + +#ifdef Q_WS_MACX + // setup special mac specific menu item + macxMenuBarInit(); +#endif + + LYXERR(Debug::GUI, "populating menu bar" << to_utf8(getMenubar().name())); + + if (getMenubar().size() == 0) { + LYXERR(Debug::GUI, "\tERROR: empty menu bar" + << to_utf8(getMenubar().name())); + return; + } + else { + LYXERR(Debug::GUI, "menu bar entries " + << getMenubar().size()); + } + + Menu menu; + expand(getMenubar(), menu, view->buffer()); + + Menu::const_iterator m = menu.begin(); + Menu::const_iterator end = menu.end(); + + for (; m != end; ++m) { + + if (m->kind() != MenuItem::Submenu) { + LYXERR(Debug::GUI, "\tERROR: not a submenu " << to_utf8(m->label())); + continue; + } + + LYXERR(Debug::GUI, "menu bar item " << to_utf8(m->label()) + << " is a submenu named " << to_utf8(m->submenuname())); + + docstring name = m->submenuname(); + if (!hasMenu(name)) { + LYXERR(Debug::GUI, "\tERROR: " << to_utf8(name) + << " submenu has no menu!"); + continue; + } + + Menu menu; + expand(getMenubar(), menu, view->buffer()); + + GuiPopupMenu * qMenu = new GuiPopupMenu(view, *m, true); + view->menuBar()->addMenu(qMenu); + + name_map_[toqstr(name)] = qMenu; + } +} + + +void Menus::openByName(QString const & name) +{ + if (QMenu * menu = name_map_.value(name)) + menu->exec(QCursor::pos()); +} + + +/// Some special Qt/Mac support hacks + +/* + Here is what the Qt documentation says about how a menubar is chosen: + + 1) If the window has a QMenuBar then it is used. 2) If the window + is a modal then its menubar is used. If no menubar is specified + then a default menubar is used (as documented below) 3) If the + window has no parent then the default menubar is used (as + documented below). + + The above 3 steps are applied all the way up the parent window + chain until one of the above are satisifed. If all else fails a + default menubar will be created, the default menubar on Qt/Mac is + an empty menubar, however you can create a different default + menubar by creating a parentless QMenuBar, the first one created + will thus be designated the default menubar, and will be used + whenever a default menubar is needed. + + Thus, for Qt/Mac, we add the menus to a free standing menubar, so + that this menubar will be used also when one of LyX' dialogs has + focus. (JMarc) +*/ + +void Menus::macxMenuBarInit(GuiView * view) +{ + /* Since Qt 4.2, the qt/mac menu code has special code for + specifying the role of a menu entry. However, it does not + work very well with our scheme of creating menus on demand, + and therefore we need to put these entries in a special + invisible menu. (JMarc) + */ + + /* The entries of our special mac menu. If we add support for + * special entries in MenuBackend, we could imagine something + * like + * SpecialItem About " "About LyX" "dialog-show aboutlyx" + * and therefore avoid hardcoding. I am not sure it is worth + * the hassle, though. (JMarc) + */ + struct MacMenuEntry { + kb_action action; + char const * arg; + char const * label; + QAction::MenuRole role; + }; + + MacMenuEntry entries[] = { + {LFUN_DIALOG_SHOW, "aboutlyx", "About LyX", + QAction::AboutRole}, + {LFUN_DIALOG_SHOW, "prefs", "Preferences", + QAction::PreferencesRole}, + {LFUN_RECONFIGURE, "", "Reconfigure", + QAction::ApplicationSpecificRole}, + {LFUN_LYX_QUIT, "", "Quit LyX", QAction::QuitRole} + }; + const size_t num_entries = sizeof(entries) / sizeof(MacMenuEntry); + + // the special menu for MenuBackend. + Menu special; + for (size_t i = 0 ; i < num_entries ; ++i) { + FuncRequest const func(entries[i].action, + from_utf8(entries[i].arg)); + special.add(MenuItem(MenuItem::Command, + from_utf8(entries[i].label), + func)); + } + specialMenu(special); + + // add the entries to a QMenu that will eventually be empty + // and therefore invisible. + QMenu * qMenu = view->menuBar()->addMenu("special"); + + // we do not use 'special' because it is a temporary variable, + // whereas MenuBackend::specialMenu points to a persistent + // copy. + Menu::const_iterator cit = specialMenu().begin(); + Menu::const_iterator end = specialMenu().end(); + for (size_t i = 0 ; cit != end ; ++cit, ++i) { + Action * action = new Action(*view, QIcon(), + toqstr(cit->label()), + cit->func(), QString()); + action->setMenuRole(entries[i].role); + qMenu->addAction(action); + + } +} + +} // namespace frontend +} // namespace lyx + +#include "Menus_moc.cpp" diff --git a/src/frontends/qt4/Menus.h b/src/frontends/qt4/Menus.h new file mode 100644 index 0000000000..633cd72151 --- /dev/null +++ b/src/frontends/qt4/Menus.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +/** + * \file Menus.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Lars Gullik Bjønnes + * \author John Levon + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef MENUS_H +#define MENUS_H + +#include "MenuBackend.h" + +#include +#include + +namespace lyx { +namespace frontend { + +class GuiView; +class GuiPopupMenu; +class GuiView; + +class Menus : public QObject, public MenuBackend +{ + Q_OBJECT +public: + Menus() {} + + /// + void fillMenuBar(GuiView * view); + + /// opens a top-level submenu given its name + void openByName(QString const & name); + + /// update the state of the menuitems - not needed + void updateView(); + +private: + /// Initialize specific MACOS X menubar + void macxMenuBarInit(GuiView * view); + + typedef QHash NameMap; + + /// name to menu for openByName + NameMap name_map_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // MENUS_H