Package gui :: Module results_viewer
[hide private]
[frames] | no frames]

Source Code for Module gui.results_viewer

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2010 Michael Bieri                                            # 
  4  # Copyright (C) 2011 Edward d'Auvergne                                        # 
  5  #                                                                             # 
  6  # This file is part of the program relax.                                     # 
  7  #                                                                             # 
  8  # relax is free software; you can redistribute it and/or modify               # 
  9  # it under the terms of the GNU General Public License as published by        # 
 10  # the Free Software Foundation; either version 2 of the License, or           # 
 11  # (at your option) any later version.                                         # 
 12  #                                                                             # 
 13  # relax is distributed in the hope that it will be useful,                    # 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 16  # GNU General Public License for more details.                                # 
 17  #                                                                             # 
 18  # You should have received a copy of the GNU General Public License           # 
 19  # along with relax; if not, write to the Free Software                        # 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """Module containing the base class for the results frame.""" 
 26   
 27  # Python module imports. 
 28  from string import lower, upper 
 29  import wx 
 30  from wx.lib import buttons 
 31   
 32  # relax module imports. 
 33  from data import Relax_data_store; ds = Relax_data_store() 
 34  from generic_fns.pipes import cdp_name, pipe_names 
 35  from status import Status; status = Status() 
 36   
 37  # relax GUI module imports. 
 38  from gui.fonts import font 
 39  from gui.icons import relax_icons 
 40  from gui.interpreter import Interpreter; interpreter = Interpreter() 
 41  from gui.misc import add_border, gui_to_str, open_file, str_to_gui 
 42  from gui.paths import icon_22x22 
 43  from gui.user_functions import User_functions 
 44   
 45   
46 -class Results_viewer(wx.Frame):
47 """The results viewer frame.""" 48 49 # Some class variables. 50 border = 10 51 size = (800, 400) 52
53 - def __init__(self, parent):
54 """Build the results frame. 55 56 @param parent: The parent wx object. 57 @type parent: wx object 58 """ 59 60 # Initialise the base frame. 61 wx.Frame.__init__(self, parent=parent, style=wx.DEFAULT_FRAME_STYLE) 62 63 # Initialise the user functions. 64 self.user_functions = User_functions(self) 65 66 # Set up the window icon. 67 self.SetIcons(relax_icons) 68 69 # Set the window title, size, etc. 70 self.SetTitle("Results viewer") 71 self.SetSize(self.size) 72 73 # Place all elements within a panel (to remove the dark grey in MS Windows). 74 self.main_panel = wx.Panel(self, -1) 75 76 # Pack a sizer into the panel. 77 box_main = wx.BoxSizer(wx.HORIZONTAL) 78 self.main_panel.SetSizer(box_main) 79 80 # Build the central sizer, with borders. 81 box_centre = add_border(box_main, border=self.border, packing=wx.VERTICAL) 82 83 # Build the data pipe selector. 84 self.build_pipe_sel(box_centre) 85 86 # Spacer. 87 box_centre.AddSpacer(self.border) 88 89 # Add the list of results files. 90 self.add_files(box_centre) 91 92 # Spacer. 93 box_centre.AddSpacer(self.border) 94 95 # Add the open button. 96 self.button_open = buttons.ThemedGenBitmapTextButton(self.main_panel, -1, None, " Open") 97 self.button_open.SetBitmapLabel(wx.Bitmap(icon_22x22.document_open, wx.BITMAP_TYPE_ANY)) 98 self.button_open.SetFont(font.normal) 99 self.button_open.SetMinSize((103, 33)) 100 self.Bind(wx.EVT_BUTTON, self.open_result_file, self.button_open) 101 box_centre.Add(self.button_open, 0, wx.ALIGN_RIGHT|wx.ADJUST_MINSIZE, 5) 102 103 # Relayout the main panel. 104 self.main_panel.Layout() 105 self.main_panel.Refresh() 106 107 # Bind some events. 108 self.Bind(wx.EVT_COMBOBOX, self.switch_pipes, self.pipe_name) 109 self.Bind(wx.EVT_CLOSE, self.handler_close) 110 111 # Initialise observer name. 112 self.name = 'results viewer'
113 114
115 - def Show(self, show=True):
116 """Change the behaviour of showing the window to update the content. 117 118 @keyword show: A flag which is True shows the window. 119 @type show: bool 120 """ 121 122 # Register a few methods in the observer objects. 123 status.observers.gui_uf.register(self.name, self.refresh) 124 status.observers.pipe_alteration.register(self.name, self.refresh) 125 status.observers.result_file.register(self.name, self.refresh) 126 status.observers.exec_lock.register(self.name, self.activate) 127 128 # First update. 129 self.refresh() 130 131 # Activate or deactivate the frame. 132 self.activate() 133 134 # Show the window using the base class method. 135 if status.show_gui: 136 super(Results_viewer, self).Show(show)
137 138
139 - def activate(self):
140 """Activate or deactivate certain elements in response to the execution lock.""" 141 142 # Flag for enabling or disabling the elements. 143 enable = False 144 if not status.exec_lock.locked(): 145 enable = True 146 147 # The pipe selector. 148 wx.CallAfter(self.pipe_name.Enable, enable) 149 150 # The open button. 151 wx.CallAfter(self.button_open.Enable, enable)
152 153
154 - def add_files(self, box):
155 """Create the list of results files. 156 157 @param box: The box sizer to pack the box into. 158 @type box: wx.BoxSizer instance 159 @return: The list box element. 160 @rtype: wx.ListBox element 161 """ 162 163 # Initialise the list box. 164 self.file_list = wx.ListCtrl(self.main_panel, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT) 165 166 # Properties. 167 self.file_list.SetFont(font.normal) 168 169 # Store the base heights. 170 self.height_char = self.file_list.GetCharHeight() 171 172 # The headers. 173 self.file_list.InsertColumn(0, "File type") 174 self.file_list.InsertColumn(1, "File path") 175 176 # Add to the sizer. 177 box.Add(self.file_list, 1, wx.ALL|wx.EXPAND, 0) 178 179 # Bind events. 180 self.file_list.Bind(wx.EVT_SIZE, self.resize) 181 self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.open_result_file, self.file_list)
182 183
184 - def build_pipe_sel(self, box):
185 """Create the data pipe selection element. 186 187 @param box: The horizontal box element to pack the elements into. 188 @type box: wx.BoxSizer instance 189 """ 190 191 # Use a horizontal packing of elements. 192 sizer = wx.BoxSizer(wx.HORIZONTAL) 193 194 # The text. 195 label = wx.StaticText(self.main_panel, -1, "Data pipe selection") 196 197 # The font and label properties. 198 label.SetFont(font.subtitle) 199 200 # Add the label to the box. 201 sizer.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 202 203 # Add a spacer. 204 sizer.AddSpacer(self.border) 205 206 # A combo box. 207 self.pipe_name = wx.ComboBox(self.main_panel, -1, value='', style=wx.CB_DROPDOWN|wx.CB_READONLY, choices=[]) 208 self.pipe_name.SetMinSize((50, 27)) 209 sizer.Add(self.pipe_name, 1, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) 210 211 # Add the pipe sizer to the main sizer. 212 box.Add(sizer, 0, wx.ALL|wx.EXPAND, 0)
213 214
215 - def handler_close(self, event):
216 """Event handler for the close window action. 217 218 @param event: The wx event. 219 @type event: wx event 220 """ 221 222 # Unregister the methods from the observers to avoid unnecessary updating. 223 status.observers.gui_uf.unregister(self.name) 224 status.observers.pipe_alteration.unregister(self.name) 225 status.observers.result_file.unregister(self.name) 226 status.observers.exec_lock.unregister(self.name) 227 228 # Close the window. 229 self.Hide()
230 231
232 - def open_result_file(self, event):
233 """Open the results in the appropriate program. 234 235 @param event: The wx event. 236 @type event: wx event 237 """ 238 239 # Loop over all files. 240 for i in range(self.file_list.GetItemCount()): 241 # Not selected. 242 if not self.file_list.IsSelected(i): 243 continue 244 245 # Get the type and file. 246 type = self.file_data[i] 247 file = gui_to_str(self.file_list.GetItem(i, 1).GetText()) 248 249 # Grace files. 250 if type == 'grace': 251 self.user_functions.grace.view(file=file) 252 253 # PyMOL macro files. 254 elif type == 'pymol': 255 self.user_functions.pymol.macro_run(file=file) 256 257 # Molmol macro files. 258 elif type == 'molmol': 259 self.user_functions.molmol.macro_run(file=file) 260 261 # Diffusion tensor PDB. 262 elif type == 'diff_tensor_pdb': 263 # Try and see if PyMOL is installed. 264 if not interpreter.apply('pymol.view'): 265 return 266 267 # Display the tensor. 268 interpreter.apply('pymol.cartoon') 269 interpreter.apply('pymol.tensor_pdb', file=file) 270 271 # A special table. 272 elif type == 'Table_of_Results': 273 # The data. 274 model_result = [ds.relax_gui.table_residue, ds.relax_gui.table_model, ds.relax_gui.table_s2, ds.relax_gui.table_rex, ds.relax_gui.table_te] 275 276 # Text files. 277 elif type == 'text': 278 open_file(file, force_text=True) 279 280 # Open all other files in which ever editor the platform decides on. 281 else: 282 open_file(file)
283 284
285 - def refresh(self):
286 """Update the list of result files.""" 287 288 # Thread safe. 289 wx.CallAfter(self.refresh_safe)
290 291
292 - def refresh_safe(self):
293 """Update the list of result files (thread safe).""" 294 295 # Acquire the pipe lock. 296 status.pipe_lock.acquire('results viewer window') 297 try: 298 # Update the data pipe selector. 299 self.update_pipes() 300 301 # Clear the list. 302 self.file_list.DeleteAllItems() 303 self.file_data = [] 304 305 # Nothing to do. 306 if not hasattr(cdp, 'result_files'): 307 return 308 309 # Update the list. 310 for i in range(len(cdp.result_files)): 311 self.file_list.Append((str_to_gui(cdp.result_files[i][1]), str_to_gui(cdp.result_files[i][2]))) 312 self.file_data.append(cdp.result_files[i][0]) 313 314 # Release the locks. 315 finally: 316 status.pipe_lock.release('results viewer window')
317 318
319 - def resize(self, event):
320 """Catch the resize to allow the element to be resized. 321 322 @param event: The wx event. 323 @type event: wx event 324 """ 325 326 # Set the column sizes. 327 self.size_cols() 328 329 # Continue with the normal resizing. 330 event.Skip()
331 332
333 - def switch_pipes(self, event):
334 """Switch data pipes. 335 336 @param event: The wx event. 337 @type event: wx event 338 """ 339 340 # The name of the selected pipe. 341 pipe = gui_to_str(self.pipe_name.GetString(event.GetSelection())) 342 343 # No pipe change. 344 if pipe == cdp_name(): 345 return 346 347 # Switch data pipes. 348 interpreter.queue('pipe.switch', pipe) 349 interpreter.flush() 350 351 # Update the window. 352 self.refresh() 353 354 # Bug fix for MS Windows (bring the window back). 355 wx.CallAfter(self.Raise)
356 357
358 - def update_pipes(self):
359 """Update the data pipe list.""" 360 361 # Clear the previous data pipe. 362 self.pipe_name.Clear() 363 364 # The list of data pipes. 365 for pipe in pipe_names(): 366 self.pipe_name.Append(str_to_gui(pipe)) 367 368 # Set the name to the current data pipe. 369 self.pipe_name.SetValue(str_to_gui(cdp_name()))
370 371
372 - def size_cols(self):
373 """Set the column sizes.""" 374 375 # The list size. 376 x, y = self.file_list.GetSize() 377 378 # Remove a little to prevent the horizontal scroll bar from appearing. 379 x = x - 10 380 381 # Set the column sizes. 382 self.file_list.SetColumnWidth(0, int(x/3)) 383 self.file_list.SetColumnWidth(1, int(2*x/3))
384