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 @@
+
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