mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Add toolbar menus for custom insets and character styles.
I'm open to putting this elsewhere on the toolbar, or even on a different toolbar. Also, we need decent icons. These ones are not intended seriously but were just borrowed for testing purposes. Anyone have good ideas about icons?
This commit is contained in:
parent
e91245362f
commit
cc4bfc7f04
@ -469,6 +469,8 @@ dist_images_DATA1X = \
|
||||
images/dialog-toggle_findreplaceadv.svgz \
|
||||
images/dialog-toggle_toc.svgz \
|
||||
images/down.svgz \
|
||||
images/dynamic-char-styles.svgz \
|
||||
images/dynamic-custom-insets.svgz \
|
||||
images/editclear.svgz \
|
||||
images/emblem-readonly.svgz \
|
||||
images/emblem-shellescape.svgz \
|
||||
@ -1746,6 +1748,8 @@ dist_imagesoxygen_DATA1X = \
|
||||
images/oxygen/dialog-show_vclog.svgz \
|
||||
images/oxygen/dialog-toggle_findreplaceadv.svgz \
|
||||
images/oxygen/dialog-toggle_toc.svgz \
|
||||
images/oxygen/dynamic-char-styles.svgz \
|
||||
images/oxygen/dynamic-custom-insets.svgz \
|
||||
images/oxygen/down.svgz \
|
||||
images/oxygen/editclear.svgz \
|
||||
images/oxygen/ert-insert.svgz \
|
||||
|
BIN
lib/images/dynamic-char-styles.svgz
Normal file
BIN
lib/images/dynamic-char-styles.svgz
Normal file
Binary file not shown.
BIN
lib/images/dynamic-custom-insets.svgz
Normal file
BIN
lib/images/dynamic-custom-insets.svgz
Normal file
Binary file not shown.
BIN
lib/images/oxygen/dynamic-char-styles.svgz
Normal file
BIN
lib/images/oxygen/dynamic-char-styles.svgz
Normal file
Binary file not shown.
BIN
lib/images/oxygen/dynamic-custom-insets.svgz
Normal file
BIN
lib/images/oxygen/dynamic-custom-insets.svgz
Normal file
Binary file not shown.
@ -96,6 +96,9 @@ ToolbarSet
|
||||
Item "Toggle math toolbar" "toolbar-toggle math"
|
||||
Item "Toggle table toolbar" "toolbar-toggle table"
|
||||
Item "Toggle review toolbar" "toolbar-toggle review"
|
||||
Separator
|
||||
DynamicMenu "dynamic-custom-insets" "Custom Insets"
|
||||
DynamicMenu "dynamic-char-styles" "Character Styles"
|
||||
End
|
||||
|
||||
Toolbar "view/update" "View/Update"
|
||||
|
@ -18,21 +18,28 @@
|
||||
#include "GuiToolbar.h"
|
||||
|
||||
#include "Action.h"
|
||||
#include "Buffer.h"
|
||||
#include "BufferParams.h"
|
||||
#include "BufferView.h"
|
||||
#include "Cursor.h"
|
||||
#include "FuncRequest.h"
|
||||
#include "FuncStatus.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "GuiCommandBuffer.h"
|
||||
#include "GuiView.h"
|
||||
#include "IconPalette.h"
|
||||
#include "InsertTableWidget.h"
|
||||
#include "LayoutBox.h"
|
||||
#include "qt_helpers.h"
|
||||
#include "Toolbars.h"
|
||||
|
||||
#include "FuncRequest.h"
|
||||
#include "FuncStatus.h"
|
||||
#include "KeyMap.h"
|
||||
#include "LayoutBox.h"
|
||||
#include "LyX.h"
|
||||
#include "LyXRC.h"
|
||||
#include "qt_helpers.h"
|
||||
#include "Session.h"
|
||||
#include "Text.h"
|
||||
#include "TextClass.h"
|
||||
#include "Toolbars.h"
|
||||
|
||||
#include "insets/InsetText.h"
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/gettext.h"
|
||||
@ -181,7 +188,7 @@ public:
|
||||
} // namespace
|
||||
|
||||
|
||||
MenuButton::MenuButton(GuiToolbar * bar, ToolbarItem const & item, bool const sticky)
|
||||
MenuButtonBase::MenuButtonBase(GuiToolbar * bar, ToolbarItem const & item)
|
||||
: QToolButton(bar), bar_(bar), tbitem_(item)
|
||||
{
|
||||
setPopupMode(QToolButton::InstantPopup);
|
||||
@ -201,6 +208,20 @@ MenuButton::MenuButton(GuiToolbar * bar, ToolbarItem const & item, bool const st
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MenuButtonBase::actionTriggered(QAction * action)
|
||||
{
|
||||
QToolButton::setDefaultAction(action);
|
||||
setPopupMode(QToolButton::DelayedPopup);
|
||||
}
|
||||
|
||||
|
||||
StaticMenuButton::StaticMenuButton(
|
||||
GuiToolbar * bar, ToolbarItem const & item, bool const sticky)
|
||||
: MenuButtonBase(bar, item)
|
||||
{
|
||||
if (sticky)
|
||||
connect(this, SIGNAL(triggered(QAction *)),
|
||||
this, SLOT(actionTriggered(QAction *)));
|
||||
@ -210,7 +231,7 @@ MenuButton::MenuButton(GuiToolbar * bar, ToolbarItem const & item, bool const st
|
||||
}
|
||||
|
||||
|
||||
void MenuButton::initialize()
|
||||
void StaticMenuButton::initialize()
|
||||
{
|
||||
QString const label = qt_(to_ascii(tbitem_.label_));
|
||||
ButtonMenu * m = new ButtonMenu(label, this);
|
||||
@ -232,14 +253,7 @@ void MenuButton::initialize()
|
||||
}
|
||||
|
||||
|
||||
void MenuButton::actionTriggered(QAction * action)
|
||||
{
|
||||
QToolButton::setDefaultAction(action);
|
||||
setPopupMode(QToolButton::DelayedPopup);
|
||||
}
|
||||
|
||||
|
||||
void MenuButton::updateTriggered()
|
||||
void StaticMenuButton::updateTriggered()
|
||||
{
|
||||
if (!menu())
|
||||
return;
|
||||
@ -261,6 +275,126 @@ void MenuButton::updateTriggered()
|
||||
}
|
||||
|
||||
|
||||
class DynamicMenuButton::Private
|
||||
{
|
||||
/// noncopyable
|
||||
Private(Private const &);
|
||||
void operator=(Private const &);
|
||||
public:
|
||||
Private() : inset_(0) {}
|
||||
///
|
||||
DocumentClassConstPtr text_class_;
|
||||
///
|
||||
InsetText const * inset_;
|
||||
};
|
||||
|
||||
|
||||
DynamicMenuButton::DynamicMenuButton(GuiToolbar * bar, ToolbarItem const & item)
|
||||
: MenuButtonBase(bar, item), d(new Private())
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
DynamicMenuButton::~DynamicMenuButton()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
void DynamicMenuButton::initialize()
|
||||
{
|
||||
QString const label = qt_(to_ascii(tbitem_.label_));
|
||||
ButtonMenu * m = new ButtonMenu(label, this);
|
||||
m->setWindowTitle(label);
|
||||
m->setTearOffEnabled(true);
|
||||
connect(bar_, SIGNAL(updated()), m, SLOT(updateParent()));
|
||||
connect(bar_, SIGNAL(updated()), this, SLOT(updateTriggered()));
|
||||
connect(bar_, SIGNAL(iconSizeChanged(QSize)),
|
||||
this, SLOT(setIconSize(QSize)));
|
||||
setMenu(m);
|
||||
}
|
||||
|
||||
|
||||
bool DynamicMenuButton::isMenuType(string const & s)
|
||||
{
|
||||
return s == "dynamic-custom-insets" ||
|
||||
s == "dynamic-char-styles";
|
||||
}
|
||||
|
||||
|
||||
void DynamicMenuButton::updateTriggered()
|
||||
{
|
||||
QMenu * m = menu();
|
||||
// the menu should exist by this point
|
||||
// if not, we can at least avoid crashing in release mode
|
||||
LASSERT(m, return);
|
||||
GuiView const & owner = bar_->owner();
|
||||
BufferView const * bv = owner.currentBufferView();
|
||||
if (!bv) {
|
||||
m->clear();
|
||||
setEnabled(false);
|
||||
setMinimumWidth(sizeHint().width());
|
||||
d->text_class_.reset();
|
||||
d->inset_ = 0;
|
||||
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();
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
||||
void DynamicMenuButton::loadFlexInsets()
|
||||
{
|
||||
QMenu * m = menu();
|
||||
m->clear();
|
||||
string const & menutype = tbitem_.name_;
|
||||
InsetLayout::InsetLyXType ftype;
|
||||
if (menutype == "dynamic-custom-insets")
|
||||
ftype = InsetLayout::CUSTOM;
|
||||
else if (menutype == "dynamic-char-styles")
|
||||
ftype = InsetLayout::CHARSTYLE;
|
||||
else {
|
||||
// this should have been taken care of earlier
|
||||
LASSERT(false, return);
|
||||
}
|
||||
|
||||
TextClass::InsetLayouts const & inset_layouts =
|
||||
d->text_class_->insetLayouts();
|
||||
for (auto const & iit : inset_layouts) {
|
||||
InsetLayout const & il = iit.second;
|
||||
if (il.lyxtype() != ftype)
|
||||
continue;
|
||||
docstring const name = iit.first;
|
||||
QString const loc_item = toqstr(translateIfPossible(
|
||||
prefixIs(name, from_ascii("Flex:")) ?
|
||||
name.substr(5) : name));
|
||||
FuncRequest func(LFUN_FLEX_INSERT,
|
||||
from_ascii("\"") + name + from_ascii("\""), FuncRequest::TOOLBAR);
|
||||
Action * act =
|
||||
new Action(func, getIcon(func, false), loc_item, loc_item, this);
|
||||
m->addAction(act);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiToolbar::add(ToolbarItem const & item)
|
||||
{
|
||||
switch (item.type_) {
|
||||
@ -299,13 +433,20 @@ void GuiToolbar::add(ToolbarItem const & item)
|
||||
case ToolbarItem::ICONPALETTE:
|
||||
addWidget(new PaletteButton(this, item));
|
||||
break;
|
||||
|
||||
case ToolbarItem::POPUPMENU: {
|
||||
addWidget(new MenuButton(this, item, false));
|
||||
addWidget(new StaticMenuButton(this, item, false));
|
||||
break;
|
||||
}
|
||||
case ToolbarItem::STICKYPOPUPMENU: {
|
||||
addWidget(new MenuButton(this, item, true));
|
||||
addWidget(new StaticMenuButton(this, item, true));
|
||||
break;
|
||||
}
|
||||
case ToolbarItem::DYNAMICMENU: {
|
||||
// we only handle certain things
|
||||
if (DynamicMenuButton::isMenuType(item.name_))
|
||||
addWidget(new DynamicMenuButton(this, item));
|
||||
else
|
||||
LYXERR0("Unknown dynamic menu type: " << item.name_);
|
||||
break;
|
||||
}
|
||||
case ToolbarItem::COMMAND: {
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
|
||||
#include "support/strfwd.h"
|
||||
|
||||
class QSettings;
|
||||
|
||||
namespace lyx {
|
||||
@ -38,30 +40,78 @@ class LayoutBox;
|
||||
class ToolbarInfo;
|
||||
class ToolbarItem;
|
||||
|
||||
class MenuButton : public QToolButton
|
||||
class MenuButtonBase : public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
MenuButton(GuiToolbar * bar, ToolbarItem const & item,
|
||||
bool const sticky = false);
|
||||
MenuButtonBase(GuiToolbar * bar, ToolbarItem const & item);
|
||||
|
||||
private:
|
||||
protected:
|
||||
///
|
||||
void initialize();
|
||||
virtual void initialize() = 0;
|
||||
///
|
||||
GuiToolbar * bar_;
|
||||
///
|
||||
ToolbarItem const & tbitem_;
|
||||
|
||||
private Q_SLOTS:
|
||||
protected Q_SLOTS:
|
||||
///
|
||||
void actionTriggered(QAction * action);
|
||||
///
|
||||
virtual void updateTriggered() = 0;
|
||||
};
|
||||
|
||||
|
||||
class StaticMenuButton : public MenuButtonBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
StaticMenuButton(GuiToolbar * bar, ToolbarItem const & item,
|
||||
bool const sticky = false);
|
||||
|
||||
protected:
|
||||
///
|
||||
void initialize();
|
||||
|
||||
protected Q_SLOTS:
|
||||
///
|
||||
void updateTriggered();
|
||||
};
|
||||
|
||||
|
||||
/// A menu which can be populated on the fly.
|
||||
/// The 'type' of menu must be given in the toolbar file
|
||||
/// (stdtoolbars.inc, usually) and must be one of:
|
||||
/// dynamic-custom-insets
|
||||
/// dynamic-char-styles
|
||||
/// 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().
|
||||
class DynamicMenuButton : public MenuButtonBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
///
|
||||
DynamicMenuButton(GuiToolbar * bar, ToolbarItem const & item);
|
||||
///
|
||||
~DynamicMenuButton();
|
||||
///
|
||||
static bool isMenuType(std::string const & s);
|
||||
protected:
|
||||
///
|
||||
void initialize();
|
||||
///
|
||||
void loadFlexInsets();
|
||||
/// pimpl so we don't have to include big files
|
||||
class Private;
|
||||
Private * d;
|
||||
protected Q_SLOTS:
|
||||
///
|
||||
void updateTriggered();
|
||||
};
|
||||
|
||||
|
||||
class GuiToolbar : public QToolBar
|
||||
{
|
||||
@ -107,6 +157,8 @@ public:
|
||||
|
||||
///
|
||||
Action * addItem(ToolbarItem const & item);
|
||||
///
|
||||
GuiView const & owner() { return owner_; }
|
||||
|
||||
Q_SIGNALS:
|
||||
///
|
||||
|
@ -74,10 +74,12 @@ ToolbarInfo & ToolbarInfo::read(Lexer & lex)
|
||||
TO_EXPORTFORMATS,
|
||||
TO_IMPORTFORMATS,
|
||||
TO_UPDATEFORMATS,
|
||||
TO_VIEWFORMATS
|
||||
TO_VIEWFORMATS,
|
||||
TO_DYNAMICMENU
|
||||
};
|
||||
|
||||
struct LexerKeyword toolTags[] = {
|
||||
{ "dynamicmenu", TO_DYNAMICMENU},
|
||||
{ "end", TO_ENDTOOLBAR },
|
||||
{ "exportformats", TO_EXPORTFORMATS },
|
||||
{ "iconpalette", TO_ICONPALETTE },
|
||||
@ -155,6 +157,16 @@ ToolbarInfo & ToolbarInfo::read(Lexer & lex)
|
||||
}
|
||||
break;
|
||||
|
||||
case TO_DYNAMICMENU: {
|
||||
if (lex.next(true)) {
|
||||
string const name = lex.getString();
|
||||
lex.next(true);
|
||||
docstring const label = lex.getDocString();
|
||||
add(ToolbarItem(ToolbarItem::DYNAMICMENU, name, label));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TO_STICKYPOPUPMENU:
|
||||
if (lex.next(true)) {
|
||||
string const pname = lex.getString();
|
||||
|
@ -44,7 +44,9 @@ public:
|
||||
/// a button that expands a menu but remembers the last choice
|
||||
STICKYPOPUPMENU,
|
||||
///
|
||||
ICONPALETTE
|
||||
ICONPALETTE,
|
||||
///
|
||||
DYNAMICMENU
|
||||
};
|
||||
|
||||
ToolbarItem(Type type,
|
||||
|
Loading…
Reference in New Issue
Block a user