1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 Uwe Kindler
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 or (at your option) any later version.
19 ** The licenses are as published by the Free Software Foundation
20 ** and appearing in the file LICENSE.LGPLv21 included in the packaging
21 ** of this file. Please review the following information to ensure
22 ** the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 3 or (at your option) any later version
28 ** approved by the KDE Free Qt Foundation. The licenses are as published by
29 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
30 ** included in the packaging of this file. Please review the following
31 ** information to ensure the GNU General Public License requirements will
32 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
33 **
34 ****************************************************************************/
35 
36 #include "dockwidgettab.h"
37 
38 #include "ads_globals.h"
39 #include "dockareawidget.h"
40 #include "dockmanager.h"
41 #include "dockoverlay.h"
42 #include "dockwidget.h"
43 #include "elidinglabel.h"
44 #include "floatingdockcontainer.h"
45 #include "floatingdragpreview.h"
46 #include "iconprovider.h"
47 
48 #include <utils/theme/theme.h>
49 
50 #include <QApplication>
51 #include <QBoxLayout>
52 #include <QLabel>
53 #include <QLoggingCategory>
54 #include <QMenu>
55 #include <QMouseEvent>
56 #include <QPushButton>
57 #include <QSplitter>
58 #include <QStyle>
59 #include <QStyleOption>
60 #include <QToolButton>
61 #include <QPainter>
62 #include <QStylePainter>
63 
64 #include <iostream>
65 
66 static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWarningMsg)
67 
68 namespace ADS
69 {
70     using TabLabelType = ElidingLabel;
71 
72     /**
73      * Private data class of DockWidgetTab class (pimpl)
74      */
75     class DockWidgetTabPrivate
76     {
77     public:
78         DockWidgetTab *q;
79         DockWidget *m_dockWidget = nullptr;
80         QLabel *m_iconLabel = nullptr;
81         TabLabelType *m_titleLabel = nullptr;
82         QPoint m_globalDragStartMousePosition;
83         QPoint m_dragStartMousePosition;
84         bool m_isActiveTab = false;
85         DockAreaWidget *m_dockArea = nullptr;
86         eDragState m_dragState = DraggingInactive;
87         AbstractFloatingWidget *m_floatingWidget = nullptr;
88         QIcon m_icon;
89         TabButton *m_closeButton = nullptr;
90         QPoint m_tabDragStartPosition;
91 
92         /**
93          * Private data constructor
94          */
95         DockWidgetTabPrivate(DockWidgetTab *parent);
96 
97         /**
98          * Creates the complete layout including all controls
99          */
100         void createLayout();
101 
102         /**
103          * Moves the tab depending on the position in the given mouse event
104          */
105         void moveTab(QMouseEvent *event);
106 
107         /**
108          * Test function for current drag state
109          */
isDraggingState(eDragState dragState) const110         bool isDraggingState(eDragState dragState) const { return this->m_dragState == dragState; }
111 
112         /**
113          * Starts floating of the dock widget that belongs to this title bar
114          * Returns true, if floating has been started and false if floating
115          * is not possible for any reason
116          */
117         bool startFloating(eDragState draggingState = DraggingFloatingWidget);
118 
119         /**
120          * Returns true if the given config flag is set
121          */
testConfigFlag(DockManager::eConfigFlag flag) const122         bool testConfigFlag(DockManager::eConfigFlag flag) const
123         {
124             return DockManager::testConfigFlag(flag);
125         }
126 
127         /**
128          * Creates the close button as QPushButton or as QToolButton
129          */
createCloseButton() const130         TabButton *createCloseButton() const
131         {
132             /*
133             if (testConfigFlag(DockManager::TabCloseButtonIsToolButton)) {
134                 auto button = new QToolButton();
135                 button->setAutoRaise(true);
136                 return button;
137             } else {
138                 return new QPushButton();
139             }
140             */
141             return new TabButton();
142         }
143 
144         template<typename T>
createFloatingWidget(T * widget,bool opaqueUndocking)145         AbstractFloatingWidget *createFloatingWidget(T *widget, bool opaqueUndocking)
146         {
147             if (opaqueUndocking) {
148                 return new FloatingDockContainer(widget);
149             } else {
150                 auto w = new FloatingDragPreview(widget);
151                 QObject::connect(w, &FloatingDragPreview::draggingCanceled, q, [=]() {
152                     m_dragState = DraggingInactive;
153                 });
154                 return w;
155             }
156         }
157 
158         /**
159          * Saves the drag start position in global and local coordinates
160          */
saveDragStartMousePosition(const QPoint & globalPos)161         void saveDragStartMousePosition(const QPoint &globalPos)
162         {
163             m_globalDragStartMousePosition = globalPos;
164             m_dragStartMousePosition = q->mapFromGlobal(globalPos);
165         }
166     }; // class DockWidgetTabPrivate
167 
DockWidgetTabPrivate(DockWidgetTab * parent)168     DockWidgetTabPrivate::DockWidgetTabPrivate(DockWidgetTab *parent)
169         : q(parent)
170     {}
171 
createLayout()172     void DockWidgetTabPrivate::createLayout()
173     {
174         m_titleLabel = new TabLabelType();
175         m_titleLabel->setElideMode(Qt::ElideRight);
176         m_titleLabel->setText(m_dockWidget->windowTitle());
177         m_titleLabel->setObjectName("dockWidgetTabLabel");
178         m_titleLabel->setAlignment(Qt::AlignCenter);
179         QObject::connect(m_titleLabel,
180                          &ElidingLabel::elidedChanged,
181                          q,
182                          &DockWidgetTab::elidedChanged);
183 
184         m_closeButton = createCloseButton();
185         m_closeButton->setObjectName("tabCloseButton");
186         internal::setButtonIcon(m_closeButton,
187                                 QStyle::SP_TitleBarCloseButton,
188                                 TabCloseIcon);
189         m_closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
190         m_closeButton->setIconSize(QSize(11, 11));
191         m_closeButton->setFixedSize(QSize(17, 17));
192         q->onDockWidgetFeaturesChanged();
193         internal::setToolTip(m_closeButton, QObject::tr("Close Tab"));
194         QObject::connect(m_closeButton,
195                          &QAbstractButton::clicked,
196                          q,
197                          &DockWidgetTab::closeRequested);
198 
199         QFontMetrics fontMetrics(m_titleLabel->font());
200         int spacing = qRound(fontMetrics.height() / 4.0);
201 
202         // Fill the layout
203         QBoxLayout *boxLayout = new QBoxLayout(QBoxLayout::LeftToRight);
204         boxLayout->setContentsMargins(2 * spacing, 0, 0, 0);
205         boxLayout->setSpacing(0);
206         q->setLayout(boxLayout);
207         boxLayout->addWidget(m_titleLabel, 1, Qt::AlignVCenter);
208         boxLayout->addSpacing(qRound(spacing * 4.0 / 3.0));
209         boxLayout->addWidget(m_closeButton, 0, Qt::AlignVCenter);
210         boxLayout->addSpacing(1);
211         boxLayout->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
212 
213         if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
214             m_closeButton->setCheckable(true);
215 
216         m_titleLabel->setVisible(true);
217     }
218 
moveTab(QMouseEvent * event)219     void DockWidgetTabPrivate::moveTab(QMouseEvent *event)
220     {
221         event->accept();
222         QPoint distance = event->globalPos() - m_globalDragStartMousePosition;
223         distance.setY(0);
224         auto targetPos = distance + m_tabDragStartPosition;
225         targetPos.rx() = qMax(targetPos.x(), 0);
226         targetPos.rx() = qMin(q->parentWidget()->rect().right() - q->width() + 1, targetPos.rx());
227         q->move(targetPos);
228         q->raise();
229     }
230 
startFloating(eDragState draggingState)231     bool DockWidgetTabPrivate::startFloating(eDragState draggingState)
232     {
233         auto dockContainer = m_dockWidget->dockContainer();
234         qCInfo(adsLog) << "isFloating " << dockContainer->isFloating();
235         qCInfo(adsLog) << "areaCount " << dockContainer->dockAreaCount();
236         qCInfo(adsLog) << "widgetCount " << m_dockWidget->dockAreaWidget()->dockWidgetsCount();
237         // if this is the last dock widget inside of this floating widget,
238         // then it does not make any sense, to make it floating because
239         // it is already floating
240         if (dockContainer->isFloating() && (dockContainer->visibleDockAreaCount() == 1)
241             && (m_dockWidget->dockAreaWidget()->dockWidgetsCount() == 1)) {
242             return false;
243         }
244 
245         qCInfo(adsLog) << "startFloating";
246         m_dragState = draggingState;
247         AbstractFloatingWidget *floatingWidget = nullptr;
248         bool opaqueUndocking = DockManager::testConfigFlag(DockManager::OpaqueUndocking)
249                                || (DraggingFloatingWidget != draggingState);
250 
251         // If section widget has multiple tabs, we take only one tab
252         // If it has only one single tab, we can move the complete
253         // dock area into floating widget
254         QSize size;
255         if (m_dockArea->dockWidgetsCount() > 1) {
256             floatingWidget = createFloatingWidget(m_dockWidget, opaqueUndocking);
257             size = m_dockWidget->size();
258         } else {
259             floatingWidget = createFloatingWidget(m_dockArea, opaqueUndocking);
260             size = m_dockArea->size();
261         }
262 
263         if (DraggingFloatingWidget == draggingState) {
264             floatingWidget->startFloating(m_dragStartMousePosition, size, DraggingFloatingWidget, q);
265             auto Overlay = m_dockWidget->dockManager()->containerOverlay();
266             Overlay->setAllowedAreas(OuterDockAreas);
267             this->m_floatingWidget = floatingWidget;
268         } else {
269             floatingWidget->startFloating(m_dragStartMousePosition, size, DraggingInactive, nullptr);
270         }
271 
272         return true;
273     }
274 
275 
TabButton(QWidget * parent)276     TabButton::TabButton(QWidget *parent)
277         : TabButtonType(parent)
278         , m_active(false)
279         , m_focus(false)
280     {}
281 
setActive(bool value)282     void TabButton::setActive(bool value) { m_active = value; }
setFocus(bool value)283     void TabButton::setFocus(bool value) { m_focus = value; }
284 
paintEvent(QPaintEvent * event)285     void TabButton::paintEvent(QPaintEvent *event)
286     {
287         Q_UNUSED(event)
288 
289         QStylePainter p(this);
290         QStyleOptionToolButton opt;
291         initStyleOption(&opt);
292         opt.icon = QIcon(); // set to null icon otherwise it is drawn twice
293         p.drawComplexControl(QStyle::CC_ToolButton, opt);
294 
295         QIcon::Mode mode = QIcon::Mode::Normal;
296         if (m_active)
297             mode = QIcon::Mode::Active;
298         if (m_focus)
299             mode = QIcon::Mode::Selected;
300 
301         const QPoint iconPosition = rect().center() - QPoint(iconSize().width() * 0.5,
302                                                              iconSize().height() * 0.5);
303 
304         p.drawPixmap(iconPosition, icon().pixmap(iconSize(), mode));
305     }
306 
307 
DockWidgetTab(DockWidget * dockWidget,QWidget * parent)308     DockWidgetTab::DockWidgetTab(DockWidget *dockWidget, QWidget *parent)
309         : QFrame(parent)
310         , d(new DockWidgetTabPrivate(this))
311     {
312         setAttribute(Qt::WA_NoMousePropagation, true);
313         d->m_dockWidget = dockWidget;
314         d->createLayout();
315         if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
316             setFocusPolicy(Qt::ClickFocus);
317     }
318 
~DockWidgetTab()319     DockWidgetTab::~DockWidgetTab()
320     {
321         qCInfo(adsLog) << Q_FUNC_INFO;
322         delete d;
323     }
324 
mousePressEvent(QMouseEvent * event)325     void DockWidgetTab::mousePressEvent(QMouseEvent *event)
326     {
327         if (event->button() == Qt::LeftButton) {
328             event->accept();
329             d->saveDragStartMousePosition(event->globalPos());
330             d->m_dragState = DraggingMousePressed;
331             emit clicked();
332             return;
333         }
334         Super::mousePressEvent(event);
335     }
336 
mouseReleaseEvent(QMouseEvent * event)337     void DockWidgetTab::mouseReleaseEvent(QMouseEvent *event)
338     {
339         if (event->button() == Qt::LeftButton) {
340             auto currentDragState = d->m_dragState;
341             d->m_globalDragStartMousePosition = QPoint();
342             d->m_dragStartMousePosition = QPoint();
343             d->m_dragState = DraggingInactive;
344 
345             switch (currentDragState) {
346             case DraggingTab:
347                 // End of tab moving, emit signal
348                 if (d->m_dockArea) {
349                     emit moved(event->globalPos());
350                 }
351                 break;
352 
353             case DraggingFloatingWidget:
354                 d->m_floatingWidget->finishDragging();
355                 break;
356 
357             default:; // do nothing
358             }
359         }
360 
361         Super::mouseReleaseEvent(event);
362     }
363 
mouseMoveEvent(QMouseEvent * event)364     void DockWidgetTab::mouseMoveEvent(QMouseEvent *event)
365     {
366         if (!(event->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) {
367             d->m_dragState = DraggingInactive;
368             Super::mouseMoveEvent(event);
369             return;
370         }
371 
372         // move floating window
373         if (d->isDraggingState(DraggingFloatingWidget)) {
374             d->m_floatingWidget->moveFloating();
375             Super::mouseMoveEvent(event);
376             return;
377         }
378 
379         // move tab
380         if (d->isDraggingState(DraggingTab)) {
381             // Moving the tab is always allowed because it does not mean moving the
382             // dock widget around
383             d->moveTab(event);
384         }
385 
386         auto mappedPos = mapToParent(event->pos());
387         bool mouseOutsideBar = (mappedPos.x() < 0) || (mappedPos.x() > parentWidget()->rect().right());
388         // Maybe a fixed drag distance is better here ?
389         int dragDistanceY = qAbs(d->m_globalDragStartMousePosition.y() - event->globalPos().y());
390         if (dragDistanceY >= DockManager::startDragDistance() || mouseOutsideBar) {
391             // If this is the last dock area in a dock container with only
392             // one single dock widget it does not make  sense to move it to a new
393             // floating widget and leave this one empty
394             if (d->m_dockArea->dockContainer()->isFloating()
395                 && d->m_dockArea->openDockWidgetsCount() == 1
396                 && d->m_dockArea->dockContainer()->visibleDockAreaCount() == 1) {
397                 return;
398             }
399 
400             // Floating is only allowed for widgets that are floatable
401             // If we do non opaque undocking, then can create the drag preview
402             // if the widget is movable.
403             auto features = d->m_dockWidget->features();
404             if (features.testFlag(DockWidget::DockWidgetFloatable)
405                 || (features.testFlag(DockWidget::DockWidgetMovable)
406                 && !DockManager::testConfigFlag(DockManager::OpaqueUndocking))) {
407                 // If we undock, we need to restore the initial position of this
408                 // tab because it looks strange if it remains on its dragged position
409                 if (d->isDraggingState(DraggingTab)
410                     && !DockManager::testConfigFlag(DockManager::OpaqueUndocking))
411                     parentWidget()->layout()->update();
412 
413                 d->startFloating();
414             }
415             return;
416         } else if (d->m_dockArea->openDockWidgetsCount() > 1
417                    && (event->globalPos() - d->m_globalDragStartMousePosition).manhattanLength()
418                           >= QApplication::startDragDistance()) // Wait a few pixels before start moving
419         {
420             // If we start dragging the tab, we save its initial position to
421             // restore it later
422             if (DraggingTab != d->m_dragState)
423                 d->m_tabDragStartPosition = this->pos();
424 
425             d->m_dragState = DraggingTab;
426             return;
427         }
428 
429         Super::mouseMoveEvent(event);
430     }
431 
contextMenuEvent(QContextMenuEvent * event)432     void DockWidgetTab::contextMenuEvent(QContextMenuEvent *event)
433     {
434         event->accept();
435         if (d->isDraggingState(DraggingFloatingWidget))
436             return;
437 
438         d->saveDragStartMousePosition(event->globalPos());
439         QMenu menu(this);
440 
441         const bool isFloatable = d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable);
442         const bool isNotOnlyTabInContainer =  !d->m_dockArea->dockContainer()->hasTopLevelDockWidget();
443         const bool isDetachable = isFloatable && isNotOnlyTabInContainer;
444 
445         auto action = menu.addAction(tr("Detach"), this, &DockWidgetTab::detachDockWidget);
446         action->setEnabled(isDetachable);
447         menu.addSeparator();
448         action = menu.addAction(tr("Close"), this, &DockWidgetTab::closeRequested);
449         action->setEnabled(isClosable());
450         menu.addAction(tr("Close Others"), this, &DockWidgetTab::closeOtherTabsRequested);
451         menu.exec(event->globalPos());
452     }
453 
isActiveTab() const454     bool DockWidgetTab::isActiveTab() const { return d->m_isActiveTab; }
455 
setActiveTab(bool active)456     void DockWidgetTab::setActiveTab(bool active)
457     {
458         bool dockWidgetClosable = d->m_dockWidget->features().testFlag(
459             DockWidget::DockWidgetClosable);
460         bool activeTabHasCloseButton = d->testConfigFlag(DockManager::ActiveTabHasCloseButton);
461         bool allTabsHaveCloseButton = d->testConfigFlag(DockManager::AllTabsHaveCloseButton);
462         bool tabHasCloseButton = (activeTabHasCloseButton && active) | allTabsHaveCloseButton;
463         d->m_closeButton->setVisible(dockWidgetClosable && tabHasCloseButton);
464 
465         d->m_closeButton->setActive(active);
466 
467         // Focus related stuff
468         if (DockManager::testConfigFlag(DockManager::FocusHighlighting)
469             && !d->m_dockWidget->dockManager()->isRestoringState()) {
470             bool updateFocusStyle = false;
471             if (active && !hasFocus()) {
472                 setFocus(Qt::OtherFocusReason);
473                 updateFocusStyle = true;
474             }
475             if (d->m_isActiveTab == active) {
476                 if (updateFocusStyle)
477                     updateStyle();
478                 return;
479             }
480         } else if (d->m_isActiveTab == active) {
481             return;
482         }
483 
484         d->m_isActiveTab = active;
485         updateStyle();
486         update();
487         updateGeometry();
488 
489         emit activeTabChanged();
490     }
491 
dockWidget() const492     DockWidget *DockWidgetTab::dockWidget() const { return d->m_dockWidget; }
493 
setDockAreaWidget(DockAreaWidget * dockArea)494     void DockWidgetTab::setDockAreaWidget(DockAreaWidget *dockArea) { d->m_dockArea = dockArea; }
495 
dockAreaWidget() const496     DockAreaWidget *DockWidgetTab::dockAreaWidget() const { return d->m_dockArea; }
497 
setIcon(const QIcon & icon)498     void DockWidgetTab::setIcon(const QIcon &icon)
499     {
500         QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout());
501         if (!d->m_iconLabel && icon.isNull())
502             return;
503 
504         if (!d->m_iconLabel) {
505             d->m_iconLabel = new QLabel();
506             d->m_iconLabel->setAlignment(Qt::AlignVCenter);
507             d->m_iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
508             internal::setToolTip(d->m_iconLabel, d->m_titleLabel->toolTip());
509             boxLayout->insertWidget(0, d->m_iconLabel, Qt::AlignVCenter);
510             boxLayout->insertSpacing(1, qRound(1.5 * boxLayout->contentsMargins().left() / 2.0));
511         } else if (icon.isNull()) {
512             // Remove icon label and spacer item
513             boxLayout->removeWidget(d->m_iconLabel);
514             boxLayout->removeItem(boxLayout->itemAt(0));
515             delete d->m_iconLabel;
516             d->m_iconLabel = nullptr;
517         }
518 
519         d->m_icon = icon;
520         if (d->m_iconLabel) {
521             d->m_iconLabel->setPixmap(
522                 icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this)));
523             d->m_iconLabel->setVisible(true);
524         }
525     }
526 
icon() const527     const QIcon &DockWidgetTab::icon() const { return d->m_icon; }
528 
text() const529     QString DockWidgetTab::text() const { return d->m_titleLabel->text(); }
530 
mouseDoubleClickEvent(QMouseEvent * event)531     void DockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
532     {
533         // If this is the last dock area in a dock container it does not make
534         // sense to move it to a new floating widget and leave this one empty
535         if ((!d->m_dockArea->dockContainer()->isFloating() || d->m_dockArea->dockWidgetsCount() > 1)
536             && d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable)) {
537             d->saveDragStartMousePosition(event->globalPos());
538             d->startFloating(DraggingInactive);
539         }
540 
541         Super::mouseDoubleClickEvent(event);
542     }
543 
setVisible(bool visible)544     void DockWidgetTab::setVisible(bool visible)
545     {
546         // Just here for debugging to insert debug output
547         Super::setVisible(visible);
548     }
549 
setText(const QString & title)550     void DockWidgetTab::setText(const QString &title) { d->m_titleLabel->setText(title); }
isTitleElided() const551     bool DockWidgetTab::isTitleElided() const { return d->m_titleLabel->isElided(); }
552 
isClosable() const553     bool DockWidgetTab::isClosable() const
554     {
555         return d->m_dockWidget
556                && d->m_dockWidget->features().testFlag(DockWidget::DockWidgetClosable);
557     }
558 
detachDockWidget()559     void DockWidgetTab::detachDockWidget()
560     {
561         if (!d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable))
562             return;
563 
564         d->saveDragStartMousePosition(QCursor::pos());
565         d->startFloating(DraggingInactive);
566     }
567 
event(QEvent * event)568     bool DockWidgetTab::event(QEvent *event)
569     {
570 #ifndef QT_NO_TOOLTIP
571         if (event->type() == QEvent::ToolTipChange) {
572             const auto text = toolTip();
573             d->m_titleLabel->setToolTip(text);
574         }
575 #endif
576 
577         return Super::event(event);
578     }
579 
onDockWidgetFeaturesChanged()580     void DockWidgetTab::onDockWidgetFeaturesChanged()
581     {
582         auto features = d->m_dockWidget->features();
583         auto sizePolicy = d->m_closeButton->sizePolicy();
584         sizePolicy.setRetainSizeWhenHidden(
585             features.testFlag(DockWidget::DockWidgetClosable)
586             && d->testConfigFlag(DockManager::RetainTabSizeWhenCloseButtonHidden));
587         d->m_closeButton->setSizePolicy(sizePolicy);
588     }
589 
setElideMode(Qt::TextElideMode mode)590     void DockWidgetTab::setElideMode(Qt::TextElideMode mode)
591     {
592         d->m_titleLabel->setElideMode(mode);
593     }
594 
updateStyle()595     void DockWidgetTab::updateStyle()
596     {
597         if (DockManager::testConfigFlag(DockManager::FocusHighlighting))
598             d->m_closeButton->setFocus(property("focused").toBool());
599 
600         internal::repolishStyle(this, internal::RepolishDirectChildren);
601     }
602 
603 } // namespace ADS
604