mirror of https://github.com/cutefishos/calamares
Merge pull request #147 from kkofler/fix-issue-31
keyboard: Write the keyboard model and layout settings to the root mount point.main
commit
99114e04d8
@ -0,0 +1,285 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
|
||||||
|
* Copyright 2014, Kevin Kofler <kevin.kofler@chello.at>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SetKeyboardLayoutJob.h>
|
||||||
|
|
||||||
|
#include "JobQueue.h"
|
||||||
|
#include "GlobalStorage.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/CalamaresUtilsSystem.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
|
||||||
|
SetKeyboardLayoutJob::SetKeyboardLayoutJob( const QString& model,
|
||||||
|
const QString& layout,
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 = m_convertedKeymapPath;
|
||||||
|
if ( !convertedKeymapPath.isEmpty() )
|
||||||
|
{
|
||||||
|
while ( convertedKeymapPath.startsWith( '/' ) )
|
||||||
|
convertedKeymapPath.remove( 0, 1 );
|
||||||
|
convertedKeymapPath = destDir.absoluteFilePath( convertedKeymapPath );
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||||
|
*
|
||||||
|
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
|
||||||
|
* Copyright 2014, Kevin Kofler <kevin.kofler@chello.at>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SETKEYBOARDLAYOUTJOB_H
|
||||||
|
#define SETKEYBOARDLAYOUTJOB_H
|
||||||
|
|
||||||
|
#include <Job.h>
|
||||||
|
|
||||||
|
|
||||||
|
class SetKeyboardLayoutJob : public Calamares::Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SetKeyboardLayoutJob( const QString& model,
|
||||||
|
const QString& layout,
|
||||||
|
const QString& variant,
|
||||||
|
const QString& xOrgConfFileName,
|
||||||
|
const QString& convertedKeymapPath );
|
||||||
|
|
||||||
|
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;
|
||||||
|
QString m_xOrgConfFileName;
|
||||||
|
QString m_convertedKeymapPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SETKEYBOARDLAYOUTJOB_H */
|
@ -0,0 +1,67 @@
|
|||||||
|
# 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
|
||||||
|
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
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
# The name of the file to write X11 keyboard settings to
|
||||||
|
# The default value is the name used by upstream systemd-localed.
|
||||||
|
# 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"
|
@ -1,5 +1,6 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
|
<file>kbd-model-map</file>
|
||||||
<file>images/restore.png</file>
|
<file>images/restore.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
Loading…
Reference in New Issue