Merge branch 'master' into features/menubutton
This commit is contained in:
commit
130bd3f9d2
|
|
@ -63,7 +63,8 @@ namespace
|
||||||
Drawer( QQuickItem* parent = nullptr )
|
Drawer( QQuickItem* parent = nullptr )
|
||||||
: QskDrawer( parent )
|
: QskDrawer( parent )
|
||||||
{
|
{
|
||||||
auto box = new QskLinearBox( Qt::Vertical );
|
auto box = new QskLinearBox( Qt::Vertical, this );
|
||||||
|
|
||||||
box->setSection( QskAspect::Header );
|
box->setSection( QskAspect::Header );
|
||||||
box->setPanel( true );
|
box->setPanel( true );
|
||||||
box->setPaddingHint( QskBox::Panel, 20 );
|
box->setPaddingHint( QskBox::Panel, 20 );
|
||||||
|
|
@ -76,8 +77,6 @@ namespace
|
||||||
|
|
||||||
auto btn = new QskPushButton( "Close", box );
|
auto btn = new QskPushButton( "Close", box );
|
||||||
connect( btn, &QskPushButton::clicked, this, &QskDrawer::close );
|
connect( btn, &QskPushButton::clicked, this, &QskDrawer::close );
|
||||||
|
|
||||||
setContent( box );
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -211,19 +210,17 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto drawer = new Drawer( parentItem() );
|
|
||||||
drawer->setEdge( Qt::RightEdge );
|
|
||||||
|
|
||||||
auto burger = new QskPushButton( "≡", this );
|
auto burger = new QskPushButton( "≡", this );
|
||||||
burger->setEmphasis( QskPushButton::LowEmphasis );
|
burger->setEmphasis( QskPushButton::LowEmphasis );
|
||||||
|
|
||||||
connect( burger, &QskPushButton::clicked,
|
connect( burger, &QskPushButton::clicked,
|
||||||
drawer, &QskPopup::open );
|
this, &Header::drawerRequested );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void enabledToggled( bool );
|
void enabledToggled( bool );
|
||||||
|
void drawerRequested();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainView : public QskMainView
|
class MainView : public QskMainView
|
||||||
|
|
@ -246,6 +243,12 @@ namespace
|
||||||
connect( header, &Header::enabledToggled,
|
connect( header, &Header::enabledToggled,
|
||||||
tabView, &TabView::setPagesEnabled );
|
tabView, &TabView::setPagesEnabled );
|
||||||
|
|
||||||
|
auto drawer = new Drawer( tabView );
|
||||||
|
drawer->setEdge( Qt::RightEdge );
|
||||||
|
|
||||||
|
connect( header, &Header::drawerRequested,
|
||||||
|
drawer, &QskPopup::toggle );
|
||||||
|
|
||||||
setHeader( header );
|
setHeader( header );
|
||||||
setBody( tabView );
|
setBody( tabView );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,35 +35,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The palette is made of a specific configurable colors and
|
The palette is made of a couple of configurable base/accent colors and a
|
||||||
predefined semitransparent shades of gray. Both need to
|
predefined set of semitransparent shades of gray. These grays are used
|
||||||
be resolved to opaque colors with the base colors of the sections.
|
to create darkened/lightend colors from the configurable colors that can
|
||||||
|
be used for borders etc.
|
||||||
|
|
||||||
Resolving the colors can be done in 2 ways:
|
However borders need to be darkened for light base colors and lightened for
|
||||||
|
dark ones. So we actually have 2 different sets of grays for light/dark
|
||||||
|
colors schemes.
|
||||||
|
|
||||||
- render time
|
The main advantage of this concept is, that a working color schemes
|
||||||
|
can be defined by setting the accent/base colors only.
|
||||||
This actually means, that we do not create opaque colors and
|
|
||||||
create the scene graph nodes with semitransparent colors.
|
|
||||||
|
|
||||||
- definition time
|
|
||||||
|
|
||||||
We create opaque colors for the base colors of the sections
|
|
||||||
and set them as skin hints.
|
|
||||||
|
|
||||||
Resolving at render time sounds like the right solution as we
|
|
||||||
background colors set in application code will just work.
|
|
||||||
|
|
||||||
Unfortunately we have 2 different sets of grays for light/dark
|
|
||||||
base colors and when applications are setting a light color, where a
|
|
||||||
dark color ( or v.v ) is expected we might end up with unacceptable
|
|
||||||
results: ( white on light or black on dark ).
|
|
||||||
|
|
||||||
So there are pros and cons and we do not have a final opinion
|
|
||||||
about waht to do. For the moment we implement resolving at definition
|
|
||||||
time as an option to be able to play with both solutions.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "QskFluent2Skin.h"
|
#include "QskFluent2Skin.h"
|
||||||
#include "QskFluent2Theme.h"
|
#include "QskFluent2Theme.h"
|
||||||
|
|
||||||
|
|
@ -139,9 +122,30 @@ namespace
|
||||||
return qRgba( value, value, value, qRound( opacity * 255 ) );
|
return qRgba( value, value, value, qRound( opacity * 255 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
When application code is manipulating base colors manually the colors of
|
||||||
|
the borders will be lightened/darkened from it like expected - as long
|
||||||
|
as the application color matches the color scheme. Otherwise we end
|
||||||
|
up with lightened borders on light backgrounds or v.v.
|
||||||
|
|
||||||
|
To avoid this problem we could resolve the grays with the background
|
||||||
|
colors of the sections at definition time. This solves the problem with
|
||||||
|
applications using backgrounds from the "wrong" color scheme, but requires
|
||||||
|
more work for customizing controls hen using the "correct" scheme
|
||||||
|
( -> border colors need to be set as well ).
|
||||||
|
|
||||||
|
When enabling QSK_RESOLVE_COLORS a code path is enabled that is intended
|
||||||
|
to play with resolving the grays at definition time. But I'm not decided
|
||||||
|
if it is worth to make a feature from it. TODO ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define QSK_RESOLVE_COLORS 0
|
||||||
|
|
||||||
|
#if QSK_RESOLVE_COLORS
|
||||||
|
|
||||||
inline constexpr QRgb rgbFlattened( QRgb foreground, QRgb background )
|
inline constexpr QRgb rgbFlattened( QRgb foreground, QRgb background )
|
||||||
{
|
{
|
||||||
//Q_ASSERT( qAlpha( background ) == 255 );
|
Q_ASSERT( qAlpha( background ) == 255 );
|
||||||
|
|
||||||
const auto r2 = qAlpha( foreground ) / 255.0;
|
const auto r2 = qAlpha( foreground ) / 255.0;
|
||||||
const auto r1 = 1.0 - r2;
|
const auto r1 = 1.0 - r2;
|
||||||
|
|
@ -160,15 +164,25 @@ namespace
|
||||||
or without resolving the foreground alpha value
|
or without resolving the foreground alpha value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
|
||||||
return rgbFlattened( foreground, background );
|
return rgbFlattened( foreground, background );
|
||||||
#else
|
}
|
||||||
//Q_ASSERT( qAlpha( background ) == 255 );
|
|
||||||
|
#else // !QSK_RESOLVE_COLORS
|
||||||
|
|
||||||
|
inline QRgb rgbFlattened( QRgb foreground, QRgb background )
|
||||||
|
{
|
||||||
|
const auto alpha = qAlpha( foreground ) / 255.0;
|
||||||
|
return QskRgb::interpolated( background, foreground, alpha );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr QRgb rgbSolid( QRgb foreground, QRgb background )
|
||||||
|
{
|
||||||
Q_UNUSED( background );
|
Q_UNUSED( background );
|
||||||
return foreground;
|
return foreground;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
class Editor : private QskSkinHintTableEditor
|
class Editor : private QskSkinHintTableEditor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -521,7 +535,8 @@ void Editor::setupComboBoxColors(
|
||||||
|
|
||||||
const auto& pal = theme.palette;
|
const auto& pal = theme.palette;
|
||||||
|
|
||||||
for ( const auto state : { QskAspect::NoState, Q::Hovered, Q::Focused, Q::Pressed, Q::Disabled } )
|
for ( const auto state :
|
||||||
|
{ QskAspect::NoState, Q::Hovered, Q::Focused, Q::Pressed, Q::Disabled } )
|
||||||
{
|
{
|
||||||
QRgb panelColor, borderColor1, borderColor2, textColor;
|
QRgb panelColor, borderColor1, borderColor2, textColor;
|
||||||
|
|
||||||
|
|
@ -606,21 +621,16 @@ void Editor::setupDialogButtonBoxColors(
|
||||||
void Editor::setupDrawerMetrics()
|
void Editor::setupDrawerMetrics()
|
||||||
{
|
{
|
||||||
using Q = QskDrawer;
|
using Q = QskDrawer;
|
||||||
|
using A = QskAspect;
|
||||||
|
|
||||||
setPadding( Q::Panel, 5 );
|
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
|
||||||
setHint( Q::Overlay | QskAspect::Style, false );
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
setAnimation( Q::Panel | QskAspect::Position, 200 );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupDrawerColors(
|
void Editor::setupDrawerColors(
|
||||||
QskAspect::Section section, const QskFluent2Theme& theme )
|
QskAspect::Section section, const QskFluent2Theme& theme )
|
||||||
{
|
{
|
||||||
using Q = QskDrawer;
|
setGradient( QskDrawer::Panel | section,
|
||||||
|
theme.palette.background.solid.base );
|
||||||
setGradient( Q::Panel | section, theme.palette.background.solid.base );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupFocusIndicatorMetrics()
|
void Editor::setupFocusIndicatorMetrics()
|
||||||
|
|
@ -735,6 +745,7 @@ void Editor::setupListViewColors(
|
||||||
void Editor::setupMenuMetrics()
|
void Editor::setupMenuMetrics()
|
||||||
{
|
{
|
||||||
using Q = QskMenu;
|
using Q = QskMenu;
|
||||||
|
using A = QskAspect;
|
||||||
|
|
||||||
setPadding( Q::Panel, { 4, 6, 4, 6 } );
|
setPadding( Q::Panel, { 4, 6, 4, 6 } );
|
||||||
setBoxBorderMetrics( Q::Panel, 1 );
|
setBoxBorderMetrics( Q::Panel, 1 );
|
||||||
|
|
@ -748,6 +759,8 @@ void Editor::setupMenuMetrics()
|
||||||
|
|
||||||
setStrutSize( Q::Icon, 12, 12 );
|
setStrutSize( Q::Icon, 12, 12 );
|
||||||
setPadding( Q::Icon, { 8, 8, 0, 8 } );
|
setPadding( Q::Icon, { 8, 8, 0, 8 } );
|
||||||
|
|
||||||
|
setAnimation( Q::Panel | A::Position, 100 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupMenuColors(
|
void Editor::setupMenuColors(
|
||||||
|
|
@ -790,7 +803,8 @@ void Editor::setupMenuColors(
|
||||||
setColor( Q::Text | Q::Selected | Q::Pressed, pal.fillColor.text.secondary );
|
setColor( Q::Text | Q::Selected | Q::Pressed, pal.fillColor.text.secondary );
|
||||||
|
|
||||||
setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary );
|
setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary );
|
||||||
setGraphicRole( Q::Icon | Q::Selected | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextSecondary );
|
setGraphicRole( Q::Icon | Q::Selected | Q::Pressed,
|
||||||
|
QskFluent2Skin::GraphicRoleFillColorTextSecondary );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupPageIndicatorMetrics()
|
void Editor::setupPageIndicatorMetrics()
|
||||||
|
|
@ -857,9 +871,11 @@ void Editor::setupPageIndicatorColors(
|
||||||
void Editor::setupPopup( const QskFluent2Theme& theme )
|
void Editor::setupPopup( const QskFluent2Theme& theme )
|
||||||
{
|
{
|
||||||
using Q = QskPopup;
|
using Q = QskPopup;
|
||||||
|
using A = QskAspect;
|
||||||
|
|
||||||
const auto& pal = theme.palette;
|
const auto& pal = theme.palette;
|
||||||
|
|
||||||
|
setHint( Q::Overlay | A::Style, true );
|
||||||
setGradient( Q::Overlay, pal.background.overlay.defaultColor );
|
setGradient( Q::Overlay, pal.background.overlay.defaultColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1866,6 +1882,8 @@ void Editor::setupSwitchButtonColors(
|
||||||
void Editor::setupSubWindow( const QskFluent2Theme& theme )
|
void Editor::setupSubWindow( const QskFluent2Theme& theme )
|
||||||
{
|
{
|
||||||
using Q = QskSubWindow;
|
using Q = QskSubWindow;
|
||||||
|
using A = QskAspect;
|
||||||
|
|
||||||
const auto& pal = theme.palette;
|
const auto& pal = theme.palette;
|
||||||
|
|
||||||
setPadding( Q::Panel, { 0, 31, 0, 0 } );
|
setPadding( Q::Panel, { 0, 31, 0, 0 } );
|
||||||
|
|
@ -1883,6 +1901,8 @@ void Editor::setupSubWindow( const QskFluent2Theme& theme )
|
||||||
setColor( Q::TitleBarText, pal.fillColor.text.primary );
|
setColor( Q::TitleBarText, pal.fillColor.text.primary );
|
||||||
setAlignment( Q::TitleBarText, Qt::AlignLeft );
|
setAlignment( Q::TitleBarText, Qt::AlignLeft );
|
||||||
setTextOptions( Q::TitleBarText, Qt::ElideRight, QskTextOptions::NoWrap );
|
setTextOptions( Q::TitleBarText, Qt::ElideRight, QskTextOptions::NoWrap );
|
||||||
|
|
||||||
|
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupVirtualKeyboardMetrics()
|
void Editor::setupVirtualKeyboardMetrics()
|
||||||
|
|
|
||||||
|
|
@ -378,11 +378,9 @@ void Editor::setupMenu()
|
||||||
setColor( Q::Text, m_pal.onSurface );
|
setColor( Q::Text, m_pal.onSurface );
|
||||||
setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium );
|
setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium );
|
||||||
|
|
||||||
setPosition( Q::Panel, 0 );
|
|
||||||
setPosition( Q::Panel | QskPopup::Closed, 1_dp );
|
|
||||||
|
|
||||||
setAnimation( Q::Panel | A::Metric, 150 );
|
|
||||||
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
|
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
|
||||||
|
|
||||||
|
setAnimation( Q::Panel | A::Position, 75 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupTextLabel()
|
void Editor::setupTextLabel()
|
||||||
|
|
@ -809,12 +807,10 @@ void Editor::setupDialogButtonBox()
|
||||||
void Editor::setupDrawer()
|
void Editor::setupDrawer()
|
||||||
{
|
{
|
||||||
using Q = QskDrawer;
|
using Q = QskDrawer;
|
||||||
|
using A = QskAspect;
|
||||||
|
|
||||||
setPadding( Q::Panel, 5_dp );
|
|
||||||
setGradient( Q::Panel, m_pal.background );
|
setGradient( Q::Panel, m_pal.background );
|
||||||
setHint( Q::Overlay | QskAspect::Style, false );
|
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
|
||||||
|
|
||||||
setAnimation( Q::Panel | QskAspect::Position, qskDuration );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupSlider()
|
void Editor::setupSlider()
|
||||||
|
|
@ -1264,6 +1260,7 @@ void Editor::setupSubWindow()
|
||||||
for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
|
for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
|
||||||
setAnimation( subControl | A::Color, qskDuration );
|
setAnimation( subControl | A::Color, qskDuration );
|
||||||
|
|
||||||
|
setAnimation( Q::Panel | A::Position, qskDuration, QEasingCurve::OutCubic );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme )
|
QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme )
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ void Editor::setupPopup()
|
||||||
using Q = QskPopup;
|
using Q = QskPopup;
|
||||||
|
|
||||||
setHint( Q::Overlay | A::Style, true );
|
setHint( Q::Overlay | A::Style, true );
|
||||||
setGradient( Q::Overlay, QColor( 220, 220, 220, 150 ) );
|
setGradient( Q::Overlay, qRgba( 220, 220, 220, 150 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupMenu()
|
void Editor::setupMenu()
|
||||||
|
|
@ -446,11 +446,8 @@ void Editor::setupMenu()
|
||||||
setGraphicRole( Q::Icon | Q::Disabled, DisabledSymbol );
|
setGraphicRole( Q::Icon | Q::Disabled, DisabledSymbol );
|
||||||
setGraphicRole( Q::Icon | Q::Selected, CursorSymbol );
|
setGraphicRole( Q::Icon | Q::Selected, CursorSymbol );
|
||||||
|
|
||||||
setPosition( Q::Panel, 0 );
|
|
||||||
setPosition( Q::Panel | QskPopup::Closed, 1 );
|
|
||||||
|
|
||||||
setAnimation( Q::Panel | A::Metric, 150 );
|
|
||||||
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
|
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
|
||||||
|
setAnimation( Q::Panel | A::Position, 100 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupTextLabel()
|
void Editor::setupTextLabel()
|
||||||
|
|
@ -759,13 +756,13 @@ void Editor::setupDialogButtonBox()
|
||||||
setBoxShape( Q::Panel, 2 );
|
setBoxShape( Q::Panel, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupDrawer() {
|
void Editor::setupDrawer()
|
||||||
|
{
|
||||||
using Q = QskDrawer;
|
using Q = QskDrawer;
|
||||||
|
using A = QskAspect;
|
||||||
|
|
||||||
setPadding( Q::Panel, 5 );
|
setPanel( Q::Panel, Plain );
|
||||||
setGradient( Q::Panel, m_pal.darker125 );
|
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
|
||||||
setAnimation( Q::Panel | QskAspect::Position, qskDuration );
|
|
||||||
setHint( Q::Overlay | QskAspect::Style, false );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupTabButton()
|
void Editor::setupTabButton()
|
||||||
|
|
@ -1127,8 +1124,12 @@ void Editor::setupSubWindow()
|
||||||
|
|
||||||
setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter );
|
setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter );
|
||||||
|
|
||||||
|
#if 1
|
||||||
for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
|
for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
|
||||||
setAnimation( subControl | A::Color, qskDuration );
|
setAnimation( subControl | A::Color, qskDuration );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setAnimation( Q::Panel | A::Position, qskDuration, QEasingCurve::OutCubic );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setupSpinBox()
|
void Editor::setupSpinBox()
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ list(APPEND HEADERS
|
||||||
controls/QskComboBoxSkinlet.h
|
controls/QskComboBoxSkinlet.h
|
||||||
controls/QskControl.h
|
controls/QskControl.h
|
||||||
controls/QskDrawer.h
|
controls/QskDrawer.h
|
||||||
|
controls/QskDrawerSkinlet.h
|
||||||
controls/QskEvent.h
|
controls/QskEvent.h
|
||||||
controls/QskFlickAnimator.h
|
controls/QskFlickAnimator.h
|
||||||
controls/QskFocusIndicator.h
|
controls/QskFocusIndicator.h
|
||||||
|
|
@ -280,6 +281,7 @@ list(APPEND SOURCES
|
||||||
controls/QskControlPrivate.cpp
|
controls/QskControlPrivate.cpp
|
||||||
controls/QskDirtyItemFilter.cpp
|
controls/QskDirtyItemFilter.cpp
|
||||||
controls/QskDrawer.cpp
|
controls/QskDrawer.cpp
|
||||||
|
controls/QskDrawerSkinlet.cpp
|
||||||
controls/QskEvent.cpp
|
controls/QskEvent.cpp
|
||||||
controls/QskFlickAnimator.cpp
|
controls/QskFlickAnimator.cpp
|
||||||
controls/QskFocusIndicator.cpp
|
controls/QskFocusIndicator.cpp
|
||||||
|
|
|
||||||
|
|
@ -915,10 +915,16 @@ void QskControl::itemChange( QQuickItem::ItemChange change,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QQuickItem::ItemChildAddedChange:
|
case QQuickItem::ItemChildAddedChange:
|
||||||
|
case QQuickItem::ItemChildRemovedChange:
|
||||||
{
|
{
|
||||||
if ( autoLayoutChildren() && qskIsAdjustableByLayout( value.item ) )
|
if ( autoLayoutChildren() )
|
||||||
polish();
|
{
|
||||||
|
if ( qskIsVisibleToLayout( value.item ) )
|
||||||
|
resetImplicitSize();
|
||||||
|
|
||||||
|
if ( qskIsAdjustableByLayout( value.item ) )
|
||||||
|
polish();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QQuickItem::ItemActiveFocusHasChanged:
|
case QQuickItem::ItemActiveFocusHasChanged:
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,268 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskDrawer.h"
|
#include "QskDrawer.h"
|
||||||
#include "QskAspect.h"
|
#include "QskAspect.h"
|
||||||
#include "QskControl.h"
|
#include "QskQuick.h"
|
||||||
|
#include "QskEvent.h"
|
||||||
|
|
||||||
#include <QskPopup.h>
|
#include "QskPanGestureRecognizer.h"
|
||||||
#include <QskBox.h>
|
#include "QskGesture.h"
|
||||||
#include <QskAnimationHint.h>
|
|
||||||
#include <QskQuick.h>
|
#include <qguiapplication.h>
|
||||||
|
#include <qstylehints.h>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquickitem_p.h>
|
||||||
|
#include <private/qquickitemchangelistener_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskDrawer, Panel )
|
QSK_SUBCONTROL( QskDrawer, Panel )
|
||||||
QSK_SUBCONTROL( QskDrawer, Overlay )
|
|
||||||
|
static inline qreal qskDefaultDragMargin()
|
||||||
|
{
|
||||||
|
// a skin hint ???
|
||||||
|
return QGuiApplication::styleHints()->startDragDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void qskCatchMouseEvents( QQuickItem* item )
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
// manipulating other items - do we really want to do this ?
|
||||||
|
item->setAcceptedMouseButtons( Qt::LeftButton );
|
||||||
|
item->setFiltersChildMouseEvents( true );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool qskCheckDirection( Qt::Edge edge, const QskPanGesture* gesture )
|
||||||
|
{
|
||||||
|
const auto degrees = gesture->angle();
|
||||||
|
|
||||||
|
switch( edge )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
return ( degrees < 90.0 ) || ( degrees ) > 270.0;
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
return ( degrees > 90.0 ) && ( degrees < 270.0 );
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
return degrees > 180.0;
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
return degrees < 180.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QRectF qskAlignedToEdge(
|
||||||
|
const QRectF& r, const QSizeF& sz, Qt::Edge edge )
|
||||||
|
{
|
||||||
|
switch( edge )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
return QRectF( r.left(), r.top(), sz.width(), r.height() );
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
return QRectF( r.right() - sz.width(), r.top(), sz.width(), r.height() );
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
return QRectF( r.left(), r.top(), r.width(), sz.height() );
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
return QRectF( r.left(), r.bottom() - sz.height(), r.width(), sz.height() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
static QPointF qskDrawerTranslation( const QskDrawer* drawer, const QSizeF& size )
|
||||||
|
{
|
||||||
|
const auto ratio = 1.0 - drawer->fadingFactor();
|
||||||
|
|
||||||
|
auto dx = 0.0;
|
||||||
|
auto dy = 0.0;
|
||||||
|
|
||||||
|
switch( drawer->edge() )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
dx = -ratio * size.width();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
dx = ratio * size.width();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
dy = -ratio * size.height();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
dy = ratio * size.height();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPointF( dx, dy );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Using an eventFilter for QskEvent::GeometryChange instead ???
|
||||||
|
|
||||||
|
class GeometryListener final : public QQuickItemChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GeometryListener( QQuickItem* item, QQuickItem* adjustedItem )
|
||||||
|
: m_item( item )
|
||||||
|
, m_adjustedItem( adjustedItem )
|
||||||
|
{
|
||||||
|
adjust();
|
||||||
|
setEnabled( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
~GeometryListener()
|
||||||
|
{
|
||||||
|
setEnabled( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void itemGeometryChanged( QQuickItem*,
|
||||||
|
QQuickGeometryChange, const QRectF& ) override
|
||||||
|
{
|
||||||
|
adjust();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void adjust()
|
||||||
|
{
|
||||||
|
m_adjustedItem->polish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled( bool on )
|
||||||
|
{
|
||||||
|
const auto changeTypes = QQuickItemPrivate::Geometry;
|
||||||
|
|
||||||
|
auto d = QQuickItemPrivate::get( m_item );
|
||||||
|
if ( on )
|
||||||
|
d->addItemChangeListener( this, changeTypes );
|
||||||
|
else
|
||||||
|
d->removeItemChangeListener( this, changeTypes );
|
||||||
|
}
|
||||||
|
|
||||||
|
QQuickItem* m_item;
|
||||||
|
QQuickItem* m_adjustedItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GestureRecognizer : public QskPanGestureRecognizer
|
||||||
|
{
|
||||||
|
using Inherited = QskPanGestureRecognizer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GestureRecognizer( QskDrawer* drawer )
|
||||||
|
: QskPanGestureRecognizer( drawer )
|
||||||
|
{
|
||||||
|
setWatchedItem( drawer->parentItem() );
|
||||||
|
setTargetItem( drawer );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool isAcceptedPos( const QPointF& pos ) const override
|
||||||
|
{
|
||||||
|
auto drawer = qobject_cast< const QskDrawer* >( targetItem() );
|
||||||
|
if ( drawer->isFading() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto rect = qskItemRect( watchedItem() );
|
||||||
|
|
||||||
|
if ( !drawer->isOpen() )
|
||||||
|
{
|
||||||
|
const auto dragMargin = drawer->dragMargin();
|
||||||
|
if ( dragMargin <= 0.0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch( drawer->edge() )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
rect.setRight( rect.left() + dragMargin );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
rect.setLeft( rect.right() - dragMargin );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
rect.setBottom( rect.top() + dragMargin );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
rect.setTop( rect.bottom() - dragMargin );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect.contains( pos );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class QskDrawer::PrivateData
|
class QskDrawer::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QskControl* content = nullptr;
|
PrivateData( Qt::Edge edge )
|
||||||
QskBox* contentBox = nullptr;
|
: edge( edge )
|
||||||
Qt::Edge edge = Qt::LeftEdge;
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void resetListener( QskDrawer* drawer )
|
||||||
|
{
|
||||||
|
delete listener;
|
||||||
|
listener = nullptr;
|
||||||
|
|
||||||
|
if ( drawer->parentItem() && drawer->isVisible() )
|
||||||
|
listener = new GeometryListener( drawer->parentItem(), drawer );
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryListener* listener = nullptr;
|
||||||
|
GestureRecognizer* gestureRecognizer = nullptr;
|
||||||
|
|
||||||
|
qreal dragMargin = qskDefaultDragMargin();
|
||||||
|
Qt::Edge edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
||||||
: Inherited ( parentItem )
|
: QskDrawer( Qt::LeftEdge, parentItem )
|
||||||
, m_data( new PrivateData )
|
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QskDrawer::QskDrawer( Qt::Edge edge, QQuickItem* parentItem )
|
||||||
|
: Inherited ( parentItem )
|
||||||
|
, m_data( new PrivateData( edge ) )
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
setZ( 1 );
|
setZ( 1 );
|
||||||
|
#endif
|
||||||
|
|
||||||
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
||||||
|
|
||||||
m_data->contentBox = new QskBox(this);
|
/*
|
||||||
m_data->contentBox->setSubcontrolProxy( QskBox::Panel, Panel );
|
A drawer wants to be on top of its parent - not being
|
||||||
m_data->contentBox->setPanel( true );
|
layouted into its layoutRect(). So we opt out and do
|
||||||
|
the layout updates manually.
|
||||||
|
*/
|
||||||
|
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||||
|
|
||||||
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
setAutoLayoutChildren( true );
|
||||||
|
setInteractive( true );
|
||||||
|
|
||||||
setFaderAspect( Panel | QskAspect::Metric );
|
connect( this, &QskPopup::fadingChanged, this, &QQuickItem::setClip );
|
||||||
|
|
||||||
connect(this, &QskDrawer::closed, this, [this]() {
|
|
||||||
startTransition( Panel | QskAspect::Metric,
|
|
||||||
animationHint( Panel | QskAspect::Position ),
|
|
||||||
0.0, 1.0 );
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QskDrawer::~QskDrawer()
|
QskDrawer::~QskDrawer()
|
||||||
{
|
{
|
||||||
|
delete m_data->listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::Edge QskDrawer::edge() const
|
Qt::Edge QskDrawer::edge() const
|
||||||
|
|
@ -60,79 +280,188 @@ void QskDrawer::setEdge( Qt::Edge edge )
|
||||||
edgeChanged( edge );
|
edgeChanged( edge );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskDrawer::setContent( QskControl* content )
|
void QskDrawer::setInteractive( bool on )
|
||||||
{
|
{
|
||||||
content->setParentItem( m_data->contentBox );
|
if ( on == isInteractive() )
|
||||||
if ( content->parent() == nullptr )
|
|
||||||
content->setParent( m_data->contentBox );
|
|
||||||
|
|
||||||
m_data->content = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskDrawer::updateLayout()
|
|
||||||
{
|
|
||||||
if ( !isOpen() && !isFading() )
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto padding = paddingHint( Panel );
|
if ( on )
|
||||||
|
|
||||||
auto contentSize = m_data->content->preferredSize();
|
|
||||||
contentSize = contentSize.grownBy( padding );
|
|
||||||
|
|
||||||
const auto parentSize = parentItem()->size();
|
|
||||||
|
|
||||||
switch( m_data->edge )
|
|
||||||
{
|
{
|
||||||
case Qt::Edge::LeftEdge:
|
m_data->gestureRecognizer = new GestureRecognizer( this );
|
||||||
{
|
if ( parentItem() )
|
||||||
qreal x = metric( faderAspect() ) * contentSize.width() * -1.0;
|
qskCatchMouseEvents( parentItem() );
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
x, 0, contentSize.width(), parentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Qt::Edge::RightEdge:
|
else
|
||||||
{
|
{
|
||||||
qreal x = ( metric( faderAspect() ) * contentSize.width() )
|
// how to revert qskCatchMouseEvents properly ???
|
||||||
+ parentSize.width() - contentSize.width();
|
delete m_data->gestureRecognizer;
|
||||||
|
m_data->gestureRecognizer = nullptr;
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
x, 0, contentSize.width(), parentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Edge::TopEdge:
|
Q_EMIT interactiveChanged( on );
|
||||||
{
|
|
||||||
qreal y = metric( faderAspect() ) * contentSize.height();
|
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
0, -y, parentSize.width(), contentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Edge::BottomEdge:
|
bool QskDrawer::isInteractive() const
|
||||||
{
|
{
|
||||||
qreal y = metric( faderAspect() ) * contentSize.height() + parentSize.height() -
|
return m_data->gestureRecognizer != nullptr;
|
||||||
contentSize.height();
|
}
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
void QskDrawer::setDragMargin( qreal margin )
|
||||||
0, y, parentSize.width(), contentSize.height() );
|
{
|
||||||
|
margin = std::max( margin, 0.0 );
|
||||||
|
|
||||||
|
if ( margin != m_data->dragMargin )
|
||||||
|
{
|
||||||
|
m_data->dragMargin = margin;
|
||||||
|
Q_EMIT dragMarginChanged( margin );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskDrawer::resetDragMargin()
|
||||||
|
{
|
||||||
|
setDragMargin( qskDefaultDragMargin() );
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QskDrawer::dragMargin() const
|
||||||
|
{
|
||||||
|
return m_data->dragMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskDrawer::gestureEvent( QskGestureEvent* event )
|
||||||
|
{
|
||||||
|
if ( event->gesture()->type() == QskGesture::Pan )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
For the moment we treat the gesture like a swipe gesture
|
||||||
|
without dragging the drawer when moving the mouse. TODO ...
|
||||||
|
*/
|
||||||
|
const auto gesture = static_cast< const QskPanGesture* >( event->gesture().get() );
|
||||||
|
if ( gesture->state() == QskGesture::Finished )
|
||||||
|
{
|
||||||
|
const auto forwards = qskCheckDirection( m_data->edge, gesture );
|
||||||
|
if ( forwards != isOpen() )
|
||||||
|
setOpen( forwards );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::gestureEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskDrawer::itemChange( QQuickItem::ItemChange change,
|
||||||
|
const QQuickItem::ItemChangeData& value )
|
||||||
|
{
|
||||||
|
Inherited::itemChange( change, value );
|
||||||
|
|
||||||
|
switch( static_cast< int >( change ) )
|
||||||
|
{
|
||||||
|
case QQuickItem::ItemParentHasChanged:
|
||||||
|
{
|
||||||
|
if ( parentItem() && isInteractive() )
|
||||||
|
qskCatchMouseEvents( parentItem() );
|
||||||
|
|
||||||
|
m_data->resetListener( this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QQuickItem::ItemVisibleHasChanged:
|
||||||
|
{
|
||||||
|
m_data->resetListener( this );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data->content->setGeometry( QPointF( padding.left(), padding.top() ),
|
|
||||||
m_data->contentBox->size().shrunkBy( padding ) );
|
|
||||||
|
|
||||||
Inherited::updateLayout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskDrawer::aboutToShow()
|
void QskDrawer::updateResources()
|
||||||
{
|
{
|
||||||
startTransition( Panel | QskAspect::Metric,
|
Inherited::updateResources();
|
||||||
animationHint( Panel | QskAspect::Position ), 1.0, 0.0 );
|
|
||||||
|
|
||||||
Inherited::aboutToShow();
|
/*
|
||||||
|
Adjusting the geometry to the parent needs to be done before
|
||||||
|
the layouting of the children ( -> autoLayoutChildren ) is done.
|
||||||
|
So we are using this hook even if it is not about resources: TODO ...
|
||||||
|
*/
|
||||||
|
if ( const auto item = parentItem() )
|
||||||
|
{
|
||||||
|
auto r = qskItemRect( item );
|
||||||
|
r = qskAlignedToEdge( r, sizeConstraint( Qt::PreferredSize ), edge() );
|
||||||
|
|
||||||
|
r.translate( qskDrawerTranslation( this, r.size() ) );
|
||||||
|
setGeometry( r );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskDrawer::updateNode( QSGNode* node )
|
||||||
|
{
|
||||||
|
if ( isFading() && clip() )
|
||||||
|
{
|
||||||
|
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The clipRect is changing while fading. Couldn't
|
||||||
|
find a way how to trigger updates - maybe be enabling/disabling
|
||||||
|
the clip. So we do the updates manually. TODO ...
|
||||||
|
*/
|
||||||
|
const auto r = clipRect();
|
||||||
|
if ( r != clipNode->rect() )
|
||||||
|
{
|
||||||
|
clipNode->setRect( r );
|
||||||
|
clipNode->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::updateNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskDrawer::clipRect() const
|
||||||
|
{
|
||||||
|
if ( isFading() && parentItem() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We might not fit into our parent and our children not
|
||||||
|
into our rect. So we want to have a clip against the
|
||||||
|
edge, where the drawer slides in/out only.
|
||||||
|
Otherwise we would have unwanted effects, when clipping gets
|
||||||
|
disabled once the transition is over.
|
||||||
|
*/
|
||||||
|
constexpr qreal d = 1e6;
|
||||||
|
|
||||||
|
QRectF r( -d, -d, 2.0 * d, 2.0 * d );
|
||||||
|
|
||||||
|
switch( edge() )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
r.setLeft( -x() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
r.setRight( parentItem()->width() - x() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
r.setTop( -y() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
r.setBottom( parentItem()->height() - y() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::clipRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAspect QskDrawer::fadingAspect() const
|
||||||
|
{
|
||||||
|
return QskDrawer::Panel | QskAspect::Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskDrawer::layoutRectForSize( const QSizeF& size ) const
|
||||||
|
{
|
||||||
|
return subControlContentsRect( size, Panel );
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_QskDrawer.cpp"
|
#include "moc_QskDrawer.cpp"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifndef QSK_DRAWER_H
|
#ifndef QSK_DRAWER_H
|
||||||
#define QSK_DRAWER_H
|
#define QSK_DRAWER_H
|
||||||
|
|
||||||
#include "QskPopup.h"
|
#include "QskPopup.h"
|
||||||
#include <qnamespace.h>
|
|
||||||
|
|
||||||
class QSK_EXPORT QskDrawer : public QskPopup
|
class QSK_EXPORT QskDrawer : public QskPopup
|
||||||
{
|
{
|
||||||
|
|
@ -12,24 +16,46 @@ class QSK_EXPORT QskDrawer : public QskPopup
|
||||||
|
|
||||||
Q_PROPERTY( Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged )
|
Q_PROPERTY( Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged )
|
||||||
|
|
||||||
|
Q_PROPERTY( qreal dragMargin READ dragMargin
|
||||||
|
WRITE setDragMargin RESET resetDragMargin NOTIFY dragMarginChanged )
|
||||||
|
|
||||||
|
Q_PROPERTY( bool interactive READ isInteractive
|
||||||
|
WRITE setInteractive NOTIFY interactiveChanged )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Panel, Overlay )
|
QSK_SUBCONTROLS( Panel )
|
||||||
|
|
||||||
QskDrawer( QQuickItem* = nullptr );
|
QskDrawer( QQuickItem* = nullptr );
|
||||||
|
QskDrawer( Qt::Edge, QQuickItem* = nullptr );
|
||||||
|
|
||||||
~QskDrawer() override;
|
~QskDrawer() override;
|
||||||
|
|
||||||
void setEdge( Qt::Edge );
|
void setEdge( Qt::Edge );
|
||||||
Qt::Edge edge() const;
|
Qt::Edge edge() const;
|
||||||
|
|
||||||
void updateLayout() override;
|
void setInteractive( bool );
|
||||||
|
bool isInteractive() const;
|
||||||
|
|
||||||
void setContent( QskControl* );
|
void setDragMargin( qreal );
|
||||||
|
void resetDragMargin();
|
||||||
|
qreal dragMargin() const;
|
||||||
|
|
||||||
|
QRectF clipRect() const override;
|
||||||
|
QskAspect fadingAspect() const override;
|
||||||
|
|
||||||
|
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void edgeChanged( Qt::Edge );
|
void edgeChanged( Qt::Edge );
|
||||||
|
void dragMarginChanged( qreal );
|
||||||
|
void interactiveChanged( bool );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void aboutToShow() override;
|
void gestureEvent( QskGestureEvent* ) override;
|
||||||
|
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||||
|
|
||||||
|
void updateResources() override;
|
||||||
|
void updateNode( QSGNode* ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskDrawerSkinlet.h"
|
||||||
|
#include "QskDrawer.h"
|
||||||
|
|
||||||
|
QskDrawerSkinlet::QskDrawerSkinlet( QskSkin* skin )
|
||||||
|
: Inherited( skin )
|
||||||
|
{
|
||||||
|
appendNodeRoles( { PanelRole } );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskDrawerSkinlet::~QskDrawerSkinlet() = default;
|
||||||
|
|
||||||
|
QRectF QskDrawerSkinlet::subControlRect(
|
||||||
|
const QskSkinnable* skinnable, const QRectF& contentsRect,
|
||||||
|
QskAspect::Subcontrol subControl ) const
|
||||||
|
{
|
||||||
|
if ( subControl == QskDrawer::Panel )
|
||||||
|
return contentsRect;
|
||||||
|
|
||||||
|
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSGNode* QskDrawerSkinlet::updateSubNode(
|
||||||
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
if ( nodeRole == PanelRole )
|
||||||
|
return updateBoxNode( skinnable, node, QskDrawer::Panel );
|
||||||
|
|
||||||
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF QskDrawerSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||||
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
||||||
|
{
|
||||||
|
if ( which == Qt::PreferredSize )
|
||||||
|
return skinnable->strutSizeHint( QskDrawer::Panel );
|
||||||
|
|
||||||
|
return Inherited::sizeHint( skinnable, which, constraint );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_QskDrawerSkinlet.cpp"
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_DRAWER_SKINLET_H
|
||||||
|
#define QSK_DRAWER_SKINLET_H
|
||||||
|
|
||||||
|
#include "QskPopupSkinlet.h"
|
||||||
|
|
||||||
|
class QSK_EXPORT QskDrawerSkinlet : public QskPopupSkinlet
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
|
||||||
|
using Inherited = QskPopupSkinlet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NodeRole
|
||||||
|
{
|
||||||
|
ContentsRole = Inherited::RoleCount,
|
||||||
|
PanelRole,
|
||||||
|
|
||||||
|
RoleCount
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_INVOKABLE QskDrawerSkinlet( QskSkin* = nullptr );
|
||||||
|
~QskDrawerSkinlet() override;
|
||||||
|
|
||||||
|
QRectF subControlRect( const QskSkinnable*,
|
||||||
|
const QRectF&, QskAspect::Subcontrol ) const override;
|
||||||
|
|
||||||
|
QSizeF sizeHint( const QskSkinnable*,
|
||||||
|
Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -68,7 +68,8 @@ class QskGestureRecognizer::PrivateData
|
||||||
return watchedItem->acceptedMouseButtons();
|
return watchedItem->acceptedMouseButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickItem* watchedItem = nullptr;
|
QPointer< QQuickItem > watchedItem = nullptr;
|
||||||
|
QPointer< QQuickItem > targetItem = nullptr;
|
||||||
|
|
||||||
QVector< QMouseEvent* > pendingEvents;
|
QVector< QMouseEvent* > pendingEvents;
|
||||||
|
|
||||||
|
|
@ -121,6 +122,16 @@ QQuickItem* QskGestureRecognizer::watchedItem() const
|
||||||
return m_data->watchedItem;
|
return m_data->watchedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskGestureRecognizer::setTargetItem( QQuickItem* item )
|
||||||
|
{
|
||||||
|
m_data->targetItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
QQuickItem* QskGestureRecognizer::targetItem() const
|
||||||
|
{
|
||||||
|
return m_data->targetItem;
|
||||||
|
}
|
||||||
|
|
||||||
void QskGestureRecognizer::setAcceptedMouseButtons( Qt::MouseButtons buttons )
|
void QskGestureRecognizer::setAcceptedMouseButtons( Qt::MouseButtons buttons )
|
||||||
{
|
{
|
||||||
m_data->buttons = buttons;
|
m_data->buttons = buttons;
|
||||||
|
|
@ -131,12 +142,9 @@ Qt::MouseButtons QskGestureRecognizer::acceptedMouseButtons() const
|
||||||
return m_data->buttons;
|
return m_data->buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF QskGestureRecognizer::gestureRect() const
|
bool QskGestureRecognizer::isAcceptedPos( const QPointF& pos ) const
|
||||||
{
|
{
|
||||||
if ( m_data->watchedItem )
|
return m_data->watchedItem && m_data->watchedItem->contains( pos );
|
||||||
return qskItemRect( m_data->watchedItem );
|
|
||||||
|
|
||||||
return QRectF( 0.0, 0.0, -1.0, -1.0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskGestureRecognizer::setRejectOnTimeout( bool on )
|
void QskGestureRecognizer::setRejectOnTimeout( bool on )
|
||||||
|
|
@ -302,7 +310,7 @@ bool QskGestureRecognizer::processMouseEvent(
|
||||||
|
|
||||||
if ( event->type() == QEvent::MouseButtonPress )
|
if ( event->type() == QEvent::MouseButtonPress )
|
||||||
{
|
{
|
||||||
if ( !gestureRect().contains( pos ) )
|
if ( !isAcceptedPos( pos ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( m_data->state != Idle )
|
if ( m_data->state != Idle )
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class QSK_EXPORT QskGestureRecognizer : public QObject
|
||||||
|
|
||||||
Q_PROPERTY( State state READ state NOTIFY stateChanged )
|
Q_PROPERTY( State state READ state NOTIFY stateChanged )
|
||||||
Q_PROPERTY( QQuickItem* watchedItem READ watchedItem WRITE setWatchedItem )
|
Q_PROPERTY( QQuickItem* watchedItem READ watchedItem WRITE setWatchedItem )
|
||||||
|
Q_PROPERTY( QQuickItem* targetItem READ targetItem WRITE setTargetItem )
|
||||||
|
|
||||||
Q_PROPERTY( Qt::MouseButtons acceptedMouseButtons
|
Q_PROPERTY( Qt::MouseButtons acceptedMouseButtons
|
||||||
READ acceptedMouseButtons WRITE setAcceptedMouseButtons )
|
READ acceptedMouseButtons WRITE setAcceptedMouseButtons )
|
||||||
|
|
@ -43,11 +44,16 @@ class QSK_EXPORT QskGestureRecognizer : public QObject
|
||||||
QskGestureRecognizer( QObject* parent = nullptr );
|
QskGestureRecognizer( QObject* parent = nullptr );
|
||||||
~QskGestureRecognizer() override;
|
~QskGestureRecognizer() override;
|
||||||
|
|
||||||
bool eventFilter( QObject* object, QEvent* event) override;
|
bool eventFilter( QObject*, QEvent* ) override;
|
||||||
|
|
||||||
|
// the item where the gesture happens
|
||||||
void setWatchedItem( QQuickItem* );
|
void setWatchedItem( QQuickItem* );
|
||||||
QQuickItem* watchedItem() const;
|
QQuickItem* watchedItem() const;
|
||||||
|
|
||||||
|
// the item processing the gesture events
|
||||||
|
void setTargetItem( QQuickItem* );
|
||||||
|
QQuickItem* targetItem() const;
|
||||||
|
|
||||||
// Qt::NoButton means: all buttons accepted
|
// Qt::NoButton means: all buttons accepted
|
||||||
void setAcceptedMouseButtons( Qt::MouseButtons );
|
void setAcceptedMouseButtons( Qt::MouseButtons );
|
||||||
Qt::MouseButtons acceptedMouseButtons() const;
|
Qt::MouseButtons acceptedMouseButtons() const;
|
||||||
|
|
@ -67,7 +73,7 @@ class QSK_EXPORT QskGestureRecognizer : public QObject
|
||||||
|
|
||||||
State state() const;
|
State state() const;
|
||||||
|
|
||||||
virtual QRectF gestureRect() const;
|
virtual bool isAcceptedPos( const QPointF& ) const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void stateChanged( State from, State to );
|
void stateChanged( State from, State to );
|
||||||
|
|
|
||||||
|
|
@ -76,20 +76,28 @@ static inline QVariant qskAligned05( const QVariant& value )
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline bool qskCheckReceiverThread( const QObject* receiver )
|
static inline void qskSendAnimatorEvent(
|
||||||
|
const QskAspect aspect, int index, bool on, QObject* receiver )
|
||||||
|
{
|
||||||
|
const auto state = on ? QskAnimatorEvent::Started : QskAnimatorEvent::Terminated;
|
||||||
|
|
||||||
|
const auto thread = receiver->thread();
|
||||||
|
if ( thread && ( thread != QThread::currentThread() ) )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
QskInputPanelSkinlet changes the skin state, what leads to
|
QskInputPanelSkinlet changes the skin state, what leads to
|
||||||
sending events from the wrong thread. Until we have fixed it
|
sending events from the wrong thread. We can't use
|
||||||
let's block sending the event to avoid running into assertions
|
QCoreApplication::sendEvent then, TODO ...
|
||||||
in QCoreApplication::sendEvent
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const QThread* thread = receiver->thread();
|
auto event = new QskAnimatorEvent( aspect, index, state );
|
||||||
if ( thread == nullptr )
|
QCoreApplication::postEvent( receiver, event );
|
||||||
return true;
|
}
|
||||||
|
else
|
||||||
return ( thread == QThread::currentThread() );
|
{
|
||||||
|
QskAnimatorEvent event( aspect, index, state );
|
||||||
|
QCoreApplication::sendEvent( receiver, &event );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QskHintAnimator::QskHintAnimator() noexcept
|
QskHintAnimator::QskHintAnimator() noexcept
|
||||||
|
|
@ -141,7 +149,7 @@ void QskHintAnimator::advance( qreal progress )
|
||||||
{
|
{
|
||||||
if ( m_updateFlags == QskAnimationHint::UpdateAuto )
|
if ( m_updateFlags == QskAnimationHint::UpdateAuto )
|
||||||
{
|
{
|
||||||
if ( m_aspect.isMetric() )
|
if ( !m_aspect.isColor() )
|
||||||
{
|
{
|
||||||
m_control->resetImplicitSize();
|
m_control->resetImplicitSize();
|
||||||
|
|
||||||
|
|
@ -338,11 +346,7 @@ void QskHintAnimatorTable::start( QskControl* control,
|
||||||
|
|
||||||
animator->start();
|
animator->start();
|
||||||
|
|
||||||
if ( qskCheckReceiverThread( control ) )
|
qskSendAnimatorEvent( aspect, index, true, control );
|
||||||
{
|
|
||||||
QskAnimatorEvent event( aspect, index, QskAnimatorEvent::Started );
|
|
||||||
QCoreApplication::sendEvent( control, &event );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect, int index ) const
|
const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect, int index ) const
|
||||||
|
|
@ -390,15 +394,7 @@ bool QskHintAnimatorTable::cleanup()
|
||||||
it = animators.erase( it );
|
it = animators.erase( it );
|
||||||
|
|
||||||
if ( control )
|
if ( control )
|
||||||
{
|
qskSendAnimatorEvent( aspect, index, false, control );
|
||||||
if ( qskCheckReceiverThread( control ) )
|
|
||||||
{
|
|
||||||
auto event = new QskAnimatorEvent(
|
|
||||||
aspect, index, QskAnimatorEvent::Terminated );
|
|
||||||
|
|
||||||
QCoreApplication::postEvent( control, event );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class QSK_EXPORT QskListViewSkinlet : public QskScrollViewSkinlet
|
||||||
public:
|
public:
|
||||||
enum NodeRole
|
enum NodeRole
|
||||||
{
|
{
|
||||||
TextRole,
|
TextRole = Inherited::RoleCount,
|
||||||
GraphicRole,
|
GraphicRole,
|
||||||
|
|
||||||
RoleCount
|
RoleCount
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ void QskMainView::focusInEvent( QFocusEvent* event )
|
||||||
{
|
{
|
||||||
if ( auto focusItem = nextItemInFocusChain( true ) )
|
if ( auto focusItem = nextItemInFocusChain( true ) )
|
||||||
{
|
{
|
||||||
if ( qskIsItemComplete( focusItem )
|
if ( !qskIsItemInDestructor( focusItem )
|
||||||
&& qskIsAncestorOf( this, focusItem ) )
|
&& qskIsAncestorOf( this, focusItem ) )
|
||||||
{
|
{
|
||||||
focusItem->setFocus( true );
|
focusItem->setFocus( true );
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,10 @@
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
#include <qeventloop.h>
|
#include <qeventloop.h>
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskMenu, Overlay )
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquickitem_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskMenu, Panel )
|
QSK_SUBCONTROL( QskMenu, Panel )
|
||||||
QSK_SUBCONTROL( QskMenu, Segment )
|
QSK_SUBCONTROL( QskMenu, Segment )
|
||||||
QSK_SUBCONTROL( QskMenu, Cursor )
|
QSK_SUBCONTROL( QskMenu, Cursor )
|
||||||
|
|
@ -58,20 +61,23 @@ QskMenu::QskMenu( QQuickItem* parent )
|
||||||
, m_data( new PrivateData )
|
, m_data( new PrivateData )
|
||||||
{
|
{
|
||||||
setModal( true );
|
setModal( true );
|
||||||
setFaderAspect( QskMenu::Panel | QskAspect::Position | QskAspect::Metric );
|
|
||||||
|
|
||||||
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
||||||
setPopupFlag( QskPopup::DeleteOnClose, true );
|
setPopupFlag( QskPopup::DeleteOnClose, true );
|
||||||
|
|
||||||
|
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||||
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
||||||
|
|
||||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
// we hide the focus indicator while fading
|
// we hide the focus indicator while sliding
|
||||||
connect( this, &QskMenu::fadingChanged, this,
|
connect( this, &QskPopup::fadingChanged,
|
||||||
&QskControl::focusIndicatorRectChanged );
|
this, &QskControl::focusIndicatorRectChanged );
|
||||||
|
|
||||||
connect( this, &QskMenu::opened, this,
|
connect( this, &QskPopup::fadingChanged,
|
||||||
|
this, &QQuickItem::setClip );
|
||||||
|
|
||||||
|
connect( this, &QskPopup::opened, this,
|
||||||
[this]() { m_data->triggeredIndex = -1; } );
|
[this]() { m_data->triggeredIndex = -1; } );
|
||||||
|
|
||||||
setAcceptHoverEvents( true );
|
setAcceptHoverEvents( true );
|
||||||
|
|
@ -81,6 +87,17 @@ QskMenu::~QskMenu()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF QskMenu::clipRect() const
|
||||||
|
{
|
||||||
|
if ( isFading() )
|
||||||
|
{
|
||||||
|
constexpr qreal d = 1e6;
|
||||||
|
return QRectF( -d, m_data->origin.y() - y(), 2.0 * d, d );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::clipRect();
|
||||||
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
// has no effect as we do not offer submenus yet. TODO ...
|
// has no effect as we do not offer submenus yet. TODO ...
|
||||||
|
|
@ -263,25 +280,57 @@ QString QskMenu::triggeredText() const
|
||||||
return optionAt( m_data->triggeredIndex ).text();
|
return optionAt( m_data->triggeredIndex ).text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskMenu::updateResources()
|
||||||
|
{
|
||||||
|
qreal dy = 0.0;
|
||||||
|
if ( isFading() )
|
||||||
|
dy = ( 1.0 - fadingFactor() ) * height();
|
||||||
|
|
||||||
|
setPosition( m_data->origin.x(), m_data->origin.y() - dy );
|
||||||
|
|
||||||
|
Inherited::updateResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskMenu::updateNode( QSGNode* node )
|
||||||
|
{
|
||||||
|
if ( isFading() && clip() )
|
||||||
|
{
|
||||||
|
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The clipRect is changing while fading. Couldn't
|
||||||
|
find a way how to trigger updates - maybe be enabling/disabling
|
||||||
|
the clip. So we do the updates manually. TODO ...
|
||||||
|
*/
|
||||||
|
const auto r = clipRect();
|
||||||
|
if ( r != clipNode->rect() )
|
||||||
|
{
|
||||||
|
clipNode->setRect( r );
|
||||||
|
clipNode->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::updateNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
void QskMenu::keyPressEvent( QKeyEvent* event )
|
void QskMenu::keyPressEvent( QKeyEvent* event )
|
||||||
{
|
{
|
||||||
if( m_data->currentIndex < 0 )
|
if( m_data->currentIndex < 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int key = event->key();
|
switch( event->key() )
|
||||||
|
|
||||||
switch( key )
|
|
||||||
{
|
{
|
||||||
case Qt::Key_Up:
|
case Qt::Key_Up:
|
||||||
{
|
{
|
||||||
traverse( -1 );
|
traverse( -1 );
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Key_Down:
|
case Qt::Key_Down:
|
||||||
{
|
{
|
||||||
traverse( 1 );
|
traverse( 1 );
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Key_Select:
|
case Qt::Key_Select:
|
||||||
|
|
@ -293,21 +342,19 @@ void QskMenu::keyPressEvent( QKeyEvent* event )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::Key_Escape:
|
|
||||||
case Qt::Key_Cancel:
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if ( const int steps = qskFocusChainIncrement( event ) )
|
if ( const int steps = qskFocusChainIncrement( event ) )
|
||||||
|
{
|
||||||
traverse( steps );
|
traverse( steps );
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Inherited::keyPressEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
void QskMenu::keyReleaseEvent( QKeyEvent* )
|
void QskMenu::keyReleaseEvent( QKeyEvent* )
|
||||||
{
|
{
|
||||||
if( isPressed() )
|
if( isPressed() )
|
||||||
|
|
@ -439,7 +486,7 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event )
|
||||||
|
|
||||||
void QskMenu::aboutToShow()
|
void QskMenu::aboutToShow()
|
||||||
{
|
{
|
||||||
setGeometry( QRectF( m_data->origin, sizeConstraint() ) );
|
setSize( sizeConstraint() );
|
||||||
|
|
||||||
if ( m_data->currentIndex < 0 )
|
if ( m_data->currentIndex < 0 )
|
||||||
{
|
{
|
||||||
|
|
@ -496,6 +543,11 @@ void QskMenu::trigger( int index )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskAspect QskMenu::fadingAspect() const
|
||||||
|
{
|
||||||
|
return QskMenu::Panel | QskAspect::Position;
|
||||||
|
}
|
||||||
|
|
||||||
int QskMenu::exec()
|
int QskMenu::exec()
|
||||||
{
|
{
|
||||||
(void) execPopup();
|
(void) execPopup();
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
using Inherited = QskPopup;
|
using Inherited = QskPopup;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Overlay, Panel, Segment, Cursor, Text, Icon, Separator )
|
QSK_SUBCONTROLS( Panel, Segment, Cursor, Text, Icon, Separator )
|
||||||
QSK_STATES( Selected, Pressed )
|
QSK_STATES( Selected, Pressed )
|
||||||
|
|
||||||
QskMenu( QQuickItem* parentItem = nullptr );
|
QskMenu( QQuickItem* parentItem = nullptr );
|
||||||
|
|
@ -81,6 +81,9 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
|
|
||||||
bool isPressed() const;
|
bool isPressed() const;
|
||||||
|
|
||||||
|
QRectF clipRect() const override;
|
||||||
|
QskAspect fadingAspect() const override;
|
||||||
|
|
||||||
Q_INVOKABLE int exec();
|
Q_INVOKABLE int exec();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
@ -115,6 +118,9 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
void aboutToShow() override;
|
void aboutToShow() override;
|
||||||
void trigger( int );
|
void trigger( int );
|
||||||
|
|
||||||
|
void updateResources() override;
|
||||||
|
void updateNode( QSGNode* ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void traverse( int steps );
|
void traverse( int steps );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,13 @@
|
||||||
#include "QskGraphic.h"
|
#include "QskGraphic.h"
|
||||||
#include "QskColorFilter.h"
|
#include "QskColorFilter.h"
|
||||||
#include "QskTextOptions.h"
|
#include "QskTextOptions.h"
|
||||||
#include "QskSGNode.h"
|
|
||||||
#include "QskFunctions.h"
|
#include "QskFunctions.h"
|
||||||
#include "QskMargins.h"
|
#include "QskMargins.h"
|
||||||
#include "QskFunctions.h"
|
#include "QskFunctions.h"
|
||||||
#include "QskLabelData.h"
|
#include "QskLabelData.h"
|
||||||
|
|
||||||
|
#include "QskSGNode.h"
|
||||||
|
|
||||||
#include <qfontmetrics.h>
|
#include <qfontmetrics.h>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
|
||||||
|
|
@ -209,11 +210,31 @@ QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
, m_data( new PrivateData() )
|
, m_data( new PrivateData() )
|
||||||
{
|
{
|
||||||
appendNodeRoles( { PanelRole } );
|
appendNodeRoles( { ContentsRole, PanelRole } );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskMenuSkinlet::~QskMenuSkinlet() = default;
|
QskMenuSkinlet::~QskMenuSkinlet() = default;
|
||||||
|
|
||||||
|
QSGNode* QskMenuSkinlet::updateSubNode(
|
||||||
|
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||||
|
{
|
||||||
|
switch ( nodeRole )
|
||||||
|
{
|
||||||
|
case ContentsRole:
|
||||||
|
{
|
||||||
|
const auto popup = static_cast< const QskPopup* >( skinnable );
|
||||||
|
|
||||||
|
auto rect = popup->contentsRect();
|
||||||
|
if ( rect.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return updateContentsNode( popup, node );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
}
|
||||||
|
|
||||||
QRectF QskMenuSkinlet::cursorRect(
|
QRectF QskMenuSkinlet::cursorRect(
|
||||||
const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const
|
const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const
|
||||||
{
|
{
|
||||||
|
|
@ -407,7 +428,8 @@ QskAspect::States QskMenuSkinlet::sampleStates(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF();
|
const auto cursorPos = menu->effectiveSkinHint(
|
||||||
|
Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF();
|
||||||
|
|
||||||
if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index )
|
if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
|
||||||
public:
|
public:
|
||||||
enum NodeRole
|
enum NodeRole
|
||||||
{
|
{
|
||||||
PanelRole = QskPopupSkinlet::RoleCount,
|
ContentsRole = Inherited::RoleCount,
|
||||||
|
PanelRole,
|
||||||
|
|
||||||
RoleCount
|
RoleCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -48,7 +50,10 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
|
||||||
Qt::SizeHint, const QSizeF& ) const override;
|
Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const override;
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
|
QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const;
|
||||||
QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const;
|
QSGNode* updateMenuNode( const QskSkinnable*, QSGNode* ) const;
|
||||||
|
|
||||||
QSGNode* updateSampleNode( const QskSkinnable*,
|
QSGNode* updateSampleNode( const QskSkinnable*,
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@
|
||||||
#include "QskEvent.h"
|
#include "QskEvent.h"
|
||||||
#include "QskGesture.h"
|
#include "QskGesture.h"
|
||||||
|
|
||||||
#include <qcoreapplication.h>
|
|
||||||
#include <qline.h>
|
#include <qline.h>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
#include <qquickitem.h>
|
#include <qquickitem.h>
|
||||||
|
#include <qguiapplication.h>
|
||||||
|
#include <qstylehints.h>
|
||||||
|
|
||||||
static inline bool qskIsInOrientation(
|
static inline bool qskIsInOrientation(
|
||||||
const QPointF& from, const QPointF& to, Qt::Orientations orientations )
|
const QPointF& from, const QPointF& to, Qt::Orientations orientations )
|
||||||
|
|
@ -60,9 +61,14 @@ static inline qreal qskAngle(
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qskSendPanGestureEvent(
|
static void qskSendPanGestureEvent(
|
||||||
QQuickItem* item, QskGesture::State state, qreal velocity, qreal angle,
|
QskGestureRecognizer* recognizer, QskGesture::State state,
|
||||||
const QPointF& origin, const QPointF& lastPosition, const QPointF& position )
|
qreal velocity, qreal angle, const QPointF& origin,
|
||||||
|
const QPointF& lastPosition, const QPointF& position )
|
||||||
{
|
{
|
||||||
|
auto item = recognizer->targetItem();
|
||||||
|
if ( item == nullptr )
|
||||||
|
item = recognizer->watchedItem();
|
||||||
|
|
||||||
auto gesture = std::make_shared< QskPanGesture >();
|
auto gesture = std::make_shared< QskPanGesture >();
|
||||||
gesture->setState( state );
|
gesture->setState( state );
|
||||||
|
|
||||||
|
|
@ -146,7 +152,7 @@ class QskPanGestureRecognizer::PrivateData
|
||||||
public:
|
public:
|
||||||
Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical;
|
Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical;
|
||||||
|
|
||||||
int minDistance = 15;
|
int minDistance = QGuiApplication::styleHints()->startDragDistance() + 5;
|
||||||
|
|
||||||
quint64 timestampVelocity = 0.0; // timestamp of the last mouse event
|
quint64 timestampVelocity = 0.0; // timestamp of the last mouse event
|
||||||
qreal angle = 0.0;
|
qreal angle = 0.0;
|
||||||
|
|
@ -243,12 +249,12 @@ void QskPanGestureRecognizer::processMove( const QPointF& pos, quint64 timestamp
|
||||||
|
|
||||||
if ( started )
|
if ( started )
|
||||||
{
|
{
|
||||||
qskSendPanGestureEvent( watchedItem(), QskGesture::Started,
|
qskSendPanGestureEvent( this, QskGesture::Started,
|
||||||
velocity, m_data->angle, m_data->origin, m_data->origin, m_data->pos );
|
velocity, m_data->angle, m_data->origin, m_data->origin, m_data->pos );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qskSendPanGestureEvent( watchedItem(), QskGesture::Updated,
|
qskSendPanGestureEvent( this, QskGesture::Updated,
|
||||||
velocity, m_data->angle, m_data->origin, oldPos, m_data->pos );
|
velocity, m_data->angle, m_data->origin, oldPos, m_data->pos );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +267,7 @@ void QskPanGestureRecognizer::processRelease( const QPointF&, quint64 timestamp
|
||||||
const ulong elapsedTotal = timestamp - timestampStarted();
|
const ulong elapsedTotal = timestamp - timestampStarted();
|
||||||
const qreal velocity = m_data->velocityTracker.velocity( elapsedTotal );
|
const qreal velocity = m_data->velocityTracker.velocity( elapsedTotal );
|
||||||
|
|
||||||
qskSendPanGestureEvent( watchedItem(), QskGesture::Finished,
|
qskSendPanGestureEvent( this, QskGesture::Finished,
|
||||||
velocity, m_data->angle, m_data->origin, m_data->pos, m_data->pos );
|
velocity, m_data->angle, m_data->origin, m_data->pos, m_data->pos );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,12 @@ class QSK_EXPORT QskPanGestureRecognizer : public QskGestureRecognizer
|
||||||
void setOrientations( Qt::Orientations );
|
void setOrientations( Qt::Orientations );
|
||||||
Qt::Orientations orientations() const;
|
Qt::Orientations orientations() const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void processPress( const QPointF&, quint64 timestamp, bool isFinal ) override;
|
void processPress( const QPointF&, quint64 timestamp, bool isFinal ) override;
|
||||||
void processMove( const QPointF&, quint64 timestamp ) override;
|
void processMove( const QPointF&, quint64 timestamp ) override;
|
||||||
void processRelease( const QPointF&, quint64 timestamp ) override;
|
void processRelease( const QPointF&, quint64 timestamp ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "QskWindow.h"
|
#include "QskWindow.h"
|
||||||
#include "QskEvent.h"
|
#include "QskEvent.h"
|
||||||
#include "QskPlatform.h"
|
#include "QskPlatform.h"
|
||||||
|
#include "QskHintAnimator.h"
|
||||||
|
|
||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
|
|
||||||
|
|
@ -75,6 +76,23 @@ static bool qskReplayMousePress()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qskStartFading( QskPopup* popup, bool on )
|
||||||
|
{
|
||||||
|
const auto aspect = popup->fadingAspect();
|
||||||
|
|
||||||
|
auto hint = popup->animationHint( aspect );
|
||||||
|
|
||||||
|
if ( hint.isValid() )
|
||||||
|
{
|
||||||
|
hint.updateFlags = QskAnimationHint::UpdatePolish | QskAnimationHint::UpdateNode;
|
||||||
|
|
||||||
|
const qreal from = on ? 0.0 : 1.0;
|
||||||
|
const qreal to = on ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
popup->startTransition( aspect, hint, from, to );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
class InputGrabber final : public QskInputGrabber
|
class InputGrabber final : public QskInputGrabber
|
||||||
|
|
@ -130,7 +148,6 @@ class QskPopup::PrivateData
|
||||||
PrivateData()
|
PrivateData()
|
||||||
: flags( 0 )
|
: flags( 0 )
|
||||||
, isModal( false )
|
, isModal( false )
|
||||||
, hasFaderEffect( true )
|
|
||||||
, autoGrabFocus( true )
|
, autoGrabFocus( true )
|
||||||
, handoverFocus( true )
|
, handoverFocus( true )
|
||||||
{
|
{
|
||||||
|
|
@ -139,11 +156,9 @@ class QskPopup::PrivateData
|
||||||
InputGrabber* inputGrabber = nullptr;
|
InputGrabber* inputGrabber = nullptr;
|
||||||
|
|
||||||
uint priority = 0;
|
uint priority = 0;
|
||||||
QskAspect faderAspect;
|
|
||||||
|
|
||||||
int flags : 4;
|
int flags : 4;
|
||||||
bool isModal : 1;
|
bool isModal : 1;
|
||||||
bool hasFaderEffect : 1;
|
|
||||||
|
|
||||||
const bool autoGrabFocus : 1;
|
const bool autoGrabFocus : 1;
|
||||||
const bool handoverFocus : 1;
|
const bool handoverFocus : 1;
|
||||||
|
|
@ -196,6 +211,11 @@ void QskPopup::close()
|
||||||
setOpen( false );
|
setOpen( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskPopup::toggle()
|
||||||
|
{
|
||||||
|
setOpen( !isOpen() );
|
||||||
|
}
|
||||||
|
|
||||||
void QskPopup::setOpen( bool on )
|
void QskPopup::setOpen( bool on )
|
||||||
{
|
{
|
||||||
if ( on == isOpen() )
|
if ( on == isOpen() )
|
||||||
|
|
@ -213,6 +233,8 @@ void QskPopup::setOpen( bool on )
|
||||||
else
|
else
|
||||||
Q_EMIT closed();
|
Q_EMIT closed();
|
||||||
|
|
||||||
|
qskStartFading( this, on );
|
||||||
|
|
||||||
if ( isFading() )
|
if ( isFading() )
|
||||||
{
|
{
|
||||||
Q_EMIT fadingChanged( true );
|
Q_EMIT fadingChanged( true );
|
||||||
|
|
@ -234,15 +256,22 @@ bool QskPopup::isOpen() const
|
||||||
return !hasSkinState( QskPopup::Closed );
|
return !hasSkinState( QskPopup::Closed );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskAspect QskPopup::fadingAspect() const
|
||||||
|
{
|
||||||
|
return QskAspect();
|
||||||
|
}
|
||||||
|
|
||||||
bool QskPopup::isFading() const
|
bool QskPopup::isFading() const
|
||||||
{
|
{
|
||||||
if ( m_data->faderAspect.value() == 0 )
|
return runningHintAnimator( fadingAspect() ) != nullptr;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
QskSkinHintStatus status;
|
qreal QskPopup::fadingFactor() const
|
||||||
(void) effectiveSkinHint( m_data->faderAspect, &status );
|
{
|
||||||
|
if ( auto animator = runningHintAnimator( fadingAspect() ) )
|
||||||
|
return animator->currentValue().value< qreal >();
|
||||||
|
|
||||||
return status.source == QskSkinHintStatus::Animator;
|
return isOpen() ? 1.0 : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF QskPopup::overlayRect() const
|
QRectF QskPopup::overlayRect() const
|
||||||
|
|
@ -293,45 +322,24 @@ void QskPopup::updateInputGrabber()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QskAspect QskPopup::faderAspect() const
|
|
||||||
{
|
|
||||||
return m_data->faderAspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskPopup::setFaderAspect( QskAspect aspect )
|
|
||||||
{
|
|
||||||
auto faderAspect = aspect;
|
|
||||||
faderAspect.clearStates(); // animated values are always stateless
|
|
||||||
|
|
||||||
if ( faderAspect == m_data->faderAspect )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( isFading() )
|
|
||||||
{
|
|
||||||
// stop the running animation TODO ...
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data->faderAspect = faderAspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskPopup::isTransitionAccepted( QskAspect aspect ) const
|
bool QskPopup::isTransitionAccepted( QskAspect aspect ) const
|
||||||
{
|
{
|
||||||
if ( isVisible() && m_data->hasFaderEffect )
|
if ( isVisible() && !isInitiallyPainted() )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Usually we suppress transitions, when a control has never been
|
||||||
|
painted before as there is no valid starting point. Popups are
|
||||||
|
different as we want to have smooth fade/slide appearances.
|
||||||
|
*/
|
||||||
if ( ( aspect.value() == 0 ) )
|
if ( ( aspect.value() == 0 ) )
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( aspect == m_data->faderAspect )
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ( aspect.isColor() )
|
if ( aspect.subControl() == effectiveSubcontrol( fadingAspect().subControl() ) )
|
||||||
{
|
return true;
|
||||||
|
|
||||||
if ( aspect.subControl() == effectiveSubcontrol( QskPopup::Overlay ) )
|
if ( aspect.subControl() == effectiveSubcontrol( QskPopup::Overlay ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::isTransitionAccepted( aspect );
|
return Inherited::isTransitionAccepted( aspect );
|
||||||
}
|
}
|
||||||
|
|
@ -366,20 +374,6 @@ bool QskPopup::isModal() const
|
||||||
return m_data->isModal;
|
return m_data->isModal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskPopup::setFaderEffect( bool on )
|
|
||||||
{
|
|
||||||
if ( on != m_data->hasFaderEffect )
|
|
||||||
{
|
|
||||||
m_data->hasFaderEffect = on;
|
|
||||||
Q_EMIT faderEffectChanged( on );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskPopup::hasFaderEffect() const
|
|
||||||
{
|
|
||||||
return m_data->hasFaderEffect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskPopup::setPopupFlags( PopupFlags flags )
|
void QskPopup::setPopupFlags( PopupFlags flags )
|
||||||
{
|
{
|
||||||
const auto newFlags = static_cast< int >( flags );
|
const auto newFlags = static_cast< int >( flags );
|
||||||
|
|
@ -488,10 +482,10 @@ bool QskPopup::event( QEvent* event )
|
||||||
}
|
}
|
||||||
case QskEvent::Animator:
|
case QskEvent::Animator:
|
||||||
{
|
{
|
||||||
const auto animtorEvent = static_cast< QskAnimatorEvent* >( event );
|
const auto animatorEvent = static_cast< QskAnimatorEvent* >( event );
|
||||||
|
|
||||||
if ( ( animtorEvent->state() == QskAnimatorEvent::Terminated )
|
if ( ( animatorEvent->state() == QskAnimatorEvent::Terminated )
|
||||||
&& ( animtorEvent->aspect() == m_data->faderAspect ) )
|
&& ( animatorEvent->aspect() == fadingAspect() ) )
|
||||||
{
|
{
|
||||||
if ( !isOpen() )
|
if ( !isOpen() )
|
||||||
{
|
{
|
||||||
|
|
@ -523,6 +517,17 @@ bool QskPopup::event( QEvent* event )
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskPopup::keyPressEvent( QKeyEvent* event )
|
||||||
|
{
|
||||||
|
if ( qskIsStandardKeyInput( event, QKeySequence::Cancel ) )
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::keyPressEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
void QskPopup::focusInEvent( QFocusEvent* event )
|
void QskPopup::focusInEvent( QFocusEvent* event )
|
||||||
{
|
{
|
||||||
Inherited::focusInEvent( event );
|
Inherited::focusInEvent( event );
|
||||||
|
|
@ -543,7 +548,7 @@ void QskPopup::focusInEvent( QFocusEvent* event )
|
||||||
|
|
||||||
if ( auto focusItem = nextItemInFocusChain( true ) )
|
if ( auto focusItem = nextItemInFocusChain( true ) )
|
||||||
{
|
{
|
||||||
if ( qskIsItemComplete( focusItem )
|
if ( !qskIsItemInDestructor( focusItem )
|
||||||
&& qskIsAncestorOf( this, focusItem ) )
|
&& qskIsAncestorOf( this, focusItem ) )
|
||||||
{
|
{
|
||||||
focusItem->setFocus( true );
|
focusItem->setFocus( true );
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,11 @@ class QSK_EXPORT QskPopup : public QskControl
|
||||||
|
|
||||||
Q_PROPERTY( bool open READ isOpen WRITE setOpen NOTIFY openChanged )
|
Q_PROPERTY( bool open READ isOpen WRITE setOpen NOTIFY openChanged )
|
||||||
Q_PROPERTY( bool modal READ isModal WRITE setModal NOTIFY modalChanged )
|
Q_PROPERTY( bool modal READ isModal WRITE setModal NOTIFY modalChanged )
|
||||||
|
Q_PROPERTY( bool fading READ isFading NOTIFY fadingChanged )
|
||||||
|
|
||||||
Q_PROPERTY( bool overlay READ hasOverlay
|
Q_PROPERTY( bool overlay READ hasOverlay
|
||||||
WRITE setOverlay RESET resetOverlay NOTIFY overlayChanged )
|
WRITE setOverlay RESET resetOverlay NOTIFY overlayChanged )
|
||||||
|
|
||||||
Q_PROPERTY( bool faderEffect READ hasFaderEffect
|
|
||||||
WRITE setFaderEffect NOTIFY faderEffectChanged )
|
|
||||||
|
|
||||||
Q_PROPERTY( uint priority READ priority WRITE setPriority NOTIFY priorityChanged )
|
Q_PROPERTY( uint priority READ priority WRITE setPriority NOTIFY priorityChanged )
|
||||||
|
|
||||||
using Inherited = QskControl;
|
using Inherited = QskControl;
|
||||||
|
|
@ -58,20 +56,20 @@ class QSK_EXPORT QskPopup : public QskControl
|
||||||
void setPriority( uint );
|
void setPriority( uint );
|
||||||
uint priority() const;
|
uint priority() const;
|
||||||
|
|
||||||
void setFaderEffect( bool );
|
bool isOpen() const;
|
||||||
bool hasFaderEffect() const;
|
bool isClosed() const;
|
||||||
|
|
||||||
QskAspect faderAspect() const;
|
bool isFading() const;
|
||||||
void setFaderAspect( QskAspect );
|
qreal fadingFactor() const;
|
||||||
|
virtual QskAspect fadingAspect() const;
|
||||||
|
|
||||||
virtual QRectF overlayRect() const;
|
virtual QRectF overlayRect() const;
|
||||||
|
|
||||||
bool isOpen() const;
|
|
||||||
bool isFading() const;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void open();
|
void open();
|
||||||
void close();
|
void close();
|
||||||
|
void toggle();
|
||||||
|
|
||||||
void setOpen( bool );
|
void setOpen( bool );
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
@ -83,7 +81,6 @@ class QSK_EXPORT QskPopup : public QskControl
|
||||||
void modalChanged( bool );
|
void modalChanged( bool );
|
||||||
void overlayChanged( bool );
|
void overlayChanged( bool );
|
||||||
void priorityChanged( uint );
|
void priorityChanged( uint );
|
||||||
void faderEffectChanged( bool );
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void aboutToShow() override;
|
void aboutToShow() override;
|
||||||
|
|
@ -92,6 +89,7 @@ class QSK_EXPORT QskPopup : public QskControl
|
||||||
bool event( QEvent* ) override;
|
bool event( QEvent* ) override;
|
||||||
void focusInEvent( QFocusEvent* ) override;
|
void focusInEvent( QFocusEvent* ) override;
|
||||||
void focusOutEvent( QFocusEvent* ) override;
|
void focusOutEvent( QFocusEvent* ) override;
|
||||||
|
void keyPressEvent( QKeyEvent* ) override;
|
||||||
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
||||||
|
|
||||||
void itemChange( QQuickItem::ItemChange,
|
void itemChange( QQuickItem::ItemChange,
|
||||||
|
|
@ -113,6 +111,11 @@ class QSK_EXPORT QskPopup : public QskControl
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool QskPopup::isClosed() const
|
||||||
|
{
|
||||||
|
return !isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS( QskPopup::PopupFlags )
|
Q_DECLARE_OPERATORS_FOR_FLAGS( QskPopup::PopupFlags )
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,108 +5,17 @@
|
||||||
|
|
||||||
#include "QskPopupSkinlet.h"
|
#include "QskPopupSkinlet.h"
|
||||||
#include "QskPopup.h"
|
#include "QskPopup.h"
|
||||||
#include "QskSGNode.h"
|
#include "QskRgbValue.h"
|
||||||
|
|
||||||
#include <qtransform.h>
|
static inline QRgb qskInterpolatedRgb( QRgb rgb, qreal factor )
|
||||||
#include <qsgnode.h>
|
|
||||||
#include <qquickwindow.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
{
|
||||||
class RootNode : public QSGNode
|
return QskRgb::toTransparent( rgb, qRound( factor * qAlpha( rgb ) ) );
|
||||||
{
|
|
||||||
public:
|
|
||||||
~RootNode() override
|
|
||||||
{
|
|
||||||
delete m_clipNode;
|
|
||||||
delete m_transformNode;
|
|
||||||
delete m_contentsNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setClipRect( const QRectF& rect )
|
|
||||||
{
|
|
||||||
if ( m_clipNode == nullptr )
|
|
||||||
{
|
|
||||||
m_clipNode = new QSGClipNode();
|
|
||||||
m_clipNode->setFlag( QSGNode::OwnedByParent, false );
|
|
||||||
m_clipNode->setIsRectangular( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clipNode->setClipRect( rect );
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetClip()
|
|
||||||
{
|
|
||||||
delete m_clipNode;
|
|
||||||
m_clipNode = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTranslation( qreal dx, qreal dy )
|
|
||||||
{
|
|
||||||
if ( dx != 0.0 || dy != 0.0 )
|
|
||||||
{
|
|
||||||
if ( m_transformNode == nullptr )
|
|
||||||
{
|
|
||||||
m_transformNode = new QSGTransformNode();
|
|
||||||
m_transformNode->setFlag( QSGNode::OwnedByParent, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
QTransform transform;
|
|
||||||
transform.translate( dx, dy );
|
|
||||||
|
|
||||||
m_transformNode->setMatrix( transform );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete m_transformNode;
|
|
||||||
m_transformNode = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setContentsNode( QSGNode* contentsNode )
|
|
||||||
{
|
|
||||||
if ( m_contentsNode != contentsNode )
|
|
||||||
{
|
|
||||||
if ( contentsNode )
|
|
||||||
contentsNode->setFlag( QSGNode::OwnedByParent, false );
|
|
||||||
|
|
||||||
delete m_contentsNode;
|
|
||||||
m_contentsNode = contentsNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void rearrangeNodes()
|
|
||||||
{
|
|
||||||
const std::initializer_list< QSGNode* > nodes =
|
|
||||||
{ m_clipNode, m_transformNode, m_contentsNode };
|
|
||||||
|
|
||||||
QSGNode* parentNode = this;
|
|
||||||
for ( auto node : nodes )
|
|
||||||
{
|
|
||||||
if ( node )
|
|
||||||
{
|
|
||||||
QskSGNode::setParentNode( node, parentNode );
|
|
||||||
parentNode = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QSGNode* contentsNode()
|
|
||||||
{
|
|
||||||
return m_contentsNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSGClipNode* m_clipNode = nullptr;
|
|
||||||
QSGTransformNode* m_transformNode = nullptr;
|
|
||||||
QSGNode* m_contentsNode = nullptr;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin )
|
QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin )
|
||||||
: Inherited( skin )
|
: Inherited( skin )
|
||||||
{
|
{
|
||||||
appendNodeRoles( { OverlayRole, ContentsRole } );
|
appendNodeRoles( { OverlayRole } );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskPopupSkinlet::~QskPopupSkinlet() = default;
|
QskPopupSkinlet::~QskPopupSkinlet() = default;
|
||||||
|
|
@ -130,49 +39,38 @@ QSGNode* QskPopupSkinlet::updateSubNode(
|
||||||
switch ( nodeRole )
|
switch ( nodeRole )
|
||||||
{
|
{
|
||||||
case OverlayRole:
|
case OverlayRole:
|
||||||
return updateBoxNode( skinnable, node, QskPopup::Overlay );
|
return updateOverlayNode( popup, node );
|
||||||
|
|
||||||
case ContentsRole:
|
|
||||||
return updateExtraNode( popup, node );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGNode* QskPopupSkinlet::updateExtraNode( const QskPopup* popup, QSGNode* node ) const
|
QSGNode* QskPopupSkinlet::updateOverlayNode(
|
||||||
|
const QskPopup* popup, QSGNode* node ) const
|
||||||
{
|
{
|
||||||
auto cr = popup->contentsRect();
|
using Q = QskPopup;
|
||||||
if ( cr.isEmpty() )
|
|
||||||
|
const auto factor = popup->fadingFactor();
|
||||||
|
if ( factor <= 0.0 )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto rootNode = QskSGNode::ensureNode< RootNode >( node );
|
const auto rect = popup->subControlRect( Q::Overlay );
|
||||||
|
if ( rect.isEmpty() )
|
||||||
const auto faderProgress = popup->metric( popup->faderAspect() );
|
|
||||||
if ( faderProgress > 0.0 && faderProgress <= 1.0 )
|
|
||||||
{
|
|
||||||
auto clipRect = QRectF( popup->mapFromScene( QPointF() ), popup->window()->size() );
|
|
||||||
clipRect.setTop( cr.top() );
|
|
||||||
|
|
||||||
rootNode->setClipRect( clipRect );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rootNode->resetClip();
|
|
||||||
}
|
|
||||||
|
|
||||||
rootNode->setTranslation( 0.0, -faderProgress * cr.height() );
|
|
||||||
|
|
||||||
auto contentsNode = updateContentsNode( popup, rootNode->contentsNode() );
|
|
||||||
rootNode->setContentsNode( contentsNode );
|
|
||||||
|
|
||||||
rootNode->rearrangeNodes();
|
|
||||||
|
|
||||||
return rootNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSGNode* QskPopupSkinlet::updateContentsNode( const QskPopup*, QSGNode* ) const
|
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
auto gradient = popup->gradientHint( Q::Overlay );
|
||||||
|
|
||||||
|
if ( gradient.isVisible() && factor != 1.0 )
|
||||||
|
{
|
||||||
|
auto stops = gradient.stops();
|
||||||
|
|
||||||
|
for ( auto& stop : stops )
|
||||||
|
stop.setRgb( qskInterpolatedRgb( stop.rgb(), factor ) );
|
||||||
|
|
||||||
|
gradient.setStops( stops );
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateBoxNode( popup, node, rect, gradient, QskPopup::Overlay );
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_QskPopupSkinlet.cpp"
|
#include "moc_QskPopupSkinlet.cpp"
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet
|
||||||
enum NodeRole
|
enum NodeRole
|
||||||
{
|
{
|
||||||
OverlayRole,
|
OverlayRole,
|
||||||
ContentsRole,
|
|
||||||
|
|
||||||
RoleCount
|
RoleCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -35,10 +33,7 @@ class QSK_EXPORT QskPopupSkinlet : public QskSkinlet
|
||||||
QSGNode* updateSubNode( const QskSkinnable*,
|
QSGNode* updateSubNode( const QskSkinnable*,
|
||||||
quint8 nodeRole, QSGNode* ) const override;
|
quint8 nodeRole, QSGNode* ) const override;
|
||||||
|
|
||||||
virtual QSGNode* updateContentsNode( const QskPopup*, QSGNode* ) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSGNode* updateExtraNode( const QskPopup*, QSGNode* ) const;
|
|
||||||
QSGNode* updateOverlayNode( const QskPopup*, QSGNode* ) const;
|
QSGNode* updateOverlayNode( const QskPopup*, QSGNode* ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,21 @@ bool qskIsItemComplete( const QQuickItem* item )
|
||||||
return QQuickItemPrivate::get( item )->componentComplete;
|
return QQuickItemPrivate::get( item )->componentComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool qskIsItemInDestructor( const QQuickItem* item )
|
||||||
|
{
|
||||||
|
auto d = QQuickItemPrivate::get( item );
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 )
|
||||||
|
return d->inDestructor;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
QskQuickItem sets componentComplete to false in its destructor,
|
||||||
|
but for other items we will will return the wrong information
|
||||||
|
*/
|
||||||
|
return !d->componentComplete;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child )
|
bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child )
|
||||||
{
|
{
|
||||||
if ( item == nullptr || child == nullptr )
|
if ( item == nullptr || child == nullptr )
|
||||||
|
|
@ -356,7 +371,7 @@ QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* item )
|
||||||
return QList< QQuickItem* >();
|
return QList< QQuickItem* >();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSGNode* qskItemNode( const QQuickItem* item )
|
const QSGTransformNode* qskItemNode( const QQuickItem* item )
|
||||||
{
|
{
|
||||||
if ( item == nullptr )
|
if ( item == nullptr )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class QskSizePolicy;
|
||||||
|
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
class QSGNode;
|
class QSGNode;
|
||||||
|
class QSGTransformNode;
|
||||||
class QRectF;
|
class QRectF;
|
||||||
template< typename T > class QList;
|
template< typename T > class QList;
|
||||||
|
|
||||||
|
|
@ -24,6 +25,7 @@ template< typename T > class QList;
|
||||||
of QQuickItem.
|
of QQuickItem.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
QSK_EXPORT bool qskIsItemInDestructor( const QQuickItem* );
|
||||||
QSK_EXPORT bool qskIsItemComplete( const QQuickItem* );
|
QSK_EXPORT bool qskIsItemComplete( const QQuickItem* );
|
||||||
QSK_EXPORT bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child );
|
QSK_EXPORT bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child );
|
||||||
QSK_EXPORT bool qskIsTabFence( const QQuickItem* );
|
QSK_EXPORT bool qskIsTabFence( const QQuickItem* );
|
||||||
|
|
@ -66,7 +68,7 @@ QSK_EXPORT QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* );
|
||||||
QSK_EXPORT void qskUpdateInputMethod( const QQuickItem*, Qt::InputMethodQueries );
|
QSK_EXPORT void qskUpdateInputMethod( const QQuickItem*, Qt::InputMethodQueries );
|
||||||
QSK_EXPORT void qskInputMethodSetVisible( const QQuickItem*, bool );
|
QSK_EXPORT void qskInputMethodSetVisible( const QQuickItem*, bool );
|
||||||
|
|
||||||
QSK_EXPORT const QSGNode* qskItemNode( const QQuickItem* );
|
QSK_EXPORT const QSGTransformNode* qskItemNode( const QQuickItem* );
|
||||||
QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* );
|
QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* );
|
||||||
|
|
||||||
QSK_EXPORT void qskItemUpdateRecursive( QQuickItem* );
|
QSK_EXPORT void qskItemUpdateRecursive( QQuickItem* );
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,11 @@ QskQuickItem::~QskQuickItem()
|
||||||
We set componentComplete to false, so that operations
|
We set componentComplete to false, so that operations
|
||||||
that are triggered by detaching the item from its parent
|
that are triggered by detaching the item from its parent
|
||||||
can be aware of the about-to-delete state.
|
can be aware of the about-to-delete state.
|
||||||
|
|
||||||
|
Note, that since Qt >= 6.5 this information is stored
|
||||||
|
in QQuickItemPrivate::inDestructor.
|
||||||
|
|
||||||
|
s.a: qskIsItemInDestructor
|
||||||
*/
|
*/
|
||||||
d_func()->componentComplete = false;
|
d_func()->componentComplete = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,15 +136,15 @@ namespace
|
||||||
setOrientations( Qt::Horizontal | Qt::Vertical );
|
setOrientations( Qt::Horizontal | Qt::Vertical );
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF gestureRect() const override
|
bool isAcceptedPos( const QPointF& pos ) const override
|
||||||
{
|
{
|
||||||
if ( auto scrollBox = qobject_cast< const QskScrollBox* >( watchedItem() ) )
|
if ( auto scrollBox = qobject_cast< const QskScrollBox* >( watchedItem() ) )
|
||||||
{
|
{
|
||||||
if ( qskIsScrollable( scrollBox, orientations() ) )
|
if ( qskIsScrollable( scrollBox, orientations() ) )
|
||||||
return scrollBox->viewContentsRect();
|
return scrollBox->viewContentsRect().contains( pos );
|
||||||
}
|
}
|
||||||
|
|
||||||
return QRectF( 0.0, 0.0, -1.0, -1.0 ); // empty
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@
|
||||||
#include "QskComboBox.h"
|
#include "QskComboBox.h"
|
||||||
#include "QskComboBoxSkinlet.h"
|
#include "QskComboBoxSkinlet.h"
|
||||||
|
|
||||||
|
#include "QskDrawer.h"
|
||||||
|
#include "QskDrawerSkinlet.h"
|
||||||
|
|
||||||
#include "QskFocusIndicator.h"
|
#include "QskFocusIndicator.h"
|
||||||
#include "QskFocusIndicatorSkinlet.h"
|
#include "QskFocusIndicatorSkinlet.h"
|
||||||
|
|
||||||
|
|
@ -160,6 +163,7 @@ QskSkin::QskSkin( QObject* parent )
|
||||||
declareSkinlet< QskBox, QskBoxSkinlet >();
|
declareSkinlet< QskBox, QskBoxSkinlet >();
|
||||||
declareSkinlet< QskCheckBox, QskCheckBoxSkinlet >();
|
declareSkinlet< QskCheckBox, QskCheckBoxSkinlet >();
|
||||||
declareSkinlet< QskComboBox, QskComboBoxSkinlet >();
|
declareSkinlet< QskComboBox, QskComboBoxSkinlet >();
|
||||||
|
declareSkinlet< QskDrawer, QskDrawerSkinlet >();
|
||||||
declareSkinlet< QskFocusIndicator, QskFocusIndicatorSkinlet >();
|
declareSkinlet< QskFocusIndicator, QskFocusIndicatorSkinlet >();
|
||||||
declareSkinlet< QskGraphicLabel, QskGraphicLabelSkinlet >();
|
declareSkinlet< QskGraphicLabel, QskGraphicLabelSkinlet >();
|
||||||
declareSkinlet< QskListView, QskListViewSkinlet >();
|
declareSkinlet< QskListView, QskListViewSkinlet >();
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ namespace
|
||||||
scheme = Qt::ColorScheme::Unknown;
|
scheme = Qt::ColorScheme::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto systemScheme = qGuiApp->styleHints()->colorScheme();
|
const auto systemScheme = QGuiApplication::styleHints()->colorScheme();
|
||||||
|
|
||||||
if( scheme == systemScheme )
|
if( scheme == systemScheme )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -988,6 +988,23 @@ bool QskSkinnable::moveSkinHint( QskAspect aspect, const QVariant& value )
|
||||||
return moveSkinHint( aspect, effectiveSkinHint( aspect ), value );
|
return moveSkinHint( aspect, effectiveSkinHint( aspect ), value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QskHintAnimator* QskSkinnable::runningHintAnimator(
|
||||||
|
QskAspect aspect, int index ) const
|
||||||
|
{
|
||||||
|
const auto& animators = m_data->animators;
|
||||||
|
|
||||||
|
if ( animators.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
aspect = qskAnimatorAspect( aspect );
|
||||||
|
|
||||||
|
auto animator = animators.animator( aspect, index );
|
||||||
|
if ( animator == nullptr && index >= 0 )
|
||||||
|
animator = animators.animator( aspect, -1 );
|
||||||
|
|
||||||
|
return animator;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant QskSkinnable::animatedHint(
|
QVariant QskSkinnable::animatedHint(
|
||||||
QskAspect aspect, QskSkinHintStatus* status ) const
|
QskAspect aspect, QskSkinHintStatus* status ) const
|
||||||
{
|
{
|
||||||
|
|
@ -1259,14 +1276,20 @@ bool QskSkinnable::isTransitionAccepted( QskAspect aspect ) const
|
||||||
{
|
{
|
||||||
Q_UNUSED( aspect )
|
Q_UNUSED( aspect )
|
||||||
|
|
||||||
|
if ( auto control = qskControlCast( owningItem() ) )
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
Usually we only need smooth transitions, when state changes
|
Usually we only need smooth transitions, when state changes
|
||||||
happen while the skinnable is visible. There are few exceptions
|
happen while the skinnable is visible. There are few exceptions
|
||||||
like QskPopup::Closed, that is used to slide/fade in.
|
like QskPopup::Closed, that is used to slide/fade in.
|
||||||
*/
|
*/
|
||||||
if ( auto control = qskControlCast( owningItem() ) )
|
|
||||||
|
if ( control->flags() & QQuickItem::ItemHasContents )
|
||||||
return control->isInitiallyPainted();
|
return control->isInitiallyPainted();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class QQuickItem;
|
||||||
class QskArcMetrics;
|
class QskArcMetrics;
|
||||||
class QskControl;
|
class QskControl;
|
||||||
class QskAnimationHint;
|
class QskAnimationHint;
|
||||||
|
class QskHintAnimator;
|
||||||
class QskColorFilter;
|
class QskColorFilter;
|
||||||
class QskBoxShapeMetrics;
|
class QskBoxShapeMetrics;
|
||||||
class QskBoxBorderMetrics;
|
class QskBoxBorderMetrics;
|
||||||
|
|
@ -262,6 +263,8 @@ class QSK_EXPORT QskSkinnable
|
||||||
bool startHintTransitions( const QVector< QskAspect::Subcontrol >&,
|
bool startHintTransitions( const QVector< QskAspect::Subcontrol >&,
|
||||||
QskAspect::States, QskAspect::States, int index = -1 );
|
QskAspect::States, QskAspect::States, int index = -1 );
|
||||||
|
|
||||||
|
const QskHintAnimator* runningHintAnimator( QskAspect, int index = -1 ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void updateNode( QSGNode* );
|
virtual void updateNode( QSGNode* );
|
||||||
virtual bool isTransitionAccepted( QskAspect ) const;
|
virtual bool isTransitionAccepted( QskAspect ) const;
|
||||||
|
|
|
||||||
|
|
@ -253,4 +253,15 @@ void QskSubWindow::itemChange( QQuickItem::ItemChange change,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskSubWindow::updateResources()
|
||||||
|
{
|
||||||
|
setOpacity( fadingFactor() );
|
||||||
|
Inherited::updateResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
QskAspect QskSubWindow::fadingAspect() const
|
||||||
|
{
|
||||||
|
return QskSubWindow::Panel | QskAspect::Position;
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_QskSubWindow.cpp"
|
#include "moc_QskSubWindow.cpp"
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ class QSK_EXPORT QskSubWindow : public QskPopup
|
||||||
QRectF titleBarRect() const;
|
QRectF titleBarRect() const;
|
||||||
|
|
||||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||||
|
QskAspect fadingAspect() const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void decorationsChanged( Decorations );
|
void decorationsChanged( Decorations );
|
||||||
|
|
@ -95,6 +96,8 @@ class QSK_EXPORT QskSubWindow : public QskPopup
|
||||||
bool event( QEvent* ) override;
|
bool event( QEvent* ) override;
|
||||||
|
|
||||||
void updateLayout() override;
|
void updateLayout() override;
|
||||||
|
void updateResources() override;
|
||||||
|
|
||||||
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
|
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
|
||||||
void itemChange( QQuickItem::ItemChange,
|
void itemChange( QQuickItem::ItemChange,
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,18 @@ QSGNode* QskSubWindowSkinlet::updateSubNode(
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
case OverlayRole:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Overloading QskPopupSkinlet: as the opacity of the subwindow already
|
||||||
|
depends on the fadingFactor we do not want the additional opacity
|
||||||
|
adjustments for the overlay node.
|
||||||
|
Maybe we should have a flag that indicates if the popup does
|
||||||
|
opacity or geometry transitions, when fading TODO ...
|
||||||
|
*/
|
||||||
|
updateBoxNode( subWindow, node, Q::Overlay );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||||
|
|
|
||||||
|
|
@ -424,8 +424,18 @@ void QskWindow::exposeEvent( QExposeEvent* event )
|
||||||
|
|
||||||
void QskWindow::resizeEvent( QResizeEvent* event )
|
void QskWindow::resizeEvent( QResizeEvent* event )
|
||||||
{
|
{
|
||||||
|
auto rootItem = contentItem();
|
||||||
|
|
||||||
|
const auto oldRect = qskItemGeometry( rootItem );
|
||||||
Inherited::resizeEvent( event );
|
Inherited::resizeEvent( event );
|
||||||
|
|
||||||
|
const auto newRect = qskItemGeometry( rootItem );
|
||||||
|
if ( newRect != oldRect )
|
||||||
|
{
|
||||||
|
QskGeometryChangeEvent event( newRect, oldRect );
|
||||||
|
QCoreApplication::sendEvent( rootItem, &event );
|
||||||
|
}
|
||||||
|
|
||||||
if ( isExposed() )
|
if ( isExposed() )
|
||||||
layoutItems();
|
layoutItems();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ static void qskSetupSubWindow(
|
||||||
const QString& title, QskDialog::Actions actions,
|
const QString& title, QskDialog::Actions actions,
|
||||||
QskDialog::Action defaultAction, QskDialogSubWindow* subWindow )
|
QskDialog::Action defaultAction, QskDialogSubWindow* subWindow )
|
||||||
{
|
{
|
||||||
|
subWindow->setPopupFlag( QskPopup::DeleteOnClose );
|
||||||
subWindow->setModal( true );
|
subWindow->setModal( true );
|
||||||
subWindow->setWindowTitle( title );
|
subWindow->setWindowTitle( title );
|
||||||
subWindow->setDialogActions( actions );
|
subWindow->setDialogActions( actions );
|
||||||
|
|
@ -128,14 +129,14 @@ static QskDialog::Action qskMessageSubWindow(
|
||||||
const QString& text, int symbolType, QskDialog::Actions actions,
|
const QString& text, int symbolType, QskDialog::Actions actions,
|
||||||
QskDialog::Action defaultAction )
|
QskDialog::Action defaultAction )
|
||||||
{
|
{
|
||||||
QskMessageSubWindow subWindow( window->contentItem() );
|
auto subWindow = new QskMessageSubWindow( window->contentItem() );
|
||||||
subWindow.setSymbolType( symbolType );
|
subWindow->setSymbolType( symbolType );
|
||||||
subWindow.setText( text );
|
subWindow->setText( text );
|
||||||
|
|
||||||
qskSetupSubWindow( title, actions, defaultAction, &subWindow );
|
qskSetupSubWindow( title, actions, defaultAction, subWindow );
|
||||||
( void ) subWindow.exec();
|
( void ) subWindow->exec();
|
||||||
|
|
||||||
auto clickedAction = subWindow.clickedAction();
|
auto clickedAction = subWindow->clickedAction();
|
||||||
if ( clickedAction == QskDialog::NoAction )
|
if ( clickedAction == QskDialog::NoAction )
|
||||||
{
|
{
|
||||||
// dialog might have been closed by the window menu
|
// dialog might have been closed by the window menu
|
||||||
|
|
@ -172,16 +173,16 @@ static QString qskSelectSubWindow(
|
||||||
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
||||||
const QStringList& entries, int selectedRow )
|
const QStringList& entries, int selectedRow )
|
||||||
{
|
{
|
||||||
QskSelectionSubWindow subWindow( window->contentItem() );
|
auto subWindow = new QskSelectionSubWindow( window->contentItem() );
|
||||||
subWindow.setInfoText( text );
|
subWindow->setInfoText( text );
|
||||||
subWindow.setEntries( entries );
|
subWindow->setEntries( entries );
|
||||||
subWindow.setSelectedRow( selectedRow );
|
subWindow->setSelectedRow( selectedRow );
|
||||||
|
|
||||||
QString selectedEntry;
|
QString selectedEntry;
|
||||||
|
|
||||||
qskSetupSubWindow( title, actions, defaultAction, &subWindow );
|
qskSetupSubWindow( title, actions, defaultAction, subWindow );
|
||||||
if ( subWindow.exec() == QskDialog::Accepted )
|
if ( subWindow->exec() == QskDialog::Accepted )
|
||||||
selectedEntry = subWindow.selectedEntry();
|
selectedEntry = subWindow->selectedEntry();
|
||||||
|
|
||||||
return selectedEntry;
|
return selectedEntry;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -278,16 +278,11 @@ void QskDialogSubWindow::keyPressEvent( QKeyEvent* event )
|
||||||
{
|
{
|
||||||
auto button = m_data->buttonBox->defaultButton();
|
auto button = m_data->buttonBox->defaultButton();
|
||||||
if ( button && button->isEnabled() )
|
if ( button && button->isEnabled() )
|
||||||
button->click();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( qskIsStandardKeyInput( event, QKeySequence::Cancel ) )
|
|
||||||
{
|
{
|
||||||
// using shortcuts instead ???
|
button->click();
|
||||||
|
|
||||||
reject();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Inherited::keyPressEvent( event );
|
Inherited::keyPressEvent( event );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue