|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt3Support module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "q3toolbar.h" |
|
43 #ifndef QT_NO_TOOLBAR |
|
44 |
|
45 #include "q3mainwindow.h" |
|
46 #include "qapplication.h" |
|
47 #include "q3combobox.h" |
|
48 #include "qcursor.h" |
|
49 #include "qdesktopwidget.h" |
|
50 #include "qdrawutil.h" |
|
51 #include "qevent.h" |
|
52 #include "qframe.h" |
|
53 #include "qlayout.h" |
|
54 #include "qmap.h" |
|
55 #include "qpainter.h" |
|
56 #include "q3popupmenu.h" |
|
57 #include "qstyle.h" |
|
58 #include "qstyleoption.h" |
|
59 #include "qtimer.h" |
|
60 #include "qtoolbutton.h" |
|
61 #include "qtooltip.h" |
|
62 |
|
63 QT_BEGIN_NAMESPACE |
|
64 |
|
65 static const char * const arrow_v_xpm[] = { |
|
66 "7 9 3 1", |
|
67 " c None", |
|
68 ". c #000000", |
|
69 "+ c none", |
|
70 ".+++++.", |
|
71 "..+++..", |
|
72 "+..+..+", |
|
73 "++...++", |
|
74 ".++.++.", |
|
75 "..+++..", |
|
76 "+..+..+", |
|
77 "++...++", |
|
78 "+++.+++"}; |
|
79 |
|
80 static const char * const arrow_h_xpm[] = { |
|
81 "9 7 3 1", |
|
82 " c None", |
|
83 ". c #000000", |
|
84 "+ c none", |
|
85 "..++..+++", |
|
86 "+..++..++", |
|
87 "++..++..+", |
|
88 "+++..++..", |
|
89 "++..++..+", |
|
90 "+..++..++", |
|
91 "..++..+++"}; |
|
92 |
|
93 class Q3ToolBarExtensionWidget; |
|
94 |
|
95 class Q3ToolBarPrivate |
|
96 { |
|
97 public: |
|
98 Q3ToolBarPrivate() : moving(false), checkingExtension(false) { |
|
99 } |
|
100 |
|
101 bool moving; |
|
102 bool checkingExtension; |
|
103 Q3ToolBarExtensionWidget *extension; |
|
104 Q3PopupMenu *extensionPopup; |
|
105 |
|
106 QMap<QAction *, QWidget *> actions; |
|
107 }; |
|
108 |
|
109 |
|
110 class Q3ToolBarSeparator : public QWidget |
|
111 { |
|
112 Q_OBJECT |
|
113 public: |
|
114 Q3ToolBarSeparator(Qt::Orientation, Q3ToolBar *parent, const char* name=0); |
|
115 |
|
116 QSize sizeHint() const; |
|
117 Qt::Orientation orientation() const { return orient; } |
|
118 public slots: |
|
119 void setOrientation(Qt::Orientation); |
|
120 protected: |
|
121 void changeEvent(QEvent *); |
|
122 void paintEvent(QPaintEvent *); |
|
123 |
|
124 private: |
|
125 Qt::Orientation orient; |
|
126 }; |
|
127 |
|
128 class Q3ToolBarExtensionWidget : public QWidget |
|
129 { |
|
130 Q_OBJECT |
|
131 |
|
132 public: |
|
133 Q3ToolBarExtensionWidget(QWidget *w); |
|
134 void setOrientation(Qt::Orientation o); |
|
135 QToolButton *button() const { return tb; } |
|
136 |
|
137 protected: |
|
138 void resizeEvent(QResizeEvent *e) { |
|
139 QWidget::resizeEvent(e); |
|
140 layOut(); |
|
141 } |
|
142 |
|
143 private: |
|
144 void layOut(); |
|
145 QToolButton *tb; |
|
146 Qt::Orientation orient; |
|
147 |
|
148 }; |
|
149 |
|
150 Q3ToolBarExtensionWidget::Q3ToolBarExtensionWidget(QWidget *w) |
|
151 : QWidget(w, "qt_dockwidget_internal") |
|
152 { |
|
153 tb = new QToolButton(this, "qt_toolbar_ext_button"); |
|
154 tb->setAutoRaise(true); |
|
155 setOrientation(Qt::Horizontal); |
|
156 setAutoFillBackground(true); |
|
157 } |
|
158 |
|
159 void Q3ToolBarExtensionWidget::setOrientation(Qt::Orientation o) |
|
160 { |
|
161 orient = o; |
|
162 if (orient == Qt::Horizontal) |
|
163 tb->setIcon(QPixmap((const char **)arrow_h_xpm)); |
|
164 else |
|
165 tb->setIcon(QPixmap((const char **)arrow_v_xpm)); |
|
166 layOut(); |
|
167 } |
|
168 |
|
169 void Q3ToolBarExtensionWidget::layOut() |
|
170 { |
|
171 tb->setGeometry(2, 2, width() - 4, height() - 4); |
|
172 } |
|
173 |
|
174 Q3ToolBarSeparator::Q3ToolBarSeparator(Qt::Orientation o , Q3ToolBar *parent, |
|
175 const char* name) |
|
176 : QWidget(parent, name) |
|
177 { |
|
178 connect(parent, SIGNAL(orientationChanged(Qt::Orientation)), |
|
179 this, SLOT(setOrientation(Qt::Orientation))); |
|
180 setOrientation(o); |
|
181 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); |
|
182 } |
|
183 |
|
184 |
|
185 |
|
186 void Q3ToolBarSeparator::setOrientation(Qt::Orientation o) |
|
187 { |
|
188 orient = o; |
|
189 } |
|
190 |
|
191 void Q3ToolBarSeparator::changeEvent(QEvent *ev) |
|
192 { |
|
193 if(ev->type() == QEvent::StyleChange) |
|
194 setOrientation(orient); |
|
195 QWidget::changeEvent(ev); |
|
196 } |
|
197 |
|
198 static QStyleOption getStyleOption(const Q3ToolBarSeparator *tbs) |
|
199 { |
|
200 QStyleOption opt(0); |
|
201 opt.rect = tbs->rect(); |
|
202 opt.palette = tbs->palette(); |
|
203 if (tbs->orientation() == Qt::Horizontal) |
|
204 opt.state = QStyle::State_Horizontal; |
|
205 else |
|
206 opt.state = QStyle::State_None; |
|
207 return opt; |
|
208 } |
|
209 |
|
210 QSize Q3ToolBarSeparator::sizeHint() const |
|
211 { |
|
212 QStyleOption opt = getStyleOption(this); |
|
213 int extent = style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, &opt, this); |
|
214 if (orient == Qt::Horizontal) |
|
215 return QSize(extent, 0); |
|
216 else |
|
217 return QSize(0, extent); |
|
218 } |
|
219 |
|
220 void Q3ToolBarSeparator::paintEvent(QPaintEvent *) |
|
221 { |
|
222 QPainter p(this); |
|
223 QStyleOption opt = getStyleOption(this); |
|
224 style()->drawPrimitive(QStyle::PE_Q3DockWindowSeparator, &opt, &p, this); |
|
225 } |
|
226 |
|
227 QT_BEGIN_INCLUDE_NAMESPACE |
|
228 #include "q3toolbar.moc" |
|
229 QT_END_INCLUDE_NAMESPACE |
|
230 |
|
231 |
|
232 /*! |
|
233 \class Q3ToolBar |
|
234 \brief The Q3ToolBar class provides a movable panel containing |
|
235 widgets such as tool buttons. |
|
236 |
|
237 \compat |
|
238 |
|
239 A toolbar is a panel that contains a set of controls, usually |
|
240 represented by small icons. It's purpose is to provide quick |
|
241 access to frequently used commands or options. Within a |
|
242 Q3MainWindow the user can drag toolbars within and between the |
|
243 \link Q3DockArea dock areas\endlink. Toolbars can also be dragged |
|
244 out of any dock area to float freely as top-level windows. |
|
245 |
|
246 Q3ToolBar is a specialization of QDockWindow, and so provides all |
|
247 the functionality of a QDockWindow. |
|
248 |
|
249 To use Q3ToolBar you simply create a Q3ToolBar as a child of a |
|
250 Q3MainWindow, create a number of QToolButton widgets (or other |
|
251 widgets) in left to right (or top to bottom) order and call |
|
252 addSeparator() when you want a separator. When a toolbar is |
|
253 floated the caption used is the label given in the constructor |
|
254 call. This can be changed with setLabel(). |
|
255 |
|
256 You may use most widgets within a toolbar, with QToolButton and |
|
257 QComboBox being the most common. But note that the toolbar's |
|
258 actions must be \l {Q3Action}s. |
|
259 |
|
260 If you create a new widget on an already visible Q3ToolBar, this |
|
261 widget will automatically become visible without needing a show() |
|
262 call. (This differs from every other Qt widget container. We |
|
263 recommend calling show() anyway since we hope to fix this anomaly |
|
264 in a future release.) |
|
265 |
|
266 Q3ToolBars, like QDockWindows, are located in \l{Q3DockArea}s or |
|
267 float as top-level windows. Q3MainWindow provides four Q3DockAreas |
|
268 (top, left, right and bottom). When you create a new toolbar (as |
|
269 in the example above) as a child of a Q3MainWindow the toolbar will |
|
270 be added to the top dock area. You can move it to another dock |
|
271 area (or float it) by calling Q3MainWindow::moveDockWindow(). Dock |
|
272 areas lay out their windows in lines. |
|
273 |
|
274 If the main window is resized so that the area occupied by the |
|
275 toolbar is too small to show all its widgets a little arrow button |
|
276 (which looks like a right-pointing chevron, '»') will appear |
|
277 at the right or bottom of the toolbar depending on its |
|
278 orientation. Clicking this button pops up a menu that shows the |
|
279 'overflowing' items. QToolButtons are represented in the menu using |
|
280 their textLabel property, other QAbstractButton subclasses are represented |
|
281 using their text property, and QComboBoxes are represented as submenus, |
|
282 with the caption text being used in the submenu item. |
|
283 |
|
284 Usually a toolbar will get precisely the space it needs. However, |
|
285 with setHorizontalStretchable(), setVerticalStretchable() or |
|
286 setStretchableWidget() you can tell the main window to expand the |
|
287 toolbar to fill all available space in the specified orientation. |
|
288 |
|
289 The toolbar arranges its buttons either horizontally or vertically |
|
290 (see orientation() for details). Generally, Q3DockArea will set the |
|
291 orientation correctly for you, but you can set it yourself with |
|
292 setOrientation() and track any changes by connecting to the |
|
293 orientationChanged() signal. |
|
294 |
|
295 You can use the clear() method to remove all items from a toolbar. |
|
296 |
|
297 \img qdockwindow.png Toolbar (dock window) |
|
298 \caption A floating QToolbar (dock window) |
|
299 |
|
300 \sa QToolButton Q3MainWindow |
|
301 */ |
|
302 |
|
303 /*! |
|
304 Constructs an empty toolbar. |
|
305 |
|
306 The toolbar is called \a name and is a child of \a parent and is |
|
307 managed by \a parent. It is initially located in dock area \a dock |
|
308 and is labeled \a label. If \a newLine is true the toolbar will be |
|
309 placed on a new line in the dock area. |
|
310 */ |
|
311 |
|
312 Q3ToolBar::Q3ToolBar(const QString &label, |
|
313 Q3MainWindow * parent, Qt::ToolBarDock dock, |
|
314 bool newLine, const char * name) |
|
315 : Q3DockWindow(InDock, parent, name, 0, true) |
|
316 { |
|
317 mw = parent; |
|
318 init(); |
|
319 |
|
320 if (parent) |
|
321 parent->addToolBar(this, label, dock, newLine); |
|
322 } |
|
323 |
|
324 |
|
325 /*! |
|
326 Constructs an empty horizontal toolbar. |
|
327 |
|
328 The toolbar is called \a name and is a child of \a parent and is |
|
329 managed by \a mainWindow. The \a label and \a newLine parameters |
|
330 are passed straight to Q3MainWindow::addDockWindow(). \a name and |
|
331 the widget flags \a f are passed on to the Q3DockWindow constructor. |
|
332 |
|
333 Use this constructor if you want to create torn-off (undocked, |
|
334 floating) toolbars or toolbars in the \link QStatusBar status |
|
335 bar\endlink. |
|
336 */ |
|
337 |
|
338 Q3ToolBar::Q3ToolBar(const QString &label, Q3MainWindow * mainWindow, |
|
339 QWidget * parent, bool newLine, const char * name, |
|
340 Qt::WindowFlags f) |
|
341 : Q3DockWindow(InDock, parent, name, f, true) |
|
342 { |
|
343 mw = mainWindow; |
|
344 init(); |
|
345 |
|
346 setParent(parent); |
|
347 |
|
348 if (mainWindow) |
|
349 mainWindow->addToolBar(this, label, Qt::DockUnmanaged, newLine); |
|
350 } |
|
351 |
|
352 |
|
353 /*! |
|
354 \overload |
|
355 |
|
356 Constructs an empty toolbar called \a name, with parent \a parent, |
|
357 in its \a parent's top dock area, without any label and without |
|
358 requiring a newline. |
|
359 */ |
|
360 |
|
361 Q3ToolBar::Q3ToolBar(Q3MainWindow * parent, const char * name) |
|
362 : Q3DockWindow(InDock, parent, name, 0, true) |
|
363 { |
|
364 mw = parent; |
|
365 init(); |
|
366 |
|
367 if (parent) |
|
368 parent->addToolBar(this, QString(), Qt::DockTop); |
|
369 } |
|
370 |
|
371 /*! |
|
372 \internal |
|
373 |
|
374 Common initialization code. Requires that \c mw and \c o are set. |
|
375 Does not call Q3MainWindow::addDockWindow(). |
|
376 */ |
|
377 void Q3ToolBar::init() |
|
378 { |
|
379 d = new Q3ToolBarPrivate; |
|
380 d->extension = 0; |
|
381 d->extensionPopup = 0; |
|
382 sw = 0; |
|
383 |
|
384 setBackgroundRole(QPalette::Button); |
|
385 setFocusPolicy(Qt::NoFocus); |
|
386 setFrameStyle(QFrame::ToolBarPanel | QFrame::Raised); |
|
387 } |
|
388 |
|
389 /*! |
|
390 Destructor. |
|
391 */ |
|
392 |
|
393 Q3ToolBar::~Q3ToolBar() |
|
394 { |
|
395 delete d; |
|
396 } |
|
397 |
|
398 /*! |
|
399 \reimp |
|
400 */ |
|
401 |
|
402 void Q3ToolBar::setOrientation(Qt::Orientation o) |
|
403 { |
|
404 Q3DockWindow::setOrientation(o); |
|
405 if (d->extension) |
|
406 d->extension->setOrientation(o); |
|
407 QObjectList childList = children(); |
|
408 for (int i = 0; i < childList.size(); ++i) { |
|
409 Q3ToolBarSeparator* w = qobject_cast<Q3ToolBarSeparator*>(childList.at(i)); |
|
410 if (w) |
|
411 w->setOrientation(o); |
|
412 } |
|
413 } |
|
414 |
|
415 /*! |
|
416 Adds a separator to the right/bottom of the toolbar. |
|
417 */ |
|
418 |
|
419 void Q3ToolBar::addSeparator() |
|
420 { |
|
421 (void) new Q3ToolBarSeparator(orientation(), this, "toolbar separator"); |
|
422 } |
|
423 |
|
424 /*! |
|
425 \internal |
|
426 */ |
|
427 |
|
428 void Q3ToolBar::styleChange(QStyle &oldStyle) |
|
429 { |
|
430 Q3DockWindow::styleChange(oldStyle); |
|
431 } |
|
432 |
|
433 |
|
434 /*! |
|
435 \reimp |
|
436 */ |
|
437 void Q3ToolBar::setVisible(bool visible) |
|
438 { |
|
439 Q3DockWindow::setVisible(visible); |
|
440 if (mw) |
|
441 mw->triggerLayout(false); |
|
442 if (visible) |
|
443 checkForExtension(size()); |
|
444 } |
|
445 |
|
446 /*! |
|
447 Returns a pointer to the Q3MainWindow which manages this toolbar. |
|
448 */ |
|
449 |
|
450 Q3MainWindow * Q3ToolBar::mainWindow() const |
|
451 { |
|
452 return mw; |
|
453 } |
|
454 |
|
455 |
|
456 /*! |
|
457 Sets the widget \a w to be expanded if this toolbar is requested |
|
458 to stretch. |
|
459 |
|
460 The request to stretch might occur because Q3MainWindow |
|
461 right-justifies the dock area the toolbar is in, or because this |
|
462 toolbar's isVerticalStretchable() or isHorizontalStretchable() is |
|
463 set to true. |
|
464 |
|
465 If you call this function and the toolbar is not yet stretchable, |
|
466 setStretchable() is called. |
|
467 |
|
468 \sa Q3MainWindow::setRightJustification(), setVerticalStretchable(), |
|
469 setHorizontalStretchable() |
|
470 */ |
|
471 |
|
472 void Q3ToolBar::setStretchableWidget(QWidget * w) |
|
473 { |
|
474 sw = w; |
|
475 boxLayout()->setStretchFactor(w, 1); |
|
476 |
|
477 if (!isHorizontalStretchable() && !isVerticalStretchable()) { |
|
478 if (orientation() == Qt::Horizontal) |
|
479 setHorizontalStretchable(true); |
|
480 else |
|
481 setVerticalStretchable(true); |
|
482 } |
|
483 } |
|
484 |
|
485 |
|
486 /*! |
|
487 \reimp |
|
488 */ |
|
489 |
|
490 bool Q3ToolBar::event(QEvent * e) |
|
491 { |
|
492 bool r = Q3DockWindow::event(e); |
|
493 // After the event filters have dealt with it, do our stuff. |
|
494 if (e->type() == QEvent::ChildInserted) { |
|
495 QObject * child = ((QChildEvent*)e)->child(); |
|
496 if (child && child->isWidgetType() && !((QWidget*)child)->isWindow() |
|
497 && child->parent() == this |
|
498 && QLatin1String("qt_dockwidget_internal") != child->objectName()) { |
|
499 boxLayout()->addWidget((QWidget*)child); |
|
500 QLayoutItem *item = boxLayout()->itemAt(boxLayout()->indexOf((QWidget*)child)); |
|
501 if (QToolButton *button = qobject_cast<QToolButton*>(child)) { |
|
502 item->setAlignment(Qt::AlignHCenter); |
|
503 button->setFocusPolicy(Qt::NoFocus); |
|
504 if (mw) { |
|
505 QObject::connect(mw, SIGNAL(pixmapSizeChanged(bool)), |
|
506 button, SLOT(setUsesBigPixmap(bool))); |
|
507 button->setUsesBigPixmap(mw->usesBigPixmaps()); |
|
508 QObject::connect(mw, SIGNAL(usesTextLabelChanged(bool)), |
|
509 child, SLOT(setUsesTextLabel(bool))); |
|
510 button->setUsesTextLabel(mw->usesTextLabel()); |
|
511 } |
|
512 button->setAutoRaise(true); |
|
513 } |
|
514 if (isVisible()) { |
|
515 // toolbar compatibility: we auto show widgets that |
|
516 // are not explicitly hidden |
|
517 if (((QWidget*)child)->testAttribute(Qt::WA_WState_Hidden) |
|
518 && !((QWidget*)child)->testAttribute(Qt::WA_WState_ExplicitShowHide)) |
|
519 ((QWidget*)child)->show(); |
|
520 checkForExtension(size()); |
|
521 } |
|
522 } |
|
523 if (child && child->isWidgetType() && ((QWidget*)child) == sw) |
|
524 boxLayout()->setStretchFactor((QWidget*)child, 1); |
|
525 } else if (e->type() == QEvent::Show) { |
|
526 layout()->activate(); |
|
527 } else if (e->type() == QEvent::LayoutHint && place() == OutsideDock) { |
|
528 adjustSize(); |
|
529 } |
|
530 return r; |
|
531 } |
|
532 |
|
533 |
|
534 /*! |
|
535 \property Q3ToolBar::label |
|
536 \brief the toolbar's label. |
|
537 |
|
538 If the toolbar is floated the label becomes the toolbar window's |
|
539 caption. There is no default label text. |
|
540 */ |
|
541 |
|
542 void Q3ToolBar::setLabel(const QString & label) |
|
543 { |
|
544 l = label; |
|
545 setWindowTitle(l); |
|
546 } |
|
547 |
|
548 QString Q3ToolBar::label() const |
|
549 { |
|
550 return l; |
|
551 } |
|
552 |
|
553 |
|
554 /*! |
|
555 Deletes all the toolbar's child widgets. |
|
556 */ |
|
557 |
|
558 void Q3ToolBar::clear() |
|
559 { |
|
560 QObjectList childList = children(); |
|
561 d->extension = 0; |
|
562 d->extensionPopup = 0; //they will both be destroyed by the following code |
|
563 for (int i = 0; i < childList.size(); ++i) { |
|
564 QObject *obj = childList.at(i); |
|
565 if (obj->isWidgetType() && QLatin1String("qt_dockwidget_internal") != obj->objectName()) |
|
566 delete obj; |
|
567 } |
|
568 } |
|
569 |
|
570 /*! |
|
571 \internal |
|
572 */ |
|
573 |
|
574 QSize Q3ToolBar::minimumSize() const |
|
575 { |
|
576 if (orientation() == Qt::Horizontal) |
|
577 return QSize(0, Q3DockWindow::minimumSize().height()); |
|
578 return QSize(Q3DockWindow::minimumSize().width(), 0); |
|
579 } |
|
580 |
|
581 /*! |
|
582 \reimp |
|
583 */ |
|
584 |
|
585 QSize Q3ToolBar::minimumSizeHint() const |
|
586 { |
|
587 if (orientation() == Qt::Horizontal) |
|
588 return QSize(0, Q3DockWindow::minimumSizeHint().height()); |
|
589 return QSize(Q3DockWindow::minimumSizeHint().width(), 0); |
|
590 } |
|
591 |
|
592 void Q3ToolBar::createPopup() |
|
593 { |
|
594 if (!d->extensionPopup) { |
|
595 d->extensionPopup = new Q3PopupMenu(this, "qt_dockwidget_internal"); |
|
596 connect(d->extensionPopup, SIGNAL(aboutToShow()), this, SLOT(createPopup())); |
|
597 } |
|
598 |
|
599 if (!d->extension) { |
|
600 d->extension = new Q3ToolBarExtensionWidget(this); |
|
601 d->extension->setOrientation(orientation()); |
|
602 d->extension->button()->setPopup(d->extensionPopup); |
|
603 d->extension->button()->setPopupMode(QToolButton::InstantPopup); |
|
604 } |
|
605 |
|
606 d->extensionPopup->clear(); |
|
607 |
|
608 // delete submenus |
|
609 QObjectList popups = d->extensionPopup->queryList("Q3PopupMenu", 0, false, true); |
|
610 while (!popups.isEmpty()) |
|
611 delete popups.takeFirst(); |
|
612 |
|
613 QObjectList childlist = queryList("QWidget", 0, false, true); |
|
614 bool hide = false; |
|
615 bool doHide = false; |
|
616 int id; |
|
617 for (int i = 0; i < childlist.size(); ++i) { |
|
618 QObject *obj = childlist.at(i); |
|
619 if (!obj->isWidgetType() || obj == d->extension->button() || obj == d->extensionPopup |
|
620 || QLatin1String("qt_dockwidget_internal") == obj->objectName()) { |
|
621 continue; |
|
622 } |
|
623 int j = 2; |
|
624 QWidget *w = (QWidget*)obj; |
|
625 if (qobject_cast<Q3ComboBox*>(w)) |
|
626 j = 1; |
|
627 hide = false; |
|
628 |
|
629 const int padding = 4; // extra pixels added by the layout hierarchy |
|
630 QPoint p(mapTo(this, w->geometry().bottomRight())); |
|
631 if (orientation() == Qt::Horizontal) { |
|
632 if ((p.x() > (doHide ? width() - d->extension->width() / j - padding : width() - padding)) |
|
633 || (p.x() > parentWidget()->width() - d->extension->width())) |
|
634 hide = true; |
|
635 } else { |
|
636 if ((p.y() > (doHide ? height()- d->extension->height() / j - padding : height() - padding)) |
|
637 || (p.y() > parentWidget()->height() - d->extension->height())) |
|
638 hide = true; |
|
639 } |
|
640 if (hide && w->isVisible()) { |
|
641 doHide = true; |
|
642 if (qobject_cast<QToolButton*>(w)) { |
|
643 QToolButton *b = (QToolButton*)w; |
|
644 QString s = b->textLabel(); |
|
645 if (s.isEmpty()) |
|
646 s = b->text(); |
|
647 if (b->popup() && b->popupDelay() == 0) |
|
648 id = d->extensionPopup->insertItem(b->iconSet(), s, b->popup()); |
|
649 else |
|
650 id = d->extensionPopup->insertItem(b->iconSet(), s, b, SLOT(click())) ; |
|
651 if (b->isToggleButton()) |
|
652 d->extensionPopup->setItemChecked(id, b->isOn()); |
|
653 if (!b->isEnabled()) |
|
654 d->extensionPopup->setItemEnabled(id, false); |
|
655 } else if (qobject_cast<QAbstractButton*>(w)) { |
|
656 QAbstractButton *b = (QAbstractButton*)w; |
|
657 QString s = b->text(); |
|
658 if (s.isEmpty()) |
|
659 s = QLatin1String(""); |
|
660 if (b->pixmap()) |
|
661 id = d->extensionPopup->insertItem(*b->pixmap(), s, b, SLOT(click())); |
|
662 else |
|
663 id = d->extensionPopup->insertItem(s, b, SLOT(click())); |
|
664 if (b->isToggleButton()) |
|
665 d->extensionPopup->setItemChecked(id, b->isOn()); |
|
666 if (!b->isEnabled()) |
|
667 d->extensionPopup->setItemEnabled(id, false); |
|
668 #ifndef QT_NO_COMBOBOX |
|
669 } else if (qobject_cast<Q3ComboBox*>(w)) { |
|
670 Q3ComboBox *c = (Q3ComboBox*)w; |
|
671 if (c->count() != 0) { |
|
672 QString s = c->windowTitle(); |
|
673 if (s.isEmpty()) |
|
674 s = c->currentText(); |
|
675 int maxItems = 0; |
|
676 Q3PopupMenu *cp = new Q3PopupMenu(d->extensionPopup); |
|
677 cp->setEnabled(c->isEnabled()); |
|
678 d->extensionPopup->insertItem(s, cp); |
|
679 connect(cp, SIGNAL(activated(int)), c, SLOT(internalActivate(int))); |
|
680 for (int i = 0; i < c->count(); ++i) { |
|
681 QString tmp = c->text(i); |
|
682 cp->insertItem(tmp, i); |
|
683 if (c->currentText() == tmp) |
|
684 cp->setItemChecked(i, true); |
|
685 if (!maxItems) { |
|
686 if (cp->actions().count() == 10) { |
|
687 int h = cp->sizeHint().height(); |
|
688 maxItems = QApplication::desktop()->height() * 10 / h; |
|
689 } |
|
690 } else if (cp->actions().count() >= maxItems - 1) { |
|
691 Q3PopupMenu* sp = new Q3PopupMenu(d->extensionPopup); |
|
692 cp->insertItem(tr("More..."), sp); |
|
693 cp = sp; |
|
694 connect(cp, SIGNAL(activated(int)), c, SLOT(internalActivate(int))); |
|
695 } |
|
696 } |
|
697 } |
|
698 #endif //QT_NO_COMBOBOX |
|
699 } |
|
700 } |
|
701 } |
|
702 } |
|
703 |
|
704 /*! |
|
705 \reimp |
|
706 */ |
|
707 |
|
708 void Q3ToolBar::resizeEvent(QResizeEvent *e) |
|
709 { |
|
710 Q3DockWindow::resizeEvent(e); |
|
711 checkForExtension(e->size()); |
|
712 } |
|
713 |
|
714 /*! |
|
715 \internal |
|
716 |
|
717 This function is called when an action is triggered. The relevant |
|
718 information is passed in the event \a e. |
|
719 */ |
|
720 void Q3ToolBar::actionEvent(QActionEvent *e) |
|
721 { |
|
722 if (e->type() == QEvent::ActionAdded) { |
|
723 QAction *a = e->action(); |
|
724 QWidget *w; |
|
725 if (a->isSeparator()) { |
|
726 w = new Q3ToolBarSeparator(orientation(), this, "toolbar separator"); |
|
727 } else { |
|
728 QToolButton* btn = new QToolButton(this); |
|
729 btn->setDefaultAction(a); |
|
730 w = btn; |
|
731 } |
|
732 d->actions.insert(a, w); |
|
733 } else if (e->type() == QEvent::ActionRemoved) { |
|
734 QAction *a = e->action(); |
|
735 delete d->actions.take(a); |
|
736 } |
|
737 } |
|
738 |
|
739 |
|
740 void Q3ToolBar::checkForExtension(const QSize &sz) |
|
741 { |
|
742 if (!isVisible()) |
|
743 return; |
|
744 |
|
745 if (d->checkingExtension) |
|
746 return; |
|
747 d->checkingExtension = true; |
|
748 |
|
749 bool tooSmall; |
|
750 if (orientation() == Qt::Horizontal) |
|
751 tooSmall = sz.width() < sizeHint().width(); |
|
752 else |
|
753 tooSmall = sz.height() < sizeHint().height(); |
|
754 |
|
755 if (tooSmall) { |
|
756 createPopup(); |
|
757 if (d->extensionPopup->actions().count()) { |
|
758 // parentWidget()->width() used since the Q3ToolBar width |
|
759 // will never be less than minimumSize() |
|
760 if (orientation() == Qt::Horizontal) |
|
761 d->extension->setGeometry((parentWidget() ? parentWidget()->width() : width()) - 20, |
|
762 1, 20, height() - 2); |
|
763 else |
|
764 d->extension->setGeometry(1, (parentWidget() ? parentWidget()->height() : height()) - 20, |
|
765 width() - 2, 20); |
|
766 d->extension->show(); |
|
767 d->extension->raise(); |
|
768 } else { |
|
769 delete d->extension; |
|
770 d->extension = 0; |
|
771 delete d->extensionPopup; |
|
772 d->extensionPopup = 0; |
|
773 } |
|
774 } else { |
|
775 delete d->extension; |
|
776 d->extension = 0; |
|
777 delete d->extensionPopup; |
|
778 d->extensionPopup = 0; |
|
779 } |
|
780 d->checkingExtension = false; |
|
781 } |
|
782 |
|
783 |
|
784 /*! |
|
785 \internal |
|
786 */ |
|
787 |
|
788 void Q3ToolBar::setMinimumSize(int, int) |
|
789 { |
|
790 } |
|
791 |
|
792 /* from chaunsee: |
|
793 |
|
794 1. Tool Bars should contain only high-frequency functions. Avoid putting |
|
795 things like About and Exit on a tool bar unless they are frequent functions. |
|
796 |
|
797 2. All tool bar buttons must have some keyboard access method (it can be a |
|
798 menu or shortcut key or a function in a dialog box that can be accessed |
|
799 through the keyboard). |
|
800 |
|
801 3. Make tool bar functions as efficient as possible (the common example is to |
|
802 Print in Microsoft applications, it doesn't bring up the Print dialog box, it |
|
803 prints immediately to the default printer). |
|
804 |
|
805 4. Avoid turning tool bars into graphical menu bars. To me, a tool bar should |
|
806 be efficient. Once you make almost all the items in a tool bar into graphical |
|
807 pull-down menus, you start to lose efficiency. |
|
808 |
|
809 5. Make sure that adjacent icons are distinctive. There are some tool bars |
|
810 where you see a group of 4-5 icons that represent related functions, but they |
|
811 are so similar that you can't differentiate among them. These tool bars are |
|
812 often a poor attempt at a "common visual language". |
|
813 |
|
814 6. Use any de facto standard icons of your platform (for windows use the |
|
815 cut, copy and paste icons provided in dev kits rather than designing your |
|
816 own). |
|
817 |
|
818 7. Avoid putting a highly destructive tool bar button (delete database) by a |
|
819 safe, high-frequency button (Find) -- this will yield 1-0ff errors). |
|
820 |
|
821 8. Tooltips in many Microsoft products simply reiterate the menu text even |
|
822 when that is not explanatory. Consider making your tooltips slightly more |
|
823 verbose and explanatory than the corresponding menu item. |
|
824 |
|
825 9. Keep the tool bar as stable as possible when you click on different |
|
826 objects. Consider disabling tool bar buttons if they are used in most, but not |
|
827 all contexts. |
|
828 |
|
829 10. If you have multiple tool bars (like the Microsoft MMC snap-ins have), |
|
830 put the most stable tool bar to at the left with less stable ones to the |
|
831 right. This arrangement (stable to less stable) makes the tool bar somewhat |
|
832 more predictable. |
|
833 |
|
834 11. Keep a single tool bar to fewer than 20 items divided into 4-7 groups of |
|
835 items. |
|
836 */ |
|
837 |
|
838 QT_END_NAMESPACE |
|
839 |
|
840 #endif |