]> git.lyx.org Git - features.git/commitdiff
merge MenuBackend into frontend/Menus
authorAndré Pönitz <poenitz@gmx.net>
Fri, 7 Mar 2008 00:21:23 +0000 (00:21 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Fri, 7 Mar 2008 00:21:23 +0000 (00:21 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23527 a592a061-630c-0410-9148-cb99ea01b6c8

src/Makefile.am
src/MenuBackend.cpp [deleted file]
src/MenuBackend.h [deleted file]
src/frontends/Application.h
src/frontends/qt4/GuiApplication.cpp
src/frontends/qt4/GuiApplication.h
src/frontends/qt4/GuiPopupMenu.cpp
src/frontends/qt4/GuiPopupMenu.h
src/frontends/qt4/GuiWorkArea.cpp
src/frontends/qt4/Menus.cpp
src/frontends/qt4/Menus.h

index 36d8cdd478bb0f3bb54425dc248a8467ed7c971d..cf22a0b3b9c6be7e04b2f1a3bda9d0d480b562e6 100644 (file)
@@ -63,8 +63,6 @@ lyx_SOURCES = \
        $(ASPELL) $(PSPELL) $(ISPELL) SpellBase.cpp \
        Box.cpp \
        Box.h \
-       MenuBackend.cpp \
-       MenuBackend.h \
        Dimension.cpp \
        Dimension.h \
        PrinterParams.cpp \
diff --git a/src/MenuBackend.cpp b/src/MenuBackend.cpp
deleted file mode 100644 (file)
index 4409135..0000000
+++ /dev/null
@@ -1,1069 +0,0 @@
-/**
- * \file MenuBackend.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Asger Alstrup
- * \author Lars Gullik Bjønnes
- * \author Jean-Marc Lasgouttes
- * \author André Pönitz
- * \author Dekel Tsur
- * \author Martin Vermeer
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "MenuBackend.h"
-
-#include "BranchList.h"
-#include "Buffer.h"
-#include "BufferList.h"
-#include "BufferParams.h"
-#include "Converter.h"
-#include "CutAndPaste.h"
-#include "Floating.h"
-#include "FloatList.h"
-#include "Format.h"
-#include "KeyMap.h"
-#include "Session.h"
-#include "LyXAction.h"
-#include "LyX.h" // for lastfiles
-#include "LyXFunc.h"
-#include "Lexer.h"
-#include "Paragraph.h"
-#include "TextClass.h"
-#include "TocBackend.h"
-#include "ToolbarBackend.h"
-
-#include "frontends/Application.h"
-
-#include "support/convert.h"
-#include "support/debug.h"
-#include "support/filetools.h"
-#include "support/gettext.h"
-#include "support/lstrings.h"
-
-#include <boost/bind.hpp>
-
-#include <algorithm>
-#include <ostream>
-
-using namespace std;
-using boost::bind;
-using namespace lyx::support;
-
-namespace lyx {
-
-namespace {
-
-class MenuNamesEqual : public unary_function<Menu, bool> {
-public:
-       MenuNamesEqual(docstring const & name)
-               : name_(name) {}
-       bool operator()(Menu const & menu) const {
-               return menu.name() == name_;
-       }
-private:
-       docstring name_;
-};
-
-} // namespace anon
-
-
-MenuItem::MenuItem(Kind kind)
-       : kind_(kind), optional_(false)
-{}
-
-
-MenuItem::MenuItem(Kind kind, docstring const & label,
-                  docstring const & submenu, bool optional)
-       : kind_(kind), label_(label),
-         submenuname_(submenu), optional_(optional)
-{
-       BOOST_ASSERT(kind == Submenu);
-}
-
-
-MenuItem::MenuItem(Kind kind, docstring const & label,
-                  FuncRequest const & func, bool optional)
-       : kind_(kind), label_(label), func_(func), optional_(optional)
-{
-       func_.origin = FuncRequest::MENU;
-}
-
-
-MenuItem::~MenuItem()
-{}
-
-
-void MenuItem::submenu(Menu * menu)
-{
-       submenu_.reset(menu);
-}
-
-
-docstring const MenuItem::label() const
-{
-       return token(label_, char_type('|'), 0);
-}
-
-
-docstring const MenuItem::shortcut() const
-{
-       return token(label_, char_type('|'), 1);
-}
-
-
-docstring const MenuItem::binding() const
-{
-       if (kind_ != Command)
-               return docstring();
-
-       // Get the keys bound to this action, but keep only the
-       // first one later
-       KeyMap::Bindings bindings = theTopLevelKeymap().findBindings(func_);
-
-       if (bindings.size())
-               return bindings.begin()->print(KeySequence::ForGui);
-
-       LYXERR(Debug::KBMAP, "No binding for "
-               << lyxaction.getActionName(func_.action)
-               << '(' << to_utf8(func_.argument()) << ')');
-       return docstring();
-}
-
-
-Menu & Menu::add(MenuItem const & i)
-{
-       items_.push_back(i);
-       return *this;
-}
-
-
-Menu & Menu::addWithStatusCheck(MenuItem const & i)
-{
-       switch (i.kind()) {
-
-       case MenuItem::Command: {
-               FuncStatus status = lyx::getStatus(i.func());
-               if (status.unknown() || (!status.enabled() && i.optional()))
-                       break;
-               items_.push_back(i);
-               items_.back().status(status);
-               break;
-       }
-
-       case MenuItem::Submenu: {
-               if (i.submenu()) {
-                       bool enabled = false;
-                       for (const_iterator cit = i.submenu()->begin();
-                            cit != i.submenu()->end(); ++cit) {
-                               if ((cit->kind() == MenuItem::Command
-                                    || cit->kind() == MenuItem::Submenu)
-                                   && cit->status().enabled()) {
-                                       enabled = true;
-                                       break;
-                               }
-                       }
-                       if (enabled || !i.optional()) {
-                               items_.push_back(i);
-                               items_.back().status().enabled(enabled);
-                       }
-               }
-               else
-                       items_.push_back(i);
-               break;
-       }
-
-       case MenuItem::Separator:
-               if (!items_.empty()
-                   && items_.back().kind() != MenuItem::Separator)
-                       items_.push_back(i);
-               break;
-
-       default:
-               items_.push_back(i);
-       }
-
-       return *this;
-}
-
-
-Menu & Menu::read(Lexer & lex)
-{
-       enum Menutags {
-               md_item = 1,
-               md_branches,
-               md_documents,
-               md_bookmarks,
-               md_charstyles,
-               md_custom,
-               md_elements,
-               md_endmenu,
-               md_exportformats,
-               md_importformats,
-               md_lastfiles,
-               md_optitem,
-               md_optsubmenu,
-               md_separator,
-               md_submenu,
-               md_toc,
-               md_updateformats,
-               md_viewformats,
-               md_floatlistinsert,
-               md_floatinsert,
-               md_pasterecent,
-               md_toolbars,
-               md_last
-       };
-
-       struct keyword_item menutags[md_last - 1] = {
-               { "bookmarks", md_bookmarks },
-               { "branches", md_branches },
-               { "charstyles", md_charstyles },
-               { "custom", md_custom },
-               { "documents", md_documents },
-               { "elements", md_elements },
-               { "end", md_endmenu },
-               { "exportformats", md_exportformats },
-               { "floatinsert", md_floatinsert },
-               { "floatlistinsert", md_floatlistinsert },
-               { "importformats", md_importformats },
-               { "item", md_item },
-               { "lastfiles", md_lastfiles },
-               { "optitem", md_optitem },
-               { "optsubmenu", md_optsubmenu },
-               { "pasterecent", md_pasterecent },
-               { "separator", md_separator },
-               { "submenu", md_submenu },
-               { "toc", md_toc },
-               { "toolbars", md_toolbars },
-               { "updateformats", md_updateformats },
-               { "viewformats", md_viewformats }
-       };
-
-       lex.pushTable(menutags, md_last - 1);
-       if (lyxerr.debugging(Debug::PARSER))
-               lex.printTable(lyxerr);
-
-       bool quit = false;
-       bool optional = false;
-
-       while (lex.isOK() && !quit) {
-               switch (lex.lex()) {
-               case md_optitem:
-                       optional = true;
-                       // fallback to md_item
-               case md_item: {
-                       lex.next(true);
-                       docstring const name = translateIfPossible(lex.getDocString());
-                       lex.next(true);
-                       string const command = lex.getString();
-                       FuncRequest func = lyxaction.lookupFunc(command);
-                       add(MenuItem(MenuItem::Command, name, func, optional));
-                       optional = false;
-                       break;
-               }
-
-               case md_separator:
-                       add(MenuItem(MenuItem::Separator));
-                       break;
-
-               case md_lastfiles:
-                       add(MenuItem(MenuItem::Lastfiles));
-                       break;
-
-               case md_charstyles:
-                       add(MenuItem(MenuItem::CharStyles));
-                       break;
-
-               case md_custom:
-                       add(MenuItem(MenuItem::Custom));
-                       break;
-
-               case md_elements:
-                       add(MenuItem(MenuItem::Elements));
-                       break;
-
-               case md_documents:
-                       add(MenuItem(MenuItem::Documents));
-                       break;
-
-               case md_bookmarks:
-                       add(MenuItem(MenuItem::Bookmarks));
-                       break;
-
-               case md_toc:
-                       add(MenuItem(MenuItem::Toc));
-                       break;
-
-               case md_viewformats:
-                       add(MenuItem(MenuItem::ViewFormats));
-                       break;
-
-               case md_updateformats:
-                       add(MenuItem(MenuItem::UpdateFormats));
-                       break;
-
-               case md_exportformats:
-                       add(MenuItem(MenuItem::ExportFormats));
-                       break;
-
-               case md_importformats:
-                       add(MenuItem(MenuItem::ImportFormats));
-                       break;
-
-               case md_floatlistinsert:
-                       add(MenuItem(MenuItem::FloatListInsert));
-                       break;
-
-               case md_floatinsert:
-                       add(MenuItem(MenuItem::FloatInsert));
-                       break;
-
-               case md_pasterecent:
-                       add(MenuItem(MenuItem::PasteRecent));
-                       break;
-
-               case md_toolbars:
-                       add(MenuItem(MenuItem::Toolbars));
-                       break;
-
-               case md_branches:
-                       add(MenuItem(MenuItem::Branches));
-                       break;
-
-               case md_optsubmenu:
-                       optional = true;
-                       // fallback to md_submenu
-               case md_submenu: {
-                       lex.next(true);
-                       docstring const mlabel = translateIfPossible(lex.getDocString());
-                       lex.next(true);
-                       docstring const mname = lex.getDocString();
-                       add(MenuItem(MenuItem::Submenu, mlabel, mname,
-                                    optional));
-                       optional = false;
-                       break;
-               }
-
-               case md_endmenu:
-                       quit = true;
-                       break;
-
-               default:
-                       lex.printError("Menu::read: "
-                                      "Unknown menu tag: `$$Token'");
-                       break;
-               }
-       }
-       lex.popTable();
-       return *this;
-}
-
-
-MenuItem const & Menu::operator[](size_type i) const
-{
-       return items_[i];
-}
-
-
-bool Menu::hasFunc(FuncRequest const & func) const
-{
-       return find_if(begin(), end(),
-                      bind(equal_to<FuncRequest>(),
-                           bind(&MenuItem::func, _1),
-                           func)) != end();
-}
-
-void Menu::checkShortcuts() const
-{
-       // This is a quadratic algorithm, but we do not care because
-       // menus are short enough
-       for (const_iterator it1 = begin(); it1 != end(); ++it1) {
-               docstring shortcut = it1->shortcut();
-               if (shortcut.empty())
-                       continue;
-               if (!contains(it1->label(), shortcut))
-                       lyxerr << "Menu warning: menu entry \""
-                              << to_utf8(it1->label())
-                              << "\" does not contain shortcut `"
-                              << to_utf8(shortcut) << "'." << endl;
-               for (const_iterator it2 = begin(); it2 != it1 ; ++it2) {
-                       if (!compare_ascii_no_case(it2->shortcut(), shortcut)) {
-                               lyxerr << "Menu warning: menu entries "
-                                      << '"' << to_utf8(it1->fulllabel())
-                                      << "\" and \"" << to_utf8(it2->fulllabel())
-                                      << "\" share the same shortcut."
-                                      << endl;
-                       }
-               }
-       }
-}
-
-
-bool Menu::searchMenu(FuncRequest const & func, vector<docstring> & names) const
-{
-       const_iterator m = begin();
-       const_iterator m_end = end();
-       for (; m != m_end; ++m) {
-               if (m->kind() == MenuItem::Command && m->func() == func) {
-                       names.push_back(m->label());
-                       return true;
-               }
-               if (m->kind() == MenuItem::Submenu) {
-                       names.push_back(m->label());
-                       Menu submenu = theApp()->menuBackend().getMenu(m->submenuname());
-                       if (submenu.searchMenu(func, names))
-                               return true;
-                       names.pop_back();
-               }
-       }
-       return false;
-}
-
-
-void MenuBackend::specialMenu(Menu const & menu)
-{
-       specialmenu_ = menu;
-}
-
-
-namespace {
-
-class compare_format {
-public:
-       bool operator()(Format const * p1, Format const * p2) {
-               return *p1 < *p2;
-       }
-};
-
-docstring const limit_string_length(docstring const & str)
-{
-       docstring::size_type const max_item_length = 45;
-
-       if (str.size() > max_item_length)
-               return str.substr(0, max_item_length - 3) + "...";
-       else
-               return str;
-}
-
-
-void expandLastfiles(Menu & tomenu)
-{
-       lyx::LastFilesSection::LastFiles const & lf = LyX::cref().session().lastFiles().lastFiles();
-       lyx::LastFilesSection::LastFiles::const_iterator lfit = lf.begin();
-
-       int ii = 1;
-
-       for (; lfit != lf.end() && ii < 10; ++lfit, ++ii) {
-               string const file = lfit->absFilename();
-               docstring const label = convert<docstring>(ii) + ". "
-                       + makeDisplayPath(file, 30)
-                       + char_type('|') + convert<docstring>(ii);
-               tomenu.add(MenuItem(MenuItem::Command, label, FuncRequest(LFUN_FILE_OPEN, file)));
-       }
-}
-
-
-void expandDocuments(Menu & tomenu)
-{
-       Buffer * first = theBufferList().first();
-       if (first) {
-               Buffer * b = first;
-               int ii = 1;
-               
-               // We cannot use a for loop as the buffer list cycles.
-               do {
-                       docstring label = b->fileName().displayName(20);
-                       if (!b->isClean())
-                               label = label + "*";
-                       if (ii < 10)
-                               label = convert<docstring>(ii) + ". " + label + '|' + convert<docstring>(ii);
-                       tomenu.add(MenuItem(MenuItem::Command, label,
-                               FuncRequest(LFUN_BUFFER_SWITCH, b->absFileName())));
-                       
-                       b = theBufferList().next(b);
-                       ++ii;
-               } while (b != first); 
-       } else {
-               tomenu.add(MenuItem(MenuItem::Command, _("No Documents Open!"),
-                          FuncRequest(LFUN_NOACTION)));
-       }
-}
-
-
-void expandBookmarks(Menu & tomenu)
-{
-       lyx::BookmarksSection const & bm = LyX::cref().session().bookmarks();
-
-       for (size_t i = 1; i <= bm.size(); ++i) {
-               if (bm.isValid(i)) {
-                       docstring const label = convert<docstring>(i) + ". "
-                               + makeDisplayPath(bm.bookmark(i).filename.absFilename(), 20)
-                               + char_type('|') + convert<docstring>(i);
-                       tomenu.add(MenuItem(MenuItem::Command, label, FuncRequest(LFUN_BOOKMARK_GOTO,
-                               convert<docstring>(i))));
-               }
-       }
-}
-
-
-void expandFormats(MenuItem::Kind kind, Menu & tomenu, Buffer const * buf)
-{
-       if (!buf && kind != MenuItem::ImportFormats) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-
-       typedef vector<Format const *> Formats;
-       Formats formats;
-       kb_action action;
-
-       switch (kind) {
-       case MenuItem::ImportFormats:
-               formats = theConverters().importableFormats();
-               action = LFUN_BUFFER_IMPORT;
-               break;
-       case MenuItem::ViewFormats:
-               formats = buf->exportableFormats(true);
-               action = LFUN_BUFFER_VIEW;
-               break;
-       case MenuItem::UpdateFormats:
-               formats = buf->exportableFormats(true);
-               action = LFUN_BUFFER_UPDATE;
-               break;
-       default:
-               formats = buf->exportableFormats(false);
-               action = LFUN_BUFFER_EXPORT;
-       }
-       sort(formats.begin(), formats.end(), compare_format());
-
-       Formats::const_iterator fit = formats.begin();
-       Formats::const_iterator end = formats.end();
-       for (; fit != end ; ++fit) {
-               if ((*fit)->dummy())
-                       continue;
-               docstring label = from_utf8((*fit)->prettyname());
-               docstring const shortcut = from_utf8((*fit)->shortcut());
-
-               switch (kind) {
-               case MenuItem::ImportFormats:
-                       // FIXME: This is a hack, we should rather solve
-                       // FIXME: bug 2488 instead.
-                       if ((*fit)->name() == "text")
-                               label = _("Plain Text");
-                       else if ((*fit)->name() == "textparagraph")
-                               label = _("Plain Text, Join Lines");
-                       label += "...";
-                       break;
-               case MenuItem::ViewFormats:
-               case MenuItem::ExportFormats:
-               case MenuItem::UpdateFormats:
-                       if (!(*fit)->documentFormat())
-                               continue;
-                       break;
-               default:
-                       BOOST_ASSERT(false);
-                       break;
-               }
-               // FIXME: if we had proper support for translating the
-               // format names defined in configure.py, there would
-               // not be a need to check whether the shortcut is
-               // correct. If we add it uncondiitonally, it would
-               // create useless warnings on bad shortcuts
-               if (!shortcut.empty() && contains(label, shortcut))
-                       label += char_type('|') + shortcut;
-
-               if (buf)
-                       tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, label,
-                               FuncRequest(action, (*fit)->name())));
-               else
-                       tomenu.add(MenuItem(MenuItem::Command, label,
-                               FuncRequest(action, (*fit)->name())));
-       }
-}
-
-
-void expandFloatListInsert(Menu & tomenu, Buffer const * buf)
-{
-       if (!buf) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-
-       FloatList const & floats = buf->params().documentClass().floats();
-       FloatList::const_iterator cit = floats.begin();
-       FloatList::const_iterator end = floats.end();
-       for (; cit != end; ++cit) {
-               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command,
-                                   _(cit->second.listName()),
-                                   FuncRequest(LFUN_FLOAT_LIST,
-                                               cit->second.type())));
-       }
-}
-
-
-void expandFloatInsert(Menu & tomenu, Buffer const * buf)
-{
-       if (!buf) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-
-       FloatList const & floats = buf->params().documentClass().floats();
-       FloatList::const_iterator cit = floats.begin();
-       FloatList::const_iterator end = floats.end();
-       for (; cit != end; ++cit) {
-               // normal float
-               docstring const label = _(cit->second.name());
-               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, label,
-                                   FuncRequest(LFUN_FLOAT_INSERT,
-                                               cit->second.type())));
-       }
-}
-
-
-void expandFlexInsert(Menu & tomenu, Buffer const * buf, string s)
-{
-       if (!buf) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-       TextClass::InsetLayouts const & insetLayouts =
-               buf->params().documentClass().insetLayouts();
-       TextClass::InsetLayouts::const_iterator cit = insetLayouts.begin();
-       TextClass::InsetLayouts::const_iterator end = insetLayouts.end();
-       for (; cit != end; ++cit) {
-               docstring const label = cit->first;
-               if (cit->second.lyxtype() == s)
-                       tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, 
-                               label, FuncRequest(LFUN_FLEX_INSERT,
-                                               label)));
-       }
-}
-
-
-Menu::size_type const max_number_of_items = 25;
-
-void expandToc2(Menu & tomenu,
-               Toc const & toc_list,
-               Toc::size_type from,
-               Toc::size_type to, int depth)
-{
-       int shortcut_count = 0;
-
-       // check whether depth is smaller than the smallest depth in toc.
-       int min_depth = 1000;
-       for (Toc::size_type i = from; i < to; ++i)
-               min_depth = min(min_depth, toc_list[i].depth());
-       if (min_depth > depth)
-               depth = min_depth;
-
-
-       if (to - from <= max_number_of_items) {
-               for (Toc::size_type i = from; i < to; ++i) {
-                       docstring label(4 * max(0, toc_list[i].depth() - depth), char_type(' '));
-                       label += limit_string_length(toc_list[i].str());
-                       if (toc_list[i].depth() == depth
-                           && shortcut_count < 9) {
-                               if (label.find(convert<docstring>(shortcut_count + 1)) != docstring::npos)
-                                       label += char_type('|') + convert<docstring>(++shortcut_count);
-                       }
-                       tomenu.add(MenuItem(MenuItem::Command, label,
-                                           FuncRequest(toc_list[i].action())));
-               }
-       } else {
-               Toc::size_type pos = from;
-               while (pos < to) {
-                       Toc::size_type new_pos = pos + 1;
-                       while (new_pos < to &&
-                              toc_list[new_pos].depth() > depth)
-                               ++new_pos;
-
-                       docstring label(4 * max(0, toc_list[pos].depth() - depth), ' ');
-                       label += limit_string_length(toc_list[pos].str());
-                       if (toc_list[pos].depth() == depth &&
-                           shortcut_count < 9) {
-                               if (label.find(convert<docstring>(shortcut_count + 1)) != docstring::npos)
-                                       label += char_type('|') + convert<docstring>(++shortcut_count);
-                       }
-                       if (new_pos == pos + 1) {
-                               tomenu.add(MenuItem(MenuItem::Command,
-                                                   label, FuncRequest(toc_list[pos].action())));
-                       } else {
-                               MenuItem item(MenuItem::Submenu, label);
-                               item.submenu(new Menu);
-                               expandToc2(*item.submenu(),
-                                          toc_list, pos, new_pos, depth + 1);
-                               tomenu.add(item);
-                       }
-                       pos = new_pos;
-               }
-       }
-}
-
-
-void expandToc(Menu & tomenu, Buffer const * buf)
-{
-       // To make things very cleanly, we would have to pass buf to
-       // all MenuItem constructors and to expandToc2. However, we
-       // know that all the entries in a TOC will be have status_ ==
-       // OK, so we avoid this unnecessary overhead (JMarc)
-
-       if (!buf) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-
-       Buffer* cbuf = const_cast<Buffer*>(buf);
-       cbuf->tocBackend().update();
-       cbuf->structureChanged();
-
-       // Add an entry for the master doc if this is a child doc
-       Buffer const * const master = buf->masterBuffer();
-       if (buf != master) {
-               ParIterator const pit = par_iterator_begin(master->inset());
-               string const arg = convert<string>(pit->id());
-               FuncRequest f(LFUN_PARAGRAPH_GOTO, arg);
-               tomenu.add(MenuItem(MenuItem::Command, _("Master Document"), f));
-       }
-
-       FloatList const & floatlist = buf->params().documentClass().floats();
-       TocList const & toc_list = buf->tocBackend().tocs();
-       TocList::const_iterator cit = toc_list.begin();
-       TocList::const_iterator end = toc_list.end();
-       for (; cit != end; ++cit) {
-               // Handle this later
-               if (cit->first == "tableofcontents")
-                       continue;
-
-               // All the rest is for floats
-               auto_ptr<Menu> menu(new Menu);
-               TocIterator ccit = cit->second.begin();
-               TocIterator eend = cit->second.end();
-               for (; ccit != eend; ++ccit) {
-                       docstring const label = limit_string_length(ccit->str());
-                       menu->add(MenuItem(MenuItem::Command,
-                                          label,
-                                          FuncRequest(ccit->action())));
-               }
-               string const & floatName = floatlist.getType(cit->first).listName();
-               docstring label;
-               if (!floatName.empty())
-                       label = _(floatName);
-               // BUG3633: listings is not a proper float so its name
-               // is not shown in floatlist.
-               else if (cit->first == "equation")
-                       label = _("List of Equations");
-               else if (cit->first == "index")
-                       label = _("List of Indexes");
-               else if (cit->first == "listing")
-                       label = _("List of Listings");
-               else if (cit->first == "marginalnote")
-                       label = _("List of Marginal notes");
-               else if (cit->first == "note")
-                       label = _("List of Notes");
-               else if (cit->first == "footnote")
-                       label = _("List of Foot notes");
-               else if (cit->first == "label")
-                       label = _("Labels and References");
-               else if (cit->first == "citation")
-                       label = _("List of Citations");
-               // this should not happen now, but if something else like
-               // listings is added later, this can avoid an empty menu name.
-               else
-                       label = _("Other floats");
-               MenuItem item(MenuItem::Submenu, label);
-               item.submenu(menu.release());
-               tomenu.add(item);
-       }
-
-       // Handle normal TOC
-       cit = toc_list.find("tableofcontents");
-       if (cit == end) {
-               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command,
-                                   _("No Table of contents"),
-                                   FuncRequest()));
-       } else {
-               expandToc2(tomenu, cit->second, 0, cit->second.size(), 0);
-       }
-}
-
-
-void expandPasteRecent(Menu & tomenu)
-{
-       vector<docstring> const sel = cap::availableSelections();
-
-       vector<docstring>::const_iterator cit = sel.begin();
-       vector<docstring>::const_iterator end = sel.end();
-
-       for (unsigned int index = 0; cit != end; ++cit, ++index) {
-               tomenu.add(MenuItem(MenuItem::Command, *cit,
-                                   FuncRequest(LFUN_PASTE, convert<string>(index))));
-       }
-}
-
-
-void expandToolbars(Menu & tomenu)
-{
-       //
-       // extracts the toolbars from the backend
-       ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin();
-       ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end();
-
-       for (; cit != end; ++cit) {
-               docstring label = _(cit->gui_name);
-               // frontends are not supposed to turn on/off toolbars,
-               // if they cannot update ToolbarBackend::flags. That
-               // is to say, ToolbarsBackend::flags should reflect
-               // the true state of toolbars.
-               //
-               // menu is displayed as
-               //       on/off review
-               // and
-               //              review (auto)
-               // in the case of auto.
-               if (cit->flags & ToolbarInfo::AUTO)
-                       label += _(" (auto)");
-               tomenu.add(MenuItem(MenuItem::Command, label,
-                                   FuncRequest(LFUN_TOOLBAR_TOGGLE, cit->name + " allowauto")));
-       }
-}
-
-
-void expandBranches(Menu & tomenu, Buffer const * buf)
-{
-       if (!buf) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-
-       BufferParams const & params = buf->masterBuffer()->params();
-       if (params.branchlist().empty()) {
-               tomenu.add(MenuItem(MenuItem::Command,
-                                   _("No Branch in Document!"),
-                                   FuncRequest(LFUN_NOACTION)));
-               return;
-       }
-
-       BranchList::const_iterator cit = params.branchlist().begin();
-       BranchList::const_iterator end = params.branchlist().end();
-
-       for (int ii = 1; cit != end; ++cit, ++ii) {
-               docstring label = cit->getBranch();
-               if (ii < 10)
-                       label = convert<docstring>(ii) + ". " + label + char_type('|') + convert<docstring>(ii);
-               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, label,
-                                   FuncRequest(LFUN_BRANCH_INSERT,
-                                               cit->getBranch())));
-       }
-}
-
-
-} // namespace anon
-
-
-void MenuBackend::expand(Menu const & frommenu, Menu & tomenu,
-                        Buffer const * buf) const
-{
-       if (!tomenu.empty())
-               tomenu.clear();
-
-       for (Menu::const_iterator cit = frommenu.begin();
-            cit != frommenu.end() ; ++cit) {
-               switch (cit->kind()) {
-               case MenuItem::Lastfiles:
-                       expandLastfiles(tomenu);
-                       break;
-
-               case MenuItem::Documents:
-                       expandDocuments(tomenu);
-                       break;
-
-               case MenuItem::Bookmarks:
-                       expandBookmarks(tomenu);
-                       break;
-
-               case MenuItem::ImportFormats:
-               case MenuItem::ViewFormats:
-               case MenuItem::UpdateFormats:
-               case MenuItem::ExportFormats:
-                       expandFormats(cit->kind(), tomenu, buf);
-                       break;
-
-               case MenuItem::CharStyles:
-                       expandFlexInsert(tomenu, buf, "charstyle");
-                       break;
-
-               case MenuItem::Custom:
-                       expandFlexInsert(tomenu, buf, "custom");
-                       break;
-
-               case MenuItem::Elements:
-                       expandFlexInsert(tomenu, buf, "element");
-                       break;
-
-               case MenuItem::FloatListInsert:
-                       expandFloatListInsert(tomenu, buf);
-                       break;
-
-               case MenuItem::FloatInsert:
-                       expandFloatInsert(tomenu, buf);
-                       break;
-
-               case MenuItem::PasteRecent:
-                       expandPasteRecent(tomenu);
-                       break;
-
-               case MenuItem::Toolbars:
-                       expandToolbars(tomenu);
-                       break;
-
-               case MenuItem::Branches:
-                       expandBranches(tomenu, buf);
-                       break;
-
-               case MenuItem::Toc:
-                       expandToc(tomenu, buf);
-                       break;
-
-               case MenuItem::Submenu: {
-                       MenuItem item(*cit);
-                       item.submenu(new Menu(cit->submenuname()));
-                       expand(getMenu(cit->submenuname()),
-                              *item.submenu(), buf);
-                       tomenu.addWithStatusCheck(item);
-               }
-               break;
-
-               case MenuItem::Separator:
-                       tomenu.addWithStatusCheck(*cit);
-                       break;
-
-               case MenuItem::Command:
-                       if (!specialmenu_.hasFunc(cit->func()))
-                               tomenu.addWithStatusCheck(*cit);
-               }
-       }
-
-       // we do not want the menu to end with a separator
-       if (!tomenu.empty()
-           && tomenu.items_.back().kind() == MenuItem::Separator)
-               tomenu.items_.pop_back();
-
-       // Check whether the shortcuts are unique
-       tomenu.checkShortcuts();
-}
-
-
-void MenuBackend::read(Lexer & lex)
-{
-       enum Menutags {
-               md_menu = 1,
-               md_menubar,
-               md_endmenuset,
-               md_last
-       };
-
-       struct keyword_item menutags[md_last - 1] = {
-               { "end", md_endmenuset },
-               { "menu", md_menu },
-               { "menubar", md_menubar }
-       };
-
-       //consistency check
-       if (compare_ascii_no_case(lex.getString(), "menuset")) {
-               lyxerr << "Menubackend::read: ERROR wrong token:`"
-                      << lex.getString() << '\'' << endl;
-       }
-
-       lex.pushTable(menutags, md_last - 1);
-       if (lyxerr.debugging(Debug::PARSER))
-               lex.printTable(lyxerr);
-
-       bool quit = false;
-
-       while (lex.isOK() && !quit) {
-               switch (lex.lex()) {
-               case md_menubar:
-                       menubar_.read(lex);
-                       break;
-               case md_menu: {
-                       lex.next(true);
-                       docstring const name = lex.getDocString();
-                       if (hasMenu(name)) {
-                               getMenu(name).read(lex);
-                       } else {
-                               Menu menu(name);
-                               menu.read(lex);
-                               add(menu);
-                       }
-                       break;
-               }
-               case md_endmenuset:
-                       quit = true;
-                       break;
-               default:
-                       lex.printError("menubackend::read: "
-                                      "Unknown menu tag: `$$Token'");
-                       break;
-               }
-       }
-       lex.popTable();
-}
-
-
-void MenuBackend::add(Menu const & menu)
-{
-       menulist_.push_back(menu);
-}
-
-
-bool MenuBackend::hasMenu(docstring const & name) const
-{
-       return find_if(begin(), end(), MenuNamesEqual(name)) != end();
-}
-
-
-Menu const & MenuBackend::getMenu(docstring const & name) const
-{
-       const_iterator cit = find_if(begin(), end(), MenuNamesEqual(name));
-       if (cit == end())
-               lyxerr << "No submenu named " << to_utf8(name) << endl;
-       BOOST_ASSERT(cit != end());
-       return (*cit);
-}
-
-
-Menu & MenuBackend::getMenu(docstring const & name)
-{
-       iterator it = find_if(begin(), end(), MenuNamesEqual(name));
-       if (it == end())
-               lyxerr << "No submenu named " << to_utf8(name) << endl;
-       BOOST_ASSERT(it != end());
-       return (*it);
-}
-
-
-Menu const & MenuBackend::getMenubar() const
-{
-       return menubar_;
-}
-
-
-} // namespace lyx
diff --git a/src/MenuBackend.h b/src/MenuBackend.h
deleted file mode 100644 (file)
index 65c2d97..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-// -*- C++ -*-
-/**
- * \file MenuBackend.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 Jean-Marc Lasgouttes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef MENUBACKEND_H
-#define MENUBACKEND_H
-
-#include "FuncStatus.h"
-#include "FuncRequest.h"
-
-#include <boost/shared_ptr.hpp>
-
-#include <vector>
-
-
-namespace lyx {
-
-class Lexer;
-class Buffer;
-class Menu;
-
-///
-class MenuItem {
-public:
-       /// The type of elements that can be in a menu
-       enum Kind {
-               ///
-               Command,
-               ///
-               Submenu,
-               ///
-               Separator,
-               /** This is the list of last opened file,
-                   typically for the File menu. */
-               Lastfiles,
-               /** This is the list of opened Documents,
-                   typically for the Documents menu. */
-               Documents,
-               /** This is the bookmarks */
-               Bookmarks,
-               ///
-               Toc,
-               /** This is a list of viewable formats
-                   typically for the File->View menu. */
-               ViewFormats,
-               /** This is a list of updatable formats
-                   typically for the File->Update menu. */
-               UpdateFormats,
-               /** This is a list of exportable formats
-                   typically for the File->Export menu. */
-               ExportFormats,
-               /** This is a list of importable formats
-                   typically for the File->Export menu. */
-               ImportFormats,
-               /** This is the list of elements available
-                * for insertion into document. */
-               CharStyles,
-               /** This is the list of user-configurable
-               insets to insert into document */
-               Custom,
-               /** This is the list of XML elements to
-               insert into the document */
-               Elements,
-               /** This is the list of floats that we can
-                   insert a list for. */
-               FloatListInsert,
-               /** This is the list of floats that we can
-                   insert. */
-               FloatInsert,
-               /** This is the list of selections that can
-                   be pasted. */
-               PasteRecent,
-               /** toolbars */
-               Toolbars,
-               /** Available branches in document */
-               Branches
-       };
-
-       explicit MenuItem(Kind kind);
-
-       MenuItem(Kind kind,
-                docstring const & label,
-                docstring const & submenu = docstring(),
-                bool optional = false);
-
-       MenuItem(Kind kind,
-                docstring const & label,
-                FuncRequest const & func,
-                bool optional = false);
-
-       /// This one is just to please boost::shared_ptr<>
-       ~MenuItem();
-       /// The label of a given menuitem
-       docstring const label() const;
-       /// The keyboard shortcut (usually underlined in the entry)
-       docstring const shortcut() const;
-       /// The complete label, with label and shortcut separated by a '|'
-       docstring const fulllabel() const { return label_;}
-       /// The kind of entry
-       Kind kind() const { return kind_; }
-       /// the action (if relevant)
-       FuncRequest const & func() const { return func_; }
-       /// returns true if the entry should be ommited when disabled
-       bool optional() const { return optional_; }
-       /// returns the status of the lfun associated with this entry
-       FuncStatus const & status() const { return status_; }
-       /// returns the status of the lfun associated with this entry
-       FuncStatus & status() { return status_; }
-       /// returns the status of the lfun associated with this entry
-       void status(FuncStatus const & status) { status_ = status; }
-       ///returns the binding associated to this action.
-       docstring const binding() const;
-       /// the description of the  submenu (if relevant)
-       docstring const & submenuname() const { return submenuname_; }
-       /// set the description of the  submenu
-       void submenuname(docstring const & name) { submenuname_ = name; }
-       ///
-       Menu * submenu() const { return submenu_.get(); }
-       ///
-       void submenu(Menu * menu);
-
-private:
-       //friend class MenuBackend;
-       ///
-       Kind kind_;
-       ///
-       docstring label_;
-       ///
-       FuncRequest func_;
-       ///
-       docstring submenuname_;
-       ///
-       bool optional_;
-       ///
-       FuncStatus status_;
-       ///
-       boost::shared_ptr<Menu> submenu_;
-};
-
-
-///
-class Menu {
-public:
-       ///
-       typedef std::vector<MenuItem> ItemList;
-       ///
-       typedef ItemList::const_iterator const_iterator;
-       ///
-       typedef ItemList::size_type size_type;
-       ///
-       explicit Menu(docstring const & name = docstring()) : name_(name) {}
-       /// Add the menu item unconditionally
-       Menu & add(MenuItem const &);
-       /// Checks the associated FuncRequest status before adding the
-       /// menu item.
-       Menu & addWithStatusCheck(MenuItem const &);
-       ///
-       Menu & read(Lexer &);
-       ///
-       docstring const & name() const { return name_; }
-       ///
-       bool empty() const { return items_.empty(); }
-       /// Clear the menu content.
-       void clear() { items_.clear(); }
-       ///
-       ItemList::size_type size() const { return items_.size(); }
-       ///
-       MenuItem const & operator[](size_type) const;
-       ///
-       bool hasFunc(FuncRequest const &) const;
-       ///
-       const_iterator begin() const { return items_.begin(); }
-       ///
-       const_iterator end() const { return items_.end(); }
-
-       // Check whether the menu shortcuts are unique
-       void checkShortcuts() const;
-       
-       // search for func in this menu iteratively, and put menu
-       // names in a stack.
-       bool searchMenu(FuncRequest const & func, std::vector<docstring> & names)
-               const;
-
-private:
-       friend class MenuBackend;
-       ///
-       ItemList items_;
-       ///
-       docstring name_;
-};
-
-
-///
-class MenuBackend {
-public:
-       ///
-       typedef std::vector<Menu> MenuList;
-       ///
-       typedef MenuList::const_iterator const_iterator;
-       ///
-       typedef MenuList::iterator iterator;
-       ///
-       MenuBackend() {}
-       ///
-       void read(Lexer &);
-       ///
-       void add(Menu const &);
-       ///
-       bool hasMenu(docstring const &) const;
-       ///
-       Menu & getMenu(docstring const &);
-       ///
-       Menu const & getMenu(docstring const &) const;
-       ///
-       Menu const & getMenubar() const;
-       ///
-       bool empty() const { return menulist_.empty(); }
-       /** This defines a menu whose entries list the FuncRequests
-           that will be removed by expand() in other menus. This is
-           used by the Qt/Mac code
-       */
-       void specialMenu(Menu const &);
-       ///
-       Menu const & specialMenu() { return specialmenu_; }
-
-       /// Expands some special entries of the menu
-       /** The entries with the following kind are expanded to a
-           sequence of Command MenuItems: Lastfiles, Documents,
-           ViewFormats, ExportFormats, UpdateFormats, Branches
-       */
-       void expand(Menu const & frommenu, Menu & tomenu,
-                   Buffer const *) const;
-       ///
-       const_iterator begin() const { return menulist_.begin(); }
-       ///
-       iterator begin() { return menulist_.begin(); }
-       ///
-       const_iterator end() const { return menulist_.end(); }
-       ///
-       iterator end() { return menulist_.end(); }
-
-private:
-       ///
-       MenuList menulist_;
-       ///
-       Menu menubar_;
-       ///
-       Menu specialmenu_;
-};
-
-} // namespace lyx
-
-#endif // MENUBACKEND_H
index ebb98e9aff8f9237ec15632d81e530c3361bf875..0cc2ed00f69eef03e37bcfa262035469e4d083a3 100644 (file)
@@ -29,7 +29,6 @@ class FuncRequest;
 class FuncStatus;
 class Inset;
 class Lexer;
-class MenuBackend;
 struct RGBColor;
 
 namespace frontend {
@@ -233,10 +232,6 @@ public:
        */
        virtual void unregisterSocketCallback(int fd) = 0;
 
-       ///
-       virtual MenuBackend const & menuBackend() const = 0;
-       virtual MenuBackend & menuBackend() = 0;
-
        virtual bool searchMenu(FuncRequest const & func,
                std::vector<docstring> & names) const = 0;
 };
index 0beb0f7c243bbc00a2998fb1973f5c1d2426375e..5c9d04894ca33aeb6d4259c07c445f8de076060b 100644 (file)
@@ -651,14 +651,14 @@ Buffer const * GuiApplication::updateInset(Inset const * inset) const
 
 void GuiApplication::readMenus(Lexer & lex)
 {
-       menuBackend().read(lex);
+       menus().read(lex);
 }
 
 
 bool GuiApplication::searchMenu(FuncRequest const & func,
        vector<docstring> & names) const
 {
-               return menuBackend().getMenubar().searchMenu(func, names);
+       return menus().getMenubar().searchMenu(func, names);
 }
 
 
index 5460de3bc80e078cac46336e13bf67384f88fb8a..f9a770a3ab910dee1b01c4413607f0d4f8fd6da9 100644 (file)
@@ -65,8 +65,6 @@ public:
        virtual Clipboard & clipboard();
        virtual Selection & selection();
        virtual FontLoader & fontLoader() { return font_loader_; }
-       MenuBackend const & menuBackend() const { return menus_; }
-       MenuBackend & menuBackend() { return menus_; }
        virtual int exec();
        virtual void exit(int status);
        virtual bool event(QEvent * e);
index cdbcf34bfa1d868c699f7ec55eab8d70918bd242..163be877fdcb03f6b4274699bfb677a6f4be1836 100644 (file)
 
 #include <config.h>
 
-#include "GuiView.h"
+#include "GuiPopupMenu.h"
 
 #include "Action.h"
 #include "GuiApplication.h"
-#include "GuiPopupMenu.h"
+#include "GuiView.h"
 #include "qt_helpers.h"
 
 #include "LyXFunc.h"
-#include "MenuBackend.h"
 
 #include "support/debug.h"
-#include "support/lstrings.h"
 
 namespace lyx {
 namespace frontend {
@@ -31,7 +29,7 @@ GuiPopupMenu::GuiPopupMenu(GuiView * owner, MenuItem const & mi,
                bool topLevelMenu)
        : QMenu(owner), owner_(owner)
 {
-       name_ = toqstr(mi.submenuname());
+       name_ = mi.submenuname();
 
        setTitle(label(mi));
 
@@ -53,13 +51,13 @@ void GuiPopupMenu::updateView()
        // Here, We make sure that theLyXFunc points to the correct LyXView.
        theLyXFunc().setLyXView(owner_);
 
-       MenuBackend const & menubackend = guiApp->menuBackend();
-       Menu const & fromLyxMenu = menubackend.getMenu(qstring_to_ucs4(name_));
-       menubackend.expand(fromLyxMenu, topLevelMenu_, owner_->buffer());
+       Menus const & menus = guiApp->menus();
+       Menu const & fromLyxMenu = menus.getMenu(name_);
+       menus.expand(fromLyxMenu, topLevelMenu_, owner_->buffer());
 
-       if (!menubackend.hasMenu(topLevelMenu_.name())) {
+       if (!menus.hasMenu(topLevelMenu_.name())) {
                LYXERR(Debug::GUI, "\tWARNING: menu seems empty"
-                       << to_utf8(topLevelMenu_.name()));
+                       << fromqstr(topLevelMenu_.name()));
        }
        populate(this, &topLevelMenu_);
 }
@@ -67,9 +65,9 @@ void GuiPopupMenu::updateView()
 
 void GuiPopupMenu::populate(QMenu * qMenu, Menu * menu)
 {
-       LYXERR(Debug::GUI, "populating menu " << to_utf8(menu->name()));
+       LYXERR(Debug::GUI, "populating menu " << fromqstr(menu->name()));
        if (menu->size() == 0) {
-               LYXERR(Debug::GUI, "\tERROR: empty menu " << to_utf8(menu->name()));
+               LYXERR(Debug::GUI, "\tERROR: empty menu " << fromqstr(menu->name()));
                return;
        }
        LYXERR(Debug::GUI, " *****  menu entries " << menu->size());
@@ -94,9 +92,9 @@ void GuiPopupMenu::populate(QMenu * qMenu, Menu * menu)
                } else { // we have a MenuItem::Command
 
                        LYXERR(Debug::GUI, "creating Menu Item "
-                               << to_utf8(m->label()));
+                               << fromqstr(m->label()));
 
-                       Action * action = new Action(*(owner_),
+                       Action * action = new Action(*owner_,
                                QIcon(), label(*m), m->func(), QString());
                        qMenu->addAction(action);
                }
@@ -106,21 +104,22 @@ void GuiPopupMenu::populate(QMenu * qMenu, Menu * menu)
 
 QString GuiPopupMenu::label(MenuItem const & mi) const
 {
-       docstring label = support::subst(mi.label(), 
-                                        from_ascii("&"), from_ascii("&&"));
-
-       docstring const shortcut = mi.shortcut();
-       if (!shortcut.empty()) {
-               size_t pos = label.find(shortcut);
-               if (pos != docstring::npos)
-                       label.insert(pos, 1, char_type('&'));
+       QString label = mi.label();
+       label.replace("&", "&&");
+
+       QString shortcut = mi.shortcut();
+       if (!shortcut.isEmpty()) {
+               int pos = label.indexOf(shortcut);
+               if (pos != -1)
+                       //label.insert(pos, 1, char_type('&'));
+                       label.replace(pos, 0, "&");
        }
 
-       docstring const binding = mi.binding();
-       if (!binding.empty())
+       QString const binding = mi.binding();
+       if (!binding.isEmpty())
                label += '\t' + binding;
 
-       return toqstr(label);
+       return label;
 }
 
 
index cf50f3b71c798777b842977e9f99747b17a97167..e17fd632a6f9196a3ebba7e2a950ace3befa1c2d 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef GUIPOPUPMENU_H
 #define GUIPOPUPMENU_H
 
-#include "MenuBackend.h"
+#include "Menus.h"
 
 #include <QMenu>
 
index 60a2de62657a62234c4abfa1f7211ba94ead1de6..81aad47b293c35e820cd39e9d901891632cc9e31 100644 (file)
@@ -23,7 +23,6 @@
 #include "GuiApplication.h"
 #include "GuiKeySymbol.h"
 #include "GuiPainter.h"
-#include "GuiPopupMenu.h"
 #include "GuiView.h"
 #include "KeySymbol.h"
 #include "Language.h"
@@ -51,6 +50,7 @@
 #include <QMacStyle>
 #endif
 #include <QMainWindow>
+#include <QMenu>
 #include <QPainter>
 #include <QPalette>
 #include <QScrollBar>
index fd4884f54b1f650a3a3c07c548590fc190982fe4..b3d3b872ee4883ed0910b4b7acc2fe40c8c1119c 100644 (file)
@@ -4,6 +4,12 @@
  * Licence details can be found in the file COPYING.
  *
  * \author John Levon
+ * \author Asger Alstrup
+ * \author Lars Gullik Bjønnes
+ * \author Jean-Marc Lasgouttes
+ * \author André Pönitz
+ * \author Dekel Tsur
+ * \author Martin Vermeer
  *
  * Full author contact details are available in file CREDITS.
  */
 #include "GuiPopupMenu.h"
 #include "GuiView.h"
 
-#include "qt_helpers.h"
+#include "BranchList.h"
+#include "Buffer.h"
+#include "BufferList.h"
+#include "BufferParams.h"
+#include "Converter.h"
+#include "CutAndPaste.h"
+#include "Floating.h"
+#include "FloatList.h"
+#include "Format.h"
+#include "KeyMap.h"
+#include "Session.h"
+#include "LyXAction.h"
+#include "LyX.h" // for lastfiles
+#include "LyXFunc.h"
+#include "Lexer.h"
+#include "Paragraph.h"
+#include "TextClass.h"
+#include "TocBackend.h"
+#include "ToolbarBackend.h"
+
+#include "frontends/Application.h"
 
+#include "support/convert.h"
 #include "support/debug.h"
+#include "support/filetools.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
+
+#include <boost/bind.hpp>
+
+#include "qt_helpers.h"
 
 #include <QCursor>
 #include <QMenuBar>
 
+#include <algorithm>
+#include <ostream>
+
+using namespace std;
+using boost::bind;
+using namespace lyx::support;
+
 
 namespace lyx {
 namespace frontend {
 
+namespace {
+
+class MenuNamesEqual
+{
+public:
+       MenuNamesEqual(QString const & name) : name_(name) {}
+       bool operator()(Menu const & menu) const { return menu.name() == name_; }
+private:
+       QString name_;
+};
+
+} // namespace anon
+
 // MacOSX specific stuff is at the end.
 
 void Menus::fillMenuBar(GuiView * view)
@@ -40,11 +94,11 @@ void Menus::fillMenuBar(GuiView * view)
        macxMenuBarInit(view);
 #endif
 
-       LYXERR(Debug::GUI, "populating menu bar" << to_utf8(getMenubar().name()));
+       LYXERR(Debug::GUI, "populating menu bar" << fromqstr(getMenubar().name()));
 
        if (getMenubar().size() == 0) {
                LYXERR(Debug::GUI, "\tERROR: empty menu bar"
-                       << to_utf8(getMenubar().name()));
+                       << fromqstr(getMenubar().name()));
                return;
        }
        else {
@@ -61,16 +115,16 @@ void Menus::fillMenuBar(GuiView * view)
        for (; m != end; ++m) {
 
                if (m->kind() != MenuItem::Submenu) {
-                       LYXERR(Debug::GUI, "\tERROR: not a submenu " << to_utf8(m->label()));
+                       LYXERR(Debug::GUI, "\tERROR: not a submenu " << fromqstr(m->label()));
                        continue;
                }
 
-               LYXERR(Debug::GUI, "menu bar item " << to_utf8(m->label())
-                       << " is a submenu named " << to_utf8(m->submenuname()));
+               LYXERR(Debug::GUI, "menu bar item " << fromqstr(m->label())
+                       << " is a submenu named " << fromqstr(m->submenuname()));
 
-               docstring name = m->submenuname();
+               QString name = m->submenuname();
                if (!hasMenu(name)) {
-                       LYXERR(Debug::GUI, "\tERROR: " << to_utf8(name)
+                       LYXERR(Debug::GUI, "\tERROR: " << fromqstr(name)
                                << " submenu has no menu!");
                        continue;
                }
@@ -78,19 +132,17 @@ void Menus::fillMenuBar(GuiView * view)
                GuiPopupMenu * qMenu = new GuiPopupMenu(view, *m, true);
                view->menuBar()->addMenu(qMenu);
 
-               name_map_[toqstr(name)] = qMenu;
+               name_map_[name] = qMenu;
        }
 }
 
 
 QMenu * Menus::menu(QString const & name)
 {
-       LYXERR(Debug::GUI, "Context menu requested: "
-               << qstring_to_ucs4(name));
+       LYXERR(Debug::GUI, "Context menu requested: " << fromqstr(name));
        GuiPopupMenu * menu = name_map_.value(name, 0);
        if (!menu)
-               LYXERR0("resquested context menu not found: "
-                       << qstring_to_ucs4(name));
+               LYXERR0("resquested context menu not found: " << fromqstr(name));
        return menu;
 }
 
@@ -135,7 +187,7 @@ void Menus::macxMenuBarInit(GuiView * view)
        */
 
        /* The entries of our special mac menu. If we add support for
-        * special entries in MenuBackend, we could imagine something
+        * special entries in Menus, we could imagine something
         * like
         *    SpecialItem About " "About LyX" "dialog-show aboutlyx"
         * and therefore avoid hardcoding. I am not sure it is worth
@@ -159,14 +211,12 @@ void Menus::macxMenuBarInit(GuiView * view)
        };
        const size_t num_entries = sizeof(entries) / sizeof(MacMenuEntry);
 
-       // the special menu for MenuBackend.
+       // the special menu for Menus.
        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));
+               special.add(MenuItem(MenuItem::Command, entries[i].label, func));
        }
        specialMenu(special);
 
@@ -175,13 +225,12 @@ void Menus::macxMenuBarInit(GuiView * view)
        QMenu * qMenu = view->menuBar()->addMenu("special");
 
        // we do not use 'special' because it is a temporary variable,
-       // whereas MenuBackend::specialMenu points to a persistent
+       // whereas Menus::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()),
+               Action * action = new Action(*view, QIcon(), cit->label(),
                                             cit->func(), QString());
                action->setMenuRole(entries[i].role);
                qMenu->addAction(action);
@@ -189,6 +238,990 @@ void Menus::macxMenuBarInit(GuiView * view)
        }
 }
 
+
+MenuItem::MenuItem(Kind kind)
+       : kind_(kind), optional_(false)
+{}
+
+
+MenuItem::MenuItem(Kind kind, QString const & label,
+                  QString const & submenu, bool optional)
+       : kind_(kind), label_(label),
+         submenuname_(submenu), optional_(optional)
+{
+       BOOST_ASSERT(kind == Submenu);
+}
+
+
+MenuItem::MenuItem(Kind kind, QString const & label,
+                  FuncRequest const & func, bool optional)
+       : kind_(kind), label_(label), func_(func), optional_(optional)
+{
+       func_.origin = FuncRequest::MENU;
+}
+
+
+MenuItem::~MenuItem()
+{}
+
+
+void MenuItem::submenu(Menu * menu)
+{
+       submenu_.reset(menu);
+}
+
+
+QString MenuItem::label() const
+{
+       return label_.split('|')[0];
+}
+
+
+QString MenuItem::shortcut() const
+{
+       return label_.contains('|') ? label_.split('|')[1] : QString();
+}
+
+
+QString MenuItem::binding() const
+{
+       if (kind_ != Command)
+               return QString();
+
+       // Get the keys bound to this action, but keep only the
+       // first one later
+       KeyMap::Bindings bindings = theTopLevelKeymap().findBindings(func_);
+
+       if (bindings.size())
+               return toqstr(bindings.begin()->print(KeySequence::ForGui));
+
+       LYXERR(Debug::KBMAP, "No binding for "
+               << lyxaction.getActionName(func_.action)
+               << '(' << func_.argument() << ')');
+       return QString();
+}
+
+
+Menu & Menu::add(MenuItem const & i)
+{
+       items_.push_back(i);
+       return *this;
+}
+
+
+Menu & Menu::addWithStatusCheck(MenuItem const & i)
+{
+       switch (i.kind()) {
+
+       case MenuItem::Command: {
+               FuncStatus status = lyx::getStatus(i.func());
+               if (status.unknown() || (!status.enabled() && i.optional()))
+                       break;
+               items_.push_back(i);
+               items_.back().status(status);
+               break;
+       }
+
+       case MenuItem::Submenu: {
+               if (i.submenu()) {
+                       bool enabled = false;
+                       for (const_iterator cit = i.submenu()->begin();
+                            cit != i.submenu()->end(); ++cit) {
+                               if ((cit->kind() == MenuItem::Command
+                                    || cit->kind() == MenuItem::Submenu)
+                                   && cit->status().enabled()) {
+                                       enabled = true;
+                                       break;
+                               }
+                       }
+                       if (enabled || !i.optional()) {
+                               items_.push_back(i);
+                               items_.back().status().enabled(enabled);
+                       }
+               }
+               else
+                       items_.push_back(i);
+               break;
+       }
+
+       case MenuItem::Separator:
+               if (!items_.empty() && items_.back().kind() != MenuItem::Separator)
+                       items_.push_back(i);
+               break;
+
+       default:
+               items_.push_back(i);
+       }
+
+       return *this;
+}
+
+
+Menu & Menu::read(Lexer & lex)
+{
+       enum Menutags {
+               md_item = 1,
+               md_branches,
+               md_documents,
+               md_bookmarks,
+               md_charstyles,
+               md_custom,
+               md_elements,
+               md_endmenu,
+               md_exportformats,
+               md_importformats,
+               md_lastfiles,
+               md_optitem,
+               md_optsubmenu,
+               md_separator,
+               md_submenu,
+               md_toc,
+               md_updateformats,
+               md_viewformats,
+               md_floatlistinsert,
+               md_floatinsert,
+               md_pasterecent,
+               md_toolbars,
+               md_last
+       };
+
+       struct keyword_item menutags[md_last - 1] = {
+               { "bookmarks", md_bookmarks },
+               { "branches", md_branches },
+               { "charstyles", md_charstyles },
+               { "custom", md_custom },
+               { "documents", md_documents },
+               { "elements", md_elements },
+               { "end", md_endmenu },
+               { "exportformats", md_exportformats },
+               { "floatinsert", md_floatinsert },
+               { "floatlistinsert", md_floatlistinsert },
+               { "importformats", md_importformats },
+               { "item", md_item },
+               { "lastfiles", md_lastfiles },
+               { "optitem", md_optitem },
+               { "optsubmenu", md_optsubmenu },
+               { "pasterecent", md_pasterecent },
+               { "separator", md_separator },
+               { "submenu", md_submenu },
+               { "toc", md_toc },
+               { "toolbars", md_toolbars },
+               { "updateformats", md_updateformats },
+               { "viewformats", md_viewformats }
+       };
+
+       lex.pushTable(menutags, md_last - 1);
+       if (lyxerr.debugging(Debug::PARSER))
+               lex.printTable(lyxerr);
+
+       bool quit = false;
+       bool optional = false;
+
+       while (lex.isOK() && !quit) {
+               switch (lex.lex()) {
+               case md_optitem:
+                       optional = true;
+                       // fallback to md_item
+               case md_item: {
+                       lex.next(true);
+                       docstring const name = translateIfPossible(lex.getDocString());
+                       lex.next(true);
+                       string const command = lex.getString();
+                       FuncRequest func = lyxaction.lookupFunc(command);
+                       add(MenuItem(MenuItem::Command, toqstr(name), func, optional));
+                       optional = false;
+                       break;
+               }
+
+               case md_separator:
+                       add(MenuItem(MenuItem::Separator));
+                       break;
+
+               case md_lastfiles:
+                       add(MenuItem(MenuItem::Lastfiles));
+                       break;
+
+               case md_charstyles:
+                       add(MenuItem(MenuItem::CharStyles));
+                       break;
+
+               case md_custom:
+                       add(MenuItem(MenuItem::Custom));
+                       break;
+
+               case md_elements:
+                       add(MenuItem(MenuItem::Elements));
+                       break;
+
+               case md_documents:
+                       add(MenuItem(MenuItem::Documents));
+                       break;
+
+               case md_bookmarks:
+                       add(MenuItem(MenuItem::Bookmarks));
+                       break;
+
+               case md_toc:
+                       add(MenuItem(MenuItem::Toc));
+                       break;
+
+               case md_viewformats:
+                       add(MenuItem(MenuItem::ViewFormats));
+                       break;
+
+               case md_updateformats:
+                       add(MenuItem(MenuItem::UpdateFormats));
+                       break;
+
+               case md_exportformats:
+                       add(MenuItem(MenuItem::ExportFormats));
+                       break;
+
+               case md_importformats:
+                       add(MenuItem(MenuItem::ImportFormats));
+                       break;
+
+               case md_floatlistinsert:
+                       add(MenuItem(MenuItem::FloatListInsert));
+                       break;
+
+               case md_floatinsert:
+                       add(MenuItem(MenuItem::FloatInsert));
+                       break;
+
+               case md_pasterecent:
+                       add(MenuItem(MenuItem::PasteRecent));
+                       break;
+
+               case md_toolbars:
+                       add(MenuItem(MenuItem::Toolbars));
+                       break;
+
+               case md_branches:
+                       add(MenuItem(MenuItem::Branches));
+                       break;
+
+               case md_optsubmenu:
+                       optional = true;
+                       // fallback to md_submenu
+               case md_submenu: {
+                       lex.next(true);
+                       docstring const mlabel = translateIfPossible(lex.getDocString());
+                       lex.next(true);
+                       docstring const mname = lex.getDocString();
+                       add(MenuItem(MenuItem::Submenu,
+                               toqstr(mlabel), toqstr(mname), optional));
+                       optional = false;
+                       break;
+               }
+
+               case md_endmenu:
+                       quit = true;
+                       break;
+
+               default:
+                       lex.printError("Menu::read: "
+                                      "Unknown menu tag: `$$Token'");
+                       break;
+               }
+       }
+       lex.popTable();
+       return *this;
+}
+
+
+MenuItem const & Menu::operator[](size_type i) const
+{
+       return items_[i];
+}
+
+
+bool Menu::hasFunc(FuncRequest const & func) const
+{
+       return find_if(begin(), end(),
+                      bind(equal_to<FuncRequest>(),
+                           bind(&MenuItem::func, _1),
+                           func)) != end();
+}
+
+void Menu::checkShortcuts() const
+{
+       // This is a quadratic algorithm, but we do not care because
+       // menus are short enough
+       for (const_iterator it1 = begin(); it1 != end(); ++it1) {
+               QString shortcut = it1->shortcut();
+               if (shortcut.isEmpty())
+                       continue;
+               if (!it1->label().contains(shortcut))
+                       lyxerr << "Menu warning: menu entry \""
+                              << fromqstr(it1->label())
+                              << "\" does not contain shortcut `"
+                              << fromqstr(shortcut) << "'." << endl;
+               for (const_iterator it2 = begin(); it2 != it1 ; ++it2) {
+                       if (!it2->shortcut().compare(shortcut, Qt::CaseInsensitive)) {
+                               lyxerr << "Menu warning: menu entries "
+                                      << '"' << fromqstr(it1->fulllabel())
+                                      << "\" and \"" << fromqstr(it2->fulllabel())
+                                      << "\" share the same shortcut."
+                                      << endl;
+                       }
+               }
+       }
+}
+
+
+bool Menu::searchMenu(FuncRequest const & func, vector<docstring> & names) const
+{
+       const_iterator m = begin();
+       const_iterator m_end = end();
+       for (; m != m_end; ++m) {
+               if (m->kind() == MenuItem::Command && m->func() == func) {
+                       names.push_back(qstring_to_ucs4(m->label()));
+                       return true;
+               }
+               if (m->kind() == MenuItem::Submenu) {
+                       names.push_back(qstring_to_ucs4(m->label()));
+                       Menu const & submenu = *m->submenu();
+                       if (submenu.searchMenu(func, names))
+                               return true;
+                       names.pop_back();
+               }
+       }
+       return false;
+}
+
+
+void Menus::specialMenu(Menu const & menu)
+{
+       specialmenu_ = menu;
+}
+
+
+namespace {
+
+bool compareFormat(Format const * p1, Format const * p2)
+{
+       return *p1 < *p2;
+}
+
+
+QString limitStringLength(docstring const & str)
+{
+       size_t const max_item_length = 45;
+
+       if (str.size() > max_item_length)
+               return toqstr(str.substr(0, max_item_length - 3) + "...");
+
+       return toqstr(str);
+}
+
+
+void expandLastfiles(Menu & tomenu)
+{
+       LastFilesSection::LastFiles const & lf = LyX::cref().session().lastFiles().lastFiles();
+       LastFilesSection::LastFiles::const_iterator lfit = lf.begin();
+
+       int ii = 1;
+
+       for (; lfit != lf.end() && ii < 10; ++lfit, ++ii) {
+               string const file = lfit->absFilename();
+               QString const label = QString("%1. %2|%3").arg(ii)
+                       .arg(toqstr(makeDisplayPath(file, 30))).arg(ii);
+               tomenu.add(MenuItem(MenuItem::Command, label, FuncRequest(LFUN_FILE_OPEN, file)));
+       }
+}
+
+
+void expandDocuments(Menu & tomenu)
+{
+       Buffer * first = theBufferList().first();
+       if (first) {
+               Buffer * b = first;
+               int ii = 1;
+               
+               // We cannot use a for loop as the buffer list cycles.
+               do {
+                       QString label = toqstr(b->fileName().displayName(20));
+                       if (!b->isClean())
+                               label += "*";
+                       if (ii < 10)
+                               label = QString::number(ii) + ". " + label + '|' + QString::number(ii);
+                       tomenu.add(MenuItem(MenuItem::Command, label,
+                               FuncRequest(LFUN_BUFFER_SWITCH, b->absFileName())));
+                       
+                       b = theBufferList().next(b);
+                       ++ii;
+               } while (b != first); 
+       } else {
+               tomenu.add(MenuItem(MenuItem::Command, qt_("No Documents Open!"),
+                          FuncRequest(LFUN_NOACTION)));
+       }
+}
+
+
+void expandBookmarks(Menu & tomenu)
+{
+       lyx::BookmarksSection const & bm = LyX::cref().session().bookmarks();
+
+       for (size_t i = 1; i <= bm.size(); ++i) {
+               if (bm.isValid(i)) {
+                       string const file = bm.bookmark(i).filename.absFilename();
+                       QString const label = QString("%1. %2|%3").arg(i)
+                               .arg(toqstr(makeDisplayPath(file, 20))).arg(i);
+                       tomenu.add(MenuItem(MenuItem::Command, label,
+                               FuncRequest(LFUN_BOOKMARK_GOTO, convert<docstring>(i))));
+               }
+       }
+}
+
+
+void expandFormats(MenuItem::Kind kind, Menu & tomenu, Buffer const * buf)
+{
+       if (!buf && kind != MenuItem::ImportFormats) {
+               tomenu.add(MenuItem(MenuItem::Command,
+                                   qt_("No Document Open!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+
+       typedef vector<Format const *> Formats;
+       Formats formats;
+       kb_action action;
+
+       switch (kind) {
+       case MenuItem::ImportFormats:
+               formats = theConverters().importableFormats();
+               action = LFUN_BUFFER_IMPORT;
+               break;
+       case MenuItem::ViewFormats:
+               formats = buf->exportableFormats(true);
+               action = LFUN_BUFFER_VIEW;
+               break;
+       case MenuItem::UpdateFormats:
+               formats = buf->exportableFormats(true);
+               action = LFUN_BUFFER_UPDATE;
+               break;
+       default:
+               formats = buf->exportableFormats(false);
+               action = LFUN_BUFFER_EXPORT;
+       }
+       sort(formats.begin(), formats.end(), &compareFormat);
+
+       Formats::const_iterator fit = formats.begin();
+       Formats::const_iterator end = formats.end();
+       for (; fit != end ; ++fit) {
+               if ((*fit)->dummy())
+                       continue;
+               QString label = toqstr((*fit)->prettyname());
+               QString const shortcut = toqstr((*fit)->shortcut());
+
+               switch (kind) {
+               case MenuItem::ImportFormats:
+                       // FIXME: This is a hack, we should rather solve
+                       // FIXME: bug 2488 instead.
+                       if ((*fit)->name() == "text")
+                               label = qt_("Plain Text");
+                       else if ((*fit)->name() == "textparagraph")
+                               label = qt_("Plain Text, Join Lines");
+                       label += "...";
+                       break;
+               case MenuItem::ViewFormats:
+               case MenuItem::ExportFormats:
+               case MenuItem::UpdateFormats:
+                       if (!(*fit)->documentFormat())
+                               continue;
+                       break;
+               default:
+                       BOOST_ASSERT(false);
+                       break;
+               }
+               // FIXME: if we had proper support for translating the
+               // format names defined in configure.py, there would
+               // not be a need to check whether the shortcut is
+               // correct. If we add it uncondiitonally, it would
+               // create useless warnings on bad shortcuts
+               if (!shortcut.isEmpty() && label.contains(shortcut))
+                       label += '|' + shortcut;
+
+               if (buf)
+                       tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, label,
+                               FuncRequest(action, (*fit)->name())));
+               else
+                       tomenu.add(MenuItem(MenuItem::Command, label,
+                               FuncRequest(action, (*fit)->name())));
+       }
+}
+
+
+void expandFloatListInsert(Menu & tomenu, Buffer const * buf)
+{
+       if (!buf) {
+               tomenu.add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+
+       FloatList const & floats = buf->params().documentClass().floats();
+       FloatList::const_iterator cit = floats.begin();
+       FloatList::const_iterator end = floats.end();
+       for (; cit != end; ++cit) {
+               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command,
+                                   qt_(cit->second.listName()),
+                                   FuncRequest(LFUN_FLOAT_LIST,
+                                               cit->second.type())));
+       }
+}
+
+
+void expandFloatInsert(Menu & tomenu, Buffer const * buf)
+{
+       if (!buf) {
+               tomenu.add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+
+       FloatList const & floats = buf->params().documentClass().floats();
+       FloatList::const_iterator cit = floats.begin();
+       FloatList::const_iterator end = floats.end();
+       for (; cit != end; ++cit) {
+               // normal float
+               QString const label = qt_(cit->second.name());
+               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, label,
+                                   FuncRequest(LFUN_FLOAT_INSERT,
+                                               cit->second.type())));
+       }
+}
+
+
+void expandFlexInsert(Menu & tomenu, Buffer const * buf, string s)
+{
+       if (!buf) {
+               tomenu.add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+       TextClass::InsetLayouts const & insetLayouts =
+               buf->params().documentClass().insetLayouts();
+       TextClass::InsetLayouts::const_iterator cit = insetLayouts.begin();
+       TextClass::InsetLayouts::const_iterator end = insetLayouts.end();
+       for (; cit != end; ++cit) {
+               docstring const label = cit->first;
+               if (cit->second.lyxtype() == s)
+                       tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, 
+                               toqstr(label), FuncRequest(LFUN_FLEX_INSERT,
+                                               label)));
+       }
+}
+
+
+size_t const max_number_of_items = 25;
+
+void expandToc2(Menu & tomenu, Toc const & toc_list,
+               size_t from, size_t to, int depth)
+{
+       int shortcut_count = 0;
+
+       // check whether depth is smaller than the smallest depth in toc.
+       int min_depth = 1000;
+       for (size_t i = from; i < to; ++i)
+               min_depth = min(min_depth, toc_list[i].depth());
+       if (min_depth > depth)
+               depth = min_depth;
+
+       if (to - from <= max_number_of_items) {
+               for (size_t i = from; i < to; ++i) {
+                       QString label(4 * max(0, toc_list[i].depth() - depth), ' ');
+                       label += limitStringLength(toc_list[i].str());
+                       if (toc_list[i].depth() == depth
+                           && shortcut_count < 9) {
+                               if (label.contains(QString::number(shortcut_count + 1)))
+                                       label += '|' + QString::number(++shortcut_count);
+                       }
+                       tomenu.add(MenuItem(MenuItem::Command, label,
+                                           FuncRequest(toc_list[i].action())));
+               }
+       } else {
+               size_t pos = from;
+               while (pos < to) {
+                       size_t new_pos = pos + 1;
+                       while (new_pos < to &&
+                              toc_list[new_pos].depth() > depth)
+                               ++new_pos;
+
+                       QString label(4 * max(0, toc_list[pos].depth() - depth), ' ');
+                       label += limitStringLength(toc_list[pos].str());
+                       if (toc_list[pos].depth() == depth &&
+                           shortcut_count < 9) {
+                               if (label.contains(QString::number(shortcut_count + 1)))
+                                       label += '|' + QString::number(++shortcut_count);
+                       }
+                       if (new_pos == pos + 1) {
+                               tomenu.add(MenuItem(MenuItem::Command,
+                                                   label, FuncRequest(toc_list[pos].action())));
+                       } else {
+                               MenuItem item(MenuItem::Submenu, label);
+                               item.submenu(new Menu);
+                               expandToc2(*item.submenu(),
+                                          toc_list, pos, new_pos, depth + 1);
+                               tomenu.add(item);
+                       }
+                       pos = new_pos;
+               }
+       }
+}
+
+
+void expandToc(Menu & tomenu, Buffer const * buf)
+{
+       // To make things very cleanly, we would have to pass buf to
+       // all MenuItem constructors and to expandToc2. However, we
+       // know that all the entries in a TOC will be have status_ ==
+       // OK, so we avoid this unnecessary overhead (JMarc)
+
+       if (!buf) {
+               tomenu.add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+
+       Buffer* cbuf = const_cast<Buffer*>(buf);
+       cbuf->tocBackend().update();
+       cbuf->structureChanged();
+
+       // Add an entry for the master doc if this is a child doc
+       Buffer const * const master = buf->masterBuffer();
+       if (buf != master) {
+               ParIterator const pit = par_iterator_begin(master->inset());
+               string const arg = convert<string>(pit->id());
+               FuncRequest f(LFUN_PARAGRAPH_GOTO, arg);
+               tomenu.add(MenuItem(MenuItem::Command, qt_("Master Document"), f));
+       }
+
+       FloatList const & floatlist = buf->params().documentClass().floats();
+       TocList const & toc_list = buf->tocBackend().tocs();
+       TocList::const_iterator cit = toc_list.begin();
+       TocList::const_iterator end = toc_list.end();
+       for (; cit != end; ++cit) {
+               // Handle this later
+               if (cit->first == "tableofcontents")
+                       continue;
+
+               // All the rest is for floats
+               auto_ptr<Menu> menu(new Menu);
+               TocIterator ccit = cit->second.begin();
+               TocIterator eend = cit->second.end();
+               for (; ccit != eend; ++ccit) {
+                       QString const label = limitStringLength(ccit->str());
+                       menu->add(MenuItem(MenuItem::Command, label,
+                                          FuncRequest(ccit->action())));
+               }
+               string const & floatName = floatlist.getType(cit->first).listName();
+               QString label;
+               if (!floatName.empty())
+                       label = qt_(floatName);
+               // BUG3633: listings is not a proper float so its name
+               // is not shown in floatlist.
+               else if (cit->first == "equation")
+                       label = qt_("List of Equations");
+               else if (cit->first == "index")
+                       label = qt_("List of Indexes");
+               else if (cit->first == "listing")
+                       label = qt_("List of Listings");
+               else if (cit->first == "marginalnote")
+                       label = qt_("List of Marginal notes");
+               else if (cit->first == "note")
+                       label = qt_("List of Notes");
+               else if (cit->first == "footnote")
+                       label = qt_("List of Foot notes");
+               else if (cit->first == "label")
+                       label = qt_("Labels and References");
+               else if (cit->first == "citation")
+                       label = qt_("List of Citations");
+               // this should not happen now, but if something else like
+               // listings is added later, this can avoid an empty menu name.
+               else
+                       label = qt_("Other floats");
+               MenuItem item(MenuItem::Submenu, label);
+               item.submenu(menu.release());
+               tomenu.add(item);
+       }
+
+       // Handle normal TOC
+       cit = toc_list.find("tableofcontents");
+       if (cit == end) {
+               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command,
+                                   qt_("No Table of contents"),
+                                   FuncRequest()));
+       } else {
+               expandToc2(tomenu, cit->second, 0, cit->second.size(), 0);
+       }
+}
+
+
+void expandPasteRecent(Menu & tomenu)
+{
+       vector<docstring> const sel = cap::availableSelections();
+
+       vector<docstring>::const_iterator cit = sel.begin();
+       vector<docstring>::const_iterator end = sel.end();
+
+       for (unsigned int index = 0; cit != end; ++cit, ++index) {
+               tomenu.add(MenuItem(MenuItem::Command, toqstr(*cit),
+                                   FuncRequest(LFUN_PASTE, convert<string>(index))));
+       }
+}
+
+
+void expandToolbars(Menu & tomenu)
+{
+       //
+       // extracts the toolbars from the backend
+       ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin();
+       ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end();
+
+       for (; cit != end; ++cit) {
+               QString label = qt_(cit->gui_name);
+               // frontends are not supposed to turn on/off toolbars,
+               // if they cannot update ToolbarBackend::flags. That
+               // is to say, ToolbarsBackend::flags should reflect
+               // the true state of toolbars.
+               //
+               // menu is displayed as
+               //       on/off review
+               // and
+               //              review (auto)
+               // in the case of auto.
+               if (cit->flags & ToolbarInfo::AUTO)
+                       label += qt_(" (auto)");
+               tomenu.add(MenuItem(MenuItem::Command, label,
+                                   FuncRequest(LFUN_TOOLBAR_TOGGLE, cit->name + " allowauto")));
+       }
+}
+
+
+void expandBranches(Menu & tomenu, Buffer const * buf)
+{
+       if (!buf) {
+               tomenu.add(MenuItem(MenuItem::Command,
+                                   qt_("No Document Open!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+
+       BufferParams const & params = buf->masterBuffer()->params();
+       if (params.branchlist().empty()) {
+               tomenu.add(MenuItem(MenuItem::Command,
+                                   qt_("No Branch in Document!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+
+       BranchList::const_iterator cit = params.branchlist().begin();
+       BranchList::const_iterator end = params.branchlist().end();
+
+       for (int ii = 1; cit != end; ++cit, ++ii) {
+               docstring label = cit->getBranch();
+               if (ii < 10)
+                       label = convert<docstring>(ii) + ". " + label + char_type('|') + convert<docstring>(ii);
+               tomenu.addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label),
+                                   FuncRequest(LFUN_BRANCH_INSERT,
+                                               cit->getBranch())));
+       }
+}
+
+
+} // namespace anon
+
+
+void Menus::expand(Menu const & frommenu, Menu & tomenu,
+                        Buffer const * buf) const
+{
+       if (!tomenu.empty())
+               tomenu.clear();
+
+       for (Menu::const_iterator cit = frommenu.begin();
+            cit != frommenu.end() ; ++cit) {
+               switch (cit->kind()) {
+               case MenuItem::Lastfiles:
+                       expandLastfiles(tomenu);
+                       break;
+
+               case MenuItem::Documents:
+                       expandDocuments(tomenu);
+                       break;
+
+               case MenuItem::Bookmarks:
+                       expandBookmarks(tomenu);
+                       break;
+
+               case MenuItem::ImportFormats:
+               case MenuItem::ViewFormats:
+               case MenuItem::UpdateFormats:
+               case MenuItem::ExportFormats:
+                       expandFormats(cit->kind(), tomenu, buf);
+                       break;
+
+               case MenuItem::CharStyles:
+                       expandFlexInsert(tomenu, buf, "charstyle");
+                       break;
+
+               case MenuItem::Custom:
+                       expandFlexInsert(tomenu, buf, "custom");
+                       break;
+
+               case MenuItem::Elements:
+                       expandFlexInsert(tomenu, buf, "element");
+                       break;
+
+               case MenuItem::FloatListInsert:
+                       expandFloatListInsert(tomenu, buf);
+                       break;
+
+               case MenuItem::FloatInsert:
+                       expandFloatInsert(tomenu, buf);
+                       break;
+
+               case MenuItem::PasteRecent:
+                       expandPasteRecent(tomenu);
+                       break;
+
+               case MenuItem::Toolbars:
+                       expandToolbars(tomenu);
+                       break;
+
+               case MenuItem::Branches:
+                       expandBranches(tomenu, buf);
+                       break;
+
+               case MenuItem::Toc:
+                       expandToc(tomenu, buf);
+                       break;
+
+               case MenuItem::Submenu: {
+                       MenuItem item(*cit);
+                       item.submenu(new Menu(cit->submenuname()));
+                       expand(getMenu(cit->submenuname()),
+                              *item.submenu(), buf);
+                       tomenu.addWithStatusCheck(item);
+               }
+               break;
+
+               case MenuItem::Separator:
+                       tomenu.addWithStatusCheck(*cit);
+                       break;
+
+               case MenuItem::Command:
+                       if (!specialmenu_.hasFunc(cit->func()))
+                               tomenu.addWithStatusCheck(*cit);
+               }
+       }
+
+       // we do not want the menu to end with a separator
+       if (!tomenu.empty()
+           && tomenu.items_.back().kind() == MenuItem::Separator)
+               tomenu.items_.pop_back();
+
+       // Check whether the shortcuts are unique
+       tomenu.checkShortcuts();
+}
+
+
+void Menus::read(Lexer & lex)
+{
+       enum Menutags {
+               md_menu = 1,
+               md_menubar,
+               md_endmenuset,
+               md_last
+       };
+
+       struct keyword_item menutags[md_last - 1] = {
+               { "end", md_endmenuset },
+               { "menu", md_menu },
+               { "menubar", md_menubar }
+       };
+
+       //consistency check
+       if (compare_ascii_no_case(lex.getString(), "menuset")) {
+               lyxerr << "Menubackend::read: ERROR wrong token:`"
+                      << lex.getString() << '\'' << endl;
+       }
+
+       lex.pushTable(menutags, md_last - 1);
+       if (lyxerr.debugging(Debug::PARSER))
+               lex.printTable(lyxerr);
+
+       bool quit = false;
+
+       while (lex.isOK() && !quit) {
+               switch (lex.lex()) {
+               case md_menubar:
+                       menubar_.read(lex);
+                       break;
+               case md_menu: {
+                       lex.next(true);
+                       QString const name = toqstr(lex.getDocString());
+                       if (hasMenu(name)) {
+                               getMenu(name).read(lex);
+                       } else {
+                               Menu menu(name);
+                               menu.read(lex);
+                               add(menu);
+                       }
+                       break;
+               }
+               case md_endmenuset:
+                       quit = true;
+                       break;
+               default:
+                       lex.printError("menubackend::read: "
+                                      "Unknown menu tag: `$$Token'");
+                       break;
+               }
+       }
+       lex.popTable();
+}
+
+
+void Menus::add(Menu const & menu)
+{
+       menulist_.push_back(menu);
+}
+
+
+bool Menus::hasMenu(QString const & name) const
+{
+       return find_if(begin(), end(), MenuNamesEqual(name)) != end();
+}
+
+
+Menu const & Menus::getMenu(QString const & name) const
+{
+       const_iterator cit = find_if(begin(), end(), MenuNamesEqual(name));
+       if (cit == end())
+               lyxerr << "No submenu named " << fromqstr(name) << endl;
+       BOOST_ASSERT(cit != end());
+       return (*cit);
+}
+
+
+Menu & Menus::getMenu(QString const & name)
+{
+       iterator it = find_if(begin(), end(), MenuNamesEqual(name));
+       if (it == end())
+               lyxerr << "No submenu named " << fromqstr(name) << endl;
+       BOOST_ASSERT(it != end());
+       return (*it);
+}
+
+
+Menu const & Menus::getMenubar() const
+{
+       return menubar_;
+}
+
+
 } // namespace frontend
 } // namespace lyx
 
index 77da32d57f9a702f40ca99e9e9708e5b3867a9f0..c20eccbd821487d75441678b56fdd7998160bc89 100644 (file)
 #ifndef MENUS_H
 #define MENUS_H
 
-#include "MenuBackend.h"
+#include "FuncStatus.h"
+#include "FuncRequest.h"
 
 #include <QObject>
 #include <QHash>
 
-class QMenu;
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
 
+class QMenu;
 
 namespace lyx {
+
+class Lexer;
+class Buffer;
+
 namespace frontend {
 
+class Menu;
 class GuiView;
 class GuiPopupMenu;
 class GuiView;
 
-class Menus : public QObject, public MenuBackend
+///
+class MenuItem {
+public:
+       /// The type of elements that can be in a menu
+       enum Kind {
+               ///
+               Command,
+               ///
+               Submenu,
+               ///
+               Separator,
+               /** This is the list of last opened file,
+                   typically for the File menu. */
+               Lastfiles,
+               /** This is the list of opened Documents,
+                   typically for the Documents menu. */
+               Documents,
+               /** This is the bookmarks */
+               Bookmarks,
+               ///
+               Toc,
+               /** This is a list of viewable formats
+                   typically for the File->View menu. */
+               ViewFormats,
+               /** This is a list of updatable formats
+                   typically for the File->Update menu. */
+               UpdateFormats,
+               /** This is a list of exportable formats
+                   typically for the File->Export menu. */
+               ExportFormats,
+               /** This is a list of importable formats
+                   typically for the File->Export menu. */
+               ImportFormats,
+               /** This is the list of elements available
+                * for insertion into document. */
+               CharStyles,
+               /** This is the list of user-configurable
+               insets to insert into document */
+               Custom,
+               /** This is the list of XML elements to
+               insert into the document */
+               Elements,
+               /** This is the list of floats that we can
+                   insert a list for. */
+               FloatListInsert,
+               /** This is the list of floats that we can
+                   insert. */
+               FloatInsert,
+               /** This is the list of selections that can
+                   be pasted. */
+               PasteRecent,
+               /** toolbars */
+               Toolbars,
+               /** Available branches in document */
+               Branches
+       };
+
+       explicit MenuItem(Kind kind);
+
+       MenuItem(Kind kind,
+                QString const & label,
+                QString const & submenu = QString(),
+                bool optional = false);
+
+       MenuItem(Kind kind,
+                QString const & label,
+                FuncRequest const & func,
+                bool optional = false);
+
+       /// This one is just to please boost::shared_ptr<>
+       ~MenuItem();
+       /// The label of a given menuitem
+       QString label() const;
+       /// The keyboard shortcut (usually underlined in the entry)
+       QString shortcut() const;
+       /// The complete label, with label and shortcut separated by a '|'
+       QString fulllabel() const { return label_;}
+       /// The kind of entry
+       Kind kind() const { return kind_; }
+       /// the action (if relevant)
+       FuncRequest const & func() const { return func_; }
+       /// returns true if the entry should be ommited when disabled
+       bool optional() const { return optional_; }
+       /// returns the status of the lfun associated with this entry
+       FuncStatus const & status() const { return status_; }
+       /// returns the status of the lfun associated with this entry
+       FuncStatus & status() { return status_; }
+       /// returns the status of the lfun associated with this entry
+       void status(FuncStatus const & status) { status_ = status; }
+       ///returns the binding associated to this action.
+       QString binding() const;
+       /// the description of the  submenu (if relevant)
+       QString const & submenuname() const { return submenuname_; }
+       /// set the description of the  submenu
+       void submenuname(QString const & name) { submenuname_ = name; }
+       ///
+       Menu * submenu() const { return submenu_.get(); }
+       ///
+       void submenu(Menu * menu);
+
+private:
+       ///
+       Kind kind_;
+       ///
+       QString label_;
+       ///
+       FuncRequest func_;
+       ///
+       QString submenuname_;
+       ///
+       bool optional_;
+       ///
+       FuncStatus status_;
+       ///
+       boost::shared_ptr<Menu> submenu_;
+};
+
+
+///
+class Menu {
+public:
+       ///
+       typedef std::vector<MenuItem> ItemList;
+       ///
+       typedef ItemList::const_iterator const_iterator;
+
+       ///
+       explicit Menu(QString const & name = QString()) : name_(name) {}
+
+       /// Add the menu item unconditionally
+       Menu & add(MenuItem const &);
+       /// Checks the associated FuncRequest status before adding the
+       /// menu item.
+       Menu & addWithStatusCheck(MenuItem const &);
+       ///
+       Menu & read(Lexer &);
+       ///
+       QString const & name() const { return name_; }
+       ///
+       bool empty() const { return items_.empty(); }
+       /// Clear the menu content.
+       void clear() { items_.clear(); }
+       ///
+       size_t size() const { return items_.size(); }
+       ///
+       MenuItem const & operator[](size_t) const;
+       ///
+       bool hasFunc(FuncRequest const &) const;
+       ///
+       const_iterator begin() const { return items_.begin(); }
+       ///
+       const_iterator end() const { return items_.end(); }
+
+       // Check whether the menu shortcuts are unique
+       void checkShortcuts() const;
+       
+       // search for func in this menu iteratively, and put menu
+       // names in a stack.
+       bool searchMenu(FuncRequest const & func, std::vector<docstring> & names)
+               const;
+
+private:
+       friend class Menus;
+       ///
+       ItemList items_;
+       ///
+       QString name_;
+};
+
+
+class Menus
 {
-       Q_OBJECT
 public:
+       ///
+       typedef std::vector<Menu> MenuList;
+       ///
+       typedef MenuList::const_iterator const_iterator;
+       ///
+       typedef MenuList::iterator iterator;
+
+
        Menus() {}
 
        ///
@@ -42,6 +228,51 @@ public:
 
        /// update the state of the menuitems - not needed
        void updateView();
+       ///
+       void read(Lexer &);
+       ///
+       void add(Menu const &);
+       ///
+       bool hasMenu(QString const &) const;
+       ///
+       Menu & getMenu(QString const &);
+       ///
+       Menu const & getMenu(QString const &) const;
+       ///
+       Menu const & getMenubar() const;
+       ///
+       bool empty() const { return menulist_.empty(); }
+       /** This defines a menu whose entries list the FuncRequests
+           that will be removed by expand() in other menus. This is
+           used by the Qt/Mac code
+       */
+       void specialMenu(Menu const &);
+       ///
+       Menu const & specialMenu() { return specialmenu_; }
+
+       /// Expands some special entries of the menu
+       /** The entries with the following kind are expanded to a
+           sequence of Command MenuItems: Lastfiles, Documents,
+           ViewFormats, ExportFormats, UpdateFormats, Branches
+       */
+       void expand(Menu const & frommenu, Menu & tomenu,
+                   Buffer const *) const;
+       ///
+       const_iterator begin() const { return menulist_.begin(); }
+       ///
+       iterator begin() { return menulist_.begin(); }
+       ///
+       const_iterator end() const { return menulist_.end(); }
+       ///
+       iterator end() { return menulist_.end(); }
+
+private:
+       ///
+       MenuList menulist_;
+       ///
+       Menu menubar_;
+       ///
+       Menu specialmenu_;
 
 private:
        /// Initialize specific MACOS X menubar