📄 qmainwindowlayout.cpp
字号:
return szHint;}QSize QMainWindowLayout::minimumSize() const{ if (!minSize.isValid()) { minSize = layoutState.minimumSize(); const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0); minSize = QSize(qMax(sbMin.width(), minSize.width()), sbMin.height() + minSize.height()); } return minSize;}void QMainWindowLayout::invalidate(){ QLayout::invalidate(); minSize = szHint = QSize();}/******************************************************************************** QMainWindowLayout - remaining stuff*/static void fixToolBarOrientation(QLayoutItem *item, int dockPos){#ifndef QT_NO_TOOLBAR QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget()); if (toolBar == 0) return; QRect oldGeo = toolBar->geometry(); QInternal::DockPosition pos = static_cast<QInternal::DockPosition>(dockPos); Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock ? Qt::Horizontal : Qt::Vertical; if (o != toolBar->orientation()) toolBar->setOrientation(o); QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize()) .expandedTo(toolBar->minimumSize()); if (toolBar->size() != hint) { QRect newGeo(oldGeo.topLeft(), hint); if (toolBar->layoutDirection() == Qt::RightToLeft) newGeo.moveRight(oldGeo.right()); toolBar->setGeometry(newGeo); }#else Q_UNUSED(item); Q_UNUSED(dockPos);#endif}void QMainWindowLayout::revert(QLayoutItem *widgetItem){ if (!savedState.isValid()) return; QWidget *widget = widgetItem->widget(); layoutState = savedState; currentGapPos = layoutState.indexOf(widget); fixToolBarOrientation(widgetItem, currentGapPos.at(1)); layoutState.unplug(currentGapPos); layoutState.fitLayout(); currentGapRect = layoutState.itemRect(currentGapPos); plug(widgetItem);}bool QMainWindowLayout::plug(QLayoutItem *widgetItem){ if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty()) return false; fixToolBarOrientation(widgetItem, currentGapPos.at(1)); QWidget *widget = widgetItem->widget(); QList<int> previousPath = layoutState.indexOf(widget); QLayoutItem *it = layoutState.plug(currentGapPos); Q_ASSERT(it == widgetItem); Q_UNUSED(it); if (!previousPath.isEmpty()) layoutState.remove(previousPath); if (dockOptions & QMainWindow::AnimatedDocks) { pluggingWidget = widget; QRect globalRect = currentGapRect; globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));#ifndef QT_NO_DOCKWIDGET if (qobject_cast<QDockWidget*>(widget) != 0) { QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout()); if (layout->nativeWindowDeco()) { globalRect.adjust(0, layout->titleHeight(), 0, 0); } else { int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, 0); globalRect.adjust(-fw, -fw, fw, fw); } }#endif widgetAnimator->animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks); } else {#ifndef QT_NO_DOCKWIDGET if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) dw->d_func()->plug(currentGapRect);#endif#ifndef QT_NO_TOOLBAR if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) tb->d_func()->plug(currentGapRect);#endif applyState(layoutState); savedState.clear();#ifndef QT_NO_DOCKWIDGET parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) emit dw->dockLocationChanged(toDockWidgetArea(currentGapPos.at(1)));#endif currentGapPos.clear(); updateGapIndicator(); } return true;}void QMainWindowLayout::allAnimationsFinished(){#ifndef QT_NO_DOCKWIDGET parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());#ifndef QT_NO_TABBAR foreach (QTabBar *tab_bar, usedTabBars) tab_bar->show();#endif#endif updateGapIndicator();}void QMainWindowLayout::animationFinished(QWidget *widget){ /* This signal is delivered from QWidgetAnimator over a qeued connection. The problem is that the widget can be deleted. This is handled as follows: The animator only ever animates widgets that have been added to this layout. If a widget is deleted during animation, the widget's destructor removes the widget form this layout. This in turn aborts the animation (see takeAt()) and this signal will never be delivered. If the widget is deleted after the animation is finished but before this qeued signal is delivered, the widget is no longer in the layout and we catch it here. The key is that QMainWindowLayoutState::contains() never dereferences the pointer. */ if (!layoutState.contains(widget)) return;#ifndef QT_NO_TOOLBAR if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) { QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout()); if (tbl->animating) { tbl->animating = false; if (tbl->expanded) tbl->layoutActions(tb->size()); tb->update(); } }#endif if (widget != pluggingWidget) return;#ifndef QT_NO_DOCKWIDGET if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) dw->d_func()->plug(currentGapRect);#endif#ifndef QT_NO_TOOLBAR if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) tb->d_func()->plug(currentGapRect);#endif applyState(layoutState, false);#ifndef QT_NO_DOCKWIDGET#ifndef QT_NO_TABBAR if (qobject_cast<QDockWidget*>(widget) != 0) { QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget); Q_ASSERT(info != 0); info->setCurrentTab(widget); }#endif if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) emit dw->dockLocationChanged(toDockWidgetArea(currentGapPos.at(1)));#endif savedState.clear(); currentGapPos.clear(); pluggingWidget = 0; updateGapIndicator();}void QMainWindowLayout::restore(bool keepSavedState){ if (!savedState.isValid()) return; layoutState = savedState; applyState(layoutState); if (!keepSavedState) savedState.clear(); currentGapPos.clear(); pluggingWidget = 0; updateGapIndicator();}QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) : QLayout(mainwindow), layoutState(mainwindow), savedState(mainwindow), dockOptions(QMainWindow::AnimatedDocks|QMainWindow::AllowTabbedDocks), statusbar(0){#ifndef QT_NO_DOCKWIDGET separatorMoveTimer = new QTimer(this); separatorMoveTimer->setSingleShot(true); separatorMoveTimer->setInterval(0); connect(separatorMoveTimer, SIGNAL(timeout()), this, SLOT(doSeparatorMove()));#endif#ifndef QT_NO_RUBBERBAND gapIndicator = new QRubberBand(QRubberBand::Rectangle, mainwindow); gapIndicator->hide();#endif pluggingWidget = 0; setObjectName(mainwindow->objectName() + QLatin1String("_layout")); widgetAnimator = new QWidgetAnimator(this); connect(widgetAnimator, SIGNAL(finished(QWidget*)), this, SLOT(animationFinished(QWidget*)), Qt::QueuedConnection); connect(widgetAnimator, SIGNAL(finishedAll()), this, SLOT(allAnimationsFinished()));}QMainWindowLayout::~QMainWindowLayout(){ layoutState.deleteAllLayoutItems(); layoutState.deleteCentralWidgetItem();#ifdef Q_WS_MAC for (int i = 0; i < toolbarItemsCopy.size(); ++i) CFRelease(toolbarItemsCopy.at(i)); toolbarItemsCopy.clear(); hitoolbarHash.clear();#endif delete statusbar;}void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts){ if (opts == dockOptions) return; dockOptions = opts;#ifndef QT_NO_DOCKWIDGET setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);#endif invalidate();}#ifndef QT_NO_STATUSBARQStatusBar *QMainWindowLayout::statusBar() const{ return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }void QMainWindowLayout::setStatusBar(QStatusBar *sb){ if (sb) addChildWidget(sb); delete statusbar; statusbar = sb ? new QWidgetItem(sb) : 0; invalidate();}#endif // QT_NO_STATUSBARQWidget *QMainWindowLayout::centralWidget() const{ return layoutState.centralWidget();}void QMainWindowLayout::setCentralWidget(QWidget *widget){ if (widget != 0) addChildWidget(widget); layoutState.setCentralWidget(widget); invalidate();}QLayoutItem *QMainWindowLayout::unplug(QWidget *widget){ QList<int> path = layoutState.indexOf(widget); if (path.isEmpty()) return 0; QLayoutItem *item = layoutState.item(path); if (widget->isWindow()) return item; QRect r = layoutState.itemRect(path); savedState = layoutState;#ifndef QT_NO_DOCKWIDGET if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { dw->d_func()->unplug(r); }#endif#ifndef QT_NO_TOOLBAR if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) { tb->d_func()->unplug(r); }#endif savedState.fitLayout(); layoutState.unplug(path); currentGapPos = path; currentGapRect = r; updateGapIndicator(); fixToolBarOrientation(item, currentGapPos.at(1)); return item;}void QMainWindowLayout::updateGapIndicator(){#ifndef QT_NO_RUBBERBAND if (widgetAnimator->animating() || currentGapPos.isEmpty()) { gapIndicator->hide(); } else { if (gapIndicator->geometry() != currentGapRect) gapIndicator->setGeometry(currentGapRect); if (!gapIndicator->isVisible()) gapIndicator->show(); }#endif}QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos){ if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || pluggingWidget != 0 || widgetItem == 0) return QList<int>(); QWidget *widget = widgetItem->widget(); QPoint pos = parentWidget()->mapFromGlobal(mousePos); if (!savedState.isValid()) savedState = layoutState; QList<int> path = savedState.gapIndex(widget, pos); if (!path.isEmpty()) { bool allowed = false;#ifndef QT_NO_DOCKWIDGET if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));#endif#ifndef QT_NO_TOOLBAR if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));#endif if (!allowed) path.clear(); } if (path == currentGapPos) return currentGapPos; // the gap is already there currentGapPos = path; if (path.isEmpty()) { fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal restore(true); return QList<int>(); } fixToolBarOrientation(widgetItem, currentGapPos.at(1)); QMainWindowLayoutState newState = savedState; if (!newState.insertGap(path, widgetItem)) { restore(true); // not enough space return QList<int>(); } QSize min = newState.minimumSize(); QSize size = newState.rect.size(); if (min.width() > size.width() || min.height() > size.height()) { restore(true); return QList<int>(); } newState.fitLayout(); currentGapRect = newState.gapRect(currentGapPos);#ifndef QT_NO_DOCKWIDGET parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());#endif layoutState = newState; applyState(layoutState); updateGapIndicator(); return path;}void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate){#ifndef QT_NO_DOCKWIDGET#ifndef QT_NO_TABBAR QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars(); QSet<QTabBar*> retired = usedTabBars - used; usedTabBars = used; foreach (QTabBar *tab_bar, retired) { tab_bar->hide(); while (tab_bar->count() > 0) tab_bar->removeTab(0); unusedTabBars.append(tab_bar); }#endif // QT_NO_TABBAR#endif newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate);}void QMainWindowLayout::saveState(QDataStream &stream) const{ layoutState.saveState(stream);}bool QMainWindowLayout::restoreState(QDataStream &stream){ savedState = layoutState; layoutState.clear(); layoutState.rect = savedState.rect; if (!layoutState.restoreState(stream, savedState)) { layoutState.deleteAllLayoutItems(); layoutState = savedState; if (parentWidget()->isVisible()) applyState(layoutState, false); // hides tabBars allocated by newState return false; } if (parentWidget()->isVisible()) { layoutState.fitLayout(); applyState(layoutState, false); } savedState.deleteAllLayoutItems(); savedState.clear();#ifndef QT_NO_DOCKWIDGET#ifndef QT_NO_TABBAR if (parentWidget()->isVisible()) { foreach (QTabBar *tab_bar, usedTabBars) tab_bar->show(); }#endif#endif return true;}// Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases// for example, you have a toolbar in the top area and then you suddenly turn on// HIToolbar.bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const{#ifndef Q_WS_MAC Q_UNUSED(toolbar); return false;#else return qtoolbarsInHIToolbarList.contains(toolbar) || ((toolBarArea(toolbar) == Qt::TopToolBarArea) && layoutState.mainWindow->unifiedTitleAndToolBarOnMac());#endif}#endif // QT_NO_MAINWINDOW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -