Skip to content

Commit

Permalink
Merge pull request #13 from DavidCEllis/no_linux_hotkeys
Browse files Browse the repository at this point in the history
Put all hotkey commands behind sys.platform == "win32" checks.
  • Loading branch information
DavidCEllis authored Sep 27, 2024
2 parents 17da95b + 31e9a1b commit ff1a0de
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 64 deletions.
2 changes: 1 addition & 1 deletion src/splitguides/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.9.3"
__version__ = "0.9.4"
1 change: 1 addition & 0 deletions src/splitguides/hotkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def read_hotkey(suppress: bool = True) -> Hotkey:
The original function returns just the names, this returns a Hotkey object.
The scancodes can then be stored while the name can be displayed.
"""
# This function is only ever called in windows

queue = _queue.Queue()

Expand Down
57 changes: 33 additions & 24 deletions src/splitguides/ui/hotkey_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
but it's currently better than the alternative of writing a keyboard hook
library myself for this one small task.
"""
import sys

import time
import json
from collections.abc import Callable
Expand All @@ -19,6 +21,9 @@
from ..hotkeys import read_hotkey


IS_WINDOWS = sys.platform == "win32"


class HotkeyManager(QtCore.QObject):
hotkey_signal = QtCore.Signal(str)
increase_signal = QtCore.Signal()
Expand All @@ -42,42 +47,46 @@ def __init__(self, parent):
self.decrease_key = None

def enable_hotkeys(self, increase_key, decrease_key):
if increase_key:
self.increase_key = keyboard.add_hotkey(
tuple(increase_key), self.increase_signal.emit
)
if decrease_key:
self.decrease_key = keyboard.add_hotkey(
tuple(decrease_key), self.decrease_signal.emit
)
self.enabled = True
if IS_WINDOWS:
if increase_key:
self.increase_key = keyboard.add_hotkey(
tuple(increase_key), self.increase_signal.emit
)
if decrease_key:
self.decrease_key = keyboard.add_hotkey(
tuple(decrease_key), self.decrease_signal.emit
)
self.enabled = True

def disable_hotkeys(self):
if self.increase_key:
keyboard.remove_hotkey(self.increase_key)
if self.decrease_key:
keyboard.remove_hotkey(self.decrease_key)
self.enabled = False
if IS_WINDOWS:
if self.increase_key:
keyboard.remove_hotkey(self.increase_key)
if self.decrease_key:
keyboard.remove_hotkey(self.decrease_key)
self.enabled = False

@staticmethod
def disable_all():
"""Backup method to just disable everything, used at close"""
keyboard.unhook_all()
if IS_WINDOWS:
keyboard.unhook_all()

def select_input(self, return_object):
"""
Choose a hotkey to be used.
:param return_object: the function to call back with the hotkey value
"""
self.hotkey_signal.connect(return_object)
if IS_WINDOWS:
self.hotkey_signal.connect(return_object)

# Sleep 100ms to allow inputs used to trigger
# The detection to clear first
time.sleep(0.1)
hotkey = read_hotkey(False)
# Sleep 100ms to allow inputs used to trigger
# The detection to clear first
time.sleep(0.1)
hotkey = read_hotkey(False)

# Esc, Backspace or Delete can be used to clear the input
if hotkey.name in ["esc", "backspace", "delete"]:
hotkey = None # Blank will be converted to None
# Esc, Backspace or Delete can be used to clear the input
if hotkey.name in ["esc", "backspace", "delete"]:
hotkey = None # Blank will be converted to None

self.hotkey_signal.emit(json.dumps(as_dict(hotkey))) # Needs to be a string
self.hotkey_signal.emit(json.dumps(as_dict(hotkey))) # Needs to be a string
83 changes: 48 additions & 35 deletions src/splitguides/ui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
icon_file = str(base_path.parents[2] / "resources" / "logo_alpha.png")


IS_WINDOWS = sys.platform == "win32"


class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
Expand Down Expand Up @@ -85,18 +88,23 @@ def __init__(self):
self.split_index = 0

self.split_offset = 0 # Offset for advancing/reversing split

# Set up hotkey manager
self.hotkey_manager = HotkeyManager(self)
if self.settings.hotkeys_enabled:
try:
self.enable_hotkeys()
except AttributeError:
QErrorMessage(parent=self).showMessage("Could not enable hotkeys.")
self.disable_hotkeys()
self.settings.hotkeys_enabled = False
self.hotkeys_toggle.setChecked(False)
if IS_WINDOWS:
self.hotkey_manager = HotkeyManager(self)

if self.settings.hotkeys_enabled:
try:
self.enable_hotkeys()
except AttributeError:
QErrorMessage(parent=self).showMessage("Could not enable hotkeys.")
self.disable_hotkeys()
self.settings.hotkeys_enabled = False
self.hotkeys_toggle.setChecked(False)
else:
self.hotkey_manager = None

self.start_loops()
self.start_loops() # Start livesplit checking loops

def toggle_on_top(self):
"""Toggle window always on top, update settings and window flag to match."""
Expand All @@ -107,30 +115,33 @@ def toggle_on_top(self):
self.show()

def toggle_hotkey_enable(self):
try:
if self.settings.hotkeys_enabled:
self.disable_hotkeys()
if IS_WINDOWS:
try:
if self.settings.hotkeys_enabled:
self.disable_hotkeys()
self.settings.hotkeys_enabled = False
self.hotkeys_toggle.setChecked(False)
else:
self.enable_hotkeys()
self.settings.hotkeys_enabled = True
self.hotkeys_toggle.setChecked(True)
except AttributeError:
QErrorMessage(parent=self).showMessage("Could not enable hotkeys.")
self.settings.hotkeys_enabled = False
self.hotkeys_toggle.setChecked(False)
else:
self.enable_hotkeys()
self.settings.hotkeys_enabled = True
self.hotkeys_toggle.setChecked(True)
except AttributeError:
QErrorMessage(parent=self).showMessage("Could not enable hotkeys.")
self.settings.hotkeys_enabled = False
self.hotkeys_toggle.setChecked(False)

def enable_hotkeys(self):
increase_key = self.settings.increase_offset_hotkey.scancodes
decrease_key = self.settings.decrease_offset_hotkey.scancodes
self.hotkey_manager.enable_hotkeys(increase_key, decrease_key)
if IS_WINDOWS:
increase_key = self.settings.increase_offset_hotkey.scancodes
decrease_key = self.settings.decrease_offset_hotkey.scancodes
self.hotkey_manager.enable_hotkeys(increase_key, decrease_key)

def disable_hotkeys(self):
self.hotkey_manager.disable_hotkeys()
self.split_offset = 0 # Reset the offset as you can no longer change it
if not self.ls.connected:
self.update_notes(0)
if IS_WINDOWS:
self.hotkey_manager.disable_hotkeys()
self.split_offset = 0 # Reset the offset as you can no longer change it
if not self.ls.connected:
self.update_notes(0)

def increase_offset(self):
self.split_offset += 1
Expand Down Expand Up @@ -165,7 +176,8 @@ def start_loops(self):
def closeEvent(self, event):
"""On close save settings and close the livesplit connection."""
self.settings.save()
self.hotkey_manager.disable_all() # Kill any hotkeys
if IS_WINDOWS:
self.hotkey_manager.disable_all() # Kill any hotkeys
self.ls.close()
event.accept()

Expand Down Expand Up @@ -198,10 +210,11 @@ def build_menu(self):
self.menu_on_top.setChecked(self.settings.on_top)
self.menu_on_top.triggered.connect(self.toggle_on_top)

self.hotkeys_toggle = self.rc_menu.addAction("Enable Hotkeys")
self.hotkeys_toggle.setCheckable(True)
self.hotkeys_toggle.setChecked(self.settings.hotkeys_enabled)
self.hotkeys_toggle.triggered.connect(self.toggle_hotkey_enable)
if IS_WINDOWS:
self.hotkeys_toggle = self.rc_menu.addAction("Enable Hotkeys")
self.hotkeys_toggle.setCheckable(True)
self.hotkeys_toggle.setChecked(self.settings.hotkeys_enabled)
self.hotkeys_toggle.triggered.connect(self.toggle_hotkey_enable)

def show_menu(self):
"""Display the context menu at the cursor position."""
Expand Down Expand Up @@ -283,7 +296,7 @@ def update_notes(self, idx, refresh=False):
def open_settings(self):
"""Open the settings dialog, refresh everything if the settings have changed."""
# Block hotkeys while in the settings menu
if self.hotkey_manager.enabled:
if IS_WINDOWS and self.hotkey_manager.enabled:
self.disable_hotkeys()

settings_dialog = SettingsDialog(
Expand Down Expand Up @@ -312,7 +325,7 @@ def open_settings(self):
self.update_notes(self.split_index, refresh=True)

# Re-enable hotkeys if enabled
if self.settings.hotkeys_enabled:
if IS_WINDOWS and self.settings.hotkeys_enabled:
self.enable_hotkeys()


Expand Down
9 changes: 7 additions & 2 deletions src/splitguides/ui/settings_ui.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
import json
Expand Down Expand Up @@ -41,8 +42,12 @@ def __init__(
self.ui.htmltemplate_button.clicked.connect(self.html_template_dialog)
self.ui.css_button.clicked.connect(self.css_dialog)

self.ui.nextsplitkey_button.clicked.connect(self.get_increase_hotkey)
self.ui.previoussplitkey_button.clicked.connect(self.get_decrease_hotkey)
if sys.platform == "win32":
self.ui.nextsplitkey_button.clicked.connect(self.get_increase_hotkey)
self.ui.previoussplitkey_button.clicked.connect(self.get_decrease_hotkey)
else:
self.ui.nextsplitkey_button.setDisabled(True)
self.ui.previoussplitkey_button.setDisabled(True)

self.pool = ThreadPoolExecutor(max_workers=1)

Expand Down
2 changes: 1 addition & 1 deletion zipapp/splitguides_desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
# [tool.ducktools.env.app]
# name = "splitguides"
# owner = "davidcellis"
# version = "0.9.3"
# version = "0.9.4"
#
# [tool.ducktools.env.include]
# data = ["../src/splitguides", "../resources"]
Expand Down
2 changes: 1 addition & 1 deletion zipapp/splitguides_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
# [tool.ducktools.env.app]
# name = "splitguides"
# owner = "davidcellis"
# version = "0.9.3"
# version = "0.9.4"
#
# [tool.ducktools.env.include]
# data = ["../src/splitguides", "../resources"]
Expand Down
File renamed without changes.

0 comments on commit ff1a0de

Please sign in to comment.