From: Juergen Spitzmueller Date: Wed, 26 Dec 2018 14:46:14 +0000 (+0100) Subject: Give textstyle-apply a history X-Git-Tag: lyx-2.4.0dev-acb2ca7b~2822 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=154b4fde;p=features.git Give textstyle-apply a history The last 20 applications are saved now and accessible both via the lfun (textstyle-apply n) and the toolbar (via button menu) Fixes: #7133 This also changes the default icon and toolbar position of the action, as requested in #11427 --- diff --git a/lib/Makefile.am b/lib/Makefile.am index 3816d5c727..032103e2ab 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -473,6 +473,7 @@ dist_images_DATA1X = \ images/down.svgz \ images/dynamic-char-styles.svgz \ images/dynamic-custom-insets.svgz \ + images/dynamic-freefonts.svgz \ images/editclear.svgz \ images/emblem-readonly.svgz \ images/emblem-shellescape.svgz \ @@ -1759,6 +1760,7 @@ dist_imagesoxygen_DATA1X = \ images/oxygen/dialog-toggle_toc.svgz \ images/oxygen/dynamic-char-styles.svgz \ images/oxygen/dynamic-custom-insets.svgz \ + images/oxygen/dynamic-freefonts.svgz \ images/oxygen/down.svgz \ images/oxygen/editclear.svgz \ images/oxygen/ert-insert.svgz \ @@ -1965,6 +1967,7 @@ dist_imagesclassic_DATA = \ images/classic/dialog-show_vclog.png \ images/classic/dialog-toggle_findreplaceadv.png \ images/classic/dialog-toggle_toc.png \ + images/classic/dynamic-freefonts.png \ images/classic/down.png \ images/classic/ert-insert.png \ images/classic/file-open.png \ diff --git a/lib/images/classic/dynamic-freefonts.png b/lib/images/classic/dynamic-freefonts.png new file mode 100644 index 0000000000..a63ad1d76a Binary files /dev/null and b/lib/images/classic/dynamic-freefonts.png differ diff --git a/lib/images/dynamic-freefonts.svgz b/lib/images/dynamic-freefonts.svgz new file mode 100644 index 0000000000..5830eefb90 Binary files /dev/null and b/lib/images/dynamic-freefonts.svgz differ diff --git a/lib/images/oxygen/dynamic-freefonts.svgz b/lib/images/oxygen/dynamic-freefonts.svgz new file mode 100644 index 0000000000..7a7ffd0d66 Binary files /dev/null and b/lib/images/oxygen/dynamic-freefonts.svgz differ diff --git a/lib/images/textstyle-apply.svgz b/lib/images/textstyle-apply.svgz index 1a037d49f1..5830eefb90 100644 Binary files a/lib/images/textstyle-apply.svgz and b/lib/images/textstyle-apply.svgz differ diff --git a/lib/ui/stdtoolbars.inc b/lib/ui/stdtoolbars.inc index e0666f0b13..412d5647f8 100644 --- a/lib/ui/stdtoolbars.inc +++ b/lib/ui/stdtoolbars.inc @@ -87,7 +87,6 @@ ToolbarSet Item "Toggle emphasis" "font-emph" Item "Toggle noun" "font-noun" DynamicMenu "dynamic-char-styles" "Custom text styles" - Item "Apply last text properties" "textstyle-apply" Separator Item "Insert math" "math-mode on" Item "Insert graphics" "dialog-show-new-inset graphics" @@ -139,6 +138,7 @@ ToolbarSet Item "Include file" "dialog-show-new-inset include" Separator Item "Text properties" "dialog-show character" + DynamicMenu "dynamic-freefonts" "Apply recent text properties" Item "Paragraph settings" "layout-paragraph" Item "Thesaurus" "thesaurus-entry" End diff --git a/src/Font.cpp b/src/Font.cpp index ea31f40b0b..bb0b54805b 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -143,41 +143,41 @@ void Font::update(Font const & newfont, } -docstring const stateText(FontInfo const & f) +docstring const stateText(FontInfo const & f, bool const terse) { odocstringstream os; - if (f.family() != INHERIT_FAMILY) + if (f.family() != INHERIT_FAMILY && (!terse || f.family() != IGNORE_FAMILY)) os << _(GUIFamilyNames[f.family()]) << ", "; - if (f.series() != INHERIT_SERIES) + if (f.series() != INHERIT_SERIES && (!terse || f.series() != IGNORE_SERIES)) os << _(GUISeriesNames[f.series()]) << ", "; - if (f.shape() != INHERIT_SHAPE) + if (f.shape() != INHERIT_SHAPE && (!terse || f.shape() != IGNORE_SHAPE)) os << _(GUIShapeNames[f.shape()]) << ", "; - if (f.size() != FONT_SIZE_INHERIT) + if (f.size() != FONT_SIZE_INHERIT && (!terse || f.size() != FONT_SIZE_IGNORE)) os << _(GUISizeNames[f.size()]) << ", "; - if (f.color() != Color_inherit) + if (f.color() != Color_inherit && (!terse || f.color() != Color_ignore)) os << lcolor.getGUIName(f.color()) << ", "; // FIXME: uncomment this when we support background. //if (f.background() != Color_inherit) // os << lcolor.getGUIName(f.background()) << ", "; - if (f.emph() != FONT_INHERIT) + if (f.emph() != FONT_INHERIT && (!terse || f.emph() != FONT_IGNORE)) os << bformat(_("Emphasis %1$s, "), _(GUIMiscNames[f.emph()])); - if (f.underbar() != FONT_INHERIT) + if (f.underbar() != FONT_INHERIT && (!terse || f.underbar() == FONT_ON)) os << bformat(_("Underline %1$s, "), _(GUIMiscNames[f.underbar()])); - if (f.strikeout() != FONT_INHERIT) - os << bformat(_("Strike out %1$s, "), - _(GUIMiscNames[f.strikeout()])); - if (f.xout() != FONT_INHERIT) - os << bformat(_("Cross out %1$s, "), - _(GUIMiscNames[f.xout()])); - if (f.uuline() != FONT_INHERIT) + if (f.uuline() != FONT_INHERIT && (!terse || f.uuline() == FONT_ON)) os << bformat(_("Double underline %1$s, "), _(GUIMiscNames[f.uuline()])); - if (f.uwave() != FONT_INHERIT) + if (f.uwave() != FONT_INHERIT && (!terse || f.uwave() == FONT_ON)) os << bformat(_("Wavy underline %1$s, "), _(GUIMiscNames[f.uwave()])); - if (f.noun() != FONT_INHERIT) + if (f.strikeout() != FONT_INHERIT && (!terse || f.strikeout() == FONT_ON)) + os << bformat(_("Strike out %1$s, "), + _(GUIMiscNames[f.strikeout()])); + if (f.xout() != FONT_INHERIT && (!terse || f.strikeout() == FONT_ON)) + os << bformat(_("Cross out %1$s, "), + _(GUIMiscNames[f.xout()])); + if (f.noun() != FONT_INHERIT && (!terse || f.noun() != FONT_IGNORE)) os << bformat(_("Noun %1$s, "), _(GUIMiscNames[f.noun()])); if (f == inherit_font) @@ -187,11 +187,12 @@ docstring const stateText(FontInfo const & f) } -docstring const Font::stateText(BufferParams * params) const +docstring const Font::stateText(BufferParams * params, bool const terse) const { odocstringstream os; - os << lyx::stateText(bits_); - if (!params || (language() != params->language)) { + os << lyx::stateText(bits_, terse); + if ((!params || (language() != params->language)) + && (!terse || language() != ignore_language)) { // reset_language is a null pointer! os << bformat(_("Language: %1$s, "), (language() == reset_language) ? _("Default") diff --git a/src/Font.h b/src/Font.h index 9ec853d533..226ad26199 100644 --- a/src/Font.h +++ b/src/Font.h @@ -90,7 +90,7 @@ public: /// Build GUI description of font state - docstring const stateText(BufferParams * params) const; + docstring const stateText(BufferParams * params, bool const terse = false) const; /// void validate(LaTeXFeatures & features) const; diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp index f5ed3f8787..6d3175222b 100644 --- a/src/LyXAction.cpp +++ b/src/LyXAction.cpp @@ -3830,8 +3830,10 @@ void LyXAction::init() /*! * \var lyx::FuncCode lyx::LFUN_TEXTSTYLE_APPLY - * \li Action: Toggle user-defined (=last-time used) text style. - * \li Notion: This style is set via #LFUN_TEXTSTYLE_UPDATE, which is + * \li Action: Apply last used text properties. + * \li Syntax: textstyle-apply [] + * \li Params: : number of the selection in the internal freefonts stack to be applied. + * \li Notion: These properties are stored via #LFUN_TEXTSTYLE_UPDATE, which is automatically triggered when using Text Style dialog. * \li Syntax: textstyle-apply * \li Origin: leeming, 12 Mar 2003 diff --git a/src/Text.h b/src/Text.h index b54277beef..054b6f6ee4 100644 --- a/src/Text.h +++ b/src/Text.h @@ -109,6 +109,8 @@ public: /// void toggleFree(Cursor & cur, Font const &, bool toggleall = false); + /// Stack to save recent text propterty applications + std::vector getFreeFonts() const; /// ??? /// FIXME: replace Cursor with DocIterator. diff --git a/src/Text3.cpp b/src/Text3.cpp index 45eb8155f2..9dce236a41 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -72,6 +72,7 @@ #include "support/debug.h" #include "support/gettext.h" #include "support/lassert.h" +#include "support/limited_stack.h" #include "support/lstrings.h" #include "support/lyxalgo.h" #include "support/lyxtime.h" @@ -105,7 +106,8 @@ using cap::pasteSimpleText; using frontend::Clipboard; // globals... -static Font freefont(ignore_font, ignore_language); +typedef limited_stack> FontStack; +static FontStack freeFonts(15); static bool toggleall = false; static void toggleAndShow(Cursor & cur, Text * text, @@ -2364,10 +2366,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_TEXTSTYLE_APPLY: - toggleAndShow(cur, this, freefont, toggleall); - cur.message(_("Character set")); + case LFUN_TEXTSTYLE_APPLY: { + unsigned int num = 0; + string const arg = to_utf8(cmd.argument()); + // Argument? + if (!arg.empty()) { + if (isStrUnsignedInt(arg)) { + num = convert(arg); + if (num >= freeFonts.size()) { + cur.message(_("Invalid argument (number exceeds stack size)!")); + break; + } + } else { + cur.message(_("Invalid argument (must be a positive number)!")); + break; + } + } + toggleAndShow(cur, this, freeFonts[num].second, toggleall); + cur.message(bformat(_("Text properties applied: %1$s"), freeFonts[num].first)); break; + } // Set the freefont using the contents of \param data dispatched from // the frontends and apply it at the current cursor location. @@ -2375,17 +2393,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) Font font; bool toggle; if (font.fromString(to_utf8(cmd.argument()), toggle)) { - freefont = font; + docstring const props = font.stateText(&bv->buffer().params(), true); + freeFonts.push(make_pair(props, font)); toggleall = toggle; - toggleAndShow(cur, this, freefont, toggleall); + toggleAndShow(cur, this, font, toggleall); // We need a buffer update if we change the language // of an info inset if (cur.insetInSelection(INFO_CODE)) cur.forceBufferUpdate(); - cur.message(_("Character set")); - } else { - lyxerr << "Argument not ok"; - } + cur.message(bformat(_("Text properties applied: %1$s"), props)); + } else + LYXERR0("Invalid argument of textstyle-update"); break; } @@ -3378,11 +3396,14 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_FONT_CROSSOUT: case LFUN_FONT_UNDERUNDERLINE: case LFUN_FONT_UNDERWAVE: - case LFUN_TEXTSTYLE_APPLY: case LFUN_TEXTSTYLE_UPDATE: enable = !cur.paragraph().isPassThru(); break; + case LFUN_TEXTSTYLE_APPLY: + enable = !freeFonts.empty(); + break; + case LFUN_WORD_DELETE_FORWARD: case LFUN_WORD_DELETE_BACKWARD: case LFUN_LINE_DELETE_FORWARD: @@ -3506,4 +3527,19 @@ bool Text::inDescriptionItem(Cursor & cur) const && (pos == 0 || par.getChar(pos - 1) != ' '))); } + +std::vector Text::getFreeFonts() const +{ + vector ffList; + + FontStack::const_iterator cit = freeFonts.begin(); + FontStack::const_iterator end = freeFonts.end(); + for (; cit != end; ++cit) + // we do not use cit-> here because gcc 2.9x does not + // like it (JMarc) + ffList.push_back((*cit).first); + + return ffList; +} + } // namespace lyx diff --git a/src/frontends/qt4/GuiFontLoader.cpp b/src/frontends/qt4/GuiFontLoader.cpp index 4f705330f9..4839ad378d 100644 --- a/src/frontends/qt4/GuiFontLoader.cpp +++ b/src/frontends/qt4/GuiFontLoader.cpp @@ -42,7 +42,8 @@ int const num_math_fonts = sizeof(math_fonts) / sizeof(*math_fonts); namespace lyx { -extern docstring const stateText(FontInfo const & f); +extern docstring const stateText(FontInfo const & f, + bool const terse = false); namespace frontend { diff --git a/src/frontends/qt4/GuiToolbar.cpp b/src/frontends/qt4/GuiToolbar.cpp index ce1b2b7e7b..ea2683b371 100644 --- a/src/frontends/qt4/GuiToolbar.cpp +++ b/src/frontends/qt4/GuiToolbar.cpp @@ -41,6 +41,7 @@ #include "insets/InsetText.h" +#include "support/convert.h" #include "support/debug.h" #include "support/gettext.h" #include "support/lstrings.h" @@ -318,8 +319,9 @@ void DynamicMenuButton::initialize() bool DynamicMenuButton::isMenuType(string const & s) { - return s == "dynamic-custom-insets" || - s == "dynamic-char-styles"; + return s == "dynamic-custom-insets" + || s == "dynamic-char-styles" + || s == "dynamic-freefonts"; } @@ -336,28 +338,54 @@ void DynamicMenuButton::updateTriggered() setEnabled(false); setMinimumWidth(sizeHint().width()); d->text_class_.reset(); - d->inset_ = 0; + d->inset_ = nullptr; return; } - DocumentClassConstPtr text_class = - bv->buffer().params().documentClassPtr(); - InsetText const * inset = &(bv->cursor().innerText()->inset()); - // if the text class has changed, then we need to reload the menu - if (d->text_class_ != text_class) { - d->text_class_ = text_class; - // at the moment, we can just call loadFlexInsets, and it will - // handle both types. if there were more types of menus, then we - // might need to have other options. - loadFlexInsets(); + string const & menutype = tbitem_.name_; + if (menutype == "dynamic-custom-insets" || menutype == "dynamic-char-styles") { + DocumentClassConstPtr text_class = + bv->buffer().params().documentClassPtr(); + InsetText const * inset = &(bv->cursor().innerText()->inset()); + // if the text class has changed, then we need to reload the menu + if (d->text_class_ != text_class) { + d->text_class_ = text_class; + // at the moment, we can just call loadFlexInsets, and it will + // handle both types. if there were more types of menus, then we + // might need to have other options. + loadFlexInsets(); + } + // remember where we are + d->inset_ = inset; + // note that enabling here might need to be more subtle if there + // were other kinds of menus. + setEnabled(!bv->buffer().isReadonly() + && !m->isEmpty() + && inset->insetAllowed(FLEX_CODE)); + } else if (menutype == "dynamic-freefonts") { + m->clear(); + vector ffList = bv->cursor().innerText()->getFreeFonts(); + unsigned int i = 0; + Action * default_act = nullptr; + for (auto const & f : ffList) { + FuncRequest func(LFUN_TEXTSTYLE_APPLY, convert(i), + FuncRequest::TOOLBAR); + docstring const lb = char_type('&') + convert(i) + + from_ascii(". ") + f ; + Action * act = new Action(func, QIcon(), toqstr(lb), toqstr(f), this); + m->addAction(act); + // The most recent one is the default + if (i == 0) + default_act = act; + ++i; + } + if (default_act) { + QToolButton::setDefaultAction(default_act); + QToolButton::setIcon(getIcon(FuncRequest(LFUN_TEXTSTYLE_APPLY), false)); + } + setPopupMode(QToolButton::DelayedPopup); + setEnabled(lyx::getStatus(FuncRequest(LFUN_TEXTSTYLE_APPLY)).enabled()); } - // remember where we are - d->inset_ = inset; - // note that enabling here might need to be more subtle if there - // were other kinds of menus. - setEnabled(!bv->buffer().isReadonly() && - !m->isEmpty() && - inset->insetAllowed(FLEX_CODE)); } diff --git a/src/frontends/qt4/GuiToolbar.h b/src/frontends/qt4/GuiToolbar.h index c82134790b..da09bbfbbf 100644 --- a/src/frontends/qt4/GuiToolbar.h +++ b/src/frontends/qt4/GuiToolbar.h @@ -86,6 +86,7 @@ protected Q_SLOTS: /// (stdtoolbars.inc, usually) and must be one of: /// dynamic-custom-insets /// dynamic-char-styles +/// dynamic-freefonts /// To add a new one of these, you must add a routine, like /// loadFlexInsets, that will populate the menu, and call it from /// updateTriggered. Make sure to add the new type to isMenuType().