From f67b8df3ebdba2d398b9cce686b7c644adffff08 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 7 May 2011 00:02:01 +0200 Subject: library split --- src/gui/widgets/qdockwidget.cpp | 1606 --------------------------------------- 1 file changed, 1606 deletions(-) delete mode 100644 src/gui/widgets/qdockwidget.cpp (limited to 'src/gui/widgets/qdockwidget.cpp') diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp deleted file mode 100644 index 9d1a737cf1..0000000000 --- a/src/gui/widgets/qdockwidget.cpp +++ /dev/null @@ -1,1606 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdockwidget.h" - -#ifndef QT_NO_DOCKWIDGET -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "qdockwidget_p.h" -#include "qmainwindowlayout_p.h" -#ifdef Q_WS_MAC -#include -#include -#include -#endif - -QT_BEGIN_NAMESPACE - -extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); // qwidget.cpp - -// qmainwindow.cpp -extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window); - -static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature) -{ return (priv->features & feature) == feature; } - -static inline bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature) -{ return (dockwidget->features() & feature) == feature; } - - -/* - A Dock Window: - - [+] is the float button - [X] is the close button - - +-------------------------------+ - | Dock Window Title [+][X]| - +-------------------------------+ - | | - | place to put the single | - | QDockWidget child (this space | - | does not yet have a name) | - | | - | | - | | - | | - | | - | | - | | - | | - | | - +-------------------------------+ - -*/ - -/****************************************************************************** -** QDockWidgetTitleButton -*/ - -class QDockWidgetTitleButton : public QAbstractButton -{ - Q_OBJECT - -public: - QDockWidgetTitleButton(QDockWidget *dockWidget); - - QSize sizeHint() const; - inline QSize minimumSizeHint() const - { return sizeHint(); } - - void enterEvent(QEvent *event); - void leaveEvent(QEvent *event); - void paintEvent(QPaintEvent *event); -}; - - -QDockWidgetTitleButton::QDockWidgetTitleButton(QDockWidget *dockWidget) - : QAbstractButton(dockWidget) -{ - setFocusPolicy(Qt::NoFocus); -} - -QSize QDockWidgetTitleButton::sizeHint() const -{ - ensurePolished(); - - int size = 2*style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, 0, this); - if (!icon().isNull()) { - int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this); - QSize sz = icon().actualSize(QSize(iconSize, iconSize)); - size += qMax(sz.width(), sz.height()); - } - - return QSize(size, size); -} - -void QDockWidgetTitleButton::enterEvent(QEvent *event) -{ - if (isEnabled()) update(); - QAbstractButton::enterEvent(event); -} - -void QDockWidgetTitleButton::leaveEvent(QEvent *event) -{ - if (isEnabled()) update(); - QAbstractButton::leaveEvent(event); -} - -void QDockWidgetTitleButton::paintEvent(QPaintEvent *) -{ - QPainter p(this); - - QRect r = rect(); - QStyleOptionToolButton opt; - opt.init(this); - opt.state |= QStyle::State_AutoRaise; - - if (style()->styleHint(QStyle::SH_DockWidget_ButtonsHaveFrame, 0, this)) - { - if (isEnabled() && underMouse() && !isChecked() && !isDown()) - opt.state |= QStyle::State_Raised; - if (isChecked()) - opt.state |= QStyle::State_On; - if (isDown()) - opt.state |= QStyle::State_Sunken; - style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &p, this); - } - - opt.icon = icon(); - opt.subControls = 0; - opt.activeSubControls = 0; - opt.features = QStyleOptionToolButton::None; - opt.arrowType = Qt::NoArrow; - int size = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this); - opt.iconSize = QSize(size, size); - style()->drawComplexControl(QStyle::CC_ToolButton, &opt, &p, this); -} - -/****************************************************************************** -** QDockWidgetLayout -*/ - -QDockWidgetLayout::QDockWidgetLayout(QWidget *parent) - : QLayout(parent), verticalTitleBar(false), item_list(RoleCount, 0) -{ -} - -QDockWidgetLayout::~QDockWidgetLayout() -{ - qDeleteAll(item_list); -} - -bool QDockWidgetLayout::nativeWindowDeco() const -{ - return nativeWindowDeco(parentWidget()->isWindow()); -} - -bool QDockWidgetLayout::nativeWindowDeco(bool floating) const -{ -#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_WINCE) - Q_UNUSED(floating); - return false; -#else - return floating && item_list[QDockWidgetLayout::TitleBar] == 0; -#endif -} - - -void QDockWidgetLayout::addItem(QLayoutItem*) -{ - qWarning() << "QDockWidgetLayout::addItem(): please use QDockWidgetLayout::setWidget()"; - return; -} - -QLayoutItem *QDockWidgetLayout::itemAt(int index) const -{ - int cnt = 0; - for (int i = 0; i < item_list.count(); ++i) { - QLayoutItem *item = item_list.at(i); - if (item == 0) - continue; - if (index == cnt++) - return item; - } - return 0; -} - -QLayoutItem *QDockWidgetLayout::takeAt(int index) -{ - int j = 0; - for (int i = 0; i < item_list.count(); ++i) { - QLayoutItem *item = item_list.at(i); - if (item == 0) - continue; - if (index == j) { - item_list[i] = 0; - invalidate(); - return item; - } - ++j; - } - return 0; -} - -int QDockWidgetLayout::count() const -{ - int result = 0; - for (int i = 0; i < item_list.count(); ++i) { - if (item_list.at(i)) - ++result; - } - return result; -} - -QSize QDockWidgetLayout::sizeFromContent(const QSize &content, bool floating) const -{ - QSize result = content; - - if (verticalTitleBar) { - result.setHeight(qMax(result.height(), minimumTitleWidth())); - result.setWidth(qMax(content.width(), 0)); - } else { - result.setHeight(qMax(result.height(), 0)); - result.setWidth(qMax(content.width(), minimumTitleWidth())); - } - - QDockWidget *w = qobject_cast(parentWidget()); - const bool nativeDeco = nativeWindowDeco(floating); - - int fw = floating && !nativeDeco - ? w->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, w) - : 0; - - const int th = titleHeight(); - if (!nativeDeco) { - if (verticalTitleBar) - result += QSize(th + 2*fw, 2*fw); - else - result += QSize(2*fw, th + 2*fw); - } - - result.setHeight(qMin(result.height(), (int) QWIDGETSIZE_MAX)); - result.setWidth(qMin(result.width(), (int) QWIDGETSIZE_MAX)); - - if (content.width() < 0) - result.setWidth(-1); - if (content.height() < 0) - result.setHeight(-1); - - int left, top, right, bottom; - w->getContentsMargins(&left, &top, &right, &bottom); - //we need to substract the contents margin (it will be added by the caller) - QSize min = w->minimumSize() - QSize(left + right, top + bottom); - QSize max = w->maximumSize() - QSize(left + right, top + bottom); - - /* A floating dockwidget will automatically get its minimumSize set to the layout's - minimum size + deco. We're *not* interested in this, we only take minimumSize() - into account if the user set it herself. Otherwise we end up expanding the result - of a calculation for a non-floating dock widget to a floating dock widget's - minimum size + window decorations. */ - - uint explicitMin = 0; - uint explicitMax = 0; - if (w->d_func()->extra != 0) { - explicitMin = w->d_func()->extra->explicitMinSize; - explicitMax = w->d_func()->extra->explicitMaxSize; - } - - if (!(explicitMin & Qt::Horizontal) || min.width() == 0) - min.setWidth(-1); - if (!(explicitMin & Qt::Vertical) || min.height() == 0) - min.setHeight(-1); - - if (!(explicitMax & Qt::Horizontal)) - max.setWidth(QWIDGETSIZE_MAX); - if (!(explicitMax & Qt::Vertical)) - max.setHeight(QWIDGETSIZE_MAX); - - return result.boundedTo(max).expandedTo(min); -} - -QSize QDockWidgetLayout::sizeHint() const -{ - QDockWidget *w = qobject_cast(parentWidget()); - - QSize content(-1, -1); - if (item_list[Content] != 0) - content = item_list[Content]->sizeHint(); - - return sizeFromContent(content, w->isFloating()); -} - -QSize QDockWidgetLayout::maximumSize() const -{ - if (item_list[Content] != 0) { - const QSize content = item_list[Content]->maximumSize(); - return sizeFromContent(content, parentWidget()->isWindow()); - } else { - return parentWidget()->maximumSize(); - } - -} - -QSize QDockWidgetLayout::minimumSize() const -{ - QDockWidget *w = qobject_cast(parentWidget()); - - QSize content(0, 0); - if (item_list[Content] != 0) - content = item_list[Content]->minimumSize(); - - return sizeFromContent(content, w->isFloating()); -} - -QWidget *QDockWidgetLayout::widgetForRole(Role r) const -{ - QLayoutItem *item = item_list.at(r); - return item == 0 ? 0 : item->widget(); -} - -QLayoutItem *QDockWidgetLayout::itemForRole(Role r) const -{ - return item_list.at(r); -} - -void QDockWidgetLayout::setWidgetForRole(Role r, QWidget *w) -{ - QWidget *old = widgetForRole(r); - if (old != 0) { - old->hide(); - removeWidget(old); - } - - if (w != 0) { - addChildWidget(w); - item_list[r] = new QWidgetItemV2(w); - w->show(); - } else { - item_list[r] = 0; - } - - invalidate(); -} - -static inline int pick(bool vertical, const QSize &size) -{ - return vertical ? size.height() : size.width(); -} - -static inline int perp(bool vertical, const QSize &size) -{ - return vertical ? size.width() : size.height(); -} - -int QDockWidgetLayout::minimumTitleWidth() const -{ - QDockWidget *q = qobject_cast(parentWidget()); - - if (QWidget *title = widgetForRole(TitleBar)) - return pick(verticalTitleBar, title->minimumSizeHint()); - - QSize closeSize(0, 0); - QSize floatSize(0, 0); - if (hasFeature(q, QDockWidget::DockWidgetClosable)) { - if (QLayoutItem *item = item_list[CloseButton]) - closeSize = item->widget()->sizeHint(); - } - if (hasFeature(q, QDockWidget::DockWidgetFloatable)) { - if (QLayoutItem *item = item_list[FloatButton]) - floatSize = item->widget()->sizeHint(); - } - - int titleHeight = this->titleHeight(); - - int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q); - int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q); - - return pick(verticalTitleBar, closeSize) - + pick(verticalTitleBar, floatSize) - + titleHeight + 2*fw + 3*mw; -} - -int QDockWidgetLayout::titleHeight() const -{ - QDockWidget *q = qobject_cast(parentWidget()); - - if (QWidget *title = widgetForRole(TitleBar)) - return perp(verticalTitleBar, title->sizeHint()); - - QSize closeSize(0, 0); - QSize floatSize(0, 0); - if (QLayoutItem *item = item_list[CloseButton]) - closeSize = item->widget()->sizeHint(); - if (QLayoutItem *item = item_list[FloatButton]) - floatSize = item->widget()->sizeHint(); - - int buttonHeight = qMax(perp(verticalTitleBar, closeSize), - perp(verticalTitleBar, floatSize)); - - QFontMetrics titleFontMetrics = q->fontMetrics(); -#ifdef Q_WS_MAC - if (qobject_cast(q->style())) { - //### this breaks on proxy styles. (But is this code still called?) - QFont font = qt_app_fonts_hash()->value("QToolButton", q->font()); - titleFontMetrics = QFontMetrics(font); - } -#endif - - int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q); - - return qMax(buttonHeight + 2, titleFontMetrics.height() + 2*mw); -} - -void QDockWidgetLayout::setGeometry(const QRect &geometry) -{ - QDockWidget *q = qobject_cast(parentWidget()); - - bool nativeDeco = nativeWindowDeco(); - - int fw = q->isFloating() && !nativeDeco - ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q) - : 0; - - if (nativeDeco) { - if (QLayoutItem *item = item_list[Content]) - item->setGeometry(geometry); - } else { - int titleHeight = this->titleHeight(); - - if (verticalTitleBar) { - _titleArea = QRect(QPoint(fw, fw), - QSize(titleHeight, geometry.height() - (fw * 2))); - } else { - _titleArea = QRect(QPoint(fw, fw), - QSize(geometry.width() - (fw * 2), titleHeight)); - } - - if (QLayoutItem *item = item_list[TitleBar]) { - item->setGeometry(_titleArea); - } else { - QStyleOptionDockWidgetV2 opt; - q->initStyleOption(&opt); - - if (QLayoutItem *item = item_list[CloseButton]) { - if (!item->isEmpty()) { - QRect r = q->style() - ->subElementRect(QStyle::SE_DockWidgetCloseButton, - &opt, q); - if (!r.isNull()) - item->setGeometry(r); - } - } - - if (QLayoutItem *item = item_list[FloatButton]) { - if (!item->isEmpty()) { - QRect r = q->style() - ->subElementRect(QStyle::SE_DockWidgetFloatButton, - &opt, q); - if (!r.isNull()) - item->setGeometry(r); - } - } - } - - if (QLayoutItem *item = item_list[Content]) { - QRect r = geometry; - if (verticalTitleBar) { - r.setLeft(_titleArea.right() + 1); - r.adjust(0, fw, -fw, -fw); - } else { - r.setTop(_titleArea.bottom() + 1); - r.adjust(fw, 0, -fw, -fw); - } - item->setGeometry(r); - } - } -} - -void QDockWidgetLayout::setVerticalTitleBar(bool b) -{ - if (b == verticalTitleBar) - return; - verticalTitleBar = b; - invalidate(); - parentWidget()->update(); -} - -/****************************************************************************** -** QDockWidgetItem -*/ - -QDockWidgetItem::QDockWidgetItem(QDockWidget *dockWidget) - : QWidgetItem(dockWidget) -{ -} - -QSize QDockWidgetItem::minimumSize() const -{ - QSize widgetMin(0, 0); - if (QLayoutItem *item = dockWidgetChildItem()) - widgetMin = item->minimumSize(); - return dockWidgetLayout()->sizeFromContent(widgetMin, false); -} - -QSize QDockWidgetItem::maximumSize() const -{ - if (QLayoutItem *item = dockWidgetChildItem()) { - return dockWidgetLayout()->sizeFromContent(item->maximumSize(), false); - } else { - return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - } -} - - -QSize QDockWidgetItem::sizeHint() const -{ - if (QLayoutItem *item = dockWidgetChildItem()) { - return dockWidgetLayout()->sizeFromContent(item->sizeHint(), false); - } else { - return QWidgetItem::sizeHint(); - } -} - -/****************************************************************************** -** QDockWidgetPrivate -*/ - -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(); -} - -/*! - 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(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(layout()); - QStyleOptionDockWidgetV2 *v2 - = qstyleoption_cast(option); - if (v2 != 0) - v2->verticalTitleBar = l->verticalTitleBar; -} - -void QDockWidgetPrivate::_q_toggleView(bool b) -{ - Q_Q(QDockWidget); - if (b == q->isHidden()) { - if (b) - q->show(); - else - q->close(); - } -} - -void QDockWidgetPrivate::updateButtons() -{ - Q_Q(QDockWidget); - QDockWidgetLayout *dwLayout = qobject_cast(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(dwLayout->widgetForRole(QDockWidgetLayout::FloatButton)); - button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q)); - button->setVisible(canFloat && !hideButtons); - - button - = qobject_cast (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(); -} - -void QDockWidgetPrivate::_q_toggleTopLevel() -{ - Q_Q(QDockWidget); - q->setFloating(!q->isFloating()); -} - -void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca) -{ - if (state != 0) - return; - - QMainWindow *win = qobject_cast(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->pressPos = pos; - state->dragging = false; - state->widgetItem = 0; - state->ownWidgetItem = false; - state->nca = nca; - state->ctrlDrag = false; -} - -void QDockWidgetPrivate::startDrag() -{ - Q_Q(QDockWidget); - - if (state == 0 || state->dragging) - return; - - QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast(q->parentWidget())); - Q_ASSERT(layout != 0); - - state->widgetItem = layout->unplug(q); - if (state->widgetItem == 0) { - /* I have a QMainWindow parent, but I was never inserted with - QMainWindow::addDockWidget, so the QMainWindowLayout has no - widget item for me. :( I have to create it myself, and then - delete it if I don't get dropped into a dock area. */ - state->widgetItem = new QDockWidgetItem(q); - state->ownWidgetItem = true; - } - - if (state->ctrlDrag) - layout->restore(); - - state->dragging = true; -} - -void QDockWidgetPrivate::endDrag(bool abort) -{ - Q_Q(QDockWidget); - Q_ASSERT(state != 0); - - q->releaseMouse(); - - if (state->dragging) { - QMainWindowLayout *mwLayout = qt_mainwindow_layout(qobject_cast(q->parentWidget())); - 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(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; -} - -bool QDockWidgetPrivate::isAnimating() const -{ - Q_Q(const QDockWidget); - - QMainWindow *mainWin = qobject_cast(parent); - if (mainWin == 0) - return false; - - QMainWindowLayout *mainWinLayout = qt_mainwindow_layout(mainWin); - if (mainWinLayout == 0) - return false; - - return (void*)mainWinLayout->pluggingWidget == (void*)q; -} - -bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event) -{ -#if !defined(QT_NO_MAINWINDOW) - Q_Q(QDockWidget); - - QDockWidgetLayout *dwLayout - = qobject_cast(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(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; -} - -bool QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event) -{ - QDockWidgetLayout *dwLayout = qobject_cast(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; -} - -bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event) -{ - bool ret = false; -#if !defined(QT_NO_MAINWINDOW) - Q_Q(QDockWidget); - - if (!state) - return ret; - - QDockWidgetLayout *dwlayout - = qobject_cast(layout); - QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast(q->parentWidget())); - 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; -} - -bool QDockWidgetPrivate::mouseReleaseEvent(QMouseEvent *event) -{ -#if !defined(QT_NO_MAINWINDOW) - - if (event->button() == Qt::LeftButton && state && !state->nca) { - endDrag(); - return true; //filter out the event - } - -#endif // !defined(QT_NO_MAINWINDOW) - return false; -} - -void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event) -{ - Q_Q(QDockWidget); - - int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q); - - QRect geo = q->geometry(); - QRect titleRect = q->frameGeometry(); -#ifdef Q_WS_MAC - if ((features & QDockWidget::DockWidgetVerticalTitleBar)) { - titleRect.setTop(geo.top()); - titleRect.setBottom(geo.bottom()); - titleRect.setRight(geo.left() - 1); - } else -#endif - { - titleRect.setLeft(geo.left()); - titleRect.setRight(geo.right()); - titleRect.setBottom(geo.top() - 1); - titleRect.adjust(0, fw, 0, 0); - } - - switch (event->type()) { - case QEvent::NonClientAreaMouseButtonPress: - if (!titleRect.contains(event->globalPos())) - break; - if (state != 0) - break; - if (qobject_cast(parent) == 0) - break; - if (isAnimating()) - break; - initDrag(event->pos(), true); - if (state == 0) - break; -#ifdef Q_OS_WIN - // On Windows, NCA mouse events don't contain modifier info - state->ctrlDrag = GetKeyState(VK_CONTROL) & 0x8000; -#else - state->ctrlDrag = event->modifiers() & Qt::ControlModifier; -#endif - startDrag(); - break; - case QEvent::NonClientAreaMouseMove: - if (state == 0 || !state->dragging) - break; - if (state->nca) { - endDrag(); - } -#ifdef Q_OS_MAC - else { // workaround for lack of mouse-grab on Mac - QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast(q->parentWidget())); - Q_ASSERT(layout != 0); - - q->move(event->globalPos() - state->pressPos); - if (!state->ctrlDrag) - layout->hover(state->widgetItem, event->globalPos()); - } -#endif - break; - case QEvent::NonClientAreaMouseButtonRelease: -#ifdef Q_OS_MAC - if (state) - endDrag(); -#endif - break; - case QEvent::NonClientAreaMouseButtonDblClick: - _q_toggleTopLevel(); - break; - default: - break; - } -} - -void QDockWidgetPrivate::moveEvent(QMoveEvent *event) -{ - Q_Q(QDockWidget); - - if (state == 0 || !state->dragging || !state->nca || !q->isWindow()) - return; - - // When the native window frame is being dragged, all we get is these mouse - // move events. - - if (state->ctrlDrag) - return; - - QMainWindowLayout *layout = qt_mainwindow_layout(qobject_cast(q->parentWidget())); - Q_ASSERT(layout != 0); - - QPoint globalMousePos = event->pos() + state->pressPos; - layout->hover(state->widgetItem, globalMousePos); -} - -void QDockWidgetPrivate::unplug(const QRect &rect) -{ - Q_Q(QDockWidget); - QRect r = rect; - r.moveTopLeft(q->mapToGlobal(QPoint(0, 0))); - QDockWidgetLayout *dwLayout = qobject_cast(layout); - if (dwLayout->nativeWindowDeco(true)) - r.adjust(0, dwLayout->titleHeight(), 0, 0); - setWindowState(true, true, r); -} - -void QDockWidgetPrivate::plug(const QRect &rect) -{ - setWindowState(false, false, rect); -} - -void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect &rect) -{ - Q_Q(QDockWidget); - - if (!floating && parent) { - QMainWindowLayout *mwlayout = qt_mainwindow_layout(qobject_cast(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(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(q->parentWidget())); - if (mwlayout) - emit q->dockLocationChanged(mwlayout->dockWidgetArea(q)); - } - } - - resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco); -} - -/*! - \class QDockWidget - - \brief The QDockWidget class provides a widget that can be docked - inside a QMainWindow or floated as a top-level window on the - desktop. - - \ingroup mainwindow-classes - - QDockWidget provides the concept of dock widgets, also know as - tool palettes or utility windows. Dock windows are secondary - windows placed in the \e {dock widget area} around the - \l{QMainWindow::centralWidget()}{central widget} in a - QMainWindow. - - \image mainwindow-docks.png - - Dock windows can be moved inside their current area, moved into - new areas and floated (e.g., undocked) by the end-user. The - QDockWidget API allows the programmer to restrict the dock widgets - ability to move, float and close, as well as the areas in which - they can be placed. - - \section1 Appearance - - A QDockWidget consists of a title bar and the content area. The - title bar displays the dock widgets \link QWidget::windowTitle() - window title\endlink, a \e float button and a \e close button. - Depending on the state of the QDockWidget, the \e float and \e - close buttons may be either disabled or not shown at all. - - The visual appearance of the title bar and buttons is dependent - on the \l{QStyle}{style} in use. - - A QDockWidget acts as a wrapper for its child widget, set with setWidget(). - Custom size hints, minimum and maximum sizes and size policies should be - implemented in the child widget. QDockWidget will respect them, adjusting - its own constraints to include the frame and title. Size constraints - should not be set on the QDockWidget itself, because they change depending - on whether it is docked; a docked QDockWidget has no frame and a smaller title - bar. - - \sa QMainWindow, {Dock Widgets Example} -*/ - -/*! - \enum QDockWidget::DockWidgetFeature - - \value DockWidgetClosable The dock widget can be closed. On some systems the dock - widget always has a close button when it's floating - (for example on MacOS 10.5). - \value DockWidgetMovable The dock widget can be moved between docks - by the user. - \value DockWidgetFloatable The dock widget can be detached from the - main window, and floated as an independent - window. - \value DockWidgetVerticalTitleBar The dock widget displays a vertical title - bar on its left side. This can be used to - increase the amount of vertical space in - a QMainWindow. - \value AllDockWidgetFeatures (Deprecated) The dock widget can be closed, moved, - and floated. Since new features might be added in future - releases, the look and behavior of dock widgets might - change if you use this flag. Please specify individual - flags instead. - \value NoDockWidgetFeatures The dock widget cannot be closed, moved, - or floated. - - \omitvalue DockWidgetFeatureMask - \omitvalue Reserved -*/ - -/*! - \property QDockWidget::windowTitle - \brief the dock widget title (caption) - - By default, this property contains an empty string. -*/ - -/*! - Constructs a QDockWidget with parent \a parent and window flags \a - flags. The dock widget will be placed in the left dock widget - area. -*/ -QDockWidget::QDockWidget(QWidget *parent, Qt::WindowFlags flags) - : QWidget(*new QDockWidgetPrivate, parent, flags) -{ - Q_D(QDockWidget); - d->init(); -} - -/*! - Constructs a QDockWidget with parent \a parent and window flags \a - flags. The dock widget will be placed in the left dock widget - area. - - The window title is set to \a title. This title is used when the - QDockWidget is docked and undocked. It is also used in the context - menu provided by QMainWindow. - - \sa setWindowTitle() -*/ -QDockWidget::QDockWidget(const QString &title, QWidget *parent, Qt::WindowFlags flags) - : QWidget(*new QDockWidgetPrivate, parent, flags) -{ - Q_D(QDockWidget); - d->init(); - setWindowTitle(title); -} - -/*! - Destroys the dock widget. -*/ -QDockWidget::~QDockWidget() -{ } - -/*! - 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(this->layout()); - return layout->widgetForRole(QDockWidgetLayout::Content); -} - -/*! - 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(this->layout()); - layout->setWidgetForRole(QDockWidgetLayout::Content, widget); -} - -/*! - \property QDockWidget::features - \brief whether the dock widget is movable, closable, and floatable - - By default, this property is set to a combination of DockWidgetClosable, - DockWidgetMovable and DockWidgetFloatable. - - \sa DockWidgetFeature -*/ - -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(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*/); - } -} - -QDockWidget::DockWidgetFeatures QDockWidget::features() const -{ - Q_D(const QDockWidget); - return d->features; -} - -/*! - \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. - - By default, this property is true. - - \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; - - d->setWindowState(floating, false, floating ? r : QRect()); - - if (floating && r.isNull()) { - if (x() < 0 || y() < 0) //may happen if we have been hidden - move(QPoint()); - setAttribute(Qt::WA_Moved, false); //we want it at the default position - } -} - -/*! - \property QDockWidget::allowedAreas - \brief areas where the dock widget may be placed - - The default is Qt::AllDockWidgetAreas. - - \sa Qt::DockWidgetArea -*/ - -void QDockWidget::setAllowedAreas(Qt::DockWidgetAreas areas) -{ - Q_D(QDockWidget); - areas &= Qt::DockWidgetArea_Mask; - if (areas == d->allowedAreas) - return; - d->allowedAreas = areas; - emit allowedAreasChanged(d->allowedAreas); -} - -Qt::DockWidgetAreas QDockWidget::allowedAreas() const -{ - Q_D(const QDockWidget); - return d->allowedAreas; -} - -/*! - \fn bool QDockWidget::isAreaAllowed(Qt::DockWidgetArea area) const - - Returns true if this dock widget can be placed in the given \a area; - otherwise returns false. -*/ - -/*! \reimp */ -void QDockWidget::changeEvent(QEvent *event) -{ - Q_D(QDockWidget); - QDockWidgetLayout *layout = qobject_cast(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(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); -} - -/*! \reimp */ -void QDockWidget::closeEvent(QCloseEvent *event) -{ - Q_D(QDockWidget); - if (d->state) - d->endDrag(true); - QWidget::closeEvent(event); -} - -/*! \reimp */ -void QDockWidget::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event) - - QDockWidgetLayout *layout - = qobject_cast(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); - } -} - -/*! \reimp */ -bool QDockWidget::event(QEvent *event) -{ - Q_D(QDockWidget); - - QMainWindow *win = qobject_cast(parentWidget()); - QMainWindowLayout *layout = qt_mainwindow_layout(win); - - switch (event->type()) { -#ifndef QT_NO_ACTION - case QEvent::Hide: - if (layout != 0) - layout->keepSize(this); - d->toggleViewAction->setChecked(false); - emit visibilityChanged(false); - break; - case QEvent::Show: - d->toggleViewAction->setChecked(true); - emit visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0); - break; -#endif - case QEvent::ApplicationLayoutDirectionChange: - case QEvent::LayoutDirectionChange: - case QEvent::StyleChange: - case QEvent::ParentChange: - d->updateButtons(); - break; - case QEvent::ZOrderChange: { - bool onTop = false; - if (win != 0) { - const QObjectList &siblings = win->children(); - onTop = siblings.count() > 0 && siblings.last() == (QObject*)this; - } - if (!isFloating() && layout != 0 && onTop) - layout->raise(this); - break; - } - case QEvent::WindowActivate: - case QEvent::WindowDeactivate: - update(qobject_cast(this->layout())->titleArea()); - break; - case QEvent::ContextMenu: - if (d->state) { - event->accept(); - return true; - } - break; - // return true after calling the handler since we don't want - // them to be passed onto the default handlers - case QEvent::MouseButtonPress: - if (d->mousePressEvent(static_cast(event))) - return true; - break; - case QEvent::MouseButtonDblClick: - if (d->mouseDoubleClickEvent(static_cast(event))) - return true; - break; - case QEvent::MouseMove: - if (d->mouseMoveEvent(static_cast(event))) - return true; - break; -#ifdef Q_OS_WIN - case QEvent::Leave: - if (d->state != 0 && d->state->dragging && !d->state->nca) { - // This is a workaround for loosing the mouse on Vista. - QPoint pos = QCursor::pos(); - QMouseEvent fake(QEvent::MouseMove, mapFromGlobal(pos), pos, Qt::NoButton, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - d->mouseMoveEvent(&fake); - } - break; -#endif - case QEvent::MouseButtonRelease: - if (d->mouseReleaseEvent(static_cast(event))) - return true; - break; - case QEvent::NonClientAreaMouseMove: - case QEvent::NonClientAreaMouseButtonPress: - case QEvent::NonClientAreaMouseButtonRelease: - case QEvent::NonClientAreaMouseButtonDblClick: - d->nonClientAreaMouseEvent(static_cast(event)); - return true; - case QEvent::Move: - d->moveEvent(static_cast(event)); - break; - case QEvent::Resize: - // if the mainwindow is plugging us, we don't want to update undocked geometry - if (isFloating() && layout != 0 && layout->pluggingWidget != this) - d->undockedGeometry = geometry(); - break; - default: - break; - } - return QWidget::event(event); -} - -#ifndef QT_NO_ACTION -/*! - Returns a checkable action that can be used to show or close this - dock widget. - - The action's text is set to the dock widget's window title. - - \sa QAction::text QWidget::windowTitle - */ -QAction * QDockWidget::toggleViewAction() const -{ - Q_D(const QDockWidget); - return d->toggleViewAction; -} -#endif // QT_NO_ACTION - -/*! - \fn void QDockWidget::featuresChanged(QDockWidget::DockWidgetFeatures features) - - This signal is emitted when the \l features property changes. The - \a features parameter gives the new value of the property. -*/ - -/*! - \fn void QDockWidget::topLevelChanged(bool topLevel) - - This signal is emitted when the \l floating property changes. - The \a topLevel parameter is true if the dock widget is now floating; - otherwise it is false. - - \sa isWindow() -*/ - -/*! - \fn void QDockWidget::allowedAreasChanged(Qt::DockWidgetAreas allowedAreas) - - This signal is emitted when the \l allowedAreas property changes. The - \a allowedAreas parameter gives the new value of the property. -*/ - -/*! - \fn void QDockWidget::visibilityChanged(bool visible) - \since 4.3 - - This signal is emitted when the dock widget becomes \a visible (or - invisible). This happens when the widget is hidden or shown, as - well as when it is docked in a tabbed dock area and its tab - becomes selected or unselected. -*/ - -/*! - \fn void QDockWidget::dockLocationChanged(Qt::DockWidgetArea area) - \since 4.3 - - This signal is emitted when the dock widget is moved to another - dock \a area, or is moved to a different location in its current - dock area. This happens when the dock widget is moved - programmatically or is dragged to a new location by the user. -*/ - -/*! - \since 4.3 - - Sets an arbitrary \a widget as the dock widget's title bar. If \a widget - is 0, any custom title bar widget previously set on the dock widget is - removed, but not deleted, and the default title bar will be used - instead. - - If a title bar widget is set, QDockWidget will not use native window - decorations when it is floated. - - Here are some tips for implementing custom title bars: - - \list - \o Mouse events that are not explicitly handled by the title bar widget - must be ignored by calling QMouseEvent::ignore(). These events then - propagate to the QDockWidget parent, which handles them in the usual - manner, moving when the title bar is dragged, docking and undocking - when it is double-clicked, etc. - - \o When DockWidgetVerticalTitleBar is set on QDockWidget, the title - bar widget is repositioned accordingly. In resizeEvent(), the title - bar should check what orientation it should assume: - \snippet doc/src/snippets/code/src_gui_widgets_qdockwidget.cpp 0 - - \o The title bar widget must have a valid QWidget::sizeHint() and - QWidget::minimumSizeHint(). These functions should take into account - the current orientation of the title bar. - - \o It is not possible to remove a title bar from a dock widget. However, - a similar effect can be achieved by setting a default constructed - QWidget as the title bar widget. - \endlist - - Using qobject_cast() as shown above, the title bar widget has full access - to its parent QDockWidget. Hence it can perform such operations as docking - and hiding in response to user actions. - - \sa titleBarWidget() DockWidgetVerticalTitleBar -*/ - -void QDockWidget::setTitleBarWidget(QWidget *widget) -{ - Q_D(QDockWidget); - QDockWidgetLayout *layout - = qobject_cast(this->layout()); - layout->setWidgetForRole(QDockWidgetLayout::TitleBar, widget); - d->updateButtons(); - if (isWindow()) { - //this ensures the native decoration is drawn - d->setWindowState(true /*floating*/, true /*unplug*/); - } -} - -/*! - \since 4.3 - Returns the custom title bar widget set on the QDockWidget, or 0 if no - custom title bar has been set. - - \sa setTitleBarWidget() -*/ - -QWidget *QDockWidget::titleBarWidget() const -{ - QDockWidgetLayout *layout - = qobject_cast(this->layout()); - return layout->widgetForRole(QDockWidgetLayout::TitleBar); -} - -QT_END_NAMESPACE - -#include "qdockwidget.moc" -#include "moc_qdockwidget.cpp" - -#endif // QT_NO_DOCKWIDGET -- cgit v1.2.3