aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@dailly.me>2025-05-04 17:22:50 +0200
committerSébastien Dailly <sebastien@chimrod.com>2025-05-05 17:36:00 +0200
commitac4fa300658b962c43768bc0867a1f46fdb23272 (patch)
treee9c30dd3a6538ef3879d7da3bee44c458d173ceb
parentc15dc5a0b4f061de73b5d97fa09b311bdb976743 (diff)
Updated the main code
-rw-r--r--configuration.py47
-rwxr-xr-xmacropad.pyw86
-rw-r--r--xlib.py2
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:
diff --git a/xlib.py b/xlib.py
index 09ec18f..051b21f 100644
--- a/xlib.py
+++ b/xlib.py
@@ -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