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
This commit is contained in:
Juergen Spitzmueller 2018-12-26 15:46:14 +01:00
parent 057d83d8ae
commit 154b4fdece
14 changed files with 130 additions and 56 deletions

View File

@ -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 \

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

View File

@ -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")

View File

@ -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;

View File

@ -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 [<NUM>]
* \li Params: <NUM>: 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

View File

@ -109,6 +109,8 @@ public:
///
void toggleFree(Cursor & cur, Font const &, bool toggleall = false);
/// Stack to save recent text propterty applications
std::vector<docstring> getFreeFonts() const;
/// ???
/// FIXME: replace Cursor with DocIterator.

View File

@ -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<pair<docstring, Font>> 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<uint>(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<docstring> Text::getFreeFonts() const
{
vector<docstring> 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

View File

@ -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 {

View File

@ -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<docstring> ffList = bv->cursor().innerText()->getFreeFonts();
unsigned int i = 0;
Action * default_act = nullptr;
for (auto const & f : ffList) {
FuncRequest func(LFUN_TEXTSTYLE_APPLY, convert<docstring>(i),
FuncRequest::TOOLBAR);
docstring const lb = char_type('&') + convert<docstring>(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));
}

View File

@ -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().