Robot Framework Integrated Development Environment (RIDE)
preview.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 
17 import wx.html
18 from io import StringIO
19 from ..pluginapi import Plugin, TreeAwarePluginMixin
20 from ..action import ActionInfo
21 from ..publish import (RideTreeSelection, RideNotebookTabChanged, RideTestCaseAdded, RideUserKeywordAdded)
22 from ..robotapi import TestCase, UserKeyword
23 from ..widgets import ButtonWithHandler, Font
24 from ..utils import Printing
25 
26 
27 
29  datafile = property(lambda self: self.get_selected_datafileget_selected_datafile())
30 
31  def __init__(self, application):
32  Plugin.__init__(self, application, default_settings={'format': 'HTML'})
33  self._panel_panel = None
34 
35  def enable(self):
36  self.register_actionregister_action(ActionInfo('Tools','Preview', self.OnShowPreviewOnShowPreview,
37  shortcut='F6',
38  doc='Show preview of the current file',
39  position=71))
40  self.subscribesubscribe(self.OnTreeSelectionOnTreeSelection, RideTreeSelection)
41  self.subscribesubscribe(self.OnTabChangedOnTabChanged, RideNotebookTabChanged)
42  self.subscribesubscribe(self._update_preview_update_preview, RideTestCaseAdded)
43  self.subscribesubscribe(self._update_preview_update_preview, RideUserKeywordAdded)
44  self.add_self_as_tree_aware_pluginadd_self_as_tree_aware_plugin()
45 
46  def disable(self):
47  self.remove_self_from_tree_aware_pluginsremove_self_from_tree_aware_plugins()
48  self.unsubscribe_allunsubscribe_all()
49  self.unregister_actionsunregister_actions()
50  self.delete_tabdelete_tab(self._panel_panel)
51  self._panel_panel = None
52 
53  def is_focused(self):
54  return self.tab_is_visibletab_is_visible(self._panel_panel)
55 
56  def OnShowPreview(self, event):
57  if not self._panel_panel:
58  self._panel_panel = PreviewPanel(self, self.notebooknotebook)
59  self.show_tabshow_tab(self._panel_panel)
60  self._update_preview_update_preview(None)
61 
62  def OnTreeSelection(self, message):
63  if self.is_focusedis_focused():
64  self._panel_panel.tree_node_selected(message.item)
65 
66  def OnTabChanged(self, message):
67  self._update_preview_update_preview(None)
68 
69  def _update_preview(self, message):
70  if self.is_focusedis_focused() and self.datafiledatafiledatafile:
71  self._panel_panel.update_preview()
72 
73 
74 class PreviewPanel(wx.Panel):
75 
78  _formats = ['HTML', 'Text (Spaces)', 'Text (Pipes)']
79 
80  def __init__(self, parent, notebook):
81  wx.Panel.__init__(self, notebook)
82  self._parent_parent = parent
83  main_sizer = wx.BoxSizer(wx.VERTICAL)
84  self.SetSizer(main_sizer)
85  self._format_format = parent.format
86  self.__view__view = None
87  self._printing_printing = Printing(self)
88  box = wx.BoxSizer(wx.HORIZONTAL)
89  box.Add(self._chooser_chooser())
90  if wx.VERSION < (4, 1, 0):
91  box.Add(self._print_button_print_button(), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
92  else:
93  box.Add(self._print_button_print_button(), 1, wx.EXPAND)
94  self.Sizer.Add(box)
95  notebook.AddPage(self, "Preview")
96 
97  def OnPrint(self, evt):
98  self._printing_printing.preview_text(self._get_content_get_content())
99 
100  @property
101  _file_format = property
102 
103  def _file_format(self):
104  if self._format_format == 'HTML':
105  return self._format_format.lower()
106  return 'txt'
107 
108  @property
109  _pipe_separated = property
110 
111  def _pipe_separated(self):
112  return 'Pipes' in self._format_format
113 
114  def _chooser(self):
115  chooser = wx.RadioBox(self, label='Format', choices=self._formats_formats)
116  chooser.SetStringSelection(self._format_format)
117  self.Bind(wx.EVT_RADIOBOX, self.OnTypeChangedOnTypeChanged, chooser)
118  return chooser
119 
120  def _print_button(self):
121  return ButtonWithHandler(self, 'Print')
122 
123  @property
124  _view = property
125 
126  def _view(self):
127  view_class = HtmlView if self._file_format_file_format_file_format == 'html' else TxtView
128  if isinstance(self.__view__view, view_class):
129  return self.__view__view
130  self._remove_current_view_remove_current_view()
131  self.__view__view = self._create_view_create_view(view_class)
132  return self.__view__view
133 
135  if self.__view__view:
136  self.Sizer.Remove(self.__view__view)
137  self.__view__view.Destroy()
138 
139  def _create_view(self, view_class):
140  view = view_class(self)
141  self.Sizer.Add(view, 1, wx.EXPAND|wx.ALL, border=8)
142  self.Sizer.Layout()
143  return view
144 
145  def tree_node_selected(self, item):
146  self.update_previewupdate_preview()
147  self._view_view_view.scroll_to_subitem(item)
148 
149  def update_preview(self):
150  self._view_view_view.set_content(self._get_content_get_content())
151 
152  def _get_content(self):
153  datafile = self._parent_parent.datafile
154  if not datafile:
155  return ''
156  output = StringIO()
157  try:
158  datafile.save(
159  output=output,
160  format=self._file_format_file_format_file_format,
161  pipe_separated=self._pipe_separated_pipe_separated_pipe_separated,
162  txt_separating_spaces=self._parent_parent.global_settings['txt number of spaces']
163  )
164  except Exception as e:
165  return "Creating preview of '%s' failed: %s" % (datafile.name, e)
166  else:
167  return output.getvalue()
168 
169  def OnTypeChanged(self, event):
170  self._format_format = event.String
171  self.update_previewupdate_preview()
172  self._parent_parent.save_setting('format', self._format_format)
173 
174 
176 
177  def __init__(self, parent):
178  wx.html.HtmlWindow.__init__(self, parent)
179  self.SetStandardFonts()
180 
181  def set_content(self, content):
182  self.SetPage(content)
183 
184  def scroll_to_subitem(self, item):
185  anchor = self._get_anchor_get_anchor(item.data)
186  if self.HasAnchor(anchor):
187  self.ScrollToAnchor(anchor)
188  self.ScrollLines(-1)
189  else:
190  self.Scroll(0,0)
191 
192  def _get_anchor(self, data):
193  if isinstance(data, UserKeyword):
194  return 'keyword_%s' % data.name
195  if isinstance(data, TestCase):
196  return 'test_%s' % data.name
197  return ''
198 
199 
200 class TxtView(wx.TextCtrl):
201 
202  def __init__(self, parent):
203  wx.TextCtrl.__init__(self, parent, style=wx.TE_MULTILINE|wx.TE_NOHIDESEL)
204  self.SetEditable(False)
205  self.SetFont(Font().fixed)
206 
207  def set_content(self, content):
208  self.SetValue(content)
209 
210  def scroll_to_subitem(self, item):
211  pass
Used to create menu entries, keyboard shortcuts and/or toolbar buttons.
Definition: actioninfo.py:176
Entry point to RIDE plugin API – all plugins must extend this class.
Definition: plugin.py:50
def delete_tab(self, tab)
Deletes the tab added using add_tab.
Definition: plugin.py:248
def get_selected_datafile(self)
Returns the data file that is currently selected in the tree.
Definition: plugin.py:286
def subscribe(self, listener, *topics)
Start to listen to messages with the given topics.
Definition: plugin.py:396
def unsubscribe_all(self)
Stops to listen to all messages this plugin has subscribed to.
Definition: plugin.py:411
def register_action(self, action_info)
Registers a menu entry and optionally a shortcut and a toolbar icon.
Definition: plugin.py:205
def unregister_actions(self)
Unregisters all actions registered by this plugin.
Definition: plugin.py:230
def show_tab(self, tab)
Makes the tab added using add_tab visible.
Definition: plugin.py:244
def tab_is_visible(self, tab)
Returns is the tab added using add_tab visible or not.
Definition: plugin.py:260
Mixin to help solve if tree aware plugin has focus.
def set_content(self, content)
Definition: preview.py:181
def _get_anchor(self, data)
Definition: preview.py:192
def __init__(self, parent)
Definition: preview.py:177
def scroll_to_subitem(self, item)
Definition: preview.py:184
def __init__(self, parent, notebook)
Definition: preview.py:80
def OnTypeChanged(self, event)
Definition: preview.py:169
def tree_node_selected(self, item)
Definition: preview.py:145
def _create_view(self, view_class)
Definition: preview.py:139
Provides preview of the test data in HTML, TSV and TXT formats.
Definition: preview.py:28
def disable(self)
Called by RIDE when the plugin is disabled.
Definition: preview.py:46
def enable(self)
This method is called by RIDE when the plugin is enabled.
Definition: preview.py:35
def _update_preview(self, message)
Definition: preview.py:69
def OnTreeSelection(self, message)
Definition: preview.py:62
def __init__(self, application)
Definition: preview.py:31
def OnTabChanged(self, message)
Definition: preview.py:66
def OnShowPreview(self, event)
Definition: preview.py:56
def set_content(self, content)
Definition: preview.py:207
def scroll_to_subitem(self, item)
Definition: preview.py:210
def __init__(self, parent)
Definition: preview.py:202