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