diff --git a/CHANGES b/CHANGES index db141384d..03d630654 100644 --- a/CHANGES +++ b/CHANGES @@ -10,9 +10,13 @@ have been shuffled around, so third-party C++ modules will need adjustment to the changed names. This release contains contributions from (alphabetically by first name): + - Kevin Kofler ## Core ## + - The side-pane, which shows the list of steps that will be executed, + now tries to fit the text (name of each module) into the available space + by shrinking the font as needed. #1137 - *libcalamares* (accidentally) linked with Qt's GUI libraries when PythonQt was found. This led to the odd situation where the non-GUI Calamares library depends on a bunch of GUI libraries. @@ -24,9 +28,12 @@ This release contains contributions from (alphabetically by first name): ## Modules ## + - *finished* has a new mechanism for configuring the behavior of the + *restart now* button. The old-style boolean configuration is still + supported but generates a warning. #1138 - *oemid* is a new module for configuring OEM phase-0 (image pre-mastering, or pre-deployment) things. It has limited functionality at the moment, - writing only a single batch-identifier file. + writing only a single batch-identifier file. #943 - All Python modules now bail out gracefully on (at least some) bad configurations, rather than raising an exception. The pre-release scripts now test for exceptions to avoid shipping modules with diff --git a/CMakeModules/BoostPython3.cmake b/CMakeModules/BoostPython3.cmake index c128b58f1..70fb0aa49 100644 --- a/CMakeModules/BoostPython3.cmake +++ b/CMakeModules/BoostPython3.cmake @@ -15,6 +15,11 @@ # libboost_python-3.4.so # depending on what python's targets you selected during install # +# On Fedora >= 30 instead, the boost-python3-devel provides boost library with a +# name like: +# libboost_python37.so +# depending on what python's targets you selected during install +# # find_boost_python3() tries to find the package with different component # names. By default it tries "python3", "python-py$suffix" and # "python-$dotsuffix", where suffix is based on the `python_version` argument. @@ -46,6 +51,10 @@ macro( find_boost_python3 boost_version python_version found_var ) string( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\..*" "\\1\\2" _fbp_python_short_version ${python_version} ) _find_boost_python3_int( ${boost_version} python-py${_fbp_python_short_version} _fbp_found ) + if (NOT _fbp_found) + _find_boost_python3_int( ${boost_version} python${_fbp_python_short_version} _fbp_found ) + endif() + if (NOT _fbp_found) # The following loop changes the searched name for Gentoo based distributions # turns "3.4.123abc" into "3.4" diff --git a/data/config-appimage/modules/finished.conf b/data/config-appimage/modules/finished.conf index 29e5e49b4..48bbdc031 100644 --- a/data/config-appimage/modules/finished.conf +++ b/data/config-appimage/modules/finished.conf @@ -1,14 +1,24 @@ # Configuration for the "finished" page, which is usually shown only at # the end of the installation (successful or not). --- -# The finished page can hold a "restart system now" checkbox. -# If this is false, no checkbox is shown and the system is not restarted -# when Calamares exits. -restartNowEnabled: true - -# Initial state of the checkbox "restart now". Only relevant when the -# checkbox is shown by restartNowEnabled. -restartNowChecked: false +# Behavior of the "restart system now" button. +# +# There are four usable values: +# - never +# Does not show the button and does not restart. +# This matches the old behavior with restartNowEnabled=false. +# - user-unchecked +# Shows the button, defaults to unchecked, restarts if it is checked. +# This matches the old behavior with restartNowEnabled=true and restartNowChecked=false. +# - user-checked +# Shows the button, defaults to checked, restarts if it is checked. +# This matches the old behavior with restartNowEnabled=true and restartNowChecked=true. +# - always +# Shows the button, checked, but the user cannot change it. +# This is new behavior. +# +# The three combinations of legacy values are still supported. +restartNowMode: user-unchecked # If the checkbox is shown, and the checkbox is checked, then when # Calamares exits from the finished-page it will run this command. diff --git a/src/calamares/CalamaresApplication.h b/src/calamares/CalamaresApplication.h index f9c919aa6..71778813e 100644 --- a/src/calamares/CalamaresApplication.h +++ b/src/calamares/CalamaresApplication.h @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2018, Adriaan de Groot + * Copyright 2018-2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +24,6 @@ #include -#define APP CalamaresApplication::instance() - class CalamaresWindow; namespace Calamares diff --git a/src/calamares/progresstree/ProgressTreeDelegate.cpp b/src/calamares/progresstree/ProgressTreeDelegate.cpp index 9c6a400f6..67dfeebda 100644 --- a/src/calamares/progresstree/ProgressTreeDelegate.cpp +++ b/src/calamares/progresstree/ProgressTreeDelegate.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,28 +18,18 @@ */ #include "ProgressTreeDelegate.h" +#include "ProgressTreeModel.h" #include "Branding.h" #include "CalamaresApplication.h" #include "CalamaresWindow.h" -#include "ProgressTreeModel.h" -#include "ViewManager.h" -#include "ViewStepItem.h" #include "utils/CalamaresUtilsGui.h" -#include #include -#define ITEM_MARGIN 12 -#define VS_FONTSIZE CalamaresUtils::defaultFontSize() + 4 - -ProgressTreeDelegate::ProgressTreeDelegate( QAbstractItemView* parent ) - : QStyledItemDelegate( parent ) - , m_parent( parent ) -{ -} - +static constexpr int const item_margin = 8; +static inline int item_fontsize() { return CalamaresUtils::defaultFontSize() + 4; } QSize ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, @@ -50,11 +40,11 @@ ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, QFont font = qApp->font(); - font.setPointSize( VS_FONTSIZE ); + font.setPointSize( item_fontsize() ); QFontMetrics fm( font ); int height = fm.height(); - height += 2*ITEM_MARGIN; //margin + height += 2 * item_margin; return QSize( option.rect.width(), height ); } @@ -88,12 +78,9 @@ ProgressTreeDelegate::paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { - QRect textRect = option.rect.adjusted( ITEM_MARGIN, - ITEM_MARGIN, - ITEM_MARGIN, - ITEM_MARGIN ); + QRect textRect = option.rect.adjusted( item_margin, item_margin, -item_margin, -item_margin ); QFont font = qApp->font(); - font.setPointSize( VS_FONTSIZE ); + font.setPointSize( item_fontsize() ); font.setBold( false ); painter->setFont( font ); @@ -107,11 +94,37 @@ ProgressTreeDelegate::paintViewStep( QPainter* painter, QString textHighlight = Calamares::Branding::instance()-> styleString( Calamares::Branding::SidebarTextHighlight ); if ( textHighlight.isEmpty() ) - painter->setBrush( APP->mainWindow()->palette().background() ); + painter->setBrush( CalamaresApplication::instance()->mainWindow()->palette().background() ); else painter->setBrush( QColor( textHighlight ) ); } - painter->fillRect( option.rect, painter->brush().color() ); - painter->drawText( textRect, index.data().toString() ); + + // Draw the text at least once. If it doesn't fit, then shrink the font + // being used by 1 pt on each iteration, up to a maximum of maximumShrink + // times. On each loop, we'll have to blank out the rectangle again, so this + // is an expensive (in terms of drawing operations) thing to do. + // + // (The loop uses <= because the counter is incremented at the start). + static constexpr int const maximumShrink = 4; + int shrinkSteps = 0; + do + { + painter->fillRect( option.rect, painter->brush().color() ); + shrinkSteps++; + + QRectF boundingBox; + painter->drawText( textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, index.data().toString(), &boundingBox ); + + // The extra check here is to avoid the changing-font-size if we're not going to use + // it in the next iteration of the loop anyway. + if ( ( shrinkSteps <= maximumShrink ) && (boundingBox.width() > textRect.width() ) ) + { + font.setPointSize( item_fontsize() - shrinkSteps ); + painter->setFont( font ); + } + else + break; // It fits + } + while ( shrinkSteps <= maximumShrink ); } diff --git a/src/calamares/progresstree/ProgressTreeDelegate.h b/src/calamares/progresstree/ProgressTreeDelegate.h index 371f5193f..83b281696 100644 --- a/src/calamares/progresstree/ProgressTreeDelegate.h +++ b/src/calamares/progresstree/ProgressTreeDelegate.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +22,6 @@ #include - /** * @brief The ProgressTreeDelegate class customizes the look and feel of the * ProgressTreeView elements. @@ -29,9 +29,8 @@ */ class ProgressTreeDelegate : public QStyledItemDelegate { - Q_OBJECT public: - explicit ProgressTreeDelegate( QAbstractItemView* parent = nullptr ); + using QStyledItemDelegate::QStyledItemDelegate; protected: QSize sizeHint( const QStyleOptionViewItem& option, @@ -44,8 +43,6 @@ private: void paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const; - - QAbstractItemView* m_parent; }; #endif // PROGRESSTREEDELEGATE_H diff --git a/src/modules/finished/FinishedPage.cpp b/src/modules/finished/FinishedPage.cpp index 1bc935d0d..c49bb9538 100644 --- a/src/modules/finished/FinishedPage.cpp +++ b/src/modules/finished/FinishedPage.cpp @@ -79,16 +79,13 @@ FinishedPage::FinishedPage( QWidget* parent ) void -FinishedPage::setRestartNowEnabled( bool enabled ) +FinishedPage::setRestart( FinishedViewStep::RestartMode mode ) { - ui->restartCheckBox->setVisible( enabled ); -} + using Mode = FinishedViewStep::RestartMode; - -void -FinishedPage::setRestartNowChecked( bool checked ) -{ - ui->restartCheckBox->setChecked( checked ); + ui->restartCheckBox->setVisible( mode != Mode::Never ); + ui->restartCheckBox->setEnabled( mode != Mode::Always ); + ui->restartCheckBox->setChecked( ( mode == Mode::Always ) || ( mode == Mode::UserChecked ) ); } @@ -138,5 +135,5 @@ FinishedPage::onInstallationFailed( const QString& message, const QString& detai "The error message was: %2." ) .arg( *Calamares::Branding::VersionedName ) .arg( message ) ); - setRestartNowEnabled( false ); + setRestart( FinishedViewStep::RestartMode::Never ); } diff --git a/src/modules/finished/FinishedPage.h b/src/modules/finished/FinishedPage.h index 493c29f34..9954e6fa0 100644 --- a/src/modules/finished/FinishedPage.h +++ b/src/modules/finished/FinishedPage.h @@ -22,6 +22,8 @@ #include +#include "FinishedViewStep.h" + namespace Ui { class FinishedPage; @@ -33,8 +35,7 @@ class FinishedPage : public QWidget public: explicit FinishedPage( QWidget* parent = nullptr ); - void setRestartNowEnabled( bool enabled ); - void setRestartNowChecked( bool checked ); + void setRestart( FinishedViewStep::RestartMode mode ); void setRestartNowCommand( const QString& command ); void setUpRestart(); diff --git a/src/modules/finished/FinishedViewStep.cpp b/src/modules/finished/FinishedViewStep.cpp index d01a99ce9..d5c3c3f69 100644 --- a/src/modules/finished/FinishedViewStep.cpp +++ b/src/modules/finished/FinishedViewStep.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019, Adriaan de Groot * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify @@ -20,17 +20,34 @@ #include "FinishedViewStep.h" #include "FinishedPage.h" + +#include "Branding.h" #include "JobQueue.h" +#include "Settings.h" #include "utils/Logger.h" +#include "utils/NamedEnum.h" +#include "utils/Variant.h" #include #include #include #include -#include "Branding.h" -#include "Settings.h" +static const NamedEnumTable< FinishedViewStep::RestartMode >& +modeNames() +{ + using Mode = FinishedViewStep::RestartMode; + + static const NamedEnumTable< Mode > names{ + { QStringLiteral( "never" ), Mode::Never }, + { QStringLiteral( "user-unchecked" ), Mode::UserUnchecked }, + { QStringLiteral( "user-checked" ), Mode::UserChecked }, + { QStringLiteral( "always" ), Mode::Always } + } ; + + return names; +} FinishedViewStep::FinishedViewStep( QObject* parent ) : Calamares::ViewStep( parent ) @@ -122,10 +139,10 @@ FinishedViewStep::sendNotification() QVariant( 0 ) ); if ( !r.isValid() ) - cDebug() << "Could not call notify for end of installation." << r.error(); + cWarning() << "Could not call org.freedesktop.Notifications.Notify at end of installation." << r.error(); } else - cDebug() << "Could not get dbus interface for notifications." << notify.lastError(); + cWarning() << "Could not get dbus interface for notifications at end of installation." << notify.lastError(); } @@ -156,28 +173,41 @@ FinishedViewStep::onInstallationFailed( const QString& message, const QString& d void FinishedViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - if ( configurationMap.contains( "restartNowEnabled" ) && - configurationMap.value( "restartNowEnabled" ).type() == QVariant::Bool ) + RestartMode mode = RestartMode::Never; + + QString restartMode = CalamaresUtils::getString( configurationMap, "restartNowMode" ); + if ( restartMode.isEmpty() ) { - bool restartNowEnabled = configurationMap.value( "restartNowEnabled" ).toBool(); + if ( configurationMap.contains( "restartNowEnabled" ) ) + cWarning() << "Configuring the finished module with deprecated restartNowEnabled settings"; - m_widget->setRestartNowEnabled( restartNowEnabled ); - if ( restartNowEnabled ) - { - if ( configurationMap.contains( "restartNowChecked" ) && - configurationMap.value( "restartNowChecked" ).type() == QVariant::Bool ) - m_widget->setRestartNowChecked( configurationMap.value( "restartNowChecked" ).toBool() ); + bool restartNowEnabled = CalamaresUtils::getBool( configurationMap, "restartNowEnabled", false ); + bool restartNowChecked = CalamaresUtils::getBool( configurationMap, "restartNowChecked", false ); - if ( configurationMap.contains( "restartNowCommand" ) && - configurationMap.value( "restartNowCommand" ).type() == QVariant::String ) - m_widget->setRestartNowCommand( configurationMap.value( "restartNowCommand" ).toString() ); - else - m_widget->setRestartNowCommand( "shutdown -r now" ); - } + if ( !restartNowEnabled ) + mode = RestartMode::Never; + else + mode = restartNowChecked ? RestartMode::UserChecked : RestartMode::UserUnchecked; } - if ( configurationMap.contains( "notifyOnFinished" ) && - configurationMap.value( "notifyOnFinished" ).type() == QVariant::Bool ) - m_notifyOnFinished = configurationMap.value( "notifyOnFinished" ).toBool(); + else + { + bool ok = false; + mode = modeNames().find( restartMode, ok ); + if ( !ok ) + cWarning() << "Configuring the finished module with bad restartNowMode" << restartMode; + } + + m_widget->setRestart( mode ); + + if ( mode != RestartMode::Never ) + { + QString restartNowCommand = CalamaresUtils::getString( configurationMap, "restartNowCommand" ); + if ( restartNowCommand.isEmpty() ) + restartNowCommand = QStringLiteral( "shutdown -r now" ); + m_widget->setRestartNowCommand( restartNowCommand ); + } + + m_notifyOnFinished = CalamaresUtils::getBool( configurationMap, "notifyOnFinished", false ); } CALAMARES_PLUGIN_FACTORY_DEFINITION( FinishedViewStepFactory, registerPlugin(); ) diff --git a/src/modules/finished/FinishedViewStep.h b/src/modules/finished/FinishedViewStep.h index b1af598c7..314f6acc6 100644 --- a/src/modules/finished/FinishedViewStep.h +++ b/src/modules/finished/FinishedViewStep.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,15 +17,15 @@ * along with Calamares. If not, see . */ -#ifndef FINISHEDPAGEPLUGIN_H -#define FINISHEDPAGEPLUGIN_H +#ifndef FINISHEDVIEWSTEP_H +#define FINISHEDVIEWSTEP_H #include -#include -#include +#include "utils/PluginFactory.h" +#include "viewpages/ViewStep.h" -#include +#include "PluginDllMacro.h" class FinishedPage; @@ -33,6 +34,14 @@ class PLUGINDLLEXPORT FinishedViewStep : public Calamares::ViewStep Q_OBJECT public: + enum class RestartMode + { + Never=0, ///< @brief Don't show button, just exit + UserUnchecked, ///< @brief Show button, starts unchecked + UserChecked, ///< @brief Show button, starts checked + Always ///< @brief Show button, can't change, checked + }; + explicit FinishedViewStep( QObject* parent = nullptr ); virtual ~FinishedViewStep() override; @@ -70,4 +79,4 @@ private: CALAMARES_PLUGIN_FACTORY_DECLARATION( FinishedViewStepFactory ) -#endif // FINISHEDPAGEPLUGIN_H +#endif diff --git a/src/modules/finished/finished.conf b/src/modules/finished/finished.conf index 29e5e49b4..3b6dd9dd1 100644 --- a/src/modules/finished/finished.conf +++ b/src/modules/finished/finished.conf @@ -1,14 +1,37 @@ # Configuration for the "finished" page, which is usually shown only at # the end of the installation (successful or not). --- +# DEPRECATED +# # The finished page can hold a "restart system now" checkbox. # If this is false, no checkbox is shown and the system is not restarted # when Calamares exits. -restartNowEnabled: true +# restartNowEnabled: true +# DEPRECATED +# # Initial state of the checkbox "restart now". Only relevant when the # checkbox is shown by restartNowEnabled. -restartNowChecked: false +# restartNowChecked: false + +# Behavior of the "restart system now" button. +# +# There are four usable values: +# - never +# Does not show the button and does not restart. +# This matches the old behavior with restartNowEnabled=false. +# - user-unchecked +# Shows the button, defaults to unchecked, restarts if it is checked. +# This matches the old behavior with restartNowEnabled=true and restartNowChecked=false. +# - user-checked +# Shows the button, defaults to checked, restarts if it is checked. +# This matches the old behavior with restartNowEnabled=true and restartNowChecked=true. +# - always +# Shows the button, checked, but the user cannot change it. +# This is new behavior. +# +# The three combinations of legacy values are still supported. +restartNowMode: user-unchecked # If the checkbox is shown, and the checkbox is checked, then when # Calamares exits from the finished-page it will run this command. diff --git a/src/modules/partition/jobs/ClearMountsJob.cpp b/src/modules/partition/jobs/ClearMountsJob.cpp index da6bee325..605087147 100644 --- a/src/modules/partition/jobs/ClearMountsJob.cpp +++ b/src/modules/partition/jobs/ClearMountsJob.cpp @@ -2,6 +2,7 @@ * * Copyright 2014-2015, Teo Mrnjavac * Copyright 2018, Adriaan de Groot + * Copyright 2019, Kevin Kofler * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -258,7 +259,11 @@ ClearMountsJob::getCryptoDevices() const QProcess process; for ( const QFileInfo &fi : fiList ) { - if ( fi.baseName() == "control" ) + QString baseName = fi.baseName(); + // Fedora live images use /dev/mapper/live-* internally. We must not + // unmount those devices, because they are used by the live image and + // because we need /dev/mapper/live-base in the unpackfs module. + if ( baseName == "control" || baseName.startsWith( "live-" ) ) continue; list.append( fi.absoluteFilePath() ); } diff --git a/src/modules/umount/umount.conf b/src/modules/umount/umount.conf index 798dfc3f5..22a2e7441 100644 --- a/src/modules/umount/umount.conf +++ b/src/modules/umount/umount.conf @@ -10,7 +10,7 @@ # destLog location in the target system to copy the log # # You can either use the default source path (which is -# `/root/.cache/Calamares/Calamares/Calamares.log` ) to copy the regular log, +# `/root/.cache/calamares/session.log` ) to copy the regular log, # or if you want to use the full output of `sudo calamares -d` you will need # to redirect standard output, for instance in a launcher script or # in the desktop file. @@ -34,7 +34,7 @@ --- # example when using the normal Calamares log: -srcLog: "/root/.cache/Calamares/Calamares/Calamares.log" +srcLog: "/root/.cache/calamares/session.log" destLog: "/var/log/Calamares.log" # example when using a log created by `sudo calamares -d`: diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py index dd9439a2c..ac90a994e 100644 --- a/src/modules/unpackfs/main.py +++ b/src/modules/unpackfs/main.py @@ -7,6 +7,7 @@ # Copyright 2014, Daniel Hillenbrand # Copyright 2014, Philip Müller # Copyright 2017, Alf Gaida +# Copyright 2019, Kevin Kofler # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -252,13 +253,19 @@ class UnpackOperation: subprocess.check_call(["mount", "--bind", entry.source, imgmountdir]) - else: + elif os.path.isfile(entry.source): subprocess.check_call(["mount", entry.source, imgmountdir, "-t", entry.sourcefs, "-o", "loop" ]) + else: # entry.source is a device + subprocess.check_call(["mount", + entry.source, + imgmountdir, + "-t", entry.sourcefs + ]) def unpack_image(self, entry, imgmountdir): """