]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/Menus.cpp
* fix spelling in comments to please John.
[lyx.git] / src / frontends / qt4 / Menus.cpp
index 51ef148db949cd3228bfd556ad923011f86caa91..8de4f83257d98e75c7508b816216b44b04262085 100644 (file)
@@ -5,9 +5,9 @@
  *
  * \author John Levon
  * \author Asger Alstrup
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author Jean-Marc Lasgouttes
- * \author André Pönitz
+ * \author André Pönitz
  * \author Dekel Tsur
  * \author Martin Vermeer
  *
 #include "Format.h"
 #include "FuncRequest.h"
 #include "FuncStatus.h"
+#include "IndicesList.h"
 #include "KeyMap.h"
 #include "Lexer.h"
 #include "LyXAction.h"
 #include "LyX.h" // for lastfiles
 #include "LyXFunc.h"
+#include "LyXRC.h"
 #include "Paragraph.h"
+#include "ParIterator.h"
 #include "Session.h"
 #include "TextClass.h"
 #include "TocBackend.h"
-#include "ToolbarBackend.h"
+#include "Toolbars.h"
+#include "WordLangTuple.h"
 
 #include "insets/Inset.h"
 #include "insets/InsetCitation.h"
@@ -54,6 +58,7 @@
 #include "support/lassert.h"
 #include "support/convert.h"
 #include "support/debug.h"
+#include "support/docstring_list.h"
 #include "support/filetools.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
@@ -93,6 +98,15 @@ public:
                Submenu,
                ///
                Separator,
+               /** This type of item explains why something is unavailable. If this
+                   menuitem is in a submenu, the submenu is enabled to make sure the
+                   user sees the information. */
+               Help,
+               /** This type of item merely shows that there might be a list or 
+                   something alike at this position, but the list is still empty.
+                   If this item is in a submenu, the submenu will not always be 
+                   enabled. */
+               Info,
                /** This is the list of last opened file,
                    typically for the File menu. */
                Lastfiles,
@@ -137,10 +151,20 @@ public:
                Toolbars,
                /** Available branches in document */
                Branches,
+               /** Available indices in document */
+               Indices,
+               /** Context menu for indices in document */
+               IndicesContext,
+               /** Available index lists in document */
+               IndicesLists,
+               /** Context menu for available indices lists in document */
+               IndicesListsContext,
                /** Available citation styles for a given citation */
                CiteStyles,
                /** Available graphics groups */
-               GraphicsGroups
+               GraphicsGroups,
+               /// Words suggested by the spellchecker.
+               SpellingSuggestions
        };
 
        explicit MenuItem(Kind kind) : kind_(kind), optional_(false) {}
@@ -151,16 +175,17 @@ public:
                 bool optional = false)
                : kind_(kind), label_(label), submenuname_(submenu), optional_(optional)
        {
-               LASSERT(kind == Submenu, /**/);
+               LASSERT(kind == Submenu || kind == Help || kind == Info, /**/);
        }
 
        MenuItem(Kind kind,
                 QString const & label,
                 FuncRequest const & func,
-                bool optional = false)
+                bool optional = false,
+                FuncRequest::Origin origin = FuncRequest::MENU)
                : kind_(kind), label_(label), func_(func), optional_(optional)
        {
-               func_.origin = FuncRequest::MENU;
+               func_.origin = origin;
        }
 
        // boost::shared_ptr<MenuDefinition> needs this apprently...
@@ -268,7 +293,7 @@ public:
        
        // search for func in this menu iteratively, and put menu
        // names in a stack.
-       bool searchMenu(FuncRequest const & func, std::vector<docstring> & names)
+       bool searchMenu(FuncRequest const & func, docstring_list & names)
                const;
        ///
        bool hasFunc(FuncRequest const &) const;
@@ -286,14 +311,17 @@ public:
        void expandFormats(MenuItem::Kind kind, Buffer const * buf);
        void expandFloatListInsert(Buffer const * buf);
        void expandFloatInsert(Buffer const * buf);
-       void expandFlexInsert(Buffer const * buf, std::string s);
+       void expandFlexInsert(Buffer const * buf, InsetLayout::InsetLyXType type);
        void expandToc2(Toc const & toc_list, size_t from, size_t to, int depth);
        void expandToc(Buffer const * buf);
-       void expandPasteRecent();
+       void expandPasteRecent(Buffer const * buf);
        void expandToolbars();
        void expandBranches(Buffer const * buf);
+       void expandIndices(Buffer const * buf, bool listof = false);
+       void expandIndicesContext(Buffer const * buf, bool listof = false);
        void expandCiteStyles(BufferView const *);
-       void expandGraphicsGroups(Buffer const * buf);
+       void expandGraphicsGroups(BufferView const *);
+       void expandSpellingSuggestions(BufferView const *);
        ///
        ItemList items_;
        ///
@@ -337,24 +365,24 @@ void MenuDefinition::addWithStatusCheck(MenuItem const & i)
        }
 
        case MenuItem::Submenu: {
+               bool enabled = false;
                if (i.hasSubmenu()) {
-                       bool enabled = false;
                        for (const_iterator cit = i.submenu().begin();
-                            cit != i.submenu().end(); ++cit) {
+                                 cit != i.submenu().end(); ++cit) {
+                               // Only these kind of items affect the status of the submenu
                                if ((cit->kind() == MenuItem::Command
-                                    || cit->kind() == MenuItem::Submenu)
+                                       || cit->kind() == MenuItem::Submenu
+                                       || cit->kind() == MenuItem::Help)
                                    && cit->status().enabled()) {
                                        enabled = true;
                                        break;
                                }
                        }
-                       if (enabled || !i.optional()) {
-                               items_.push_back(i);
-                               items_.back().status().enabled(enabled);
-                       }
                }
-               else
+               if (enabled || !i.optional()) {
                        items_.push_back(i);
+                       items_.back().status().setEnabled(enabled);
+               }
                break;
        }
 
@@ -383,6 +411,10 @@ void MenuDefinition::read(Lexer & lex)
                md_endmenu,
                md_exportformats,
                md_importformats,
+               md_indices,
+               md_indicescontext,
+               md_indiceslists,
+               md_indiceslistscontext,
                md_lastfiles,
                md_optitem,
                md_optsubmenu,
@@ -395,7 +427,8 @@ void MenuDefinition::read(Lexer & lex)
                md_floatinsert,
                md_pasterecent,
                md_toolbars,
-               md_graphicsgroups
+               md_graphicsgroups,
+               md_spellingsuggestions
        };
 
        LexerKeyword menutags[] = {
@@ -412,12 +445,17 @@ void MenuDefinition::read(Lexer & lex)
                { "floatlistinsert", md_floatlistinsert },
                { "graphicsgroups", md_graphicsgroups },
                { "importformats", md_importformats },
+               { "indices", md_indices },
+               { "indicescontext", md_indicescontext },
+               { "indiceslists", md_indiceslists },
+               { "indiceslistscontext", md_indiceslistscontext },
                { "item", md_item },
                { "lastfiles", md_lastfiles },
                { "optitem", md_optitem },
                { "optsubmenu", md_optsubmenu },
                { "pasterecent", md_pasterecent },
                { "separator", md_separator },
+               { "spellingsuggestions", md_spellingsuggestions },
                { "submenu", md_submenu },
                { "toc", md_toc },
                { "toolbars", md_toolbars },
@@ -442,7 +480,10 @@ void MenuDefinition::read(Lexer & lex)
                        lex.next(true);
                        string const command = lex.getString();
                        FuncRequest func = lyxaction.lookupFunc(command);
-                       add(MenuItem(MenuItem::Command, toqstr(name), func, optional));
+                       FuncRequest::Origin origin = FuncRequest::MENU;
+                       if (name_.startsWith("context-toc-"))
+                               origin = FuncRequest::TOC;
+                       add(MenuItem(MenuItem::Command, toqstr(name), func, optional, origin));
                        optional = false;
                        break;
                }
@@ -523,6 +564,26 @@ void MenuDefinition::read(Lexer & lex)
                        add(MenuItem(MenuItem::GraphicsGroups));
                        break;
 
+               case md_spellingsuggestions:
+                       add(MenuItem(MenuItem::SpellingSuggestions));
+                       break;
+
+               case md_indices:
+                       add(MenuItem(MenuItem::Indices));
+                       break;
+
+               case md_indicescontext:
+                       add(MenuItem(MenuItem::IndicesContext));
+                       break;
+
+               case md_indiceslists:
+                       add(MenuItem(MenuItem::IndicesLists));
+                       break;
+
+               case md_indiceslistscontext:
+                       add(MenuItem(MenuItem::IndicesListsContext));
+                       break;
+
                case md_optsubmenu:
                        optional = true;
                        // fallback to md_submenu
@@ -590,7 +651,7 @@ void MenuDefinition::checkShortcuts() const
 }
 
 
-bool MenuDefinition::searchMenu(FuncRequest const & func, vector<docstring> & names) const
+bool MenuDefinition::searchMenu(FuncRequest const & func, docstring_list & names) const
 {
        const_iterator m = begin();
        const_iterator m_end = end();
@@ -633,32 +694,82 @@ QString limitStringLength(docstring const & str)
 }
 
 
-void MenuDefinition::expandGraphicsGroups(Buffer const * buf)
+void MenuDefinition::expandGraphicsGroups(BufferView const * bv)
 {
+       if (!bv)
+               return;
        set<string> grp;
-       InsetGraphics::getGraphicsGroups(*buf, grp);
+       graphics::getGraphicsGroups(bv->buffer(), grp);
+       if (grp.empty())
+               return;
+
        set<string>::const_iterator it = grp.begin();
        set<string>::const_iterator end = grp.end();
-       if (grp.empty()) return;
-
-       add(MenuItem(MenuItem::Separator));
-       add(MenuItem(MenuItem::Command, qt_("Clear group"), FuncRequest(LFUN_SET_GRAPHICS_GROUP)));
+       add(MenuItem(MenuItem::Command, qt_("No Group"), 
+                    FuncRequest(LFUN_SET_GRAPHICS_GROUP)));
        for (; it != end; it++) {
-               add(MenuItem(MenuItem::Command, toqstr(*it), FuncRequest(LFUN_SET_GRAPHICS_GROUP, *it)));
+               addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(*it),
+                               FuncRequest(LFUN_SET_GRAPHICS_GROUP, *it)));
+       }
+}
+
+
+void MenuDefinition::expandSpellingSuggestions(BufferView const * bv)
+{
+       if (!bv)
+               return;
+       WordLangTuple wl;
+       docstring_list suggestions;
+       pos_type from = bv->cursor().pos();
+       pos_type to = from;
+       Paragraph const & par = bv->cursor().paragraph();
+       if (!par.spellCheck(from, to, wl, suggestions))
+               return;
+       LYXERR(Debug::GUI, "Misspelled Word! Suggested Words = ");
+       size_t i = 0;
+       MenuItem item(MenuItem::Submenu, qt_("More Spelling Suggestions"));
+       item.setSubmenu(MenuDefinition(qt_("More Spelling Suggestions")));
+       for (; i != suggestions.size(); ++i) {
+               docstring const & suggestion = suggestions[i];
+               LYXERR(Debug::GUI, suggestion);
+               MenuItem w(MenuItem::Command, toqstr(suggestion),
+                       FuncRequest(LFUN_WORD_REPLACE, suggestion));
+               if (i < 10)
+                       add(w);
+               else
+                       item.submenu().add(w);
        }
+       if (i >= 10)
+               add(item);
+       if (i > 0)
+               add(MenuItem(MenuItem::Separator));
+       docstring arg = wl.word() + " " + from_ascii(wl.lang_code());
+       if (!wl.lang_variety().empty())
+               arg += from_ascii("-") + from_ascii(wl.lang_variety());
+       add(MenuItem(MenuItem::Command, qt_("Add to personal dictionary|c"),
+                       FuncRequest(LFUN_SPELLING_ADD, arg)));
+       add(MenuItem(MenuItem::Command, qt_("Ignore all|I"),
+                       FuncRequest(LFUN_SPELLING_IGNORE, arg)));
+       
 }
 
+
 void MenuDefinition::expandLastfiles()
 {
-       LastFilesSection::LastFiles const & lf = LyX::cref().session().lastFiles().lastFiles();
+       LastFilesSection::LastFiles const & lf = theSession().lastFiles().lastFiles();
        LastFilesSection::LastFiles::const_iterator lfit = lf.begin();
 
-       int ii = 1;
+       unsigned int ii = 1;
 
-       for (; lfit != lf.end() && ii < 10; ++lfit, ++ii) {
+       for (; lfit != lf.end() && ii <= lyxrc.num_lastfiles; ++lfit, ++ii) {
                string const file = lfit->absFilename();
-               QString const label = QString("%1. %2|%3").arg(ii)
-                       .arg(toqstr(makeDisplayPath(file, 30))).arg(ii);
+               QString label;
+               if (ii < 10)
+                       label = QString("%1. %2|%3").arg(ii)
+                               .arg(toqstr(makeDisplayPath(file, 30))).arg(ii);
+               else
+                       label = QString("%1. %2").arg(ii)
+                               .arg(toqstr(makeDisplayPath(file, 30)));
                add(MenuItem(MenuItem::Command, label, FuncRequest(LFUN_FILE_OPEN, file)));
        }
 }
@@ -666,35 +777,48 @@ void MenuDefinition::expandLastfiles()
 
 void MenuDefinition::expandDocuments()
 {
+       MenuItem item(MenuItem::Submenu, qt_("Invisible"));
+       item.setSubmenu(MenuDefinition(qt_("Invisible")));
+
        Buffer * first = theBufferList().first();
        if (first) {
                Buffer * b = first;
-               int ii = 1;
+               int vis = 1;
+               int invis = 1;
                
                // We cannot use a for loop as the buffer list cycles.
                do {
                        QString label = toqstr(b->fileName().displayName(20));
                        if (!b->isClean())
                                label += "*";
+                       bool const shown = guiApp->currentView()
+                                          ? guiApp->currentView()->workArea(*b) : false;
+                       int ii = shown ? vis : invis;
                        if (ii < 10)
                                label = QString::number(ii) + ". " + label + '|' + QString::number(ii);
-                       add(MenuItem(MenuItem::Command, label,
-                               FuncRequest(LFUN_BUFFER_SWITCH, b->absFileName())));
-                       
+                       if (shown) {
+                               add(MenuItem(MenuItem::Command, label,
+                                       FuncRequest(LFUN_BUFFER_SWITCH, b->absFileName())));
+                               ++vis;
+                       } else {
+                               item.submenu().add(MenuItem(MenuItem::Command, label,
+                                       FuncRequest(LFUN_BUFFER_SWITCH, b->absFileName())));
+                               ++invis;
+                       }
                        b = theBufferList().next(b);
-                       ++ii;
                } while (b != first); 
-       } else {
-               add(MenuItem(MenuItem::Command, qt_("No Documents Open!"),
-                          FuncRequest(LFUN_NOACTION)));
-       }
+               if (!item.submenu().empty())
+                       add(item);
+       } else
+               add(MenuItem(MenuItem::Info, qt_("<No Documents Open>")));
 }
 
 
 void MenuDefinition::expandBookmarks()
 {
-       lyx::BookmarksSection const & bm = LyX::cref().session().bookmarks();
+       lyx::BookmarksSection const & bm = theSession().bookmarks();
 
+       bool empty = true;
        for (size_t i = 1; i <= bm.size(); ++i) {
                if (bm.isValid(i)) {
                        string const file = bm.bookmark(i).filename.absFilename();
@@ -702,19 +826,18 @@ void MenuDefinition::expandBookmarks()
                                .arg(toqstr(makeDisplayPath(file, 20))).arg(i);
                        add(MenuItem(MenuItem::Command, label,
                                FuncRequest(LFUN_BOOKMARK_GOTO, convert<docstring>(i))));
+                       empty = false;
                }
        }
+       if (empty)
+               add(MenuItem(MenuItem::Info, qt_("<No Bookmarks Saved Yet>")));
 }
 
 
 void MenuDefinition::expandFormats(MenuItem::Kind kind, Buffer const * buf)
 {
-       if (!buf && kind != MenuItem::ImportFormats) {
-               add(MenuItem(MenuItem::Command,
-                                   qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       if (!buf && kind != MenuItem::ImportFormats)
                return;
-       }
 
        typedef vector<Format const *> Formats;
        Formats formats;
@@ -739,27 +862,54 @@ void MenuDefinition::expandFormats(MenuItem::Kind kind, Buffer const * buf)
        }
        sort(formats.begin(), formats.end(), &compareFormat);
 
+       bool const view_update = (kind == MenuItem::ViewFormats
+                       || kind == MenuItem::UpdateFormats);
+
+       QString smenue;
+       if (view_update)
+               smenue = (kind == MenuItem::ViewFormats ?
+                       qt_("View (Other Formats)|F")
+                       : qt_("Update (Other Formats)|p"));
+       MenuItem item(MenuItem::Submenu, smenue);
+       item.setSubmenu(MenuDefinition(smenue));
+
        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());
+
+               docstring lab = from_utf8((*fit)->prettyname());
+               docstring scut = from_utf8((*fit)->shortcut());
+               docstring const tmplab = lab;
+               if (!scut.empty())
+                       lab += char_type('|') + scut;
+               docstring lab_i18n = translateIfPossible(lab);
+               bool const untranslated = (lab == lab_i18n);
+               QString const shortcut = toqstr(split(lab_i18n, lab, '|'));
+               QString label = toqstr(lab);
+               if (untranslated)
+                       // this might happen if the shortcut
+                       // has been redefined
+                       label = toqstr(translateIfPossible(tmplab));
 
                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)->name() == buf->getDefaultOutputFormat()) {
+                               docstring lbl = (kind == MenuItem::ViewFormats ?
+                                       bformat(_("View [%1$s]|V"), qstring_to_ucs4(label))
+                                       : bformat(_("Update [%1$s]|U"), qstring_to_ucs4(label)));
+                               MenuItem w(MenuItem::Command, toqstr(lbl),
+                                               FuncRequest(action, (*fit)->name()));
+                               add(w);
+                               continue;
+                       }
+               case MenuItem::ExportFormats:
                        if (!(*fit)->documentFormat())
                                continue;
                        break;
@@ -767,31 +917,34 @@ void MenuDefinition::expandFormats(MenuItem::Kind kind, Buffer const * buf)
                        LASSERT(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))
+               if (!shortcut.isEmpty())
                        label += '|' + shortcut;
 
-               if (buf)
-                       addWithStatusCheck(MenuItem(MenuItem::Command, label,
-                               FuncRequest(action, (*fit)->name())));
-               else
-                       add(MenuItem(MenuItem::Command, label,
-                               FuncRequest(action, (*fit)->name())));
+               if (view_update) {
+                       if (buf)
+                               item.submenu().addWithStatusCheck(MenuItem(MenuItem::Command, label,
+                                       FuncRequest(action, (*fit)->name())));
+                       else
+                               item.submenu().add(MenuItem(MenuItem::Command, label,
+                                       FuncRequest(action, (*fit)->name())));
+               } else {
+                       if (buf)
+                               addWithStatusCheck(MenuItem(MenuItem::Command, label,
+                                       FuncRequest(action, (*fit)->name())));
+                       else
+                               add(MenuItem(MenuItem::Command, label,
+                                       FuncRequest(action, (*fit)->name())));
+               }
        }
+       if (view_update)
+               add(item);
 }
 
 
 void MenuDefinition::expandFloatListInsert(Buffer const * buf)
 {
-       if (!buf) {
-               add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       if (!buf)
                return;
-       }
 
        FloatList const & floats = buf->params().documentClass().floats();
        FloatList::const_iterator cit = floats.begin();
@@ -799,7 +952,7 @@ void MenuDefinition::expandFloatListInsert(Buffer const * buf)
        for (; cit != end; ++cit) {
                addWithStatusCheck(MenuItem(MenuItem::Command,
                                    qt_(cit->second.listName()),
-                                   FuncRequest(LFUN_FLOAT_LIST,
+                                   FuncRequest(LFUN_FLOAT_LIST_INSERT,
                                                cit->second.type())));
        }
 }
@@ -807,11 +960,8 @@ void MenuDefinition::expandFloatListInsert(Buffer const * buf)
 
 void MenuDefinition::expandFloatInsert(Buffer const * buf)
 {
-       if (!buf) {
-               add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       if (!buf)
                return;
-       }
 
        FloatList const & floats = buf->params().documentClass().floats();
        FloatList::const_iterator cit = floats.begin();
@@ -826,24 +976,27 @@ void MenuDefinition::expandFloatInsert(Buffer const * buf)
 }
 
 
-void MenuDefinition::expandFlexInsert(Buffer const * buf, string s)
+void MenuDefinition::expandFlexInsert(
+               Buffer const * buf, InsetLayout::InsetLyXType type)
 {
-       if (!buf) {
-               add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       if (!buf)
                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)
+               if (cit->second.lyxtype() == type) {
+                       docstring const label = cit->first;
                        addWithStatusCheck(MenuItem(MenuItem::Command, 
-                               toqstr(label), FuncRequest(LFUN_FLEX_INSERT,
-                                               label)));
+                               toqstr(translateIfPossible(label)),
+                               FuncRequest(LFUN_FLEX_INSERT, Lexer::quoteString(label))));
+               }
        }
