Merge branch 'master' of https://github.com/calamares/calamares into development

This commit is contained in:
Philip Müller 2019-06-02 09:28:30 +02:00
commit 36ce87e1dc
20 changed files with 201 additions and 87 deletions

View File

@ -36,8 +36,6 @@ and moral support from (alphabetically by first name or nickname):
- Kyle Robertze
- Lisa Vitolo
- n3rdopolis
- Phil Mueller
- Philip Mueller
- Philip Müller
- Ramon Buldó
- Raul Rodrigo Segura

View File

@ -10,6 +10,9 @@ This release contains contributions from (alphabetically by first name):
## Core ##
No user- or deployer-visible changes. Bugfixing as usual, see the
milestone for details.
## Modules ##
- *branding* now supports os-release variables in the *strings* section,
@ -19,6 +22,9 @@ This release contains contributions from (alphabetically by first name):
*productLogo* and *productIcon* keys. If a file is named there, then
the file is used, and otherwise the icon is looked up in the current
theme.
- *welcome* allows a custom image path or icon name to be set for the
language-selection drop-down (instead of the international standard one).
# 3.2.8 (2019-05-10) #

View File

@ -60,6 +60,8 @@ some PEP8 guidelines.
* Function and class definitions have their braces on separate lines.
* A function implementation's return type is on its own line.
* `CamelCase.{cpp,h}` style file names.
* Lambdas are preferrably indented to a 4-space tab, even when passed as an
argument to functions.
Example:
```

View File

@ -125,8 +125,8 @@ LabelModel::find( const QString& countryCode ) const
LabelModel* availableTranslations()
{
static LabelModel model( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';') );
return &model;
static LabelModel* model = new LabelModel( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';') );
return model;
}
}

View File

@ -129,16 +129,16 @@ Branding::Branding( const QString& brandingFilePath,
, m_welcomeExpandingLogo( true )
{
cDebug() << "Using Calamares branding file at" << brandingFilePath;
QDir componentDir( componentDirectory() );
if ( !componentDir.exists() )
bail( "Bad component directory path." );
QFile file( brandingFilePath );
if ( file.exists() && file.open( QFile::ReadOnly | QFile::Text ) )
{
QByteArray ba = file.readAll();
QFileInfo fi ( m_descriptorPath );
QDir componentDir = fi.absoluteDir();
if ( !componentDir.exists() )
bail( "Bad component directory path." );
try
{
YAML::Node doc = YAML::Load( ba.constData() );
@ -146,7 +146,7 @@ Branding::Branding( const QString& brandingFilePath,
m_componentName = QString::fromStdString( doc[ "componentName" ]
.as< std::string >() );
if ( m_componentName != QFileInfo( m_descriptorPath ).absoluteDir().dirName() )
if ( m_componentName != componentDir.dirName() )
bail( "The branding component name should match the name of the "
"component directory." );
@ -186,6 +186,7 @@ Branding::Branding( const QString& brandingFilePath,
loadStrings( m_images, doc, "images",
[&]( const QString& s ) -> QString
{
// See also image()
const QString imageName( expand( s ) );
QFileInfo imageFi( componentDir.absoluteFilePath( imageName ) );
if ( !imageFi.exists() )
@ -314,6 +315,22 @@ Branding::image( Branding::ImageEntry imageEntry, const QSize& size ) const
}
}
QPixmap
Branding::image(const QString& imageName, const QSize& size) const
{
QDir componentDir( componentDirectory() );
QFileInfo imageFi( componentDir.absoluteFilePath( imageName ) );
if ( !imageFi.exists() )
{
const auto icon = QIcon::fromTheme( imageName );
// Not found, bail out with the filename used
if ( icon.isNull() )
return QPixmap();
return icon.pixmap( size );
}
return ImageRegistry::instance()->pixmap( imageFi.absoluteFilePath(), size );
}
QString
Branding::stylesheet() const
{

View File

@ -123,6 +123,16 @@ public:
QString styleString( Branding::StyleEntry styleEntry ) const;
QString imagePath( Branding::ImageEntry imageEntry ) const;
QPixmap image( Branding::ImageEntry imageEntry, const QSize& size ) const;
/** @brief Look up an image in the branding directory or as an icon
*
* The @p name is checked in the branding directory: if it is an image
* file, return the pixmap from that file, at the requested size.
* If it isn't a file, look it up as an icon name in the current theme.
* May return a null pixmap if nothing is found.
*/
QPixmap image( const QString& name, const QSize& size ) const;
/** @brief Stylesheet to apply for this branding. May be empty.
*
* The file is loaded every time this function is called, so

View File

@ -23,9 +23,13 @@
#include "core/PartitionInfo.h"
#include "core/KPMHelpers.h"
#include "utils/Logger.h"
// KPMcore
#include <kpmcore/core/device.h>
#include <QComboBox>
static QStandardItem*
createBootLoaderItem( const QString& description, const QString& path, bool isPartition )
{
@ -47,12 +51,12 @@ BootLoaderModel::~BootLoaderModel()
void
BootLoaderModel::init( const QList< Device* >& devices )
{
cDebug() << "BLM::init with" << devices.count() << "devices" << rowCount() << "rows";
beginResetModel();
blockSignals( true );
m_devices = devices;
clear();
createMbrItems();
updateInternal();
blockSignals( false );
endResetModel();
@ -74,6 +78,7 @@ BootLoaderModel::createMbrItems()
void
BootLoaderModel::update()
{
cDebug() << "BLM::update holds" << m_devices.count() << "devices" << rowCount() << "rows";
beginResetModel();
blockSignals( true );
updateInternal();
@ -89,6 +94,10 @@ BootLoaderModel::updateInternal()
clear();
createMbrItems();
// An empty model is possible if you don't havee permissions: don't crash though.
if ( rowCount() < 1 )
return;
QString partitionText;
Partition* partition = KPMHelpers::findPartitionByMountPoint( m_devices, "/boot" );
if ( partition )
@ -148,3 +157,48 @@ BootLoaderModel::data( const QModelIndex& index, int role ) const
}
return QStandardItemModel::data( index, role );
}
namespace Calamares
{
int
findBootloader( const QAbstractItemModel* model, const QString& path )
{
for ( int i = 0; i < model->rowCount(); ++i)
{
const auto index = model->index( i, 0, QModelIndex() );
if ( !index.isValid() )
continue;
QVariant var = model->data( index, BootLoaderModel::BootLoaderPathRole );
if ( var.isValid() && var.toString() == path )
return i;
}
return -1;
}
void
restoreSelectedBootLoader( QComboBox& combo, const QString& path )
{
const auto* model = combo.model();
if ( model->rowCount() < 1 )
{
cDebug() << "No items in BootLoaderModel";
return;
}
int r = -1;
if ( path.isEmpty() )
{
combo.setCurrentIndex( 0 );
}
else if ( (r = findBootloader( model, path )) >= 0 )
{
combo.setCurrentIndex( r );
}
else
{
combo.setCurrentIndex( 0 );
}
}
} // namespace

View File

@ -25,6 +25,7 @@
#include <QStandardItemModel>
class Device;
class QComboBox;
/**
* This model contains one entry for each device MBR plus one entry for the
@ -63,4 +64,20 @@ private:
void updateInternal();
};
namespace Calamares
{
/** @brief Returns the row number of boot-loader @p path (e.g. /dev/sda)
*
* Assuming the @p model is a BootLoaderModel, will return a row number
* in the model. Returns -1 otherwise.
*/
int findBootloader( const QAbstractItemModel* model, const QString& path );
/** @brief Tries to set @p path as selected item in @p combo
*
* Matches a boot-loader install path (e.g. /dev/sda) with a model
* row and sets that as the current row.
*/
void restoreSelectedBootLoader( QComboBox& combo, const QString& path );
} // namespace
#endif /* BOOTLOADERMODEL_H */

View File

@ -22,6 +22,8 @@
#include "core/KPMHelpers.h"
#include "core/PartitionIterator.h"
#include "utils/Logger.h"
// KPMcore
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/luks.h>
@ -81,6 +83,12 @@ _findRootForPartition( PartitionNode* partition )
QColor
colorForPartition( Partition* partition )
{
if ( !partition )
{
cWarning() << "NULL partition";
return FREE_SPACE_COLOR;
}
if ( KPMHelpers::isPartitionFreeSpace( partition ) )
return FREE_SPACE_COLOR;
if ( partition->roles().has( PartitionRole::Extended ) )

View File

@ -402,7 +402,7 @@ PartitionCoreModule::deletePartition( Device* device, Partition* partition )
deletePartition( device, childPartition );
}
QList< Calamares::job_ptr >& jobs = deviceInfo->jobs;
Calamares::JobList& jobs = deviceInfo->jobs;
if ( partition->state() == KPM_PARTITION_STATE(New) )
{
// First remove matching SetPartFlagsJobs
@ -496,10 +496,10 @@ PartitionCoreModule::setPartitionFlags( Device* device,
PartitionInfo::setFlags( partition, flags );
}
QList< Calamares::job_ptr >
Calamares::JobList
PartitionCoreModule::jobs() const
{
QList< Calamares::job_ptr > lst;
Calamares::JobList lst;
QList< Device* > devices;
#ifdef DEBUG_PARTITION_UNSAFE
@ -947,12 +947,7 @@ PartitionCoreModule::revertDevice( Device* dev, bool individualRevert )
QList< Device* > devices;
for ( DeviceInfo* const info : m_deviceInfos )
{
// device is a QScopedPointer
if ( !info || info->device.isNull() )
continue;
if ( info->device->type() != Device::Type::Disk_Device )
continue;
else
if ( info && !info->device.isNull() && info->device->type() == Device::Type::Disk_Device )
devices.append( info->device.data() );
}

View File

@ -247,7 +247,7 @@ private:
QScopedPointer< Device > device;
QScopedPointer< PartitionModel > partitionModel;
const QScopedPointer< Device > immutableDevice;
QList< Calamares::job_ptr > jobs;
Calamares::JobList jobs;
// To check if LVM VGs are deactivated
bool isAvailable;

View File

@ -960,19 +960,18 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
QLabel* sizeLabel = new QLabel( m_previewAfterFrame );
layout->addWidget( sizeLabel );
sizeLabel->setWordWrap( true );
connect( m_afterPartitionSplitterWidget, &PartitionSplitterWidget::partitionResized,
this, [ this, sizeLabel ]( const QString& path,
qint64 size,
qint64 sizeNext )
{
Q_UNUSED( path )
sizeLabel->setText( tr( "%1 will be shrunk to %2MiB and a new "
"%3MiB partition will be created for %4." )
.arg( m_beforePartitionBarsView->selectionModel()->currentIndex().data().toString() )
.arg( CalamaresUtils::BytesToMiB( size ) )
.arg( CalamaresUtils::BytesToMiB( sizeNext ) )
.arg( *Calamares::Branding::ShortProductName ) );
} );
connect( m_afterPartitionSplitterWidget, &PartitionSplitterWidget::partitionResized, this,
[ this, sizeLabel ]( const QString& path, qint64 size, qint64 sizeNext )
{
Q_UNUSED( path )
sizeLabel->setText( tr( "%1 will be shrunk to %2MiB and a new "
"%3MiB partition will be created for %4." )
.arg( m_beforePartitionBarsView->selectionModel()->currentIndex().data().toString() )
.arg( CalamaresUtils::BytesToMiB( size ) )
.arg( CalamaresUtils::BytesToMiB( sizeNext ) )
.arg( *Calamares::Branding::ShortProductName ) );
}
);
m_previewAfterFrame->show();
m_previewAfterLabel->show();
@ -1025,18 +1024,25 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
eraseBootloaderLabel->setText( tr( "Boot loader location:" ) );
m_bootloaderComboBox = createBootloaderComboBox( eraseWidget );
connect( m_core, &PartitionCoreModule::deviceReverted,
this, [ this ]( Device* dev )
{
Q_UNUSED( dev )
if ( !m_bootloaderComboBox.isNull() )
connect( m_core->bootLoaderModel(), &QAbstractItemModel::modelReset,
[ this ]()
{
if ( m_bootloaderComboBox->model() != m_core->bootLoaderModel() )
m_bootloaderComboBox->setModel( m_core->bootLoaderModel() );
m_bootloaderComboBox->setCurrentIndex( m_lastSelectedDeviceIndex );
if ( !m_bootloaderComboBox.isNull() )
Calamares::restoreSelectedBootLoader( *m_bootloaderComboBox, m_core->bootLoaderInstallPath() );
}
}, Qt::QueuedConnection );
);
connect( m_core, &PartitionCoreModule::deviceReverted, this,
[ this ]( Device* dev )
{
Q_UNUSED( dev )
if ( !m_bootloaderComboBox.isNull() )
{
if ( m_bootloaderComboBox->model() != m_core->bootLoaderModel() )
m_bootloaderComboBox->setModel( m_core->bootLoaderModel() );
m_bootloaderComboBox->setCurrentIndex( m_lastSelectedDeviceIndex );
}
}, Qt::QueuedConnection );
// ^ Must be Queued so it's sure to run when the widget is already visible.
eraseLayout->addWidget( m_bootloaderComboBox );

View File

@ -219,7 +219,7 @@ PartitionPage::onNewPartitionTableClicked()
m_core->createPartitionTable( device, type );
}
delete dlg;
// PartionModelReset isn't emmited after createPartitionTable, so we have to manually update
// PartionModelReset isn't emitted after createPartitionTable, so we have to manually update
// the bootLoader index after the reset.
updateBootLoaderIndex();
}
@ -511,45 +511,10 @@ PartitionPage::updateSelectedBootLoaderIndex()
cDebug() << "Selected bootloader index" << m_lastSelectedBootLoaderIndex;
}
int
findBootloader( const QAbstractItemModel* model, const QString& path )
{
for ( int i = 0; i < model->rowCount(); ++i)
{
const auto index = model->index( i, 0, QModelIndex() );
if ( !index.isValid() )
continue;
QVariant var = model->data( index, BootLoaderModel::BootLoaderPathRole );
if ( var.isValid() && var.toString() == path )
return i;
}
return -1;
}
void
PartitionPage::restoreSelectedBootLoader()
{
const auto* model = m_ui->bootLoaderComboBox->model();
if ( model->rowCount() < 1 )
{
cDebug() << "No items in BootLoaderModel";
return;
}
int r = -1;
if ( m_core->bootLoaderInstallPath().isEmpty() )
{
m_ui->bootLoaderComboBox->setCurrentIndex( 0 );
}
else if ( (r = findBootloader( model, m_core->bootLoaderInstallPath() )) >= 0 )
{
m_ui->bootLoaderComboBox->setCurrentIndex( r );
}
else
{
m_ui->bootLoaderComboBox->setCurrentIndex( 0 );
}
Calamares::restoreSelectedBootLoader( *(m_ui->bootLoaderComboBox), m_core->bootLoaderInstallPath() );
}

View File

@ -619,7 +619,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
}
QList< Calamares::job_ptr >
Calamares::JobList
PartitionViewStep::jobs() const
{
return m_core->jobs();
@ -638,7 +638,11 @@ PartitionViewStep::checkRequirements()
[]{ return tr( "has at least one disk device available." ); },
[]{ return tr( "There are no partitons to install on." ); },
m_core->deviceModel()->rowCount() > 0, // satisfied
true // required
#ifdef DEBUG_PARTITION_UNSAFE
false // optional
#else
true // required
#endif
} );
return l;

View File

@ -69,7 +69,7 @@ public:
void setConfigurationMap( const QVariantMap& configurationMap ) override;
QList< Calamares::job_ptr > jobs() const override;
Calamares::JobList jobs() const override;
Calamares::RequirementsList checkRequirements() override;

View File

@ -270,6 +270,12 @@ WelcomePage::externallySelectedLanguage( int row )
ui->languageWidget->setCurrentIndex( row );
}
void
WelcomePage::setLanguageIcon( QPixmap i )
{
ui->languageIcon->setPixmap( i );
}
void
LocaleTwoColumnDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const

View File

@ -42,6 +42,8 @@ public:
void setUpLinks( bool showSupportUrl,
bool showKnownIssuesUrl,
bool showReleaseNotesUrl );
/// @brief Set international language-selector icon
void setLanguageIcon( QPixmap );
/// @brief Results of requirements checking
bool verdict() const;

View File

@ -67,7 +67,7 @@
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="languageIcon">
<property name="toolTip">
<string>Select language</string>
</property>

View File

@ -24,10 +24,12 @@
#include "geoip/Handler.h"
#include "locale/Lookup.h"
#include "modulesystem/ModuleManager.h"
#include "utils/Logger.h"
#include "utils/Variant.h"
#include "Branding.h"
#include "modulesystem/ModuleManager.h"
#include <QFutureWatcher>
#include <QVariant>
@ -137,6 +139,15 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap )
} );
future->setFuture( handler->queryRaw() );
}
QString language = CalamaresUtils::getString( configurationMap, "languageIcon" );
if ( !language.isEmpty() )
{
auto icon = Calamares::Branding::instance()->image( language, QSize( 48, 48 ) );
if ( !icon.isNull() )
m_widget->setLanguageIcon( icon );
}
}
Calamares::RequirementsList

View File

@ -64,3 +64,16 @@ geoip:
style: "none"
url: "https://geoip.kde.org/v1/ubiquity" # extended XML format
selector: "CountryCode" # blank uses default, which is wrong
# User interface
#
# The "select language" icon is an international standard, but it
# might not theme very well with your desktop environment.
# Fill in an icon name (following FreeDesktop standards) to
# use that named icon instead of the usual one.
#
# Leave blank or unset to use the international standard.
#
# Known icons in this space are "set-language" and "config-language".
#
# languageIcon: set-language