diff --git a/ipc.py b/ipc.py new file mode 100644 index 0000000..da269d0 --- /dev/null +++ b/ipc.py @@ -0,0 +1,82 @@ +#!/usr/bin/python3 + +import sys +import socket +import json +import threading + +HOST = "127.0.0.1" +PORT = 58592 + + +class IPC: + def __init__(self, app): + self.app = app + + self.first_instance = not self.already_running() + + self.server_thread = threading.Thread(target=self.server) + self.server_thread.daemon = True + + if self.first_instance: + self.server_thread.start() + + else: + self.send_open_file_message(sys.argv[1:]) + + def already_running(self): + try: + with socket.create_connection((HOST, PORT), timeout=1): + return True + + except (ConnectionRefusedError, OSError): + return False + + def server(self): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: + server_socket.bind((HOST, PORT)) + server_socket.listen(1) + + while True: + conn, addr = server_socket.accept() + + with conn: + data = conn.recv(1024) + if data: + message = data.decode('utf-8') + + self.evaluate_message(message) + + def send(self, message): + try: + with socket.create_connection((HOST, PORT)) as client_socket: + client_socket.sendall(message.encode('utf-8')) + + except Exception as error: + print("IPC-error:", error) + + def evaluate_message(self, raw_message): + data_dict = json.loads(raw_message) + message = Message(data_dict["type"], data_dict["content"]) + + match message.type: + case "open_files": + self.app.open_files_queue += message.content + + def send_open_file_message(self, filenames): + message = Message("open_files", filenames) + + self.send(message.get_message_data()) + + +class Message: + def __init__(self, message_type: str, content): + self.type = message_type + self.content = content + + def get_message_data(self): + data_dict = self.__dict__ + data_dict = dict(filter(lambda pair: not callable(pair[1]), data_dict.items())) # filter out functions + data = json.dumps(data_dict) + + return data diff --git a/main.py b/main.py index 42b255a..52e3d64 100755 --- a/main.py +++ b/main.py @@ -1,25 +1,41 @@ #!/usr/bin/python3 import sys +from PyQt6.QtCore import QTimer from wobbl_tools.data_file import load_dataclass_json from utils import Utils from file import File, FileActions from ui import GUI from settings import Settings +from ipc import IPC class BreadEditor: def __init__(self): - self.settings = load_dataclass_json(Settings, "settings.json") self.utils = Utils(self) + self.settings = load_dataclass_json(Settings, f"{self.utils.editor_path}/settings.json") + self.file_actions = FileActions(self) + + self.ipc = IPC(self) + if not self.ipc.first_instance: + return + self.gui = GUI(self) self.gui.connect_gui(self) self.open_files: dict[str, File] = {} + self.open_files_queue = [] + + self.files_queue_timer = QTimer(self.gui.QTMainWindow) + self.files_queue_timer.timeout.connect(self.utils.check_file_queue) + self.files_queue_timer.start(500) def run(self): + if not self.ipc.first_instance: + return + self.gui.post_setup() self.utils.on_start() diff --git a/utils.py b/utils.py index f3da91e..24a2fe3 100644 --- a/utils.py +++ b/utils.py @@ -104,7 +104,7 @@ class Utils: self.app.settings.last_opened_files = open_files - self.app.settings.save("settings.json") + self.app.settings.save(f"{self.editor_path}/settings.json") def update_style_in_all_bit_editors(self): self.app.settings.highlight_ones = self.app.gui.main_window.highlightOnesSetting.isChecked() @@ -129,3 +129,10 @@ class Utils: if os.path.isfile(file_path): file = File(self.app, file_path, file_path.split("/")[-1]) self.app.open_files[file_path] = file + + def check_file_queue(self): + if not len(self.app.open_files_queue) == 0: + filenames = self.app.open_files_queue + self.app.open_files_queue = [] + + self.load_files(filenames)