Merge branch 'master' into Qt-5.6

This commit is contained in:
Uwe Rathmann 2022-04-06 10:50:13 +02:00
commit a0f3a925ff
102 changed files with 2175 additions and 1515 deletions

View File

@ -7,7 +7,6 @@
#include "SkinFactory.h"
#include <SkinnyShortcut.h>
#include <SkinnyFont.h>
#include <QskSetup.h>
#include <QskSkinManager.h>
@ -33,7 +32,6 @@ int main( int argc, char** argv )
*/
qskSetup->setItemUpdateFlag( QskQuickItem::PreferRasterForTextures, true );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
MainWindow window;

View File

@ -5,7 +5,6 @@
#include "Box.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskLinearBox.h>
@ -555,7 +554,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::Quit | SkinnyShortcut::DebugShortcuts );
auto* tabView = new TabView();

View File

@ -5,10 +5,17 @@ Qsk.PushButton
{
sizePolicy
{
// long texts, should not have an effect
horizontalPolicy: Qsk.SizePolicy.Ignored
verticalPolicy: Qsk.SizePolicy.Ignored
}
minimumSize
{
width: 80
height: 60
}
shape
{
sizeMode: Qt.RelativeSize

View File

@ -6,12 +6,20 @@ Qsk.Window
{
id: window
visible: true
// visibility: QskWindow.Minimized
width: 600
height: 600
color: "Beige"
Component.onCompleted:
{
// very much standard: we should find a better way
var hint = sizeConstraint();
setMinimumWidth( hint.width )
setMinimumHeight( hint.height )
}
Qsk.Shortcut
{
sequence : "Ctrl+X"

View File

@ -3,7 +3,6 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include <SkinnyShapeProvider.h>
#include <SkinnyShortcut.h>
@ -24,7 +23,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
QQmlApplicationEngine engine( QUrl( "qrc:/qml/buttons.qml" ) );

View File

@ -1,117 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "Theme.h"
#include <QskAspect.h>
#include <QskBoxBorderColors.h>
#include <QskFocusIndicator.h>
#include <QskListView.h>
#include <QskSetup.h>
#include <QskSkin.h>
#include <QskSkinTransition.h>
#include <QskSkinHintTable.h>
#include <QskSkinHintTableEditor.h>
namespace
{
class SkinTransition final : public QskSkinTransition
{
public:
SkinTransition( const QColor& accent )
: m_accent( accent )
{
}
protected:
void updateSkin( QskSkin*, QskSkin* newSkin ) override
{
newSkin->resetColors( m_accent );
/*
The current implementation of the skins is not that good
and we don't have support for customizing them by a minimal set
of attributes. So we do some manual extra work here
*/
QskSkinHintTableEditor ed( &newSkin->hintTable() );
ed.setColor( QskListView::Cell | QskListView::Selected, m_accent.darker( 130 ) );
ed.setBoxBorderColors( QskFocusIndicator::Panel, m_accent.darker( 150 ) );
}
private:
const QColor m_accent;
};
}
Theme::Theme( QObject* parent )
: QObject( parent )
, m_accent( Qt::blue )
{
connect( qskSetup, &QskSetup::skinChanged,
this, [ this ]( QskSkin* ) { updateColors(); } );
connect( qskSetup, &QskSetup::skinChanged,
this, [ this ]( QskSkin* ) { Q_EMIT skinChanged(); } );
}
void Theme::setAccent( QColor color )
{
if ( m_accent != color )
{
m_accent = color;
updateColors();
Q_EMIT accentChanged();
}
}
QColor Theme::accent() const
{
return m_accent;
}
void Theme::setSkin( const QString& skinName )
{
if ( skinName == qskSetup->skinName() )
return;
auto oldSkin = qskSetup->skin();
if ( oldSkin->parent() == qskSetup )
oldSkin->setParent( nullptr ); // otherwise setSkin deletes it
auto newSkin = qskSetup->setSkin( skinName );
SkinTransition transition( m_accent );
transition.setSourceSkin( oldSkin );
transition.setTargetSkin( newSkin );
transition.setAnimation( 500 );
transition.process();
if ( oldSkin->parent() == nullptr )
delete oldSkin;
}
QString Theme::skin() const
{
return qskSetup->skinName();
}
void Theme::updateColors()
{
SkinTransition transition( m_accent );
transition.setMask( SkinTransition::Color );
transition.setSourceSkin( qskSetup->skin() );
transition.setTargetSkin( qskSetup->skin() );
transition.setAnimation( 500 );
transition.process();
}
#include "moc_Theme.cpp"

View File

@ -1,35 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#pragma once
#include <QColor>
#include <QObject>
class Theme : public QObject
{
Q_OBJECT
Q_PROPERTY( QColor accent READ accent WRITE setAccent NOTIFY accentChanged )
Q_PROPERTY( QString skin READ skin WRITE setSkin NOTIFY skinChanged )
public:
Theme( QObject* parent = nullptr );
void setAccent( QColor color );
QColor accent() const;
void setSkin( const QString& );
QString skin() const;
Q_SIGNALS:
void accentChanged();
void skinChanged();
private:
void updateColors();
QColor m_accent;
};

View File

@ -1,11 +0,0 @@
CONFIG += qskexample qskqmlexport
RESOURCES += \
colorswitch.qrc
HEADERS += \
Theme.h
SOURCES += \
Theme.cpp \
main.cpp

View File

@ -1,187 +0,0 @@
import QtQuick 2.5
import Skinny 1.0
import Theme 1.0 // things beyond supersimple are way more convenient with C++
Main
{
id: main
property var accentColors: [ "red", "lightgreen", "#66336699" ]
Theme
{
accent: accentColors[ tabBar.currentIndex < 0 ? 0 : tabBar.currentIndex ]
skin: listBox.entries[ listBox.selectedRow ]
}
Window
{
id: window
visible: true
color: "Gainsboro"
width: 600
height: 600
Component.onCompleted:
{
// very much standard: we should find a better way
var hint = sizeConstraint();
setMinimumWidth( hint.width )
setMinimumHeight( hint.height )
}
LinearBox
{
orientation: Qt.Horizontal
spacing: 20
//margins: 8 // so that we can see the focus frame
margins { left: 8; top: 8; right: 8; bottom: 8 }
SimpleListBox
{
id: listBox
preferredWidthFromColumns: true
sizePolicy.horizontalPolicy: SizePolicy.Fixed
entries: main.skinList
selectedRow: 1
}
LinearBox
{
// margins: 10
margins { left: 10; top: 10; right: 10; bottom: 10 }
orientation: Qt.Vertical
defaultAlignment: Qt.AlignCenter
extraSpacingAt: Qt.BottomEdge
TabBar
{
id: tabBar
currentIndex: 1
Instantiator
{
onObjectAdded: {
tabBar.insertTab( index, object );
}
model: accentColors
delegate: TabButton
{
id: tabButton1
sizePolicy.horizontalPolicy: SizePolicy.MinimumExpanding
text: modelData
}
}
}
LinearBox
{
orientation: Qt.Horizontal
dimension: 3
spacing: 20
//margins: 20
margins { left: 20; top: 20; right: 20; bottom: 20 }
sizePolicy
{
horizontalPolicy: SizePolicy.Fixed
verticalPolicy: SizePolicy.Fixed
}
PushButton
{
text: "normal"
focus: true
}
PushButton
{
text: checked ? "checked" : "unchecked"
checked: true
checkable: true
}
PushButton
{
text: "disabled"
enabled: false
}
PushButton
{
text: "flat"
flat: true
}
PushButton
{
text: ( checked ? "\u2714 " : "" ) + "flat"
flat: true
checkable: true
checked: true
}
PushButton
{
text: "flat"
flat: true
enabled: false
}
}
LinearBox
{
spacing: 5
orientation: Qt.Horizontal
sizePolicy
{
horizontalPolicy: SizePolicy.MinimumExpanding
verticalPolicy: SizePolicy.Fixed
}
Slider
{
id: slider
minimum: 0
maximum: 100
value: 42
snap: true
stepSize: 1
}
TextLabel
{
id: sliderValue
FontMetrics
{
id: fontMetrics
}
property rect textRect: fontMetrics.boundingRect("100")
preferredSize: Qt.size( textRect.width, textRect.height )
sizePolicy: SizePolicy.Fixed
text: slider.value
}
}
}
}
FocusIndicator
{
}
}
}

View File

@ -1,5 +0,0 @@
<RCC>
<qresource prefix="/qml">
<file>colorswitch.qml</file>
</qresource>
</RCC>

View File

@ -1,38 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "Theme.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskQml.h>
#include <QskObjectCounter.h>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
int main( int argc, char* argv[] )
{
#ifdef ITEM_STATISTICS
QskObjectCounter counter( true );
#endif
qputenv( "QT_IM_MODULE", "skinny" );
QskQml::registerTypes();
qmlRegisterType< Theme >( "Theme", 1, 0, "Theme" );
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::Quit |
SkinnyShortcut::ChangeFonts | SkinnyShortcut::DebugShortcuts );
QQmlApplicationEngine engine( QUrl( "qrc:/qml/colorswitch.qml" ) );
return app.exec();
}

View File

@ -32,7 +32,6 @@ qtHaveModule(svg) {
SUBDIRS += \
boxes \
buttons \
colorswitch \
frames \
gbenchmark \
glabels \

View File

@ -4,29 +4,11 @@
*****************************************************************************/
#include "Page.h"
#include <QskRgbValue.h>
Page::Page( Qt::Orientation orientation, QQuickItem* parent )
: QskLinearBox( orientation, parent )
, m_gradient( QskRgb::GhostWhite )
{
setMargins( 20 );
setPadding( 10 );
setSpacing( 10 );
}
void Page::setGradient( const QskGradient& gradient )
{
if ( gradient != m_gradient )
{
m_gradient = gradient;
if ( parentItem() && isVisibleToParent() )
parentItem()->update();
}
}
QskGradient Page::gradient() const
{
return m_gradient;
}

View File

@ -6,16 +6,9 @@
#pragma once
#include <QskLinearBox.h>
#include <QskGradient.h>
class Page : public QskLinearBox
{
public:
Page( Qt::Orientation, QQuickItem* parent = nullptr );
void setGradient( const QskGradient& );
QskGradient gradient() const;
private:
QskGradient m_gradient;
};

View File

@ -0,0 +1,116 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "ButtonPage.h"
#include <QskSwitchButton.h>
#include <QskPushButton.h>
#include <QskCheckBox.h>
#include <QskSeparator.h>
#include <QskLinearBox.h>
namespace
{
class ButtonBox : public QskLinearBox
{
public:
ButtonBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, 4, parent )
{
setSpacing( 20 );
setExtraSpacingAt( Qt::BottomEdge );
setDefaultAlignment( Qt::AlignCenter );
populate();
}
private:
void populate()
{
const char* texts[] = { "Press Me", "Check Me" };
const char* graphics[] = { "diamond/khaki", "ellipse/sandybrown" };
for ( int i = 0; i < 6; i++ )
{
const int index = i % 2;
auto button = new QskPushButton( this );
button->setCheckable( index != 0 );
//button->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
if ( i > 1 )
{
auto src = QStringLiteral( "image://shapes/" ) + graphics[ index ];
button->setGraphicSource( src );
}
if ( i < 2 || i > 3 )
{
button->setText( texts[ index ] );
}
}
}
};
class SwitchButtonBox : public QskLinearBox
{
public:
SwitchButtonBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
setSpacing( 20 );
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
for ( auto orientation : { Qt::Vertical, Qt::Horizontal } )
{
(void) new QskSwitchButton( orientation, this );
auto button = new QskSwitchButton( orientation, this );
button->setChecked( true );
button = new QskSwitchButton( orientation, this );
button->setInverted( true );
button = new QskSwitchButton( orientation, this );
button->setInverted( true );
button->setChecked( true );
}
}
};
class CheckButtonBox : public QskLinearBox
{
public:
CheckButtonBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
setSpacing( 20 );
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
for ( auto state : { Qt::Unchecked, Qt::PartiallyChecked, Qt::Checked } )
{
auto button = new QskCheckBox( this );
button->setTristate( true );
button->setCheckState( state );
}
}
};
}
ButtonPage::ButtonPage( QQuickItem* parent )
: Page( Qt::Vertical, parent )
{
setSpacing( 40 );
populate();
}
void ButtonPage::populate()
{
new ButtonBox( this );
new QskSeparator( Qt::Horizontal, this );
new SwitchButtonBox( this );
new QskSeparator( Qt::Horizontal, this );
new CheckButtonBox( this );
}

View File

@ -7,10 +7,10 @@
#include "Page.h"
class SwitchButtonPage : public Page
class ButtonPage : public Page
{
public:
SwitchButtonPage( QQuickItem* = nullptr );
ButtonPage( QQuickItem* = nullptr );
private:
void populate();

View File

@ -7,15 +7,9 @@ SOURCES += \
label/LabelPage.cpp \
HEADERS += \
slider/CustomSlider.h \
slider/CustomSliderSkinlet.h \
slider/OtherSlider.h \
slider/SliderPage.h
SOURCES += \
slider/CustomSlider.cpp \
slider/CustomSliderSkinlet.cpp \
slider/OtherSlider.cpp \
slider/SliderPage.cpp
HEADERS += \
@ -25,10 +19,10 @@ SOURCES += \
progressbar/ProgressBarPage.cpp \
HEADERS += \
switchbutton/SwitchButtonPage.h
button/ButtonPage.h
SOURCES += \
switchbutton/SwitchButtonPage.cpp \
button/ButtonPage.cpp \
HEADERS += \
Page.h

View File

@ -8,29 +8,51 @@
#include <QskGraphicLabel.h>
#include <QskSeparator.h>
#include <QskRgbValue.h>
#include <QskSkin.h>
namespace
{
class TextLabel : public QskTextLabel
{
public:
TextLabel( int role, QQuickItem* parent = nullptr )
: QskTextLabel( parent )
{
setText( textFromRole( role ) );
setFontRole( role );
setSizePolicy( Qt::Horizontal, QskSizePolicy::Ignored );
}
private:
QString textFromRole( int role ) const
{
static QMetaEnum metaEnum;
if ( !metaEnum.isValid() )
{
const auto& mo = QskSkin::staticMetaObject;
metaEnum = mo.enumerator( mo.indexOfEnumerator( "SkinFontRole" ) );
}
QString s( metaEnum.valueToKey( role ) );
s.remove( QStringLiteral( "Font" ) );
return s;
}
};
class TextBox : public QskLinearBox
{
public:
TextBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Vertical, 3, parent )
: QskLinearBox( Qt::Horizontal, 3, parent )
{
setMargins( 10 );
//setDefaultAlignment( Qt::AlignTop );
setExtraSpacingAt( Qt::BottomEdge );
setDefaultAlignment( Qt::AlignCenter );
const QStringList texts =
{ "Default", "Tiny", "Small", "Medium", "Large", "Huge" };
for ( int i = 0; i < texts.size(); i++ )
{
auto label = new QskTextLabel( texts[ i ] + " Font", this );
//label->setPanel( true );
label->setFontRole( i );
}
for ( int i = 0; i <= QskSkin::HugeFont; i++ )
( void ) new TextLabel( i, this );
}
};
@ -67,7 +89,6 @@ namespace
LabelPage::LabelPage( QQuickItem* parent )
: Page( Qt::Vertical, parent )
{
setGradient( QskRgb::AliceBlue );
setSpacing( 40 );
(void) new TextBox( this );

View File

@ -6,15 +6,19 @@
#include "label/LabelPage.h"
#include "progressbar/ProgressBarPage.h"
#include "slider/SliderPage.h"
#include "switchbutton/SwitchButtonPage.h"
#include "button/ButtonPage.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <SkinnyShapeProvider.h>
#include <SkinnyNamespace.h>
#include <QskFocusIndicator.h>
#include <QskObjectCounter.h>
#include <QskTabView.h>
#include <QskTextLabel.h>
#include <QskSwitchButton.h>
#include <QskPushButton.h>
#include <QskMenu.h>
#include <QskWindow.h>
#include <QGuiApplication>
@ -30,27 +34,107 @@ namespace
setMargins( 10 );
setTabPosition( Qsk::Left );
setAutoFitTabs( true );
connect( this, &QskTabView::currentIndexChanged,
this, &TabView::updateViewPanel );
}
protected:
void aboutToShow() override
void setTabsEnabled( bool on )
{
updateViewPanel();
for ( int i = 0; i < count(); i++ )
itemAt( i )->setEnabled( on );
}
};
class MenuButton : public QskPushButton
{
public:
MenuButton( const QString& text, QQuickItem* parent = nullptr )
: QskPushButton( text, parent )
{
setFlat( true ); // until we have the section bit in QskAspect
connect( this, &QskPushButton::pressed, this, &MenuButton::openMenu );
}
private:
void updateViewPanel()
void openMenu()
{
/*
We should have a better way to set individual colors
for each tab page background
*/
auto menu = new QskMenu( window()->contentItem() );
if ( auto page = dynamic_cast< const ::Page* >( currentItem() ) )
setGradientHint( QskTabView::Page, page->gradient() );
menu->addOption( "image://shapes/Rectangle/White", "Print" );
menu->addOption( "image://shapes/Diamond/Yellow", "Save As" );
menu->addOption( "image://shapes/Ellipse/Red", "Setup" );
menu->addSeparator();
menu->addOption( "image://shapes/Hexagon/PapayaWhip", "Help" );
menu->setOrigin( geometry().bottomLeft() );
menu->open();
}
};
/*
Once QskApplicationView and friends are implemented we can replace
Header/ApplicationWindow with it. TODO ...
*/
class Header : public QskLinearBox
{
Q_OBJECT
public:
Header( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
initSizePolicy( QskSizePolicy::Ignored, QskSizePolicy::Fixed );
setMargins( 10 );
setBackgroundColor( Qt::lightGray );
{
auto button = new QskPushButton( "Skin", this );
#if 1
button->setFlat( true ); // until we have the section bit in QskAspect
#endif
// transition leads to errors, when changing the tab before being completed. TODO ...
connect( button, &QskSwitchButton::clicked,
[] { Skinny::changeSkin( 500 ); } );
}
{
new MenuButton( "Menu", this );
}
addStretch( 10 );
{
new QskTextLabel( "Enabled", this );
auto button = new QskSwitchButton( this );
button->setChecked( true );
connect( button, &QskSwitchButton::toggled,
this, &Header::enabledToggled );
}
}
Q_SIGNALS:
void enabledToggled( bool );
};
class ApplicationView : public QskLinearBox
{
public:
ApplicationView( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Vertical, parent )
{
auto header = new Header( this );
auto tabView = new TabView( this );
tabView->addTab( "Labels", new LabelPage() );
tabView->addTab( "Buttons", new ButtonPage() );
tabView->addTab( "Sliders", new SliderPage() );
tabView->addTab( "Progress\nBars", new ProgressBarPage() );
connect( header, &Header::enabledToggled,
tabView, &TabView::setTabsEnabled );
}
};
}
@ -65,21 +149,15 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
auto tabView = new TabView();
tabView->addTab( "Labels", new LabelPage() );
tabView->addTab( "Sliders", new SliderPage() );
tabView->addTab( "Progress\nBars", new ProgressBarPage() );
tabView->addTab( "Switches", new SwitchButtonPage() );
auto mainView = new ApplicationView();
QSize size( 800, 600 );
size = size.expandedTo( tabView->sizeHint().toSize() );
size = size.expandedTo( mainView->sizeHint().toSize() );
QskWindow window;
window.addItem( tabView );
window.addItem( mainView );
window.addItem( new QskFocusIndicator() );
window.resize( size );
@ -87,3 +165,5 @@ int main( int argc, char* argv[] )
return app.exec();
}
#include "main.moc"

View File

@ -45,9 +45,7 @@ namespace
ProgressBarPage::ProgressBarPage( QQuickItem* parent )
: Page( Qt::Horizontal, parent )
{
setGradient( QskRgb::AliceBlue );
setSpacing( 40 );
populate();
}

View File

@ -4,17 +4,28 @@
*****************************************************************************/
#include "SliderPage.h"
#include "CustomSlider.h"
#include "OtherSlider.h"
#include <QskSlider.h>
#include <QskRgbValue.h>
#include <QskMargins.h>
SliderPage::SliderPage( QQuickItem* parentItem )
: Page( Qt::Vertical, parentItem )
namespace
{
setGradient( QskRgb::PeachPuff );
class Slider : public QskSlider
{
public:
Slider( Qt::Orientation orientation, QQuickItem* parent = nullptr )
: QskSlider( orientation, parent )
{
setBoundaries( 0, 1000 );
setPageSize( 10 );
setStepSize( 10 );
setSnap( true );
}
};
}
SliderPage::SliderPage( QQuickItem* parent )
: Page( Qt::Horizontal, parent )
{
setMargins( 10 );
setSpacing( 20 );
@ -37,54 +48,6 @@ SliderPage::SliderPage( QQuickItem* parentItem )
void SliderPage::populate()
{
{
auto slider = new QskSlider( this );
slider->setMinimum( 0 );
slider->setMaximum( 1000 );
slider->setPageSize( 10 );
slider->setStepSize( 10 );
slider->setSnap( true );
}
{
auto slider = new OtherSlider( this );
slider->setMinimum( 0 );
slider->setMaximum( 10 );
slider->setStepSize( 1 );
}
auto hBox = new QskLinearBox( Qt::Horizontal, this );
{
auto slider = new QskSlider( Qt::Vertical, hBox );
slider->setMinimum( 0 );
slider->setMaximum( 1000 );
slider->setPageSize( 10 );
slider->setStepSize( 10 );
slider->setSnap( true );
}
{
auto slider = new OtherSlider( hBox );
slider->setOrientation( Qt::Vertical );
slider->setMinimum( 0 );
slider->setMaximum( 10 );
slider->setStepSize( 1 );
}
{
auto slider = new CustomSlider( this );
slider->setMargins( QskMargins( 0, 15 ) );
slider->setSnap( true );
slider->setMinimum( 0 );
slider->setMaximum( 2000 );
slider->setStepSize( 10 );
slider->setPageSize( 10 );
}
( void ) new Slider( Qt::Horizontal, this );
( void ) new Slider( Qt::Vertical, this );
}

View File

@ -1,56 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "SwitchButtonPage.h"
#include <QskSwitchButton.h>
#include <QskLinearBox.h>
#include <QskTextLabel.h>
#include <QskSeparator.h>
#include <QskRgbValue.h>
SwitchButtonPage::SwitchButtonPage( QQuickItem* parent )
: Page( Qt::Horizontal, parent )
{
setGradient( QskRgb::AliceBlue );
setSpacing( 40 );
populate();
}
void SwitchButtonPage::populate()
{
auto hbox1 = new QskLinearBox();
hbox1->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
hbox1->setExtraSpacingAt( Qt::LeftEdge );
auto label = new QskTextLabel( "Disable the switches:", hbox1 );
label->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
auto button0 = new QskSwitchButton( hbox1 );
auto hbox2 = new QskLinearBox( Qt::Horizontal );
hbox2->setDefaultAlignment( Qt::AlignHCenter | Qt::AlignTop );
hbox2->setMargins( 30 );
(void) new QskSwitchButton( Qt::Vertical, hbox2 );
(void) new QskSwitchButton( Qt::Horizontal, hbox2 );
auto button3 = new QskSwitchButton( Qt::Vertical, hbox2 );
button3->setInverted( true );
auto button4 = new QskSwitchButton( Qt::Horizontal, hbox2 );
button4->setInverted( true );
auto vbox = new QskLinearBox( Qt::Vertical, this );
vbox->addItem( hbox1 );
vbox->addItem( new QskSeparator() );
vbox->addItem( hbox2 );
vbox->setExtraSpacingAt( Qt::BottomEdge );
QObject::connect( button0, &QskSwitchButton::checkedChanged,
hbox2, &QskQuickItem::setDisabled );
}

View File

@ -7,7 +7,6 @@
#include "GraphicProvider.h"
#include "Skin.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskSetup.h>
@ -61,8 +60,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
Qsk::addGraphicProvider( QString(), new GraphicProvider() );
// disable default skins

View File

@ -10,7 +10,6 @@
#include "StackLayoutPage.h"
#include "TestRectangle.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskFocusIndicator.h>
@ -31,7 +30,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
auto tabView = new QskTabView();

View File

@ -3,7 +3,6 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskAspect.h>
@ -65,7 +64,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
QskWindow window;

View File

@ -3,7 +3,6 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QFontDatabase>
@ -126,7 +125,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
qskDialog->setPolicy( QskDialog::EmbeddedBox );

View File

@ -3,7 +3,6 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskQml.h>
@ -22,7 +21,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
QQmlApplicationEngine engine( QUrl( "qrc:/qml/messagebox.qml" ) );

View File

@ -6,7 +6,6 @@
#include "MySkin.h"
#include "MyToggleButton.h"
#include <SkinnyFont.h>
#include <SkinnyShapeProvider.h>
#include <SkinnyShortcut.h>
@ -136,7 +135,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::DebugBackground |
SkinnyShortcut::DebugStatistics | SkinnyShortcut::Quit );

View File

@ -20,11 +20,6 @@
#include <QskTabView.h>
#include <QskBoxShapeMetrics.h>
#ifdef CONTEXT_MENU
#include <QskMenu.h>
#include <QskEvent.h>
#endif
#include <QDir>
#include <QVariant>
@ -46,10 +41,6 @@ class GraphicLabel : public QskGraphicLabel
setBoxShapeHint( Panel, 8 );
setAlignment( Qt::AlignCenter );
setDarknessMode( false );
#ifdef CONTEXT_MENU
setAcceptedMouseButtons( Qt::LeftButton );
#endif
}
void setDarknessMode( bool on )
@ -80,27 +71,6 @@ class GraphicLabel : public QskGraphicLabel
startTransition( QskGraphicLabel::Graphic | QskAspect::GraphicRole,
duration, oldRole, graphicRole() );
}
#ifdef CONTEXT_MENU
protected:
void mousePressEvent( QMouseEvent* event ) override
{
QskMenu menu( this );
menu.setPopupFlag( QskPopup::DeleteOnClose, false );
menu.addOption( "image://shapes/Rectangle/White", "Print" );
menu.addOption( "image://shapes/Diamond/Yellow", "Save As" );
menu.addOption( "image://shapes/Ellipse/Red", "Setup" );
menu.addSeparator();
menu.addOption( "image://shapes/Hexagon/PapayaWhip", "Help" );
menu.setOrigin( qskMousePosition( event ) );
const int result = menu.exec();
if ( result >= 0 )
qDebug() << "Selected:" << result;
}
#endif
};
MainWindow::MainWindow()

View File

@ -5,13 +5,8 @@
#include "MainWindow.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#ifdef CONTEXT_MENU
#include <SkinnyShapeProvider.h>
#endif
#include <QskFocusIndicator.h>
#include <QskObjectCounter.h>
@ -23,13 +18,8 @@ int main( int argc, char* argv[] )
QskObjectCounter counter( true );
#endif
#ifdef CONTEXT_MENU
Qsk::addGraphicProvider( "shapes", new SkinnyShapeProvider() );
#endif
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
QskFocusIndicator* focusIndicator = new QskFocusIndicator();

View File

@ -1,5 +1,4 @@
CONFIG += qskexample
DEFINES += CONTEXT_MENU
HEADERS += \
MainWindow.h

View File

@ -3,7 +3,9 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include "CustomSlider.h"
#include "OtherSlider.h"
#include <SkinnyShortcut.h>
#include <QskAspect.h>
@ -34,6 +36,36 @@ class Label : public QskTextLabel
}
};
class SliderBox : public QskLinearBox
{
public:
SliderBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Vertical, parent )
{
setMargins( 30 );
setSpacing( 50 );
setExtraSpacingAt( Qt::BottomEdge );
{
auto slider = new OtherSlider( this );
slider->setMinimum( 0 );
slider->setMaximum( 10 );
slider->setStepSize( 1 );
}
{
auto slider = new CustomSlider( this );
slider->setSnap( true );
slider->setMinimum( 0 );
slider->setMaximum( 2000 );
slider->setStepSize( 10 );
slider->setPageSize( 10 );
}
}
};
class TabView : public QskTabView
{
public:
@ -44,11 +76,20 @@ class TabView : public QskTabView
{
QString text;
if ( i == 4 )
text = QString( "Another Tab" );
{
const auto text = QStringLiteral( "Another Tab" );
addTab( text, new Label( text ) );
}
else if ( i == 7 )
{
addTab( "Sliders", new SliderBox() );
}
else
text = QString( "Tab %1" ).arg( i + 1 );
{
const auto text = QString( "Tab %1" ).arg( i + 1 );
addTab( text, new Label( text ) );
}
addTab( text, new Label( text ) );
}
buttonAt( 2 )->setEnabled( false );
@ -90,7 +131,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
auto tabView = new TabView();

View File

@ -1,4 +1,12 @@
CONFIG += qskexample
HEADERS += \
CustomSlider.h \
CustomSliderSkinlet.h \
OtherSlider.h \
SOURCES += \
CustomSlider.cpp \
CustomSliderSkinlet.cpp \
OtherSlider.cpp \
main.cpp

View File

@ -0,0 +1,71 @@
=========================
The Kiwi licensing terms
=========================
Kiwi is licensed under the terms of the Modified BSD License (also known as
New or Revised BSD), as follows:
Copyright (c) 2013, Nucleic Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
Neither the name of the Nucleic Development Team nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
About Kiwi
----------
Chris Colbert began the Kiwi project in December 2013 in an effort to
create a blisteringly fast UI constraint solver. Chris is still the
project lead.
The Nucleic Development Team is the set of all contributors to the Nucleic
project and its subprojects.
The core team that coordinates development on GitHub can be found here:
http://github.com/nucleic. The current team consists of:
* Chris Colbert
Our Copyright Policy
--------------------
Nucleic uses a shared copyright model. Each contributor maintains copyright
over their contributions to Nucleic. But, it is important to note that these
contributions are typically only changes to the repositories. Thus, the Nucleic
source code, in its entirety is not the copyright of any single person or
institution. Instead, it is the collective copyright of the entire Nucleic
Development Team. If individual contributors want to maintain a record of what
changes/contributions they have specific copyright on, they should indicate
their copyright in the commit message of the change, when they commit the
change to one of the Nucleic repositories.
With this in mind, the following banner should be used in any source code file
to indicate the copyright and license terms:
#------------------------------------------------------------------------------
# Copyright (c) 2013, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------

View File

@ -0,0 +1,17 @@
This code is a stripped down version of the implementation of the Cassowary constraint
solving algorithm of the Kiwi project:
https://github.com/nucleic/kiwi
All credits go to the Nucleic Development Team !
For the QSkinny use case the following adjustments have been made:
- implementations moved from *.h to *.cpp files
- replacing AssocVector from the Loki Library by yet another stupid
implementation of a "flat map"
I forgot what version of Kiwi had been used - a migration of the code
for a more recent official version will happen soon.

View File

@ -5,7 +5,6 @@
#include "AnchorBox.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskControl.h>
@ -153,7 +152,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::Quit | SkinnyShortcut::DebugShortcuts );
auto box = new MyBox();

View File

@ -5,7 +5,6 @@
#include "Window.h"
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskFocusIndicator.h>
@ -21,7 +20,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
Window window( Qt::Horizontal );

View File

@ -5,8 +5,6 @@
#include "TestBox.h"
#include <SkinnyFont.h>
#include <QskSizePolicy.h>
#include <QskFunctions.h>
@ -389,15 +387,6 @@ int main( int argc, char** argv )
{
QApplication app( argc, argv );
#if 1
/*
we don't need the fonts, but by calling something from
the support library initializations regarding the skins
are loaded. TODO ...
*/
SkinnyFont::init( &app );
#endif
int testcase = 0;
if ( argc == 2 )
testcase = atoi( argv[1] );

View File

@ -17,7 +17,8 @@ Qsk.Window
orientation: Qt.Horizontal
dimension: 3
margins: 10
//margins: 10 // only possible with Qt <= 6.1
margins { left: 10; top: 10; right: 10; bottom: 10 }
spacing: 10
Repeater

View File

@ -3,7 +3,6 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskDialog.h>
@ -285,7 +284,6 @@ int main( int argc, char* argv[] )
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
#if 1

View File

@ -3,7 +3,6 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include <SkinnyFont.h>
#include <SkinnyShortcut.h>
#include <QskWindow.h>
@ -43,7 +42,6 @@ int main( int argc, char* argv[] )
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app( argc, argv );
SkinnyFont::init( &app );
SkinnyShortcut::enable( SkinnyShortcut::Quit | SkinnyShortcut::DebugShortcuts );
QskWindow window;

View File

@ -8,11 +8,13 @@
#include <QskSkinHintTableEditor.h>
#include <QskBox.h>
#include <QskCheckBox.h>
#include <QskDialogButton.h>
#include <QskDialogButtonBox.h>
#include <QskFocusIndicator.h>
#include <QskInputPanelBox.h>
#include <QskListView.h>
#include <QskMenu.h>
#include <QskPageIndicator.h>
#include <QskPushButton.h>
#include <QskProgressBar.h>
@ -112,12 +114,14 @@ namespace
void setupControl();
void setupBox();
void setupCheckBox();
void setupDialogButtonBox();
void setupDialogButton();
void setupFocusIndicator();
void setupInputPanel();
void setupVirtualKeyboard();
void setupListView();
void setupMenu();
void setupPageIndicator();
void setupPopup();
void setupProgressBar();
@ -142,12 +146,14 @@ void Editor::setup()
setupControl();
setupBox();
setupCheckBox();
setupDialogButtonBox();
setupDialogButton();
setupFocusIndicator();
setupInputPanel();
setupVirtualKeyboard();
setupListView();
setupMenu();
setupPageIndicator();
setupPopup();
setupProgressBar();
@ -177,6 +183,27 @@ void Editor::setupControl()
qskShadedColor( m_pal.textColor, 0.6 ) );
}
void Editor::setupCheckBox()
{
using A = QskAspect;
using Q = QskCheckBox;
const qreal size = qskDpiScaled( 18 );
setStrutSize( Q::Panel, size, size );
setPadding( Q::Panel, 3 );
setBoxShape( Q::Panel, 2 );
setGradient( Q::Panel, m_pal.baseColor);
setGradient( Q::Panel | Q::Checked, m_pal.accentColor );
setGradient( Q::Panel | Q::Checked | Q::Disabled, QskRgb::Grey );
setColor( Q::Indicator, m_pal.contrastColor );
setAnimation( Q::Panel | A::Color, qskDuration );
}
void Editor::setupBox()
{
using Q = QskBox;
@ -199,6 +226,45 @@ void Editor::setupPopup()
setGradient( Q::Overlay, gradient );
}
void Editor::setupMenu()
{
using A = QskAspect;
using Q = QskMenu;
setBoxShape( Q::Panel, qskDpiScaled( 4 ) );
setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) );
setBoxBorderColors( Q::Panel, m_pal.darker125 );
setGradient( Q::Panel, m_pal.baseColor );
const bool isCascading = qskMaybeDesktopPlatform();
setFlagHint( Q::Panel | A::Style, isCascading );
#if 0
setPadding( Q::Separator, QMarginsF( 10, 0, 10, 0 ) );
#endif
setMetric( Q::Separator | A::Size, qskDpiScaled( 1 ) );
setBoxShape( Q::Separator, 0 );
setBoxBorderMetrics( Q::Separator, 0 );
setGradient( Q::Separator, m_pal.darker125 );
setPadding( Q::Cell, QskMargins( 2, 10, 2, 10 ) );
setSpacing( Q::Cell, 5 );
setGradient( Q::Cell, Qt::transparent );
setGradient( Q::Cursor, m_pal.accentColor );
setColor( Q::Text, m_pal.textColor );
setColor( Q::Text | Q::Selected, m_pal.contrastColor );
setFontRole( Q::Text, QskSkin::SmallFont );
setPosition( Q::Panel, 0 );
setPosition( Q::Panel | QskPopup::Closed, 1 );
setAnimation( Q::Panel | A::Metric, 150 );
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
}
void Editor::setupTextLabel()
{
using Q = QskTextLabel;

View File

@ -24,7 +24,7 @@ QStringList QskMaterialSkinFactory::skinNames() const
QskSkin* QskMaterialSkinFactory::createSkin( const QString& skinName )
{
if ( skinName.toLower() == materialSkinName )
if ( QString::compare( skinName, materialSkinName, Qt::CaseInsensitive ) == 0 )
return new QskMaterialSkin();
return nullptr;

View File

@ -8,6 +8,7 @@
#include <QskSkinHintTableEditor.h>
#include <QskBox.h>
#include <QskCheckBox.h>
#include <QskDialogButton.h>
#include <QskDialogButtonBox.h>
#include <QskFocusIndicator.h>
@ -132,6 +133,7 @@ namespace
void setupControl();
void setupBox();
void setupCheckBox();
void setupDialogButton();
void setupDialogButtonBox();
void setupFocusIndicator();
@ -251,6 +253,7 @@ void Editor::setup()
setupControl();
setupBox();
setupCheckBox();
setupDialogButtonBox();
setupDialogButton();
setupFocusIndicator();
@ -292,6 +295,28 @@ void Editor::setupBox()
setPanel( QskBox::Panel, Plain );
}
void Editor::setupCheckBox()
{
using A = QskAspect;
using Q = QskCheckBox;
const qreal size = qskDpiScaled( 26 );
setStrutSize( Q::Panel, size, size );
setPadding( Q::Panel, qskDpiScaled( 5 ) );
setBoxShape( Q::Panel, qskDpiScaled( 3 ) );
setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) );
setBoxBorderColors( Q::Panel, m_pal.darker125 );
setGradient( Q::Panel, m_pal.lighter135 );
setGradient( Q::Panel | Q::Checked, m_pal.highlighted );
setColor( Q::Indicator, m_pal.lighter135 );
setAnimation( Q::Panel | A::Color, qskDuration );
}
void Editor::setupPopup()
{
using A = QskAspect;
@ -306,11 +331,11 @@ void Editor::setupMenu()
using A = QskAspect;
using Q = QskMenu;
const QColor c1( 78, 158, 38 );
const QColor c2( 15, 103, 43 );
setBoxShape( Q::Panel, qskDpiScaled( 4 ) );
setBoxBorderMetrics( Q::Panel, qskDpiScaled( 1 ) );
setBoxBorderColors( Q::Panel, m_pal.darker125 );
setBoxShape( Q::Panel, 4 );
setVGradient( Q::Panel, c1, c2 );
setGradient( Q::Panel, m_pal.lighter110 );
const bool isCascading = qskMaybeDesktopPlatform();
setFlagHint( Q::Panel | A::Style, isCascading );
@ -318,16 +343,17 @@ void Editor::setupMenu()
#if 0
setPadding( Q::Separator, QMarginsF( 10, 0, 10, 0 ) );
#endif
setMetric( Q::Separator | A::Size, 2 );
setMetric( Q::Separator | A::Size, qskDpiScaled( 2 ) );
setSeparator( Q::Separator | A::Horizontal );
setPadding( Q::Cell, QskMargins( 2, 10, 2, 10 ) );
setSpacing( Q::Cell, 5 );
setGradient( Q::Cell, Qt::transparent );
setHGradient( Q::Cursor, c2, c2.lighter( 2 ) );
setGradient( Q::Cursor, m_pal.highlighted );
setColor( Q::Text, QColor( 255, 255, 255 ) );
setColor( Q::Text, m_pal.contrastedText );
setColor( Q::Text | Q::Selected, m_pal.highlightedText );
setFontRole( Q::Text, QskSkin::SmallFont );
setPosition( Q::Panel, 0 );
@ -892,7 +918,7 @@ void Editor::setupSwitchButton()
using A = QskAspect;
using Q = QskSwitchButton;
const qreal radius = qskDpiScaled( 18 );
const qreal radius = qskDpiScaled( 12 );
const qreal handleSize = 2 * ( radius - 2 );
setBoxShape( Q::Groove, 100, Qt::RelativeSize );

View File

@ -24,7 +24,7 @@ QStringList QskSquiekSkinFactory::skinNames() const
QskSkin* QskSquiekSkinFactory::createSkin( const QString& skinName )
{
if ( skinName.toLower() == squiekSkinName )
if ( QString::compare( skinName, squiekSkinName, Qt::CaseInsensitive ) == 0 )
return new QskSquiekSkin();
return nullptr;

View File

@ -11,6 +11,10 @@
static void qskRegisterArcMetrics()
{
qRegisterMetaType< QskArcMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskArcMetrics >();
#endif
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterArcMetrics )

View File

@ -144,7 +144,7 @@ QVector< QskAspect::Subcontrol > QskAspect::subControls( const QMetaObject* meta
static QByteArray qskEnumString( const char* name, int value )
{
const QMetaObject& mo = QskAspect::staticMetaObject;
const auto& mo = QskAspect::staticMetaObject;
const QMetaEnum metaEnum = mo.enumerator( mo.indexOfEnumerator( name ) );
const char* key = metaEnum.valueToKey( value );

View File

@ -109,8 +109,18 @@ class QSK_EXPORT QskAspect
constexpr QskAspect operator|( Type ) const noexcept;
constexpr QskAspect operator|( Primitive ) const noexcept;
constexpr QskAspect operator|( Placement ) const noexcept;
constexpr QskAspect operator|( State ) const noexcept;
QskAspect& operator|=( State ) noexcept;
constexpr QskAspect operator&( State ) const noexcept;
QskAspect& operator&=( State ) noexcept;
constexpr QskAspect operator|( States ) const noexcept;
QskAspect& operator|=( States ) noexcept;
constexpr QskAspect operator&( States ) const noexcept;
QskAspect& operator&=( States ) noexcept;
constexpr QskAspect stateless() const noexcept;
constexpr QskAspect trunk() const noexcept;
@ -283,12 +293,48 @@ inline constexpr QskAspect QskAspect::operator|( State state ) const noexcept
m_bits.primitive, m_bits.placement, m_bits.states | state );
}
inline QskAspect& QskAspect::operator|=( State state ) noexcept
{
m_bits.states |= state;
return *this;
}
inline constexpr QskAspect QskAspect::operator&( State state ) const noexcept
{
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
m_bits.primitive, m_bits.placement, m_bits.states & state );
}
inline QskAspect& QskAspect::operator&=( State state ) noexcept
{
m_bits.states &= state;
return *this;
}
inline constexpr QskAspect QskAspect::operator|( States states ) const noexcept
{
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
m_bits.primitive, m_bits.placement, m_bits.states | states );
}
inline QskAspect& QskAspect::operator|=( States states ) noexcept
{
m_bits.states |= states;
return *this;
}
inline constexpr QskAspect QskAspect::operator&( States states ) const noexcept
{
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
m_bits.primitive, m_bits.placement, m_bits.states & states );
}
inline QskAspect& QskAspect::operator&=( States states ) noexcept
{
m_bits.states &= states;
return *this;
}
inline constexpr QskAspect QskAspect::stateless() const noexcept
{
return QskAspect( m_bits.subControl, m_bits.type, m_bits.isAnimator,
@ -538,6 +584,11 @@ namespace std
};
}
inline QskHashValue qHash( const QskAspect aspect, QskHashValue seed = 0 ) noexcept
{
return qHash( aspect.value(), seed );
}
#ifndef QT_NO_DEBUG_STREAM
class QDebug;

View File

@ -13,6 +13,10 @@ static void qskRegisterBoxBorderColors()
{
qRegisterMetaType< QskBoxBorderColors >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskBoxBorderColors >();
#endif
QMetaType::registerConverter< QColor, QskBoxBorderColors >(
[]( const QColor& color ) { return QskBoxBorderColors( color ); } );
@ -110,6 +114,26 @@ void QskBoxBorderColors::setGradientAt( Qt::Edges edges, const QskGradient& grad
m_gradients[ Qsk::Bottom ] = gradient;
}
void QskBoxBorderColors::setLeft( const QskGradient& gradient )
{
m_gradients[ Qsk::Left ] = gradient;
}
void QskBoxBorderColors::setTop( const QskGradient& gradient )
{
m_gradients[ Qsk::Top ] = gradient;
}
void QskBoxBorderColors::setRight( const QskGradient& gradient )
{
m_gradients[ Qsk::Right ] = gradient;
}
void QskBoxBorderColors::setBottom( const QskGradient& gradient )
{
m_gradients[ Qsk::Bottom ] = gradient;
}
const QskGradient& QskBoxBorderColors::gradientAt( Qt::Edge edge ) const
{
switch ( edge )
@ -165,6 +189,14 @@ bool QskBoxBorderColors::isMonochrome() const
&& m_gradients[ 3 ].isMonochrome();
}
bool QskBoxBorderColors::isValid() const
{
return m_gradients[ 0 ].isValid()
|| m_gradients[ 1 ].isValid()
|| m_gradients[ 2 ].isValid()
|| m_gradients[ 3 ].isValid();
}
QskBoxBorderColors QskBoxBorderColors::interpolated(
const QskBoxBorderColors& to, qreal ratio ) const
{
@ -172,8 +204,14 @@ QskBoxBorderColors QskBoxBorderColors::interpolated(
for ( size_t i = 0; i < 4; i++ )
{
colors.m_gradients[ i ] = colors.m_gradients[ i ].interpolated(
to.m_gradients[ i ], ratio );
#if 1
/*
When one border has a width of 0 we would prefer to ignore
the color and use always use the other color. TODO ...
*/
#endif
auto& gradient = colors.m_gradients[ i ];
gradient = gradient.interpolated( to.m_gradients[ i ], ratio );
}
return colors;
@ -204,14 +242,44 @@ QDebug operator<<( QDebug debug, const QskBoxBorderColors& colors )
QDebugStateSaver saver( debug );
debug.nospace();
debug << "BoxBorderColors" << '(';
debug << "BoxBorderColors";
debug << " L" << colors.gradient( Qsk::Left );
debug << ", T" << colors.gradient( Qsk::Top );
debug << ", R" << colors.gradient( Qsk::Right );
debug << ", B" << colors.gradient( Qsk::Bottom );
if ( !colors.isValid() )
{
debug << "()";
}
else
{
debug << "( ";
debug << " )";
if ( colors.isMonochrome() )
{
const auto& gradient = colors.gradient( Qsk::Left );
QskRgb::debugColor( debug, gradient.startColor() );
}
else
{
const char prompts[] = { 'L', 'T', 'R', 'B' };
for ( int i = 0; i <= Qsk::Bottom; i++ )
{
if ( i != 0 )
debug << ", ";
const auto& gradient = colors.gradient(
static_cast< Qsk::Position >( i ) );
debug << prompts[ i ] << ": ";
if ( gradient.isValid() && gradient.isMonochrome() )
QskRgb::debugColor( debug, gradient.startColor() );
else
debug << gradient;
}
}
debug << " )";
}
return debug;
}

View File

@ -12,10 +12,15 @@
#include <qcolor.h>
#include <qmetatype.h>
class QDebug;
class QSK_EXPORT QskBoxBorderColors
{
Q_GADGET
Q_PROPERTY( QskGradient left READ left WRITE setLeft )
Q_PROPERTY( QskGradient top READ top WRITE setTop )
Q_PROPERTY( QskGradient right READ right WRITE setRight )
Q_PROPERTY( QskGradient bottom READ bottom WRITE setBottom )
public:
QskBoxBorderColors();
@ -44,6 +49,18 @@ class QSK_EXPORT QskBoxBorderColors
void setGradientAt( Qt::Edges, const QskGradient& );
const QskGradient& gradientAt( Qt::Edge ) const;
void setLeft( const QskGradient& );
const QskGradient& left() const;
void setTop( const QskGradient& );
const QskGradient& top() const;
void setRight( const QskGradient& );
const QskGradient& right() const;
void setBottom( const QskGradient& );
const QskGradient& bottom() const;
QskBoxBorderColors interpolated( const QskBoxBorderColors&, qreal value ) const;
static QVariant interpolate( const QskBoxBorderColors&,
@ -53,6 +70,7 @@ class QSK_EXPORT QskBoxBorderColors
bool isMonochrome() const;
bool isVisible() const;
bool isValid() const;
private:
QskGradient m_gradients[ 4 ];
@ -78,8 +96,29 @@ inline const QskGradient& QskBoxBorderColors::gradient( Qsk::Position position )
return m_gradients[ position ];
}
inline const QskGradient& QskBoxBorderColors::left() const
{
return m_gradients[ Qsk::Left ];
}
inline const QskGradient& QskBoxBorderColors::top() const
{
return m_gradients[ Qsk::Top ];
}
inline const QskGradient& QskBoxBorderColors::right() const
{
return m_gradients[ Qsk::Right ];
}
inline const QskGradient& QskBoxBorderColors::bottom() const
{
return m_gradients[ Qsk::Bottom ];
}
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
QSK_EXPORT QDebug operator<<( QDebug, const QskBoxBorderColors& );
#endif

View File

@ -12,6 +12,10 @@ static void qskRegisterBoxBorderMetrics()
{
qRegisterMetaType< QskBoxBorderMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskBoxBorderMetrics >();
#endif
QMetaType::registerConverter< QskMargins, QskBoxBorderMetrics >(
[]( const QskMargins& margins ) { return QskBoxBorderMetrics( margins ); } );
@ -109,9 +113,24 @@ QDebug operator<<( QDebug debug, const QskBoxBorderMetrics& metrics )
QDebugStateSaver saver( debug );
debug.nospace();
debug << "BoxBorder" << '(';
debug << metrics.sizeMode() << ',' << metrics.widths();
debug << ')';
debug << "BoxBorder" << "( ";
if ( metrics.sizeMode() != Qt::AbsoluteSize )
debug << metrics.sizeMode() << ", ";
const auto& w = metrics.widths();
if ( metrics.isEquidistant() )
{
debug << w.left();
}
else
{
const char s[] = ", ";
debug << w.left() << s << w.top() << s << w.right() << s << w.bottom();
}
debug << " )";
return debug;
}

View File

@ -60,6 +60,8 @@ class QSK_EXPORT QskBoxBorderMetrics
static QVariant interpolate( const QskBoxBorderMetrics&,
const QskBoxBorderMetrics&, qreal progress );
constexpr bool isEquidistant() const noexcept;
private:
QskMargins m_widths;
Qt::SizeMode m_sizeMode;
@ -115,6 +117,11 @@ inline constexpr bool QskBoxBorderMetrics::isNull() const noexcept
return m_widths.isNull();
}
inline constexpr bool QskBoxBorderMetrics::isEquidistant() const noexcept
{
return m_widths.isEquidistant();
}
inline constexpr const QskMargins& QskBoxBorderMetrics::widths() const noexcept
{
return m_widths;

View File

@ -14,6 +14,10 @@ static void qskRegisterBoxShapeMetrics()
{
qRegisterMetaType< QskBoxShapeMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskBoxShapeMetrics >();
#endif
QMetaType::registerConverter< int, QskBoxShapeMetrics >(
[]( int radius ) { return QskBoxShapeMetrics( radius ); } );

View File

@ -15,6 +15,10 @@ static void qskRegisterGradient()
{
qRegisterMetaType< QskGradient >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskGradient >();
#endif
QMetaType::registerConverter< QColor, QskGradient >(
[]( const QColor& color ) { return QskGradient( color ); } );
}
@ -503,6 +507,14 @@ QskGradient QskGradient::interpolated(
return QskGradient( gradient->orientation(), stops );
}
if ( isMonochrome() && to.isMonochrome() )
{
const auto c = QskRgb::interpolated(
m_stops[ 0 ].color(), to.m_stops[ 0 ].color(), value );
return QskGradient( to.orientation(), c, c );
}
if ( isMonochrome() )
{
// we can ignore our stops
@ -628,7 +640,49 @@ void QskGradient::updateStatusBits() const
QDebug operator<<( QDebug debug, const QskGradient& gradient )
{
debug << "GR:" << gradient.orientation() << gradient.stops().count();
QDebugStateSaver saver( debug );
debug.nospace();
debug << "Gradient";
if ( !gradient.isValid() )
{
debug << "()";
}
else
{
debug << "( ";
if ( gradient.isMonochrome() )
{
QskRgb::debugColor( debug, gradient.startColor() );
}
else
{
const char o[] = { 'H', 'V', 'D' };
debug << o[ gradient.orientation() ] << ", ";
if ( gradient.stops().count() == 2 )
{
QskRgb::debugColor( debug, gradient.startColor() );
debug << ", ";
QskRgb::debugColor( debug, gradient.endColor() );
}
else
{
const auto& s = gradient.stops();
for ( int i = 0; i < s.count(); i++ )
{
if ( i != 0 )
debug << ", ";
debug << s[i];
}
}
}
debug << " )";
}
return debug;
}

View File

@ -49,7 +49,6 @@ class QSK_EXPORT QskGradient
QskGradient( QRgb );
QskGradient( const QColor& );
QskGradient( Qt::Orientation, const QVector< QskGradientStop >& );
QskGradient( Qt::Orientation, const QColor&, const QColor& );

View File

@ -14,6 +14,10 @@
static void qskRegisterGradientStop()
{
qRegisterMetaType< QskGradientStop >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskGradientStop >();
#endif
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterGradientStop )
@ -78,7 +82,12 @@ QColor QskGradientStop::interpolated(
QDebug operator<<( QDebug debug, const QskGradientStop& stop )
{
debug << stop.position() << ": " << stop.color();
QDebugStateSaver saver( debug );
debug.nospace();
debug << stop.position() << ": ";
QskRgb::debugColor( debug, stop.color() );
return debug;
}

View File

@ -47,7 +47,10 @@ class QSK_EXPORT QskGradientStop
QColor m_color; // using RGBA instead ?
};
Q_DECLARE_TYPEINFO( QskGradientStop, Q_MOVABLE_TYPE );
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
Q_DECLARE_TYPEINFO( QskGradientStop, Q_RELOCATABLE_TYPE );
#endif
Q_DECLARE_METATYPE( QskGradientStop )
inline QskGradientStop::QskGradientStop() noexcept

View File

@ -12,6 +12,10 @@
static void qskRegisterIntervalF()
{
qRegisterMetaType< QskIntervalF >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskIntervalF >();
#endif
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterIntervalF )

View File

@ -61,6 +61,7 @@ class QSK_EXPORT QskMargins : public QMarginsF
QskMargins interpolated( const QskMargins&, qreal progress ) const noexcept;
constexpr bool isExpanding() const noexcept;
constexpr bool isEquidistant() const noexcept;
static QVariant interpolate( const QskMargins&,
const QskMargins&, qreal progress ) noexcept;
@ -181,6 +182,11 @@ constexpr inline qreal QskMargins::height() const noexcept
return top() + bottom();
}
inline constexpr bool QskMargins::isEquidistant() const noexcept
{
return ( left() == top() ) && ( left() == right() ) && ( left() == bottom() );
}
Q_DECLARE_TYPEINFO( QskMargins, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( QskMargins )

View File

@ -172,3 +172,29 @@ QRgb QskRgb::darker( QRgb rgb, int factor ) noexcept
return QColor::fromRgba( rgb ).darker( factor ).rgba();
}
#ifndef QT_NO_DEBUG_STREAM
#include <qdebug.h>
void QskRgb::debugColor( QDebug debug, const QColor& color )
{
debugColor( debug, color.rgba() );
}
void QskRgb::debugColor( QDebug debug, QRgb rgb )
{
QDebugStateSaver saver( debug );
debug.nospace();
debug << '[';
debug << qRed( rgb ) << "r," << qGreen( rgb ) << "g,"
<< qBlue( rgb ) << 'b';
if ( qAlpha( rgb ) != 255 )
debug << ',' << qAlpha( rgb ) << 'a';
debug << ']';
}
#endif

View File

@ -461,23 +461,35 @@ namespace QskRgb
return ( rgb & ColorMask ) | ( ( static_cast< uint >( alpha ) & 0xffu ) << 24 );
}
inline QColor toTransparentF( const QColor& color, qreal alpha )
inline QColor toTransparentF( const QColor& color, qreal opacity )
{
return toTransparent( color, qRound( alpha * 255 ) );
return toTransparent( color, qRound( opacity * 255 ) );
}
inline QColor toTransparentF( Qt::GlobalColor color, qreal alpha )
inline QColor toTransparentF( Qt::GlobalColor color, qreal opacity )
{
return toTransparent( QColor( color ), qRound( alpha * 255 ) );
return toTransparent( QColor( color ), qRound( opacity * 255 ) );
}
inline constexpr QRgb toTransparentF( QRgb rgb, qreal alpha ) noexcept
inline constexpr QRgb toTransparentF( QRgb rgb, qreal opacity ) noexcept
{
return toTransparent( rgb, qRound( alpha * 255 ) );
return toTransparent( rgb, qRound( opacity * 255 ) );
}
QSK_EXPORT QRgb lighter( QRgb, int factor = 150 ) noexcept;
QSK_EXPORT QRgb darker( QRgb, int factor = 200 ) noexcept;
}
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
namespace QskRgb
{
QSK_EXPORT void debugColor( QDebug, const QColor& );
QSK_EXPORT void debugColor( QDebug, QRgb );
}
#endif
#endif

View File

@ -9,6 +9,10 @@
static void qskRegisterTickmarks()
{
qRegisterMetaType< QskScaleTickmarks >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskScaleTickmarks >();
#endif
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterTickmarks )

View File

@ -12,6 +12,10 @@
static void qskRegisterShadowMetrics()
{
qRegisterMetaType< QskShadowMetrics >();
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::registerEqualsComparator< QskShadowMetrics >();
#endif
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterShadowMetrics )

View File

@ -1,14 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskStateCombination.h"
static void qskRegisterStateCombination()
{
qRegisterMetaType< QskStateCombination >();
}
Q_CONSTRUCTOR_FUNCTION( qskRegisterStateCombination )

View File

@ -21,6 +21,9 @@ class QSK_EXPORT QskStateCombination
constexpr QskStateCombination( QskAspect::States = QskAspect::States() ) noexcept;
constexpr QskStateCombination( Type, QskAspect::States = QskAspect::States() ) noexcept;
constexpr bool operator==( QskStateCombination ) const noexcept;
constexpr bool operator!=( QskStateCombination ) const noexcept;
constexpr bool isNull() const noexcept;
void setType( Type ) noexcept;
@ -36,7 +39,6 @@ class QSK_EXPORT QskStateCombination
};
Q_DECLARE_TYPEINFO( QskStateCombination, Q_MOVABLE_TYPE );
Q_DECLARE_METATYPE( QskStateCombination )
constexpr inline QskStateCombination::QskStateCombination(
QskAspect::State state ) noexcept
@ -90,4 +92,14 @@ constexpr inline QskAspect::States QskStateCombination::states() const noexcept
return m_states;
}
constexpr bool QskStateCombination::operator==( QskStateCombination other ) const noexcept
{
return ( m_type == other.m_type ) && ( m_states == other.m_states );
}
constexpr bool QskStateCombination::operator!=( QskStateCombination other ) const noexcept
{
return !( *this == other );
}
#endif

View File

@ -0,0 +1,184 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskCheckBox.h"
#include "QskAspect.h"
#include <qset.h>
QSK_SUBCONTROL( QskCheckBox, Panel )
QSK_SUBCONTROL( QskCheckBox, Indicator )
QSK_SYSTEM_STATE( QskCheckBox, PartiallyChecked, QskAspect::LastUserState << 2 )
class QskCheckBox::PrivateData
{
public:
PrivateData()
: checkState( Qt::Unchecked )
, checkStateChanging( false )
, toggleChanging( false )
, tristate( false )
{
}
QSet< QskAbstractButton* > group;
int groupItemsChecked = 0;
Qt::CheckState checkState : 2;
bool checkStateChanging : 1;
bool toggleChanging : 1;
bool tristate : 1;
};
QskCheckBox::QskCheckBox( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
setAcceptHoverEvents( true );
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
connect( this, &QskCheckBox::checkedChanged, this,
[ this ]( bool on ) { setCheckStateInternal( on ? Qt::Checked : Qt::Unchecked ); } );
}
QskCheckBox::~QskCheckBox()
{
Q_EMIT removeFromAllGroupsRequested();
}
bool QskCheckBox::isCheckable() const
{
return true;
}
Qt::CheckState QskCheckBox::checkState() const
{
return m_data->checkState;
}
void QskCheckBox::setCheckStateInternal( Qt::CheckState checkState )
{
if( m_data->checkStateChanging )
return;
setSkinStateFlag( PartiallyChecked, checkState == Qt::PartiallyChecked );
m_data->checkState = checkState;
Q_EMIT checkStateChanged( checkState );
}
void QskCheckBox::setCheckState( Qt::CheckState checkState )
{
if( checkState == m_data->checkState )
return;
m_data->checkStateChanging = true;
if( checkState == Qt::PartiallyChecked )
{
setChecked( true );
setTristate( true );
}
else
{
setChecked( checkState == Qt::Checked );
}
m_data->checkStateChanging = false;
setCheckStateInternal( checkState );
}
bool QskCheckBox::isTristate() const
{
return m_data->tristate;
}
void QskCheckBox::setTristate( bool tristate )
{
if( m_data->tristate != tristate )
{
m_data->tristate = tristate;
Q_EMIT tristateChanged( tristate );
}
}
void QskCheckBox::updated()
{
if( m_data->toggleChanging )
return;
const auto& groupItemsChecked = m_data->groupItemsChecked;
if( groupItemsChecked == m_data->group.size() )
{
setCheckState( Qt::Checked );
}
else if ( groupItemsChecked == 0 )
{
setCheckState( Qt::Unchecked );
}
else
{
setCheckState( Qt::PartiallyChecked );
}
}
void QskCheckBox::addToGroup( QskCheckBox* groupItem )
{
if( m_data->group.contains( groupItem ) )
return;
m_data->group.insert( groupItem );
if( groupItem->checkState() == Qt::Checked )
m_data->groupItemsChecked++;
updated();
connect( this, &QskCheckBox::checkStateChanged,
groupItem, [ this, groupItem ]( Qt::CheckState checkState )
{
if( checkState == Qt::Checked )
{
m_data->toggleChanging = true;
groupItem->setChecked( true );
m_data->groupItemsChecked = m_data->group.size();
m_data->toggleChanging = false;
}
else if ( checkState == Qt::Unchecked )
{
m_data->toggleChanging = true;
groupItem->setChecked( false );
m_data->groupItemsChecked = 0;
m_data->toggleChanging = false;
}
} );
connect( groupItem, &QskAbstractButton::toggled,
this, [ this, groupItem ]( bool toggled )
{
m_data->groupItemsChecked += toggled ? 1 : -1;
updated();
} );
connect( groupItem, &QskCheckBox::removeFromAllGroupsRequested,
this, [ this, groupItem ]( ) { removeFromGroup( groupItem ); } );
}
void QskCheckBox::removeFromGroup( QskCheckBox* groupItem )
{
if( !m_data->group.remove( groupItem ) )
return;
if( groupItem->checkState() == Qt::Checked )
m_data->groupItemsChecked--;
updated();
}
#include "moc_QskCheckBox.cpp"

View File

@ -0,0 +1,54 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_CHECK_BOX_H
#define QSK_CHECK_BOX_H
#include "QskAbstractButton.h"
class QSK_EXPORT QskCheckBox : public QskAbstractButton
{
Q_OBJECT
Q_PROPERTY( Qt::CheckState checkState READ checkState
WRITE setCheckState NOTIFY checkStateChanged FINAL )
Q_PROPERTY( bool tristate READ isTristate
WRITE setTristate NOTIFY tristateChanged FINAL )
using Inherited = QskAbstractButton;
public:
QSK_SUBCONTROLS( Panel, Indicator )
QSK_STATES( PartiallyChecked )
QskCheckBox( QQuickItem* parent = nullptr );
~QskCheckBox() override;
Qt::CheckState checkState() const;
bool isTristate() const;
bool isCheckable() const override final;
void addToGroup( QskCheckBox* );
void removeFromGroup( QskCheckBox* );
public Q_SLOTS:
void setCheckState( Qt::CheckState );
void setTristate( bool triState = true );
Q_SIGNALS:
void checkStateChanged( Qt::CheckState );
void tristateChanged( bool );
void removeFromAllGroupsRequested();
private:
void setCheckStateInternal( Qt::CheckState );
void updated();
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -0,0 +1,137 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskCheckBoxSkinlet.h"
#include "QskCheckBox.h"
#include "QskSGNode.h"
#include <QSGFlatColorMaterial>
#include <qsgnode.h>
namespace
{
class IndicatorNode : public QSGGeometryNode
{
public:
IndicatorNode()
: m_geometry( QSGGeometry::defaultAttributes_Point2D(), 3 )
{
#if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 )
m_geometry.setDrawingMode( QSGGeometry::DrawLineStrip );
#else
m_geometry.setDrawingMode( GL_LINE_STRIP );
#endif
m_geometry.setLineWidth( 2 );
setGeometry( &m_geometry );
setMaterial( &m_material );
}
void update( bool isPartially, const QRectF& rect, const QColor& color )
{
if ( color != m_material.color() )
{
m_material.setColor( color );
markDirty( QSGNode::DirtyMaterial );
}
if ( rect != m_rect || isPartially != m_isPartially )
{
m_rect = rect;
m_isPartially = isPartially;
const auto x = rect.x();
const auto y = rect.y();
const auto w = rect.width();
const auto h = rect.height();
auto points = m_geometry.vertexDataAsPoint2D();
if ( isPartially )
{
points[0].set( x, y + h / 2 );
points[1] = points[0];
points[2].set( x + w, y + h / 2 );
}
else
{
points[0].set( x, y + h / 2 );
points[1].set( x + w / 3, y + h );
points[2].set( x + w, y );
}
markDirty( QSGNode::DirtyGeometry );
}
}
private:
QSGFlatColorMaterial m_material;
QSGGeometry m_geometry;
QRectF m_rect;
bool m_isPartially;
};
}
QskCheckBoxSkinlet::QskCheckBoxSkinlet( QskSkin* skin )
: QskSkinlet( skin )
{
setNodeRoles( { PanelRole, IndicatorRole } );
}
QskCheckBoxSkinlet::~QskCheckBoxSkinlet()
{
}
QRectF QskCheckBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
{
if ( subControl == QskCheckBox::Indicator )
return skinnable->innerBox( QskCheckBox::Panel, contentsRect );
return contentsRect;
}
QSGNode* QskCheckBoxSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
auto checkBox = static_cast< const QskCheckBox* >( skinnable );
switch( nodeRole )
{
case PanelRole:
return updateBoxNode( skinnable, node, QskCheckBox::Panel );
case IndicatorRole:
return updateIndicatorNode( checkBox, node );
}
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QSGNode* QskCheckBoxSkinlet::updateIndicatorNode(
const QskCheckBox* checkBox, QSGNode* node ) const
{
using Q = QskCheckBox;
const auto state = checkBox->checkState();
if ( state == Qt::Unchecked )
return nullptr;
const auto rect = checkBox->subControlRect( Q::Indicator );
if ( rect.isEmpty() )
return nullptr;
auto indicatorNode = QskSGNode::ensureNode< IndicatorNode >( node );
indicatorNode->update( state != Qt::Checked, rect, checkBox->color( Q::Indicator ) );
return indicatorNode;
}
QSizeF QskCheckBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint, const QSizeF& ) const
{
return skinnable->strutSizeHint( QskCheckBox::Panel );
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_CHECK_BOX_SKINLET_H
#define QSK_CHECK_BOX_SKINLET_H
#include "QskSkinlet.h"
class QskCheckBox;
class QSK_EXPORT QskCheckBoxSkinlet : public QskSkinlet
{
Q_GADGET
using Inherited = QskSkinlet;
public:
enum NodeRole
{
PanelRole,
IndicatorRole,
};
Q_INVOKABLE QskCheckBoxSkinlet( QskSkin* = nullptr );
~QskCheckBoxSkinlet() override;
QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const override;
QSizeF sizeHint( const QskSkinnable*,
Qt::SizeHint, const QSizeF& ) const override;
protected:
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
protected:
virtual QSGNode* updateIndicatorNode( const QskCheckBox*, QSGNode* ) const;
};
#endif

View File

@ -23,6 +23,12 @@ class QWheelEvent;
class QHoverEvent;
class QKeyEvent;
#define QSK_EVENT_DISABLE_COPY(Class) \
Class(const Class &) = default; \
Class(Class &&) = delete; \
Class &operator=(const Class &other) = default; \
Class &operator=(Class &&) = delete;
class QSK_EXPORT QskEvent : public QEvent
{
public:
@ -53,6 +59,8 @@ class QSK_EXPORT QskEvent : public QEvent
virtual QskEvent* clone() const;
#endif
protected:
QSK_EVENT_DISABLE_COPY( QskEvent )
};
class QSK_EXPORT QskGeometryChangeEvent : public QskEvent
@ -68,6 +76,9 @@ class QSK_EXPORT QskGeometryChangeEvent : public QskEvent
QskGeometryChangeEvent* clone() const override;
protected:
QSK_EVENT_DISABLE_COPY( QskGeometryChangeEvent )
private:
const QRectF m_rect;
const QRectF m_oldRect;
@ -83,6 +94,9 @@ class QSK_EXPORT QskWindowChangeEvent : public QskEvent
QskWindowChangeEvent* clone() const override;
protected:
QSK_EVENT_DISABLE_COPY( QskWindowChangeEvent )
private:
QQuickWindow* const m_oldWindow;
QQuickWindow* const m_window;
@ -97,6 +111,9 @@ class QSK_EXPORT QskPopupEvent : public QskEvent
QskPopupEvent* clone() const override;
protected:
QSK_EVENT_DISABLE_COPY( QskPopupEvent )
private:
QskPopup* const m_popup;
};
@ -110,6 +127,9 @@ class QSK_EXPORT QskGestureEvent : public QskEvent
QskGestureEvent* clone() const override;
protected:
QSK_EVENT_DISABLE_COPY( QskGestureEvent )
private:
std::shared_ptr< const QskGesture > m_gesture;
};
@ -130,6 +150,9 @@ class QSK_EXPORT QskAnimatorEvent : public QskEvent
QskAnimatorEvent* clone() const override;
protected:
QSK_EVENT_DISABLE_COPY( QskAnimatorEvent )
private:
const QskAspect m_aspect;
const State m_state;

View File

