From 8d9f75ffba9566f6aa04cb7844902141fd125e94 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Jun 2017 10:15:13 -0400 Subject: [PATCH 01/19] Keyboard: refactor type declaration --- src/modules/keyboard/KeyboardLayoutModel.cpp | 5 +++-- src/modules/keyboard/keyboardwidget/keyboardglobal.h | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/modules/keyboard/KeyboardLayoutModel.cpp b/src/modules/keyboard/KeyboardLayoutModel.cpp index 9f045043e..63989819c 100644 --- a/src/modules/keyboard/KeyboardLayoutModel.cpp +++ b/src/modules/keyboard/KeyboardLayoutModel.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2016, Teo Mrnjavac + * Copyright 2017, 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 @@ -59,9 +60,9 @@ KeyboardLayoutModel::data( const QModelIndex& index, int role ) const void KeyboardLayoutModel::init() { - QMap< QString, KeyboardGlobal::KeyboardInfo > layouts = + KeyboardGlobal::LayoutsMap layouts = KeyboardGlobal::getKeyboardLayouts(); - for ( QMap< QString, KeyboardGlobal::KeyboardInfo >::const_iterator it = layouts.constBegin(); + for ( KeyboardGlobal::LayoutsMap::const_iterator it = layouts.constBegin(); it != layouts.constEnd(); ++it ) { m_layouts.append( qMakePair( it.key(), it.value() ) ); diff --git a/src/modules/keyboard/keyboardwidget/keyboardglobal.h b/src/modules/keyboard/keyboardwidget/keyboardglobal.h index 8710fdaa2..965e0828f 100644 --- a/src/modules/keyboard/keyboardwidget/keyboardglobal.h +++ b/src/modules/keyboard/keyboardwidget/keyboardglobal.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac + * Copyright 2017, Adriaan de Groot * * Originally from the Manjaro Installation Framework * by Roland Singer @@ -44,12 +45,15 @@ public: QMap< QString, QString > variants; }; - static QMap< QString, KeyboardInfo > getKeyboardLayouts(); + using LayoutsMap = QMap< QString, KeyboardInfo >; + + static LayoutsMap getKeyboardLayouts(); static QMap< QString, QString > getKeyboardModels(); + private: static QMap< QString, QString > parseKeyboardModels(QString filepath); - static QMap< QString, KeyboardInfo > parseKeyboardLayouts(QString filepath); + static LayoutsMap parseKeyboardLayouts(QString filepath); }; #endif // KEYBOARDGLOBAL_H From 88715b9a0fbf8a77104408b1e37d68762dc63d87 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Jun 2017 14:05:13 -0400 Subject: [PATCH 02/19] Keyboard: guess at layout based on locale Split locale into _ and go looking for keyboard layouts that match. Do that in reverse, so look for country first. - known weakness is el_CY (should get layout gr) because CY and el don't name any keyboard layout. - known weakness are Hausa, Igbo .. which are ha_NG and ig_NG. They select keyboard layout ng, which is labeled "English (Nigeria)"; they ought to select ng(hausa) and ng(igbo), which are the right variant keyboard layouts to use. - similar selecting a locale in Canada (en_CA, fr_CA, iu_CA ...) will select keyboard layout ca, which is for French-speaking Canada. Locale en_CA should select keyboard en -- e.g. en(us). But iu_CA (Inuktituk) needs layout ca(ike). --- src/modules/keyboard/KeyboardPage.cpp | 49 +++++++++++++++++++++++++++ src/modules/keyboard/KeyboardPage.h | 3 ++ 2 files changed, 52 insertions(+) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index 117530a88..770c7c6b1 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2016, Teo Mrnjavac + * Copyright 2017, Adriaan de Groot * * Portions from the Manjaro Installation Framework * by Roland Singer @@ -221,10 +222,58 @@ KeyboardPage::createJobs( const QString& xOrgConfFileName, } +void +KeyboardPage::guessLayout( const QStringList& langParts ) +{ + const KeyboardLayoutModel* klm = dynamic_cast< KeyboardLayoutModel* >( ui->listLayout->model() ); + bool foundCountryPart = false; + for ( auto countryPart = langParts.rbegin(); !foundCountryPart && countryPart != langParts.rend(); ++countryPart) + { + cDebug() << " .. looking for locale part" << *countryPart; + for ( int i = 0; i < klm->rowCount(); ++i ) + { + QModelIndex idx = klm->index( i ); + if ( idx.isValid() && + ( idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString().compare( *countryPart, Qt::CaseInsensitive ) == 0 ) ) + { + cDebug() << " .. matched" << idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString(); + ui->listLayout->setCurrentIndex( idx ); + foundCountryPart = true; + break; + } + } + } +} + + void KeyboardPage::onActivate() { ui->listLayout->setFocus(); + + // Try to preselect a layout, depending on language and locale + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + QString lang = gs->value( "localeConf" ).toMap().value( "LANG" ).toString(); + + cDebug() << "Got locale language" << lang; + if ( !lang.isEmpty() ) + { + // Chop off .codeset and @modifier + int index = lang.indexOf('.'); + if ( index >= 0 ) + lang.truncate( index ); + index = lang.indexOf('@'); + if ( index >= 0 ) + lang.truncate( index ); + + lang.replace( '-', '_' ); // Normalize separators + const auto langParts = lang.split( '_' , QString::SkipEmptyParts ); + + QString country = QLocale::countryToString( QLocale( lang ).country() ); + cDebug() << " .. extracted country" << country << "::" << langParts; + + guessLayout( langParts ); + } } diff --git a/src/modules/keyboard/KeyboardPage.h b/src/modules/keyboard/KeyboardPage.h index c60d62b2b..6f828f446 100644 --- a/src/modules/keyboard/KeyboardPage.h +++ b/src/modules/keyboard/KeyboardPage.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2016, Teo Mrnjavac + * Copyright 2017, Adriaan de Groot * * Portions from the Manjaro Installation Framework * by Roland Singer @@ -70,6 +71,8 @@ private: KeyboardGlobal::KeyboardInfo info; }; + /// Guess a layout based on the split-apart locale + void guessLayout( const QStringList& langParts ); void updateVariants( const QPersistentModelIndex& currentItem, QString currentVariant = QString() ); From 9b9801d48d838478c82acb59e807dd1b99ca2228 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Sep 2017 11:22:51 +0200 Subject: [PATCH 03/19] Code-style: format the keyboard module --- src/modules/keyboard/KeyboardLayoutModel.cpp | 8 +-- src/modules/keyboard/KeyboardPage.cpp | 66 +++++++++---------- src/modules/keyboard/KeyboardViewStep.cpp | 22 ++----- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 42 ++++++------ 4 files changed, 63 insertions(+), 75 deletions(-) diff --git a/src/modules/keyboard/KeyboardLayoutModel.cpp b/src/modules/keyboard/KeyboardLayoutModel.cpp index 63989819c..e03c2a36c 100644 --- a/src/modules/keyboard/KeyboardLayoutModel.cpp +++ b/src/modules/keyboard/KeyboardLayoutModel.cpp @@ -61,15 +61,13 @@ void KeyboardLayoutModel::init() { KeyboardGlobal::LayoutsMap layouts = - KeyboardGlobal::getKeyboardLayouts(); + KeyboardGlobal::getKeyboardLayouts(); for ( KeyboardGlobal::LayoutsMap::const_iterator it = layouts.constBegin(); - it != layouts.constEnd(); ++it ) - { + it != layouts.constEnd(); ++it ) m_layouts.append( qMakePair( it.key(), it.value() ) ); - } std::stable_sort( m_layouts.begin(), m_layouts.end(), []( const QPair< QString, KeyboardGlobal::KeyboardInfo >& a, - const QPair< QString, KeyboardGlobal::KeyboardInfo >& b ) + const QPair< QString, KeyboardGlobal::KeyboardInfo >& b ) { return a.second.description < b.second.description; } ); diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index 3287dc711..d7b14b338 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -58,7 +58,7 @@ findLayout( const KeyboardLayoutModel* klm, const QString& currentLayout ) { QModelIndex idx = klm->index( i ); if ( idx.isValid() && - idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString() == currentLayout ) + idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString() == currentLayout ) currentLayoutItem = idx; } @@ -86,7 +86,7 @@ KeyboardPage::KeyboardPage( QWidget* parent ) [this] { ui->comboBoxModel->setCurrentIndex( m_defaultIndex ); - }); + } ); connect( ui->comboBoxModel, static_cast< void ( QComboBox::* )( const QString& ) >( &QComboBox::currentIndexChanged ), @@ -97,7 +97,7 @@ KeyboardPage::KeyboardPage( QWidget* parent ) // Set Xorg keyboard model QProcess::execute( QLatin1Literal( "setxkbmap" ), QStringList() << "-model" << model ); - }); + } ); CALAMARES_RETRANSLATE( ui->retranslateUi( this ); ) } @@ -121,7 +121,7 @@ KeyboardPage::init() if ( process.waitForFinished() ) { const QStringList list = QString( process.readAll() ) - .split( "\n", QString::SkipEmptyParts ); + .split( "\n", QString::SkipEmptyParts ); for ( QString line : list ) { @@ -130,8 +130,8 @@ KeyboardPage::init() continue; line = line.remove( "}" ) - .remove( "{" ) - .remove( ";" ); + .remove( "{" ) + .remove( ";" ); line = line.mid( line.indexOf( "\"" ) + 1 ); QStringList split = line.split( "+", QString::SkipEmptyParts ); @@ -143,7 +143,7 @@ KeyboardPage::init() { int parenthesisIndex = currentLayout.indexOf( "(" ); currentVariant = currentLayout.mid( parenthesisIndex + 1 ) - .trimmed(); + .trimmed(); currentVariant.chop( 1 ); currentLayout = currentLayout .mid( 0, parenthesisIndex ) @@ -189,8 +189,8 @@ KeyboardPage::init() QPersistentModelIndex currentLayoutItem = findLayout( klm, currentLayout ); if ( !currentLayoutItem.isValid() && ( - ( currentLayout == "latin" ) - || ( currentLayout == "pc" ) ) ) + ( currentLayout == "latin" ) + || ( currentLayout == "pc" ) ) ) { currentLayout = "us"; currentLayoutItem = findLayout( klm, currentLayout ); @@ -237,11 +237,11 @@ KeyboardPage::createJobs( const QString& xOrgConfFileName, "pc105" ); Calamares::Job* j = new SetKeyboardLayoutJob( selectedModel, - m_selectedLayout, - m_selectedVariant, - xOrgConfFileName, - convertedKeymapPath, - writeEtcDefaultKeyboard ); + m_selectedLayout, + m_selectedVariant, + xOrgConfFileName, + convertedKeymapPath, + writeEtcDefaultKeyboard ); list.append( Calamares::job_ptr( j ) ); return list; @@ -253,14 +253,14 @@ KeyboardPage::guessLayout( const QStringList& langParts ) { const KeyboardLayoutModel* klm = dynamic_cast< KeyboardLayoutModel* >( ui->listLayout->model() ); bool foundCountryPart = false; - for ( auto countryPart = langParts.rbegin(); !foundCountryPart && countryPart != langParts.rend(); ++countryPart) + for ( auto countryPart = langParts.rbegin(); !foundCountryPart && countryPart != langParts.rend(); ++countryPart ) { cDebug() << " .. looking for locale part" << *countryPart; for ( int i = 0; i < klm->rowCount(); ++i ) { QModelIndex idx = klm->index( i ); if ( idx.isValid() && - ( idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString().compare( *countryPart, Qt::CaseInsensitive ) == 0 ) ) + ( idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString().compare( *countryPart, Qt::CaseInsensitive ) == 0 ) ) { cDebug() << " .. matched" << idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString(); ui->listLayout->setCurrentIndex( idx ); @@ -285,15 +285,15 @@ KeyboardPage::onActivate() if ( !lang.isEmpty() ) { // Chop off .codeset and @modifier - int index = lang.indexOf('.'); + int index = lang.indexOf( '.' ); if ( index >= 0 ) lang.truncate( index ); - index = lang.indexOf('@'); + index = lang.indexOf( '@' ); if ( index >= 0 ) lang.truncate( index ); lang.replace( '-', '_' ); // Normalize separators - const auto langParts = lang.split( '_' , QString::SkipEmptyParts ); + const auto langParts = lang.split( '_', QString::SkipEmptyParts ); QString country = QLocale::countryToString( QLocale( lang ).country() ); cDebug() << " .. extracted country" << country << "::" << langParts; @@ -325,8 +325,8 @@ KeyboardPage::updateVariants( const QPersistentModelIndex& currentItem, ui->listVariant->blockSignals( true ); QMap< QString, QString > variants = - currentItem.data( KeyboardLayoutModel::KeyboardVariantsRole ) - .value< QMap< QString, QString > >(); + currentItem.data( KeyboardLayoutModel::KeyboardVariantsRole ) + .value< QMap< QString, QString > >(); QMapIterator< QString, QString > li( variants ); LayoutItem* defaultItem = nullptr; @@ -334,17 +334,17 @@ KeyboardPage::updateVariants( const QPersistentModelIndex& currentItem, while ( li.hasNext() ) { - li.next(); + li.next(); - LayoutItem* item = new LayoutItem(); - item->setText( li.key() ); - item->data = li.value(); - ui->listVariant->addItem( item ); + LayoutItem* item = new LayoutItem(); + item->setText( li.key() ); + item->data = li.value(); + ui->listVariant->addItem( item ); - // currentVariant defaults to QString(). It is only non-empty during the - // initial setup. - if ( li.value() == currentVariant ) - defaultItem = item; + // currentVariant defaults to QString(). It is only non-empty during the + // initial setup. + if ( li.value() == currentVariant ) + defaultItem = item; } // Unblock signals @@ -352,13 +352,13 @@ KeyboardPage::updateVariants( const QPersistentModelIndex& currentItem, // Set to default value if ( defaultItem ) - ui->listVariant->setCurrentItem( defaultItem ); + ui->listVariant->setCurrentItem( defaultItem ); } void KeyboardPage::onListLayoutCurrentItemChanged( const QModelIndex& current, - const QModelIndex& previous ) + const QModelIndex& previous ) { Q_UNUSED( previous ); if ( !current.isValid() ) @@ -370,7 +370,7 @@ KeyboardPage::onListLayoutCurrentItemChanged( const QModelIndex& current, /* Returns stringlist with suitable setxkbmap command-line arguments * to set the given @p layout and @p variant. */ -static inline QStringList xkbmap_args( QStringList&& r, const QString& layout, const QString& variant) +static inline QStringList xkbmap_args( QStringList&& r, const QString& layout, const QString& variant ) { r << "-layout" << layout; if ( !variant.isEmpty() ) diff --git a/src/modules/keyboard/KeyboardViewStep.cpp b/src/modules/keyboard/KeyboardViewStep.cpp index 0dd326a8d..e04e94ce1 100644 --- a/src/modules/keyboard/KeyboardViewStep.cpp +++ b/src/modules/keyboard/KeyboardViewStep.cpp @@ -135,36 +135,28 @@ void KeyboardViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { if ( configurationMap.contains( "xOrgConfFileName" ) && - configurationMap.value( "xOrgConfFileName" ).type() == QVariant::String && - !configurationMap.value( "xOrgConfFileName" ).toString().isEmpty() ) + configurationMap.value( "xOrgConfFileName" ).type() == QVariant::String && + !configurationMap.value( "xOrgConfFileName" ).toString().isEmpty() ) { m_xOrgConfFileName = configurationMap.value( "xOrgConfFileName" ) - .toString(); + .toString(); } else - { m_xOrgConfFileName = "00-keyboard.conf"; - } if ( configurationMap.contains( "convertedKeymapPath" ) && - configurationMap.value( "convertedKeymapPath" ).type() == QVariant::String && - !configurationMap.value( "convertedKeymapPath" ).toString().isEmpty() ) + configurationMap.value( "convertedKeymapPath" ).type() == QVariant::String && + !configurationMap.value( "convertedKeymapPath" ).toString().isEmpty() ) { m_convertedKeymapPath = configurationMap.value( "convertedKeymapPath" ) - .toString(); + .toString(); } else - { m_convertedKeymapPath = QString(); - } if ( configurationMap.contains( "writeEtcDefaultKeyboard" ) && - configurationMap.value( "writeEtcDefaultKeyboard" ).type() == QVariant::Bool ) - { + configurationMap.value( "writeEtcDefaultKeyboard" ).type() == QVariant::Bool ) m_writeEtcDefaultKeyboard = configurationMap.value( "writeEtcDefaultKeyboard" ).toBool(); - } else - { m_writeEtcDefaultKeyboard = true; - } } diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 430a227eb..1b94502ea 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -37,11 +37,11 @@ SetKeyboardLayoutJob::SetKeyboardLayoutJob( const QString& model, - const QString& layout, - const QString& variant, - const QString& xOrgConfFileName, - const QString& convertedKeymapPath, - bool writeEtcDefaultKeyboard) + const QString& layout, + const QString& variant, + const QString& xOrgConfFileName, + const QString& convertedKeymapPath, + bool writeEtcDefaultKeyboard ) : Calamares::Job() , m_model( model ) , m_layout( layout ) @@ -57,8 +57,8 @@ QString SetKeyboardLayoutJob::prettyName() const { return tr( "Set keyboard model to %1, layout to %2-%3" ).arg( m_model ) - .arg( m_layout ) - .arg( m_variant ); + .arg( m_layout ) + .arg( m_variant ); } @@ -74,7 +74,7 @@ SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath ) QString name = m_variant.isEmpty() ? m_layout : ( m_layout + '-' + m_variant ); if ( convertedKeymapDir.exists( name + ".map" ) - || convertedKeymapDir.exists( name + ".map.gz" ) ) + || convertedKeymapDir.exists( name + ".map.gz" ) ) { cDebug() << "Found converted keymap" << name; @@ -154,7 +154,7 @@ SetKeyboardLayoutJob::findLegacyKeymap() const bool SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, - const QString& convertedKeymapPath ) const + const QString& convertedKeymapPath ) const { QString keymap = findConvertedKeymap( convertedKeymapPath ); if ( keymap.isEmpty() ) @@ -215,10 +215,10 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const QTextStream stream( &file ); stream << "# Read and parsed by systemd-localed. It's probably wise not to edit this file\n" - "# manually too freely.\n" - "Section \"InputClass\"\n" - " Identifier \"system-keyboard\"\n" - " MatchIsKeyboard \"on\"\n"; + "# manually too freely.\n" + "Section \"InputClass\"\n" + " Identifier \"system-keyboard\"\n" + " MatchIsKeyboard \"on\"\n"; if ( !m_layout.isEmpty() ) stream << " Option \"XkbLayout\" \"" << m_layout << "\"\n"; @@ -235,8 +235,8 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const file.close(); cDebug() << "Written XkbLayout" << m_layout << - "; XkbModel" << m_model << - "; XkbVariant" << m_variant << "to X.org file" << keyboardConfPath; + "; XkbModel" << m_model << + "; XkbVariant" << m_variant << "to X.org file" << keyboardConfPath; return ( stream.status() == QTextStream::Ok ); } @@ -250,7 +250,7 @@ SetKeyboardLayoutJob::writeDefaultKeyboardData( const QString& defaultKeyboardPa QTextStream stream( &file ); stream << "# KEYBOARD CONFIGURATION FILE\n\n" - "# Consult the keyboard(5) manual page.\n\n"; + "# Consult the keyboard(5) manual page.\n\n"; stream << "XKBMODEL=\"" << m_model << "\"\n"; stream << "XKBLAYOUT=\"" << m_layout << "\"\n"; @@ -262,9 +262,9 @@ SetKeyboardLayoutJob::writeDefaultKeyboardData( const QString& defaultKeyboardPa file.close(); cDebug() << "Written XKBMODEL" << m_model << - "; XKBLAYOUT" << m_layout << - "; XKBVARIANT" << m_variant << - "to /etc/default/keyboard file" << defaultKeyboardPath; + "; XKBLAYOUT" << m_layout << + "; XKBVARIANT" << m_variant << + "to /etc/default/keyboard file" << defaultKeyboardPath; return ( stream.status() == QTextStream::Ok ); } @@ -297,15 +297,13 @@ SetKeyboardLayoutJob::exec() { xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); keyboardConfPath = QDir( xorgConfDPath ) - .absoluteFilePath( m_xOrgConfFileName ); + .absoluteFilePath( m_xOrgConfFileName ); } destDir.mkpath( xorgConfDPath ); QString defaultKeyboardPath; if ( QDir( destDir.absoluteFilePath( "etc/default" ) ).exists() ) - { defaultKeyboardPath = destDir.absoluteFilePath( "etc/default/keyboard" ); - } // Get the path to the destination's path to the converted key mappings QString convertedKeymapPath = m_convertedKeymapPath; From 6704121946d3c67eda26ff269f68f93cbe86d18a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Sep 2017 11:32:52 -0400 Subject: [PATCH 04/19] Keyboard: try a little harder to match keyboard layouts with selected system language --- src/modules/keyboard/KeyboardPage.cpp | 38 ++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index d7b14b338..e21219c12 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -259,15 +259,32 @@ KeyboardPage::guessLayout( const QStringList& langParts ) for ( int i = 0; i < klm->rowCount(); ++i ) { QModelIndex idx = klm->index( i ); - if ( idx.isValid() && - ( idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString().compare( *countryPart, Qt::CaseInsensitive ) == 0 ) ) + QString name = idx.isValid() ? idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString() : QString(); + if ( idx.isValid() && ( name.compare( *countryPart, Qt::CaseInsensitive ) == 0 ) ) { - cDebug() << " .. matched" << idx.data( KeyboardLayoutModel::KeyboardLayoutKeyRole ).toString(); + cDebug() << " .. matched" << name; ui->listLayout->setCurrentIndex( idx ); foundCountryPart = true; break; } } + if ( foundCountryPart ) + { + ++countryPart; + if ( countryPart != langParts.rend() ) + { + cDebug() << "Next level:" << *countryPart; + for (int variantnumber = 0; variantnumber < ui->listVariant->count(); ++variantnumber) + { + LayoutItem *variantdata = dynamic_cast< LayoutItem* >( ui->listVariant->item( variantnumber ) ); + if ( variantdata && (variantdata->data.compare( *countryPart, Qt::CaseInsensitive ) == 0) ) + { + ui->listVariant->setCurrentItem( variantdata ); + cDebug() << " .. matched variant" << variantdata->data << ' ' << variantdata->text(); + } + } + } + } } } @@ -275,6 +292,12 @@ KeyboardPage::guessLayout( const QStringList& langParts ) void KeyboardPage::onActivate() { + static auto specialCaseMap = QMap( { + { "ar_EG", "ara" }, + { "ca_ES", "cat_ES" }, + { "as_ES", "ast_ES" }, + } ); + ui->listLayout->setFocus(); // Try to preselect a layout, depending on language and locale @@ -293,6 +316,15 @@ KeyboardPage::onActivate() lang.truncate( index ); lang.replace( '-', '_' ); // Normalize separators + } + if ( !lang.isEmpty() && specialCaseMap.contains( lang.toStdString() ) ) + { + QLatin1String newLang( specialCaseMap.value( lang.toStdString() ).c_str() ); + cDebug() << " .. special case language" << lang << '>' << newLang; + lang = newLang; + } + if ( !lang.isEmpty() ) + { const auto langParts = lang.split( '_', QString::SkipEmptyParts ); QString country = QLocale::countryToString( QLocale( lang ).country() ); From 784bbd3bc876f537c03b7db27770b090e2f849f3 Mon Sep 17 00:00:00 2001 From: Alf Gaida Date: Tue, 26 Dec 2017 22:25:40 +0100 Subject: [PATCH 05/19] finally !must! never fail unhandled but it does without help --- src/modules/unpackfs/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py index 96b979a58..851335513 100644 --- a/src/modules/unpackfs/main.py +++ b/src/modules/unpackfs/main.py @@ -218,7 +218,7 @@ class UnpackOperation: return None finally: - shutil.rmtree(source_mount_path) + shutil.rmtree(source_mount_path, ignore_errors=True, onerror=None) def mount_image(self, entry, imgmountdir): """ From a7d7f3a83b69bf7188058e2018b4d5fd54e8de15 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 3 Jan 2018 04:20:21 -0500 Subject: [PATCH 06/19] [welcome] Make link to Calamares site https --- src/modules/welcome/WelcomePage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index e3bedb0f8..852a5bfb9 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -2,7 +2,7 @@ * * Copyright 2014-2015, Teo Mrnjavac * Copyright 2015, Anke Boersma - * Copyright 2017, Adriaan de Groot + * Copyright 2017-2018, 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 @@ -82,7 +82,7 @@ WelcomePage::WelcomePage( RequirementsChecker* requirementsChecker, QWidget* par " Philip Müller, Pier Luigi Fiorini, Rohan Garg and the Calamares " "translators team.

" - "Calamares " + "Calamares " "development is sponsored by
" "Blue Systems - " "Liberating Software." From 6f7b5a051089e7f9cb6dfa3fe64eb0020eb30b72 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 3 Jan 2018 04:33:20 -0500 Subject: [PATCH 07/19] [umount] Move module documentation into config file, fix wording FIXES #831 --- src/modules/umount/README.md | 18 -------------- src/modules/umount/umount.conf | 45 +++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 24 deletions(-) delete mode 100644 src/modules/umount/README.md diff --git a/src/modules/umount/README.md b/src/modules/umount/README.md deleted file mode 100644 index 2a0ccace3..000000000 --- a/src/modules/umount/README.md +++ /dev/null @@ -1,18 +0,0 @@ -### Umount Module ---------- -This module represents the last part of the installation, the unmounting of partitions used for the install. It is also the last place where it is possible to copy files to the target system, thus the best place to copy an installation log. - -You can either use the default ```/root/.cache/Calamares/Calamares/Calamares.log``` -to copy or if you want to use the full output of ```sudo calamares -d``` to create a log you will need to include a log creation to your launcher script or add it to the used calamares.desktop, example of a launcher script: - -``` -#!/bin/sh -sudo /usr/bin/calamares -d > installation.log -``` -Example desktop line: -``` -Exec=sudo /usr/bin/calamares -d > installation.log -``` -Set the source and destination path of your install log in umount.conf. -If you do not wish to use the copy of an install log feature, no action needed, the default settings do not execute the copy of an install log in this module. - diff --git a/src/modules/umount/umount.conf b/src/modules/umount/umount.conf index 907b8d890..798dfc3f5 100644 --- a/src/modules/umount/umount.conf +++ b/src/modules/umount/umount.conf @@ -1,9 +1,42 @@ +### Umount Module +# +# This module represents the last part of the installation, the unmounting +# of partitions used for the install. It is also the last place where it +# is possible to copy files to the target system, thus the best place to +# copy an installation log. +# +# This module has two configuration keys: +# srcLog location in the live system where the log is +# 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, +# 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. +# +# Example launcher script: +# +# ``` +# #!/bin/sh +# sudo /usr/bin/calamares -d > installation.log +# ``` +# +# Example desktop line: +# +# ``` +# Exec=sudo /usr/bin/calamares -d > installation.log +# ``` +# +# If no source and destination are set, no copy is attempted. If the +# copy fails for some reason, a warning is printed but the installation +# does not fail. + --- -#srcLog: "/path/to/installation.log" -#destLog: "/var/log/installation.log" -# example when using the Calamares created log: -#srcLog: "/root/.cache/Calamares/Calamares/Calamares.log" -#destLog: "/var/log/Calamares.log" -# example when creating with a sudo calamares -d log: +# example when using the normal Calamares log: +srcLog: "/root/.cache/Calamares/Calamares/Calamares.log" +destLog: "/var/log/Calamares.log" + +# example when using a log created by `sudo calamares -d`: #srcLog: "/home/live/installation.log" #destLog: "/var/log/installation.log" From 2a0a2a26bc15207b51dbb29e233ece69108997ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 3 Jan 2018 05:01:38 -0500 Subject: [PATCH 08/19] [umount] Don't raise when copying log file fails. --- src/modules/umount/main.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/modules/umount/main.py b/src/modules/umount/main.py index aa42ba023..5a04796f6 100644 --- a/src/modules/umount/main.py +++ b/src/modules/umount/main.py @@ -55,11 +55,18 @@ def run(): "destLog" in libcalamares.job.configuration): log_source = libcalamares.job.configuration["srcLog"] log_destination = libcalamares.job.configuration["destLog"] + # Relocate log_destination into target system + log_destination = '{!s}/{!s}'.format(root_mount_point, log_destination) + # Make sure source is a string + log_source = '{!s}'.format(log_source) # copy installation log before umount - if os.path.exists('{!s}'.format(log_source)): - shutil.copy2('{!s}'.format(log_source), '{!s}/{!s}'.format( - root_mount_point, log_destination)) + if os.path.exists(log_source): + try: + shutil.copy2(log_source, log_destination) + except Exception as e: + libcalamares.utils.debug("WARNING Could not preserve file {!s}, " + "error {!s}".format(log_source, e)) if not root_mount_point: return ("No mount point for root partition in globalstorage", From 28d61c406e95ee461ad5de354b0cc5c64f32af30 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jan 2018 16:14:28 +0100 Subject: [PATCH 09/19] [bootloader] Improve description of *efiBootloaderId* option --- src/modules/bootloader/bootloader.conf | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/modules/bootloader/bootloader.conf b/src/modules/bootloader/bootloader.conf index 7975324b0..70f1ef22d 100644 --- a/src/modules/bootloader/bootloader.conf +++ b/src/modules/bootloader/bootloader.conf @@ -20,8 +20,16 @@ timeout: "10" grubInstall: "grub-install" grubMkconfig: "grub-mkconfig" grubCfg: "/boot/grub/grub.cfg" -# Optionally set the --bootloader-id to use for EFI. If not set, this defaults -# to the bootloaderEntryName from branding.desc with problematic characters -# replaced. If an efiBootloaderId is specified here, it is taken to already be a -# valid directory name, so no such postprocessing is done in this case. + +# Optionally set the bootloader ID to use for EFI. This is passed to +# grub-install --bootloader-id. +# +# If not set here, the value from bootloaderEntryName from branding.desc +# is used, with problematic characters (space and slash) replaced. +# +# The ID is also used as a directory name within the EFI environment, +# and the bootloader is copied from /boot/efi/EFI// . When +# setting the option here, take care to use only valid directory +# names since no sanitizing is done. +# # efiBootloaderId: "dirname" From 7249b41e3e7bd5a04a546c60400792f1c62593ae Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jan 2018 11:02:20 -0500 Subject: [PATCH 10/19] [keyboard] Explain table format, add more edge cases --- src/modules/keyboard/KeyboardPage.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index db43284b5..a1904f5d4 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -292,10 +292,29 @@ KeyboardPage::guessLayout( const QStringList& langParts ) void KeyboardPage::onActivate() { + /* Guessing a keyboard layout based on the locale means + * mapping between language identifiers in _ + * format to keyboard mappings, which are _ + * format; in addition, some countries have multiple languages, + * so fr_BE and nl_BE want different layouts (both Belgian) + * and sometimes the language-country name doesn't match the + * keyboard-country name at all (e.g. Ellas vs. Greek). + * + * This is a table of language-to-keyboard mappings. The + * language identifier is the key, while the value is + * a string that is used instead of the real language + * identifier in guessing -- so it should be something + * like _. + */ static auto specialCaseMap = QMap( { - { "ar_EG", "ara" }, - { "ca_ES", "cat_ES" }, - { "as_ES", "ast_ES" }, + { "ar_EG", "ara" }, /* Egyptian Arabic */ + { "ca_ES", "cat_ES" }, /* Catalan */ + { "as_ES", "ast_ES" }, /* Asturian */ + { "en_CA", "eng_CA" }, /* Canadian English */ + { "el_CY", "gr" }, /* Greek in Cyprus */ + { "el_GR", "gr" }, /* Greek in Greeze */ + { "ig_NG", "igbo_NG" }, /* Igbo in Nigeria */ + { "ha_NG", "hausa_NG" } /* Hausa */ } ); ui->listLayout->setFocus(); From 05967311defaa72896303bbf7dabf3f2692f8c7b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jan 2018 05:09:24 -0500 Subject: [PATCH 11/19] [partition] Be defensive against no device-device-available. Scenario is this: you have no suitable installation devices on your system (everything is mounted, or HDD has died), click through to partition page, where you have all the buttons available, but no devices in the list. The following actions then cause a crash: - clicking "back" - clicking any button Prevent that: - you can click "back", but if there is no device selected nothing happens to the device state (no nullptr deref, and no crash) - button code is now more resilient to this scenario - buttons are hidden until a device is available, so you can't even click on them to trigger the code. --- src/modules/partition/gui/ChoicePage.cpp | 35 +++++++++++++++++++----- src/modules/partition/gui/ChoicePage.h | 8 ++++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 77b807a2b..008a64d8d 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -300,6 +300,16 @@ ChoicePage::selectedDevice() } +void +ChoicePage::hideButtons() +{ + m_eraseButton->hide(); + m_replaceButton->hide(); + m_alongsideButton->hide(); + m_somethingElseButton->hide(); +} + + /** * @brief ChoicePage::applyDeviceChoice handler for the selected event of the device * picker. Calls ChoicePage::selectedDevice() to get the current Device*, then @@ -311,7 +321,10 @@ void ChoicePage::applyDeviceChoice() { if ( !selectedDevice() ) + { + hideButtons(); return; + } if ( m_core->isDirty() ) { @@ -342,11 +355,14 @@ ChoicePage::continueApplyDeviceChoice() // applyDeviceChoice() will be called again momentarily as soon as we handle the // PartitionCoreModule::reverted signal. if ( !currd ) + { + hideButtons(); return; + } updateDeviceStatePreview(); - // Preview setup done. Now we show/hide choices as needed. + // Preview setup done. Now we show/hide choices as needed. setupActions(); m_lastSelectedDeviceIndex = m_drivesCombo->currentIndex(); @@ -562,7 +578,11 @@ ChoicePage::onLeave() { if ( m_bootloaderComboBox.isNull() ) { - m_core->setBootLoaderInstallPath( selectedDevice()->deviceNode() ); + auto d_p = selectedDevice(); + if ( d_p ) + m_core->setBootLoaderInstallPath( d_p->deviceNode() ); + else + cDebug() << "WARNING: No device selected for bootloader."; } else { @@ -1156,6 +1176,9 @@ ChoicePage::setupActions() else m_deviceInfoWidget->setPartitionTableType( PartitionTable::unknownTableType ); + // Manual partitioning is always a possibility + m_somethingElseButton->show(); + bool atLeastOneCanBeResized = false; bool atLeastOneCanBeReplaced = false; bool atLeastOneIsMounted = false; // Suppress 'erase' if so @@ -1332,18 +1355,16 @@ ChoicePage::updateNextEnabled() { bool enabled = false; + auto sm_p = m_beforePartitionBarsView ? m_beforePartitionBarsView->selectionModel() : nullptr; + switch ( m_choice ) { case NoChoice: enabled = false; break; case Replace: - enabled = m_beforePartitionBarsView->selectionModel()-> - currentIndex().isValid(); - break; case Alongside: - enabled = m_beforePartitionBarsView->selectionModel()-> - currentIndex().isValid(); + enabled = sm_p && sm_p->currentIndex().isValid(); break; case Erase: case Manual: diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index 8d600978e..91274d152 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -113,8 +113,12 @@ private: void setupChoices(); QComboBox* createBootloaderComboBox( QWidget* parentButton ); Device* selectedDevice(); - void applyDeviceChoice(); - void continueApplyDeviceChoice(); + + /* Change the UI depending on the device selected. */ + void hideButtons(); // Hide everything when no device + void applyDeviceChoice(); // Start scanning new device + void continueApplyDeviceChoice(); // .. called after scan + void updateDeviceStatePreview(); void updateActionChoicePreview( ChoicePage::Choice choice ); void setupActions(); From 3ff68bce98e30203e75a6b52e79a8125f1683be8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jan 2018 16:24:55 +0100 Subject: [PATCH 12/19] [keyboard] Correct guessing for Arabic variants --- src/modules/keyboard/KeyboardPage.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index a1904f5d4..9e4b7e3ae 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -306,8 +306,28 @@ KeyboardPage::onActivate() * identifier in guessing -- so it should be something * like _. */ - static auto specialCaseMap = QMap( { - { "ar_EG", "ara" }, /* Egyptian Arabic */ + static constexpr char arabic[] = "ara"; + static const auto specialCaseMap = QMap( { + /* Most Arab countries map to Arabic keyboard (Default) */ + { "ar_AE", arabic }, + { "ar_BH", arabic }, + { "ar_DZ", arabic }, + { "ar_EG", arabic }, + { "ar_IN", arabic }, + { "ar_IQ", arabic }, + { "ar_JO", arabic }, + { "ar_KW", arabic }, + { "ar_LB", arabic }, + { "ar_LY", arabic }, + /* Not Morocco: use layout ma */ + { "ar_OM", arabic }, + { "ar_QA", arabic }, + { "ar_SA", arabic }, + { "ar_SD", arabic }, + { "ar_SS", arabic }, + /* Not Syria: use layout sy */ + { "ar_TN", arabic }, + { "ar_YE", arabic }, { "ca_ES", "cat_ES" }, /* Catalan */ { "as_ES", "ast_ES" }, /* Asturian */ { "en_CA", "eng_CA" }, /* Canadian English */ From 94b6c95c4443d8266e52663fb5ba787085bf1b5a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jan 2018 10:53:33 -0500 Subject: [PATCH 13/19] [partition] Introduce function for checking various flag-combinations for ESP boot. --- src/modules/partition/core/PartUtils.cpp | 22 ++++++++++++++++++++++ src/modules/partition/core/PartUtils.h | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 4a7253f92..a8e004979 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -340,4 +340,26 @@ isEfiSystem() return QDir( "/sys/firmware/efi/efivars" ).exists(); } +bool +isEfiBootable( const Partition* candidate ) +{ + /* If bit 17 is set, old-style Esp flag, it's OK */ + if ( candidate->activeFlags().testFlag( PartitionTable::FlagEsp ) ) + return true; + + + /* Otherwise, if it's a GPT table, Boot (bit 0) is the same as Esp */ + const PartitionNode* root = candidate; + while ( root && !root->isRoot() ) + root = root->parent(); + + // Strange case: no root found, no partition table node? + if ( !root ) + return false; + + const PartitionTable* table = dynamic_cast( root ); + return table && ( table->type() == PartitionTable::TableType::gpt ) && + candidate->activeFlags().testFlag( PartitionTable::FlagBoot ); +} + } // nmamespace PartUtils diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 144e9e45b..c81258712 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -67,6 +67,11 @@ OsproberEntryList runOsprober( PartitionCoreModule* core ); */ bool isEfiSystem(); +/** + * @brief Is the given @p partition bootable in EFI? Depending on + * the partition table layout, this may mean different flags. + */ +bool isEfiBootable( const Partition* candidate ); } #endif // PARTUTILS_H From 637d6ad7523810972707cd70ab7b72b7374cad36 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jan 2018 11:12:13 -0500 Subject: [PATCH 14/19] [partition] Find Esp partition with modern flags. --- src/modules/partition/core/PartitionCoreModule.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index e8cdc64b8..178860e2e 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -504,16 +504,7 @@ PartitionCoreModule::scanForEfiSystemPartitions() } QList< Partition* > efiSystemPartitions = - KPMHelpers::findPartitions( devices, - []( Partition* partition ) -> bool - { - if ( partition->activeFlags().testFlag( PartitionTable::FlagEsp ) ) - { - cDebug() << "Found EFI system partition at" << partition->partitionPath(); - return true; - } - return false; - } ); + KPMHelpers::findPartitions( devices, PartUtils::isEfiBootable ); if ( efiSystemPartitions.isEmpty() ) cDebug() << "WARNING: system is EFI but no EFI system partitions found."; From e3b7a2884b1229e9d189a17332eefd832d3d917e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jan 2018 11:15:30 -0500 Subject: [PATCH 15/19] [partition] Relax check with UI-level warning message, too --- src/modules/partition/gui/PartitionViewStep.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index f26c49ae7..8e46da71a 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -408,7 +408,7 @@ PartitionViewStep::onLeave() .arg( *Calamares::Branding::ShortProductName ) .arg( espMountPoint ); } - else if ( esp && !esp->activeFlags().testFlag( PartitionTable::FlagEsp ) ) + else if ( esp && !PartUtils::isEfiBootable( esp ) ) { message = tr( "EFI system partition flag not set" ); description = tr( "An EFI system partition is necessary to start %1." From 58252fc16d98e8650d534732ffbe694a839b3e37 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jan 2018 09:05:15 -0500 Subject: [PATCH 16/19] [partition] Handle missing requirements by disabling the module --- src/modules/partition/CMakeLists.txt | 128 ++++++++++++++------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 59b897092..156ff86f5 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -5,64 +5,72 @@ include(GenerateExportHeader) find_package( Qt5 REQUIRED DBus ) find_package( KF5 REQUIRED Config CoreAddons I18n WidgetsAddons ) -find_package( KPMcore 3.3 REQUIRED ) - -include_directories( ${KPMCORE_INCLUDE_DIR} ) -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) - -add_subdirectory( tests ) - -calamares_add_plugin( partition - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - core/BootLoaderModel.cpp - core/ColorUtils.cpp - core/DeviceList.cpp - core/DeviceModel.cpp - core/KPMHelpers.cpp - core/PartitionActions.cpp - core/PartitionCoreModule.cpp - core/PartitionInfo.cpp - core/PartitionIterator.cpp - core/PartitionModel.cpp - core/PartUtils.cpp - gui/BootInfoWidget.cpp - gui/ChoicePage.cpp - gui/CreatePartitionDialog.cpp - gui/DeviceInfoWidget.cpp - gui/EditExistingPartitionDialog.cpp - gui/EncryptWidget.cpp - gui/PartitionPage.cpp - gui/PartitionBarsView.cpp - gui/PartitionLabelsView.cpp - gui/PartitionSizeController.cpp - gui/PartitionSplitterWidget.cpp - gui/PartitionViewStep.cpp - gui/PrettyRadioButton.cpp - gui/ScanningDialog.cpp - gui/ReplaceWidget.cpp - jobs/ClearMountsJob.cpp - jobs/ClearTempMountsJob.cpp - jobs/CreatePartitionJob.cpp - jobs/CreatePartitionTableJob.cpp - jobs/DeletePartitionJob.cpp - jobs/FillGlobalStorageJob.cpp - jobs/FormatPartitionJob.cpp - jobs/PartitionJob.cpp - jobs/ResizePartitionJob.cpp - jobs/SetPartitionFlagsJob.cpp - UI - gui/ChoicePage.ui - gui/CreatePartitionDialog.ui - gui/CreatePartitionTableDialog.ui - gui/EditExistingPartitionDialog.ui - gui/EncryptWidget.ui - gui/PartitionPage.ui - gui/ReplaceWidget.ui - LINK_PRIVATE_LIBRARIES - kpmcore - calamaresui - KF5::CoreAddons - SHARED_LIB +find_package( KPMcore 3.3 ) +set_package_properties( + KPMcore PROPERTIES + PURPOSE "For partitioning module" ) + +if ( KPMcore_FOUND ) + include_directories( ${KPMCORE_INCLUDE_DIR} ) + include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) + + add_subdirectory( tests ) + + calamares_add_plugin( partition + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + core/BootLoaderModel.cpp + core/ColorUtils.cpp + core/DeviceList.cpp + core/DeviceModel.cpp + core/KPMHelpers.cpp + core/PartitionActions.cpp + core/PartitionCoreModule.cpp + core/PartitionInfo.cpp + core/PartitionIterator.cpp + core/PartitionModel.cpp + core/PartUtils.cpp + gui/BootInfoWidget.cpp + gui/ChoicePage.cpp + gui/CreatePartitionDialog.cpp + gui/DeviceInfoWidget.cpp + gui/EditExistingPartitionDialog.cpp + gui/EncryptWidget.cpp + gui/PartitionPage.cpp + gui/PartitionBarsView.cpp + gui/PartitionLabelsView.cpp + gui/PartitionSizeController.cpp + gui/PartitionSplitterWidget.cpp + gui/PartitionViewStep.cpp + gui/PrettyRadioButton.cpp + gui/ScanningDialog.cpp + gui/ReplaceWidget.cpp + jobs/ClearMountsJob.cpp + jobs/ClearTempMountsJob.cpp + jobs/CreatePartitionJob.cpp + jobs/CreatePartitionTableJob.cpp + jobs/DeletePartitionJob.cpp + jobs/FillGlobalStorageJob.cpp + jobs/FormatPartitionJob.cpp + jobs/PartitionJob.cpp + jobs/ResizePartitionJob.cpp + jobs/SetPartitionFlagsJob.cpp + UI + gui/ChoicePage.ui + gui/CreatePartitionDialog.ui + gui/CreatePartitionTableDialog.ui + gui/EditExistingPartitionDialog.ui + gui/EncryptWidget.ui + gui/PartitionPage.ui + gui/ReplaceWidget.ui + LINK_PRIVATE_LIBRARIES + kpmcore + calamaresui + KF5::CoreAddons + SHARED_LIB + ) +else() + calamares_skip_module( "partition (missing suitable KPMcore)" ) +endif() From 6e01bb0fa40a70666700f2178389e978aea0c32c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jan 2018 09:20:49 -0500 Subject: [PATCH 17/19] CMake: factor out explanation of skipped modules. Make a function out of explaining-skipped-modules, and call it not only after collecting all the modules, but also after the feature summary, so that it's quite clear which modules are skipped. --- CMakeLists.txt | 9 ++++++++- CMakeModules/CalamaresAddModuleSubdirectory.cmake | 11 ++++++++++- src/modules/CMakeLists.txt | 12 +++--------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7473876ce..e3c4ee7fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ if( POLICY CMP0071 ) cmake_policy( SET CMP0071 NEW ) endif() if(NOT CMAKE_VERSION VERSION_LESS "3.10.0") - list(APPEND CMAKE_AUTOMOC_MACRO_NAMES + list(APPEND CMAKE_AUTOMOC_MACRO_NAMES "K_PLUGIN_FACTORY_WITH_JSON" "K_EXPORT_PLASMA_DATAENGINE_WITH_JSON" "K_EXPORT_PLASMA_RUNNER" @@ -119,6 +119,7 @@ if( CMAKE_COMPILER_IS_GNUCXX ) endif() include( FeatureSummary ) +include( CMakeColors ) set( QT_VERSION 5.6.0 ) @@ -313,6 +314,12 @@ add_feature_info(KCrash ${WITH_KF5Crash} "Crash dumps via KCrash") feature_summary(WHAT ALL) +get_directory_property( SKIPPED_MODULES + DIRECTORY src/modules + DEFINITION LIST_SKIPPED_MODULES +) +calamares_explain_skipped_modules( ${SKIPPED_MODULES} ) + # Add all targets to the build-tree export set set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" ) set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" ) diff --git a/CMakeModules/CalamaresAddModuleSubdirectory.cmake b/CMakeModules/CalamaresAddModuleSubdirectory.cmake index 12aad380f..f85de36e9 100644 --- a/CMakeModules/CalamaresAddModuleSubdirectory.cmake +++ b/CMakeModules/CalamaresAddModuleSubdirectory.cmake @@ -1,4 +1,3 @@ -include( CMakeColors ) include( CalamaresAddTranslations ) set( MODULE_DATA_DESTINATION share/calamares/modules ) @@ -9,6 +8,16 @@ macro( calamares_skip_module ) set( SKIPPED_MODULES ${SKIPPED_MODULES} ${ARGV} PARENT_SCOPE ) endmacro() +function( calamares_explain_skipped_modules ) + if ( ARGN ) + message( "${ColorReset}-- Skipped modules:" ) + foreach( SUBDIRECTORY ${ARGN} ) + message( "${ColorReset}-- Skipped ${BoldRed}${SUBDIRECTORY}${ColorReset}." ) + endforeach() + message( "" ) + endif() +endfunction() + function( calamares_add_module_subdirectory ) set( SUBDIRECTORY ${ARGV0} ) diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 8235bc2e9..d793b718f 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -1,5 +1,3 @@ -include( CMakeColors ) - # The variable SKIP_MODULES can be set to skip particular modules; # individual modules can also decide they must be skipped (e.g. OS-specific # modules, or ones with unmet dependencies). Collect the skipped modules @@ -31,13 +29,9 @@ foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) endif() endforeach() -if ( LIST_SKIPPED_MODULES ) - message( "${ColorReset}-- Skipped modules:" ) - foreach( SUBDIRECTORY ${LIST_SKIPPED_MODULES} ) - message( "${ColorReset}-- Skipped ${BoldRed}${SUBDIRECTORY}${ColorReset}." ) - endforeach() - message( "" ) -endif() +# This is *also* done in top-level, so list is displayed +# both before and after the feature summary. +calamares_explain_skipped_modules( ${LIST_SKIPPED_MODULES} ) include( CalamaresAddTranslations ) add_calamares_python_translations( ${CALAMARES_TRANSLATION_LANGUAGES} ) From b0c4fbc1bb002bab9e9c92ed974f6af791735bac Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 13 Jan 2018 21:19:08 +0100 Subject: [PATCH 18/19] Clang: reduce warnings - mark some things override - make conversion of 0 to flags explicit --- src/calamares/CalamaresWindow.h | 2 +- src/modules/netinstall/PackageModel.cpp | 2 +- src/modules/tracking/TrackingJobs.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/calamares/CalamaresWindow.h b/src/calamares/CalamaresWindow.h index 19aeaa59e..faca8974a 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() {} + virtual ~CalamaresWindow() override {} public slots: /** diff --git a/src/modules/netinstall/PackageModel.cpp b/src/modules/netinstall/PackageModel.cpp index 6585abcee..3e721c017 100644 --- a/src/modules/netinstall/PackageModel.cpp +++ b/src/modules/netinstall/PackageModel.cpp @@ -144,7 +144,7 @@ Qt::ItemFlags PackageModel::flags( const QModelIndex& index ) const { if ( !index.isValid() ) - return 0; + return Qt::ItemFlags(); if ( index.column() == 0 ) return Qt::ItemIsUserCheckable | QAbstractItemModel::flags( index ); return QAbstractItemModel::flags( index ); diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h index 2d90c2b15..4ad3652ca 100644 --- a/src/modules/tracking/TrackingJobs.h +++ b/src/modules/tracking/TrackingJobs.h @@ -30,7 +30,7 @@ class TrackingInstallJob : public Calamares::Job Q_OBJECT public: TrackingInstallJob( const QString& url ); - ~TrackingInstallJob(); + ~TrackingInstallJob() override; QString prettyName() const override; QString prettyDescription() const override; From 2bc394656d3446369223200c5d48363a0c1d922a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 13 Jan 2018 21:26:31 +0100 Subject: [PATCH 19/19] [welcome] Make libparted optional - This turns off the space-available check in the welcome module; without libparted, always fail that check. - Allows running the welcome module on OS without libparted. --- src/modules/welcome/CMakeLists.txt | 20 ++++++++++++------- .../welcome/checker/RequirementsChecker.cpp | 5 +++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index 42ce62beb..a520aa080 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -1,20 +1,24 @@ include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) -find_package( LIBPARTED REQUIRED ) find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) +find_package( LIBPARTED ) +if ( LIBPARTED_FOUND ) + set( PARTMAN_SRC checker/partman_devices.c ) + set( CHECKER_LINK_LIBRARIES ${LIBPARTED_LIBRARY} ) +else() + set( PARTMAN_SRC ) + set( CHECKER_LINK_LIBRARIES ) + add_definitions( -DWITHOUT_LIBPARTED ) +endif() + include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) set( CHECKER_SOURCES checker/CheckItemWidget.cpp checker/CheckerWidget.cpp checker/RequirementsChecker.cpp - checker/partman_devices.c -) -set( CHECKER_LINK_LIBRARIES - ${LIBPARTED_LIBRARY} - Qt5::DBus - Qt5::Network + ${PARTMAN_SRC} ) calamares_add_plugin( welcome @@ -29,5 +33,7 @@ calamares_add_plugin( welcome LINK_PRIVATE_LIBRARIES calamaresui ${CHECKER_LINK_LIBRARIES} + Qt5::DBus + Qt5::Network SHARED_LIB ) diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/RequirementsChecker.cpp index f059cc914..4dbd977d1 100644 --- a/src/modules/welcome/checker/RequirementsChecker.cpp +++ b/src/modules/welcome/checker/RequirementsChecker.cpp @@ -313,7 +313,12 @@ RequirementsChecker::verdict() const bool RequirementsChecker::checkEnoughStorage( qint64 requiredSpace ) { +#ifdef WITHOUT_LIBPARTED + cDebug() << "WARNING: RequirementsChecker is configured without libparted."; + return false; +#else return check_big_enough( requiredSpace ); +#endif }