diff --git a/data/key-mapper.glade b/data/key-mapper.glade index 46c8940b..f9bd8839 100644 --- a/data/key-mapper.glade +++ b/data/key-mapper.glade @@ -244,11 +244,15 @@ + + True + False + gtk-redo + 450 False Key Mapper - 280 mouse @@ -478,6 +482,26 @@ 2 + + + Apply Defaults + True + True + True + To give your keys back their original mapping. + end + 10 + 10 + 0 + gtk-redo-icon-2 + + + + False + False + 3 + + True @@ -486,7 +510,7 @@ False True - 3 + 4 @@ -505,7 +529,7 @@ False True - 4 + 5 diff --git a/keymapper/X.py b/keymapper/X.py index 4c040d33..9bc46612 100644 --- a/keymapper/X.py +++ b/keymapper/X.py @@ -153,8 +153,32 @@ DEFAULT_SYMBOLS_NAME = get_preset_name('default') def apply_preset(device, preset): - """Apply a preset to the device.""" - logger.info('Applying preset "%s" on device %s', preset, device) + """Apply a preset to the device. + + Parameters + ---------- + device : string + preset : string + """ + layout = get_preset_name(device, preset) + setxkbmap(device, layout) + + +def setxkbmap(device, layout): + """Apply a preset to the device. + + Parameters + ---------- + device : string + layout : string + For example 'de', passed to setxkbmap unmodified + """ + with open(os.path.join(X11_SYMBOLS, layout), 'r') as f: + if f.read() == '': + logger.error('Tried to load empty config') + return + + logger.info('Applying layout "%s" on device %s', layout, device) group = get_devices()[device] # apply it to every device that hangs on the same usb port, because I @@ -165,15 +189,9 @@ def apply_preset(device, preset): # only all virtual devices of the same hardware device continue - layout_path = get_usr_path(device, preset) - with open(layout_path, 'r') as f: - if f.read() == '': - logger.error('Tried to load empty config') - return - cmd = [ 'setxkbmap', - '-layout', get_preset_name(device, preset), + '-layout', layout, '-keycodes', 'key-mapper', '-device', str(xinput_id) ] @@ -314,8 +332,8 @@ def parse_symbols_file(device, preset): result = re.findall(r'\n\s+?key <(.+?)>.+?\[\s+(\w+)', f.read()) logger.debug('Found %d mappings in this preset', len(result)) for keycode, character in result: - custom_mapping.changed = False custom_mapping.change(None, int(keycode), character) + custom_mapping.changed = False def create_default_symbols(): diff --git a/keymapper/gtk/unsaved.py b/keymapper/gtk/unsaved.py new file mode 100644 index 00000000..9763c150 --- /dev/null +++ b/keymapper/gtk/unsaved.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# key-mapper - GUI for device specific keyboard mappings +# Copyright (C) 2020 sezanzeb +# +# This file is part of key-mapper. +# +# key-mapper 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. +# +# key-mapper 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 key-mapper. If not, see . + + +"""Error dialog.""" + + +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('GLib', '2.0') +from gi.repository import Gtk + +from keymapper.data import get_data_path + + +CONTINUE = True +GO_BACK = False + + +def unsavedChangesDialog(): + gladefile = get_data_path('key-mapper.glade') + builder = Gtk.Builder() + builder.add_from_file(gladefile) + dialog = builder.get_object('unsaved_changes') + dialog.show() + dialog.run() + dialog.hide() + # TODO do something meaningful + return GO_BACK diff --git a/keymapper/gtk/window.py b/keymapper/gtk/window.py index 686dd9f3..ed2799ee 100755 --- a/keymapper/gtk/window.py +++ b/keymapper/gtk/window.py @@ -29,12 +29,14 @@ from gi.repository import Gtk, Gdk, GLib from keymapper.data import get_data_path from keymapper.X import create_setxkbmap_config, apply_preset, \ - create_preset, custom_mapping, parse_symbols_file + create_preset, custom_mapping, parse_symbols_file, setxkbmap, \ + DEFAULT_SYMBOLS_NAME from keymapper.presets import get_presets, find_newest_preset, \ delete_preset, rename_preset from keymapper.logger import logger from keymapper.linux import get_devices, keycode_reader from keymapper.gtk.row import Row +from keymapper.gtk.unsaved import unsavedChangesDialog, GO_BACK def gtk_iteration(): @@ -169,6 +171,10 @@ class Window: key_list.forall(key_list.remove) custom_mapping.empty() + def on_apply_defaults_clicked(self, button): + """Load the mapping that was known to be used before key-mapper.""" + setxkbmap(self.selected_device, DEFAULT_SYMBOLS_NAME) + def on_save_preset_clicked(self, button): """Save changes to a preset to the file system.""" new_name = self.get('preset_name_input').get_text() @@ -215,7 +221,9 @@ class Window: def on_select_device(self, dropdown): """List all presets, create one if none exist yet.""" - # TODO unsaved changes dialog + if custom_mapping.changed: + if unsavedChangesDialog() == GO_BACK: + return device = dropdown.get_active_text() @@ -231,7 +239,9 @@ class Window: def on_create_preset_clicked(self, button): """Create a new preset and select it.""" - # TODO unsaved changes dialog + if custom_mapping.changed: + if unsavedChangesDialog() == GO_BACK: + return new_preset = create_preset(self.selected_device) self.get('preset_selection').append(new_preset, new_preset) @@ -240,7 +250,9 @@ class Window: def on_select_preset(self, dropdown): """Show the mappings of the preset.""" - # TODO unsaved changes dialog + if custom_mapping.changed: + if unsavedChangesDialog() == GO_BACK: + return self.clear_mapping_table() @@ -296,3 +308,5 @@ class Window: self.selected_device, self.selected_preset ) + + custom_mapping.changed = False