diff --git a/docs/source/application.rst b/docs/source/application.rst index bf4a25b..973b925 100644 --- a/docs/source/application.rst +++ b/docs/source/application.rst @@ -118,5 +118,157 @@ And enabled. `OpenFromCalc` is options for open documents in calc, disable or enabled menu entry and icon toolbar. +LibreOffice configuration +------------------------- + +Get value +^^^^^^^^^ + +Some values are read only. + +.. code-block:: python + + node_name = '/org.openoffice.Office.Common/Help' + key = 'System' + value = app.get_app_config(node_name, key) + app.debug(value) + + node_name = '/org.openoffice.Office.Common/Misc/' + key = 'FirstRun' + value = app.get_app_config(node_name, key) + app.debug(value) + + key = 'UseSystemFileDialog' + value = app.get_app_config(node_name, key) + app.debug(value) + + +Set value +^^^^^^^^^ + +.. code-block:: python + + node_name = '/org.openoffice.Office.UI/ColorScheme' + key = 'CurrentColorScheme' + new_value = 'LibreOffice Dark' + result = app.set_app_config(node_name, key, new_value) + app.debug(result) + +.. warning:: + + Caution with modify registry, not all nodes we can change. + + +Shortcuts +--------- + +Global +^^^^^^ + +Iter in all shortcuts. Shortcuts for all applications. + +.. code-block:: python + + for shortcut, command in app.shortcuts: + app.debug(shortcut, command) + + +If you want all info. + +.. code-block:: python + + sc = app.shortcuts + data = sc.get_all() + app.debug(data) + + +Verify if exists shortcut. + +.. code-block:: python + + sc = app.shortcuts + shortcut = 'Shift+Ctrl+Alt+T' + app.debug(shortcut in sc) + + +Add new shortcut for execute uno command. + +.. code-block:: python + + sc = app.shortcuts + shortcut = 'Shift+Ctrl+Alt+T' + command = 'MacroDialog' + sc.set(shortcut, command) + + +Add new shortcut for execute macro. + +.. code-block:: python + + sc = app.shortcuts + shortcut = 'Shift+Ctrl+Alt+M' + macro = {'library': 'test', 'name': 'main'} + sc.set(shortcut, macro) + + +Get `command` by `shortcut`. + +.. code-block:: python + + sc = app.shortcuts + shortcut = 'Shift+Ctrl+Alt+M' + command = sc.get_by_shortcut(shortcut) + app.debug(command) + + +Get `shortcut` by `command`. Could be more than one. + +.. code-block:: python + + sc = app.shortcuts + command = 'MacroDialog' + shortcuts = sc.get_by_command(command) + app.debug(shortcuts) + + +Remove by shortcut. + +.. code-block:: python + + sc = app.shortcuts + shortcut = 'Shift+Ctrl+Alt+M' + sc.remove_by_shortcut(shortcut) + + +Remove by command. + +.. code-block:: python + + sc = app.shortcuts + macro = {'library': 'test', 'name': 'main'} + sc.remove_by_command(macro) + + +Reset all editions. + +.. code-block:: python + + app.shortcuts.reset() + + +For applications +---------------- + +Get shortcuts for application. For Calc. + +.. code-block:: python + + sc = app.shortcuts['calc'] + +All methods some the same. + +For other applications: `writer`, `draw`, `impress`, `math` + + .. _dispatch command: https://wiki.documentfoundation.org/Development/DispatchCommands .. _support filters: https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html diff --git a/source/easymacro.py b/source/easymacro.py index 076e903..af0a817 100644 --- a/source/easymacro.py +++ b/source/easymacro.py @@ -61,6 +61,7 @@ from email import encoders import uno import unohelper +from com.sun.star.awt import Key, KeyEvent, KeyModifier from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS from com.sun.star.awt.MessageBoxResults import YES from com.sun.star.beans import PropertyValue, NamedValue @@ -68,6 +69,7 @@ from com.sun.star.datatransfer import XTransferable, DataFlavor from com.sun.star.io import IOException, XOutputStream from com.sun.star.ui.dialogs import TemplateDescription +from com.sun.star.container import NoSuchElementException # Global variables OS = platform.system() @@ -662,7 +664,7 @@ class Macro(object): return result @classmethod - def _get_url_script(cls, args: dict): + def get_url_script(cls, args: dict): library = args['library'] name = args['name'] language = args.get('language', 'Python') @@ -682,7 +684,7 @@ class Macro(object): @classmethod def _call(cls, args: dict): - url = cls._get_url_script(args) + url = cls.get_url_script(args) args = args.get('args', ()) service = 'com.sun.star.script.provider.MasterScriptProviderFactory' @@ -2003,10 +2005,219 @@ class IOStream(object): return cls.OutputStream() +class LOShortCuts(object): + """Classe for manager shortcuts""" + KEYS = {getattr(Key, k): k for k in dir(Key)} + MODIFIERS = { + 'shift': KeyModifier.SHIFT, + 'ctrl': KeyModifier.MOD1, + 'alt': KeyModifier.MOD2, + 'ctrlmac': KeyModifier.MOD3, + } + COMBINATIONS = { + 0: '', + 1: 'shift', + 2: 'ctrl', + 4: 'alt', + 8: 'ctrlmac', + 3: 'shift+ctrl', + 5: 'shift+alt', + 9: 'shift+ctrlmac', + 6: 'ctrl+alt', + 10: 'ctrl+ctrlmac', + 12: 'alt+ctrlmac', + 7: 'shift+ctrl+alt', + 11: 'shift+ctrl+ctrlmac', + 13: 'shift+alt+ctrlmac', + 14: 'ctrl+alt+ctrlmac', + 15: 'shift+ctrl+alt+ctrlmac', + } + + def __init__(self, app: str=''): + self._app = app + service = 'com.sun.star.ui.GlobalAcceleratorConfiguration' + if app: + service = 'com.sun.star.ui.ModuleUIConfigurationManagerSupplier' + type_app = LODocuments.TYPES[app] + manager = create_instance(service, True) + uicm = manager.getUIConfigurationManager(type_app) + self._config = uicm.ShortCutManager + else: + self._config = create_instance(service) + + def __getitem__(self, index): + return LOShortCuts(index) + + def __contains__(self, item): + cmd = self.get_by_shortcut(item) + return bool(cmd) + + def __iter__(self): + self._i = -1 + return self + + def __next__(self): + self._i += 1 + try: + event = self._config.AllKeyEvents[self._i] + event = self._get_info(event) + except IndexError: + raise StopIteration + + return event + + @classmethod + def to_key_event(cls, shortcut: str): + """Convert from string shortcut (Shift+Ctrl+Alt+LETTER) to KeyEvent""" + key_event = KeyEvent() + keys = shortcut.split('+') + try: + for m in keys[:-1]: + key_event.Modifiers += cls.MODIFIERS[m.lower()] + key_event.KeyCode = getattr(Key, keys[-1].upper()) + except Exception as e: + error(e) + key_event = None + return key_event + + @classmethod + def get_url_script(cls, command: Union[str, dict]) -> str: + """Get uno command or url for macro""" + url = command + if isinstance(url, str) and not url.startswith('.uno:'): + url = f'.uno:{command}' + elif isinstance(url, dict): + url = Macro.get_url_script(command) + return url + + def _get_shortcut(self, k): + """Get shortcut for key event""" + # ~ print(k.KeyCode, str(k.KeyChar), k.KeyFunc, k.Modifiers) + shortcut = f'{self.COMBINATIONS[k.Modifiers]}+{self.KEYS[k.KeyCode]}' + return shortcut + + def _get_info(self, key): + """Get shortcut and command""" + cmd = self._config.getCommandByKeyEvent(key) + shortcut = self._get_shortcut(key) + return shortcut, cmd + + def get_all(self): + """Get all events key""" + events = [(self._get_info(k)) for k in self._config.AllKeyEvents] + return events + + def get_by_command(self, command: Union[str, dict]): + """Get shortcuts by command""" + url = LOShortCuts.get_url_script(command) + key_events = self._config.getKeyEventsByCommand(url) + shortcuts = [self._get_shortcut(k) for k in key_events] + return shortcuts + + def get_by_shortcut(self, shortcut: str): + """Get command by shortcut""" + command = '' + key_event = LOShortCuts.to_key_event(shortcut) + if key_event: + command = self._config.getCommandByKeyEvent(key_event) + return command + + def set(self, shortcut: str, command: Union[str, dict]) -> bool: + """Set shortcut to command + + :param shortcut: Shortcut like Shift+Ctrl+Alt+LETTER + :type shortcut: str + :param command: Command tu assign, 'UNOCOMMAND' or dict with macro info + :type command: str or dict + :return: True if set sucesfully + :rtype: bool + """ + result = True + url = LOShortCuts.get_url_script(command) + key_event = LOShortCuts.to_key_event(shortcut) + try: + self._config.setKeyEvent(key_event, url) + self._config.store() + except Exception as e: + error(e) + result = False + + return result + + def remove_by_shortcut(self, shortcut: str): + """Remove by shortcut""" + key_event = LOShortCuts.to_key_event(shortcut) + try: + self._config.removeKeyEvent(key_event) + result = True + except NoSuchElementException: + debug(f'No exists: {shortcut}') + result = False + return result + + def remove_by_command(self, command: Union[str, dict]): + """Remove by shortcut""" + url = LOShortCuts.get_url_script(command) + self._config.removeCommandFromAllKeyEvents(url) + return + + def reset(self): + """Reset configuration""" + self._config.reset() + self._config.store() + return + + +class LOMenu(object): + NODE = 'private:resource/menubar/menubar' + MENUS = { + 'file': '.uno:PickList', + 'tools': '.uno:ToolsMenu', + 'help': '.uno:HelpMenu', + 'windows': '.uno:WindowList', + 'edit': '.uno:EditMenu', + 'view': '.uno:ViewMenu', + 'insert': '.uno:InsertMenu', + 'format': '.uno:FormatMenu', + 'styles': '.uno:FormatStylesMenu', + 'sheet': '.uno:SheetMenu', + 'data': '.uno:DataMenu', + 'table': '.uno:TableMenu', + 'form': '.uno:FormatFormMenu', + 'page': '.uno:PageMenu', + 'shape': '.uno:ShapeMenu', + 'slide': '.uno:SlideMenu', + 'show': '.uno:SlideShowMenu', + } + + def __init__(self, app): + self._app = app + self._config = self._get_config() + self._menus = self._config.getSettings(self.NODE, True) + + def _get_config(self): + service = 'com.sun.star.ui.ModuleUIConfigurationManagerSupplier' + type_app = LODocuments.TYPES[self._app] + manager = create_instance(service, True) + config = manager.getUIConfigurationManager(type_app) + return config + + def debug(self): + + return + + +class LOMenus(object): + """Classe for manager menus""" + + def __getitem__(self, index): + return LOMenu(index) + + class LOMain(): """Classe for LibreOffice""" - class _commands(): + class commands(): """Class for disable and enable commands `See DispatchCommands `_ @@ -2070,7 +2281,7 @@ class LOMain(): @classproperty def cmd(cls): """Disable or enable commands""" - return cls._commands + return cls.commands @classproperty def desktop(cls): @@ -2404,6 +2615,7 @@ class LODocument(): class LODocMain(): + """Classe for start module""" _type = 'main' def __init__(self, obj): @@ -2425,6 +2637,30 @@ class LODocCalc(LODocument): super().__init__(obj) +class LOCalcSheet(object): + + def __init__(self, obj): + self._obj = obj + + def __getitem__(self, index): + return LOCalcRange(self.obj[index]) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + pass + + def __str__(self): + return f'easymacro.LOCalcSheet: {self.name}' + + +class LOCalcRange(object): + + def __init__(self, obj): + self._obj = obj + + class LODocWriter(LODocument): _type = 'writer' @@ -2484,6 +2720,16 @@ class LODocIDE(LODocument): class LODocuments(): """Classe for documents """ + TYPES = { + 'calc': 'com.sun.star.sheet.SpreadsheetDocument', + 'writerr': 'com.sun.star.text.TextDocument', + 'draw': 'com.sun.star.drawing.DrawingDocument', + 'impress': 'com.sun.star.presentation.PresentationDocument', + 'math': 'com.sun.star.formula.FormulaProperties', + 'ide': 'com.sun.star.script.BasicIDE', + 'base': 'com.sun.star.sdb.OfficeDatabaseDocument', + 'main': 'com.sun.star.frame.StartModule', + } _classes = { 'com.sun.star.sheet.SpreadsheetDocument': LODocCalc, 'com.sun.star.text.TextDocument': LODocWriter, @@ -2610,6 +2856,7 @@ def __getattr__(name): 'color': Color(), 'io': IOStream, 'clipboard': ClipBoard, + 'shortcuts': LOShortCuts(), 'lo': LOMain, 'command': LOMain.cmd, 'docs': LODocuments(),