@ -37,6 +37,11 @@ namespace
QString text;
QskGraphic graphic;
#if 0
// TODO ...
bool isEnabled = true;
#endif
};
}
@ -75,6 +80,9 @@ QskMenu::~QskMenu()
{
}
#if 1
// has no effect as we do not offer submenus yet. TODO ...
bool QskMenu::isCascading() const
{
return flagHint( QskMenu::Panel | QskAspect::Style );
@ -92,6 +100,8 @@ void QskMenu::resetCascading()
Q_EMIT cascadingChanged( isCascading() );
}
#endif
void QskMenu::setOrigin( const QPointF& origin )
{
if ( origin != m_data->origin )

View File

@ -12,6 +12,7 @@
#include "QskGraphicProviderMap.h"
#include "QskSkinHintTable.h"
#include "QskStandardSymbol.h"
#include "QskPlatform.h"
#include "QskMargins.h"
@ -28,6 +29,9 @@ QSK_QT_PRIVATE_END
#include "QskBox.h"
#include "QskBoxSkinlet.h"
#include "QskCheckBox.h"
#include "QskCheckBoxSkinlet.h"
#include "QskFocusIndicator.h"
#include "QskFocusIndicatorSkinlet.h"
@ -128,7 +132,6 @@ class QskSkin::PrivateData
std::unordered_map< const QMetaObject*, SkinletData > skinletMap;
QskSkinHintTable hintTable;
QskAspect::States stateMask = QskAspect::AllStates;
std::unordered_map< int, QFont > fonts;
std::unordered_map< int, QskColorFilter > graphicFilters;
@ -143,6 +146,7 @@ QskSkin::QskSkin( QObject* parent )
declareSkinlet< QskControl, QskSkinlet >();
declareSkinlet< QskBox, QskBoxSkinlet >();
declareSkinlet< QskCheckBox, QskCheckBoxSkinlet >();
declareSkinlet< QskFocusIndicator, QskFocusIndicatorSkinlet >();
declareSkinlet< QskGraphicLabel, QskGraphicLabelSkinlet >();
declareSkinlet< QskListView, QskListViewSkinlet >();
@ -217,13 +221,15 @@ void QskSkin::declareSkinlet( const QMetaObject* metaObject,
void QskSkin::setupFonts( const QString& family, int weight, bool italic )
{
const int sizes[] = { 10, 15, 20, 32, 66 };
static_assert( sizeof( sizes ) / sizeof( sizes[ 0 ] ) == HugeFont,
"QskSkin::setupFonts: bad list size." );
QFont font( family, -1, weight, italic );
const uint base = TinyFont;
for ( int i = TinyFont; i <= HugeFont; i++ )
{
// TODO: make the scaling components configurable
font.setPixelSize( int( std::pow( uint( i ) - base + 2, 2.5 ) ) );
font.setPixelSize( qskDpiScaled( sizes[i-1] ) );
m_data->fonts[ i ] = font;
}
@ -349,22 +355,6 @@ const int* QskSkin::dialogButtonLayout( Qt::Orientation orientation ) const
return QPlatformDialogHelper::buttonLayout( orientation, policy );
}
void QskSkin::setStateMask( QskAspect::States mask )
{
for ( auto state : { QskControl::Disabled, QskControl::Hovered, QskControl::Focused } )
{
if ( mask & state )
m_data->stateMask |= state;
else
m_data->stateMask &= ~state;
}
}
QskAspect::States QskSkin::stateMask() const
{
return m_data->stateMask;
}
QskSkinlet* QskSkin::skinlet( const QMetaObject* metaObject )
{
while ( metaObject )

View File

@ -77,9 +77,6 @@ class QSK_EXPORT QskSkin : public QObject
virtual const int* dialogButtonLayout( Qt::Orientation ) const;
virtual QString dialogButtonText( int button ) const;
void setStateMask( QskAspect::States );
QskAspect::States stateMask() const;
QskSkinlet* skinlet( const QMetaObject* );
const QskSkinHintTable& hintTable() const;

View File

@ -64,41 +64,11 @@ QskSkinHintTable::QskSkinHintTable()
{
}
QskSkinHintTable::QskSkinHintTable( const QskSkinHintTable& other )
: m_hints( nullptr )
, m_animatorCount( other.m_animatorCount )
, m_statefulCount( other.m_statefulCount )
{
if ( other.m_hints )
m_hints = new HintMap( *( other.m_hints ) );
}
QskSkinHintTable::~QskSkinHintTable()
{
delete m_hints;
}
QskSkinHintTable& QskSkinHintTable::operator=( const QskSkinHintTable& other )
{
m_animatorCount = other.m_animatorCount;
m_statefulCount = other.m_statefulCount;
if ( other.m_hints )
{
if ( m_hints == nullptr )
m_hints = new HintMap();
*m_hints = *other.m_hints;
}
else
{
delete m_hints;
m_hints = nullptr;
}
return *this;
}
const std::unordered_map< QskAspect, QVariant >& QskSkinHintTable::hints() const
{
if ( m_hints )
@ -126,11 +96,7 @@ bool QskSkinHintTable::setHint( QskAspect aspect, const QVariant& skinHint )
QSK_ASSERT_COUNTER( m_animatorCount );
}
if ( aspect.hasStates() )
{
m_statefulCount++;
QSK_ASSERT_COUNTER( m_statefulCount );
}
m_states |= aspect.states();
return true;
}
@ -158,8 +124,7 @@ bool QskSkinHintTable::removeHint( QskAspect aspect )
if ( aspect.isAnimator() )
m_animatorCount--;
if ( aspect.hasStates() )
m_statefulCount--;
// how to clear m_states ? TODO ...
if ( m_hints->empty() )
{
@ -184,8 +149,7 @@ QVariant QskSkinHintTable::takeHint( QskAspect aspect )
if ( aspect.isAnimator() )
m_animatorCount--;
if ( aspect.hasStates() )
m_statefulCount--;
// how to clear m_states ? TODO ...
if ( m_hints->empty() )
{
@ -206,14 +170,14 @@ void QskSkinHintTable::clear()
m_hints = nullptr;
m_animatorCount = 0;
m_statefulCount = 0;
m_states = QskAspect::NoState;
}
const QVariant* QskSkinHintTable::resolvedHint(
QskAspect aspect, QskAspect* resolvedAspect ) const
{
if ( m_hints != nullptr )
return qskResolvedHint( aspect, *m_hints, resolvedAspect );
return qskResolvedHint( aspect & m_states, *m_hints, resolvedAspect );
return nullptr;
}
@ -223,7 +187,7 @@ QskAspect QskSkinHintTable::resolvedAspect( QskAspect aspect ) const
QskAspect a;
if ( m_hints != nullptr )
qskResolvedHint( aspect, *m_hints, &a );
qskResolvedHint( aspect & m_states, *m_hints, &a );
return a;
}
@ -233,6 +197,8 @@ QskAspect QskSkinHintTable::resolvedAnimator(
{
if ( m_hints && m_animatorCount > 0 )
{
aspect &= m_states;
Q_FOREVER
{
auto it = m_hints->find( aspect );
@ -268,15 +234,16 @@ bool QskSkinHintTable::setAnimation(
bool QskSkinHintTable::isResolutionMatching(
QskAspect aspect1, QskAspect aspect2 ) const
{
// remove states we do not have early
aspect1 &= m_states;
aspect2 &= m_states;
if ( aspect1 == aspect2 )
return true;
if ( aspect1.trunk() != aspect2.trunk() )
return false;
if ( !hasStates() )
return false;
const auto a1 = aspect1;
const auto a2 = aspect2;

View File

@ -17,12 +17,8 @@ class QSK_EXPORT QskSkinHintTable
{
public:
QskSkinHintTable();
QskSkinHintTable( const QskSkinHintTable& other );
~QskSkinHintTable();
QskSkinHintTable& operator=( const QskSkinHintTable& );
bool setAnimation( QskAspect, QskAnimationHint );
QskAnimationHint animation( QskAspect ) const;
@ -40,9 +36,10 @@ class QSK_EXPORT QskSkinHintTable
const std::unordered_map< QskAspect, QVariant >& hints() const;
bool hasAnimators() const;
bool hasStates() const;
bool hasHints() const;
QskAspect::States states() const;
void clear();
const QVariant* resolvedHint( QskAspect,
@ -56,13 +53,15 @@ class QSK_EXPORT QskSkinHintTable
bool isResolutionMatching( QskAspect, QskAspect ) const;
private:
Q_DISABLE_COPY( QskSkinHintTable )
static const QVariant invalidHint;
typedef std::unordered_map< QskAspect, QVariant > HintMap;
HintMap* m_hints = nullptr;
unsigned short m_animatorCount = 0;
unsigned short m_statefulCount = 0;
QskAspect::States m_states;
};
inline bool QskSkinHintTable::hasHints() const
@ -70,9 +69,9 @@ inline bool QskSkinHintTable::hasHints() const
return m_hints != nullptr;
}
inline bool QskSkinHintTable::hasStates() const
inline QskAspect::States QskSkinHintTable::states() const
{
return m_statefulCount > 0;
return m_states;
}
inline bool QskSkinHintTable::hasAnimators() const

File diff suppressed because it is too large Load Diff

View File

@ -49,17 +49,6 @@ static inline bool qskIsControl( const QskSkinnable* skinnable )
#endif
}
static inline QVariant qskTypedNullValue( const QVariant& value )
{
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
const auto vType = static_cast< QMetaType >( value.userType() );
#else
const auto vType = value.userType();
#endif
return QVariant( vType, nullptr );
}
static inline bool qskSetFlag( QskSkinnable* skinnable,
const QskAspect aspect, int flag )
{
@ -951,23 +940,12 @@ const QVariant& QskSkinnable::storedHint(
{
const auto skin = effectiveSkin();
// clearing all state bits not being handled from the skin
aspect.clearStates( ~skin->stateMask() );
QskAspect resolvedAspect;
const auto& localTable = m_data->hintTable;
if ( localTable.hasHints() )
{
auto a = aspect;
if ( !localTable.hasStates() )
{
// we don't need to clear the state bits stepwise
a.clearStates();
}
if ( const QVariant* value = localTable.resolvedHint( a, &resolvedAspect ) )
if ( const auto value = localTable.resolvedHint( aspect, &resolvedAspect ) )
{
if ( status )
{
@ -983,10 +961,7 @@ const QVariant& QskSkinnable::storedHint(
const auto& skinTable = skin->hintTable();
if ( skinTable.hasHints() )
{
auto a = aspect;
const QVariant* value = skinTable.resolvedHint( a, &resolvedAspect );
if ( value )
if ( const auto value = skinTable.resolvedHint( aspect, &resolvedAspect ) )
{
if ( status )
{
@ -1004,8 +979,7 @@ const QVariant& QskSkinnable::storedHint(
aspect.setSubControl( QskAspect::Control );
aspect.clearStates();
value = skinTable.resolvedHint( aspect, &resolvedAspect );
if ( value )
if ( const auto value = skinTable.resolvedHint( aspect, &resolvedAspect ) )
{
if ( status )
{
@ -1182,28 +1156,12 @@ void QskSkinnable::startHintTransition( QskAspect aspect,
if ( control->window() == nullptr || !isTransitionAccepted( aspect ) )
return;
/*
We might be invalid for one of the values, when an aspect
has not been defined for all states ( f.e. metrics are expected
to fallback to 0.0 ). In this case we create a default one.
*/
if ( !QskVariantAnimator::maybeInterpolate( from, to ) )
return;
auto v1 = from;
auto v2 = to;
if ( !v1.isValid() )
{
v1 = qskTypedNullValue( v2 );
}
else if ( !v2.isValid() )
{
v2 = qskTypedNullValue( v1 );
}
else if ( v1.userType() != v2.userType() )
{
return;
}
if ( aspect.flagPrimitive() == QskAspect::GraphicRole )
{
const auto skin = effectiveSkin();
@ -1268,7 +1226,8 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
if ( skin )
{
const auto mask = skin->stateMask();
const auto mask = skin->hintTable().states() | m_data->hintTable.states();
if ( ( newStates & mask ) == ( m_data->skinStates & mask ) )
{
// the modified bits are not handled by the skin
@ -1308,24 +1267,13 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
const auto primitive = static_cast< QskAspect::Primitive >( i );
aspect.setPrimitive( type, primitive );
auto a1 = aspect | m_data->skinStates;
auto a2 = aspect | newStates;
const auto a1 = aspect | m_data->skinStates;
const auto a2 = aspect | newStates;
bool doTransition = true;
if ( !m_data->hintTable.hasStates() )
{
/*
The hints are found by stripping the state bits one by
one until a lookup into the hint table is successful.
So for deciding whether two aspects lead to the same hint
we can stop as soon as the aspects have the same state bits.
This way we can reduce the number of lookups significantly
for skinnables with many state bits.
*/
if ( m_data->hintTable.states() == QskAspect::NoState )
doTransition = !skinTable.isResolutionMatching( a1, a2 );
}
if ( doTransition )
{
@ -1354,12 +1302,7 @@ QskSkin* QskSkinnable::effectiveSkin() const
if ( skin == nullptr )
{
if ( const auto control = owningControl() )
{
if ( auto window = qobject_cast< const QskWindow* >( control->window() ) )
{
skin = window->skin();
}
}
skin = qskEffectiveSkin( control->window() );
}
return skin ? skin : qskSetup->skin();

View File

@ -230,6 +230,8 @@ class QSK_EXPORT QskSkinnable
bool resetGraphicRoleHint( QskAspect );
int graphicRoleHint( QskAspect, QskSkinHintStatus* = nullptr ) const;
const QskSkinHintTable& hintTable() const;
protected:
virtual void updateNode( QSGNode* );
virtual bool isTransitionAccepted( QskAspect ) const;
@ -237,7 +239,6 @@ class QSK_EXPORT QskSkinnable
virtual QskAspect::Subcontrol substitutedSubcontrol( QskAspect::Subcontrol ) const;
QskSkinHintTable& hintTable();
const QskSkinHintTable& hintTable() const;
private:
Q_DISABLE_COPY( QskSkinnable )

View File

@ -301,6 +301,8 @@ QskTextInput::QskTextInput( QQuickItem* parent )
m_data->hasPanel = true;
setPolishOnResize( true );
setAcceptHoverEvents( true );
setFocusPolicy( Qt::StrongFocus );
setFlag( QQuickItem::ItemAcceptsInputMethod );

View File

@ -53,13 +53,13 @@ Q_CONSTRUCTOR_FUNCTION( qskRegisterInterpolator )
#endif
#if defined( Q_CC_CLANG )
#if __has_feature( address_sanitizer )
#define QSK_DECL_INSANE __attribute__( ( no_sanitize( "undefined" ) ) )
#endif
#if __has_feature( address_sanitizer )
#define QSK_DECL_INSANE __attribute__( ( no_sanitize( "undefined" ) ) )
#endif
#endif
#if !defined( QSK_DECL_INSANE )
#define QSK_DECL_INSANE
#define QSK_DECL_INSANE
#endif
QSK_DECL_INSANE static inline QVariant qskInterpolate(
@ -76,6 +76,31 @@ QSK_DECL_INSANE static inline QVariant qskInterpolate(
return f( from.constData(), to.constData(), progress );
}
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
using QskMetaType = int;
static inline QskMetaType qskMetaType( const QVariant& v ) { return v.userType(); }
#else
using QskMetaType = QMetaType;
static inline QskMetaType qskMetaType( const QVariant& v ) { return v.metaType(); }
#endif
static inline QVariant qskDefaultVariant( QskMetaType type )
{
return QVariant( type, nullptr );
}
static inline QVariant qskConvertedVariant( const QVariant& from, QskMetaType type )
{
auto v = from;
v.convert( type );
return v;
}
QskVariantAnimator::QskVariantAnimator()
: m_interpolator( nullptr )
{
@ -87,11 +112,13 @@ QskVariantAnimator::~QskVariantAnimator()
void QskVariantAnimator::setStartValue( const QVariant& value )
{
stop();
m_startValue = value;
}
void QskVariantAnimator::setEndValue( const QVariant& value )
{
stop();
m_endValue = value;
}
@ -100,16 +127,60 @@ void QskVariantAnimator::setCurrentValue( const QVariant& value )
m_currentValue = value;
}
bool QskVariantAnimator::convertValues( QVariant& v1, QVariant& v2 )
{
if ( !v1.isValid() && !v2.isValid() )
return false;
const auto type1 = qskMetaType( v1 );
const auto type2 = qskMetaType( v2 );
if ( !v1.isValid() )
{
v1 = qskDefaultVariant( type2 );
return true;
}
if ( !v2.isValid() )
{
v2 = qskDefaultVariant( type1 );
return true;
}
if ( type1 != type2 )
{
if ( v1.canConvert( type2 ) )
{
v1.convert( type2 );
return true;
}
if ( v2.canConvert( type1 ) )
{
v2.convert( type1 );
return true;
}
return false;
}
return true;
}
void QskVariantAnimator::setup()
{
m_interpolator = nullptr;
const auto type = m_startValue.userType();
if ( type == m_endValue.userType() )
if ( convertValues( m_startValue, m_endValue ) )
{
// all what has been registered by qRegisterAnimationInterpolator
m_interpolator = reinterpret_cast< void ( * )() >(
QVariantAnimationPrivate::getInterpolator( type ) );
if ( m_startValue != m_endValue )
{
const auto id = m_startValue.userType();
// all what has been registered by qRegisterAnimationInterpolator
m_interpolator = reinterpret_cast< void ( * )() >(
QVariantAnimationPrivate::getInterpolator( id ) );
}
}
m_currentValue = m_interpolator ? m_startValue : m_endValue;
@ -122,6 +193,8 @@ void QskVariantAnimator::advance( qreal progress )
if ( qFuzzyCompare( progress, 1.0 ) )
progress = 1.0;
Q_ASSERT( qskMetaType( m_startValue ) == qskMetaType( m_endValue ) );
m_currentValue = qskInterpolate( m_interpolator,
m_startValue, m_endValue, progress );
}
@ -131,3 +204,32 @@ void QskVariantAnimator::done()
{
m_interpolator = nullptr;
}
bool QskVariantAnimator::maybeInterpolate(
const QVariant& value1, const QVariant& value2 )
{
if ( !value1.isValid() && !value2.isValid() )
return false;
const auto type1 = qskMetaType( value1 );
const auto type2 = qskMetaType( value2 );
if ( !value1.isValid() )
return value2 != qskDefaultVariant( type2 );
if ( !value2.isValid() )
return value1 != qskDefaultVariant( type1 );
if ( type1 != type2 )
{
if ( value1.canConvert( type2 ) )
return value2 != qskConvertedVariant( value1, type2 );
if ( value2.canConvert( type1 ) )
return value1 != qskConvertedVariant( value2, type1 );
return false;
}
return value1 != value2;
}

View File

@ -24,6 +24,9 @@ class QSK_EXPORT QskVariantAnimator : public QskAnimator
void setEndValue( const QVariant& );
QVariant endValue() const;
static bool maybeInterpolate( const QVariant&, const QVariant& );
static bool convertValues( QVariant&, QVariant& );
protected:
void setup() override;
void advance( qreal value ) override;

View File

@ -501,15 +501,15 @@ QSize QskWindow::sizeConstraint() const
const auto children = contentItem()->childItems();
for ( auto child : children )
{
if ( auto control = qskControlCast( child ) )
if ( !qskIsTransparentForPositioner( child ) )
{
const QSizeF itemConstraint = control->sizeConstraint();
const auto size = qskSizeConstraint( child, Qt::PreferredSize );
if ( doWidth )
constraint.setWidth( qMax( constraint.width(), itemConstraint.width() ) );
constraint.setWidth( qMax( constraint.width(), size.width() ) );
if ( doHeight )
constraint.setHeight( qMax( constraint.height(), itemConstraint.height() ) );
constraint.setHeight( qMax( constraint.height(), size.height() ) );
}
}
}

View File

@ -48,11 +48,7 @@ void QskGraphicProviderMap::insert(
void QskGraphicProviderMap::remove( const QString& providerId )
{
const auto it = m_data->hashTab.find( qskKey( providerId ) );
if ( it == m_data->hashTab.end() )
delete it.value();
m_data->hashTab.erase( it );
delete take( providerId );
}
QskGraphicProvider* QskGraphicProviderMap::take( const QString& providerId )
@ -60,10 +56,11 @@ QskGraphicProvider* QskGraphicProviderMap::take( const QString& providerId )
QskGraphicProvider* provider = nullptr;
const auto it = m_data->hashTab.find( qskKey( providerId ) );
if ( it == m_data->hashTab.end() )
if ( it != m_data->hashTab.end() )
{
provider = it.value();
m_data->hashTab.erase( it );
m_data->hashTab.erase( it );
}
return provider;
}

View File

@ -12,7 +12,7 @@
class QskGraphicProvider;
class QString;
class QSK_EXPORT QskGraphicProviderMap
class QskGraphicProviderMap
{
public:
QskGraphicProviderMap();

View File

@ -102,3 +102,5 @@ void QskPinyinTextPredictor::request( const QString& text )
m_data->candidates = candidates;
Q_EMIT predictionChanged();
}
#include "moc_QskPinyinTextPredictor.cpp"

View File

@ -12,6 +12,8 @@
class QSK_INPUTCONTEXT_EXPORT QskPinyinTextPredictor : public QskTextPredictor
{
Q_OBJECT
using Inherited = QskTextPredictor;
public:

View File

@ -63,7 +63,6 @@ SOURCES += \
common/QskScaleTickmarks.cpp \
common/QskShadowMetrics.cpp \
common/QskSizePolicy.cpp \
common/QskStateCombination.cpp \
common/QskTextColors.cpp \
common/QskTextOptions.cpp
@ -142,6 +141,8 @@ HEADERS += \
controls/QskBoundedValueInput.h \
controls/QskBox.h \
controls/QskBoxSkinlet.h \
controls/QskCheckBox.h \
controls/QskCheckBoxSkinlet.h \
controls/QskControl.h \
controls/QskControlPrivate.h \
controls/QskDirtyItemFilter.h \
@ -222,6 +223,8 @@ SOURCES += \
controls/QskBoundedValueInput.cpp \
controls/QskBox.cpp \
controls/QskBoxSkinlet.cpp \
controls/QskCheckBox.cpp \
controls/QskCheckBoxSkinlet.cpp \
controls/QskControl.cpp \
controls/QskControlPrivate.cpp \
controls/QskDirtyItemFilter.cpp \

View File

@ -1,43 +0,0 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "SkinnyFont.h"
#include <QFontDatabase>
#include <QGuiApplication>
#include <QElapsedTimer>
#include <QDebug>
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
void SkinnyFont::init( QGuiApplication* )
{
#ifdef FONTCONFIG_FILE
const char env[] = "FONTCONFIG_FILE";
if ( !qEnvironmentVariableIsSet( env ) )
qputenv( env, STRING( FONTCONFIG_FILE ) );
#endif
QElapsedTimer timer;
timer.start();
QFontDatabase();
const auto elapsed = timer.elapsed();
if ( elapsed > 20 )
{
qWarning() << "Loading fonts needed" << elapsed << "ms"
<< "- usually because of creating a font cache.";
}
/*
The default initialization in QskSkin sets up its font table
with using the application font for the default font role.
*/
QGuiApplication::setFont( QFont( "DejaVuSans", 12 ) );
}

View File

@ -3,23 +3,20 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#ifndef SKINNY_GLOBAL_H
#define SKINNY_GLOBAL_H
#pragma once
#include <QskGlobal.h>
#ifdef QSK_DLL
#if defined( SKINNY_MAKEDLL ) // create a DLL library
#define SKINNY_EXPORT Q_DECL_EXPORT
#else // use a DLL library
#define SKINNY_EXPORT Q_DECL_IMPORT
#endif
#if defined( SKINNY_MAKEDLL ) // create a DLL library
#define SKINNY_EXPORT Q_DECL_EXPORT
#else // use a DLL library
#define SKINNY_EXPORT Q_DECL_IMPORT
#endif
#endif // QSK_DLL
#ifndef SKINNY_EXPORT
#define SKINNY_EXPORT
#endif
#define SKINNY_EXPORT
#endif

140
support/SkinnyNamespace.cpp Normal file
View File

@ -0,0 +1,140 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#include "SkinnyNamespace.h"
#include <QskSetup.h>
#include <QskSkinManager.h>
#include <QskSkin.h>
#include <QskSkinTransition.h>
#include <QskAnimationHint.h>
#include <QGuiApplication>
#include <QDebug>
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
#if defined( ENSURE_SKINS )
#include <squiek/QskSquiekSkinFactory.h>
#include <material/QskMaterialSkinFactory.h>
static void initSkins()
{
if ( qskSkinManager->skinNames().isEmpty() )
{
/*
To avoid having problems with not finding the skin plugins
we manually add them here.
*/
qskSkinManager->registerFactory( "SquiekFactory", new QskSquiekSkinFactory() );
qskSkinManager->registerFactory( "MaterialFactory", new QskMaterialSkinFactory() );
qWarning() << "Couldn't find skin plugins, adding some manually.";
}
}
Q_COREAPP_STARTUP_FUNCTION( initSkins )
#endif
#define ENSURE_FONTS
#if defined( ENSURE_FONTS )
#include <QFontDatabase>
#include <QElapsedTimer>
static void initFonts()
{
#ifdef FONTCONFIG_FILE
const char env[] = "FONTCONFIG_FILE";
if ( !qEnvironmentVariableIsSet( env ) )
qputenv( env, STRING( FONTCONFIG_FILE ) );
#endif
QElapsedTimer timer;
timer.start();
QFontDatabase();
const auto elapsed = timer.elapsed();
if ( elapsed > 20 )
{
qWarning() << "Loading fonts needed" << elapsed << "ms"
<< "- usually because of creating a font cache.";
}
/*
The default initialization in QskSkin sets up its font table
with using the application font for the default font role.
*/
QGuiApplication::setFont( QFont( "DejaVuSans", 12 ) );
}
#endif
Q_COREAPP_STARTUP_FUNCTION( initFonts )
void Skinny::changeSkin( QskAnimationHint hint )
{
const auto names = qskSkinManager->skinNames();
if ( names.size() <= 1 )
return;
int index = names.indexOf( qskSetup->skinName() );
index = ( index + 1 ) % names.size();
auto oldSkin = qskSetup->skin();
if ( oldSkin->parent() == qskSetup )
oldSkin->setParent( nullptr ); // otherwise setSkin deletes it
if ( auto newSkin = qskSetup->setSkin( names[ index ] ) )
{
QskSkinTransition transition;
//transition.setMask( QskAspect::Color ); // Metrics are flickering -> TODO
transition.setSourceSkin( oldSkin );
transition.setTargetSkin( newSkin );
transition.setAnimation( hint );
transition.process();
if ( oldSkin->parent() == nullptr )
delete oldSkin;
}
}
void Skinny::changeFonts( int increment )
{
auto skin = qskSetup->skin();
const auto fonts = skin->fonts();
for ( auto it = fonts.begin(); it != fonts.end(); ++it )
{
auto role = it->first;
auto font = it->second;
if ( font.pixelSize() > 0 )
{
const auto newSize = font.pixelSize() + increment;
if ( newSize > 0 )
font.setPixelSize( newSize );
}
else
{
const auto newSize = font.pointSizeF() + increment;
if ( newSize > 0 )
font.setPointSizeF( font.pointSizeF() + increment );
}
skin->setFont( role, font );
}
Q_EMIT qskSetup->skinChanged( skin );
}

View File

@ -3,16 +3,13 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#ifndef SKINNY_FONT_H_
#define SKINNY_FONT_H_
#pragma once
#include "SkinnyGlobal.h"
#include <QskAnimationHint.h>
class QGuiApplication;
namespace SkinnyFont
namespace Skinny
{
SKINNY_EXPORT void init( QGuiApplication* );
SKINNY_EXPORT void changeSkin( QskAnimationHint hint = 500 );
SKINNY_EXPORT void changeFonts( int increment );
}
#endif

View File

@ -3,8 +3,7 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#ifndef SKINNY_SHAPE_FACTORY_H_
#define SKINNY_SHAPE_FACTORY_H_
#pragma once
#include "SkinnyGlobal.h"
#include <QPainterPath>
@ -32,5 +31,3 @@ namespace SkinnyShapeFactory
SKINNY_EXPORT QPainterPath shapePath( Shape, const QSizeF& );
}
#endif

View File

@ -3,8 +3,7 @@
* This file may be used under the terms of the 3-clause BSD License
*****************************************************************************/
#ifndef SKINNY_SHAPE_PROVIDER_H
#define SKINNY_SHAPE_PROVIDER_H
#pragma once
#include "SkinnyGlobal.h"
#include <QskGraphicProvider.h>
@ -15,5 +14,3 @@ class SKINNY_EXPORT SkinnyShapeProvider : public QskGraphicProvider
const QskGraphic* loadGraphic( const QString& id ) const override final;
};
#endif

View File

@ -1,15 +1,11 @@
#include "SkinnyShortcut.h"
#include "SkinnyNamespace.h"
#include <QskShortcutMap.h>
#include <QskSetup.h>
#include <QskSkinManager.h>
#include <QskWindow.h>
#include <QskAspect.h>
#include <QskSkin.h>
#include <QskControl.h>
#include <QskQuick.h>
#include <QskAnimationHint.h>
#include <QskSkinTransition.h>
#include <QQuickItem>
#include <QKeySequence>
@ -17,7 +13,6 @@
#include <QSGNode>
#include <QDebug>
#include <unordered_map>
#include <iostream>
SkinnyShortcut::SkinnyShortcut( QObject* parent ):
@ -34,17 +29,17 @@ void SkinnyShortcut::enable( Types types )
if ( types & RotateSkin )
{
QskShortcutMap::addShortcut( QKeySequence( Qt::CTRL | Qt::Key_S ),
false, &s_shortcut, &SkinnyShortcut::rotateSkin );
false, &s_shortcut, [] { Skinny::changeSkin(); } );
cout << "CTRL-S to change the skin." << endl;
}
if ( types & ChangeFonts )
{
QskShortcutMap::addShortcut( QKeySequence( Qt::CTRL | Qt::Key_F ),
false, &s_shortcut, [] { s_shortcut.changeFonts( +1 ); } );
false, &s_shortcut, [] { Skinny::changeFonts( +1 ); } );
QskShortcutMap::addShortcut( QKeySequence( Qt::CTRL | Qt::Key_G ),
false, &s_shortcut, [] { s_shortcut.changeFonts( -1 ); } );
false, &s_shortcut, [] { Skinny::changeFonts( -1 ); } );
cout << "CTRL-F to increase the font size." << endl;
cout << "CTRL-G to decrease the font size." << endl;
@ -75,34 +70,6 @@ void SkinnyShortcut::enable( Types types )
}
}
void SkinnyShortcut::rotateSkin()
{
const QStringList names = qskSkinManager->skinNames();
if ( names.size() <= 1 )
return;
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.setMask( QskAspect::Color ); // Metrics are flickering -> TODO
transition.setSourceSkin( oldSkin );
transition.setTargetSkin( newSkin );
transition.setAnimation( 500 );
transition.process();
if ( oldSkin->parent() == nullptr )
delete oldSkin;
}
void SkinnyShortcut::showBackground()
{
#if 0
@ -148,36 +115,6 @@ void SkinnyShortcut::showBackground()
}
}
void SkinnyShortcut::changeFonts( int increment )
{
auto skin = qskSetup->skin();
const auto fonts = skin->fonts();
for ( auto it = fonts.begin(); it != fonts.end(); ++it )
{
auto role = it->first;
auto font = it->second;
if ( font.pixelSize() > 0 )
{
const auto newSize = font.pixelSize() + increment;
if ( newSize > 0 )
font.setPixelSize( newSize );
}
else
{
const auto newSize = font.pointSizeF() + increment;
if ( newSize > 0 )
font.setPointSizeF( font.pointSizeF() + increment );
}
skin->setFont( role, font );
}
Q_EMIT qskSetup->skinChanged( skin );
}
static inline void countNodes( const QSGNode* node, int& counter )
{
if ( node )

Some files were not shown because too many files have changed in this diff Show More