📄 qmdiarea.cpp
字号:
return findMinOverlapRect(source, rects).topLeft(); QList<QRect> maxOverlappers; findMaxOverlappers(domain, nonInsiders, maxOverlappers); return findMinOverlapRect(maxOverlappers, rects).topLeft();}/*! \internal Places the rectangle defined by 'size' relative to 'rects' and 'domain' so that it overlaps 'rects' as little as possible and 'domain' as much as possible. Returns the position of the resulting rectangle.*/QPoint MinOverlapPlacer::place(const QSize &size, const QList<QRect> &rects, const QRect &domain) const{ if (size.isEmpty() || !domain.isValid()) return QPoint(); foreach (QRect rect, rects) { if (!rect.isValid()) return QPoint(); } QList<QRect> candidates; getCandidatePlacements(size, rects, domain, candidates); return findBestPlacement(domain, rects, candidates);}/*! \internal*/QMdiAreaPrivate::QMdiAreaPrivate() : cascader(0), regularTiler(0), iconTiler(0), placer(0), ignoreGeometryChange(false), ignoreWindowStateChange(false), isActivated(false), isSubWindowsTiled(false), showActiveWindowMaximized(false), tileCalledFromResizeEvent(false), updatesDisabledByUs(false), indexToNextWindow(-1), indexToPreviousWindow(-1), resizeTimerId(-1){}/*! \internal*/void QMdiAreaPrivate::_q_deactivateAllWindows(QMdiSubWindow *aboutToActivate){ if (ignoreWindowStateChange) return; Q_Q(QMdiArea); if (!aboutToActivate) aboutToBecomeActive = qobject_cast<QMdiSubWindow *>(q->sender()); else aboutToBecomeActive = aboutToActivate; Q_ASSERT(aboutToBecomeActive); foreach (QMdiSubWindow *child, childWindows) { if (!sanityCheck(child, "QMdiArea::deactivateAllWindows") || aboutToBecomeActive == child) continue; // We don't want to handle signals caused by child->showNormal(). ignoreWindowStateChange = true; if(!(options & QMdiArea::DontMaximizeSubWindowOnActivation) && !showActiveWindowMaximized) showActiveWindowMaximized = child->isMaximized() && child->isVisible(); if (showActiveWindowMaximized && child->isMaximized()) { if (q->updatesEnabled()) { updatesDisabledByUs = true; q->setUpdatesEnabled(false); } child->showNormal(); } if (child->isMinimized() && !child->isShaded() && !windowStaysOnTop(child)) child->lower(); ignoreWindowStateChange = false; child->d_func()->setActive(false); }}/*! \internal*/void QMdiAreaPrivate::_q_processWindowStateChanged(Qt::WindowStates oldState, Qt::WindowStates newState){ if (ignoreWindowStateChange) return; Q_Q(QMdiArea); QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(q->sender()); if (!child) return; // windowActivated if (!(oldState & Qt::WindowActive) && (newState & Qt::WindowActive)) emitWindowActivated(child); // windowDeactivated else if ((oldState & Qt::WindowActive) && !(newState & Qt::WindowActive)) resetActiveWindow(child); // windowMinimized if (!(oldState & Qt::WindowMinimized) && (newState & Qt::WindowMinimized)) { isSubWindowsTiled = false; arrangeMinimizedSubWindows(); // windowMaximized } else if (!(oldState & Qt::WindowMaximized) && (newState & Qt::WindowMaximized)) { internalRaise(child); // windowRestored } else if (!(newState & (Qt::WindowMaximized | Qt::WindowMinimized))) { internalRaise(child); if (oldState & Qt::WindowMinimized) arrangeMinimizedSubWindows(); }}/*! \internal*/void QMdiAreaPrivate::appendChild(QMdiSubWindow *child){ Q_Q(QMdiArea); Q_ASSERT(child && childWindows.indexOf(child) == -1); if (child->parent() != q->viewport()) child->setParent(q->viewport(), child->windowFlags()); childWindows.append(QPointer<QMdiSubWindow>(child)); if (!child->testAttribute(Qt::WA_Resized) && q->isVisible()) { QSize newSize(child->sizeHint().boundedTo(q->viewport()->size())); child->resize(newSize.expandedTo(child->minimumSize())); } if (!placer) placer = new MinOverlapPlacer; place(placer, child); if (hbarpolicy != Qt::ScrollBarAlwaysOff) child->setOption(QMdiSubWindow::AllowOutsideAreaHorizontally, true); else child->setOption(QMdiSubWindow::AllowOutsideAreaHorizontally, false); if (vbarpolicy != Qt::ScrollBarAlwaysOff) child->setOption(QMdiSubWindow::AllowOutsideAreaVertically, true); else child->setOption(QMdiSubWindow::AllowOutsideAreaVertically, false); internalRaise(child); indicesToStackedChildren.prepend(childWindows.size() - 1); Q_ASSERT(indicesToStackedChildren.size() == childWindows.size()); if (!(child->windowFlags() & Qt::SubWindow)) child->setWindowFlags(Qt::SubWindow); child->installEventFilter(q); QObject::connect(child, SIGNAL(aboutToActivate()), q, SLOT(_q_deactivateAllWindows())); QObject::connect(child, SIGNAL(windowStateChanged(Qt::WindowStates, Qt::WindowStates)), q, SLOT(_q_processWindowStateChanged(Qt::WindowStates, Qt::WindowStates)));}/*! \internal*/void QMdiAreaPrivate::place(Placer *placer, QMdiSubWindow *child){ if (!placer || !child) return; Q_Q(QMdiArea); if (!q->isVisible()) { // The window is only laid out when it's added to QMdiArea, // so there's no need to check that we don't have it in the // list already. appendChild() ensures that. pendingPlacements.append(child); return; } QList<QRect> rects; QRect parentRect = q->rect(); foreach (QMdiSubWindow *window, childWindows) { if (!sanityCheck(window, "QMdiArea::place") || window == child || !window->isVisibleTo(q) || !window->testAttribute(Qt::WA_Moved)) { continue; } QRect occupiedGeometry; if (window->isMaximized()) { occupiedGeometry = QRect(window->d_func()->oldGeometry.topLeft(), window->d_func()->restoreSize); } else { occupiedGeometry = window->geometry(); } rects.append(QStyle::visualRect(child->layoutDirection(), parentRect, occupiedGeometry)); } QPoint newPos = placer->place(child->size(), rects, parentRect); QRect newGeometry = QRect(newPos.x(), newPos.y(), child->width(), child->height()); child->setGeometry(QStyle::visualRect(child->layoutDirection(), parentRect, newGeometry));}/*! \internal*/void QMdiAreaPrivate::rearrange(Rearranger *rearranger){ if (!rearranger) return; Q_Q(QMdiArea); if (!q->isVisible()) { // Compress if we already have the rearranger in the list. int index = pendingRearrangements.indexOf(rearranger); if (index != -1) pendingRearrangements.move(index, pendingRearrangements.size() - 1); else pendingRearrangements.append(rearranger); return; } QList<QWidget *> widgets; const bool reverseList = rearranger->type() == Rearranger::RegularTiler; const QList<QMdiSubWindow *> subWindows = subWindowList(QMdiArea::StackingOrder, reverseList); foreach (QMdiSubWindow *child, subWindows) { if (!sanityCheck(child, "QMdiArea::rearrange") || !child->isVisible()) continue; if (rearranger->type() == Rearranger::IconTiler) { if (child->isMinimized() && !child->isShaded()) widgets.append(child); } else { if (child->isMinimized() && !child->isShaded()) continue; if (child->isMaximized() || child->isShaded()) child->showNormal(); widgets.append(child); } } if (active && rearranger->type() == Rearranger::RegularTiler) { // Move active window in front if necessary. That's the case if we // have any windows with staysOnTopHint set. int indexToActive = widgets.indexOf((QWidget *)active); if (indexToActive > 0) widgets.move(indexToActive, 0); } rearranger->rearrange(widgets, q->viewport()->rect()); if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty()) isSubWindowsTiled = true; else if (rearranger->type() == Rearranger::SimpleCascader) isSubWindowsTiled = false;}/*! \internal Arranges all minimized windows at the bottom of the workspace.*/void QMdiAreaPrivate::arrangeMinimizedSubWindows(){ if (!iconTiler) iconTiler = new IconTiler; rearrange(iconTiler);}/*! \internal*/void QMdiAreaPrivate::activateWindow(QMdiSubWindow *child){ if (childWindows.isEmpty()) { Q_ASSERT(!child); Q_ASSERT(!active); return; } if (!child) { if (active) { Q_ASSERT(active->d_func()->isActive); active->d_func()->setActive(false); resetActiveWindow(); } return; } if (child->isHidden() || child == active) return; child->d_func()->setActive(true);}/*! \internal*/void QMdiAreaPrivate::activateCurrentWindow(){ QMdiSubWindow *current = q_func()->currentSubWindow(); if (current && !isExplicitlyDeactivated(current)) { current->d_func()->activationEnabled = true; current->d_func()->setActive(true); }}/*! \internal*/void QMdiAreaPrivate::emitWindowActivated(QMdiSubWindow *activeWindow){ Q_Q(QMdiArea); Q_ASSERT(activeWindow); if (activeWindow == active) return; Q_ASSERT(activeWindow->d_func()->isActive); if (!aboutToBecomeActive) _q_deactivateAllWindows(activeWindow); Q_ASSERT(aboutToBecomeActive); // This is true only if 'DontMaximizeSubWindowOnActivation' is disabled // and the previous active window was maximized. if (showActiveWindowMaximized) { if (!activeWindow->isMaximized()) activeWindow->showMaximized(); showActiveWindowMaximized = false; } int indexToActiveWindow = childWindows.indexOf(activeWindow); Q_ASSERT(indexToActiveWindow != -1); setIndex(&indexToNextWindow, indexToActiveWindow + 1, 0, childWindows.size() - 1 , true); setIndex(&indexToPreviousWindow, indexToActiveWindow - 1, 0, childWindows.size() - 1, false); // Put in front to update stacking order int index = indicesToStackedChildren.indexOf(indexToActiveWindow); Q_ASSERT(index != -1); indicesToStackedChildren.move(index, 0); internalRaise(activeWindow); if (updatesDisabledByUs) { q->setUpdatesEnabled(true); updatesDisabledByUs = false; } Q_ASSERT(aboutToBecomeActive == activeWindow); active = activeWindow; aboutToBecomeActive = 0; Q_ASSERT(active->d_func()->isActive); if (active->isMaximized() && scrollBarsEnabled()) updateScrollBars(); emit q->subWindowActivated(active);}/*! \internal*/void QMdiAreaPrivate::resetActiveWindow(QMdiSubWindow *deactivatedWindow){ Q_Q(QMdiArea); if (deactivatedWindow) { if (deactivatedWindow != active) return; active = 0; if ((aboutToBecomeActive || isActivated || lastWindowAboutToBeDestroyed()) && !isExplicitlyDeactivated(deactivatedWindow) && !q->window()->isMinimized()) { return; } emit q->subWindowActivated(0); return; } if (aboutToBecomeActive) return; active = 0; emit q->subWindowActivated(0);}/*! \internal*/void QMdiAreaPrivate::updateActiveWindow(int removedIndex){ Q_ASSERT(indicesToStackedChildren.size() == childWindows.size()); if (childWindows.isEmpty()) { indexToNextWindow = -1; indexToPreviousWindow = -1; showActiveWindowMaximized = false; resetActiveWindow(); return; } // Update indices list for (int i = 0; i < indicesToStackedChildren.size(); ++i) { int *index = &indicesToStackedChildren[i]; if (*index > removedIndex) --*index; } // This is -1 only if there's no active window if (indexToNextWindow == -1) { Q_ASSERT(!active); return; } // Check if active window was removed if (indexToNextWindow - 1 == removedIndex) { activateWindow(childWindows.at(removedIndex)); } else if (indexToNextWindow == 0 && removedIndex == childWindows.size()) { activateWindow(childWindows.at(0)); // Active window is still in charge, update next and previous indices // if necessary. } else if (indexToNextWindow > removedIndex) { int nextCandidate = indexToNextWindow - 1; int prevCandidate = indexToPreviousWindow; if (indexToPreviousWindow >= removedIndex) --prevCandidate; setIndex(&indexToNextWindow, nextCandidate, 0, childWindows.size(), true); setIndex(&indexToPreviousWindow, prevCandidate, 0, childWindows.size(), false); }}/*! \internal*/void QMdiAreaPrivate::updateScrollBars(){ if (ignoreGeometryChange || !scrollBarsEnabled()) return; Q_Q(QMdiArea); QSize maxSize = q->maximumViewportSize(); QSize hbarExtent = hbar->sizeHint(); QSize vbarExtent = vbar->sizeHint(); if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)) { const int doubleFrameWidth = frameWidth * 2; if (hbarpolicy == Qt::ScrollBarAlwaysOn) maxSize.rheight() -= doubleFrameWidth; if (vbarpolicy == Qt::ScrollBarAlwaysOn) maxSize.rwidth() -= doubleFrameWidth; hbarExtent.rheight() += doubleFrameWidth; vbarExtent.rwidth() += doubleFrameWidth; } const QRect childrenRect = active && active->isMaximized() ? active->geometry() : viewport->childrenRect();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -