ubuntu-22.04.3-desktop-amd64/casper/filesystem/usr/lib/ubiquity/plugins/ubi-console-setup.py

868 lines
35 KiB
Python

# -*- coding: utf-8; Mode: Python; indent-tabs-mode: nil; tab-width: 4 -*-
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd.
# Written by Tollef Fog Heen <tfheen@ubuntu.com> and
# Colin Watson <cjwatson@ubuntu.com>
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import re
from ubiquity import gsettings, keyboard_names, misc, osextras, plugin
NAME = 'console_setup'
AFTER = 'language'
WEIGHT = 10
class PageGtk(plugin.PluginUI):
plugin_title = 'ubiquity/text/keyboard_heading_label'
def __init__(self, controller, *args, **kwargs):
self.controller = controller
self.current_layout = None
self.keyboard_layout_timeout_id = 0
self.keyboard_variant_timeout_id = 0
try:
from gi.repository import Gtk
builder = Gtk.Builder()
self.controller.add_builder(builder)
builder.add_from_file(os.path.join(
os.environ['UBIQUITY_GLADE'], 'stepKeyboardConf.ui'))
builder.connect_signals(self)
self.page = builder.get_object('stepKeyboardConf')
self.keyboardlayoutview = builder.get_object('keyboardlayoutview')
self.keyboardvariantview = builder.get_object(
'keyboardvariantview')
self.calculate_keymap_button = builder.get_object('deduce_layout')
self.keyboard_test = builder.get_object('keyboard_test')
self.calculate_keymap_button.connect(
'clicked', self.calculate_clicked)
except Exception as e:
self.debug('Could not create keyboard page: %s', e)
self.page = None
self.plugin_widgets = self.page
def plugin_translate(self, lang):
# TODO Move back into the frontend as we can check
# isinstance(LabelledEntry) and just call set_label. We'll need to
# properly name the debconf keys though (s/inactive_label//)
test_label = self.controller.get_string('keyboard_test_label', lang)
self.keyboard_test.set_placeholder_text(test_label)
def cancel_timeouts(self):
from gi.repository import GLib
if self.keyboard_layout_timeout_id:
GLib.source_remove(self.keyboard_layout_timeout_id)
if self.keyboard_variant_timeout_id:
GLib.source_remove(self.keyboard_variant_timeout_id)
@plugin.only_this_page
def calculate_result(self, w, keymap):
ret = self.controller.dbfilter.get_locale()
keymap = keymap.split(':')
if len(keymap) == 1:
keymap.append('')
layout = keyboard_names.layout_human(ret, keymap[0])
variant = keyboard_names.variant_human(ret, keymap[0], keymap[1])
self.set_keyboard(layout)
self.controller.dbfilter.change_layout(layout)
self.controller.dbfilter.apply_keyboard(layout, variant)
# Necessary to clean up references so self.query is garbage collected.
self.calculate_closed()
def calculate_closed(self, *args):
if self.query:
self.query.destroy()
self.query = None
def calculate_clicked(self, *args):
from ubiquity.frontend.gtk_components.keyboard_query import (
KeyboardQuery,
)
self.query = KeyboardQuery(self.controller._wizard)
self.query.connect('layout_result', self.calculate_result)
self.query.connect('delete-event', self.calculate_closed)
# self.controller._wizard.overlay.set_property('greyed', True)
self.query.set_transient_for(self.page.get_toplevel())
self.query.run()
def on_keyboardlayoutview_row_activated(self, *args):
self.controller.go_forward()
@plugin.only_this_page
def on_keyboard_layout_selected(self, *args):
if not self.is_automatic:
# Let's not call this every time the user presses a key.
from gi.repository import GLib
if self.keyboard_layout_timeout_id:
GLib.source_remove(self.keyboard_layout_timeout_id)
self.keyboard_layout_timeout_id = GLib.timeout_add(
600, self.keyboard_layout_timeout)
else:
self.keyboard_layout_timeout()
def keyboard_layout_timeout(self, *args):
layout = self.get_keyboard()
if layout is not None and layout != self.current_layout:
self.current_layout = layout
self.controller.dbfilter.change_layout(layout)
return False
def on_keyboardvariantview_row_activated(self, *args):
self.controller.go_forward()
@plugin.only_this_page
def on_keyboard_variant_selected(self, *args):
if not self.is_automatic:
# Let's not call this every time the user presses a key.
from gi.repository import GLib
if self.keyboard_variant_timeout_id:
GLib.source_remove(self.keyboard_variant_timeout_id)
self.keyboard_variant_timeout_id = GLib.timeout_add(
600, self.keyboard_variant_timeout)
else:
self.keyboard_variant_timeout()
def keyboard_variant_timeout(self, *args):
layout = self.get_keyboard()
variant = self.get_keyboard_variant()
if layout is not None and variant is not None:
self.controller.dbfilter.apply_keyboard(layout, variant)
return False
def set_keyboard_choices(self, choices):
# Sort the choices including these with accents
import locale
try:
# Try with the current locale (will fail if not generated
# pre-install)
locale.setlocale(locale.LC_ALL, '')
except locale.Error:
try:
if os.path.exists("/etc/locale.gen"):
# Try with the locale generated by casper
with open("/etc/locale.gen", "r") as locale_gen:
locale.setlocale(
locale.LC_ALL, locale_gen.read().split()[0])
else:
# Try a default, usually working locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
choices.sort(key=lambda c: locale.strxfrm(c.encode('utf-8')))
except Exception:
# Let's avoid crashing when we get a bad locale
choices.sort()
from gi.repository import Gtk, GObject
layouts = Gtk.ListStore(GObject.TYPE_STRING)
self.keyboardlayoutview.set_model(layouts)
for v in choices:
layouts.append([v])
if len(self.keyboardlayoutview.get_columns()) < 1:
column = Gtk.TreeViewColumn(
"Layout", Gtk.CellRendererText(), text=0)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
self.keyboardlayoutview.append_column(column)
selection = self.keyboardlayoutview.get_selection()
selection.connect('changed',
self.on_keyboard_layout_selected)
if self.current_layout is not None:
self.set_keyboard(self.current_layout)
def set_keyboard(self, layout):
self.current_layout = layout
model = self.keyboardlayoutview.get_model()
if model is None:
return
iterator = model.iter_children(None)
while iterator is not None:
if misc.utf8(model.get_value(iterator, 0)) == layout:
path = model.get_path(iterator)
selection = self.keyboardlayoutview.get_selection()
if not selection.path_is_selected(path):
selection.select_path(path)
self.keyboardlayoutview.scroll_to_cell(
path, use_align=True, row_align=0.5)
break
iterator = model.iter_next(iterator)
def get_keyboard(self):
selection = self.keyboardlayoutview.get_selection()
(model, iterator) = selection.get_selected()
if iterator is None:
return None
else:
return misc.utf8(model.get_value(iterator, 0))
def set_keyboard_variant_choices(self, choices):
from gi.repository import Gtk, GObject
variants = Gtk.ListStore(GObject.TYPE_STRING)
self.keyboardvariantview.set_model(variants)
for v in sorted(choices):
variants.append([v])
if len(self.keyboardvariantview.get_columns()) < 1:
column = Gtk.TreeViewColumn(
"Variant", Gtk.CellRendererText(), text=0)
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
self.keyboardvariantview.append_column(column)
selection = self.keyboardvariantview.get_selection()
selection.connect('changed',
self.on_keyboard_variant_selected)
def set_keyboard_variant(self, variant):
model = self.keyboardvariantview.get_model()
if model is None:
return
iterator = model.iter_children(None)
while iterator is not None:
if misc.utf8(model.get_value(iterator, 0)) == variant:
path = model.get_path(iterator)
self.keyboardvariantview.get_selection().select_path(path)
self.keyboardvariantview.scroll_to_cell(
path, use_align=True, row_align=0.5)
break
iterator = model.iter_next(iterator)
def get_keyboard_variant(self):
selection = self.keyboardvariantview.get_selection()
(model, iterator) = selection.get_selected()
if iterator is None:
return None
else:
return misc.utf8(model.get_value(iterator, 0))
class PageKde(plugin.PluginUI):
plugin_breadcrumb = 'ubiquity/text/breadcrumb_keyboard'
def __init__(self, controller, *args, **kwargs):
self.controller = controller
self.current_layout = None
self.default_keyboard_layout = None
self.default_keyboard_variant = None
try:
from PyQt5 import uic
from PyQt5.QtWidgets import QVBoxLayout
from ubiquity.frontend.kde_components.Keyboard import Keyboard
self.page = uic.loadUi(
'/usr/share/ubiquity/qt/stepKeyboardConf.ui')
self.keyboardDisplay = Keyboard(self.page.keyboard_frame)
self.page.keyboard_frame.setLayout(QVBoxLayout())
self.page.keyboard_frame.layout().addWidget(self.keyboardDisplay)
# use activated instead of changed because we only want to act
# when the user changes the selection not when we are populating
# the combo box
self.page.keyboard_layout_combobox.activated.connect(
self.on_keyboard_layout_selected)
self.page.keyboard_variant_combobox.activated.connect(
self.on_keyboard_variant_selected)
except Exception as e:
self.debug('Could not create keyboard page: %s', e)
self.page = None
self.plugin_widgets = self.page
@plugin.only_this_page
def on_keyboard_layout_selected(self, *args):
layout = self.get_keyboard()
lang = self.controller.dbfilter.get_locale()
if layout is not None:
# skip updating keyboard if not using display
if self.keyboardDisplay:
try:
ly = keyboard_names.layout_id(lang, misc.utf8(layout))
except KeyError:
ly = keyboard_names.layout_id('C', misc.utf8(layout))
self.keyboardDisplay.setLayout(ly)
# no variants, force update by setting none
# if not keyboard_names.has_variants(l, ly):
# self.keyboardDisplay.setVariant(None)
self.current_layout = layout
self.controller.dbfilter.change_layout(layout)
@plugin.only_this_page
def on_keyboard_variant_selected(self, *args):
layout = self.get_keyboard()
variant = self.get_keyboard_variant()
if self.keyboardDisplay:
var = None
lang = self.controller.dbfilter.get_locale()
try:
ly = keyboard_names.layout_id(lang, layout)
except KeyError:
ly = keyboard_names.layout_id('C', layout)
if variant:
try:
var = keyboard_names.variant_id(lang, ly,
misc.utf8(variant))
except KeyError:
var = None
self.keyboardDisplay.setVariant(var)
if layout is not None and variant is not None:
self.controller.dbfilter.apply_keyboard(layout, variant)
def set_keyboard_choices(self, choices):
self.page.keyboard_layout_combobox.clear()
for choice in sorted(choices):
self.page.keyboard_layout_combobox.addItem(misc.utf8(choice))
if self.current_layout is not None:
self.set_keyboard(self.current_layout)
@plugin.only_this_page
def set_keyboard(self, layout):
index = self.page.keyboard_layout_combobox.findText(misc.utf8(layout))
if index > -1:
self.page.keyboard_layout_combobox.setCurrentIndex(index)
if self.keyboardDisplay:
lang = self.controller.dbfilter.get_locale()
try:
ly = keyboard_names.layout_id(lang, misc.utf8(layout))
except KeyError:
ly = keyboard_names.layout_id('C', misc.utf8(layout))
self.keyboardDisplay.setLayout(ly)
def get_keyboard(self):
if self.page.keyboard_layout_combobox.currentIndex() < 0:
return None
return str(self.page.keyboard_layout_combobox.currentText())
def set_keyboard_variant_choices(self, choices):
self.page.keyboard_variant_combobox.clear()
for choice in sorted(choices):
self.page.keyboard_variant_combobox.addItem(misc.utf8(choice))
@plugin.only_this_page
def set_keyboard_variant(self, variant):
index = self.page.keyboard_variant_combobox.findText(
misc.utf8(variant))
if index > -1:
self.page.keyboard_variant_combobox.setCurrentIndex(index)
if self.keyboardDisplay:
lang = self.controller.dbfilter.get_locale()
try:
layout = keyboard_names.layout_id(lang, self.get_keyboard())
except KeyError:
layout = keyboard_names.layout_id('C', self.get_keyboard())
if variant:
try:
var = keyboard_names.variant_id(
lang, layout, misc.utf8(variant))
except KeyError:
var = None
self.keyboardDisplay.setVariant(var)
def get_keyboard_variant(self):
if self.page.keyboard_variant_combobox.currentIndex() < 0:
return None
return str(self.page.keyboard_variant_combobox.currentText())
class PageDebconf(plugin.PluginUI):
plugin_title = 'ubiquity/text/keyboard_heading_label'
class PageNoninteractive(plugin.PluginUI):
def set_keyboard_choices(self, choices):
"""Set the available keyboard layout choices."""
pass
def set_keyboard(self, layout):
"""Set the current keyboard layout."""
self.current_layout = layout
def get_keyboard(self):
"""Get the current keyboard layout."""
return self.current_layout
def set_keyboard_variant_choices(self, choices):
"""Set the available keyboard variant choices."""
pass
def set_keyboard_variant(self, variant):
"""Set the current keyboard variant."""
self.keyboard_variant = variant
def get_keyboard_variant(self):
return self.keyboard_variant
class Page(plugin.Plugin):
def prepare(self, unfiltered=False):
self.preseed('console-setup/ask_detect', 'false')
# We need to get rid of /etc/default/keyboard, or console-setup will
# think it's already configured and behave differently. Try to save
# the old file for interest's sake, but it's not a big deal if we
# can't.
with misc.raised_privileges():
osextras.unlink_force('/etc/default/keyboard.pre-ubiquity')
try:
os.rename('/etc/default/keyboard',
'/etc/default/keyboard.pre-ubiquity')
except OSError:
osextras.unlink_force('/etc/default/keyboard')
# Make sure debconf doesn't do anything with crazy "preseeded"
# answers to these questions. If you want to preseed these, use the
# *code variants.
self.db.fset('keyboard-configuration/layout', 'seen', 'false')
self.db.fset('keyboard-configuration/variant', 'seen', 'false')
self.db.fset('keyboard-configuration/model', 'seen', 'false')
self.db.fset('console-setup/codeset47', 'seen', 'false')
# Roughly taken from console-setup's config.proto:
di_locale = self.db.get('debian-installer/locale')
ret = di_locale.rsplit('.', 1)[0]
if not keyboard_names.has_language(ret):
self.debug("No keyboard layout translations for locale '%s'" % ret)
ret = ret.rsplit('_', 1)[0]
if not keyboard_names.has_language(ret):
self.debug("No keyboard layout translations for locale '%s'" % ret)
# TODO should this be C.UTF-8?!
ret = 'C'
self._locale = ret
self.has_variants = False
self.gnome_input_sources = self.get_gnome_input_sources()
# Technically we should provide a version as the second argument,
# but that isn't currently needed and it would require querying
# apt/dpkg for the current version, which would be slow, so we don't
# bother for now.
command = [
'/usr/lib/ubiquity/console-setup/keyboard-configuration.postinst',
'configure',
]
questions = [
'^keyboard-configuration/layout',
'^keyboard-configuration/variant',
'^keyboard-configuration/model',
'^keyboard-configuration/altgr$',
'^keyboard-configuration/unsupported_',
]
environ = {
'OVERRIDE_ALLOW_PRESEEDING': '1',
'OVERRIDE_USE_DEBCONF_LOCALE': '1',
'LC_ALL': di_locale,
'PATH': '/usr/lib/ubiquity/console-setup:' + os.environ['PATH'],
'DPKG_MAINTSCRIPT_NAME': 'postinst',
'DPKG_MAINTSCRIPT_PACKAGE': 'keyboard-configuration',
}
return command, questions, environ
# keyboard-configuration has a complex model of whether to store defaults
# in debconf, induced by its need to run well both in an installer context
# and as a package. We need to adjust this while we're running in order
# that we can go back and forward without keyboard-configuration
# overwriting our answers with default values.
def store_defaults(self, store):
self.preseed_bool(
'keyboard-configuration/store_defaults_in_debconf_db', store,
seen=False)
def run(self, priority, question):
if self.done:
return self.succeeded
if question == 'keyboard-configuration/layout':
# TODO cjwatson 2006-09-07: no keyboard-configuration support
# for layout choice translation yet
self.ui.set_keyboard_choices(
self.choices_untranslated(question))
self.ui.set_keyboard(misc.utf8(self.db.get(question)))
# Reset these in case we just backed up from the variant
# question.
self.store_defaults(True)
self.has_variants = False
self.succeeded = True
return True
elif question in ('keyboard-configuration/variant',
'keyboard-configuration/altgr'):
if question == 'keyboard-configuration/altgr':
if self.has_variants:
return True
else:
# If there's only one variant, it is always the same as
# the layout name.
single_variant = misc.utf8(self.db.get(
'keyboard-configuration/layout'))
self.ui.set_keyboard_variant_choices([single_variant])
self.ui.set_keyboard_variant(single_variant)
else:
# TODO cjwatson 2006-10-02: no keyboard-configuration
# support for variant choice translation yet
self.has_variants = True
self.ui.set_keyboard_variant_choices(
self.choices_untranslated(question))
self.ui.set_keyboard_variant(misc.utf8(self.db.get(question)))
# keyboard-configuration preseeding is special, and needs to be
# checked by hand. The seen flag on
# keyboard-configuration/layout is used internally by
# keyboard-configuration, so we can't just force it to true.
if (self.is_automatic and
self.db.fget(
'keyboard-configuration/layoutcode', 'seen') == 'true'):
return True
else:
return plugin.Plugin.run(self, priority, question)
elif question == 'keyboard-configuration/model':
# Backing up from the variant question inconveniently goes back
# to the model question. Catch this and go forward again so
# that we can reach the layout question.
return True
elif question.startswith('keyboard-configuration/unsupported_'):
response = self.frontend.question_dialog(
self.description(question),
self.extended_description(question),
('ubiquity/imported/yes', 'ubiquity/imported/no'))
if response == 'ubiquity/imported/yes':
self.preseed(question, 'true')
else:
self.preseed(question, 'false')
return True
else:
return True
def change_layout(self, layout):
self.preseed('keyboard-configuration/layout', layout)
self.store_defaults(False)
# Back up in order to get keyboard-configuration to recalculate the
# list of possible variants.
self.succeeded = False
self.exit_ui_loops()
def cancel_handler(self):
if hasattr(self.ui, "cancel_timeouts"):
self.ui.cancel_timeouts()
return plugin.Plugin.cancel_handler(self)
def ok_handler(self):
variant = self.ui.get_keyboard_variant()
if variant is not None:
self.preseed('keyboard-configuration/variant', variant)
if hasattr(self.ui, "cancel_timeouts"):
self.ui.cancel_timeouts()
return plugin.Plugin.ok_handler(self)
# TODO cjwatson 2006-09-07: This is duplication from
# keyboard-configuration, but currently difficult to avoid; we need to
# apply the keymap immediately when the user selects it in the UI (and
# before they move to the next page), so this needs to be fast and
# moving through keyboard-configuration to get the corrections it
# applies will be too slow.
def adjust_keyboard(self, model, layout, variant, options):
"""Apply any necessary tweaks to the supplied model, layout, variant,
and options."""
if layout in ('am', 'ara', 'ben', 'bd', 'bg', 'bt', 'by', 'deva', 'ge',
'gh', 'gr', 'guj', 'guru', 'il', 'in', 'ir', 'iku',
'kan', 'kh', 'kz', 'la', 'lao', 'lk', 'mk', 'mm', 'mn',
'mv', 'mal', 'ori', 'pk', 'ru', 'scc', 'sy', 'syr',
'tel', 'th', 'tj', 'tam', 'ua', 'uz'):
latin = False
real_layout = 'us,%s' % layout
elif layout == 'jp':
if variant in ('106', 'common', 'OADG109A', 'nicola_f_bs', ''):
latin = True
real_layout = layout
else:
latin = False
real_layout = 'jp,jp'
elif layout == 'lt':
latin = False
real_layout = 'lt,lt'
elif layout == 'me':
if variant == 'basic' or variant.startswith('latin'):
latin = True
real_layout = layout
else:
latin = False
real_layout = 'me,me'
elif layout == 'rs':
if variant == 'basic' or variant.startswith('latin'):
latin = True
real_layout = layout
else:
latin = False
real_layout = 'rs,rs'
else:
latin = True
real_layout = layout
if latin:
real_variant = variant
elif real_layout == 'jp,jp':
real_variant = '106,%s' % variant
elif real_layout == 'lt,lt':
if variant == 'us':
real_variant = 'us,'
else:
real_variant = '%s,us' % variant
elif real_layout == 'me,me':
if variant == 'cyrillicyz':
real_variant = 'latinyz,%s' % variant
elif variant == 'cyrillicalternatequotes':
real_variant = 'latinalternatequotes,%s' % variant
else:
real_variant = 'basic,%s' % variant
elif real_layout == 'rs,rs':
if variant == 'yz':
real_variant = 'latinyz,%s' % variant
elif variant == 'alternatequotes':
real_variant = 'latinalternatequotes,%s' % variant
else:
real_variant = 'latin,%s' % variant
else:
real_variant = ',%s' % variant
real_options = [opt for opt in options if not opt.startswith('lv3:')]
if not latin:
toggle = re.compile(r'^grp:.*toggle$')
real_options = [
opt for opt in real_options if not toggle.match(opt)]
# TODO cjwatson 2006-09-07: honour crazy preseeding; probably
# not quite right, especially for Apples which may need a level
# 3 shift
real_options.append('grp:alt_shift_toggle')
if layout != 'us':
real_options.append('lv3:ralt_switch')
real_model = model
if model == 'pc105':
if real_layout == 'br':
real_model = 'abnt2'
elif real_layout == 'jp':
real_model = 'jp106'
return (real_model, real_layout, real_variant, real_options)
def get_locale(self):
return self._locale
def apply_keyboard(self, layout_name, variant_name):
model = self.db.get('keyboard-configuration/modelcode')
ret = self.get_locale()
try:
layout = keyboard_names.layout_id(ret, layout_name)
except KeyError:
self.debug("Unknown keyboard layout '%s'" % layout_name)
return
if not keyboard_names.has_variants(ret, layout):
self.debug("No known variants for layout '%s'" % layout)
variant = ''
else:
try:
variant = keyboard_names.variant_id(
ret, layout, variant_name)
except KeyError:
self.debug("Unknown keyboard variant '%s' for layout '%s'" %
(variant_name, layout_name))
return
(model, layout, variant, options) = \
self.adjust_keyboard(model, layout, variant, [])
self.set_gnome_keyboard_layout(layout, variant)
self.debug("Setting keyboard layout: %s %s %s %s" %
(model, layout, variant, options))
self.apply_real_keyboard(model, layout, variant, options)
@staticmethod
def get_gnome_input_sources():
return gsettings.get_list("org.gnome.desktop.input-sources", "sources")
def set_gnome_input_sources(self, input_sources):
self.debug(
"Setting org.gnome.desktop.input-sources sources to %r",
input_sources,
)
gsettings.set_list(
"org.gnome.desktop.input-sources", "sources", input_sources
)
def set_gnome_keyboard_layout(self, layout, variant):
if variant:
input_source = ("xkb", f"{layout}+{variant}")
else:
input_source = ("xkb", f"{layout}")
# The only reliable way to change the keyboard layout in GNOME is to
# set the input sources to exacly the desired layout. See also
# https://discourse.gnome.org/t/how-to-set-gnome-keyboard-layout-programatically/9459
self.set_gnome_input_sources([input_source])
if not self.gnome_input_sources:
return
if input_source in self.gnome_input_sources:
input_sources = self.gnome_input_sources
else:
input_sources = [input_source] + self.gnome_input_sources
self.set_gnome_input_sources(input_sources)
def apply_real_keyboard(self, model, layout, variant, options):
args = []
if model is not None and model != '':
args.extend(("-model", model))
args.extend(("-layout", layout))
if variant != '':
args.extend(("-variant", variant))
args.extend(("-option", ""))
for option in options:
args.extend(("-option", option))
misc.execute("setxkbmap", *args)
@misc.raise_privileges
def rewrite_xorg_conf(self, model, layout, variant, options):
oldconfigfile = '/etc/X11/xorg.conf'
newconfigfile = '/etc/X11/xorg.conf.new'
try:
oldconfig = open(oldconfigfile)
except IOError:
# Did they remove /etc/X11/xorg.conf or something? Oh well,
# better to carry on than to crash.
return
newconfig = open(newconfigfile, 'w')
re_section_inputdevice = re.compile(r'\s*Section\s+"InputDevice"\s*$')
re_driver_kbd = re.compile(r'\s*Driver\s+"kbd"\s*$')
re_endsection = re.compile(r'\s*EndSection\s*$')
re_option_xkbmodel = re.compile(r'(\s*Option\s*"XkbModel"\s*).*')
re_option_xkblayout = re.compile(r'(\s*Option\s*"XkbLayout"\s*).*')
re_option_xkbvariant = re.compile(r'(\s*Option\s*"XkbVariant"\s*).*')
re_option_xkboptions = re.compile(r'(\s*Option\s*"XkbOptions"\s*).*')
in_inputdevice = False
in_inputdevice_kbd = False
done = {'model': model == '', 'layout': False,
'variant': variant == '', 'options': options == ''}
for line in oldconfig:
line = line.rstrip('\n')
if re_section_inputdevice.match(line) is not None:
in_inputdevice = True
elif in_inputdevice and re_driver_kbd.match(line) is not None:
in_inputdevice_kbd = True
elif re_endsection.match(line) is not None:
if in_inputdevice_kbd:
if not done['model']:
print('\tOption\t\t"XkbModel"\t"%s"' % model,
file=newconfig)
if not done['layout']:
print('\tOption\t\t"XkbLayout"\t"%s"' % layout,
file=newconfig)
if not done['variant']:
print('\tOption\t\t"XkbVariant"\t"%s"' % variant,
file=newconfig)
if not done['options']:
print('\tOption\t\t"XkbOptions"\t"%s"' % options,
file=newconfig)
in_inputdevice = False
in_inputdevice_kbd = False
done = {'model': model == '', 'layout': False,
'variant': variant == '', 'options': options == ''}
elif in_inputdevice_kbd:
match = re_option_xkbmodel.match(line)
if match is not None:
if model == '':
# hmm, not quite sure what to do here; guessing that
# forcing to pc105 will be reasonable
line = match.group(1) + '"pc105"'
else:
line = match.group(1) + '"%s"' % model
done['model'] = True
else:
match = re_option_xkblayout.match(line)
if match is not None:
line = match.group(1) + '"%s"' % layout
done['layout'] = True
else:
match = re_option_xkbvariant.match(line)
if match is not None:
if variant == '':
continue # delete this line
else:
line = match.group(1) + '"%s"' % variant
done['variant'] = True
else:
match = re_option_xkboptions.match(line)
if match is not None:
if options == '':
continue # delete this line
else:
line = match.group(1) + '"%s"' % options
done['options'] = True
print(line, file=newconfig)
newconfig.close()
oldconfig.close()
os.rename(newconfigfile, oldconfigfile)
def cleanup(self):
# TODO cjwatson 2006-09-07: I'd use dexconf, but it seems reasonable
# for somebody to edit /etc/X11/xorg.conf on the live CD and expect
# that to be carried over to the installed system (indeed, we've
# always supported that up to now). So we get this horrible mess
# instead ...
model = self.db.get('keyboard-configuration/modelcode')
layout = self.db.get('keyboard-configuration/layoutcode')
variant = self.db.get('keyboard-configuration/variantcode')
options = self.db.get('keyboard-configuration/optionscode')
if options:
options_list = options.split(',')
else:
options_list = []
self.set_gnome_keyboard_layout(layout, variant)
self.apply_real_keyboard(model, layout, variant, options_list)
plugin.Plugin.cleanup(self)
if layout == '':
return
self.rewrite_xorg_conf(model, layout, variant, options)
class Install(plugin.InstallPlugin):
def prepare(self, unfiltered=False):
return (['/usr/share/ubiquity/console-setup-apply'], [])
def install(self, target, progress, *args, **kwargs):
progress.info('ubiquity/install/keyboard')
return plugin.InstallPlugin.install(
self, target, progress, *args, **kwargs)