⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qdockwidget.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qdockwidget.h"#ifndef QT_NO_DOCKWIDGET#include <qaction.h>#include <qapplication.h>#include <qdesktopwidget.h>#include <qdrawutil.h>#include <qevent.h>#include <qfontmetrics.h>#include <qmainwindow.h>#include <qpainter.h>#include <qrubberband.h>#include <qstyle.h>#include <qstyleoption.h>#include <qtoolbutton.h>#include <qdebug.h>#include <private/qwidgetresizehandler_p.h>#include "qdockwidget_p.h"#include "qdockwidgetlayout_p.h"#include "qmainwindowlayout_p.h"#ifdef Q_WS_MAC#include <qmacstyle_mac.h>#endifstatic inline bool hasFeature(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)     |    |                               |    |                               |    |                               |    |                               |    |                               |    |                               |    |                               |    |                               |    |                               |    +-------------------------------+*//*  Tool window title*/class QDockWidgetTitleButton : public QAbstractButton{    Q_OBJECTpublic:    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 dim = 0;    if (!icon().isNull()) {        const QPixmap pm = icon().pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize), QIcon::Normal);        dim = qMax(pm.width(), pm.height());    }    return QSize(dim + 4, dim + 4);}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();    QStyleOption opt;    opt.init(this);    opt.state |= QStyle::State_AutoRaise;    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);    r.adjust(2, 2, -2, -2);    QPixmap pm = icon().pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize), isEnabled() ?                                underMouse() ? QIcon::Active : QIcon::Normal                                    : QIcon::Disabled,                                isDown() ? QIcon::On : QIcon::Off);    style()->drawItemPixmap(&p, r, Qt::AlignCenter, pm);}/*  Private class*/void QDockWidgetPrivate::init() {    Q_Q(QDockWidget);    top = new QGridLayout(q);    top->setMargin(0);    top->setSpacing(0);    box = new QDockWidgetBoxLayout;    box->setMargin(0);    box->setSpacing(0);    top->addLayout(box, 1, 0);    topSpacer = new QSpacerItem(0, 20, QSizePolicy::Ignored, QSizePolicy::Fixed);    box->addItem(topSpacer);    resizer = new QWidgetResizeHandler(q);    resizer->setMovingEnabled(false);    resizer->setActive(false);#ifndef QT_NO_ACTION    toggleViewAction = new QAction(q);    toggleViewAction->setCheckable(true);    toggleViewAction->setText(q->windowTitle());    QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), q, SLOT(_q_toggleView(bool)));#endif    updateButtons();}QStyleOptionDockWidget QDockWidgetPrivate::getStyleOption(){    Q_Q(QDockWidget);    QStyleOptionDockWidget opt;    opt.init(q);    opt.rect = titleArea;    opt.title = q->windowTitle();    opt.closable = hasFeature(q, QDockWidget::DockWidgetClosable);    opt.movable = hasFeature(q, QDockWidget::DockWidgetMovable);    opt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable);    return opt;}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);    if (hasFeature(q, QDockWidget::DockWidgetFloatable)) {        if (!floatButton) {            floatButton = new QDockWidgetTitleButton(q);            QObject::connect(floatButton, SIGNAL(clicked()), q, SLOT(_q_toggleTopLevel()));            if (!q->isHidden())                floatButton->show();        }    } else {        delete floatButton;        floatButton = 0;    }    if (hasFeature(q, QDockWidget::DockWidgetClosable)) {        if (!closeButton) {            closeButton = new QDockWidgetTitleButton(q);            QObject::connect(closeButton, SIGNAL(clicked()), q, SLOT(close()));            if (!q->isHidden())                closeButton->show();        }    } else {        delete closeButton;        closeButton = 0;    }    bool anyButton = (floatButton || closeButton);    if (anyButton) {        QStyleOptionDockWidget opt = getStyleOption();        if (floatButton)            floatButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));        if (closeButton)            closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));    }    q->setAttribute(Qt::WA_ContentsPropagated, anyButton);    relayout();}// ### Todo 4.1: Add subrects to style API, this will cover our styles for now//               Also, add posibilty to get standardIconsvoid QDockWidgetPrivate::relayout(){    Q_Q(QDockWidget);    int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q) : 0;    int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q);    QSize closeSize = closeButton ? closeButton->sizeHint() : QSize(0,0);    QSize floatSize = floatButton ? floatButton->sizeHint() : QSize(0,0);    int minWidth  = q->fontMetrics().width(q->windowTitle()) + 2 * fw + 2 * mw;    int minHeight = qMax(closeSize.width(), closeSize.height()) + 2 * mw;    minHeight = qMax(minHeight, qMax(floatSize.width(), floatSize.height()));    minHeight += 2; // Allow 1px frame around title area with buttons inside#ifdef Q_WS_MAC    if (qobject_cast<QMacStyle *>(q->style())) {        extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp        QFont font = qt_app_fonts_hash()->value("QToolButton", q->font());        QFontMetrics fm(font);        minHeight = qMax(minHeight, fm.lineSpacing() + 2 + 2 * mw) - fw; //Ensure 2 px margin around font    } else#endif    {        minHeight = qMax(minHeight, q->fontMetrics().lineSpacing() + 2 + 2 * mw) - fw; //Ensure 2 px margin around font    }    titleArea = QRect(QPoint(fw, fw),                      QSize(q->rect().width() - (fw * 2), minHeight));    int posX = titleArea.right();    QPoint buttonOffset(0, 0);#ifdef Q_OS_WIN    //### Fix this properly in Qt 4.2    if (q->style()->inherits("QWindowsXPStyle")) {        if(q->isFloating())            buttonOffset = QPoint(2, -1);        else            buttonOffset = QPoint(0, 1);    }#endif    if (closeButton) {        //### Fix this properly in Qt 4.2        closeButton->setGeometry(QStyle::visualRect(				    qApp->layoutDirection(),                                    titleArea, QRect(posX - closeSize.width() - mw + buttonOffset.x(),                                    titleArea.center().y() - closeSize.height() / 2 + + buttonOffset.y(),                                    closeSize.width(), closeSize.height())));        posX -= closeSize.width() + 1;    }    if (floatButton) {        //### Fix this properly in Qt 4.2        floatButton->setGeometry(QStyle::visualRect(				    qApp->layoutDirection(),                                    titleArea, QRect(posX - floatSize.width() - mw + buttonOffset.x(),                                    titleArea.center().y() - floatSize.height() / 2 + buttonOffset.y(),                                    floatSize.width(), floatSize.height())));        posX -= floatSize.width() + 1;    }    topSpacer->changeSize(minWidth, 0 + titleArea.height(), QSizePolicy::Expanding, QSizePolicy::Fixed);    top->setMargin(fw);    top->invalidate();}void QDockWidgetPrivate::_q_toggleTopLevel(){    Q_Q(QDockWidget);    QPoint p = q->mapToGlobal(QPoint(titleArea.height(), titleArea.height()));    bool visible = q->isVisible();    if (visible)        q->hide();    q->setFloating(!q->isFloating());    if (q->isWindow())        q->move(p);    if (visible)        q->show();}QMainWindow *QDockWidgetPrivate::findMainWindow(QWidget *widget) const{    Q_Q(const QDockWidget);    QMainWindow *mainwindow = 0;    // look for our QMainWindow    while (widget && !mainwindow) {        if (widget == q->parentWidget()) {            // found our parent widget, has to be the mainwindow we're looking for            mainwindow = qobject_cast<QMainWindow *>(widget);            break;        } else if (widget->isWindow()) {            // found a window that isn't our QMainWindow, stop looking            widget = 0;        } else {            widget = widget->parentWidget();        }    }    return mainwindow;}void QDockWidgetPrivate::mousePressEvent(QMouseEvent *event){#if !defined(QT_NO_MAINWINDOW)    Q_Q(QDockWidget);    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 (!q->parentWidget())        return;    QMainWindowLayout *layout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());    if (!layout)        return;    layout->saveLayoutInfo();    Q_ASSERT(!state);    state = new QDockWidgetPrivate::DragState;    state->rubberband = 0;    // the current location of the tool window in global coordinates    state->origin = QRect(q->mapToGlobal(QPoint(0, 0)), q->size());    state->current = state->origin;    const QPoint globalPos = event->globalPos();    const int dl = globalPos.x() - state->current.left(),              dr = state->current.right() - globalPos.x(),       halfWidth = state->origin.width() / 2;    state->offset = q->mapFrom(q,                               (dl < dr)                               ? QPoint(qMin(dl, halfWidth), 0)                               : QPoint(state->origin.width() - qMin(dr, halfWidth) - 1, 0));    state->offset = q->mapTo(q, QPoint(state->offset.x(), event->pos().y()));    state->canDrop = true;#ifdef Q_WS_WIN    /* Work around windows expose bug when windows are partially covered by     * a top level transparent object.     */    q->update();    QWidgetList children = qFindChildren<QWidget *>(q);    for (int i=0; i<children.size(); ++i)        children.at(i)->update();#endif#endif // !defined(QT_NO_MAINWINDOW)}void QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event){    Q_Q(QDockWidget);    if (event->button() != Qt::LeftButton)        return;    if (!titleArea.contains(event->pos()))        return;    if (!::hasFeature(q, QDockWidget::DockWidgetFloatable))        return;    _q_toggleTopLevel();}void QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event){#if !defined(QT_NO_MAINWINDOW)    Q_Q(QDockWidget);    if (!state)        return;    QRect target;    if (!(event->modifiers() & Qt::ControlModifier)) {        // see if there is a main window under us, and ask it to place the tool window        QWidget *widget = QApplication::widgetAt(event->globalPos());        if (widget) {            QMainWindow *mainwindow = findMainWindow(widget);            if (mainwindow) {                QMainWindowLayout *layout =                    qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());                Q_ASSERT(layout != 0);                QRect request = state->origin;                // ### remove extra frame                request.moveTopLeft(event->globalPos() - state->offset);                target = layout->placeDockWidget(q, request, event->globalPos());                layout->resetLayoutInfo();            }        }    }    state->canDrop = target.isValid();    if (!state->canDrop) {        if (hasFeature(q, QDockWidget::DockWidgetFloatable)) {            /*              main window refused to accept the tool window,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -