Slicer 4.2
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
EditOptions.py
Go to the documentation of this file.
00001 import slicer
00002 from __main__ import qt
00003 from __main__ import ctk
00004 from __main__ import vtk
00005 from __main__ import getNodes
00006 import EditUtil
00007 
00008 #########################################################
00009 #
00010 # 
00011 comment = """
00012 In this file:
00013 
00014   Helpers - small widget-like helper classes
00015   EditOptions - EffectOptions superclass
00016 
00017   Each effect interface is created when the corresponding
00018   editor effect is active on the slice views.  The main
00019   (only) responsibility of these GUIs is to set parameters
00020   on the mrml node that influence the behavior of the 
00021   editor effects.
00022 
00023 """
00024 #
00025 #########################################################
00026 
00027 #########################################################
00028 # Helpers
00029 #########################################################
00030 
00031 class HelpButton(object):
00032   """ 
00033   Puts a button on the interface that pops up a message
00034   dialog for help when pressed
00035   """
00036   def __init__(self, parent, helpString = ""):
00037     self.helpString = helpString
00038     self.message = qt.QMessageBox()
00039     self.message.setWindowTitle("Editor Help")
00040     self.button = qt.QPushButton("?", parent)
00041     self.button.setMaximumWidth(15)
00042     self.button.setToolTip("Bring up a help window")
00043     parent.layout().addWidget(self.button)
00044     self.button.connect('clicked()', self.showHelp)
00045 
00046   def showHelp(self):
00047     self.message.setText(self.helpString)
00048     self.message.open()
00049 
00050 #########################################################
00051 # Options
00052 #########################################################
00053 class EditOptions(object):
00054   """ This EditOptions is a parent class for all the GUI options
00055   for editor effects.  These are small custom interfaces
00056   that it in the toolOptionsFrame of the Editor interface.
00057   TODO: no support yet for scope options
00058   """
00059 
00060   def __init__(self, parent=None):
00061     self.parent = parent
00062     self.updatingGUI = False
00063     self.observerTags = []
00064     self.widgets = []
00065     self.parameterNode = None
00066     self.parameterNodeTag = None
00067     self.editUtil = EditUtil.EditUtil()
00068     self.tools = []
00069 
00070     # connections is a list of widget/signal/slot tripples
00071     # for the options gui that can be connected/disconnected
00072     # as needed to prevent triggering mrml updates while
00073     # updating the state of the gui
00074     # - each level of the inheritance tree can add entries
00075     #   to this list for use by the connectWidgets
00076     #   and disconnectWidgets methods
00077     self.connections = []
00078     self.connectionsConnected = False
00079 
00080     # 1) find the parameter node in the scene and observe it
00081     # 2) set the defaults (will only set them if they are not
00082     # already set)
00083     self.updateParameterNode(self.parameterNode, vtk.vtkCommand.ModifiedEvent)
00084     self.setMRMLDefaults()
00085 
00086     # TODO: change this to look for specfic events (added, removed...)
00087     # but this requires being able to access events by number from wrapped code
00088     tag = slicer.mrmlScene.AddObserver(vtk.vtkCommand.ModifiedEvent, self.updateParameterNode)
00089     self.observerTags.append( (slicer.mrmlScene, tag) )
00090 
00091   def __del__(self):
00092     self.destroy()
00093     if self.parameterNode:
00094       self.parameterNode.RemoveObserver(self.parameterNodeTag)
00095     for tagpair in self.observerTags:
00096       tagpair[0].RemoveObserver(tagpair[1])
00097 
00098   def connectWidgets(self):
00099     if self.connectionsConnected: return
00100     for widget,signal,slot in self.connections:
00101       success = widget.connect(signal,slot)
00102       if not success:
00103         print("Could not connect {signal} to {slot} for {widget}".format(
00104           signal = signal, slot = slot, widget = widget))
00105     self.connectionsConnected = True
00106 
00107   def disconnectWidgets(self):
00108     if not self.connectionsConnected: return
00109     for widget,signal,slot in self.connections:
00110       success = widget.disconnect(signal,slot)
00111       if not success:
00112         print("Could not disconnect {signal} to {slot} for {widget}".format(
00113           signal = signal, slot = slot, widget = widget))
00114     self.connectionsConnected = False
00115 
00116   def create(self):
00117     if not self.parent:
00118       self.parent = slicer.qMRMLWidget()
00119       self.parent.setLayout(qt.QVBoxLayout())
00120       self.parent.setMRMLScene(slicer.mrmlScene)
00121       self.parent.show()
00122     self.frame = qt.QFrame(self.parent)
00123     self.frame.setLayout(qt.QVBoxLayout())
00124     self.parent.layout().addWidget(self.frame)
00125     self.widgets.append(self.frame)
00126 
00127   def destroy(self):
00128     for w in self.widgets:
00129       self.parent.layout().removeWidget(w)
00130       w.deleteLater()
00131       w.setParent(None)
00132     self.widgets = []
00133 
00134   #
00135   # update the GUI for the given label
00136   # - to be overriden by the subclass
00137   #
00138   def updateMRMLFromGUI(self):
00139     pass
00140 
00141   #
00142   # update the GUI from MRML
00143   # - to be overriden by the subclass
00144   #
00145   def updateGUIFromMRML(self,caller,event):
00146     pass
00147 
00148   #
00149   # update the GUI from MRML
00150   # - to be overriden by the subclass
00151   #
00152   def updateGUI(self):
00153     self.updateGUIFromMRML(self.parameterNode, vtk.vtkCommand.ModifiedEvent)
00154 
00155   #
00156   # set the default option values
00157   # - to be overriden by the subclass
00158   #
00159   def setMRMLDefaults(self):
00160     pass
00161 
00162   def getBackgroundScalarRange(self):
00163     success = False
00164     lo = -1
00165     hi = -1
00166     backgroundVolume = self.editUtil.getBackgroundVolume()
00167     if backgroundVolume:
00168       backgroundImage = backgroundVolume.GetImageData()
00169       if backgroundImage:
00170         lo, hi = backgroundImage.GetScalarRange()
00171         success = True
00172     return success, lo, hi    
00173 
00174   def setRangeWidgetToBackgroundRange(self, rangeWidget):
00175     """Set the range widget based on current backgroun
00176     volume - note that hi+1 is used since the range widget
00177     will round floating numbers to 2 significant digits"""
00178     if not rangeWidget:
00179       return
00180     success, lo, hi = self.getBackgroundScalarRange()
00181     if success:
00182       rangeWidget.minimum, rangeWidget.maximum = lo, hi+1
00183 
00184   def statusText(self,text):
00185     slicer.util.showStatusMessage(text)
00186 
00187   def debug(self,text):
00188     import inspect
00189     print('*'*80)
00190     print(text)
00191     print(self)
00192     stack = inspect.stack()
00193     for frame in stack:
00194       print(frame)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines