Esempio n. 1
0
    def create_scrolled_panel(self, parent):
        """ Returns a panel that can scroll its contents.
        """
        sa = QScrollArea(check_parent(parent))
        sa.setFrameShape(QFrame.NoFrame)
        sa.setWidgetResizable(True)

        return control_adapter_for(sa)
Esempio n. 2
0
class SimpleEditor ( Editor ):
    """ Simple style of editor for lists, which displays a scrolling list box
        with only one item visible at a time. A icon next to the list box
        displays a menu of operations on the list.
    """

    #-- Class Constants --------------------------------------------------------

    # Whether the list is displayed in a single row:
    single_row = True

    # Menu for modifying the list
    list_menu = """
       Add &Before     [_menu_before]: self.add_before()
       Add &After      [_menu_after]:  self.add_after()
       ---
       &Delete         [_menu_delete]: self.delete_item()
       ---
       Move &Up        [_menu_up]:     self.move_up()
       Move &Down      [_menu_down]:   self.move_down()
       Move to &Top    [_menu_top]:    self.move_top()
       Move to &Bottom [_menu_bottom]: self.move_bottom()
    """

    empty_list_menu = """
       Add: self.add_empty()
    """

    #-- Facet Definitions ------------------------------------------------------

    # The kind of editor to create for each list item:
    kind = Str

    # Is the list of items being edited mutable?
    mutable = Bool( True )

    #-- Public Methods ---------------------------------------------------------

    def init ( self, parent ):
        """ Finishes initializing the editor by creating the underlying toolkit
            widget.
        """
        # Initialize the facet handler to use:
        facet_handler = self.factory.facet_handler
        if facet_handler is None:
            facet_handler = self.object.base_facet( self.name ).handler
        self._facet_handler = facet_handler

        # Create a scrolled window to hold all of the list item controls:
        self.control = QScrollArea( parent )
        self.control.setFrameShape( QFrame.NoFrame )

        # Create a widget with a grid layout as the container.
        self._list_pane = QWidget()
        layout = QGridLayout( self._list_pane )
        layout.setMargin( 0 )

        # Remember the editor to use for each individual list item:
        editor = self.factory.editor
        if editor is None:
            editor = facet_handler.item_facet.get_editor()

        self._editor = getattr( editor, self.kind )

        # Set up the additional 'list items changed' event handler needed for
        # a list based facet:
        self.context_object.on_facet_set(
            self.update_editor_item, self.extended_name + '_items?',
            dispatch = 'ui'
        )
        self.set_tooltip()


    def dispose ( self ):
        """ Disposes of the contents of an editor.
        """
        self.context_object.on_facet_set(
            self.update_editor_item, self.extended_name + '_items?',
            remove = True
        )

        super( SimpleEditor, self ).dispose()


    def update_editor ( self ):
        """ Updates the editor when the object facet changes externally to the
            editor.
        """
        # Disconnect the editor from any control about to be destroyed:
        self._dispose_items()

        list_pane = self._list_pane
        layout    = list_pane.layout()

        # Create all of the list item facet editors:
        facet_handler = self._facet_handler
        resizable     = ((facet_handler.minlen != facet_handler.maxlen) and
                         self.mutable)
        item_facet    = facet_handler.item_facet
        values        = self.value
        index         = 0

        is_fake       = (resizable and (len( values ) == 0))
        if is_fake:
            values = [ item_facet.default_value()[1] ]

        editor = self._editor
        # FIXME: Add support for more than one column.
        for value in values:
            if resizable:
                control = IconButton( '@facets:list_editor', self.popup_menu )
                layout.addWidget( control, index, 0 )

            try:
                proxy = ListItemProxy( self.object, self.name, index,
                                       item_facet, value )
                if resizable:
                    control.proxy = proxy

                peditor = editor( self.ui, proxy, 'value',
                                  self.description ).set( object_name = '' )
                peditor.prepare( list_pane )
                pcontrol = peditor.control
                pcontrol.proxy = proxy
            except:
                if not is_fake:
                    raise

                pcontrol = QPushButton( 'sample', list_pane )

            if isinstance( pcontrol, QWidget ):
                layout.addWidget( pcontrol, index, 1 )
            else:
                layout.addLayout( pcontrol, index, 1 )

            index += 1

        if is_fake:
           self._cur_control = control
           self.empty_list()
           control.setParent( None )

        if self.single_row:
            rows = 1
        else:
            rows = self.factory.rows

        #list_pane.SetSize( wx.Size(
        #     width + ((facet_handler.maxlen > rows) * scrollbar_dx),
        #     height * rows ) )

        # QScrollArea can have problems if the widget being scrolled is set too
        # early (ie. before it contains something).
        if self.control.widget() is None:
            self.control.setWidget( list_pane )


    def update_editor_item ( self, object, name, old, event ):
        """ Updates the editor when an item in the object facet changes
            externally to the editor.
        """
        # If this is not a simple, single item update, rebuild entire editor:
        if (len( event.removed ) != 1) or (len( event.added ) != 1):
            self.update_editor()

            return

        # Otherwise, find the proxy for this index and update it with the
        # changed value:
        for control in self.control.widget().children():
            if isinstance( control, QLayout ):
                continue

            proxy = control.proxy
            if proxy.index == event.index:
                proxy.value = event.added[0]
                break


    def empty_list ( self ):
        """ Creates an empty list entry (so the user can add a new item).
        """
        control          = IconButton( '@facets:list_editor', self.popup_menu )
        control.is_empty = True
        proxy          = ListItemProxy( self.object, self.name, -1, None, None )
        pcontrol       = QLabel( '   (Empty List)' )
        pcontrol.proxy = control.proxy = proxy
        self.reload_sizer( [ ( control, pcontrol ) ] )


    def reload_sizer ( self, controls, extra = 0 ):
        """ Reloads the layout from the specified list of ( button, proxy )
            pairs.
        """
        layout = self._list_pane.layout()

        child = layout.takeAt( 0 )
        while child is not None:
            child = layout.takeAt( 0 )

        del child

        index = 0
        for control, pcontrol in controls:
            layout.addWidget( control )
            layout.addWidget( pcontrol )

            control.proxy.index = index
            index += 1


    def get_info ( self ):
        """ Returns the associated object list and current item index.
        """
        proxy = self._cur_control.proxy
        return ( proxy.list, proxy.index )


    def popup_empty_menu ( self, control ):
        """ Displays the empty list editor popup menu.
        """
        self._cur_control = control
        control.PopupMenuXY( MakeMenu( self.empty_list_menu, self, True,
                                       control ).menu, 0, 0 )


    def popup_menu ( self ):
        """ Displays the list editor popup menu.
        """
        self._cur_control = control = self.control.sender()
        proxy    = control.proxy
        index    = proxy.index
        menu     = MakeMenu( self.list_menu, self, True, control ).menu
        len_list = len( proxy.list )
        not_full = ( len_list < self._facet_handler.maxlen )
        self._menu_before.enabled( not_full )
        self._menu_after.enabled(  not_full )
        self._menu_delete.enabled( len_list > self._facet_handler.minlen )
        self._menu_up.enabled(  index > 0 )
        self._menu_top.enabled( index > 0 )
        self._menu_down.enabled(   index < (len_list - 1) )
        self._menu_bottom.enabled( index < (len_list - 1) )
        menu.exec_( control.mapToGlobal( QPoint( 0, 0 ) ) )


    def add_item ( self, offset ):
        """ Adds a new value at the specified list index.
        """
        list, index = self.get_info()
        index      += offset
        item_facet  = self._facet_handler.item_facet
        dv          = item_facet.default_value()
        if dv[0] == 7:
            func, args, kw = dv[1]
            if kw is None:
                kw = {}
            value = func( *args, **kw )
        else:
            value = dv[1]
        self.value = list[ : index ] + [ value ] + list[ index: ]
        self.update_editor()


    def add_before ( self ):
        """ Inserts a new item before the current item.
        """
        self.add_item( 0 )


    def add_after ( self ):
        """ Inserts a new item after the current item.
        """
        self.add_item( 1 )


    def add_empty ( self ):
        """ Adds a new item when the list is empty.
        """
        list, index = self.get_info()
        self.add_item( 0 )


    def delete_item ( self ):
        """ Delete the current item.
        """
        list, index = self.get_info()
        self.value  = list[ : index ] + list[ index + 1: ]
        self.update_editor()


    def move_up ( self ):
        """ Move the current item up one in the list.
        """
        list, index = self.get_info()
        self.value  = (list[ :index - 1 ] + [ list[ index ],
                       list[ index - 1 ] ] + list[ index + 1: ])


    def move_down ( self ):
        """ Moves the current item down one in the list.
        """
        list, index = self.get_info()
        self.value  = ( list[ : index ] + [ list[ index + 1 ], list[ index ] ] +
                       list[ index + 2: ] )


    def move_top ( self ):
        """ Moves the current item to the top of the list.
        """
        list, index = self.get_info()
        self.value  = [ list[ index ] ] + list[ : index ] + list[ index + 1: ]


    def move_bottom ( self ):
        """ Moves the current item to the bottom of the list.
        """
        list, index = self.get_info()
        self.value  = list[ : index ] + list[ index + 1: ] + [ list[ index ] ]

    #-- Private Methods --------------------------------------------------------

    def _dispose_items ( self ):
        """ Disposes of each current list item.
        """
        list_pane = self._list_pane
        layout = list_pane.layout()

        for control in list_pane.children():
            editor = getattr( control, '_editor', None )
            if editor is not None:
                editor.dispose()
                editor.control = None
            elif control is not layout:
                control.setParent( None )

        del control
class PointsWidget(QWidget):
	"""
	PointsWidget
	"""

	activeLandmarkChanged = Signal(int)
	landmarkDeleted = Signal(int)

	def __init__(self):
		super(PointsWidget, self).__init__()

		self.landmarkWidgets = []
		self.activeIndex = 0

		self.scrollArea = QScrollArea(self)
		self.scrollArea.setFrameShape(QFrame.NoFrame)
		self.scrollArea.setAutoFillBackground(False)
		self.scrollArea.setAttribute(Qt.WA_TranslucentBackground)
		self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
		self.scrollArea.setWidgetResizable(True)

		landmarkLocationsLayout = QGridLayout()
		landmarkLocationsLayout.setSpacing(0)
		landmarkLocationsLayout.setContentsMargins(0, 0, 0, 0)
		landmarkLocationsLayout.setAlignment(Qt.AlignTop)

		self.landmarkLocationsWidget = QWidget()
		Style.styleWidgetForTab(self.landmarkLocationsWidget)
		self.landmarkLocationsWidget.setLayout(landmarkLocationsLayout)
		self.scrollArea.setWidget(self.landmarkLocationsWidget)

		layout = QGridLayout()
		layout.setContentsMargins(0, 0, 0, 0)
		layout.addWidget(self.scrollArea)
		self.setLayout(layout)

	@Slot(list)
	def setPoints(self, points):
		self._clearLandmarkWidgets()
		layout = self.landmarkLocationsWidget.layout()
		for index in range(len(points)):
			landmarkWidget = LandmarkLocationWidget()
			landmarkWidget.setIndex(index)
			landmarkWidget.active = (index == self.activeIndex)
			landmarkWidget.activated.connect(self.activateLandmark)
			landmarkWidget.deleted.connect(self.deleteLandmark)
			landmarkWidget.setLandmarkSet(points[index])
			layout.addWidget(landmarkWidget, index, 0)
			self.landmarkWidgets.append(landmarkWidget)

	def _clearLandmarkWidgets(self):
		layout = self.landmarkLocationsWidget.layout()
		for widget in self.landmarkWidgets:
			widget.activated.disconnect()
			layout.removeWidget(widget)
			widget.deleteLater()
		self.landmarkWidgets = []

	@Slot(int, object)
	def activateLandmark(self, index, state):
		if not state:
			self.activeIndex = len(self.landmarkWidgets)
		else:
			self.activeIndex = index
		self.activeLandmarkChanged.emit(self.activeIndex)

	@Slot(int)
	def deleteLandmark(self, index):
		self.activateLandmark(index, False)
		self.landmarkDeleted.emit(index)
