diff options
author | Sébastien Dailly <sebastien@dailly.me> | 2025-05-04 17:22:50 +0200 |
---|---|---|
committer | Sébastien Dailly <sebastien@chimrod.com> | 2025-05-05 17:36:00 +0200 |
commit | ac4fa300658b962c43768bc0867a1f46fdb23272 (patch) | |
tree | e9c30dd3a6538ef3879d7da3bee44c458d173ceb | |
parent | c15dc5a0b4f061de73b5d97fa09b311bdb976743 (diff) |
Updated the main code
-rw-r--r-- | configuration.py | 47 | ||||
-rwxr-xr-x | macropad.pyw | 86 | ||||
-rw-r--r-- | xlib.py | 2 |
3 files changed, 92 insertions, 43 deletions
diff --git a/configuration.py b/configuration.py new file mode 100644 index 0000000..fceef14 --- /dev/null +++ b/configuration.py @@ -0,0 +1,47 @@ +from collections import OrderedDict
+from os import path
+import json
+class Mapping():
+
+ def __init__(self, configuration):
+ self.init_mapping = configuration["mapping"]
+ self.mapping = OrderedDict()
+ tmp_mapping = dict(self.init_mapping)
+ for key in tmp_mapping.keys() :
+ json_file = self.init_mapping[key]
+ if not path.exists(json_file):
+ print("The file '%s' does not exists" % json_file)
+ continue
+ with open(json_file, "r") as file:
+ json_data = file.read()
+ j = json.loads(json_data)
+ self.mapping[key] = j
+
+ def reset(self):
+ """ Remove all the keys added and not in the configuration file.
+ """
+ # Create a copy of the dictonnary before updating the keys
+ tmp_mapping = dict(self.mapping)
+ for key in tmp_mapping.keys() :
+ if key not in self.init_mapping.keys():
+ del self.mapping[key]
+
+ def get(self, key, default):
+ return self.mapping.get(key, default)
+
+ def __getitem__(self, key):
+ return self.mapping.get(key, None)
+
+ def __setitem__(self, key, value):
+ self.mapping[key] = value
+
+ def items(self):
+ """ Implement the keys items from the dictionnary
+ """
+ return self.mapping.items()
+
+ def keys(self):
+ """ Implement the keys method from the dictionnary
+ """
+ return self.mapping.keys()
+
diff --git a/macropad.pyw b/macropad.pyw index 3a3b7e2..35bd77a 100755 --- a/macropad.pyw +++ b/macropad.pyw @@ -8,8 +8,8 @@ import pystray from pystray import MenuItem as item from PIL import Image, ImageTk +from typing import Dict import threading -from os import path import sys from zope import component @@ -19,6 +19,7 @@ from interfaces.message import IMessage, Debug import configparser +from os import path script_path = path.dirname(path.realpath(__file__)) config_file = path.join(script_path, "config.ini") @@ -27,8 +28,9 @@ config.read(config_file) from collections import OrderedDict -init_mapping = config["mapping"] -mapping = OrderedDict(init_mapping) +from configuration import Mapping
+mapping = Mapping(config)
+ from queue import Queue q = Queue() @@ -39,19 +41,6 @@ component.provideAdapter(interfaces.endpoint.EndPoint) # Guess the platform and the load the corresponding event listener # -from sys import platform -if platform == "win32": - import win32 - window_listener = win32.Listener(mapping, q) - component.provideUtility(window_listener, interfaces.desktopEvent.IDesktop) - window_listener.start() - -elif platform == 'linux': - import xlib - xlib_listener = xlib.Listener(mapping, q) - component.provideUtility(xlib_listener, interfaces.desktopEvent.IDesktop) - xlib_listener.start() - # # How to connect to the peripherical # @@ -111,13 +100,8 @@ class Icon(object): self.show_hide.set() def reset(self): - # Create a copy of the dictonnary before updating the keys - tmp_mapping = dict(mapping) - for key in tmp_mapping.keys() : - if key not in init_mapping.keys(): - del mapping[key] + mapping.reset() -import json class Application(object): def __init__(self): @@ -149,13 +133,31 @@ class Application(object): self.icon.start() component.handle(Debug("Started")) + + def connect_desktop(self): + """ Launch the thread listening events from the desktop + """ + from sys import platform + component.handle(Debug(platform)) + if platform == "win32": + import win32 + window_listener = win32.Listener(mapping, q) + component.provideUtility(window_listener, interfaces.desktopEvent.IDesktop) + window_listener.start() + + elif platform == 'linux': + import xlib + xlib_listener = xlib.Listener(mapping, q) + component.provideUtility(xlib_listener, interfaces.desktopEvent.IDesktop) + component.handle(Debug("Starting xlib")) + xlib_listener.start() + def hide(self): self.icon.show_hide.clear() self.visible = False self.window.withdraw() self.update() - def update(self): if self.icon.stop.is_set(): self.icon.quit() @@ -176,42 +178,37 @@ class Application(object): def log(self, message : str): print(message.content) try: - f = open("/tmp/macropad.log", "a") - f.write(message.content) - f.write("\n") - f.close() self.text.insert("1.0", "\n") self.text.insert("1.0", message.content) self.text.delete("200.0", "end") except Exception as e: print(e) - """ Send the message to the endpoint. - If the content is the same, ignore the message and return. - """ + def send(self, data: str): + """ Send the configuration to the device. + The configuration can be either + - a dictionnary, and will be send as is + - a string, and will be load in a file + If the content is the same, ignore the message and return. + """ if data == self.last_layout: return + # Merge the new layout with the previous one, ignoring all the null. self.last_layout = data conn = component.queryUtility(interfaces.endpoint.IEndpoint) if isinstance(data, dict): conn.send(data) - return elif isinstance(data, str): - if not path.exists(data): - print("The file '%s' does not exists" % data) - return - with open(data, "r") as json_file: - json_data = json_file.read() - j = json.loads(json_data) - content = json.dumps(j) - - conn.send(j) + layer = mapping.get(data, None) + if layer is not None: + conn.send(layer) - def associate(self, layout: str, name: str): + def associate(self, layout: Dict, name: str): mapping[name] = layout - component.handle(Debug("Associating %s with %s" % (name, layout))) + for key in layout.keys(): + component.handle(Debug("Associating %s with %s" % (name, key))) def exec(self): try: @@ -241,11 +238,16 @@ class Application(object): self.send(last_layout) if app_ is not None: self.associate(last_layout, app_) + if __name__ == '__main__': + # Start the main application, Initializing the message listener before + # listening desktop events app = Application() + app.connect_desktop() # Initialize the main loop app.exec() + component.handle(Debug("Exec runned first")) try: app.window.mainloop() except: @@ -66,7 +66,7 @@ class Listener(Thread): # Create a reveverse dictionnary for getting the users added first
# In python, the elements in a dictionnary are sorted by insertion
# order, so we get the user added first here
- for pattern in reversed(self.mapping):
+ for pattern in reversed(self.mapping.keys()):
# Ignore the default layout
if pattern == "default":
continue
|