📄 qmdiarea.cpp
字号:
QMdiSubWindow *QMdiArea::addSubWindow(QWidget *widget, Qt::WindowFlags windowFlags){ if (!widget) { qWarning("QMdiArea::addSubWindow: null pointer to widget"); return 0; } Q_D(QMdiArea); // QWidget::setParent clears focusWidget so store it QWidget *childFocus = widget->focusWidget(); QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(widget); // Widget is already a QMdiSubWindow if (child) { if (d->childWindows.indexOf(child) != -1) { qWarning("QMdiArea::addSubWindow: window is already added"); return child; } child->setParent(viewport(), windowFlags ? windowFlags : child->windowFlags()); // Create a QMdiSubWindow } else { child = new QMdiSubWindow(viewport(), windowFlags); child->setAttribute(Qt::WA_DeleteOnClose); child->setWidget(widget); Q_ASSERT(child->testAttribute(Qt::WA_DeleteOnClose)); } if (childFocus) childFocus->setFocus(); d->appendChild(child); return child;}/*! Removes \a widget from the MDI area. The \a widget must be either a QMdiSubWindow or a widget that is the internal widget of a subwindow. Note that the subwindow is not deleted by QMdiArea and that its parent is set to 0. \sa addSubWindow()*/void QMdiArea::removeSubWindow(QWidget *widget){ if (!widget) { qWarning("QMdiArea::removeSubWindow: null pointer to widget"); return; } Q_D(QMdiArea); if (d->childWindows.isEmpty()) return; if (QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(widget)) { int index = d->childWindows.indexOf(child); if (index == -1) { qWarning("QMdiArea::removeSubWindow: window is not inside workspace"); return; } d->childWindows.removeAll(child); d->indicesToStackedChildren.removeAll(index); d->updateActiveWindow(index); child->setParent(0); return; } bool found = false; foreach (QMdiSubWindow *child, d->childWindows) { if (!sanityCheck(child, "QMdiArea::removeSubWindow")) continue; if (child->widget() == widget) { child->setWidget(0); Q_ASSERT(!child->widget()); found = true; break; } } if (!found) qWarning("QMdiArea::removeSubWindow: widget is not child of any window inside QMdiArea");}/*! \property QMdiArea::background \brief the background brush for the workspace This property sets the background brush for the workspace area itself. By default, it is a gray color, but can be any brush (e.g., colors, gradients or pixmaps).*/QBrush QMdiArea::background() const{ return d_func()->background;}void QMdiArea::setBackground(const QBrush &brush){ Q_D(QMdiArea); if (d->background != brush) { d->background = brush; update(); }}/*! If \a on is true, \a option is enabled on the MDI area; otherwise it is disabled. See AreaOption for the effect of each option. \sa AreaOption, testOption()*/void QMdiArea::setOption(AreaOption option, bool on){ Q_D(QMdiArea); if (on && !(d->options & option)) d->options |= option; else if (!on && (d->options & option)) d->options &= ~option;}/*! Returns true if \a option is enabled; otherwise returns false. \sa AreaOption, setOption()*/bool QMdiArea::testOption(AreaOption option) const{ return d_func()->options & option;}/*! \reimp*/void QMdiArea::childEvent(QChildEvent *childEvent){ Q_D(QMdiArea); if (childEvent->type() == QEvent::ChildPolished) { if (QMdiSubWindow *mdiChild = qobject_cast<QMdiSubWindow *>(childEvent->child())) { if (d->childWindows.indexOf(mdiChild) == -1) d->appendChild(mdiChild); } }}/*! \reimp*/void QMdiArea::resizeEvent(QResizeEvent *resizeEvent){ Q_D(QMdiArea); if (d->childWindows.isEmpty()) { resizeEvent->ignore(); return; } // Re-tile the views if we're in tiled mode. Re-tile means we will change // the geometry of the children, which in turn means 'isSubWindowsTiled' // is set to false, so we have to update the state at the end. if (d->isSubWindowsTiled) { d->tileCalledFromResizeEvent = true; tileSubWindows(); d->tileCalledFromResizeEvent = false; d->isSubWindowsTiled = true; d->startResizeTimer(); // We don't have scroll bars or any maximized views. return; } // Resize maximized views. bool hasMaximizedSubWindow = false; foreach (QMdiSubWindow *child, d->childWindows) { if (sanityCheck(child, "QMdiArea::resizeEvent") && child->isMaximized() && child->size() != resizeEvent->size()) { child->resize(resizeEvent->size()); if (!hasMaximizedSubWindow) hasMaximizedSubWindow = true; } } d->updateScrollBars(); // Minimized views are stacked under maximized views so there's // no need to re-arrange minimized views on-demand. Start a timer // just to make things faster with subsequent resize events. if (hasMaximizedSubWindow) d->startResizeTimer(); else d->arrangeMinimizedSubWindows();}/*! \reimp*/void QMdiArea::timerEvent(QTimerEvent *timerEvent){ Q_D(QMdiArea); if (timerEvent->timerId() == d->resizeTimerId) { killTimer(d->resizeTimerId); d->resizeTimerId = -1; d->arrangeMinimizedSubWindows(); }}/*! \reimp*/void QMdiArea::showEvent(QShowEvent *showEvent){ Q_D(QMdiArea); if (!d->pendingRearrangements.isEmpty()) { bool skipPlacement = false; foreach (Rearranger *rearranger, d->pendingRearrangements) { // If this is the case, we don't have to lay out pending child windows // since the rearranger will find a placement for them. if (rearranger->type() != Rearranger::IconTiler && !skipPlacement) skipPlacement = true; d->rearrange(rearranger); } d->pendingRearrangements.clear(); if (skipPlacement && !d->pendingPlacements.isEmpty()) d->pendingPlacements.clear(); } if (!d->pendingPlacements.isEmpty()) { foreach (QMdiSubWindow *window, d->pendingPlacements) { if (!window) continue; if (!window->testAttribute(Qt::WA_Resized)) { QSize newSize(window->sizeHint().boundedTo(viewport()->size())); window->resize(newSize.expandedTo(window->minimumSize())); } if (!window->testAttribute(Qt::WA_Moved) && !window->isMinimized() && !window->isMaximized()) { d->place(d->placer, window); } } d->pendingPlacements.clear(); } d->setChildActivationEnabled(true); d->activateCurrentWindow(); QAbstractScrollArea::showEvent(showEvent);}/*! \reimp*/bool QMdiArea::viewportEvent(QEvent *event){ Q_D(QMdiArea); switch (event->type()) { case QEvent::ChildRemoved: { d->isSubWindowsTiled = false; QObject *removedChild = static_cast<QChildEvent *>(event)->child(); for (int i = 0; i < d->childWindows.size(); ++i) { QObject *child = d->childWindows.at(i); if (!child || child == removedChild || !child->parent() || child->parent() != viewport()) { if (!testOption(DontMaximizeSubWindowOnActivation)) { // In this case we can only rely on the child being a QObject // (or 0), but let's try and see if we can get more information. QWidget *mdiChild = qobject_cast<QWidget *>(removedChild); if (mdiChild && mdiChild->isMaximized()) d->showActiveWindowMaximized = true; } d->childWindows.removeAt(i); d->indicesToStackedChildren.removeAll(i); d->updateActiveWindow(i); d->arrangeMinimizedSubWindows(); break; } } break; } case QEvent::Destroy: d->isSubWindowsTiled = false; d->indexToNextWindow = -1; d->indexToPreviousWindow = -1; d->resetActiveWindow(); d->childWindows.clear(); qWarning("QMdiArea: Deleting the view port is undefined, use setViewport instead."); break; default: break; } return QAbstractScrollArea::viewportEvent(event);}/*! \reimp*/void QMdiArea::scrollContentsBy(int dx, int dy){ Q_D(QMdiArea); const bool wasSubWindowsTiled = d->isSubWindowsTiled; d->ignoreGeometryChange = true; viewport()->scroll(isLeftToRight() ? dx : -dx, dy); d->arrangeMinimizedSubWindows(); d->ignoreGeometryChange = false; if (wasSubWindowsTiled) d->isSubWindowsTiled = true;}/*! Arranges all child windows in a tile pattern. \sa cascadeSubWindows()*/void QMdiArea::tileSubWindows(){ Q_D(QMdiArea); if (!d->regularTiler) d->regularTiler = new RegularTiler; d->rearrange(d->regularTiler);}/*! Arranges all the child windows in a cascade pattern. \sa tileSubWindows()*/void QMdiArea::cascadeSubWindows(){ Q_D(QMdiArea); if (!d->cascader) d->cascader = new SimpleCascader; d->rearrange(d->cascader);}/*! \reimp*/bool QMdiArea::event(QEvent *event){ Q_D(QMdiArea); switch (event->type()) {#ifdef Q_WS_WIN // QWidgetPrivate::hide_helper activates another sub-window when closing a // modal dialog on Windows (see activateWindow() inside the the ifdef). case QEvent::WindowUnblocked: d->activateCurrentWindow(); break;#endif case QEvent::WindowActivate: { d->isActivated = true; if (d->childWindows.isEmpty()) break; if (!d->active) d->activateCurrentWindow(); d->setChildActivationEnabled(false, true); break; } case QEvent::WindowDeactivate: d->isActivated = false; d->setChildActivationEnabled(false, true); break; case QEvent::StyleChange: // Re-tile the views if we're in tiled mode. Re-tile means we will change // the geometry of the children, which in turn means 'isSubWindowsTiled' // is set to false, so we have to update the state at the end. if (d->isSubWindowsTiled) { tileSubWindows(); d->isSubWindowsTiled = true; } break; case QEvent::WindowIconChange: foreach (QMdiSubWindow *window, d->childWindows) { if (sanityCheck(window, "QMdiArea::WindowIconChange")) QApplication::sendEvent(window, event); } break; case QEvent::Hide: d->setActive(d->active, false); d->setChildActivationEnabled(false); break; default: break; } return QAbstractScrollArea::event(event);}/*! \reimp*/bool QMdiArea::eventFilter(QObject *object, QEvent *event){ Q_D(QMdiArea); if (!qobject_cast<QMdiSubWindow *>(object)) { // QApplication events: if (event->type() == QEvent::ApplicationActivate && !d->active && isVisible() && !window()->isMinimized()) { d->activateCurrentWindow(); } else if (event->type() == QEvent::ApplicationDeactivate && d->active) { d->setActive(d->active, false); } return QAbstractScrollArea::eventFilter(object, event); } // QMdiSubWindow events: switch (event->type()) { case QEvent::Move: case QEvent::Resize: if (d->tileCalledFromResizeEvent) break; d->updateScrollBars(); if (!static_cast<QMdiSubWindow *>(object)->isMinimized()) d->isSubWindowsTiled = false; break; case QEvent::Show: case QEvent::Hide: d->isSubWindowsTiled = false; break; default: break; } return QAbstractScrollArea::eventFilter(object, event);}/*! \reimp*/void QMdiArea::paintEvent(QPaintEvent *paintEvent){ Q_D(QMdiArea); QPainter painter(viewport()); const QVector<QRect> exposedRects = paintEvent->region().rects(); for (int i = 0; i < exposedRects.size(); ++i) painter.fillRect(exposedRects.at(i), d->background);}/*! This slot is called by QAbstractScrollArea after setViewport() has been called. Reimplement this function in a subclass of QMdiArea to initialize the new \a viewport before it is used. \sa setViewport()*/void QMdiArea::setupViewport(QWidget *viewport){ foreach (QMdiSubWindow *child, d_func()->childWindows) { if (!sanityCheck(child, "QMdiArea::setupViewport")) continue; child->setParent(viewport, child->windowFlags()); }}#include "moc_qmdiarea.cpp"#endif // QT_NO_MDIAREA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -