Coverage for src/robotide/editor/__init__.py: 62%
202 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
1# Copyright 2008-2015 Nokia Networks
2# Copyright 2016- Robot Framework Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
16import builtins 1ab
17import wx 1ab
19from .editorcreator import EditorCreator 1ab
20from ..pluginapi import (Plugin, action_info_collection, TreeAwarePluginMixin) 1ab
21from ..publish import (RideTreeSelection, RideNotebookTabChanging, RideNotebookTabChanged, RideSaving) 1ab
22from ..publish.messages import RideDataFileRemoved 1ab
23from ..widgets import PopupCreator 1ab
25_ = wx.GetTranslation # To keep linter/code analyser happy 1ab
26builtins.__dict__['_'] = wx.GetTranslation 1ab
29def get_menudata(): 1ab
30 # Menus to translate
31 edit_0 = _("[Edit]\n") 1ac
32 edit_1 = _("&Undo | Undo last modification | Ctrlcmd-Z\n") 1ac
33 edit_2 = _("&Redo | Redo modification | Ctrlcmd-Y\n") 1ac
34 SEPARATOR = "---\n" 1ac
35 edit_3 = _("Cu&t | Cut | Ctrlcmd-X\n") 1ac
36 edit_4 = _("&Copy | Copy | Ctrlcmd-C\n") 1ac
37 edit_5 = _("&Paste | Paste | Ctrlcmd-V\n") 1ac
38 edit_6 = _("&Insert | Insert | Shift-Ctrl-V\n") 1ac
39 edit_7 = _("&Delete | Delete | Del\n") 1ac
40 edit_8 = _("Comment Rows | Comment selected rows | Ctrlcmd-3\n") 1ac
41 edit_9 = _("Comment Cells | Comment cells with # | Ctrlcmd-Shift-3\n") 1ac
42 edit_10 = _("Uncomment Rows | Uncomment selected rows | Ctrlcmd-4\n") 1ac
43 edit_11 = _("Uncomment Cells | Uncomment cells with # | Ctrlcmd-Shift-4\n") 1ac
44 edit_12 = _("Insert Cells | Insert Cells | Ctrlcmd-Shift-I\n") 1ac
45 edit_13 = _("Delete Cells | Delete Cells | Ctrlcmd-Shift-D\n") 1ac
46 edit_14 = _("Insert Rows | Insert Rows | Ctrlcmd-I\n") 1ac
47 edit_15 = _("Delete Rows | Delete Rows | Ctrlcmd-D\n") 1ac
48 edit_16 = _("Move Rows Up | Move Rows Up | Alt-Up\n") 1ac
49 edit_17 = _("Move Rows Down | Move Rows Down | Alt-Down\n") 1ac
50 tools_0 = _("[Tools]\n") 1ac
51 tools_1 = _("Content Assistance (Ctrl-Space or Ctrl-Alt-Space) | Show possible keyword and variable completions" 1ac
52 " | | | POSITION-70\n")
54 return (edit_0 + edit_1 + edit_2 + SEPARATOR + edit_3 + edit_4 + edit_5 + edit_6 + edit_7 + SEPARATOR + 1ac
55 edit_8 + edit_9 + edit_10 + edit_11 + SEPARATOR + edit_12 + edit_13 + edit_14 + edit_15 + edit_16 +
56 edit_17 + tools_0 + tools_1)
59_EDIT_nt = """[Edit] 1ab
60&Undo | Undo last modification | Ctrlcmd-Z
61&Redo | Redo modification | Ctrlcmd-Y
62---
63Cu&t | Cut | Ctrlcmd-X
64&Copy | Copy | Ctrlcmd-C
65&Paste | Paste | Ctrlcmd-V
66&Insert | Insert | Shift-Ctrl-V
67&Delete | Delete | Del
68---
69Comment Rows | Comment selected rows | Ctrlcmd-3
70Comment Cells | Comment cells with # | Ctrlcmd-Shift-3
71Uncomment Rows | Uncomment selected rows | Ctrlcmd-4
72Uncomment Cells | Uncomment cells with # | Ctrlcmd-Shift-4
73---
74Insert Cells | Insert Cells | Ctrlcmd-Shift-I
75Delete Cells | Delete Cells | Ctrlcmd-Shift-D
76Insert Rows | Insert Rows | Ctrlcmd-I
77Delete Rows | Delete Rows | Ctrlcmd-D
78Move Rows Up | Move Rows Up | Alt-Up
79Move Rows Down | Move Rows Down | Alt-Down
80[Tools]
81Content Assistance (Ctrl-Space or Ctrl-Alt-Space) | Show possible keyword and variable completions | | | POSITION-70
82"""
85class EditorPlugin(Plugin, TreeAwarePluginMixin): 1ab
87 def __init__(self, application): 1ab
88 self.__doc__ = _("""The default editor plugin. Also known as Grid or Cell Editor.
90 This plugin implements editors for the various items of Robot Framework
91 test data.
92 """)
93 Plugin.__init__(self, application, name='Editor')
94 self._tab = None
95 self.name = _('Editor')
96 self.grid_popup_creator = PopupCreator()
97 self._creator = EditorCreator(self.register_editor)
98 self._editor = None
100 def enable(self): 1ab
101 self._creator.register_editors()
102 self._show_editor()
103 _menudata = get_menudata()
104 self.register_actions(action_info_collection(_menudata, self._tab, data_nt=_EDIT_nt, container=self._tab))
105 self.subscribe(self.on_tree_item_selected, RideTreeSelection)
106 self.subscribe(self.on_tab_changed, RideNotebookTabChanged)
107 self.subscribe(self.on_tab_changing, RideNotebookTabChanging)
108 self.subscribe(self.on_save_to_model, RideSaving)
109 self.subscribe(self.on_file_deleted, RideDataFileRemoved)
110 self.add_self_as_tree_aware_plugin()
112 def disable(self): 1ab
113 self.remove_self_from_tree_aware_plugins()
114 self.unsubscribe_all()
115 self.delete_tab(self._tab)
116 wx.CallLater(500, self.unregister_actions())
117 self._tab = None
118 self._editor = None
120 def is_focused(self): 1ab
121 return self.tab_is_visible(self._tab)
123 def highlight_cell(self, obj, row, column): 1ab
124 self.show()
125 self._editor.highlight_cell(obj, row, column)
127 def highlight(self, text): 1ab
128 self.show()
129 self._editor.highlight(text)
131 def show(self): 1ab
132 self.show_tab(self._tab)
134 def register_context_menu_hook_to_grid(self, hook): 1ab
135 """ Used to register own items to grid's right click context menu
137 hook is called with current selection (list of list containing
138 values) and it is expected to return list of PopupMenuItem.
139 If user selects one of the returned PopupMenuItem, related function
140 is called with one argument, the wx event.
141 """
142 self.grid_popup_creator.add_hook(hook)
144 def unregister_context_menu_hook_to_grid(self, hook): 1ab
145 self.grid_popup_creator.remove_hook(hook)
147 def _show_editor(self): 1ab
148 if not self._tab:
149 self._tab = _EditorTab(self)
150 self.add_tab(self._tab, self._tab.plugin.name, allow_closing=False)
151 if self.is_focused():
152 self._editor = self._create_editor()
153 self._tab.show_editor(self._editor)
155 def _create_editor(self): 1ab
156 return self._creator.editor_for(self, self._tab, self.tree)
158 def on_tree_item_selected(self, message): 1ab
159 self._show_editor()
160 if not self.is_focused() and \
161 not self.is_focus_on_tree_aware_plugin() and \
162 (not message or not message.silent):
163 self._editor = self._create_editor()
164 self._tab.show_editor(self._editor)
165 self.show()
166 if self._editor:
167 self._editor.tree_item_selected(message.item)
169 def get_selected_datafile(self): 1ab
170 if self._editor and self._editor.controller: 170 ↛ 171line 170 didn't jump to line 171 because the condition on line 170 was never true
171 return self._editor.controller.datafile
172 return Plugin.get_selected_datafile(self)
174 def on_open_editor(self, event): 1ab
175 __ = event
176 self._show_editor()
178 def on_tab_changed(self, message): 1ab
179 __ = message
180 self._show_editor()
182 def on_tab_changing(self, message): 1ab
183 if 'Editor' in message.oldtab: 183 ↛ exitline 183 didn't return from function 'on_tab_changing' because the condition on line 183 was always true
184 self._tab.save()
186 def on_save_to_model(self, message): 1ab
187 __ = message
188 if self._tab:
189 self._tab.save()
191 def on_file_deleted(self, message): 1ab
192 __ = message
193 self._create_editor()
196class _EditorTab(wx.Panel): 1ab
198 def __init__(self, plugin): 1ab
199 wx.Panel.__init__(self, plugin.notebook, style=wx.SUNKEN_BORDER)
200 self.plugin = plugin
201 self.sizer = wx.BoxSizer(wx.VERTICAL)
202 self.SetSizer(self.sizer)
203 """
204 self.SetBackgroundColour(Colour(200, 222, 40))
205 self.SetOwnBackgroundColour(Colour(200, 222, 40))
206 self.SetForegroundColour(Colour(7, 0, 70))
207 self.SetOwnForegroundColour(Colour(7, 0, 70))
208 """
209 self.Refresh(True)
210 self.editor = None
212 def show_editor(self, editor): 1ab
213 if editor is None:
214 return
215 if editor is self.editor: 215 ↛ 216line 215 didn't jump to line 216 because the condition on line 215 was never true
216 self.Show(True)
217 return
218 self.sizer.Clear()
219 self.editor = editor
220 self.sizer.Add(self.editor, 1, wx.ALL | wx.EXPAND)
221 self.Layout()
222 self.Show(True)
224 def hide_editor(self): 1ab
225 self.Show(False)
227 def on_save(self, event): 1ab
228 __ = event
229 self.plugin.save_selected_datafile()
231 def on_undo(self, event): 1ab
232 __ = event
233 self.editor.undo()
235 def on_redo(self, event): 1ab
236 __ = event
237 self.editor.redo()
239 def on_cut(self, event): 1ab
240 __ = event
241 self.editor.cut()
243 def on_copy(self, event): 1ab
244 __ = event
245 self.editor.copy()
247 def on_paste(self, event): 1ab
248 __ = event
249 self.editor.paste()
251 def on_insert(self, event): 1ab
252 __ = event
253 self.editor.insert()
255 def on_insert_cells(self, event): 1ab
256 __ = event
257 self.editor.insert_cells()
259 def on_delete_cells(self, event): 1ab
260 __ = event
261 # print("DEBUG init delete cells call")
262 self.editor.delete_cells()
264 def on_insert_rows(self, event): 1ab
265 __ = event
266 self.editor.insert_rows()
268 def on_delete_rows(self, event): 1ab
269 __ = event
270 wx.CallAfter(self.editor.delete_rows)
272 def on_move_rows_up(self, event): 1ab
273 __ = event
274 self.editor.on_move_rows_up()
276 def on_move_rows_down(self, event): 1ab
277 __ = event
278 self.editor.on_move_rows_down()
280 def on_delete(self, event): 1ab
281 __ = event
282 self.editor.delete()
284 def on_comment_rows(self, event): 1ab
285 __ = event
286 self.editor.comment_rows()
288 def on_uncomment_rows(self, event): 1ab
289 __ = event
290 self.editor.uncomment_rows()
292 def on_sharp_comment_rows(self, event): 1ab
293 __ = event
294 self.editor.sharp_comment_rows()
296 def on_sharp_uncomment_rows(self, event): 1ab
297 __ = event
298 self.editor.sharp_uncomment_rows()
300 def on_comment_cells(self, event): 1ab
301 __ = event
302 self.editor.comment_cells()
304 def on_uncomment_cells(self, event): 1ab
305 __ = event
306 self.editor.uncomment_cells()
308 def on_content_assistance(self, event): 1ab
309 __ = event
310 self.editor.show_content_assist()
312 def save(self, message=None): 1ab
313 __ = message
314 if self.editor: 314 ↛ 315line 314 didn't jump to line 315 because the condition on line 314 was never true
315 self.editor.save()
317 def on_key(self, *args): 1ab
318 """ Intentional override """
319 pass