Merge branch 'master' into features/modelobjectbinder
|
@ -175,7 +175,7 @@ jobs:
|
|||
}
|
||||
- {
|
||||
name: "macOS Latest Clang Qt5",
|
||||
os: macos-latest,
|
||||
os: macos-13,
|
||||
artifact: "macos_clang.7z",
|
||||
build_type: "Release",
|
||||
cc: "clang",
|
||||
|
@ -277,7 +277,8 @@ jobs:
|
|||
- name: Install dependencies on macos
|
||||
if: startsWith(matrix.config.os, 'macos')
|
||||
run: |
|
||||
brew install p7zip cmake ninja
|
||||
find /opt/homebrew/ -name EXTERNALLY-MANAGED|xargs rm
|
||||
brew install cmake ninja
|
||||
ninja --version
|
||||
cmake --version
|
||||
|
||||
|
@ -322,7 +323,7 @@ jobs:
|
|||
|
||||
- name: Install Qt5
|
||||
if: endsWith(matrix.config.name, 'Qt5')
|
||||
uses: jurplel/install-qt-action@v3
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: "5.15.2"
|
||||
target: "desktop"
|
||||
|
@ -336,7 +337,7 @@ jobs:
|
|||
|
||||
- name: Install Qt6
|
||||
if: endsWith(matrix.config.name, 'Qt6')
|
||||
uses: jurplel/install-qt-action@v3
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: "6.5.0"
|
||||
target: "desktop"
|
||||
|
|
10
LICENSES
|
@ -19,3 +19,13 @@ b) Cassowary constraint solving algorithm
|
|||
Code: https://github.com/nucleic/kiwi
|
||||
SPDX-License-Identifier: BSD 3-Clause "New" or "Revised" License
|
||||
Copyright (c) 2013, Nucleic Development Team
|
||||
|
||||
c) Material3 Icons
|
||||
|
||||
Code: https://github.com/marella/material-design-icons
|
||||
SPDX-License-Identifier: Apache License 2.0
|
||||
|
||||
d) Fluent2 Icons
|
||||
|
||||
Code: https://github.com/microsoft/fluentui-system-icons
|
||||
SPDX-License-Identifier: MIT License
|
||||
|
|
|
@ -9,7 +9,7 @@ set(SOURCES
|
|||
QskFluent2Skin.h QskFluent2Skin.cpp
|
||||
QskFluent2SkinFactory.h QskFluent2SkinFactory.cpp
|
||||
)
|
||||
qt_add_resources(SOURCES icons.qrc)
|
||||
qt_add_resources(SOURCES QskFluent2Icons.qrc)
|
||||
|
||||
qsk_add_plugin(fluent2skin skins QskFluent2SkinFactory ${SOURCES})
|
||||
set_target_properties(fluent2skin PROPERTIES DEFINE_SYMBOL QSK_FLUENT2_MAKEDLL )
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/fluent2">
|
||||
<file>icons/qvg/checkmark.qvg</file>
|
||||
<file>icons/qvg/chevron_down.qvg</file>
|
||||
<file>icons/qvg/chevron_up.qvg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -103,6 +103,13 @@
|
|||
#include <qguiapplication.h>
|
||||
#include <qfontinfo.h>
|
||||
|
||||
static void qskFluent2InitResources()
|
||||
{
|
||||
Q_INIT_RESOURCE( QskFluent2Icons );
|
||||
}
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( qskFluent2InitResources )
|
||||
|
||||
namespace Fluent2
|
||||
{
|
||||
using F = QskFontRole;
|
||||
|
@ -412,7 +419,6 @@ void Editor::setupCheckBoxMetrics()
|
|||
setStrutSize( Q::Box, { 20_px, 20_px } ); // 18 + 2*1 border
|
||||
setBoxShape( Q::Box, 4_px ); // adapt to us taking the border into account
|
||||
setBoxBorderMetrics( Q::Box, 1_px );
|
||||
setPadding( Q::Box, 5_px ); // "icon size"
|
||||
|
||||
setFontRole( Q::Text, Fluent2::Body );
|
||||
}
|
||||
|
@ -541,9 +547,9 @@ void Editor::setupComboBoxMetrics()
|
|||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
setFontRole( Q::Text, Fluent2::Body );
|
||||
|
||||
setStrutSize( Q::StatusIndicator, 12_px, 12_px );
|
||||
setSymbol( Q::StatusIndicator, symbol( "spin-box-arrow-down" ) );
|
||||
setSymbol( Q::StatusIndicator | Q::PopupOpen, symbol( "spin-box-arrow-up" ) );
|
||||
setStrutSize( Q::StatusIndicator, 16_px, 16_px );
|
||||
setSymbol( Q::StatusIndicator, symbol( "chevron_down" ) );
|
||||
// setSymbol( Q::StatusIndicator | Q::PopupOpen, symbol( "chevron_up" ) );
|
||||
|
||||
// Using Focused (Pressed doesn't exist yet):
|
||||
setBoxBorderMetrics( Q::Panel | Q::Focused, { 1_px, 1_px, 1_px, 2_px } );
|
||||
|
@ -1497,28 +1503,38 @@ void Editor::setupSpinBoxMetrics()
|
|||
{
|
||||
using Q = QskSpinBox;
|
||||
|
||||
/*
|
||||
The F2 NumberBox has 2 modes for the Up/Down panels ( a.k.a Spinner ):
|
||||
|
||||
- compact ( -> QskSpinBox::UpDownControl )
|
||||
- inline ( -> QskSpinBox::ButtonsRight )
|
||||
|
||||
TODO: in compact mode the panels/indicators are blown up, when being hovered
|
||||
*/
|
||||
setHint( Q::Panel | QskAspect::Style, Q::ButtonsRight );
|
||||
|
||||
setStrutSize( Q::Panel, { -1, 32_px } );
|
||||
setBoxBorderMetrics( Q::Panel, 1_px );
|
||||
setBoxShape( Q::Panel, 3_px );
|
||||
setPadding( Q::Panel, { 11_px, 0, 11_px, 0 } );
|
||||
|
||||
setAlignment( Q::Text, Qt::AlignLeft );
|
||||
setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
|
||||
setFontRole( Q::Text, Fluent2::Body );
|
||||
|
||||
setPadding( Q::TextPanel, { 11_px, 5_px, 0, 0 } );
|
||||
setPadding( Q::TextPanel, { 11_px, 0, 11_px, 0 } );
|
||||
|
||||
setStrutSize( Q::UpPanel, 32_px, 20_px );
|
||||
setPadding( Q::UpPanel, { 11_px, 7_px, 11_px, 7_px } );
|
||||
for ( auto panel : { Q::UpPanel, Q::DownPanel } )
|
||||
setStrutSize( panel, 32_px, 18_px );
|
||||
|
||||
setStrutSize( Q::DownPanel, 34_px, 20_px );
|
||||
setPadding( Q::DownPanel, { 11_px, 7_px, 13_px, 7_px } );
|
||||
setSymbol( Q::UpIndicator, symbol( "chevron_up" ) );
|
||||
setSymbol( Q::DownIndicator, symbol( "chevron_down" ) );
|
||||
|
||||
setSymbol( Q::UpIndicator, symbol( "spin-box-arrow-up" ) );
|
||||
setSymbol( Q::DownIndicator, symbol( "spin-box-arrow-down" ) );
|
||||
setPadding( Q::UpPanel, { 0, 1_px, 0, 0 } );
|
||||
setPadding( Q::DownPanel, { 0, 0, 0, 1_px } );
|
||||
|
||||
// Focused (Pressed doesn't exist yet):
|
||||
setBoxBorderMetrics( Q::Panel | Q::Focused, { 1_px, 1_px, 1_px, 2_px } );
|
||||
#if 0
|
||||
// QskSpinBox::Pressed is missing yet
|
||||
setBoxBorderMetrics( Q::Panel | Q::Pressed, { 1_px, 1_px, 1_px, 2_px } );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Editor::setupSpinBoxColors(
|
||||
|
@ -1581,8 +1597,17 @@ void Editor::setupSpinBoxColors(
|
|||
panelColor = rgbSolid( panelColor, pal.background.solid.base );
|
||||
|
||||
setGradient( panel, panelColor );
|
||||
|
||||
setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor );
|
||||
|
||||
if ( state == Q::Focused )
|
||||
{
|
||||
const auto colors = boxBorderColors( panel );
|
||||
|
||||
setBoxBorderColors( panel | Q::Decreasing, colors );
|
||||
setBoxBorderColors( panel | Q::Increasing, colors );
|
||||
}
|
||||
|
||||
setColor( text, textColor );
|
||||
|
||||
setGraphicRole( upIndicator, graphicRole );
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/fluent2">
|
||||
<file>icons/qvg/checkmark.qvg</file>
|
||||
<file>icons/qvg/combo-box-arrow-closed.qvg</file>
|
||||
<file>icons/qvg/combo-box-arrow-open.qvg</file>
|
||||
<file>icons/qvg/segmented-button-check.qvg</file>
|
||||
<file>icons/qvg/spin-box-arrow-down.qvg</file>
|
||||
<file>icons/qvg/spin-box-arrow-up.qvg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,10 @@
|
|||
SVGs have been taken from https://github.com/microsoft/fluentui-system-icons/tree/main/assets.
|
||||
|
||||
Icons are available in different sizes. As SVGs can be scaled we only need
|
||||
one version of them - chosing the '12'.
|
||||
|
||||
As we are replacing the colors of the SVGs using graphic filters we set the
|
||||
color in the SVGs manually to black ( instead of #212121 ). So they are in
|
||||
line with icons coming from somewhere else.
|
||||
|
||||
Names have been shortened ( ic_fluent_xyz_16_regular.svg -> xyz.svg )
|
|
@ -1,4 +1,3 @@
|
|||
<svg width="11" height="8" viewBox="0 0 11 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.00195312 3.49805C0.00195312 3.36133 0.0507812 3.24414 0.148438 3.14648C0.246094 3.04883 0.363281 3 0.5 3C0.636719 3 0.753906 3.04883 0.851562 3.14648L3.5 5.79492L9.14844 0.146484C9.24609 0.0488281 9.36328 0 9.5 0C9.57031 0 9.63477 0.0136719 9.69336 0.0410156C9.75586 0.0644531 9.80859 0.0996094 9.85156 0.146484C9.89844 0.189453 9.93555 0.242187 9.96289 0.304688C9.99023 0.363281 10.0039 0.427734 10.0039 0.498047C10.0039 0.634766 9.95312 0.753906 9.85156 0.855469L3.85156 6.85547C3.75391 6.95312 3.63672 7.00195 3.5 7.00195C3.36328 7.00195 3.24609 6.95312 3.14844 6.85547L0.148438 3.85547C0.0507812 3.75781 0.00195312 3.63867 0.00195312 3.49805Z" fill="black"/>
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.85355 3.14645C10.0488 3.34171 10.0488 3.65829 9.85355 3.85355L5.35355 8.35355C5.15829 8.54882 4.84171 8.54882 4.64645 8.35355L2.64645 6.35355C2.45118 6.15829 2.45118 5.84171 2.64645 5.64645C2.84171 5.45118 3.15829 5.45118 3.35355 5.64645L5 7.29289L9.14645 3.14645C9.34171 2.95118 9.65829 2.95118 9.85355 3.14645Z" fill="black"/>
|
||||
</svg>
|
||||
|
||||
|
|
Before Width: | Height: | Size: 777 B After Width: | Height: | Size: 444 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.14645 4.64645C2.34171 4.45118 2.65829 4.45118 2.85355 4.64645L6 7.79289L9.14645 4.64645C9.34171 4.45118 9.65829 4.45118 9.85355 4.64645C10.0488 4.84171 10.0488 5.15829 9.85355 5.35355L6.35355 8.85355C6.15829 9.04882 5.84171 9.04882 5.64645 8.85355L2.14645 5.35355C1.95118 5.15829 1.95118 4.84171 2.14645 4.64645Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 444 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.14645 7.35355C2.34171 7.54882 2.65829 7.54882 2.85355 7.35355L6 4.20711L9.14645 7.35355C9.34171 7.54882 9.65829 7.54882 9.85355 7.35355C10.0488 7.15829 10.0488 6.84171 9.85355 6.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645L2.14645 6.64645C1.95118 6.84171 1.95118 7.15829 2.14645 7.35355Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 444 B |
|
@ -1,4 +0,0 @@
|
|||
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.25 0.5L4 4.25L7.75 0.5H0.25Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 157 B |
|
@ -1,4 +0,0 @@
|
|||
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.25 0.5L4 4.25L7.75 0.5H0.25Z" transform="rotate(180 4 2.5)" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 187 B |
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage $0 file ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in $*
|
||||
do
|
||||
base=`basename -s .svg $file`
|
||||
echo "${base}.svg -> qvg/${base}.qvg"
|
||||
svg2qvg ${base}.svg qvg/${base}.qvg
|
||||
done
|
||||
|
||||
exit $status
|
|
@ -1,4 +0,0 @@
|
|||
<svg width="14" height="11" viewBox="0 0 14 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.24914 8.12738L1.12164 4.99988L0.0566406 6.05738L4.24914 10.2499L13.2491 1.24988L12.1916 0.192383L4.24914 8.12738Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 246 B |
|
@ -1,4 +0,0 @@
|
|||
<svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.5 1.125C0.5 1.02344 0.537109 0.935547 0.611328 0.861328C0.685547 0.787109 0.773438 0.75 0.875 0.75C0.976562 0.75 1.06445 0.787109 1.13867 0.861328L5 4.7168L8.86133 0.861328C8.93555 0.787109 9.02344 0.75 9.125 0.75C9.22656 0.75 9.31445 0.787109 9.38867 0.861328C9.46289 0.935547 9.5 1.02344 9.5 1.125C9.5 1.22656 9.46289 1.31445 9.38867 1.38867L5.26367 5.51367C5.18945 5.58789 5.10156 5.625 5 5.625C4.89844 5.625 4.81055 5.58789 4.73633 5.51367L0.611328 1.38867C0.537109 1.31445 0.5 1.22656 0.5 1.125Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 631 B |
|
@ -1,4 +0,0 @@
|
|||
<svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.5 4.875C0.5 4.77344 0.537109 4.68555 0.611328 4.61133L4.73633 0.486328C4.81055 0.412109 4.89844 0.375 5 0.375C5.10156 0.375 5.18945 0.412109 5.26367 0.486328L9.38867 4.61133C9.46289 4.68555 9.5 4.77344 9.5 4.875C9.5 4.97656 9.46289 5.06445 9.38867 5.13867C9.31445 5.21289 9.22656 5.25 9.125 5.25C9.02344 5.25 8.93555 5.21289 8.86133 5.13867L5 1.2832L1.13867 5.13867C1.06445 5.21289 0.976562 5.25 0.875 5.25C0.773438 5.25 0.685547 5.21289 0.611328 5.13867C0.537109 5.06445 0.5 4.97656 0.5 4.875Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 625 B |
|
@ -145,13 +145,21 @@ namespace
|
|||
|
||||
if ( strcmp( name, "checkMark" ) == 0 )
|
||||
{
|
||||
graphic.setViewBox( QRectF( 0.0, 0.0, 14.0, 14.0 ) );
|
||||
|
||||
QPainterPath path;
|
||||
path.moveTo( 0.11, 0.47 );
|
||||
path.lineTo( 0.5, 1.0);
|
||||
path.lineTo( 1.0, 0.0 );
|
||||
path.moveTo( 3.5, 7.0 );
|
||||
path.lineTo( 6.5, 14.0 );
|
||||
path.lineTo( 11.0, 1.0 );
|
||||
|
||||
QPen pen( Qt::black, 2.8 );
|
||||
pen.setCapStyle( Qt::FlatCap );
|
||||
pen.setJoinStyle( Qt::BevelJoin );
|
||||
|
||||
QPainter painter( &graphic );
|
||||
painter.setPen( QPen( Qt::black, 0.25 ) );
|
||||
painter.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
painter.setPen( pen );
|
||||
painter.drawPath( path );
|
||||
}
|
||||
|
||||
|
@ -209,19 +217,12 @@ void Editor::setupCheckBox()
|
|||
}
|
||||
}
|
||||
|
||||
setGraphicRole( Q::Indicator, QskFusionSkin::GraphicNormal );
|
||||
setGraphicRole( Q::Indicator, QskFusionSkin::GraphicIndicator );
|
||||
setGraphicRole( Q::Indicator | Q::Disabled, QskFusionSkin::GraphicDisabled );
|
||||
setGraphicRole( Q::Indicator | Q::Error, QskFusionSkin::GraphicError );
|
||||
|
||||
#if 0
|
||||
// aligning/scaling of the symbols needs to be fixed in the skinlet TODO ..
|
||||
|
||||
setPadding( Q::Box, 4_dp );
|
||||
setPadding( Q::Box, 3_dp );
|
||||
const auto checkMark = symbol( "checkMark" );
|
||||
#else
|
||||
setPadding( Q::Box, 2_dp );
|
||||
const auto checkMark = QskStandardSymbol::graphic( QskStandardSymbol::CheckMark );
|
||||
#endif
|
||||
|
||||
for ( auto state : { QskAspect::NoState, Q::Disabled } )
|
||||
{
|
||||
|
@ -277,6 +278,7 @@ void Editor::setupComboBox()
|
|||
setGraphicRole( Q::Icon | Q::Disabled, QskFusionSkin::GraphicDisabled );
|
||||
|
||||
setStrutSize( Q::StatusIndicator, 10_dp, 10_dp );
|
||||
setGraphicRole( Q::StatusIndicator, QskFusionSkin::GraphicIndicator );
|
||||
setGraphicRole( Q::StatusIndicator | Q::Disabled, QskFusionSkin::GraphicDisabled );
|
||||
|
||||
setAlignment( Q::StatusIndicator, Qt::AlignRight | Qt::AlignVCenter );
|
||||
|
@ -859,8 +861,6 @@ void Editor::setupSpinBox()
|
|||
|
||||
setPadding( Q::TextPanel, 5_dp );
|
||||
setBoxShape( Q::TextPanel, 2, 0, 2, 0 );
|
||||
|
||||
setColor( Q::Text, m_pal.active( P::Text ) );
|
||||
setGradient( Q::TextPanel | Q::Disabled, m_pal.disabled( P::Base ) );
|
||||
|
||||
setBoxBorderMetrics( Q::TextPanel, 1_dp );
|
||||
|
@ -872,6 +872,9 @@ void Editor::setupSpinBox()
|
|||
Combination( { Q::Increasing, Q::Decreasing, Q::Hovered } ) );
|
||||
#endif
|
||||
|
||||
setColor( Q::Text, m_pal.active( P::Text ) );
|
||||
setAlignment( Q::Text, Qt::AlignCenter );
|
||||
|
||||
setBoxShape( Q::UpPanel, 0, 2_dp, 0, 0 );
|
||||
setBoxBorderMetrics( Q::UpPanel, 0_dp, 1_dp, 1_dp, 0_dp );
|
||||
|
||||
|
@ -1338,6 +1341,13 @@ void QskFusionSkin::initHints()
|
|||
setGraphicColor( GraphicError, palette.error );
|
||||
setGraphicColor( GraphicHighlighted, palette.active( P::HighlightedText ) );
|
||||
|
||||
{
|
||||
auto rgb = palette.darker( P::Active, P::Text, 120 );
|
||||
rgb = QskRgb::toTransparent( rgb, 180 );
|
||||
|
||||
setGraphicColor( GraphicIndicator, rgb );
|
||||
}
|
||||
|
||||
Editor editor( palette, &hintTable() );
|
||||
editor.setup();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ class QSK_FUSION_EXPORT QskFusionSkin : public QskSkin
|
|||
GraphicNormal,
|
||||
GraphicDisabled,
|
||||
GraphicHighlighted,
|
||||
GraphicError
|
||||
GraphicError,
|
||||
GraphicIndicator
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -7,7 +7,7 @@ set(SOURCES
|
|||
QskMaterial3Global.h QskMaterial3Skin.h QskMaterial3Skin.cpp
|
||||
QskMaterial3SkinFactory.h QskMaterial3SkinFactory.cpp
|
||||
)
|
||||
qt_add_resources(SOURCES icons.qrc)
|
||||
qt_add_resources(SOURCES QskMaterial3Icons.qrc)
|
||||
|
||||
qsk_add_plugin(material3skin skins QskMaterial3SkinFactory ${SOURCES})
|
||||
set_target_properties(material3skin PROPERTIES DEFINE_SYMBOL QSK_MATERIAL3_MAKEDLL )
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<RCC>
|
||||
<qresource prefix="/m3">
|
||||
|
||||
<!-- needed until we have fixed a rendering bug for small icons -->
|
||||
|
||||
<file>icons/qvg/check_small.qvg</file>
|
||||
<file>icons/qvg/combo-box-arrow-closed.qvg</file>
|
||||
<file>icons/qvg/combo-box-arrow-open.qvg</file>
|
||||
<file>icons/qvg/segmented-button-check.qvg</file>
|
||||
|
||||
<!-- https://github.com/marella/material-design-icons/tree/main/svg/round -->
|
||||
|
||||
<file>icons/qvg/add.qvg</file>
|
||||
<file>icons/qvg/arrow_drop_down.qvg</file>
|
||||
<file>icons/qvg/arrow_drop_up.qvg</file>
|
||||
<file>icons/qvg/check.qvg</file>
|
||||
<file>icons/qvg/remove.qvg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -64,6 +64,13 @@
|
|||
#include <qguiapplication.h>
|
||||
#include <qfontinfo.h>
|
||||
|
||||
static void qskMaterial3InitResources()
|
||||
{
|
||||
Q_INIT_RESOURCE( QskMaterial3Icons );
|
||||
}
|
||||
|
||||
Q_CONSTRUCTOR_FUNCTION( qskMaterial3InitResources )
|
||||
|
||||
static const int qskDuration = 150;
|
||||
|
||||
namespace
|
||||
|
@ -105,6 +112,15 @@ namespace
|
|||
return qskDpToPixels( value );
|
||||
}
|
||||
|
||||
class Combination : public QskStateCombination
|
||||
{
|
||||
public:
|
||||
constexpr Combination( const QskAspect::States states )
|
||||
: QskStateCombination( CombinationNoState, states )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Editor : private QskSkinHintTableEditor
|
||||
{
|
||||
Q_GADGET
|
||||
|
@ -585,7 +601,7 @@ void Editor::setupSegmentedBar()
|
|||
{
|
||||
// Icon
|
||||
|
||||
setSymbol( Q::Icon, symbol( "segmented-button-check" ) );
|
||||
setSymbol( Q::Icon, symbol( "check" ) );
|
||||
setStrutSize( Q::Icon, 18_dp, 18_dp );
|
||||
|
||||
setGraphicRole( Q::Icon, QskMaterial3Skin::GraphicRoleOnSurface );
|
||||
|
@ -881,13 +897,21 @@ void Editor::setupSpinBox()
|
|||
using Q = QskSpinBox;
|
||||
|
||||
setHint( Q::Panel | QskAspect::Style, Q::ButtonsLeftAndRight );
|
||||
|
||||
setBoxShape( Q::Panel, 4_dp );
|
||||
setBoxBorderMetrics( Q::Panel, 1_dp );
|
||||
|
||||
setBoxBorderColors( Q::Panel, m_pal.outline );
|
||||
setBoxBorderColors( Q::Panel | Q::Focused, m_pal.primary,
|
||||
Combination( { Q::Increasing, Q::Decreasing } ) );
|
||||
|
||||
setPadding( Q::Panel, 4_dp );
|
||||
setSpacing( Q::Panel, 4_dp );
|
||||
|
||||
setStrutSize( Q::TextPanel, 80_dp, 40_dp );
|
||||
setStrutSize( Q::UpPanel, 40_dp,40_dp );
|
||||
setStrutSize( Q::DownPanel, 40_dp, 40_dp );
|
||||
|
||||
setAlignment( Q::Panel, Qt::AlignHCenter );
|
||||
setAlignment( Q::Text, Qt::AlignCenter );
|
||||
|
||||
for( const auto subControl : { Q::DownPanel, Q::UpPanel, Q::TextPanel } )
|
||||
|
@ -898,31 +922,31 @@ void Editor::setupSpinBox()
|
|||
|
||||
for( const auto subControl : { Q::DownPanel, Q::UpPanel } )
|
||||
{
|
||||
setGradient( subControl, m_pal.primary );
|
||||
setGradient( subControl | Q::Disabled, m_pal.onSurface12 );
|
||||
setGradient( subControl | Q::Hovered, m_pal.primary8 );
|
||||
setPadding( subControl, 10 );
|
||||
}
|
||||
|
||||
{
|
||||
const auto focusColor = flattenedColor( m_pal.onPrimary, m_pal.primary, 0.12 );
|
||||
|
||||
setGradient( Q::DownPanel | Q::Decreasing, focusColor );
|
||||
setGradient( Q::UpPanel | Q::Increasing, focusColor );
|
||||
setGradient( Q::DownPanel | Q::Decreasing, m_pal.primary12 );
|
||||
setGradient( Q::UpPanel | Q::Increasing, m_pal.primary12 );
|
||||
}
|
||||
|
||||
setSymbol( Q::UpIndicator, symbol( "combo-box-arrow-open" ) );
|
||||
setSymbol( Q::DownIndicator, symbol( "combo-box-arrow-closed" ) );
|
||||
setSymbol( Q::UpIndicator, symbol( "add" ) );
|
||||
setSymbol( Q::DownIndicator, symbol( "remove" ) );
|
||||
|
||||
for( const auto subControl : { Q::DownIndicator, Q::UpIndicator } )
|
||||
{
|
||||
setAlignment( subControl, Qt::AlignCenter );
|
||||
#if 0
|
||||
setGraphicRole( subControl, QskMaterial3Skin::GraphicRoleOnPrimary );
|
||||
setGraphicRole( subControl | Q::Disabled, QskMaterial3Skin::GraphicRoleOnSurface38 );
|
||||
#endif
|
||||
}
|
||||
|
||||
setColor( Q::Text, m_pal.onBackground );
|
||||
setColor( Q::Text | Q::Disabled, m_pal.onSurface38 );
|
||||
|
||||
#if 0
|
||||
setPadding( Q::TextPanel, 5_dp );
|
||||
setBoxShape( Q::TextPanel, 4_dp, 4_dp, 0, 0 );
|
||||
setBoxBorderMetrics( Q::TextPanel, 0, 0, 0, 1_dp );
|
||||
|
@ -939,6 +963,7 @@ void Editor::setupSpinBox()
|
|||
|
||||
setColor( Q::TextPanel | Q::Disabled, m_pal.onSurface38 );
|
||||
setBoxBorderColors( Q::TextPanel | Q::Disabled, m_pal.onSurface38 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Editor::setupSwitchButton()
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/m3">
|
||||
<file>icons/qvg/check_small.qvg</file>
|
||||
<file>icons/qvg/combo-box-arrow-closed.qvg</file>
|
||||
<file>icons/qvg/combo-box-arrow-open.qvg</file>
|
||||
<file>icons/qvg/segmented-button-check.qvg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M18 13h-5v5c0 .55-.45 1-1 1s-1-.45-1-1v-5H6c-.55 0-1-.45-1-1s.45-1 1-1h5V6c0-.55.45-1 1-1s1 .45 1 1v5h5c.55 0 1 .45 1 1s-.45 1-1 1z"/></svg>
|
After Width: | Height: | Size: 232 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="m8.71 11.71 2.59 2.59c.39.39 1.02.39 1.41 0l2.59-2.59c.63-.63.18-1.71-.71-1.71H9.41c-.89 0-1.33 1.08-.7 1.71z"/></svg>
|
After Width: | Height: | Size: 211 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M8.71 12.29 11.3 9.7a.996.996 0 0 1 1.41 0l2.59 2.59c.63.63.18 1.71-.71 1.71H9.41c-.89 0-1.33-1.08-.7-1.71z"/></svg>
|
After Width: | Height: | Size: 208 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9 16.17 5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41L9 16.17z"/></svg>
|
After Width: | Height: | Size: 221 B |
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage $0 file ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in $*
|
||||
do
|
||||
base=`basename -s .svg $file`
|
||||
echo "${base}.svg -> qvg/${base}.qvg"
|
||||
svg2qvg ${base}.svg qvg/${base}.qvg
|
||||
done
|
||||
|
||||
exit $status
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M18 13H6c-.55 0-1-.45-1-1s.45-1 1-1h12c.55 0 1 .45 1 1s-.45 1-1 1z"/></svg>
|
After Width: | Height: | Size: 167 B |
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
title: 10. Building QSkinny for WebAssembly (Wasm)
|
||||
layout: docs
|
||||
---
|
||||
|
||||
:doctitle: 10. Building QSkinny for WebAssembly (Wasm)
|
||||
:notitle:
|
||||
|
||||
== 10. Building QSkinny for WebAssembly (Wasm)
|
||||
|
||||
|
||||
=== Build Qt for Wasm
|
||||
|
||||
Build Qt for Wasm from source as described here: https://doc.qt.io/qt-6/wasm.html#building-qt-from-source ; The verified Qt version for QSkinny as of this writing was 6.6.0. It might also work to use a downloaded version of Qt for Wasm, but some additional libraries will need to be built.
|
||||
After configuring Qt as described in the link above, for QSkinny you will need the qtbase, qtdeclarative, qtshadertools and qtsvg modules.
|
||||
Assuming the Emscripten SDK in `~/dev/emscripten` and Qt in `~/dev/qt6`, Qt can be compiled the following way:
|
||||
|
||||
[source]
|
||||
....
|
||||
cd ~/dev/qt6
|
||||
source "~/dev/emsdk/emsdk_env.sh"
|
||||
cmake --build . -t qtbase -t qtdeclarative -t qtshadertools -t qtsvg
|
||||
....
|
||||
|
||||
This will install all required libs in `~/dev/qt6/qtbase/lib`.
|
||||
|
||||
|
||||
=== Build QSkinny for Wasm
|
||||
|
||||
With the Qt version from above QSkinny can be built for WAsm, assuming it has been checked out at `~/dev/qskinny`. Note the configuration option `BUILD_QSKDLL=OFF` for static
|
||||
builds:
|
||||
|
||||
[source]
|
||||
....
|
||||
mkdir -p ~/dev/qskinny-wasm-build
|
||||
source "~/dev/emsdk/emsdk_env.sh"
|
||||
~/dev/qt6/qtbase/bin/qt-cmake -S ~/dev/qskinny -B ~/dev/qskinny-wasm-build -DBUILD_QSKDLL=OFF
|
||||
....
|
||||
|
||||
|
||||
=== Run QSkinny for Wasm
|
||||
|
||||
Qt creates the HTML wrappers automatically, so there is not much to do except letting Emscripten start the server and open our app in the browser:
|
||||
|
||||
[source]
|
||||
....
|
||||
/usr/bin/python3 ~/dev/emsdk/upstream/emscripten/emrun.py --browser firefox --port 30001 --no_emrun_detect ~/dev/qskinny-wasm-build/examples/bin/iotdashboard.html
|
||||
....
|
||||
|
||||
.The IOT dashboard example in a browser
|
||||
image::../images/iotdashboard-wasm.png[The IOT dashboard example in a browser]
|
After Width: | Height: | Size: 109 KiB |
|
@ -9,6 +9,60 @@
|
|||
#include <QskLinearBox.h>
|
||||
#include <QskPushButton.h>
|
||||
|
||||
#if QT_CONFIG(thread)
|
||||
/*
|
||||
WebAssembly without asyncify support does not allow recursive
|
||||
event loops. As we did not implement QskDialog::message and friends
|
||||
with callbacks yet ( TODO ) we do have some dummy code here to avoid
|
||||
crashes.
|
||||
*/
|
||||
#define QSK_USE_EXEC
|
||||
#endif
|
||||
|
||||
#ifndef QSK_USE_EXEC
|
||||
|
||||
#include <QskMessageSubWindow.h>
|
||||
#include <QskSelectionSubWindow.h>
|
||||
#include <qquickwindow.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
void openMessageSubWindow( QQuickWindow* window, const QString& title,
|
||||
const QString& text, QskDialog::Actions actions, QskDialog::Action defaultAction )
|
||||
{
|
||||
auto subWindow = new QskMessageSubWindow( window->contentItem() );
|
||||
subWindow->setPopupFlag( QskPopup::DeleteOnClose );
|
||||
subWindow->setModal( true );
|
||||
|
||||
subWindow->setTitle( title );
|
||||
subWindow->setDialogActions( actions );
|
||||
subWindow->setDefaultDialogAction( defaultAction );
|
||||
|
||||
subWindow->setText( text );
|
||||
( void ) subWindow->open();
|
||||
}
|
||||
|
||||
void openSelectSubWindow( QQuickWindow* window, const QString& title,
|
||||
QskDialog::Actions actions, QskDialog::Action defaultAction,
|
||||
const QStringList& entries, int selectedRow )
|
||||
{
|
||||
auto subWindow = new QskSelectionSubWindow( window->contentItem() );
|
||||
subWindow->setPopupFlag( QskPopup::DeleteOnClose );
|
||||
subWindow->setModal( true );
|
||||
|
||||
subWindow->setTitle( title );
|
||||
subWindow->setDialogActions( actions );
|
||||
subWindow->setDefaultDialogAction( defaultAction );
|
||||
|
||||
subWindow->setEntries( entries );
|
||||
subWindow->setSelectedRow( selectedRow );
|
||||
|
||||
( void ) subWindow->open();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
class Button : public QskPushButton
|
||||
|
@ -48,17 +102,32 @@ namespace
|
|||
private:
|
||||
void execMessage()
|
||||
{
|
||||
qskDialog->information( "Message", "Request vector, over." );
|
||||
const QString title( "Message" );
|
||||
const QString message( "Request vector, over." );
|
||||
#ifndef QSK_USE_EXEC
|
||||
openMessageSubWindow( window(), title, message,
|
||||
QskDialog::Ok, QskDialog::Ok );
|
||||
#else
|
||||
qskDialog->information( title, message );
|
||||
#endif
|
||||
}
|
||||
|
||||
void execQuestion()
|
||||
{
|
||||
qskDialog->question( "Question",
|
||||
"Roger, Roger. Do we have a vector, Victor ?" );
|
||||
const QString title( "Question" );
|
||||
const QString question( "Roger, Roger. Do we have a vector, Victor ?" );
|
||||
#ifndef QSK_USE_EXEC
|
||||
openMessageSubWindow( window(), title, question,
|
||||
QskDialog::Yes | QskDialog::No, QskDialog::Yes );
|
||||
#else
|
||||
(void )qskDialog->question( title, question );
|
||||
#endif
|
||||
}
|
||||
|
||||
void execSelection()
|
||||
{
|
||||
const QString title( "The Teens" );
|
||||
|
||||
const QStringList entries =
|
||||
{
|
||||
"Give Me More",
|
||||
|
@ -81,7 +150,12 @@ namespace
|
|||
"Gimme Gimme Gimme Gimme Gimme Your Love"
|
||||
};
|
||||
|
||||
qskDialog->select( "The Teens", entries, 7 );
|
||||
#ifndef QSK_USE_EXEC
|
||||
openSelectSubWindow( window(), title,
|
||||
QskDialog::Ok | QskDialog::Cancel, QskDialog::Ok, entries, 7 );
|
||||
#else
|
||||
(void )qskDialog->select( title, entries, 7 );
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage $0 file ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in $*
|
||||
do
|
||||
base=`basename -s .svg $file`
|
||||
echo "${base}.svg -> qvg/${base}.qvg"
|
||||
svg2qvg ${base}.svg qvg/${base}.qvg
|
||||
done
|
||||
|
||||
exit $status
|
|
@ -62,16 +62,10 @@ namespace
|
|||
|
||||
{
|
||||
auto spinBox = new QskSpinBox( 0.0, 100.0, 1.0, this );
|
||||
spinBox->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
|
||||
spinBox->setPageSize( 5 );
|
||||
spinBox->setValue( 35 );
|
||||
}
|
||||
|
||||
{
|
||||
auto spinBox = new QskSpinBox( 10.0, 100.0, 1.0, this );
|
||||
spinBox->setPageSize( 10 );
|
||||
spinBox->setDecoration( QskSpinBox::NoDecoration );
|
||||
spinBox->setValue( 50 );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ void ProgressBarPage::populate()
|
|||
{
|
||||
auto* ring = new QskProgressRing( determinateRingsHBox );
|
||||
ring->setSize( size );
|
||||
ring->setLayoutAlignmentHint( Qt::AlignCenter );
|
||||
|
||||
QQuickItem* parentItem;
|
||||
|
||||
|
|
|
@ -6,11 +6,8 @@
|
|||
set(SOURCES
|
||||
Box.h Box.cpp
|
||||
BoxWithButtons.h BoxWithButtons.cpp
|
||||
CircularProgressBar.h CircularProgressBar.cpp
|
||||
CircularProgressBarSkinlet.h CircularProgressBarSkinlet.cpp
|
||||
Diagram.h Diagram.cpp
|
||||
DiagramSkinlet.h DiagramSkinlet.cpp
|
||||
EnergyMeter.h EnergyMeter.cpp
|
||||
GraphicProvider.h GraphicProvider.cpp
|
||||
GridBox.h GridBox.cpp
|
||||
LightDisplaySkinlet.h LightDisplaySkinlet.cpp
|
||||
|
@ -31,7 +28,7 @@ set(SOURCES
|
|||
UsageBox.h UsageBox.cpp
|
||||
UsageDiagram.h UsageDiagram.cpp
|
||||
StoragePage.h StoragePage.cpp
|
||||
StorageMeter.h StorageMeter.cpp
|
||||
ValueMeter.h ValueMeter.cpp
|
||||
StorageBar.h StorageBar.cpp
|
||||
StorageBarSkinlet.h StorageBarSkinlet.cpp
|
||||
nodes/DiagramDataNode.h nodes/DiagramDataNode.cpp
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2021 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "CircularProgressBar.h"
|
||||
|
||||
#include <QskAnimator.h>
|
||||
#include <QskFunctions.h>
|
||||
|
||||
QSK_SUBCONTROL( CircularProgressBar, Groove )
|
||||
QSK_SUBCONTROL( CircularProgressBar, Bar )
|
||||
|
||||
namespace
|
||||
{
|
||||
class PositionAnimator : public QskAnimator
|
||||
{
|
||||
public:
|
||||
PositionAnimator( CircularProgressBar* progressBar )
|
||||
: m_progressBar( progressBar )
|
||||
{
|
||||
setAutoRepeat( true );
|
||||
setDuration( 1300 );
|
||||
|
||||
setWindow( progressBar->window() );
|
||||
}
|
||||
|
||||
void advance( qreal value ) override
|
||||
{
|
||||
const auto aspect = CircularProgressBar::Bar | QskAspect::Position;
|
||||
|
||||
m_progressBar->setMetric( aspect, value );
|
||||
m_progressBar->update();
|
||||
}
|
||||
|
||||
private:
|
||||
CircularProgressBar* m_progressBar;
|
||||
};
|
||||
}
|
||||
|
||||
class CircularProgressBar::PrivateData
|
||||
{
|
||||
public:
|
||||
void updateIndeterminateAnimator( CircularProgressBar* progressBar )
|
||||
{
|
||||
if ( !isIndeterminate )
|
||||
{
|
||||
delete animator;
|
||||
animator = nullptr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( progressBar->window() && progressBar->isVisible() )
|
||||
{
|
||||
if ( animator == nullptr )
|
||||
animator = new PositionAnimator( progressBar );
|
||||
|
||||
animator->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( animator )
|
||||
animator->stop();
|
||||
}
|
||||
}
|
||||
|
||||
PositionAnimator* animator = nullptr;
|
||||
|
||||
qreal value = 0.0;
|
||||
qreal origin = 0.0;
|
||||
|
||||
bool hasOrigin = false;
|
||||
bool isIndeterminate = false;
|
||||
};
|
||||
|
||||
CircularProgressBar::~CircularProgressBar() = default;
|
||||
|
||||
CircularProgressBar::CircularProgressBar( qreal min, qreal max, QQuickItem* parent )
|
||||
: QskBoundedControl( min, max, parent )
|
||||
, m_data( new PrivateData )
|
||||
{
|
||||
m_data->value = minimum();
|
||||
|
||||
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::MinimumExpanding );
|
||||
|
||||
connect( this, &QskBoundedControl::boundariesChanged,
|
||||
this, &CircularProgressBar::adjustValue );
|
||||
}
|
||||
|
||||
CircularProgressBar::CircularProgressBar( QQuickItem* parent )
|
||||
: CircularProgressBar( 0.0, 100.0, parent )
|
||||
{
|
||||
}
|
||||
|
||||
bool CircularProgressBar::isIndeterminate() const
|
||||
{
|
||||
return m_data->isIndeterminate;
|
||||
}
|
||||
|
||||
void CircularProgressBar::setIndeterminate( bool on )
|
||||
{
|
||||
if ( on == m_data->isIndeterminate )
|
||||
return;
|
||||
|
||||
m_data->isIndeterminate = on;
|
||||
m_data->updateIndeterminateAnimator( this );
|
||||
|
||||
update();
|
||||
Q_EMIT indeterminateChanged( on );
|
||||
}
|
||||
|
||||
void CircularProgressBar::resetOrigin()
|
||||
{
|
||||
if ( m_data->hasOrigin )
|
||||
{
|
||||
m_data->hasOrigin = false;
|
||||
|
||||
update();
|
||||
Q_EMIT originChanged( origin() );
|
||||
}
|
||||
}
|
||||
|
||||
qreal CircularProgressBar::origin() const
|
||||
{
|
||||
if ( m_data->hasOrigin )
|
||||
{
|
||||
return boundedValue( m_data->origin );
|
||||
}
|
||||
|
||||
return minimum();
|
||||
}
|
||||
|
||||
qreal CircularProgressBar::value() const
|
||||
{
|
||||
return m_data->value;
|
||||
}
|
||||
|
||||
qreal CircularProgressBar::valueAsRatio() const
|
||||
{
|
||||
return QskBoundedControl::valueAsRatio( m_data->value );
|
||||
}
|
||||
|
||||
void CircularProgressBar::setValue( qreal value )
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
value = boundedValue( value );
|
||||
|
||||
setValueInternal( value );
|
||||
}
|
||||
|
||||
void CircularProgressBar::setValueAsRatio( qreal ratio )
|
||||
{
|
||||
ratio = qBound( 0.0, ratio, 1.0 );
|
||||
setValue( minimum() + ratio * boundaryLength() );
|
||||
}
|
||||
|
||||
void CircularProgressBar::setOrigin( qreal origin )
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
origin = boundedValue( origin );
|
||||
|
||||
if( !m_data->hasOrigin || !qskFuzzyCompare( m_data->origin, origin ) )
|
||||
{
|
||||
m_data->hasOrigin = true;
|
||||
m_data->origin = origin;
|
||||
|
||||
update();
|
||||
Q_EMIT originChanged( origin );
|
||||
}
|
||||
}
|
||||
|
||||
void CircularProgressBar::componentComplete()
|
||||
{
|
||||
Inherited::componentComplete();
|
||||
adjustValue();
|
||||
}
|
||||
|
||||
void CircularProgressBar::setValueInternal( qreal value )
|
||||
{
|
||||
if ( !qskFuzzyCompare( value, m_data->value ) )
|
||||
{
|
||||
m_data->value = value;
|
||||
|
||||
Q_EMIT valueChanged( value );
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void CircularProgressBar::adjustValue()
|
||||
{
|
||||
if ( isComponentComplete() )
|
||||
setValueInternal( boundedValue( m_data->value ) );
|
||||
}
|
||||
|
||||
#include "moc_CircularProgressBar.cpp"
|
|
@ -1,61 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2021 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskBoundedControl.h>
|
||||
|
||||
class CircularProgressBar : public QskBoundedControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( bool indeterminate READ isIndeterminate
|
||||
WRITE setIndeterminate NOTIFY indeterminateChanged )
|
||||
|
||||
Q_PROPERTY( qreal origin READ origin
|
||||
WRITE setOrigin RESET resetOrigin NOTIFY originChanged )
|
||||
|
||||
Q_PROPERTY( qreal value READ value WRITE setValue NOTIFY valueChanged )
|
||||
Q_PROPERTY( qreal valueAsRatio READ valueAsRatio
|
||||
WRITE setValueAsRatio NOTIFY valueChanged )
|
||||
|
||||
using Inherited = QskBoundedControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Groove, Bar )
|
||||
|
||||
CircularProgressBar( qreal min, qreal max, QQuickItem* parent = nullptr );
|
||||
CircularProgressBar( QQuickItem* parent = nullptr );
|
||||
~CircularProgressBar() override;
|
||||
|
||||
bool isIndeterminate() const;
|
||||
void setIndeterminate( bool on = true );
|
||||
|
||||
void resetOrigin();
|
||||
qreal origin() const;
|
||||
|
||||
qreal value() const;
|
||||
qreal valueAsRatio() const; // [0.0, 1.0]
|
||||
|
||||
public Q_SLOTS:
|
||||
void setValue( qreal );
|
||||
void setValueAsRatio( qreal );
|
||||
void setOrigin( qreal );
|
||||
|
||||
Q_SIGNALS:
|
||||
void indeterminateChanged( bool );
|
||||
void valueChanged( qreal );
|
||||
void originChanged( qreal );
|
||||
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
|
||||
private:
|
||||
void setValueInternal( qreal value );
|
||||
void adjustValue();
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2021 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "CircularProgressBarSkinlet.h"
|
||||
#include "CircularProgressBar.h"
|
||||
|
||||
CircularProgressBarSkinlet::CircularProgressBarSkinlet( QskSkin* skin )
|
||||
: QskSkinlet( skin )
|
||||
{
|
||||
setNodeRoles( { GrooveRole, BarRole } );
|
||||
}
|
||||
|
||||
CircularProgressBarSkinlet::~CircularProgressBarSkinlet()
|
||||
{
|
||||
}
|
||||
|
||||
QRectF CircularProgressBarSkinlet::subControlRect(
|
||||
const QskSkinnable*, const QRectF& contentsRect, QskAspect::Subcontrol ) const
|
||||
{
|
||||
return contentsRect;
|
||||
}
|
||||
|
||||
QSGNode* CircularProgressBarSkinlet::updateSubNode(
|
||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||
{
|
||||
switch( nodeRole )
|
||||
{
|
||||
case GrooveRole:
|
||||
{
|
||||
return updateArcNode( skinnable, node, CircularProgressBar::Groove );
|
||||
}
|
||||
case BarRole:
|
||||
{
|
||||
const auto bar = static_cast< const CircularProgressBar* >( skinnable );
|
||||
|
||||
const qreal startAngle = 90.0;
|
||||
const qreal spanAngle = 360.0 * bar->valueAsRatio();
|
||||
|
||||
return updateArcNode( skinnable, node, startAngle, -spanAngle,
|
||||
CircularProgressBar::Bar );
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
}
|
||||
|
||||
#include "moc_CircularProgressBarSkinlet.cpp"
|
|
@ -1,36 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2021 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskSkinlet.h>
|
||||
|
||||
class CircularProgressBar;
|
||||
|
||||
class CircularProgressBarSkinlet : public QskSkinlet
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
using Inherited = QskSkinlet;
|
||||
|
||||
public:
|
||||
enum NodeRole
|
||||
{
|
||||
GrooveRole,
|
||||
BarRole,
|
||||
|
||||
RoleCount,
|
||||
};
|
||||
|
||||
Q_INVOKABLE CircularProgressBarSkinlet( QskSkin* = nullptr );
|
||||
~CircularProgressBarSkinlet() override;
|
||||
|
||||
QRectF subControlRect( const QskSkinnable*,
|
||||
const QRectF&, QskAspect::Subcontrol ) const override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateSubNode( const QskSkinnable*,
|
||||
quint8 nodeRole, QSGNode* ) const override;
|
||||
};
|
|
@ -14,17 +14,6 @@
|
|||
#include "TopBar.h"
|
||||
#include "UsageBox.h"
|
||||
|
||||
#include <QskBoxBorderColors.h>
|
||||
#include <QskBoxBorderMetrics.h>
|
||||
#include <QskBoxShapeMetrics.h>
|
||||
#include <QskGridBox.h>
|
||||
#include <QskSetup.h>
|
||||
#include <QskSkin.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskQuick.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
QSK_SUBCONTROL( DashboardPage, Panel )
|
||||
|
||||
namespace
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2021 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "EnergyMeter.h"
|
||||
#include "CircularProgressBar.h"
|
||||
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskFontRole.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class ValueLabel : public QskTextLabel
|
||||
{
|
||||
public:
|
||||
ValueLabel( QQuickItem* parent )
|
||||
: QskTextLabel( parent )
|
||||
{
|
||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||
setLayoutAlignmentHint( Qt::AlignCenter );
|
||||
setFontRole( QskFontRole::Caption );
|
||||
}
|
||||
|
||||
void setValue( int value )
|
||||
{
|
||||
setText( locale().toString( value ) + " " + locale().percent() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
EnergyMeter::EnergyMeter( const QColor& textColor,
|
||||
const QskGradient& gradient, int value, QQuickItem* parent )
|
||||
: QskControl( parent )
|
||||
{
|
||||
setAutoLayoutChildren( true );
|
||||
|
||||
auto valueBar = new CircularProgressBar( this );
|
||||
valueBar->setGradientHint( CircularProgressBar::Bar, gradient );
|
||||
valueBar->setValue( value );
|
||||
|
||||
auto valueLabel = new ValueLabel( this );
|
||||
valueLabel->setTextColor( textColor );
|
||||
valueLabel->setValue( value );
|
||||
}
|
||||
|
||||
QSizeF EnergyMeter::contentsSizeHint(
|
||||
Qt::SizeHint which, const QSizeF& constraint ) const
|
||||
{
|
||||
if ( which != Qt::PreferredSize )
|
||||
return QSizeF();
|
||||
|
||||
qreal size;
|
||||
|
||||
if ( constraint.width() > 0 )
|
||||
{
|
||||
size = constraint.width();
|
||||
}
|
||||
else if ( constraint.height() > 0 )
|
||||
{
|
||||
size = constraint.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 57;
|
||||
}
|
||||
|
||||
return QSizeF( size, size );
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2021 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskControl.h>
|
||||
|
||||
class EnergyMeter : public QskControl
|
||||
{
|
||||
public:
|
||||
EnergyMeter( const QColor&, const QskGradient&,
|
||||
int progress, QQuickItem* parent = nullptr );
|
||||
|
||||
protected:
|
||||
QSizeF contentsSizeHint( Qt::SizeHint, const QSizeF& ) const override;
|
||||
};
|
|
@ -51,17 +51,6 @@ bool LightDisplay::isPressed() const
|
|||
return hasSkinState( Pressed );
|
||||
}
|
||||
|
||||
void LightDisplay::setGradient( const QskGradient& gradient )
|
||||
{
|
||||
m_gradient = gradient;
|
||||
update();
|
||||
}
|
||||
|
||||
const QskGradient& LightDisplay::gradient() const
|
||||
{
|
||||
return m_gradient;
|
||||
}
|
||||
|
||||
void LightDisplay::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
QRectF handleRect = subControlRect( LightDisplay::Knob );
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <QskBoundedValueInput.h>
|
||||
#include <QskBoxShapeMetrics.h>
|
||||
#include <QskShadowMetrics.h>
|
||||
|
||||
class LightDisplay : public QskBoundedValueInput
|
||||
|
@ -22,9 +21,6 @@ class LightDisplay : public QskBoundedValueInput
|
|||
|
||||
bool isPressed() const;
|
||||
|
||||
void setGradient( const QskGradient& );
|
||||
const QskGradient& gradient() const;
|
||||
|
||||
protected:
|
||||
void mousePressEvent( QMouseEvent* e ) override;
|
||||
void mouseMoveEvent( QMouseEvent* e ) override;
|
||||
|
@ -33,9 +29,4 @@ class LightDisplay : public QskBoundedValueInput
|
|||
private:
|
||||
qreal angleFromPoint( const QRectF&, const QPointF& ) const;
|
||||
bool arcContainsPoint( const QRectF&, const QPointF& ) const;
|
||||
|
||||
QskShadowMetrics m_shadow;
|
||||
QColor m_shadowColor = Qt::black;
|
||||
|
||||
QskGradient m_gradient;
|
||||
};
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include "Box.h"
|
||||
#include "BoxWithButtons.h"
|
||||
#include "CircularProgressBar.h"
|
||||
#include "CircularProgressBarSkinlet.h"
|
||||
#include "DashboardPage.h"
|
||||
#include "Diagram.h"
|
||||
#include "DiagramSkinlet.h"
|
||||
|
@ -21,7 +19,6 @@
|
|||
#include "RoundedIcon.h"
|
||||
#include "StorageBar.h"
|
||||
#include "StorageBarSkinlet.h"
|
||||
#include "StorageMeter.h"
|
||||
#include "StoragePage.h"
|
||||
#include "TopBar.h"
|
||||
#include "UsageBox.h"
|
||||
|
@ -37,6 +34,7 @@
|
|||
#include <QskSkinHintTableEditor.h>
|
||||
#include <QskStateCombination.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskProgressRing.h>
|
||||
#include <QskGraphicLabel.h>
|
||||
#include <QskFontRole.h>
|
||||
|
||||
|
@ -56,7 +54,6 @@ Skin::Skin( QObject* parent )
|
|||
{
|
||||
setObjectName( "iot" );
|
||||
|
||||
declareSkinlet< CircularProgressBar, CircularProgressBarSkinlet >();
|
||||
declareSkinlet< Diagram, DiagramSkinlet >();
|
||||
declareSkinlet< LightDisplay, LightDisplaySkinlet >();
|
||||
declareSkinlet< StorageBar, StorageBarSkinlet >();
|
||||
|
@ -87,9 +84,9 @@ void Skin::initHints()
|
|||
|
||||
ed.setPadding( MainContentGridBox::Panel, { 19, 0, 27, 24 } );
|
||||
|
||||
// menu bar:
|
||||
|
||||
{
|
||||
// menu bar:
|
||||
|
||||
using Q = QskPushButton;
|
||||
using A = QskAspect;
|
||||
|
||||
|
@ -113,25 +110,27 @@ void Skin::initHints()
|
|||
ed.setAlignment( Q::Icon | A::Header, Qt::AlignCenter );
|
||||
}
|
||||
|
||||
// top bar:
|
||||
ed.setPadding( TopBar::Panel, { 25, 35, 25, 0 } );
|
||||
{
|
||||
// top bar:
|
||||
|
||||
ed.setColor( TopBarItem::Item1 | QskAspect::TextColor, 0xffff3122 );
|
||||
ed.setColor( TopBarItem::Item2 | QskAspect::TextColor, 0xff6776ff );
|
||||
ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, 0xfff99055 );
|
||||
ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, 0xff6776ff );
|
||||
ed.setPadding( TopBar::Panel, { 25, 35, 25, 0 } );
|
||||
|
||||
// arcs are counterclockwise, so specify the 2nd color first:
|
||||
ed.setGradient( TopBarItem::Item1, 0xffff3122, 0xffff5c00 );
|
||||
ed.setGradient( TopBarItem::Item2, 0xff6100ff, 0xff6776ff );
|
||||
ed.setGradient( TopBarItem::Item3, 0xffff3122, 0xffffce50 );
|
||||
ed.setGradient( TopBarItem::Item4, 0xff6100ff, 0xff6776ff );
|
||||
ed.setColor( TopBarItem::Item1 | QskAspect::TextColor, 0xffff3122 );
|
||||
ed.setColor( TopBarItem::Item2 | QskAspect::TextColor, 0xff6776ff );
|
||||
ed.setColor( TopBarItem::Item3 | QskAspect::TextColor, 0xfff99055 );
|
||||
ed.setColor( TopBarItem::Item4 | QskAspect::TextColor, 0xff6776ff );
|
||||
|
||||
ed.setGradient( TopBarItem::Item1, 0xffff5c00, 0xffff3122 );
|
||||
ed.setGradient( TopBarItem::Item2, 0xff6776ff, 0xff6100ff );
|
||||
ed.setGradient( TopBarItem::Item3, 0xffffce50, 0xffff3122 );
|
||||
ed.setGradient( TopBarItem::Item4, 0xff6776ff, 0xff6100ff );
|
||||
}
|
||||
|
||||
// the bar gradient is defined through the top bar items above
|
||||
ed.setArcMetrics( CircularProgressBar::Groove, 90, -360, 8.53 );
|
||||
ed.setArcMetrics( QskProgressRing::Groove, 90, -360, 8.53 );
|
||||
// the span angle will be set in the progress bar, we just give a dummy
|
||||
// value here:
|
||||
ed.setArcMetrics( CircularProgressBar::Bar, 90, -180, 8.53 );
|
||||
ed.setArcMetrics( QskProgressRing::Fill, ed.arcMetrics( QskProgressRing::Groove ) );
|
||||
|
||||
ed.setFontRole( TimeTitleLabel::Text, { QskFontRole::Caption, QskFontRole::High } );
|
||||
|
||||
|
@ -283,8 +282,8 @@ void Skin::initHints()
|
|||
ed.setColor( QskTextLabel::Text, palette.text );
|
||||
ed.setColor( UsageDiagramBox::DayText, palette.text );
|
||||
|
||||
ed.setMetric( CircularProgressBar::Groove | QskAspect::Border, 2 );
|
||||
ed.setColor( CircularProgressBar::Groove | QskAspect::Border,
|
||||
ed.setMetric( QskProgressRing::Groove | QskAspect::Border, 2 );
|
||||
ed.setColor( QskProgressRing::Groove | QskAspect::Border,
|
||||
palette.circularProgressBarGroove );
|
||||
|
||||
// storage bar
|
||||
|
@ -302,9 +301,13 @@ void Skin::initHints()
|
|||
|
||||
// storage meter
|
||||
{
|
||||
ed.setGradient( StorageMeter::Status,
|
||||
{ { { 0.00, "#00ff00" }, { 0.33, "#00ff00" }, { 0.33, "#ffaf00" }, { 0.66, "#ffaf00" },
|
||||
{ 0.66, "#ff0000" }, { 1.00, "#ff0000" } } } );
|
||||
ed.setGradient( StoragePage::Status,
|
||||
{ {
|
||||
{ 0.00, "#00ff00" }, { 0.33, "#00ff00" },
|
||||
{ 0.33, "#ffaf00" }, { 0.66, "#ffaf00" },
|
||||
{ 0.66, "#ff0000" }, { 1.00, "#ff0000" }
|
||||
} }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +325,7 @@ Skin::Palette Skin::palette( QskSkin::ColorScheme colorScheme ) const
|
|||
Qt::white,
|
||||
0xff4a4a4a,
|
||||
0xff555555,
|
||||
{ { { 0.0, 0xff991100 }, { 0.2, 0xff9a7a57 }, { 0.5, 0xff3726af }, { 1.0, Qt::black } } },
|
||||
{ { { 0.0, 0xff991100 }, { 0.4, 0xff9a7a57 }, { 1.0, 0xff3726af } } },
|
||||
0x10ffffff,
|
||||
0xff222222
|
||||
};
|
||||
|
@ -339,8 +342,7 @@ Skin::Palette Skin::palette( QskSkin::ColorScheme colorScheme ) const
|
|||
Qt::black,
|
||||
0xffe5e5e5,
|
||||
0xffc4c4c4,
|
||||
{ { { 0.0, 0xffff3122 }, { 0.2, 0xfffeeeb7 }, { 0.3, 0xffa7b0ff }, { 0.5, 0xff6776ff },
|
||||
{ 1.0, Qt::black } } },
|
||||
{ { { 0.0, 0xffff3122 }, { 0.4, 0xfffeeeb7 }, { 0.6, 0xffa7b0ff }, { 1.0, 0xff6776ff } } },
|
||||
0x10000000,
|
||||
0xffdddddd
|
||||
};
|
||||
|
|
|
@ -34,5 +34,4 @@ class Skin : public QskSkin
|
|||
void initHints() override;
|
||||
|
||||
Palette palette( ColorScheme ) const;
|
||||
void initHints( const Palette& );
|
||||
};
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2022 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "StorageMeter.h"
|
||||
#include "CircularProgressBar.h"
|
||||
#include <QskFontRole.h>
|
||||
#include <QskTextLabel.h>
|
||||
|
||||
QSK_SUBCONTROL( StorageMeter, Status )
|
||||
|
||||
namespace
|
||||
{
|
||||
inline QString make_text( const QLocale& locale, const qreal value )
|
||||
{
|
||||
return locale.toString( static_cast< int >( value ) ) + " " + locale.percent();
|
||||
}
|
||||
}
|
||||
|
||||
StorageMeter::StorageMeter( QQuickItem* parent ) noexcept
|
||||
: CircularProgressBar( parent )
|
||||
, label( new QskTextLabel( this ) )
|
||||
{
|
||||
setAutoLayoutChildren( true );
|
||||
setSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Constrained );
|
||||
|
||||
label->setText( make_text( locale(), value() ) );
|
||||
label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||
label->setLayoutAlignmentHint( Qt::AlignCenter );
|
||||
label->setFontRole( QskFontRole::Caption );
|
||||
}
|
||||
|
||||
void StorageMeter::setValue( const qreal value )
|
||||
{
|
||||
const auto gradient = gradientHint( StorageMeter::Status );
|
||||
const auto color = gradient.extracted( value / 100.0, value / 100.0 ).startColor();
|
||||
setGradientHint( StorageMeter::Bar, { color, color.lighter() } );
|
||||
CircularProgressBar::setValue( value );
|
||||
label->setTextColor( color );
|
||||
label->setText( make_text( locale(), value ) );
|
||||
}
|
||||
|
||||
QSizeF StorageMeter::contentsSizeHint( Qt::SizeHint which, const QSizeF& constraint ) const
|
||||
{
|
||||
if ( which != Qt::PreferredSize )
|
||||
return QSizeF();
|
||||
|
||||
qreal size;
|
||||
|
||||
if ( constraint.width() > 0 )
|
||||
{
|
||||
size = constraint.width();
|
||||
}
|
||||
else if ( constraint.height() > 0 )
|
||||
{
|
||||
size = constraint.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 57;
|
||||
}
|
||||
|
||||
return QSizeF( size, size );
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2022 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CircularProgressBar.h"
|
||||
#include <QskControl.h>
|
||||
|
||||
class StorageMeter final : public CircularProgressBar
|
||||
{
|
||||
public:
|
||||
QSK_SUBCONTROLS( Status )
|
||||
explicit StorageMeter( QQuickItem* parent = nullptr ) noexcept;
|
||||
public Q_SLOTS:
|
||||
void setValue( qreal value );
|
||||
|
||||
private:
|
||||
QSizeF contentsSizeHint( Qt::SizeHint which, const QSizeF& constraint ) const override;
|
||||
class QskTextLabel* label = nullptr;
|
||||
};
|
|
@ -6,7 +6,7 @@
|
|||
#include "StoragePage.h"
|
||||
#include "Box.h"
|
||||
#include "StorageBar.h"
|
||||
#include "StorageMeter.h"
|
||||
#include "ValueMeter.h"
|
||||
#include <QTimer>
|
||||
#include <QskAnimator.h>
|
||||
#include <QskBox.h>
|
||||
|
@ -20,6 +20,60 @@
|
|||
#include <QskTextLabel.h>
|
||||
|
||||
QSK_SUBCONTROL( StoragePage, Panel )
|
||||
QSK_SUBCONTROL( StoragePage, Status )
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Storage
|
||||
{
|
||||
struct Media
|
||||
{
|
||||
qreal pictures = 0;
|
||||
qreal music = 0;
|
||||
qreal videos = 0;
|
||||
qreal documents = 0;
|
||||
qreal others = 0;
|
||||
|
||||
inline constexpr bool operator==( const Media& rhs ) const noexcept
|
||||
{
|
||||
return pictures == rhs.pictures && music == rhs.music && videos == rhs.videos &&
|
||||
documents == rhs.documents && others == rhs.others;
|
||||
}
|
||||
|
||||
inline constexpr qreal free() const noexcept
|
||||
{
|
||||
return 1.0 - pictures - music - videos - documents - others;
|
||||
}
|
||||
};
|
||||
|
||||
QString title;
|
||||
QString description;
|
||||
Media distribution;
|
||||
};
|
||||
|
||||
class StorageMeter final : public ValueMeter
|
||||
{
|
||||
public:
|
||||
StorageMeter( QQuickItem* parent = nullptr )
|
||||
: ValueMeter( parent )
|
||||
{
|
||||
setFixedSize( 64, 64 );
|
||||
|
||||
connect( this, &ValueMeter::valueChanged,
|
||||
this, &StorageMeter::setStatusColor );
|
||||
}
|
||||
|
||||
private:
|
||||
void setStatusColor( qreal value )
|
||||
{
|
||||
const auto color = qskInterpolatedColorAt(
|
||||
gradientHint( StoragePage::Status ).stops(), value / 100.0 );
|
||||
|
||||
setFillGradient( { color, color.lighter() } );
|
||||
setTextColor( color );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct StorageRowAnimator final : public QObject, public QskAnimator
|
||||
{
|
||||
|
@ -85,8 +139,6 @@ void StoragePage::addRow( const QString& title, const QString& description,
|
|||
const auto percent = 100.0 * ( 1.0 - storage.distribution.free() );
|
||||
auto* const meter = new StorageMeter( left );
|
||||
meter->setValue( percent );
|
||||
meter->setMinimumSize( 64, 64 );
|
||||
meter->setMaximumSize( 64, 64 );
|
||||
|
||||
auto* const maintitle = new QskTextLabel( storage.title, center );
|
||||
maintitle->setFontRole( QskFontRole::Headline );
|
||||
|
@ -136,5 +188,6 @@ void StoragePage::addRow( const QString& title, const QString& description,
|
|||
bar->setDocuments( media.documents * v );
|
||||
bar->setOthers( media.others * v );
|
||||
};
|
||||
connect( sync, &QskPushButton::clicked, animator, [ animator ]() { animator->start(); } );
|
||||
connect( sync, &QskPushButton::clicked,
|
||||
animator, [ animator ]() { animator->start(); } );
|
||||
}
|
||||
|
|
|
@ -7,44 +7,15 @@
|
|||
|
||||
#include <QVector>
|
||||
#include <QskLinearBox.h>
|
||||
#include <memory>
|
||||
|
||||
class QQuickItem;
|
||||
|
||||
class StoragePage final : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel )
|
||||
explicit StoragePage( QQuickItem* parent = nullptr );
|
||||
QSK_SUBCONTROLS( Panel, Status )
|
||||
|
||||
StoragePage( QQuickItem* parent = nullptr );
|
||||
|
||||
private:
|
||||
struct Storage
|
||||
{
|
||||
struct Media
|
||||
{
|
||||
qreal pictures = 0;
|
||||
qreal music = 0;
|
||||
qreal videos = 0;
|
||||
qreal documents = 0;
|
||||
qreal others = 0;
|
||||
|
||||
inline constexpr bool operator==( const Media& rhs ) const noexcept
|
||||
{
|
||||
return pictures == rhs.pictures && music == rhs.music && videos == rhs.videos &&
|
||||
documents == rhs.documents && others == rhs.others;
|
||||
}
|
||||
|
||||
inline constexpr qreal free() const noexcept
|
||||
{
|
||||
return 1.0 - pictures - music - videos - documents - others;
|
||||
}
|
||||
};
|
||||
|
||||
QString title;
|
||||
QString description;
|
||||
Media distribution;
|
||||
};
|
||||
|
||||
void addRow( const QString& title, const QString& description,
|
||||
qreal pictures, qreal music, qreal videos, qreal documents, qreal others );
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "TopBar.h"
|
||||
#include "EnergyMeter.h"
|
||||
#include "ValueMeter.h"
|
||||
|
||||
#include <QskFontRole.h>
|
||||
#include <QskTextLabel.h>
|
||||
|
@ -41,6 +41,22 @@ namespace
|
|||
return TopBarItem::Item4;
|
||||
}
|
||||
}
|
||||
|
||||
class EnergyMeter : public ValueMeter
|
||||
{
|
||||
public:
|
||||
EnergyMeter( const QColor& textColor,
|
||||
const QskGradient& gradient, int value, QQuickItem* parent )
|
||||
: ValueMeter( parent )
|
||||
{
|
||||
setFillGradient( gradient );
|
||||
setValue( value );
|
||||
setTextColor( textColor );
|
||||
|
||||
setFixedSize( 57, 57 );
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
TopBarItem::TopBarItem(
|
||||
|
@ -62,9 +78,7 @@ TopBarItem::TopBarItem(
|
|||
const auto subcontrol = subcontrolForIndex( index );
|
||||
const auto textColor = color( subcontrol | QskAspect::TextColor );
|
||||
|
||||
auto pieChart = new EnergyMeter(
|
||||
textColor, gradient, progress, pieChartAndDisplay );
|
||||
pieChart->setSizePolicy( Qt::Horizontal, QskSizePolicy::Constrained );
|
||||
(void) new EnergyMeter( textColor, gradient, progress, pieChartAndDisplay );
|
||||
|
||||
auto display = new QskLinearBox( Qt::Vertical, pieChartAndDisplay );
|
||||
display->setSpacing( 0 );
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2022 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ValueMeter.h"
|
||||
|
||||
#include <QskFontRole.h>
|
||||
#include <QskTextLabel.h>
|
||||
|
||||
ValueMeter::ValueMeter( QQuickItem* parent )
|
||||
: QskProgressRing( parent )
|
||||
{
|
||||
setAutoLayoutChildren( true );
|
||||
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Constrained );
|
||||
|
||||
m_label = new QskTextLabel( this );
|
||||
m_label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||
m_label->setLayoutAlignmentHint( Qt::AlignCenter );
|
||||
m_label->setFontRole( QskFontRole::Caption );
|
||||
|
||||
connect( this, &QskProgressRing::valueChanged,
|
||||
this, &ValueMeter::updateMeter );
|
||||
|
||||
updateMeter( value() );
|
||||
}
|
||||
|
||||
void ValueMeter::updateMeter( const qreal value )
|
||||
{
|
||||
m_label->setText( text( value ) );
|
||||
}
|
||||
|
||||
QString ValueMeter::text( qreal value ) const
|
||||
{
|
||||
value = static_cast< int >( value );
|
||||
return locale().toString( value ) + ' ' + locale().percent();
|
||||
}
|
||||
|
||||
void ValueMeter::setTextColor( const QColor& color )
|
||||
{
|
||||
m_label->setTextColor( color );
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2022 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QskProgressRing.h>
|
||||
|
||||
class QskTextLabel;
|
||||
|
||||
class ValueMeter : public QskProgressRing
|
||||
{
|
||||
public:
|
||||
ValueMeter( QQuickItem* parent = nullptr );
|
||||
|
||||
void setTextColor( const QColor& );
|
||||
|
||||
protected:
|
||||
virtual QString text( qreal ) const;
|
||||
|
||||
private:
|
||||
void updateMeter( qreal value );
|
||||
QskTextLabel* m_label = nullptr;
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage $0 file ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in $*
|
||||
do
|
||||
base=`basename -s .svg $file`
|
||||
echo "${base}.svg -> qvg/${base}.qvg"
|
||||
svg2qvg ${base}.svg qvg/${base}.qvg
|
||||
done
|
||||
|
||||
exit $status
|
|
@ -28,7 +28,6 @@ int main( int argc, char* argv[] )
|
|||
|
||||
QGuiApplication app( argc, argv );
|
||||
|
||||
QskSetup::setUpdateFlag( QskItem::PreferRasterForTextures, true );
|
||||
qskSkinManager->setSkin( new Skin() );
|
||||
|
||||
Qsk::addGraphicProvider( QString(), new GraphicProvider() );
|
||||
|
|
|
@ -139,8 +139,6 @@ int main( int argc, char* argv[] )
|
|||
qskSkinManager->registerFactory(
|
||||
QStringLiteral( "MySkinFactory" ), new MySkinFactory() );
|
||||
|
||||
QskSetup::setUpdateFlag( QskItem::PreferRasterForTextures, true );
|
||||
|
||||
Window window;
|
||||
window.resize( 480, 360 );
|
||||
window.show();
|
||||
|
|
|
@ -9,153 +9,10 @@
|
|||
|
||||
#include <QskIntervalF.h>
|
||||
#include <QskArcMetrics.h>
|
||||
#include <QskArcNode.h>
|
||||
#include <QskArcRenderNode.h>
|
||||
|
||||
#include <qpainterpath.h>
|
||||
#include <qmath.h>
|
||||
|
||||
#define PAINTED_NODE 0
|
||||
|
||||
#if PAINTED_NODE
|
||||
|
||||
/*
|
||||
This is a fallback implementation for a user who is using an outdated
|
||||
version of QSkinny where only shaders for linear gradients are available.
|
||||
*/
|
||||
#include <QskPaintedNode.h>
|
||||
#include <qpainter.h>
|
||||
#include <qpainterpath.h>
|
||||
#include <qpen.h>
|
||||
#include <qbrush.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
QConicalGradient qskQConicalGradient(
|
||||
const QskGradientStops& stops, qreal startAngle, qreal spanAngle )
|
||||
{
|
||||
QskGradientStops scaledStops;
|
||||
scaledStops.reserve( stops.size() );
|
||||
|
||||
const auto ratio = qAbs( spanAngle ) / 360.0;
|
||||
|
||||
if ( spanAngle > 0.0 )
|
||||
{
|
||||
for ( auto it = stops.cbegin(); it != stops.cend(); ++it )
|
||||
scaledStops += { ratio * it->position(), it->color() };
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( auto it = stops.crbegin(); it != stops.crend(); ++it )
|
||||
scaledStops += { 1.0 - ratio * it->position(), it->color() };
|
||||
}
|
||||
|
||||
QConicalGradient qGradient( QPointF(), startAngle );
|
||||
qGradient.setStops( qskToQGradientStops( scaledStops ) );
|
||||
|
||||
return qGradient;
|
||||
}
|
||||
|
||||
class PaintedArcNode : public QskPaintedNode
|
||||
{
|
||||
public:
|
||||
void setArcData( const QRectF&, const QskArcMetrics&,
|
||||
qreal, const QColor&, const QskGradient&, QQuickWindow* );
|
||||
|
||||
protected:
|
||||
void paint( QPainter*, const QSize&, const void* nodeData ) override;
|
||||
QskHashValue hash( const void* nodeData ) const override;
|
||||
|
||||
private:
|
||||
QskHashValue arcHash( const QRectF&, const QskArcMetrics&,
|
||||
qreal, const QColor&, const QskGradient& ) const;
|
||||
|
||||
QBrush fillBrush( const QskGradient&, const QRectF&, qreal, qreal ) const;
|
||||
|
||||
struct ArcData
|
||||
{
|
||||
QPointF translation;
|
||||
QPen pen;
|
||||
QBrush brush;
|
||||
QPainterPath path;
|
||||
|
||||
QskHashValue hash;
|
||||
};
|
||||
};
|
||||
|
||||
void PaintedArcNode::setArcData(
|
||||
const QRectF& rect, const QskArcMetrics& metrics,
|
||||
qreal borderWidth, const QColor& borderColor,
|
||||
const QskGradient& gradient, QQuickWindow* window )
|
||||
{
|
||||
const auto hash = arcHash( rect, metrics, borderWidth, borderColor, gradient );
|
||||
|
||||
const auto brush = fillBrush( gradient, rect,
|
||||
metrics.startAngle(), metrics.spanAngle() );
|
||||
|
||||
QPen pen( borderColor, borderWidth );
|
||||
if ( borderWidth <= 0.0 )
|
||||
pen.setStyle( Qt::NoPen );
|
||||
|
||||
const auto path = metrics.painterPath( rect );
|
||||
const auto r = path.controlPointRect();
|
||||
|
||||
const ArcData arcData { r.topLeft(), pen, brush, path, hash };
|
||||
update( window, r, QSizeF(), &arcData );
|
||||
}
|
||||
|
||||
void PaintedArcNode::paint( QPainter* painter, const QSize&, const void* nodeData )
|
||||
{
|
||||
const auto arcData = reinterpret_cast< const ArcData* >( nodeData );
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing, true );
|
||||
painter->translate( -arcData->translation );
|
||||
painter->setPen( arcData->pen );
|
||||
painter->setBrush( arcData->brush );
|
||||
painter->drawPath( arcData->path );
|
||||
}
|
||||
|
||||
QskHashValue PaintedArcNode::hash( const void* nodeData ) const
|
||||
{
|
||||
const auto arcData = reinterpret_cast< const ArcData* >( nodeData );
|
||||
return arcData->hash;
|
||||
}
|
||||
|
||||
QBrush PaintedArcNode::fillBrush( const QskGradient& gradient,
|
||||
const QRectF& rect, qreal startAngle, qreal spanAngle ) const
|
||||
{
|
||||
const auto qGradient = qskQConicalGradient(
|
||||
gradient.stops(), startAngle, spanAngle );
|
||||
|
||||
const qreal sz = qMax( rect.width(), rect.height() );
|
||||
const qreal sx = rect.width() / sz;
|
||||
const qreal sy = rect.height() / sz;
|
||||
|
||||
QTransform t;
|
||||
t.scale( sx, sy );
|
||||
t.translate( rect.center().x() / sx, rect.center().y() / sy );
|
||||
|
||||
QBrush brush( qGradient );
|
||||
brush.setTransform( t );
|
||||
|
||||
return brush;
|
||||
}
|
||||
|
||||
inline QskHashValue PaintedArcNode::arcHash(
|
||||
const QRectF& rect, const QskArcMetrics& metrics, qreal borderWidth,
|
||||
const QColor& borderColor, const QskGradient& gradient ) const
|
||||
{
|
||||
auto hash = metrics.hash( 6753 );
|
||||
hash = qHashBits( &rect, sizeof( rect ), hash );
|
||||
hash = qHash( borderWidth, hash );
|
||||
hash = qHash( borderColor.rgba(), hash );
|
||||
hash = gradient.hash( hash );
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAINTED_NODE
|
||||
|
||||
namespace
|
||||
{
|
||||
inline QskArcMetrics segmentMetrics(
|
||||
|
@ -334,39 +191,16 @@ QSGNode* CircularChartSkinlet::updateSampleNode( const QskSkinnable* skinnable,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
QSGNode* CircularChartSkinlet::updateArcSegmentNode(
|
||||
const QskSkinnable* skinnable,
|
||||
QSGNode* CircularChartSkinlet::updateArcSegmentNode( const QskSkinnable*,
|
||||
QSGNode* node, qreal borderWidth, const QColor& borderColor,
|
||||
const QskGradient& gradient, const QskArcMetrics& metrics ) const
|
||||
{
|
||||
#if PAINTED_NODE
|
||||
auto arcNode = static_cast< PaintedArcNode* >( node );
|
||||
auto arcNode = static_cast< QskArcRenderNode* >( node );
|
||||
if ( arcNode == nullptr )
|
||||
arcNode = new PaintedArcNode();
|
||||
arcNode = new QskArcRenderNode();
|
||||
|
||||
const auto chart = static_cast< const CircularChart* >( skinnable );
|
||||
|
||||
arcNode->setArcData( m_data->closedArcRect, metrics,
|
||||
borderWidth, borderColor, gradient, chart->window() );
|
||||
#else
|
||||
Q_UNUSED( skinnable )
|
||||
|
||||
auto fillGradient = gradient;
|
||||
|
||||
if ( fillGradient.type() == QskGradient::Stops )
|
||||
{
|
||||
fillGradient.setStretchMode( QskGradient::StretchToSize );
|
||||
fillGradient.setConicDirection( 0.5, 0.5,
|
||||
metrics.startAngle(), metrics.spanAngle() );
|
||||
}
|
||||
|
||||
auto arcNode = static_cast< QskArcNode* >( node );
|
||||
if ( arcNode == nullptr )
|
||||
arcNode = new QskArcNode();
|
||||
|
||||
arcNode->setArcData( m_data->closedArcRect, metrics,
|
||||
borderWidth, borderColor, fillGradient );
|
||||
#endif
|
||||
arcNode->updateNode( m_data->closedArcRect, metrics, true,
|
||||
borderWidth, borderColor, gradient );
|
||||
|
||||
return arcNode;
|
||||
}
|
||||
|
|
|
@ -73,32 +73,36 @@ namespace
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Arc : public ShadowedArc
|
||||
{
|
||||
public:
|
||||
Arc()
|
||||
{
|
||||
setStartAngle( 45.0 );
|
||||
setSpanAngle( 270.0 );
|
||||
setThickness( 10.0 );
|
||||
|
||||
setFillGradient( Qt::darkRed );
|
||||
|
||||
setBorderWidth( 0 );
|
||||
setBorderColor( Qt::darkYellow );
|
||||
|
||||
setShadowColor( Qt::black );
|
||||
setSpreadRadius( 0.0 );
|
||||
setBlurRadius( 4.0 );
|
||||
setOffsetX( 2.0 );
|
||||
setOffsetY( 2.0 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ArcPage::ArcPage( QQuickItem* parent )
|
||||
: QskLinearBox( Qt::Vertical, parent )
|
||||
{
|
||||
auto arc = new ShadowedArc();
|
||||
auto arc = new Arc();
|
||||
arc->setMargins( 40 ); // some extra space for testing the offsets
|
||||
|
||||
{
|
||||
// initial settings
|
||||
arc->setStartAngle( 45.0 );
|
||||
arc->setSpanAngle( 270.0 );
|
||||
arc->setThickness( 10.0 );
|
||||
|
||||
arc->setFillColor( Qt::darkRed );
|
||||
|
||||
arc->setBorderWidth( 0 );
|
||||
arc->setBorderColor( Qt::darkYellow );
|
||||
|
||||
arc->setShadowColor( Qt::black );
|
||||
arc->setSpreadRadius( 0.0 );
|
||||
arc->setBlurRadius( 4.0 );
|
||||
arc->setOffsetX( 2.0 );
|
||||
arc->setOffsetY( 2.0 );
|
||||
}
|
||||
|
||||
auto panel = new ControlPanel( arc );
|
||||
panel->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ ShadowedArc::ShadowedArc( QQuickItem* parent )
|
|||
|
||||
setArcMetrics( { 0.0, 360.0, 1.0, Qt::RelativeSize } );
|
||||
|
||||
setFillColor( Qt::darkRed );
|
||||
setFillGradient( Qt::darkRed );
|
||||
|
||||
setBorderWidth( 0 );
|
||||
setBorderColor( Qt::gray );
|
||||
|
@ -216,14 +216,14 @@ qreal ShadowedArc::blurRadius() const
|
|||
return shadowMetrics().blurRadius();
|
||||
}
|
||||
|
||||
void ShadowedArc::setFillColor( const QColor& color )
|
||||
void ShadowedArc::setFillGradient( const QskGradient& gradient )
|
||||
{
|
||||
setColor( Arc, color );
|
||||
setGradientHint( Arc, gradient );
|
||||
}
|
||||
|
||||
QColor ShadowedArc::fillColor() const
|
||||
QskGradient ShadowedArc::fillGradient() const
|
||||
{
|
||||
return color( Arc );
|
||||
return gradientHint( Arc );
|
||||
}
|
||||
|
||||
void ShadowedArc::setShadowColor( const QColor& color )
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
class QskShadowMetrics;
|
||||
class QskArcMetrics;
|
||||
class QskGradient;
|
||||
|
||||
class ShadowedArc : public QskControl
|
||||
{
|
||||
|
@ -35,7 +36,7 @@ class ShadowedArc : public QskControl
|
|||
qreal blurRadius() const;
|
||||
|
||||
QColor borderColor() const;
|
||||
QColor fillColor() const;
|
||||
QskGradient fillGradient() const;
|
||||
QColor shadowColor() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
@ -52,7 +53,7 @@ class ShadowedArc : public QskControl
|
|||
void setBlurRadius( qreal );
|
||||
|
||||
void setBorderColor( const QColor& );
|
||||
void setFillColor( const QColor& );
|
||||
void setFillGradient( const QskGradient& );
|
||||
void setShadowColor( const QColor& );
|
||||
|
||||
private:
|
||||
|
|