Compare commits

..

17 Commits

Author SHA1 Message Date
Uwe Rathmann 9040e006ad Merge branch 'master' into features/modelobjectbinder 2025-02-28 09:31:35 +01:00
Uwe Rathmann d9ef4f51ae Merge branch 'master' into features/modelobjectbinder 2025-02-06 10:28:04 +01:00
Uwe Rathmann 04e3378abb QskTextInput -> QskTextField 2024-12-10 14:29:36 +01:00
Uwe Rathmann 52686242ec Merge branch 'master' into features/modelobjectbinder 2024-12-10 14:10:57 +01:00
Uwe Rathmann c6fc72e07c Merge branch 'master' into features/modelobjectbinder 2024-12-02 10:16:42 +01:00
Uwe Rathmann 69eae90d3a Merge branch 'master' into features/modelobjectbinder 2024-09-17 17:43:06 +02:00
Uwe Rathmann a888d9c5a8 dummy implementation of the destructor in C++ file to avoid compiler
errors because of not knowing PrivateData otherwise
2024-09-11 18:49:17 +02:00
Uwe Rathmann cd8fd0d2b2 Merge branch 'master' into features/modelobjectbinder 2024-09-11 18:13:26 +02:00
Uwe Rathmann 6a547e4698 Qt5 incompatibility fixed 2024-02-26 15:49:06 +01:00
Uwe Rathmann 0a651782ba QskModelObjectBinder API improved, models example polished 2024-02-26 15:27:52 +01:00
Uwe Rathmann 7b4db3afc1 wip 2024-02-26 12:16:56 +01:00
Uwe Rathmann e2486f914d QSql dependency removed ( using a QStandardItemModel instead ) 2024-02-26 11:39:16 +01:00
Uwe Rathmann 60c7442fd0 role check fixed 2024-02-26 11:37:59 +01:00
Uwe Rathmann 8faa6a8cad bugs fixed, QskModelObjectBinder improved 2024-02-26 10:52:52 +01:00
Uwe Rathmann 1a5dc6d358 Qt5 incompatibility fixed 2024-02-25 13:55:40 +01:00
Uwe Rathmann 59afa42c84 QskModelObjectBinder modified and moved to src/controls 2024-02-25 13:28:11 +01:00
Uwe Rathmann 6ea2126638 Squashed commit of the following:
Merge: f614117d f0d49d9e
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date:   Sun Feb 25 09:11:12 2024 +0100

    Merge branch 'master' of https://github.com/ovenpasta/qskinny into models
    ( Author: Aldo Nicolas Bruno <ovenpasta@pizzahack.eu> )
2024-02-25 13:21:59 +01:00
41 changed files with 1008 additions and 537 deletions

View File

@ -202,6 +202,7 @@ jobs:
install-deps: "true" install-deps: "true"
modules: "qtwebengine" modules: "qtwebengine"
cached: ${{ steps.cache-qt-5-15.outputs.cache-hit }} cached: ${{ steps.cache-qt-5-15.outputs.cache-hit }}
setup-python: "false"
tools: "" tools: ""
set-env: "true" set-env: "true"
tools-only: "false" tools-only: "false"
@ -215,6 +216,7 @@ jobs:
install-deps: "true" install-deps: "true"
modules: "qtwebengine qtshadertools" modules: "qtwebengine qtshadertools"
cached: ${{ steps.cache-qt-6-2.outputs.cache-hit }} cached: ${{ steps.cache-qt-6-2.outputs.cache-hit }}
setup-python: "false"
tools: "" tools: ""
set-env: "true" set-env: "true"
tools-only: "false" tools-only: "false"

View File

@ -149,7 +149,7 @@ function(qsk_add_example target)
endfunction() endfunction()
function(qsk_add_shaders target shader_name) function(qsk_add_shaders target)
cmake_parse_arguments( arg "" "" "FILES" ${ARGN} ) cmake_parse_arguments( arg "" "" "FILES" ${ARGN} )
@ -160,7 +160,7 @@ function(qsk_add_shaders target shader_name)
list(APPEND outfiles "${qsbname}.qsb") list(APPEND outfiles "${qsbname}.qsb")
endforeach() endforeach()
qt6_add_shaders( ${target} ${shader_name} BATCHABLE PRECOMPILE QUIET qt6_add_shaders( ${target} "qskshaders" BATCHABLE PRECOMPILE QUIET
PREFIX "/qskinny/shaders" ${ARGV} OUTPUTS ${outfiles} ) PREFIX "/qskinny/shaders" ${ARGV} OUTPUTS ${outfiles} )
# pass on OUTPUT_TARGETS to the caller of this function # pass on OUTPUT_TARGETS to the caller of this function

View File

@ -5,7 +5,9 @@
#include "QskMaterial3ProgressBarSkinlet.h" #include "QskMaterial3ProgressBarSkinlet.h"
#include <QskProgressBar.h> #include <QskProgressBar.h>
#include <QskBoxHints.h> #include <QskBoxShapeMetrics.h>
#include <QskBoxBorderMetrics.h>
#include <QskBoxBorderColors.h>
#include <QskMargins.h> #include <QskMargins.h>
#include <QskClipNode.h> #include <QskClipNode.h>
#include <QskSGNode.h> #include <QskSGNode.h>
@ -63,11 +65,11 @@ QSGNode* QskMaterial3ProgressBarSkinlet::updateStopIndicatorNode(
else else
rect.setBottom( rect.top() + rect.width() ); rect.setBottom( rect.top() + rect.width() );
QskBoxHints hints; const auto color = progressBar->gradientHint( Q::Fill ).endColor();
hints.shape = progressBar->boxShapeHint( Q::Fill ); const auto shape = progressBar->boxShapeHint( Q::Fill );
hints.gradient = progressBar->gradientHint( Q::Fill ).endColor();
return updateBoxNode( progressBar, node, rect, hints ); return updateBoxNode( progressBar, node, rect, shape,
QskBoxBorderMetrics(), QskBoxBorderColors(), color );
} }
QSGNode* QskMaterial3ProgressBarSkinlet::updateGrooveClipNode( QSGNode* QskMaterial3ProgressBarSkinlet::updateGrooveClipNode(

View File

@ -14,8 +14,8 @@ StorageBarSkinlet::StorageBarSkinlet( QskSkin* skin )
setNodeRoles( { Pictures, Music, Videos, Documents, Others, Free } ); setNodeRoles( { Pictures, Music, Videos, Documents, Others, Free } );
} }
QRectF StorageBarSkinlet::subControlRect( const QskSkinnable* skinnable, QRectF StorageBarSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const QskAspect::Subcontrol subControl ) const
{ {
const auto* const bar = static_cast< const S* >( skinnable ); const auto* const bar = static_cast< const S* >( skinnable );
@ -70,29 +70,35 @@ QRectF StorageBarSkinlet::subControlRect( const QskSkinnable* skinnable,
return Inherited::subControlRect( skinnable, contentsRect, subControl ); return Inherited::subControlRect( skinnable, contentsRect, subControl );
} }
namespace
{
inline QSGNode* updateSegmentBoxNode(
const S* const skinnable, const QskAspect::Subcontrol& subcontrol, QSGNode* const node )
{
return QskSkinlet::updateBoxNode( skinnable, node, skinnable->subControlRect( subcontrol ),
skinnable->gradientHint( subcontrol ), subcontrol );
}
}
QSGNode* StorageBarSkinlet::updateSubNode( QSGNode* StorageBarSkinlet::updateSubNode(
const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const const QskSkinnable* const skinnable, const quint8 nodeRole, QSGNode* const node ) const
{ {
const auto* const bar = static_cast< const S* >( skinnable );
switch ( nodeRole ) switch ( nodeRole )
{ {
case Pictures: case Pictures:
return updateBoxNode( skinnable, node, S::Pictures ); return updateSegmentBoxNode( bar, S::Pictures, node );
case Music: case Music:
return updateBoxNode( skinnable, node, S::Music ); return updateSegmentBoxNode( bar, S::Music, node );
case Videos: case Videos:
return updateBoxNode( skinnable, node, S::Videos ); return updateSegmentBoxNode( bar, S::Videos, node );
case Documents: case Documents:
return updateBoxNode( skinnable, node, S::Documents ); return updateSegmentBoxNode( bar, S::Documents, node );
case Others: case Others:
return updateBoxNode( skinnable, node, S::Others ); return updateSegmentBoxNode( bar, S::Others, node );
case Free: case Free:
return updateBoxNode( skinnable, node, S::Free ); return updateSegmentBoxNode( bar, S::Free, node );
default: default:
return Inherited::updateSubNode( skinnable, nodeRole, node ); return Inherited::updateSubNode( skinnable, nodeRole, node );
} }

View File

@ -9,6 +9,7 @@ add_subdirectory(shadows)
add_subdirectory(shapes) add_subdirectory(shapes)
add_subdirectory(charts) add_subdirectory(charts)
add_subdirectory(plots) add_subdirectory(plots)
add_subdirectory(models)
if (BUILD_INPUTCONTEXT) if (BUILD_INPUTCONTEXT)
add_subdirectory(inputpanel) add_subdirectory(inputpanel)

View File

@ -0,0 +1,7 @@
############################################################################
# QSkinny - Copyright (C) The authors
# SPDX-License-Identifier: BSD-3-Clause
############################################################################
qsk_add_example(models MainView.h MainView.cpp main.cpp)
target_link_libraries(models)

View File

@ -0,0 +1,215 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "MainView.h"
#include <QskLinearBox.h>
#include <QskPushButton.h>
#include <QskTextLabel.h>
#include <QskTextField.h>
#include <QskSpinBox.h>
#include <QskSeparator.h>
#include <QskFontRole.h>
#include <QskModelObjectBinder.h>
#include <QStandardItemModel>
namespace
{
class TitleLabel : public QskTextLabel
{
public:
TitleLabel( const QString& text, QQuickItem* parent = nullptr )
: QskTextLabel( text, parent )
{
setFontRole( QskFontRole::Title );
}
};
class SpinBox : public QskSpinBox
{
public:
SpinBox( QQuickItem* parent = nullptr )
: QskSpinBox( -100.0, 100.0, 1.0, parent )
{
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
}
};
class Header : public QskLinearBox
{
Q_OBJECT
public:
Header( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
initSizePolicy( QskSizePolicy::Ignored, QskSizePolicy::Fixed );
setPaddingHint( QskBox::Panel, 5 );
setPanel( true );
auto rowButton = new QskPushButton( "Toggle Row" );
auto submitButton = new QskPushButton( "Submit Changes" );
connect( rowButton, &QskPushButton::clicked,
this, &Header::rowClicked );
connect( submitButton, &QskPushButton::clicked,
this, &Header::submitClicked );
addItem( rowButton );
addItem( submitButton );
addStretch( 1 );
}
Q_SIGNALS:
void rowClicked();
void submitClicked();
};
class Model : public QStandardItemModel
{
public:
Model( QObject* parent = nullptr )
: QStandardItemModel( 2, 2, parent )
{
initValue( 0, 0, 1.0 );
initValue( 0, 1, "HELLO" );
initValue( 1, 0, 2.0 );
initValue( 1, 1, "WORLD" );
}
private:
void initValue( int row, int col, const QVariant& value )
{
setData( index( row, col ), value, Qt::EditRole );
}
};
class DisplayBox : public QskLinearBox
{
public:
DisplayBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
setMargins( 10, 0, 10, 0 );
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed );
addItem( new SpinBox() );
addItem( new QskTextField() );
}
};
class ModelBox : public QskLinearBox
{
public:
ModelBox( QAbstractItemModel* model )
: QskLinearBox( Qt::Horizontal, model->columnCount() )
, m_model( model )
{
setMargins( 10, 0, 10, 0 );
setExtraSpacingAt( Qt::BottomEdge );
for ( int row = 0; row < model->rowCount(); row++ )
{
for ( int col = 0; col < model->columnCount(); col++ )
{
const auto value = model->data(
model->index( row, col ), Qt::EditRole );
if ( value.userType() == QVariant::Double )
{
auto spinBox = new SpinBox( this );
connect( spinBox, &QskSpinBox::valueChanged,
this, &ModelBox::updateModel );
}
else
{
auto textField = new QskTextField( this );
connect( textField, &QskTextField::textChanged,
this, &ModelBox::updateModel );
}
}
}
updateDisplay();
connect( m_model, &Model::dataChanged, this, &ModelBox::updateDisplay );
}
private:
void updateModel()
{
if ( auto item = qobject_cast< const QQuickItem* >( sender() ) )
{
const int index = indexOf( item );
const auto modelIndex = m_model->index(
index / dimension(), index % dimension() );
const auto property = item->metaObject()->userProperty();
m_model->setData( modelIndex, property.read( item ), Qt::EditRole );
}
}
void updateDisplay() const
{
for ( int row = 0; row < m_model->rowCount(); row++ )
{
for ( int col = 0; col < m_model->columnCount(); col++ )
{
const auto index = m_model->index( row, col );
if ( auto item = itemAtIndex( row * dimension() + col ) )
{
const auto property = item->metaObject()->userProperty();
property.write( item, m_model->data( index, Qt::EditRole ) );
}
}
}
}
QPointer< QAbstractItemModel > m_model;
};
}
MainView::MainView( QQuickItem* parent )
: QskMainView( parent )
{
m_binder = new QskModelObjectBinder( new Model( this ), this );
auto header = new Header();
auto displayBox = new DisplayBox();
for ( int i = 0; i < displayBox->elementCount(); i++ )
m_binder->bindObject( displayBox->itemAtIndex( i ), i );
auto box = new QskLinearBox( Qt::Vertical );
box->addItem( new TitleLabel( "Editor:" ) );
box->addItem( displayBox );
box->addItem( new QskSeparator() );
box->addItem( new TitleLabel( "Model:" ) );
box->addItem( new ModelBox( m_binder->model() ) );
setHeader( header );
setBody( box );
connect( header, &Header::rowClicked,
this, &MainView::toogleRow );
connect( header, &Header::submitClicked,
m_binder, &QskModelObjectBinder::submit );
}
void MainView::toogleRow()
{
m_binder->setCurrentRow( m_binder->currentRow() == 0 ? 1 : 0 );
}
#include "MainView.moc"

View File

@ -0,0 +1,21 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#pragma once
#include <QskMainView.h>
class QskModelObjectBinder;
class MainView : public QskMainView
{
public:
MainView( QQuickItem* = nullptr );
private:
void toogleRow();
QskModelObjectBinder* m_binder;
};

View File

@ -0,0 +1,37 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "MainView.h"
#include <SkinnyShortcut.h>
#include <QskObjectCounter.h>
#include <QskFocusIndicator.h>
#include <QskWindow.h>
#include <QGuiApplication>
int main( int argc, char* argv[] )
{
#ifdef ITEM_STATISTICS
QskObjectCounter counter( true );
#endif
QGuiApplication app( argc, argv );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
QskWindow window;
window.resize( 600, 400 );
auto focusIndicator = new QskFocusIndicator();
focusIndicator->setObjectName( "FocusIndicator" );
window.addItem( focusIndicator );
window.addItem( new MainView() );
window.show();
return app.exec();
}

View File

@ -9,7 +9,6 @@
#include <QskSGNode.h> #include <QskSGNode.h>
#include <QskTextOptions.h> #include <QskTextOptions.h>
#include <QskTextColors.h> #include <QskTextColors.h>
#include <QskBoxHints.h>
#include <QskPlotCurve.h> #include <QskPlotCurve.h>
#include <QskPlotCorridor.h> #include <QskPlotCorridor.h>
@ -144,10 +143,8 @@ QSGNode* PlotCursorSkinlet::updateSampleNode( const QskSkinnable* skinnable,
if ( subControl == Q::LabelPanel ) if ( subControl == Q::LabelPanel )
{ {
auto hints = skinnable->boxHints( subControl ); const auto gradient = skinnable->gradientHint( aspect );
hints.gradient = skinnable->gradientHint( aspect ); return updateBoxNode( skinnable, node, rect, gradient, subControl );
return updateBoxNode( skinnable, node, rect, hints );
} }
if ( subControl == Q::LabelText ) if ( subControl == Q::LabelText )

View File

@ -35,6 +35,6 @@ if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
shaders/arcshadow-vulkan.vert shaders/arcshadow-vulkan.vert
shaders/arcshadow-vulkan.frag shaders/arcshadow-vulkan.frag
) )
qsk_add_shaders( ${target} "qskArcShaders" FILES ${SHADERS} OUTPUT_TARGETS shader_target) qsk_add_shaders( ${target} FILES ${SHADERS} OUTPUT_TARGETS shader_target)
endif() endif()

View File

@ -8,7 +8,7 @@
#include <QskSkinlet.h> #include <QskSkinlet.h>
#include <QskArcNode.h> #include <QskArcNode.h>
#include <QskArcHints.h> #include <QskArcMetrics.h>
#include <QskShadowMetrics.h> #include <QskShadowMetrics.h>
#include <QskSGNode.h> #include <QskSGNode.h>
#include <QskRgbValue.h> #include <QskRgbValue.h>
@ -107,7 +107,14 @@ namespace
return nullptr; return nullptr;
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node ); auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
arcNode->setArcData( rect, arc->arcHints( Q::Arc ) );
const auto metrics = arc->arcMetricsHint( Q::Arc );
const auto fillGradient = arc->gradientHint( Q::Arc );
const auto borderColor = arc->color( Q::Arc | QskAspect::Border );
const auto borderWidth = arc->metric( Q::Arc | QskAspect::Border );
arcNode->setArcData( rect, metrics, borderWidth, borderColor, fillGradient );
return arcNode; return arcNode;
} }

View File

@ -21,7 +21,6 @@ Slider::Slider( const QString& text, qreal min, qreal max,
m_slider->setBoundaries( min, max ); m_slider->setBoundaries( min, max );
m_slider->setStepSize( step ); m_slider->setStepSize( step );
m_slider->setSnapping( true ); m_slider->setSnapping( true );
m_slider->setTickPolicy( Qsk::Never ); // too many steps
m_slider->setValue( value ); m_slider->setValue( value );
m_valueLabel = new QskTextLabel( this ); m_valueLabel = new QskTextLabel( this );

View File

@ -5,7 +5,6 @@
list(APPEND HEADERS list(APPEND HEADERS
common/QskArcMetrics.h common/QskArcMetrics.h
common/QskArcHints.h
common/QskAspect.h common/QskAspect.h
common/QskBoxBorderColors.h common/QskBoxBorderColors.h
common/QskBoxBorderMetrics.h common/QskBoxBorderMetrics.h
@ -42,7 +41,6 @@ list(APPEND HEADERS
list(APPEND SOURCES list(APPEND SOURCES
common/QskArcMetrics.cpp common/QskArcMetrics.cpp
common/QskArcHints.cpp
common/QskAspect.cpp common/QskAspect.cpp
common/QskBoxBorderColors.cpp common/QskBoxBorderColors.cpp
common/QskBoxBorderMetrics.cpp common/QskBoxBorderMetrics.cpp
@ -235,6 +233,7 @@ list(APPEND HEADERS
controls/QskListViewSkinlet.h controls/QskListViewSkinlet.h
controls/QskMenu.h controls/QskMenu.h
controls/QskMenuSkinlet.h controls/QskMenuSkinlet.h
controls/QskModelObjectBinder.h
controls/QskObjectTree.h controls/QskObjectTree.h
controls/QskPageIndicator.h controls/QskPageIndicator.h
controls/QskPageIndicatorSkinlet.h controls/QskPageIndicatorSkinlet.h
@ -347,6 +346,7 @@ list(APPEND SOURCES
controls/QskListViewSkinlet.cpp controls/QskListViewSkinlet.cpp
controls/QskMenuSkinlet.cpp controls/QskMenuSkinlet.cpp
controls/QskMenu.cpp controls/QskMenu.cpp
controls/QskModelObjectBinder.cpp
controls/QskObjectTree.cpp controls/QskObjectTree.cpp
controls/QskPageIndicator.cpp controls/QskPageIndicator.cpp
controls/QskPageIndicatorSkinlet.cpp controls/QskPageIndicatorSkinlet.cpp
@ -510,7 +510,7 @@ else()
endif() endif()
if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6) if (QT_VERSION_MAJOR VERSION_GREATER_EQUAL 6)
qsk_add_shaders( ${target} "qskshaders" FILES ${SHADERS} OUTPUT_TARGETS shader_target) qsk_add_shaders( ${target} FILES ${SHADERS} OUTPUT_TARGETS shader_target)
endif() endif()
target_include_directories(${target} PUBLIC target_include_directories(${target} PUBLIC

View File

@ -1,69 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskArcHints.h"
#include "QskRgbValue.h"
static inline qreal qskInterpolated( qreal from, qreal to, qreal ratio )
{
return from + ( to - from ) * ratio;
}
QskArcHints::QskArcHints()
{
}
QskArcHints::QskArcHints( const QskArcMetrics& metrics, qreal borderWidth,
const QColor& borderColor, const QskGradient& gradient )
: metrics( metrics )
, borderWidth( borderWidth )
, borderColor( borderColor )
, gradient( gradient )
{
}
bool QskArcHints::isVisible() const
{
if ( metrics.isNull() )
return false;
if ( borderWidth > 0.0 && borderColor.isValid() && borderColor.alpha() > 0 )
return true;
return gradient.isVisible();
}
QskArcHints QskArcHints::toAbsolute( const QSizeF& size ) const noexcept
{
return QskArcHints( metrics.toAbsolute( size ),
borderWidth, borderColor, gradient );
}
QskArcHints QskArcHints::interpolated(
const QskArcHints& to, qreal value ) const noexcept
{
return QskArcHints(
metrics.interpolated( to.metrics, value ),
qskInterpolated( borderWidth, to.borderWidth, value ),
QskRgb::interpolated( borderColor, to.borderColor, value ),
gradient.interpolated( to.gradient, value )
);
}
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
QDebug operator<<( QDebug debug, const QskArcHints& hints )
{
debug << hints.metrics << hints.borderWidth
<< hints.borderColor << hints.gradient;
return debug;
}
#endif
#include "moc_QskArcHints.cpp"

View File

@ -1,47 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_ARC_HINTS_H
#define QSK_ARC_HINTS_H
#include "QskArcMetrics.h"
#include "QskGradient.h"
#include <qcolor.h>
class QSK_EXPORT QskArcHints
{
Q_GADGET
Q_PROPERTY( QskArcMetrics metrics MEMBER metrics )
Q_PROPERTY( qreal borderWidth MEMBER borderWidth )
Q_PROPERTY( QColor borderColor MEMBER borderColor )
public:
QskArcHints();
QskArcHints( const QskArcMetrics&, qreal borderWidth,
const QColor& borderColor, const QskGradient& );
QskArcHints toAbsolute( const QSizeF& ) const noexcept;
QskArcHints interpolated(
const QskArcHints&, qreal value ) const noexcept;
bool isVisible() const;
QskArcMetrics metrics;
qreal borderWidth = 0.0;
QColor borderColor;
QskGradient gradient;
};
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskArcHints& );
#endif
#endif

View File

@ -81,7 +81,7 @@ QskGradient::QskGradient( const QColor& color1, const QColor& color2 )
QskGradient::QskGradient( QGradient::Preset preset ) QskGradient::QskGradient( QGradient::Preset preset )
: QskGradient() : QskGradient()
{ {
setStops( qskFromQGradientStops( QGradient( preset ).stops() ) ); setStops( qskBuildGradientStops( QGradient( preset ).stops() ) );
} }
QskGradient::QskGradient( const QVector< QskGradientStop >& stops ) QskGradient::QskGradient( const QVector< QskGradientStop >& stops )
@ -165,7 +165,7 @@ QskGradient::QskGradient( const QGradient& qGradient )
} }
} }
setStops( qskFromQGradientStops( qGradient.stops() ) ); setStops( qskBuildGradientStops( qGradient.stops() ) );
} }
QskGradient::QskGradient( const QskGradient& other ) noexcept QskGradient::QskGradient( const QskGradient& other ) noexcept
@ -305,7 +305,7 @@ void QskGradient::setStops( const QColor& color1, const QColor& color2 )
void QskGradient::setStops( QGradient::Preset preset ) void QskGradient::setStops( QGradient::Preset preset )
{ {
const auto stops = qskFromQGradientStops( QGradient( preset ).stops() ); const auto stops = qskBuildGradientStops( QGradient( preset ).stops() );
setStops( stops ); setStops( stops );
} }

View File

@ -23,31 +23,6 @@ static void qskRegisterGradientStop()
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop ) Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop )
static inline qreal qskBoundedStopPos( qreal pos )
{
if ( ( pos < 0.0 ) || qFuzzyIsNull( pos ) )
return 0.0;
if ( ( pos > 1.0 ) || qFuzzyCompare( pos, 1.0 ) )
return 1.0;
return pos;
}
static inline QVector< QskGradientStop >
qskNormalizedStops( const QVector< QskGradientStop >& stops )
{
auto s = stops;
if ( s.first().position() > 0.0 )
s.prepend( QskGradientStop( 0.0, s.first().color() ) );
if ( s.last().position() < 1.0 )
s.append( QskGradientStop( 1.0, s.last().color() ) );
return s;
}
void QskGradientStop::setPosition( qreal position ) noexcept void QskGradientStop::setPosition( qreal position ) noexcept
{ {
m_position = position; m_position = position;
@ -81,19 +56,26 @@ QskHashValue QskGradientStop::hash( QskHashValue seed ) const noexcept
return qHashBits( &m_color, sizeof( m_color ), hash ); return qHashBits( &m_color, sizeof( m_color ), hash );
} }
QskGradientStop QskGradientStop::interpolated( QColor QskGradientStop::interpolated(
const QskGradientStop& to, qreal ratio ) const const QskGradientStop& s1, const QskGradientStop& s2, qreal position ) noexcept
{ {
return QskGradientStop( if ( s1.color() == s2.color() )
m_position + ( to.m_position - m_position ) * ratio, return s1.color();
QskRgb::interpolated( m_color, to.m_color, ratio )
);
}
QVariant QskGradientStop::interpolate( auto min = &s1;
const QskGradientStop& from, const QskGradientStop& to, qreal ratio ) auto max = &s2;
{
return QVariant::fromValue( from.interpolated( to, ratio ) ); if ( min->position() > max->position() )
std::swap( min, max );
if ( position <= min->position() )
return min->color();
if ( position >= max->position() )
return max->color();
const qreal r = ( position - min->position() ) / ( max->position() - min->position() );
return QskRgb::interpolated( min->color(), max->color(), r );
} }
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
@ -113,23 +95,19 @@ QDebug operator<<( QDebug debug, const QskGradientStop& stop )
#endif #endif
#include "moc_QskGradientStop.cpp"
// some helper functions around QskGradientStops // some helper functions around QskGradientStops
static inline QColor qskColorAtPosition( static inline QColor qskInterpolatedColor(
const QskGradientStop& s1, const QskGradientStop& s2, qreal pos ) const QskGradientStops& stops, int index1, int index2, qreal position )
{ {
const auto dp = s2.position() - s1.position(); const auto max = static_cast< int >( stops.count() ) - 1;
if ( qFuzzyIsNull( dp ) )
return s1.color();
return QskRgb::interpolated( index1 = qBound( 0, index1, max );
s1.color(), s2.color(), ( pos - s1.position() ) / dp ); index2 = qBound( 0, index2, max );
}
static inline QskGradientStop qskCreateStopAtPosition( return QskGradientStop::interpolated( stops[ index1 ], stops[ index2 ], position );
const QskGradientStop& s1, const QskGradientStop& s2, qreal pos )
{
return { pos, qskColorAtPosition( s1, s2, pos ) };
} }
bool qskIsVisible( const QskGradientStops& stops ) noexcept bool qskIsVisible( const QskGradientStops& stops ) noexcept
@ -300,126 +278,43 @@ QColor qskInterpolatedColorAt( const QskGradientStops& stops, qreal pos ) noexce
if ( stops.isEmpty() ) if ( stops.isEmpty() )
return QColor(); return QColor();
pos = qBound( 0.0, pos, 1.0 );
if ( pos <= stops.first().position() ) if ( pos <= stops.first().position() )
return stops.first().color(); return stops.first().color();
for ( int i = 1; i < stops.count(); i++ ) for ( int i = 1; i < stops.count(); i++ )
{ {
if ( pos <= stops[ i ].position() ) if ( pos <= stops[i].position() )
return qskColorAtPosition( stops[ i - 1 ], stops[ i ], pos ); return qskInterpolatedColor( stops, i - 1, i, pos );
} }
return stops.last().color(); return stops.last().color();
} }
QskGradientStops qskReplacedGradientStops( const QskGradientStops& gradientStops,
const QskGradientStop& stop1, const QskGradientStop& stop2 )
{
if ( stop1.position() >= stop2.position() )
return gradientStops;
const auto s1 = QskGradientStop( qskBoundedStopPos( stop1.position() ), stop1.color() );
const auto s2 = QskGradientStop( qskBoundedStopPos( stop2.position() ), stop2.color() );
QskGradientStops stops;
if ( s1.position() == 0.0 && s2.position() == 1.0 )
{
stops = { s1, s2 };
}
else if ( qskIsMonochrome( gradientStops ) )
{
stops.reserve( 4 );
const auto c = gradientStops.isEmpty()
? QColor::fromRgba( 0 ) : gradientStops.first().color();
if ( s1.position() > 0.0 )
stops += { s1.position(), c };
stops += s1;
stops += s2;
if ( s2.position() < 1.0 )
stops += { s2.position(), c };
}
else
{
// not the most efficient implementation - maybe later TODO ...
const auto stops0 = qskNormalizedStops( gradientStops );
int i = 0;
if ( s1.position() > 0.0 )
{
while ( s1.position() > stops0[i].position() )
stops += stops0[i++];
if ( s1.position() == stops0[i].position() )
stops += stops0[i++];
else
stops += qskCreateStopAtPosition( stops0[i - 1], stops0[i], s1.position() );
}
stops += s1;
while ( s2.position() > stops0[i].position() )
i++;
stops += s2;
if ( s2.position() < 1.0 )
{
while ( stops0[i + 1].position() == s2.position() )
i++;
if ( s2.position() != stops0[i].position() )
stops += qskCreateStopAtPosition( stops0[i - 1], stops0[i], s2.position() );
while( i < stops0.count() )
stops += stops0[i++];
}
}
return stops;
}
QskGradientStops qskClippedGradientStops(
const QskGradientStops& stops, qreal from, qreal to )
{
return qskReplacedGradientStops( stops, { from, 0 }, { to, 0 } );
}
QskGradientStops qskExtractedGradientStops( QskGradientStops qskExtractedGradientStops(
const QskGradientStops& stops, qreal from, qreal to ) const QskGradientStops& gradientStops, qreal from, qreal to )
{ {
if ( ( from > to ) || ( to > 1.0 ) || ( from < 0.0 ) || stops.isEmpty() ) if ( ( from > to ) || ( from > 1.0 ) || gradientStops.isEmpty() )
return QskGradientStops(); return QskGradientStops();
from = qskBoundedStopPos( from ); if ( ( from <= 0.0 ) && ( to >= 1.0 ) )
to = qskBoundedStopPos( to ); return gradientStops;
if ( ( from == 0.0 ) && ( to == 1.0 ) ) from = qMax( from, 0.0 );
return stops; to = qMin( to, 1.0 );
if ( from == to ) QVector< QskGradientStop > stops1 = gradientStops;
{
const auto color = qskInterpolatedColorAt( stops, from );
QVector< QskGradientStop > s; #if 1
s.reserve( 2 ); // not the most efficient implementation - maybe later TODO ...
s += QskGradientStop( 0.0, color );
s += QskGradientStop( 1.0, color );
return s; if ( stops1.first().position() > 0.0 )
} stops1.prepend( QskGradientStop( 0.0, stops1.first().color() ) );
/* if ( stops1.last().position() < 1.0 )
For situations where we have no stops at 0.0 and 1.0 we insert them stops1.append( QskGradientStop( 1.0, stops1.last().color() ) );
manually. Not the most efficient implementation, but we avoid having #endif
to deal with these situations for the moment. TODO ...
*/
const auto stops1 = qskNormalizedStops( stops );
QVector< QskGradientStop > stops2; QVector< QskGradientStop > stops2;
stops2.reserve( stops1.count() ); stops2.reserve( stops1.count() );
@ -436,26 +331,26 @@ QskGradientStops qskExtractedGradientStops(
{ {
int i = 0; int i = 0;
if ( from == 0.0 ) for ( ; i < stops1.count(); i++ )
{ {
stops2 += stops1[i++]; if ( stops1[i].position() > from )
} break;
else
{
while( stops1[++i].position() <= from ); // skip leading stops
stops2 += QskGradientStop( 0.0,
qskColorAtPosition( stops1[i - 1], stops1[ i ], from ) );
} }
while ( stops1[i].position() < to ) stops2 += QskGradientStop( 0.0,
qskInterpolatedColor( stops1, i - 1, i, from ) );
for ( ; i < stops1.count(); i++ )
{ {
if ( stops1[i].position() >= to )
break;
const auto pos = ( stops1[i].position() - from ) / ( to - from ); const auto pos = ( stops1[i].position() - from ) / ( to - from );
stops2 += QskGradientStop( pos, stops1[i++].color() ); stops2 += QskGradientStop( pos, stops1[i].color() );
} }
stops2 += QskGradientStop( 1.0, stops2 += QskGradientStop( 1.0,
qskColorAtPosition( stops1[i - 1], stops1[ i ], to ) ); qskInterpolatedColor( stops1, i, i + 1, to ) );
} }
return stops2; return stops2;
@ -472,7 +367,7 @@ QskGradientStops qskRevertedGradientStops( const QskGradientStops& stops )
return s; return s;
} }
QVector< QskGradientStop > qskFromQGradientStops( const QGradientStops& qtStops ) QVector< QskGradientStop > qskBuildGradientStops( const QGradientStops& qtStops )
{ {
QVector< QskGradientStop > stops; QVector< QskGradientStop > stops;
stops.reserve( qtStops.count() ); stops.reserve( qtStops.count() );
@ -568,5 +463,3 @@ QGradientStops qskToQGradientStops( const QskGradientStops& stops )
return qStops; return qStops;
} }
#include "moc_QskGradientStop.cpp"

View File

@ -45,10 +45,8 @@ class QSK_EXPORT QskGradientStop
void setRgb( QRgb ) noexcept; void setRgb( QRgb ) noexcept;
QRgb rgb() const noexcept; QRgb rgb() const noexcept;
QskGradientStop interpolated( const QskGradientStop&, qreal ) const; static QColor interpolated(
const QskGradientStop&, const QskGradientStop&, qreal position ) noexcept;
static QVariant interpolate( const QskGradientStop&,
const QskGradientStop&, qreal );
QskHashValue hash( QskHashValue seed ) const noexcept; QskHashValue hash( QskHashValue seed ) const noexcept;
@ -131,48 +129,27 @@ QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
const QskGradientStops&, bool, const QskGradientStops&, bool, const QskGradientStops&, bool, const QskGradientStops&, bool,
qreal ratio ); qreal ratio );
// interpolating colors in direction of a color.
QSK_EXPORT QskGradientStops qskInterpolatedGradientStops( QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
const QskGradientStops&, const QColor&, qreal ratio ); const QskGradientStops&, const QColor&, qreal ratio );
// interpolating colors starting from a color.
QSK_EXPORT QskGradientStops qskInterpolatedGradientStops( QSK_EXPORT QskGradientStops qskInterpolatedGradientStops(
const QColor&, const QskGradientStops&, qreal ratio ); const QColor&, const QskGradientStops&, qreal ratio );
// interpolating the opacity of the colors
QSK_EXPORT QskGradientStops qskTransparentGradientStops( QSK_EXPORT QskGradientStops qskTransparentGradientStops(
const QskGradientStops&, qreal ratio ); const QskGradientStops&, qreal ratio );
// extracting the colors of [from, to ] and stretching them to [0.0, 1.0]
QSK_EXPORT QskGradientStops qskExtractedGradientStops( QSK_EXPORT QskGradientStops qskExtractedGradientStops(
const QskGradientStops&, qreal from, qreal to ); const QskGradientStops&, qreal from, qreal to );
// reverting the color stops
QSK_EXPORT QskGradientStops qskRevertedGradientStops( const QskGradientStops& );
QSK_EXPORT QskGradientStops qskReplacedGradientStops(
const QskGradientStops&, const QskGradientStop&, const QskGradientStop& );
QSK_EXPORT QskGradientStops qskClippedGradientStops(
const QskGradientStops&, qreal from, qreal to );
/*
creating equidistant color stops from a list of colors.
when discrete is true the result will contain 2 stops at each position
one with the previous and one with the following color so that the
interval [pos1-pos2] will be monochrome.
*/
QSK_EXPORT QskGradientStops qskBuildGradientStops( QSK_EXPORT QskGradientStops qskBuildGradientStops(
const QVector< QRgb >&, bool discrete = false ); const QVector< QRgb >&, bool discrete = false );
QSK_EXPORT QskGradientStops qskBuildGradientStops( QSK_EXPORT QskGradientStops qskBuildGradientStops(
const QVector< QColor >&, bool discrete = false ); const QVector< QColor >&, bool discrete = false );
/* QSK_EXPORT QskGradientStops qskRevertedGradientStops( const QskGradientStops& );
convert color stops from/to a vector of QGradientStop, that can be
used for QGradients. QSK_EXPORT QskGradientStops qskBuildGradientStops( const QVector< QGradientStop >& );
*/
QSK_EXPORT QskGradientStops qskFromQGradientStops( const QVector< QGradientStop >& );
QSK_EXPORT QVector< QGradientStop > qskToQGradientStops( const QVector< QskGradientStop >& ); QSK_EXPORT QVector< QGradientStop > qskToQGradientStops( const QVector< QskGradientStop >& );
#endif #endif

View File

@ -41,7 +41,7 @@ class QSK_EXPORT QskTextColors
void setLinkColor( QRgb ); void setLinkColor( QRgb );
void setLinkColor( Qt::GlobalColor ); void setLinkColor( Qt::GlobalColor );
QskTextColors interpolated( const QskTextColors&, qreal ratio ) const; QskTextColors interpolated( const QskTextColors&, qreal value ) const;
static QVariant interpolate( const QskTextColors&, static QVariant interpolate( const QskTextColors&,
const QskTextColors&, qreal ratio ); const QskTextColors&, qreal ratio );

View File

@ -9,7 +9,6 @@
#include "QskGraphic.h" #include "QskGraphic.h"
#include "QskColorFilter.h" #include "QskColorFilter.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskBoxHints.h"
#include "QskFunctions.h" #include "QskFunctions.h"
#include "QskMargins.h" #include "QskMargins.h"
#include "QskFunctions.h" #include "QskFunctions.h"
@ -573,13 +572,11 @@ QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable,
if ( subControl == Q::Separator ) if ( subControl == Q::Separator )
{ {
auto hints = skinnable->boxHints( subControl ); auto gradient = menu->gradientHint( subControl );
auto& gradient = hints.gradient;
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() ) if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
gradient.setLinearDirection( Qt::Vertical ); gradient.setLinearDirection( Qt::Vertical );
return updateBoxNode( menu, node, rect, hints ); return updateBoxNode( menu, node, rect, gradient, subControl );
} }
return nullptr; return nullptr;

View File

@ -0,0 +1,274 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskModelObjectBinder.h"
#include <qmetaobject.h>
#include <qabstractitemmodel.h>
#include <qpointer.h>
static inline QMetaProperty qskMetaProperty(
const QMetaObject* metaObject, const QByteArray& name )
{
if ( name.isEmpty() )
return metaObject->userProperty();
const auto idx = metaObject->indexOfProperty( name );
return ( idx >= 0 ) ? metaObject->property( idx ) : QMetaProperty();
}
static void qskEnableConnections( QObject* object,
QskModelObjectBinder* binder, bool on )
{
if ( on )
{
QObject::connect( object, &QObject::destroyed,
binder, &QskModelObjectBinder::unbindObject );
}
else
{
QObject::disconnect( object, &QObject::destroyed,
binder, &QskModelObjectBinder::unbindObject );
}
}
namespace
{
struct Binding
{
Binding( int column, const QMetaProperty& property )
: property( property )
, column( column )
{
}
QMetaProperty property;
int column;
};
}
class QskModelObjectBinder::PrivateData
{
public:
void updateProperties()
{
if ( model && currentRowIndex.isValid() )
{
for ( auto it = bindings.constBegin(); it != bindings.constEnd(); ++it )
updateObjectProperty( it.key(), it.value() );
}
}
void updateProperties( const QModelIndex& topLeft,
const QModelIndex& bottomRight, const QVector< int >& roles )
{
if ( !( model && currentRowIndex.isValid() ) )
return;
if ( !( roles.isEmpty() || roles.contains( Qt::EditRole ) ) )
return;
const int row = currentRowIndex.row();
if ( topLeft.row() <= row && row <= bottomRight.row() )
{
for ( auto it = bindings.constBegin(); it != bindings.constEnd(); ++it )
{
const int col = it.value().column;
if( topLeft.column() <= col && col <= bottomRight.column() )
updateObjectProperty( it.key(), it.value() );
}
}
}
void updateObjectProperty( QObject* object, const Binding& binding )
{
const auto index = model->index( currentRowIndex.row(), binding.column );
binding.property.write( object, index.data( Qt::EditRole ) );
}
public:
QMap< QObject*, Binding > bindings;
QPointer< QAbstractItemModel > model;
QPersistentModelIndex currentRowIndex;
};
QskModelObjectBinder::QskModelObjectBinder( QObject* parent )
: QObject( parent )
, m_data( new PrivateData() )
{
}
QskModelObjectBinder::QskModelObjectBinder( QAbstractItemModel* model, QObject* parent )
: QskModelObjectBinder( parent )
{
setModel( model );
}
QskModelObjectBinder::~QskModelObjectBinder()
{
}
void QskModelObjectBinder::bindObject(
QObject* object, int column, const QByteArray& propertyName )
{
if( object == nullptr )
return;
// does not work with dynamic properties ...
const auto metaProperty = qskMetaProperty( object->metaObject(), propertyName );
Q_ASSERT( metaProperty.isValid() );
if ( metaProperty.isValid() )
{
const Binding binding = { column, metaProperty };
m_data->bindings.insert( object, binding );
qskEnableConnections( object, this, true );
if ( m_data->model && m_data->currentRowIndex.isValid() )
m_data->updateObjectProperty( object, binding );
}
}
void QskModelObjectBinder::unbindObject( QObject* object )
{
auto& bindings = m_data->bindings;
auto it = bindings.find( object );
if ( it != bindings.end() )
{
qskEnableConnections( object, this, false );
bindings.erase( it );
}
}
void QskModelObjectBinder::clearBindings()
{
auto& bindings = m_data->bindings;
for ( auto it = bindings.constBegin(); it != bindings.constEnd(); ++it )
qskEnableConnections( it.key(), this, false );
bindings.clear();
}
QObjectList QskModelObjectBinder::boundObjects() const
{
auto& bindings = m_data->bindings;
QObjectList objects;
objects.reserve( bindings.count() );
for ( auto it = bindings.constBegin(); it != bindings.constEnd(); ++it )
objects += it.key();
return objects;
}
QMetaProperty QskModelObjectBinder::boundProperty( const QObject* object ) const
{
auto it = m_data->bindings.constFind( const_cast< QObject* >( object ) );
if ( it != m_data->bindings.constEnd() )
return it.value().property;
return QMetaProperty();
}
void QskModelObjectBinder::setModel( QAbstractItemModel* model )
{
if ( model == m_data->model )
return;
if ( m_data->model )
{
disconnect( m_data->model, &QAbstractItemModel::dataChanged, this, nullptr );
m_data->model = nullptr;
m_data->currentRowIndex = QModelIndex();
clearBindings();
}
m_data->model = model;
if( model )
{
auto updateProperties = [this](
const QModelIndex& topLeft, const QModelIndex& bottomRight,
const QVector< int >& roles )
{
m_data->updateProperties( topLeft, bottomRight, roles );
};
connect( m_data->model, &QAbstractItemModel::dataChanged,
this, updateProperties );
connect( m_data->model, &QObject::destroyed,
this, &QskModelObjectBinder::clearBindings );
setCurrentRow( 0 );
}
}
const QAbstractItemModel* QskModelObjectBinder::model() const
{
return m_data->model;
}
QAbstractItemModel* QskModelObjectBinder::model()
{
return m_data->model;
}
void QskModelObjectBinder::setCurrentRow( int row )
{
auto model = m_data->model.data();
auto& bindings = m_data->bindings;
Q_ASSERT( model != nullptr );
if ( model && row >= 0 && row < model->rowCount() )
{
m_data->currentRowIndex = model->index( row, 0 );
for ( auto it = bindings.constBegin(); it != bindings.constEnd(); ++it )
m_data->updateObjectProperty( it.key(), it.value() );
Q_EMIT currentRowChanged( row );
}
}
int QskModelObjectBinder::currentRow() const
{
return m_data->currentRowIndex.row();
}
void QskModelObjectBinder::submit()
{
if ( auto model = m_data->model )
{
const auto& bindings = m_data->bindings;
for ( auto it = bindings.begin(); it != bindings.end(); ++it )
{
const auto value = it.value().property.read( it.key() );
const auto row = m_data->currentRowIndex.row();
const auto index = model->index( row, it.value().column );
model->setData( index, value );
}
}
}
void QskModelObjectBinder::revert()
{
m_data->updateProperties();
}
#include "moc_QskModelObjectBinder.cpp"

View File

@ -0,0 +1,61 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_MODEL_OBJECT_BINDER_H
#define QSK_MODEL_OBJECT_BINDER_H
#include "QskGlobal.h"
#include <qobject.h>
#include <qbytearray.h>
#include <memory>
class QAbstractItemModel;
class QMetaProperty;
class QSK_EXPORT QskModelObjectBinder : public QObject
{
Q_OBJECT
Q_PROPERTY( int currentRow READ currentRow
WRITE setCurrentRow NOTIFY currentRowChanged )
public:
QskModelObjectBinder( QObject* parent = nullptr );
QskModelObjectBinder( QAbstractItemModel*, QObject* parent = nullptr );
~QskModelObjectBinder() override;
void setModel( QAbstractItemModel* );
const QAbstractItemModel* model() const;
QAbstractItemModel* model();
void setCurrentRow( int row );
int currentRow() const;
void bindObject( QObject*, int column,
const QByteArray& propertyName = QByteArray() );
void unbindObject( QObject* );
QMetaProperty boundProperty( const QObject* ) const;
QObjectList boundObjects() const;
Q_SIGNALS:
void currentRowChanged( int );
public Q_SLOTS:
void submit();
void revert();
void clearBindings();
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -6,7 +6,6 @@
#include "QskPopupSkinlet.h" #include "QskPopupSkinlet.h"
#include "QskPopup.h" #include "QskPopup.h"
#include "QskRgbValue.h" #include "QskRgbValue.h"
#include "QskBoxHints.h"
static inline QRgb qskInterpolatedRgb( QRgb rgb, qreal factor ) static inline QRgb qskInterpolatedRgb( QRgb rgb, qreal factor )
{ {
@ -59,9 +58,7 @@ QSGNode* QskPopupSkinlet::updateOverlayNode(
if ( rect.isEmpty() ) if ( rect.isEmpty() )
return nullptr; return nullptr;
auto hints = popup->boxHints( Q::Overlay ); auto gradient = popup->gradientHint( Q::Overlay );
auto& gradient = hints.gradient;
if ( gradient.isVisible() && factor != 1.0 ) if ( gradient.isVisible() && factor != 1.0 )
{ {
@ -73,7 +70,7 @@ QSGNode* QskPopupSkinlet::updateOverlayNode(
gradient.setStops( stops ); gradient.setStops( stops );
} }
return updateBoxNode( popup, node, rect, hints ); return updateBoxNode( popup, node, rect, gradient, QskPopup::Overlay );
} }
#include "moc_QskPopupSkinlet.cpp" #include "moc_QskPopupSkinlet.cpp"

View File

@ -6,7 +6,7 @@
#include "QskProgressBarSkinlet.h" #include "QskProgressBarSkinlet.h"
#include "QskProgressBar.h" #include "QskProgressBar.h"
#include "QskIntervalF.h" #include "QskIntervalF.h"
#include "QskBoxHints.h" #include "QskBoxBorderMetrics.h"
#include <qeasingcurve.h> #include <qeasingcurve.h>
#include <cmath> #include <cmath>
@ -50,6 +50,41 @@ static QskIntervalF qskFillInterval( const QskProgressIndicator* indicator )
return QskIntervalF( pos1, pos2 ); return QskIntervalF( pos1, pos2 );
} }
static QskGradient qskFillGradient( const QskProgressBar* progressBar )
{
auto gradient = progressBar->gradientHint( Q::Fill );
if ( gradient.isVisible() && !gradient.isMonochrome()
&& ( gradient.type() == QskGradient::Stops ) )
{
/*
When having stops only we use a linear gradient,
where the colors are increasing in direction of the
progress value. We interprete the gradient as a
definition for the 100% situation and have to adjust
the stops for smaller bars.
For this situation it would be more convenient to
adjust the start/stop positions, but the box renderer is
not supporting this yet. TODO ...
*/
const auto intv = qskFillInterval( progressBar );
const auto stops = qskExtractedGradientStops(
gradient.stops(), intv.lowerBound(), intv.upperBound() );
gradient.setStops( stops );
gradient.setLinearDirection( progressBar->orientation() );
if ( progressBar->orientation() == Qt::Vertical || progressBar->layoutMirroring() )
gradient.reverse();
}
return gradient;
}
QskProgressBarSkinlet::QskProgressBarSkinlet( QskSkin* skin ) QskProgressBarSkinlet::QskProgressBarSkinlet( QskSkin* skin )
: Inherited( skin ) : Inherited( skin )
{ {
@ -87,40 +122,9 @@ QSGNode* QskProgressBarSkinlet::updateFillNode(
if ( rect.isEmpty() ) if ( rect.isEmpty() )
return nullptr; return nullptr;
auto hints = indicator->boxHints( Q::Fill ); const auto progressBar = static_cast< const Q* >( indicator );
return updateBoxNode( indicator, node, rect,
auto& gradient = hints.gradient; qskFillGradient( progressBar ), Q::Fill );
if ( gradient.isVisible() && !gradient.isMonochrome()
&& ( gradient.type() == QskGradient::Stops ) )
{
/*
When having stops only we use a linear gradient,
where the colors are increasing in direction of the
progress value. We interprete the gradient as a
definition for the 100% situation and have to adjust
the stops for smaller bars.
For this situation it would be more convenient to
adjust the start/stop positions, but the box renderer is
not supporting this yet. TODO ...
*/
const auto intv = qskFillInterval( indicator );
const auto stops = qskExtractedGradientStops(
gradient.stops(), intv.lowerBound(), intv.upperBound() );
gradient.setStops( stops );
const auto orientation = static_cast< const Q* >( indicator )->orientation();
gradient.setLinearDirection( orientation );
if ( orientation == Qt::Vertical || indicator->layoutMirroring() )
gradient.reverse();
}
return updateBoxNode( indicator, node, rect, hints );
} }
QRectF QskProgressBarSkinlet::grooveRect( QRectF QskProgressBarSkinlet::grooveRect(

View File

@ -4,7 +4,7 @@
*****************************************************************************/ *****************************************************************************/
#include "QskProgressRingSkinlet.h" #include "QskProgressRingSkinlet.h"
#include "QskArcHints.h" #include "QskArcMetrics.h"
#include "QskProgressRing.h" #include "QskProgressRing.h"
#include "QskIntervalF.h" #include "QskIntervalF.h"
@ -85,12 +85,8 @@ QSGNode* QskProgressRingSkinlet::updateGrooveNode(
endAngle = fillAngles.first - 360.0 + spacing; endAngle = fillAngles.first - 360.0 + spacing;
} }
auto hints = indicator->arcHints( Q::Groove ); return updateArcNode( ring, node,
hints.metrics.setStartAngle( startAngle ); startAngle, endAngle - startAngle, Q::Groove );
hints.metrics.setSpanAngle( endAngle - startAngle );
const auto rect = indicator->subControlRect( Q::Groove );
return updateArcNode( ring, node, rect, hints );
} }
} }
@ -108,14 +104,16 @@ QSGNode* QskProgressRingSkinlet::updateFillNode(
if ( rect.isEmpty() ) if ( rect.isEmpty() )
return nullptr; return nullptr;
auto hints = ring->arcHints( subControl ); const auto metrics = ring->arcMetricsHint( subControl );
if ( !hints.isVisible() ) if ( metrics.isNull() )
return nullptr;
auto gradient = ring->gradientHint( subControl );
if ( !gradient.isVisible() )
return nullptr; return nullptr;
const auto intv = qskFillInterval( ring ); const auto intv = qskFillInterval( ring );
auto& gradient = hints.gradient;
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() ) if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
{ {
const auto stops = qskExtractedGradientStops( gradient.stops(), const auto stops = qskExtractedGradientStops( gradient.stops(),
@ -123,15 +121,14 @@ QSGNode* QskProgressRingSkinlet::updateFillNode(
gradient.setStops( stops ); gradient.setStops( stops );
if ( hints.metrics.spanAngle() < 0.0 ) if ( metrics.spanAngle() < 0.0 )
gradient.reverse(); gradient.reverse();
} }
const auto angles = qskFillAngles( hints.metrics, intv ); const auto angles = qskFillAngles( metrics, intv );
hints.metrics.setStartAngle( angles.first );
hints.metrics.setSpanAngle( angles.second - angles.first );
return updateArcNode( ring, node, rect, hints ); return updateArcNode( ring, node, rect, gradient,
angles.first, angles.second - angles.first, subControl );
} }
QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable, QSizeF QskProgressRingSkinlet::sizeHint( const QskSkinnable* skinnable,

View File

@ -6,7 +6,6 @@
#include "QskSeparatorSkinlet.h" #include "QskSeparatorSkinlet.h"
#include "QskSeparator.h" #include "QskSeparator.h"
#include "QskBoxHints.h"
#include "QskGradientDirection.h" #include "QskGradientDirection.h"
#include "QskAspect.h" #include "QskAspect.h"
@ -43,12 +42,8 @@ QSGNode* QskSeparatorSkinlet::updateSubNode(
using Q = QskSeparator; using Q = QskSeparator;
const auto rect = separator->subControlRect( Q::Panel ); const auto rect = separator->subControlRect( Q::Panel );
if ( rect.isEmpty() )
return nullptr;
auto hints = separator->boxHints( Q::Panel ); auto gradient = separator->gradientHint( Q::Panel );
auto& gradient = hints.gradient;
if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() ) if ( ( gradient.type() == QskGradient::Stops ) && !gradient.isMonochrome() )
{ {
// gradient in opposite orientation // gradient in opposite orientation
@ -58,7 +53,7 @@ QSGNode* QskSeparatorSkinlet::updateSubNode(
gradient.setLinearDirection( orientation ); gradient.setLinearDirection( orientation );
} }
return updateBoxNode( separator, node, rect, hints ); return updateBoxNode( separator, node, rect, gradient, Q::Panel );
} }
} }

View File

@ -7,7 +7,9 @@
#include "QskArcNode.h" #include "QskArcNode.h"
#include "QskAspect.h" #include "QskAspect.h"
#include "QskArcHints.h" #include "QskArcMetrics.h"
#include "QskBoxBorderColors.h"
#include "QskBoxBorderMetrics.h"
#include "QskBoxNode.h" #include "QskBoxNode.h"
#include "QskBoxRectangleNode.h" #include "QskBoxRectangleNode.h"
#include "QskBoxShapeMetrics.h" #include "QskBoxShapeMetrics.h"
@ -154,6 +156,18 @@ static inline bool qskIsBoxVisible( const QskBoxBorderMetrics& borderMetrics,
return !borderMetrics.isNull() && borderColors.isVisible(); return !borderMetrics.isNull() && borderColors.isVisible();
} }
static inline bool qskIsArcVisible( const QskArcMetrics& arcMetrics,
qreal borderWidth, const QColor borderColor, const QskGradient& gradient )
{
if ( arcMetrics.isNull() )
return false;
if ( borderWidth > 0.0 && borderColor.isValid() && borderColor.alpha() > 0 )
return true;
return gradient.isVisible();
}
static inline bool qskIsLineVisible( const QColor& lineColor, qreal lineWidth ) static inline bool qskIsLineVisible( const QColor& lineColor, qreal lineWidth )
{ {
return ( lineWidth > 0.0 ) && lineColor.isValid() && ( lineColor.alpha() > 0 ); return ( lineWidth > 0.0 ) && lineColor.isValid() && ( lineColor.alpha() > 0 );
@ -188,18 +202,22 @@ static inline QQuickWindow* qskWindowOfSkinnable( const QskSkinnable* skinnable
return nullptr; return nullptr;
} }
static inline QSGNode* qskUpdateBoxNode( const QskSkinnable* skinnable, static inline QSGNode* qskUpdateBoxNode(
QSGNode* node, const QRectF& rect, const QskBoxHints& hints ) const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{ {
if ( !rect.isEmpty() ) if ( !rect.isEmpty() )
{ {
if ( qskIsBoxVisible( hints.borderMetrics, hints.borderColors, hints.gradient ) if ( qskIsBoxVisible( borderMetrics, borderColors, gradient )
|| qskIsShadowVisible( hints.shadowMetrics, hints.shadowColor ) ) || qskIsShadowVisible( shadowMetrics, shadowColor ) )
{ {
if ( auto window = qskWindowOfSkinnable( skinnable ) ) if ( auto window = qskWindowOfSkinnable( skinnable ) )
{ {
auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node ); auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node );
boxNode->updateNode( window, rect, hints ); boxNode->updateNode( window, rect, shape, borderMetrics,
borderColors, gradient, shadowMetrics, shadowColor );
return boxNode; return boxNode;
} }
@ -209,20 +227,21 @@ static inline QSGNode* qskUpdateBoxNode( const QskSkinnable* skinnable,
return nullptr; return nullptr;
} }
static inline QSGNode* qskUpdateArcNode( const QskSkinnable* skinnable, static inline QSGNode* qskUpdateArcNode(
QSGNode* node, const QRectF& rect, const QskArcHints& hints ) const QskSkinnable*, QSGNode* node, const QRectF& rect,
qreal borderWidth, const QColor borderColor,
const QskGradient& gradient, const QskArcMetrics& metrics )
{ {
Q_UNUSED( skinnable ); if ( rect.isEmpty() )
return nullptr;
if ( !rect.isEmpty() && hints.isVisible() ) if ( !qskIsArcVisible( metrics, borderWidth, borderColor, gradient ) )
{ return nullptr;
auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
arcNode->setArcData( rect, hints );
return arcNode; auto arcNode = QskSGNode::ensureNode< QskArcNode >( node );
} arcNode->setArcData( rect, metrics, borderWidth, borderColor, gradient );
return nullptr; return arcNode;
} }
static inline QSGNode* qskUpdateLineNode( static inline QSGNode* qskUpdateLineNode(
@ -415,30 +434,54 @@ void QskSkinlet::replaceChildNode( quint8 role,
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, QskAspect::Subcontrol subControl ) const QSGNode* node, QskAspect::Subcontrol subControl ) const
{ {
auto r = qskSubControlRect( this, skinnable, subControl ); const auto rect = qskSubControlRect( this, skinnable, subControl );
if ( r.isEmpty() ) return updateBoxNode( skinnable, node, rect, subControl );
return nullptr;
r = r.marginsRemoved( skinnable->marginHint( subControl ) );
return qskUpdateBoxNode( skinnable, node,
r, skinnable->boxHints( subControl ) );
} }
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl ) QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
{ {
if ( rect.isEmpty() ) const auto fillGradient = skinnable->gradientHint( subControl );
return updateBoxNode( skinnable, node, rect, fillGradient, subControl );
}
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskGradient& fillGradient,
QskAspect::Subcontrol subControl )
{
const auto margins = skinnable->marginHint( subControl );
const auto boxRect = rect.marginsRemoved( margins );
if ( boxRect.isEmpty() )
return nullptr; return nullptr;
const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) ); const auto borderMetrics = skinnable->boxBorderMetricsHint( subControl );
return qskUpdateBoxNode( skinnable, node, r, skinnable->boxHints( subControl ) ); const auto borderColors = skinnable->boxBorderColorsHint( subControl );
const auto shape = skinnable->boxShapeHint( subControl );
const auto shadowMetrics = skinnable->shadowMetricsHint( subControl );
const auto shadowColor = skinnable->shadowColorHint( subControl );
return qskUpdateBoxNode( skinnable, node,
boxRect, shape, borderMetrics, borderColors, fillGradient,
shadowMetrics, shadowColor );
}
QSGNode* QskSkinlet::updateBoxNode(
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
const QskBoxShapeMetrics& shape, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& fillGradient )
{
return qskUpdateBoxNode( skinnable, node,
rect, shape, borderMetrics, borderColors, fillGradient,
QskShadowMetrics(), QColor() );
} }
QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateBoxNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskBoxHints& hints ) QSGNode* node, const QRectF& rect, const QskBoxHints& hints )
{ {
return qskUpdateBoxNode( skinnable, node, rect, hints ); return qskUpdateBoxNode( skinnable, node, rect,
hints.shape, hints.borderMetrics, hints.borderColors, hints.gradient,
hints.shadowMetrics, hints.shadowColor );
} }
QSGNode* QskSkinlet::updateInterpolatedBoxNode( QSGNode* QskSkinlet::updateInterpolatedBoxNode(
@ -483,24 +526,79 @@ QSGNode* QskSkinlet::updateInterpolatedBoxNode(
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, QskAspect::Subcontrol subControl ) const QSGNode* node, QskAspect::Subcontrol subControl ) const
{ {
auto rect = qskSubControlRect( this, skinnable, subControl ); const auto rect = qskSubControlRect( this, skinnable, subControl );
rect = rect.marginsRemoved( skinnable->marginHint( subControl ) ); return updateArcNode( skinnable, node, rect, subControl );
return qskUpdateArcNode( skinnable,
node, rect, skinnable->arcHints( subControl ) );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskArcHints& hints )
{
return qskUpdateArcNode( skinnable, node, rect, hints );
} }
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl ) QSGNode* node, const QRectF& rect, QskAspect::Subcontrol subControl )
{ {
const auto fillGradient = skinnable->gradientHint( subControl );
return updateArcNode( skinnable, node, rect, fillGradient, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskGradient& fillGradient,
QskAspect::Subcontrol subControl )
{
const auto metrics = skinnable->arcMetricsHint( subControl );
const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) );
const qreal borderWidth = skinnable->metric( subControl | QskAspect::Border );
QColor borderColor;
if ( borderWidth > 0.0 )
borderColor = skinnable->color( subControl | QskAspect::Border );
return qskUpdateArcNode( skinnable, node, return qskUpdateArcNode( skinnable, node,
rect, skinnable->arcHints( subControl ) ); r, borderWidth, borderColor, fillGradient, metrics );
}
QSGNode* QskSkinlet::updateArcNode(
const QskSkinnable* skinnable, QSGNode* node, const QRectF& rect,
qreal borderWidth, const QColor& borderColor,
const QskGradient& fillGradient, const QskArcMetrics& metrics )
{
return qskUpdateArcNode( skinnable, node, rect,
borderWidth, borderColor, fillGradient, metrics );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol subControl ) const
{
const auto rect = qskSubControlRect( this, skinnable, subControl );
return updateArcNode( skinnable, node,
rect, startAngle, spanAngle, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol subControl )
{
const auto fillGradient = skinnable->gradientHint( subControl );
return updateArcNode( skinnable, node, rect,
fillGradient, startAngle, spanAngle, subControl );
}
QSGNode* QskSkinlet::updateArcNode( const QskSkinnable* skinnable,
QSGNode* node, const QRectF& rect, const QskGradient& fillGradient,
qreal startAngle, qreal spanAngle, QskAspect::Subcontrol subControl )
{
auto arcMetrics = skinnable->arcMetricsHint( subControl );
arcMetrics.setStartAngle( startAngle );
arcMetrics.setSpanAngle( spanAngle );
const qreal borderWidth = skinnable->metric( subControl | QskAspect::Border );
QColor borderColor;
if ( borderWidth > 0.0 )
borderColor = skinnable->color( subControl | QskAspect::Border );
const auto r = rect.marginsRemoved( skinnable->marginHint( subControl ) );
return updateArcNode( skinnable, node, r,
borderWidth, borderColor, fillGradient, arcMetrics );
} }
QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable, QSGNode* QskSkinlet::updateLineNode( const QskSkinnable* skinnable,

View File

@ -23,8 +23,10 @@ class QskColorFilter;
class QskGraphic; class QskGraphic;
class QskTextOptions; class QskTextOptions;
class QskTextColors; class QskTextColors;
class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskBoxHints; class QskBoxHints;
class QskArcHints;
class QSGNode; class QSGNode;
@ -74,6 +76,13 @@ class QSK_EXPORT QskSkinlet
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*, static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, QskAspect::Subcontrol ); const QRectF&, QskAspect::Subcontrol );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskGradient&, QskAspect::Subcontrol );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient& );
static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*, static QSGNode* updateBoxNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskBoxHints& ); const QRectF&, const QskBoxHints& );
@ -85,7 +94,18 @@ class QSK_EXPORT QskSkinlet
const QRectF&, QskAspect::Subcontrol ); const QRectF&, QskAspect::Subcontrol );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskArcHints& ); const QRectF&, const QskGradient&, QskAspect::Subcontrol );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, qreal borderWidth, const QColor& borderColor,
const QskGradient&, const QskArcMetrics& );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, qreal startAngle, qreal spanAngle, QskAspect::Subcontrol );
static QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
const QRectF&, const QskGradient&, qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol );
static QSGNode* updateLineNode( const QskSkinnable*, QSGNode*, static QSGNode* updateLineNode( const QskSkinnable*, QSGNode*,
const QLineF&, QskAspect::Subcontrol ); const QLineF&, QskAspect::Subcontrol );
@ -136,6 +156,10 @@ class QSK_EXPORT QskSkinlet
QSGNode* updateArcNode( const QskSkinnable*, QSGNode*, QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
QskAspect::Subcontrol ) const; QskAspect::Subcontrol ) const;
QSGNode* updateArcNode( const QskSkinnable*, QSGNode*,
qreal startAngle, qreal spanAngle,
QskAspect::Subcontrol ) const;
QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*, QSGNode* updateBoxClipNode( const QskSkinnable*, QSGNode*,
QskAspect::Subcontrol ) const; QskAspect::Subcontrol ) const;

View File

@ -6,7 +6,7 @@
#include "QskSkinnable.h" #include "QskSkinnable.h"
#include "QskAnimationHint.h" #include "QskAnimationHint.h"
#include "QskArcHints.h" #include "QskArcMetrics.h"
#include "QskAspect.h" #include "QskAspect.h"
#include "QskColorFilter.h" #include "QskColorFilter.h"
#include "QskControl.h" #include "QskControl.h"
@ -637,23 +637,9 @@ QColor QskSkinnable::shadowColorHint( QskAspect aspect, QskSkinHintStatus* statu
QskBoxHints QskSkinnable::boxHints( QskAspect aspect ) const QskBoxHints QskSkinnable::boxHints( QskAspect aspect ) const
{ {
return QskBoxHints( return QskBoxHints(
boxShapeHint( aspect ), boxShapeHint( aspect ), boxBorderMetricsHint( aspect ),
boxBorderMetricsHint( aspect ), boxBorderColorsHint( aspect ), gradientHint( aspect ),
boxBorderColorsHint( aspect ), shadowMetricsHint( aspect ), shadowColorHint( aspect ) );
gradientHint( aspect ),
shadowMetricsHint( aspect ),
shadowColorHint( aspect )
);
}
QskArcHints QskSkinnable::arcHints( QskAspect aspect ) const
{
return QskArcHints(
arcMetricsHint( aspect ),
metric( aspect | QskAspect::Border ),
color( aspect | QskAspect::Border ),
gradientHint( aspect )
);
} }
bool QskSkinnable::setArcMetricsHint( bool QskSkinnable::setArcMetricsHint(

View File

@ -22,7 +22,6 @@ class QDebug;
class QSGNode; class QSGNode;
class QQuickItem; class QQuickItem;
class QskArcHints;
class QskArcMetrics; class QskArcMetrics;
class QskControl; class QskControl;
class QskAnimationHint; class QskAnimationHint;
@ -227,7 +226,6 @@ class QSK_EXPORT QskSkinnable
QColor shadowColorHint( QskAspect, QskSkinHintStatus* = nullptr ) const; QColor shadowColorHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
QskBoxHints boxHints( QskAspect ) const; QskBoxHints boxHints( QskAspect ) const;
QskArcHints arcHints( QskAspect ) const;
bool setArcMetricsHint( QskAspect, const QskArcMetrics& ); bool setArcMetricsHint( QskAspect, const QskArcMetrics& );
bool resetArcMetricsHint( QskAspect ); bool resetArcMetricsHint( QskAspect );

View File

@ -197,23 +197,6 @@ bool QskSlider::hasOrigin() const
return m_data->hasOrigin; return m_data->hasOrigin;
} }
void QskSlider::setTickPolicy( Qsk::Policy policy )
{
if ( setFlagHint( Tick | QskAspect::Option, policy ) )
Q_EMIT tickPolicyChanged( policy );
}
void QskSlider::resetTickPolicy()
{
if ( resetSkinHint( Tick | QskAspect::Option ) )
Q_EMIT tickPolicyChanged( tickPolicy() );
}
Qsk::Policy QskSlider::tickPolicy() const
{
return flagHint< Qsk::Policy >( Tick | QskAspect::Option, Qsk::Maybe );
}
QskAspect::Variation QskSlider::effectiveVariation() const QskAspect::Variation QskSlider::effectiveVariation() const
{ {
return static_cast< QskAspect::Variation >( m_data->orientation ); return static_cast< QskAspect::Variation >( m_data->orientation );

View File

@ -22,9 +22,6 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
Q_PROPERTY( bool tracking READ isTracking Q_PROPERTY( bool tracking READ isTracking
WRITE setTracking NOTIFY trackingChanged ) WRITE setTracking NOTIFY trackingChanged )
Q_PROPERTY( Qsk::Policy tickPolicy READ tickPolicy
WRITE setTickPolicy RESET resetTickPolicy NOTIFY tickPolicyChanged )
Q_PROPERTY( qreal origin READ origin Q_PROPERTY( qreal origin READ origin
WRITE setOrigin RESET resetOrigin NOTIFY originChanged ) WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
@ -42,10 +39,6 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
void setOrientation( Qt::Orientation ); void setOrientation( Qt::Orientation );
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
void setTickPolicy( Qsk::Policy );
void resetTickPolicy();
Qsk::Policy tickPolicy() const;
void setInverted( bool ); void setInverted( bool );
bool isInverted() const; bool isInverted() const;
@ -68,7 +61,6 @@ class QSK_EXPORT QskSlider : public QskBoundedValueInput
void invertedChanged( bool ); void invertedChanged( bool );
void trackingChanged( bool ); void trackingChanged( bool );
void originChanged( qreal ); void originChanged( qreal );
void tickPolicyChanged( Qsk::Policy );
protected: protected:
void mousePressEvent( QMouseEvent* ) override; void mousePressEvent( QMouseEvent* ) override;

View File

@ -388,7 +388,10 @@ bool QskSliderSkinlet::hasGraduation( const QskSlider* slider ) const
{ {
if ( slider->stepSize() ) if ( slider->stepSize() )
{ {
switch( slider->tickPolicy() ) const auto policy = slider->flagHint< Qsk::Policy >(
Q::Tick | QskAspect::Option, Qsk::Never );
switch( policy )
{ {
case Qsk::Always: case Qsk::Always:
return true; return true;

View File

@ -129,7 +129,7 @@ namespace
{ {
if ( qskIsAncestorOf( this, item ) ) if ( qskIsAncestorOf( this, item ) )
{ {
const auto pos = mapFromItem( item, QPointF() ) + scrollPos(); const auto pos = mapFromItem( item, QPointF() );
ensureVisible( QRectF( pos.x(), pos.y(), item->width(), item->height() ) ); ensureVisible( QRectF( pos.x(), pos.y(), item->width(), item->height() ) );
} }
} }

View File

@ -13,7 +13,6 @@
#include "QskGraduationMetrics.h" #include "QskGraduationMetrics.h"
#include "QskColorFilter.h" #include "QskColorFilter.h"
#include "QskGradient.h" #include "QskGradient.h"
#include "QskGradientStop.h"
#include "QskMargins.h" #include "QskMargins.h"
#include "QskIntervalF.h" #include "QskIntervalF.h"
#include "QskTextColors.h" #include "QskTextColors.h"
@ -44,7 +43,6 @@ static void qskRegisterInterpolator()
qRegisterAnimationInterpolator< QskColorFilter >( QskColorFilter::interpolate ); qRegisterAnimationInterpolator< QskColorFilter >( QskColorFilter::interpolate );
qRegisterAnimationInterpolator< QskIntervalF >( QskIntervalF::interpolate ); qRegisterAnimationInterpolator< QskIntervalF >( QskIntervalF::interpolate );
qRegisterAnimationInterpolator< QskMargins >( QskMargins::interpolate ); qRegisterAnimationInterpolator< QskMargins >( QskMargins::interpolate );
qRegisterAnimationInterpolator< QskGradientStop >( QskGradientStop::interpolate );
qRegisterAnimationInterpolator< QskGradient >( QskGradient::interpolate ); qRegisterAnimationInterpolator< QskGradient >( QskGradient::interpolate );
qRegisterAnimationInterpolator< QskBoxShapeMetrics >( QskBoxShapeMetrics::interpolate ); qRegisterAnimationInterpolator< QskBoxShapeMetrics >( QskBoxShapeMetrics::interpolate );
qRegisterAnimationInterpolator< QskBoxBorderMetrics >( QskBoxBorderMetrics::interpolate ); qRegisterAnimationInterpolator< QskBoxBorderMetrics >( QskBoxBorderMetrics::interpolate );

View File

@ -4,10 +4,11 @@
*****************************************************************************/ *****************************************************************************/
#include "QskArcNode.h" #include "QskArcNode.h"
#include "QskArcHints.h" #include "QskArcMetrics.h"
#include "QskArcRenderNode.h" #include "QskArcRenderNode.h"
#include "QskArcRenderer.h" #include "QskArcRenderer.h"
#include "QskMargins.h" #include "QskMargins.h"
#include "QskGradient.h"
#include "QskSGNode.h" #include "QskSGNode.h"
#include "QskRgbValue.h" #include "QskRgbValue.h"
@ -57,21 +58,24 @@ QskArcNode::~QskArcNode()
{ {
} }
void QskArcNode::setArcData( const QRectF& rect, const QskArcHints& hints ) void QskArcNode::setArcData( const QRectF& rect,
const QskArcMetrics& arcMetrics, const QskGradient& gradient )
{
setArcData( rect, arcMetrics, 0.0, QColor(), gradient );
}
void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics,
const qreal borderWidth, const QColor& borderColor, const QskGradient& gradient )
{ {
using namespace QskSGNode; using namespace QskSGNode;
QskArcRenderNode* arcNode = nullptr; QskArcRenderNode* arcNode = nullptr;
QskArcRenderNode* fillNode = nullptr; QskArcRenderNode* fillNode = nullptr;
if ( !rect.isEmpty() && hints.isVisible() ) if ( !( rect.isEmpty() || arcMetrics.isNull() ) )
{ {
const auto& gradient = hints.gradient;
const auto borderWidth = hints.borderWidth;
const auto borderColor = hints.borderColor;
const bool radial = false; const bool radial = false;
const auto metricsArc = hints.metrics.toAbsolute( rect.size() ); const auto metricsArc = arcMetrics.toAbsolute( rect.size() );
const auto hasFilling = gradient.isVisible(); const auto hasFilling = gradient.isVisible();
const auto hasBorder = ( borderWidth > 0.0 ) && QskRgb::isVisible( borderColor ); const auto hasBorder = ( borderWidth > 0.0 ) && QskRgb::isVisible( borderColor );

View File

@ -9,7 +9,8 @@
#include "QskGlobal.h" #include "QskGlobal.h"
#include <qsgnode.h> #include <qsgnode.h>
class QskArcHints; class QskArcMetrics;
class QskGradient;
class QSK_EXPORT QskArcNode : public QSGNode class QSK_EXPORT QskArcNode : public QSGNode
{ {
@ -17,7 +18,10 @@ class QSK_EXPORT QskArcNode : public QSGNode
QskArcNode(); QskArcNode();
~QskArcNode() override; ~QskArcNode() override;
void setArcData( const QRectF&, const QskArcHints& ); void setArcData( const QRectF&, const QskArcMetrics&, const QskGradient& );
void setArcData( const QRectF&, const QskArcMetrics&,
qreal borderWidth, const QColor& borderColor, const QskGradient& );
}; };
#endif #endif

View File

@ -8,8 +8,12 @@
#include "QskBoxRectangleNode.h" #include "QskBoxRectangleNode.h"
#include "QskSGNode.h" #include "QskSGNode.h"
#include "QskBoxHints.h" #include "QskGradient.h"
#include "QskGradientDirection.h" #include "QskGradientDirection.h"
#include "QskShadowMetrics.h"
#include "QskBoxBorderMetrics.h"
#include "QskBoxBorderColors.h"
#include "QskBoxShapeMetrics.h"
#include "QskRgbValue.h" #include "QskRgbValue.h"
namespace namespace
@ -56,8 +60,10 @@ QskBoxNode::~QskBoxNode()
{ {
} }
void QskBoxNode::updateNode( const QQuickWindow* window, void QskBoxNode::updateNode( const QQuickWindow* window, const QRectF& rect,
const QRectF& rect, const QskBoxHints& hints ) const QskBoxShapeMetrics& shapeMetrics, const QskBoxBorderMetrics& borderMetrics,
const QskBoxBorderColors& borderColors, const QskGradient& gradient,
const QskShadowMetrics& shadowMetrics, const QColor& shadowColor )
{ {
using namespace QskSGNode; using namespace QskSGNode;
@ -68,13 +74,6 @@ void QskBoxNode::updateNode( const QQuickWindow* window,
if ( !rect.isEmpty() ) if ( !rect.isEmpty() )
{ {
const auto& shapeMetrics = hints.shape;
const auto& borderMetrics = hints.borderMetrics;
const auto& borderColors = hints.borderColors;
const auto& gradient = hints.gradient;
const auto& shadowMetrics = hints.shadowMetrics;
const auto& shadowColor = hints.shadowColor;
const auto hasFilling = gradient.isVisible(); const auto hasFilling = gradient.isVisible();
const auto hasBorder = !borderMetrics.isNull() && borderColors.isVisible(); const auto hasBorder = !borderMetrics.isNull() && borderColors.isVisible();
const auto hasShadow = !shadowMetrics.isNull() && QskRgb::isVisible( shadowColor ); const auto hasShadow = !shadowMetrics.isNull() && QskRgb::isVisible( shadowColor );

View File

@ -9,8 +9,14 @@
#include "QskGlobal.h" #include "QskGlobal.h"
#include <qsgnode.h> #include <qsgnode.h>
class QskBoxHints; class QskShadowMetrics;
class QskBoxShapeMetrics;
class QskBoxBorderMetrics;
class QskBoxBorderColors;
class QskGradient;
class QskShadowMetrics;
class QQuickWindow; class QQuickWindow;
class QColor;
class QSK_EXPORT QskBoxNode : public QSGNode class QSK_EXPORT QskBoxNode : public QSGNode
{ {
@ -18,7 +24,10 @@ class QSK_EXPORT QskBoxNode : public QSGNode
QskBoxNode(); QskBoxNode();
~QskBoxNode() override; ~QskBoxNode() override;
void updateNode( const QQuickWindow*, const QRectF&, const QskBoxHints& ); void updateNode( const QQuickWindow*, const QRectF&,
const QskBoxShapeMetrics&, const QskBoxBorderMetrics&,
const QskBoxBorderColors&, const QskGradient&,
const QskShadowMetrics&, const QColor& shadowColor );
}; };
#endif #endif

View File

@ -54,16 +54,16 @@ namespace
} }
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
// make Qt 5/6 APIs matching
QSGMaterialShader* createShader( QSGMaterialShader* createShader(
QSGRendererInterface::RenderMode ) const override final QSGRendererInterface::RenderMode ) const override final
#else
QSGMaterialShader* createShader() const override final
#endif
{ {
return createMaterialShader(); return createShader();
} }
virtual QSGMaterialShader* createMaterialShader() const = 0; virtual QSGMaterialShader* createShader() const = 0;
#endif
virtual bool setGradient( const QskGradient& ) = 0; virtual bool setGradient( const QskGradient& ) = 0;
}; };
@ -217,7 +217,7 @@ namespace
return GradientMaterial::compare( other ); return GradientMaterial::compare( other );
} }
QSGMaterialShader* createMaterialShader() const override; QSGMaterialShader* createShader() const override;
/* /*
xy: position xy: position
@ -299,7 +299,7 @@ namespace
}; };
#endif #endif
QSGMaterialShader* LinearMaterial::createMaterialShader() const QSGMaterialShader* LinearMaterial::createShader() const
{ {
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
if ( !( flags() & QSGMaterial::RhiShaderWanted ) ) if ( !( flags() & QSGMaterial::RhiShaderWanted ) )
@ -371,7 +371,7 @@ namespace
} }
} }
QSGMaterialShader* createMaterialShader() const override; QSGMaterialShader* createShader() const override;
QVector2D m_center; QVector2D m_center;
QVector2D m_radius; QVector2D m_radius;
@ -465,7 +465,7 @@ namespace
}; };
#endif #endif
QSGMaterialShader* RadialMaterial::createMaterialShader() const QSGMaterialShader* RadialMaterial::createShader() const
{ {
#ifdef SHADER_GL #ifdef SHADER_GL
if ( !( flags() & QSGMaterial::RhiShaderWanted ) ) if ( !( flags() & QSGMaterial::RhiShaderWanted ) )
@ -575,7 +575,7 @@ namespace
return GradientMaterial::compare( other ); return GradientMaterial::compare( other );
} }
QSGMaterialShader* createMaterialShader() const override; QSGMaterialShader* createShader() const override;
QVector2D m_center; QVector2D m_center;
float m_aspectRatio = 1.0; float m_aspectRatio = 1.0;
@ -685,7 +685,7 @@ namespace
}; };
#endif #endif
QSGMaterialShader* ConicMaterial::createMaterialShader() const QSGMaterialShader* ConicMaterial::createShader() const
{ {
#ifdef SHADER_GL #ifdef SHADER_GL
if ( !( flags() & QSGMaterial::RhiShaderWanted ) ) if ( !( flags() & QSGMaterial::RhiShaderWanted ) )