|
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 "q3dockwindow.h" |
|
43 |
|
44 #ifndef QT_NO_MAINWINDOW |
|
45 #include "qapplication.h" |
|
46 #include "qcursor.h" |
|
47 #include "qdesktopwidget.h" |
|
48 #include "q3dockarea.h" |
|
49 #include "qevent.h" |
|
50 #include "qlayout.h" |
|
51 #include "q3mainwindow.h" |
|
52 #include "qpainter.h" |
|
53 #include "qpointer.h" |
|
54 #include "qstyle.h" |
|
55 #include "qstyleoption.h" |
|
56 #include "qtimer.h" |
|
57 #include "q3toolbar.h" |
|
58 #include "qtoolbutton.h" |
|
59 #include "qtooltip.h" |
|
60 #include <private/q3titlebar_p.h> |
|
61 #include <private/qwidgetresizehandler_p.h> |
|
62 #include <qrubberband.h> |
|
63 #include <qdebug.h> |
|
64 |
|
65 QT_BEGIN_NAMESPACE |
|
66 |
|
67 #ifdef Q_WS_MAC |
|
68 static bool default_opaque = true; |
|
69 #else |
|
70 static bool default_opaque = false; |
|
71 #endif |
|
72 |
|
73 class Q3DockWindowPrivate |
|
74 { |
|
75 }; |
|
76 |
|
77 class Q3DockWindowResizeHandle : public QWidget |
|
78 { |
|
79 Q_OBJECT |
|
80 |
|
81 public: |
|
82 Q3DockWindowResizeHandle(Qt::Orientation o, QWidget *parent, Q3DockWindow *w, const char* /*name*/=0); |
|
83 void setOrientation(Qt::Orientation o); |
|
84 Qt::Orientation orientation() const { return orient; } |
|
85 |
|
86 QSize sizeHint() const; |
|
87 |
|
88 protected: |
|
89 void paintEvent(QPaintEvent *); |
|
90 void mouseMoveEvent(QMouseEvent *); |
|
91 void mousePressEvent(QMouseEvent *); |
|
92 void mouseReleaseEvent(QMouseEvent *); |
|
93 bool event(QEvent *event); |
|
94 |
|
95 private: |
|
96 void startLineDraw(); |
|
97 void endLineDraw(); |
|
98 void drawLine(const QPoint &globalPos); |
|
99 |
|
100 private: |
|
101 Qt::Orientation orient; |
|
102 bool mousePressed; |
|
103 QRubberBand *rubberBand; |
|
104 QPoint lastPos, firstPos; |
|
105 Q3DockWindow *dockWindow; |
|
106 bool mouseOver; |
|
107 }; |
|
108 |
|
109 Q3DockWindowResizeHandle::Q3DockWindowResizeHandle(Qt::Orientation o, QWidget *parent, |
|
110 Q3DockWindow *w, const char *) |
|
111 : QWidget(parent, "qt_dockwidget_internal"), mousePressed(false), rubberBand(0), dockWindow(w), |
|
112 mouseOver(false) |
|
113 { |
|
114 setOrientation(o); |
|
115 } |
|
116 |
|
117 QSize Q3DockWindowResizeHandle::sizeHint() const |
|
118 { |
|
119 QStyleOptionQ3DockWindow opt; |
|
120 opt.init(this); |
|
121 if (!dockWindow->area() || dockWindow->area()->orientation() == Qt::Horizontal) |
|
122 opt.state |= QStyle::State_Horizontal; |
|
123 |
|
124 opt.rect = rect(); |
|
125 opt.docked = dockWindow->area(); |
|
126 opt.closeEnabled = dockWindow->isCloseEnabled(); |
|
127 int sw = 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, &opt, this) / 3; |
|
128 return (style()->sizeFromContents(QStyle::CT_Q3DockWindow, &opt, QSize(sw, sw), this).expandedTo(QApplication::globalStrut())); |
|
129 } |
|
130 |
|
131 void Q3DockWindowResizeHandle::setOrientation(Qt::Orientation o) |
|
132 { |
|
133 orient = o; |
|
134 if (o == Qt::Horizontal) { |
|
135 #ifndef QT_NO_CURSOR |
|
136 setCursor(Qt::splitVCursor); |
|
137 #endif |
|
138 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); |
|
139 } else { |
|
140 #ifndef QT_NO_CURSOR |
|
141 setCursor(Qt::splitHCursor); |
|
142 #endif |
|
143 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding)); |
|
144 } |
|
145 } |
|
146 |
|
147 void Q3DockWindowResizeHandle::mousePressEvent(QMouseEvent *e) |
|
148 { |
|
149 e->ignore(); |
|
150 if (e->button() != Qt::LeftButton) |
|
151 return; |
|
152 e->accept(); |
|
153 mousePressed = true; |
|
154 if (!dockWindow->opaqueMoving()) |
|
155 startLineDraw(); |
|
156 lastPos = firstPos = e->globalPos(); |
|
157 if (!dockWindow->opaqueMoving()) |
|
158 drawLine(e->globalPos()); |
|
159 } |
|
160 |
|
161 void Q3DockWindowResizeHandle::mouseMoveEvent(QMouseEvent *e) |
|
162 { |
|
163 if (!mousePressed) |
|
164 return; |
|
165 if (!dockWindow->opaqueMoving()) { |
|
166 if (orientation() != dockWindow->area()->orientation()) { |
|
167 if (orientation() == Qt::Horizontal) { |
|
168 int minpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).y(); |
|
169 int maxpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).y() + dockWindow->area()->height(); |
|
170 if (e->globalPos().y() < minpos || e->globalPos().y() > maxpos) |
|
171 return; |
|
172 } else { |
|
173 int minpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).x(); |
|
174 int maxpos = dockWindow->area()->mapToGlobal(QPoint(0, 0)).x() + dockWindow->area()->width(); |
|
175 if (e->globalPos().x() < minpos || e->globalPos().x() > maxpos) |
|
176 return; |
|
177 } |
|
178 } else { |
|
179 QWidget *w = dockWindow->area()->window(); |
|
180 if (w) { |
|
181 if (orientation() == Qt::Horizontal) { |
|
182 int minpos = w->mapToGlobal(QPoint(0, 0)).y(); |
|
183 int maxpos = w->mapToGlobal(QPoint(0, 0)).y() + w->height(); |
|
184 if (e->globalPos().y() < minpos || e->globalPos().y() > maxpos) |
|
185 return; |
|
186 } else { |
|
187 int minpos = w->mapToGlobal(QPoint(0, 0)).x(); |
|
188 int maxpos = w->mapToGlobal(QPoint(0, 0)).x() + w->width(); |
|
189 if (e->globalPos().x() < minpos || e->globalPos().x() > maxpos) |
|
190 return; |
|
191 } |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 if (!dockWindow->opaqueMoving()) |
|
197 drawLine(lastPos); |
|
198 lastPos = e->globalPos(); |
|
199 if (dockWindow->opaqueMoving()) { |
|
200 mouseReleaseEvent(e); |
|
201 mousePressed = true; |
|
202 firstPos = e->globalPos(); |
|
203 } |
|
204 if (!dockWindow->opaqueMoving()) |
|
205 drawLine(e->globalPos()); |
|
206 } |
|
207 |
|
208 void Q3DockWindowResizeHandle::mouseReleaseEvent(QMouseEvent *e) |
|
209 { |
|
210 if (mousePressed) { |
|
211 if (!dockWindow->opaqueMoving()) { |
|
212 drawLine(lastPos); |
|
213 endLineDraw(); |
|
214 } |
|
215 if (orientation() != dockWindow->area()->orientation()) |
|
216 dockWindow->area()->invalidNextOffset(dockWindow); |
|
217 if (orientation() == Qt::Horizontal) { |
|
218 int dy; |
|
219 if (dockWindow->area()->handlePosition() == Q3DockArea::Normal || orientation() != dockWindow->area()->orientation()) |
|
220 dy = e->globalPos().y() - firstPos.y(); |
|
221 else |
|
222 dy = firstPos.y() - e->globalPos().y(); |
|
223 int d = dockWindow->height() + dy; |
|
224 if (orientation() != dockWindow->area()->orientation()) { |
|
225 dockWindow->setFixedExtentHeight(-1); |
|
226 d = qMax(d, dockWindow->minimumHeight()); |
|
227 int ms = dockWindow->area()->maxSpace(d, dockWindow); |
|
228 d = qMin(d, ms); |
|
229 dockWindow->setFixedExtentHeight(d); |
|
230 } else { |
|
231 dockWindow->area()->setFixedExtent(d, dockWindow); |
|
232 } |
|
233 } else { |
|
234 int dx; |
|
235 if (dockWindow->area()->handlePosition() == Q3DockArea::Normal || orientation() != dockWindow->area()->orientation()) |
|
236 dx = e->globalPos().x() - firstPos.x(); |
|
237 else |
|
238 dx = firstPos.x() - e->globalPos().x(); |
|
239 int d = dockWindow->width() + dx; |
|
240 if (orientation() != dockWindow->area()->orientation()) { |
|
241 dockWindow->setFixedExtentWidth(-1); |
|
242 d = qMax(d, dockWindow->minimumWidth()); |
|
243 int ms = dockWindow->area()->maxSpace(d, dockWindow); |
|
244 d = qMin(d, ms); |
|
245 dockWindow->setFixedExtentWidth(d); |
|
246 } else { |
|
247 dockWindow->area()->setFixedExtent(d, dockWindow); |
|
248 } |
|
249 } |
|
250 } |
|
251 |
|
252 QApplication::postEvent(dockWindow->area(), new QEvent(QEvent::LayoutHint)); |
|
253 mousePressed = false; |
|
254 } |
|
255 |
|
256 bool Q3DockWindowResizeHandle::event(QEvent *event) |
|
257 { |
|
258 switch (event->type()) { |
|
259 case QEvent::HoverEnter: |
|
260 if (!mouseOver) { |
|
261 mouseOver = true; |
|
262 update(); |
|
263 } |
|
264 break; |
|
265 case QEvent::HoverLeave: |
|
266 if (mouseOver) { |
|
267 mouseOver = false; |
|
268 update(); |
|
269 } |
|
270 break; |
|
271 default: |
|
272 break; |
|
273 } |
|
274 return QWidget::event(event); |
|
275 } |
|
276 |
|
277 void Q3DockWindowResizeHandle::paintEvent(QPaintEvent *) |
|
278 { |
|
279 QPainter p(this); |
|
280 QStyleOption opt(0); |
|
281 opt.init(this); |
|
282 if (orientation() == Qt::Horizontal) |
|
283 opt.state |= QStyle::State_Horizontal; |
|
284 style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, &p, this); |
|
285 } |
|
286 |
|
287 void Q3DockWindowResizeHandle::startLineDraw() |
|
288 { |
|
289 if (rubberBand) |
|
290 endLineDraw(); |
|
291 rubberBand = new QRubberBand(QRubberBand::Line); |
|
292 rubberBand->setGeometry(-1, -1, 1, 1); |
|
293 rubberBand->show(); |
|
294 } |
|
295 |
|
296 void Q3DockWindowResizeHandle::endLineDraw() |
|
297 { |
|
298 delete rubberBand; |
|
299 rubberBand = 0; |
|
300 } |
|
301 |
|
302 void Q3DockWindowResizeHandle::drawLine(const QPoint &globalPos) |
|
303 { |
|
304 QPoint start = mapToGlobal(QPoint(0, 0)); |
|
305 QPoint starta = dockWindow->area()->mapToGlobal(QPoint(0, 0)); |
|
306 QPoint end = globalPos; |
|
307 if (orientation() == Qt::Horizontal) { |
|
308 if (orientation() == dockWindow->orientation()) |
|
309 rubberBand->setGeometry(starta.x(), end.y(), dockWindow->area()->width(), height()); |
|
310 else |
|
311 rubberBand->setGeometry(start.x(), end.y(), width(), height()); |
|
312 } else { |
|
313 if (orientation() == dockWindow->orientation()) |
|
314 rubberBand->setGeometry(end.x(), starta.y(), width(), dockWindow->area()->height()); |
|
315 else |
|
316 rubberBand->setGeometry(end.x(), start.y(), width(), height()); |
|
317 } |
|
318 } |
|
319 |
|
320 static QPoint realWidgetPos(Q3DockWindow *w) |
|
321 { |
|
322 if (!w->parentWidget() || w->place() == Q3DockWindow::OutsideDock) |
|
323 return w->pos(); |
|
324 return w->parentWidget()->mapToGlobal(w->geometry().topLeft()); |
|
325 } |
|
326 |
|
327 class Q3DockWindowHandle : public QWidget |
|
328 { |
|
329 Q_OBJECT |
|
330 Q_PROPERTY(QString windowTitle READ windowTitle) |
|
331 friend class Q3DockWindow; |
|
332 friend class Q3DockWindowTitleBar; |
|
333 |
|
334 public: |
|
335 Q3DockWindowHandle(Q3DockWindow *dw); |
|
336 void updateGui(); |
|
337 |
|
338 QSize minimumSizeHint() const; |
|
339 QSize minimumSize() const { return minimumSizeHint(); } |
|
340 QSize sizeHint() const { return minimumSize(); } |
|
341 void setOpaqueMoving(bool b) { opaque = b; } |
|
342 |
|
343 QString windowTitle() const { return dockWindow->windowTitle(); } |
|
344 |
|
345 signals: |
|
346 void doubleClicked(); |
|
347 |
|
348 protected: |
|
349 void paintEvent(QPaintEvent *e); |
|
350 void resizeEvent(QResizeEvent *e); |
|
351 void mousePressEvent(QMouseEvent *e); |
|
352 void mouseMoveEvent(QMouseEvent *e); |
|
353 void mouseReleaseEvent(QMouseEvent *e); |
|
354 void mouseDoubleClickEvent(QMouseEvent *e); |
|
355 void keyPressEvent(QKeyEvent *e); |
|
356 void keyReleaseEvent(QKeyEvent *e); |
|
357 void changeEvent(QEvent *); |
|
358 |
|
359 private slots: |
|
360 void minimize(); |
|
361 |
|
362 private: |
|
363 Q3DockWindow *dockWindow; |
|
364 QPoint offset; |
|
365 QToolButton *closeButton; |
|
366 QTimer *timer; |
|
367 uint opaque : 1; |
|
368 uint mousePressed : 1; |
|
369 uint hadDblClick : 1; |
|
370 uint ctrlDown : 1; |
|
371 QPointer<QWidget> oldFocus; |
|
372 }; |
|
373 |
|
374 class Q3DockWindowTitleBar : public Q3TitleBar |
|
375 { |
|
376 Q_OBJECT |
|
377 friend class Q3DockWindow; |
|
378 friend class Q3DockWindowHandle; |
|
379 |
|
380 public: |
|
381 Q3DockWindowTitleBar(Q3DockWindow *dw); |
|
382 void updateGui(); |
|
383 void setOpaqueMoving(bool b) { opaque = b; } |
|
384 |
|
385 protected: |
|
386 void resizeEvent(QResizeEvent *e); |
|
387 void mousePressEvent(QMouseEvent *e); |
|
388 void mouseMoveEvent(QMouseEvent *e); |
|
389 void mouseReleaseEvent(QMouseEvent *e); |
|
390 void mouseDoubleClickEvent(QMouseEvent *e); |
|
391 void keyPressEvent(QKeyEvent *e); |
|
392 void keyReleaseEvent(QKeyEvent *e); |
|
393 |
|
394 private: |
|
395 Q3DockWindow *dockWindow; |
|
396 QPoint offset; |
|
397 uint mousePressed : 1; |
|
398 uint hadDblClick : 1; |
|
399 uint opaque : 1; |
|
400 uint ctrlDown : 1; |
|
401 QPointer<QWidget> oldFocus; |
|
402 |
|
403 }; |
|
404 |
|
405 Q3DockWindowHandle::Q3DockWindowHandle(Q3DockWindow *dw) |
|
406 : QWidget(dw, "qt_dockwidget_internal"), dockWindow(dw), |
|
407 closeButton(0), opaque(default_opaque), mousePressed(false) |
|
408 { |
|
409 ctrlDown = false; |
|
410 timer = new QTimer(this); |
|
411 connect(timer, SIGNAL(timeout()), this, SLOT(minimize())); |
|
412 #ifdef Q_WS_WIN |
|
413 setCursor(Qt::SizeAllCursor); |
|
414 #endif |
|
415 } |
|
416 |
|
417 void Q3DockWindowHandle::paintEvent(QPaintEvent *e) |
|
418 { |
|
419 if (!dockWindow->dockArea && !opaque) |
|
420 return; |
|
421 QPainter p(this); |
|
422 QStyleOptionQ3DockWindow opt; |
|
423 opt.init(this); |
|
424 if (!dockWindow->area() || dockWindow->area()->orientation() == Qt::Horizontal) |
|
425 opt.state |= QStyle::State_Horizontal; |
|
426 |
|
427 opt.rect = rect(); |
|
428 opt.docked = dockWindow->area(); |
|
429 opt.closeEnabled = dockWindow->isCloseEnabled(); |
|
430 opt.rect = QStyle::visualRect(opt.direction, opt.rect, |
|
431 style()->subElementRect(QStyle::SE_Q3DockWindowHandleRect, &opt, this)); |
|
432 style()->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this); |
|
433 QWidget::paintEvent(e); |
|
434 } |
|
435 |
|
436 void Q3DockWindowHandle::keyPressEvent(QKeyEvent *e) |
|
437 { |
|
438 if (!mousePressed) |
|
439 return; |
|
440 if (e->key() == Qt::Key_Control) { |
|
441 ctrlDown = true; |
|
442 dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque); |
|
443 } |
|
444 } |
|
445 |
|
446 void Q3DockWindowHandle::keyReleaseEvent(QKeyEvent *e) |
|
447 { |
|
448 if (!mousePressed) |
|
449 return; |
|
450 if (e->key() == Qt::Key_Control) { |
|
451 ctrlDown = false; |
|
452 dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque); |
|
453 } |
|
454 } |
|
455 |
|
456 void Q3DockWindowHandle::mousePressEvent(QMouseEvent *e) |
|
457 { |
|
458 if (!dockWindow->dockArea) |
|
459 return; |
|
460 ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton; |
|
461 oldFocus = qApp->focusWidget(); |
|
462 setFocus(); |
|
463 e->ignore(); |
|
464 if (e->button() != Qt::LeftButton) |
|
465 return; |
|
466 e->accept(); |
|
467 hadDblClick = false; |
|
468 mousePressed = true; |
|
469 offset = e->pos(); |
|
470 dockWindow->startRectDraw(mapToGlobal(e->pos()), !opaque); |
|
471 if (!opaque) |
|
472 qApp->installEventFilter(dockWindow); |
|
473 } |
|
474 |
|
475 void Q3DockWindowHandle::mouseMoveEvent(QMouseEvent *e) |
|
476 { |
|
477 if (!mousePressed || e->pos() == offset) |
|
478 return; |
|
479 ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton; |
|
480 dockWindow->handleMove(e->pos() - offset, e->globalPos(), !opaque); |
|
481 if (opaque) |
|
482 dockWindow->updatePosition(e->globalPos()); |
|
483 } |
|
484 |
|
485 void Q3DockWindowHandle::mouseReleaseEvent(QMouseEvent *e) |
|
486 { |
|
487 ctrlDown = false; |
|
488 qApp->removeEventFilter(dockWindow); |
|
489 if (oldFocus) |
|
490 oldFocus->setFocus(); |
|
491 if (!mousePressed) |
|
492 return; |
|
493 dockWindow->endRectDraw(!opaque); |
|
494 mousePressed = false; |
|
495 #ifdef Q_WS_MAC |
|
496 releaseMouse(); |
|
497 #endif |
|
498 if (!hadDblClick && offset == e->pos()) { |
|
499 timer->start(QApplication::doubleClickInterval(), true); |
|
500 } else if (!hadDblClick) { |
|
501 dockWindow->updatePosition(e->globalPos()); |
|
502 } |
|
503 if (opaque) |
|
504 dockWindow->titleBar->mousePressed = false; |
|
505 if (dockWindow->parentWidget()) |
|
506 QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint)); |
|
507 } |
|
508 |
|
509 void Q3DockWindowHandle::minimize() |
|
510 { |
|
511 if (!dockWindow->area()) |
|
512 return; |
|
513 |
|
514 Q3MainWindow *mw = qobject_cast<Q3MainWindow*>(dockWindow->area()->parentWidget()); |
|
515 if (mw && mw->isDockEnabled(dockWindow, Qt::DockMinimized)) |
|
516 mw->moveDockWindow(dockWindow, Qt::DockMinimized); |
|
517 } |
|
518 |
|
519 void Q3DockWindowHandle::resizeEvent(QResizeEvent *) |
|
520 { |
|
521 updateGui(); |
|
522 } |
|
523 |
|
524 void Q3DockWindowHandle::updateGui() |
|
525 { |
|
526 updateGeometry(); |
|
527 |
|
528 if (!closeButton) { |
|
529 closeButton = new QToolButton(this, "qt_close_button1"); |
|
530 #ifndef QT_NO_CURSOR |
|
531 closeButton->setCursor(Qt::ArrowCursor); |
|
532 #endif |
|
533 QStyleOption opt(0); |
|
534 opt.init(closeButton); |
|
535 closeButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton, &opt, |
|
536 closeButton)); |
|
537 closeButton->setFixedSize(12, 12); |
|
538 connect(closeButton, SIGNAL(clicked()), |
|
539 dockWindow, SLOT(hide())); |
|
540 } |
|
541 |
|
542 if (dockWindow->isCloseEnabled() && dockWindow->area()) |
|
543 closeButton->show(); |
|
544 else |
|
545 closeButton->hide(); |
|
546 |
|
547 if (!dockWindow->area()) |
|
548 return; |
|
549 |
|
550 if (dockWindow->area()->orientation() == Qt::Horizontal) { |
|
551 int off = (width() - closeButton->width() - 1) / 2; |
|
552 closeButton->move(off, 2); |
|
553 } else { |
|
554 int off = (height() - closeButton->height() - 1) / 2; |
|
555 int x = QApplication::reverseLayout() ? 2 : width() - closeButton->width() - 2; |
|
556 closeButton->move(x, off); |
|
557 } |
|
558 } |
|
559 |
|
560 void Q3DockWindowHandle::changeEvent(QEvent *ev) |
|
561 { |
|
562 if(ev->type() == QEvent::StyleChange) { |
|
563 if (closeButton) { |
|
564 QStyleOption opt(0); |
|
565 opt.init(closeButton); |
|
566 closeButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton, |
|
567 &opt, closeButton)); |
|
568 } |
|
569 } |
|
570 QWidget::changeEvent(ev); |
|
571 } |
|
572 |
|
573 QSize Q3DockWindowHandle::minimumSizeHint() const |
|
574 { |
|
575 if (!dockWindow->dockArea) |
|
576 return QSize(0, 0); |
|
577 int wh = dockWindow->isCloseEnabled() ? 17 : style()->pixelMetric(QStyle::PM_ToolBarHandleExtent, 0, this); |
|
578 if (dockWindow->orientation() == Qt::Horizontal) |
|
579 return QSize(wh, 0); |
|
580 return QSize(0, wh); |
|
581 } |
|
582 |
|
583 void Q3DockWindowHandle::mouseDoubleClickEvent(QMouseEvent *e) |
|
584 { |
|
585 e->ignore(); |
|
586 if (e->button() != Qt::LeftButton) |
|
587 return; |
|
588 e->accept(); |
|
589 timer->stop(); |
|
590 emit doubleClicked(); |
|
591 hadDblClick = true; |
|
592 if (dockWindow->parentWidget()) |
|
593 QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint)); |
|
594 } |
|
595 |
|
596 Q3DockWindowTitleBar::Q3DockWindowTitleBar(Q3DockWindow *dw) |
|
597 : Q3TitleBar(0, dw), dockWindow(dw), |
|
598 mousePressed(false), hadDblClick(false), opaque(default_opaque) |
|
599 { |
|
600 setObjectName(QLatin1String("qt_dockwidget_internal")); |
|
601 ctrlDown = false; |
|
602 setMouseTracking(true); |
|
603 QStyleOptionTitleBar opt = getStyleOption(); |
|
604 setFixedHeight(style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt, this)); |
|
605 connect(this, SIGNAL(doClose()), dockWindow, SLOT(hide())); |
|
606 } |
|
607 |
|
608 void Q3DockWindowTitleBar::keyPressEvent(QKeyEvent *e) |
|
609 { |
|
610 if (!mousePressed) |
|
611 return; |
|
612 if (e->key() == Qt::Key_Control) { |
|
613 ctrlDown = true; |
|
614 dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque); |
|
615 } |
|
616 } |
|
617 |
|
618 void Q3DockWindowTitleBar::keyReleaseEvent(QKeyEvent *e) |
|
619 { |
|
620 if (!mousePressed) |
|
621 return; |
|
622 if (e->key() == Qt::Key_Control) { |
|
623 ctrlDown = false; |
|
624 dockWindow->handleMove(mapFromGlobal(QCursor::pos()) - offset, QCursor::pos(), !opaque); |
|
625 } |
|
626 } |
|
627 |
|
628 void Q3DockWindowTitleBar::mousePressEvent(QMouseEvent *e) |
|
629 { |
|
630 QStyleOptionTitleBar opt; |
|
631 opt.init(this); |
|
632 opt.subControls = QStyle::SC_All; |
|
633 opt.activeSubControls = QStyle::SC_None; |
|
634 opt.text = windowTitle(); |
|
635 //################ |
|
636 QIcon icon = windowIcon(); |
|
637 QSize s = icon.actualSize(QSize(64, 64)); |
|
638 opt.icon = icon.pixmap(s); |
|
639 opt.titleBarState = window() ? window()->windowState() : static_cast<Qt::WindowStates>(Qt::WindowNoState); |
|
640 opt.titleBarFlags = fakeWindowFlags(); |
|
641 QStyle::SubControl tbctrl = style()->hitTestComplexControl(QStyle::CC_TitleBar, &opt, |
|
642 e->pos(), this); |
|
643 |
|
644 if (tbctrl < QStyle::SC_TitleBarLabel && tbctrl != QStyle::SC_None) { |
|
645 Q3TitleBar::mousePressEvent(e); |
|
646 return; |
|
647 } |
|
648 |
|
649 ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton; |
|
650 oldFocus = qApp->focusWidget(); |
|
651 // setFocus activates the window, which deactivates the main window |
|
652 // not what we want, and not required anyway on Windows |
|
653 #ifndef Q_WS_WIN |
|
654 setFocus(); |
|
655 #endif |
|
656 |
|
657 e->ignore(); |
|
658 if (e->button() != Qt::LeftButton) |
|
659 return; |
|
660 if (e->y() < 3 && dockWindow->isResizeEnabled()) |
|
661 return; |
|
662 |
|
663 e->accept(); |
|
664 bool oldPressed = mousePressed; |
|
665 mousePressed = true; |
|
666 hadDblClick = false; |
|
667 offset = e->pos(); |
|
668 dockWindow->startRectDraw(mapToGlobal(e->pos()), !opaque); |
|
669 // grabMouse resets the Windows mouse press count, so we never receive a double click on Windows |
|
670 // not required on Windows, and did work on X11, too, but no problem there in the first place |
|
671 #ifndef Q_WS_WIN |
|
672 if(!oldPressed && dockWindow->opaqueMoving()) |
|
673 grabMouse(); |
|
674 #else |
|
675 Q_UNUSED(oldPressed); |
|
676 #endif |
|
677 } |
|
678 |
|
679 void Q3DockWindowTitleBar::mouseMoveEvent(QMouseEvent *e) |
|
680 { |
|
681 if (!mousePressed) { |
|
682 Q3TitleBar::mouseMoveEvent(e); |
|
683 return; |
|
684 } |
|
685 |
|
686 ctrlDown = (e->state() & Qt::ControlButton) == Qt::ControlButton; |
|
687 e->accept(); |
|
688 dockWindow->handleMove(e->pos() - offset, e->globalPos(), !opaque); |
|
689 } |
|
690 |
|
691 void Q3DockWindowTitleBar::mouseReleaseEvent(QMouseEvent *e) |
|
692 { |
|
693 if (!mousePressed) { |
|
694 Q3TitleBar::mouseReleaseEvent(e); |
|
695 return; |
|
696 } |
|
697 |
|
698 ctrlDown = false; |
|
699 qApp->removeEventFilter(dockWindow); |
|
700 if (oldFocus) |
|
701 oldFocus->setFocus(); |
|
702 |
|
703 if (dockWindow->place() == Q3DockWindow::OutsideDock) |
|
704 dockWindow->raise(); |
|
705 |
|
706 if(dockWindow->opaqueMoving()) |
|
707 releaseMouse(); |
|
708 if (!mousePressed) |
|
709 return; |
|
710 dockWindow->endRectDraw(!opaque); |
|
711 mousePressed = false; |
|
712 if (!hadDblClick) |
|
713 dockWindow->updatePosition(e->globalPos()); |
|
714 if (opaque) { |
|
715 dockWindow->horHandle->mousePressed = false; |
|
716 dockWindow->verHandle->mousePressed = false; |
|
717 } |
|
718 if (dockWindow->parentWidget()) |
|
719 QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint)); |
|
720 } |
|
721 |
|
722 void Q3DockWindowTitleBar::resizeEvent(QResizeEvent *e) |
|
723 { |
|
724 updateGui(); |
|
725 Q3TitleBar::resizeEvent(e); |
|
726 } |
|
727 |
|
728 void Q3DockWindowTitleBar::updateGui() |
|
729 { |
|
730 if (dockWindow->isCloseEnabled()) { |
|
731 setFakeWindowFlags(fakeWindowFlags() | Qt::WStyle_SysMenu); |
|
732 } else { |
|
733 setFakeWindowFlags(fakeWindowFlags() & ~Qt::WStyle_SysMenu); |
|
734 } |
|
735 } |
|
736 |
|
737 void Q3DockWindowTitleBar::mouseDoubleClickEvent(QMouseEvent *) |
|
738 { |
|
739 emit doubleClicked(); |
|
740 hadDblClick = true; |
|
741 if (dockWindow->parentWidget()) |
|
742 QApplication::postEvent(dockWindow->parentWidget(), new QEvent(QEvent::LayoutHint)); |
|
743 } |
|
744 |
|
745 /*! |
|
746 \class Q3DockWindow |
|
747 \brief The Q3DockWindow class provides a widget which can be docked |
|
748 inside a Q3DockArea or floated as a top level window on the |
|
749 desktop. |
|
750 |
|
751 \compat |
|
752 |
|
753 This class handles moving, resizing, docking and undocking dock |
|
754 windows. Q3ToolBar is a subclass of Q3DockWindow so the |
|
755 functionality provided for dock windows is available with the same |
|
756 API for toolbars. |
|
757 |
|
758 \img qmainwindow-qdockareas.png Q3DockWindows in a Q3DockArea |
|
759 \caption Two Q3DockWindows (\l{Q3ToolBar}s) in a \l Q3DockArea |
|
760 |
|
761 \img qdockwindow.png A Q3DockWindow |
|
762 \caption A Floating Q3DockWindow |
|
763 |
|
764 If the user drags the dock window into the dock area the dock |
|
765 window will be docked. If the user drags the dock area outside any |
|
766 dock areas the dock window will be undocked (floated) and will |
|
767 become a top level window. Double clicking a floating dock |
|
768 window's title bar will dock the dock window to the last dock area |
|
769 it was docked in. Double clicking a docked dock window's handle |
|
770 will undock (float) the dock window. |
|
771 \omit |
|
772 Single clicking a docked dock window's handle will minimize the |
|
773 dock window (only its handle will appear, below the menu bar). |
|
774 Single clicking the minimized handle will restore the dock window |
|
775 to the last dock area that it was docked in. |
|
776 \endomit |
|
777 If the user clicks the close button (which appears on floating |
|
778 dock windows by default) the dock window will disappear. You can |
|
779 control whether or not a dock window has a close button with |
|
780 setCloseMode(). |
|
781 |
|
782 Q3MainWindow provides four dock areas (top, left, right and bottom) |
|
783 which can be used by dock windows. For many applications using the |
|
784 dock areas provided by Q3MainWindow is sufficient. (See the \l |
|
785 Q3DockArea documentation if you want to create your own dock |
|
786 areas.) In Q3MainWindow a right-click popup menu (the dock window |
|
787 menu) is available which lists dock windows and can be used to |
|
788 show or hide them. (The popup menu only lists dock windows that |
|
789 have a \link QWidget::setWindowTitle() caption\endlink.) |
|
790 |
|
791 When you construct a dock window you \e must pass it a Q3DockArea |
|
792 or a Q3MainWindow as its parent if you want it docked. Pass 0 for |
|
793 the parent if you want it floated. |
|
794 |
|
795 \snippet doc/src/snippets/code/src_qt3support_widgets_q3dockwindow.cpp 0 |
|
796 |
|
797 In the example above we create a new Q3ToolBar in the constructor |
|
798 of a Q3MainWindow subclass (so that the \e this pointer points to |
|
799 the Q3MainWindow). By default the toolbar will be added to the \c |
|
800 Top dock area, but we've moved it to the \c Left dock area. |
|
801 |
|
802 A dock window is often used to contain a single widget. In these |
|
803 cases the widget can be set by calling setWidget(). If you're |
|
804 constructing a dock window that contains multiple widgets, e.g. a |
|
805 toolbar, arrange the widgets within a box layout inside the dock |
|
806 window. To do this use the boxLayout() function to get a pointer |
|
807 to the dock window's box layout, then add widgets to the layout |
|
808 using the box layout's QBoxLayout::addWidget() function. The dock |
|
809 window will dynamically set the orientation of the layout to be |
|
810 vertical or horizontal as necessary, although you can control this |
|
811 yourself with setOrientation(). |
|
812 |
|
813 Although a common use of dock windows is for toolbars, they can be |
|
814 used with any widgets. When using larger |
|
815 widgets it may make sense for the dock window to be resizable by |
|
816 calling setResizeEnabled(). Resizable dock windows are given |
|
817 splitter-like handles to allow the user to resize them within |
|
818 their dock area. When resizable dock windows are undocked they |
|
819 become top level windows and can be resized like any other top |
|
820 level windows, e.g. by dragging a corner or edge. |
|
821 |
|
822 Qt::Dock windows can be docked and undocked using dock() and undock(). |
|
823 A dock window's orientation can be set with setOrientation(). You |
|
824 can also use Q3DockArea::moveDockWindow(). If you're using a |
|
825 Q3MainWindow, Q3MainWindow::moveDockWindow() and |
|
826 Q3MainWindow::removeDockWindow() are available. |
|
827 |
|
828 A dock window can have some preferred settings, for example, you |
|
829 can set a preferred offset from the left edge (or top edge for |
|
830 vertical dock areas) of the dock area using setOffset(). If you'd |
|
831 prefer a dock window to start on a new line when it is docked use |
|
832 setNewLine(). The setFixedExtentWidth() and setFixedExtentHeight() |
|
833 functions can be used to define the dock window's preferred size, |
|
834 and the setHorizontallyStretchable() and setVerticallyStretchable() |
|
835 functions set whether the dock window can be stretched or not. |
|
836 Dock windows can be moved by default, but this can be changed with |
|
837 setMovingEnabled(). When a dock window is moved it is shown as a |
|
838 rectangular outline, but it can be shown normally using |
|
839 setOpaqueMoving(). |
|
840 |
|
841 When a dock window's visibility changes, i.e. it is shown or |
|
842 hidden, the visibilityChanged() signal is emitted. When a dock |
|
843 window is docked, undocked or moved inside the dock area the |
|
844 placeChanged() signal is emitted. |
|
845 */ |
|
846 |
|
847 /*! |
|
848 \enum Q3DockWindow::Place |
|
849 |
|
850 This enum specifies the possible locations for a Q3DockWindow: |
|
851 |
|
852 \value InDock Inside a Q3DockArea. |
|
853 \value OutsideDock Floating as a top level window on the desktop. |
|
854 */ |
|
855 |
|
856 /*! |
|
857 \enum Q3DockWindow::CloseMode |
|
858 |
|
859 This enum type specifies when (if ever) a dock window has a close |
|
860 button. |
|
861 |
|
862 \value Never The dock window never has a close button and cannot |
|
863 be closed by the user. |
|
864 \value Docked The dock window has a close button only when |
|
865 docked. |
|
866 \value Undocked The dock window has a close button only when |
|
867 floating. |
|
868 \value Always The dock window always has a close button. |
|
869 \omit |
|
870 Note that dock windows can always be minimized if the user clicks |
|
871 their dock window handle when they are docked. |
|
872 \endomit |
|
873 */ |
|
874 |
|
875 /*! |
|
876 \fn void Q3DockWindow::setHorizontalStretchable(bool b) |
|
877 |
|
878 If \a b is true the dock window is set to be horizontally |
|
879 stretchable. |
|
880 */ |
|
881 /*! |
|
882 \fn void Q3DockWindow::setVerticalStretchable(bool b) |
|
883 |
|
884 If \a b is true the dock window is set to be vertically |
|
885 stretchable. |
|
886 */ |
|
887 /*! |
|
888 \fn bool Q3DockWindow::isHorizontalStretchable() const |
|
889 |
|
890 Returns true if the dock window can be stretched horizontally; |
|
891 otherwise returns false. |
|
892 */ |
|
893 /*! |
|
894 \fn bool Q3DockWindow::isVerticalStretchable() const |
|
895 |
|
896 Returns true if the dock window can be stretched vertically; |
|
897 otherwise returns false. |
|
898 */ |
|
899 /*! |
|
900 \fn void Q3DockWindow::orientationChanged(Qt::Orientation o) |
|
901 |
|
902 This signal is emitted when the orientation of the dock window is |
|
903 changed. The new orientation is \a o. |
|
904 */ |
|
905 |
|
906 /*! |
|
907 \fn void Q3DockWindow::placeChanged(Q3DockWindow::Place p) |
|
908 |
|
909 This signal is emitted when the dock window is docked (\a p is \c |
|
910 InDock), undocked (\a p is \c OutsideDock) or moved inside the |
|
911 the dock area. |
|
912 |
|
913 \sa Q3DockArea::moveDockWindow(), Q3DockArea::removeDockWindow(), |
|
914 Q3MainWindow::moveDockWindow(), Q3MainWindow::removeDockWindow() |
|
915 */ |
|
916 |
|
917 /*! |
|
918 \fn void Q3DockWindow::visibilityChanged(bool visible) |
|
919 |
|
920 This signal is emitted when the visibility of the dock window |
|
921 relatively to its dock area is changed. If \a visible is true, the |
|
922 Q3DockWindow is now visible to the dock area, otherwise it has been |
|
923 hidden. |
|
924 |
|
925 A dock window can be hidden if it has a close button which the |
|
926 user has clicked. In the case of a Q3MainWindow a dock window can |
|
927 have its visibility changed (hidden or shown) by clicking its name |
|
928 in the dock window menu that lists the Q3MainWindow's dock windows. |
|
929 */ |
|
930 |
|
931 /*! |
|
932 \fn Q3DockArea *Q3DockWindow::area() const |
|
933 |
|
934 Returns the dock area in which this dock window is docked, or 0 if |
|
935 the dock window is floating. |
|
936 */ |
|
937 |
|
938 /*! |
|
939 \property Q3DockWindow::place |
|
940 \brief the location where the dock window is placed |
|
941 |
|
942 This is either \c InDock or \c OutsideDock. |
|
943 |
|
944 \sa Q3DockArea::moveDockWindow(), Q3DockArea::removeDockWindow(), |
|
945 Q3MainWindow::moveDockWindow(), Q3MainWindow::removeDockWindow() |
|
946 */ |
|
947 |
|
948 /*! |
|
949 Constructs a Q3DockWindow with parent \a parent, called \a name and |
|
950 with widget flags \a f. |
|
951 */ |
|
952 |
|
953 Q3DockWindow::Q3DockWindow(QWidget* parent, const char* name, Qt::WindowFlags f) |
|
954 : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder) |
|
955 { |
|
956 curPlace = InDock; |
|
957 isToolbar = false; |
|
958 init(); |
|
959 } |
|
960 |
|
961 /*! |
|
962 Constructs a Q3DockWindow with parent \a parent, called \a name and |
|
963 with widget flags \a f. |
|
964 |
|
965 If \a p is \c InDock, the dock window is docked into a dock area |
|
966 and \a parent \e must be a Q3DockArea or a Q3MainWindow. If the \a |
|
967 parent is a Q3MainWindow the dock window will be docked in the main |
|
968 window's \c Top dock area. |
|
969 |
|
970 If \a p is \c OutsideDock, the dock window is created as a floating |
|
971 window. |
|
972 |
|
973 We recommend creating the dock area \c InDock with a Q3MainWindow |
|
974 as parent then calling Q3MainWindow::moveDockWindow() to move the |
|
975 dock window where you want it. |
|
976 */ |
|
977 |
|
978 Q3DockWindow::Q3DockWindow(Place p, QWidget *parent, const char *name, Qt::WindowFlags f) |
|
979 : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder) |
|
980 { |
|
981 curPlace = p; |
|
982 isToolbar = false; |
|
983 init(); |
|
984 } |
|
985 |
|
986 /*! \internal |
|
987 */ |
|
988 |
|
989 Q3DockWindow::Q3DockWindow(Place p, QWidget *parent, const char *name, Qt::WindowFlags f, bool toolbar) |
|
990 : Q3Frame(parent, name, f | Qt::WType_Dialog | Qt::WStyle_Customize | Qt::WStyle_NoBorder) |
|
991 { |
|
992 curPlace = p; |
|
993 isToolbar = toolbar; |
|
994 init(); |
|
995 } |
|
996 |
|
997 class Q3DockWindowGridLayout : public QGridLayout |
|
998 { |
|
999 public: |
|
1000 Q3DockWindowGridLayout(QWidget *parent, int nRows, int nCols) |
|
1001 : QGridLayout(parent, nRows, nCols) {}; |
|
1002 |
|
1003 Qt::Orientations expandingDirections() const |
|
1004 { |
|
1005 return 0; |
|
1006 } |
|
1007 }; |
|
1008 |
|
1009 void Q3DockWindow::init() |
|
1010 { |
|
1011 wid = 0; |
|
1012 rubberBand = 0; |
|
1013 dockArea = 0; |
|
1014 tmpDockArea = 0; |
|
1015 resizeEnabled = false; |
|
1016 moveEnabled = true; |
|
1017 nl = false; |
|
1018 opaque = default_opaque; |
|
1019 cMode = Never; |
|
1020 offs = 0; |
|
1021 fExtent = QSize(-1, -1); |
|
1022 dockWindowData = 0; |
|
1023 lastPos = QPoint(-1, -1); |
|
1024 lastSize = QSize(-1, -1); |
|
1025 stretchable[Qt::Horizontal] = false; |
|
1026 stretchable[Qt::Vertical] = false; |
|
1027 |
|
1028 widgetResizeHandler = new QWidgetResizeHandler(this); |
|
1029 widgetResizeHandler->setMovingEnabled(false); |
|
1030 |
|
1031 titleBar = new Q3DockWindowTitleBar(this); |
|
1032 verHandle = new Q3DockWindowHandle(this); |
|
1033 verHandle->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred)); |
|
1034 horHandle = new Q3DockWindowHandle(this); |
|
1035 horHandle->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); |
|
1036 |
|
1037 vHandleLeft = new Q3DockWindowResizeHandle(Qt::Vertical, this, this, "vert. handle"); |
|
1038 vHandleRight = new Q3DockWindowResizeHandle(Qt::Vertical, this, this, "vert. handle"); |
|
1039 hHandleTop = new Q3DockWindowResizeHandle(Qt::Horizontal, this, this, "horz. handle"); |
|
1040 hHandleBottom = new Q3DockWindowResizeHandle(Qt::Horizontal, this, this, "horz. handle"); |
|
1041 |
|
1042 // Creating inner layout |
|
1043 hbox = new QVBoxLayout(); |
|
1044 vbox = new QHBoxLayout(); |
|
1045 childBox = new QBoxLayout(QBoxLayout::LeftToRight); |
|
1046 vbox->addSpacing(2); |
|
1047 vbox->addWidget(verHandle); |
|
1048 vbox->addStretch(0); |
|
1049 vbox->addLayout(childBox, 1); |
|
1050 vbox->addStretch(0); |
|
1051 |
|
1052 hbox->setResizeMode(QLayout::FreeResize); |
|
1053 hbox->setMargin(isResizeEnabled() || curPlace == OutsideDock ? 2 : 0); |
|
1054 hbox->setSpacing(1); |
|
1055 hbox->addWidget(titleBar); |
|
1056 hbox->addWidget(horHandle); |
|
1057 hbox->addLayout(vbox); |
|
1058 |
|
1059 // Set up the initial handle layout for Qt::Vertical |
|
1060 // Handle layout will change on calls to setOrienation() |
|
1061 QGridLayout *glayout = new Q3DockWindowGridLayout(this, 3, 3); |
|
1062 glayout->setResizeMode(QLayout::Minimum); |
|
1063 glayout->addMultiCellWidget(hHandleTop, 0, 0, 1, 1); |
|
1064 glayout->addMultiCellWidget(hHandleBottom, 2, 2, 1, 1); |
|
1065 glayout->addMultiCellWidget(vHandleLeft, 0, 2, 0, 0); |
|
1066 glayout->addMultiCellWidget(vHandleRight, 0, 2, 2, 2); |
|
1067 glayout->addLayout(hbox, 1, 1); |
|
1068 glayout->setRowStretch(1, 1); |
|
1069 glayout->setColStretch(1, 1); |
|
1070 |
|
1071 hHandleBottom->hide(); |
|
1072 vHandleRight->hide(); |
|
1073 hHandleTop->hide(); |
|
1074 vHandleLeft->hide(); |
|
1075 setFrameStyle(Q3Frame::StyledPanel | Q3Frame::Raised); |
|
1076 setLineWidth(2); |
|
1077 |
|
1078 if (parentWidget()) |
|
1079 parentWidget()->installEventFilter(this); |
|
1080 QWidget *mw = parentWidget(); |
|
1081 Q3DockArea *da = qobject_cast<Q3DockArea*>(parentWidget()); |
|
1082 if (da) { |
|
1083 if (curPlace == InDock) |
|
1084 da->moveDockWindow(this); |
|
1085 mw = da->parentWidget(); |
|
1086 } |
|
1087 if (qobject_cast<Q3MainWindow*>(mw)) { |
|
1088 if (place() == InDock) { |
|
1089 Qt::Dock myDock = Qt::DockTop; |
|
1090 // make sure we put the window in the correct dock. |
|
1091 if (dockArea) { |
|
1092 Q3MainWindow *mainw = (Q3MainWindow*)mw; |
|
1093 // I'm not checking if it matches the top because I've |
|
1094 // done the assignment to it above. |
|
1095 if (dockArea == mainw->leftDock()) |
|
1096 myDock = Qt::DockLeft; |
|
1097 else if (dockArea == mainw->rightDock()) |
|
1098 myDock = Qt::DockRight; |
|
1099 else if (dockArea == mainw->bottomDock()) |
|
1100 myDock = Qt::DockBottom; |
|
1101 } |
|
1102 ((Q3MainWindow*)mw)->addDockWindow(this, myDock); |
|
1103 } |
|
1104 moveEnabled = ((Q3MainWindow*)mw)->dockWindowsMovable(); |
|
1105 opaque = ((Q3MainWindow*)mw)->opaqueMoving(); |
|
1106 } |
|
1107 |
|
1108 updateGui(); |
|
1109 |
|
1110 connect(titleBar, SIGNAL(doubleClicked()), this, SLOT(dock())); |
|
1111 connect(verHandle, SIGNAL(doubleClicked()), this, SLOT(undock())); |
|
1112 connect(horHandle, SIGNAL(doubleClicked()), this, SLOT(undock())); |
|
1113 connect(this, SIGNAL(orientationChanged(Qt::Orientation)), |
|
1114 this, SLOT(setOrientation(Qt::Orientation))); |
|
1115 } |
|
1116 |
|
1117 /*! |
|
1118 Sets the orientation of the dock window to \a o. The orientation |
|
1119 is propagated to the layout boxLayout(). |
|
1120 |
|
1121 \warning All undocked Q3ToolBars will always have a horizontal orientation. |
|
1122 */ |
|
1123 |
|
1124 void Q3DockWindow::setOrientation(Qt::Orientation o) |
|
1125 { |
|
1126 QGridLayout *glayout = (QGridLayout*)layout(); |
|
1127 glayout->removeWidget(hHandleTop); |
|
1128 glayout->removeWidget(hHandleBottom); |
|
1129 glayout->removeWidget(vHandleLeft); |
|
1130 glayout->removeWidget(vHandleRight); |
|
1131 |
|
1132 if (o == Qt::Horizontal) { |
|
1133 // Set up the new layout as |
|
1134 // 3 3 3 1 = vHandleLeft 4 = hHandleBottom |
|
1135 // 1 X 2 2 = vHandleRight X = Inner Layout |
|
1136 // 4 4 4 3 = hHandleTop |
|
1137 glayout->addMultiCellWidget(hHandleTop, 0, 0, 0, 2); |
|
1138 glayout->addMultiCellWidget(hHandleBottom, 2, 2, 0, 2); |
|
1139 glayout->addMultiCellWidget(vHandleLeft, 1, 1, 0, 0); |
|
1140 glayout->addMultiCellWidget(vHandleRight, 1, 1, 2, 2); |
|
1141 } else { |
|
1142 // Set up the new layout as |
|
1143 // 1 3 2 1 = vHandleLeft 4 = hHandleBottom |
|
1144 // 1 X 2 2 = vHandleRight X = Inner Layout |
|
1145 // 1 4 2 3 = hHandleTop |
|
1146 glayout->addMultiCellWidget(hHandleTop, 0, 0, 1, 1); |
|
1147 glayout->addMultiCellWidget(hHandleBottom, 2, 2, 1, 1); |
|
1148 glayout->addMultiCellWidget(vHandleLeft, 0, 2, 0, 0); |
|
1149 glayout->addMultiCellWidget(vHandleRight, 0, 2, 2, 2); |
|
1150 } |
|
1151 boxLayout()->setDirection(o == Qt::Horizontal ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom); |
|
1152 QApplication::sendPostedEvents(this, QEvent::LayoutHint); |
|
1153 QEvent *e = new QEvent(QEvent::LayoutHint); |
|
1154 QApplication::postEvent(this, e); |
|
1155 } |
|
1156 |
|
1157 /*! |
|
1158 Destroys the dock window and its child widgets. |
|
1159 */ |
|
1160 |
|
1161 Q3DockWindow::~Q3DockWindow() |
|
1162 { |
|
1163 qApp->removeEventFilter(this); |
|
1164 if (area()) |
|
1165 area()->removeDockWindow(this, false, false); |
|
1166 Q3DockArea *a = area(); |
|
1167 if (!a && dockWindowData) |
|
1168 a = ((Q3DockArea::DockWindowData*)dockWindowData)->area; |
|
1169 Q3MainWindow *mw = a ? qobject_cast<Q3MainWindow*>(a->parentWidget()) : 0; |
|
1170 if (mw) |
|
1171 mw->removeDockWindow(this); |
|
1172 |
|
1173 delete (Q3DockArea::DockWindowData*)dockWindowData; |
|
1174 } |
|
1175 |
|
1176 /*! \reimp |
|
1177 */ |
|
1178 |
|
1179 void Q3DockWindow::resizeEvent(QResizeEvent *e) |
|
1180 { |
|
1181 Q3Frame::resizeEvent(e); |
|
1182 updateGui(); |
|
1183 } |
|
1184 |
|
1185 |
|
1186 void Q3DockWindow::swapRect(QRect &r, Qt::Orientation o, const QPoint &offset, Q3DockArea *) |
|
1187 { |
|
1188 r.setSize(QSize(r.height(), r.width())); |
|
1189 bool reverse = QApplication::reverseLayout(); |
|
1190 if (o == Qt::Horizontal) |
|
1191 r.moveBy(-r.width()/2, 0); |
|
1192 else |
|
1193 r.moveBy(reverse ? - r.width() : 0, -r.height() / 2 ); |
|
1194 r.moveBy(offset.x(), offset.y()); |
|
1195 } |
|
1196 |
|
1197 QWidget *Q3DockWindow::areaAt(const QPoint &gp) |
|
1198 { |
|
1199 QWidget *w = qApp->widgetAt(gp); |
|
1200 |
|
1201 if (w && (w == this || w == titleBar) && parentWidget()) |
|
1202 w = parentWidget()->childAt(parentWidget()->mapFromGlobal(gp)); |
|
1203 |
|
1204 while (w) { |
|
1205 if (qobject_cast<Q3DockArea*>(w)) { |
|
1206 Q3DockArea *a = (Q3DockArea*)w; |
|
1207 if (a->isDockWindowAccepted(this)) |
|
1208 return w; |
|
1209 } |
|
1210 if (qobject_cast<Q3MainWindow*>(w)) { |
|
1211 Q3MainWindow *mw = (Q3MainWindow*)w; |
|
1212 Q3DockArea *a = mw->dockingArea(mw->mapFromGlobal(gp)); |
|
1213 if (a && a->isDockWindowAccepted(this)) |
|
1214 return a; |
|
1215 } |
|
1216 w = w->isWindow() ? 0 : (QWidget *)w->parent(); |
|
1217 } |
|
1218 return 0; |
|
1219 } |
|
1220 |
|
1221 void Q3DockWindow::handleMove(const QPoint &pos, const QPoint &gp, bool drawRect) |
|
1222 { |
|
1223 if (!rubberBand) |
|
1224 return; |
|
1225 |
|
1226 currRect = QRect(realWidgetPos(this), size()); |
|
1227 QWidget *w = areaAt(gp); |
|
1228 if (titleBar->ctrlDown || horHandle->ctrlDown || verHandle->ctrlDown) |
|
1229 w = 0; |
|
1230 currRect.moveBy(pos.x(), pos.y()); |
|
1231 if (!qobject_cast<Q3DockArea*>(w)) { |
|
1232 if (startOrientation != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this)) |
|
1233 swapRect(currRect, Qt::Horizontal, startOffset, (Q3DockArea*)w); |
|
1234 if (drawRect) { |
|
1235 rubberBand->setGeometry(currRect); |
|
1236 } else { |
|
1237 QPoint mp(mapToGlobal(pos)); |
|
1238 if(place() == InDock) { |
|
1239 undock(); |
|
1240 if(titleBar) { |
|
1241 mp = QPoint(titleBar->width() / 2, titleBar->height() / 2); |
|
1242 QMouseEvent me(QEvent::MouseButtonPress, mp, Qt::LeftButton, 0); |
|
1243 QApplication::sendEvent(titleBar, &me); |
|
1244 mp = titleBar->mapToGlobal(mp); |
|
1245 } |
|
1246 } |
|
1247 move(mp); |
|
1248 } |
|
1249 state = OutsideDock; |
|
1250 return; |
|
1251 } |
|
1252 |
|
1253 Q3DockArea *area = (Q3DockArea*)w; |
|
1254 if(area->isVisible()) { |
|
1255 state = InDock; |
|
1256 Qt::Orientation o = (area ? area->orientation() : |
|
1257 (boxLayout()->direction() == QBoxLayout::LeftToRight || |
|
1258 boxLayout()->direction() == QBoxLayout::RightToLeft ? |
|
1259 Qt::Horizontal : Qt::Vertical)); |
|
1260 if (startOrientation != o) |
|
1261 swapRect(currRect, o, startOffset, area); |
|
1262 if (drawRect) { |
|
1263 rubberBand->setGeometry(currRect); |
|
1264 } |
|
1265 tmpDockArea = area; |
|
1266 } |
|
1267 } |
|
1268 |
|
1269 void Q3DockWindow::updateGui() |
|
1270 { |
|
1271 if (curPlace == OutsideDock) { |
|
1272 hbox->setMargin(2); |
|
1273 horHandle->hide(); |
|
1274 verHandle->hide(); |
|
1275 if (moveEnabled) |
|
1276 titleBar->show(); |
|
1277 else |
|
1278 titleBar->hide(); |
|
1279 titleBar->updateGui(); |
|
1280 hHandleTop->hide(); |
|
1281 vHandleLeft->hide(); |
|
1282 hHandleBottom->hide(); |
|
1283 vHandleRight->hide(); |
|
1284 setLineWidth(2); |
|
1285 widgetResizeHandler->setActive(isResizeEnabled()); |
|
1286 } else { |
|
1287 hbox->setMargin(0); |
|
1288 titleBar->hide(); |
|
1289 if (orientation() == Qt::Horizontal) { |
|
1290 horHandle->hide(); |
|
1291 if (moveEnabled) |
|
1292 verHandle->show(); |
|
1293 else |
|
1294 verHandle->hide(); |
|
1295 #ifdef Q_WS_MAC |
|
1296 if(horHandle->mousePressed) { |
|
1297 horHandle->mousePressed = false; |
|
1298 verHandle->mousePressed = true; |
|
1299 verHandle->grabMouse(); |
|
1300 } |
|
1301 #endif |
|
1302 verHandle->updateGui(); |
|
1303 } else { |
|
1304 if (moveEnabled) |
|
1305 horHandle->show(); |
|
1306 else |
|
1307 horHandle->hide(); |
|
1308 horHandle->updateGui(); |
|
1309 #ifdef Q_WS_MAC |
|
1310 if(verHandle->mousePressed) { |
|
1311 verHandle->mousePressed = false; |
|
1312 horHandle->mousePressed = true; |
|
1313 horHandle->grabMouse(); |
|
1314 } |
|
1315 #endif |
|
1316 verHandle->hide(); |
|
1317 } |
|
1318 if (isResizeEnabled()) { |
|
1319 if (orientation() == Qt::Horizontal) { |
|
1320 hHandleBottom->raise(); |
|
1321 hHandleTop->raise(); |
|
1322 } else { |
|
1323 vHandleRight->raise(); |
|
1324 vHandleLeft->raise(); |
|
1325 } |
|
1326 |
|
1327 if (area()) { |
|
1328 if (orientation() == Qt::Horizontal) { |
|
1329 if (area()->handlePosition() == Q3DockArea::Normal) { |
|
1330 hHandleBottom->show(); |
|
1331 hHandleTop->hide(); |
|
1332 } else { |
|
1333 hHandleTop->show(); |
|
1334 hHandleBottom->hide(); |
|
1335 } |
|
1336 if (!area()->isLastDockWindow(this)) |
|
1337 vHandleRight->show(); |
|
1338 else |
|
1339 vHandleRight->hide(); |
|
1340 vHandleLeft->hide(); |
|
1341 } else { |
|
1342 if ((area()->handlePosition() == Q3DockArea::Normal) != QApplication::reverseLayout()) { |
|
1343 vHandleRight->show(); |
|
1344 vHandleLeft->hide(); |
|
1345 } else { |
|
1346 vHandleLeft->show(); |
|
1347 vHandleRight->hide(); |
|
1348 } |
|
1349 if (!area()->isLastDockWindow(this)) |
|
1350 hHandleBottom->show(); |
|
1351 else |
|
1352 hHandleBottom->hide(); |
|
1353 hHandleTop->hide(); |
|
1354 } |
|
1355 } |
|
1356 } |
|
1357 #ifndef Q_OS_WINCE |
|
1358 if (moveEnabled) |
|
1359 setLineWidth(1); |
|
1360 else |
|
1361 setLineWidth(0); |
|
1362 #endif |
|
1363 widgetResizeHandler->setActive(false); |
|
1364 } |
|
1365 } |
|
1366 |
|
1367 void Q3DockWindow::updatePosition(const QPoint &globalPos) |
|
1368 { |
|
1369 if (curPlace == OutsideDock && state == InDock) |
|
1370 lastSize = size(); |
|
1371 |
|
1372 bool doAdjustSize = curPlace != state && state == OutsideDock; |
|
1373 bool doUpdate = true; |
|
1374 bool doOrientationChange = true; |
|
1375 if (state != curPlace && state == InDock) { |
|
1376 doUpdate = false; |
|
1377 curPlace = state; |
|
1378 updateGui(); |
|
1379 QApplication::sendPostedEvents(); |
|
1380 } |
|
1381 Qt::Orientation oo = orientation(); |
|
1382 |
|
1383 if (state == InDock) { |
|
1384 if (tmpDockArea) { |
|
1385 bool differentDocks = false; |
|
1386 if (dockArea && dockArea != tmpDockArea) { |
|
1387 differentDocks = true; |
|
1388 delete (Q3DockArea::DockWindowData*)dockWindowData; |
|
1389 dockWindowData = dockArea->dockWindowData(this); |
|
1390 dockArea->removeDockWindow(this, false, false); |
|
1391 } |
|
1392 dockArea = tmpDockArea; |
|
1393 if (differentDocks) { |
|
1394 if (doUpdate) { |
|
1395 doUpdate = false; |
|
1396 curPlace = state; |
|
1397 updateGui(); |
|
1398 } |
|
1399 emit orientationChanged(tmpDockArea->orientation()); |
|
1400 doOrientationChange = false; |
|
1401 } else { |
|
1402 updateGui(); |
|
1403 } |
|
1404 dockArea->moveDockWindow(this, globalPos, currRect, startOrientation != oo); |
|
1405 } |
|
1406 } else { |
|
1407 if (dockArea) { |
|
1408 Q3MainWindow *mw = (Q3MainWindow*)dockArea->parentWidget(); |
|
1409 if (qobject_cast<Q3MainWindow*>(mw) && |
|
1410 (!mw->isDockEnabled(Qt::DockTornOff) || |
|
1411 !mw->isDockEnabled(this, Qt::DockTornOff))) |
|
1412 return; |
|
1413 delete (Q3DockArea::DockWindowData*)dockWindowData; |
|
1414 dockWindowData = dockArea->dockWindowData(this); |
|
1415 dockArea->removeDockWindow(this, true, |
|
1416 startOrientation != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this)); |
|
1417 } |
|
1418 dockArea = 0; |
|
1419 QPoint topLeft = currRect.topLeft(); |
|
1420 QRect screen = qApp->desktop()->availableGeometry(topLeft); |
|
1421 if (!screen.contains(topLeft)) { |
|
1422 topLeft.setY(qMax(topLeft.y(), screen.top())); |
|
1423 topLeft.setY(qMin(topLeft.y(), screen.bottom()-height())); |
|
1424 topLeft.setX(qMax(topLeft.x(), screen.left())); |
|
1425 topLeft.setX(qMin(topLeft.x(), screen.right()-width())); |
|
1426 } |
|
1427 move(topLeft); |
|
1428 } |
|
1429 |
|
1430 if (curPlace == InDock && state == OutsideDock && !qobject_cast<Q3ToolBar*>(this)) { |
|
1431 if (lastSize != QSize(-1, -1)) |
|
1432 resize(lastSize); |
|
1433 } |
|
1434 |
|
1435 if (doUpdate) { |
|
1436 curPlace = state; |
|
1437 updateGui(); |
|
1438 } |
|
1439 if (doOrientationChange) |
|
1440 emit orientationChanged(orientation()); |
|
1441 tmpDockArea = 0; |
|
1442 if (doAdjustSize) { |
|
1443 QApplication::sendPostedEvents(this, QEvent::LayoutHint); |
|
1444 if (qobject_cast<Q3ToolBar*>(this)) |
|
1445 adjustSize(); |
|
1446 if (lastSize == QSize(-1, -1)) |
|
1447 setAttribute(Qt::WA_Resized, false); // Ensures size is recalculated (non-opaque). |
|
1448 show(); |
|
1449 if (parentWidget() && isWindow()) |
|
1450 parentWidget()->setActiveWindow(); |
|
1451 |
|
1452 } |
|
1453 |
|
1454 emit placeChanged(curPlace); |
|
1455 } |
|
1456 |
|
1457 /*! |
|
1458 Sets the dock window's main widget to \a w. |
|
1459 |
|
1460 \sa boxLayout() |
|
1461 */ |
|
1462 |
|
1463 void Q3DockWindow::setWidget(QWidget *w) |
|
1464 { |
|
1465 wid = w; |
|
1466 boxLayout()->addWidget(w); |
|
1467 updateGui(); |
|
1468 } |
|
1469 |
|
1470 /*! |
|
1471 Returns the dock window's main widget. |
|
1472 |
|
1473 \sa setWidget() |
|
1474 */ |
|
1475 |
|
1476 QWidget *Q3DockWindow::widget() const |
|
1477 { |
|
1478 return wid; |
|
1479 } |
|
1480 |
|
1481 void Q3DockWindow::startRectDraw(const QPoint &so, bool drawRect) |
|
1482 { |
|
1483 state = place(); |
|
1484 if (rubberBand) |
|
1485 endRectDraw(!opaque); |
|
1486 rubberBand = new QRubberBand(QRubberBand::Rectangle); |
|
1487 currRect = QRect(realWidgetPos(this), size()); |
|
1488 if (drawRect) { |
|
1489 rubberBand->setGeometry(currRect); |
|
1490 } |
|
1491 startOrientation = orientation(); |
|
1492 startOffset = mapFromGlobal(so); |
|
1493 rubberBand->show(); |
|
1494 } |
|
1495 |
|
1496 void Q3DockWindow::endRectDraw(bool) |
|
1497 { |
|
1498 delete rubberBand; |
|
1499 rubberBand = 0; |
|
1500 } |
|
1501 |
|
1502 /*! |
|
1503 \reimp |
|
1504 */ |
|
1505 void Q3DockWindow::drawFrame(QPainter *p) |
|
1506 { |
|
1507 if (place() == InDock) { |
|
1508 Q3Frame::drawFrame(p); |
|
1509 return; |
|
1510 } |
|
1511 |
|
1512 QStyleOptionFrame opt; |
|
1513 opt.rect = rect(); |
|
1514 opt.palette = palette(); |
|
1515 opt.state = QStyle::State_None; |
|
1516 if (titleBar->isActive()) |
|
1517 opt.state |= QStyle::State_Active; |
|
1518 opt.lineWidth = lineWidth(); |
|
1519 opt.midLineWidth = midLineWidth(); |
|
1520 |
|
1521 style()->drawPrimitive(QStyle::PE_FrameWindow, &opt, p, this); |
|
1522 } |
|
1523 |
|
1524 /*! |
|
1525 \reimp |
|
1526 */ |
|
1527 void Q3DockWindow::drawContents(QPainter *p) |
|
1528 { |
|
1529 // This is only used by the PocketPC style. We probably need to revist later. |
|
1530 QStyleOption opt(0, QStyleOption::SO_Default); |
|
1531 opt.init(this); |
|
1532 if (titleBar->isActive()) |
|
1533 opt.state |= QStyle::State_Active; |
|
1534 style()->drawControl(QStyle::CE_Q3DockWindowEmptyArea, &opt, p, this); |
|
1535 } |
|
1536 |
|
1537 /*! |
|
1538 \property Q3DockWindow::resizeEnabled |
|
1539 \brief whether the dock window is resizeable |
|
1540 |
|
1541 A resizeable dock window can be resized using splitter-like |
|
1542 handles inside a dock area and like every other top level window |
|
1543 when floating. |
|
1544 |
|
1545 A dock window is both horizontally and vertically stretchable if |
|
1546 you call setResizeEnabled(true). |
|
1547 |
|
1548 This property is false by default. |
|
1549 |
|
1550 \sa setVerticallyStretchable() setHorizontallyStretchable() |
|
1551 */ |
|
1552 |
|
1553 void Q3DockWindow::setResizeEnabled(bool b) |
|
1554 { |
|
1555 resizeEnabled = b; |
|
1556 updateGui(); |
|
1557 } |
|
1558 |
|
1559 /*! |
|
1560 \property Q3DockWindow::movingEnabled |
|
1561 \brief whether the user can move the dock window within the dock |
|
1562 area, move the dock window to another dock area, or float the dock |
|
1563 window. |
|
1564 |
|
1565 This property is true by default. |
|
1566 */ |
|
1567 |
|
1568 void Q3DockWindow::setMovingEnabled(bool b) |
|
1569 { |
|
1570 moveEnabled = b; |
|
1571 updateGui(); |
|
1572 } |
|
1573 |
|
1574 bool Q3DockWindow::isResizeEnabled() const |
|
1575 { |
|
1576 return resizeEnabled; |
|
1577 } |
|
1578 |
|
1579 bool Q3DockWindow::isMovingEnabled() const |
|
1580 { |
|
1581 return moveEnabled; |
|
1582 } |
|
1583 |
|
1584 /*! |
|
1585 \property Q3DockWindow::closeMode |
|
1586 \brief the close mode of a dock window |
|
1587 |
|
1588 Defines when (if ever) the dock window has a close button. The |
|
1589 choices are \c Never, \c Docked (i.e. only when docked), \c |
|
1590 Undocked (only when undocked, i.e. floated) or \c Always. |
|
1591 |
|
1592 The default is \c Never. |
|
1593 */ |
|
1594 |
|
1595 void Q3DockWindow::setCloseMode(int m) |
|
1596 { |
|
1597 cMode = m; |
|
1598 if (place() == InDock) { |
|
1599 horHandle->updateGui(); |
|
1600 verHandle->updateGui(); |
|
1601 } else { |
|
1602 titleBar->updateGui(); |
|
1603 } |
|
1604 } |
|
1605 |
|
1606 /*! |
|
1607 Returns true if the dock window has a close button; otherwise |
|
1608 returns false. The result depends on the dock window's \l Place |
|
1609 and its \l CloseMode. |
|
1610 |
|
1611 \sa setCloseMode() |
|
1612 */ |
|
1613 |
|
1614 bool Q3DockWindow::isCloseEnabled() const |
|
1615 { |
|
1616 return (((cMode & Docked) == Docked && place() == InDock) || |
|
1617 ((cMode & Undocked) == Undocked && place() == OutsideDock)); |
|
1618 } |
|
1619 |
|
1620 int Q3DockWindow::closeMode() const |
|
1621 { |
|
1622 return cMode; |
|
1623 } |
|
1624 |
|
1625 /*! |
|
1626 \property Q3DockWindow::horizontallyStretchable |
|
1627 \brief whether the dock window is horizontally stretchable. |
|
1628 |
|
1629 A dock window is horizontally stretchable if you call |
|
1630 setHorizontallyStretchable(true) or setResizeEnabled(true). |
|
1631 |
|
1632 \warning Stretchability is broken. You must call |
|
1633 setResizeEnabled(true) to get proper behavior and even then |
|
1634 Q3DockWindow does not limit stretchablilty. |
|
1635 |
|
1636 \sa setResizeEnabled() |
|
1637 */ |
|
1638 |
|
1639 void Q3DockWindow::setHorizontallyStretchable(bool b) |
|
1640 { |
|
1641 stretchable[Qt::Horizontal] = b; |
|
1642 } |
|
1643 |
|
1644 /*! |
|
1645 \property Q3DockWindow::verticallyStretchable |
|
1646 \brief whether the dock window is vertically stretchable. |
|
1647 |
|
1648 A dock window is vertically stretchable if you call |
|
1649 setVerticallyStretchable(true) or setResizeEnabled(true). |
|
1650 |
|
1651 \sa setResizeEnabled() |
|
1652 |
|
1653 \warning Stretchability is broken. You must call |
|
1654 setResizeEnabled(true) to get proper behavior and even then |
|
1655 Q3DockWindow does not limit stretchablilty. |
|
1656 */ |
|
1657 |
|
1658 void Q3DockWindow::setVerticallyStretchable(bool b) |
|
1659 { |
|
1660 stretchable[Qt::Vertical] = b; |
|
1661 } |
|
1662 |
|
1663 bool Q3DockWindow::isHorizontallyStretchable() const |
|
1664 { |
|
1665 return isResizeEnabled() || stretchable[Qt::Horizontal]; |
|
1666 } |
|
1667 |
|
1668 bool Q3DockWindow::isVerticallyStretchable() const |
|
1669 { |
|
1670 return isResizeEnabled() || stretchable[Qt::Vertical]; |
|
1671 } |
|
1672 |
|
1673 /*! |
|
1674 \property Q3DockWindow::stretchable |
|
1675 \brief whether the dock window is stretchable in the current |
|
1676 orientation() |
|
1677 |
|
1678 This property can be set using setHorizontallyStretchable() and |
|
1679 setVerticallyStretchable(), or with setResizeEnabled(). |
|
1680 |
|
1681 \warning Stretchability is broken. You must call |
|
1682 setResizeEnabled(true) to get proper behavior and even then |
|
1683 Q3DockWindow does not limit stretchablilty. |
|
1684 |
|
1685 \sa setResizeEnabled() |
|
1686 */ |
|
1687 |
|
1688 bool Q3DockWindow::isStretchable() const |
|
1689 { |
|
1690 if (orientation() == Qt::Horizontal) |
|
1691 return isHorizontallyStretchable(); |
|
1692 return isVerticallyStretchable(); |
|
1693 } |
|
1694 |
|
1695 /*! |
|
1696 Returns the orientation of the dock window. |
|
1697 |
|
1698 \sa orientationChanged() |
|
1699 */ |
|
1700 |
|
1701 Qt::Orientation Q3DockWindow::orientation() const |
|
1702 { |
|
1703 if (dockArea) |
|
1704 return dockArea->orientation(); |
|
1705 if (qobject_cast<const Q3ToolBar*>(this)) |
|
1706 return Qt::Horizontal; |
|
1707 return (((Q3DockWindow*)this)->boxLayout()->direction() == QBoxLayout::LeftToRight || |
|
1708 ((Q3DockWindow*)this)->boxLayout()->direction() == QBoxLayout::RightToLeft ? |
|
1709 Qt::Horizontal : Qt::Vertical); |
|
1710 } |
|
1711 |
|
1712 int Q3DockWindow::offset() const |
|
1713 { |
|
1714 return offs; |
|
1715 } |
|
1716 |
|
1717 /*! |
|
1718 \property Q3DockWindow::offset |
|
1719 \brief the dock window's preferred offset from the dock area's |
|
1720 left edge (top edge for vertical dock areas) |
|
1721 |
|
1722 The default is 0. |
|
1723 */ |
|
1724 |
|
1725 void Q3DockWindow::setOffset(int o) |
|
1726 { |
|
1727 offs = o; |
|
1728 } |
|
1729 |
|
1730 /*! |
|
1731 Returns the dock window's preferred size (fixed extent). |
|
1732 |
|
1733 \sa setFixedExtentWidth() setFixedExtentHeight() |
|
1734 */ |
|
1735 |
|
1736 QSize Q3DockWindow::fixedExtent() const |
|
1737 { |
|
1738 return fExtent; |
|
1739 } |
|
1740 |
|
1741 /*! |
|
1742 Sets the dock window's preferred width for its fixed extent (size) |
|
1743 to \a w. |
|
1744 |
|
1745 \sa setFixedExtentHeight() |
|
1746 */ |
|
1747 |
|
1748 void Q3DockWindow::setFixedExtentWidth(int w) |
|
1749 { |
|
1750 fExtent.setWidth(w); |
|
1751 } |
|
1752 |
|
1753 /*! |
|
1754 Sets the dock window's preferred height for its fixed extent |
|
1755 (size) to \a h. |
|
1756 |
|
1757 \sa setFixedExtentWidth() |
|
1758 */ |
|
1759 |
|
1760 void Q3DockWindow::setFixedExtentHeight(int h) |
|
1761 { |
|
1762 fExtent.setHeight(h); |
|
1763 } |
|
1764 |
|
1765 /*! |
|
1766 \property Q3DockWindow::newLine |
|
1767 \brief whether the dock window prefers to start a new line in the |
|
1768 dock area. |
|
1769 |
|
1770 The default is false, i.e. the dock window doesn't require a new |
|
1771 line in the dock area. |
|
1772 */ |
|
1773 |
|
1774 void Q3DockWindow::setNewLine(bool b) |
|
1775 { |
|
1776 nl = b; |
|
1777 } |
|
1778 |
|
1779 bool Q3DockWindow::newLine() const |
|
1780 { |
|
1781 return nl; |
|
1782 } |
|
1783 |
|
1784 /*! |
|
1785 Returns the layout which is used for adding widgets to the dock |
|
1786 window. The layout's orientation is set automatically to match the |
|
1787 orientation of the dock window. You can add widgets to the layout |
|
1788 using the box layout's QBoxLayout::addWidget() function. |
|
1789 |
|
1790 If the dock window only needs to contain a single widget use |
|
1791 setWidget() instead. |
|
1792 |
|
1793 \sa setWidget() setOrientation() |
|
1794 */ |
|
1795 |
|
1796 QBoxLayout *Q3DockWindow::boxLayout() |
|
1797 { |
|
1798 return childBox; |
|
1799 } |
|
1800 |
|
1801 /*! \reimp |
|
1802 */ |
|
1803 |
|
1804 QSize Q3DockWindow::sizeHint() const |
|
1805 { |
|
1806 QSize sh(Q3Frame::sizeHint()); |
|
1807 if (place() == InDock) |
|
1808 sh = sh.expandedTo(fixedExtent()); |
|
1809 sh = sh.expandedTo(QSize(16, 16)); |
|
1810 if (area()) { |
|
1811 if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible()) |
|
1812 sh.setWidth(sh.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3); |
|
1813 else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible()) |
|
1814 sh.setHeight(sh.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3); |
|
1815 } |
|
1816 return sh; |
|
1817 } |
|
1818 |
|
1819 /*! \internal |
|
1820 */ |
|
1821 |
|
1822 QSize Q3DockWindow::minimumSize() const |
|
1823 { |
|
1824 QSize ms(Q3Frame::minimumSize()); |
|
1825 if (place() == InDock) |
|
1826 ms = ms.expandedTo(fixedExtent()); |
|
1827 ms = ms.expandedTo(QSize(16, 16)); |
|
1828 if (area()) { |
|
1829 if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible()) |
|
1830 ms.setWidth(ms.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3); |
|
1831 else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible()) |
|
1832 ms.setHeight(ms.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3); |
|
1833 } |
|
1834 return ms; |
|
1835 } |
|
1836 |
|
1837 /*! \reimp |
|
1838 */ |
|
1839 |
|
1840 QSize Q3DockWindow::minimumSizeHint() const |
|
1841 { |
|
1842 QSize msh(Q3Frame::minimumSize()); |
|
1843 if (place() == InDock) |
|
1844 msh = msh.expandedTo(fixedExtent()); |
|
1845 msh = msh.expandedTo(QSize(16, 16)); |
|
1846 if (area()) { |
|
1847 if (area()->orientation() == Qt::Horizontal && !vHandleRight->isVisible()) |
|
1848 msh.setWidth(msh.width() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3); |
|
1849 else if (area()->orientation() == Qt::Vertical && !hHandleBottom->isVisible()) |
|
1850 msh.setHeight(msh.height() + 2 * style()->pixelMetric(QStyle::PM_SplitterWidth, 0, this) / 3); |
|
1851 } |
|
1852 return msh; |
|
1853 } |
|
1854 |
|
1855 /*! |
|
1856 \fn void Q3DockWindow::undock() |
|
1857 |
|
1858 Undocks the Q3DockWindow from its current dock area if it is |
|
1859 docked; otherwise does nothing. |
|
1860 |
|
1861 \sa dock() Q3DockArea::moveDockWindow(), |
|
1862 Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(), |
|
1863 Q3MainWindow::removeDockWindow() |
|
1864 */ |
|
1865 |
|
1866 /*! |
|
1867 \fn void Q3DockWindow::undock(QWidget *widget) |
|
1868 |
|
1869 Undocks the specified \a widget from its current dock area if it is |
|
1870 docked; otherwise does nothing. |
|
1871 |
|
1872 \sa dock() Q3DockArea::moveDockWindow(), |
|
1873 Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(), |
|
1874 Q3MainWindow::removeDockWindow() |
|
1875 */ |
|
1876 void Q3DockWindow::undock(QWidget *w) |
|
1877 { |
|
1878 Q3MainWindow *mw = 0; |
|
1879 if (area()) |
|
1880 mw = qobject_cast<Q3MainWindow*>(area()->parentWidget()); |
|
1881 if (mw && !mw->isDockEnabled(this, Qt::DockTornOff)) |
|
1882 return; |
|
1883 if ((place() == OutsideDock && !w)) |
|
1884 return; |
|
1885 |
|
1886 QPoint p(50, 50); |
|
1887 if (window()) |
|
1888 p = window()->pos() + QPoint(20, 20); |
|
1889 if (dockArea) { |
|
1890 delete (Q3DockArea::DockWindowData*)dockWindowData; |
|
1891 dockWindowData = dockArea->dockWindowData(this); |
|
1892 dockArea->removeDockWindow(this, true, orientation() != Qt::Horizontal && qobject_cast<Q3ToolBar*>(this)); |
|
1893 } |
|
1894 dockArea = 0; |
|
1895 if (lastPos != QPoint(-1, -1) && lastPos.x() > 0 && lastPos.y() > 0) |
|
1896 move(lastPos); |
|
1897 else |
|
1898 move(p); |
|
1899 if (lastSize != QSize(-1, -1)) |
|
1900 resize(lastSize); |
|
1901 curPlace = OutsideDock; |
|
1902 updateGui(); |
|
1903 emit orientationChanged(orientation()); |
|
1904 QApplication::sendPostedEvents(this, QEvent::LayoutHint); |
|
1905 if (qobject_cast<Q3ToolBar*>(this)) |
|
1906 adjustSize(); |
|
1907 if (!w) { |
|
1908 if (!parentWidget() || parentWidget()->isVisible()) { |
|
1909 if (lastSize == QSize(-1, -1)) |
|
1910 setAttribute(Qt::WA_Resized, false);// Ensures size is recalculated (opaque). |
|
1911 show(); |
|
1912 } |
|
1913 } else { |
|
1914 setParent(w, 0); |
|
1915 move(-width() - 5, -height() - 5); |
|
1916 resize(1, 1); |
|
1917 show(); |
|
1918 } |
|
1919 if (parentWidget() && isWindow()) |
|
1920 parentWidget()->setActiveWindow(); |
|
1921 emit placeChanged(place()); |
|
1922 } |
|
1923 |
|
1924 void Q3DockWindow::removeFromDock(bool fixNewLines) |
|
1925 { |
|
1926 if (dockArea) |
|
1927 dockArea->removeDockWindow(this, false, false, fixNewLines); |
|
1928 } |
|
1929 |
|
1930 /*! |
|
1931 Docks the dock window into the last dock area in which it was |
|
1932 docked. |
|
1933 |
|
1934 If the dock window has no last dock area (e.g. it was created as a |
|
1935 floating window and has never been docked), or if the last dock |
|
1936 area it was docked in does not exist (e.g. the dock area has been |
|
1937 deleted), nothing happens. |
|
1938 |
|
1939 The dock window will dock with the dock area regardless of the return value |
|
1940 of Q3DockArea::isDockWindowAccepted(). |
|
1941 |
|
1942 \sa undock() Q3DockArea::moveDockWindow(), |
|
1943 Q3DockArea::removeDockWindow(), Q3MainWindow::moveDockWindow(), |
|
1944 Q3MainWindow::removeDockWindow(), Q3DockArea::isDockWindowAccepted() |
|
1945 |
|
1946 */ |
|
1947 |
|
1948 void Q3DockWindow::dock() |
|
1949 { |
|
1950 if (!(Q3DockArea::DockWindowData*)dockWindowData || |
|
1951 !((Q3DockArea::DockWindowData*)dockWindowData)->area) |
|
1952 return; |
|
1953 curPlace = InDock; |
|
1954 lastPos = pos(); |
|
1955 lastSize = size(); |
|
1956 ((Q3DockArea::DockWindowData*)dockWindowData)-> |
|
1957 area->dockWindow(this, (Q3DockArea::DockWindowData*)dockWindowData); |
|
1958 emit orientationChanged(orientation()); |
|
1959 emit placeChanged(place()); |
|
1960 } |
|
1961 |
|
1962 /*! \reimp |
|
1963 */ |
|
1964 |
|
1965 void Q3DockWindow::hideEvent(QHideEvent *e) |
|
1966 { |
|
1967 Q3Frame::hideEvent(e); |
|
1968 } |
|
1969 |
|
1970 /*! \reimp |
|
1971 */ |
|
1972 |
|
1973 void Q3DockWindow::showEvent(QShowEvent *e) |
|
1974 { |
|
1975 if (curPlace == OutsideDock && (parent() && parent()->objectName() == QLatin1String("qt_hide_dock"))) { |
|
1976 QRect sr = qApp->desktop()->availableGeometry(this); |
|
1977 if (!sr.contains(pos())) { |
|
1978 int nx = qMin(qMax(x(), sr.x()), sr.right()-width()); |
|
1979 int ny = qMin(qMax(y(), sr.y()), sr.bottom()-height()); |
|
1980 move(nx, ny); |
|
1981 } |
|
1982 } |
|
1983 |
|
1984 Q3Frame::showEvent(e); |
|
1985 } |
|
1986 |
|
1987 /*! |
|
1988 \property Q3DockWindow::opaqueMoving |
|
1989 \brief whether the dock window will be shown normally whilst it is |
|
1990 being moved. |
|
1991 |
|
1992 If this property is false, (the default), the dock window will be |
|
1993 represented by an outline rectangle whilst it is being moved. |
|
1994 |
|
1995 \warning Currently opaque moving has some problems and we do not |
|
1996 recommend using it at this time. We expect to fix these problems |
|
1997 in a future release. |
|
1998 */ |
|
1999 |
|
2000 void Q3DockWindow::setOpaqueMoving(bool b) |
|
2001 { |
|
2002 opaque = b; |
|
2003 horHandle->setOpaqueMoving(b); |
|
2004 verHandle->setOpaqueMoving(b); |
|
2005 titleBar->setOpaqueMoving(b); |
|
2006 } |
|
2007 |
|
2008 bool Q3DockWindow::opaqueMoving() const |
|
2009 { |
|
2010 return opaque; |
|
2011 } |
|
2012 |
|
2013 void Q3DockWindow::updateSplitterVisibility(bool visible) |
|
2014 { |
|
2015 if (area() && isResizeEnabled()) { |
|
2016 if (orientation() == Qt::Horizontal) { |
|
2017 if (visible) |
|
2018 vHandleRight->show(); |
|
2019 else |
|
2020 vHandleRight->hide(); |
|
2021 vHandleLeft->hide(); |
|
2022 } else { |
|
2023 if (visible) |
|
2024 hHandleBottom->show(); |
|
2025 else |
|
2026 hHandleBottom->hide(); |
|
2027 hHandleTop->hide(); |
|
2028 } |
|
2029 } |
|
2030 } |
|
2031 |
|
2032 /*! \reimp */ |
|
2033 bool Q3DockWindow::eventFilter(QObject * o, QEvent *e) |
|
2034 { |
|
2035 if (!o->isWidgetType()) |
|
2036 return false; |
|
2037 |
|
2038 if (e->type() == QEvent::KeyPress && |
|
2039 (horHandle->mousePressed || |
|
2040 verHandle->mousePressed || |
|
2041 titleBar->mousePressed)) { |
|
2042 QKeyEvent *ke = (QKeyEvent*)e; |
|
2043 if (ke->key() == Qt::Key_Escape) { |
|
2044 horHandle->mousePressed = |
|
2045 verHandle->mousePressed = |
|
2046 titleBar->mousePressed = false; |
|
2047 endRectDraw(!opaque); |
|
2048 qApp->removeEventFilter(this); |
|
2049 return true; |
|
2050 } |
|
2051 } else if (((QWidget*)o)->window() != this && place() == OutsideDock && isWindow()) { |
|
2052 if ((e->type() == QEvent::WindowDeactivate || |
|
2053 e->type() == QEvent::WindowActivate)) |
|
2054 event(e); |
|
2055 } |
|
2056 return false; |
|
2057 } |
|
2058 |
|
2059 /*! \reimp */ |
|
2060 bool Q3DockWindow::event(QEvent *e) |
|
2061 { |
|
2062 switch (e->type()) { |
|
2063 case QEvent::WindowDeactivate: |
|
2064 if (place() == OutsideDock && isWindow() && parentWidget() |
|
2065 && parentWidget()->isActiveWindow()) |
|
2066 return true; |
|
2067 break; |
|
2068 case QEvent::HideToParent: |
|
2069 emit visibilityChanged(false); |
|
2070 break; |
|
2071 case QEvent::ShowToParent: |
|
2072 emit visibilityChanged(true); |
|
2073 break; |
|
2074 case QEvent::WindowTitleChange: |
|
2075 { |
|
2076 QString s = Q3Frame::windowTitle(); |
|
2077 titleBar->setWindowTitle(s); |
|
2078 #ifndef QT_NO_TOOLTIP |
|
2079 horHandle->setToolTip(s); |
|
2080 verHandle->setToolTip(s); |
|
2081 #endif |
|
2082 break; |
|
2083 } |
|
2084 default: |
|
2085 break; |
|
2086 } |
|
2087 return Q3Frame::event(e); |
|
2088 } |
|
2089 |
|
2090 /*! |
|
2091 Returns the dock window's title. |
|
2092 */ |
|
2093 QString Q3DockWindow::windowTitle() const |
|
2094 { |
|
2095 return titleBar->windowTitle(); |
|
2096 } |
|
2097 |
|
2098 /*! \reimp */ |
|
2099 void Q3DockWindow::contextMenuEvent(QContextMenuEvent *e) |
|
2100 { |
|
2101 QObject *o = this; |
|
2102 while (o) { |
|
2103 if (qobject_cast<Q3MainWindow*>(o)) |
|
2104 break; |
|
2105 o = o->parent(); |
|
2106 } |
|
2107 if (!o || ! ((Q3MainWindow*)o)->showDockMenu(e->globalPos())) |
|
2108 e->ignore(); |
|
2109 } |
|
2110 |
|
2111 QT_END_NAMESPACE |
|
2112 |
|
2113 #include "q3dockwindow.moc" |
|
2114 |
|
2115 #endif //QT_NO_MAINWINDOW |