forked from balisujohn/localwriter
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy patheditor_context_menu.py
More file actions
148 lines (122 loc) · 5.21 KB
/
Copy patheditor_context_menu.py
File metadata and controls
148 lines (122 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# WriterAgent - AI Writing Assistant for LibreOffice
# Copyright (c) 2026 KeithCu (modifications and relicensing)
#
# SPDX-License-Identifier: GPL-3.0-or-later
"""Calc cell context menu: Edit Python in Cell… (right-click on a cell)."""
from __future__ import annotations
import logging
import threading
from typing import Any, cast
import unohelper
log = logging.getLogger(__name__)
_EDIT_PYTHON_CELL_URL = "org.extension.writeragent:scripting.edit_python_cell"
_CELL_MENU_FIRST_COMMAND = ".uno:Cut"
_lock = threading.RLock()
_registered_frames: set[int] = set()
_interceptor: Any = None
def _frame_key(frame: Any) -> int | None:
try:
return id(frame)
except Exception:
return None
def _is_calc_spreadsheet(frame: Any) -> bool:
try:
controller = frame.getController()
if controller is None:
return False
model = controller.getModel()
if model is None:
return False
return bool(model.supportsService("com.sun.star.sheet.SpreadsheetDocument"))
except Exception:
log.debug("python_editor_context_menu: could not resolve frame model", exc_info=True)
return False
def _looks_like_cell_context_menu(container: Any) -> bool:
try:
if container is None or container.getCount() == 0:
return False
first = container.getByIndex(0)
if first is None:
return False
cmd = first.getPropertyValue("CommandURL")
return str(cmd) == _CELL_MENU_FIRST_COMMAND
except Exception:
return False
def _get_interceptor() -> Any:
global _interceptor
if _interceptor is not None:
return _interceptor
from com.sun.star.ui import ActionTriggerSeparatorType, XContextMenuInterceptor
from com.sun.star.ui.ContextMenuInterceptorAction import IGNORED, CONTINUE_MODIFIED
class _CalcCellContextMenuInterceptor(unohelper.Base, XContextMenuInterceptor): # type: ignore[misc, valid-type]
def notifyContextMenuExecute(self, aEvent): # noqa: N802 — UNO API
try:
if not _is_calc_spreadsheet(aEvent.SourceWindow):
return IGNORED
container = aEvent.ActionTriggerContainer
if not _looks_like_cell_context_menu(container):
return IGNORED
import uno
factory = cast("Any", container).queryInterface(uno.getTypeByName("com.sun.star.lang.XMultiServiceFactory"))
if factory is None:
return IGNORED
separator = factory.createInstance("com.sun.star.ui.ActionTriggerSeparator")
separator.setPropertyValue("SeparatorType", ActionTriggerSeparatorType.LINE)
entry = factory.createInstance("com.sun.star.ui.ActionTrigger")
from plugin.framework.i18n import _
entry.setPropertyValue("Text", _("Edit Python in Cell..."))
entry.setPropertyValue("CommandURL", _EDIT_PYTHON_CELL_URL)
count = container.getCount()
container.insertByIndex(count, separator)
container.insertByIndex(count + 1, entry)
return CONTINUE_MODIFIED
except Exception:
log.exception("Calc cell context menu interceptor failed")
return IGNORED
_interceptor = _CalcCellContextMenuInterceptor()
return _interceptor
def _register_frame(frame: Any) -> None:
key = _frame_key(frame)
if key is None:
return
with _lock:
if key in _registered_frames:
return
try:
controller = frame.getController()
if controller is None:
return
import uno
interception = controller.queryInterface(uno.getTypeByName("com.sun.star.ui.XContextMenuInterception"))
if interception is None:
return
interception.registerContextMenuInterceptor(_get_interceptor())
with _lock:
_registered_frames.add(key)
log.debug("python_editor_context_menu: registered on frame %s", key)
except Exception:
log.debug("python_editor_context_menu: register failed", exc_info=True)
def install_calc_cell_context_menu(ctx: Any) -> None:
"""Register the cell context menu interceptor on open Calc frames."""
try:
from plugin.framework.uno_context import get_desktop
desktop = get_desktop(ctx)
if desktop is None:
return
frames = desktop.getFrames()
if frames is not None:
for i in range(frames.getCount()):
try:
frame = frames.getByIndex(i)
if frame is not None and _is_calc_spreadsheet(frame):
_register_frame(frame)
except Exception:
log.debug("python_editor_context_menu: frame %s skipped", i, exc_info=True)
try:
current = desktop.getCurrentFrame()
if current is not None and _is_calc_spreadsheet(current):
_register_frame(current)
except Exception:
log.debug("python_editor_context_menu: current frame skipped", exc_info=True)
except Exception:
log.debug("python_editor_context_menu: install failed", exc_info=True)