Merge branch 'issue-1446' into calamares

Improve margin handling.

There's a margin around the "central widget" in Calamares, which serves
to keep the contents away from window edges. This works for widgets,
which all have a content widget with a layout, but is a little weird for
QML components: the QML component probably has its own internal margins,
and the margin around it serves little purpose.

If there's panels (navigation, progress) around the central widget, the
margins also serve to keep the content away from those navigation
elements.

**But** if there are no panels, then a QML component still gets a margin
around it. Pretty much the only reason for a no-panel setup is that you
have a full-screen QML version of Calamares where the navigation is
"inside" each QML component. This could be the case in a customised OEM
tool built from Cala, for instance.

For this special case, improve overall margin handling by giving the
view steps some control over their own margins.

FIXES #1446
main
Adriaan de Groot 5 years ago
commit 3c48bbdb9c

@ -7,6 +7,12 @@
---
componentName: default
### WELCOME / OVERALL WORDING
#
# These settings affect some overall phrasing and looks,
# which are most visible in the welcome page.
# This selects between different welcome texts. When false, uses
# the traditional "Welcome to the %1 installer.", and when true,
# uses "Welcome to the Calamares installer for %1." This allows
@ -20,6 +26,12 @@ welcomeStyleCalamares: false
# may have surprising effects on HiDPI monitors).
welcomeExpandingLogo: true
### WINDOW CONFIGURATION
#
# The settings here affect the placement of the Calamares
# window through hints to the window manager and initial
# sizing of the Calamares window.
# Size and expansion policy for Calamares.
# - "normal" or unset, expand as needed, use *windowSize*
# - "fullscreen", start as large as possible, ignore *windowSize*
@ -41,6 +53,14 @@ windowSize: 800px,520px
# *windowExpanding* set to "fullscreen").
windowPlacement: center
### PANELS CONFIGURATION
#
# Calamares has a main content area, and two panels (navigation
# and progress / sidebar). The panels can be controlled individually,
# or switched off. If both panels are switched off, the layout of
# the main content area loses its margins, on the assumption that
# you're doing something special.
# Kind of sidebar (panel on the left, showing progress).
# - "widget" or unset, use traditional sidebar (logo, items)
# - "none", hide it entirely
@ -66,6 +86,12 @@ sidebar: widget
# except the default is *bottom*.
navigation: widget
### STRINGS, IMAGES AND COLORS
#
# This section contains the "branding proper" of names
# and images, rather than global-look settings.
# These are strings shown to the user in the user interface.
# There is no provision for translating them -- since they
# are names, the string is included as-is.
@ -139,9 +165,28 @@ images:
# productWallpaper: "wallpaper.png"
productWelcome: "languages.png"
# Colors for text and background components.
#
# - sidebarBackground is the background of the sidebar
# - sidebarText is the (foreground) text color
# - sidebarTextHighlight sets the background of the selected (current) step.
# Optional, and defaults to the application palette.
# - sidebarSelect is the text color of the selected step.
#
# These colors can **also** be set through the stylesheet, if the
# branding component also ships a stylesheet.qss. Then they are
# the corresponding CSS attributes of #sidebarApp.
style:
sidebarBackground: "#292F34"
sidebarText: "#FFFFFF"
sidebarTextSelect: "#292F34"
sidebarTextHighlight: "#D35400"
### SLIDESHOW
#
# The slideshow is displayed during execution steps (e.g. when the
# installer is actually writing to disk and doing other slow things).
#
# The slideshow can be a QML file (recommended) which can display
# arbitrary things -- text, images, animations, or even play a game --
# during the execution step. The QML **is** abruptly stopped when the
@ -171,19 +216,3 @@ slideshow: "show.qml"
slideshowAPI: 2
# Colors for text and background components.
#
# - sidebarBackground is the background of the sidebar
# - sidebarText is the (foreground) text color
# - sidebarTextHighlight sets the background of the selected (current) step.
# Optional, and defaults to the application palette.
# - sidebarSelect is the text color of the selected step.
#
# These colors can **also** be set through the stylesheet, if the
# branding component also ships a stylesheet.qss. Then they are
# the corresponding CSS attributes of #sidebarApp.
style:
sidebarBackground: "#292F34"
sidebarText: "#FFFFFF"
sidebarTextSelect: "#292F34"
sidebarTextHighlight: "#D35400"

@ -111,12 +111,12 @@ CalamaresWindow::getWidgetSidebar( QWidget* parent, int desiredWidth )
sideLayout->addWidget( debugWindowBtn );
debugWindowBtn->setFlat( true );
debugWindowBtn->setCheckable( true );
connect( debugWindowBtn, &QPushButton::clicked, this, [ = ]( bool checked ) {
connect( debugWindowBtn, &QPushButton::clicked, this, [=]( bool checked ) {
if ( checked )
{
m_debugWindow = new Calamares::DebugWindow();
m_debugWindow->show();
connect( m_debugWindow.data(), &Calamares::DebugWindow::closed, this, [ = ]() {
connect( m_debugWindow.data(), &Calamares::DebugWindow::closed, this, [=]() {
m_debugWindow->deleteLater();
debugWindowBtn->setChecked( false );
} );
@ -167,7 +167,7 @@ CalamaresWindow::getWidgetNavigation( QWidget* parent )
connect( back, &QPushButton::clicked, m_viewManager, &Calamares::ViewManager::back );
connect( m_viewManager, &Calamares::ViewManager::backEnabledChanged, back, &QPushButton::setEnabled );
connect( m_viewManager, &Calamares::ViewManager::backLabelChanged, back, &QPushButton::setText );
connect( m_viewManager, &Calamares::ViewManager::backIconChanged, this, [ = ]( QString n ) {
connect( m_viewManager, &Calamares::ViewManager::backIconChanged, this, [=]( QString n ) {
setButtonIcon( back, n );
} );
bottomLayout->addWidget( back );
@ -179,7 +179,7 @@ CalamaresWindow::getWidgetNavigation( QWidget* parent )
connect( next, &QPushButton::clicked, m_viewManager, &Calamares::ViewManager::next );
connect( m_viewManager, &Calamares::ViewManager::nextEnabledChanged, next, &QPushButton::setEnabled );
connect( m_viewManager, &Calamares::ViewManager::nextLabelChanged, next, &QPushButton::setText );
connect( m_viewManager, &Calamares::ViewManager::nextIconChanged, this, [ = ]( QString n ) {
connect( m_viewManager, &Calamares::ViewManager::nextIconChanged, this, [=]( QString n ) {
setButtonIcon( next, n );
} );
bottomLayout->addWidget( next );
@ -191,7 +191,7 @@ CalamaresWindow::getWidgetNavigation( QWidget* parent )
connect( quit, &QPushButton::clicked, m_viewManager, &Calamares::ViewManager::quit );
connect( m_viewManager, &Calamares::ViewManager::quitEnabledChanged, quit, &QPushButton::setEnabled );
connect( m_viewManager, &Calamares::ViewManager::quitLabelChanged, quit, &QPushButton::setText );
connect( m_viewManager, &Calamares::ViewManager::quitIconChanged, this, [ = ]( QString n ) {
connect( m_viewManager, &Calamares::ViewManager::quitIconChanged, this, [=]( QString n ) {
setButtonIcon( quit, n );
} );
connect( m_viewManager, &Calamares::ViewManager::quitTooltipChanged, quit, &QPushButton::setToolTip );
@ -237,11 +237,13 @@ CalamaresWindow::getQmlNavigation( QWidget* parent )
}
#else
// Bogus to keep the linker happy
QWidget * CalamaresWindow::getQmlSidebar(QWidget* , int )
QWidget*
CalamaresWindow::getQmlSidebar( QWidget*, int )
{
return nullptr;
}
QWidget * CalamaresWindow::getQmlNavigation(QWidget* )
QWidget*
CalamaresWindow::getQmlNavigation( QWidget* )
{
return nullptr;
}
@ -401,6 +403,14 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
insertIf( mainLayout, PanelSide::Right, navigation, branding->navigationSide() );
insertIf( mainLayout, PanelSide::Right, sideBox, branding->sidebarSide() );
// layout->count() returns number of things in it; above we have put
// at **least** the central widget, which comes from the view manager,
// both vertically and horizontally -- so if there's a panel along
// either axis, the count in that axis will be > 1.
m_viewManager->setPanelSides(
( contentsLayout->count() > 1 ? Qt::Orientations( Qt::Horizontal ) : Qt::Orientations() )
| ( mainLayout->count() > 1 ? Qt::Orientations( Qt::Vertical ) : Qt::Orientations() ) );
CalamaresUtils::unmarginLayout( mainLayout );
CalamaresUtils::unmarginLayout( contentsLayout );
baseWidget->setLayout( mainLayout );

@ -67,10 +67,12 @@ ViewManager::ViewManager( QObject* parent )
: QAbstractListModel( parent )
, m_currentStep( -1 )
, m_widget( new QWidget() )
, m_panelSides( Qt::Horizontal | Qt::Vertical )
{
Q_ASSERT( !s_instance );
QBoxLayout* mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins( 0, 0, 0, 0 );
m_widget->setObjectName( "viewManager" );
m_widget->setLayout( mainLayout );
@ -127,15 +129,19 @@ ViewManager::insertViewStep( int before, ViewStep* step )
{
cError() << "ViewStep" << step->moduleInstanceKey() << "has no widget.";
}
QLayout* layout = step->widget()->layout();
if ( layout )
else
{
layout->setContentsMargins( 0, 0, 0, 0 );
QLayout* layout = step->widget()->layout();
if ( layout )
{
const auto margins = step->widgetMargins( m_panelSides );
layout->setContentsMargins( margins.width(), margins.height(), margins.width(), margins.height() );
}
m_stack->insertWidget( before, step->widget() );
m_stack->setCurrentIndex( 0 );
step->widget()->setFocus();
}
m_stack->insertWidget( before, step->widget() );
m_stack->setCurrentIndex( 0 );
step->widget()->setFocus();
emit endInsertRows();
}

@ -54,6 +54,9 @@ class UIDLLEXPORT ViewManager : public QAbstractListModel
Q_PROPERTY( bool quitVisible READ quitVisible NOTIFY quitVisibleChanged FINAL )
///@brief Sides on which the ViewManager has side-panels
Q_PROPERTY( Qt::Orientations panelSides READ panelSides WRITE setPanelSides MEMBER m_panelSides )
public:
/**
* @brief instance access to the ViewManager singleton.
@ -100,13 +103,17 @@ public:
int currentStepIndex() const;
/**
* @ brief Called when "Cancel" is clicked; asks for confirmation.
* @brief Called when "Cancel" is clicked; asks for confirmation.
* Other means of closing Calamares also call this method, e.g. alt-F4.
* At the end of installation, no confirmation is asked. Returns true
* if the user confirms closing the window.
* At the end of installation, no confirmation is asked.
*
* @return @c true if the user confirms closing the window.
*/
bool confirmCancelInstallation();
Qt::Orientations panelSides() const { return m_panelSides; }
void setPanelSides( Qt::Orientations panelSides ) { m_panelSides = panelSides; }
public Q_SLOTS:
/**
* @brief next moves forward to the next page of the current ViewStep (if any),
@ -244,6 +251,8 @@ private:
QString m_quitTooltip;
bool m_quitVisible = true;
Qt::Orientations m_panelSides;
public:
/** @section Model
*

@ -87,6 +87,7 @@ UIDLLEXPORT QPixmap defaultPixmap( ImageType type,
ImageMode mode = CalamaresUtils::Original,
const QSize& size = QSize( 0, 0 ) );
// TODO:3.3:This has only one consumer, move to ImageRegistry, make static
/**
* @brief createRoundedImage returns a rounded version of a pixmap.
* @param avatar the input pixmap.
@ -103,6 +104,7 @@ UIDLLEXPORT QPixmap createRoundedImage( const QPixmap& avatar, const QSize& size
*/
UIDLLEXPORT void unmarginLayout( QLayout* layout );
// TODO:3.3:This has only one consumer, move to LicensePage, make static
/**
* @brief clearLayout recursively walks the QLayout tree and deletes all the child
* widgets and layouts.
@ -113,7 +115,7 @@ UIDLLEXPORT void clearLayout( QLayout* layout );
UIDLLEXPORT void setDefaultFontSize( int points );
UIDLLEXPORT int defaultFontSize(); // in points
UIDLLEXPORT int defaultFontHeight(); // in pixels, DPI-specific
UIDLLEXPORT QFont defaultFont();
UIDLLEXPORT QFont defaultFont(); // TODO:3.3:This has one consumer, move to BlankViewStep
UIDLLEXPORT QFont largeFont();
UIDLLEXPORT QSize defaultIconSize();

@ -151,6 +151,22 @@ QmlViewStep::widget()
return m_widget;
}
QSize
QmlViewStep::widgetMargins( Qt::Orientations panelSides )
{
// If any panels around it, use the standard, but if all the
// panels are hidden, like on full-screen with subsumed navigation,
// then no margins.
if ( panelSides )
{
return ViewStep::widgetMargins( panelSides );
}
else
{
return QSize( 0, 0 );
}
}
void
QmlViewStep::loadComplete()
{

@ -55,6 +55,7 @@ public:
virtual QString prettyName() const override;
virtual QWidget* widget() override;
virtual QSize widgetMargins( Qt::Orientations panelSides ) override;
virtual bool isNextEnabled() const override;
virtual bool isBackEnabled() const override;

@ -19,6 +19,9 @@
#include "ViewStep.h"
#include <QApplication>
#include <QStyle>
namespace Calamares
{
@ -85,4 +88,14 @@ ViewStep::checkRequirements()
return RequirementsList();
}
QSize
ViewStep::widgetMargins( Qt::Orientations panelSides )
{
Q_UNUSED( panelSides );
// Application's default style
const auto* s = QApplication::style();
return QSize( s->pixelMetric( QStyle::PM_LayoutLeftMargin ), s->pixelMetric( QStyle::PM_LayoutTopMargin ) );
}
} // namespace Calamares

@ -52,27 +52,61 @@ public:
explicit ViewStep( QObject* parent = nullptr );
virtual ~ViewStep() override;
/** @brief Human-readable name of the step
*
* This (translated) string is shown in the sidebar (progress)
* and during installation. There is no default.
*/
virtual QString prettyName() const = 0;
/**
/** @brief Describe what this step will do during install
*
* Optional. May return a non-empty string describing what this
* step is going to do (should be translated). This is also used
* in the summary page to describe what is going to be done.
* Return an empty string to provide no description.
*
* The default implementation returns an empty string, so nothing
* will be displayed for this step when a summary is shown.
*/
virtual QString prettyStatus() const;
/**
/** @brief Return a long description what this step will do during install
*
* Optional. May return a widget which will be inserted in the summary
* page. The caller takes ownership of the widget. Return nullptr to
* provide no widget. In general, this is only used for complicated
* steps where prettyStatus() is not sufficient.
*
* The default implementation returns nullptr, so nothing
* will be displayed for this step when a summary is shown.
*/
virtual QWidget* createSummaryWidget() const;
//TODO: we might want to make this a QSharedPointer
/** @brief Get (or create) the widget for this view step
*
* While a view step **may** create the widget when it is loaded,
* it is recommended to wait with widget creation until the
* widget is actually asked for: a view step **may** be used
* without a UI.
*/
virtual QWidget* widget() = 0;
/** @brief Get margins for this widget
*
* This is called by the layout manager to find the desired
* margins (width is used for left and right margin, height is
* used for top and bottom margins) for the widget. The
* @p panelSides indicates where there are panels in the overall
* layout: horizontally and / or vertically adjacent (or none!)
* to the view step's widget.
*
* Should return a size based also on QStyle metrics for layout.
* The default implementation just returns the default layout metrics
* (often 11 pixels on a side).
*/
virtual QSize widgetMargins( Qt::Orientations panelSides );
/**
* @brief Multi-page support, go next
*

Loading…
Cancel
Save