3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Asger Alstrup
8 * \author Lars Gullik Bjønnes
9 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
12 * \author Martin Vermeer
14 * Full author contact details are available in file CREDITS.
22 #include "GuiApplication.h"
24 #include "qt_helpers.h"
26 #include "BiblioInfo.h"
27 #include "BranchList.h"
29 #include "BufferList.h"
30 #include "BufferParams.h"
31 #include "BufferView.h"
32 #include "Converter.h"
33 #include "CutAndPaste.h"
35 #include "FloatList.h"
37 #include "FuncRequest.h"
38 #include "FuncStatus.h"
39 #include "IndicesList.h"
42 #include "LyXAction.h"
43 #include "LyX.h" // for lastfiles
46 #include "Paragraph.h"
47 #include "ParIterator.h"
49 #include "TextClass.h"
50 #include "TocBackend.h"
52 #include "WordLangTuple.h"
54 #include "insets/Inset.h"
55 #include "insets/InsetCitation.h"
56 #include "insets/InsetGraphics.h"
58 #include "support/lassert.h"
59 #include "support/convert.h"
60 #include "support/debug.h"
61 #include "support/docstring_list.h"
62 #include "support/filetools.h"
63 #include "support/gettext.h"
64 #include "support/lstrings.h"
72 #include <boost/shared_ptr.hpp>
78 using namespace lyx::support
;
86 // MacOSX specific stuff is at the end.
93 /// The type of elements that can be in a menu
101 /** This type of item explains why something is unavailable. If this
102 menuitem is in a submenu, the submenu is enabled to make sure the
103 user sees the information. */
105 /** This type of item merely shows that there might be a list or
106 something alike at this position, but the list is still empty.
107 If this item is in a submenu, the submenu will not always be
110 /** This is the list of last opened file,
111 typically for the File menu. */
113 /** This is the list of opened Documents,
114 typically for the Documents menu. */
116 /** This is the bookmarks */
120 /** This is a list of viewable formats
121 typically for the File->View menu. */
123 /** This is a list of updatable formats
124 typically for the File->Update menu. */
126 /** This is a list of exportable formats
127 typically for the File->Export menu. */
129 /** This is a list of importable formats
130 typically for the File->Export menu. */
132 /** This is the list of elements available
133 * for insertion into document. */
135 /** This is the list of user-configurable
136 insets to insert into document */
138 /** This is the list of XML elements to
139 insert into the document */
141 /** This is the list of floats that we can
142 insert a list for. */
144 /** This is the list of floats that we can
147 /** This is the list of selections that can
152 /** Available branches in document */
154 /** Available indices in document */
156 /** Context menu for indices in document */
158 /** Available index lists in document */
160 /** Context menu for available indices lists in document */
162 /** Available citation styles for a given citation */
164 /** Available graphics groups */
166 /// Words suggested by the spellchecker.
170 explicit MenuItem(Kind kind
) : kind_(kind
), optional_(false) {}
173 QString
const & label
,
174 QString
const & submenu
= QString(),
175 bool optional
= false)
176 : kind_(kind
), label_(label
), submenuname_(submenu
), optional_(optional
)
178 LASSERT(kind
== Submenu
|| kind
== Help
|| kind
== Info
, /**/);
182 QString
const & label
,
183 FuncRequest
const & func
,
184 bool optional
= false,
185 FuncRequest::Origin origin
= FuncRequest::MENU
)
186 : kind_(kind
), label_(label
), func_(func
), optional_(optional
)
188 func_
.origin
= origin
;
191 // boost::shared_ptr<MenuDefinition> needs this apprently...
194 /// The label of a given menuitem
195 QString
label() const { return label_
.split('|')[0]; }
197 /// The keyboard shortcut (usually underlined in the entry)
198 QString
shortcut() const
200 return label_
.contains('|') ? label_
.split('|')[1] : QString();
202 /// The complete label, with label and shortcut separated by a '|'
203 QString
fulllabel() const { return label_
;}
204 /// The kind of entry
205 Kind
kind() const { return kind_
; }
206 /// the action (if relevant)
207 FuncRequest
const & func() const { return func_
; }
208 /// returns true if the entry should be ommited when disabled
209 bool optional() const { return optional_
; }
210 /// returns the status of the lfun associated with this entry
211 FuncStatus
const & status() const { return status_
; }
212 /// returns the status of the lfun associated with this entry
213 FuncStatus
& status() { return status_
; }
214 /// returns the status of the lfun associated with this entry
215 void status(FuncStatus
const & status
) { status_
= status
; }
217 ///returns the binding associated to this action.
218 QString
binding() const
220 if (kind_
!= Command
)
222 // Get the keys bound to this action, but keep only the
224 KeyMap::Bindings bindings
= theTopLevelKeymap().findBindings(func_
);
226 return toqstr(bindings
.begin()->print(KeySequence::ForGui
));
228 LYXERR(Debug::KBMAP
, "No binding for "
229 << lyxaction
.getActionName(func_
.action
)
230 << '(' << func_
.argument() << ')');
234 /// the description of the submenu (if relevant)
235 QString
const & submenuname() const { return submenuname_
; }
236 /// set the description of the submenu
237 void submenuname(QString
const & name
) { submenuname_
= name
; }
239 bool hasSubmenu() const { return !submenu_
.isEmpty(); }
241 MenuDefinition
const & submenu() const { return submenu_
.at(0); }
242 MenuDefinition
& submenu() { return submenu_
[0]; }
244 void setSubmenu(MenuDefinition
const & menu
)
247 submenu_
.append(menu
);
258 QString submenuname_
;
263 /// contains 0 or 1 item.
264 QList
<MenuDefinition
> submenu_
;
268 class MenuDefinition
{
271 typedef std::vector
<MenuItem
> ItemList
;
273 typedef ItemList::const_iterator const_iterator
;
275 explicit MenuDefinition(QString
const & name
= QString()) : name_(name
) {}
280 QString
const & name() const { return name_
; }
282 bool empty() const { return items_
.empty(); }
283 /// Clear the menu content.
284 void clear() { items_
.clear(); }
286 size_t size() const { return items_
.size(); }
288 MenuItem
const & operator[](size_t) const;
290 const_iterator
begin() const { return items_
.begin(); }
292 const_iterator
end() const { return items_
.end(); }
294 // search for func in this menu iteratively, and put menu
296 bool searchMenu(FuncRequest
const & func
, docstring_list
& names
)
299 bool hasFunc(FuncRequest
const &) const;
300 /// Add the menu item unconditionally
301 void add(MenuItem
const & item
) { items_
.push_back(item
); }
302 /// Checks the associated FuncRequest status before adding the
304 void addWithStatusCheck(MenuItem
const &);
305 // Check whether the menu shortcuts are unique
306 void checkShortcuts() const;
308 void expandLastfiles();
309 void expandDocuments();
310 void expandBookmarks();
311 void expandFormats(MenuItem::Kind kind
, Buffer
const * buf
);
312 void expandFloatListInsert(Buffer
const * buf
);
313 void expandFloatInsert(Buffer
const * buf
);
314 void expandFlexInsert(Buffer
const * buf
, InsetLayout::InsetLyXType type
);
315 void expandToc2(Toc
const & toc_list
, size_t from
, size_t to
, int depth
);
316 void expandToc(Buffer
const * buf
);
317 void expandPasteRecent(Buffer
const * buf
);
318 void expandToolbars();
319 void expandBranches(Buffer
const * buf
);
320 void expandIndices(Buffer
const * buf
, bool listof
= false);
321 void expandIndicesContext(Buffer
const * buf
, bool listof
= false);
322 void expandCiteStyles(BufferView
const *);
323 void expandGraphicsGroups(BufferView
const *);
324 void expandSpellingSuggestions(BufferView
const *);
332 /// Helper for std::find_if
336 MenuNamesEqual(QString
const & name
) : name_(name
) {}
337 bool operator()(MenuDefinition
const & menu
) const { return menu
.name() == name_
; }
344 typedef std::vector
<MenuDefinition
> MenuList
;
346 typedef MenuList::const_iterator const_iterator
;
348 typedef MenuList::iterator iterator
;
350 /////////////////////////////////////////////////////////////////////
351 // MenuDefinition implementation
352 /////////////////////////////////////////////////////////////////////
354 void MenuDefinition::addWithStatusCheck(MenuItem
const & i
)
358 case MenuItem::Command
: {
359 FuncStatus status
= lyx::getStatus(i
.func());
360 if (status
.unknown() || (!status
.enabled() && i
.optional()))
363 items_
.back().status(status
);
367 case MenuItem::Submenu
: {
368 bool enabled
= false;
369 if (i
.hasSubmenu()) {
370 for (const_iterator cit
= i
.submenu().begin();
371 cit
!= i
.submenu().end(); ++cit
) {
372 // Only these kind of items affect the status of the submenu
373 if ((cit
->kind() == MenuItem::Command
374 || cit
->kind() == MenuItem::Submenu
375 || cit
->kind() == MenuItem::Help
)
376 && cit
->status().enabled()) {
382 if (enabled
|| !i
.optional()) {
384 items_
.back().status().setEnabled(enabled
);
389 case MenuItem::Separator
:
390 if (!items_
.empty() && items_
.back().kind() != MenuItem::Separator
)
400 void MenuDefinition::read(Lexer
& lex
)
417 md_indiceslistscontext
,
431 md_spellingsuggestions
434 LexerKeyword menutags
[] = {
435 { "bookmarks", md_bookmarks
},
436 { "branches", md_branches
},
437 { "charstyles", md_charstyles
},
438 { "citestyles", md_citestyles
},
439 { "custom", md_custom
},
440 { "documents", md_documents
},
441 { "elements", md_elements
},
442 { "end", md_endmenu
},
443 { "exportformats", md_exportformats
},
444 { "floatinsert", md_floatinsert
},
445 { "floatlistinsert", md_floatlistinsert
},
446 { "graphicsgroups", md_graphicsgroups
},
447 { "importformats", md_importformats
},
448 { "indices", md_indices
},
449 { "indicescontext", md_indicescontext
},
450 { "indiceslists", md_indiceslists
},
451 { "indiceslistscontext", md_indiceslistscontext
},
453 { "lastfiles", md_lastfiles
},
454 { "optitem", md_optitem
},
455 { "optsubmenu", md_optsubmenu
},
456 { "pasterecent", md_pasterecent
},
457 { "separator", md_separator
},
458 { "spellingsuggestions", md_spellingsuggestions
},
459 { "submenu", md_submenu
},
461 { "toolbars", md_toolbars
},
462 { "updateformats", md_updateformats
},
463 { "viewformats", md_viewformats
}
466 lex
.pushTable(menutags
);
467 lex
.setContext("MenuDefinition::read: ");
470 bool optional
= false;
472 while (lex
.isOK() && !quit
) {
476 // fallback to md_item
479 docstring
const name
= translateIfPossible(lex
.getDocString());
481 string
const command
= lex
.getString();
482 FuncRequest func
= lyxaction
.lookupFunc(command
);
483 FuncRequest::Origin origin
= FuncRequest::MENU
;
484 if (name_
.startsWith("context-toc-"))
485 origin
= FuncRequest::TOC
;
486 add(MenuItem(MenuItem::Command
, toqstr(name
), func
, optional
, origin
));
492 add(MenuItem(MenuItem::Separator
));
496 add(MenuItem(MenuItem::Lastfiles
));
500 add(MenuItem(MenuItem::CharStyles
));
504 add(MenuItem(MenuItem::Custom
));
508 add(MenuItem(MenuItem::Elements
));
512 add(MenuItem(MenuItem::Documents
));
516 add(MenuItem(MenuItem::Bookmarks
));
520 add(MenuItem(MenuItem::Toc
));
524 add(MenuItem(MenuItem::ViewFormats
));
527 case md_updateformats
:
528 add(MenuItem(MenuItem::UpdateFormats
));
531 case md_exportformats
:
532 add(MenuItem(MenuItem::ExportFormats
));
535 case md_importformats
:
536 add(MenuItem(MenuItem::ImportFormats
));
539 case md_floatlistinsert
:
540 add(MenuItem(MenuItem::FloatListInsert
));
544 add(MenuItem(MenuItem::FloatInsert
));
548 add(MenuItem(MenuItem::PasteRecent
));
552 add(MenuItem(MenuItem::Toolbars
));
556 add(MenuItem(MenuItem::Branches
));
560 add(MenuItem(MenuItem::CiteStyles
));
563 case md_graphicsgroups
:
564 add(MenuItem(MenuItem::GraphicsGroups
));
567 case md_spellingsuggestions
:
568 add(MenuItem(MenuItem::SpellingSuggestions
));
572 add(MenuItem(MenuItem::Indices
));
575 case md_indicescontext
:
576 add(MenuItem(MenuItem::IndicesContext
));
579 case md_indiceslists
:
580 add(MenuItem(MenuItem::IndicesLists
));
583 case md_indiceslistscontext
:
584 add(MenuItem(MenuItem::IndicesListsContext
));
589 // fallback to md_submenu
592 docstring
const mlabel
= translateIfPossible(lex
.getDocString());
594 docstring
const mname
= lex
.getDocString();
595 add(MenuItem(MenuItem::Submenu
,
596 toqstr(mlabel
), toqstr(mname
), optional
));
606 lex
.printError("Unknown menu tag");
614 MenuItem
const & MenuDefinition::operator[](size_type i
) const
620 bool MenuDefinition::hasFunc(FuncRequest
const & func
) const
622 for (const_iterator it
= begin(), et
= end(); it
!= et
; ++it
)
623 if (it
->func() == func
)
629 void MenuDefinition::checkShortcuts() const
631 // This is a quadratic algorithm, but we do not care because
632 // menus are short enough
633 for (const_iterator it1
= begin(); it1
!= end(); ++it1
) {
634 QString shortcut
= it1
->shortcut();
635 if (shortcut
.isEmpty())
637 if (!it1
->label().contains(shortcut
))
638 LYXERR0("Menu warning: menu entry \""
640 << "\" does not contain shortcut `"
641 << shortcut
<< "'.");
642 for (const_iterator it2
= begin(); it2
!= it1
; ++it2
) {
643 if (!it2
->shortcut().compare(shortcut
, Qt::CaseInsensitive
)) {
644 LYXERR0("Menu warning: menu entries "
645 << '"' << it1
->fulllabel()
646 << "\" and \"" << it2
->fulllabel()
647 << "\" share the same shortcut.");
654 bool MenuDefinition::searchMenu(FuncRequest
const & func
, docstring_list
& names
) const
656 const_iterator m
= begin();
657 const_iterator m_end
= end();
658 for (; m
!= m_end
; ++m
) {
659 if (m
->kind() == MenuItem::Command
&& m
->func() == func
) {
660 names
.push_back(qstring_to_ucs4(m
->label()));
663 if (m
->kind() == MenuItem::Submenu
) {
664 names
.push_back(qstring_to_ucs4(m
->label()));
665 if (!m
->hasSubmenu()) {
666 LYXERR(Debug::GUI
, "Warning: non existing sub menu label="
667 << m
->label() << " name=" << m
->submenuname());
671 if (m
->submenu().searchMenu(func
, names
))
680 bool compareFormat(Format
const * p1
, Format
const * p2
)
686 QString
limitStringLength(docstring
const & str
)
688 size_t const max_item_length
= 45;
690 if (str
.size() > max_item_length
)
691 return toqstr(str
.substr(0, max_item_length
- 3) + "...");
697 void MenuDefinition::expandGraphicsGroups(BufferView
const * bv
)
702 graphics::getGraphicsGroups(bv
->buffer(), grp
);
706 set
<string
>::const_iterator it
= grp
.begin();
707 set
<string
>::const_iterator end
= grp
.end();
708 add(MenuItem(MenuItem::Command
, qt_("No Group"),
709 FuncRequest(LFUN_SET_GRAPHICS_GROUP
)));
710 for (; it
!= end
; it
++) {
711 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(*it
),
712 FuncRequest(LFUN_SET_GRAPHICS_GROUP
, *it
)));
717 void MenuDefinition::expandSpellingSuggestions(BufferView
const * bv
)
722 docstring_list suggestions
;
723 pos_type from
= bv
->cursor().pos();
725 Paragraph
const & par
= bv
->cursor().paragraph();
726 if (!par
.spellCheck(from
, to
, wl
, suggestions
))
728 LYXERR(Debug::GUI
, "Misspelled Word! Suggested Words = ");
730 MenuItem
item(MenuItem::Submenu
, qt_("More Spelling Suggestions"));
731 item
.setSubmenu(MenuDefinition(qt_("More Spelling Suggestions")));
732 for (; i
!= suggestions
.size(); ++i
) {
733 docstring
const & suggestion
= suggestions
[i
];
734 LYXERR(Debug::GUI
, suggestion
);
735 MenuItem
w(MenuItem::Command
, toqstr(suggestion
),
736 FuncRequest(LFUN_WORD_REPLACE
, suggestion
));
740 item
.submenu().add(w
);
747 void MenuDefinition::expandLastfiles()
749 LastFilesSection::LastFiles
const & lf
= theSession().lastFiles().lastFiles();
750 LastFilesSection::LastFiles::const_iterator lfit
= lf
.begin();
754 for (; lfit
!= lf
.end() && ii
<= lyxrc
.num_lastfiles
; ++lfit
, ++ii
) {
755 string
const file
= lfit
->absFilename();
758 label
= QString("%1. %2|%3").arg(ii
)
759 .arg(toqstr(makeDisplayPath(file
, 30))).arg(ii
);
761 label
= QString("%1. %2").arg(ii
)
762 .arg(toqstr(makeDisplayPath(file
, 30)));
763 add(MenuItem(MenuItem::Command
, label
, FuncRequest(LFUN_FILE_OPEN
, file
)));
768 void MenuDefinition::expandDocuments()
770 MenuItem
item(MenuItem::Submenu
, qt_("Invisible"));
771 item
.setSubmenu(MenuDefinition(qt_("Invisible")));
773 Buffer
* first
= theBufferList().first();
779 // We cannot use a for loop as the buffer list cycles.
781 QString label
= toqstr(b
->fileName().displayName(20));
784 bool const shown
= guiApp
->currentView()->workArea(*b
);
785 int ii
= shown
? vis
: invis
;
787 label
= QString::number(ii
) + ". " + label
+ '|' + QString::number(ii
);
789 add(MenuItem(MenuItem::Command
, label
,
790 FuncRequest(LFUN_BUFFER_SWITCH
, b
->absFileName())));
793 item
.submenu().add(MenuItem(MenuItem::Command
, label
,
794 FuncRequest(LFUN_BUFFER_SWITCH
, b
->absFileName())));
797 b
= theBufferList().next(b
);
798 } while (b
!= first
);
799 if (!item
.submenu().empty())
802 add(MenuItem(MenuItem::Info
, qt_("<No Documents Open>")));
806 void MenuDefinition::expandBookmarks()
808 lyx::BookmarksSection
const & bm
= theSession().bookmarks();
811 for (size_t i
= 1; i
<= bm
.size(); ++i
) {
813 string
const file
= bm
.bookmark(i
).filename
.absFilename();
814 QString
const label
= QString("%1. %2|%3").arg(i
)
815 .arg(toqstr(makeDisplayPath(file
, 20))).arg(i
);
816 add(MenuItem(MenuItem::Command
, label
,
817 FuncRequest(LFUN_BOOKMARK_GOTO
, convert
<docstring
>(i
))));
822 add(MenuItem(MenuItem::Info
, qt_("<No Bookmarks Saved Yet>")));
826 void MenuDefinition::expandFormats(MenuItem::Kind kind
, Buffer
const * buf
)
828 if (!buf
&& kind
!= MenuItem::ImportFormats
)
831 typedef vector
<Format
const *> Formats
;
836 case MenuItem::ImportFormats
:
837 formats
= theConverters().importableFormats();
838 action
= LFUN_BUFFER_IMPORT
;
840 case MenuItem::ViewFormats
:
841 formats
= buf
->exportableFormats(true);
842 action
= LFUN_BUFFER_VIEW
;
844 case MenuItem::UpdateFormats
:
845 formats
= buf
->exportableFormats(true);
846 action
= LFUN_BUFFER_UPDATE
;
849 formats
= buf
->exportableFormats(false);
850 action
= LFUN_BUFFER_EXPORT
;
852 sort(formats
.begin(), formats
.end(), &compareFormat
);
854 Formats::const_iterator fit
= formats
.begin();
855 Formats::const_iterator end
= formats
.end();
856 for (; fit
!= end
; ++fit
) {
860 docstring lab
= from_utf8((*fit
)->prettyname());
861 docstring scut
= from_utf8((*fit
)->shortcut());
862 docstring
const tmplab
= lab
;
865 lab
+= char_type('|') + scut
;
866 docstring lab_i18n
= translateIfPossible(lab
);
867 bool const untranslated
= (lab
== lab_i18n
);
868 QString
const shortcut
= toqstr(split(lab_i18n
, lab
, '|'));
869 QString label
= toqstr(lab
);
871 // this might happen if the shortcut
872 // has been redefined
873 label
= toqstr(translateIfPossible(tmplab
));
876 case MenuItem::ImportFormats
:
879 case MenuItem::ViewFormats
:
880 case MenuItem::UpdateFormats
:
881 if ((*fit
)->name() == buf
->getDefaultOutputFormat())
883 case MenuItem::ExportFormats
:
884 if (!(*fit
)->documentFormat())
888 LASSERT(false, /**/);
891 if (!shortcut
.isEmpty())
892 label
+= '|' + shortcut
;
895 addWithStatusCheck(MenuItem(MenuItem::Command
, label
,
896 FuncRequest(action
, (*fit
)->name())));
898 add(MenuItem(MenuItem::Command
, label
,
899 FuncRequest(action
, (*fit
)->name())));
904 void MenuDefinition::expandFloatListInsert(Buffer
const * buf
)
909 FloatList
const & floats
= buf
->params().documentClass().floats();
910 FloatList::const_iterator cit
= floats
.begin();
911 FloatList::const_iterator end
= floats
.end();
912 for (; cit
!= end
; ++cit
) {
913 addWithStatusCheck(MenuItem(MenuItem::Command
,
914 qt_(cit
->second
.listName()),
915 FuncRequest(LFUN_FLOAT_LIST_INSERT
,
916 cit
->second
.type())));
921 void MenuDefinition::expandFloatInsert(Buffer
const * buf
)
926 FloatList
const & floats
= buf
->params().documentClass().floats();
927 FloatList::const_iterator cit
= floats
.begin();
928 FloatList::const_iterator end
= floats
.end();
929 for (; cit
!= end
; ++cit
) {
931 QString
const label
= qt_(cit
->second
.name());
932 addWithStatusCheck(MenuItem(MenuItem::Command
, label
,
933 FuncRequest(LFUN_FLOAT_INSERT
,
934 cit
->second
.type())));
939 void MenuDefinition::expandFlexInsert(
940 Buffer
const * buf
, InsetLayout::InsetLyXType type
)
945 TextClass::InsetLayouts
const & insetLayouts
=
946 buf
->params().documentClass().insetLayouts();
947 TextClass::InsetLayouts::const_iterator cit
= insetLayouts
.begin();
948 TextClass::InsetLayouts::const_iterator end
= insetLayouts
.end();
949 for (; cit
!= end
; ++cit
) {
950 if (cit
->second
.lyxtype() == type
) {
951 docstring
const label
= cit
->first
;
952 addWithStatusCheck(MenuItem(MenuItem::Command
,
953 toqstr(translateIfPossible(label
)),
954 FuncRequest(LFUN_FLEX_INSERT
, Lexer::quoteString(label
))));
957 // FIXME This is a little clunky.
958 if (items_
.empty() && type
== InsetLayout::CUSTOM
)
959 add(MenuItem(MenuItem::Help
, qt_("No Custom Insets Defined!")));
963 size_t const max_number_of_items
= 25;
965 void MenuDefinition::expandToc2(Toc
const & toc_list
,
966 size_t from
, size_t to
, int depth
)
968 int shortcut_count
= 0;
970 // check whether depth is smaller than the smallest depth in toc.
971 int min_depth
= 1000;
972 for (size_t i
= from
; i
< to
; ++i
)
973 min_depth
= min(min_depth
, toc_list
[i
].depth());
974 if (min_depth
> depth
)
977 if (to
- from
<= max_number_of_items
) {
978 for (size_t i
= from
; i
< to
; ++i
) {
979 QString
label(4 * max(0, toc_list
[i
].depth() - depth
), ' ');
980 label
+= limitStringLength(toc_list
[i
].str());
981 if (toc_list
[i
].depth() == depth
982 && shortcut_count
< 9) {
983 if (label
.contains(QString::number(shortcut_count
+ 1)))
984 label
+= '|' + QString::number(++shortcut_count
);
986 add(MenuItem(MenuItem::Command
, label
,
987 FuncRequest(toc_list
[i
].action())));
992 size_t new_pos
= pos
+ 1;
993 while (new_pos
< to
&& toc_list
[new_pos
].depth() > depth
)
996 QString
label(4 * max(0, toc_list
[pos
].depth() - depth
), ' ');
997 label
+= limitStringLength(toc_list
[pos
].str());
998 if (toc_list
[pos
].depth() == depth
&&
999 shortcut_count
< 9) {
1000 if (label
.contains(QString::number(shortcut_count
+ 1)))
1001 label
+= '|' + QString::number(++shortcut_count
);
1003 if (new_pos
== pos
+ 1) {
1004 add(MenuItem(MenuItem::Command
,
1005 label
, FuncRequest(toc_list
[pos
].action())));
1008 sub
.expandToc2(toc_list
, pos
, new_pos
, depth
+ 1);
1009 MenuItem
item(MenuItem::Submenu
, label
);
1010 item
.setSubmenu(sub
);
1019 void MenuDefinition::expandToc(Buffer
const * buf
)
1021 // To make things very cleanly, we would have to pass buf to
1022 // all MenuItem constructors and to expandToc2. However, we
1023 // know that all the entries in a TOC will be have status_ ==
1024 // OK, so we avoid this unnecessary overhead (JMarc)
1027 add(MenuItem(MenuItem::Info
, qt_("<No Document Open>")));
1031 // Add an entry for the master doc if this is a child doc
1032 Buffer
const * const master
= buf
->masterBuffer();
1033 if (buf
!= master
) {
1034 ParIterator
const pit
= par_iterator_begin(master
->inset());
1035 string
const arg
= convert
<string
>(pit
->id());
1036 FuncRequest
f(LFUN_PARAGRAPH_GOTO
, arg
);
1037 add(MenuItem(MenuItem::Command
, qt_("Master Document"), f
));
1040 MenuDefinition other_lists
;
1042 FloatList
const & floatlist
= buf
->params().documentClass().floats();
1043 TocList
const & toc_list
= buf
->tocBackend().tocs();
1044 TocList::const_iterator cit
= toc_list
.begin();
1045 TocList::const_iterator end
= toc_list
.end();
1046 for (; cit
!= end
; ++cit
) {
1047 // Handle this later
1048 if (cit
->first
== "tableofcontents")
1051 MenuDefinition submenu
;
1052 if (cit
->second
.size() >= 30) {
1053 FuncRequest
f(LFUN_DIALOG_SHOW
, "toc " + cit
->first
);
1054 submenu
.add(MenuItem(MenuItem::Command
, qt_("Open Navigator..."), f
));
1056 TocIterator ccit
= cit
->second
.begin();
1057 TocIterator eend
= cit
->second
.end();
1058 for (; ccit
!= eend
; ++ccit
) {
1059 submenu
.add(MenuItem(MenuItem::Command
,
1060 limitStringLength(ccit
->str()),
1061 FuncRequest(ccit
->action())));
1065 MenuItem
item(MenuItem::Submenu
, guiName(cit
->first
, buf
->params()));
1066 item
.setSubmenu(submenu
);
1067 if (floatlist
.typeExist(cit
->first
) || cit
->first
== "child") {
1068 // Those two types deserve to be in the main menu.
1069 item
.setSubmenu(submenu
);
1072 other_lists
.add(item
);
1074 if (!other_lists
.empty()) {
1075 MenuItem
item(MenuItem::Submenu
, qt_("Other Lists"));
1076 item
.setSubmenu(other_lists
);
1080 // Handle normal TOC
1081 cit
= toc_list
.find("tableofcontents");
1083 LYXERR(Debug::GUI
, "No table of contents.");
1085 if (cit
->second
.size() > 0 )
1086 expandToc2(cit
->second
, 0, cit
->second
.size(), 0);
1088 add(MenuItem(MenuItem::Info
, qt_("<Empty Table of Contents>")));
1093 void MenuDefinition::expandPasteRecent(Buffer
const * buf
)
1095 docstring_list
const sel
= cap::availableSelections(buf
);
1097 docstring_list::const_iterator cit
= sel
.begin();
1098 docstring_list::const_iterator end
= sel
.end();
1100 for (unsigned int index
= 0; cit
!= end
; ++cit
, ++index
) {
1101 add(MenuItem(MenuItem::Command
, toqstr(*cit
),
1102 FuncRequest(LFUN_PASTE
, convert
<string
>(index
))));
1107 void MenuDefinition::expandToolbars()
1109 MenuDefinition other_lists
;
1110 // extracts the toolbars from the backend
1111 Toolbars::Infos::const_iterator cit
= guiApp
->toolbars().begin();
1112 Toolbars::Infos::const_iterator end
= guiApp
->toolbars().end();
1113 for (; cit
!= end
; ++cit
) {
1114 MenuItem
const item(MenuItem::Command
, toqstr(cit
->gui_name
),
1115 FuncRequest(LFUN_TOOLBAR_TOGGLE
, cit
->name
));
1116 if (guiApp
->toolbars().isMainToolbar(cit
->name
))
1119 other_lists
.add(item
);
1122 if (!other_lists
.empty()) {
1123 MenuItem
item(MenuItem::Submenu
, qt_("Other Toolbars"));
1124 item
.setSubmenu(other_lists
);
1130 void MenuDefinition::expandBranches(Buffer
const * buf
)
1135 BufferParams
const & master_params
= buf
->masterBuffer()->params();
1136 BufferParams
const & params
= buf
->params();
1137 if (params
.branchlist().empty() && master_params
.branchlist().empty() ) {
1138 add(MenuItem(MenuItem::Help
, qt_("No Branches Set for Document!")));
1142 BranchList::const_iterator cit
= master_params
.branchlist().begin();
1143 BranchList::const_iterator end
= master_params
.branchlist().end();
1145 for (int ii
= 1; cit
!= end
; ++cit
, ++ii
) {
1146 docstring label
= cit
->branch();
1148 label
= convert
<docstring
>(ii
) + ". " + label
1149 + char_type('|') + convert
<docstring
>(ii
);
1151 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(label
),
1152 FuncRequest(LFUN_BRANCH_INSERT
,
1156 if (buf
== buf
->masterBuffer())
1159 MenuDefinition child_branches
;
1161 BranchList::const_iterator ccit
= params
.branchlist().begin();
1162 BranchList::const_iterator cend
= params
.branchlist().end();
1164 for (int ii
= 1; ccit
!= cend
; ++ccit
, ++ii
) {
1165 docstring label
= ccit
->branch();
1167 label
= convert
<docstring
>(ii
) + ". " + label
1168 + char_type('|') + convert
<docstring
>(ii
);
1170 child_branches
.addWithStatusCheck(MenuItem(MenuItem::Command
,
1172 FuncRequest(LFUN_BRANCH_INSERT
,
1176 if (!child_branches
.empty()) {
1177 MenuItem
item(MenuItem::Submenu
, qt_("Child Document"));
1178 item
.setSubmenu(child_branches
);
1184 void MenuDefinition::expandIndices(Buffer
const * buf
, bool listof
)
1189 BufferParams
const & params
= buf
->masterBuffer()->params();
1190 if (!params
.use_indices
) {
1192 addWithStatusCheck(MenuItem(MenuItem::Command
,
1193 qt_("Index List|I"),
1194 FuncRequest(LFUN_INDEX_PRINT
,
1195 from_ascii("idx"))));
1197 addWithStatusCheck(MenuItem(MenuItem::Command
,
1198 qt_("Index Entry|d"),
1199 FuncRequest(LFUN_INDEX_INSERT
,
1200 from_ascii("idx"))));
1204 if (params
.indiceslist().empty())
1207 IndicesList::const_iterator cit
= params
.indiceslist().begin();
1208 IndicesList::const_iterator end
= params
.indiceslist().end();
1210 for (int ii
= 1; cit
!= end
; ++cit
, ++ii
) {
1212 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(cit
->index()),
1213 FuncRequest(LFUN_INDEX_PRINT
,
1216 docstring label
= _("Index Entry");
1217 label
+= " (" + cit
->index() + ")";
1218 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(label
),
1219 FuncRequest(LFUN_INDEX_INSERT
,
1226 void MenuDefinition::expandIndicesContext(Buffer
const * buf
, bool listof
)
1231 BufferParams
const & params
= buf
->masterBuffer()->params();
1232 if (!params
.use_indices
|| params
.indiceslist().empty())
1235 IndicesList::const_iterator cit
= params
.indiceslist().begin();
1236 IndicesList::const_iterator end
= params
.indiceslist().end();
1238 for (int ii
= 1; cit
!= end
; ++cit
, ++ii
) {
1240 InsetCommandParams
p(INDEX_PRINT_CODE
);
1241 p
["type"] = cit
->shortcut();
1242 string
const data
= InsetCommand::params2string("index_print", p
);
1243 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(cit
->index()),
1244 FuncRequest(LFUN_NEXT_INSET_MODIFY
, data
)));
1246 docstring label
= _("Index Entry");
1247 label
+= " (" + cit
->index() + ")";
1248 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(label
),
1249 FuncRequest(LFUN_NEXT_INSET_MODIFY
,
1250 from_ascii("changetype ") + cit
->shortcut())));
1256 void MenuDefinition::expandCiteStyles(BufferView
const * bv
)
1261 Inset
const * inset
= bv
->cursor().nextInset();
1262 if (!inset
|| inset
->lyxCode() != CITE_CODE
) {
1263 add(MenuItem(MenuItem::Command
,
1264 qt_("No Citation in Scope!"),
1265 FuncRequest(LFUN_NOACTION
)));
1268 InsetCommand
const * citinset
=
1269 static_cast<InsetCommand
const *>(inset
);
1271 Buffer
const * buf
= &bv
->buffer();
1272 docstring key
= citinset
->getParam("key");
1273 // we can only handle one key currently
1274 if (contains(key
, ','))
1275 key
= qstring_to_ucs4(toqstr(key
).split(',')[0]);
1277 vector
<CiteStyle
> citeStyleList
= citeStyles(buf
->params().citeEngine());
1278 docstring_list citeStrings
=
1279 buf
->masterBibInfo().getCiteStrings(key
, bv
->buffer());
1281 docstring_list::const_iterator cit
= citeStrings
.begin();
1282 docstring_list::const_iterator end
= citeStrings
.end();
1284 for (int ii
= 1; cit
!= end
; ++cit
, ++ii
) {
1285 docstring label
= *cit
;
1287 CiteStyle cst
= citeStyleList
[ii
- 1];
1289 addWithStatusCheck(MenuItem(MenuItem::Command
, toqstr(label
),
1290 FuncRequest(LFUN_NEXT_INSET_MODIFY
,
1291 "changetype " + from_utf8(citationStyleToString(cs
)))));
1298 /////////////////////////////////////////////////////////////////////
1299 // Menu::Impl definition and implementation
1300 /////////////////////////////////////////////////////////////////////
1304 /// populates the menu or one of its submenu
1305 /// This is used as a recursive function
1306 void populate(QMenu
& qMenu
, MenuDefinition
const & menu
);
1308 /// Only needed for top level menus.
1309 MenuDefinition
* top_level_menu
;
1312 /// the name of this menu
1318 /// Get a MenuDefinition item label from the menu backend
1319 static QString
label(MenuItem
const & mi
)
1321 QString label
= mi
.label();
1322 label
.replace("&", "&&");
1324 QString shortcut
= mi
.shortcut();
1325 if (!shortcut
.isEmpty()) {
1326 int pos
= label
.indexOf(shortcut
);
1328 //label.insert(pos, 1, char_type('&'));
1329 label
.replace(pos
, 0, "&");
1332 QString
const binding
= mi
.binding();
1333 if (!binding
.isEmpty())
1334 label
+= '\t' + binding
;
1339 void Menu::Impl::populate(QMenu
& qMenu
, MenuDefinition
const & menu
)
1341 LYXERR(Debug::GUI
, "populating menu " << menu
.name());
1342 if (menu
.size() == 0) {
1343 LYXERR(Debug::GUI
, "\tERROR: empty menu " << menu
.name());
1346 LYXERR(Debug::GUI
, " ***** menu entries " << menu
.size());
1347 MenuDefinition::const_iterator m
= menu
.begin();
1348 MenuDefinition::const_iterator end
= menu
.end();
1349 for (; m
!= end
; ++m
) {
1350 if (m
->kind() == MenuItem::Separator
)
1351 qMenu
.addSeparator();
1352 else if (m
->kind() == MenuItem::Submenu
) {
1353 QMenu
* subMenu
= qMenu
.addMenu(label(*m
));
1354 populate(*subMenu
, m
->submenu());
1355 subMenu
->setEnabled(m
->status().enabled());
1357 // we have a MenuItem::Command
1358 qMenu
.addAction(new Action(view
, QIcon(), label(*m
),
1359 m
->func(), QString(), &qMenu
));
1364 /////////////////////////////////////////////////////////////////////
1365 // Menu implementation
1366 /////////////////////////////////////////////////////////////////////
1368 Menu::Menu(GuiView
* gv
, QString
const & name
, bool top_level
)
1369 : QMenu(gv
), d(new Menu::Impl
)
1371 d
->top_level_menu
= top_level
? new MenuDefinition
: 0;
1375 if (d
->top_level_menu
)
1376 connect(this, SIGNAL(aboutToShow()), this, SLOT(updateView()));
1382 delete d
->top_level_menu
;
1387 void Menu::updateView()
1389 guiApp
->menus().updateMenu(this);
1393 /////////////////////////////////////////////////////////////////////
1394 // Menus::Impl definition and implementation
1395 /////////////////////////////////////////////////////////////////////
1397 struct Menus::Impl
{
1399 bool hasMenu(QString
const &) const;
1401 MenuDefinition
& getMenu(QString
const &);
1403 MenuDefinition
const & getMenu(QString
const &) const;
1405 /// Expands some special entries of the menu
1406 /** The entries with the following kind are expanded to a
1407 sequence of Command MenuItems: Lastfiles, Documents,
1408 ViewFormats, ExportFormats, UpdateFormats, Branches, Indices
1410 void expand(MenuDefinition
const & frommenu
, MenuDefinition
& tomenu
,
1411 BufferView
const *) const;
1413 /// Initialize specific MACOS X menubar
1414 void macxMenuBarInit(GuiView
* view
, QMenuBar
* qmb
);
1416 /// Mac special menu.
1417 /** This defines a menu whose entries list the FuncRequests
1418 that will be removed by expand() in other menus. This is
1419 used by the Qt/Mac code.
1421 NOTE: Qt does not remove the menu items when clearing a QMenuBar,
1422 such that the items will keep accessing the FuncRequests in
1423 the MenuDefinition. While Menus::Impl might be recreated,
1424 we keep mac_special_menu_ in memory by making it static.
1426 static MenuDefinition mac_special_menu_
;
1431 MenuDefinition menubar_
;
1433 typedef QMap
<GuiView
*, QHash
<QString
, Menu
*> > NameMap
;
1435 /// name to menu for \c menu() method.
1440 MenuDefinition
Menus::Impl::mac_special_menu_
;
1444 Here is what the Qt documentation says about how a menubar is chosen:
1446 1) If the window has a QMenuBar then it is used. 2) If the window
1447 is a modal then its menubar is used. If no menubar is specified
1448 then a default menubar is used (as documented below) 3) If the
1449 window has no parent then the default menubar is used (as
1452 The above 3 steps are applied all the way up the parent window
1453 chain until one of the above are satisifed. If all else fails a
1454 default menubar will be created, the default menubar on Qt/Mac is
1455 an empty menubar, however you can create a different default
1456 menubar by creating a parentless QMenuBar, the first one created
1457 will thus be designated the default menubar, and will be used
1458 whenever a default menubar is needed.
1460 Thus, for Qt/Mac, we add the menus to a free standing menubar, so
1461 that this menubar will be used also when one of LyX' dialogs has
1464 void Menus::Impl::macxMenuBarInit(GuiView
* view
, QMenuBar
* qmb
)
1466 /* Since Qt 4.2, the qt/mac menu code has special code for
1467 specifying the role of a menu entry. However, it does not
1468 work very well with our scheme of creating menus on demand,
1469 and therefore we need to put these entries in a special
1470 invisible menu. (JMarc)
1473 /* The entries of our special mac menu. If we add support for
1474 * special entries in Menus, we could imagine something
1476 * SpecialItem About " "About LyX" "dialog-show aboutlyx"
1477 * and therefore avoid hardcoding. I am not sure it is worth
1478 * the hassle, though. (JMarc)
1480 struct MacMenuEntry
{
1484 QAction::MenuRole role
;
1487 MacMenuEntry entries
[] = {
1488 {LFUN_DIALOG_SHOW
, "aboutlyx", "About LyX",
1489 QAction::AboutRole
},
1490 {LFUN_DIALOG_SHOW
, "prefs", "Preferences",
1491 QAction::PreferencesRole
},
1492 {LFUN_RECONFIGURE
, "", "Reconfigure",
1493 QAction::ApplicationSpecificRole
},
1494 {LFUN_LYX_QUIT
, "", "Quit LyX", QAction::QuitRole
}
1496 const size_t num_entries
= sizeof(entries
) / sizeof(entries
[0]);
1498 // the special menu for Menus. Fill it up only once.
1499 if (mac_special_menu_
.size() == 0) {
1500 for (size_t i
= 0 ; i
< num_entries
; ++i
) {
1501 FuncRequest
const func(entries
[i
].action
,
1502 from_utf8(entries
[i
].arg
));
1503 mac_special_menu_
.add(MenuItem(MenuItem::Command
,
1504 entries
[i
].label
, func
));
1508 // add the entries to a QMenu that will eventually be empty
1509 // and therefore invisible.
1510 QMenu
* qMenu
= qmb
->addMenu("special");
1511 MenuDefinition::const_iterator cit
= mac_special_menu_
.begin();
1512 MenuDefinition::const_iterator end
= mac_special_menu_
.end();
1513 for (size_t i
= 0 ; cit
!= end
; ++cit
, ++i
) {
1514 Action
* action
= new Action(view
, QIcon(), cit
->label(),
1515 cit
->func(), QString(), qMenu
);
1516 action
->setMenuRole(entries
[i
].role
);
1517 qMenu
->addAction(action
);
1522 void Menus::Impl::expand(MenuDefinition
const & frommenu
,
1523 MenuDefinition
& tomenu
, BufferView
const * bv
) const
1525 if (!tomenu
.empty())
1528 for (MenuDefinition::const_iterator cit
= frommenu
.begin();
1529 cit
!= frommenu
.end() ; ++cit
) {
1530 Buffer
const * buf
= bv
? &bv
->buffer() : 0;
1531 switch (cit
->kind()) {
1532 case MenuItem::Lastfiles
:
1533 tomenu
.expandLastfiles();
1536 case MenuItem::Documents
:
1537 tomenu
.expandDocuments();
1540 case MenuItem::Bookmarks
:
1541 tomenu
.expandBookmarks();
1544 case MenuItem::ImportFormats
:
1545 case MenuItem::ViewFormats
:
1546 case MenuItem::UpdateFormats
:
1547 case MenuItem::ExportFormats
:
1548 tomenu
.expandFormats(cit
->kind(), buf
);
1551 case MenuItem::CharStyles
:
1552 tomenu
.expandFlexInsert(buf
, InsetLayout::CHARSTYLE
);
1555 case MenuItem::Custom
:
1556 tomenu
.expandFlexInsert(buf
, InsetLayout::CUSTOM
);
1559 case MenuItem::Elements
:
1560 tomenu
.expandFlexInsert(buf
, InsetLayout::ELEMENT
);
1563 case MenuItem::FloatListInsert
:
1564 tomenu
.expandFloatListInsert(buf
);
1567 case MenuItem::FloatInsert
:
1568 tomenu
.expandFloatInsert(buf
);
1571 case MenuItem::PasteRecent
:
1572 tomenu
.expandPasteRecent(buf
);
1575 case MenuItem::Toolbars
:
1576 tomenu
.expandToolbars();
1579 case MenuItem::Branches
:
1580 tomenu
.expandBranches(buf
);
1583 case MenuItem::Indices
:
1584 tomenu
.expandIndices(buf
);
1587 case MenuItem::IndicesContext
:
1588 tomenu
.expandIndicesContext(buf
);
1591 case MenuItem::IndicesLists
:
1592 tomenu
.expandIndices(buf
, true);
1595 case MenuItem::IndicesListsContext
:
1596 tomenu
.expandIndicesContext(buf
, true);
1599 case MenuItem::CiteStyles
:
1600 tomenu
.expandCiteStyles(bv
);
1604 tomenu
.expandToc(buf
);
1607 case MenuItem::GraphicsGroups
:
1608 tomenu
.expandGraphicsGroups(bv
);
1611 case MenuItem::SpellingSuggestions
:
1612 tomenu
.expandSpellingSuggestions(bv
);
1615 case MenuItem::Submenu
: {
1616 MenuItem
item(*cit
);
1617 item
.setSubmenu(MenuDefinition(cit
->submenuname()));
1618 expand(getMenu(cit
->submenuname()), item
.submenu(), bv
);
1619 tomenu
.addWithStatusCheck(item
);
1623 case MenuItem::Info
:
1624 case MenuItem::Help
:
1625 case MenuItem::Separator
:
1626 tomenu
.addWithStatusCheck(*cit
);
1629 case MenuItem::Command
:
1630 if (!mac_special_menu_
.hasFunc(cit
->func()))
1631 tomenu
.addWithStatusCheck(*cit
);
1635 // we do not want the menu to end with a separator
1636 if (!tomenu
.empty() && tomenu
.items_
.back().kind() == MenuItem::Separator
)
1637 tomenu
.items_
.pop_back();
1639 // Check whether the shortcuts are unique
1640 tomenu
.checkShortcuts();
1644 bool Menus::Impl::hasMenu(QString
const & name
) const
1646 return find_if(menulist_
.begin(), menulist_
.end(),
1647 MenuNamesEqual(name
)) != menulist_
.end();
1651 MenuDefinition
const & Menus::Impl::getMenu(QString
const & name
) const
1653 const_iterator cit
= find_if(menulist_
.begin(), menulist_
.end(),
1654 MenuNamesEqual(name
));
1655 if (cit
== menulist_
.end())
1656 LYXERR0("No submenu named " << name
);
1657 LASSERT(cit
!= menulist_
.end(), /**/);
1662 MenuDefinition
& Menus::Impl::getMenu(QString
const & name
)
1664 iterator it
= find_if(menulist_
.begin(), menulist_
.end(),
1665 MenuNamesEqual(name
));
1666 if (it
== menulist_
.end())
1667 LYXERR0("No submenu named " << name
);
1668 LASSERT(it
!= menulist_
.end(), /**/);
1673 /////////////////////////////////////////////////////////////////////
1677 /////////////////////////////////////////////////////////////////////
1679 Menus::Menus() : d(new Impl
) {}
1695 void Menus::read(Lexer
& lex
)
1703 LexerKeyword menutags
[] = {
1704 { "end", md_endmenuset
},
1705 { "menu", md_menu
},
1706 { "menubar", md_menubar
}
1709 // consistency check
1710 if (compare_ascii_no_case(lex
.getString(), "menuset"))
1711 LYXERR0("Menus::read: ERROR wrong token: `" << lex
.getString() << '\'');
1713 lex
.pushTable(menutags
);
1714 lex
.setContext("Menus::read");
1718 while (lex
.isOK() && !quit
) {
1719 switch (lex
.lex()) {
1721 d
->menubar_
.read(lex
);
1725 QString
const name
= toqstr(lex
.getDocString());
1726 if (d
->hasMenu(name
))
1727 d
->getMenu(name
).read(lex
);
1729 MenuDefinition
menu(name
);
1731 d
->menulist_
.push_back(menu
);
1739 lex
.printError("Unknown menu tag");
1747 bool Menus::searchMenu(FuncRequest
const & func
,
1748 docstring_list
& names
) const
1750 MenuDefinition menu
;
1751 d
->expand(d
->menubar_
, menu
, 0);
1752 return menu
.searchMenu(func
, names
);
1756 void Menus::fillMenuBar(QMenuBar
* qmb
, GuiView
* view
, bool initial
)
1760 // setup special mac specific menu items, but only do this
1761 // the first time a QMenuBar is created. Otherwise Qt will
1762 // create duplicate items in the application menu. It seems
1763 // that Qt does not remove them when the QMenubar is cleared.
1764 LYXERR(Debug::GUI
, "Creating Mac OS X special menu bar");
1765 d
->macxMenuBarInit(view
, qmb
);
1768 // Clear all menubar contents before filling it.
1772 LYXERR(Debug::GUI
, "populating menu bar" << d
->menubar_
.name());
1774 if (d
->menubar_
.size() == 0) {
1775 LYXERR(Debug::GUI
, "\tERROR: empty menu bar"
1776 << d
->menubar_
.name());
1779 LYXERR(Debug::GUI
, "menu bar entries " << d
->menubar_
.size());
1781 MenuDefinition menu
;
1782 BufferView
* bv
= 0;
1785 d
->expand(d
->menubar_
, menu
, bv
);
1787 MenuDefinition::const_iterator m
= menu
.begin();
1788 MenuDefinition::const_iterator end
= menu
.end();
1790 for (; m
!= end
; ++m
) {
1792 if (m
->kind() != MenuItem::Submenu
) {
1793 LYXERR(Debug::GUI
, "\tERROR: not a submenu " << m
->label());
1797 LYXERR(Debug::GUI
, "menu bar item " << m
->label()
1798 << " is a submenu named " << m
->submenuname());
1800 QString name
= m
->submenuname();
1801 if (!d
->hasMenu(name
)) {
1802 LYXERR(Debug::GUI
, "\tERROR: " << name
1803 << " submenu has no menu!");
1807 Menu
* menu
= new Menu(view
, m
->submenuname(), true);
1808 menu
->setTitle(label(*m
));
1811 d
->name_map_
[view
][name
] = menu
;
1816 void Menus::updateMenu(Menu
* qmenu
)
1818 LYXERR(Debug::GUI
, "Triggered menu: " << qmenu
->d
->name
);
1821 if (qmenu
->d
->name
.isEmpty())
1824 // Here, We make sure that theLyXFunc points to the correct LyXView.
1825 theLyXFunc().setLyXView(qmenu
->d
->view
);
1827 if (!d
->hasMenu(qmenu
->d
->name
)) {
1828 qmenu
->addAction(qt_("No Action Defined!"));
1829 LYXERR(Debug::GUI
, "\tWARNING: non existing menu: "
1834 MenuDefinition
const & fromLyxMenu
= d
->getMenu(qmenu
->d
->name
);
1835 BufferView
* bv
= 0;
1837 bv
= qmenu
->d
->view
->view();
1838 d
->expand(fromLyxMenu
, *qmenu
->d
->top_level_menu
, bv
);
1839 qmenu
->d
->populate(*qmenu
, *qmenu
->d
->top_level_menu
);
1843 Menu
* Menus::menu(QString
const & name
, GuiView
& view
)
1845 LYXERR(Debug::GUI
, "Context menu requested: " << name
);
1846 Menu
* menu
= d
->name_map_
[&view
].value(name
, 0);
1847 if (!menu
&& !name
.startsWith("context-")) {
1848 LYXERR0("requested context menu not found: " << name
);
1852 menu
= new Menu(&view
, name
, true);
1853 d
->name_map_
[&view
][name
] = menu
;
1857 } // namespace frontend
1860 #include "moc_Menus.cpp"