27 focusNext = focusPrev = q;
28 focusPolicy = Qt::NoFocus;
30 adjustWindowFlags(&wFlags);
33 q->setParentItem(parentItem);
34 q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
35 q->setGraphicsItem(q);
38 q->unsetWindowFrameMargins();
39 flags |= QGraphicsItem::ItemUsesExtendedStyleOption;
40 flags |= QGraphicsItem::ItemSendsGeometryChanges;
41 if (windowFlags & Qt::Window)
42 flags |= QGraphicsItem::ItemIsPanel;
131 Q_Q(QGraphicsWidget);
133 this->palette = palette;
136 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
141 for (
int i = 0; i < children.size(); ++i) {
142 QGraphicsItem *item = children.at(i);
143 if (item->isWidget()) {
144 QGraphicsWidget *w =
static_cast<QGraphicsWidget *>(item);
145 if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
146 w->d_func()->resolvePalette(mask);
148 item->d_ptr->resolvePalette(mask);
153 QEvent event(QEvent::PaletteChange);
154 QCoreApplication::sendEvent(q, &event);
159 Q_Q(QGraphicsWidget);
160 if ((direction == Qt::RightToLeft) == (testAttribute(Qt::WA_RightToLeft)))
162 q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));
165 for (
int i = 0; i < children.size(); ++i) {
166 QGraphicsItem *item = children.at(i);
167 if (item->isWidget()) {
168 QGraphicsWidget *widget =
static_cast<QGraphicsWidget *>(item);
169 if (widget->parentWidget() && !widget->testAttribute(Qt::WA_SetLayoutDirection))
170 widget->d_func()->setLayoutDirection_helper(direction);
175 QEvent e(QEvent::LayoutDirectionChange);
176 QCoreApplication::sendEvent(q, &e);
229 Q_Q(QGraphicsWidget);
234 if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
239 for (
int i = 0; i < children.size(); ++i) {
240 QGraphicsItem *item = children.at(i);
241 if (item->isWidget()) {
242 QGraphicsWidget *w =
static_cast<QGraphicsWidget *>(item);
243 if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
244 w->d_func()->resolveFont(mask);
246 item->d_ptr->resolveFont(mask);
253 QEvent event(QEvent::FontChange);
254 QCoreApplication::sendEvent(q, &event);
272 Q_Q(QGraphicsWidget);
274 q->initStyleOption(option);
275 option->rect.setHeight(titleBarHeight(*option));
276 option->titleBarFlags = windowFlags;
277 option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
278 option->activeSubControls = windowData->hoveredSubControl;
279 bool isActive = q->isActiveWindow();
280 option->state.setFlag(QStyle::State_Active, isActive);
282 option->titleBarState = Qt::WindowActive;
283 option->titleBarState |= QStyle::State_Active;
285 option->titleBarState = Qt::WindowNoState;
287 QFont windowTitleFont = QApplication::font(
"QMdiSubWindowTitleBar");
288 QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel,
nullptr);
289 option->text = QFontMetrics(windowTitleFont).elidedText(
290 windowData->windowTitle, Qt::ElideRight, textRect.width());
295 bool customize = (*flags & (Qt::CustomizeWindowHint
296 | Qt::FramelessWindowHint
297 | Qt::WindowTitleHint
298 | Qt::WindowSystemMenuHint
299 | Qt::WindowMinimizeButtonHint
300 | Qt::WindowMaximizeButtonHint
301 | Qt::WindowContextHelpButtonHint));
303 uint type = (*flags & Qt::WindowType_Mask);
306 else if (type == Qt::Dialog || type == Qt::Sheet)
307 *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint;
308 else if (type == Qt::Tool)
309 *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
310 else if (type == Qt::Window || type == Qt::SubWindow)
311 *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
312 | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
317 Q_Q(QGraphicsWidget);
319 if (windowData->grabbedSection != Qt::NoSection) {
320 if (windowData->grabbedSection == Qt::TitleBarArea) {
321 windowData->buttonSunken =
false;
322 QStyleOptionTitleBar bar;
325 bar.rect = q->windowFrameRect().toRect();
326 bar.rect.moveTo(0,0);
327 bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
329 if (windowFrameMargins) {
330 pos.rx() += windowFrameMargins->left();
331 pos.ry() += windowFrameMargins->top();
333 bar.subControls = QStyle::SC_TitleBarCloseButton;
334 if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
335 QStyle::SC_TitleBarCloseButton,
336 event->widget()).contains(pos.toPoint())) {
340 if (!(
static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
341 windowData->grabbedSection = Qt::NoSection;
374 const QGraphicsWidget *widget,
375 bool heightForWidth =
true)
377 qreal minimumHeightForWidth = -1;
378 const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth();
379 if (hasHFW == heightForWidth) {
380 minimumHeightForWidth = hasHFW
381 ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
382 : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width();
385 const qreal constraint = width;
386 while (maxh - minh > 0.1) {
387 qreal middle = minh + (maxh - minh)/2;
392 ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height()
393 : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width();
394 if (hfw > constraint) {
396 }
else if (hfw <= constraint) {
400 minimumHeightForWidth = maxh;
402 return minimumHeightForWidth;
412 const QGraphicsWidget *widget)
414 const QSizeF current = widget->size();
416 qreal minw = proposed.width();
417 qreal maxw = current.width();
418 qreal minh = proposed.height();
419 qreal maxh = current.height();
421 qreal middlew = maxw;
422 qreal middleh = maxh;
424 min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget);
427 if (maxw - minw < 0.1) {
432 middlew = minw + (maxw - minw)/2.0;
433 middleh = minh + (maxh - minh)/2.0;
435 min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
437 if (min_hfw > middleh) {
440 }
else if (min_hfw <= middleh) {
444 }
while (maxw != minw);
446 min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
449 if (min_hfw < maxh) {
450 result = QSizeF(middlew, min_hfw);
453 result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh);
459 QRectF *rect, Qt::WindowFrameSection section,
460 const QSizeF &min,
const QSizeF &max,
461 const QGraphicsWidget *widget)
463 const QRectF proposedRect = *rect;
464 qreal width = qBound(min.width(), proposedRect.width(), max.width());
465 qreal height = qBound(min.height(), proposedRect.height(), max.height());
467 const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth();
468 const bool hasWFH = QGraphicsLayoutItemPrivate::get(widget)->hasWidthForHeight();
470 const bool widthChanged = proposedRect.width() != widget->size().width();
471 const bool heightChanged = proposedRect.height() != widget->size().height();
473 if (hasHFW || hasWFH) {
474 if (widthChanged || heightChanged) {
480 minExtent = min.height();
481 maxExtent = max.height();
483 proposed = proposedRect.height();
486 minExtent = min.width();
487 maxExtent = max.width();
489 proposed = proposedRect.width();
491 if (minimumHeightForWidth(constraint, minExtent, maxExtent, widget, hasHFW) > proposed) {
492 QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
493 width = effectiveSize.width();
494 height = effectiveSize.height();
500 case Qt::LeftSection:
501 rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
502 qRound(width), startGeometry.height());
504 case Qt::TopLeftSection:
505 rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height),
506 qRound(width), qRound(height));
509 rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height),
510 startGeometry.width(), qRound(height));
512 case Qt::TopRightSection:
513 rect->setTop(rect->bottom() - qRound(height));
514 rect->setWidth(qRound(width));
516 case Qt::RightSection:
517 rect->setWidth(qRound(width));
519 case Qt::BottomRightSection:
520 rect->setWidth(qRound(width));
521 rect->setHeight(qRound(height));
523 case Qt::BottomSection:
524 rect->setHeight(qRound(height));
526 case Qt::BottomLeftSection:
527 rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
528 qRound(width), qRound(height));
537 Q_Q(QGraphicsWidget);
539 if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
542 QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos());
543 QLineF parentDelta(q->mapToParent(delta.p1()), q->mapToParent(delta.p2()));
544 QLineF parentXDelta(q->mapToParent(QPointF(delta.p1().x(), 0)), q->mapToParent(QPointF(delta.p2().x(), 0)));
545 QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y())));
548 switch (windowData->grabbedSection) {
549 case Qt::LeftSection:
550 newGeometry = QRectF(windowData->startGeometry.topLeft()
551 + QPointF(parentXDelta.dx(), parentXDelta.dy()),
552 windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
554 case Qt::TopLeftSection:
555 newGeometry = QRectF(windowData->startGeometry.topLeft()
556 + QPointF(parentDelta.dx(), parentDelta.dy()),
557 windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
560 newGeometry = QRectF(windowData->startGeometry.topLeft()
561 + QPointF(parentYDelta.dx(), parentYDelta.dy()),
562 windowData->startGeometry.size() - QSizeF(0, delta.dy()));
564 case Qt::TopRightSection:
565 newGeometry = QRectF(windowData->startGeometry.topLeft()
566 + QPointF(parentYDelta.dx(), parentYDelta.dy()),
567 windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
569 case Qt::RightSection:
570 newGeometry = QRectF(windowData->startGeometry.topLeft(),
571 windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
573 case Qt::BottomRightSection:
574 newGeometry = QRectF(windowData->startGeometry.topLeft(),
575 windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
577 case Qt::BottomSection:
578 newGeometry = QRectF(windowData->startGeometry.topLeft(),
579 windowData->startGeometry.size() + QSizeF(0, delta.dy()));
581 case Qt::BottomLeftSection:
582 newGeometry = QRectF(windowData->startGeometry.topLeft()
583 + QPointF(parentXDelta.dx(), parentXDelta.dy()),
584 windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
586 case Qt::TitleBarArea:
587 newGeometry = QRectF(windowData->startGeometry.topLeft()
588 + QPointF(parentDelta.dx(), parentDelta.dy()),
589 windowData->startGeometry.size());
595 if (windowData->grabbedSection != Qt::NoSection) {
596 _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
597 windowData->grabbedSection,
598 q->effectiveSizeHint(Qt::MinimumSize),
599 q->effectiveSizeHint(Qt::MaximumSize),
601 q->setGeometry(newGeometry);
607 Q_Q(QGraphicsWidget);
613 if (q->rect().contains(event->pos())) {
614 if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
619 bool wasMouseOver = windowData->buttonMouseOver;
620 QRect oldButtonRect = windowData->buttonRect;
621 windowData->buttonRect = QRect();
622 windowData->buttonMouseOver =
false;
624 QStyleOptionTitleBar bar;
626 if (windowFrameMargins) {
627 pos.rx() += windowFrameMargins->left();
628 pos.ry() += windowFrameMargins->top();
631 bar.rect = q->windowFrameRect().toRect();
632 bar.rect.moveTo(0,0);
633 bar.rect.setHeight(
int(titleBarHeight(bar)));
635 Qt::CursorShape cursorShape = Qt::ArrowCursor;
636 bool needsSetCursorCall =
true;
637 switch (q->windowFrameSectionAt(event->pos())) {
638 case Qt::TopLeftSection:
639 case Qt::BottomRightSection:
640 cursorShape = Qt::SizeFDiagCursor;
642 case Qt::TopRightSection:
643 case Qt::BottomLeftSection:
644 cursorShape = Qt::SizeBDiagCursor;
646 case Qt::LeftSection:
647 case Qt::RightSection:
648 cursorShape = Qt::SizeHorCursor;
651 case Qt::BottomSection:
652 cursorShape = Qt::SizeVerCursor;
654 case Qt::TitleBarArea:
655 windowData->buttonRect = q->style()->subControlRect(
656 QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton,
nullptr);
657 if (windowData->buttonRect.contains(pos.toPoint()))
658 windowData->buttonMouseOver =
true;
662 needsSetCursorCall =
false;
666 if (needsSetCursorCall)
667 q->setCursor(cursorShape);
669 Q_UNUSED(needsSetCursorCall);
670 Q_UNUSED(cursorShape);
673 windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(),
nullptr);
674 if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
675 windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;
677 if (windowData->buttonMouseOver != wasMouseOver) {
678 if (!oldButtonRect.isNull())
679 q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
680 if (!windowData->buttonRect.isNull())
681 q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
719void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene)
721 Q_Q(QGraphicsWidget);
722 Q_ASSERT(focusNext && focusPrev);
724 if (q_ptr->isPanel()) {
735 QGraphicsWidget *focusFirst = q;
736 QGraphicsWidget *focusBefore = focusPrev;
737 QGraphicsWidget *focusLast = focusFirst;
738 QGraphicsWidget *focusAfter = focusNext;
740 if (!q->isAncestorOf(focusAfter))
742 focusLast = focusAfter;
743 }
while ((focusAfter = focusAfter->d_func()->focusNext));
745 if (!parent && oldScene && oldScene != newScene && oldScene->d_func()->tabFocusFirst == q) {
747 oldScene->d_func()->tabFocusFirst = (focusAfter != q) ? focusAfter :
nullptr;
751 focusBefore->d_func()->focusNext = focusAfter;
753 focusAfter->d_func()->focusPrev = focusBefore;
758 QGraphicsWidget *newFocusFirst = newParent;
759 QGraphicsWidget *newFocusLast = newFocusFirst;
760 QGraphicsWidget *newFocusAfter = newFocusFirst->d_func()->focusNext;
762 if (!newParent->isAncestorOf(newFocusAfter))
764 newFocusLast = newFocusAfter;
765 }
while ((newFocusAfter = newFocusAfter->d_func()->focusNext));
767 newFocusLast->d_func()->focusNext = q;
768 focusLast->d_func()->focusNext = newFocusAfter;
770 newFocusAfter->d_func()->focusPrev = focusLast;
771 focusPrev = newFocusLast;
774 focusPrev = focusLast;
775 focusLast->d_func()->focusNext = q;