Esempio n. 4
0
class RenderParameterWidget(QWidget):
	"""
	RenderParameterWidget is a widget that is shown in the render property
	widget. It holds a combo box with which different visualizations can be
	chosen. Beneath the combo box it displays a widget in a scroll view that
	contains widgets with which parameters of the visualization can be adjusted.
	"""

	def __init__(self, renderController, parent=None):
		super(RenderParameterWidget, self).__init__(parent=parent)

		self.renderController = renderController
		self.renderController.visualizationChanged.connect(self.visualizationLoaded)

		self.paramWidget = None

		self.visTypeComboBox = QComboBox()
		for visualizationType in self.renderController.visualizationTypes:
			self.visTypeComboBox.addItem(visualizationType)

		layout = QGridLayout()
		layout.setAlignment(Qt.AlignTop)
		layout.setSpacing(10)
		layout.setContentsMargins(10, 0, 10, 0)
		if len(self.renderController.visualizationTypes) > 1:
			layout.addWidget(QLabel("Visualization type:"), 0, 0)
			layout.addWidget(self.visTypeComboBox, 0, 1)
		self.setLayout(layout)

		self.scrollArea = QScrollArea()
		self.scrollArea.setFrameShape(QFrame.NoFrame)
		self.scrollArea.setAutoFillBackground(False)
		self.scrollArea.setAttribute(Qt.WA_TranslucentBackground)
		self.scrollArea.setWidgetResizable(True)

		self.visTypeComboBox.currentIndexChanged.connect(self.visTypeComboBoxChanged)

	def UpdateWidgetFromRenderWidget(self):
		"""
		Update the parameter widget with a widget from the render widget.
		"""
		# Add the scroll area for the parameter widget if it is not there yet
		layout = self.layout()
		if layout.indexOf(self.scrollArea) == -1:
			layout.addWidget(self.scrollArea, 1, 0, 1, 2)
			self.setLayout(layout)

		# Clear the previous parameter widget
		if self.paramWidget is not None:
			self.paramWidget.setParent(None)
			if self.renderController.visualization is not None:
				self.renderController.visualization.disconnect(SIGNAL("updatedTransferFunction"), self.transferFunctionChanged)

		# Get a new parameter widget from the render widget
		self.paramWidget = self.renderController.getParameterWidget()
		Style.styleWidgetForTab(self.paramWidget)
		self.scrollArea.setWidget(self.paramWidget)

		if self.renderController.visualization is not None:
			self.renderController.visualization.updatedTransferFunction.connect(self.transferFunctionChanged)

		self.visTypeComboBox.setCurrentIndex(self.visTypeComboBox.findText(self.renderController.visualizationType))

	@Slot(int)
	def visTypeComboBoxChanged(self, index):
		"""
		Slot that changes the render type. Also updates parameters and makes
		sure that the renderWidget renders with the new visualizationType.
		:type index: any
		"""
		self.renderController.setVisualizationType(self.visTypeComboBox.currentText())
		self.UpdateWidgetFromRenderWidget()
		self.renderController.updateVisualization()

	def visualizationLoaded(self, visualization):
		self.UpdateWidgetFromRenderWidget()

	@Slot()
	def transferFunctionChanged(self):
		"""
		Slot that can be used when a transfer function has changed so that
		the render will be updated afterwards.
		Should be called on valueChanged by the widgets from the parameter widget.
		"""
		self.renderController.updateVisualization()
class RenderInfoWidget(QWidget):
	"""
	RenderInfoWidget shows information about the loaded dataset. Things like
	filenames, range of data values, size of data, etc.
	"""
	def __init__(self):
		super(RenderInfoWidget, self).__init__()

		self.scrollArea = QScrollArea()
		self.scrollArea.setFrameShape(QFrame.NoFrame)
		self.scrollArea.setAutoFillBackground(False)
		self.scrollArea.setAttribute(Qt.WA_TranslucentBackground)
		self.scrollArea.setWidgetResizable(True)

		Style.styleWidgetForTab(self)
		Style.styleWidgetForTab(self.scrollArea)

	@Slot(basestring)
	def setFile(self, fileName):
		"""
		Slot that reads properties of the dataset and displays them in a few widgets.
		"""
		if fileName is None:
			return

		self.fileName = fileName

		# Read info from dataset
		# TODO: read out the real world dimensions in inch or cm
		# TODO: scalar type (int, float, short, etc.)
		imageReader = DataReader()
		imageData = imageReader.GetImageData(fileName)

		directory, name = os.path.split(fileName)
		dimensions = imageData.GetDimensions()
		minimum, maximum = imageData.GetScalarRange()
		scalarType = imageData.GetScalarTypeAsString()

		bins = DataAnalyzer.histogramForData(imageData, 256)

		self.histogram = Histogram()
		self.histogram.bins = bins
		self.histogram.enabled = True

		self.histogramWidget = HistogramWidget()
		self.histogramWidget.setMinimumHeight(100)
		self.histogramWidget.setHistogram(self.histogram)
		self.histogramWidget.setAxeMode(bottom=HistogramWidget.AxeClear,
			left=HistogramWidget.AxeLog)
		Style.styleWidgetForTab(self.histogramWidget)

		nameText = name
		dimsText = "(" + str(dimensions[0]) + ", " + str(dimensions[1]) + ", " + str(dimensions[2]) + ")"
		voxsText = str(dimensions[0] * dimensions[1] * dimensions[2])
		rangText = "[" + str(minimum) + " : " + str(maximum) + "]"
		typeText = scalarType

		layout = self.layout()
		if not layout:
			# Create a new layout
			layout = QGridLayout()
			layout.setAlignment(Qt.AlignTop)

			# Create string representations
			nameLabels = []
			nameLabels.append(QLabel("File name:"))
			nameLabels.append(QLabel("Dimensions:"))
			nameLabels.append(QLabel("Voxels:"))
			nameLabels.append(QLabel("Range:"))
			nameLabels.append(QLabel("Data type:"))

			for label in nameLabels:
				label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)

			# Create 'dynamic' labels
			self.labelTitle = QLabel(nameText)
			self.labelDimensions = QLabel(dimsText)
			self.labelVoxels = QLabel(voxsText)
			self.labelRange = QLabel(rangText)
			self.labelType = QLabel(typeText)

			index = 0
			for label in nameLabels:
				layout.addWidget(label, index, 0)
				index += 1

			layout.addWidget(self.labelTitle, 0, 1)
			layout.addWidget(self.labelDimensions, 1, 1)
			layout.addWidget(self.labelVoxels, 2, 1)
			layout.addWidget(self.labelRange, 3, 1)
			layout.addWidget(self.labelType, 4, 1)
			layout.addWidget(self.histogramWidget, 5, 0, 1, 2)

			widget = QWidget()
			widget.setLayout(layout)
			Style.styleWidgetForTab(widget)
			self.scrollArea.setWidget(widget)

			scrollLayout = QGridLayout()
			scrollLayout.setSpacing(0)
			scrollLayout.setContentsMargins(0, 0, 0, 0)
			scrollLayout.addWidget(self.scrollArea)
			self.setLayout(scrollLayout)
		else:
			# Just update the text for the 'dynamic' labels
			self.labelTitle.setText(nameText)
			self.labelDimensions.setText(dimsText)
			self.labelVoxels.setText(voxsText)
			self.labelRange.setText(rangText)
			self.labelType.setText(typeText)