Try to fix clipboard and simple plugins.

This commit is contained in:
Storm Dragon 2025-04-04 18:04:58 -04:00
parent 48575ab6cd
commit 02be96aa69
2 changed files with 86 additions and 39 deletions

View File

@ -20,6 +20,8 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
#
# Fork of Orca Screen Reader (GNOME)
# Original source: https://gitlab.gnome.org/GNOME/orca
"""Clipboard plugin for Cthulhu."""
@ -62,6 +64,36 @@ class Clipboard(Plugin):
except Exception as e:
logger.error(f"Error activating Clipboard plugin: {e}")
@cthulhu_hookimpl
def deactivate(self, plugin=None):
"""Deactivate the plugin."""
# Skip if this deactivation call isn't for us
if plugin is not None and plugin is not self:
return
logger.info("Deactivating Clipboard plugin")
try:
# Unregister keyboard shortcut
if self.app:
api_helper = self.app.getAPIHelper()
if api_helper and hasattr(api_helper, 'unregisterShortcut'):
api_helper.unregisterShortcut('kb:cthulhu+shift+c')
logger.debug("Unregistered clipboard shortcut")
except Exception as e:
logger.error(f"Error deactivating Clipboard plugin: {e}")
"""Activate the plugin."""
# Skip if this activation call isn't for us
if plugin is not None and plugin is not self:
return
logger.info("Activating Clipboard plugin")
try:
# Register keyboard shortcut
self.registerGestureByString(self.speakClipboard, _('clipboard'), 'kb:cthulhu+shift+c')
logger.debug("Registered shortcut for clipboard")
except Exception as e:
logger.error(f"Error activating Clipboard plugin: {e}")
@cthulhu_hookimpl
def deactivate(self, plugin=None):
"""Deactivate the plugin."""

View File

@ -1,9 +1,6 @@
#!/usr/bin/env python3
#
# Copyright (c) 2024 Stormux
# Copyright (c) 2010-2012 The Orca Team
# Copyright (c) 2012 Igalia, S.L.
# Copyright (c) 2005-2010 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@ -20,8 +17,6 @@
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
#
# Fork of Orca Screen Reader (GNOME)
# Original source: https://gitlab.gnome.org/GNOME/orca
"""Simple Plugin System for Cthulhu."""
@ -57,11 +52,11 @@ def outputMessage(Message):
class SimplePluginSystem(Plugin):
"""Simple plugin system implementation for Cthulhu.
This plugin allows loading and managing simple script-based plugins
from a designated directory.
"""
def __init__(self, *args, **kwargs):
"""Initialize the plugin system."""
super().__init__(*args, **kwargs)
@ -77,22 +72,22 @@ class SimplePluginSystem(Plugin):
# Skip if this activation call isn't for us
if plugin is not None and plugin is not self:
return
logger.info("Activating SimplePluginSystem plugin")
try:
global settings
global speech
global braille
global input_event
settings = self.app.getDynamicApiManager().getAPI('Settings')
speech = self.app.getDynamicApiManager().getAPI('Speech')
braille = self.app.getDynamicApiManager().getAPI('Braille')
input_event = self.app.getDynamicApiManager().getAPI('InputEvent')
if not self.loaded:
self.load_plugins()
except Exception as e:
logger.error(f"Error activating SimplePluginSystem plugin: {e}")
@ -102,7 +97,7 @@ class SimplePluginSystem(Plugin):
# Skip if this deactivation call isn't for us
if plugin is not None and plugin is not self:
return
logger.info("Deactivating SimplePluginSystem plugin")
try:
# Remove all registered keybindings
@ -144,7 +139,7 @@ class SimplePluginSystem(Plugin):
# If translation fails, use the original name
plugin_name = currPluginSetting['pluginname']
logger.warning(f"Translation failed for plugin: {currPluginSetting['pluginname']}")
self.registerGestureByString(currPluginSetting['function'], plugin_name, shortcut)
return currPluginSetting
@ -254,7 +249,7 @@ class SimplePluginSystem(Plugin):
currPluginSetting['loadmodule'] = ('sopsproperty:loadmodule' in line.lower().replace(" ", "")) or currPluginSetting['loadmodule']
except Exception as e:
logger.error(f"Error reading plugin file: {e}")
return currPluginSetting
def buildPluginSubprocess(self, currPluginSetting):
@ -317,75 +312,95 @@ class SimplePluginSystem(Plugin):
def registerGestureByString(self, function, description, shortcut):
"""Register a keyboard shortcut for a function.
This is a compatibility wrapper for the new plugin system.
"""
try:
# Try to get the InputEventManager and register the shortcut
input_manager = self.app.getDynamicApiManager().getAPI('InputEventManager')
if input_manager:
input_manager.registerGestureByString(function, description, shortcut)
logger.debug(f"Registered shortcut {shortcut} for {description}")
if self.app:
api_helper = self.app.getAPIHelper()
if api_helper:
api_helper.registerGestureByString(
function,
description,
shortcut,
'default',
'cthulhu',
True,
contextName=self.module_name
)
logger.debug(f"Registered shortcut {shortcut} for {description}")
return True
else:
logger.error("Could not get APIHelper")
else:
logger.error("Could not get InputEventManager API")
logger.error("No app reference available")
except Exception as e:
logger.error(f"Error registering shortcut {shortcut}: {e}")
def unregisterShortcut(self, function, shortcut):
"""Unregister a keyboard shortcut for a function.
This is a compatibility wrapper for the new plugin system.
"""
try:
# Try to get the InputEventManager and unregister the shortcut
input_manager = self.app.getDynamicApiManager().getAPI('InputEventManager')
if input_manager:
input_manager.unregisterGestureByString(shortcut)
logger.debug(f"Unregistered shortcut {shortcut}")
if self.app:
api_helper = self.app.getAPIHelper()
if api_helper and hasattr(api_helper, 'unregisterShortcut'):
api_helper.unregisterShortcut(shortcut)
logger.debug(f"Unregistered shortcut {shortcut}")
return True
else:
logger.error("Could not get APIHelper or unregisterShortcut method")
else:
logger.error("Could not get InputEventManager API")
logger.error("No app reference available")
except Exception as e:
logger.error(f"Error unregistering shortcut {shortcut}: {e}")
def load_plugins(self):
"""Load and setup all plugins in the plugin repository."""
if not self.loaded:
try:
logger.info(f"Loading plugins from {self.plugin_repo}")
self.plugin_list = glob.glob(self.plugin_repo + '*')
for currplugin in self.plugin_list:
plugin_files = glob.glob(self.plugin_repo + '*')
self.plugin_list = [] # Reset the plugin list to avoid confusion
for currplugin in plugin_files:
try:
# Ensure currplugin is a valid path string
if not isinstance(currplugin, (str, bytes, os.PathLike)):
logger.error(f"Invalid plugin path: {type(currplugin)}")
continue
currPluginSetting = self.initSettings()
currPluginSetting = self.getPluginSettings(currplugin, currPluginSetting)
if not currPluginSetting['valid']:
logger.debug(f"Skipping invalid plugin: {currplugin}")
continue
currPluginSetting = self.getFunctionName(currPluginSetting)
if currPluginSetting['loadmodule']:
exec(self.buildPluginExec(currPluginSetting)) # load as python module
else:
exec(self.buildPluginSubprocess(currPluginSetting)) # run as subprocess
if currPluginSetting['blockcall']:
currPluginSetting['function'] = globals()[currPluginSetting['functionname']] # non threaded
else:
currPluginSetting['function'] = globals()[currPluginSetting['functionname'] + "T"] # T = Threaded
if currPluginSetting['exec']: # exec on load if we want
currPluginSetting['function']()
if not currPluginSetting['key'] == '':
currPluginSetting = self.SetupShortcutAndHandle(currPluginSetting)
logger.debug(f"Loaded plugin: {currPluginSetting['pluginname']}")
self.plugin_list.append(currPluginSetting) # store in a list
except Exception as e:
logger.error(f"Error loading plugin {currplugin}: {e}")
self.loaded = True
logger.info(f"Loaded {len(self.plugin_list)} plugins")
except Exception as e: