Robot Framework Integrated Development Environment (RIDE)
kweditor.py
Go to the documentation of this file.
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.
15 
16 import json
17 from json.decoder import JSONDecodeError
18 
19 import wx
20 from wx import grid, Colour
21 from wx.grid import GridCellEditor
22 
23 from .contentassist import ExpandingContentAssistTextCtrl
24 from .editordialogs import UserKeywordNameDialog, ScalarVariableDialog, ListVariableDialog
25 from .gridbase import GridEditor, linesep
26 from .gridcolorizer import Colorizer
27 from .tooltips import GridToolTips
28 from .. import context
29 from .. import robotapi
30 from ..context import IS_MAC
31 from ..controller.cellinfo import TipMessage, ContentType, CellType
32 from ..controller.ctrlcommands import ChangeCellValue, ClearArea, \
33  PasteArea, DeleteRows, AddRows, CommentRows, InsertCells, DeleteCells, \
34  UncommentRows, Undo, Redo, RenameKeywordOccurrences, ExtractKeyword, \
35  AddKeywordFromCells, MoveRowsUp, MoveRowsDown, ExtractScalar, ExtractList, \
36  InsertArea
37 from ..editor.cellrenderer import CellRenderer
38 from ..pluginapi import Plugin
39 from ..publish import (RideItemStepsChanged, RideSaved, RideSettingsChanged,
40  PUBLISHER, RideBeforeSaving)
41 from ..ui.progress import RenameProgressObserver
42 from ..usages.UsageRunner import Usages, VariableUsages
43 from ..utils import variablematcher
44 from ..widgets import RIDEDialog, PopupMenu, PopupMenuItems
45 
46 
49 _DEFAULT_FONT_SIZE = 11
50 
51 
52 def requires_focus(function):
53  def _row_header_selected_on_linux(self):
54  return self.FindFocus() is None
55 
56  def decorated_function(self, *args):
57  if not self.has_focus():
58  return
59  if self.has_focus() or self.IsCellEditControlShown() or _row_header_selected_on_linux(self):
60  function(self, *args)
61 
62  return decorated_function
63 
64 
65 class KeywordEditor(GridEditor, Plugin):
66 
69  _no_cell = (-1, -1)
70 
73  _popup_menu_shown = False
74  dirty = property(lambda self: self._controller_controller.dirty)
75  update_value = lambda *args: None
76 
79  _popup_items = [
80  'Create Keyword',
81  'Extract Keyword',
82  'Extract Variable',
83  'Rename Keyword',
84  'Find Where Used',
85  'JSON Editor\tCtrl-Shift-J',
86  '---',
87  'Go to Definition\tCtrl-B',
88  '---',
89  'Undo\tCtrl-Z',
90  'Redo\tCtrl-Y',
91  '---',
92  'Make Variable\tCtrl-1',
93  'Make List Variable\tCtrl-2',
94  'Make Dict Variable\tCtrl-5',
95  '---',
96  'Comment Cells\tCtrl-Shift-3',
97  'Uncomment Cells\tCtrl-Shift-4',
98  'Move Cursor Down\tAlt-Enter',
99  '---',
100  'Comment Rows\tCtrl-3',
101  'Uncomment Rows\tCtrl-4',
102  'Move Rows Up\tAlt-Up',
103  'Move Rows Down\tAlt-Down',
104  'Swap Row Up\tCtrl-T',
105  '---',
106  ] + GridEditor._popup_items
107 
108  def __init__(self, parent, controller, tree):
109  self.settingssettingssettings = parent.plugin.global_settings['Grid']
110  self.general_settingsgeneral_settingsgeneral_settings = parent.plugin.global_settings['General']
111  # self.color_background_help = self.general_settings.get('background help', (240, 242, 80))
112  # self.color_foreground_text = self.general_settings.get('foreground text', (7, 0, 70))
113  self.color_backgroundcolor_backgroundcolor_background = self.general_settingsgeneral_settingsgeneral_settings['background']
114  self.color_foregroundcolor_foregroundcolor_foreground = self.general_settingsgeneral_settingsgeneral_settings['foreground']
115  self.color_secondary_backgroundcolor_secondary_backgroundcolor_secondary_background = self.general_settingsgeneral_settingsgeneral_settings['secondary background']
116  self.color_secondary_foregroundcolor_secondary_foregroundcolor_secondary_foreground = self.general_settingsgeneral_settingsgeneral_settings['secondary foreground']
117  self.color_background_helpcolor_background_helpcolor_background_help = self.general_settingsgeneral_settingsgeneral_settings['background help']
118  self.color_foreground_textcolor_foreground_textcolor_foreground_text = self.general_settingsgeneral_settingsgeneral_settings['foreground text']
119  GridEditor.__init__(
120  self, parent, len(controller.steps) + 5,
121  max((controller.max_columns + 1), 5),
122  parent.plugin._grid_popup_creator)
123  self._parent_parent = parent
124  self._plugin_plugin = parent.plugin
125  self._cell_selected_cell_selected = False
126  self._colorizer_colorizer = Colorizer(self, controller)
127  self._controller_controller = controller
128  self._configure_grid_configure_grid()
129  self._updating_namespace_updating_namespace = False
130  self._controller_controller.datafile_controller.register_for_namespace_updates(
131  self._namespace_updated_namespace_updated_namespace_updated)
132  self._tooltips_tooltips = GridToolTips(self)
133  self._marked_cell_marked_cell = None
134  self._make_bindings_make_bindings()
135  self._write_steps_write_steps(self._controller_controller)
136  self.autosizeautosize()
137  self._tree_tree = tree
138  self._has_been_clicked_has_been_clicked = False
139  self._counter_counter = 0 # Workaround for double delete actions
140  self._dcells_dcells = None # Workaround for double delete actions
141  self._icells_icells = None # Workaround for double insert actions
142  self.InheritAttributes()
143 
144  # TODO: This is ineffective, why?
145  """
146  self.SetBackgroundColour(Colour(self.color_secondary_background))
147  self.SetOwnBackgroundColour(Colour(self.color_secondary_background))
148  self.SetForegroundColour(Colour(self.color_secondary_foreground))
149  self.SetOwnForegroundColour(Colour(self.color_secondary_foreground))
150  """
151  # self.Refresh()
152  PUBLISHER.subscribe(self._before_saving_before_saving, RideBeforeSaving)
153  PUBLISHER.subscribe(self._data_changed_data_changed, RideItemStepsChanged)
154  # PUBLISHER.subscribe(self.OnSettingsChanged, RideSettingsChanged)
155  PUBLISHER.subscribe(self._ps_on_resize_grid_ps_on_resize_grid, RideSaved)
156 
158  if not self._updating_namespace_updating_namespace:
159  self._updating_namespace_updating_namespace = True
160  # See following issue for history of the next line:
161  # http://code.google.com/p/robotframework-ride/issues/detail?id=1108
162  wx.CallAfter(
163  wx.CallLater, 200, self._update_based_on_namespace_change_update_based_on_namespace_change)
164 
166  try:
167  self._colorize_grid_colorize_grid()
168  finally:
169  self._updating_namespace_updating_namespace = False
170 
171  def _ps_on_resize_grid(self, message):
172  self._resize_grid_resize_grid()
173 
174  @requires_focus
175  def _resize_grid(self):
176  if self.settingssettingssettings.get("auto size cols", False):
177  self.AutoSizeColumns(False)
178  if self.settingssettingssettings.get("word wrap", True):
179  self.AutoSizeRows(False)
180 
181  def _set_cells(self):
182  col_size = self.settingssettingssettings.get("col size", 150)
183  max_col_size = self.settingssettingssettings.get("max col size", 450)
184  auto_col_size = self.settingssettingssettings.get("auto size cols", False)
185  word_wrap = self.settingssettingssettings.get("word wrap", True)
186 
187  self.SetDefaultRenderer(
188  CellRenderer(col_size, max_col_size, auto_col_size, word_wrap))
189  self.SetRowLabelSize(wx.grid.GRID_AUTOSIZE)
190  self.SetColLabelSize(0)
191 
192  if auto_col_size:
193  self.SetDefaultColSize(wx.grid.GRID_AUTOSIZE, resizeExistingCols=True)
194  else:
195  self.SetDefaultColSize(col_size, resizeExistingCols=True)
196  self.SetColMinimalAcceptableWidth(col_size)
197 
198  if auto_col_size:
199  self.Bind(grid.EVT_GRID_CMD_COL_SIZE, self.OnCellColSizeChangedOnCellColSizeChanged)
200  else:
201  self.Unbind(grid.EVT_GRID_CMD_COL_SIZE)
202 
203  if word_wrap:
204  self.SetDefaultRowSize(wx.grid.GRID_AUTOSIZE)
205  self.SetDefaultCellOverflow(False) # DEBUG
206  self.autosizeautosize()
207  self._colorize_grid_colorize_grid()
208 
209  def _configure_grid(self):
210  self._set_cells_set_cells()
211  self.SetDefaultEditor(
212  ContentAssistCellEditor(self._plugin_plugin, self._controller_controller))
213  self._set_fonts_set_fonts()
214 
215  def _set_fonts(self, update_cells=False):
216  font_size = self.settingssettingssettings.get('font size', _DEFAULT_FONT_SIZE)
217  font_family = wx.FONTFAMILY_MODERN if self.settingssettingssettings['fixed font'] \
218  else wx.FONTFAMILY_DEFAULT
219  font_face = self.settingssettingssettings.get('font face', None)
220  if font_face is None:
221  font = wx.Font(font_size, font_family, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
222  self.settingssettingssettings.set('font face', font.GetFaceName())
223  else:
224  font = wx.Font(font_size, font_family, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, font_face)
225  self.SetDefaultCellFont(font)
226  for row in range(self.NumberRows):
227  for col in range(self.NumberCols):
228  self.SetCellFont(row, col, font)
229  self.ForceRefresh()
230 
231  def _make_bindings(self):
232  self.Bind(grid.EVT_GRID_EDITOR_SHOWN, self.OnEditorOnEditor)
233  self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDownOnKeyDown)
234  self.Bind(wx.EVT_CHAR, self.OnCharOnChar)
235  self.Bind(wx.EVT_KEY_UP, self.OnKeyUpOnKeyUp)
236  self.GetGridWindow().Bind(wx.EVT_MOTION, self.OnMotionOnMotion)
237  self.Bind(grid.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClickOnCellLeftClick)
238  self.Bind(grid.EVT_GRID_LABEL_RIGHT_CLICK, self.OnLabelRightClickOnLabelRightClick)
239  self.Bind(grid.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClickOnLabelLeftClick)
240  self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocusOnKillFocus)
241 
243  if self.IsCellEditControlShown() or self._popup_menu_shown_popup_menu_shown_popup_menu_shown:
244  return ''
245  cell = self.cell_under_cursorcell_under_cursorcell_under_cursor
246  cell_info = self._controller_controller.get_cell_info(cell.Row, cell.Col)
247  return TipMessage(cell_info)
248 
249 
250  def OnSettingsChanged(self, message):
251  section, setting = message.keys
252  if section == 'Grid':
253  if 'font' in setting:
254  self._set_fonts_set_fonts(update_cells=True)
255  elif ('col size' in setting
256  or 'max col size' in setting
257  or 'auto size cols' in setting
258  or 'word wrap' in setting):
259  self._set_cells_set_cells()
260  return
261  self.autosizeautosize()
262  self._colorize_grid_colorize_grid()
263 
264  def OnSelectCell(self, event):
265  self._cell_selected_cell_selected = True
266  GridEditor.OnSelectCell(self, event)
267  self._colorize_grid_colorize_grid()
268  event.Skip()
269 
270  def OnKillFocus(self, event):
271  self._tooltips_tooltips.hide()
272  self._hide_link_if_necessary_hide_link_if_necessary()
273  event.Skip()
274 
275  def _execute(self, command):
276  return self._controller_controller.execute(command)
277 
278  def _toggle_underlined(self, cell):
279  font = self.GetCellFont(cell.Row, cell.Col)
280  font.SetUnderlined(not font.Underlined)
281  self.SetCellFont(cell.Row, cell.Col, font)
282  self.Refresh()
283 
284  def OnLabelRightClick(self, event):
285  if event.Col == -1:
286  self._row_label_right_click_row_label_right_click(event)
287  else:
288  self._col_label_right_click_col_label_right_click(event)
289 
290  def _row_label_right_click(self, event):
291  selected_row = event.GetRow()
292  selected_rows = self.selectionselection.rows()
293  if selected_row not in selected_rows:
294  self.SelectRow(selected_row, addToSelected=False)
295  self.SetGridCursor(event.Row, 0)
296  popupitems = [
297  'Comment Rows\tCtrl-3',
298  'Uncomment Rows\tCtrl-4',
299  'Move Rows Up\tAlt-Up',
300  'Move Rows Down\tAlt-Down',
301  'Swap Row Up\tCtrl-T',
302  'Insert Rows\tCtrl-I',
303  'Delete Rows\tCtrl-D',
304  '---',
305  'Comment Cells\tCtrl-Shift-3',
306  'Uncomment Cells\tCtrl-Shift-4',
307  ]
308  PopupMenu(self, PopupMenuItems(self, popupitems))
309  event.Skip()
310 
311  def _col_label_right_click(self, event):
312  pass
313 
314  def OnLabelLeftClick(self, event):
315  if event.Col == -1:
316  self._row_label_left_click(event)
317  else:
318  self._col_label_left_click(event)
319 
320  def _row_label_left_click(self, event):
321  if event.ShiftDown() or event.ControlDown():
322  self.ClearSelection()
323  cursor_row = self.GetGridCursorRow()
324  event_row = event.Row
325  start, end = (cursor_row, event_row) \
326  if cursor_row < event_row else (event_row, cursor_row)
327  for row in range(start, end + 1):
328  self.SelectRow(row, addToSelected=True)
329  else:
330  self.SelectRow(event.Row, addToSelected=False)
331  self.SetGridCursor(event.Row, 0)
332 
333  def _col_label_left_click(self, event):
334  pass
335 
336  def OnMoveCursorDown(self, event=None):
337  self._move_cursor_down(event)
338 
339  def OnInsertRows(self, event):
340  self._execute_execute(AddRows(self.selectionselection.rows()))
341  self.ClearSelection()
342  self._resize_grid_resize_grid()
343  self._skip_except_on_mac_skip_except_on_mac(event)
344 
345  def _skip_except_on_mac(self, event): # TODO Do we still need this?
346  if event is not None and not IS_MAC:
347  # print("DEBUG skip!")
348  event.Skip()
349 
350  def OnInsertCells(self, event=None):
351  # TODO remove below workaround for double actions
352  if self._counter_counter == 1:
353  if self._icells_icells == (
354  self.selectionselection.topleft, self.selectionselection.bottomright):
355  self._counter_counter = 0
356  self._icells_icells = None
357  return
358  else:
359  self._counter_counter = 1
360 
361  self._icells_icells = (self.selectionselection.topleft,
362  self.selectionselection.bottomright)
363  self._execute_execute(InsertCells(self.selectionselection.topleft,
364  self.selectionselection.bottomright))
365  self._resize_grid_resize_grid()
366  self._skip_except_on_mac_skip_except_on_mac(event)
367 
368  def OnDeleteCells(self, event=None):
369  # TODO remove below workaround for double actions
370  if self._counter_counter == 1:
371  if self._dcells_dcells == (self.selectionselection.topleft,
372  self.selectionselection.bottomright):
373  self._counter_counter = 0
374  self._dcells_dcells = None
375  return
376  else:
377  self._counter_counter = 1
378 
379  self._dcells_dcells = (self.selectionselection.topleft, self.selectionselection.bottomright)
380  self._execute_execute(DeleteCells(self.selectionselection.topleft, self.selectionselection.bottomright))
381  self._resize_grid_resize_grid()
382  self._skip_except_on_mac_skip_except_on_mac(event)
383 
384  # DEBUG @requires_focus
385  def OnCommentRows(self, event=None):
386  self._execute_execute(CommentRows(self.selectionselection.rows()))
387  self._resize_grid_resize_grid()
388  self._skip_except_on_mac_skip_except_on_mac(event)
389 
390  # DEBUG @requires_focus
391  def OnUncommentRows(self, event=None):
392  self._execute_execute(UncommentRows(self.selectionselection.rows()))
393  self._resize_grid_resize_grid()
394  self._skip_except_on_mac_skip_except_on_mac(event)
395 
396  def OnMoveRowsUp(self, event=None):
397  self._row_move_row_move(MoveRowsUp, -1)
398 
399  def OnMoveRowsDown(self, event=None):
400  self._row_move_row_move(MoveRowsDown, 1)
401 
402  def OnSwapRowUp(self, event=None):
403  self._row_move_row_move(MoveRowsUp, 1, True)
404 
405  def _row_move(self, command, change, swap=False):
406  # Workaround for double actions, see issue #2048
407  if self._counter_counter == 1:
408  if IS_MAC:
409  row=self.GetGridCursorRow() + change
410  col=self.GetGridCursorCol()
411  if row >= 0:
412  self.SetGridCursor(row, col)
413  self._counter_counter = 0
414  return
415  else:
416  self._counter_counter += 1
417  rows = self.selectionselection.rows()
418  if self._execute_execute(command(rows)):
419  if swap:
420  wx.CallAfter(self._select_rows_select_rows, [r for r in rows])
421  else:
422  wx.CallAfter(self._select_rows_select_rows, [r + change for r in rows])
423  self._resize_grid_resize_grid()
424 
425  def _select_rows(self, rows):
426  self.ClearSelection()
427  for r in rows:
428  self.SelectRow(r, True)
429 
430  def OnMotion(self, event):
431  if IS_MAC:
432  if self.IsCellEditControlShown():
433  return
434  event.Skip()
435 
436  def _before_saving(self, message):
437  if self.IsCellEditControlShown():
438  # Fix: cannot save modifications in edit mode
439  # Exit edit mode before saving
440  self.HideCellEditControl()
441  self.SaveEditControlValue()
442  self.SetFocus()
443 
444  def _data_changed(self, message):
445  if self._controller_controller == message.item:
446  self._write_steps_write_steps(message.item)
447 
448  def _write_steps(self, controller):
449  data = []
450  self._write_headers_write_headers(controller)
451  for step in controller.steps:
452  data.append(self._format_comments_format_comments(step.as_list()))
453  self.ClearGrid()
454  self._write_data_write_data(data, update_history=False)
455  self._colorize_grid_colorize_grid()
456 
457  def _write_headers(self, controller):
458  headers = controller.data.parent.header[1:]
459  if not headers:
460  self.SetColLabelSize(0)
461  return
462  self.SetColLabelSize(wx.grid.GRID_AUTOSIZE) # DEBUG
463  for col, header in enumerate(headers):
464  self.SetColLabelValue(col, header)
465  for empty_col in range(col + 1, self.NumberCols + 1):
466  self.SetColLabelValue(empty_col, '')
467 
468  def _colorize_grid(self):
469  selection_content = \
470  self._get_single_selection_content_or_none_on_first_call_get_single_selection_content_or_none_on_first_call()
471  if selection_content is None:
472  self.highlighthighlight(None)
473  else:
474  self._parent_parent.highlight(selection_content, expand=False)
475 
476  def highlight(self, text, expand=True):
477  # Below CallAfter was causing C++ assertions(objects not found)
478  # When calling Preferences Grid Colors change
479  wx.CallLater(100, self._colorizer_colorizer.colorize, text)
480 
481  def autosize(self):
482  wx.CallAfter(self.AutoSizeColumns, False)
483  wx.CallAfter(self.AutoSizeRows, False)
484 
486  if self._cell_selected_cell_selected:
487  return self.get_single_selection_contentget_single_selection_content()
488 
489  def _format_comments(self, data):
490  # TODO: This should be moved to robot.model
491  in_comment = False
492  ret = []
493  for cell in data:
494  if cell.strip().startswith('#'):
495  in_comment = True
496  if in_comment:
497  cell = cell.replace(' |', '')
498  ret.append(cell)
499  return ret
500 
501  def cell_value_edited(self, row, col, value):
502  self._execute_execute(ChangeCellValue(row, col, value))
503  wx.CallAfter(self.AutoSizeColumn, col, False)
504  wx.CallAfter(self.AutoSizeRow, row, False)
505 
507  return self._controller_controller.datafile_controller
508 
509  # DEBUG @requires_focus
510  def OnCopy(self, event=None):
511  # print("DEBUG: OnCopy called event %s\n" % str(event))
512  self.copycopy()
513 
514  # DEBUG @requires_focus
515  def OnCut(self, event=None):
516  self._clipboard_handler_clipboard_handler.cut()
517  self.OnDeleteOnDelete(event)
518 
519  def OnDelete(self, event=None):
520  if not self.IsCellEditControlShown():
521  self._execute_execute(ClearArea(self.selectionselection.topleft,
522  self.selectionselection.bottomright))
523  self._resize_grid_resize_grid()
524 
525  # DEBUG @requires_focus
526  def OnPaste(self, event=None):
527  if self.IsCellEditControlShown():
528  self.pastepaste()
529  else:
530  self._execute_clipboard_command_execute_clipboard_command(PasteArea)
531  self._resize_grid_resize_grid()
532 
533  def _execute_clipboard_command(self, command_class):
534  if not self.IsCellEditControlShown():
535  data = self._clipboard_handler_clipboard_handler.clipboard_content()
536  if data:
537  data = [[data]] if isinstance(data, str) else data
538  self._execute_execute(command_class(self.selectionselection.topleft, data))
539 
540  # DEBUG @requires_focus
541  def OnInsert(self, event=None):
542  self._execute_clipboard_command_execute_clipboard_command(InsertArea)
543  self._resize_grid_resize_grid()
544 
545  def OnDeleteRows(self, event):
546  self._execute_execute(DeleteRows(self.selectionselection.rows()))
547  self.ClearSelection()
548  self._resize_grid_resize_grid()
549  self._skip_except_on_mac_skip_except_on_mac(event)
550 
551  # DEBUG @requires_focus
552  def OnUndo(self, event=None):
553  if not self.IsCellEditControlShown():
554  self._execute_execute(Undo())
555  else:
556  self.GetCellEditor(*self.selectionselection.cell).Reset()
557  self._resize_grid_resize_grid()
558 
559  # DEBUG @requires_focus
560  def OnRedo(self, event=None):
561  self._execute_execute(Redo())
562  self._resize_grid_resize_grid()
563 
564  def close(self):
565  self._colorizer_colorizer.close()
566  self.savesave()
567  PUBLISHER.unsubscribe_all(self)
568  if self._namespace_updated_namespace_updated_namespace_updated:
569  # Prevent re-entry to unregister method
570  self._controller_controller.datafile_controller.unregister_namespace_updates(
571  self._namespace_updated_namespace_updated_namespace_updated)
572  self._namespace_updated_namespace_updated_namespace_updated = None
573 
574  def save(self):
575  self._tooltips_tooltips.hide()
576  if self.IsCellEditControlShown():
577  cell_editor = self.GetCellEditor(*self.selectionselection.cell)
578  cell_editor.EndEdit(self.selectionselection.topleft.row,
579  self.selectionselection.topleft.col, self)
580 
582  if self.IsCellEditControlShown():
583  self.GetCellEditor(*self.selectionselection.cell).show_content_assist(self.selectionselection.cell)
584 
585  def refresh_datafile(self, item, event):
586  self._tree_tree.refresh_datafile(item, event)
587 
589  x, y = wx.GetMousePosition()
590  return x, y + 20
591 
592  def OnEditor(self, event):
593  self._tooltips_tooltips.hide()
594  row_height = self.GetRowSize(self.selectionselection.topleft.row)
595  self.GetCellEditor(*self.selectionselection.cell).SetHeight(row_height)
596  event.Skip()
597 
598  def _move_cursor_down(self, event):
599  self.DisableCellEditControl()
600  if event:
601  try:
602  shiftdown = event.ShiftDown()
603  except AttributeError:
604  shiftdown = False
605  else:
606  shiftdown = False
607  self.MoveCursorDown(shiftdown)
608 
609  def OnKeyDown(self, event):
610  keycode = event.GetUnicodeKey() or event.GetKeyCode()
611  if event.ControlDown():
612  if event.ShiftDown():
613  if keycode == ord('I'):
614  self.OnInsertCellsOnInsertCellsOnInsertCells()
615  elif keycode == ord('J'):
616  self.OnJsonEditorOnJsonEditor(event)
617  elif keycode == ord('D'):
618  self.OnDeleteCellsOnDeleteCellsOnDeleteCells()
619  """
620  elif keycode == ord('3'):
621  self._open_cell_editor_and_execute_sharp_comment()
622  elif keycode == ord('4'):
623  self._open_cell_editor_and_execute_sharp_uncomment()
624  """
625  else:
626  if keycode == wx.WXK_SPACE:
627  self._open_cell_editor_with_content_assist_open_cell_editor_with_content_assist()
628  return # event must not be skipped in this case
629  elif keycode == ord('C'):
630  self.OnCopyOnCopy(event)
631  elif keycode == ord('X'):
632  self.OnCutOnCut(event)
633  elif keycode == ord('V'):
634  self.OnPasteOnPaste(event)
635  elif keycode == ord('Z'):
636  self.OnUndoOnUndo(event)
637  elif keycode == ord('A'):
638  self.OnSelectAllOnSelectAll(event)
639  elif keycode == ord('B'):
640  self._navigate_to_matching_user_keyword_navigate_to_matching_user_keyword(
641  self.GetGridCursorRow(), self.GetGridCursorCol())
642  elif keycode == ord('F'):
643  if not self.has_focushas_focus():
644  self.SetFocus() # Avoiding Search field on Text Edit
645  elif keycode in (ord('1'), ord('2'), ord('5')):
646  self._open_cell_editor_and_execute_variable_creator_open_cell_editor_and_execute_variable_creator(
647  list_variable=(keycode == ord('2')),
648  dict_variable=(keycode == ord('5')))
649  elif keycode == ord('T'):
650  self._row_move_row_move(MoveRowsUp, 1, True)
651  else:
652  self.show_cell_informationshow_cell_information()
653  elif event.AltDown():
654  if keycode == wx.WXK_SPACE:
655  self._open_cell_editor_with_content_assist_open_cell_editor_with_content_assist() # Mac CMD
656  elif keycode in [wx.WXK_DOWN, wx.WXK_UP]:
657  self._move_rows_move_rows(keycode)
658  elif keycode == wx.WXK_RETURN:
659  if self.IsCellEditControlShown():
660  event.GetEventObject().WriteText(linesep)
661  else:
662  self._move_cursor_down_move_cursor_down(event)
663  return # event must not be skipped in this case
664  else:
665  if keycode == wx.WXK_WINDOWS_MENU:
666  self.OnCellRightClickOnCellRightClickOnCellRightClick(event)
667  elif keycode == wx.WXK_BACK:
668  self._move_grid_cursor_move_grid_cursor(event, keycode)
669  elif keycode == wx.WXK_RETURN:
670  if self.IsCellEditControlShown():
671  self._move_grid_cursor_move_grid_cursor(event, keycode)
672  else:
673  self._open_cell_editor_open_cell_editor()
674  return # event must not be skipped in this case
675  elif keycode == wx.WXK_F2:
676  self._open_cell_editor_open_cell_editor()
677  event.Skip()
678 
679  def OnChar(self, event):
680  keychar = event.GetUnicodeKey()
681  if keychar < ord(' '):
682  return
683  if keychar in [ord('['), ord('{'), ord('('), ord("'"), ord('\"'), ord('`')]:
684  self._open_cell_editor_open_cell_editor().execute_enclose_text(chr(keychar))
685  else:
686  event.Skip()
687 
688  def OnGoToDefinition(self, event):
689  self._navigate_to_matching_user_keyword_navigate_to_matching_user_keyword(
690  self.GetGridCursorRow(), self.GetGridCursorCol())
691 
693  cell = self.cell_under_cursorcell_under_cursorcell_under_cursor
694  value = self._cell_value_cell_value(cell)
695  if value:
696  self._show_user_keyword_link_show_user_keyword_link(cell, value)
697  self._show_keyword_details_show_keyword_details(cell, value)
698 
699  def _cell_value(self, cell):
700  if cell == self._no_cell_no_cell:
701  return None
702  return self.GetCellValue(cell.Row, cell.Col)
703 
704  def _show_user_keyword_link(self, cell, value):
705  if cell != self._marked_cell_marked_cell and self._plugin_plugin.get_user_keyword(value):
706  self._toggle_underlined_toggle_underlined(cell)
707  self._marked_cell_marked_cell = cell
708 
709  def _show_keyword_details(self, cell, value):
710  details = self._plugin_plugin.get_keyword_details(value)
711  if not details:
712  info = self._controller_controller.get_cell_info(cell.Row, cell.Col)
713  if info.cell_type == CellType.KEYWORD and info.content_type == \
714  ContentType.STRING:
715  details = """\
716  <b>Keyword was not detected by RIDE</b>
717  <br>Possible corrections:<br>
718  <ul>
719  <li>Import library or resource file containing the keyword.</li>
720  <li>For library import errors: Consider importing library spec XML
721  (Tools / Import Library Spec XML or by adding the XML file with the
722  correct name to PYTHONPATH) to enable keyword completion
723  for example for Java libraries.
724  Library spec XML can be created using libdoc tool from Robot Frame\
725 work.</li>
726  </ul>"""
727  if details:
728  self._tooltips_tooltips.show_info_at(
729  details, value, self._cell_to_screen_coordinates_cell_to_screen_coordinates(cell))
730 
732  point = self.CellToRect(cell.Row, cell.Col).GetTopRight()
733  point.x += self.GetRowLabelSize() + 5
734  return self.ClientToScreen(self.CalcScrolledPosition(point))
735 
736  def _move_rows(self, keycode):
737  if keycode == wx.WXK_UP:
738  self.OnMoveRowsUpOnMoveRowsUp()
739  else:
740  self.OnMoveRowsDownOnMoveRowsDown()
741 
742  def _move_grid_cursor(self, event, keycode):
743  self.DisableCellEditControl()
744  if keycode == wx.WXK_RETURN:
745  self.MoveCursorRight(event.ShiftDown())
746  else:
747  self.MoveCursorLeft(event.ShiftDown())
748 
750  # cell = self.cell_under_cursor()
751  # self.MoveCursorRight(False)
752  self._open_cell_editor_open_cell_editor()
753 
754  def OnKeyUp(self, event):
755  event.Skip() # DEBUG seen this skip as soon as possible
756  self._tooltips_tooltips.hide()
757  self._hide_link_if_necessary_hide_link_if_necessary()
758  # event.Skip()
759 
760  def _open_cell_editor(self):
761  if not self.IsCellEditControlEnabled():
762  self.EnableCellEditControl()
763  row = self.GetGridCursorRow()
764  celleditor = self.GetCellEditor(self.GetGridCursorCol(), row)
765  celleditor.Show(True)
766  return celleditor
767 
769  # print(f"DEBUG: kweditor call _open_cell_editor_with_content_assist")
770  wx.CallAfter(self._open_cell_editor_open_cell_editor().show_content_assist)
771  # wx.CallAfter(self._move_grid_cursor, wx.grid.GridEvent(), wx.WXK_RETURN)
772 
774  self, list_variable=False, dict_variable=False):
775  wx.CallAfter(self._open_cell_editor_open_cell_editor().execute_variable_creator,
776  list_variable, dict_variable)
777 
778  def OnMakeVariable(self, event):
779  self._open_cell_editor_and_execute_variable_creator_open_cell_editor_and_execute_variable_creator(list_variable=False)
780 
781  def OnMakeListVariable(self, event):
782  self._open_cell_editor_and_execute_variable_creator_open_cell_editor_and_execute_variable_creator(list_variable=True)
783 
784  def OnMakeDictVariable(self, event):
785  self._open_cell_editor_and_execute_variable_creator_open_cell_editor_and_execute_variable_creator(dict_variable=True)
786 
788  # Meant for a single cell selection!
789  wx.CallAfter(self._open_cell_editor_open_cell_editor().execute_sharp_comment)
790 
792  # Meant for a single cell selection!
793  wx.CallAfter(self._open_cell_editor_open_cell_editor().execute_sharp_uncomment)
794 
795  def OnCommentCells(self, event):
796  self._open_cell_editor_and_execute_sharp_comment_open_cell_editor_and_execute_sharp_comment()
797 
798  def OnUncommentCells(self, event):
799  self._open_cell_editor_and_execute_sharp_uncomment_open_cell_editor_and_execute_sharp_uncomment()
800 
801  def OnCellRightClick(self, event):
802  self._tooltips_tooltips.hide()
803  self._popup_menu_shown_popup_menu_shown_popup_menu_shown = True
804  GridEditor.OnCellRightClick(self, event)
805  self._popup_menu_shown_popup_menu_shown_popup_menu_shown = False
806 
807  def OnSelectAll(self, event):
808  self.SelectAll()
809 
810  def OnCellColSizeChanged(self, event):
811  wx.CallAfter(self.AutoSizeRows, False)
812  event.Skip()
813 
814  def OnCellLeftClick(self, event):
815  self._tooltips_tooltips.hide()
816  if event.ControlDown():
817  if self._navigate_to_matching_user_keyword_navigate_to_matching_user_keyword(event.Row, event.Col):
818  return
819  if not self._has_been_clicked_has_been_clicked:
820  self.SetGridCursor(event.Row, event.Col)
821  self._has_been_clicked_has_been_clicked = True
822  else:
823  event.Skip()
824 
826  value = self.GetCellValue(row, col)
827  uk = self._plugin_plugin.get_user_keyword(value)
828  if uk:
829  self._toggle_underlined_toggle_underlined((grid.GridCellCoords(row, col)))
830  self._marked_cell_marked_cell = None
831  wx.CallAfter(self._tree_tree.select_user_keyword_node, uk)
832  return True
833  return False
834 
835  def _is_active_window(self):
836  return self.IsShownOnScreen() and self.FindFocus()
837 
839  if not self._marked_cell_marked_cell:
840  return
841  self._toggle_underlined_toggle_underlined(self._marked_cell_marked_cell)
842  self._marked_cell_marked_cell = None
843 
844  def OnCreateKeyword(self, event):
845  cells = self._data_cells_from_current_row_data_cells_from_current_row()
846  if not cells:
847  return
848  try:
849  self._execute_execute(AddKeywordFromCells(cells))
850  except ValueError as err:
851  wx.MessageBox(str(err))
852 
854  currow, curcol = self.selectionselection.cell
855  rowdata = self._row_data_row_data(currow)[curcol:]
856  return self._strip_trailing_empty_cells_strip_trailing_empty_cells(self._remove_comments_remove_comments(rowdata))
857 
858  def _remove_comments(self, data):
859  for index, cell in enumerate(data):
860  if cell.strip().startswith('#'):
861  return data[:index]
862  return data
863 
864  def OnExtractKeyword(self, event):
865  dlg = UserKeywordNameDialog(self._controller_controller)
866  if dlg.ShowModal() == wx.ID_OK:
867  name, args = dlg.get_value()
868  rows = self.selectionselection.topleft.row, self.selectionselection.bottomright.row
869  self._execute_execute(ExtractKeyword(name, args, rows))
870 
871  def OnExtractVariable(self, event):
872  cells = self.selectionselection.cells()
873  if len(cells) == 1:
874  self._extract_scalar_extract_scalar(cells[0])
875  elif min(row for row, _ in cells) == max(row for row, _ in cells):
876  self._extract_list_extract_list(cells)
877  self._resize_grid_resize_grid()
878 
879  def OnFindWhereUsed(self, event):
880  is_variable, searchstring = self._get_is_variable_and_searchstring_get_is_variable_and_searchstring()
881  if searchstring:
882  self._execute_find_where_used_execute_find_where_used(is_variable, searchstring)
883 
885  cellvalue = self.GetCellValue(*self.selectionselection.cells()[0])
886  if self._cell_value_contains_multiple_search_items_cell_value_contains_multiple_search_items(cellvalue):
887  choice_dialog = ChooseUsageSearchStringDialog(cellvalue)
888  choice_dialog.ShowModal()
889  is_var, value = choice_dialog.GetStringSelection()
890  choice_dialog.Destroy()
891  return is_var, value
892  else:
893  return variablematcher.is_variable(cellvalue), cellvalue
894 
895  def _execute_find_where_used(self, is_variable, searchstring):
896  usages_dialog_class = VariableUsages if is_variable else Usages
897  usages_dialog_class(
898  self._controller_controller,
899  self._tree_tree.highlight, searchstring).show()
900 
902  variables = variablematcher.find_variable_basenames(value)
903  return variables and variables[0] != value
904 
905  def _extract_scalar(self, cell):
906  var = robotapi.Variable(
907  self._controller_controller.datafile.variable_table, '',
908  self.GetCellValue(*cell), '')
909  dlg = ScalarVariableDialog(
910  self._controller_controller.datafile_controller.variables, var)
911  if dlg.ShowModal() == wx.ID_OK:
912  name, value = dlg.get_value()
913  comment = dlg.get_comment()
914  self._execute_execute(ExtractScalar(name, value, comment, cell))
915 
916  def _extract_list(self, cells):
917  var = robotapi.Variable(
918  self._controller_controller.datafile.variable_table,
919  '', [self.GetCellValue(*cell) for cell in cells], '')
920  dlg = ListVariableDialog(
921  self._controller_controller.datafile_controller.variables, var, self._plugin_plugin)
922  if dlg.ShowModal() == wx.ID_OK:
923  name, value = dlg.get_value()
924  comment = dlg.get_comment()
925  self._execute_execute(ExtractList(name, value, comment, cells))
926 
927  def OnRenameKeyword(self, event):
928  old_name = self._current_cell_value_current_cell_value()
929  if not old_name.strip() or variablematcher.is_variable(old_name):
930  return
931  new_name = wx.GetTextFromUser('New name', 'Rename Keyword',
932  default_value=old_name)
933  if new_name:
934  self._execute_execute(RenameKeywordOccurrences(
935  old_name, new_name, RenameProgressObserver(self.GetParent())))
936 
937  # Add one new Dialog to edit pretty json String TODO: use better editor with more functions
938  def OnJsonEditor(self, event=None):
939  if event:
940  event.Skip()
941  dialog = RIDEDialog()
942  dialog.SetTitle('JSON Editor')
943  dialog.SetSizer(wx.BoxSizer(wx.HORIZONTAL))
944  okBtn = wx.Button(dialog, wx.ID_OK, "Save")
945  cnlBtn = wx.Button(dialog, wx.ID_CANCEL, "Cancel")
946  richText = wx.TextCtrl(dialog, wx.ID_ANY, "If supported by the native "
947  "control, this is reversed, "
948  "and this is a different "
949  "font.",
950  size=(400, 475),
951  style=wx.HSCROLL | wx.TE_MULTILINE | wx.TE_NOHIDESEL)
952  dialog.Sizer.Add(richText, flag=wx.GROW, proportion=1)
953  dialog.Sizer.Add(okBtn, flag=wx.ALL)
954  dialog.Sizer.Add(cnlBtn, flag=wx.ALL)
955  # Get cell value of parent grid
956  if self.is_jsonis_json(self._current_cell_value_current_cell_value()):
957  jsonStr = json.loads(self._current_cell_value_current_cell_value())
958  richText.SetValue(
959  json.dumps(jsonStr, indent=4, ensure_ascii=False))
960  else:
961  richText.SetValue(self._current_cell_value_current_cell_value())
962  dialog.SetSize((650, 550))
963  # If click Save, then save the value in richText into the original
964  # grid cell, and clear all indent.
965  if dialog.ShowModal() == wx.ID_OK:
966  content = richText.GetValue()
967  if self.is_jsonis_json(content):
968  strJson = json.loads(content)
969  self.cell_value_editedcell_value_edited(self.selectionselection.cell[0], self.selectionselection.cell[1],
970  json.dumps(strJson, ensure_ascii=False))
971  else:
972  try:
973  json.loads(content) # Yes, we need the error
974  except JSONDecodeError as e:
975  res = wx.MessageDialog(dialog,
976  f"Error in JSON: {e}\n\n"
977  "Save anyway?",
978  "Validation Error!",
979  wx.YES_NO)
980  res.InheritAttributes()
981  response = res.ShowModal()
982  if response == wx.ID_YES:
983  self.cell_value_editedcell_value_edited(self.selectionselection.cell[0],
984  self.selectionselection.cell[1],
985  richText.GetValue())
986  else:
987  pass
988 
989  # If the jsonStr is json format, then return True
990  def is_json(self, jsonStr):
991  try:
992  json.loads(jsonStr)
993  except JSONDecodeError:
994  return False
995  return True
996 
997 
998 class ContentAssistCellEditor(GridCellEditor):
999 
1000  def __init__(self, plugin, controller):
1001  self.settingssettings = plugin.global_settings['Grid']
1002  self.general_settingsgeneral_settings = plugin.global_settings['General']
1003  self.color_background_helpcolor_background_help = self.general_settingsgeneral_settings['background help']
1004  self.color_foreground_textcolor_foreground_text = self.general_settingsgeneral_settings['foreground text']
1005  GridCellEditor.__init__(self)
1006  self._plugin_plugin = plugin
1007  self._controller_controller = controller
1008  self._grid_grid = None
1009  self._original_value_original_value = None
1010  self._value_value = None
1011  self._tc_tc = None
1012  self._counter_counter = 0
1013 
1014  def show_content_assist(self, args=None):
1015  if self._tc_tc:
1016  self._tc_tc.show_content_assist()
1017 
1018  def execute_variable_creator(self, list_variable=False,
1019  dict_variable=False):
1020  self._tc_tc.execute_variable_creator(list_variable, dict_variable)
1021 
1022  def execute_enclose_text(self, keycode):
1023  self._tc_tc.execute_enclose_text(keycode)
1024 
1026  self._tc_tc.execute_sharp_comment()
1027 
1029  self._tc_tc.execute_sharp_uncomment()
1030 
1031  def Create(self, parent, id, evthandler):
1033  parent, self._plugin_plugin, self._controller_controller)
1034  self.SetControl(self._tc_tc)
1035  if evthandler:
1036  self._tc_tc.PushEventHandler(evthandler)
1037 
1038  def SetSize(self, rect):
1039  self._tc_tc.SetSize(rect.x, rect.y, rect.width + 2, rect.height + 2, wx.SIZE_ALLOW_MINUS_ONE)
1040 
1041  def SetHeight(self, height):
1042  self._height_height = height
1043 
1044  def BeginEdit(self, row, col, grid):
1045  self._counter_counter = 0
1046  self._tc_tc.SetSize((-1, self._height_height))
1047  self._tc_tc.SetBackgroundColour(self.color_background_helpcolor_background_help) # DEBUG: We are now in Edit mode
1048  self._tc_tc.SetForegroundColour(self.color_foreground_textcolor_foreground_text)
1049  self._tc_tc.set_row(row)
1050  self._original_value_original_value = grid.GetCellValue(row, col)
1051  self._tc_tc.SetValue(self._original_value_original_value)
1052  self._tc_tc.SetSelection(0, self._tc_tc.GetLastPosition())
1053  self._tc_tc.SetFocus()
1054  self._grid_grid = grid
1055 
1056  def EndEdit(self, row, col, grid, *ignored):
1057  value = self._get_value_get_value()
1058  if value != self._original_value_original_value:
1059  self._value_value = value
1060  # print(f"DEBUG: kweditor returning ContentAssistCellEditor.EndEdit {value} and moving right")
1061  wx.CallAfter(self._grid_grid.move_grid_cursor_and_edit)
1062  return value
1063  else:
1064  self._tc_tc.hide()
1065  grid.SetFocus()
1066 
1067  def ApplyEdit(self, row, col, grid):
1068  val = self._tc_tc.GetValue()
1069  grid.GetTable().SetValue(row, col, val) # update the table
1070  self._original_value_original_value = ''
1071  self._tc_tc.SetValue('')
1072  # if self._value and val != '': # DEBUG Fix #1967 crash when click other cell
1073  # this will cause deleting all text in edit mode not working
1074  self._grid_grid.cell_value_edited(row, col, self._value_value)
1075 
1076  def _get_value(self):
1077  suggestion = self._tc_tc.content_assist_value()
1078  return suggestion or self._tc_tc.GetValue()
1079 
1080  def Reset(self):
1081  self._tc_tc.SetValue(self._original_value_original_value)
1082  self._tc_tc.reset()
1083 
1084  def StartingKey(self, event):
1085  key = event.GetKeyCode()
1086  event.Skip() # DEBUG seen this skip as soon as possible
1087  if key == wx.WXK_DELETE or key > 255:
1088  # print(f"DEBUG: Delete key at ContentAssist key {key}")
1089  self._grid_grid.HideCellEditControl()
1090  elif key == wx.WXK_BACK:
1091  self._tc_tc.SetValue(self._original_value_original_value)
1092  else:
1093  self._tc_tc.SetValue(chr(key))
1094  self._tc_tc.SetFocus()
1095  self._tc_tc.SetInsertionPointEnd()
1096 
1097  def Clone(self):
1098  return ContentAssistCellEditor()
1099 
1100 
1102 
1103  def __init__(self, cellvalue):
1104  wx.Dialog.__init__(self, None, wx.ID_ANY, "Find Where Used",
1105  style=wx.DEFAULT_DIALOG_STYLE)
1106  """
1107  self.SetBackgroundColour(Colour(200, 222, 40))
1108  self.SetForegroundColour(Colour(7, 0, 70))
1109  """
1110  self.captioncaption = "Please select what you want to check for usage"
1111  variables = set(variablematcher.find_variable_basenames(cellvalue))
1112  self.choiceschoices = [(False, cellvalue)] + [(True, v) for v in variables]
1113  self.choices_stringchoices_string = ["Complete cell content"] + \
1114  ["Variable " + var.replace("&", "&&") for var
1115  in variables]
1116  self._build_ui_build_ui()
1117 
1118  def _build_ui(self):
1119  self.radiobox_choicesradiobox_choices = wx.RadioBox(
1120  self, choices=self.choices_stringchoices_string, style=wx.RA_SPECIFY_COLS,
1121  majorDimension=1)
1122  sizer = wx.BoxSizer(wx.VERTICAL)
1123  sizer.Add(wx.StaticText(self, label=self.captioncaption), 0, wx.ALL |
1124  wx.EXPAND, 5)
1125  sizer.Add(self.radiobox_choicesradiobox_choices, 0, wx.ALL | wx.EXPAND, 5)
1126  sizer.Add(wx.Button(self, wx.ID_OK, label="Search"),
1127  0, wx.ALL | wx.ALIGN_CENTER, 5)
1128  big_sizer = wx.BoxSizer(wx.VERTICAL)
1129  big_sizer.Add(sizer, 0, wx.ALL, 10)
1130  self.SetSizer(big_sizer)
1131  self.Fit()
1132  self.CenterOnParent()
1133 
1135  return self.choiceschoices[self.radiobox_choicesradiobox_choices.GetSelection()]
GridCellAutoWrapStringRenderer()
Definition: cellrenderer.py:22
def _write_data(self, data, update_history=True)
Definition: gridbase.py:222
def OnCellRightClick(self, event)
Definition: gridbase.py:255
def _strip_trailing_empty_cells(self, rowdata)
Definition: gridbase.py:211
def __init__(self, plugin, controller)
Definition: kweditor.py:1000
def execute_variable_creator(self, list_variable=False, dict_variable=False)
Definition: kweditor.py:1019
def Create(self, parent, id, evthandler)
Definition: kweditor.py:1031
def EndEdit(self, row, col, grid, *ignored)
Definition: kweditor.py:1056
def OnMoveRowsUp(self, event=None)
Definition: kweditor.py:396
def refresh_datafile(self, item, event)
Definition: kweditor.py:585
def _open_cell_editor_and_execute_sharp_uncomment(self)
Definition: kweditor.py:791
def OnMoveRowsDown(self, event=None)
Definition: kweditor.py:399
def highlight(self, text, expand=True)
Definition: kweditor.py:476
def cell_value_edited(self, row, col, value)
Definition: kweditor.py:501
def _row_move(self, command, change, swap=False)
Definition: kweditor.py:405
def OnSwapRowUp(self, event=None)
Definition: kweditor.py:402
def _execute_find_where_used(self, is_variable, searchstring)
Definition: kweditor.py:895
def __init__(self, parent, controller, tree)
Definition: kweditor.py:108
def _write_headers(self, controller)
Definition: kweditor.py:457
def _cell_value_contains_multiple_search_items(self, value)
Definition: kweditor.py:901
def _col_label_left_click(self, event)
Definition: kweditor.py:333
def _navigate_to_matching_user_keyword(self, row, col)
Definition: kweditor.py:825
def _row_label_left_click(self, event)
Definition: kweditor.py:320
def _show_user_keyword_link(self, cell, value)
Definition: kweditor.py:704
def _open_cell_editor_and_execute_sharp_comment(self)
Definition: kweditor.py:787
def OnInsert(self, event=None)
Definition: kweditor.py:541
def _set_fonts(self, update_cells=False)
Definition: kweditor.py:215
def OnDelete(self, event=None)
Definition: kweditor.py:519
def OnRedo(self, event=None)
Definition: kweditor.py:560
def OnUncommentRows(self, event=None)
Definition: kweditor.py:391
def _move_grid_cursor(self, event, keycode)
Definition: kweditor.py:742
def _show_keyword_details(self, cell, value)
Definition: kweditor.py:709
def _col_label_right_click(self, event)
Definition: kweditor.py:311
def OnJsonEditor(self, event=None)
Definition: kweditor.py:938
def _write_steps(self, controller)
Definition: kweditor.py:448
def OnCommentRows(self, event=None)
Definition: kweditor.py:385
def OnMoveCursorDown(self, event=None)
Definition: kweditor.py:336
def _open_cell_editor_and_execute_variable_creator(self, list_variable=False, dict_variable=False)
Definition: kweditor.py:774
def OnPaste(self, event=None)
Definition: kweditor.py:526
def OnUndo(self, event=None)
Definition: kweditor.py:552
def _row_label_right_click(self, event)
Definition: kweditor.py:290
def _get_single_selection_content_or_none_on_first_call(self)
Definition: kweditor.py:485
def OnSettingsChanged(self, message)
Redraw the colors if the color settings are modified.
Definition: kweditor.py:250
def _cell_to_screen_coordinates(self, cell)
Definition: kweditor.py:731
def _ps_on_resize_grid(self, message)
Definition: kweditor.py:171
def OnDeleteCells(self, event=None)
Definition: kweditor.py:368
def _execute_clipboard_command(self, command_class)
Definition: kweditor.py:533
def OnCopy(self, event=None)
Definition: kweditor.py:510
def OnInsertCells(self, event=None)
Definition: kweditor.py:350
def ExtractScalar(name, value, comment, cell)
def ClearArea(top_left, bottom_right)
def InsertCells(top_left, bottom_right)
def ExtractList(name, value, comment, cells)
def DeleteCells(top_left, bottom_right)
def requires_focus(function)
Definition: kweditor.py:52