void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca) { if (state != 0) return; Q_Q(QDockWidget); QMainWindow *win = qobject_cast<QMainWindow*>(parent); Q_ASSERT(win != 0); QMainWindowLayout *layout = qt_mainwindow_layout(win); Q_ASSERT(layout != 0); if (layout->pluggingWidget != 0) // the main window is animating a docking operation return; state = new QDockWidgetPrivate::DragState; state->dragging = false; state->widgetItem = 0; state->ownWidgetItem = false; state->nca = nca; state->ctrlDrag = false; if (!q->isFloating()) { // When dragging the widget out of the docking area, // use the middle of title area as pressPos QDockWidgetLayout *dwlayout = qobject_cast<QDockWidgetLayout*>(q->layout()); Q_ASSERT(dwlayout != 0); int width = undockedGeometry.isNull() ? q->width() : undockedGeometry.width(); state->pressPos.setY(dwlayout->titleArea().height() / 2); state->pressPos.setX(width / 2); } else { state->pressPos = pos; } }
/*! \reimp */ void QDockWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); bool customTitleBar = layout->widgetForRole(QDockWidgetLayout::TitleBar) != 0; bool nativeDeco = layout->nativeWindowDeco(); if (!nativeDeco && !customTitleBar) { QStylePainter p(this); // ### Add PixelMetric to change spacers, so style may show border // when not floating. if (isFloating()) { QStyleOptionFrame framOpt; framOpt.init(this); p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt); } // Title must be painted after the frame, since the areas overlap, and // the title may wish to extend out to all sides (eg. XP style) QStyleOptionDockWidgetV2 titleOpt; initStyleOption(&titleOpt); p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt); } }
void QDockWidgetPrivate::init() { Q_Q(QDockWidget); QDockWidgetLayout *layout = new QDockWidgetLayout(q); layout->setSizeConstraint(QLayout::SetMinAndMaxSize); QAbstractButton *button = new QDockWidgetTitleButton(q); button->setObjectName(QLatin1String("qt_dockwidget_floatbutton")); QObject::connect(button, SIGNAL(clicked()), q, SLOT(_q_toggleTopLevel())); layout->setWidgetForRole(QDockWidgetLayout::FloatButton, button); button = new QDockWidgetTitleButton(q); button->setObjectName(QLatin1String("qt_dockwidget_closebutton")); QObject::connect(button, SIGNAL(clicked()), q, SLOT(close())); layout->setWidgetForRole(QDockWidgetLayout::CloseButton, button); resizer = new QWidgetResizeHandler(q); resizer->setMovingEnabled(false); resizer->setActive(false); #ifndef QT_NO_ACTION toggleViewAction = new QAction(q); toggleViewAction->setCheckable(true); fixedWindowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q); toggleViewAction->setText(fixedWindowTitle); QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), q, SLOT(_q_toggleView(bool))); #endif updateButtons(); }
void QDockWidgetPrivate::updateButtons() { Q_Q(QDockWidget); QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); QStyleOptionDockWidget opt; q->initStyleOption(&opt); bool customTitleBar = dwLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0; bool nativeDeco = dwLayout->nativeWindowDeco(); bool hideButtons = nativeDeco || customTitleBar; bool canClose = hasFeature(this, QDockWidget::DockWidgetClosable); bool canFloat = hasFeature(this, QDockWidget::DockWidgetFloatable); QAbstractButton *button = qobject_cast<QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::FloatButton)); button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q)); button->setVisible(canFloat && !hideButtons); button = qobject_cast <QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::CloseButton)); button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q)); button->setVisible(canClose && !hideButtons); q->setAttribute(Qt::WA_ContentsPropagated, (canFloat || canClose) && !hideButtons); layout->invalidate(); }
bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event) { #if !defined(QT_NO_MAINWINDOW) Q_Q(QDockWidget); QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); if (!dwLayout->nativeWindowDeco()) { QRect titleArea = dwLayout->titleArea(); if (event->button() != Qt::LeftButton || !titleArea.contains(event->pos()) || // check if the tool window is movable... do nothing if it // is not (but allow moving if the window is floating) (!hasFeature(this, QDockWidget::DockWidgetMovable) && !q->isFloating()) || qobject_cast<QMainWindow*>(parent) == 0 || isAnimating() || state != 0) { return false; } initDrag(event->pos(), false); if (state) state->ctrlDrag = hasFeature(this, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier; return true; } #endif // !defined(QT_NO_MAINWINDOW) return false; }
/*! \reimp */ void QDockWidget::changeEvent(QEvent *event) { Q_D(QDockWidget); QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); switch (event->type()) { case QEvent::ModifiedChange: case QEvent::WindowTitleChange: update(layout->titleArea()); #ifndef QT_NO_ACTION d->fixedWindowTitle = qt_setWindowTitle_helperHelper(windowTitle(), this); d->toggleViewAction->setText(d->fixedWindowTitle); #endif #ifndef QT_NO_TABBAR { QMainWindow *win = qobject_cast<QMainWindow*>(parentWidget()); if (QMainWindowLayout *winLayout = qt_mainwindow_layout(win)) { if (QDockAreaLayoutInfo *info = winLayout->layoutState.dockAreaLayout.info(this)) info->updateTabBar(); } } #endif // QT_NO_TABBAR break; default: break; } QWidget::changeEvent(event); }
void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect &rect) { Q_Q(QDockWidget); if (!floating && parent) { QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget())); if (mwlayout && mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea) return; // this dockwidget can't be redocked } bool wasFloating = q->isFloating(); bool hidden = q->isHidden(); if (q->isVisible()) q->hide(); Qt::WindowFlags flags = floating ? Qt::Tool : Qt::Widget; QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); const bool nativeDeco = dwLayout->nativeWindowDeco(floating); if (nativeDeco) { flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint; if (hasFeature(this, QDockWidget::DockWidgetClosable)) flags |= Qt::WindowCloseButtonHint; } else { flags |= Qt::FramelessWindowHint; } if (unplug) flags |= Qt::X11BypassWindowManagerHint; q->setWindowFlags(flags); #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) if (floating && nativeDeco && (q->features() & QDockWidget::DockWidgetVerticalTitleBar)) { ChangeWindowAttributes(HIViewGetWindow(HIViewRef(q->winId())), kWindowSideTitlebarAttribute, 0); } #endif if (!rect.isNull()) q->setGeometry(rect); updateButtons(); if (!hidden) q->show(); if (floating != wasFloating) { emit q->topLevelChanged(floating); if (!floating && parent) { QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget())); if (mwlayout) emit q->dockLocationChanged(mwlayout->dockWidgetArea(q)); } } resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco); }
void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect &rect) { Q_Q(QDockWidget); if (!floating && parent) { QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget())); if (mwlayout && mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea) return; // this dockwidget can't be redocked } bool wasFloating = q->isFloating(); bool hidden = q->isHidden(); if (q->isVisible()) q->hide(); Qt::WindowFlags flags = floating ? Qt::Tool : Qt::Widget; QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); const bool nativeDeco = dwLayout->nativeWindowDeco(floating); if (nativeDeco) { flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint; if (hasFeature(this, QDockWidget::DockWidgetClosable)) flags |= Qt::WindowCloseButtonHint; } else { flags |= Qt::FramelessWindowHint; } if (unplug) flags |= Qt::X11BypassWindowManagerHint; q->setWindowFlags(flags); if (!rect.isNull()) q->setGeometry(rect); updateButtons(); if (!hidden) q->show(); if (floating != wasFloating) { emit q->topLevelChanged(floating); if (!floating && parent) { QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast<QMainWindow *>(q->parentWidget())); if (mwlayout) emit q->dockLocationChanged(mwlayout->dockWidgetArea(q)); } } if (floating && nativeDeco) if (const QWindow *window = q->windowHandle()) if (QPlatformWindow *platformWindow = window->handle()) platformWindow->setFrameStrutEventsEnabled(true); resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco); }
void QDockWidget::setTitleBarWidget(QWidget *widget) { Q_D(QDockWidget); QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); layout->setWidget(QDockWidgetLayout::TitleBar, widget); d->updateButtons(); }
void QDockWidgetPrivate::unplug(const QRect &rect) { Q_Q(QDockWidget); QRect r = rect; r.moveTopLeft(q->mapToGlobal(QPoint(0, 0))); QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); if (dwLayout->nativeWindowDeco(true)) r.adjust(0, dwLayout->titleHeight(), 0, 0); setWindowState(true, true, r); }
void QDockWidgetPrivate::unplug(const QRect &rect) { Q_Q(QDockWidget); QRect r = rect; r.moveTopLeft(q->mapToGlobal(QPoint(0, 0))); #ifndef Q_WS_X11 QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout()); r.adjust(0, layout->titleHeight(), 0, 0); #endif setWindowState(true, true, r); }
void QDockWidget::setTitleBarWidget(QWidget *widget) { Q_D(QDockWidget); QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); layout->setWidgetForRole(QDockWidgetLayout::TitleBar, widget); d->updateButtons(); if (isWindow()) { //this ensures the native decoration is drawn d->setWindowState(true /*floating*/, true /*unplug*/); } }
void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect &rect) { Q_Q(QDockWidget); bool wasFloating = q->isFloating(); bool hidden = q->isHidden(); if (q->isVisible()) q->hide(); Qt::WindowFlags flags = floating ? Qt::Tool : Qt::Widget; QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout()); bool nativeDeco = floating && layout->widget(QDockWidgetLayout::TitleBar) == 0; #if defined(Q_WS_X11) || defined(Q_WS_QWS) nativeDeco = false; #endif if (nativeDeco) { flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint; if (hasFeature(q, QDockWidget::DockWidgetClosable)) flags |= Qt::WindowSystemMenuHint; } else { flags |= Qt::FramelessWindowHint; } if (unplug) flags |= Qt::X11BypassWindowManagerHint; q->setWindowFlags(flags); #ifdef Q_WS_MAC if (floating && nativeDeco && (q->features() & QDockWidget::DockWidgetVerticalTitleBar)) { ChangeWindowAttributes(HIViewGetWindow(HIViewRef(q->winId())), kWindowSideTitlebarAttribute, 0); } #endif if (!rect.isNull()) q->setGeometry(rect); updateButtons(); if (!hidden) q->show(); if (floating != wasFloating) emit q->topLevelChanged(floating); resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco); }
void QDockWidget::setFeatures(QDockWidget::DockWidgetFeatures features) { Q_D(QDockWidget); features &= DockWidgetFeatureMask; if (d->features == features) return; d->features = features; QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); layout->setVerticalTitleBar(features & DockWidgetVerticalTitleBar); d->updateButtons(); d->toggleViewAction->setEnabled((d->features & DockWidgetClosable) == DockWidgetClosable); emit featuresChanged(d->features); update(); }
bool QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event) { QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout); if (!dwLayout->nativeWindowDeco()) { QRect titleArea = dwLayout->titleArea(); if (event->button() == Qt::LeftButton && titleArea.contains(event->pos()) && hasFeature(this, QDockWidget::DockWidgetFloatable)) { _q_toggleTopLevel(); return true; } } return false; }
void tst_QDockWidget::taskQTBUG_1665_closableChanged() { QDockWidget dock; dock.show(); QVERIFY(QTest::qWaitForWindowExposed(&dock)); QDockWidgetLayout *l = qobject_cast<QDockWidgetLayout*>(dock.layout()); if (l && !l->nativeWindowDeco()) QSKIP("this machine doesn't support native dock widget"); QVERIFY(dock.windowFlags() & Qt::WindowCloseButtonHint); //now let's remove the closable attribute dock.setFeatures(dock.features() ^ QDockWidget::DockWidgetClosable); QVERIFY(!(dock.windowFlags() & Qt::WindowCloseButtonHint)); }
void QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event) { Q_Q(QDockWidget); QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout()); if (!layout->nativeWindowDeco()) { QRect titleArea = layout->titleArea(); if (event->button() != Qt::LeftButton) return; if (!titleArea.contains(event->pos())) return; if (!::hasFeature(q, QDockWidget::DockWidgetFloatable)) return; _q_toggleTopLevel(); } }
/*! \property QDockWidget::floating \brief whether the dock widget is floating A floating dock widget is presented to the user as an independent window "on top" of its parent QMainWindow, instead of being docked in the QMainWindow. \sa isWindow() */ void QDockWidget::setFloating(bool floating) { Q_D(QDockWidget); // the initial click of a double-click may have started a drag... if (d->state != 0) d->endDrag(true); QRect r = d->undockedGeometry; if (floating && r.isNull()) { QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); QRect titleArea = layout->titleArea(); int h = layout->verticalTitleBar ? titleArea.width() : titleArea.height(); QPoint p = mapToGlobal(QPoint(h, h)); r = QRect(p, size()); } d->setWindowState(floating, false, floating ? r : QRect()); }
void QDockWidget::setFeatures(QDockWidget::DockWidgetFeatures features) { Q_D(QDockWidget); features &= DockWidgetFeatureMask; if (d->features == features) return; const bool closableChanged = (d->features ^ features) & DockWidgetClosable; d->features = features; QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); layout->setVerticalTitleBar(features & DockWidgetVerticalTitleBar); d->updateButtons(); d->toggleViewAction->setEnabled((d->features & DockWidgetClosable) == DockWidgetClosable); emit featuresChanged(d->features); update(); if (closableChanged && layout->nativeWindowDeco()) { //this ensures the native decoration is drawn d->setWindowState(true /*floating*/, true /*unplug*/); } }
bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event) { bool ret = false; #if !defined(QT_NO_MAINWINDOW) Q_Q(QDockWidget); if (!state) return ret; QDockWidgetLayout *dwlayout = qobject_cast<QDockWidgetLayout*>(layout); QMainWindowLayout *mwlayout = qobject_cast<QMainWindowLayout*>(q->parentWidget()->layout()); if (!dwlayout->nativeWindowDeco()) { if (!state->dragging && mwlayout->pluggingWidget == 0 && (event->pos() - state->pressPos).manhattanLength() > QApplication::startDragDistance()) { startDrag(); #ifdef Q_OS_WIN grabMouseWhileInWindow(); #else q->grabMouse(); #endif ret = true; } } if (state->dragging && !state->nca) { QPoint pos = event->globalPos() - state->pressPos; q->move(pos); if (!state->ctrlDrag) mwlayout->hover(state->widgetItem, event->globalPos()); ret = true; } #endif // !defined(QT_NO_MAINWINDOW) return ret; }
/*! Initialize \a option with the values from this QDockWidget. This method is useful for subclasses when they need a QStyleOptionDockWidget, but don't want to fill in all the information themselves. \sa QStyleOption::initFrom() */ void QDockWidget::initStyleOption(QStyleOptionDockWidget *option) const { Q_D(const QDockWidget); if (!option) return; QDockWidgetLayout *dwlayout = qobject_cast<QDockWidgetLayout*>(layout()); option->initFrom(this); option->rect = dwlayout->titleArea(); option->title = d->fixedWindowTitle; option->closable = hasFeature(this, QDockWidget::DockWidgetClosable); option->movable = hasFeature(this, QDockWidget::DockWidgetMovable); option->floatable = hasFeature(this, QDockWidget::DockWidgetFloatable); QDockWidgetLayout *l = qobject_cast<QDockWidgetLayout*>(layout()); QStyleOptionDockWidgetV2 *v2 = qstyleoption_cast<QStyleOptionDockWidgetV2*>(option); if (v2 != 0) v2->verticalTitleBar = l->verticalTitleBar; }
void QDockWidgetPrivate::endDrag(bool abort) { Q_Q(QDockWidget); Q_ASSERT(state != 0); q->releaseMouse(); if (state->dragging) { QMainWindowLayout *mwLayout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout()); Q_ASSERT(mwLayout != 0); if (abort || !mwLayout->plug(state->widgetItem)) { if (hasFeature(this, QDockWidget::DockWidgetFloatable)) { if (state->ownWidgetItem) delete state->widgetItem; mwLayout->restore(); #ifdef Q_WS_X11 // get rid of the X11BypassWindowManager window flag and activate the resizer Qt::WindowFlags flags = q->windowFlags(); flags &= ~Qt::X11BypassWindowManagerHint; q->setWindowFlags(flags); resizer->setActive(QWidgetResizeHandler::Resize, true); q->show(); #else QDockWidgetLayout *myLayout = qobject_cast<QDockWidgetLayout*>(layout); resizer->setActive(QWidgetResizeHandler::Resize, myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0); #endif undockedGeometry = q->geometry(); q->activateWindow(); } else { mwLayout->revert(state->widgetItem); } } } delete state; state = 0; }
void QDockWidgetPrivate::mousePressEvent(QMouseEvent *event) { #if !defined(QT_NO_MAINWINDOW) Q_Q(QDockWidget); QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout()); if (!layout->nativeWindowDeco()) { QRect titleArea = layout->titleArea(); if (event->button() != Qt::LeftButton) return; if (!titleArea.contains(event->pos())) return; // check if the tool window is movable... do nothing if it is not if (!::hasFeature(q, QDockWidget::DockWidgetMovable)) return; if (qobject_cast<QMainWindow*>(q->parentWidget()) == 0) return; if (isAnimating()) return; if (state != 0) return; initDrag(event->pos(), false); if (state == 0) return; state->ctrlDrag = event->modifiers() & Qt::ControlModifier; } #endif // !defined(QT_NO_MAINWINDOW) }
/*! Returns the widget for the dock widget. This function returns zero if the widget has not been set. \sa setWidget() */ QWidget *QDockWidget::widget() const { QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); return layout->widgetForRole(QDockWidgetLayout::Content); }
QWidget *QDockWidget::titleBarWidget() const { QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); return layout->widgetForRole(QDockWidgetLayout::TitleBar); }
/*! Sets the widget for the dock widget to \a widget. If the dock widget is visible when \a widget is added, you must \l{QWidget::}{show()} it explicitly. Note that you must add the layout of the \a widget before you call this function; if not, the \a widget will not be visible. \sa widget() */ void QDockWidget::setWidget(QWidget *widget) { QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); layout->setWidgetForRole(QDockWidgetLayout::Content, widget); }