#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 "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 "FuncRequest.h"
-#include "FuncStatus.h"
-#include "KeyMap.h"
-#include "LyX.h"
-#include "LyXRC.h"
+#include "insets/InsetText.h"
#include "support/debug.h"
#include "support/gettext.h"
GuiToolbar::GuiToolbar(ToolbarInfo const & tbinfo, GuiView & owner)
: QToolBar(toqstr(tbinfo.gui_name), &owner), visibility_(0),
- owner_(owner), command_buffer_(0), tbinfo_(tbinfo), filled_(false)
+ owner_(owner), command_buffer_(0), tbinfo_(tbinfo), filled_(false),
+ restored_(false)
{
setIconSize(owner.iconSize());
connect(&owner, SIGNAL(iconSizeChanged(QSize)), this,
SLOT(setIconSize(QSize)));
- // Toolbar dragging is allowed.
- setMovable(true);
// This is used by QMainWindow::restoreState for proper main window state
// restauration.
setObjectName(toqstr(tbinfo.name));
}
+void GuiToolbar::setVisible(bool visible)
+{
+ // This is a hack to find out which toolbars have been restored by
+ // MainWindow::restoreState and which toolbars should be initialized
+ // by us (i.e., new toolbars)
+ restored_ = true;
+ QToolBar::setVisible(visible);
+}
+
+
+bool GuiToolbar::isRestored() const
+{
+ return restored_;
+}
+
+
void GuiToolbar::fill()
{
if (filled_)
ToolbarInfo::item_iterator it = tbinfo_.items.begin();
ToolbarInfo::item_iterator end = tbinfo_.items.end();
for (; it != end; ++it)
- add(*it);
+ add(*it);
filled_ = true;
}
QString text = toqstr(item.label_);
// Get the keys bound to this action, but keep only the
// first one later
- KeyMap::Bindings bindings = theTopLevelKeymap().findBindings(item.func_);
- if (bindings.size())
+ KeyMap::Bindings bindings = theTopLevelKeymap().findBindings(*item.func_);
+ if (!bindings.empty())
text += " [" + toqstr(bindings.begin()->print(KeySequence::ForGui)) + "]";
- Action * act = new Action(&owner_, getIcon(item.func_, false),
- text, item.func_, text, this);
+ Action * act = new Action(item.func_, getIcon(*item.func_, false), text,
+ text, this);
actions_.append(act);
return act;
}
ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
if (tbinfo)
// use the icon of first action for the toolbar button
- setIcon(getIcon(tbinfo->items.begin()->func_, true));
+ setIcon(getIcon(*tbinfo->items.begin()->func_, true));
}
void mousePressEvent(QMouseEvent * e)
ToolbarInfo::item_iterator it = tbinfo->items.begin();
ToolbarInfo::item_iterator const end = tbinfo->items.end();
for (; it != end; ++it)
- if (!getStatus(it->func_).unknown())
+ if (!getStatus(*it->func_).unknown())
panel->addButton(bar_->addItem(*it));
QToolButton::mousePressEvent(e);
}
};
-}
+} // namespace
-MenuButton::MenuButton(GuiToolbar * bar, ToolbarItem const & item, bool const sticky)
- : QToolButton(bar), bar_(bar), tbitem_(item), initialized_(false)
+MenuButtonBase::MenuButtonBase(GuiToolbar * bar, ToolbarItem const & item)
+ : QToolButton(bar), bar_(bar), tbitem_(item)
{
setPopupMode(QToolButton::InstantPopup);
QString const label = qt_(to_ascii(tbitem_.label_));
setStatusTip(label);
setText(label);
QString const name = toqstr(tbitem_.name_);
- QString imagedir = "images/math/";
- FileName const fname = imageLibFileSearch(imagedir, name, "png");
- if (fname.exists()) {
- setIcon(QIcon(getPixmap(imagedir, name, "png")));
- } else {
- imagedir = "images/";
- imageLibFileSearch(imagedir, name, "png");
- setIcon(QIcon(getPixmap(imagedir, name, "png")));
+ QStringList imagedirs;
+ imagedirs << "images/math/" << "images/";
+ for (int i = 0; i < imagedirs.size(); ++i) {
+ QString imagedir = imagedirs.at(i);
+ FileName const fname = imageLibFileSearch(imagedir, name, "svgz,png",
+ theGuiApp()->imageSearchMode());
+ if (fname.exists()) {
+ setIcon(QIcon(getPixmap(imagedir, name, "svgz,png")));
+ 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 *)));
connect(bar, SIGNAL(iconSizeChanged(QSize)),
this, SLOT(setIconSize(QSize)));
+ initialize();
}
-void MenuButton::mousePressEvent(QMouseEvent * e)
-{
- if (initialized_) {
- QToolButton::mousePressEvent(e);
- return;
- }
-
- initialized_ = true;
+void StaticMenuButton::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()));
ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
if (!tbinfo) {
LYXERR0("Unknown toolbar " << tbitem_.name_);
ToolbarInfo::item_iterator it = tbinfo->items.begin();
ToolbarInfo::item_iterator const end = tbinfo->items.end();
for (; it != end; ++it)
- if (!getStatus(it->func_).unknown())
+ if (!getStatus(*it->func_).unknown())
m->add(bar_->addItem(*it));
setMenu(m);
+}
- QToolButton::mousePressEvent(e);
+
+void StaticMenuButton::updateTriggered()
+{
+ if (!menu())
+ return;
+
+ bool enabled = false;
+ QList<QAction *> acts = menu()->actions();
+ for (int i = 0; i < acts.size(); ++i)
+ if (acts[i]->isEnabled()) {
+ enabled = true;
+ break;
+ }
+ // Enable the MenuButton if at least one menu item is enabled
+ setEnabled(enabled);
+ // If a disabled item is default, switch to InstantPopup
+ // (this can happen if a user selects e.g. DVI and then
+ // turns non-TeX fonts on)
+ if (defaultAction() && !defaultAction()->isEnabled())
+ setPopupMode(QToolButton::InstantPopup);
}
-void MenuButton::actionTriggered(QAction * action)
+class DynamicMenuButton::Private
{
- QToolButton::setDefaultAction(action);
- setPopupMode(QToolButton::DelayedPopup);
+ /// 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);
+ }
}
tb->setToolTip(label);
tb->setStatusTip(label);
tb->setText(label);
- InsertTableWidget * iv = new InsertTableWidget(owner_, tb);
+ InsertTableWidget * iv = new InsertTableWidget(tb);
connect(tb, SIGNAL(clicked(bool)), iv, SLOT(show(bool)));
connect(iv, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
connect(this, SIGNAL(updated()), iv, SLOT(updateParent()));
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: {
- if (!getStatus(item.func_).unknown())
+ if (!getStatus(*item.func_).unknown())
addAction(addItem(item));
break;
}
}
-void GuiToolbar::update(bool in_math, bool in_table, bool in_review,
- bool in_mathmacrotemplate)
+void GuiToolbar::update(int context)
{
if (visibility_ & Toolbars::AUTO) {
- bool show_it = (in_math && (visibility_ & Toolbars::MATH))
- || (in_table && (visibility_ & Toolbars::TABLE))
- || (in_review && (visibility_ & Toolbars::REVIEW))
- || (in_mathmacrotemplate && (visibility_ & Toolbars::MATHMACROTEMPLATE));
- setVisible(show_it);
+ setVisible(visibility_ & context & Toolbars::ALLOWAUTO);
+ if (isVisible() && commandBuffer() && (context & Toolbars::MINIBUFFER_FOCUS))
+ commandBuffer()->setFocus();
}
// update visible toolbars only
}
-void GuiToolbar::saveSession() const
+void GuiToolbar::saveSession(QSettings & settings) const
{
- QSettings settings;
settings.setValue(sessionKey() + "/visibility", visibility_);
+ settings.setValue(sessionKey() + "/movability", isMovable());
}
settings.value(sessionKey() + "/visibility", error_val).toInt();
if (visibility == error_val || visibility == 0) {
// This should not happen, but in case we use the defaults
- LYXERR0("Session settings could not be found! Defaults are used instead.");
- visibility =
+ LYXERR(Debug::GUI, "Session settings could not be found! Defaults are used instead.");
+ visibility =
guiApp->toolbars().defaultVisibility(fromqstr(objectName()));
}
setVisibility(visibility);
+
+ int movability = settings.value(sessionKey() + "/movability", true).toBool();
+ setMovable(movability);
}
qstring_to_ucs4(windowTitle()), state));
}
+void GuiToolbar::movable(bool silent)
+{
+ // toggle movability
+ setMovable(!isMovable());
+
+ // manual update avoids bug in qt that the drag handle is not removed
+ // properly, e.g. in Windows
+ Q_EMIT update();
+
+ // silence for toggling of many toolbars for performance
+ if (!silent) {
+ docstring state;
+ if (isMovable())
+ state = _("movable");
+ else
+ state = _("immovable");
+ owner_.message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
+ qstring_to_ucs4(windowTitle()), state));
+ }
+}
+
} // namespace frontend
} // namespace lyx