+       // FIXME This is a little clunky.
+       if (items_.empty() && type == InsetLayout::CUSTOM)
+               add(MenuItem(MenuItem::Help, qt_("No Custom Insets Defined!")));
 }
 
 
@@ -911,15 +1064,10 @@ void MenuDefinition::expandToc(Buffer const * buf)
        // OK, so we avoid this unnecessary overhead (JMarc)
 
        if (!buf) {
-               add(MenuItem(MenuItem::Command, qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+               add(MenuItem(MenuItem::Info, qt_("<No Document Open>")));
                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) {
@@ -940,45 +1088,7 @@ void MenuDefinition::expandToc(Buffer const * buf)
                if (cit->first == "tableofcontents")
                        continue;
 
-               string const & floatName = floatlist.getType(cit->first).listName();
-               QString label;
-               bool in_other_list = true;
-               if (!floatName.empty()) {
-                       label = qt_(floatName);
-                       in_other_list = false;
-               }
-               else if (cit->first == "child") {
-                       label = qt_("Child Documents");
-                       in_other_list = false;
-               } else if (cit->first == "graphics")
-                       label = qt_("List of Graphics");
-               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") {
-                       // FIXME: the listing navigate menu causes a crash for unknown
-                       // reason. See http://bugzilla.lyx.org/show_bug.cgi?id=4613
-                       // This is a temporary fix:
-                       //label = qt_("List of Listings");
-                       continue;
-               }
-               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 Footnotes");
-               else if (cit->first == "label")
-                       label = qt_("Labels and References");
-               else if (cit->first == "citation")
-                       label = qt_("List of Citations");
-               else
-                       // This should not happen unless the entry is missing above.
-                       label = qt_("Other floats: ") + toqstr(cit->first);
-
                MenuDefinition submenu;
-
                if (cit->second.size() >= 30) {
                        FuncRequest f(LFUN_DIALOG_SHOW, "toc " + cit->first);
                        submenu.add(MenuItem(MenuItem::Command, qt_("Open Navigator..."), f));
@@ -986,20 +1096,20 @@ void MenuDefinition::expandToc(Buffer const * buf)
                        TocIterator ccit = cit->second.begin();
                        TocIterator eend = cit->second.end();
                        for (; ccit != eend; ++ccit) {
-                               QString const label = limitStringLength(ccit->str());
-                               submenu.add(MenuItem(MenuItem::Command, label,
+                               submenu.add(MenuItem(MenuItem::Command,
+                                       limitStringLength(ccit->str()),
                                        FuncRequest(ccit->action())));
                        }
                }
 
-               MenuItem item(MenuItem::Submenu, label);
+               MenuItem item(MenuItem::Submenu, guiName(cit->first, buf->params()));
                item.setSubmenu(submenu);
-               if (in_other_list)
-                       other_lists.add(item);
-               else {
+               if (floatlist.typeExist(cit->first) || cit->first == "child") {
+                       // Those two types deserve to be in the main menu.
                        item.setSubmenu(submenu);
                        add(item);
-               }
+               } else
+                       other_lists.add(item);
        }
        if (!other_lists.empty()) {
                MenuItem item(MenuItem::Submenu, qt_("Other Lists"));
@@ -1007,25 +1117,25 @@ void MenuDefinition::expandToc(Buffer const * buf)
                add(item);
        }
 
-
        // Handle normal TOC
        cit = toc_list.find("tableofcontents");
-       if (cit == end) {
-               addWithStatusCheck(MenuItem(MenuItem::Command,
-                                   qt_("No Table of contents"),
-                                   FuncRequest()));
-       } else {
-               expandToc2(cit->second, 0, cit->second.size(), 0);
+       if (cit == end)
+               LYXERR(Debug::GUI, "No table of contents.");
+       else {
+               if (cit->second.size() > 0 ) 
+                       expandToc2(cit->second, 0, cit->second.size(), 0);
+               else
+                       add(MenuItem(MenuItem::Info, qt_("<Empty Table of Contents>")));
        }
 }
 
 
-void MenuDefinition::expandPasteRecent()
+void MenuDefinition::expandPasteRecent(Buffer const * buf)
 {
-       vector<docstring> const sel = cap::availableSelections();
+       docstring_list const sel = cap::availableSelections(buf);
 
-       vector<docstring>::const_iterator cit = sel.begin();
-       vector<docstring>::const_iterator end = sel.end();
+       docstring_list::const_iterator cit = sel.begin();
+       docstring_list::const_iterator end = sel.end();
 
        for (unsigned int index = 0; cit != end; ++cit, ++index) {
                add(MenuItem(MenuItem::Command, toqstr(*cit),
@@ -1036,70 +1146,157 @@ void MenuDefinition::expandPasteRecent()
 
 void MenuDefinition::expandToolbars()
 {
-       //
+       MenuDefinition other_lists;
        // extracts the toolbars from the backend
-       ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin();
-       ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end();
-
+       Toolbars::Infos::const_iterator cit = guiApp->toolbars().begin();
+       Toolbars::Infos::const_iterator end = guiApp->toolbars().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)");
-               add(MenuItem(MenuItem::Command, label,
-                                   FuncRequest(LFUN_TOOLBAR_TOGGLE, cit->name + " allowauto")));
+               MenuItem const item(MenuItem::Command, toqstr(cit->gui_name),
+                               FuncRequest(LFUN_TOOLBAR_TOGGLE, cit->name));
+               if (guiApp->toolbars().isMainToolbar(cit->name))
+                       add(item);
+               else
+                       other_lists.add(item);
+       }
+
+       if (!other_lists.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_("Other Toolbars"));
+               item.setSubmenu(other_lists);
+               add(item);
        }
 }
 
 
 void MenuDefinition::expandBranches(Buffer const * buf)
 {
-       if (!buf) {
-               add(MenuItem(MenuItem::Command,
-                                   qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       if (!buf)
                return;
-       }
 
-       BufferParams const & params = buf->masterBuffer()->params();
-       if (params.branchlist().empty()) {
-               add(MenuItem(MenuItem::Command,
-                                   qt_("No Branch in Document!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       BufferParams const & master_params = buf->masterBuffer()->params();
+       BufferParams const & params = buf->params();
+       if (params.branchlist().empty() && master_params.branchlist().empty() ) {
+               add(MenuItem(MenuItem::Help, qt_("No Branches Set for Document!")));
                return;
        }
 
-       BranchList::const_iterator cit = params.branchlist().begin();
-       BranchList::const_iterator end = params.branchlist().end();
+       BranchList::const_iterator cit = master_params.branchlist().begin();
+       BranchList::const_iterator end = master_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);
+               docstring label = cit->branch();
+               if (ii < 10) {
+                       label = convert<docstring>(ii) + ". " + label
+                               + char_type('|') + convert<docstring>(ii);
+               }
                addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label),
                                    FuncRequest(LFUN_BRANCH_INSERT,
-                                               cit->getBranch())));
+                                               cit->branch())));
+       }
+       
+       if (buf == buf->masterBuffer())
+               return;
+       
+       MenuDefinition child_branches;
+       
+       BranchList::const_iterator ccit = params.branchlist().begin();
+       BranchList::const_iterator cend = params.branchlist().end();
+
+       for (int ii = 1; ccit != cend; ++ccit, ++ii) {
+               docstring label = ccit->branch();
+               if (ii < 10) {
+                       label = convert<docstring>(ii) + ". " + label
+                               + char_type('|') + convert<docstring>(ii);
+               }
+               child_branches.addWithStatusCheck(MenuItem(MenuItem::Command,
+                                   toqstr(label),
+                                   FuncRequest(LFUN_BRANCH_INSERT,
+                                               ccit->branch())));
+       }
+       
+       if (!child_branches.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_("Child Document"));
+               item.setSubmenu(child_branches);
+               add(item);
        }
 }
 
 
-void MenuDefinition::expandCiteStyles(BufferView const * bv)
+void MenuDefinition::expandIndices(Buffer const * buf, bool listof)
 {
-       if (!bv) {
-               add(MenuItem(MenuItem::Command,
-                                   qt_("No Document Open!"),
-                                   FuncRequest(LFUN_NOACTION)));
+       if (!buf)
+               return;
+
+       BufferParams const & params = buf->masterBuffer()->params();
+       if (!params.use_indices) {
+               if (listof)
+                       addWithStatusCheck(MenuItem(MenuItem::Command,
+                                          qt_("Index List|I"),
+                                          FuncRequest(LFUN_INDEX_PRINT,
+                                                 from_ascii("idx"))));
+               else
+                       addWithStatusCheck(MenuItem(MenuItem::Command,
+                                          qt_("Index Entry|d"),
+                                          FuncRequest(LFUN_INDEX_INSERT,
+                                                 from_ascii("idx"))));
+               return;
+       }
+
+       if (params.indiceslist().empty())
+               return;
+
+       IndicesList::const_iterator cit = params.indiceslist().begin();
+       IndicesList::const_iterator end = params.indiceslist().end();
+
+       for (int ii = 1; cit != end; ++cit, ++ii) {
+               if (listof)
+                       addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(cit->index()),
+                                          FuncRequest(LFUN_INDEX_PRINT,
+                                                 cit->shortcut())));
+               else {
+                       docstring label = _("Index Entry");
+                       label += " (" + cit->index() + ")";
+                       addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label),
+                                          FuncRequest(LFUN_INDEX_INSERT,
+                                                 cit->shortcut())));
+               }
+       }
+}
+
+
+void MenuDefinition::expandIndicesContext(Buffer const * buf, bool listof)
+{
+       if (!buf)
                return;
+
+       BufferParams const & params = buf->masterBuffer()->params();
+       if (!params.use_indices || params.indiceslist().empty())
+               return;
+
+       IndicesList::const_iterator cit = params.indiceslist().begin();
+       IndicesList::const_iterator end = params.indiceslist().end();
+
+       for (int ii = 1; cit != end; ++cit, ++ii) {
+               if (listof) {
+                       InsetCommandParams p(INDEX_PRINT_CODE);
+                       p["type"] = cit->shortcut();
+                       string const data = InsetCommand::params2string("index_print", p);
+                       addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(cit->index()),
+                                          FuncRequest(LFUN_INSET_MODIFY, data)));
+               } else {
+                       docstring label = _("Index Entry");
+                       label += " (" + cit->index() + ")";
+                       addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label),
+                                          FuncRequest(LFUN_INSET_MODIFY,
+                                                 from_ascii("changetype ") + cit->shortcut())));
+               }
        }
+}
+
+
+void MenuDefinition::expandCiteStyles(BufferView const * bv)
+{
+       if (!bv)
+               return;
 
        Inset const * inset = bv->cursor().nextInset();
        if (!inset || inset->lyxCode() != CITE_CODE) {
@@ -1118,11 +1315,11 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
                key = qstring_to_ucs4(toqstr(key).split(',')[0]);
 
        vector<CiteStyle> citeStyleList = citeStyles(buf->params().citeEngine());
-       vector<docstring> citeStrings =
+       docstring_list citeStrings =
                buf->masterBibInfo().getCiteStrings(key, bv->buffer());
 
-       vector<docstring>::const_iterator cit = citeStrings.begin();
-       vector<docstring>::const_iterator end = citeStrings.end();
+       docstring_list::const_iterator cit = citeStrings.begin();
+       docstring_list::const_iterator end = citeStrings.end();
 
        for (int ii = 1; cit != end; ++cit, ++ii) {
                docstring label = *cit;
@@ -1130,7 +1327,7 @@ void MenuDefinition::expandCiteStyles(BufferView const * bv)
                CiteStyle cst = citeStyleList[ii - 1];
                cs.style = cst;
                addWithStatusCheck(MenuItem(MenuItem::Command, toqstr(label),
-                                   FuncRequest(LFUN_NEXT_INSET_MODIFY,
+                                   FuncRequest(LFUN_INSET_MODIFY,
                                                "changetype " + from_utf8(citationStyleToString(cs)))));
        }
 }
@@ -1195,6 +1392,7 @@ void Menu::Impl::populate(QMenu & qMenu, MenuDefinition const & menu)
                else if (m->kind() == MenuItem::Submenu) {
                        QMenu * subMenu = qMenu.addMenu(label(*m));
                        populate(*subMenu, m->submenu());
+                       subMenu->setEnabled(m->status().enabled());
                } else {
                        // we have a MenuItem::Command
                        qMenu.addAction(new Action(view, QIcon(), label(*m), 
@@ -1247,7 +1445,7 @@ struct Menus::Impl {
        /// 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
+           ViewFormats, ExportFormats, UpdateFormats, Branches, Indices
        */
        void expand(MenuDefinition const & frommenu, MenuDefinition & tomenu,
                BufferView const *) const;
@@ -1258,9 +1456,14 @@ struct Menus::Impl {
        /// Mac special menu.
        /** 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
+           used by the Qt/Mac code.
+
+           NOTE: Qt does not remove the menu items when clearing a QMenuBar,
+           such that the items will keep accessing the FuncRequests in
+           the MenuDefinition. While Menus::Impl might be recreated,
+           we keep mac_special_menu_ in memory by making it static.
        */
-       MenuDefinition specialmenu_;
+       static MenuDefinition mac_special_menu_;
 
        ///
        MenuList menulist_;
@@ -1273,6 +1476,10 @@ struct Menus::Impl {
        NameMap name_map_;
 };
 
+
+MenuDefinition Menus::Impl::mac_special_menu_;
+
+
 /*
   Here is what the Qt documentation says about how a menubar is chosen:
 
@@ -1329,11 +1536,11 @@ void Menus::Impl::macxMenuBarInit(GuiView * view, QMenuBar * qmb)
        const size_t num_entries = sizeof(entries) / sizeof(entries[0]);
 
        // the special menu for Menus. Fill it up only once.
-       if (specialmenu_.size() == 0) {
+       if (mac_special_menu_.size() == 0) {
                for (size_t i = 0 ; i < num_entries ; ++i) {
                        FuncRequest const func(entries[i].action,
                                from_utf8(entries[i].arg));
-                       specialmenu_.add(MenuItem(MenuItem::Command, 
+                       mac_special_menu_.add(MenuItem(MenuItem::Command,
                                entries[i].label, func));
                }
        }
@@ -1341,8 +1548,8 @@ void Menus::Impl::macxMenuBarInit(GuiView * view, QMenuBar * qmb)
        // add the entries to a QMenu that will eventually be empty
        // and therefore invisible.
        QMenu * qMenu = qmb->addMenu("special");
-       MenuDefinition::const_iterator cit = specialmenu_.begin();
-       MenuDefinition::const_iterator end = specialmenu_.end();
+       MenuDefinition::const_iterator cit = mac_special_menu_.begin();
+       MenuDefinition::const_iterator end = mac_special_menu_.end();
        for (size_t i = 0 ; cit != end ; ++cit, ++i) {
                Action * action = new Action(view, QIcon(), cit->label(),
                        cit->func(), QString(), qMenu);
@@ -1382,15 +1589,15 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                        break;
 
                case MenuItem::CharStyles:
-                       tomenu.expandFlexInsert(buf, "charstyle");
+                       tomenu.expandFlexInsert(buf, InsetLayout::CHARSTYLE);
                        break;
 
                case MenuItem::Custom:
-                       tomenu.expandFlexInsert(buf, "custom");
+                       tomenu.expandFlexInsert(buf, InsetLayout::CUSTOM);
                        break;
 
                case MenuItem::Elements:
-                       tomenu.expandFlexInsert(buf, "element");
+                       tomenu.expandFlexInsert(buf, InsetLayout::ELEMENT);
                        break;
 
                case MenuItem::FloatListInsert:
@@ -1402,7 +1609,7 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                        break;
 
                case MenuItem::PasteRecent:
-                       tomenu.expandPasteRecent();
+                       tomenu.expandPasteRecent(buf);
                        break;
 
                case MenuItem::Toolbars:
@@ -1413,6 +1620,22 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                        tomenu.expandBranches(buf);
                        break;
 
+               case MenuItem::Indices:
+                       tomenu.expandIndices(buf);
+                       break;
+
+               case MenuItem::IndicesContext:
+                       tomenu.expandIndicesContext(buf);
+                       break;
+
+               case MenuItem::IndicesLists:
+                       tomenu.expandIndices(buf, true);
+                       break;
+
+               case MenuItem::IndicesListsContext:
+                       tomenu.expandIndicesContext(buf, true);
+                       break;
+
                case MenuItem::CiteStyles:
                        tomenu.expandCiteStyles(bv);
                        break;
@@ -1422,7 +1645,11 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                        break;
 
                case MenuItem::GraphicsGroups:
-                       tomenu.expandGraphicsGroups(buf);
+                       tomenu.expandGraphicsGroups(bv);
+                       break;
+
+               case MenuItem::SpellingSuggestions:
+                       tomenu.expandSpellingSuggestions(bv);
                        break;
 
                case MenuItem::Submenu: {
@@ -1433,12 +1660,14 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                }
                break;
 
+               case MenuItem::Info:
+               case MenuItem::Help:
                case MenuItem::Separator:
                        tomenu.addWithStatusCheck(*cit);
                        break;
 
                case MenuItem::Command:
-                       if (!specialmenu_.hasFunc(cit->func()))
+                       if (!mac_special_menu_.hasFunc(cit->func()))
                                tomenu.addWithStatusCheck(*cit);
                }
        }
@@ -1489,11 +1718,20 @@ MenuDefinition & Menus::Impl::getMenu(QString const & name)
 
 Menus::Menus() : d(new Impl) {}
 
+
 Menus::~Menus()
 {
   delete d;
 }
 
+
+void Menus::reset()
+{
+       delete d;
+       d = new Impl;
+}
+
+
 void Menus::read(Lexer & lex)
 {
        enum {
@@ -1547,7 +1785,7 @@ void Menus::read(Lexer & lex)
 
 
 bool Menus::searchMenu(FuncRequest const & func,
-       vector<docstring> & names) const
+       docstring_list & names) const
 {
        MenuDefinition menu;
        d->expand(d->menubar_, menu, 0);
@@ -1559,7 +1797,11 @@ void Menus::fillMenuBar(QMenuBar * qmb, GuiView * view, bool initial)
 {
        if (initial) {
 #ifdef Q_WS_MACX
-               // setup special mac specific menu item
+               // setup special mac specific menu items, but only do this
+               // the first time a QMenuBar is created. Otherwise Qt will
+               // create duplicate items in the application menu. It seems
+               // that Qt does not remove them when the QMenubar is cleared.
+               LYXERR(Debug::GUI, "Creating Mac OS X special menu bar");
                d->macxMenuBarInit(view, qmb);
 #endif
        } else {
@@ -1579,7 +1821,7 @@ void Menus::fillMenuBar(QMenuBar * qmb, GuiView * view, bool initial)
        MenuDefinition menu;
        BufferView * bv = 0;
        if (view)
-               bv = view->view();
+               bv = view->currentBufferView();
        d->expand(d->menubar_, menu, bv);
 
        MenuDefinition::const_iterator m = menu.begin();
@@ -1619,11 +1861,8 @@ void Menus::updateMenu(Menu * qmenu)
        if (qmenu->d->name.isEmpty())
                return;
 
-       // Here, We make sure that theLyXFunc points to the correct LyXView.
-       theLyXFunc().setLyXView(qmenu->d->view);
-
        if (!d->hasMenu(qmenu->d->name)) {
-               qmenu->addAction(qt_("No action defined!"));
+               qmenu->addAction(qt_("No Action Defined!"));
                LYXERR(Debug::GUI, "\tWARNING: non existing menu: "
                        << qmenu->d->name);
                return;
@@ -1632,7 +1871,7 @@ void Menus::updateMenu(Menu * qmenu)
        MenuDefinition const & fromLyxMenu = d->getMenu(qmenu->d->name);
        BufferView * bv = 0;
        if (qmenu->d->view)
-               bv = qmenu->d->view->view();
+               bv = qmenu->d->view->currentBufferView();
        d->expand(fromLyxMenu, *qmenu->d->top_level_menu, bv);
        qmenu->d->populate(*qmenu, *qmenu->d->top_level_menu);
 }
@@ -1655,4 +1894,4 @@ Menu * Menus::menu(QString const & name, GuiView & view)
 } // namespace frontend
 } // namespace lyx
 
-#include "Menus_moc.cpp"
+#include "moc_Menus.cpp"