QskAspect::Primitive cleanup

This commit is contained in:
Uwe Rathmann 2021-04-28 09:32:49 +02:00
parent 3112df6c2f
commit 75a9ee305c
7 changed files with 200 additions and 174 deletions

View File

@ -4,10 +4,10 @@
\brief Lookup key for a QskSkinHintTable \brief Lookup key for a QskSkinHintTable
Used by the \ref qskskinning "themeing system" to determine how a given aspect QskAspect is used by the \ref qskskinning "themeing system" to determine how
of a control is drawn. While an aspect is simply a 64-bit unsigned integer, it a given aspect of a control is drawn. While an aspect is simply a 64-bit
is composed of smaller enum bitfields which can be ORed together to unsigned integer, it is composed of smaller enum bitfields which can be ORed
describe a more specific part of the user interface. together to describe a more specific part of the user interface.
For example, the border colors of a QskPushButton while pressed is For example, the border colors of a QskPushButton while pressed is
defined by combining the State (QskAbstractButton::Pressed) with the defined by combining the State (QskAbstractButton::Pressed) with the
@ -38,14 +38,12 @@
\var QskAspect::Type QskAspect::Flag \var QskAspect::Type QskAspect::Flag
Flags are all sort of attributes that are no metrics or colors - f.e Flags are all sort of attributes that are no metrics or colors - f.e
an alignment. A reasonable subset of possible flags is offered as an alignment.
QskAspect::FlagPrimitive
\var QskAspect::Type QskAspect::Metric \var QskAspect::Type QskAspect::Metric
Metrics are related to geometries in most cases corresponding to pixel distances. Metrics are related to geometries in most cases corresponding to pixel distances.
Examples are the margin/padding. A reasonable subset of possible metrics Examples are margin/padding(s).
is offered as QskAspect::MetricPrimitive.
\var QskAspect::Type QskAspect::Color \var QskAspect::Type QskAspect::Color
@ -53,45 +51,77 @@
*/ */
/*! /*!
\enum QskAspect::FlagPrimitive \enum QskAspect::Primitive
\var QskAspect::FlagPrimitive QskAspect::NoFlagPrimitive \sa setPrimitive(), clearPrimitive(), primitive(),
\var QskAspect::FlagPrimitive QskAspect::Alignment reservePrimitives(), primitiveCount()
\var QskAspect::FlagPrimitive QskAspect::Direction
\var QskAspect::FlagPrimitive QskAspect::Style
\var QskAspect::FlagPrimitive QskAspect::Decoration
\var QskAspect::FlagPrimitive QskAspect::GraphicRole
\var QskAspect::FlagPrimitive QskAspect::FontRole
\sa setPrimitive(), clearPrimitive(), primitive() \var QskAspect::Primitive QskAspect::NoPrimitive
*/ No specific primitive
/*! \var QskAspect::Primitive QskAspect::Alignment
\enum QskAspect::MetricPrimitive Usually used in combination with QskAspect::Flag
\var QskAspect::MetricPrimitive QskAspect::NoMetricPrimitive \sa QskSkinnable::alignmentHint(), QskSkinHintTableEditor::alignment()
\var QskAspect::MetricPrimitive QskAspect::StrutSize
\var QskAspect::MetricPrimitive QskAspect::Size
\var QskAspect::MetricPrimitive QskAspect::Position
\var QskAspect::MetricPrimitive QskAspect::Margin
\var QskAspect::MetricPrimitive QskAspect::Padding
\var QskAspect::MetricPrimitive QskAspect::Shadow
\var QskAspect::MetricPrimitive QskAspect::Spacing
\var QskAspect::MetricPrimitive QskAspect::Shape
\var QskAspect::MetricPrimitive QskAspect::Border
\sa setPrimitive(), clearPrimitive(), primitive() \var QskAspect::Primitive QskAspect::Style
*/ Usually used in combination with QskAspect::Flag
/*! \var QskAspect::Primitive QskAspect::GraphicRole
\enum QskAspect::ColorPrimitive
\var QskAspect::ColorPrimitive QskAspect::NoColorPrimitive \sa QskSkinnable::graphicRoleHint(), QskSkinHintTableEditor::graphicRole()
\var QskAspect::ColorPrimitive QskAspect::TextColor
\var QskAspect::ColorPrimitive QskAspect::StyleColor
\var QskAspect::ColorPrimitive QskAspect::LinkColor
\sa setPrimitive(), clearPrimitive(), primitive() \var QskAspect::Primitive QskAspect::FontRole
\sa QskSkinnable::fontRoleHint(), QskSkinHintTableEditor::fontRole()
\var QskAspect::Primitive QskAspect::TextColor
bla
\var QskAspect::Primitive QskAspect::StyleColor
bla
\var QskAspect::Primitive QskAspect::LinkColor
bla
\var QskAspect::Primitive QskAspect::StrutSize
bla
\sa QskSkinnable::strutSizeHint(), QskSkinHintTableEditor::strutSize()
\var QskAspect::Primitive QskAspect::Size
bla
\var QskAspect::Primitive QskAspect::Position
bla
\var QskAspect::Primitive QskAspect::Margin
bla
\sa QskSkinnable::marginHint(), QskSkinHintTableEditor::margin()
\var QskAspect::Primitive QskAspect::Padding
bla
\sa QskSkinnable::paddingHint(), QskSkinHintTableEditor::padding()
\var QskAspect::Primitive QskAspect::Spacing
bla
\sa QskSkinnable::spacingHint(), QskSkinHintTableEditor::spacing()
\var QskAspect::Primitive QskAspect::Shadow
bla
\var QskAspect::Primitive QskAspect::Shape
bla
\sa QskSkinnable::boxShapeHint(), QskSkinHintTableEditor::boxShape()
\var QskAspect::Primitive QskAspect::Border
bla
\sa QskSkinnable::boxBorderMetricsHint(), QskSkinnable::boxBorderColorsHint()
QskSkinHintTableEditor::boxBorderMetrics(), QskSkinHintTableEditor::boxBorderColors()
*/ */
/*! /*!
@ -275,19 +305,7 @@
*/ */
/*! /*!
\fn QskAspect::operator|( FlagPrimitive ) const \fn QskAspect::operator|( Primitive ) const
Sets the primitive bits
*/
/*!
\fn QskAspect::operator|( MetricPrimitive ) const
Sets the primitive bits
*/
/*!
\fn QskAspect::operator|( ColorPrimitive ) const
Sets the primitive bits Sets the primitive bits
*/ */

View File

@ -673,7 +673,6 @@ void Editor::setupSubWindow()
// Panel // Panel
setFlagHint( Q::Panel | A::Decoration, true );
setPadding( Q::Panel, 10 ); setPadding( Q::Panel, 10 );
setBoxShape( Q::Panel, 0 ); setBoxShape( Q::Panel, 0 );
setBoxBorderMetrics( Q::Panel, 2 ); setBoxBorderMetrics( Q::Panel, 2 );
@ -685,15 +684,18 @@ void Editor::setupSubWindow()
setBoxBorderColors( Q::Panel, colors ); setBoxBorderColors( Q::Panel, colors );
// TitleBar // TitleBarPanel
setGradient( Q::TitleBar, m_pal.darker200 ); setFlagHint( Q::TitleBarPanel | QskAspect::Style,
setGradient( Q::TitleBar | Q::Focused, m_pal.accentColor ); Q::TitleBar | Q::Title | Q::Symbol );
setGradient( Q::TitleBarPanel, m_pal.darker200 );
setGradient( Q::TitleBarPanel | Q::Focused, m_pal.accentColor );
// TitleBarText // TitleBarText
setFontRole( Q::TitleBarText, QskSkin::SmallFont ); setFontRole( Q::TitleBarText, QskSkin::SmallFont );
setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter ); setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter );
for ( auto subControl : { Q::Panel, Q::TitleBar, Q::TitleBarText } ) for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
setAnimation( subControl | A::Color, qskDuration ); setAnimation( subControl | A::Color, qskDuration );
} }

View File

@ -816,7 +816,6 @@ void Editor::setupSubWindow()
// Panel // Panel
setFlagHint( Q::Panel | A::Decoration, true );
setPadding( Q::Panel, 10 ); setPadding( Q::Panel, 10 );
setBoxBorderMetrics( Q::Panel, 2 ); setBoxBorderMetrics( Q::Panel, 2 );
setBoxShape( Q::Panel, radius, radius, 0, 0, Qt::AbsoluteSize ); setBoxShape( Q::Panel, radius, radius, 0, 0, Qt::AbsoluteSize );
@ -828,13 +827,16 @@ void Editor::setupSubWindow()
setBoxBorderColors( Q::Panel, borderColors ); setBoxBorderColors( Q::Panel, borderColors );
setGradient( Q::Panel, m_pal.lighter135 ); setGradient( Q::Panel, m_pal.lighter135 );
// TitleBar // TitleBarPanel
setGradient( Q::TitleBar | Q::Focused, m_pal.highlighted ); setFlagHint( Q::TitleBarPanel | QskAspect::Style,
setGradient( Q::TitleBar, m_pal.contrasted ); Q::TitleBar | Q::Title | Q::Symbol );
setSpacing( Q::TitleBar, 5 );
setStrutSize( Q::TitleBar, 0, 20 ); setGradient( Q::TitleBarPanel | Q::Focused, m_pal.highlighted );
setBoxShape( Q::TitleBar, radius, radius, 0, 0, Qt::AbsoluteSize ); setGradient( Q::TitleBarPanel, m_pal.contrasted );
setSpacing( Q::TitleBarPanel, 5 );
setStrutSize( Q::TitleBarPanel, 0, 20 );
setBoxShape( Q::TitleBarPanel, radius, radius, 0, 0, Qt::AbsoluteSize );
// TitleBarText // TitleBarText
setFontRole( Q::TitleBarText, QskSkin::SmallFont ); setFontRole( Q::TitleBarText, QskSkin::SmallFont );
@ -843,7 +845,7 @@ void Editor::setupSubWindow()
setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter ); setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter );
for ( auto subControl : { Q::Panel, Q::TitleBar, Q::TitleBarText } ) for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
setAnimation( subControl | A::Color, qskDuration ); setAnimation( subControl | A::Color, qskDuration );
} }

View File

@ -33,9 +33,7 @@ class QSK_EXPORT QskAspect
NoPrimitive = 0, NoPrimitive = 0,
Alignment, Alignment,
Direction,
Style, Style,
Decoration,
GraphicRole, GraphicRole,
FontRole, FontRole,

View File

@ -14,26 +14,27 @@
#include <qurl.h> #include <qurl.h>
QSK_SUBCONTROL( QskSubWindow, Panel ) QSK_SUBCONTROL( QskSubWindow, Panel )
QSK_SUBCONTROL( QskSubWindow, TitleBar ) QSK_SUBCONTROL( QskSubWindow, TitleBarPanel )
QSK_SUBCONTROL( QskSubWindow, TitleBarSymbol ) QSK_SUBCONTROL( QskSubWindow, TitleBarSymbol )
QSK_SUBCONTROL( QskSubWindow, TitleBarText ) QSK_SUBCONTROL( QskSubWindow, TitleBarText )
namespace
{
inline QskAspect aspectDecoration()
{
return QskSubWindow::TitleBarPanel | QskAspect::Flag | QskAspect::Style;
}
}
class QskSubWindow::PrivateData class QskSubWindow::PrivateData
{ {
public: public:
PrivateData() PrivateData()
: isWindowIconSourceDirty( false ) : isWindowIconSourceDirty( false )
{ {
// should be available from the platform somehow. TODO ...
windowButtons = QskSubWindow::WindowButtons( QskSubWindow::MinimizeButton |
QskSubWindow::MaximizeButton | QskSubWindow::CloseButton );
windowTitleTextOptions.setElideMode( Qt::ElideRight ); windowTitleTextOptions.setElideMode( Qt::ElideRight );
} }
QskSubWindow::WindowButtons windowButtons;
QString windowTitle; QString windowTitle;
QskTextOptions windowTitleTextOptions; QskTextOptions windowTitleTextOptions;
@ -57,24 +58,38 @@ QskSubWindow::~QskSubWindow()
{ {
} }
void QskSubWindow::setDecorated( bool on ) void QskSubWindow::setDecorations( Decorations decorations )
{ {
if ( on == isDecorated() ) if ( setFlagHint( aspectDecoration(), decorations ) )
return; Q_EMIT decorationsChanged( decorations );
setFlagHint( Panel | QskAspect::Decoration, on );
resetImplicitSize(); // in case some parent wants to layout
polish();
update();
Q_EMIT decoratedChanged();
} }
bool QskSubWindow::isDecorated() const QskSubWindow::Decorations QskSubWindow::decorations() const
{ {
return flagHint< bool >( Panel | QskAspect::Decoration, true ); return flagHint< QskSubWindow::Decorations >( aspectDecoration() );
}
void QskSubWindow::setDecoration( Decoration decoration, bool on )
{
auto d = decorations();
if ( on )
d |= decoration;
else
d &= ~decoration;
setDecorations( d );
}
void QskSubWindow::resetDecorations()
{
if ( resetFlagHint( aspectDecoration() ) )
Q_EMIT decorationsChanged( decorations() );
}
bool QskSubWindow::hasDecoration( Decoration decoration ) const
{
return decorations() & decoration;
} }
void QskSubWindow::setWindowTitle( const QString& title ) void QskSubWindow::setWindowTitle( const QString& title )
@ -166,44 +181,9 @@ bool QskSubWindow::hasWindowIcon() const
return !( windowIcon().isEmpty() && windowIconSource().isEmpty() ); return !( windowIcon().isEmpty() && windowIconSource().isEmpty() );
} }
void QskSubWindow::setWindowButtons( WindowButtons buttons )
{
if ( buttons != m_data->windowButtons )
{
m_data->windowButtons = buttons;
update();
Q_EMIT windowButtonsChanged();
}
}
QskSubWindow::WindowButtons QskSubWindow::windowButtons() const
{
return m_data->windowButtons;
}
void QskSubWindow::setWindowButton( WindowButton button, bool on )
{
if ( on == bool( button & m_data->windowButtons ) )
return;
if ( on )
m_data->windowButtons |= button;
else
m_data->windowButtons &= ~button;
Q_EMIT windowButtonsChanged();
}
bool QskSubWindow::testWindowButton( WindowButton button ) const
{
return m_data->windowButtons & button;
}
QRectF QskSubWindow::titleBarRect() const QRectF QskSubWindow::titleBarRect() const
{ {
return subControlRect( TitleBar ); return subControlRect( TitleBarPanel );
} }
bool QskSubWindow::event( QEvent* event ) bool QskSubWindow::event( QEvent* event )
@ -234,7 +214,7 @@ QRectF QskSubWindow::layoutRectForSize( const QSizeF& size ) const
{ {
QRectF rect; QRectF rect;
rect.setSize( size ); rect.setSize( size );
rect.setTop( subControlRect( size, TitleBar ).bottom() ); rect.setTop( subControlRect( size, TitleBarPanel ).bottom() );
return innerBox( Panel, rect ); return innerBox( Panel, rect );
} }

View File

@ -16,8 +16,8 @@ class QSK_EXPORT QskSubWindow : public QskPopup
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( bool decorated READ isDecorated Q_PROPERTY( Decorations decorations READ decorations
WRITE setDecorated NOTIFY decoratedChanged ) WRITE setDecorations RESET resetDecorations NOTIFY decorationsChanged )
Q_PROPERTY( QString windowTitle READ windowTitle Q_PROPERTY( QString windowTitle READ windowTitle
WRITE setWindowTitle NOTIFY windowTitleChanged ) WRITE setWindowTitle NOTIFY windowTitleChanged )
@ -31,29 +31,39 @@ class QSK_EXPORT QskSubWindow : public QskPopup
Q_PROPERTY( QskGraphic windowIcon READ windowIcon Q_PROPERTY( QskGraphic windowIcon READ windowIcon
WRITE setWindowIcon NOTIFY windowIconChanged FINAL ) WRITE setWindowIcon NOTIFY windowIconChanged FINAL )
Q_PROPERTY( WindowButtons windowButtons READ windowButtons
WRITE setWindowButtons NOTIFY windowButtonsChanged )
using Inherited = QskPopup; using Inherited = QskPopup;
public: public:
enum WindowButton enum Decoration
{ {
MinimizeButton = 0x1, NoDecoration = 0,
MaximizeButton = 0x2,
CloseButton = 0x4 TitleBar = 1 << 0,
Title = 1 << 1,
Symbol = 1 << 2
#if 0
MinimizeButton = 1 << 3,
MaximizeButton = 1 << 4,
CloseButton = 1 << 5
#endif
}; };
Q_ENUM( WindowButton ) Q_ENUM( Decoration )
Q_DECLARE_FLAGS( WindowButtons, WindowButton ) Q_DECLARE_FLAGS( Decorations, Decoration )
QSK_SUBCONTROLS( Panel, TitleBar, TitleBarSymbol, TitleBarText ) QSK_SUBCONTROLS( Panel, TitleBarPanel, TitleBarSymbol, TitleBarText )
QskSubWindow( QQuickItem* parent = nullptr ); QskSubWindow( QQuickItem* parent = nullptr );
~QskSubWindow() override; ~QskSubWindow() override;
void setDecorated( bool ); void setDecorations( Decorations );
bool isDecorated() const; void resetDecorations();
Decorations decorations() const;
void setDecoration( Decoration, bool on = true );
bool hasDecoration( Decoration ) const;
void setWindowTitleTextOptions( const QskTextOptions& ); void setWindowTitleTextOptions( const QskTextOptions& );
QskTextOptions windowTitleTextOptions() const; QskTextOptions windowTitleTextOptions() const;
@ -70,23 +80,16 @@ class QSK_EXPORT QskSubWindow : public QskPopup
bool hasWindowIcon() const; bool hasWindowIcon() const;
void setWindowButtons( WindowButtons );
WindowButtons windowButtons() const;
void setWindowButton( WindowButton, bool on = true );
bool testWindowButton( WindowButton ) const;
QRectF titleBarRect() const; QRectF titleBarRect() const;
QRectF layoutRectForSize( const QSizeF& ) const override; QRectF layoutRectForSize( const QSizeF& ) const override;
Q_SIGNALS: Q_SIGNALS:
void decoratedChanged(); void decorationsChanged( Decorations );
void windowTitleChanged(); void windowTitleChanged();
void windowTitleTextOptionsChanged(); void windowTitleTextOptionsChanged();
void windowIconChanged(); void windowIconChanged();
void windowIconSourceChanged(); void windowIconSourceChanged();
void windowButtonsChanged();
protected: protected:
bool event( QEvent* ) override; bool event( QEvent* ) override;

View File

@ -30,7 +30,7 @@ QRectF QskSubWindowSkinlet::subControlRect( const QskSkinnable* skinnable,
{ {
return contentsRect; return contentsRect;
} }
else if ( subControl == QskSubWindow::TitleBar ) else if ( subControl == QskSubWindow::TitleBarPanel )
{ {
return titleBarRect( subWindow, contentsRect ); return titleBarRect( subWindow, contentsRect );
} }
@ -49,37 +49,45 @@ QRectF QskSubWindowSkinlet::subControlRect( const QskSkinnable* skinnable,
QSGNode* QskSubWindowSkinlet::updateSubNode( QSGNode* QskSubWindowSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{ {
using Q = QskSubWindow;
const auto subWindow = static_cast< const QskSubWindow* >( skinnable ); const auto subWindow = static_cast< const QskSubWindow* >( skinnable );
switch ( nodeRole ) switch ( nodeRole )
{ {
case PanelRole: case PanelRole:
{ {
return updateBoxNode( subWindow, node, QskSubWindow::Panel ); return updateBoxNode( subWindow, node, Q::Panel );
} }
case TitleBarRole: case TitleBarRole:
{ {
if ( subWindow->isDecorated() ) const auto decorations = subWindow->decorations();
return updateBoxNode( subWindow, node, QskSubWindow::TitleBar );
if ( decorations & Q::TitleBar )
return updateBoxNode( subWindow, node, Q::TitleBarPanel );
return nullptr; return nullptr;
} }
case SymbolRole: case SymbolRole:
{ {
if ( subWindow->isDecorated() ) const auto decorations = subWindow->decorations();
if ( ( decorations & Q::TitleBar ) && ( decorations & Q::Symbol ) )
{ {
return updateGraphicNode( subWindow, node, return updateGraphicNode( subWindow, node,
subWindow->windowIcon(), QskSubWindow::TitleBarSymbol ); subWindow->windowIcon(), Q::TitleBarSymbol );
} }
return nullptr; return nullptr;
} }
case TitleRole: case TitleRole:
{ {
if ( subWindow->isDecorated() ) const auto decorations = subWindow->decorations();
if ( ( decorations & Q::TitleBar ) && ( decorations & Q::Title ) )
{ {
return updateTextNode( subWindow, node, subWindow->windowTitle(), return updateTextNode( subWindow, node, subWindow->windowTitle(),
subWindow->windowTitleTextOptions(), QskSubWindow::TitleBarText ); subWindow->windowTitleTextOptions(), Q::TitleBarText );
} }
return nullptr; return nullptr;
@ -104,16 +112,23 @@ qreal QskSubWindowSkinlet::titleBarHeight( const QskSubWindow* subWindow ) const
{ {
using Q = QskSubWindow; using Q = QskSubWindow;
if ( !subWindow->isDecorated() ) const auto decorations = subWindow->decorations();
if ( !( decorations & Q::TitleBar ) )
return 0; return 0;
const auto margins = subWindow->paddingHint( Q::TitleBar ); auto height = subWindow->strutSizeHint( Q::TitleBarPanel ).height();
const QFontMetricsF fm( subWindow->effectiveFont( Q::TitleBarText ) );
const qreal height = fm.height() + margins.top() + margins.bottom(); if ( decorations & Q::Title )
const auto strutSize = subWindow->strutSizeHint( Q::TitleBar ); {
const auto padding = subWindow->paddingHint( Q::TitleBarPanel );
const QFontMetricsF fm( subWindow->effectiveFont( Q::TitleBarText ) );
return qMax( height, strutSize.height() ); const qreal h = fm.height() + padding.top() + padding.bottom();
if ( h > height )
height = h;
}
return height;
} }
QRectF QskSubWindowSkinlet::symbolRect( QRectF QskSubWindowSkinlet::symbolRect(
@ -121,13 +136,16 @@ QRectF QskSubWindowSkinlet::symbolRect(
{ {
using Q = QskSubWindow; using Q = QskSubWindow;
auto rect = subWindow->subControlContentsRect( contentsRect, Q::TitleBar ); if ( !subWindow->hasDecoration( Q::Symbol ) )
return QRectF();
int w = 0; auto rect = subWindow->subControlContentsRect( contentsRect, Q::TitleBarPanel );
if ( !rect.isEmpty() ) if ( !rect.isEmpty() )
{ {
const auto symbol = subWindow->windowIcon(); const auto symbol = subWindow->windowIcon();
int w = 0;
if ( !symbol.isNull() ) if ( !symbol.isNull() )
w = symbol.widthForHeight( rect.height() ); w = symbol.widthForHeight( rect.height() );
@ -142,14 +160,19 @@ QRectF QskSubWindowSkinlet::titleRect(
{ {
using Q = QskSubWindow; using Q = QskSubWindow;
auto rect = subWindow->subControlContentsRect( contentsRect, Q::TitleBar ); if ( !subWindow->hasDecoration( Q::Title ) )
return QRectF();
auto rect = subWindow->subControlContentsRect( contentsRect, Q::TitleBarPanel );
if ( !rect.isEmpty() ) if ( !rect.isEmpty() )
{ {
const auto spacing = subWindow->spacingHint( Q::TitleBar );
const auto symbolRect = subControlRect( subWindow, rect, Q::TitleBarSymbol ); const auto symbolRect = subControlRect( subWindow, rect, Q::TitleBarSymbol );
if ( !symbolRect.isEmpty() )
rect.setX( rect.x() + symbolRect.right() + spacing ); {
const auto spacing = subWindow->spacingHint( Q::TitleBarPanel );
rect.setX( symbolRect.right() + spacing );
}
#if 0 #if 0
const QFontMetricsF fm( subWindow->effectiveFont( Q::TitleBarText ) ); const QFontMetricsF fm( subWindow->effectiveFont( Q::TitleBarText ) );