Merge panel-layout code: choose where to place sidebar + nav
This commit is contained in:
commit
59ef307af2
3
CHANGES
3
CHANGES
@ -16,6 +16,9 @@ This release contains contributions from (alphabetically by first name):
|
|||||||
Calamares). The example QML that is compiled into Calamares has
|
Calamares). The example QML that is compiled into Calamares has
|
||||||
been improved. To use your own QML, put files `calamares-sidebar.qml`
|
been improved. To use your own QML, put files `calamares-sidebar.qml`
|
||||||
or `calamares-navigation.qml` into the branding directory.
|
or `calamares-navigation.qml` into the branding directory.
|
||||||
|
- The sidebar and navigation can now be placed on any side of the
|
||||||
|
main window. This is probably only useful for QML-based UIs.
|
||||||
|
See `branding.desc` for details.
|
||||||
|
|
||||||
## Modules ##
|
## Modules ##
|
||||||
- The *welcomeq* module has been improved with better layout and
|
- The *welcomeq* module has been improved with better layout and
|
||||||
|
@ -45,12 +45,25 @@ windowPlacement: center
|
|||||||
# - "widget" or unset, use traditional sidebar (logo, items)
|
# - "widget" or unset, use traditional sidebar (logo, items)
|
||||||
# - "none", hide it entirely
|
# - "none", hide it entirely
|
||||||
# - "qml", use calamares-sidebar.qml from branding folder
|
# - "qml", use calamares-sidebar.qml from branding folder
|
||||||
|
# In addition, you **may** specify a side, separated by a comma,
|
||||||
|
# from the kind. Valid sides are:
|
||||||
|
# - "left" (if not specified, uses this)
|
||||||
|
# - "right"
|
||||||
|
# - "top"
|
||||||
|
# - "bottom"
|
||||||
|
# For instance, "widget,right" is valid; so is "qml", which defaults
|
||||||
|
# to putting the sidebar on the left. Also valid is "qml,top".
|
||||||
|
# While "widget,top" is valid, the widgets code is **not** flexible
|
||||||
|
# and results will be terrible.
|
||||||
sidebar: widget
|
sidebar: widget
|
||||||
|
|
||||||
# Kind of navigation (button panel on the bottom).
|
# Kind of navigation (button panel on the bottom).
|
||||||
# - "widget" or unset, use traditional navigation
|
# - "widget" or unset, use traditional navigation
|
||||||
# - "none", hide it entirely
|
# - "none", hide it entirely
|
||||||
# - "qml", use calamares-navigation.qml from branding folder
|
# - "qml", use calamares-navigation.qml from branding folder
|
||||||
|
# In addition, you **may** specify a side, separated by a comma,
|
||||||
|
# from the kind. The same sides are valid as for *sidebar*,
|
||||||
|
# except the default is *bottom*.
|
||||||
navigation: widget
|
navigation: widget
|
||||||
|
|
||||||
# These are strings shown to the user in the user interface.
|
# These are strings shown to the user in the user interface.
|
||||||
|
@ -132,11 +132,10 @@ CalamaresWindow::getWidgetSidebar( int desiredWidth )
|
|||||||
}
|
}
|
||||||
|
|
||||||
QWidget*
|
QWidget*
|
||||||
CalamaresWindow::getQmlSidebar( int desiredWidth )
|
CalamaresWindow::getQmlSidebar( int )
|
||||||
{
|
{
|
||||||
CalamaresUtils::registerCalamaresModels();
|
CalamaresUtils::registerCalamaresModels();
|
||||||
QQuickWidget* w = new QQuickWidget( this );
|
QQuickWidget* w = new QQuickWidget( this );
|
||||||
w->setFixedWidth( desiredWidth );
|
|
||||||
w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
|
w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
|
||||||
w->setResizeMode( QQuickWidget::SizeRootObjectToView );
|
w->setResizeMode( QQuickWidget::SizeRootObjectToView );
|
||||||
w->setSource( QUrl(
|
w->setSource( QUrl(
|
||||||
@ -217,7 +216,6 @@ CalamaresWindow::getQmlNavigation()
|
|||||||
{
|
{
|
||||||
CalamaresUtils::registerCalamaresModels();
|
CalamaresUtils::registerCalamaresModels();
|
||||||
QQuickWidget* w = new QQuickWidget( this );
|
QQuickWidget* w = new QQuickWidget( this );
|
||||||
w->setFixedHeight( 64 );
|
|
||||||
w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
|
w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
|
||||||
w->setResizeMode( QQuickWidget::SizeRootObjectToView );
|
w->setResizeMode( QQuickWidget::SizeRootObjectToView );
|
||||||
w->setSource( QUrl(
|
w->setSource( QUrl(
|
||||||
@ -251,6 +249,28 @@ flavoredWidget( Calamares::Branding::PanelFlavor flavor,
|
|||||||
NOTREACHED return nullptr; // All enum values handled above
|
NOTREACHED return nullptr; // All enum values handled above
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Adds widgets to @p layout if they belong on this @p side
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
insertIf( QBoxLayout* layout,
|
||||||
|
Calamares::Branding::PanelSide side,
|
||||||
|
QWidget* first,
|
||||||
|
Calamares::Branding::PanelSide firstSide )
|
||||||
|
{
|
||||||
|
if ( first && side == firstSide )
|
||||||
|
{
|
||||||
|
if ( ( side == Calamares::Branding::PanelSide::Left ) || ( side == Calamares::Branding::PanelSide::Right ) )
|
||||||
|
{
|
||||||
|
first->setMinimumWidth( qMax( first->minimumWidth(), 64 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first->setMinimumHeight( qMax( first->minimumHeight(), 64 ) );
|
||||||
|
}
|
||||||
|
layout->addWidget( first );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CalamaresWindow::CalamaresWindow( QWidget* parent )
|
CalamaresWindow::CalamaresWindow( QWidget* parent )
|
||||||
: QWidget( parent )
|
: QWidget( parent )
|
||||||
, m_debugWindow( nullptr )
|
, m_debugWindow( nullptr )
|
||||||
@ -273,6 +293,8 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
|
|||||||
using CalamaresUtils::windowPreferredHeight;
|
using CalamaresUtils::windowPreferredHeight;
|
||||||
using CalamaresUtils::windowPreferredWidth;
|
using CalamaresUtils::windowPreferredWidth;
|
||||||
|
|
||||||
|
using PanelSide = Calamares::Branding::PanelSide;
|
||||||
|
|
||||||
// Needs to match what's checked in DebugWindow
|
// Needs to match what's checked in DebugWindow
|
||||||
this->setObjectName( "mainApp" );
|
this->setObjectName( "mainApp" );
|
||||||
|
|
||||||
@ -292,21 +314,6 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
|
|||||||
resize( w, h );
|
resize( w, h );
|
||||||
|
|
||||||
m_viewManager = Calamares::ViewManager::instance( this );
|
m_viewManager = Calamares::ViewManager::instance( this );
|
||||||
|
|
||||||
QBoxLayout* mainLayout = new QHBoxLayout;
|
|
||||||
setLayout( mainLayout );
|
|
||||||
|
|
||||||
QWidget* sideBox = flavoredWidget(
|
|
||||||
branding->sidebarFlavor(),
|
|
||||||
this,
|
|
||||||
&CalamaresWindow::getWidgetSidebar,
|
|
||||||
&CalamaresWindow::getQmlSidebar,
|
|
||||||
qBound( 100, CalamaresUtils::defaultFontHeight() * 12, w < windowPreferredWidth ? 100 : 190 ) );
|
|
||||||
if ( sideBox )
|
|
||||||
{
|
|
||||||
mainLayout->addWidget( sideBox );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( branding->windowExpands() )
|
if ( branding->windowExpands() )
|
||||||
{
|
{
|
||||||
connect( m_viewManager, &Calamares::ViewManager::enlarge, this, &CalamaresWindow::enlarge );
|
connect( m_viewManager, &Calamares::ViewManager::enlarge, this, &CalamaresWindow::enlarge );
|
||||||
@ -319,16 +326,35 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
|
|||||||
// and requires an extra show() (at least with KWin/X11) which
|
// and requires an extra show() (at least with KWin/X11) which
|
||||||
// is too annoying. Instead, leave it up to ignoring-the-quit-
|
// is too annoying. Instead, leave it up to ignoring-the-quit-
|
||||||
// event, which is also the ViewManager's responsibility.
|
// event, which is also the ViewManager's responsibility.
|
||||||
|
|
||||||
|
QBoxLayout* mainLayout = new QHBoxLayout;
|
||||||
QBoxLayout* contentsLayout = new QVBoxLayout;
|
QBoxLayout* contentsLayout = new QVBoxLayout;
|
||||||
contentsLayout->addWidget( m_viewManager->centralWidget() );
|
|
||||||
|
setLayout( mainLayout );
|
||||||
|
|
||||||
|
QWidget* sideBox = flavoredWidget(
|
||||||
|
branding->sidebarFlavor(),
|
||||||
|
this,
|
||||||
|
&CalamaresWindow::getWidgetSidebar,
|
||||||
|
&CalamaresWindow::getQmlSidebar,
|
||||||
|
qBound( 100, CalamaresUtils::defaultFontHeight() * 12, w < windowPreferredWidth ? 100 : 190 ) );
|
||||||
QWidget* navigation = flavoredWidget(
|
QWidget* navigation = flavoredWidget(
|
||||||
branding->navigationFlavor(), this, &CalamaresWindow::getWidgetNavigation, &CalamaresWindow::getQmlNavigation );
|
branding->navigationFlavor(), this, &CalamaresWindow::getWidgetNavigation, &CalamaresWindow::getQmlNavigation );
|
||||||
if ( navigation )
|
|
||||||
{
|
|
||||||
contentsLayout->addWidget( navigation );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Build up the contentsLayout (a VBox) top-to-bottom
|
||||||
|
// .. note that the bottom is mirrored wrt. the top
|
||||||
|
insertIf( contentsLayout, PanelSide::Top, sideBox, branding->sidebarSide() );
|
||||||
|
insertIf( contentsLayout, PanelSide::Top, navigation, branding->navigationSide() );
|
||||||
|
contentsLayout->addWidget( m_viewManager->centralWidget() );
|
||||||
|
insertIf( contentsLayout, PanelSide::Bottom, navigation, branding->navigationSide() );
|
||||||
|
insertIf( contentsLayout, PanelSide::Bottom, sideBox, branding->sidebarSide() );
|
||||||
|
|
||||||
|
// .. and then the mainLayout left-to-right
|
||||||
|
insertIf( mainLayout, PanelSide::Left, sideBox, branding->sidebarSide() );
|
||||||
|
insertIf( mainLayout, PanelSide::Left, navigation, branding->navigationSide() );
|
||||||
mainLayout->addLayout( contentsLayout );
|
mainLayout->addLayout( contentsLayout );
|
||||||
|
insertIf( mainLayout, PanelSide::Right, navigation, branding->navigationSide() );
|
||||||
|
insertIf( mainLayout, PanelSide::Right, sideBox, branding->sidebarSide() );
|
||||||
|
|
||||||
CalamaresUtils::unmarginLayout( mainLayout );
|
CalamaresUtils::unmarginLayout( mainLayout );
|
||||||
CalamaresUtils::unmarginLayout( contentsLayout );
|
CalamaresUtils::unmarginLayout( contentsLayout );
|
||||||
|
@ -405,6 +405,79 @@ getString( const YAML::Node& doc, const char* key )
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
flavorAndSide( const YAML::Node& doc, const char* key, Branding::PanelFlavor& flavor, Branding::PanelSide& side )
|
||||||
|
{
|
||||||
|
using PanelFlavor = Branding::PanelFlavor;
|
||||||
|
using PanelSide = Branding::PanelSide;
|
||||||
|
|
||||||
|
// *INDENT-OFF*
|
||||||
|
// clang-format off
|
||||||
|
static const NamedEnumTable< PanelFlavor > sidebarFlavorNames {
|
||||||
|
{ QStringLiteral( "widget" ), PanelFlavor::Widget },
|
||||||
|
{ QStringLiteral( "none" ), PanelFlavor::None },
|
||||||
|
{ QStringLiteral( "hidden" ), PanelFlavor::None },
|
||||||
|
{ QStringLiteral( "qml" ), PanelFlavor::Qml }
|
||||||
|
};
|
||||||
|
static const NamedEnumTable< PanelSide > panelSideNames {
|
||||||
|
{ QStringLiteral( "left" ), PanelSide::Left },
|
||||||
|
{ QStringLiteral( "right" ), PanelSide::Right },
|
||||||
|
{ QStringLiteral( "top" ), PanelSide::Top },
|
||||||
|
{ QStringLiteral( "bottom" ), PanelSide::Bottom }
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
// *INDENT-ON*
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
QString configValue = getString( doc, key );
|
||||||
|
if ( configValue.isEmpty() )
|
||||||
|
{
|
||||||
|
// Complain with the original values
|
||||||
|
cWarning() << "Branding setting for" << key << "is missing, using" << sidebarFlavorNames.find( flavor, ok )
|
||||||
|
<< panelSideNames.find( side, ok );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList parts = configValue.split( ',' );
|
||||||
|
if ( parts.length() == 1 )
|
||||||
|
{
|
||||||
|
PanelFlavor f = sidebarFlavorNames.find( configValue, ok );
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
flavor = f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Complain with the original value
|
||||||
|
cWarning() << "Branding setting for" << key << "interpreted as" << sidebarFlavorNames.find( flavor, ok )
|
||||||
|
<< panelSideNames.find( side, ok );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const QString& spart : parts )
|
||||||
|
{
|
||||||
|
bool isFlavor = false;
|
||||||
|
bool isSide = false;
|
||||||
|
PanelFlavor f = sidebarFlavorNames.find( spart, isFlavor );
|
||||||
|
PanelSide s = panelSideNames.find( spart, isSide );
|
||||||
|
if ( isFlavor )
|
||||||
|
{
|
||||||
|
flavor = f;
|
||||||
|
}
|
||||||
|
else if ( isSide )
|
||||||
|
{
|
||||||
|
side = s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cWarning() << "Branding setting for" << key << "contains unknown" << spart << "interpreted as"
|
||||||
|
<< sidebarFlavorNames.find( flavor, ok ) << panelSideNames.find( side, ok );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Branding::initSimpleSettings( const YAML::Node& doc )
|
Branding::initSimpleSettings( const YAML::Node& doc )
|
||||||
{
|
{
|
||||||
@ -419,12 +492,6 @@ Branding::initSimpleSettings( const YAML::Node& doc )
|
|||||||
{ QStringLiteral( "free" ), WindowPlacement::Free },
|
{ QStringLiteral( "free" ), WindowPlacement::Free },
|
||||||
{ QStringLiteral( "center" ), WindowPlacement::Center }
|
{ QStringLiteral( "center" ), WindowPlacement::Center }
|
||||||
};
|
};
|
||||||
static const NamedEnumTable< PanelFlavor > sidebarFlavorNames {
|
|
||||||
{ QStringLiteral( "widget" ), PanelFlavor::Widget },
|
|
||||||
{ QStringLiteral( "none" ), PanelFlavor::None },
|
|
||||||
{ QStringLiteral( "hidden" ), PanelFlavor::None },
|
|
||||||
{ QStringLiteral( "qml" ), PanelFlavor::Qml }
|
|
||||||
};
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
// *INDENT-ON*
|
// *INDENT-ON*
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
@ -443,18 +510,8 @@ Branding::initSimpleSettings( const YAML::Node& doc )
|
|||||||
cWarning() << "Branding module-setting *windowPlacement* interpreted as"
|
cWarning() << "Branding module-setting *windowPlacement* interpreted as"
|
||||||
<< placementNames.find( m_windowPlacement, ok );
|
<< placementNames.find( m_windowPlacement, ok );
|
||||||
}
|
}
|
||||||
m_sidebarFlavor = sidebarFlavorNames.find( getString( doc, "sidebar" ), ok );
|
flavorAndSide( doc, "sidebar", m_sidebarFlavor, m_sidebarSide );
|
||||||
if ( !ok )
|
flavorAndSide( doc, "navigation", m_navigationFlavor, m_navigationSide );
|
||||||
{
|
|
||||||
cWarning() << "Branding module-setting *sidebar* interpreted as"
|
|
||||||
<< sidebarFlavorNames.find( m_sidebarFlavor, ok );
|
|
||||||
}
|
|
||||||
m_navigationFlavor = sidebarFlavorNames.find( getString( doc, "navigation" ), ok);
|
|
||||||
if ( !ok )
|
|
||||||
{
|
|
||||||
cWarning() << "Branding module-setting *navigation* interpreted as"
|
|
||||||
<< sidebarFlavorNames.find( m_navigationFlavor, ok );
|
|
||||||
}
|
|
||||||
|
|
||||||
QString windowSize = getString( doc, "windowSize" );
|
QString windowSize = getString( doc, "windowSize" );
|
||||||
if ( !windowSize.isEmpty() )
|
if ( !windowSize.isEmpty() )
|
||||||
|
@ -123,7 +123,7 @@ public:
|
|||||||
Free
|
Free
|
||||||
};
|
};
|
||||||
Q_ENUM( WindowPlacement )
|
Q_ENUM( WindowPlacement )
|
||||||
///@brief What kind of sidebar to use in the main window
|
///@brief What kind of panel (sidebar, navigation) to use in the main window
|
||||||
enum class PanelFlavor
|
enum class PanelFlavor
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
@ -131,6 +131,16 @@ public:
|
|||||||
Qml
|
Qml
|
||||||
};
|
};
|
||||||
Q_ENUM( PanelFlavor )
|
Q_ENUM( PanelFlavor )
|
||||||
|
///@brief Where to place a panel (sidebar, navigation)
|
||||||
|
enum class PanelSide
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Top,
|
||||||
|
Bottom
|
||||||
|
};
|
||||||
|
Q_ENUM( PanelSide )
|
||||||
|
|
||||||
static Branding* instance();
|
static Branding* instance();
|
||||||
|
|
||||||
@ -201,6 +211,9 @@ public slots:
|
|||||||
QString styleString( StyleEntry styleEntry ) const;
|
QString styleString( StyleEntry styleEntry ) const;
|
||||||
QString imagePath( ImageEntry imageEntry ) const;
|
QString imagePath( ImageEntry imageEntry ) const;
|
||||||
|
|
||||||
|
PanelSide sidebarSide() const { return m_sidebarSide; }
|
||||||
|
PanelSide navigationSide() const { return m_navigationSide; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Branding* s_instance;
|
static Branding* s_instance;
|
||||||
|
|
||||||
@ -231,6 +244,8 @@ private:
|
|||||||
|
|
||||||
PanelFlavor m_sidebarFlavor = PanelFlavor::Widget;
|
PanelFlavor m_sidebarFlavor = PanelFlavor::Widget;
|
||||||
PanelFlavor m_navigationFlavor = PanelFlavor::Widget;
|
PanelFlavor m_navigationFlavor = PanelFlavor::Widget;
|
||||||
|
PanelSide m_sidebarSide = PanelSide::Left;
|
||||||
|
PanelSide m_navigationSide = PanelSide::Bottom;
|
||||||
};
|
};
|
||||||
|
|
||||||
template < typename U >
|
template < typename U >
|
||||||
|
Loading…
Reference in New Issue
Block a user