diff --git a/examples/hmi-demo/DefaultSkin.cpp b/examples/hmi-demo/DefaultSkin.cpp index e8d93241..86c1a5e1 100644 --- a/examples/hmi-demo/DefaultSkin.cpp +++ b/examples/hmi-demo/DefaultSkin.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -21,7 +22,8 @@ protected: } }; -class Palette { +class Palette +{ public: Palette( DefaultSkin::Scheme scheme = DefaultSkin::Daylight ) @@ -65,8 +67,8 @@ namespace { } -DefaultSkin::DefaultSkin( const QString& name, QObject* parent ) : - QskSkin( parent ), +DefaultSkin::DefaultSkin( const QString& name, QObject* parent ): + QskSkin( parent ), m_name( name ), m_palette( new Palette ), m_scheme( Daylight ) @@ -82,11 +84,26 @@ void DefaultSkin::initHints() setColor( QskTextLabel::Text, m_palette->color4 ); - setColor( FilledRectangle::Panel, m_palette->color3 ); + setColor( SoundControl::CrossHair, m_palette->color3 ); + setColor( SoundControl::Marker, m_palette->color5 ); + // a circle + setMetric( SoundControl::Marker | QskAspect::Radius, 100 ); + setSkinHint( SoundControl::Marker + | QskAspect::Radius | QskAspect::AllCorners + | QskAspect::SizeMode, Qt::RelativeSize ); + + setColor( QskSeparator::Panel, m_palette->color3 ); + setMetric( QskSeparator::Panel, 2 ); + + setMetric( QskPushButton::Panel | QskAspect::Padding, 10 ); setColor( QskPushButton::Panel, m_palette->color1 ); setColor( QskPushButton::Text, m_palette->color3 ); setColor( QskPushButton::Panel | QskPushButton::Pressed, m_palette->color2 ); + + setColor( SoundControl::SliderControl, m_palette->color1 ); + setColor( SoundControl::SliderControl | QskPushButton::Pressed, m_palette->color2 ); + setMetric( QskPushButton::Text | QskAspect::Size, 20 ); setSkinHint( QskPushButton::Text | QskAspect::FontRole, int( QskSkin::LargeFont ) ); setSkinHint( QskPushButton::Text | QskAspect::Alignment, Qt::AlignCenter ); @@ -98,9 +115,6 @@ void DefaultSkin::initHints() setMetric( QskSlider::Handle | QskAspect::Radius, 9 ); setColor( QskSlider::Handle, m_palette->color5 ); - setColor( BalanceFadeBox::Panel, m_palette->color5 ); - setMetric( BalanceFadeBox::Panel | QskAspect::Radius, 15 ); - // animator for daylight/night scheme transitions setAnimation( QskAspect::Color, QskAnimationHint( 1000, QEasingCurve::InQuad ) ); } diff --git a/examples/hmi-demo/MainWindow.cpp b/examples/hmi-demo/MainWindow.cpp index 75f93860..f7cc1e03 100644 --- a/examples/hmi-demo/MainWindow.cpp +++ b/examples/hmi-demo/MainWindow.cpp @@ -3,6 +3,7 @@ #include "SoundControl.h" #include +#include #include #include #include @@ -18,40 +19,40 @@ namespace ButtonBar( QQuickItem* parentItem = nullptr ): QskLinearBox( parentItem ) { - setOpacity( 0.5 ); - setBackgroundColor( Qt::black ); - setMargins( QMarginsF( 20, 0, 20, 0 ) ); + QColor c( Qt::black ); + c.setAlphaF( 0.5 ); + setBackgroundColor( c ); - setSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed ); + setMargins( QMarginsF( 20, 15, 20, 15 ) ); + setSpacing( 20 ); + + setSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::MinimumExpanding ); } void addIcon( const char* name ) { - const QString fileName = QString( ":/images/%1" ).arg( name ); - auto* label = new QskGraphicLabel( this ); - label->setFixedSize( 76, 36 ); - label->setMargins( QMarginsF( 20, 7, 20, 7 ) ); - label->setGraphic( QskGraphic::fromImage( QImage( fileName ) ) ); + + /* + The label should adjust vertically and be stretched horizontally + according to its aspect ratio. + */ + + label->setSizePolicy( QskSizePolicy::Constrained, QskSizePolicy::Ignored ); + + const QString fileName = QString( ":/qvg/%1.qvg" ).arg( name ); + label->setGraphic( QskGraphicIO::read( fileName ) ); } protected: virtual QSizeF contentsSizeHint() const override final { - return QSizeF( -1, 50 ); + return QSizeF( -1, 20 ); } }; } MainWindow::MainWindow() -{ - setPreferredSize( QSize( 1024, 576 ) ); - setAutoLayoutChildren( true ); - - populate(); -} - -void MainWindow::populate() { const QImage image( ":/images/background.jpg" ); @@ -66,23 +67,30 @@ void MainWindow::populate() auto layout = new QskLinearBox( Qt::Vertical, contentItem() ); layout->addItem( header ); + layout->setStretchFactor( header, 1 ); + layout->addItem( content ); + layout->setStretchFactor( content, 10 ); + layout->addItem( footer ); + layout->setStretchFactor( footer, 1 ); + + setAutoLayoutChildren( true ); } QQuickItem* MainWindow::headerBar() const { auto* header = new ButtonBar(); - header->addIcon( "ic_pan_tool_white_48dp_2x.png" ); - header->addIcon( "ic_star_rate_white_18dp_2x.png" ); - header->addIcon( "ic_airplanemode_active_white_18dp_2x.png" ); + header->addIcon( "bluetooth" ); + header->addIcon( "location" ); + header->addIcon( "phone" ); auto dateLabel = new QskTextLabel( QDate::currentDate().toString(), header ); dateLabel->setColor( QskTextLabel::Text, Qt::white ); - header->addIcon( "ic_face_white_48px.svg" ); - header->addIcon( "ic_extension_white_48dp_2x.png" ); - header->addIcon( "ic_build_white_24dp_2x.png" ); + header->addIcon( "user" ); + header->addIcon( "bookmark" ); + header->addIcon( "menu" ); return header; } @@ -100,9 +108,12 @@ QQuickItem* MainWindow::footerBar() const { auto* footer = new ButtonBar(); - footer->addIcon( "ic_pan_tool_white_48dp_2x.png" ); - footer->addIcon( "ic_star_rate_white_18dp_2x.png" ); - footer->addIcon( "ic_airplanemode_active_white_18dp_2x.png" ); + footer->addIcon( "cloud" ); + footer->addIcon( "man" ); + footer->addIcon( "bus" ); + footer->addIcon( "plane" ); + footer->addIcon( "train" ); + footer->addStretch( 10 ); return footer; diff --git a/examples/hmi-demo/MainWindow.h b/examples/hmi-demo/MainWindow.h index b73bcf0e..de1166de 100644 --- a/examples/hmi-demo/MainWindow.h +++ b/examples/hmi-demo/MainWindow.h @@ -11,8 +11,6 @@ public: MainWindow(); private: - void populate(); - QQuickItem* headerBar() const; QQuickItem* mainContent() const; QQuickItem* footerBar() const; diff --git a/examples/hmi-demo/OtherSkin.cpp b/examples/hmi-demo/OtherSkin.cpp index d07cfc65..e55623f5 100644 --- a/examples/hmi-demo/OtherSkin.cpp +++ b/examples/hmi-demo/OtherSkin.cpp @@ -42,7 +42,7 @@ namespace { } -OtherSkin::OtherSkin( const QString& name, QObject* parent ) : +OtherSkin::OtherSkin( const QString& name, QObject* parent ): QskSkin( parent ), m_name( name ), m_palette( new Palette ) @@ -58,10 +58,16 @@ void OtherSkin::initHints() setColor( QskTextLabel::Text, m_palette->color4 ); - setColor( FilledRectangle::Panel, m_palette->color3 ); + setColor( SoundControl::CrossHair, m_palette->color3 ); + setColor( SoundControl::Marker, m_palette->color3 ); + setMetric( SoundControl::Marker | QskAspect::Radius, 100 ); + setSkinHint( SoundControl::Marker + | QskAspect::Radius | QskAspect::AllCorners + | QskAspect::SizeMode, Qt::RelativeSize ); setColor( QskPushButton::Panel, m_palette->color1 ); setColor( QskPushButton::Text, m_palette->color3 ); + setMetric( QskPushButton::Text | QskAspect::Size, 20 ); setSkinHint( QskPushButton::Text | QskAspect::FontRole, int( QskSkin::LargeFont ) ); setSkinHint( QskPushButton::Text | QskAspect::Alignment, Qt::AlignCenter ); @@ -72,9 +78,6 @@ void OtherSkin::initHints() setMetric( QskSlider::Handle | QskAspect::Size, 18 ); setMetric( QskSlider::Handle | QskAspect::Radius, 9 ); setColor( QskSlider::Handle, m_palette->color5 ); - - setColor( BalanceFadeBox::Panel, m_palette->color5 ); - setMetric( BalanceFadeBox::Panel | QskAspect::Radius, 15 ); } OtherSkin::~OtherSkin() diff --git a/examples/hmi-demo/README.images b/examples/hmi-demo/README.images index 4c20831c..5e0c06e3 100644 --- a/examples/hmi-demo/README.images +++ b/examples/hmi-demo/README.images @@ -1,4 +1,3 @@ * background image: http://7-themes.com/collections/green-wallpapers/4440155/ , license unknown * car image: https://openclipart.org/detail/234440/white-blank-racing-car-top-view , unlimited commercial use -* arrow images: https://www.flaticon.com/free-icon/right-arrow_108522 etc. made by Butterflytronics from www.flaticon.com * icons: https://www.flaticon.com/packs/material-design, made by Material Design from www.flaticon.com diff --git a/examples/hmi-demo/SkinFactory.cpp b/examples/hmi-demo/SkinFactory.cpp new file mode 100644 index 00000000..e0b91522 --- /dev/null +++ b/examples/hmi-demo/SkinFactory.cpp @@ -0,0 +1,64 @@ +#include "SkinFactory.h" +#include "DefaultSkin.h" +#include "OtherSkin.h" + +#include +#include + +#include +#include + +QStringList SkinFactory::skinNames() const +{ + return { "DefaultSkin", "OtherSkin", "Squiek", "Material" }; +} + +QskSkin* SkinFactory::createSkin( const QString& skinName ) +{ + if ( skinName == "DefaultSkin" ) + return new DefaultSkin( skinName ); + + if ( skinName == "OtherSkin" ) + return new OtherSkin( skinName ); + + if ( skinName == "SquiekSkin" ) + return new QskSquiekSkin(); + + if ( skinName == "MaterialSkin" ) + return new QskMaterialSkin(); + + return nullptr; +} + +void SkinFactory::toggleScheme() +{ + if ( qskSetup->skinName() == "DefaultSkin" ) + static_cast< DefaultSkin* >( qskSetup->skin() )->toggleScheme(); +} + +void SkinFactory::rotateSkin() +{ + const QStringList names = skinNames(); + + int index = names.indexOf( qskSetup->skinName() ); + index = ( index + 1 ) % names.size(); + + QskSkin* oldSkin = qskSetup->skin(); + if ( oldSkin->parent() == qskSetup ) + oldSkin->setParent( nullptr ); // otherwise setSkin deletes it + + QskSkin* newSkin = qskSetup->setSkin( names[ index ] ); + + QskSkinTransition transition; + + transition.setSourceSkin( oldSkin ); + transition.setTargetSkin( newSkin ); + transition.setAnimation( 500 ); + + transition.process(); + + if ( oldSkin->parent() == nullptr ) + delete oldSkin; +} + +#include "moc_SkinFactory.cpp" diff --git a/examples/hmi-demo/SkinFactory.h b/examples/hmi-demo/SkinFactory.h new file mode 100644 index 00000000..fddaf4de --- /dev/null +++ b/examples/hmi-demo/SkinFactory.h @@ -0,0 +1,19 @@ +#ifndef _SKIN_FACTORY_H_ +#define _SKIN_FACTORY_H_ + +#include + +class SkinFactory : public QskSkinFactory +{ + Q_OBJECT + +public: + virtual QStringList skinNames() const override; + virtual QskSkin* createSkin( const QString& skinName ) override; + +public Q_SLOTS: + void rotateSkin(); + void toggleScheme(); +}; + +#endif diff --git a/examples/hmi-demo/SoundControl.cpp b/examples/hmi-demo/SoundControl.cpp index 916eec33..f840f9e4 100644 --- a/examples/hmi-demo/SoundControl.cpp +++ b/examples/hmi-demo/SoundControl.cpp @@ -2,44 +2,158 @@ #include #include -#include +#include #include #include #include #include -#include #include +#include +#include +#include -#include +QSK_SUBCONTROL( SoundControl, CrossHair ) +QSK_SUBCONTROL( SoundControl, Marker ) +QSK_SUBCONTROL( SoundControl, SliderControl ) -QSK_SUBCONTROL( FilledRectangle, Panel ) - -QskAspect::Subcontrol FilledRectangle::effectiveSubcontrol( - QskAspect::Subcontrol subControl ) const +class CrossHairLine : public QskBox { - if ( subControl == QskPushButton::Panel ) - return FilledRectangle::Panel; +public: + CrossHairLine( QQuickItem* parent ): + QskBox( parent ) + { + } - return subControl; -} + virtual QskAspect::Subcontrol effectiveSubcontrol( + QskAspect::Subcontrol subControl ) const override final + { + if ( subControl == QskBox::Panel ) + return SoundControl::CrossHair; -QSK_SUBCONTROL( BalanceFadeBox, Panel ) + return subControl; + } +}; -QskAspect::Subcontrol BalanceFadeBox::effectiveSubcontrol( - QskAspect::Subcontrol subControl ) const +class BalanceFadeMarker : public QskBox { - if ( subControl == QskPushButton::Panel ) - return BalanceFadeBox::Panel; +public: + BalanceFadeMarker( QQuickItem* parent ): + QskBox( parent ) + { + } - return subControl; -} + virtual QskAspect::Subcontrol effectiveSubcontrol( + QskAspect::Subcontrol subControl ) const override final + { + if ( subControl == QskBox::Panel ) + return SoundControl::Marker; -class StackedControl : public QskControl { + return subControl; + } +}; + +class NavigationButton : public QskPushButton +{ +public: + NavigationButton( Qsk::Direction direction, QQuickItem* parentItem = nullptr ): + QskPushButton( parentItem ), + m_direction( direction ) + { + const char* svgList[] = { "right", "left", "down", "up" }; + + const QString fileName = QString( ":/qvg/%1.qvg" ).arg( svgList[ direction ] ); + setGraphic( QskGraphicIO::read( fileName ) ); + + setAutoRepeat( true ); + setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + } + + QPointF offset() const + { + const qreal off = 5.0; + + switch( m_direction ) + { + case Qsk::LeftToRight: + return QPointF( off, 0.0 ); + + case Qsk::RightToLeft: + return QPointF( -off, 0.0 ); + + case Qsk::TopToBottom: + return QPointF( 0.0, off ); + + case Qsk::BottomToTop: + return QPointF( 0.0, -off ); + } + + return QPointF(); + } + +protected: + virtual QSizeF contentsSizeHint() const override final + { + const qreal dim = 100; + + if ( m_direction == Qsk::LeftToRight || m_direction == Qsk::RightToLeft ) + return QSizeF( 0.5 * dim, dim ); + else + return QSizeF( dim, 0.5 * dim ); + } + +private: + const Qsk::Direction m_direction; +}; + +class ControlButton : public QskPushButton +{ +public: + ControlButton( const char symbol, QQuickItem* parentItem = nullptr ): + QskPushButton( parentItem ) + { + setText( QChar( symbol ) ); + setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed ); + + setAutoRepeat( true ); + } + + virtual QskAspect::Subcontrol effectiveSubcontrol( + QskAspect::Subcontrol subControl ) const override + { + if ( subControl == QskPushButton::Panel ) + return SoundControl::SliderControl; + + return QskPushButton::effectiveSubcontrol( subControl ); + } + + virtual QSizeF contentsSizeHint() const override final + { + qreal h = QskPushButton::contentsSizeHint().height(); + return QSizeF( h, h ); + } +}; + +class StackedControl : public QskControl +{ public: StackedControl( QQuickItem* parent = nullptr ): QskControl( parent ), m_offset( 0.0, 0.0 ) { + setPolishOnResize( true ); // we have t re-layout the crosshair + setSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding ); + + auto horizontalCarRectangle = new CrossHairLine( this ); + horizontalCarRectangle->setObjectName( "horizontalBar" ); + + auto verticalCarRectangle = new CrossHairLine( this ); + verticalCarRectangle->setObjectName( "verticalBar" ); + + auto* carLabel = new QskGraphicLabel( this ); + carLabel->setGraphic( QskGraphicIO::read( QString( ":/qvg/car.qvg" ) ) ); + + auto marker = new BalanceFadeMarker( this ); + marker->setObjectName( "marker" ); } QPointF offset() const @@ -50,44 +164,41 @@ public: void setOffset( const QPointF& offset ) { m_offset = offset; + polish(); } protected: virtual void updateLayout() override final { const QRectF cr = contentsRect(); + const qreal crossHairSize = 3; for ( int a = 0; a < children().count(); a++ ) { QskControl* control = static_cast< QskControl* >( children().at( a ) ); - qreal xCenter = ( cr.width() + margins().top() + margins().bottom() ) / 2; - qreal yCenter = ( cr.height() + margins().left() + margins().right() ) / 2; - if ( control->objectName() == "verticalBar" ) { - control->setPosition( QPointF( xCenter, margins().top() ) ); - control->setSize( QSizeF( 3, cr.height() ) ); + control->setGeometry( cr.center().x(), cr.top(), crossHairSize, cr.height() ); control->setZ( 1 ); } else if ( control->objectName() == "horizontalBar" ) { - control->setPosition( QPointF( margins().left(), yCenter ) ); - control->setSize( QSizeF( cr.width(), 3 ) ); + control->setGeometry( cr.left(), cr.center().y(), cr.width(), crossHairSize ); control->setZ( 1 ); } - else if ( control->objectName() == "box" ) + else if ( control->objectName() == "marker" ) { - qreal size = 30; - control->setPosition( QPointF( xCenter - ( size / 2 ) + 1 + m_offset.x(), - yCenter - ( size / 2 ) + 1 + m_offset.y() ) ); + qreal size = 31; + + control->setPosition( + cr.center() - 0.5 * QPointF( size, size ) + m_offset + QPointF( 1, 1 ) ); control->setSize( QSizeF( size, size ) ); - control->setZ( 2 ); + control->setZ( 1 ); } else { - control->setPosition( cr.topLeft() ); - control->setSize( cr.size() ); + control->setGeometry( cr ); } } } @@ -96,198 +207,160 @@ private: QPointF m_offset; }; +class SectionTitleBar : public QskLinearBox +{ +public: + SectionTitleBar( const char* title, QQuickItem* parentItem = nullptr ): + QskLinearBox( Qt::Horizontal, parentItem ) + { + setSpacing( 10 ); + + auto* label = new QskTextLabel( title ); + label->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed ); + + addItem( new QskSeparator() ); + addItem( label ); + addItem( new QskSeparator() ); + + setStretchFactor( 0, 1 ); + setStretchFactor( 2, 5 ); + } +}; + +class SliderBox : public QskLinearBox +{ +public: + SliderBox( const char* title, qreal min, qreal max, QQuickItem* parentItem = nullptr ): + QskLinearBox( Qt::Vertical, parentItem ) + { + auto label = new QskTextLabel( title ); + m_numberLabel = new QskTextLabel(); + + // don't stretch the labels, so that the layout centers them + label->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed ); + m_numberLabel->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed ); + + auto* plusButton = new ControlButton( '+' ); + auto minusButton = new ControlButton( '-' ); + + m_slider = new QskSlider( Qt::Vertical ); + m_slider->setMinimum( min ); + m_slider->setMaximum( max ); + + // layout + + addItem( label ); + addItem( m_numberLabel ); + addItem( plusButton ); + addSpacer( 10 ); + addItem( m_slider ); + addSpacer( 10 ); + addItem( minusButton ); + + setDefaultAlignment( Qt::AlignCenter ); + + // finally connect buttons/slider/labels + + connect( plusButton, &QskPushButton::pressed, + [ this ]() { increment( 1 ); } ); + + connect( minusButton, &QskPushButton::pressed, + [ this ]() { increment( -1 ); } ); + + connect( m_slider, &QskSlider::valueChanged, + this, &SliderBox::setValue ); + } + +public Q_SLOTS: + void setValue( qreal value ) + { + m_slider->setValue( value ); + + QString txt; + txt.setNum( m_slider->value(), 'f', 1 ); + + m_numberLabel->setText( txt ); + } + +private: + void increment( qreal offset ) + { + setValue( m_slider->value() + offset ); + } + + QskTextLabel* m_numberLabel; + QskSlider* m_slider; +}; + +class ToneControlBox : public QskLinearBox +{ +public: + ToneControlBox( QQuickItem* parentItem = nullptr ): + QskLinearBox( Qt::Horizontal, parentItem ) + { + auto bassControl = new SliderBox( "Bass", 0.0, 40.0, this ); + auto treebleControl = new SliderBox( "Treeble", 0.0, 40.0, this ); + auto subControl = new SliderBox( "Sub", 0.0, 40.0, this ); + + bassControl->setValue( 30 ); + treebleControl->setValue( 11 ); + subControl->setValue( 18 ); + } +}; + +class BalanceFadeControlBox : public QskGridBox +{ +public: + BalanceFadeControlBox( QQuickItem* parentItem = nullptr ): + QskGridBox( parentItem ) + { + NavigationButton* buttons[4]; + for ( int i = 0; i < 4; i++ ) + buttons[i] = new NavigationButton( static_cast< Qsk::Direction >( i ) ); + + m_carControl = new StackedControl(); + + addItem( buttons[ Qsk::RightToLeft ], 1, 0 ); + addItem( buttons[ Qsk::BottomToTop ], 0, 0, 1, 3 ); + addItem( buttons[ Qsk::LeftToRight ], 1, 2 ); + addItem( buttons[ Qsk::TopToBottom ], 2, 0, 1, 3 ); + + addItem( m_carControl, 1, 1 ); + + for ( int i = 0; i < 4; i++ ) + { + const auto button = buttons[i]; + + setAlignment( button, Qt::AlignCenter ); + + connect( button, &QskPushButton::pressed, + [ = ]() { shift( button->offset() ); } ); + } + } + + void shift( const QPointF& offset ) + { + m_carControl->setOffset( m_carControl->offset() + offset ); + } + + StackedControl* m_carControl; +}; + SoundControl::SoundControl( QQuickItem* parent ): QskControl( parent ) { setMargins( QMarginsF( 40, 20, 40, 20 ) ); setAutoLayoutChildren( true ); - QskGridBox* outterLayout = new QskGridBox( this ); - outterLayout->setVerticalSpacing( 40 ); - outterLayout->setHorizontalSpacing( 60 ); - outterLayout->setColumnStretchFactor( 0, 1 ); - outterLayout->setColumnStretchFactor( 1, 2 ); + QskGridBox* outerLayout = new QskGridBox( this ); + outerLayout->setVerticalSpacing( 10 ); + outerLayout->setHorizontalSpacing( 60 ); + outerLayout->setColumnStretchFactor( 0, 1 ); + outerLayout->setColumnStretchFactor( 1, 2 ); - QskLinearBox* toneBox = new QskLinearBox( Qt::Horizontal, outterLayout ); - toneBox->setSpacing( 20 ); - toneBox->setAutoAddChildren( true ); - toneBox->setAutoLayoutChildren( true ); - toneBox->addSpacer( 0, 1 ); - FilledRectangle* toneRectangle = new FilledRectangle( toneBox ); - QskTextLabel* toneLabel = new QskTextLabel( "Tone", toneBox ); - toneLabel->setAlignment( Qt::AlignLeft ); - toneRectangle->setFixedHeight( - QFontMetricsF( toneLabel->effectiveFont( QskTextLabel::Text ) ).height() ); - toneBox->addSpacer( 0, 1 ); - outterLayout->addItem( toneBox, 0, 0 ); + outerLayout->addItem( new SectionTitleBar( "Tone" ), 0, 0 ); + outerLayout->addItem( new ToneControlBox(), 1, 0 ); - - QskLinearBox* balanceBox = new QskLinearBox( Qt::Horizontal, outterLayout ); - balanceBox->setSpacing( 20 ); - balanceBox->setAutoAddChildren( true ); - balanceBox->setAutoLayoutChildren( true ); - balanceBox->addSpacer( 0, 1 ); - FilledRectangle* balanceRectangle = new FilledRectangle( balanceBox ); - QskTextLabel* balanceLabel = new QskTextLabel( "Balance / Fade", balanceBox ); - balanceLabel->setAlignment( Qt::AlignLeft ); - balanceRectangle->setFixedHeight( - QFontMetricsF( balanceLabel->effectiveFont( QskTextLabel::Text ) ).height() ); - balanceBox->addSpacer( 0, 1 ); - outterLayout->addItem( balanceBox, 0, 1 ); - - - QskGridBox* toneGridBox = new QskGridBox( outterLayout ); - QskTextLabel* bassLabel = new QskTextLabel( "Bass", toneGridBox ); - toneGridBox->addItem( bassLabel, 0, 0 ); - QskTextLabel* trebleLabel = new QskTextLabel( "Treble", toneGridBox ); - toneGridBox->addItem( trebleLabel, 0, 1 ); - QskTextLabel* subLabel = new QskTextLabel( "Sub", toneGridBox ); - toneGridBox->addItem( subLabel, 0, 2 ); - - QskTextLabel* bassNumberLabel = new QskTextLabel( "0", toneGridBox ); - toneGridBox->addItem( bassNumberLabel, 1, 0 ); - QskTextLabel* trebleNumberLabel = new QskTextLabel( "0", toneGridBox ); - toneGridBox->addItem( trebleNumberLabel, 1, 1 ); - QskTextLabel* subNumberLabel = new QskTextLabel( "0", toneGridBox ); - toneGridBox->addItem( subNumberLabel, 1, 2 ); - - QskPushButton* bassPlusButton = new QskPushButton( "+", toneGridBox ); - bassPlusButton->setFixedSize( 35, 35 ); - toneGridBox->addItem( bassPlusButton, 2, 0 ); - toneGridBox->setAlignment( bassPlusButton, Qt::AlignCenter ); - QskPushButton* treblePlusButton = new QskPushButton( "+", toneGridBox ); - treblePlusButton->setFixedSize( 35, 35 ); - toneGridBox->addItem( treblePlusButton, 2, 1 ); - toneGridBox->setAlignment( treblePlusButton, Qt::AlignCenter ); - QskPushButton* subPlusButton = new QskPushButton( "+", toneGridBox ); - subPlusButton->setFixedSize( 35, 35 ); - toneGridBox->addItem( subPlusButton, 2, 2 ); - toneGridBox->setAlignment( subPlusButton, Qt::AlignCenter ); - - QskSlider* bassSlider = new QskSlider( Qt::Vertical, toneGridBox ); - bassSlider->setMinimum( 0 ); - bassSlider->setMaximum( 40 ); - bassSlider->setValue( 30 ); - toneGridBox->addItem( bassSlider, 3, 0 ); - toneGridBox->setAlignment( bassSlider, Qt::AlignCenter ); - QskSlider* trebleSlider = new QskSlider( Qt::Vertical, toneGridBox ); - trebleSlider->setMinimum( 0 ); - trebleSlider->setMaximum( 40 ); - trebleSlider->setValue( 11 ); - toneGridBox->addItem( trebleSlider, 3, 1 ); - toneGridBox->setAlignment( trebleSlider, Qt::AlignCenter ); - QskSlider* subSlider = new QskSlider( Qt::Vertical, toneGridBox ); - subSlider->setMinimum( 0 ); - subSlider->setMaximum( 40 ); - subSlider->setValue( 18 ); - toneGridBox->addItem( subSlider, 3, 2 ); - toneGridBox->setAlignment( subSlider, Qt::AlignCenter ); - - QskPushButton* bassMinusButton = new QskPushButton( "-", toneGridBox ); - bassMinusButton->setFixedSize( 35, 35 ); - toneGridBox->addItem( bassMinusButton, 4, 0 ); - toneGridBox->setAlignment( bassMinusButton, Qt::AlignCenter ); - QskPushButton* trebleMinusButton = new QskPushButton( "-", toneGridBox ); - trebleMinusButton->setFixedSize( 35, 35 ); - toneGridBox->addItem( trebleMinusButton, 4, 1 ); - toneGridBox->setAlignment( trebleMinusButton, Qt::AlignCenter ); - QskPushButton* subMinusButton = new QskPushButton( "-", toneGridBox ); - subMinusButton->setFixedSize( 35, 35 ); - toneGridBox->addItem( subMinusButton, 4, 2 ); - toneGridBox->setAlignment( subMinusButton, Qt::AlignCenter ); - - connect( bassPlusButton, &QskPushButton::pressed, [ bassSlider ]() { - bassSlider->setValue( bassSlider->value() + 1 ); - } ); - connect( treblePlusButton, &QskPushButton::pressed, [ trebleSlider ]() { - trebleSlider->setValue( trebleSlider->value() + 1 ); - } ); - connect( subPlusButton, &QskPushButton::pressed, [ subSlider ]() { - subSlider->setValue( subSlider->value() + 1 ); - } ); - connect( bassMinusButton, &QskPushButton::pressed, [ bassSlider ]() { - bassSlider->setValue( bassSlider->value() - 1 ); - } ); - connect( trebleMinusButton, &QskPushButton::pressed, [ trebleSlider ]() { - trebleSlider->setValue( trebleSlider->value() - 1 ); - } ); - connect( subMinusButton, &QskPushButton::pressed, [ subSlider ]() { - subSlider->setValue( subSlider->value() - 1 ); - } ); - - outterLayout->addItem( toneGridBox, 1, 0 ); - - - QskGridBox* carGridBox = new QskGridBox( outterLayout ); - carGridBox->setAutoLayoutChildren( true ); - - QskPushButton* upButton = new QskPushButton( carGridBox ); - upButton->setFixedSize( 100, 50 ); - QImage upImage( ":/images/up.svg" ); - QskGraphic upGraphic = QskGraphic::fromImage( upImage ); - upButton->setGraphic( upGraphic ); // ### try with setGraphicSource - carGridBox->addItem( upButton, 0, 0, 1, 3 ); - carGridBox->setAlignment( upButton, Qt::AlignCenter ); - - QskPushButton* leftButton = new QskPushButton( carGridBox ); - leftButton->setFixedSize( 50, 100 ); - QImage leftImage( ":/images/left.svg" ); - QskGraphic leftGraphic = QskGraphic::fromImage( leftImage ); - leftButton->setGraphic( leftGraphic ); - carGridBox->addItem( leftButton, 1, 0 ); - - StackedControl* carControl = new StackedControl( carGridBox ); - carControl->setSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Expanding ); - carControl->setPolishOnResize( true ); - carControl->setMargins( 10 ); - FilledRectangle* horizontalCarRectangle = new FilledRectangle( carControl ); - horizontalCarRectangle->setObjectName( "horizontalBar" ); - FilledRectangle* verticalCarRectangle = new FilledRectangle( carControl ); - verticalCarRectangle->setObjectName( "verticalBar" ); - BalanceFadeBox *box = new BalanceFadeBox( carControl ); - box->setObjectName( "box" ); - QImage carImage( ":/images/car.svg" ); - QskGraphic graphic = QskGraphic::fromImage( carImage ); - QskGraphicLabel* carLabel = new QskGraphicLabel( carControl ); - carLabel->setGraphic( graphic ); - carGridBox->addItem( carControl, 1, 1 ); - - QskPushButton* rightButton = new QskPushButton( carGridBox ); - rightButton->setFixedSize( 50, 100 ); - QImage rightImage( ":/images/right.svg" ); - QskGraphic rightGraphic = QskGraphic::fromImage( rightImage ); - rightButton->setGraphic( rightGraphic ); - carGridBox->addItem( rightButton, 1, 2 ); - carGridBox->setAlignment( rightButton, Qt::AlignRight ); - - QskPushButton* downButton = new QskPushButton( carGridBox ); - downButton->setFixedSize( 100, 50 ); - QImage downImage( ":/images/down.svg" ); - QskGraphic downGraphic = QskGraphic::fromImage( downImage ); - downButton->setGraphic( downGraphic ); - carGridBox->addItem( downButton, 2, 0, 1, 3 ); - carGridBox->setAlignment( downButton, Qt::AlignCenter ); - - connect( upButton, &QskPushButton::pressed, [ carControl ]() { - carControl->setOffset( QPointF( carControl->offset().x(), - carControl->offset().y() - 5.0 ) ); - carControl->polish(); - } ); - connect( leftButton, &QskPushButton::pressed, [ carControl ]() { - carControl->setOffset( QPointF( carControl->offset().x() - 5.0, - carControl->offset().y() ) ); - carControl->polish(); - } ); - connect( rightButton, &QskPushButton::pressed, [ carControl ]() { - carControl->setOffset( QPointF( carControl->offset().x() + 5.0, - carControl->offset().y() ) ); - carControl->polish(); - } ); - connect( downButton, &QskPushButton::pressed, [ carControl ]() { - carControl->setOffset( QPointF( carControl->offset().x(), - carControl->offset().y() + 5.0 ) ); - carControl->polish(); - } ); - - outterLayout->addItem( carGridBox, 1, 1 ); + outerLayout->addItem( new SectionTitleBar( "Balance / Fade" ), 0, 1 ); + outerLayout->addItem( new BalanceFadeControlBox(), 1, 1 ); } diff --git a/examples/hmi-demo/SoundControl.h b/examples/hmi-demo/SoundControl.h index 18f177c3..5d973751 100644 --- a/examples/hmi-demo/SoundControl.h +++ b/examples/hmi-demo/SoundControl.h @@ -1,43 +1,13 @@ #ifndef SOUNDCONTROL_H #define SOUNDCONTROL_H -#include #include -#include - -class QskGridBox; - -class FilledRectangle : public QskPushButton // ### move to some main control file -{ -public: - QSK_SUBCONTROLS( Panel ) - - FilledRectangle( QQuickItem* parent ): QskPushButton( parent ) - { - setFlat( true ); - setFixedWidth( 80 ); // ### style - } - - virtual QskAspect::Subcontrol effectiveSubcontrol( - QskAspect::Subcontrol subControl ) const override final; -}; - -class BalanceFadeBox : public QskPushButton -{ -public: - QSK_SUBCONTROLS( Panel ) - - BalanceFadeBox( QQuickItem* parent ): QskPushButton( parent ) - { - } - - virtual QskAspect::Subcontrol effectiveSubcontrol( - QskAspect::Subcontrol subControl ) const override final; -}; class SoundControl : public QskControl { public: + QSK_SUBCONTROLS( CrossHair, Marker, SliderControl ) + SoundControl( QQuickItem* parent = nullptr ); }; diff --git a/examples/hmi-demo/hmi-demo.pro b/examples/hmi-demo/hmi-demo.pro index 894828a7..988ed197 100644 --- a/examples/hmi-demo/hmi-demo.pro +++ b/examples/hmi-demo/hmi-demo.pro @@ -2,12 +2,11 @@ include( $${PWD}/../examples.pri ) TARGET = hmi-demo -RESOURCES = images.qrc - HEADERS += \ MainWindow.h \ RadioControl.h \ SoundControl.h \ + SkinFactory.h \ DefaultSkin.h \ OtherSkin.h @@ -16,5 +15,95 @@ SOURCES += \ MainWindow.cpp \ RadioControl.cpp \ SoundControl.cpp \ + SkinFactory.cpp \ DefaultSkin.cpp \ OtherSkin.cpp + +QRCFILES += \ + images.qrc + +SVGSOURCES = \ + images/car.svg + +SVGSOURCES += \ + images/left.svg \ + images/down.svg \ + images/right.svg \ + images/up.svg + +SVGSOURCES += \ + images/bluetooth.svg \ + images/bookmark.svg \ + images/bus.svg \ + images/cloud.svg \ + images/compass.svg \ + images/location.svg \ + images/man.svg \ + images/menu.svg \ + images/phone.svg \ + images/plane.svg \ + images/train.svg \ + images/user.svg \ + + +########### +# The rcc file includes the precompiled SVGs and so we need to build +# rules for running svg2qvg, when a SVG has changed into the Makefile +# before running rccgen. +# While this would be an easy one in Makefile syntax it is a nightmare +# with qmake. + +# TODO: we should at least offer some sort of *.pri file to help with +# writing application project files. +########### + +SVG2QVG=$${QSK_OUT_ROOT}/tools/bin/svg2qvg + +svg2qvg.name = SVG compiler +svg2qvg.input = SVGSOURCES +svg2qvg.output = qvg/${QMAKE_FILE_BASE}.qvg +svg2qvg.variable_out = +svg2qvg.commands += mkdir -p qvg && $${SVG2QVG} ${QMAKE_FILE_IN} $${svg2qvg.output} + +rccgen.name = RCC compiler +rccgen.input = QRCFILES +rccgen.output = $${RCC_DIR}/qrc_${QMAKE_FILE_BASE}.cpp +rccgen.variable_out = SOURCES + +rccgen.commands += $${QMAKE_MKDIR} $${RCC_DIR} + +!equals( OUT_PWD, $${PWD} ) { + + # Paths inside a qrc file are always relative to the path of the + # qrc file itself. So in case of shadow builds we need to copy the + # qrc file into the shadow directory as the included qvg files + # are generated locally. + + QRC_SHADOW_CLONE = $${OUT_PWD}/${QMAKE_FILE_BASE}_shadow.qrc + + rccgen.commands += && $${QMAKE_COPY} ${QMAKE_FILE_IN} $${QRC_SHADOW_CLONE} + rccgen.commands += && rcc $${QRC_SHADOW_CLONE} -o ${QMAKE_FILE_OUT} + rccgen.commands += && $${QMAKE_DEL_FILE} $${QRC_SHADOW_CLONE} +} +else { + rccgen.commands += && rcc ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} +} + +# We would like to define a dependency for "svg2qvg.variable_out" - +# but how to do this ? As long as we don't have a solution we have to use +# the workaround below. + +defineReplace(qvgfiles) { + svgfiles = $$1 + + myfiles= + for(svgfile, svgfiles) myfiles += $$replace(svgfile, svg, qvg) + + myfiles2= + for(myfile, myfiles) myfiles2 += $$replace(myfile, images, qvg) + + return($$myfiles2) +} +rccgen.depends += $$qvgfiles( $${SVGSOURCES} ) + +QMAKE_EXTRA_COMPILERS += svg2qvg rccgen diff --git a/examples/hmi-demo/images.qrc b/examples/hmi-demo/images.qrc index 4b72d97e..b780d7a6 100644 --- a/examples/hmi-demo/images.qrc +++ b/examples/hmi-demo/images.qrc @@ -1,22 +1,28 @@ + images/background.jpg - images/car.svg - images/down.svg - images/ic_airplanemode_active_white_18dp_2x.png - images/ic_build_white_24dp_2x.png - images/ic_extension_white_48dp_2x.png - images/ic_face_white_48px.svg - images/ic_fast_forward_white_18dp_2x.png - images/ic_fast_rewind_white_18dp_2x.png - images/ic_pan_tool_white_48dp_2x.png - images/ic_skip_next_white_18dp_1x.png - images/ic_skip_previous_white_18dp_2x.png - images/ic_star_rate_white_18dp_2x.png - images/left.svg - images/right.svg - images/up.svg + qvg/car.qvg + + qvg/bluetooth.qvg + qvg/bookmark.qvg + qvg/bus.qvg + qvg/cloud.qvg + qvg/face.qvg + qvg/location.qvg + qvg/man.qvg + qvg/menu.qvg + qvg/phone.qvg + qvg/plane.qvg + qvg/train.qvg + qvg/user.qvg + + qvg/down.qvg + qvg/left.qvg + qvg/right.qvg + qvg/up.qvg + diff --git a/examples/hmi-demo/images/bluetooth.svg b/examples/hmi-demo/images/bluetooth.svg new file mode 100644 index 00000000..90dd0265 --- /dev/null +++ b/examples/hmi-demo/images/bluetooth.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/bookmark.svg b/examples/hmi-demo/images/bookmark.svg new file mode 100644 index 00000000..543bb07f --- /dev/null +++ b/examples/hmi-demo/images/bookmark.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/bus.svg b/examples/hmi-demo/images/bus.svg new file mode 100644 index 00000000..83997da9 --- /dev/null +++ b/examples/hmi-demo/images/bus.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/cloud.svg b/examples/hmi-demo/images/cloud.svg new file mode 100644 index 00000000..4423f38a --- /dev/null +++ b/examples/hmi-demo/images/cloud.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/compass.svg b/examples/hmi-demo/images/compass.svg new file mode 100644 index 00000000..c94138f2 --- /dev/null +++ b/examples/hmi-demo/images/compass.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/down.svg b/examples/hmi-demo/images/down.svg index 0acfad0c..0e2fbc13 100644 --- a/examples/hmi-demo/images/down.svg +++ b/examples/hmi-demo/images/down.svg @@ -1,38 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/examples/hmi-demo/images/ic_face_white_48px.svg b/examples/hmi-demo/images/face.svg similarity index 100% rename from examples/hmi-demo/images/ic_face_white_48px.svg rename to examples/hmi-demo/images/face.svg diff --git a/examples/hmi-demo/images/left.svg b/examples/hmi-demo/images/left.svg index 016fdd2c..6e47594e 100644 --- a/examples/hmi-demo/images/left.svg +++ b/examples/hmi-demo/images/left.svg @@ -1,38 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/examples/hmi-demo/images/location.svg b/examples/hmi-demo/images/location.svg new file mode 100644 index 00000000..23d7f7ff --- /dev/null +++ b/examples/hmi-demo/images/location.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/man.svg b/examples/hmi-demo/images/man.svg new file mode 100644 index 00000000..27c3d066 --- /dev/null +++ b/examples/hmi-demo/images/man.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/menu.svg b/examples/hmi-demo/images/menu.svg new file mode 100644 index 00000000..8f6b932f --- /dev/null +++ b/examples/hmi-demo/images/menu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/phone.svg b/examples/hmi-demo/images/phone.svg new file mode 100644 index 00000000..a4469c14 --- /dev/null +++ b/examples/hmi-demo/images/phone.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/plane.svg b/examples/hmi-demo/images/plane.svg new file mode 100644 index 00000000..14113600 --- /dev/null +++ b/examples/hmi-demo/images/plane.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/right.svg b/examples/hmi-demo/images/right.svg index f88ab81a..879abe7f 100644 --- a/examples/hmi-demo/images/right.svg +++ b/examples/hmi-demo/images/right.svg @@ -1,38 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/examples/hmi-demo/images/train.svg b/examples/hmi-demo/images/train.svg new file mode 100644 index 00000000..701f418b --- /dev/null +++ b/examples/hmi-demo/images/train.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/images/up.svg b/examples/hmi-demo/images/up.svg index 52619ba8..d0ac978c 100644 --- a/examples/hmi-demo/images/up.svg +++ b/examples/hmi-demo/images/up.svg @@ -1,38 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/examples/hmi-demo/images/user.svg b/examples/hmi-demo/images/user.svg new file mode 100644 index 00000000..bd66d1f4 --- /dev/null +++ b/examples/hmi-demo/images/user.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/hmi-demo/main.cpp b/examples/hmi-demo/main.cpp index aefd73d9..c020fd08 100644 --- a/examples/hmi-demo/main.cpp +++ b/examples/hmi-demo/main.cpp @@ -1,70 +1,31 @@ #include "MainWindow.h" -#include "DefaultSkin.h" -#include "OtherSkin.h" +#include "SkinFactory.h" #include -#include #include - #include #include -namespace { - - class SkinFactory : public QskSkinFactory - { - Q_OBJECT - -public: - SkinFactory(): QskSkinFactory() - { - } - - virtual QStringList skinNames() const override final - { - return { "DefaultSkin", "OtherSkin" }; - } - - virtual QskSkin* createSkin( const QString& skinName ) override - { - if ( skinName == "DefaultSkin" ) - return new DefaultSkin( skinName ); - - if ( skinName == "OtherSkin" ) - return new OtherSkin( skinName ); - - return nullptr; - } - -public Q_SLOTS: - void toggleScheme() - { - DefaultSkin* skin = static_cast< DefaultSkin* >( qskSetup->skin() ); - if ( skin ) - skin->toggleScheme(); - } - }; - -} - int main( int argc, char** argv ) { QGuiApplication app( argc, argv ); SkinFactory skinFactory; Qsk::registerSkinFactory( "SampleSkinFactory", &skinFactory ); - QskSetup::instance()->setSkin( "DefaultSkin" ); - SkinnyShortcut::enable( SkinnyShortcut::DebugBackground | SkinnyShortcut::Quit | SkinnyShortcut::RotateSkin ); + qskSetup->setSkin( "DefaultSkin" ); - QskShortcut::addShortcut( QKeySequence( Qt::CTRL + Qt::Key_T ), &skinFactory, - SLOT(toggleScheme()), false ); + SkinnyShortcut::enable( SkinnyShortcut::DebugBackground | SkinnyShortcut::Quit ); + + QskShortcut::addShortcut( QKeySequence( Qt::CTRL + Qt::Key_T ), + &skinFactory, SLOT( toggleScheme()), false ); + + QskShortcut::addShortcut( QKeySequence( Qt::CTRL + Qt::Key_S ), + &skinFactory, SLOT( rotateSkin()), false ); MainWindow mainWindow; mainWindow.show(); return app.exec(); } - -#include "main.moc"