]> git.lyx.org Git - features.git/blob - src/frontends/qt/IconPalette.cpp
Show suggestions containing the input in the command buffer
[features.git] / src / frontends / qt / IconPalette.cpp
1 /**
2  * \file IconPalette.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "IconPalette.h"
14 #include "qt_helpers.h"
15
16 #include <QPixmap>
17 #include <QGridLayout>
18 #include <QToolButton>
19 #include <QToolTip>
20 #include <QToolBar>
21 #include <QApplication>
22 #if QT_VERSION < 0x060000
23 #include <QDesktopWidget>
24 #endif
25 #include <QPainter>
26 #include <QStyle>
27 #include <QStyleOptionFrame>
28 #include <QMouseEvent>
29 #include <QVBoxLayout>
30 #if QT_VERSION >= 0x060000
31 #include <QWindow>
32 #endif
33
34 namespace lyx {
35 namespace frontend {
36
37 TearOff::TearOff(QWidget * parent)
38         : QWidget(parent)
39 {
40         highlighted_ = false;
41         // + 2 because the default is a bit tight, see also:
42         // http://trolltech.com/developer/task-tracker/index_html?id=167954&method=entry
43         setMinimumHeight(style()->pixelMetric(QStyle::PM_MenuTearoffHeight) + 2);
44         setToolTip(qt_("Click to detach"));
45         // trigger tooltip (children of popups do not receive mousemove events)
46         setMouseTracking(true);
47 }
48
49
50 void TearOff::mouseReleaseEvent(QMouseEvent * /*event*/)
51 {
52         // signal
53         tearOff();
54 }
55
56
57 #if QT_VERSION < 0x060000
58 void TearOff::enterEvent(QEvent * event)
59 #else
60 void TearOff::enterEvent(QEnterEvent * event)
61 #endif
62 {
63         highlighted_ = true;
64         update();
65         event->ignore();
66 }
67
68
69 void TearOff::leaveEvent(QEvent * event)
70 {
71         highlighted_ = false;
72         update();
73         event->ignore();
74 }
75
76
77 void TearOff::paintEvent(QPaintEvent * /*event*/)
78 {
79         QPainter p(this);
80         const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
81         QStyleOptionMenuItem menuOpt;
82         menuOpt.initFrom(this);
83         menuOpt.palette = palette();
84         menuOpt.state = QStyle::State_None;
85         menuOpt.checkType = QStyleOptionMenuItem::NotCheckable;
86         menuOpt.menuRect = rect();
87         menuOpt.maxIconWidth = 0;
88 #if QT_VERSION < 0x060000
89         menuOpt.tabWidth = 0;
90 #endif
91         menuOpt.menuItemType = QStyleOptionMenuItem::TearOff;
92         menuOpt.rect.setRect(fw, fw, width() - (fw * 2),
93                 style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this));
94         p.setClipRect(menuOpt.rect);
95         menuOpt.state = QStyle::State_None;
96         if (highlighted_)
97                 menuOpt.state |= QStyle::State_Selected;
98         style()->drawControl(QStyle::CE_MenuTearoff, &menuOpt, &p, this);
99 }
100
101
102 IconPalette::IconPalette(QWidget * parent)
103         : QWidget(parent, Qt::Popup), tornoff_(false)
104 {
105         QVBoxLayout * v = new QVBoxLayout(this);
106 #if QT_VERSION < 0x060000
107         v->setMargin(0);
108 #else
109         v->setContentsMargins(0, 0, 0, 0);
110 #endif
111         v->setSpacing(0);
112         layout_ = new QGridLayout;
113         layout_->setSpacing(0);
114 #if QT_VERSION < 0x060000
115         const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
116         layout_->setMargin(fw);
117 #else
118         layout_->setContentsMargins(0, 0, 0, 0);
119 #endif
120         tearoffwidget_ = new TearOff(this);
121         connect(tearoffwidget_, SIGNAL(tearOff()), this, SLOT(tearOff()));
122         v->addWidget(tearoffwidget_);
123         v->addLayout(layout_);
124 }
125
126
127 void IconPalette::addButton(QAction * action)
128 {
129         actions_.push_back(action);
130         QToolButton * tb = new QToolButton;
131         tb->setAutoRaise(true);
132         tb->setDefaultAction(action);
133         // trigger tooltip (children of popups do not receive mousemove events)
134         tb->setMouseTracking(true);
135
136         connect(tb, SIGNAL(triggered(QAction *)),
137                 this, SLOT(clicked(QAction *)));
138         QToolBar * toolbar = qobject_cast<QToolBar *>(parentWidget()->parentWidget());
139         connect(toolbar, SIGNAL(iconSizeChanged(const QSize &)),
140                 tb, SLOT(setIconSize(const QSize &)));
141         tb->setIconSize(toolbar->iconSize());
142
143         int const i = actions_.size();
144         int const ncols = qMin(6, i);
145         int const row = (i - 1)/ncols + 1;
146         int const col = qMax(1, i - (row - 1) * 6);
147         layout_->addWidget(tb, row, col);
148 }
149
150
151 void IconPalette::tearOff()
152 {
153         blockSignals(true);
154         hide();
155         setWindowFlags(Qt::Tool);
156         tornoff_ = true;
157         tearoffwidget_->setVisible(!tornoff_);
158         show();
159         blockSignals(false);
160 }
161
162
163 void IconPalette::clicked(QAction * action)
164 {
165         triggered(action);
166         if (!tornoff_)
167                 setVisible(false);
168 }
169
170
171 void IconPalette::showEvent(QShowEvent * /*event*/)
172 {
173         resize(sizeHint());
174         setMaximumSize(sizeHint());
175
176         int hoffset = - parentWidget()->pos().x();
177         int voffset = - parentWidget()->pos().y();
178         int const parwidth = parentWidget()->geometry().width();
179         int const parheight = parentWidget()->geometry().height();
180
181         // vertical toolbar?
182         QToolBar * toolbar = qobject_cast<QToolBar *>(parentWidget()->parentWidget());
183         if (toolbar && toolbar->orientation() == Qt::Vertical) {
184                 hoffset += parwidth;
185                 voffset -= parheight;
186         }
187
188 #if QT_VERSION < 0x060000
189         QRect const screen = qApp->desktop()->availableGeometry(this);
190 #else
191         QRect const screen = window()->windowHandle()->screen()->availableGeometry();
192 #endif
193         QPoint const gpos = parentWidget()->mapToGlobal(
194                 parentWidget()->geometry().bottomLeft());
195
196         // space to the right?
197         if (gpos.x() + hoffset + width() > screen.width()) {
198                 hoffset -= width();
199                 if (toolbar && toolbar->orientation() == Qt::Vertical)
200                         hoffset -= parwidth;
201                 else
202                         hoffset += parwidth;
203         }
204         // space at the bottom?
205         if (gpos.y() + voffset + height() > screen.height()) {
206                 voffset -= height();
207                 if (toolbar && toolbar->orientation() == Qt::Horizontal)
208                         voffset -= parheight;
209                 else
210                         voffset += parheight;
211         }
212
213         QRect r = rect();
214         r.moveTo(gpos.x() + hoffset, gpos.y() + voffset);
215         setGeometry(r);
216 }
217
218
219 void IconPalette::hideEvent(QHideEvent * event )
220 {
221         QWidget::hideEvent(event);
222         visible(false);
223         if (tornoff_) {
224                 setWindowFlags(Qt::Popup);
225                 tornoff_ = false;
226                 tearoffwidget_->setVisible(!tornoff_);
227         }
228 }
229
230
231 void IconPalette::paintEvent(QPaintEvent * /*event*/)
232 {
233         // draw border
234         const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this);
235         if (fw && !tornoff_) {
236                 QPainter p(this);
237                 QRegion borderReg;
238                 borderReg += QRegion(QRect(0, 0, fw, height())); //left
239                 borderReg += QRegion(QRect(width() - fw, 0, fw, height())); //right
240                 borderReg += QRegion(QRect(0, 0, width(), fw)); //top
241                 borderReg += QRegion(QRect(0, height() - fw, width(), fw)); //bottom
242                 p.setClipRegion(borderReg);
243                 QStyleOptionFrame frame;
244                 frame.rect = rect();
245                 frame.palette = palette();
246                 frame.state = QStyle::State_None;
247                 frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuPanelWidth);
248                 frame.midLineWidth = 0;
249                 style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, &p, this);
250         }
251 }
252
253
254 ButtonMenu::ButtonMenu(const QString & title, QWidget * parent)
255         : QMenu(title, parent)
256 {
257 }
258
259
260 void ButtonMenu::add(QAction * action)
261 {
262         addAction(action);
263         actions_.push_back(action);
264 }
265
266
267 void ButtonMenu::updateParent()
268 {
269         bool enable = false;
270         // FIXME: so this is commented out for speed considerations
271         // true fix is to repair the updating mechanism of the toolbar
272 #if 0
273         for (int i = 0; i < actions_.size(); ++i)
274                 if (actions_.at(i)->isEnabled()) {
275                         enable = true;
276                         break;
277                 }
278 #else
279         // we check only the first action to enable/disable the menu
280         if (!actions_.isEmpty())
281                 enable = actions_.at(0)->isEnabled();
282 #endif
283
284         parentWidget()->setEnabled(enable);
285 }
286
287
288 } // namespace frontend
289 } // namespace lyx
290
291 #include "moc_IconPalette.cpp"