Attached please find a patch that implements a combo box for custom
insets, much like the layout box. This is a very simple version. More
complicated ones might also have an InsetLayout tag that governed
whether an inset would appear here. It would also be very easy to adapt
this also to give us a combo for charstyles.

Comments welcome.

Richard

>From 1151bc1c0392a010cafa040f7216553e6d54ed1a Mon Sep 17 00:00:00 2001
From: Richard Heck <rgh...@lyx.org>
Date: Fri, 24 Jun 2016 17:47:30 -0400
Subject: [PATCH] Initial work for inset toolbar combo.

---
 lib/ui/stdtoolbars.inc           |   2 +
 src/frontends/qt4/GuiToolbar.cpp |   9 ++
 src/frontends/qt4/GuiView.cpp    |  24 ++++-
 src/frontends/qt4/GuiView.h      |   3 +
 src/frontends/qt4/InsetCombo.cpp | 194 +++++++++++++++++++++++++++++++++++++++
 src/frontends/qt4/InsetCombo.h   |  56 +++++++++++
 src/frontends/qt4/Makefile.am    |   2 +
 src/frontends/qt4/Toolbars.cpp   |   9 +-
 src/frontends/qt4/Toolbars.h     |   4 +-
 9 files changed, 299 insertions(+), 4 deletions(-)
 create mode 100644 src/frontends/qt4/InsetCombo.cpp
 create mode 100644 src/frontends/qt4/InsetCombo.h

diff --git a/lib/ui/stdtoolbars.inc b/lib/ui/stdtoolbars.inc
index d375afa..c504e4a 100644
--- a/lib/ui/stdtoolbars.inc
+++ b/lib/ui/stdtoolbars.inc
@@ -95,6 +95,8 @@ ToolbarSet
 		Item "Toggle outline" "dialog-toggle toc"
 		Item "Toggle math toolbar" "toolbar-toggle math"
 		Item "Toggle table toolbar" "toolbar-toggle table"
+		Separator
+		Insets
 	End
 
 	Toolbar "view/update" "View/Update"
diff --git a/src/frontends/qt4/GuiToolbar.cpp b/src/frontends/qt4/GuiToolbar.cpp
index 77471c9..8958813 100644
--- a/src/frontends/qt4/GuiToolbar.cpp
+++ b/src/frontends/qt4/GuiToolbar.cpp
@@ -23,6 +23,7 @@
 #include "GuiView.h"
 #include "IconPalette.h"
 #include "InsertTableWidget.h"
+#include "InsetCombo.h"
 #include "LayoutBox.h"
 #include "qt_helpers.h"
 #include "Toolbars.h"
@@ -277,6 +278,14 @@ void GuiToolbar::add(ToolbarItem const & item)
 		action->setVisible(true);
 		break;
 	}
+	case ToolbarItem::INSETS: {
+		InsetCombo * insets = owner_.getInsetCombo();
+		QObject::connect(this, SIGNAL(iconSizeChanged(QSize)),
+			insets, SLOT(setIconSize(QSize)));
+		QAction * action = addWidget(insets);
+		action->setVisible(true);
+		break;
+	}
 	case ToolbarItem::MINIBUFFER:
 		command_buffer_ = new GuiCommandBuffer(&owner_);
 		addWidget(command_buffer_);
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 87ee553..34da998 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -27,6 +27,7 @@
 #include "GuiToolbar.h"
 #include "GuiWorkArea.h"
 #include "GuiProgress.h"
+#include "InsetCombo.h"
 #include "LayoutBox.h"
 #include "Menus.h"
 #include "TocModel.h"
@@ -277,7 +278,7 @@ class GuiView::GuiViewPrivate
 public:
 	GuiViewPrivate(GuiView * gv)
 		: gv_(gv), current_work_area_(0), current_main_work_area_(0),
-		layout_(0), autosave_timeout_(5000),
+		layout_(0), insets_(0), autosave_timeout_(5000),
 		in_show_(false)
 	{
 		// hardcode here the platform specific icon size
@@ -328,6 +329,7 @@ public:
 		delete splitter_;
 		delete bg_widget_;
 		delete stack_widget_;
+		delete insets_;
 	}
 
 	QMenu * toolBarPopup(GuiView * parent)
@@ -462,6 +464,7 @@ public:
 	 * to only one dialog.
 	 */
 	LayoutBox * layout_;
+	InsetCombo * insets_;
 
 	///
 	map<string, DialogPtr> dialogs_;
@@ -808,6 +811,7 @@ void GuiView::constructToolbars()
 	d.layout_ = new LayoutBox(*this);
 	d.stack_widget_->addWidget(d.layout_);
 	d.layout_->move(0,0);
+	d.insets_ = new InsetCombo(*this);
 
 	// extracts the toolbars from the backend
 	Toolbars::Infos::iterator cit = guiApp->toolbars().begin();
@@ -1344,7 +1348,8 @@ void GuiView::setBusy(bool busy)
 		return;
 	}
 	QApplication::restoreOverrideCursor();
-	updateLayoutList();	
+	updateLayoutList();
+	updateInsetCombo();
 }
 
 
@@ -1535,6 +1540,12 @@ LayoutBox * GuiView::getLayoutDialog() const
 }
 
 
+InsetCombo * GuiView::getInsetCombo() const
+{
+	return d.insets_;
+}
+
+
 void GuiView::updateLayoutList()
 {
 	if (d.layout_)
@@ -1542,6 +1553,13 @@ void GuiView::updateLayoutList()
 }
 
 
+void GuiView::updateInsetCombo()
+{
+	if (d.insets_)
+		d.insets_->updateContents(false);
+}
+
+
 void GuiView::updateToolbars()
 {
 	ToolbarMap::iterator end = d.toolbars_.end();
@@ -4213,6 +4231,7 @@ void GuiView::resetDialogs()
 	constructToolbars();
 	guiApp->menus().fillMenuBar(menuBar(), this, false);
 	d.layout_->updateContents(true);
+	d.insets_->updateContents(true);
 	// Now update controls with current buffer.
 	guiApp->setCurrentView(this);
 	restoreLayout();
@@ -4350,6 +4369,7 @@ void GuiView::updateDialogs()
 	}
 	updateToolbars();
 	updateLayoutList();
+	updateInsetCombo();
 }
 
 Dialog * createDialog(GuiView & lv, string const & name);
diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h
index c3ccdbd..e11db90 100644
--- a/src/frontends/qt4/GuiView.h
+++ b/src/frontends/qt4/GuiView.h
@@ -46,6 +46,7 @@ class Dialog;
 class LayoutBox;
 class GuiToolbar;
 class GuiWorkArea;
+class InsetCombo;
 class TabWorkArea;
 class TocModels;
 class ToolbarInfo;
@@ -144,11 +145,13 @@ public:
 
 	/// updates the possible layouts selectable
 	void updateLayoutList();
+	void updateInsetCombo();
 	void updateToolbars();
 	QMenu * createPopupMenu();
 
 	///
 	LayoutBox * getLayoutDialog() const;
+	InsetCombo * getInsetCombo() const;
 
 	/// hides the workarea and makes sure it is clean
 	bool hideWorkArea(GuiWorkArea * wa);
diff --git a/src/frontends/qt4/InsetCombo.cpp b/src/frontends/qt4/InsetCombo.cpp
new file mode 100644
index 0000000..042d26a
--- /dev/null
+++ b/src/frontends/qt4/InsetCombo.cpp
@@ -0,0 +1,194 @@
+/**
+ * \file qt4/InsetCombo.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ * \author John Levon
+ * \author Jean-Marc Lasgouttes
+ * \author Angus Leeming
+ * \author Stefan Schimanski
+ * \author Abdelrazak Younes
+ * \author Richard Heck
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "InsetCombo.h"
+
+#include "GuiView.h"
+#include "qt_helpers.h"
+
+#include "Buffer.h"
+#include "BufferParams.h"
+#include "BufferView.h"
+#include "Cursor.h"
+#include "DocumentClassPtr.h"
+#include "FuncRequest.h"
+#include "FuncStatus.h"
+#include "LyX.h"
+#include "TextClass.h"
+
+#include "insets/InsetLayout.h"
+#include "insets/InsetText.h"
+
+#include "support/debug.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
+
+#include <QStandardItemModel>
+
+using namespace std;
+using namespace lyx::support;
+
+namespace lyx {
+namespace frontend {
+
+	
+/////////////////////////////////////////////////////////////////////
+//
+// InsetCombo::Private
+//
+/////////////////////////////////////////////////////////////////////
+
+class InsetCombo::Private
+{
+	/// noncopyable
+	Private(Private const &);
+	void operator=(Private const &);
+public:
+	Private(InsetCombo * parent, GuiView & gv) : p(parent), owner_(gv),
+		inset_(0),
+		// set the layout model with two columns
+		// 1st: translated layout names
+		// 2nd: raw layout names
+		model_(new QStandardItemModel(0, 2, p)),
+		lastSel_(-1)
+	{}
+
+	InsetCombo * p;
+	///
+	GuiView & owner_;
+	///
+	DocumentClassConstPtr text_class_;
+	///
+	Inset const * inset_;
+	/// the layout model: 1st column translated, 2nd column raw layout name
+	QStandardItemModel * model_;
+	/// the (model-) index of the last successful selection
+	int lastSel_;
+};
+
+
+InsetCombo::InsetCombo(GuiView & owner)
+	: d(new Private(this, owner))
+{
+	setSizeAdjustPolicy(QComboBox::AdjustToContents);
+	setFocusPolicy(Qt::ClickFocus);
+	setMinimumWidth(sizeHint().width());
+	setMaxVisibleItems(100);
+
+	setModel(d->model_);
+
+	QObject::connect(this, SIGNAL(activated(int)),
+		this, SLOT(selected(int)));
+
+	updateContents(true);
+}
+
+
+InsetCombo::~InsetCombo() {
+	delete d;
+}
+
+
+void InsetCombo::setIconSize(QSize size)
+{
+#ifdef Q_OS_MAC
+	bool small = size.height() < 20;
+	setAttribute(Qt::WA_MacSmallSize, small);
+	setAttribute(Qt::WA_MacNormalSize, !small);
+#else
+	(void)size; // suppress warning
+#endif
+}
+
+
+void InsetCombo::updateContents(bool reset)
+{
+	BufferView const * bv = d->owner_.currentBufferView();
+	if (!bv) {
+		d->model_->clear();
+		setEnabled(false);
+		setMinimumWidth(sizeHint().width());
+		d->text_class_.reset();
+		d->inset_ = 0;
+		return;
+	}
+	// we'll only update the inset list if the text class has changed
+	// or we've moved from one inset to another
+	DocumentClassConstPtr text_class = bv->buffer().params().documentClassPtr();
+	Inset const * inset = &(bv->cursor().innerText()->inset());
+	if (!reset && d->text_class_ == text_class && d->inset_ == inset)
+		return;
+
+	d->inset_ = inset;
+	d->text_class_ = text_class;
+	d->model_->clear();
+	
+	TextClass::InsetLayouts const & insetLayouts = d->text_class_->insetLayouts();
+	TextClass::InsetLayouts::const_iterator iit = insetLayouts.begin();
+	TextClass::InsetLayouts::const_iterator ien = insetLayouts.end();
+	
+	for (; iit != ien; ++iit) {
+		InsetLayout const & il = iit->second;
+		if (il.lyxtype() != InsetLayout::CUSTOM)
+			continue;
+		docstring name = iit->first;
+		QString qitem = toqstr(name);
+		QString const loc_item = 
+			toqstr(translateIfPossible(
+				prefixIs(name, from_ascii("Flex:")) ? 
+				name.substr(5) : name));
+	
+		QList<QStandardItem *> row;
+		row.append(new QStandardItem(loc_item));
+		row.append(new QStandardItem(qitem));
+	
+		d->model_->appendRow(row);
+	}
+
+	setMinimumWidth(sizeHint().width());
+	setEnabled(!bv->buffer().isReadonly() && d->inset_->insetAllowed(FLEX_CODE));
+}
+
+
+void InsetCombo::selected(int index)
+{
+	// get selection
+	docstring insetName = qstring_to_ucs4(
+		d->model_->item(index, 1)->text());
+	d->owner_.setFocus();
+
+	if (!d->text_class_) {
+		updateContents(false);
+		return;
+	}
+
+	// find corresponding text class
+	if (d->text_class_->hasInsetLayout(insetName)) {
+		FuncRequest const func(LFUN_FLEX_INSERT, insetName, FuncRequest::TOOLBAR);
+		lyx::dispatch(func);
+		updateContents(false);
+		return;
+	}
+	LYXERR0("ERROR (inset toolbar): inset " << insetName << " not found!");
+}
+
+
+} // namespace frontend
+} // namespace lyx
+
+#include "moc_InsetCombo.cpp"
diff --git a/src/frontends/qt4/InsetCombo.h b/src/frontends/qt4/InsetCombo.h
new file mode 100644
index 0000000..11da027
--- /dev/null
+++ b/src/frontends/qt4/InsetCombo.h
@@ -0,0 +1,56 @@
+// -*- C++ -*-
+/**
+ * \file LayoutBox.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ * \author John Levon
+ * \author Jean-Marc Lasgouttes
+ * \author Angus Leeming
+ * \author Abdelrazak Younes
+ * \author Richard Heck
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef LYX_INSET_BOX_H
+#define LYX_INSET_BOX_H
+
+#include "support/strfwd.h"
+
+#include <QComboBox>
+
+namespace lyx {
+
+class DocumentClass;
+
+namespace frontend {
+
+class GuiView;
+
+class InsetCombo : public QComboBox
+{
+	Q_OBJECT
+public:
+	InsetCombo(GuiView &);
+	~InsetCombo();
+
+	/// Populate the combobox.
+	void updateContents(bool reset);
+
+private Q_SLOTS:
+	///
+	void selected(int index);
+	///
+	void setIconSize(QSize size);
+
+private:
+	class Private;
+	Private * const d;
+};
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // LYX_LAYOUT_BOX_H
diff --git a/src/frontends/qt4/Makefile.am b/src/frontends/qt4/Makefile.am
index 103105e..c418e10 100644
--- a/src/frontends/qt4/Makefile.am
+++ b/src/frontends/qt4/Makefile.am
@@ -142,6 +142,7 @@ SOURCEFILES = \
 	InsertTableWidget.cpp \
 	InsetParamsDialog.cpp \
 	InsetParamsWidget.cpp \
+	InsetCombo.cpp \
 	LengthCombo.cpp \
 	LyXFileDialog.cpp \
 	LyXToolBox.cpp \
@@ -249,6 +250,7 @@ MOCHEADER = \
 	IconPalette.h \
 	InGuiThread.h \
 	InsertTableWidget.h \
+	InsetCombo.h \
 	InsetParamsDialog.h \
 	InsetParamsWidget.h \
 	LayoutBox.h \
diff --git a/src/frontends/qt4/Toolbars.cpp b/src/frontends/qt4/Toolbars.cpp
index 20eee93..a1d5ce9 100644
--- a/src/frontends/qt4/Toolbars.cpp
+++ b/src/frontends/qt4/Toolbars.cpp
@@ -74,7 +74,8 @@ ToolbarInfo & ToolbarInfo::read(Lexer & lex)
 		TO_EXPORTFORMATS,
 		TO_IMPORTFORMATS,
 		TO_UPDATEFORMATS,
-		TO_VIEWFORMATS
+		TO_VIEWFORMATS,
+		TO_INSETS
 	};
 
 	struct LexerKeyword toolTags[] = {
@@ -82,6 +83,7 @@ ToolbarInfo & ToolbarInfo::read(Lexer & lex)
 		{ "exportformats", TO_EXPORTFORMATS },
 		{ "iconpalette", TO_ICONPALETTE },
 		{ "importformats", TO_IMPORTFORMATS },
+		{ "insets", TO_INSETS },
 		{ "item", TO_COMMAND },
 		{ "layouts", TO_LAYOUTS },
 		{ "minibuffer", TO_MINIBUFFER },
@@ -178,6 +180,11 @@ ToolbarInfo & ToolbarInfo::read(Lexer & lex)
 				FuncRequest(FuncCode(ToolbarItem::LAYOUTS))));
 			break;
 
+		case TO_INSETS:
+			add(ToolbarItem(ToolbarItem::INSETS,
+				FuncRequest(FuncCode(ToolbarItem::INSETS))));
+			break;
+
 		case TO_TABLEINSERT:
 			if (lex.next(true)) {
 				docstring const tooltip = lex.getDocString();
diff --git a/src/frontends/qt4/Toolbars.h b/src/frontends/qt4/Toolbars.h
index 02d0ebe..01d4679 100644
--- a/src/frontends/qt4/Toolbars.h
+++ b/src/frontends/qt4/Toolbars.h
@@ -43,7 +43,9 @@ public:
 		/// a button that expands a menu but remembers the last choice
 		STICKYPOPUPMENU,
 		///
-		ICONPALETTE
+		ICONPALETTE,
+		///
+		INSETS
 	};
 
 	ToolbarItem(Type type,
-- 
2.1.0

Reply via email to