diff --git a/CHANGES b/CHANGES index bab4da677..a541d7380 100644 --- a/CHANGES +++ b/CHANGES @@ -6,12 +6,14 @@ website will have to do for older versions. # 3.2.24 (unreleased) # This release contains contributions from (alphabetically by first name): + - Bill Auger - Gaël PORTAY - Luna Jernberg ## Core ## - There is now a bash-completions script for Calamares; turn on the (CMake-time) option INSTALL_COMPLETION to get it. (Thanks Gaël) + - The *productWallpaper* setting is documented and works. (Thanks Bill) ## Modules ## - No module changes yet diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc index 53884e311..945aaef4c 100644 --- a/src/branding/default/branding.desc +++ b/src/branding/default/branding.desc @@ -118,6 +118,12 @@ strings: # productLogo is used as the logo at the top of the left-hand column # which shows the steps to be taken. The image should be square, # and is displayed at 80x80 pixels (also on HiDPI). +# productWallpaper is an optional image, which if present, will replace +# the normal solid background on every page of the application. +# It can be any size and proportion, +# and will be tiled to fit the entire window. +# For a non-tiled wallpaper, the size should be the same as +# the overall window, see *windowSize* above (800x520). # productWelcome is shown on the welcome page of the application in # the middle of the window, below the welcome text. It can be # any size and proportion, and will be scaled to fit inside @@ -129,6 +135,9 @@ images: # productBanner: "banner.png" productIcon: "squid.png" productLogo: "squid.png" + productIcon: "squid.png" + productLogo: "squid.png" + # productWallpaper: "wallpaper.png" productWelcome: "languages.png" # The slideshow is displayed during execution steps (e.g. when the diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp index 57fffd1bb..7dda0cbd3 100644 --- a/src/calamares/CalamaresWindow.cpp +++ b/src/calamares/CalamaresWindow.cpp @@ -61,11 +61,11 @@ windowDimensionToPixels( const Calamares::Branding::WindowDimension& u ) QWidget* -CalamaresWindow::getWidgetSidebar( int desiredWidth ) +CalamaresWindow::getWidgetSidebar( QWidget* parent, int desiredWidth ) { const Calamares::Branding* const branding = Calamares::Branding::instance(); - QWidget* sideBox = new QWidget( this ); + QWidget* sideBox = new QWidget( parent ); sideBox->setObjectName( "sidebarApp" ); QBoxLayout* sideLayout = new QVBoxLayout; @@ -107,12 +107,12 @@ CalamaresWindow::getWidgetSidebar( 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 ); } ); @@ -132,10 +132,10 @@ CalamaresWindow::getWidgetSidebar( int desiredWidth ) } QWidget* -CalamaresWindow::getQmlSidebar( int ) +CalamaresWindow::getQmlSidebar( QWidget* parent, int ) { CalamaresUtils::registerCalamaresModels(); - QQuickWidget* w = new QQuickWidget( this ); + QQuickWidget* w = new QQuickWidget( parent ); w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); w->setResizeMode( QQuickWidget::SizeRootObjectToView ); w->setSource( QUrl( @@ -161,9 +161,9 @@ setButtonIcon( QPushButton* button, const QString& name ) } QWidget* -CalamaresWindow::getWidgetNavigation() +CalamaresWindow::getWidgetNavigation( QWidget* parent ) { - QWidget* navigation = new QWidget( this ); + QWidget* navigation = new QWidget( parent ); QBoxLayout* bottomLayout = new QHBoxLayout; bottomLayout->addStretch(); @@ -175,7 +175,7 @@ CalamaresWindow::getWidgetNavigation() 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 ); @@ -187,7 +187,7 @@ CalamaresWindow::getWidgetNavigation() 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 ); @@ -199,7 +199,7 @@ CalamaresWindow::getWidgetNavigation() 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 ); @@ -213,10 +213,10 @@ CalamaresWindow::getWidgetNavigation() } QWidget* -CalamaresWindow::getQmlNavigation() +CalamaresWindow::getQmlNavigation( QWidget* parent ) { CalamaresUtils::registerCalamaresModels(); - QQuickWidget* w = new QQuickWidget( this ); + QQuickWidget* w = new QQuickWidget( parent ); w->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); w->setResizeMode( QQuickWidget::SizeRootObjectToView ); w->setSource( QUrl( @@ -234,6 +234,7 @@ template < typename widgetMaker, typename... args > QWidget* flavoredWidget( Calamares::Branding::PanelFlavor flavor, CalamaresWindow* w, + QWidget* parent, widgetMaker widget, widgetMaker qml, args... a ) @@ -242,9 +243,9 @@ flavoredWidget( Calamares::Branding::PanelFlavor flavor, switch ( flavor ) { case Calamares::Branding::PanelFlavor::Widget: - return ( w->*widget )( a... ); + return ( w->*widget )( parent, a... ); case Calamares::Branding::PanelFlavor::Qml: - return ( w->*qml )( a... ); + return ( w->*qml )( parent, a... ); case Calamares::Branding::PanelFlavor::None: return nullptr; } @@ -281,6 +282,7 @@ CalamaresWindow::CalamaresWindow( QWidget* parent ) : tr( "%1 Installer" ).arg( *Calamares::Branding::ProductName ) ); ) const Calamares::Branding* const branding = Calamares::Branding::instance(); + using ImageEntry = Calamares::Branding::ImageEntry; using CalamaresUtils::windowMinimumHeight; using CalamaresUtils::windowMinimumWidth; @@ -307,7 +309,23 @@ CalamaresWindow::CalamaresWindow( QWidget* parent ) cDebug() << Logger::SubEntry << "Proposed window size:" << w << h; resize( w, h ); - m_viewManager = Calamares::ViewManager::instance( this ); + QWidget* baseWidget = this; + if ( !( branding->imagePath( ImageEntry::ProductWallpaper ).isEmpty() ) ) + { + QWidget* label = new QWidget( this ); + QVBoxLayout* l = new QVBoxLayout; + CalamaresUtils::unmarginLayout( l ); + l->addWidget( label ); + setLayout( l ); + label->setObjectName( "backgroundWidget" ); + label->setStyleSheet( + QStringLiteral( "#backgroundWidget { background-image: url(%1); background-repeat: repeat-xy; }" ) + .arg( branding->imagePath( ImageEntry::ProductWallpaper ) ) ); + + baseWidget = label; + } + + m_viewManager = Calamares::ViewManager::instance( baseWidget ); if ( branding->windowExpands() ) { connect( m_viewManager, &Calamares::ViewManager::ensureSize, this, &CalamaresWindow::ensureSize ); @@ -328,11 +346,15 @@ CalamaresWindow::CalamaresWindow( QWidget* parent ) QWidget* sideBox = flavoredWidget( branding->sidebarFlavor(), this, + baseWidget, &CalamaresWindow::getWidgetSidebar, &CalamaresWindow::getQmlSidebar, qBound( 100, CalamaresUtils::defaultFontHeight() * 12, w < windowPreferredWidth ? 100 : 190 ) ); - QWidget* navigation = flavoredWidget( - branding->navigationFlavor(), this, &CalamaresWindow::getWidgetNavigation, &CalamaresWindow::getQmlNavigation ); + QWidget* navigation = flavoredWidget( branding->navigationFlavor(), + this, + baseWidget, + &CalamaresWindow::getWidgetNavigation, + &CalamaresWindow::getQmlNavigation ); // Build up the contentsLayout (a VBox) top-to-bottom // .. note that the bottom is mirrored wrt. the top @@ -351,7 +373,7 @@ CalamaresWindow::CalamaresWindow( QWidget* parent ) CalamaresUtils::unmarginLayout( mainLayout ); CalamaresUtils::unmarginLayout( contentsLayout ); - setLayout( mainLayout ); + baseWidget->setLayout( mainLayout ); setStyleSheet( Calamares::Branding::instance()->stylesheet() ); } diff --git a/src/calamares/CalamaresWindow.h b/src/calamares/CalamaresWindow.h index 1d3162b86..e6c27fd3f 100644 --- a/src/calamares/CalamaresWindow.h +++ b/src/calamares/CalamaresWindow.h @@ -37,7 +37,7 @@ class CalamaresWindow : public QWidget Q_OBJECT public: CalamaresWindow( QWidget* parent = nullptr ); - virtual ~CalamaresWindow() override {} + virtual ~CalamaresWindow() override { } public slots: /** @@ -52,12 +52,12 @@ protected: private: // Two variations on sidebar (the progress view) - QWidget* getWidgetSidebar( int desiredWidth ); - QWidget* getQmlSidebar( int desiredWidth ); + QWidget* getWidgetSidebar( QWidget* parent, int desiredWidth ); + QWidget* getQmlSidebar( QWidget* parent, int desiredWidth ); // Two variations on navigation (buttons at bottom) - QWidget* getWidgetNavigation(); - QWidget* getQmlNavigation(); + QWidget* getWidgetNavigation( QWidget* parent ); + QWidget* getQmlNavigation( QWidget* parent ); QPointer< Calamares::DebugWindow > m_debugWindow; // Managed by self Calamares::ViewManager* m_viewManager; diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index 67054a902..bd2d94c5c 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -193,7 +193,7 @@ Branding::Branding( const QString& brandingFilePath, QObject* parent ) { QStringLiteral( "VARIANT" ), relInfo.variant() }, { QStringLiteral( "VARIANT_ID" ), relInfo.variantId() }, { QStringLiteral( "LOGO" ), relInfo.logo() } } }; - auto expand = [&]( const QString& s ) -> QString { + auto expand = [ & ]( const QString& s ) -> QString { return KMacroExpander::expandMacros( s, relMap, QLatin1Char( '@' ) ); }; #else @@ -203,7 +203,7 @@ Branding::Branding( const QString& brandingFilePath, QObject* parent ) // Massage the strings, images and style sections. loadStrings( m_strings, doc, "strings", expand ); - loadStrings( m_images, doc, "images", [&]( const QString& s ) -> QString { + loadStrings( m_images, doc, "images", [ & ]( const QString& s ) -> QString { // See also image() const QString imageName( expand( s ) ); QFileInfo imageFi( componentDir.absoluteFilePath( imageName ) ); @@ -359,11 +359,10 @@ Branding::image( const QString& imageName, const QSize& size ) const return ImageRegistry::instance()->pixmap( imageFi.absoluteFilePath(), size ); } -QString -Branding::stylesheet() const +static QString +_stylesheet( const QDir& dir ) { - QFileInfo fi( m_descriptorPath ); - QFileInfo importQSSPath( fi.absoluteDir().filePath( "stylesheet.qss" ) ); + QFileInfo importQSSPath( dir.filePath( "stylesheet.qss" ) ); if ( importQSSPath.exists() && importQSSPath.isReadable() ) { QFile stylesheetFile( importQSSPath.filePath() ); @@ -372,11 +371,17 @@ Branding::stylesheet() const } else { - cWarning() << "The branding component" << fi.absoluteDir().absolutePath() << "does not ship stylesheet.qss."; + cWarning() << "The branding component" << dir.absolutePath() << "does not ship stylesheet.qss."; } return QString(); } +QString +Branding::stylesheet() const +{ + return _stylesheet( QFileInfo( m_descriptorPath ).absoluteDir() ); +} + void Branding::setGlobals( GlobalStorage* globalStorage ) const { @@ -538,7 +543,7 @@ Branding::initSimpleSettings( const YAML::Node& doc ) [[noreturn]] void Branding::bail( const QString& message ) { - cError() << "FATAL in" << m_descriptorPath << Logger::Continuation << Logger::NoQuote{} << message; + cError() << "FATAL in" << m_descriptorPath << Logger::Continuation << Logger::NoQuote {} << message; ::exit( EXIT_FAILURE ); } diff --git a/src/libcalamaresui/Branding.h b/src/libcalamaresui/Branding.h index 847f28d89..78c0c54c1 100644 --- a/src/libcalamaresui/Branding.h +++ b/src/libcalamaresui/Branding.h @@ -250,7 +250,8 @@ private: }; template < typename U > -inline QString operator*( U e ) +inline QString +operator*( U e ) { return Branding::instance()->string( e ); } diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 137a7d99e..a4b8d8b8d 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -71,9 +71,11 @@ ViewManager::ViewManager( QObject* parent ) Q_ASSERT( !s_instance ); QBoxLayout* mainLayout = new QVBoxLayout; + m_widget->setObjectName( "viewManager" ); m_widget->setLayout( mainLayout ); m_stack = new QStackedWidget( m_widget ); + m_stack->setObjectName( "viewManagerStack" ); m_stack->setContentsMargins( 0, 0, 0, 0 ); mainLayout->addWidget( m_stack ); @@ -181,7 +183,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail msgBox->show(); cDebug() << "Calamares will quit when the dialog closes."; - connect( msgBox, &QMessageBox::buttonClicked, [msgBox]( QAbstractButton* button ) { + connect( msgBox, &QMessageBox::buttonClicked, [ msgBox ]( QAbstractButton* button ) { if ( msgBox->buttonRole( button ) == QMessageBox::ButtonRole::YesRole ) { // TODO: host and port should be configurable