the Qt/Mac merge menu patch; this is actually different from macmove8, so I hope it still works...

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8926 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jean-Marc Lasgouttes 2004-08-14 18:06:10 +00:00
parent d20f0af816
commit a9114d0e44
11 changed files with 157 additions and 46 deletions

View File

@ -1,3 +1,8 @@
2004-08-14 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
* ui/stdmenus.ui:
* ui/classic.ui: add LyX menu
2004-08-14 Bennett Helm <bennett.helm@fandm.edu> 2004-08-14 Bennett Helm <bennett.helm@fandm.edu>
* bind/mac.bind: new file. This is the Mac flavour bind file, based on * bind/mac.bind: new file. This is the Mac flavour bind file, based on

View File

@ -407,6 +407,16 @@ Menuset
Item "About LyX|X" "dialog-show aboutlyx" Item "About LyX|X" "dialog-show aboutlyx"
End End
#
# LYX MENU - this menu is only used by LyX/Mac
#
Menu "LyX"
Item "About LyX" "dialog-show aboutlyx"
Item "Preferences..." "dialog-show prefs"
Item "Quit LyX" "lyx-quit"
End
End End
# Which toolbars to use. # Which toolbars to use.

View File

@ -437,4 +437,14 @@ Menuset
Item "About LyX...|X" "dialog-show aboutlyx" Item "About LyX...|X" "dialog-show aboutlyx"
End End
#
# LYX MENU - this menu is only used by LyX/Mac
#
Menu "LyX"
Item "About LyX" "dialog-show aboutlyx"
Item "Preferences..." "dialog-show prefs"
Item "Quit LyX" "lyx-quit"
End
End End

View File

@ -1,3 +1,13 @@
2004-08-14 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
* MenuBackend.C (Menu::operator[]): new method to access
individual menu items
(Menu::hasFunc): new method. search for an item that corresponds
to a given func
(MenuBackend::specialMenu): new method
(MenuBackend::expand): if a special menu has been set, skip
entries whose func() appears in this menu
2004-08-14 Lars Gullik Bjonnes <larsbj@lyx.org> 2004-08-14 Lars Gullik Bjonnes <larsbj@lyx.org>
* text3.C: use Debug::DEBUG a bit more * text3.C: use Debug::DEBUG a bit more

View File

@ -357,6 +357,20 @@ Menu & Menu::read(LyXLex & lex)
} }
MenuItem const & Menu::operator[](size_type i) const
{
return items_[i];
}
bool Menu::hasFunc(FuncRequest const & func) const
{
return find_if(begin(), end(),
bind(std::equal_to<FuncRequest>(),
bind(&MenuItem::func, _1),
func)) != end();
}
void Menu::checkShortcuts() const void Menu::checkShortcuts() const
{ {
// This is a quadratic algorithm, but we do not care because // This is a quadratic algorithm, but we do not care because
@ -383,6 +397,13 @@ void Menu::checkShortcuts() const
} }
void MenuBackend::specialMenu(string const &name)
{
if (hasMenu(name))
specialmenu_ = &getMenu(name);
}
namespace { namespace {
class compare_format { class compare_format {
@ -775,7 +796,13 @@ void MenuBackend::expand(Menu const & frommenu, Menu & tomenu,
} }
break; break;
default: case MenuItem::Separator:
tomenu.add(*cit, view);
break;
case MenuItem::Command:
if (!specialmenu_
|| !specialmenu_->hasFunc(cit->func()))
tomenu.add(*cit, view); tomenu.add(*cit, view);
} }
} }
@ -790,27 +817,6 @@ void MenuBackend::expand(Menu const & frommenu, Menu & tomenu,
} }
bool Menu::hasSubmenu(string const & name) const
{
#if 1
return find_if(begin(), end(),
bind(std::equal_to<string>(),
bind(&MenuItem::submenuname, _1),
name)) != end();
#else
// I would have prefered this, but I am not sure if it
// makes a difference. (Lgb)
return find_if(
make_transform_iterator(begin(),
bind(&MenuItem::submenuname, _1)),
make_transform_iterator(end(),
bind(&MenuItem::submenuname, _1)),
name
).base() != end();
#endif
}
void MenuBackend::read(LyXLex & lex) void MenuBackend::read(LyXLex & lex)
{ {
enum Menutags { enum Menutags {

View File

@ -156,7 +156,9 @@ public:
/// ///
ItemList::size_type size() const { return items_.size(); } ItemList::size_type size() const { return items_.size(); }
/// ///
bool hasSubmenu(std::string const &) const; MenuItem const & operator[](size_type) const;
///
bool hasFunc(FuncRequest const &) const;
/// ///
const_iterator begin() const { const_iterator begin() const {
return items_.begin(); return items_.begin();
@ -188,6 +190,8 @@ public:
/// ///
typedef MenuList::iterator iterator; typedef MenuList::iterator iterator;
/// ///
MenuBackend::MenuBackend() : specialmenu_(0) {}
///
void read(LyXLex &); void read(LyXLex &);
/// ///
void add(Menu const &); void add(Menu const &);
@ -201,6 +205,11 @@ public:
Menu const & getMenubar() const; Menu const & getMenubar() const;
/// ///
bool empty() const { return menulist_.empty(); } bool empty() const { return menulist_.empty(); }
/** This defines a menu whose entries list the FuncRequests
will be removed by expand() in other menus. This is used by
the Qt/Mac code
*/
void specialMenu(std::string const &);
/// Expands some special entries of the menu /// Expands some special entries of the menu
/** The entries with the following kind are expanded to a /** The entries with the following kind are expanded to a
sequence of Command MenuItems: Lastfiles, Documents, sequence of Command MenuItems: Lastfiles, Documents,
@ -229,6 +238,8 @@ private:
MenuList menulist_; MenuList menulist_;
/// ///
Menu menubar_; Menu menubar_;
///
Menu * specialmenu_;
}; };
/// ///

View File

@ -1,3 +1,20 @@
2004-08-11 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
Fix problem with the menu merging functionality of Qt/Mac. All the
code below is #ifdef Q_WS_MACX.
* QLPopupMenu.C (showing): append dummy entries to one menu (so that
Qt/Mac moves them to the LyX menu) and give them special index value.
(fire): if index is more than indexOffset, dispatch to the
corresponding entry from the "LyX" menu.
* lyx_gui.C (parse_init): add a new translator whose sole purpose
is to hide some menu entries from Qt/Mac scrutiny and avoid some
menu merging.
* QLMenubar.C (QLMenubar): Use "LyX" as special menu; initialize
the contents of the first menu in the menubar
2004-08-14 Jean-Marc Lasgouttes <lasgouttes@lyx.org> 2004-08-14 Jean-Marc Lasgouttes <lasgouttes@lyx.org>
* QPrefsDialog.C (change_color): * QPrefsDialog.C (change_color):

View File

@ -22,14 +22,13 @@
#include <qmenubar.h> #include <qmenubar.h>
#include <qcursor.h> #include <qcursor.h>
using std::pair; using std::pair;
using std::string; using std::string;
namespace lyx { namespace lyx {
namespace frontend { namespace frontend {
QLMenubar::QLMenubar(LyXView * view, MenuBackend const & mbe) QLMenubar::QLMenubar(LyXView * view, MenuBackend & mbe)
: owner_(static_cast<QtView*>(view)), menubackend_(mbe) : owner_(static_cast<QtView*>(view)), menubackend_(mbe)
#ifdef Q_WS_MACX #ifdef Q_WS_MACX
, menubar_(new QMenuBar) , menubar_(new QMenuBar)
@ -41,18 +40,14 @@ QLMenubar::QLMenubar(LyXView * view, MenuBackend const & mbe)
pair<int, QLPopupMenu *> menu = pair<int, QLPopupMenu *> menu =
createMenu(menuBar(), &(*m), this, true); createMenu(menuBar(), &(*m), this, true);
name_map_[m->submenuname()] = menu.second; name_map_[m->submenuname()] = menu.second;
#ifdef Q_WS_MACX
/* The qt/mac menu code has a very silly hack that
moves some menu entries that it recognizes by name
(ex: "Preferences...") to the "LyX" menu. This
feature can only work if the menu entries are
always available. Since we build menus on demand,
we have to have a reasonable default value before
the menus have been explicitely opened. (JMarc)
*/
menu.second->showing();
#endif
} }
#ifdef Q_WS_MACX
// this is the name of the menu that contains our special entries
menubackend_.specialMenu("LyX");
// make sure that the special entries are added to the first
// menu even before this menu has been opened.
name_map_[mbe.getMenubar().begin()->submenuname()]->showing();
#endif
} }
void QLMenubar::openByName(string const & name) void QLMenubar::openByName(string const & name)

View File

@ -29,7 +29,7 @@ class QtView;
class QLMenubar : public Menubar { class QLMenubar : public Menubar {
public: public:
QLMenubar(LyXView *, MenuBackend const &); QLMenubar(LyXView *, MenuBackend &);
/// opens a top-level submenu given its name /// opens a top-level submenu given its name
void openByName(std::string const &); void openByName(std::string const &);
@ -47,7 +47,7 @@ private:
QtView * owner_; QtView * owner_;
/// menu controller /// menu controller
MenuBackend const & menubackend_; MenuBackend & menubackend_;
typedef std::map<std::string, QLPopupMenu *> NameMap; typedef std::map<std::string, QLPopupMenu *> NameMap;

View File

@ -57,6 +57,11 @@ string const getLabel(MenuItem const & mi)
return label; return label;
} }
#ifdef Q_WS_MACX
// The offset added to the special Mac menu entries
const int indexOffset = 5000;
#endif
} // namespace anon } // namespace anon
@ -84,6 +89,12 @@ QLPopupMenu::QLPopupMenu(QLMenubar * owner,
void QLPopupMenu::fire(int index) void QLPopupMenu::fire(int index)
{ {
qApp->processEvents(); qApp->processEvents();
#ifdef Q_WS_MACX
if (index >= indexOffset) {
MenuItem mi = owner_->backend().getMenu("LyX")[index - indexOffset];
owner_->view()->activated(mi.func());
} else
#endif
owner_->view()->activated(funcs_[index]); owner_->view()->activated(funcs_[index]);
} }
@ -101,7 +112,7 @@ void QLPopupMenu::populate(Menu * menu)
pair<int, QLPopupMenu *> res = createMenu(this, &(*m), owner_); pair<int, QLPopupMenu *> res = createMenu(this, &(*m), owner_);
setItemEnabled(res.first, m->status().enabled()); setItemEnabled(res.first, m->status().enabled());
res.second->populate(m->submenu()); res.second->populate(m->submenu());
} else { } else { // we have a MenuItem::Command
FuncStatus const status = m->status(); FuncStatus const status = m->status();
Funcs::iterator fit = Funcs::iterator fit =
@ -131,6 +142,8 @@ void QLPopupMenu::populate(Menu * menu)
label += '\t' + toqstr(binding); label += '\t' + toqstr(binding);
} }
#endif #endif
// Actually insert the menu item
insertItem(label, index); insertItem(label, index);
setItemEnabled(index, status.enabled()); setItemEnabled(index, status.enabled());
setItemChecked(index, status.onoff(true)); setItemChecked(index, status.onoff(true));
@ -146,6 +159,24 @@ void QLPopupMenu::showing()
Menu const frommenu = owner_->backend().getMenu(name_); Menu const frommenu = owner_->backend().getMenu(name_);
owner_->backend().expand(frommenu, tomenu, owner_->view()); owner_->backend().expand(frommenu, tomenu, owner_->view());
populate(&tomenu); populate(&tomenu);
#ifdef Q_WS_MACX
/* The qt/mac menu code has a very silly hack that
moves some menu entries that it recognizes by name
(e.g. "Preferences...") to the "LyX" menu. This
feature can only work if the menu entries are
always available. Since we build menus on demand,
we add some dummy contents to one of the menus (JMarc)
*/
static QLPopupMenu * themenu = this;
if (themenu == this && owner_->backend().hasMenu("LyX")) {
Menu special = owner_->backend().getMenu("LyX");
Menu::const_iterator end = special.end();
Menu::size_type i = 0;
for (Menu::const_iterator cit = special.begin();
cit != end ; ++cit, ++i)
insertItem(toqstr(cit->label()), indexOffset + i);
}
#endif
} }
} // namespace frontend } // namespace frontend

View File

@ -152,7 +152,6 @@ namespace lyx_gui {
bool use_gui = true; bool use_gui = true;
void parse_init(int & argc, char * argv[]) void parse_init(int & argc, char * argv[])
{ {
static LQApplication app(argc, argv); static LQApplication app(argc, argv);
@ -175,6 +174,23 @@ void parse_init(int & argc, char * argv[])
<< QTextCodec::locale() << std::endl; << QTextCodec::locale() << std::endl;
#endif #endif
#ifdef Q_WS_MACX
// These translations are meant to break Qt/Mac menu merging
// algorithm on some entries. It lists the menu names that
// should not be moved to the LyX menu
static QTranslator aqua_trans(0);
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
"do_not_merge_me"));
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
"do_not_merge_me"));
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Options", 0,
"do_not_merge_me"));
aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
"do_not_merge_me"));
app.installTranslator(&aqua_trans);
#endif
using namespace lyx::graphics; using namespace lyx::graphics;
Image::newImage = boost::bind(&QLImage::newImage); Image::newImage = boost::bind(&QLImage::newImage);