Merge branch 'master' into features/menubutton
This commit is contained in:
commit
f67ff13f93
|
|
@ -6,8 +6,6 @@
|
|||
add_subdirectory(desktop)
|
||||
add_subdirectory(gallery)
|
||||
add_subdirectory(layouts)
|
||||
add_subdirectory(listbox)
|
||||
add_subdirectory(messagebox)
|
||||
add_subdirectory(mycontrols)
|
||||
add_subdirectory(qvgviewer)
|
||||
add_subdirectory(thumbnails)
|
||||
|
|
@ -19,5 +17,4 @@ if( BUILD_QML_EXPORT )
|
|||
add_subdirectory(buttons)
|
||||
add_subdirectory(frames)
|
||||
add_subdirectory(glabels)
|
||||
add_subdirectory(messageboxQml)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ Qsk.Window
|
|||
|
||||
width: 600
|
||||
height: 600
|
||||
color: "Beige"
|
||||
|
||||
Component.onCompleted:
|
||||
{
|
||||
|
|
@ -30,9 +29,10 @@ Qsk.Window
|
|||
{
|
||||
orientation: Qt.Horizontal
|
||||
dimension: 3
|
||||
panel : true // to have a themed background
|
||||
|
||||
//margins: 10 // only possible with Qt <= 6.1
|
||||
margins { left: 10; top: 10; right: 10; bottom: 10 }
|
||||
// padding: 10 // only possible with Qt <= 6.1
|
||||
padding { left: 10; top: 10; right: 10; bottom: 10 }
|
||||
spacing: 10
|
||||
|
||||
TestButton
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ set(SOURCES
|
|||
button/ButtonPage.h button/ButtonPage.cpp
|
||||
selector/SelectorPage.h selector/SelectorPage.cpp
|
||||
dialog/DialogPage.h dialog/DialogPage.cpp
|
||||
listbox/ListBoxPage.h listbox/ListBoxPage.cpp
|
||||
Page.h Page.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,80 +15,106 @@ namespace
|
|||
{
|
||||
class Button : public QskPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum ButtonType
|
||||
Button( const QString& text, QQuickItem* parent = nullptr )
|
||||
: QskPushButton( text, parent )
|
||||
{
|
||||
Message,
|
||||
Information,
|
||||
Warning,
|
||||
Critical,
|
||||
}
|
||||
};
|
||||
|
||||
Question,
|
||||
Selection,
|
||||
|
||||
TypeCount
|
||||
};
|
||||
Q_ENUM( ButtonType )
|
||||
|
||||
Button( ButtonType type, QQuickItem* parent = nullptr )
|
||||
: QskPushButton( parent )
|
||||
, m_type( type )
|
||||
class ButtonBox : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
ButtonBox( QQuickItem* parent = nullptr )
|
||||
: QskLinearBox( Qt::Horizontal, 2, parent )
|
||||
{
|
||||
setShape( 10 );
|
||||
initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed );
|
||||
setObjectName( "ButtonBox" );
|
||||
|
||||
const int index = metaObject()->indexOfEnumerator( "ButtonType" );
|
||||
setText( metaObject()->enumerator( index ).key( m_type ) );
|
||||
setMargins( 10 );
|
||||
setSpacing( 20 );
|
||||
|
||||
connect( this, &QskPushButton::clicked, this, &Button::showDialog );
|
||||
auto messageButton = new Button( "Message", this );
|
||||
connect( messageButton, &Button::clicked, this, &ButtonBox::execMessage );
|
||||
|
||||
auto informationButton = new Button( "Information", this );
|
||||
connect( informationButton, &Button::clicked, this, &ButtonBox::execInformation );
|
||||
|
||||
auto questionButton = new Button( "Question", this );
|
||||
connect( questionButton, &Button::clicked, this, &ButtonBox::execQuestion );
|
||||
|
||||
auto warningButton = new Button( "Warning", this );
|
||||
connect( warningButton, &Button::clicked, this, &ButtonBox::execWarning );
|
||||
|
||||
auto criticalButton = new Button( "Critical", this );
|
||||
connect( criticalButton, &Button::clicked, this, &ButtonBox::execCritical );
|
||||
|
||||
auto selectButton = new Button( "Selection", this );
|
||||
connect( selectButton, &Button::clicked, this, &ButtonBox::execSelection );
|
||||
|
||||
setExtraSpacingAt( Qt::BottomEdge );
|
||||
}
|
||||
|
||||
private:
|
||||
void showDialog()
|
||||
void execMessage()
|
||||
{
|
||||
switch( static_cast< int >( m_type ) )
|
||||
{
|
||||
case Message:
|
||||
qskDialog->message( text(), text(), QskStandardSymbol::Ok );
|
||||
break;
|
||||
|
||||
case Information:
|
||||
qskDialog->information( text(), text() );
|
||||
break;
|
||||
|
||||
case Warning:
|
||||
qskDialog->warning( text(), text() );
|
||||
break;
|
||||
|
||||
case Critical:
|
||||
qskDialog->critical( text(), text() );
|
||||
break;
|
||||
|
||||
case Question:
|
||||
qskDialog->question( text(), text() );
|
||||
break;
|
||||
|
||||
case Selection:
|
||||
qskDialog->select( text(), text(), { "yes", "no", "maybe" } );
|
||||
break;
|
||||
}
|
||||
qskDialog->message( "Message", "Request vector, over.",
|
||||
QskStandardSymbol::NoSymbol, QskDialog::Close );
|
||||
}
|
||||
|
||||
const ButtonType m_type;
|
||||
void execInformation()
|
||||
{
|
||||
qskDialog->information( "Information",
|
||||
"We have clearance, Clarence." );
|
||||
}
|
||||
|
||||
void execQuestion()
|
||||
{
|
||||
qskDialog->question( "Question",
|
||||
"Roger, Roger. Do we have a vector, Victor ?" );
|
||||
}
|
||||
|
||||
void execWarning()
|
||||
{
|
||||
qskDialog->warning( "Warning", "We have clearance, Clarence." );
|
||||
}
|
||||
|
||||
void execCritical()
|
||||
{
|
||||
qskDialog->critical( "Critical", "That's Clarence Oveur. Over." );
|
||||
}
|
||||
|
||||
void execSelection()
|
||||
{
|
||||
// of course we all love "The Teens"
|
||||
const QStringList entries =
|
||||
{
|
||||
"Give Me More",
|
||||
"Gimme Gimme Your Love",
|
||||
"1-2-3-4 Red Light",
|
||||
"New York",
|
||||
"If You Walk Away",
|
||||
"Eloise",
|
||||
"On The Radio",
|
||||
"We Are The Teens",
|
||||
"Never Gonna Tell No Lie To You",
|
||||
"Walking On Sunshine ",
|
||||
"Get Out Of My Mind",
|
||||
"Cover Girl ",
|
||||
"Here I Stand",
|
||||
"Gypsy Caravan",
|
||||
"It´s Good To Have A Friend",
|
||||
"We´ll Have A Party Tonite ´nite",
|
||||
"Automatic World",
|
||||
"Gimme Gimme Gimme Gimme Gimme Your Love"
|
||||
};
|
||||
|
||||
qskDialog->select( "Here we go ...", "Hot Hot Hot", entries, 7 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
DialogPage::DialogPage( QQuickItem* parent )
|
||||
: Page( Qt::Horizontal, parent )
|
||||
{
|
||||
auto box = new QskLinearBox( Qt::Horizontal, 2, this );
|
||||
box->setSpacing( 20 );
|
||||
box->setExtraSpacingAt( Qt::BottomEdge );
|
||||
|
||||
for ( int i = 0; i < Button::TypeCount; i++ )
|
||||
new Button( static_cast< Button::ButtonType >( i ), box );
|
||||
( void ) new ButtonBox( this );
|
||||
}
|
||||
|
||||
#include "DialogPage.moc"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ListBoxPage.h"
|
||||
#include <QskSimpleListBox.h>
|
||||
#include <QskFunctions.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class ListBox : public QskSimpleListBox
|
||||
{
|
||||
public:
|
||||
ListBox( QQuickItem* parent = nullptr )
|
||||
: QskSimpleListBox( parent )
|
||||
{
|
||||
setMargins( QMarginsF( 15, 10, 10, 10 ) );
|
||||
populate();
|
||||
|
||||
setSelectedRow( 5 );
|
||||
}
|
||||
|
||||
private:
|
||||
void populate()
|
||||
{
|
||||
const int count = 10000;
|
||||
|
||||
const QString format( "Row %1: The quick brown fox jumps over the lazy dog" );
|
||||
|
||||
QStringList entries;
|
||||
entries.reserve( count );
|
||||
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
entries += format.arg( i + 1 );
|
||||
}
|
||||
|
||||
// we know, that the last entry is the longest one and
|
||||
// can prevent the list box from having to find it out
|
||||
// the expensive way.
|
||||
|
||||
const qreal maxWidth = qskHorizontalAdvance( effectiveFont( Cell ), entries.last() );
|
||||
setColumnWidthHint( 0, maxWidth );
|
||||
|
||||
append( entries );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ListBoxPage::ListBoxPage( QQuickItem* parent )
|
||||
: Page( Qt::Horizontal, parent )
|
||||
{
|
||||
setMargins( 5 );
|
||||
(void) new ListBox( this );
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Page.h"
|
||||
|
||||
class ListBoxPage : public Page
|
||||
{
|
||||
public:
|
||||
ListBoxPage( QQuickItem* = nullptr );
|
||||
};
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
#include "button/ButtonPage.h"
|
||||
#include "selector/SelectorPage.h"
|
||||
#include "dialog/DialogPage.h"
|
||||
#include "listbox/ListBoxPage.h"
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
#include <SkinnyShapeProvider.h>
|
||||
|
|
@ -100,6 +101,14 @@ namespace
|
|||
auto scrollArea = new QskScrollArea();
|
||||
scrollArea->setMargins( 5 );
|
||||
|
||||
#if 1
|
||||
/*
|
||||
We need a mode, where the focus policy gets adjusted
|
||||
when a scroll bar becomes visible. TODO ...
|
||||
*/
|
||||
scrollArea->setFocusPolicy( Qt::NoFocus );
|
||||
#endif
|
||||
|
||||
// hiding the viewport
|
||||
scrollArea->setGradientHint( QskScrollView::Viewport, QskGradient() );
|
||||
scrollArea->setBoxShapeHint( QskScrollView::Viewport, 0 );
|
||||
|
|
@ -232,6 +241,7 @@ namespace
|
|||
tabView->addPage( "Progress\nBars", new ProgressBarPage() );
|
||||
tabView->addPage( "Selectors", new SelectorPage() );
|
||||
tabView->addPage( "Dialogs", new DialogPage() );
|
||||
tabView->addPage( "ListBox", new ListBoxPage() );
|
||||
|
||||
connect( header, &Header::enabledToggled,
|
||||
tabView, &TabView::setPagesEnabled );
|
||||
|
|
@ -251,8 +261,11 @@ int main( int argc, char* argv[] )
|
|||
Qsk::addGraphicProvider( QString(), new GraphicProvider() );
|
||||
Qsk::addGraphicProvider( "shapes", new SkinnyShapeProvider() );
|
||||
|
||||
// dialogs in faked windows -> QskSubWindow
|
||||
QskDialog::instance()->setPolicy( QskDialog::EmbeddedBox );
|
||||
if ( true ) // environment variable, TODO ...
|
||||
{
|
||||
// dialogs in faked windows -> QskSubWindow
|
||||
QskDialog::instance()->setPolicy( QskDialog::EmbeddedBox );
|
||||
}
|
||||
|
||||
QGuiApplication app( argc, argv );
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ Qsk.Window
|
|||
width: 600
|
||||
height: 600
|
||||
|
||||
color: "Beige"
|
||||
|
||||
Qsk.LinearBox
|
||||
{
|
||||
orientation: Qt.Horizontal
|
||||
panel: true
|
||||
|
||||
dimension: 3
|
||||
|
||||
//margins: 10
|
||||
margins { left: 10; top: 10; right: 10; bottom: 10 }
|
||||
//padding: 10
|
||||
padding { left: 10; top: 10; right: 10; bottom: 10 }
|
||||
spacing: 20
|
||||
|
||||
Repeater
|
||||
|
|
|
|||
|
|
@ -20,6 +20,29 @@
|
|||
|
||||
#include <QGuiApplication>
|
||||
|
||||
namespace
|
||||
{
|
||||
class TabView : public QskTabView
|
||||
{
|
||||
public:
|
||||
TabView( QQuickItem* parent = nullptr )
|
||||
: QskTabView( parent )
|
||||
{
|
||||
setMargins( 10 );
|
||||
setTabBarEdge( Qt::LeftEdge );
|
||||
setAutoFitTabs( true );
|
||||
|
||||
addTab( "Grid Layout", new GridLayoutPage() );
|
||||
addTab( "Flow Layout", new FlowLayoutPage() );
|
||||
addTab( "Linear Layout", new LinearLayoutPage() );
|
||||
addTab( "Dynamic\nConstraints", new DynamicConstraintsPage() );
|
||||
addTab( "Stack Layout", new StackLayoutPage() );
|
||||
|
||||
setCurrentIndex( 0 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
#ifdef ITEM_STATISTICS
|
||||
|
|
@ -32,25 +55,16 @@ int main( int argc, char* argv[] )
|
|||
|
||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
auto tabView = new QskTabView();
|
||||
auto box = new QskBox(); // to have a themed application background
|
||||
box->setAutoLayoutChildren( true );
|
||||
|
||||
tabView->setMargins( 10 );
|
||||
tabView->setTabBarEdge( Qt::LeftEdge );
|
||||
tabView->setAutoFitTabs( true );
|
||||
|
||||
tabView->addTab( "Grid Layout", new GridLayoutPage() );
|
||||
tabView->addTab( "Flow Layout", new FlowLayoutPage() );
|
||||
tabView->addTab( "Linear Layout", new LinearLayoutPage() );
|
||||
tabView->addTab( "Dynamic\nConstraints", new DynamicConstraintsPage() );
|
||||
tabView->addTab( "Stack Layout", new StackLayoutPage() );
|
||||
|
||||
tabView->setCurrentIndex( 0 );
|
||||
(void) new TabView( box );
|
||||
|
||||
QSize size( 800, 600 );
|
||||
size = size.expandedTo( tabView->sizeHint().toSize() );
|
||||
size = size.expandedTo( box->sizeHint().toSize() );
|
||||
|
||||
QskWindow window;
|
||||
window.addItem( tabView );
|
||||
window.addItem( box );
|
||||
window.addItem( new QskFocusIndicator() );
|
||||
|
||||
window.resize( size );
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
############################################################################
|
||||
# QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
############################################################################
|
||||
|
||||
qsk_add_example(listbox main.cpp)
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
|
||||
#include <QskAspect.h>
|
||||
#include <QskObjectCounter.h>
|
||||
#include <QskSimpleListBox.h>
|
||||
#include <QskWindow.h>
|
||||
#include <QskFunctions.h>
|
||||
|
||||
#include <QFontMetricsF>
|
||||
#include <QGuiApplication>
|
||||
|
||||
class ListBox : public QskSimpleListBox
|
||||
{
|
||||
public:
|
||||
ListBox()
|
||||
{
|
||||
setMargins( QMarginsF( 15, 10, 10, 10 ) );
|
||||
setAlternatingRowColors( true );
|
||||
|
||||
// increasing the padding of each row: usually the job of the skin !
|
||||
setPaddingHint( Cell, QMargins( 10, 20, 10, 20 ) );
|
||||
|
||||
populate();
|
||||
|
||||
setSelectedRow( 5 );
|
||||
}
|
||||
|
||||
private:
|
||||
void populate()
|
||||
{
|
||||
const int count = 10000;
|
||||
|
||||
const QString format( "Row %1: The quick brown fox jumps over the lazy dog" );
|
||||
|
||||
QStringList entries;
|
||||
entries.reserve( count );
|
||||
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
entries += format.arg( i + 1 );
|
||||
}
|
||||
|
||||
// we know, that the last entry is the longest one and
|
||||
// can prevent the list box from having to find it out
|
||||
// the expensive way.
|
||||
|
||||
const qreal maxWidth = qskHorizontalAdvance( effectiveFont( Cell ), entries.last() );
|
||||
setColumnWidthHint( 0, maxWidth );
|
||||
|
||||
append( entries );
|
||||
}
|
||||
};
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
#ifdef ITEM_STATISTICS
|
||||
QskObjectCounter counter( true );
|
||||
#endif
|
||||
|
||||
QGuiApplication app( argc, argv );
|
||||
|
||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
QskWindow window;
|
||||
window.setColor( "Silver" );
|
||||
|
||||
window.addItem( new ListBox() );
|
||||
window.resize( 400, 600 );
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
############################################################################
|
||||
# QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
############################################################################
|
||||
|
||||
qsk_add_example(messagebox main.cpp)
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
|
||||
#include <QFontDatabase>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <QskAspect.h>
|
||||
#include <QskDialog.h>
|
||||
#include <QskFocusIndicator.h>
|
||||
#include <QskLinearBox.h>
|
||||
#include <QskObjectCounter.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskStandardSymbol.h>
|
||||
#include <QskWindow.h>
|
||||
|
||||
class Button : public QskPushButton
|
||||
{
|
||||
public:
|
||||
Button( const QString& text, QQuickItem* parent = nullptr )
|
||||
: QskPushButton( text, parent )
|
||||
{
|
||||
setObjectName( text );
|
||||
setSizePolicy( QskSizePolicy::MinimumExpanding,
|
||||
QskSizePolicy::MinimumExpanding );
|
||||
}
|
||||
};
|
||||
|
||||
class ButtonBox : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
ButtonBox( QQuickItem* parent = nullptr )
|
||||
: QskLinearBox( Qt::Horizontal, 2, parent )
|
||||
{
|
||||
setObjectName( "ButtonBox" );
|
||||
|
||||
setMargins( 10 );
|
||||
setSpacing( 5 );
|
||||
|
||||
Button* messageButton = new Button( "Message", this );
|
||||
connect( messageButton, &Button::clicked, this, &ButtonBox::execMessage );
|
||||
|
||||
Button* informationButton = new Button( "Information", this );
|
||||
connect( informationButton, &Button::clicked, this, &ButtonBox::execInformation );
|
||||
|
||||
Button* questionButton = new Button( "Question", this );
|
||||
connect( questionButton, &Button::clicked, this, &ButtonBox::execQuestion );
|
||||
|
||||
Button* warningButton = new Button( "Warning", this );
|
||||
connect( warningButton, &Button::clicked, this, &ButtonBox::execWarning );
|
||||
|
||||
Button* criticalButton = new Button( "Critical", this );
|
||||
connect( criticalButton, &Button::clicked, this, &ButtonBox::execCritical );
|
||||
|
||||
Button* selectButton = new Button( "Selection", this );
|
||||
connect( selectButton, &Button::clicked, this, &ButtonBox::execSelection );
|
||||
}
|
||||
|
||||
private:
|
||||
void execMessage()
|
||||
{
|
||||
qDebug() << qskDialog->message( "Message", "Request vector, over.",
|
||||
QskStandardSymbol::NoSymbol, QskDialog::Close );
|
||||
}
|
||||
|
||||
void execInformation()
|
||||
{
|
||||
qDebug() << qskDialog->information( "Information",
|
||||
"We have clearance, Clarence." );
|
||||
}
|
||||
|
||||
void execQuestion()
|
||||
{
|
||||
qDebug() << qskDialog->question( "Question",
|
||||
"Roger, Roger. Do we have a vector, Victor ?" );
|
||||
}
|
||||
|
||||
void execWarning()
|
||||
{
|
||||
qDebug() << qskDialog->warning( "Warning", "We have clearance, Clarence." );
|
||||
}
|
||||
|
||||
void execCritical()
|
||||
{
|
||||
qDebug() << qskDialog->critical( "Critical", "That's Clarence Oveur. Over." );
|
||||
}
|
||||
|
||||
void execSelection()
|
||||
{
|
||||
// of course we all love "The Teens"
|
||||
const QStringList entries =
|
||||
{
|
||||
"Give Me More",
|
||||
"Gimme Gimme Your Love",
|
||||
"1-2-3-4 Red Light",
|
||||
"New York",
|
||||
"If You Walk Away",
|
||||
"Eloise",
|
||||
"On The Radio",
|
||||
"We Are The Teens",
|
||||
"Never Gonna Tell No Lie To You",
|
||||
"Walking On Sunshine ",
|
||||
"Get Out Of My Mind",
|
||||
"Cover Girl ",
|
||||
"Here I Stand",
|
||||
"Gypsy Caravan",
|
||||
"It´s Good To Have A Friend",
|
||||
"We´ll Have A Party Tonite ´nite",
|
||||
"Automatic World",
|
||||
"Gimme Gimme Gimme Gimme Gimme Your Love"
|
||||
};
|
||||
|
||||
qDebug() << qskDialog->select( "Here we go ...", "Hot Hot Hot", entries, 7 );
|
||||
}
|
||||
};
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
#ifdef ITEM_STATISTICS
|
||||
QskObjectCounter counter( true );
|
||||
#endif
|
||||
|
||||
QGuiApplication app( argc, argv );
|
||||
|
||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
qskDialog->setPolicy( QskDialog::EmbeddedBox );
|
||||
|
||||
auto box = new ButtonBox();
|
||||
|
||||
/*
|
||||
To avoid losing the focus, when a message box is executed
|
||||
we have to define the "main window" ( here a ButtonBox ) to
|
||||
be a focusScope.
|
||||
*/
|
||||
box->setFlag( QQuickItem::ItemIsFocusScope, true );
|
||||
box->setTabFence( true );
|
||||
box->setFocusPolicy( Qt::TabFocus );
|
||||
|
||||
// setting the initial focus
|
||||
box->itemAtIndex( 0 )->setFocus( true );
|
||||
box->setFocus( true );
|
||||
|
||||
QskWindow window;
|
||||
window.addItem( box );
|
||||
window.addItem( new QskFocusIndicator() );
|
||||
|
||||
window.resize( 800, 800 );
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
############################################################################
|
||||
# QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
############################################################################
|
||||
|
||||
set(SOURCES main.cpp)
|
||||
qt_add_resources(SOURCES messagebox.qrc)
|
||||
|
||||
qsk_add_example(messageboxQml ${SOURCES})
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include <SkinnyShortcut.h>
|
||||
|
||||
#include <QskQml.h>
|
||||
#include <QskObjectCounter.h>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
#ifdef ITEM_STATISTICS
|
||||
QskObjectCounter counter( true );
|
||||
#endif
|
||||
|
||||
QskQml::registerTypes();
|
||||
|
||||
QGuiApplication app( argc, argv );
|
||||
|
||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
QQmlApplicationEngine engine( QUrl( "qrc:/qml/messagebox.qml" ) );
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
import QtQuick 2.0
|
||||
import Skinny 1.0 as Qsk
|
||||
import "qrc:/qml"
|
||||
|
||||
Qsk.Window
|
||||
{
|
||||
id: window
|
||||
|
||||
visible: true
|
||||
width: 600
|
||||
height: 400
|
||||
// color: "Beige"
|
||||
|
||||
Qsk.LinearBox
|
||||
{
|
||||
orientation: Qt.Horizontal
|
||||
dimension: 2
|
||||
|
||||
margins { left: 10; top: 10; right: 10; bottom: 10 }
|
||||
//margins: 10
|
||||
|
||||
Qsk.PushButton
|
||||
{
|
||||
id: messageButton
|
||||
text: "Message"
|
||||
|
||||
focus: true
|
||||
|
||||
sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var answer = Qsk.Dialog.message(
|
||||
"Message", "Request vector, over.",
|
||||
Qsk.StandardSymbol.NoSymbol, Qsk.Dialog.Close
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Qsk.PushButton
|
||||
{
|
||||
id: informationButton
|
||||
text: "Information"
|
||||
|
||||
sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var answer = Qsk.Dialog.information(
|
||||
"Information", "We have clearance, Clarence."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Qsk.PushButton
|
||||
{
|
||||
id: questionButton
|
||||
text: "Question"
|
||||
|
||||
sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var answer = Qsk.Dialog.question(
|
||||
"Question", "Roger, Roger. Do we have a vector, Victor ?",
|
||||
Qsk.Dialog.Yes | Qsk.Dialog.No
|
||||
)
|
||||
|
||||
if ( answer == Qsk.Dialog.Yes )
|
||||
console.log( "Yes" )
|
||||
else
|
||||
console.log( "No" )
|
||||
}
|
||||
}
|
||||
|
||||
Qsk.PushButton
|
||||
{
|
||||
id: warningButton
|
||||
text: "Warning"
|
||||
|
||||
sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var answer = Qsk.Dialog.warning(
|
||||
"Warning", "We have clearance, Clarence."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Qsk.PushButton
|
||||
{
|
||||
id: criticalButton
|
||||
text: "Critical"
|
||||
|
||||
sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var answer = Qsk.Dialog.critical(
|
||||
"Critical", "That's Clarence Oveur. Over."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Qsk.PushButton
|
||||
{
|
||||
id: selectionButton
|
||||
text: "Selection"
|
||||
|
||||
sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding
|
||||
|
||||
onClicked:
|
||||
{
|
||||
var hotTracks = [
|
||||
"Give Me More",
|
||||
"Gimme Gimme Your Love",
|
||||
"1-2-3-4 Red Light",
|
||||
"New York",
|
||||
"If You Walk Away",
|
||||
"Eloise",
|
||||
"On The Radio",
|
||||
"We Are The Teens",
|
||||
"Never Gonna Tell No Lie To You",
|
||||
"Walking On Sunshine ",
|
||||
"Get Out Of My Mind",
|
||||
"Cover Girl ",
|
||||
"Here I Stand",
|
||||
"Gypsy Caravan",
|
||||
"It´s Good To Have A Friend",
|
||||
"We´ll Have A Party Tonite ´nite",
|
||||
"Automatic World",
|
||||
"Gimme Gimme Gimme Gimme Gimme Your Love"
|
||||
]
|
||||
|
||||
var hottestTrackEver = Qsk.Dialog.select(
|
||||
"Here we go ...", "Hot Hot Hot", hotTracks, 7 )
|
||||
|
||||
console.log( hottestTrackEver )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qsk.FocusIndicator
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/qml">
|
||||
<file>messagebox.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
@ -28,7 +28,7 @@ class GraphicLabel : public QskGraphicLabel
|
|||
public:
|
||||
enum Role
|
||||
{
|
||||
Normal,
|
||||
Normal = 1000,
|
||||
Inverted
|
||||
};
|
||||
|
||||
|
|
@ -94,7 +94,8 @@ MainWindow::MainWindow()
|
|||
invertButton->setLayoutAlignmentHint( Qt::AlignRight );
|
||||
|
||||
auto box = new QskLinearBox( Qt::Vertical );
|
||||
box->setMargins( 5 );
|
||||
box->setPanel( true );
|
||||
box->setPadding( 5 );
|
||||
box->addItem( invertButton );
|
||||
box->addItem( m_tabView );
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ int main( int argc, char* argv[] )
|
|||
|
||||
QGuiApplication app( argc, argv );
|
||||
|
||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
SkinnyShortcut::enable( SkinnyShortcut::DebugBackground |
|
||||
SkinnyShortcut::DebugStatistics | SkinnyShortcut::Quit );
|
||||
|
||||
auto focusIndicator = new QskFocusIndicator();
|
||||
focusIndicator->setObjectName( "FocusIndicator" );
|
||||
|
|
|
|||
|
|
@ -160,8 +160,9 @@ int main( int argc, char* argv[] )
|
|||
|
||||
auto layoutBox = new QskLinearBox( Qt::Vertical );
|
||||
layoutBox->setDefaultAlignment( Qt::AlignLeft );
|
||||
layoutBox->setMargins( 20 );
|
||||
layoutBox->setPadding( 20 );
|
||||
layoutBox->setSpacing( 10 );
|
||||
layoutBox->setPanel( true );
|
||||
layoutBox->addItem( buttonBox );
|
||||
layoutBox->addItem( tabView );
|
||||
|
||||
|
|
|
|||
|
|
@ -77,8 +77,6 @@ class Thumbnail : public QskPushButton
|
|||
|
||||
setBoxShapeHint( QskPushButton::Panel, QskBoxShapeMetrics( 20, Qt::RelativeSize ) );
|
||||
setStrutSizeHint( QskPushButton::Icon, -1, -1 );
|
||||
|
||||
setSection( QskAspect::Header ); // to make them flat
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -191,7 +189,8 @@ class ScrollArea : public QskScrollArea
|
|||
{
|
||||
// settings usually done in the skins
|
||||
setBoxBorderMetricsHint( Viewport, 2 );
|
||||
setBoxShapeHint( Viewport, 20 );
|
||||
setBoxBorderColorsHint( Viewport, Qt::gray ); // works with most color schemes
|
||||
setBoxShapeHint( Viewport, 40 ); // a radius to see that clipping works
|
||||
|
||||
for ( auto subControl : { HorizontalScrollBar, VerticalScrollBar } )
|
||||
setMetric( subControl | QskAspect::Size, 20 );
|
||||
|
|
@ -257,7 +256,8 @@ int main( int argc, char* argv[] )
|
|||
*/
|
||||
|
||||
auto box = new QskLinearBox( Qt::Vertical );
|
||||
box->setMargins( 20 );
|
||||
box->setPanel( true );
|
||||
box->setPadding( 20 );
|
||||
|
||||
auto buttonBox = new QskLinearBox( Qt::Horizontal, box );
|
||||
buttonBox->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
|
||||
|
|
@ -280,7 +280,6 @@ int main( int argc, char* argv[] )
|
|||
|
||||
QskWindow window;
|
||||
window.resize( 600, 600 );
|
||||
window.setColor( "SteelBlue" );
|
||||
window.addItem( box );
|
||||
window.addItem( focusIndicator );
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ Window::Window( Qt::Orientation orientation )
|
|||
{
|
||||
m_layoutBox = new QskLinearBox( invertedOrientation() );
|
||||
m_layoutBox->setObjectName( "MainBox" );
|
||||
m_layoutBox->setMargins( 10 );
|
||||
m_layoutBox->setPanel( true );
|
||||
m_layoutBox->setPadding( 10 );
|
||||
m_layoutBox->setExtraSpacingAt( Qt::BottomEdge | Qt::RightEdge );
|
||||
|
||||
addBox( QskDialog::Ok );
|
||||
|
|
|
|||
|
|
@ -329,7 +329,8 @@ class Window : public QskWindow
|
|||
{
|
||||
auto box = new QskLinearBox( Qt::Horizontal );
|
||||
box->setSpacing( 10 );
|
||||
box->setMargins( 20 );
|
||||
box->setPadding( 10 );
|
||||
box->setPanel( true );
|
||||
|
||||
auto listView = new LocaleListView( box );
|
||||
auto inputBox = new InputBox( box );
|
||||
|
|
@ -367,14 +368,14 @@ int main( int argc, char* argv[] )
|
|||
|
||||
Window window1;
|
||||
window1.setObjectName( "Window 1" );
|
||||
window1.setColor( "PapayaWhip" );
|
||||
window1.setTitle( "Window 1" );
|
||||
window1.resize( 600, 600 );
|
||||
window1.show();
|
||||
|
||||
#if 1
|
||||
Window window2;
|
||||
window2.setObjectName( "Window 2" );
|
||||
window2.setColor( "Pink" );
|
||||
window2.setTitle( "Window 2" );
|
||||
window2.setX( window1.x() + 100 );
|
||||
window2.resize( 600, 600 );
|
||||
window2.show();
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ class GridBox : public QskGridBox
|
|||
GridBox( QQuickItem* parent = nullptr )
|
||||
: QskGridBox( parent )
|
||||
{
|
||||
setMargins( 5 );
|
||||
setPanel( true );
|
||||
setPadding( 5 );
|
||||
setColumnStretchFactor( 1, 1 );
|
||||
|
||||
auto sliderX = new Slider( -50, 50, 1, 10 );
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
############################################################################
|
||||
|
||||
set(SOURCES
|
||||
QskFluent2Global.h QskFluent2Skin.h QskFluent2Skin.cpp
|
||||
QskFluent2Global.h
|
||||
QskFluent2Theme.h QskFluent2Theme.cpp
|
||||
QskFluent2Skin.h QskFluent2Skin.cpp
|
||||
QskFluent2SkinFactory.h QskFluent2SkinFactory.cpp
|
||||
)
|
||||
qt_add_resources(SOURCES icons.qrc)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef QSK_FLUENT2_GLOBAL_H
|
||||
#define QSK_FLUENT2_GLOBAL_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <QskGlobal.h>
|
||||
|
||||
#ifdef QSK_DLL
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,327 +7,9 @@
|
|||
#define QSK_FLUENT2_SKIN_H
|
||||
|
||||
#include "QskFluent2Global.h"
|
||||
|
||||
#include <QskBoxShapeMetrics.h>
|
||||
#include <QskGradient.h>
|
||||
#include <QskShadowMetrics.h>
|
||||
#include <QskSkin.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
class QSK_FLUENT2_EXPORT QskFluent2Theme
|
||||
{
|
||||
public:
|
||||
enum Theme
|
||||
{
|
||||
Light,
|
||||
Dark
|
||||
};
|
||||
|
||||
enum AccentColors
|
||||
{
|
||||
AccentLight3,
|
||||
AccentLight2,
|
||||
AccentLight1,
|
||||
AccentBase,
|
||||
AccentDark1,
|
||||
AccentDark2,
|
||||
AccentDark3,
|
||||
|
||||
NumAccentColors
|
||||
};
|
||||
|
||||
QskFluent2Theme( Theme );
|
||||
QskFluent2Theme( Theme, std::array< QRgb, NumAccentColors > );
|
||||
|
||||
typedef std::array< QRgb, 2 > BorderGradient;
|
||||
|
||||
struct FillColor
|
||||
{
|
||||
struct Text
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct AccentText
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct TextOnAccent
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
QRgb selectedText;
|
||||
};
|
||||
|
||||
struct Control
|
||||
{
|
||||
QRgb transparent;
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb inputActive;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct ControlStrong
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct Subtle
|
||||
{
|
||||
QRgb transparent;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct ControlSolid
|
||||
{
|
||||
QRgb defaultColor;
|
||||
};
|
||||
|
||||
struct ControlAlt
|
||||
{
|
||||
QRgb transparent;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb quaternary;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct Accent
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
QRgb selectedTextBackground;
|
||||
};
|
||||
|
||||
struct System
|
||||
{
|
||||
QRgb critical;
|
||||
QRgb success;
|
||||
QRgb attention;
|
||||
QRgb caution;
|
||||
QRgb attentionBackground;
|
||||
QRgb successBackground;
|
||||
QRgb cautionBackground;
|
||||
QRgb criticalBackground;
|
||||
QRgb neutral;
|
||||
QRgb neutralBackground;
|
||||
QRgb solidNeutral;
|
||||
QRgb solidAttentionBackground;
|
||||
QRgb solidNeutralBackground;
|
||||
};
|
||||
|
||||
struct ControlOnImage
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
Text text;
|
||||
AccentText accentText;
|
||||
TextOnAccent textOnAccent;
|
||||
Control control;
|
||||
ControlStrong controlStrong;
|
||||
Subtle subtle;
|
||||
ControlSolid controlSolid;
|
||||
ControlAlt controlAlt;
|
||||
Accent accent;
|
||||
System system;
|
||||
ControlOnImage controlOnImage;
|
||||
};
|
||||
|
||||
struct Elevation
|
||||
{
|
||||
struct Control
|
||||
{
|
||||
BorderGradient border;
|
||||
};
|
||||
|
||||
struct Circle
|
||||
{
|
||||
BorderGradient border;
|
||||
};
|
||||
|
||||
struct TextControl
|
||||
{
|
||||
BorderGradient border;
|
||||
BorderGradient borderFocused;
|
||||
};
|
||||
|
||||
struct AccentControl
|
||||
{
|
||||
BorderGradient border;
|
||||
};
|
||||
|
||||
Control control;
|
||||
Circle circle;
|
||||
TextControl textControl;
|
||||
AccentControl accentControl;
|
||||
};
|
||||
|
||||
struct StrokeColor
|
||||
{
|
||||
struct ControlStroke
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb onAccentDefault;
|
||||
QRgb onAccentSecondary;
|
||||
QRgb onAccentTertiary;
|
||||
QRgb onAccentDisabled;
|
||||
QRgb forStrongFillWhenOnImage;
|
||||
};
|
||||
|
||||
struct ControlStrongStroke
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb disabled;
|
||||
};
|
||||
|
||||
struct CardStroke
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb defaultSolid;
|
||||
};
|
||||
|
||||
struct DividerStroke
|
||||
{
|
||||
QRgb defaultColor;
|
||||
};
|
||||
|
||||
struct SurfaceStroke
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb flyout;
|
||||
};
|
||||
|
||||
struct FocusStroke
|
||||
{
|
||||
QRgb outer;
|
||||
QRgb inner;
|
||||
};
|
||||
|
||||
ControlStroke controlStroke;
|
||||
ControlStrongStroke controlStrongStroke;
|
||||
CardStroke cardStroke;
|
||||
DividerStroke dividerStroke;
|
||||
SurfaceStroke surfaceStroke;
|
||||
FocusStroke focusStroke;
|
||||
};
|
||||
|
||||
struct Background
|
||||
{
|
||||
struct FillColor
|
||||
{
|
||||
struct CardBackground
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
};
|
||||
|
||||
struct Smoke
|
||||
{
|
||||
QRgb defaultColor;
|
||||
};
|
||||
|
||||
struct Layer
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb alt;
|
||||
};
|
||||
|
||||
struct LayerOnAcrylic
|
||||
{
|
||||
QRgb defaultColor;
|
||||
};
|
||||
|
||||
struct LayerOnAccentAcrylic
|
||||
{
|
||||
QRgb defaultColor;
|
||||
};
|
||||
|
||||
struct AcrylicBackground
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb base;
|
||||
};
|
||||
|
||||
struct AccentAcrylicBackground
|
||||
{
|
||||
QRgb base;
|
||||
QRgb defaultColor;
|
||||
};
|
||||
|
||||
struct MicaBackground
|
||||
{
|
||||
QRgb base;
|
||||
};
|
||||
|
||||
struct SolidBackground
|
||||
{
|
||||
QRgb base;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb quaternary;
|
||||
};
|
||||
|
||||
CardBackground cardBackground;
|
||||
Smoke smoke;
|
||||
Layer layer;
|
||||
LayerOnAcrylic layerOnAcrylic;
|
||||
LayerOnAccentAcrylic layerOnAccentAcrylic;
|
||||
AcrylicBackground acrylicBackground;
|
||||
AccentAcrylicBackground accentAcrylicBackground;
|
||||
MicaBackground micaBackground;
|
||||
SolidBackground solidBackground;
|
||||
};
|
||||
|
||||
FillColor fillColor;
|
||||
};
|
||||
|
||||
|
||||
struct Palette
|
||||
{
|
||||
FillColor fillColor;
|
||||
Elevation elevation;
|
||||
StrokeColor strokeColor;
|
||||
Background background;
|
||||
};
|
||||
|
||||
Palette palette;
|
||||
|
||||
typedef QPair< QskShadowMetrics, QRgb > ShadowSettings;
|
||||
|
||||
struct Shadow
|
||||
{
|
||||
ShadowSettings cardRest;
|
||||
ShadowSettings cardHover;
|
||||
ShadowSettings tooltip;
|
||||
ShadowSettings flyout;
|
||||
ShadowSettings dialog;
|
||||
};
|
||||
|
||||
Shadow shadow;
|
||||
};
|
||||
class QskFluent2Theme;
|
||||
|
||||
class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin
|
||||
{
|
||||
|
|
@ -336,8 +18,11 @@ class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin
|
|||
using Inherited = QskSkin;
|
||||
|
||||
public:
|
||||
QskFluent2Skin( const QskFluent2Theme&, QObject* parent = nullptr );
|
||||
~QskFluent2Skin() override;
|
||||
QskFluent2Skin( QObject* parent = nullptr );
|
||||
~QskFluent2Skin() override;
|
||||
|
||||
void addTheme( QskAspect::Section, const QskFluent2Theme& );
|
||||
void setup();
|
||||
|
||||
enum GraphicRole
|
||||
{
|
||||
|
|
@ -366,7 +51,7 @@ class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin
|
|||
|
||||
private:
|
||||
void setupFonts();
|
||||
void setupGraphicFilters( const QskFluent2Theme& palette );
|
||||
void setupGraphicFilters( const QskFluent2Theme& );
|
||||
void setGraphicColor( GraphicRole, QRgb );
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,18 @@
|
|||
|
||||
#include "QskFluent2SkinFactory.h"
|
||||
#include "QskFluent2Skin.h"
|
||||
#include "QskFluent2Theme.h"
|
||||
|
||||
static const QString fluent2LightSkinName = QStringLiteral( "Fluent2 Light" );
|
||||
static const QString fluent2DarkSkinName = QStringLiteral( "Fluent2 Dark" );
|
||||
static const QString nameLight = QStringLiteral( "Fluent2 Light" );
|
||||
static const QString nameDark = QStringLiteral( "Fluent2 Dark" );
|
||||
|
||||
namespace
|
||||
{
|
||||
inline constexpr QRgb rgbGray( int value )
|
||||
{
|
||||
return qRgba( value, value, value, 255 );
|
||||
}
|
||||
}
|
||||
|
||||
QskFluent2SkinFactory::QskFluent2SkinFactory( QObject* parent )
|
||||
: QskSkinFactory( parent )
|
||||
|
|
@ -20,23 +29,71 @@ QskFluent2SkinFactory::~QskFluent2SkinFactory()
|
|||
|
||||
QStringList QskFluent2SkinFactory::skinNames() const
|
||||
{
|
||||
return { fluent2LightSkinName, fluent2DarkSkinName };
|
||||
return { nameLight, nameDark };
|
||||
}
|
||||
|
||||
QskSkin* QskFluent2SkinFactory::createSkin( const QString& skinName )
|
||||
{
|
||||
if ( QString::compare( skinName, fluent2LightSkinName, Qt::CaseInsensitive ) == 0 )
|
||||
QskSkin::ColorScheme colorScheme;
|
||||
|
||||
if ( QString::compare( skinName, nameLight, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
QskFluent2Theme theme( QskFluent2Theme::Light );
|
||||
return new QskFluent2Skin( theme );
|
||||
colorScheme = QskSkin::LightScheme;
|
||||
}
|
||||
else if ( QString::compare( skinName, fluent2DarkSkinName, Qt::CaseInsensitive ) == 0 )
|
||||
else if ( QString::compare( skinName, nameDark, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
QskFluent2Theme theme( QskFluent2Theme::Dark );
|
||||
return new QskFluent2Skin( theme );
|
||||
colorScheme = QskSkin::DarkScheme;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
struct
|
||||
{
|
||||
QskSkin::ColorScheme scheme;
|
||||
QskFluent2Theme::BaseColors baseColors;
|
||||
QskFluent2Theme::AccentColors accentColors;
|
||||
|
||||
QskFluent2Theme theme() const { return { scheme, baseColors, accentColors }; }
|
||||
} colors[2];
|
||||
|
||||
switch( colorScheme )
|
||||
{
|
||||
case QskSkin::LightScheme:
|
||||
{
|
||||
colors[0].scheme = colorScheme;
|
||||
colors[0].baseColors = { rgbGray( 243 ), rgbGray( 249 ), rgbGray( 238 ) };
|
||||
colors[0].accentColors = { 0xff0078d4, 0xff005eb7, 0xff003d92, 0xff001968 };
|
||||
|
||||
colors[1].scheme = colorScheme;
|
||||
colors[1].baseColors = { rgbGray( 249 ), rgbGray( 249 ), rgbGray( 238 ) };
|
||||
colors[1].accentColors = colors[0].accentColors;
|
||||
|
||||
break;
|
||||
}
|
||||
case QskSkin::DarkScheme:
|
||||
{
|
||||
colors[0].scheme = colorScheme;
|
||||
colors[0].baseColors = { rgbGray( 32 ), rgbGray( 40 ), rgbGray( 28 ) };
|
||||
colors[0].accentColors = { 0xff0078d4, 0xff0093f9, 0xff60ccfe, 0xff98ecfe };
|
||||
|
||||
colors[1].scheme = colorScheme;
|
||||
colors[1].baseColors = { rgbGray( 40 ), rgbGray( 44 ), rgbGray( 28 ) };
|
||||
colors[1].accentColors = colors[0].accentColors;
|
||||
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
|
||||
auto skin = new QskFluent2Skin();
|
||||
|
||||
skin->addTheme( QskAspect::Body, colors[0].theme() );
|
||||
skin->addTheme( QskAspect::Header, colors[1].theme() );
|
||||
skin->addTheme( QskAspect::Footer, colors[1].theme() );
|
||||
|
||||
return skin;
|
||||
}
|
||||
|
||||
#include "moc_QskFluent2SkinFactory.cpp"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class QSK_FLUENT2_EXPORT QskFluent2SkinFactory : public QskSkinFactory
|
|||
|
||||
public:
|
||||
QskFluent2SkinFactory( QObject* parent = nullptr );
|
||||
~QskFluent2SkinFactory() override;
|
||||
~QskFluent2SkinFactory() override;
|
||||
|
||||
QStringList skinNames() const override;
|
||||
QskSkin* createSkin( const QString& skinName ) override;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,278 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2023 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskFluent2Theme.h"
|
||||
#include <QskRgbValue.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline constexpr QRgb rgbGray( int value, qreal opacity = 1.0 )
|
||||
{
|
||||
return qRgba( value, value, value, qRound( opacity * 255 ) );
|
||||
}
|
||||
}
|
||||
|
||||
QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme,
|
||||
const BaseColors& baseColors, const AccentColors& accentColors )
|
||||
{
|
||||
using namespace QskRgb;
|
||||
|
||||
{
|
||||
auto& colors = palette.background;
|
||||
|
||||
colors.solid.base = baseColors.primary;
|
||||
colors.solid.secondary = baseColors.secondary;
|
||||
colors.solid.tertiary = baseColors.tertiary;
|
||||
}
|
||||
|
||||
if( colorScheme != QskSkin::DarkScheme )
|
||||
{
|
||||
{
|
||||
palette.background.solid.quaternary = rgbGray( 255 );
|
||||
}
|
||||
|
||||
{
|
||||
auto& colors = palette.fillColor;
|
||||
|
||||
colors.text.primary = rgbGray( 0, 0.8956 );
|
||||
colors.text.secondary = rgbGray( 0, 0.6063 );
|
||||
colors.text.tertiary = rgbGray( 0, 0.4458 );
|
||||
colors.text.disabled = rgbGray( 0, 0.3614 );
|
||||
|
||||
colors.accentText.primary = accentColors.tertiary;
|
||||
colors.accentText.secondary = accentColors.quaternary;
|
||||
colors.accentText.tertiary = accentColors.secondary;
|
||||
|
||||
colors.accentText.disabled = rgbGray( 0, 0.3614 );
|
||||
|
||||
colors.textOnAccent.primary = rgbGray( 255 );
|
||||
colors.textOnAccent.secondary = rgbGray( 255, 0.70 );
|
||||
colors.textOnAccent.disabled = rgbGray( 255 );
|
||||
colors.textOnAccent.selectedText = rgbGray( 255 );
|
||||
|
||||
colors.control.defaultColor = rgbGray( 255, 0.70 );
|
||||
colors.control.secondary = rgbGray( 249, 0.50 );
|
||||
colors.control.tertiary = rgbGray( 249, 0.30 );
|
||||
colors.control.inputActive = rgbGray( 255 );
|
||||
colors.control.disabled = rgbGray( 249, 0.30 );
|
||||
|
||||
colors.controlStrong.defaultColor = rgbGray( 0, 0.4458 );
|
||||
colors.controlStrong.disabled = rgbGray( 0, 0.3173 );
|
||||
|
||||
colors.subtle.secondary = rgbGray( 0, 0.0373 );
|
||||
colors.subtle.tertiary = rgbGray( 0, 0.0241 );
|
||||
colors.subtle.disabled = Qt::transparent;
|
||||
|
||||
colors.controlSolid.defaultColor = rgbGray( 255 );
|
||||
|
||||
colors.controlAlt.secondary = rgbGray( 0, 0.0241 );
|
||||
colors.controlAlt.tertiary = rgbGray( 0, 0.0578 );
|
||||
colors.controlAlt.quaternary = rgbGray( 0, 0.0924 );
|
||||
colors.controlAlt.disabled = Qt::transparent;
|
||||
|
||||
colors.accent.defaultColor = accentColors.secondary;
|
||||
colors.accent.secondary = toTransparentF( accentColors.secondary, 0.90 );
|
||||
colors.accent.tertiary = toTransparentF( accentColors.secondary, 0.80 );
|
||||
colors.accent.disabled = rgbGray( 0, 0.2169 );
|
||||
colors.accent.selectedTextBackground = accentColors.primary;
|
||||
|
||||
colors.acrylic.background = rgbGray( 252, 0.85 );
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// system colors
|
||||
|
||||
critical = 0xffc42b1c;
|
||||
success = 0xff0f7b0f;
|
||||
attention = 0xff005fb7;
|
||||
caution = 0xff9d5d00;
|
||||
attentionBackground = rgbGray( 246, 0.50 );
|
||||
successBackground = 0xffdff6dd;
|
||||
cautionBackground = 0xfffff4ce;
|
||||
criticalBackground = 0xfffde7e9;
|
||||
neutral = rgbGray( 0, 0.4458 );
|
||||
neutralBackground = rgbGray( 0, 0.0241 );
|
||||
|
||||
solidNeutral = rgbGray( 138 );
|
||||
solidAttentionBackground = rgbGray( 247 );
|
||||
solidNeutralBackground = rgbGray( 243 );
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
auto& colors = palette.elevation;
|
||||
|
||||
colors.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) };
|
||||
colors.circle.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) };
|
||||
colors.textControl.border = { rgbGray( 0, 0.0578 ), palette.fillColor.text.secondary };
|
||||
colors.textControl.borderFocused = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.0578 ) };
|
||||
colors.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.40 ) };
|
||||
}
|
||||
|
||||
{
|
||||
auto& colors = palette.strokeColor;
|
||||
|
||||
colors.control.defaultColor = rgbGray( 0, 0.0578 );
|
||||
colors.control.secondary = rgbGray( 0, 0.1622 );
|
||||
colors.control.onAccentDefault = rgbGray( 255.08 );
|
||||
colors.control.onAccentSecondary = rgbGray( 0, 0.40 );
|
||||
colors.control.onAccentTertiary = rgbGray( 0, 0.2169 );
|
||||
colors.control.onAccentDisabled = rgbGray( 0, 0.0578 );
|
||||
|
||||
colors.controlStrong.defaultColor = rgbGray( 0, 0.4458 );
|
||||
colors.controlStrong.disabled = rgbGray( 0, 0.2169 );
|
||||
|
||||
colors.card.defaultColor = rgbGray( 0, 0.0578 );
|
||||
colors.card.defaultSolid = rgbGray( 235 );
|
||||
|
||||
colors.divider.defaultColor = rgbGray( 0, 0.0803 );
|
||||
|
||||
colors.surface.defaultColor = rgbGray( 117, 0.40 );
|
||||
colors.surface.flyout = rgbGray( 0, 0.0578 );
|
||||
|
||||
colors.focus.outer = rgbGray( 0, 0.8956 );
|
||||
colors.focus.inner = rgbGray( 255 );
|
||||
}
|
||||
|
||||
{
|
||||
auto& colors = palette.background;
|
||||
|
||||
colors.overlay.defaultColor = rgbGray( 0, 0.30 );
|
||||
colors.layer.alt = rgbGray( 255 );
|
||||
colors.flyout.defaultColor = rgbGray( 252, 0.85 );
|
||||
|
||||
}
|
||||
|
||||
// Shadow:
|
||||
|
||||
shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.14 ) };
|
||||
// ### should actually be drawn twice with different values:
|
||||
shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) };
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
palette.background.solid.quaternary = rgbGray( 44 );
|
||||
}
|
||||
{
|
||||
auto& colors = palette.fillColor;
|
||||
|
||||
colors.text.primary = rgbGray( 255 );
|
||||
colors.text.secondary = rgbGray( 255, 0.786 );
|
||||
colors.text.tertiary = rgbGray( 255, 0.5442 );
|
||||
colors.text.disabled = rgbGray( 255, 0.3628 );
|
||||
|
||||
colors.accentText.primary = accentColors.quaternary;
|
||||
colors.accentText.secondary = accentColors.quaternary;
|
||||
colors.accentText.tertiary = accentColors.tertiary;
|
||||
colors.accentText.disabled = rgbGray( 255, 0.3628 );
|
||||
|
||||
colors.textOnAccent.primary = rgbGray( 0 );
|
||||
colors.textOnAccent.secondary = rgbGray( 0, 0.50 );
|
||||
colors.textOnAccent.disabled = rgbGray( 255, 0.5302 );
|
||||
colors.textOnAccent.selectedText = rgbGray( 255 );
|
||||
|
||||
colors.control.defaultColor = rgbGray( 255, 0.0605 );
|
||||
colors.control.secondary = rgbGray( 255, 0.0837 );
|
||||
colors.control.tertiary = rgbGray( 255, 0.0326 );
|
||||
colors.control.inputActive = rgbGray( 30, 0.70 );
|
||||
colors.control.disabled = rgbGray( 255, 0.0419 );
|
||||
|
||||
colors.controlStrong.defaultColor = rgbGray( 255, 0.5442 );
|
||||
colors.controlStrong.disabled = rgbGray( 255, 0.2465 );
|
||||
|
||||
colors.subtle.secondary = rgbGray( 255, 0.0605 );
|
||||
colors.subtle.tertiary = rgbGray( 255, 0.0419 );
|
||||
colors.subtle.disabled = Qt::transparent;
|
||||
|
||||
colors.controlSolid.defaultColor = rgbGray( 69 );
|
||||
|
||||
colors.controlAlt.secondary = rgbGray( 0, 0.10 );
|
||||
colors.controlAlt.tertiary = rgbGray( 255, 0.0419 );
|
||||
colors.controlAlt.quaternary = rgbGray( 255, 0.0698 );
|
||||
colors.controlAlt.disabled = Qt::transparent;
|
||||
|
||||
colors.accent.defaultColor = accentColors.tertiary;
|
||||
colors.accent.secondary = toTransparentF( accentColors.tertiary, 0.90 );
|
||||
colors.accent.tertiary = toTransparentF( accentColors.tertiary, 0.80 );
|
||||
colors.accent.disabled = rgbGray( 255, 0.1581 );
|
||||
colors.accent.selectedTextBackground = accentColors.primary;
|
||||
|
||||
colors.acrylic.background = rgbGray( 44, 0.96 );
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// system colors
|
||||
|
||||
critical = 0xffff99a4;
|
||||
success = 0xff6ccb5f;
|
||||
attention = 0xff60cdff;
|
||||
caution = 0xfffce100;
|
||||
attentionBackground = rgbGray( 255, 0.0326 );
|
||||
successBackground = 0xff393d1b;
|
||||
cautionBackground = 0xff433519;
|
||||
criticalBackground = 0xff442726;
|
||||
neutral = rgbGray( 255, 0.5442 );
|
||||
neutralBackground = rgbGray( 255, 0.0326 );
|
||||
solidNeutral = rgbGray( 157 );
|
||||
solidAttentionBackground = rgbGray( 46 );
|
||||
solidNeutralBackground = rgbGray( 46 );
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
auto& colors = palette.elevation;
|
||||
|
||||
colors.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) };
|
||||
colors.circle.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) };
|
||||
|
||||
colors.textControl.border = { rgbGray( 255, 0.08 ), palette.fillColor.text.secondary };
|
||||
|
||||
colors.textControl.borderFocused = { rgbGray( 255, 0.08 ), rgbGray( 255, 0.08 ) };
|
||||
colors.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.14 ) };
|
||||
}
|
||||
|
||||
{
|
||||
auto& colors = palette.strokeColor;
|
||||
|
||||
colors.control.defaultColor = rgbGray( 255, 0.0698 );
|
||||
colors.control.secondary = rgbGray( 255, 0.093 );
|
||||
colors.control.onAccentDefault = rgbGray( 255, 0.08 );
|
||||
colors.control.onAccentSecondary = rgbGray( 0, 0.14 );
|
||||
colors.control.onAccentTertiary = rgbGray( 0, 0.2169 );
|
||||
colors.control.onAccentDisabled = rgbGray( 0, 0.20 );
|
||||
|
||||
colors.controlStrong.defaultColor = rgbGray( 255, 0.5442 );
|
||||
colors.controlStrong.disabled = rgbGray( 255, 0.1581 );
|
||||
|
||||
colors.card.defaultColor = rgbGray( 255, 0.0578 );
|
||||
colors.card.defaultSolid = rgbGray( 235 );
|
||||
|
||||
colors.divider.defaultColor = rgbGray( 255, 0.0837 );
|
||||
|
||||
colors.surface.defaultColor = rgbGray( 117, 0.40 );
|
||||
colors.surface.flyout = rgbGray( 0, 0.20 );
|
||||
|
||||
colors.focus.outer = rgbGray( 255 );
|
||||
colors.focus.inner = rgbGray( 0, 0.70 );
|
||||
}
|
||||
|
||||
{
|
||||
auto& colors = palette.background;
|
||||
|
||||
colors.overlay.defaultColor = rgbGray( 0, 0.30 );
|
||||
colors.layer.alt = rgbGray( 255, 0.0538 );
|
||||
colors.flyout.defaultColor = rgbGray( 44, 0.96 );
|
||||
}
|
||||
|
||||
// Shadow:
|
||||
|
||||
shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.26 ) };
|
||||
// ### should actually be drawn twice with different values:
|
||||
shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.37 ) };
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2023 Edelhirsch Software GmbH
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_FLUENT2_THEME_H
|
||||
#define QSK_FLUENT2_THEME_H
|
||||
|
||||
#include "QskFluent2Global.h"
|
||||
|
||||
#include <QskSkin.h>
|
||||
#include <QskShadowMetrics.h>
|
||||
|
||||
#include <qcolor.h>
|
||||
#include <array>
|
||||
|
||||
class QSK_FLUENT2_EXPORT QskFluent2Theme
|
||||
{
|
||||
public:
|
||||
struct BaseColors
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
};
|
||||
|
||||
struct AccentColors
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb quaternary;
|
||||
};
|
||||
|
||||
QskFluent2Theme( QskSkin::ColorScheme, const BaseColors& baseColors,
|
||||
const AccentColors& accentColors );
|
||||
|
||||
typedef std::array< QRgb, 2 > BorderGradient;
|
||||
|
||||
struct FillColor
|
||||
{
|
||||
struct
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
} text;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
} accentText;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb primary;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
QRgb selectedText;
|
||||
} textOnAccent;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb inputActive;
|
||||
QRgb disabled;
|
||||
} control;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb disabled;
|
||||
} controlStrong;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
} subtle;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
} controlSolid;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb quaternary;
|
||||
QRgb disabled;
|
||||
} controlAlt;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb disabled;
|
||||
QRgb selectedTextBackground;
|
||||
} accent;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb background;
|
||||
} acrylic;
|
||||
};
|
||||
|
||||
struct Elevation
|
||||
{
|
||||
struct
|
||||
{
|
||||
BorderGradient border;
|
||||
} control;
|
||||
|
||||
struct
|
||||
{
|
||||
BorderGradient border;
|
||||
} circle;
|
||||
|
||||
struct
|
||||
{
|
||||
BorderGradient border;
|
||||
BorderGradient borderFocused;
|
||||
} textControl;
|
||||
|
||||
struct
|
||||
{
|
||||
BorderGradient border;
|
||||
} accentControl;
|
||||
};
|
||||
|
||||
struct StrokeColor
|
||||
{
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb secondary;
|
||||
QRgb onAccentDefault;
|
||||
QRgb onAccentSecondary;
|
||||
QRgb onAccentTertiary;
|
||||
QRgb onAccentDisabled;
|
||||
} control;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb disabled;
|
||||
} controlStrong;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb defaultSolid;
|
||||
} card;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
} divider;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
QRgb flyout;
|
||||
} surface;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb outer;
|
||||
QRgb inner;
|
||||
} focus;
|
||||
};
|
||||
|
||||
struct Background
|
||||
{
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
} overlay;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb alt;
|
||||
} layer;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb defaultColor;
|
||||
} flyout;
|
||||
|
||||
struct
|
||||
{
|
||||
QRgb base;
|
||||
QRgb secondary;
|
||||
QRgb tertiary;
|
||||
QRgb quaternary;
|
||||
} solid;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
FillColor fillColor;
|
||||
Elevation elevation;
|
||||
StrokeColor strokeColor;
|
||||
Background background;
|
||||
} palette;
|
||||
|
||||
struct ShadowSettings
|
||||
{
|
||||
QskShadowMetrics metrics;
|
||||
QRgb color;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
ShadowSettings flyout;
|
||||
ShadowSettings dialog;
|
||||
} shadow;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"FactoryId": "Fluent2Factory",
|
||||
"Skins": [ "Fluent2 Light", "Fluent2 Dark" ]
|
||||
"Skins": [ { "Name": "Fluent2 Light", "Scheme": "Light" },
|
||||
{ "Name": "Fluent2 Dark", "Scheme": "Dark" } ]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,6 +278,10 @@ void Editor::setupComboBox()
|
|||
m_pal.surfaceVariant, m_pal.focusOpacity );
|
||||
setGradient( Q::Panel | Q::Focused, focusColor );
|
||||
|
||||
const auto pressedColor = flattenedColor( m_pal.onSurfaceVariant,
|
||||
m_pal.surfaceVariant, m_pal.pressedOpacity );
|
||||
setGradient( Q::Panel | Q::Pressed, pressedColor );
|
||||
|
||||
const auto activeColor = flattenedColor( m_pal.onSurfaceVariant,
|
||||
m_pal.surfaceVariant, m_pal.pressedOpacity );
|
||||
setGradient( Q::Panel | Q::PopupOpen, activeColor );
|
||||
|
|
@ -340,8 +344,8 @@ void Editor::setupMenu()
|
|||
|
||||
// The color here is primary with an opacity of 8% - we blend that
|
||||
// with the background, because we don't want the menu to have transparency:
|
||||
const auto panel = flattenedColor( m_pal.primary, m_pal.background, 0.08 );
|
||||
setGradient( Q::Panel, panel );
|
||||
const auto panelColor = flattenedColor( m_pal.primary, m_pal.background, 0.08 );
|
||||
setGradient( Q::Panel, panelColor );
|
||||
|
||||
setShadowMetrics( Q::Panel, m_pal.elevation2 );
|
||||
setShadowColor( Q::Panel, m_pal.shadow );
|
||||
|
|
@ -355,7 +359,14 @@ void Editor::setupMenu()
|
|||
setSpacing( Q::Segment, 5_dp );
|
||||
setGradient( Q::Segment, Qt::transparent );
|
||||
|
||||
setGradient( Q::Cursor, m_pal.primary12 );
|
||||
const auto hoverColor = flattenedColor( m_pal.onSurface, panelColor, m_pal.hoverOpacity );
|
||||
setGradient( Q::Segment | Q::Hovered, hoverColor );
|
||||
|
||||
setGradient( Q::Segment | Q::Selected, m_pal.primary12 );
|
||||
const auto hoverSelectedColor = flattenedColor( m_pal.onSurface, m_pal.primary12, m_pal.hoverOpacity );
|
||||
setGradient( Q::Segment | Q::Selected | Q::Hovered, hoverSelectedColor );
|
||||
const auto pressedSelectedColor = flattenedColor( m_pal.onSurface, m_pal.primary12, m_pal.pressedOpacity );
|
||||
setGradient( Q::Segment | Q::Pressed | Q::Selected, pressedSelectedColor );
|
||||
|
||||
setPadding( Q::Icon, 7_dp );
|
||||
setStrutSize( Q::Icon, 24_dp, 24_dp );
|
||||
|
|
@ -489,7 +500,6 @@ void Editor::setupFocusIndicator()
|
|||
|
||||
void Editor::setupSegmentedBar()
|
||||
{
|
||||
// copied from Squiek: we need something similar to a tab bar here. TODO ...
|
||||
using A = QskAspect;
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
|
|
@ -507,18 +517,33 @@ void Editor::setupSegmentedBar()
|
|||
|
||||
setBoxBorderMetrics( Q::Panel, 1_dp );
|
||||
setBoxBorderColors( Q::Panel, m_pal.outline );
|
||||
|
||||
setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface12 );
|
||||
|
||||
setStrutSize( Q::Panel | A::Horizontal, panelStrutSize );
|
||||
setStrutSize( Q::Panel | A::Vertical, panelStrutSize.transposed() );
|
||||
|
||||
setFlag( Q::Panel | A::Option, true ); // adjust segments to the panel radius
|
||||
}
|
||||
|
||||
{
|
||||
// Segment
|
||||
// Segment / Splash
|
||||
|
||||
setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize );
|
||||
setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() );
|
||||
setGradient( Q::Segment, Qt::transparent );
|
||||
|
||||
setGradient( Q::Segment | Q::Hovered, m_pal.onSurface8 );
|
||||
setGradient( Q::Segment | Q::Focused, m_pal.onSurface12 );
|
||||
setGradient( Q::Segment | Q::Selected, m_pal.secondaryContainer );
|
||||
|
||||
setGradient( Q::Segment | Q::Selected | Q::Hovered,
|
||||
flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.hoverOpacity ) );
|
||||
|
||||
setGradient( Q::Segment | Q::Selected | Q::Focused,
|
||||
flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.focusOpacity ) );
|
||||
|
||||
setGradient( Q::Segment | Q::Selected | Q::Disabled, m_pal.onSurface12 );
|
||||
|
||||
setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 );
|
||||
setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp );
|
||||
}
|
||||
|
|
@ -534,30 +559,10 @@ void Editor::setupSegmentedBar()
|
|||
}
|
||||
|
||||
{
|
||||
// Cursor
|
||||
setBoxShape( Q::Cursor, 0 );
|
||||
// Splash
|
||||
|
||||
setBoxShape( Q::Cursor | Q::Minimum | A::Horizontal,
|
||||
{ 100, 0, 100, 0, Qt::RelativeSize },
|
||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
||||
|
||||
setBoxShape( Q::Cursor | Q::Maximum | A::Horizontal,
|
||||
{ 0, 100, 0, 100, Qt::RelativeSize },
|
||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
||||
|
||||
setBoxShape( Q::Cursor | Q::Minimum | A::Vertical,
|
||||
{ 100, 100, 0, 0, Qt::RelativeSize },
|
||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
||||
|
||||
setBoxShape( Q::Cursor | Q::Maximum | A::Vertical,
|
||||
{ 0, 0, 100, 100, Qt::RelativeSize },
|
||||
{ QskStateCombination::CombinationNoState, Q::Disabled } );
|
||||
|
||||
setGradient( Q::Cursor, m_pal.secondaryContainer );
|
||||
setGradient( Q::Cursor | Q::Disabled, m_pal.onSurface12 );
|
||||
|
||||
setBoxBorderMetrics( Q::Cursor, 1_dp );
|
||||
setBoxBorderColors( Q::Cursor, Qt::transparent );
|
||||
setGradient( Q::Splash, stateLayerColor( m_pal.onSecondaryContainer, m_pal.pressedOpacity ) );
|
||||
setAnimation( Q::Splash | A::Color, qskDuration );
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -634,6 +639,7 @@ void Editor::setupPushButton()
|
|||
setSpacing( Q::Panel, 8_dp );
|
||||
setPadding( Q::Panel, { 24_dp, 0, 24_dp, 0 } );
|
||||
setBoxShape( Q::Panel, 100, Qt::RelativeSize );
|
||||
setShadowColor( Q::Panel, m_pal.shadow );
|
||||
|
||||
setStrutSize( Q::Icon, 18_dp, 18_dp );
|
||||
setPadding( Q::Icon, { 0, 0, 8_dp, 0 } );
|
||||
|
|
@ -642,8 +648,7 @@ void Editor::setupPushButton()
|
|||
setFontRole( Q::Text, QskMaterial3Skin::M3LabelLarge );
|
||||
setPadding( Q::Text, 0 );
|
||||
|
||||
setShadowColor( Q::Panel, m_pal.shadow );
|
||||
|
||||
setBoxShape( Q::Splash, 40_dp );
|
||||
setAnimation( Q::Splash | QskAspect::Color, qskDuration );
|
||||
|
||||
|
||||
|
|
@ -985,6 +990,11 @@ void Editor::setupTabButton()
|
|||
using Q = QskTabButton;
|
||||
|
||||
setStrutSize( Q::Panel, 48_dp, 64_dp );
|
||||
#if 1
|
||||
// couldn't find a value in the specs
|
||||
setPadding( Q::Panel, 8, 0, 8, 0 );
|
||||
#endif
|
||||
|
||||
setGradient( Q::Panel, m_pal.surface );
|
||||
|
||||
setColor( Q::Text, m_pal.onSurfaceVariant );
|
||||
|
|
@ -1114,12 +1124,11 @@ void Editor::setupScrollView()
|
|||
using Q = QskScrollView;
|
||||
|
||||
setGradient( Q::Panel, m_pal.background );
|
||||
|
||||
setGradient( Q::Viewport, m_pal.secondaryContainer );
|
||||
|
||||
for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } )
|
||||
{
|
||||
setMetric( subControl | A::Size, 10_dp );
|
||||
setMetric( subControl | A::Size, 6_dp );
|
||||
setPadding( subControl, 0 );
|
||||
}
|
||||
|
||||
|
|
@ -1129,9 +1138,9 @@ void Editor::setupScrollView()
|
|||
|
||||
for ( auto subControl : { Q::HorizontalScrollHandle, Q::VerticalScrollHandle } )
|
||||
{
|
||||
setBoxShape( subControl, 3_dp );
|
||||
setBoxShape( subControl, { 100, Qt::RelativeSize } );
|
||||
setBoxBorderMetrics( subControl, 0 );
|
||||
setGradient( subControl, m_pal.primary );
|
||||
setGradient( subControl, m_pal.secondary );
|
||||
setAnimation( subControl | A::Color, qskDuration );
|
||||
}
|
||||
|
||||
|
|
@ -1143,13 +1152,14 @@ void Editor::setupListView()
|
|||
{
|
||||
using Q = QskListView;
|
||||
|
||||
setStrutSize( Q::Cell, { -1, 56 } );
|
||||
setPadding( Q::Cell, { 16_dp, 12_dp, 16_dp, 12_dp } );
|
||||
setBoxBorderMetrics( Q::Cell, { 0, 0, 0, 1_dp } );
|
||||
setBoxBorderColors( Q::Cell, m_pal.outline );
|
||||
setColor( Q::Cell, m_pal.surface );
|
||||
setColor( Q::Cell | Q::Selected, m_pal.primary12 );
|
||||
|
||||
setColor( Q::Text, m_pal.onSurfaceVariant );
|
||||
setBoxBorderColors( Q::Cell, m_pal.outline );
|
||||
setGradient( Q::Cell, m_pal.surface );
|
||||
setGradient( Q::Cell | Q::Selected, m_pal.primary12 );
|
||||
|
||||
setColor( Q::Text, m_pal.onSurface );
|
||||
}
|
||||
|
||||
void Editor::setupSubWindow()
|
||||
|
|
@ -1187,8 +1197,8 @@ void Editor::setupSubWindow()
|
|||
|
||||
}
|
||||
|
||||
QskMaterial3Theme::QskMaterial3Theme( Lightness lightness )
|
||||
: QskMaterial3Theme( lightness,
|
||||
QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme )
|
||||
: QskMaterial3Theme( colorScheme,
|
||||
{ // default Material colors:
|
||||
0xff6750A4,
|
||||
0xff625B71,
|
||||
|
|
@ -1200,11 +1210,11 @@ QskMaterial3Theme::QskMaterial3Theme( Lightness lightness )
|
|||
{
|
||||
}
|
||||
|
||||
QskMaterial3Theme::QskMaterial3Theme( Lightness lightness,
|
||||
QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme,
|
||||
std::array< QskHctColor, NumPaletteTypes > palettes )
|
||||
: m_palettes( palettes )
|
||||
{
|
||||
if ( lightness == Light )
|
||||
if ( colorScheme == QskSkin::LightScheme )
|
||||
{
|
||||
primary = m_palettes[ Primary ].toned( 40 ).rgb();
|
||||
onPrimary = m_palettes[ Primary ].toned( 100 ).rgb();
|
||||
|
|
@ -1238,7 +1248,7 @@ QskMaterial3Theme::QskMaterial3Theme( Lightness lightness,
|
|||
|
||||
shadow = m_palettes[ Neutral ].toned( 0 ).rgb();
|
||||
}
|
||||
else if ( lightness == Dark )
|
||||
else if ( colorScheme == QskSkin::DarkScheme )
|
||||
{
|
||||
primary = m_palettes[ Primary ].toned( 80 ).rgb();
|
||||
onPrimary = m_palettes[ Primary ].toned( 20 ).rgb();
|
||||
|
|
|
|||
|
|
@ -18,12 +18,6 @@
|
|||
class QSK_MATERIAL3_EXPORT QskMaterial3Theme
|
||||
{
|
||||
public:
|
||||
enum Lightness
|
||||
{
|
||||
Light,
|
||||
Dark
|
||||
};
|
||||
|
||||
enum PaletteType
|
||||
{
|
||||
Primary,
|
||||
|
|
@ -36,8 +30,8 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme
|
|||
NumPaletteTypes
|
||||
};
|
||||
|
||||
QskMaterial3Theme( Lightness );
|
||||
QskMaterial3Theme( Lightness, std::array< QskHctColor, NumPaletteTypes > );
|
||||
QskMaterial3Theme( QskSkin::ColorScheme );
|
||||
QskMaterial3Theme( QskSkin::ColorScheme, std::array< QskHctColor, NumPaletteTypes > );
|
||||
|
||||
QRgb primary;
|
||||
QRgb primary8; // ### rename to primaryHovered or so?
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ QskSkin* QskMaterial3SkinFactory::createSkin( const QString& skinName )
|
|||
{
|
||||
if ( QString::compare( skinName, materialLightSkinName, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
QskMaterial3Theme theme( QskMaterial3Theme::Light );
|
||||
QskMaterial3Theme theme( QskSkin::LightScheme );
|
||||
return new QskMaterial3Skin( theme );
|
||||
}
|
||||
else if ( QString::compare( skinName, materialDarkSkinName, Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
QskMaterial3Theme theme( QskMaterial3Theme::Dark );
|
||||
QskMaterial3Theme theme( QskSkin::DarkScheme );
|
||||
return new QskMaterial3Skin( theme );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"FactoryId": "Material3Factory",
|
||||
"Skins": [ "Material3 Light", "Material3 Dark" ]
|
||||
"Skins": [ { "Name": "Material3 Light", "Scheme": "Light" },
|
||||
{ "Name": "Material3 Dark", "Scheme": "Dark" } ]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -521,13 +521,15 @@ void Editor::setupProgressBar()
|
|||
using A = QskAspect;
|
||||
using Q = QskProgressBar;
|
||||
|
||||
setMetric( Q::Groove | A::Size, 8 );
|
||||
setPadding( Q::Groove, 0 );
|
||||
setGradient( Q::Groove, m_pal.darker200 );
|
||||
setBoxShape( Q::Groove, 4 );
|
||||
for ( auto subControl : { Q::Groove, Q::Bar } )
|
||||
{
|
||||
setMetric( subControl | A::Size, 6 );
|
||||
setPadding( subControl, 0 );
|
||||
setBoxShape( subControl, 4 );
|
||||
}
|
||||
|
||||
setGradient( Q::Groove, m_pal.darker200 );
|
||||
setGradient( Q::Bar, m_pal.highlighted );
|
||||
setBoxShape( Q::Bar, 4 );
|
||||
}
|
||||
|
||||
void Editor::setupFocusIndicator()
|
||||
|
|
@ -778,7 +780,7 @@ void Editor::setupTabButton()
|
|||
{
|
||||
const auto aspect = Q::Panel | variation;
|
||||
|
||||
QskMargins margins0, margins1, padding;
|
||||
QskMargins margins0, margins1;
|
||||
QskBoxBorderMetrics border( 1 );
|
||||
QskBoxShapeMetrics shape( 4 );
|
||||
|
||||
|
|
@ -830,7 +832,7 @@ void Editor::setupTabButton()
|
|||
for ( const auto state : { Q::Checked | A::NoState, Q::Checked | Q::Pressed } )
|
||||
setMargin( aspect | state, margins1 );
|
||||
|
||||
setPadding( aspect, padding );
|
||||
setPadding( aspect, { 6, 12, 6, 12 } );
|
||||
|
||||
setBoxBorderMetrics( aspect, border );
|
||||
setBoxShape( aspect, shape );
|
||||
|
|
@ -1010,9 +1012,13 @@ void Editor::setupScrollView()
|
|||
// scroll bars
|
||||
for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } )
|
||||
{
|
||||
setMetric( subControl | A::Size, 12_dp );
|
||||
setPadding( subControl, 0 );
|
||||
setMetric( subControl | A::Size, 14 );
|
||||
setPadding( subControl, 2 );
|
||||
setMargin( subControl, 0 );
|
||||
|
||||
setPanel( subControl, Sunken );
|
||||
setBoxShape( subControl, 100, Qt::RelativeSize );
|
||||
setBoxBorderMetrics( subControl, 1 );
|
||||
}
|
||||
|
||||
// scrollbar handles
|
||||
|
|
@ -1021,19 +1027,16 @@ void Editor::setupScrollView()
|
|||
const qreal bw = 1.0;
|
||||
|
||||
setButton( subControl, Raised, bw );
|
||||
setButton( subControl | Q::Pressed, Sunken, bw );
|
||||
setBoxShape( subControl, 100, Qt::RelativeSize );
|
||||
setBoxShape( subControl | Q::Pressed, 100, Qt::RelativeSize );
|
||||
|
||||
const auto extent = 40_dp;
|
||||
|
||||
if ( subControl == Q::HorizontalScrollHandle )
|
||||
{
|
||||
setStrutSize( subControl, extent, 0.0 );
|
||||
setButton( subControl | Q::HorizontalHandlePressed, Sunken, bw );
|
||||
}
|
||||
else
|
||||
{
|
||||
setStrutSize( subControl, 0.0, extent );
|
||||
setButton( subControl | Q::VerticalHandlePressed, Sunken, bw );
|
||||
}
|
||||
|
||||
setAnimation( subControl | A::Color, qskDuration );
|
||||
}
|
||||
|
|
@ -1044,15 +1047,21 @@ void Editor::setupScrollView()
|
|||
|
||||
void Editor::setupListView()
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskListView;
|
||||
|
||||
// padding for each cell
|
||||
setPadding( Q::Cell, QskMargins( 4, 8 ) );
|
||||
|
||||
setColor( Q::Text, m_pal.themeForeground );
|
||||
setColor( Q::Cell, m_pal.contrasted );
|
||||
|
||||
setColor( Q::Cell | Q::Selected, m_pal.highlighted );
|
||||
// alternating row colors
|
||||
setColor( Q::Cell | A::Lower, Qt::white );
|
||||
setColor( Q::Cell | Q::Selected | A::Lower, m_pal.highlighted );
|
||||
|
||||
setColor( Q::Cell | A::Upper, m_pal.contrasted );
|
||||
setColor( Q::Cell | Q::Selected | A::Upper, m_pal.highlighted );
|
||||
|
||||
setColor( Q::Text | Q::Selected, m_pal.highlightedText );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"FactoryId": "SquiekFactory",
|
||||
"Skins": [ "Squiek" ]
|
||||
"Skins": [ { "Name": "Squiek", "Scheme": "Unknown" } ]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class QSK_EXPORT QskAspect
|
|||
Header,
|
||||
Footer,
|
||||
|
||||
Card,
|
||||
|
||||
Floating
|
||||
};
|
||||
Q_ENUM( Section )
|
||||
|
|
@ -109,7 +111,7 @@ class QSK_EXPORT QskAspect
|
|||
NoState = 0,
|
||||
|
||||
FirstSystemState = 1 << 0,
|
||||
FirstUserState = 1 << 4,
|
||||
FirstUserState = 1 << 5,
|
||||
LastUserState = 1 << 11,
|
||||
LastSystemState = 1 << 15,
|
||||
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ inline const QskGradientStops& QskGradient::stops() const noexcept
|
|||
#if 1
|
||||
/*
|
||||
Returning a const& so that it is possible to write:
|
||||
for ( const auto& stop : qAsConst( gradient.stops() ) )
|
||||
for ( const auto& stop : gradient.stops() )
|
||||
|
||||
Once we have changed QskGradientStop from QColor to QRgb
|
||||
we should check if there is a better solution possible
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qhooks_p.h>
|
||||
#include <private/qquickitem_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
#define QSK_OBJECT_INFO 0
|
||||
|
|
@ -20,19 +21,8 @@ QSK_QT_PRIVATE_END
|
|||
#include <qset.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 4, 0 )
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickitem_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
#endif
|
||||
|
||||
static inline bool qskIsItem( const QObject* object )
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 4, 0 )
|
||||
return object->isQuickItemType();
|
||||
#else
|
||||
/*
|
||||
The addObject hook is called from the constructor of QObject,
|
||||
where we don't have the derived class constructed yet.
|
||||
|
|
@ -42,7 +32,6 @@ static inline bool qskIsItem( const QObject* object )
|
|||
|
||||
auto o_p = QObjectPrivate::get( const_cast< QObject* >( object ) );
|
||||
return dynamic_cast< QQuickItemPrivate* >( o_p ) != nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
@ -173,7 +162,7 @@ void CounterHook::addObject( QObject* object )
|
|||
{
|
||||
const bool isItem = qskIsItem( object );
|
||||
|
||||
for ( auto counterData : qAsConst( m_counterDataSet ) )
|
||||
for ( auto counterData : std::as_const( m_counterDataSet ) )
|
||||
{
|
||||
counterData->counter[ QskObjectCounter::Objects ].increment();
|
||||
|
||||
|
|
@ -193,7 +182,7 @@ void CounterHook::removeObject( QObject* object )
|
|||
{
|
||||
const bool isItem = qskIsItem( object );
|
||||
|
||||
for ( auto counterData : qAsConst( m_counterDataSet ) )
|
||||
for ( auto counterData : std::as_const( m_counterDataSet ) )
|
||||
{
|
||||
counterData->counter[ QskObjectCounter::Objects ].decrement();
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ QSK_SUBCONTROL( QskComboBox, Icon )
|
|||
QSK_SUBCONTROL( QskComboBox, Text )
|
||||
QSK_SUBCONTROL( QskComboBox, StatusIndicator )
|
||||
|
||||
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskComboBox, Pressed, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 2 )
|
||||
|
||||
static inline void qskTraverseOptions( QskComboBox* comboBox, int steps )
|
||||
{
|
||||
|
|
@ -89,6 +90,25 @@ QskComboBox::~QskComboBox()
|
|||
{
|
||||
}
|
||||
|
||||
bool QskComboBox::isPressed() const
|
||||
{
|
||||
return hasSkinState( Pressed );
|
||||
}
|
||||
|
||||
void QskComboBox::setPressed( bool on )
|
||||
{
|
||||
if ( on == isPressed() )
|
||||
return;
|
||||
|
||||
setSkinStateFlag( Pressed, on );
|
||||
Q_EMIT pressedChanged( on );
|
||||
|
||||
if ( on )
|
||||
Q_EMIT pressed();
|
||||
else
|
||||
Q_EMIT released();
|
||||
}
|
||||
|
||||
void QskComboBox::setPopupOpen( bool on )
|
||||
{
|
||||
if ( on == isPopupOpen() )
|
||||
|
|
@ -246,11 +266,13 @@ void QskComboBox::closePopup()
|
|||
|
||||
void QskComboBox::mousePressEvent( QMouseEvent* )
|
||||
{
|
||||
setPressed( true );
|
||||
setPopupOpen( true );
|
||||
}
|
||||
|
||||
void QskComboBox::mouseReleaseEvent( QMouseEvent* )
|
||||
{
|
||||
setPressed( false );
|
||||
}
|
||||
|
||||
void QskComboBox::keyPressEvent( QKeyEvent* event )
|
||||
|
|
@ -259,6 +281,7 @@ void QskComboBox::keyPressEvent( QKeyEvent* event )
|
|||
{
|
||||
if ( !event->isAutoRepeat() )
|
||||
{
|
||||
setPressed( true );
|
||||
setPopupOpen( true );
|
||||
return;
|
||||
}
|
||||
|
|
@ -270,6 +293,7 @@ void QskComboBox::keyPressEvent( QKeyEvent* event )
|
|||
case Qt::Key_F4:
|
||||
{
|
||||
// QComboBox does this ???
|
||||
setPressed( true );
|
||||
setPopupOpen( true );
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,16 +34,22 @@ class QSK_EXPORT QskComboBox : public QskControl
|
|||
Q_PROPERTY( int indexInPopup READ indexInPopup
|
||||
NOTIFY indexInPopupChanged )
|
||||
|
||||
Q_PROPERTY( bool pressed READ isPressed
|
||||
WRITE setPressed NOTIFY pressedChanged FINAL )
|
||||
|
||||
using Inherited = QskControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Icon, Text, StatusIndicator )
|
||||
QSK_STATES( PopupOpen )
|
||||
QSK_STATES( Pressed, PopupOpen )
|
||||
|
||||
QskComboBox( QQuickItem* parent = nullptr );
|
||||
|
||||
~QskComboBox() override;
|
||||
|
||||
void setPressed( bool on );
|
||||
bool isPressed() const;
|
||||
|
||||
void setPopupOpen( bool );
|
||||
bool isPopupOpen() const;
|
||||
|
||||
|
|
@ -78,6 +84,10 @@ class QSK_EXPORT QskComboBox : public QskControl
|
|||
void setCurrentIndex( int );
|
||||
|
||||
Q_SIGNALS:
|
||||
void pressed();
|
||||
void released();
|
||||
void pressedChanged( bool );
|
||||
|
||||
void currentIndexChanged( int );
|
||||
void indexInPopupChanged( int );
|
||||
|
||||
|
|
|
|||
|
|
@ -44,12 +44,20 @@ static inline QRectF qskFocusIndicatorClipRect( const QQuickItem* item )
|
|||
return rect;
|
||||
}
|
||||
|
||||
static inline QskAspect::Section qskItemSection( const QQuickItem* item )
|
||||
{
|
||||
if ( auto control = qskControlCast( item ) )
|
||||
return control->section();
|
||||
|
||||
return QskAspect::Body;
|
||||
}
|
||||
|
||||
class QskFocusIndicator::PrivateData
|
||||
{
|
||||
public:
|
||||
void resetConnections()
|
||||
{
|
||||
for ( const auto& connection : qAsConst( connections ) )
|
||||
for ( const auto& connection : std::as_const( connections ) )
|
||||
QObject::disconnect( connection );
|
||||
|
||||
connections.clear();
|
||||
|
|
@ -122,6 +130,8 @@ void QskFocusIndicator::onFocusItemChanged()
|
|||
|
||||
if ( focusItem && ( focusItem != window()->contentItem() ) )
|
||||
{
|
||||
setSection( qskItemSection( focusItem ) );
|
||||
|
||||
auto item = focusItem;
|
||||
m_data->connections += connectItem( item );
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ namespace
|
|||
{
|
||||
Timer* timer = nullptr;
|
||||
|
||||
for ( auto t : qAsConst( m_table ) )
|
||||
for ( auto t : std::as_const( m_table ) )
|
||||
{
|
||||
if ( t->recognizer() == nullptr ||
|
||||
t->recognizer() == recognizer )
|
||||
|
|
@ -153,7 +153,7 @@ namespace
|
|||
|
||||
void stopTimer( const QskGestureRecognizer* recognizer )
|
||||
{
|
||||
for ( auto timer : qAsConst( m_table ) )
|
||||
for ( auto timer : std::as_const( m_table ) )
|
||||
{
|
||||
if ( timer->recognizer() == recognizer )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "QskAspect.h"
|
||||
#include "QskColorFilter.h"
|
||||
#include "QskEvent.h"
|
||||
#include "QskSkinlet.h"
|
||||
|
||||
#include <qguiapplication.h>
|
||||
#include <qstylehints.h>
|
||||
|
|
@ -15,31 +16,55 @@
|
|||
|
||||
QSK_SUBCONTROL( QskListView, Cell )
|
||||
QSK_SUBCONTROL( QskListView, Text )
|
||||
QSK_SUBCONTROL( QskListView, Graphic )
|
||||
|
||||
QSK_STATE( QskListView, Selected, QskAspect::FirstUserState )
|
||||
|
||||
#define FOCUS_ON_CURRENT 1
|
||||
|
||||
static inline int qskRowAt( const QskListView* listView, const QPointF& pos )
|
||||
{
|
||||
const auto rect = listView->viewContentsRect();
|
||||
if ( rect.contains( pos ) )
|
||||
{
|
||||
const auto y = pos.y() - rect.top() + listView->scrollPos().y();
|
||||
|
||||
const int row = y / listView->rowHeight();
|
||||
if ( row >= 0 && row < listView->rowCount() )
|
||||
return row;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
class QskListView::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData()
|
||||
: preferredWidthFromColumns( false )
|
||||
, alternatingRowColors( false )
|
||||
, selectionMode( QskListView::SingleSelection )
|
||||
, selectedRow( -1 )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Currently we only support single selection. We can't navigate
|
||||
the current item ( = focus ) without changing the selection.
|
||||
So for the moment the selected row is always the currentRow.
|
||||
*/
|
||||
|
||||
bool preferredWidthFromColumns : 1;
|
||||
bool alternatingRowColors : 1;
|
||||
SelectionMode selectionMode : 4;
|
||||
|
||||
int selectedRow;
|
||||
int selectedRow = -1;
|
||||
};
|
||||
|
||||
QskListView::QskListView( QQuickItem* parent )
|
||||
: QskScrollView( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
#if FOCUS_ON_CURRENT
|
||||
connect( this, &QskScrollView::scrollPosChanged, &QskControl::focusIndicatorRectChanged );
|
||||
#endif
|
||||
}
|
||||
|
||||
QskListView::~QskListView()
|
||||
|
|
@ -62,22 +87,6 @@ bool QskListView::preferredWidthFromColumns() const
|
|||
return m_data->preferredWidthFromColumns;
|
||||
}
|
||||
|
||||
void QskListView::setAlternatingRowColors( bool on )
|
||||
{
|
||||
if ( on != m_data->alternatingRowColors )
|
||||
{
|
||||
m_data->alternatingRowColors = on;
|
||||
update();
|
||||
|
||||
Q_EMIT alternatingRowColorsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool QskListView::alternatingRowColors() const
|
||||
{
|
||||
return m_data->alternatingRowColors;
|
||||
}
|
||||
|
||||
void QskListView::setTextOptions( const QskTextOptions& textOptions )
|
||||
{
|
||||
if ( setTextOptionsHint( Text, textOptions ) )
|
||||
|
|
@ -92,6 +101,15 @@ QskTextOptions QskListView::textOptions() const
|
|||
return textOptionsHint( Text );
|
||||
}
|
||||
|
||||
void QskListView::resetTextOptions()
|
||||
{
|
||||
if ( resetTextOptionsHint( Text ) )
|
||||
{
|
||||
updateScrollableSize();
|
||||
Q_EMIT textOptionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QskListView::setSelectedRow( int row )
|
||||
{
|
||||
if ( row < 0 )
|
||||
|
|
@ -115,6 +133,7 @@ void QskListView::setSelectedRow( int row )
|
|||
{
|
||||
m_data->selectedRow = row;
|
||||
Q_EMIT selectedRowChanged( row );
|
||||
Q_EMIT focusIndicatorRectChanged();
|
||||
|
||||
update();
|
||||
}
|
||||
|
|
@ -143,12 +162,21 @@ QskListView::SelectionMode QskListView::selectionMode() const
|
|||
return m_data->selectionMode;
|
||||
}
|
||||
|
||||
QskColorFilter QskListView::graphicFilterAt( int row, int col ) const
|
||||
QRectF QskListView::focusIndicatorRect() const
|
||||
{
|
||||
Q_UNUSED( row )
|
||||
Q_UNUSED( col )
|
||||
#if FOCUS_ON_CURRENT
|
||||
if( m_data->selectedRow >= 0 )
|
||||
{
|
||||
auto rect = effectiveSkinlet()->sampleRect(
|
||||
this, contentsRect(), Cell, m_data->selectedRow );
|
||||
|
||||
return QskColorFilter();
|
||||
rect = rect.translated( -scrollPos() );
|
||||
if ( rect.intersects( viewContentsRect() ) )
|
||||
return rect;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Inherited::focusIndicatorRect();
|
||||
}
|
||||
|
||||
void QskListView::keyPressEvent( QKeyEvent* event )
|
||||
|
|
@ -249,13 +277,10 @@ void QskListView::mousePressEvent( QMouseEvent* event )
|
|||
{
|
||||
if ( m_data->selectionMode != NoSelection )
|
||||
{
|
||||
const QRectF vr = viewContentsRect();
|
||||
if ( vr.contains( event->pos() ) )
|
||||
const int row = qskRowAt( this, qskMousePosition( event ) );
|
||||
if ( row >= 0 )
|
||||
{
|
||||
const int row = ( event->pos().y() - vr.top() + scrollPos().y() ) / rowHeight();
|
||||
if ( row >= 0 && row < rowCount() )
|
||||
setSelectedRow( row );
|
||||
|
||||
setSelectedRow( row );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -268,6 +293,14 @@ void QskListView::mouseReleaseEvent( QMouseEvent* event )
|
|||
Inherited::mouseReleaseEvent( event );
|
||||
}
|
||||
|
||||
void QskListView::changeEvent( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::StyleChange )
|
||||
updateScrollableSize();
|
||||
|
||||
Inherited::changeEvent( event );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
|
||||
static qreal qskAlignedToRows( const qreal y0, qreal dy,
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ class QSK_EXPORT QskListView : public QskScrollView
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( bool alternatingRowColors READ alternatingRowColors
|
||||
WRITE setAlternatingRowColors NOTIFY alternatingRowColorsChanged FINAL )
|
||||
|
||||
Q_PROPERTY( SelectionMode selectionMode READ selectionMode
|
||||
WRITE setSelectionMode NOTIFY selectionModeChanged FINAL )
|
||||
|
||||
|
|
@ -23,7 +20,8 @@ class QSK_EXPORT QskListView : public QskScrollView
|
|||
WRITE setSelectedRow NOTIFY selectedRowChanged FINAL )
|
||||
|
||||
Q_PROPERTY( QskTextOptions textOptions READ textOptions
|
||||
WRITE setTextOptions NOTIFY textOptionsChanged FINAL )
|
||||
WRITE setTextOptions RESET resetTextOptions
|
||||
NOTIFY textOptionsChanged FINAL )
|
||||
|
||||
Q_PROPERTY( bool preferredWidthFromColumns READ preferredWidthFromColumns
|
||||
WRITE setPreferredWidthFromColumns NOTIFY preferredWidthFromColumnsChanged() )
|
||||
|
|
@ -31,7 +29,7 @@ class QSK_EXPORT QskListView : public QskScrollView
|
|||
using Inherited = QskScrollView;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Cell, Text )
|
||||
QSK_SUBCONTROLS( Cell, Text, Graphic )
|
||||
QSK_STATES( Selected )
|
||||
|
||||
enum SelectionMode
|
||||
|
|
@ -48,13 +46,11 @@ class QSK_EXPORT QskListView : public QskScrollView
|
|||
void setPreferredWidthFromColumns( bool );
|
||||
bool preferredWidthFromColumns() const;
|
||||
|
||||
void setAlternatingRowColors( bool );
|
||||
bool alternatingRowColors() const;
|
||||
|
||||
void setSelectionMode( SelectionMode );
|
||||
SelectionMode selectionMode() const;
|
||||
|
||||
void setTextOptions( const QskTextOptions& textOptions );
|
||||
void resetTextOptions();
|
||||
QskTextOptions textOptions() const;
|
||||
|
||||
Q_INVOKABLE int selectedRow() const;
|
||||
|
|
@ -67,9 +63,7 @@ class QSK_EXPORT QskListView : public QskScrollView
|
|||
|
||||
Q_INVOKABLE virtual QVariant valueAt( int row, int col ) const = 0;
|
||||
|
||||
#if 1
|
||||
virtual QskColorFilter graphicFilterAt( int row, int col ) const;
|
||||
#endif
|
||||
QRectF focusIndicatorRect() const override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setSelectedRow( int row );
|
||||
|
|
@ -78,11 +72,12 @@ class QSK_EXPORT QskListView : public QskScrollView
|
|||
void selectedRowChanged( int row );
|
||||
|
||||
void selectionModeChanged();
|
||||
void alternatingRowColorsChanged();
|
||||
void preferredWidthFromColumnsChanged();
|
||||
void textOptionsChanged();
|
||||
|
||||
protected:
|
||||
void changeEvent( QEvent* ) override;
|
||||
|
||||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,81 +8,168 @@
|
|||
|
||||
#include "QskColorFilter.h"
|
||||
#include "QskGraphic.h"
|
||||
#include "QskBoxHints.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskSkinStateChanger.h"
|
||||
#include "QskQuick.h"
|
||||
|
||||
#include <qmath.h>
|
||||
#include <qsgnode.h>
|
||||
#include <qsgsimplerectnode.h>
|
||||
#include <qtransform.h>
|
||||
|
||||
class QskListViewNode final : public QSGTransformNode
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
inline QskListViewNode( int columnCount )
|
||||
: m_columnCount( columnCount )
|
||||
class ForegroundNode : public QSGNode
|
||||
{
|
||||
m_backgroundNode.setFlag( QSGNode::OwnedByParent, false );
|
||||
appendChildNode( &m_backgroundNode );
|
||||
public:
|
||||
void invalidate()
|
||||
{
|
||||
removeAllChildNodes();
|
||||
m_columnCount = m_oldRowMin = m_oldRowMax = -1;
|
||||
}
|
||||
|
||||
m_foregroundNode.setFlag( QSGNode::OwnedByParent, false );
|
||||
appendChildNode( &m_foregroundNode );
|
||||
void rearrangeNodes( int rowMin, int rowMax, int columnCount )
|
||||
{
|
||||
const bool doReorder = ( columnCount == m_columnCount )
|
||||
&& ( rowMin <= m_oldRowMax ) && ( rowMax >= m_oldRowMin );
|
||||
|
||||
if ( doReorder )
|
||||
{
|
||||
/*
|
||||
We have nodes that will be at a different position in the
|
||||
list of child nodes - however their content might be unchanged.
|
||||
|
||||
This is a common situation, when resizing or scrolling the list.
|
||||
|
||||
To avoid that the text/graphic nodes have to be updated we
|
||||
try to rearrange the nodes, so that they are in increasing
|
||||
row order for further processing.
|
||||
|
||||
To avoid delete/new calls we append the leading and prepend
|
||||
the trailing nodes, so that they might be used later.
|
||||
*/
|
||||
|
||||
if ( rowMin >= m_oldRowMin )
|
||||
{
|
||||
for ( int row = m_oldRowMin; row < rowMin; row++ )
|
||||
{
|
||||
for ( int col = 0; col < columnCount; col++ )
|
||||
{
|
||||
auto childNode = firstChild();
|
||||
removeChildNode( childNode );
|
||||
appendChildNode( childNode );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int row = rowMin; row < m_oldRowMin; row++ )
|
||||
{
|
||||
for ( int col = 0; col < columnCount; col++ )
|
||||
{
|
||||
auto childNode = lastChild();
|
||||
removeChildNode( childNode );
|
||||
prependChildNode( childNode );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_oldRowMin = rowMin;
|
||||
m_oldRowMax = rowMax;
|
||||
m_columnCount = columnCount;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
When scrolling the majority of the child nodes are simply translated
|
||||
while only few rows appear/disappear. To implement this in an efficient
|
||||
way we store how the nodes were related to the rows in the previous update,
|
||||
*/
|
||||
|
||||
int m_oldRowMin = -1;
|
||||
int m_oldRowMax = -1;
|
||||
int m_columnCount = -1;
|
||||
};
|
||||
|
||||
class ListViewNode final : public QSGTransformNode
|
||||
{
|
||||
public:
|
||||
inline ListViewNode()
|
||||
{
|
||||
m_backgroundNode.setFlag( QSGNode::OwnedByParent, false );
|
||||
appendChildNode( &m_backgroundNode );
|
||||
|
||||
m_foregroundNode.setFlag( QSGNode::OwnedByParent, false );
|
||||
appendChildNode( &m_foregroundNode );
|
||||
}
|
||||
|
||||
void initialize( const QskListView* listView )
|
||||
{
|
||||
const auto scrollPos = listView->scrollPos();
|
||||
setMatrix( QTransform::fromTranslate( -scrollPos.x(), -scrollPos.y() ) );
|
||||
|
||||
m_clipRect = listView->viewContentsRect();
|
||||
m_rowHeight = listView->rowHeight();
|
||||
|
||||
m_rowMin = qFloor( scrollPos.y() / m_rowHeight );
|
||||
|
||||
const auto rowMax = ( scrollPos.y() + m_clipRect.height() ) / m_rowHeight;
|
||||
m_rowMax = qFloor( rowMax - 10e-6 );
|
||||
|
||||
if ( m_rowMax >= listView->rowCount() )
|
||||
m_rowMax = listView->rowCount() - 1;
|
||||
}
|
||||
|
||||
QRectF clipRect() const { return m_clipRect; }
|
||||
|
||||
int rowMin() const { return m_rowMin; }
|
||||
int rowMax() const { return m_rowMax; }
|
||||
int rowCount() const { return m_rowMax - m_rowMin + 1; }
|
||||
|
||||
int rowHeight() const { return m_rowHeight; }
|
||||
|
||||
QSGNode* backgroundNode() { return &m_backgroundNode; }
|
||||
ForegroundNode* foregroundNode() { return &m_foregroundNode; }
|
||||
|
||||
private:
|
||||
// caching some calculations to speed things up
|
||||
|
||||
QRectF m_clipRect;
|
||||
qreal m_rowHeight;
|
||||
|
||||
int m_rowMin, m_rowMax;
|
||||
|
||||
QSGNode m_backgroundNode;
|
||||
ForegroundNode m_foregroundNode;
|
||||
};
|
||||
}
|
||||
|
||||
static inline ListViewNode* qskListViewNode( const QskListView* listView )
|
||||
{
|
||||
if ( auto node = const_cast< QSGNode* >( qskPaintNode( listView ) ) )
|
||||
{
|
||||
using namespace QskSGNode;
|
||||
|
||||
node = findChildNode( node, QskScrollViewSkinlet::ContentsRootRole );
|
||||
if ( node )
|
||||
{
|
||||
node = node->firstChild();
|
||||
if ( node )
|
||||
{
|
||||
Q_ASSERT( node->type() == QSGNode::TransformNodeType );
|
||||
return static_cast< ListViewNode* >( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSGNode* backgroundNode()
|
||||
{
|
||||
return &m_backgroundNode;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QSGNode* foregroundNode()
|
||||
{
|
||||
return &m_foregroundNode;
|
||||
}
|
||||
|
||||
inline void resetRows( int rowMin, int rowMax )
|
||||
{
|
||||
m_rowMin = rowMin;
|
||||
m_rowMax = rowMax;
|
||||
}
|
||||
|
||||
inline int rowMin() const
|
||||
{
|
||||
return m_rowMin;
|
||||
}
|
||||
|
||||
inline int rowMax() const
|
||||
{
|
||||
return m_rowMax;
|
||||
}
|
||||
|
||||
inline bool intersects( int rowMin, int rowMax ) const
|
||||
{
|
||||
return ( rowMin <= m_rowMax ) && ( rowMax >= m_rowMin );
|
||||
}
|
||||
|
||||
inline int nodeCount() const
|
||||
{
|
||||
return ( m_rowMin >= 0 ) ? ( m_rowMax - m_rowMin + 1 ) * m_columnCount : 0;
|
||||
}
|
||||
|
||||
inline int columnCount() const
|
||||
{
|
||||
return m_columnCount;
|
||||
}
|
||||
|
||||
inline void invalidate()
|
||||
{
|
||||
m_rowMin = m_rowMax = -1;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_columnCount;
|
||||
int m_rowMin = -1;
|
||||
int m_rowMax = -1;
|
||||
|
||||
QSGNode m_backgroundNode;
|
||||
QSGNode m_foregroundNode;
|
||||
};
|
||||
static inline ListViewNode* qskListViewNode( const QskSkinnable* skinnable )
|
||||
{
|
||||
return qskListViewNode( static_cast< const QskListView* >( skinnable ) );
|
||||
}
|
||||
|
||||
QskListViewSkinlet::QskListViewSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
|
|
@ -96,119 +183,67 @@ QSGNode* QskListViewSkinlet::updateContentsNode(
|
|||
{
|
||||
const auto listView = static_cast< const QskListView* >( scrollView );
|
||||
|
||||
auto listViewNode = static_cast< QskListViewNode* >( node );
|
||||
if ( listViewNode == nullptr )
|
||||
listViewNode = new QskListViewNode( listView->columnCount() );
|
||||
auto listViewNode = QskSGNode::ensureNode< ListViewNode >( node );
|
||||
listViewNode->initialize( listView );
|
||||
|
||||
QTransform transform;
|
||||
transform.translate( -listView->scrollPos().x(), -listView->scrollPos().y() );
|
||||
listViewNode->setMatrix( transform );
|
||||
|
||||
updateBackgroundNodes( listView, listViewNode );
|
||||
updateForegroundNodes( listView, listViewNode );
|
||||
updateBackgroundNodes( listView, listViewNode->backgroundNode() );
|
||||
updateForegroundNodes( listView, listViewNode->foregroundNode() );
|
||||
|
||||
return listViewNode;
|
||||
}
|
||||
|
||||
void QskListViewSkinlet::updateBackgroundNodes(
|
||||
const QskListView* listView, QskListViewNode* listViewNode ) const
|
||||
const QskListView* listView, QSGNode* backgroundNode ) const
|
||||
{
|
||||
QSGNode* backgroundNode = listViewNode->backgroundNode();
|
||||
using Q = QskListView;
|
||||
using A = QskAspect;
|
||||
|
||||
const qreal cellHeight = listView->rowHeight();
|
||||
const QRectF viewRect = listView->viewContentsRect();
|
||||
auto listViewNode = static_cast< const ListViewNode* >( backgroundNode->parent() );
|
||||
|
||||
const QPointF scrolledPos = listView->scrollPos();
|
||||
const int rowMin = qFloor( scrolledPos.y() / cellHeight );
|
||||
auto rowNode = backgroundNode->firstChild();
|
||||
|
||||
int rowMax = qCeil( ( scrolledPos.y() + viewRect.height() ) / cellHeight );
|
||||
if ( rowMax >= listView->rowCount() )
|
||||
rowMax = listView->rowCount() - 1;
|
||||
|
||||
const int rowSelected = listView->selectedRow();
|
||||
const double x0 = viewRect.left() + scrolledPos.x();
|
||||
const double y0 = viewRect.top();
|
||||
|
||||
auto* rowNode = static_cast< QSGSimpleRectNode* >( backgroundNode->firstChild() );
|
||||
|
||||
if ( listView->alternatingRowColors() )
|
||||
{
|
||||
#if 1
|
||||
/*
|
||||
Cell might be better for regular cells, while ( Cell | AlternateColor )
|
||||
could be used for the alternate color TODO ...
|
||||
*/
|
||||
#endif
|
||||
const auto color = listView->color( QskListView::Cell );
|
||||
|
||||
for ( int row = rowMin; row <= rowMax; row++ )
|
||||
{
|
||||
if ( row % 2 )
|
||||
{
|
||||
if ( rowNode == nullptr )
|
||||
{
|
||||
rowNode = new QSGSimpleRectNode();
|
||||
backgroundNode->appendChildNode( rowNode );
|
||||
}
|
||||
|
||||
rowNode->setRect( x0, y0 + row * cellHeight, viewRect.width(), cellHeight );
|
||||
rowNode->setColor( color );
|
||||
|
||||
rowNode = static_cast< QSGSimpleRectNode* >( rowNode->nextSibling() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( rowSelected >= rowMin && rowSelected <= rowMax )
|
||||
for ( int row = listViewNode->rowMin(); row <= listViewNode->rowMax(); row++ )
|
||||
{
|
||||
QskSkinStateChanger stateChanger( listView );
|
||||
stateChanger.setStates( listView->skinStates() | QskListView::Selected );
|
||||
stateChanger.setStates( sampleStates( listView, Q::Cell, row ) );
|
||||
|
||||
const QColor color = listView->color( QskListView::Cell );
|
||||
const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, row );
|
||||
|
||||
if ( rowNode == nullptr )
|
||||
const QskAspect aspect = Q::Cell | ( ( row % 2 ) ? A::Upper : A::Lower );
|
||||
const auto boxHints = listView->boxHints( aspect );
|
||||
|
||||
auto newNode = updateBoxNode( listView, rowNode, rect, boxHints );
|
||||
if ( newNode )
|
||||
{
|
||||
rowNode = new QSGSimpleRectNode();
|
||||
backgroundNode->appendChildNode( rowNode );
|
||||
if ( newNode->parent() != backgroundNode )
|
||||
backgroundNode->appendChildNode( newNode );
|
||||
else
|
||||
rowNode = newNode->nextSibling();
|
||||
}
|
||||
|
||||
rowNode->setRect( x0, y0 + rowSelected * cellHeight, viewRect.width(), cellHeight );
|
||||
rowNode->setColor( color );
|
||||
|
||||
rowNode = static_cast< QSGSimpleRectNode* >( rowNode->nextSibling() );
|
||||
}
|
||||
|
||||
QSGNode* nextNode = rowNode;
|
||||
while ( nextNode != nullptr )
|
||||
{
|
||||
QSGNode* tmpNode = nextNode;
|
||||
nextNode = nextNode->nextSibling();
|
||||
delete tmpNode;
|
||||
}
|
||||
QskSGNode::removeAllChildNodesFrom( backgroundNode, rowNode );
|
||||
}
|
||||
|
||||
void QskListViewSkinlet::updateForegroundNodes(
|
||||
const QskListView* listView, QskListViewNode* listViewNode ) const
|
||||
const QskListView* listView, QSGNode* parentNode ) const
|
||||
{
|
||||
auto parentNode = listViewNode->foregroundNode();
|
||||
auto foregroundNode = static_cast< ForegroundNode* >( parentNode );
|
||||
|
||||
if ( listView->rowCount() <= 0 || listView->columnCount() <= 0 )
|
||||
{
|
||||
parentNode->removeAllChildNodes();
|
||||
listViewNode->invalidate();
|
||||
foregroundNode->invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto margins = listView->paddingHint( QskListView::Cell );
|
||||
auto listViewNode = static_cast< const ListViewNode* >( parentNode->parent() );
|
||||
|
||||
const auto cr = listView->viewContentsRect();
|
||||
const auto scrolledPos = listView->scrollPos();
|
||||
const auto clipRect = listViewNode->clipRect();
|
||||
|
||||
const int rowMin = qFloor( scrolledPos.y() / listView->rowHeight() );
|
||||
const int rowMin = listViewNode->rowMin();
|
||||
const int rowMax = listViewNode->rowMax();
|
||||
|
||||
int rowMax = rowMin + qCeil( cr.height() / listView->rowHeight() );
|
||||
if ( rowMax >= listView->rowCount() )
|
||||
rowMax = listView->rowCount() - 1;
|
||||
foregroundNode->rearrangeNodes( rowMin, rowMax, listView->columnCount() );
|
||||
|
||||
#if 1
|
||||
// should be optimized for visible columns only
|
||||
|
|
@ -216,67 +251,28 @@ void QskListViewSkinlet::updateForegroundNodes(
|
|||
const int colMax = listView->columnCount() - 1;
|
||||
#endif
|
||||
|
||||
bool forwards = true;
|
||||
const auto margins = listView->paddingHint( QskListView::Cell );
|
||||
|
||||
if ( listViewNode->intersects( rowMin, rowMax ) )
|
||||
{
|
||||
/*
|
||||
We try to avoid reallcations when scrolling, by reusing
|
||||
the nodes of the cells leaving the viewport for those becoming visible.
|
||||
*/
|
||||
|
||||
forwards = ( rowMin >= listViewNode->rowMin() );
|
||||
|
||||
if ( forwards )
|
||||
{
|
||||
// usually scrolling down
|
||||
for ( int row = listViewNode->rowMin(); row < rowMin; row++ )
|
||||
{
|
||||
for ( int col = 0; col < listView->columnCount(); col++ )
|
||||
{
|
||||
QSGNode* childNode = parentNode->firstChild();
|
||||
parentNode->removeChildNode( childNode );
|
||||
parentNode->appendChildNode( childNode );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// usually scrolling up
|
||||
for ( int row = rowMax; row < listViewNode->rowMax(); row++ )
|
||||
{
|
||||
for ( int col = 0; col < listView->columnCount(); col++ )
|
||||
{
|
||||
QSGNode* childNode = parentNode->lastChild();
|
||||
parentNode->removeChildNode( childNode );
|
||||
parentNode->prependChildNode( childNode );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateVisibleForegroundNodes( listView, listViewNode,
|
||||
rowMin, rowMax, colMin, colMax, margins, forwards );
|
||||
updateVisibleForegroundNodes(
|
||||
listView, foregroundNode, rowMin, rowMax, margins );
|
||||
|
||||
// finally putting the nodes into their position
|
||||
auto node = parentNode->firstChild();
|
||||
auto node = foregroundNode->firstChild();
|
||||
|
||||
const qreal rowHeight = listView->rowHeight();
|
||||
qreal y = cr.top() + rowMin * rowHeight;
|
||||
const auto rowHeight = listView->rowHeight();
|
||||
auto y = clipRect.top() + rowMin * rowHeight;
|
||||
|
||||
for ( int row = rowMin; row <= rowMax; row++ )
|
||||
{
|
||||
qreal x = cr.left();
|
||||
qreal x = clipRect.left();
|
||||
|
||||
for ( int col = colMin; col <= colMax; col++ )
|
||||
{
|
||||
Q_ASSERT( node->type() == QSGNode::TransformNodeType );
|
||||
auto transformNode = static_cast< QSGTransformNode* >( node );
|
||||
|
||||
QTransform transform;
|
||||
transform.translate( x + margins.left(), y + margins.top() );
|
||||
|
||||
transformNode->setMatrix( transform );
|
||||
transformNode->setMatrix(
|
||||
QTransform::fromTranslate( x + margins.left(), y + margins.top() ) );
|
||||
|
||||
node = node->nextSibling();
|
||||
x += listView->columnWidth( col );
|
||||
|
|
@ -284,72 +280,36 @@ void QskListViewSkinlet::updateForegroundNodes(
|
|||
|
||||
y += rowHeight;
|
||||
}
|
||||
|
||||
listViewNode->resetRows( rowMin, rowMax );
|
||||
}
|
||||
|
||||
void QskListViewSkinlet::updateVisibleForegroundNodes(
|
||||
const QskListView* listView, QskListViewNode* listViewNode,
|
||||
int rowMin, int rowMax, int colMin, int colMax, const QMarginsF& margins,
|
||||
bool forward ) const
|
||||
const QskListView* listView, QSGNode* parentNode,
|
||||
int rowMin, int rowMax, const QMarginsF& margins ) const
|
||||
{
|
||||
auto parentNode = listViewNode->foregroundNode();
|
||||
auto node = parentNode->firstChild();
|
||||
|
||||
const int rowCount = rowMax - rowMin + 1;
|
||||
const int colCount = colMax - colMin + 1;
|
||||
const int obsoleteNodesCount = listViewNode->nodeCount() - rowCount * colCount;
|
||||
|
||||
if ( forward )
|
||||
for ( int row = rowMin; row <= rowMax; row++ )
|
||||
{
|
||||
for ( int i = 0; i < obsoleteNodesCount; i++ )
|
||||
delete parentNode->lastChild();
|
||||
const auto h = listView->rowHeight() - ( margins.top() + margins.bottom() );
|
||||
|
||||
auto node = parentNode->firstChild();
|
||||
|
||||
for ( int row = rowMin; row <= rowMax; row++ )
|
||||
for ( int col = 0; col < listView->columnCount(); col++ )
|
||||
{
|
||||
const qreal h = listView->rowHeight() - ( margins.top() + margins.bottom() );
|
||||
const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() );
|
||||
|
||||
for ( int col = 0; col < listView->columnCount(); col++ )
|
||||
{
|
||||
const qreal w = listView->columnWidth( col ) - ( margins.left() + margins.right() );
|
||||
node = updateForegroundNode( listView,
|
||||
parentNode, static_cast< QSGTransformNode* >( node ),
|
||||
row, col, QSizeF( w, h ) );
|
||||
|
||||
node = updateForegroundNode( listView,
|
||||
parentNode, static_cast< QSGTransformNode* >( node ),
|
||||
row, col, QSizeF( w, h ), forward );
|
||||
|
||||
node = node->nextSibling();
|
||||
}
|
||||
node = node->nextSibling();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < obsoleteNodesCount; i++ )
|
||||
delete parentNode->firstChild();
|
||||
|
||||
auto* node = parentNode->lastChild();
|
||||
|
||||
for ( int row = rowMax; row >= rowMin; row-- )
|
||||
{
|
||||
const qreal h = listView->rowHeight() - ( margins.top() + margins.bottom() );
|
||||
|
||||
for ( int col = listView->columnCount() - 1; col >= 0; col-- )
|
||||
{
|
||||
const qreal w = listView->columnWidth( col ) - ( margins.left() + margins.right() );
|
||||
|
||||
node = updateForegroundNode( listView,
|
||||
parentNode, static_cast< QSGTransformNode* >( node ),
|
||||
row, col, QSizeF( w, h ), forward );
|
||||
|
||||
node = node->previousSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
QskSGNode::removeAllChildNodesFrom( parentNode, node );
|
||||
}
|
||||
|
||||
QSGTransformNode* QskListViewSkinlet::updateForegroundNode(
|
||||
const QskListView* listView, QSGNode* parentNode, QSGTransformNode* cellNode,
|
||||
int row, int col, const QSizeF& size, bool forward ) const
|
||||
int row, int col, const QSizeF& size ) const
|
||||
{
|
||||
const QRectF cellRect( 0.0, 0.0, size.width(), size.height() );
|
||||
|
||||
|
|
@ -421,10 +381,7 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode(
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( forward )
|
||||
parentNode->appendChildNode( newCellNode );
|
||||
else
|
||||
parentNode->prependChildNode( newCellNode );
|
||||
parentNode->appendChildNode( newCellNode );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -434,14 +391,11 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode(
|
|||
QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView,
|
||||
QSGNode* contentNode, const QRectF& rect, int row, int col ) const
|
||||
{
|
||||
using Q = QskListView;
|
||||
using namespace QskSGNode;
|
||||
|
||||
auto rowStates = listView->skinStates();
|
||||
if ( row == listView->selectedRow() )
|
||||
rowStates |= QskListView::Selected;
|
||||
|
||||
QskSkinStateChanger stateChanger( listView );
|
||||
stateChanger.setStates( rowStates );
|
||||
stateChanger.setStates( sampleStates( listView, Q::Cell, row ) );
|
||||
|
||||
QSGNode* newNode = nullptr;
|
||||
|
||||
|
|
@ -453,7 +407,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView,
|
|||
*/
|
||||
#endif
|
||||
const auto alignment = listView->alignmentHint(
|
||||
QskListView::Cell, Qt::AlignVCenter | Qt::AlignLeft );
|
||||
Q::Cell, Qt::AlignVCenter | Qt::AlignLeft );
|
||||
|
||||
const auto value = listView->valueAt( row, col );
|
||||
|
||||
|
|
@ -462,7 +416,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView,
|
|||
if ( nodeRole( contentNode ) == GraphicRole )
|
||||
newNode = contentNode;
|
||||
|
||||
const auto colorFilter = listView->graphicFilterAt( row, col );
|
||||
const auto colorFilter = listView->effectiveGraphicFilter( Q::Graphic );
|
||||
|
||||
newNode = updateGraphicNode( listView, newNode,
|
||||
value.value< QskGraphic >(), colorFilter, rect, alignment );
|
||||
|
|
@ -476,7 +430,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView,
|
|||
newNode = contentNode;
|
||||
|
||||
newNode = updateTextNode( listView, newNode, rect, alignment,
|
||||
value.toString(), QskListView::Text );
|
||||
value.toString(), Q::Text );
|
||||
|
||||
if ( newNode )
|
||||
setNodeRole( newNode, TextRole );
|
||||
|
|
@ -508,4 +462,46 @@ QSizeF QskListViewSkinlet::sizeHint( const QskSkinnable* skinnable,
|
|||
return QSizeF( w, -1.0 );
|
||||
}
|
||||
|
||||
QskAspect::States QskListViewSkinlet::sampleStates( const QskSkinnable* skinnable,
|
||||
QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
using Q = QskListView;
|
||||
|
||||
if ( subControl == Q::Cell || subControl == Q::Text || subControl == Q::Graphic )
|
||||
{
|
||||
const auto listView = static_cast< const QskListView* >( skinnable );
|
||||
|
||||
auto states = listView->skinStates();
|
||||
if ( index == listView->selectedRow() )
|
||||
states |= Q::Selected;
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
return Inherited::sampleStates( skinnable, subControl, index );
|
||||
}
|
||||
|
||||
QRectF QskListViewSkinlet::sampleRect( const QskSkinnable* skinnable,
|
||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
using Q = QskListView;
|
||||
|
||||
const auto listView = static_cast< const QskListView* >( skinnable );
|
||||
|
||||
if ( subControl == Q::Cell )
|
||||
{
|
||||
auto node = qskListViewNode( listView );
|
||||
const auto clipRect = node ? node->clipRect() : listView->viewContentsRect();
|
||||
|
||||
const auto w = clipRect.width();
|
||||
const auto h = listView->rowHeight();
|
||||
const auto x = clipRect.left() + listView->scrollPos().x();
|
||||
const auto y = clipRect.top() + index * h;
|
||||
|
||||
return QRectF( x, y, w, h );
|
||||
}
|
||||
|
||||
return Inherited::sampleRect( skinnable, contentsRect, subControl, index );
|
||||
}
|
||||
|
||||
#include "moc_QskListViewSkinlet.cpp"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include "QskScrollViewSkinlet.h"
|
||||
|
||||
class QskListView;
|
||||
class QskListViewNode;
|
||||
|
||||
class QMarginsF;
|
||||
class QSizeF;
|
||||
|
|
@ -37,25 +36,30 @@ class QSK_EXPORT QskListViewSkinlet : public QskScrollViewSkinlet
|
|||
QSizeF sizeHint( const QskSkinnable*,
|
||||
Qt::SizeHint, const QSizeF& ) const override;
|
||||
|
||||
QRectF sampleRect( const QskSkinnable*,
|
||||
const QRectF&, QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
QskAspect::States sampleStates( const QskSkinnable*,
|
||||
QskAspect::Subcontrol, int index ) const override;
|
||||
|
||||
protected:
|
||||
QSGNode* updateContentsNode(
|
||||
const QskScrollView*, QSGNode* ) const override;
|
||||
|
||||
virtual QSGNode* updateCellNode( const QskListView*,
|
||||
QSGNode*, const QRectF&, int row, int col ) const;
|
||||
|
||||
private:
|
||||
void updateForegroundNodes( const QskListView*, QskListViewNode* ) const;
|
||||
void updateBackgroundNodes( const QskListView*, QskListViewNode* ) const;
|
||||
void updateForegroundNodes( const QskListView*, QSGNode* ) const;
|
||||
void updateBackgroundNodes( const QskListView*, QSGNode* ) const;
|
||||
|
||||
void updateVisibleForegroundNodes(
|
||||
const QskListView*, QskListViewNode*,
|
||||
int rowMin, int rowMax, int colMin, int colMax,
|
||||
const QMarginsF& margin, bool forward ) const;
|
||||
const QskListView*, QSGNode*,
|
||||
int rowMin, int rowMax, const QMarginsF& margin ) const;
|
||||
|
||||
QSGTransformNode* updateForegroundNode( const QskListView*,
|
||||
QSGNode* parentNode, QSGTransformNode* cellNode,
|
||||
int row, int col, const QSizeF&, bool forward ) const;
|
||||
int row, int col, const QSizeF& ) const;
|
||||
|
||||
QSGNode* updateCellNode( const QskListView*,
|
||||
QSGNode*, const QRectF&, int row, int col ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ QskMainView::QskMainView( QQuickItem* parent )
|
|||
setPanel( true );
|
||||
|
||||
setFlag( QQuickItem::ItemIsFocusScope, true );
|
||||
setTabFence( true );
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ QSK_SUBCONTROL( QskMenu, Icon )
|
|||
QSK_SUBCONTROL( QskMenu, Separator )
|
||||
|
||||
QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskMenu, Pressed, QskAspect::FirstSystemState << 3 )
|
||||
|
||||
static inline int qskActionIndex( const QVector< int >& actions, int index )
|
||||
{
|
||||
|
|
@ -72,6 +73,8 @@ QskMenu::QskMenu( QQuickItem* parent )
|
|||
|
||||
connect( this, &QskMenu::opened, this,
|
||||
[this]() { m_data->triggeredIndex = -1; } );
|
||||
|
||||
setAcceptHoverEvents( true );
|
||||
}
|
||||
|
||||
QskMenu::~QskMenu()
|
||||
|
|
@ -307,7 +310,7 @@ void QskMenu::keyPressEvent( QKeyEvent* event )
|
|||
|
||||
void QskMenu::keyReleaseEvent( QKeyEvent* )
|
||||
{
|
||||
if( m_data->isPressed )
|
||||
if( isPressed() )
|
||||
{
|
||||
m_data->isPressed = false;
|
||||
|
||||
|
|
@ -319,6 +322,30 @@ void QskMenu::keyReleaseEvent( QKeyEvent* )
|
|||
}
|
||||
}
|
||||
|
||||
void QskMenu::hoverEnterEvent( QHoverEvent* event )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
||||
update();
|
||||
}
|
||||
|
||||
void QskMenu::hoverMoveEvent( QHoverEvent* event )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
||||
update();
|
||||
}
|
||||
|
||||
void QskMenu::hoverLeaveEvent( QHoverEvent* )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() );
|
||||
update();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
|
||||
void QskMenu::wheelEvent( QWheelEvent* event )
|
||||
|
|
@ -390,7 +417,7 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event )
|
|||
{
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
{
|
||||
if( m_data->isPressed )
|
||||
if( isPressed() )
|
||||
{
|
||||
m_data->isPressed = false;
|
||||
|
||||
|
|
@ -455,6 +482,11 @@ int QskMenu::indexAtPosition( const QPointF& pos ) const
|
|||
return m_data->actions.value( index, -1 );
|
||||
}
|
||||
|
||||
bool QskMenu::isPressed() const
|
||||
{
|
||||
return m_data->isPressed;
|
||||
}
|
||||
|
||||
void QskMenu::trigger( int index )
|
||||
{
|
||||
if ( index >= 0 && index < m_data->options.count() )
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class QSK_EXPORT QskMenu : public QskPopup
|
|||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Overlay, Panel, Segment, Cursor, Text, Icon, Separator )
|
||||
QSK_STATES( Selected )
|
||||
QSK_STATES( Selected, Pressed )
|
||||
|
||||
QskMenu( QQuickItem* parentItem = nullptr );
|
||||
~QskMenu() override;
|
||||
|
|
@ -68,6 +68,7 @@ class QSK_EXPORT QskMenu : public QskPopup
|
|||
QVector< int > actions() const;
|
||||
|
||||
int currentIndex() const;
|
||||
|
||||
QString currentText() const;
|
||||
|
||||
int triggeredIndex() const;
|
||||
|
|
@ -78,6 +79,8 @@ class QSK_EXPORT QskMenu : public QskPopup
|
|||
QRectF cellRect( int index ) const;
|
||||
int indexAtPosition( const QPointF& ) const;
|
||||
|
||||
bool isPressed() const;
|
||||
|
||||
Q_INVOKABLE int exec();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
@ -97,6 +100,10 @@ class QSK_EXPORT QskMenu : public QskPopup
|
|||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
void hoverEnterEvent( QHoverEvent* ) override;
|
||||
void hoverMoveEvent( QHoverEvent* ) override;
|
||||
void hoverLeaveEvent( QHoverEvent* ) override;
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
void wheelEvent( QWheelEvent* ) override;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -385,6 +385,7 @@ QskAspect::States QskMenuSkinlet::sampleStates(
|
|||
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
using Q = QskMenu;
|
||||
using A = QskAspect;
|
||||
|
||||
auto states = Inherited::sampleStates( skinnable, subControl, index );
|
||||
|
||||
|
|
@ -393,7 +394,29 @@ QskAspect::States QskMenuSkinlet::sampleStates(
|
|||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
|
||||
if ( menu->currentIndex() == menu->actions()[ index ] )
|
||||
states |= QskMenu::Selected;
|
||||
{
|
||||
states |= Q::Selected;
|
||||
|
||||
if( menu->isPressed() )
|
||||
{
|
||||
states |= Q::Pressed;
|
||||
}
|
||||
else
|
||||
{
|
||||
states &= ~Q::Pressed;
|
||||
}
|
||||
}
|
||||
|
||||
const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF();
|
||||
|
||||
if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index )
|
||||
{
|
||||
states |= Q::Hovered;
|
||||
}
|
||||
else
|
||||
{
|
||||
states &= ~Q::Hovered;
|
||||
}
|
||||
}
|
||||
|
||||
return states;
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ void QskPushButton::mousePressEvent( QMouseEvent* event )
|
|||
using A = QskAspect;
|
||||
|
||||
const auto hint = animationHint( Splash | A::Color );
|
||||
|
||||
if( hint.isValid() )
|
||||
{
|
||||
setPositionHint( Splash, qskMousePosition( event ).x() );
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ void qskItemUpdateRecursive( QQuickItem* item )
|
|||
|
||||
static const QQuickPointerTouchEvent* qskPointerPressEvent( const QQuickWindowPrivate* wd )
|
||||
{
|
||||
for ( const auto event : qAsConst( wd->pointerEventInstances ) )
|
||||
for ( const auto event : std::as_const( wd->pointerEventInstances ) )
|
||||
{
|
||||
if ( auto touchEvent = event->asPointerTouchEvent() )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,30 +15,134 @@ QSK_SUBCONTROL( QskScrollView, HorizontalScrollHandle )
|
|||
QSK_SUBCONTROL( QskScrollView, VerticalScrollBar )
|
||||
QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle )
|
||||
|
||||
QSK_SYSTEM_STATE( QskScrollView, VerticalHandlePressed, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskScrollView, HorizontalHandlePressed, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskScrollView, Pressed, QskAspect::FirstSystemState << 1 )
|
||||
|
||||
static inline QskAspect::Subcontrol qskSubControlAt(
|
||||
const QskScrollView* scrollView, const QPointF& pos )
|
||||
{
|
||||
using Q = QskScrollView;
|
||||
|
||||
const auto rect = scrollView->contentsRect();
|
||||
|
||||
// order is important as the handles are inside the bars !
|
||||
|
||||
for ( auto subControl : { Q::VerticalScrollHandle, Q::VerticalScrollBar,
|
||||
Q::HorizontalScrollHandle, Q::HorizontalScrollBar } )
|
||||
{
|
||||
if ( scrollView->subControlRect( rect, subControl ).contains( pos ) )
|
||||
return subControl;
|
||||
}
|
||||
|
||||
return QskAspect::NoSubcontrol;
|
||||
}
|
||||
|
||||
class QskScrollView::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData()
|
||||
: horizontalScrollBarPolicy( Qt::ScrollBarAsNeeded )
|
||||
, verticalScrollBarPolicy( Qt::ScrollBarAsNeeded )
|
||||
, isScrolling( 0 )
|
||||
inline void resetScrolling( QskScrollView* scrollView )
|
||||
{
|
||||
setScrolling( scrollView, QskAspect::NoSubcontrol, 0.0 );
|
||||
}
|
||||
|
||||
Qt::ScrollBarPolicy horizontalScrollBarPolicy;
|
||||
Qt::ScrollBarPolicy verticalScrollBarPolicy;
|
||||
inline void setScrolling( QskScrollView* scrollView,
|
||||
QskAspect::Subcontrol subControl, qreal pos )
|
||||
{
|
||||
if ( subControl == pressedSubControl )
|
||||
return;
|
||||
|
||||
qreal scrollPressPos;
|
||||
int isScrolling;
|
||||
QskAspect::Subcontrol subControls[2];
|
||||
if ( subControl == VerticalScrollHandle || pressedSubControl == VerticalScrollHandle )
|
||||
{
|
||||
subControls[0] = VerticalScrollHandle;
|
||||
subControls[1] = VerticalScrollBar;
|
||||
}
|
||||
else
|
||||
{
|
||||
subControls[0] = HorizontalScrollHandle;;
|
||||
subControls[1] = HorizontalScrollBar;
|
||||
}
|
||||
|
||||
pressedSubControl = subControl;
|
||||
scrollPressPos = pos;
|
||||
|
||||
scrollView->update();
|
||||
|
||||
auto oldStates = scrollView->skinStates() | scrollView->scrollBarStates( subControl );
|
||||
auto newStates = oldStates | QskScrollView::Pressed;
|
||||
|
||||
if ( pressedSubControl == QskAspect::NoSubcontrol )
|
||||
qSwap( oldStates, newStates );
|
||||
|
||||
scrollView->startHintTransitions( { subControls[0] }, oldStates, newStates );
|
||||
scrollView->startHintTransitions( { subControls[1] }, oldStates, newStates );
|
||||
}
|
||||
|
||||
void setHovered( QskScrollView* scrollView, QskAspect::Subcontrol subControl )
|
||||
{
|
||||
if ( subControl == this->hoveredSubControl )
|
||||
return;
|
||||
|
||||
QskAspect::Subcontrol subControls[2];
|
||||
if ( subControl == VerticalScrollHandle
|
||||
|| hoveredSubControl == VerticalScrollHandle
|
||||
|| subControl == VerticalScrollBar
|
||||
|| hoveredSubControl == VerticalScrollBar )
|
||||
{
|
||||
subControls[0] = VerticalScrollHandle;
|
||||
subControls[1] = VerticalScrollBar;
|
||||
}
|
||||
else
|
||||
{
|
||||
subControls[0] = HorizontalScrollHandle;;
|
||||
subControls[1] = HorizontalScrollBar;
|
||||
}
|
||||
|
||||
hoveredSubControl = subControl;
|
||||
|
||||
auto oldStates = scrollView->skinStates();
|
||||
auto newStates = oldStates | QskScrollView::Hovered;
|
||||
|
||||
if ( hoveredSubControl == QskAspect::NoSubcontrol )
|
||||
qSwap( oldStates, newStates );
|
||||
|
||||
scrollView->startHintTransitions( { subControls[0] }, oldStates, newStates );
|
||||
scrollView->startHintTransitions( { subControls[1] }, oldStates, newStates );
|
||||
}
|
||||
|
||||
bool hasState( QskAspect::Subcontrol subControl, QskAspect::State state ) const
|
||||
{
|
||||
if ( subControl == QskAspect::NoSubcontrol )
|
||||
return false;
|
||||
|
||||
const auto stateSubcontrol =
|
||||
( state == QskControl::Hovered ) ? hoveredSubControl : pressedSubControl;
|
||||
|
||||
if ( subControl == stateSubcontrol )
|
||||
return true;
|
||||
|
||||
if ( subControl == VerticalScrollBar )
|
||||
return stateSubcontrol == VerticalScrollHandle;
|
||||
|
||||
if ( subControl == HorizontalScrollBar )
|
||||
return stateSubcontrol == HorizontalScrollHandle;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded;
|
||||
Qt::ScrollBarPolicy verticalScrollBarPolicy = Qt::ScrollBarAsNeeded;
|
||||
|
||||
qreal scrollPressPos = 0.0;
|
||||
|
||||
QskAspect::Subcontrol pressedSubControl = QskAspect::NoSubcontrol;
|
||||
QskAspect::Subcontrol hoveredSubControl = QskAspect::NoSubcontrol;
|
||||
};
|
||||
|
||||
QskScrollView::QskScrollView( QQuickItem* parent )
|
||||
: Inherited( parent )
|
||||
, m_data( new PrivateData() )
|
||||
{
|
||||
setAcceptHoverEvents( true );
|
||||
}
|
||||
|
||||
QskScrollView::~QskScrollView()
|
||||
|
|
@ -85,16 +189,32 @@ Qt::ScrollBarPolicy QskScrollView::horizontalScrollBarPolicy() const
|
|||
|
||||
bool QskScrollView::isScrolling( Qt::Orientation orientation ) const
|
||||
{
|
||||
return m_data->isScrolling == orientation;
|
||||
if ( orientation == Qt::Vertical )
|
||||
return m_data->pressedSubControl == VerticalScrollHandle;
|
||||
else
|
||||
return m_data->pressedSubControl == HorizontalScrollHandle;
|
||||
}
|
||||
|
||||
QskAspect::States QskScrollView::scrollBarStates(
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
auto states = skinStates();
|
||||
|
||||
if ( m_data->hasState( subControl, Pressed ) )
|
||||
states |= Pressed;
|
||||
|
||||
if ( m_data->hasState( subControl, Hovered ) )
|
||||
states |= Hovered;
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
QRectF QskScrollView::viewContentsRect() const
|
||||
{
|
||||
// This code should be done in the skinlet. TODO ...
|
||||
const qreal bw = boxBorderMetricsHint( Viewport ).widthAt( Qt::TopEdge );
|
||||
const auto borderMetrics = boxBorderMetricsHint( Viewport );
|
||||
|
||||
const QRectF r = subControlRect( Viewport );
|
||||
return r.adjusted( bw, bw, -bw, -bw );
|
||||
return r.marginsRemoved( borderMetrics.widths() );
|
||||
}
|
||||
|
||||
void QskScrollView::mousePressEvent( QMouseEvent* event )
|
||||
|
|
@ -103,14 +223,11 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
|
|||
|
||||
if ( subControlRect( VerticalScrollBar ).contains( mousePos ) )
|
||||
{
|
||||
const QRectF handleRect = subControlRect( VerticalScrollHandle );
|
||||
const auto handleRect = subControlRect( VerticalScrollHandle );
|
||||
|
||||
if ( handleRect.contains( mousePos ) )
|
||||
{
|
||||
m_data->isScrolling = Qt::Vertical;
|
||||
m_data->scrollPressPos = mousePos.y();
|
||||
|
||||
setSkinStateFlag( VerticalHandlePressed, true );
|
||||
m_data->setScrolling( this, VerticalScrollHandle, mousePos.y() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -135,10 +252,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
|
|||
|
||||
if ( handleRect.contains( mousePos ) )
|
||||
{
|
||||
m_data->isScrolling = Qt::Horizontal;
|
||||
m_data->scrollPressPos = mousePos.x();
|
||||
|
||||
setSkinStateFlag( HorizontalHandlePressed, true );
|
||||
m_data->setScrolling( this, HorizontalScrollHandle, mousePos.x() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -162,7 +276,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event )
|
|||
|
||||
void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
||||
{
|
||||
if ( !m_data->isScrolling )
|
||||
if ( m_data->pressedSubControl == QskAspect::NoSubcontrol )
|
||||
{
|
||||
Inherited::mouseMoveEvent( event );
|
||||
return;
|
||||
|
|
@ -171,7 +285,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
|||
const auto mousePos = qskMousePosition( event );
|
||||
QPointF pos = scrollPos();
|
||||
|
||||
if ( m_data->isScrolling == Qt::Horizontal )
|
||||
if ( m_data->pressedSubControl == HorizontalScrollHandle )
|
||||
{
|
||||
const qreal dx = mousePos.x() - m_data->scrollPressPos;
|
||||
const qreal w = subControlRect( HorizontalScrollBar ).width();
|
||||
|
|
@ -179,7 +293,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
|||
pos.rx() += dx / w * scrollableSize().width();
|
||||
m_data->scrollPressPos = mousePos.x();
|
||||
}
|
||||
else if ( m_data->isScrolling == Qt::Vertical )
|
||||
else
|
||||
{
|
||||
const qreal dy = mousePos.y() - m_data->scrollPressPos;
|
||||
const qreal h = subControlRect( VerticalScrollBar ).height();
|
||||
|
|
@ -194,17 +308,35 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event )
|
|||
|
||||
void QskScrollView::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
if ( !m_data->isScrolling )
|
||||
if ( m_data->pressedSubControl == QskAspect::NoSubcontrol )
|
||||
{
|
||||
Inherited::mouseReleaseEvent( event );
|
||||
return;
|
||||
}
|
||||
|
||||
m_data->isScrolling = 0;
|
||||
m_data->scrollPressPos = 0;
|
||||
m_data->resetScrolling( this );
|
||||
}
|
||||
|
||||
setSkinStateFlag( HorizontalHandlePressed, false );
|
||||
setSkinStateFlag( VerticalHandlePressed, false );
|
||||
void QskScrollView::mouseUngrabEvent()
|
||||
{
|
||||
m_data->resetScrolling( this );
|
||||
}
|
||||
|
||||
void QskScrollView::hoverEnterEvent( QHoverEvent* event )
|
||||
{
|
||||
const auto subControl = qskSubControlAt( this, qskHoverPosition( event ) );
|
||||
m_data->setHovered( this, subControl );
|
||||
}
|
||||
|
||||
void QskScrollView::hoverMoveEvent( QHoverEvent* event )
|
||||
{
|
||||
const auto subControl = qskSubControlAt( this, qskHoverPosition( event ) );
|
||||
m_data->setHovered( this, subControl );
|
||||
}
|
||||
|
||||
void QskScrollView::hoverLeaveEvent( QHoverEvent* )
|
||||
{
|
||||
m_data->setHovered( this, QskAspect::NoSubcontrol );
|
||||
}
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
|
|||
HorizontalScrollBar, HorizontalScrollHandle,
|
||||
VerticalScrollBar, VerticalScrollHandle )
|
||||
|
||||
QSK_STATES( VerticalHandlePressed, HorizontalHandlePressed )
|
||||
QSK_STATES( Pressed )
|
||||
|
||||
QskScrollView( QQuickItem* parent = nullptr );
|
||||
~QskScrollView() override;
|
||||
|
|
@ -39,6 +39,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
|
|||
Qt::Orientations scrollableOrientations() const;
|
||||
|
||||
bool isScrolling( Qt::Orientation ) const;
|
||||
QskAspect::States scrollBarStates( QskAspect::Subcontrol ) const;
|
||||
|
||||
QRectF viewContentsRect() const override;
|
||||
QskAnimationHint flickHint() const override;
|
||||
|
|
@ -51,6 +52,11 @@ class QSK_EXPORT QskScrollView : public QskScrollBox
|
|||
void mouseMoveEvent( QMouseEvent* ) override;
|
||||
void mousePressEvent( QMouseEvent* ) override;
|
||||
void mouseReleaseEvent( QMouseEvent* ) override;
|
||||
void mouseUngrabEvent() override;
|
||||
|
||||
void hoverEnterEvent( QHoverEvent* ) override;
|
||||
void hoverMoveEvent( QHoverEvent* ) override;
|
||||
void hoverLeaveEvent( QHoverEvent* ) override;
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
QPointF scrollOffset( const QWheelEvent* ) const override;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "QskAspect.h"
|
||||
#include "QskQuick.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskSkinStateChanger.h"
|
||||
|
||||
#include <qsgnode.h>
|
||||
|
||||
|
|
@ -16,7 +17,9 @@ static void qskAlignedHandle( qreal start, qreal end,
|
|||
qreal scrollBarLength, qreal minHandleLength,
|
||||
qreal& handleStart, qreal& handleEnd )
|
||||
{
|
||||
minHandleLength = qBound( 4.0, minHandleLength, scrollBarLength );
|
||||
// no qBound: scrollBarLength might be < 4.0
|
||||
minHandleLength = qMax( 4.0, minHandleLength );
|
||||
minHandleLength = qMin( minHandleLength, scrollBarLength );
|
||||
|
||||
handleStart = start * scrollBarLength;
|
||||
handleEnd = end * scrollBarLength;
|
||||
|
|
@ -38,6 +41,18 @@ static void qskAlignedHandle( qreal start, qreal end,
|
|||
}
|
||||
}
|
||||
|
||||
static qreal qskScrollBarExtent(
|
||||
const QskScrollView* scrollView, Qt::Orientation orientation )
|
||||
{
|
||||
const auto subControl = ( orientation == Qt::Horizontal )
|
||||
? QskScrollView::HorizontalScrollBar : QskScrollView::VerticalScrollBar;
|
||||
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( subControl ) );
|
||||
|
||||
return scrollView->metric( subControl | QskAspect::Size );
|
||||
}
|
||||
|
||||
QskScrollViewSkinlet::QskScrollViewSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
|
|
@ -51,37 +66,27 @@ QskScrollViewSkinlet::~QskScrollViewSkinlet() = default;
|
|||
QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable,
|
||||
const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
using Q = QskScrollView;
|
||||
|
||||
const auto scrollView = static_cast< const QskScrollView* >( skinnable );
|
||||
|
||||
if ( subControl == QskScrollView::Panel )
|
||||
{
|
||||
if ( subControl == Q::Panel )
|
||||
return contentsRect;
|
||||
}
|
||||
|
||||
if ( subControl == QskScrollView::Viewport )
|
||||
{
|
||||
if ( subControl == Q::Viewport )
|
||||
return viewportRect( scrollView, contentsRect );
|
||||
}
|
||||
|
||||
if ( subControl == QskScrollView::HorizontalScrollBar )
|
||||
{
|
||||
if ( subControl == Q::HorizontalScrollBar )
|
||||
return scrollBarRect( scrollView, contentsRect, Qt::Horizontal );
|
||||
}
|
||||
|
||||
if ( subControl == QskScrollView::HorizontalScrollHandle )
|
||||
{
|
||||
if ( subControl == Q::HorizontalScrollHandle )
|
||||
return scrollHandleRect( scrollView, contentsRect, Qt::Horizontal );
|
||||
}
|
||||
|
||||
if ( subControl == QskScrollView::VerticalScrollBar )
|
||||
{
|
||||
if ( subControl == Q::VerticalScrollBar )
|
||||
return scrollBarRect( scrollView, contentsRect, Qt::Vertical );
|
||||
}
|
||||
|
||||
if ( subControl == QskScrollView::VerticalScrollHandle )
|
||||
{
|
||||
if ( subControl == Q::VerticalScrollHandle )
|
||||
return scrollHandleRect( scrollView, contentsRect, Qt::Vertical );
|
||||
}
|
||||
|
||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||
}
|
||||
|
|
@ -89,44 +94,50 @@ QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable,
|
|||
QSGNode* QskScrollViewSkinlet::updateSubNode(
|
||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||
{
|
||||
using Q = QskScrollView;
|
||||
|
||||
const auto scrollView = static_cast< const QskScrollView* >( skinnable );
|
||||
|
||||
switch ( nodeRole )
|
||||
{
|
||||
case PanelRole:
|
||||
{
|
||||
return updateBoxNode( skinnable, node, QskScrollView::Panel );
|
||||
}
|
||||
return updateBoxNode( skinnable, node, Q::Panel );
|
||||
|
||||
case ViewportRole:
|
||||
{
|
||||
return updateBoxNode( skinnable, node, QskScrollView::Viewport );
|
||||
}
|
||||
return updateBoxNode( skinnable, node, Q::Viewport );
|
||||
|
||||
case HorizontalScrollHandleRole:
|
||||
{
|
||||
return updateBoxNode( skinnable, node, QskScrollView::HorizontalScrollHandle );
|
||||
}
|
||||
return updateScrollBarNode( scrollView, Q::HorizontalScrollHandle, node );
|
||||
|
||||
case VerticalScrollHandleRole:
|
||||
{
|
||||
return updateBoxNode( skinnable, node, QskScrollView::VerticalScrollHandle );
|
||||
}
|
||||
|
||||
case ContentsRootRole:
|
||||
{
|
||||
return updateContentsRootNode( scrollView, node );
|
||||
}
|
||||
return updateScrollBarNode( scrollView, Q::VerticalScrollHandle, node );
|
||||
|
||||
case HorizontalScrollBarRole:
|
||||
return updateScrollBarNode( scrollView, Q::HorizontalScrollBar, node );
|
||||
|
||||
case VerticalScrollBarRole:
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return updateScrollBarNode( scrollView, Q::VerticalScrollBar, node );
|
||||
|
||||
case ContentsRootRole:
|
||||
return updateContentsRootNode( scrollView, node );
|
||||
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
}
|
||||
|
||||
QSGNode* QskScrollViewSkinlet::updateScrollBarNode( const QskScrollView* scrollView,
|
||||
QskAspect::Subcontrol subControl, QSGNode* node ) const
|
||||
{
|
||||
const auto rect = subControlRect( scrollView,
|
||||
scrollView->contentsRect(), subControl );
|
||||
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( subControl ) );
|
||||
|
||||
return updateBoxNode( scrollView, node, rect, subControl );
|
||||
}
|
||||
|
||||
QSGNode* QskScrollViewSkinlet::updateContentsRootNode(
|
||||
const QskScrollView* scrollView, QSGNode* node ) const
|
||||
{
|
||||
|
|
@ -169,22 +180,6 @@ QSGNode* QskScrollViewSkinlet::updateContentsNode(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
QSGNode* QskScrollViewSkinlet::contentsNode( const QskScrollView* scrollView )
|
||||
{
|
||||
if ( auto node = const_cast< QSGNode* >( qskPaintNode( scrollView ) ) )
|
||||
{
|
||||
node = QskSGNode::findChildNode( node, ContentsRootRole );
|
||||
if ( node )
|
||||
{
|
||||
node = node->firstChild();
|
||||
if ( node )
|
||||
return node->firstChild();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QRectF QskScrollViewSkinlet::viewportRect(
|
||||
const QskScrollView* scrollView, const QRectF& contentsRect ) const
|
||||
{
|
||||
|
|
@ -236,22 +231,23 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
|
|||
const auto vRect = subControlRect(
|
||||
scrollView, contentsRect, QskScrollView::Viewport );
|
||||
|
||||
const auto scrollableSize = scrollView->scrollableSize();
|
||||
|
||||
QRectF handleRect;
|
||||
|
||||
if ( orientation == Qt::Vertical )
|
||||
{
|
||||
const auto subControlBar = Q::VerticalScrollBar;
|
||||
const auto sbRect = subControlRect( scrollView, contentsRect, Q::VerticalScrollBar );
|
||||
|
||||
const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar );
|
||||
const auto padding = scrollView->paddingHint( subControlBar );
|
||||
|
||||
const qreal h = scrollView->scrollableSize().height();
|
||||
|
||||
const qreal y1 = pos.y() / h;
|
||||
const qreal y2 = ( pos.y() + vRect.height() ) / h;
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( Q::VerticalScrollBar ) );
|
||||
|
||||
const auto padding = scrollView->paddingHint( Q::VerticalScrollBar );
|
||||
const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle );
|
||||
|
||||
const qreal y1 = pos.y() / scrollableSize.height();
|
||||
const qreal y2 = ( pos.y() + vRect.height() ) / scrollableSize.height();
|
||||
|
||||
qreal top, bottom;
|
||||
qskAlignedHandle( y1, y2, sbRect.height(), strut.height(), top, bottom );
|
||||
|
||||
|
|
@ -262,15 +258,15 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
|
|||
}
|
||||
else
|
||||
{
|
||||
const auto subControlBar = Q::HorizontalScrollBar;
|
||||
const auto sbRect = subControlRect( scrollView, contentsRect, Q::HorizontalScrollBar );
|
||||
|
||||
const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar );
|
||||
const auto padding = scrollView->paddingHint( subControlBar );
|
||||
QskSkinStateChanger stateChanger( scrollView );
|
||||
stateChanger.setStates( scrollView->scrollBarStates( Q::HorizontalScrollBar ) );
|
||||
|
||||
const qreal w = scrollView->scrollableSize().width();
|
||||
const auto padding = scrollView->paddingHint( Q::HorizontalScrollBar );
|
||||
|
||||
const qreal x1 = pos.x() / w;
|
||||
const qreal x2 = ( pos.x() + vRect.width() ) / w;
|
||||
const qreal x1 = pos.x() / scrollableSize.width();
|
||||
const qreal x2 = ( pos.x() + vRect.width() ) / scrollableSize.width();
|
||||
|
||||
const auto strut = scrollView->strutSizeHint( Q::HorizontalScrollHandle );
|
||||
|
||||
|
|
@ -289,7 +285,6 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView,
|
|||
QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView,
|
||||
const QRectF& contentsRect, Qt::Orientation orientation ) const
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskScrollView;
|
||||
|
||||
const auto scrollOrientations = scrollView->scrollableOrientations();
|
||||
|
|
@ -300,23 +295,23 @@ QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView,
|
|||
|
||||
if ( orientation == Qt::Horizontal )
|
||||
{
|
||||
const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size );
|
||||
const qreal h = qskScrollBarExtent( scrollView, Qt::Horizontal );
|
||||
r.setTop( r.bottom() - h );
|
||||
|
||||
if ( scrollOrientations & Qt::Vertical )
|
||||
{
|
||||
const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size );
|
||||
const qreal w = qskScrollBarExtent( scrollView, Qt::Vertical );
|
||||
r.setRight( r.right() - w );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size );
|
||||
const qreal w = qskScrollBarExtent( scrollView, Qt::Vertical );
|
||||
r.setLeft( r.right() - w );
|
||||
|
||||
if ( scrollOrientations & Qt::Horizontal )
|
||||
{
|
||||
const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size );
|
||||
const qreal h = qskScrollBarExtent( scrollView, Qt::Horizontal );
|
||||
r.setBottom( r.bottom() - h );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,10 +43,11 @@ class QSK_EXPORT QskScrollViewSkinlet : public QskSkinlet
|
|||
quint8 nodeRole, QSGNode* ) const override;
|
||||
|
||||
virtual QSGNode* updateContentsNode( const QskScrollView*, QSGNode* ) const;
|
||||
QSGNode* contentsNode( const QskScrollView* );
|
||||
|
||||
private:
|
||||
QSGNode* updateContentsRootNode( const QskScrollView*, QSGNode* ) const;
|
||||
QSGNode* updateScrollBarNode(
|
||||
const QskScrollView*, QskAspect::Subcontrol, QSGNode* ) const;
|
||||
|
||||
QRectF viewportRect( const QskScrollView*, const QRectF& ) const;
|
||||
QRectF scrollBarRect( const QskScrollView*, const QRectF&, Qt::Orientation ) const;
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@
|
|||
#include "QskEvent.h"
|
||||
#include "QskSkinlet.h"
|
||||
#include "QskAspect.h"
|
||||
#include "QskAnimationHint.h"
|
||||
|
||||
#include <qguiapplication.h>
|
||||
#include <qstylehints.h>
|
||||
#include <qfontmetrics.h>
|
||||
|
||||
QSK_SUBCONTROL( QskSegmentedBar, Panel )
|
||||
QSK_SUBCONTROL( QskSegmentedBar, Splash )
|
||||
QSK_SUBCONTROL( QskSegmentedBar, Segment )
|
||||
QSK_SUBCONTROL( QskSegmentedBar, Separator )
|
||||
QSK_SUBCONTROL( QskSegmentedBar, Cursor )
|
||||
|
|
@ -23,8 +25,7 @@ QSK_SUBCONTROL( QskSegmentedBar, Text )
|
|||
QSK_SUBCONTROL( QskSegmentedBar, Icon )
|
||||
|
||||
QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState << 1 )
|
||||
QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 2 )
|
||||
QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 3 )
|
||||
QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 2 )
|
||||
|
||||
class QskSegmentedBar::PrivateData
|
||||
{
|
||||
|
|
@ -53,6 +54,8 @@ QskSegmentedBar::QskSegmentedBar( Qt::Orientation orientation, QQuickItem* paren
|
|||
: Inherited( parent )
|
||||
, m_data( new PrivateData( orientation ) )
|
||||
{
|
||||
setAcceptHoverEvents( true );
|
||||
|
||||
if( orientation == Qt::Horizontal )
|
||||
initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed );
|
||||
else
|
||||
|
|
@ -148,6 +151,8 @@ QskAspect::Variation QskSegmentedBar::effectiveVariation() const
|
|||
|
||||
void QskSegmentedBar::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
const int index = indexAtPosition( qskMousePosition( event ) );
|
||||
|
||||
if( isSegmentEnabled( index ) )
|
||||
|
|
@ -163,6 +168,14 @@ void QskSegmentedBar::mousePressEvent( QMouseEvent* event )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto hint = animationHint( Splash | A::Color );
|
||||
|
||||
if( hint.isValid() )
|
||||
{
|
||||
setSkinHint( Splash | A::Metric | A::Position, qskMousePosition( event ) );
|
||||
startTransition( Splash | A::Metric | A::Size, hint, 0.0, 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
void QskSegmentedBar::mouseUngrabEvent()
|
||||
|
|
@ -260,6 +273,30 @@ void QskSegmentedBar::keyReleaseEvent( QKeyEvent* event )
|
|||
Inherited::keyReleaseEvent( event );
|
||||
}
|
||||
|
||||
void QskSegmentedBar::hoverEnterEvent( QHoverEvent* event )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
||||
update();
|
||||
}
|
||||
|
||||
void QskSegmentedBar::hoverMoveEvent( QHoverEvent* event )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
||||
update();
|
||||
}
|
||||
|
||||
void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* )
|
||||
{
|
||||
using A = QskAspect;
|
||||
|
||||
setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() );
|
||||
update();
|
||||
}
|
||||
|
||||
void QskSegmentedBar::focusInEvent( QFocusEvent* event )
|
||||
{
|
||||
int index = m_data->currentIndex;
|
||||
|
|
@ -291,6 +328,12 @@ void QskSegmentedBar::focusInEvent( QFocusEvent* event )
|
|||
Inherited::focusInEvent( event );
|
||||
}
|
||||
|
||||
void QskSegmentedBar::focusOutEvent( QFocusEvent* event )
|
||||
{
|
||||
setCurrentIndex( -1 );
|
||||
Inherited::focusOutEvent( event );
|
||||
}
|
||||
|
||||
void QskSegmentedBar::clear()
|
||||
{
|
||||
if( count() == 0 )
|
||||
|
|
@ -322,6 +365,8 @@ void QskSegmentedBar::setCurrentIndex( int index )
|
|||
if( index != m_data->currentIndex )
|
||||
{
|
||||
m_data->currentIndex = index;
|
||||
setPositionHint( Segment | Focused, index );
|
||||
|
||||
Q_EMIT currentIndexChanged( index );
|
||||
}
|
||||
}
|
||||
|
|
@ -354,9 +399,6 @@ void QskSegmentedBar::setSelectedIndex( int index )
|
|||
|
||||
Q_EMIT selectedIndexChanged( index );
|
||||
|
||||
setSkinStateFlag( Minimum, ( m_data->selectedIndex == 0 ) );
|
||||
setSkinStateFlag( Maximum, ( m_data->selectedIndex == count() - 1 ) );
|
||||
|
||||
const auto states = skinStates();
|
||||
|
||||
if ( oldIndex >= 0 )
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ class QSK_EXPORT QskSegmentedBar : public QskControl
|
|||
using Inherited = QskControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Segment, Separator, Cursor, Text, Icon )
|
||||
QSK_STATES( Selected, Minimum, Maximum )
|
||||
QSK_SUBCONTROLS( Panel, Splash, Segment, Separator, Cursor, Text, Icon )
|
||||
QSK_STATES( Selected, Pressed )
|
||||
|
||||
QskSegmentedBar( QQuickItem* parent = nullptr );
|
||||
QskSegmentedBar( Qt::Orientation, QQuickItem* parent = nullptr );
|
||||
|
|
@ -94,7 +94,12 @@ class QSK_EXPORT QskSegmentedBar : public QskControl
|
|||
void keyPressEvent( QKeyEvent* ) override;
|
||||
void keyReleaseEvent( QKeyEvent* ) override;
|
||||
|
||||
void hoverEnterEvent( QHoverEvent* ) override;
|
||||
void hoverMoveEvent( QHoverEvent* ) override;
|
||||
void hoverLeaveEvent( QHoverEvent* ) override;
|
||||
|
||||
void focusInEvent( QFocusEvent* ) override;
|
||||
void focusOutEvent( QFocusEvent* ) override;
|
||||
|
||||
private:
|
||||
int nextIndex( int index, bool forward ) const;
|
||||
|
|
|
|||
|
|
@ -10,22 +10,85 @@
|
|||
#include "QskGraphic.h"
|
||||
#include "QskColorFilter.h"
|
||||
#include "QskFunctions.h"
|
||||
#include "QskSGNode.h"
|
||||
#include "QskSkin.h"
|
||||
#include "QskStandardSymbol.h"
|
||||
#include "QskSkinStateChanger.h"
|
||||
#include "QskSubcontrolLayoutEngine.h"
|
||||
#include "QskBoxHints.h"
|
||||
|
||||
#include <qfontmetrics.h>
|
||||
#include <qmath.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
QskBoxHints effectiveBoxHints( QskAspect::Subcontrol subControl,
|
||||
const QskSegmentedBar* bar, int index )
|
||||
{
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
auto boxHints = bar->boxHints( subControl );
|
||||
|
||||
const bool leading = ( index == 0 );
|
||||
const bool trailing = ( index == bar->count() - 1 );
|
||||
|
||||
if ( !( leading || trailing ) )
|
||||
return boxHints;
|
||||
|
||||
// something more expressive than just a boolean. TODO ...
|
||||
if ( !bar->flagHint< bool >( Q::Panel | QskAspect::Option, false ) )
|
||||
return boxHints;
|
||||
|
||||
const auto panelShape = bar->boxShapeHint( Q::Panel );
|
||||
auto& shape = boxHints.shape;
|
||||
|
||||
// when there is only 1 segment we have to fit both ends
|
||||
|
||||
if ( leading )
|
||||
{
|
||||
Qt::Corner corners[2];
|
||||
|
||||
corners[0] = Qt::TopLeftCorner;
|
||||
|
||||
if ( bar->orientation() == Qt::Vertical )
|
||||
corners[1] = Qt::TopRightCorner;
|
||||
else
|
||||
corners[1] = Qt::BottomLeftCorner;
|
||||
|
||||
shape.setSizeMode( panelShape.sizeMode() );
|
||||
shape.setRadius( corners[0], panelShape.radius( corners[0] ) );
|
||||
shape.setRadius( corners[1], panelShape.radius( corners[1] ) );
|
||||
}
|
||||
|
||||
if ( trailing )
|
||||
{
|
||||
Qt::Corner corners[2];
|
||||
|
||||
corners[0] = Qt::BottomRightCorner;
|
||||
|
||||
if ( bar->orientation() == Qt::Vertical )
|
||||
corners[1] = Qt::BottomLeftCorner;
|
||||
else
|
||||
corners[1] = Qt::TopRightCorner;
|
||||
|
||||
shape.setSizeMode( panelShape.sizeMode() );
|
||||
shape.setRadius( corners[0], panelShape.radius( corners[0] ) );
|
||||
shape.setRadius( corners[1], panelShape.radius( corners[1] ) );
|
||||
}
|
||||
|
||||
boxHints.borderMetrics = bar->boxBorderMetricsHint( Q::Panel );
|
||||
boxHints.borderColors = QColor();
|
||||
|
||||
return boxHints;
|
||||
}
|
||||
|
||||
|
||||
QskGraphic iconAt( const QskSegmentedBar* bar, const int index )
|
||||
{
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
if ( bar->selectedIndex() == index )
|
||||
{
|
||||
/*
|
||||
/*
|
||||
Material 3 replaces the icon of the selected element by a checkmark,
|
||||
when icon and text are set. So this code is actually not correct
|
||||
as it also replaces the icon when there is no text
|
||||
|
|
@ -66,8 +129,8 @@ namespace
|
|||
QskSegmentedBarSkinlet::QskSegmentedBarSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
{
|
||||
setNodeRoles( { PanelRole, SegmentRole,
|
||||
SeparatorRole, CursorRole, TextRole, IconRole } );
|
||||
setNodeRoles( { PanelRole, SegmentRole, SeparatorRole,
|
||||
CursorRole, SplashRole, TextRole, IconRole } );
|
||||
}
|
||||
|
||||
QskSegmentedBarSkinlet::~QskSegmentedBarSkinlet() = default;
|
||||
|
|
@ -86,6 +149,9 @@ QRectF QskSegmentedBarSkinlet::subControlRect(
|
|||
if( subControl == Q::Cursor )
|
||||
return cursorRect( bar, contentsRect );
|
||||
|
||||
if( subControl == Q::Splash )
|
||||
return splashRect( bar, contentsRect );
|
||||
|
||||
return Inherited::subControlRect( skinnable, contentsRect, subControl );
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +186,48 @@ QRectF QskSegmentedBarSkinlet::cursorRect(
|
|||
return cursorRect;
|
||||
}
|
||||
|
||||
QRectF QskSegmentedBarSkinlet::splashRect(
|
||||
const QskSegmentedBar* bar, const QRectF& contentsRect ) const
|
||||
{
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
QRectF rect;
|
||||
|
||||
const auto ratio = bar->metric( Q::Splash | QskAspect::Size );
|
||||
|
||||
if ( ratio > 0.0 )
|
||||
{
|
||||
const auto pos = bar->effectiveSkinHint(
|
||||
Q::Splash | QskAspect::Metric | QskAspect::Position ).toPointF();
|
||||
|
||||
const int index = bar->indexAtPosition( pos );
|
||||
|
||||
if( index >= 0 && index < bar->count() )
|
||||
{
|
||||
const auto sr = segmentRect( bar, contentsRect, index );
|
||||
rect = sr;
|
||||
qreal w, h;
|
||||
|
||||
if( bar->orientation() == Qt::Horizontal )
|
||||
{
|
||||
w = 2.0 * rect.width() * ratio;
|
||||
h = 2.0 * rect.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
w = 2.0 * rect.width();
|
||||
h = 2.0 * rect.height() * ratio;
|
||||
}
|
||||
|
||||
rect.setSize( { w, h } );
|
||||
rect.moveCenter( pos );
|
||||
rect = rect.intersected( sr );
|
||||
}
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
QRectF QskSegmentedBarSkinlet::segmentRect(
|
||||
const QskSegmentedBar* bar, const QRectF& contentsRect, int index ) const
|
||||
{
|
||||
|
|
@ -163,7 +271,7 @@ QRectF QskSegmentedBarSkinlet::separatorRect(
|
|||
|
||||
if( bar->orientation() == Qt::Horizontal )
|
||||
{
|
||||
rect.setLeft( rect.right() ); // ### *0.5 or so?
|
||||
rect.setLeft( rect.right() );
|
||||
rect.setSize( { strutSize.width(), sh.height() } );
|
||||
}
|
||||
else
|
||||
|
|
@ -183,11 +291,16 @@ QSGNode* QskSegmentedBarSkinlet::updateSubNode(
|
|||
{
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
const auto bar = static_cast< const QskSegmentedBar* >( skinnable );
|
||||
|
||||
switch( nodeRole )
|
||||
{
|
||||
case CursorRole:
|
||||
return updateBoxNode( skinnable, node, Q::Cursor );
|
||||
|
||||
case SplashRole:
|
||||
return updateSplashNode( bar, node );
|
||||
|
||||
case PanelRole:
|
||||
return updateBoxNode( skinnable, node, Q::Panel );
|
||||
|
||||
|
|
@ -317,13 +430,52 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates(
|
|||
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const
|
||||
{
|
||||
using Q = QskSegmentedBar;
|
||||
using A = QskAspect;
|
||||
|
||||
auto states = Inherited::sampleStates( skinnable, subControl, index );
|
||||
|
||||
if ( subControl == Q::Segment || subControl == Q::Icon || subControl == Q::Text )
|
||||
{
|
||||
const auto bar = static_cast< const QskSegmentedBar* >( skinnable );
|
||||
const auto* bar = static_cast< const QskSegmentedBar* >( skinnable );
|
||||
|
||||
if ( subControl == Q::Segment )
|
||||
{
|
||||
if ( bar->isSegmentEnabled( index ) )
|
||||
{
|
||||
if ( bar->selectedIndex() == index )
|
||||
states |= Q::Selected;
|
||||
}
|
||||
else
|
||||
{
|
||||
states |= Q::Disabled;
|
||||
}
|
||||
|
||||
const auto cursorPos = bar->effectiveSkinHint(
|
||||
Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF();
|
||||
|
||||
if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index )
|
||||
{
|
||||
states |= Q::Hovered;
|
||||
}
|
||||
else
|
||||
{
|
||||
states &= ~Q::Hovered;
|
||||
}
|
||||
|
||||
const auto focusIndex = bar->positionHint( Q::Segment | Q::Focused );
|
||||
|
||||
if( focusIndex >= 0 && focusIndex < bar->count() )
|
||||
{
|
||||
if( focusIndex == index )
|
||||
{
|
||||
states |= Q::Focused;
|
||||
}
|
||||
else
|
||||
{
|
||||
states &= ~Q::Focused;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( subControl == Q::Icon || subControl == Q::Text )
|
||||
{
|
||||
if ( bar->isSegmentEnabled( index ) )
|
||||
{
|
||||
if ( bar->selectedIndex() == index )
|
||||
|
|
@ -347,11 +499,17 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable
|
|||
|
||||
const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index );
|
||||
|
||||
if ( subControl == Q::Segment || subControl == Q::Separator )
|
||||
if ( subControl == Q::Separator )
|
||||
{
|
||||
return updateBoxNode( skinnable, node, rect, subControl );
|
||||
}
|
||||
|
||||
if ( subControl == Q::Segment )
|
||||
{
|
||||
const auto boxHints = effectiveBoxHints( subControl, bar, index );
|
||||
return updateBoxNode( bar, node, rect, boxHints );
|
||||
}
|
||||
|
||||
const auto alignment = bar->alignmentHint( subControl, Qt::AlignCenter );
|
||||
|
||||
if ( subControl == Q::Text )
|
||||
|
|
@ -387,4 +545,26 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable
|
|||
return Inherited::updateSampleNode( skinnable, subControl, index, node );
|
||||
}
|
||||
|
||||
QSGNode* QskSegmentedBarSkinlet::updateSplashNode(
|
||||
const QskSegmentedBar* bar, QSGNode* node ) const
|
||||
{
|
||||
using Q = QskSegmentedBar;
|
||||
|
||||
const auto splashRect = bar->subControlRect( Q::Splash );
|
||||
if ( splashRect.isEmpty() )
|
||||
return nullptr;
|
||||
|
||||
auto clipNode = updateBoxClipNode(
|
||||
bar, node, bar->subControlRect( Q::Panel ), Q::Panel );
|
||||
|
||||
if ( clipNode )
|
||||
{
|
||||
auto boxNode = updateBoxNode( bar, clipNode->firstChild(), splashRect, Q::Splash );
|
||||
if ( boxNode->parent() == nullptr )
|
||||
clipNode->appendChildNode( boxNode );
|
||||
}
|
||||
|
||||
return clipNode;
|
||||
}
|
||||
|
||||
#include "moc_QskSegmentedBarSkinlet.cpp"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class QSK_EXPORT QskSegmentedBarSkinlet : public QskSkinlet
|
|||
SegmentRole,
|
||||
SeparatorRole,
|
||||
CursorRole,
|
||||
SplashRole,
|
||||
|
||||
TextRole,
|
||||
IconRole,
|
||||
|
|
@ -60,6 +61,9 @@ class QSK_EXPORT QskSegmentedBarSkinlet : public QskSkinlet
|
|||
QRectF segmentRect( const QskSegmentedBar*, const QRectF&, int index ) const;
|
||||
QRectF separatorRect( const QskSegmentedBar*, const QRectF&, int index ) const;
|
||||
QRectF cursorRect( const QskSegmentedBar*, const QRectF& ) const;
|
||||
QRectF splashRect( const QskSegmentedBar*, const QRectF& ) const;
|
||||
|
||||
QSGNode* updateSplashNode( const QskSegmentedBar*, QSGNode* ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ void QskShortcutHandler::remove( int id )
|
|||
Finally let's check if we can disconnect
|
||||
from the destroyed signals
|
||||
*/
|
||||
for ( const auto& entry : qAsConst( m_invokeDataMap ) )
|
||||
for ( const auto& entry : std::as_const( m_invokeDataMap ) )
|
||||
{
|
||||
if ( item == nullptr && receiver == nullptr )
|
||||
break;
|
||||
|
|
@ -276,7 +276,7 @@ bool QskShortcutHandler::invoke( QQuickItem* item, const QKeySequence& sequence
|
|||
{
|
||||
bool found = false;
|
||||
|
||||
for ( const auto& entry : qAsConst( m_invokeDataMap ) )
|
||||
for ( const auto& entry : std::as_const( m_invokeDataMap ) )
|
||||
{
|
||||
auto& data = entry.second;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,18 @@ class QSK_EXPORT QskSkin : public QObject
|
|||
|
||||
Q_ENUM( SkinFontRole )
|
||||
|
||||
#if 1
|
||||
// Use Qt::ColorScheme once minimum version is Qt 6.5
|
||||
enum ColorScheme
|
||||
{
|
||||
UnknownScheme,
|
||||
|
||||
LightScheme,
|
||||
DarkScheme
|
||||
};
|
||||
Q_ENUM( ColorScheme )
|
||||
#endif
|
||||
|
||||
QskSkin( QObject* parent = nullptr );
|
||||
~QskSkin() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@
|
|||
#include <qpointer.h>
|
||||
#include <qset.h>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 )
|
||||
#include <qguiapplication.h>
|
||||
#include <qstylehints.h>
|
||||
#endif
|
||||
|
||||
static inline QStringList qskSplitPath( const QString& s )
|
||||
{
|
||||
const auto separator = QDir::listSeparator();
|
||||
|
|
@ -74,6 +79,8 @@ namespace
|
|||
const QLatin1String TokenData( "MetaData" );
|
||||
const QLatin1String TokenFactoryId( "FactoryId" );
|
||||
const QLatin1String TokenSkins( "Skins" );
|
||||
const QLatin1String TokenName( "Name" );
|
||||
const QLatin1String TokenScheme( "Scheme" );
|
||||
|
||||
const QLatin1String InterfaceId( QskSkinFactoryIID );
|
||||
|
||||
|
|
@ -83,10 +90,6 @@ namespace
|
|||
const auto factoryData = pluginData.value( TokenData ).toObject();
|
||||
|
||||
m_factoryId = factoryData.value( TokenFactoryId ).toString().toLower();
|
||||
#if 1
|
||||
if ( m_factoryId == "fluent2factory" )
|
||||
return false; // we need to solve a couple of problems first
|
||||
#endif
|
||||
if ( m_factoryId.isEmpty() )
|
||||
{
|
||||
// Creating a dummy factory id
|
||||
|
|
@ -94,10 +97,45 @@ namespace
|
|||
m_factoryId = QStringLiteral( "skin_factory_" ) + QString::number( i++ );
|
||||
}
|
||||
|
||||
const auto skinNames = factoryData.value( TokenSkins ).toArray();
|
||||
const auto skins = factoryData.value( TokenSkins ).toArray();
|
||||
|
||||
for ( const auto& name : skinNames )
|
||||
m_skinNames += name.toString();
|
||||
for ( const auto& skin : skins )
|
||||
{
|
||||
const auto& skinObject = skin.toObject();
|
||||
const auto& name = skinObject.value( TokenName ).toString();
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 )
|
||||
const auto& schemeString = skinObject.value( TokenScheme ).toString();
|
||||
Qt::ColorScheme scheme;
|
||||
|
||||
if( schemeString == QStringLiteral( "Light" ) )
|
||||
{
|
||||
scheme = Qt::ColorScheme::Light;
|
||||
}
|
||||
else if( schemeString == QStringLiteral( "Dark" ) )
|
||||
{
|
||||
scheme = Qt::ColorScheme::Dark;
|
||||
}
|
||||
else
|
||||
{
|
||||
scheme = Qt::ColorScheme::Unknown;
|
||||
}
|
||||
|
||||
const auto systemScheme = qGuiApp->styleHints()->colorScheme();
|
||||
|
||||
if( scheme == systemScheme )
|
||||
{
|
||||
m_skinNames.prepend( name );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_skinNames.append( name );
|
||||
}
|
||||
#else
|
||||
Q_UNUSED( TokenScheme )
|
||||
m_skinNames += name;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return !m_skinNames.isEmpty();
|
||||
|
|
@ -327,7 +365,7 @@ class QskSkinManager::PrivateData
|
|||
{
|
||||
if ( !pluginsRegistered )
|
||||
{
|
||||
for ( const auto& path : qAsConst( pluginPaths ) )
|
||||
for ( const auto& path : std::as_const( pluginPaths ) )
|
||||
registerPlugins( path + QStringLiteral( "/skins" ) );
|
||||
|
||||
pluginsRegistered = true;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class QskSkinStateChanger
|
|||
~QskSkinStateChanger();
|
||||
|
||||
void setStates( QskAspect::States );
|
||||
void resetStates();
|
||||
|
||||
private:
|
||||
QskSkinnable* m_skinnable;
|
||||
|
|
@ -30,8 +31,7 @@ inline QskSkinStateChanger::QskSkinStateChanger( const QskSkinnable* skinnable )
|
|||
|
||||
inline QskSkinStateChanger::~QskSkinStateChanger()
|
||||
{
|
||||
if ( m_oldStates != m_skinnable->skinStates() )
|
||||
m_skinnable->replaceSkinStates( m_oldStates );
|
||||
resetStates();
|
||||
}
|
||||
|
||||
inline void QskSkinStateChanger::setStates( QskAspect::States states )
|
||||
|
|
@ -40,4 +40,10 @@ inline void QskSkinStateChanger::setStates( QskAspect::States states )
|
|||
m_skinnable->replaceSkinStates( states );
|
||||
}
|
||||
|
||||
inline void QskSkinStateChanger::resetStates()
|
||||
{
|
||||
if ( m_oldStates != m_skinnable->skinStates() )
|
||||
m_skinnable->replaceSkinStates( m_oldStates );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ void QskSkinlet::updateNode( QskSkinnable* skinnable, QSGNode* parentNode ) cons
|
|||
replaceChildNode( DebugRole, parentNode, oldNode, newNode );
|
||||
}
|
||||
|
||||
for ( const auto nodeRole : qAsConst( m_data->nodeRoles ) )
|
||||
for ( const auto nodeRole : std::as_const( m_data->nodeRoles ) )
|
||||
{
|
||||
Q_ASSERT( nodeRole < FirstReservedRole );
|
||||
|
||||
|
|
|
|||
|
|
@ -1382,7 +1382,19 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates )
|
|||
bool QskSkinnable::startHintTransitions(
|
||||
QskAspect::States oldStates, QskAspect::States newStates, int index )
|
||||
{
|
||||
if ( !isTransitionAccepted( QskAspect() ) )
|
||||
QVector< QskAspect::Subcontrol > subControls;
|
||||
|
||||
if ( const auto control = qskControlCast( owningItem() ) )
|
||||
subControls = control->subControls();
|
||||
|
||||
return startHintTransitions( subControls, oldStates, newStates, index );
|
||||
}
|
||||
|
||||
bool QskSkinnable::startHintTransitions(
|
||||
const QVector< QskAspect::Subcontrol >& subControls,
|
||||
QskAspect::States oldStates, QskAspect::States newStates, int index )
|
||||
{
|
||||
if ( !isTransitionAccepted( QskAspect() ) || subControls.isEmpty() )
|
||||
{
|
||||
// the control does not like any animated transition at the moment
|
||||
return false;
|
||||
|
|
@ -1401,7 +1413,6 @@ bool QskSkinnable::startHintTransitions(
|
|||
|
||||
const auto primitiveCount = QskAspect::primitiveCount();
|
||||
|
||||
const auto subControls = control->subControls();
|
||||
for ( const auto subControl : subControls )
|
||||
{
|
||||
aspect.setSubcontrol( subControl );
|
||||
|
|
|
|||
|
|
@ -260,6 +260,8 @@ class QSK_EXPORT QskSkinnable
|
|||
const QskSkinHintTable& hintTable() const;
|
||||
|
||||
bool startHintTransitions( QskAspect::States, QskAspect::States, int index = -1 );
|
||||
bool startHintTransitions( const QVector< QskAspect::Subcontrol >&,
|
||||
QskAspect::States, QskAspect::States, int index = -1 );
|
||||
|
||||
protected:
|
||||
virtual void updateNode( QSGNode* );
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ QskDialogButtonBox::~QskDialogButtonBox()
|
|||
{
|
||||
for ( int i = 0; i < QskDialog::NActionRoles; i++ )
|
||||
{
|
||||
for ( auto button : qAsConst( m_data->buttons[ i ] ) )
|
||||
for ( auto button : std::as_const( m_data->buttons[ i ] ) )
|
||||
{
|
||||
/*
|
||||
The destructor of QQuickItem sets the parentItem of
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ QskDialogWindow::QskDialogWindow( QWindow* parent )
|
|||
// doing the layout manually instead ???
|
||||
setAutoLayoutChildren( true );
|
||||
m_data->layoutBox = new QskLinearBox( Qt::Vertical, contentItem() );
|
||||
m_data->layoutBox->setMargins( 5 );
|
||||
m_data->layoutBox->setPadding( 5 );
|
||||
m_data->layoutBox->setPanel( true ); // for a themed background
|
||||
}
|
||||
|
||||
QskDialogWindow::~QskDialogWindow()
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ QRectF QskGraphic::scaledBoundingRect( qreal sx, qreal sy ) const
|
|||
|
||||
QRectF rect = transform.mapRect( m_data->pointRect );
|
||||
|
||||
for ( const auto& info : qAsConst( m_data->pathInfos ) )
|
||||
for ( const auto& info : std::as_const( m_data->pathInfos ) )
|
||||
rect |= info.scaledBoundingRect( sx, sy, scalePens );
|
||||
|
||||
return rect;
|
||||
|
|
@ -681,7 +681,7 @@ void QskGraphic::render( QPainter* painter, const QRectF& rect,
|
|||
|
||||
const bool scalePens = !( m_data->renderHints & RenderPensUnscaled );
|
||||
|
||||
for ( const auto& info : qAsConst( m_data->pathInfos ) )
|
||||
for ( const auto& info : std::as_const( m_data->pathInfos ) )
|
||||
{
|
||||
const qreal ssx = info.scaleFactorX( m_data->pointRect,
|
||||
rect, m_data->boundingRect, scalePens );
|
||||
|
|
|
|||
|
|
@ -524,6 +524,8 @@ bool QskGridLayoutEngine::clear()
|
|||
m_data->rowSettings.clear();
|
||||
m_data->columnSettings.clear();
|
||||
|
||||
m_data->rowCount = m_data->columnCount = 0;
|
||||
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ void QskStackBox::autoRemoveItem( QQuickItem* item )
|
|||
|
||||
void QskStackBox::clear( bool autoDelete )
|
||||
{
|
||||
for ( const auto item : qAsConst( m_data->items ) )
|
||||
for ( const auto item : std::as_const( m_data->items ) )
|
||||
{
|
||||
if( autoDelete && ( item->parent() == this ) )
|
||||
delete item;
|
||||
|
|
@ -380,7 +380,7 @@ QSizeF QskStackBox::layoutSizeHint(
|
|||
qreal w = -1.0;
|
||||
qreal h = -1.0;
|
||||
|
||||
for ( const auto item : qAsConst( m_data->items ) )
|
||||
for ( const auto item : std::as_const( m_data->items ) )
|
||||
{
|
||||
/*
|
||||
We ignore the retainSizeWhenVisible flag and include all
|
||||
|
|
|
|||
|
|
@ -39,7 +39,25 @@ void QskBoxClipNode::setBox( const QRectF& rect,
|
|||
m_rect = rect;
|
||||
m_hash = hash;
|
||||
|
||||
bool isRectangular = false;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Depending on isRectangular the "renderer can use scissoring instead of stencil,
|
||||
which is significantly faster."
|
||||
|
||||
However the batch renderer ( qsgbatchrenderer.cpp ) is rounding the clip rectangle
|
||||
to integers and the clip might become too small/large.
|
||||
|
||||
So we always have to use stencil clipping - even if it might have a negative
|
||||
impact on the performance. TODO ...
|
||||
*/
|
||||
|
||||
if ( shape.isRectangle() )
|
||||
isRectangular = true;
|
||||
#endif
|
||||
|
||||
if ( isRectangular )
|
||||
{
|
||||
if ( m_geometry.vertexCount() > 0 )
|
||||
m_geometry.allocate( 0 );
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class QskColorFilter;
|
|||
class QSGNode;
|
||||
class QVariant;
|
||||
class QRectF;
|
||||
class QSizeF;
|
||||
|
||||
class QSK_EXPORT QskScaleRenderer
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue