From 4f9f7d7858d218ea480ed040257fec82966d21ae Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Tue, 11 Nov 2014 02:58:14 +0100 Subject: [PATCH 1/5] keyboard: Write the keyboard model and layout settings to the root mount point. This is implemented as a new SetKeyboardLayout job that does the work. Portions of the code are adapted from systemd-localed's source code, which is under a compatible license (LGPLv2.1+, can be converted to our GPLv3+ license). I ported it from C to to C++/Qt and made some minor tweaks to the mapping logic (from X11 to vconsole layouts) though. Fixes #31. Tested on a Fedora Remix (Kannolo 21) with the default module settings (finds the converted X11 keymaps for the virtual console) and with convertedKeymapPath: "" (does the legacy keymap conversion as expected). --- src/modules/keyboard/CMakeLists.txt | 1 + src/modules/keyboard/KeyboardPage.cpp | 17 ++ src/modules/keyboard/KeyboardPage.h | 4 + src/modules/keyboard/KeyboardViewStep.cpp | 38 ++- src/modules/keyboard/KeyboardViewStep.h | 4 + src/modules/keyboard/SetKeyboardLayoutJob.cpp | 255 ++++++++++++++++++ src/modules/keyboard/SetKeyboardLayoutJob.h | 49 ++++ src/modules/keyboard/kbd-model-map | 66 +++++ src/modules/keyboard/keyboard.conf | 7 + src/modules/keyboard/keyboard.qrc | 1 + 10 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 src/modules/keyboard/SetKeyboardLayoutJob.cpp create mode 100644 src/modules/keyboard/SetKeyboardLayoutJob.h create mode 100644 src/modules/keyboard/kbd-model-map create mode 100644 src/modules/keyboard/keyboard.conf diff --git a/src/modules/keyboard/CMakeLists.txt b/src/modules/keyboard/CMakeLists.txt index 99405c99f..c2a67aa22 100644 --- a/src/modules/keyboard/CMakeLists.txt +++ b/src/modules/keyboard/CMakeLists.txt @@ -6,6 +6,7 @@ calamares_add_plugin( keyboard SOURCES KeyboardViewStep.cpp KeyboardPage.cpp + SetKeyboardLayoutJob.cpp keyboardwidget/keyboardglobal.cpp keyboardwidget/keyboardpreview.cpp UI diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index 6961306a0..d110bc728 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -24,6 +24,7 @@ #include "ui_KeyboardPage.h" #include "keyboardwidget/keyboardpreview.h" +#include "SetKeyboardLayoutJob.h" #include "GlobalStorage.h" #include "JobQueue.h" @@ -188,6 +189,22 @@ KeyboardPage::prettyStatus() const } +QList< Calamares::job_ptr > +KeyboardPage::createJobs() +{ + QList< Calamares::job_ptr > list; + QString selectedModel = m_models.value( ui->comboBoxModel->currentText(), + "pc105" ); + + Calamares::Job* j = new SetKeyboardLayoutJob( selectedModel, + m_selectedLayout, + m_selectedVariant ); + list.append( Calamares::job_ptr( j ) ); + + return list; +} + + void KeyboardPage::finalize() { diff --git a/src/modules/keyboard/KeyboardPage.h b/src/modules/keyboard/KeyboardPage.h index 82b965a13..2861ed837 100644 --- a/src/modules/keyboard/KeyboardPage.h +++ b/src/modules/keyboard/KeyboardPage.h @@ -25,6 +25,8 @@ #include "keyboardwidget/keyboardglobal.h" +#include "Typedefs.h" + #include #include @@ -46,6 +48,8 @@ public: QString prettyStatus() const; + QList< Calamares::job_ptr > createJobs(); + void finalize(); protected slots: diff --git a/src/modules/keyboard/KeyboardViewStep.cpp b/src/modules/keyboard/KeyboardViewStep.cpp index ab8129b19..82d3d6d85 100644 --- a/src/modules/keyboard/KeyboardViewStep.cpp +++ b/src/modules/keyboard/KeyboardViewStep.cpp @@ -18,6 +18,9 @@ #include "KeyboardViewStep.h" +#include "JobQueue.h" +#include "GlobalStorage.h" + #include "KeyboardPage.h" @@ -97,7 +100,7 @@ KeyboardViewStep::isAtEnd() const QList< Calamares::job_ptr > KeyboardViewStep::jobs() const { - return QList< Calamares::job_ptr >(); + return m_jobs; } @@ -105,5 +108,38 @@ void KeyboardViewStep::onLeave() { m_widget->finalize(); + m_jobs = m_widget->createJobs(); m_prettyStatus = m_widget->prettyStatus(); } + + +void +KeyboardViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ + // Save the settings to the global settings for the SetKeyboardLayoutJob to use + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + + if ( configurationMap.contains( "xOrgConfFileName" ) && + configurationMap.value( "xOrgConfFileName" ).type() == QVariant::String && + !configurationMap.value( "xOrgConfFileName" ).toString().isEmpty() ) + { + gs->insert( "keyboardXOrgConfFileName", + configurationMap.value( "xOrgConfFileName" ) ); + } + else + { + gs->insert( "keyboardXOrgConfFileName", "00-keyboard.conf" ); + } + + if ( configurationMap.contains( "convertedKeymapPath" ) && + configurationMap.value( "convertedKeymapPath" ).type() == QVariant::String && + !configurationMap.value( "convertedKeymapPath" ).toString().isEmpty() ) + { + gs->insert( "keyboardConvertedKeymapPath", + configurationMap.value( "convertedKeymapPath" ) ); + } + else + { + gs->remove( "keyboardConvertedKeymapPath" ); + } +} diff --git a/src/modules/keyboard/KeyboardViewStep.h b/src/modules/keyboard/KeyboardViewStep.h index c5d8328c4..45c458057 100644 --- a/src/modules/keyboard/KeyboardViewStep.h +++ b/src/modules/keyboard/KeyboardViewStep.h @@ -54,10 +54,14 @@ public: void onLeave() override; + void setConfigurationMap( const QVariantMap& configurationMap ) override; + private: KeyboardPage* m_widget; bool m_nextEnabled; QString m_prettyStatus; + + QList< Calamares::job_ptr > m_jobs; }; #endif // KEYBOARDVIEWSTEP_H diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp new file mode 100644 index 000000000..a13c32fe8 --- /dev/null +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -0,0 +1,255 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * Copyright 2014, Kevin Kofler + * + * Portions from systemd (localed.c): + * Copyright 2011 Lennart Poettering + * Copyright 2013 Kay Sievers + * (originally under LGPLv2.1+, used under the LGPL to GPL conversion clause) + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include + +#include "JobQueue.h" +#include "GlobalStorage.h" +#include "utils/Logger.h" +#include "utils/CalamaresUtilsSystem.h" + +#include +#include +#include +#include + + +SetKeyboardLayoutJob::SetKeyboardLayoutJob( const QString& model, + const QString& layout, + const QString& variant ) + : Calamares::Job() + , m_model( model ) + , m_layout( layout ) + , m_variant( variant ) +{ +} + + +QString +SetKeyboardLayoutJob::prettyName() const +{ + return tr( "Set keyboard model to %1, layout to %2-%3" ).arg( m_model ) + .arg( m_layout ) + .arg( m_variant ); +} + + +QString +SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath ) const { + // No search path supplied, assume the distribution does not provide + // converted keymaps + if ( convertedKeymapPath.isEmpty() ) + return QString(); + + QDir convertedKeymapDir( convertedKeymapPath ); + QString name = m_variant.isEmpty() ? m_layout : (m_layout + '-' + m_variant); + + if ( convertedKeymapDir.exists( name + ".map" ) + || convertedKeymapDir.exists( name + ".map.gz" ) ) { + cDebug() << "Found converted keymap" << name; + + return name; + } + + return QString(); +} + + +QString +SetKeyboardLayoutJob::findLegacyKeymap() const { + int bestMatching = 0; + QString name; + + QFile file( ":/kbd-model-map" ); + file.open( QIODevice::ReadOnly | QIODevice::Text ); + QTextStream stream( &file ); + while ( !stream.atEnd() ) { + QString line = stream.readLine().trimmed(); + if ( line.isEmpty() || line.startsWith( '#' ) ) + continue; + + QStringList mapping = line.split( '\t', QString::SkipEmptyParts ); + if ( mapping.size() < 5 ) + continue; + + int matching = 0; + + // Determine how well matching this entry is + // We assume here that we have one X11 layout. If the UI changes to + // allow more than one layout, this should change too. + if ( m_layout == mapping[1] ) + // If we got an exact match, this is best + matching = 10; + // Look for an entry whose first layout matches ours + else if ( mapping[1].startsWith( m_layout + ',' ) ) + matching = 5; + + if (matching > 0) { + if ( m_model.isEmpty() || m_model == mapping[2] ) + matching++; + + QString mappingVariant = mapping[3]; + if ( mappingVariant == "-" ) + mappingVariant = QString(); + else if ( mappingVariant.startsWith( ',' ) ) + mappingVariant.remove( 1, 0 ); + + if ( m_variant == mappingVariant ) + matching++; + + // We ignore mapping[4], the xkb options, for now. If we ever + // allow setting options in the UI, we should match them here. + } + + // The best matching entry so far, then let's save that + if ( matching >= qMax( bestMatching, 1 ) ) { + cDebug() << "Found legacy keymap" << mapping[0] + << "with score" << matching; + + if ( matching > bestMatching ) { + bestMatching = matching; + name = mapping[0]; + } + } + } + + return name; +} + + +bool +SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, + const QString& convertedKeymapPath ) const { + QString keymap = findConvertedKeymap( convertedKeymapPath ); + if ( keymap.isEmpty() ) + keymap = findLegacyKeymap(); + if ( keymap.isEmpty() ) { + cDebug() << "Trying to use X11 layout" << m_layout + << "as the virtual console layout"; + keymap = m_layout; + } + + QStringList existingLines; + + // Read in the existing vconsole.conf, if it exists + QFile file( vconsoleConfPath ); + if ( file.exists() ) { + file.open( QIODevice::ReadOnly | QIODevice::Text ); + QTextStream stream( &file ); + while ( !stream.atEnd() ) + existingLines << stream.readLine(); + file.close(); + if ( stream.status() != QTextStream::Ok ) + return false; + } + + // Write out the existing lines and replace the KEYMAP= line + file.open( QIODevice::WriteOnly | QIODevice::Text ); + QTextStream stream( &file ); + bool found = false; + foreach ( const QString& existingLine, existingLines ) { + if ( existingLine.trimmed().startsWith( "KEYMAP=" ) ) { + stream << "KEYMAP=" << keymap << '\n'; + found = true; + } else + stream << existingLine << '\n'; + } + // Add a KEYMAP= line if there wasn't any + if (!found) + stream << "KEYMAP=" << keymap << '\n'; + stream.flush(); + file.close(); + + return (stream.status() == QTextStream::Ok); +} + + +bool +SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const { + QFile file( keyboardConfPath ); + file.open( QIODevice::WriteOnly | QIODevice::Text ); + 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"; + + if ( !m_layout.isEmpty() ) + stream << " Option \"XkbLayout\" \"" << m_layout << "\"\n"; + + if ( !m_model.isEmpty() ) + stream << " Option \"XkbModel\" \"" << m_model << "\"\n"; + + if ( !m_variant.isEmpty() ) + stream << " Option \"XkbVariant\" \"" << m_variant << "\"\n"; + + stream << "EndSection\n"; + stream.flush(); + + file.close(); + + return (stream.status() == QTextStream::Ok); +} + + +Calamares::JobResult +SetKeyboardLayoutJob::exec() +{ + // Read the location of the destination's / in the host file system from + // the global settings + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + QDir destDir( gs->value( "rootMountPoint" ).toString() ); + + // Get the path to the destination's /etc/vconsole.conf + QString vconsoleConfPath = destDir.absoluteFilePath( "etc/vconsole.conf" ); + + // Get the path to the destination's /etc/X11/xorg.conf.d/00-keyboard.conf + QString xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); + destDir.mkpath( xorgConfDPath ); + QString keyboardConfFile = gs->value( "keyboardXOrgConfFileName" ).toString(); + QString keyboardConfPath = QDir( xorgConfDPath ) + .absoluteFilePath( keyboardConfFile ); + + // Get the path to the destination's path to the converted key mappings + QString convertedKeymapPath; + QString convertedKeymapPathSetting + = gs->value( "keyboardConvertedKeymapPath" ).toString(); + if ( !convertedKeymapPathSetting.isEmpty() ) { + while ( convertedKeymapPathSetting.startsWith( '/' ) ) + convertedKeymapPathSetting.remove( 0, 1 ); + convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPathSetting ); + } + + if ( !writeVConsoleData( vconsoleConfPath, convertedKeymapPath ) ) + return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for the virtual console." ), + tr( "Failed to write to %1" ).arg( vconsoleConfPath ) ); + + if ( !writeX11Data( keyboardConfPath ) ) + return Calamares::JobResult::error( tr( "Failed to write keyboard configuration for X11." ), + tr( "Failed to write to %1" ).arg( keyboardConfPath ) ); + + return Calamares::JobResult::ok(); +} diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.h b/src/modules/keyboard/SetKeyboardLayoutJob.h new file mode 100644 index 000000000..710c9741a --- /dev/null +++ b/src/modules/keyboard/SetKeyboardLayoutJob.h @@ -0,0 +1,49 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * Copyright 2014, 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef SETKEYBOARDLAYOUTJOB_H +#define SETKEYBOARDLAYOUTJOB_H + +#include + + +class SetKeyboardLayoutJob : public Calamares::Job +{ + Q_OBJECT +public: + SetKeyboardLayoutJob( const QString& model, + const QString& layout, + const QString& variant ); + + QString prettyName() const override; + Calamares::JobResult exec() override; + +private: + QString findConvertedKeymap( const QString& convertedKeymapPath ) const; + QString findLegacyKeymap() const; + bool writeVConsoleData( const QString& vconsoleConfPath, + const QString& convertedKeymapPath ) const; + bool writeX11Data( const QString& keyboardConfPath ) const; + + QString m_model; + QString m_layout; + QString m_variant; +}; + +#endif /* SETKEYBOARDLAYOUTJOB_H */ diff --git a/src/modules/keyboard/kbd-model-map b/src/modules/keyboard/kbd-model-map new file mode 100644 index 000000000..136e543fb --- /dev/null +++ b/src/modules/keyboard/kbd-model-map @@ -0,0 +1,66 @@ +# Copied from systemd-localed +# (originally under LGPLv2.1+, used under the LGPL to GPL conversion clause) +# Generated from system-config-keyboard's model list +# consolelayout xlayout xmodel xvariant xoptions +sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp +nl nl pc105 - terminate:ctrl_alt_bksp +mk-utf mk,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +trq tr pc105 - terminate:ctrl_alt_bksp +uk gb pc105 - terminate:ctrl_alt_bksp +is-latin1 is pc105 - terminate:ctrl_alt_bksp +de de pc105 - terminate:ctrl_alt_bksp +la-latin1 latam pc105 - terminate:ctrl_alt_bksp +us us pc105+inet - terminate:ctrl_alt_bksp +ko kr pc105 - terminate:ctrl_alt_bksp +ro-std ro pc105 std terminate:ctrl_alt_bksp +de-latin1 de pc105 - terminate:ctrl_alt_bksp +slovene si pc105 - terminate:ctrl_alt_bksp +hu101 hu pc105 qwerty terminate:ctrl_alt_bksp +jp106 jp jp106 - terminate:ctrl_alt_bksp +croat hr pc105 - terminate:ctrl_alt_bksp +it2 it pc105 - terminate:ctrl_alt_bksp +hu hu pc105 - terminate:ctrl_alt_bksp +sr-latin rs pc105 latin terminate:ctrl_alt_bksp +fi fi pc105 - terminate:ctrl_alt_bksp +fr_CH ch pc105 fr terminate:ctrl_alt_bksp +dk-latin1 dk pc105 - terminate:ctrl_alt_bksp +fr fr pc105 - terminate:ctrl_alt_bksp +it it pc105 - terminate:ctrl_alt_bksp +ua-utf ua,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +fr-latin1 fr pc105 - terminate:ctrl_alt_bksp +sg-latin1 ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp +be-latin1 be pc105 - terminate:ctrl_alt_bksp +dk dk pc105 - terminate:ctrl_alt_bksp +fr-pc fr pc105 - terminate:ctrl_alt_bksp +bg_pho-utf8 bg,us pc105 ,phonetic terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +it-ibm it pc105 - terminate:ctrl_alt_bksp +cz-us-qwertz cz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +br-abnt2 br abnt2 - terminate:ctrl_alt_bksp +ro ro pc105 - terminate:ctrl_alt_bksp +us-acentos us pc105 intl terminate:ctrl_alt_bksp +pt-latin1 pt pc105 - terminate:ctrl_alt_bksp +ro-std-cedilla ro pc105 std_cedilla terminate:ctrl_alt_bksp +tj_alt-UTF8 tj pc105 - terminate:ctrl_alt_bksp +de-latin1-nodeadkeys de pc105 nodeadkeys terminate:ctrl_alt_bksp +no no pc105 - terminate:ctrl_alt_bksp +bg_bds-utf8 bg,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +dvorak us pc105 dvorak terminate:ctrl_alt_bksp +dvorak us pc105 dvorak-alt-intl terminate:ctrl_alt_bksp +ru ru,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +cz-lat2 cz pc105 qwerty terminate:ctrl_alt_bksp +pl2 pl pc105 - terminate:ctrl_alt_bksp +es es pc105 - terminate:ctrl_alt_bksp +ro-cedilla ro pc105 cedilla terminate:ctrl_alt_bksp +ie ie pc105 - terminate:ctrl_alt_bksp +et ee pc105 - terminate:ctrl_alt_bksp +sk-qwerty sk pc105 - terminate:ctrl_alt_bksp,qwerty +fr-latin9 fr pc105 latin9 terminate:ctrl_alt_bksp +fr_CH-latin1 ch pc105 fr terminate:ctrl_alt_bksp +cf ca pc105 - terminate:ctrl_alt_bksp +sv-latin1 se pc105 - terminate:ctrl_alt_bksp +sr-cy rs pc105 - terminate:ctrl_alt_bksp +gr gr,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +by by,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +il il pc105 - terminate:ctrl_alt_bksp +kazakh kz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +lt lt pc105 - terminate:ctrl_alt_bksp diff --git a/src/modules/keyboard/keyboard.conf b/src/modules/keyboard/keyboard.conf new file mode 100644 index 000000000..244639bd3 --- /dev/null +++ b/src/modules/keyboard/keyboard.conf @@ -0,0 +1,7 @@ +--- +# The name of the file to write to /etc/X11/xorg.conf.d +# The default value is the name used by upstream systemd-localed. +xOrgConfFileName: "00-keyboard.conf" +# The path to search for keymaps converted from X11 to kbd format +# Leave this empty if the setting does not make sense on your distribution. +convertedKeymapPath: "/lib/kbd/keymaps/xkb" diff --git a/src/modules/keyboard/keyboard.qrc b/src/modules/keyboard/keyboard.qrc index 3d5b1c1cd..dd211e630 100644 --- a/src/modules/keyboard/keyboard.qrc +++ b/src/modules/keyboard/keyboard.qrc @@ -1,5 +1,6 @@ + kbd-model-map images/restore.png From bfdcf0dbc0e1622fcde0859e76150e23365d681b Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Tue, 11 Nov 2014 13:57:08 +0100 Subject: [PATCH 2/5] keyboard: Coding style fixes. --- src/modules/keyboard/KeyboardPage.h | 3 +- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 53 ++++++++++++------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/modules/keyboard/KeyboardPage.h b/src/modules/keyboard/KeyboardPage.h index 2861ed837..9cb75ae6b 100644 --- a/src/modules/keyboard/KeyboardPage.h +++ b/src/modules/keyboard/KeyboardPage.h @@ -59,7 +59,8 @@ protected slots: QListWidgetItem* previous ); private: - class LayoutItem : public QListWidgetItem { + class LayoutItem : public QListWidgetItem + { public: QString data; KeyboardGlobal::KeyboardInfo info; diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index a13c32fe8..48196d14b 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -56,17 +56,19 @@ SetKeyboardLayoutJob::prettyName() const QString -SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath ) const { +SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath ) const +{ // No search path supplied, assume the distribution does not provide // converted keymaps if ( convertedKeymapPath.isEmpty() ) return QString(); QDir convertedKeymapDir( convertedKeymapPath ); - QString name = m_variant.isEmpty() ? m_layout : (m_layout + '-' + m_variant); + 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; return name; @@ -77,14 +79,16 @@ SetKeyboardLayoutJob::findConvertedKeymap( const QString& convertedKeymapPath ) QString -SetKeyboardLayoutJob::findLegacyKeymap() const { +SetKeyboardLayoutJob::findLegacyKeymap() const +{ int bestMatching = 0; QString name; QFile file( ":/kbd-model-map" ); file.open( QIODevice::ReadOnly | QIODevice::Text ); QTextStream stream( &file ); - while ( !stream.atEnd() ) { + while ( !stream.atEnd() ) + { QString line = stream.readLine().trimmed(); if ( line.isEmpty() || line.startsWith( '#' ) ) continue; @@ -105,7 +109,8 @@ SetKeyboardLayoutJob::findLegacyKeymap() const { else if ( mapping[1].startsWith( m_layout + ',' ) ) matching = 5; - if (matching > 0) { + if ( matching > 0 ) + { if ( m_model.isEmpty() || m_model == mapping[2] ) matching++; @@ -123,11 +128,13 @@ SetKeyboardLayoutJob::findLegacyKeymap() const { } // The best matching entry so far, then let's save that - if ( matching >= qMax( bestMatching, 1 ) ) { + if ( matching >= qMax( bestMatching, 1 ) ) + { cDebug() << "Found legacy keymap" << mapping[0] << "with score" << matching; - if ( matching > bestMatching ) { + if ( matching > bestMatching ) + { bestMatching = matching; name = mapping[0]; } @@ -140,11 +147,13 @@ SetKeyboardLayoutJob::findLegacyKeymap() const { bool SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, - const QString& convertedKeymapPath ) const { + const QString& convertedKeymapPath ) const +{ QString keymap = findConvertedKeymap( convertedKeymapPath ); if ( keymap.isEmpty() ) keymap = findLegacyKeymap(); - if ( keymap.isEmpty() ) { + if ( keymap.isEmpty() ) + { cDebug() << "Trying to use X11 layout" << m_layout << "as the virtual console layout"; keymap = m_layout; @@ -154,7 +163,8 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, // Read in the existing vconsole.conf, if it exists QFile file( vconsoleConfPath ); - if ( file.exists() ) { + if ( file.exists() ) + { file.open( QIODevice::ReadOnly | QIODevice::Text ); QTextStream stream( &file ); while ( !stream.atEnd() ) @@ -168,25 +178,29 @@ SetKeyboardLayoutJob::writeVConsoleData( const QString& vconsoleConfPath, file.open( QIODevice::WriteOnly | QIODevice::Text ); QTextStream stream( &file ); bool found = false; - foreach ( const QString& existingLine, existingLines ) { - if ( existingLine.trimmed().startsWith( "KEYMAP=" ) ) { + foreach ( const QString& existingLine, existingLines ) + { + if ( existingLine.trimmed().startsWith( "KEYMAP=" ) ) + { stream << "KEYMAP=" << keymap << '\n'; found = true; - } else + } + else stream << existingLine << '\n'; } // Add a KEYMAP= line if there wasn't any - if (!found) + if ( !found ) stream << "KEYMAP=" << keymap << '\n'; stream.flush(); file.close(); - return (stream.status() == QTextStream::Ok); + return ( stream.status() == QTextStream::Ok ); } bool -SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const { +SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const +{ QFile file( keyboardConfPath ); file.open( QIODevice::WriteOnly | QIODevice::Text ); QTextStream stream( &file ); @@ -211,7 +225,7 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const { file.close(); - return (stream.status() == QTextStream::Ok); + return ( stream.status() == QTextStream::Ok ); } @@ -237,7 +251,8 @@ SetKeyboardLayoutJob::exec() QString convertedKeymapPath; QString convertedKeymapPathSetting = gs->value( "keyboardConvertedKeymapPath" ).toString(); - if ( !convertedKeymapPathSetting.isEmpty() ) { + if ( !convertedKeymapPathSetting.isEmpty() ) + { while ( convertedKeymapPathSetting.startsWith( '/' ) ) convertedKeymapPathSetting.remove( 0, 1 ); convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPathSetting ); From 2fec6e320234fab943b97a3f22d72eb134806a4d Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Tue, 11 Nov 2014 14:04:21 +0100 Subject: [PATCH 3/5] keyboard: kbd-model-map: Add link to the original. In particular, to the upstream git log for the file. --- src/modules/keyboard/kbd-model-map | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/keyboard/kbd-model-map b/src/modules/keyboard/kbd-model-map index 136e543fb..7f76f8af8 100644 --- a/src/modules/keyboard/kbd-model-map +++ b/src/modules/keyboard/kbd-model-map @@ -1,4 +1,5 @@ # Copied from systemd-localed +# http://cgit.freedesktop.org/systemd/systemd/log/src/locale/kbd-model-map # (originally under LGPLv2.1+, used under the LGPL to GPL conversion clause) # Generated from system-config-keyboard's model list # consolelayout xlayout xmodel xvariant xoptions From 86d51b4a9cbee6f965d12b44b77952ff26ded9c0 Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Tue, 11 Nov 2014 14:37:05 +0100 Subject: [PATCH 4/5] keyboard: Pass settings directly, not through GlobalStorage. Pass the settings from keyboard.conf directly to the SetKeyboardLayoutJob rather than through GlobalStorage. --- src/modules/keyboard/KeyboardPage.cpp | 7 +++++-- src/modules/keyboard/KeyboardPage.h | 3 ++- src/modules/keyboard/KeyboardViewStep.cpp | 14 +++++++------- src/modules/keyboard/KeyboardViewStep.h | 3 +++ src/modules/keyboard/SetKeyboardLayoutJob.cpp | 12 +++++++----- src/modules/keyboard/SetKeyboardLayoutJob.h | 6 +++++- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/modules/keyboard/KeyboardPage.cpp b/src/modules/keyboard/KeyboardPage.cpp index d110bc728..7170505c5 100644 --- a/src/modules/keyboard/KeyboardPage.cpp +++ b/src/modules/keyboard/KeyboardPage.cpp @@ -190,7 +190,8 @@ KeyboardPage::prettyStatus() const QList< Calamares::job_ptr > -KeyboardPage::createJobs() +KeyboardPage::createJobs( const QString& xOrgConfFileName, + const QString& convertedKeymapPath ) { QList< Calamares::job_ptr > list; QString selectedModel = m_models.value( ui->comboBoxModel->currentText(), @@ -198,7 +199,9 @@ KeyboardPage::createJobs() Calamares::Job* j = new SetKeyboardLayoutJob( selectedModel, m_selectedLayout, - m_selectedVariant ); + m_selectedVariant, + xOrgConfFileName, + convertedKeymapPath ); list.append( Calamares::job_ptr( j ) ); return list; diff --git a/src/modules/keyboard/KeyboardPage.h b/src/modules/keyboard/KeyboardPage.h index 9cb75ae6b..e4ed5b715 100644 --- a/src/modules/keyboard/KeyboardPage.h +++ b/src/modules/keyboard/KeyboardPage.h @@ -48,7 +48,8 @@ public: QString prettyStatus() const; - QList< Calamares::job_ptr > createJobs(); + QList< Calamares::job_ptr > createJobs( const QString& xOrgConfFileName, + const QString& convertedKeymapPath ); void finalize(); diff --git a/src/modules/keyboard/KeyboardViewStep.cpp b/src/modules/keyboard/KeyboardViewStep.cpp index 82d3d6d85..d613171e3 100644 --- a/src/modules/keyboard/KeyboardViewStep.cpp +++ b/src/modules/keyboard/KeyboardViewStep.cpp @@ -108,7 +108,7 @@ void KeyboardViewStep::onLeave() { m_widget->finalize(); - m_jobs = m_widget->createJobs(); + m_jobs = m_widget->createJobs( m_xOrgConfFileName, m_convertedKeymapPath ); m_prettyStatus = m_widget->prettyStatus(); } @@ -123,23 +123,23 @@ KeyboardViewStep::setConfigurationMap( const QVariantMap& configurationMap ) configurationMap.value( "xOrgConfFileName" ).type() == QVariant::String && !configurationMap.value( "xOrgConfFileName" ).toString().isEmpty() ) { - gs->insert( "keyboardXOrgConfFileName", - configurationMap.value( "xOrgConfFileName" ) ); + m_xOrgConfFileName = configurationMap.value( "xOrgConfFileName" ) + .toString(); } else { - gs->insert( "keyboardXOrgConfFileName", "00-keyboard.conf" ); + m_xOrgConfFileName = "00-keyboard.conf"; } if ( configurationMap.contains( "convertedKeymapPath" ) && configurationMap.value( "convertedKeymapPath" ).type() == QVariant::String && !configurationMap.value( "convertedKeymapPath" ).toString().isEmpty() ) { - gs->insert( "keyboardConvertedKeymapPath", - configurationMap.value( "convertedKeymapPath" ) ); + m_convertedKeymapPath = configurationMap.value( "convertedKeymapPath" ) + .toString(); } else { - gs->remove( "keyboardConvertedKeymapPath" ); + m_convertedKeymapPath = QString(); } } diff --git a/src/modules/keyboard/KeyboardViewStep.h b/src/modules/keyboard/KeyboardViewStep.h index 45c458057..d88343bda 100644 --- a/src/modules/keyboard/KeyboardViewStep.h +++ b/src/modules/keyboard/KeyboardViewStep.h @@ -61,6 +61,9 @@ private: bool m_nextEnabled; QString m_prettyStatus; + QString m_xOrgConfFileName; + QString m_convertedKeymapPath; + QList< Calamares::job_ptr > m_jobs; }; diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 48196d14b..1160759d1 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -37,11 +37,15 @@ SetKeyboardLayoutJob::SetKeyboardLayoutJob( const QString& model, const QString& layout, - const QString& variant ) + const QString& variant, + const QString& xOrgConfFileName, + const QString& convertedKeymapPath ) : Calamares::Job() , m_model( model ) , m_layout( layout ) , m_variant( variant ) + , m_xOrgConfFileName( xOrgConfFileName ) + , m_convertedKeymapPath( convertedKeymapPath ) { } @@ -243,14 +247,12 @@ SetKeyboardLayoutJob::exec() // Get the path to the destination's /etc/X11/xorg.conf.d/00-keyboard.conf QString xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); destDir.mkpath( xorgConfDPath ); - QString keyboardConfFile = gs->value( "keyboardXOrgConfFileName" ).toString(); QString keyboardConfPath = QDir( xorgConfDPath ) - .absoluteFilePath( keyboardConfFile ); + .absoluteFilePath( m_xOrgConfFileName ); // Get the path to the destination's path to the converted key mappings QString convertedKeymapPath; - QString convertedKeymapPathSetting - = gs->value( "keyboardConvertedKeymapPath" ).toString(); + QString convertedKeymapPathSetting = m_convertedKeymapPath; if ( !convertedKeymapPathSetting.isEmpty() ) { while ( convertedKeymapPathSetting.startsWith( '/' ) ) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.h b/src/modules/keyboard/SetKeyboardLayoutJob.h index 710c9741a..096a1fce3 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.h +++ b/src/modules/keyboard/SetKeyboardLayoutJob.h @@ -29,7 +29,9 @@ class SetKeyboardLayoutJob : public Calamares::Job public: SetKeyboardLayoutJob( const QString& model, const QString& layout, - const QString& variant ); + const QString& variant, + const QString& xOrgConfFileName, + const QString& convertedKeymapPath ); QString prettyName() const override; Calamares::JobResult exec() override; @@ -44,6 +46,8 @@ private: QString m_model; QString m_layout; QString m_variant; + QString m_xOrgConfFileName; + QString m_convertedKeymapPath; }; #endif /* SETKEYBOARDLAYOUTJOB_H */ From 3e9de2a05aae39a912447a321628ba19cb02176a Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Tue, 11 Nov 2014 14:59:30 +0100 Subject: [PATCH 5/5] keyboard: Allow absolute paths for the xOrgConfFileName setting. This should ensure it works on all distributions. --- src/modules/keyboard/SetKeyboardLayoutJob.cpp | 31 +++++++++++++------ src/modules/keyboard/keyboard.conf | 5 +-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/modules/keyboard/SetKeyboardLayoutJob.cpp b/src/modules/keyboard/SetKeyboardLayoutJob.cpp index 1160759d1..162b97f54 100644 --- a/src/modules/keyboard/SetKeyboardLayoutJob.cpp +++ b/src/modules/keyboard/SetKeyboardLayoutJob.cpp @@ -30,6 +30,7 @@ #include "utils/CalamaresUtilsSystem.h" #include +#include #include #include #include @@ -245,19 +246,31 @@ SetKeyboardLayoutJob::exec() QString vconsoleConfPath = destDir.absoluteFilePath( "etc/vconsole.conf" ); // Get the path to the destination's /etc/X11/xorg.conf.d/00-keyboard.conf - QString xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); - destDir.mkpath( xorgConfDPath ); - QString keyboardConfPath = QDir( xorgConfDPath ) + QString xorgConfDPath; + QString keyboardConfPath; + if ( QDir::isAbsolutePath( m_xOrgConfFileName ) ) + { + keyboardConfPath = m_xOrgConfFileName; + while ( keyboardConfPath.startsWith( '/' ) ) + keyboardConfPath.remove( 0, 1 ); + keyboardConfPath = destDir.absoluteFilePath( keyboardConfPath ); + xorgConfDPath = QFileInfo( keyboardConfPath ).path(); + } + else + { + xorgConfDPath = destDir.absoluteFilePath( "etc/X11/xorg.conf.d" ); + keyboardConfPath = QDir( xorgConfDPath ) .absoluteFilePath( m_xOrgConfFileName ); + } + destDir.mkpath( xorgConfDPath ); // Get the path to the destination's path to the converted key mappings - QString convertedKeymapPath; - QString convertedKeymapPathSetting = m_convertedKeymapPath; - if ( !convertedKeymapPathSetting.isEmpty() ) + QString convertedKeymapPath = m_convertedKeymapPath; + if ( !convertedKeymapPath.isEmpty() ) { - while ( convertedKeymapPathSetting.startsWith( '/' ) ) - convertedKeymapPathSetting.remove( 0, 1 ); - convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPathSetting ); + while ( convertedKeymapPath.startsWith( '/' ) ) + convertedKeymapPath.remove( 0, 1 ); + convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPath ); } if ( !writeVConsoleData( vconsoleConfPath, convertedKeymapPath ) ) diff --git a/src/modules/keyboard/keyboard.conf b/src/modules/keyboard/keyboard.conf index 244639bd3..a2606b94e 100644 --- a/src/modules/keyboard/keyboard.conf +++ b/src/modules/keyboard/keyboard.conf @@ -1,7 +1,8 @@ --- -# The name of the file to write to /etc/X11/xorg.conf.d +# The name of the file to write X11 keyboard settings to # The default value is the name used by upstream systemd-localed. -xOrgConfFileName: "00-keyboard.conf" +# Relative paths are assumed to be relative to /etc/X11/xorg.conf.d +xOrgConfFileName: "/etc/X11/xorg.conf.d/00-keyboard.conf" # The path to search for keymaps converted from X11 to kbd format # Leave this empty if the setting does not make sense on your distribution. convertedKeymapPath: "/lib/kbd/keymaps/xkb"