Bennett Helm wrote:
> What I meant is that when the panel pops up, there's no clear indication 
> from its appearance that tearing it off can work, and so people won't 
> likely try clicking there and discover the tear-off feature. Is there 
> some other way to make this function more apparent?

i've added a tooltip but for the moment tooltips don't show in the panels

i don't know why: when we tear off the panel (ie set windowflags to Qt:Tool) 
they *do* show

so i am afraid that for the moment this is just the way it is (unless someone 
else comes up with the solution)...

> But then it should not be resizable.


the attached patch does that

...

in summary:

- allow panels to tear off using only qt 4.1 functionality

- reported to work on windows, linux and mac

seeking 2 ok's

Index: src/frontends/qt4/IconPalette.cpp
===================================================================
--- src/frontends/qt4/IconPalette.cpp	(revision 18822)
+++ src/frontends/qt4/IconPalette.cpp	(working copy)
@@ -25,99 +25,80 @@
 #include <QStyle>
 #include <QStyleOptionFrame>
 #include <QMouseEvent>
+#include <QVBoxLayout>
 
 namespace lyx {
 namespace frontend {
 
-#if QT_VERSION >= 0x040200
-
-
-class MathButton : public QToolButton
+TearOff::TearOff(QWidget * parent) 
+	: QWidget(parent)
 {
-public:
-	MathButton(QWidget * parent = 0) {}
-	void mouseReleaseEvent(QMouseEvent *event); 
-	void mousePressEvent(QMouseEvent *event); 
-};
+	highlighted_ = false;
+	setMinimumHeight(8);
+	setToolTip(qt_("Click to tear off"));
+	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+}
 
 
-void MathButton::mouseReleaseEvent(QMouseEvent *event)
+void TearOff::mouseReleaseEvent(QMouseEvent * event)
 {
-	QToolButton::mouseReleaseEvent(event);
-	event->ignore();
+	// signal
+	tearOff();
 }
 
 
-void MathButton::mousePressEvent(QMouseEvent *event)
+void TearOff::enterEvent(QEvent * event)
 {
-	QToolButton::mousePressEvent(event);
+	highlighted_ = true;
+	update();
 	event->ignore();
 }
 
 
-IconPalette::IconPalette(QWidget * parent)
-	: QWidgetAction(parent), size_(QSize(22, 22))
+void TearOff::leaveEvent(QEvent * event)
 {
+	highlighted_ = false;
+	update();
+	event->ignore();
 }
 
 
-void IconPalette::addButton(QAction * action)
+void TearOff::paintEvent(QPaintEvent * event)
 {
-	actions_.push_back(action);
+	QPainter p(this);
+	const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
+	QStyleOptionMenuItem menuOpt;
+	menuOpt.initFrom(this);
+	menuOpt.palette = palette();
+	menuOpt.state = QStyle::State_None;
+	menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
+	menuOpt.menuRect = rect();
+	menuOpt.maxIconWidth = 0;
+	menuOpt.tabWidth = 0;
+	menuOpt.menuItemType = QStyleOptionMenuItem::TearOff;
+	menuOpt.rect.setRect(fw, fw, width() - (fw * 2),
+		style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this));
+	p.setClipRect(menuOpt.rect);
+	menuOpt.state = QStyle::State_None;
+	if (highlighted_)
+		menuOpt.state |= QStyle::State_Selected;
+	style()->drawControl(QStyle::CE_MenuTearoff, &menuOpt, &p, this);
 }
 
 
-QWidget * IconPalette::createWidget(QWidget * parent)
-{
-	QWidget * widget = new QWidget(parent);
-	QGridLayout * layout = new QGridLayout(widget);
-	layout->setSpacing(0);
-
-	for (int i = 0; i < actions_.size(); ++i) {
-		MathButton * tb = new MathButton(widget);
-		tb->setAutoRaise(true);
-		tb->setDefaultAction(actions_.at(i));
-		tb->setIconSize(size_);
-		connect(this, SIGNAL(iconSizeChanged(const QSize &)),
-			tb, SLOT(setIconSize(const QSize &)));
-	
-		int const row = i/qMin(6, i + 1) + 1;
-		int const col = qMax(1, i + 1 - (row - 1) * 6);
-		layout->addWidget(tb, row, col);
-	}
-
-	return widget;
-}
-
-
-void IconPalette::setIconSize(const QSize & size)
-{
-	size_ = size;
-	// signal
-	iconSizeChanged(size);
-}
-
-
-void IconPalette::updateParent()
-{
-	bool enable = false;
-	for (int i = 0; i < actions_.size(); ++i)
-		if (actions_.at(i)->isEnabled()) {
-			enable = true;
-			break;
-		}
-	// signal
-	enabled(enable);
-}
-
-#else  // QT_VERSION >= 0x040200
-
 IconPalette::IconPalette(QWidget * parent)
-	: QWidget(parent, Qt::Popup)
+	: QWidget(parent, Qt::Popup), tornoff_(false)
 {
-	layout_ = new QGridLayout(this);
+	QVBoxLayout * v = new QVBoxLayout(this);
+	v->setMargin(0);
+	v->setSpacing(0);
+	layout_ = new QGridLayout;
 	layout_->setSpacing(0);
-	layout_->setMargin(3);
+	layout_->setMargin(2);
+	tearoffwidget_ = new TearOff(this);
+	connect(tearoffwidget_, SIGNAL(tearOff()), this, SLOT(tearOff()));
+	v->addWidget(tearoffwidget_);
+	v->addLayout(layout_);
 }
 
 
@@ -141,15 +122,30 @@
 }
 
 
+void IconPalette::tearOff()
+{
+	blockSignals(true);
+	setWindowFlags(Qt::Tool);
+	tornoff_ = true;
+	tearoffwidget_->setVisible(!tornoff_);
+	show();
+	blockSignals(false);
+}
+
+
 void IconPalette::clicked(QAction * action)
 {
 	triggered(action);
-	setVisible(false);
+	if (!tornoff_)
+		setVisible(false);
 }
 
 
 void IconPalette::showEvent(QShowEvent * event)
 {
+	resize(sizeHint());
+	setMaximumSize(sizeHint());
+
 	int hoffset = - parentWidget()->pos().x();
 	int voffset = - parentWidget()->pos().y();
 	int const parwidth = parentWidget()->geometry().width();
@@ -183,14 +179,20 @@
 			voffset += parheight;
 	}
 
-	move(gpos.x() + hoffset, gpos.y() + voffset);
-	QWidget::showEvent(event);
+	QRect r = rect();
+	r.moveTo(gpos.x() + hoffset, gpos.y() + voffset);
+	setGeometry(r);	
 }
 
 
 void IconPalette::hideEvent(QHideEvent * event )
 {
 	visible(false);
+	if (tornoff_) {
+		setWindowFlags(Qt::Window | Qt::Popup);
+		tornoff_ = false;
+		tearoffwidget_->setVisible(!tornoff_);
+	}
 	QWidget::hideEvent(event);
 }
 
@@ -211,17 +213,15 @@
 void IconPalette::paintEvent(QPaintEvent * event)
 {
 	// draw border
-	QPainter p(this);
-	QRegion emptyArea = QRegion(rect());
 	const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
-	if (fw) {
+	if (fw && !tornoff_) {
+		QPainter p(this);
 		QRegion borderReg;
 		borderReg += QRect(0, 0, fw, height()); //left
-		borderReg += QRect(width()-fw, 0, fw, height()); //right
+		borderReg += QRect(width() - fw, 0, fw, height()); //right
 		borderReg += QRect(0, 0, width(), fw); //top
-		borderReg += QRect(0, height()-fw, width(), fw); //bottom
+		borderReg += QRect(0, height() - fw, width(), fw); //bottom
 		p.setClipRegion(borderReg);
-		emptyArea -= borderReg;
 		QStyleOptionFrame frame;
 		frame.rect = rect();
 		frame.palette = palette();
@@ -230,11 +230,7 @@
 		frame.midLineWidth = 0;
 		style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, &p, this);
 	}
-	p.end();
-	// draw the rest (buttons)
-	QWidget::paintEvent(event);
 }
-#endif // QT_VERSION >= 0x040200
 
 
 ButtonMenu::ButtonMenu(const QString & title, QWidget * parent)
Index: src/frontends/qt4/IconPalette.h
===================================================================
--- src/frontends/qt4/IconPalette.h	(revision 18822)
+++ src/frontends/qt4/IconPalette.h	(working copy)
@@ -17,40 +17,32 @@
 #include <QLayout>
 #include "Action.h"
 
-// FIXME: this can go when we move to Qt 4.3
-#define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
 
-#if QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)
-#include <QWidgetAction>
-#endif
-
 namespace lyx {
 namespace frontend {
 
 /**
- * For holding an arbitrary set of icons.
- */
-#if QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)
-
-class IconPalette : public QWidgetAction {
+  * tear-off widget
+  */
+class TearOff : public QWidget {
 	Q_OBJECT
 public:
-	IconPalette(QWidget * parent);
-	void addButton(QAction *);
-	QWidget * createWidget(QWidget * parent);
-public Q_SLOTS:
-	void updateParent();
-	void setIconSize(const QSize &);
+	TearOff(QWidget * parent);
+	void enterEvent(QEvent *);
+	void leaveEvent(QEvent *);
+	void mouseReleaseEvent (QMouseEvent *);
 Q_SIGNALS:
-	void enabled(bool);
-	void iconSizeChanged(const QSize &);
+	void tearOff();
+protected:
+	void paintEvent(QPaintEvent *);
 private:
-	QList<QAction *> actions_;
-	QSize size_;
+	bool highlighted_;
 };
 
-#else
 
+/**
+ * For holding an arbitrary set of icons.
+ */
 class IconPalette : public QWidget {
 	Q_OBJECT
 public:
@@ -70,14 +62,16 @@
 	void paintEvent(QPaintEvent * event);
 
 private Q_SLOTS:
+	void tearOff();
 	virtual void clicked(QAction *);
 
 private:
 	QGridLayout * layout_;
 	QList<QAction *> actions_;
+	bool tornoff_;
+	TearOff * tearoffwidget_; 
 };
 
-#endif // QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)
 
 /**
  * Popup menu for a toolbutton.
Index: src/frontends/qt4/QLToolbar.cpp
===================================================================
--- src/frontends/qt4/QLToolbar.cpp	(revision 18822)
+++ src/frontends/qt4/QLToolbar.cpp	(working copy)
@@ -212,15 +212,8 @@
 		connect(this, SIGNAL(iconSizeChanged(const QSize &)),
 			tb, SLOT(setIconSize(const QSize &)));
 
-#if QT_VERSION >= 0x040200
-		IconPalette * panel = new IconPalette(&owner_);
-		connect(panel, SIGNAL(enabled(bool)),
-			tb, SLOT(setEnabled(bool)));
-		connect(this, SIGNAL(iconSizeChanged(const QSize &)),
-			panel, SLOT(setIconSize(const QSize &)));
-#else
 		IconPalette * panel = new IconPalette(tb);
-#endif
+
 		connect(this, SIGNAL(updated()), panel, SLOT(updateParent()));
 		ToolbarInfo const & tbinfo = toolbarbackend.getToolbar(item.name_);
 		ToolbarInfo::item_iterator it = tbinfo.items.begin();
@@ -239,18 +232,10 @@
 					tb->setIcon(QPixmap(getIcon(it->func_).c_str()));
 			}
 
-#if QT_VERSION >= 0x040200
-		QMenu * m = new QMenu(tb);
-		m->addAction(panel);
-		m->setTearOffEnabled(true);
-		m->setWindowTitle(qt_(to_ascii(item.label_)));
-		tb->setPopupMode(QToolButton::InstantPopup);
-		tb->setMenu(m);
-#else
+
 		tb->setCheckable(true);
 		connect(tb, SIGNAL(clicked(bool)), panel, SLOT(setVisible(bool)));
 		connect(panel, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
-#endif // QT_VERSION >= 0x040200
 
 		addWidget(tb);
 		break;

Reply via email to