Enrico Forestieri wrote:
Edwin, I really appreciate your effort for trying to provide this
feature with Qt 4.1. However, I think that we should not jump through
hoops if something is hard to obtain with older Qt versions.
It suffices to let the thing compile, even with reduced functionality.
I tried the patch with Qt 4.1 and it almost works (I am really impressed).
There's a quirk, though. After detaching a panel and trying to close it
again, LyX freezes. There's no cpu load, LyX simply doesn't respond
anymore and after a Ctrl-C an emergency file is created.
i admit i was using qt 4.2
i now compiled with 4.1 and it turns out we cannot change windowflags on
visible windows
hiding the widget before changing the windowflags solves the problem for me
could you try the attached?
Taking into account the time and effort you put in this, I am really
afraid to suggest leaving things as they are now and simply applying
that small patch curing the moc problem. What do you (and others) think?
the attached patch has the advantage that it also allows tearoff panels
on the mac
i would be very surprised if this one doesn't work for you
Index: src/frontends/qt4/IconPalette.cpp
===================================================================
--- src/frontends/qt4/IconPalette.cpp (revision 18822)
+++ src/frontends/qt4/IconPalette.cpp (working copy)
@@ -25,99 +25,81 @@
#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);
+ const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
+ layout_->setMargin(fw);
+ tearoffwidget_ = new TearOff(this);
+ connect(tearoffwidget_, SIGNAL(tearOff()), this, SLOT(tearOff()));
+ v->addWidget(tearoffwidget_);
+ v->addLayout(layout_);
}
@@ -141,15 +123,31 @@
}
+void IconPalette::tearOff()
+{
+ blockSignals(true);
+ hide();
+ 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,15 +181,21 @@
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);
QWidget::hideEvent(event);
+ visible(false);
+ if (tornoff_) {
+ setWindowFlags(Qt::Popup);
+ tornoff_ = false;
+ tearoffwidget_->setVisible(!tornoff_);
+ }
}
@@ -211,17 +215,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 +232,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;