Example #1
0
class SelectionToolBar(BaseToolBar):

    selectAllTriggered = QtCore.Signal()
    clearSelectionTriggered = QtCore.Signal()

    def __init__(self, view=None, parent=None, designMode=False):
        BaseToolBar.__init__(self,
                             name="Selection toolbar",
                             view=view,
                             parent=parent,
                             designMode=designMode)

        self._selectAllAction = Action("Select All",
                                       parent=self,
                                       icon=getIcon("edit-select-all"),
                                       tooltip="Select all items",
                                       triggered=self.onSelectAll)
        self._clearSelectionAction = Action("Clear selection",
                                            parent=self,
                                            icon=getIcon("edit-clear"),
                                            tooltip="Clears current selection",
                                            triggered=self.onclearSelection)

        self.addAction(self._selectAllAction)
        self.addAction(self._clearSelectionAction)

    def onSelectAll(self):
        self.selectAllTriggered.emit()

    def onclearSelection(self):
        self.clearSelectionTriggered.emit()
Example #2
0
class ExpansionBar(BaseToolBar):

    expandTriggered = QtCore.Signal()
    collapseTriggered = QtCore.Signal()
    expandSelectionTriggered = QtCore.Signal()
    collapseSelectionTriggered = QtCore.Signal()

    def __init__(self, view=None, parent=None):
        BaseToolBar.__init__(self,
                             name="Taurus selection toolbar",
                             view=view,
                             parent=parent)

        self._expandAllAction = getAction(
            "Expand All",
            parent=self,
            icon=getIcon(":/controls/expand.png"),
            tooltip="Expand all items",
            triggered=self.onExpandAll)
        self._collapseAllAction = getAction(
            "Collapse All",
            parent=self,
            icon=getIcon(":/controls/collapse.png"),
            tooltip="Collapse all items",
            triggered=self.onCollapseAll)
        self._expandSelectionAction = getAction(
            "Expand selection",
            parent=self,
            icon=getIcon(":/controls/expand-selection.png"),
            tooltip="Expand selection",
            triggered=self.onExpandSelection)
        self._collapseSelectionAction = getAction(
            "Collapse All",
            parent=self,
            icon=getIcon(":/controls/collapse-selection.png"),
            tooltip="Collapse selection",
            triggered=self.onCollapseSelection)
        self.addAction(self._expandAllAction)
        self.addAction(self._collapseAllAction)
        self.addAction(self._expandSelectionAction)
        self.addAction(self._collapseSelectionAction)

    def onExpandAll(self):
        self.expandTriggered.emit()

    def onCollapseAll(self):
        self.collapseTriggered.emit()

    def onExpandSelection(self):
        self.expandSelectionTriggered.emit()

    def onCollapseSelection(self):
        self.collapseSelectionTriggered.emit()
Example #3
0
class NavigationToolBar(BaseToolBar):

    goIntoTriggered = QtCore.Signal()
    goUpTriggered = QtCore.Signal()
    goTopTriggered = QtCore.Signal()

    def __init__(self, view=None, parent=None):
        BaseToolBar.__init__(self,
                             name="Taurus selection toolbar",
                             view=view,
                             parent=parent)

        self._goIntoAction = getAction("Go Into",
                                       parent=self,
                                       icon=getIcon("go-down"),
                                       tooltip="Go into the selected item",
                                       triggered=self.goInto)
        self._goUpAction = getAction("Go Up",
                                     parent=self,
                                     icon=getIcon("go-up"),
                                     tooltip="Go up one level",
                                     triggered=self.goUp)
        self._goTopAction = getAction("Go Top",
                                      parent=self,
                                      icon=getIcon("go-top"),
                                      tooltip="Go to top level",
                                      triggered=self.goTop)
        self.addAction(self._goIntoAction)
        self.addAction(self._goUpAction)
        self.addAction(self._goTopAction)
        self._navigationWidget = _NavigationWidget(view, self, parent=self)
        self._navigationAction = self.addWidget(self._navigationWidget)

    def goIntoAction(self):
        return self._goIntoAction

    def goTopAction(self):
        return self._goTopAction

    def goUpAction(self):
        return self._goUpAction

    def goInto(self):
        self.goIntoTriggered.emit()

    def goUp(self):
        self.goUpTriggered.emit()

    def goTop(self):
        self.goTopTriggered.emit()
Example #4
0
class FilterToolBar(BaseToolBar):
    """Internal widget providing quick filter to be placed in a _QToolArea"""

    clearFilterTriggered = QtCore.Signal()
    filterChanged = QtCore.Signal(str)
    filterEdited = QtCore.Signal(str)

    def __init__(self, view=None, parent=None, designMode=False):
        BaseToolBar.__init__(self,
                             name="Filter toolbar",
                             view=view,
                             parent=parent,
                             designMode=designMode)
        filterLineEdit = self._filterLineEdit = QtGui.QLineEdit(self)
        filterLineEdit.setSizePolicy(
            QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
                              QtGui.QSizePolicy.Preferred))
        filterLineEdit.setToolTip("Quick filter")
        filterLineEdit.textChanged.connect(self.onFilterChanged)
        filterLineEdit.textEdited.connect(self.onFilterEdited)
        self.addWidget(filterLineEdit)

        self._clearFilterAction = Action("Clear",
                                         parent=self,
                                         icon=getIcon("edit-clear"),
                                         tooltip="Clears the filter",
                                         triggered=self.onClearFilter)
        self.addAction(self._clearFilterAction)

    def getFilterLineEdit(self):
        return self._filterLineEdit

    def onClearFilter(self):
        self.getFilterLineEdit().setText("")
        self.clearFilterTriggered.emit()

    def onFilterChanged(self, text=None):
        text = text or self.getFilterLineEdit().text()
        self.filterChanged.emit(text)

    def onFilterEdited(self, text=None):
        text = text or self.getFilterLineEdit().text()
        self.filterEdited.emit(text)

    def setFilterText(self, text):
        self.getFilterLineEdit().setText(text)
Example #5
0
class PerspectiveToolBar(BaseToolBar):

    perspectiveChanged = QtCore.Signal(str)

    def __init__(self, perspective, view=None, parent=None, designMode=False):
        BaseToolBar.__init__(self,
                             name="Perspective toolbar",
                             view=view,
                             parent=parent,
                             designMode=designMode)
        self._perspective = perspective
        view = self.viewWidget()
        b = self._perspective_button = QtGui.QToolButton(self)
        b.setToolTip("Perspective selection")
        b.setPopupMode(QtGui.QToolButton.InstantPopup)
        b.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)

        menu = QtGui.QMenu("Perspective", b)
        b.setMenu(menu)
        for persp, persp_data in view.KnownPerspectives.items():
            label = persp_data["label"]
            icon = QtGui.QIcon(persp_data["icon"])
            tooltip = persp_data["tooltip"]
            action = Action(label,
                            parent=self,
                            icon=icon,
                            tooltip=tooltip,
                            triggered=self.onSwitchPerspective)
            action.perspective = persp
            menu.addAction(action)
            if persp == perspective:
                b.setDefaultAction(action)

        self._perspectiveAction = self.addWidget(b)

    def switchPerspectiveButton(self):
        """Returns the QToolButton that handles the switch perspective.

        :return: (PyQt4.QtGui.QToolButton) the switch perspective tool button
        """
        return self._perspective_button

    def onSwitchPerspective(self):
        action = self.sender()
        self._perspective = action.perspective
        self._perspective_button.setDefaultAction(action)
        self.perspectiveChanged.emit(action.perspective)

    def perspective(self):
        return self._perspective
Example #6
0
class __Grabber(QtCore.QObject):

    grab = QtCore.Signal()

    def __init__(self, widget, fileName):
        QtCore.QObject.__init__(self)
        self.__widget = widget
        self.__fileName = fileName
        self.grab.connect(self.__onGrab)
    
    def grabTrigger(self):
        self.grab.emit()
        
    def __onGrab(self):
        grabWidget(self._widget, self._fileName)
Example #7
0
class RefreshToolBar(BaseToolBar):

    refreshTriggered = QtCore.Signal()

    def __init__(self, view=None, parent=None, designMode=False):
        BaseToolBar.__init__(self,
                             name="Refresh toolbar",
                             view=view,
                             parent=parent,
                             designMode=designMode)

        self._refreshAction = Action("Refresh",
                                     parent=self,
                                     icon=getIcon("view-refresh"),
                                     tooltip="Refresh view",
                                     triggered=self.onRefresh)
        self.addAction(self._refreshAction)

    def onRefresh(self):
        self.refreshTriggered.emit()
Example #8
0
class PixmapWidget(QtGui.QWidget):
    """This widget displays an image (pixmap). By default the pixmap is
    scaled to the widget size and the aspect ratio is kept.
    The default alignment of the pixmap inside the widget space is horizontal
    left, vertical center."""

    DefaultAlignment = QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter
    DefaultAspectRatioMode = QtCore.Qt.KeepAspectRatio
    DefaultTransformationMode = QtCore.Qt.SmoothTransformation

    #: Signal emited when pixmap source changes
    pixmapChanged = QtCore.Signal()

    def __init__(self, parent=None):
        self._pixmap = QtGui.QPixmap()
        self._pixmapDrawn = None
        self._alignment = self.DefaultAlignment
        self._pixmapAspectRatioMode = self.DefaultAspectRatioMode
        self._pixmapTransformationMode = self.DefaultTransformationMode

        QtGui.QWidget.__init__(self, parent)

    def _getPixmap(self):
        if self._pixmapDrawn is None:
            self._pixmapDrawn = self.recalculatePixmap()
        return self._pixmapDrawn

    def recalculatePixmap(self):
        origPixmap = self._pixmap
        if origPixmap.isNull():
            return origPixmap
        return origPixmap.scaled(self.size(), self._pixmapAspectRatioMode,
                                 self._pixmapTransformationMode)

    def _setDirty(self):
        self._pixmapDrawn = None

    def paintEvent(self, paintEvent):
        """Overwrite the paintEvent from QWidget to draw the pixmap"""
        pixmap = self._getPixmap()

        w, h = self.width(), self.height()
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        pw, ph = pixmap.width(), pixmap.height()
        align = self._alignment
        hAlign = align & QtCore.Qt.AlignHorizontal_Mask
        vAlign = align & QtCore.Qt.AlignVertical_Mask
        x, y = 0, 0
        if hAlign & QtCore.Qt.AlignHCenter:
            x = (w - pw) / 2
        elif hAlign & QtCore.Qt.AlignRight:
            x = w - pw
        if vAlign & QtCore.Qt.AlignVCenter:
            y = (h - ph) / 2
        elif vAlign & QtCore.Qt.AlignBottom:
            y = h - ph
        x, y = max(0, x), max(0, y)
        painter.drawPixmap(x, y, pixmap)

    def resizeEvent(self, event):
        self._setDirty()
        return QtGui.QWidget.resizeEvent(self, event)

    def sizeHint(self):
        return self._pixmap.size()

    #--------------------------------------------------------------------------
    # QT property definition
    #--------------------------------------------------------------------------

    def getPixmap(self):
        """Returns the pixmap.Returns None if no pixmap is set.

        :return: the current pixmap
        :rtype: QtGui.QPixmap"""
        return self._pixmap

    def setPixmap(self, pixmap):
        """Sets the pixmap for this widget. Setting it to None disables pixmap

        :param pixmap: the new pixmap
        :type  pixmap: QtGui.QPixmap"""
        # make sure to make a copy because of bug in PyQt 4.4. This is actually
        # not copying the internal bitmap, just the qpixmap, so there is no
        # performance penalty here
        self._pixmap = QtGui.QPixmap(pixmap)
        self._setDirty()
        self.update()
        self.pixmapChanged.emit()

    def resetPixmap(self):
        """Resets the pixmap for this widget."""
        self.setPixmap(QtGui.QPixmap())

    def getAspectRatioMode(self):
        """Returns the aspect ratio to apply when drawing the pixmap.

        :return: the current aspect ratio
        :rtype: QtCore.Qt.AspectRatioMode"""
        return self._pixmapAspectRatioMode

    def setAspectRatioMode(self, aspect):
        """Sets the aspect ratio mode to apply when drawing the pixmap.

        :param pixmap: the new aspect ratio mode
        :type  pixmap: QtCore.Qt.AspectRatioMode"""
        self._pixmapAspectRatioMode = aspect
        self._setDirty()
        self.update()

    def resetAspectRatioMode(self):
        """Resets the aspect ratio mode to KeepAspectRatio"""
        self.setAspectRatioMode(self.DefaultAspectRatioMode)

    def getTransformationMode(self):
        """Returns the transformation mode to apply when drawing the pixmap.

        :return: the current transformation mode
        :rtype: QtCore.Qt.TransformationMode"""
        return self._pixmapTransformationMode

    def setTransformationMode(self, transformation):
        """Sets the transformation mode to apply when drawing the pixmap.

        :param pixmap: the new transformation mode
        :type  pixmap: QtCore.Qt.TransformationMode"""
        self._pixmapTransformationMode = transformation
        self._setDirty()
        self.update()

    def resetTransformationMode(self):
        """Resets the transformation mode to SmoothTransformation"""
        self.setTransformationMode(self.DefaultTransformationMode)

    def getAlignment(self):
        """Returns the alignment to apply when drawing the pixmap.

        :return: the current alignment
        :rtype: QtCore.Qt.Alignment"""
        return self._alignment

    def setAlignment(self, alignment):
        """Sets the alignment to apply when drawing the pixmap.

        :param pixmap: the new alignment
        :type  pixmap: QtCore.Qt.Alignment"""
        self._alignment = alignment
        self.update()

    def resetAlignment(self):
        """Resets the transformation mode to
        QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter"""
        self.setAlignment(self.DefaultAlignment)

    #: This property holds the widget's pixmap
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`PixmapWidget.getPixmap`
    #:     * :meth:`PixmapWidget.setPixmap`
    #:     * :meth:`PixmapWidget.resetPixmap`
    pixmap = QtCore.Property("QPixmap", getPixmap, setPixmap,
                             resetPixmap, doc="the widget's pixmap")

    #: This property holds the widget's pixmap aspect ratio mode
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`PixmapWidget.getAspectRatioMode`
    #:     * :meth:`PixmapWidget.setAspectRatioMode`
    #:     * :meth:`PixmapWidget.resetAspectRatioMode`
    aspectRatioMode = QtCore.Property("Qt::AspectRatioMode",
                                      getAspectRatioMode, setAspectRatioMode,
                                      resetAspectRatioMode,
                                      doc="the widget's pixmap aspect ratio "\
                                          "mode")

    #: This property holds the widget's pixmap transformation mode
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`PixmapWidget.getTransformationMode`
    #:     * :meth:`PixmapWidget.setTransformationMode`
    #:     * :meth:`PixmapWidget.resetTransformationMode`
    transformationMode = QtCore.Property("Qt::TransformationMode",
                                         getTransformationMode,
                                         setTransformationMode,
                                         resetTransformationMode,
                                         doc="the widget's pixmap "\
                                             "transformation mode")

    #: This property holds the widget's pixmap alignment
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`PixmapWidget.getAlignment`
    #:     * :meth:`PixmapWidget.setAlignment`
    #:     * :meth:`PixmapWidget.resetAlignment`
    alignment = QtCore.Property("Qt::Alignment", getAlignment, setAlignment,
                                resetAlignment,
                                doc="the widget's pixmap alignment")
Example #9
0
class EditorToolBar(BaseToolBar):
    """Internal widget to be placed in a _QToolArea providing buttons for
    moving, adding and removing items from a view based widget"""

    addTriggered = QtCore.Signal()
    removeTriggered = QtCore.Signal()
    moveTopTriggered = QtCore.Signal()
    moveUpTriggered = QtCore.Signal()
    moveDownTriggered = QtCore.Signal()
    moveBottomTriggered = QtCore.Signal()

    def __init__(self, view=None, parent=None, designMode=False):
        BaseToolBar.__init__(self,
                             name="Editor toolbar",
                             view=view,
                             parent=parent,
                             designMode=designMode)

        self._addAction = Action("New item",
                                 parent=self,
                                 icon=getIcon("list-add"),
                                 tooltip="Add new item",
                                 triggered=self.onAdd)
        self._removeAction = Action("Remove item",
                                    parent=self,
                                    icon=getIcon("list-remove"),
                                    tooltip="Remove item",
                                    triggered=self.onRemove)
        self._moveTopAction = Action("To top",
                                     parent=self,
                                     icon=getIcon("go-top"),
                                     tooltip="Move selected item to top",
                                     triggered=self.onMoveTop)
        self._moveUpAction = Action("Move up",
                                    parent=self,
                                    icon=getIcon("go-up"),
                                    tooltip="Move selected item up one level",
                                    triggered=self.onMoveUp)
        self._moveDownAction = Action(
            "Move down",
            parent=self,
            icon=getIcon("go-down"),
            tooltip="Move selected item down one level",
            triggered=self.onMoveDown)
        self._moveBottomAction = Action("To bottom",
                                        parent=self,
                                        icon=getIcon("go-bottom"),
                                        tooltip="Move selected item to bottom",
                                        triggered=self.onMoveBottom)
        self.addAction(self._addAction)
        self.addAction(self._removeAction)
        self.addAction(self._moveTopAction)
        self.addAction(self._moveUpAction)
        self.addAction(self._moveDownAction)
        self.addAction(self._moveBottomAction)

    def onAdd(self):
        self.addTriggered.emit()

    def onRemove(self):
        self.removeTriggered.emit()

    def onMoveTop(self):
        self.moveTopTriggered.emit()

    def onMoveUp(self):
        self.moveUpTriggered.emit()

    def onMoveDown(self):
        self.moveDownTriggered.emit()

    def onMoveBottom(self):
        self.moveBottomTriggered.emit()
Example #10
0
class BaseModelWidget(QtGui.QMainWindow):
    """A pure Qt widget designed to display a Qt view widget (QTreeView for
    example), envolved by optional toolbar and statusbar.
    The Qt model associated with the internal Qt view widget should be a
    :class:`Framework4.GUI.Qt.Model.BaseModel`"""

    KnownPerspectives = {}
    DftPerspective = None

    itemClicked = QtCore.Signal(object, int)
    itemDoubleClicked = QtCore.Signal(object, int)
    itemSelectionChanged = QtCore.Signal()
    currentItemChanged = QtCore.Signal(object, object)

    def __init__(self,
                 parent=None,
                 designMode=False,
                 with_filter_widget=True,
                 with_selection_widget=True,
                 with_refresh_widget=True,
                 perspective=None,
                 proxy=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.setWindowFlags(QtCore.Qt.Widget)
        self._baseQModel = None
        self._toolBars = []

        if with_filter_widget:
            if isinstance(with_filter_widget, (bool, int)):
                self._with_filter_widget = FilterToolBar
            else:
                self._with_filter_widget = with_filter_widget
        else:
            self._with_filter_widget = None

        if with_selection_widget:
            if isinstance(with_selection_widget, (bool, int)):
                self._with_selection_widget = SelectionToolBar
            else:
                self._with_selection_widget = with_selection_widget
        else:
            self._with_selection_widget = None

        if with_refresh_widget:
            if isinstance(with_refresh_widget, (bool, int)):
                self._with_refresh_widget = RefreshToolBar
            else:
                self._with_refresh_widget = with_refresh_widget
        else:
            self._with_refresh_widget = None

        self._proxyModel = proxy

        toolBars = self.createToolArea()
        self._viewWidget = self.createViewWidget()
        statusbar = self.createStatusBar()

        for toolBar in toolBars:
            #toolBar.addSeparator()
            self.addToolBar(toolBar)
        self.setContentsMargins(0, 0, 0, 0)
        self.setCentralWidget(self._viewWidget)
        self.setStatusBar(statusbar)

        if perspective is None:
            perspective = self.DftPerspective

        if len(self.KnownPerspectives) > 1:
            p_bar = self._perspectiveBar = PerspectiveToolBar(perspective,
                                                              view=self,
                                                              parent=self)
            p_bar.perspectiveChanged.connect(self.onSwitchPerspective)
            self.addToolBar(p_bar)
        else:
            self._perspectiveBar = None
        self._setPerspective(perspective)

    def createViewWidget(self, klass=None):
        raise NotImplementedError

    def createStatusBar(self):
        sb = QtGui.QStatusBar()
        sb.setSizeGripEnabled(False)
        return sb

    def createToolArea(self):
        tb = []  # tb = self._toolArea = QToolArea(self)
        if self._with_filter_widget:
            f_bar = self._filterBar = self._with_filter_widget(view=self,
                                                               parent=self)
            f_bar.filterChanged.connect(self.onFilterChanged)
            tb.append(f_bar)
        else:
            self._filterBar = None

        if self._with_selection_widget:
            s_bar = self._selectionBar = self._with_selection_widget(
                view=self, parent=self)
            s_bar.selectAllTriggered.connect(self.onSelectAll)
            s_bar.clearSelectionTriggered.connect(self.onClearSelection)
            tb.append(s_bar)
        else:
            self._selectionBar = None

        if self._with_refresh_widget:
            r_bar = self._refreshBar = self._with_refresh_widget(view=self,
                                                                 parent=self)
            r_bar.refreshTriggered.connect(self.onRefreshModel)
            tb.append(r_bar)
        else:
            self._refreshBar = None

        return tb

    def getPerspectiveBar(self):
        return self._perspectiveBar

    def getFilterBar(self):
        return self._filterBar

    def getSelectionBar(self):
        return self._selectionBar

    def getRefreshBar(self):
        return self._refreshBar

    def onRefreshModel(self):
        self.getQModel().refresh()

    def onSelectAll(self):
        view = self.viewWidget()
        view.selectAll()

    def onClearSelection(self):
        view = self.viewWidget()
        view.clearSelection()

    def _onClicked(self, index):
        '''Emits an "itemClicked" signal with with the clicked item and column
        as arguments'''
        item = self._mapToSource(index).internalPointer()
        self.itemClicked.emit(item, index.column())

    def _onDoubleClicked(self, index):
        '''Emits an "itemDoubleClicked" signal with the clicked item and column
        as arguments'''
        item = self._mapToSource(index).internalPointer()
        self.itemDoubleClicked.emit(item, index.column())

    def viewWidget(self):
        return self._viewWidget

    def getQModel(self):
        return self.viewWidget().model()

    def getBaseQModel(self):
        return self._baseQModel

    def usesProxyQModel(self):
        return isinstance(self.getQModel(), QtGui.QAbstractProxyModel)

    def _mapToSource(self, index):
        if not self.usesProxyQModel():
            return index
        model = self.getQModel()
        while isinstance(model, QtGui.QAbstractProxyModel):
            index = model.mapToSource(index)
            model = model.sourceModel()
        return index

    def setQModel(self, qmodel):

        self._baseQModel = qmodel
        while isinstance(self._baseQModel, QtGui.QAbstractProxyModel):
            self._baseQModel = self._baseQModel.sourceModel()

        view = self.viewWidget()
        old_smodel = view.selectionModel()
        if old_smodel is not None:
            old_smodel.currentChanged.disconnect(self.viewCurrentIndexChanged)
            old_smodel.selectionChanged.disconnect(self.viewSelectionChanged)
        view.setModel(qmodel)
        new_smodel = view.selectionModel()
        if new_smodel is not None:
            new_smodel.currentChanged.connect(self.viewCurrentIndexChanged)
            new_smodel.selectionChanged.connect(self.viewSelectionChanged)
        view.setCurrentIndex(view.rootIndex())
        self._updateToolBar()

    def viewSelectionChanged(self, selected, deselected):
        self.itemSelectionChanged.emit()

    def viewCurrentIndexChanged(self, current, previous):
        # if there is a proxy model we have to translate the selection
        base_current = self._mapToSource(current)
        base_previous = self._mapToSource(previous)

        self._updateToolBar(current)

        if base_current.isValid():
            currentTreeItem = base_current.internalPointer()
        else:
            currentTreeItem = None

        if base_previous.isValid():
            previousTreeItem = base_previous.internalPointer()
        else:
            previousTreeItem = None
        self.currentItemChanged.emit(currentTreeItem, previousTreeItem)

    def _updateToolBar(self, current=None, previous=None):
        pass

    def selectedItems(self):
        """Returns a list of all selected non-hidden items

        :return: (list<BaseTreeItem>)
        """
        view = self.viewWidget()
        return [
            self._mapToSource(index).internalPointer()
            for index in view.selectedIndexes()
        ]

    def onFilterChanged(self, new_filter):
        if not self.usesProxyQModel():
            return
        proxy_model = self.getQModel()
        if len(new_filter) > 0 and new_filter[0] != '^':
            new_filter = '^' + filter
        proxy_model.setFilterRegExp(new_filter)
        #proxy_model.setFilterFixedString(filter)
        #proxy_model.setFilterWildcard(filter)
        #self.update()

    def refresh(self):
        self.getQModel().refresh()

    #--------------------------------------------------------------------------
    # Perspective handling
    #--------------------------------------------------------------------------

    def perspective(self):
        return self._perspectiveBar.perspective()

    def onSwitchPerspective(self, perspective):
        old_qmodel = self.getQModel()
        self._setPerspective(perspective)

        #set the selectables as they where in the previous model
        if hasattr(old_qmodel, "selectables"):
            self.getQModel().setSelectables(old_qmodel.selectables())

        #set the taurus model (if any) to the qmodel
        if hasattr(self, 'getModelObj'):
            taurusModel = self.getModelObj()
            if taurusModel is not None:
                self.getQModel().setDataSource(taurusModel)

    def _setPerspective(self, perspective):
        qmodel_classes = self.KnownPerspectives[perspective]["model"]
        qmodel_class = qmodel_classes[-1]
        qmodel_proxy_classes = qmodel_classes[-2::-1]  # reversed
        qmodel = qmodel_class(self)
        qmodel_source = qmodel
        if self._proxyModel is None:  # applies the chain of proxies
            for qmodel_proxy_class in qmodel_proxy_classes:
                qproxy = qmodel_proxy_class(self)
                qproxy.setSourceModel(qmodel_source)
                qmodel_source = qproxy
        else:
            self._proxyModel.setSourceModel(qmodel_source)
            qmodel_source = self._proxyModel
        self.setQModel(qmodel_source)

    #--------------------------------------------------------------------------
    # QMainWindow overwriting
    #--------------------------------------------------------------------------

    def addToolBar(self, toolbar):
        QtGui.QMainWindow.addToolBar(self, toolbar)
        self._toolBars.append(toolbar)

    def insertToolBar(self, before, toolbar):
        if isinstance(before, QtGui.QToolBar):
            index = self._toolBars.index(before)
        else:
            index = before
            before = self._toolBars[before]
        QtGui.QMainWindow.insertToolBar(self, before, toolbar)
        self._toolBars.insert(index, toolbar)
Example #11
0
class ErrorWidget(QtGui.QWidget):
    """A panel intended to display an error.
    Example::

        l = [1, 2, 3]
        try:
            print(l[3])
        except IndexError:
            msgbox = ErrorWidget()
            msgbox.show()

    You can show the error outside the exception handling code. If you do this,
    you should keep a record of the exception information as given by
    :func:`sys.exc_info`::

        l = [1, 2, 3]
        exc_info = None
        try:
            print(l[3])
        except IndexError:
            exc_info = sys.exc_info()

        if exc_info:
            msgbox = ErrorWidget(*exc_info)
            msgbox.show()"""

    toggledDetails = QtCore.Signal(bool)

    def __init__(self,
                 err_type=None,
                 err_value=None,
                 err_traceback=None,
                 parent=None):
        QtGui.QWidget.__init__(self, parent)

        if err_type is None and err_value is None and err_traceback is None:
            err_type, err_value, err_traceback = sys.exc_info()[:3]

        self._exc_info = err_type, err_value, err_traceback
        ui_file_name = os.path.join(os.path.dirname(__file__), "ui",
                                    "errorpanel.ui")
        uic.loadUi(ui_file_name, baseinstance=self)
        self.detailsWidget.setVisible(False)
        self.checkBox.setVisible(False)
        self.checkBox.setCheckState(QtCore.Qt.Unchecked)
        self._initReportCombo()

        self.showDetailsButton.toggled.connect(self._onShowDetails)
        self.reportComboBox.activated.connect(self._onReportTriggered)

        self.setIcon(Icon("emblem-important"))

        if err_value is not None:
            self.setError(*self._exc_info)
        self.adjustSize()

    def _initReportCombo(self):
        report_handlers = get_report_handlers()
        combo = self.reportComboBox
        for name, report_handler in report_handlers.items():
            combo.addItem(report_handler.Label, name)

    def _onReportTriggered(self, index):
        report_handlers = get_report_handlers()
        combo = self.reportComboBox
        name = combo.itemData(index)
        report_handler = report_handlers[name]
        report = report_handler(self)
        app = Application()
        txt = _REPORT.format(appName=app.applicationName(),
                             appVersion=app.applicationVersion(),
                             time=datetime.datetime.now().ctime(),
                             text=self.getText(),
                             detail=self.getDetailedText(),
                             origin=self.getOriginText())
        report.report(txt)

    def _onShowDetails(self, show):
        self.detailsWidget.setVisible(show)
        if show:
            text = "Hide details..."
        else:
            text = "Show details..."
        self.showDetailsButton.setText(text)
        self.adjustSize()
        self.toggledDetails.emit(show)

    def checkBoxState(self):
        """Returns the check box state

        :return: the check box state
        :rtype: PyQt4.Qt.CheckState"""
        return self.checkBox.checkState()

    def checkBoxText(self):
        """Returns the check box text

        :return: the check box text
        :rtype: str"""
        return str(self.checkBox.text())

    def setCheckBoxText(self, text):
        """Sets the checkbox text.

        :param text: new checkbox text
        :type text: str"""
        self.checkBox.setText(text)

    def setCheckBoxState(self, state):
        """Sets the checkbox state.

        :param text: new checkbox state
        :type text: PyQt4.Qt.CheckState"""
        self.checkBox.setCheckState(state)

    def setCheckBoxVisible(self, visible):
        """Sets the checkbox visibility.

        :param visible: True makes checkbox visible, False hides it
        :type visible: bool"""
        self.checkBox.setVisible(visible)

    def addButton(self, button, role=QtGui.QDialogButtonBox.ActionRole):
        """Adds the given button with the given to the button box

        :param button: the button to be added
        :type button: PyQt4.QtGui.QPushButton
        :param role: button role
        :type role: PyQt4.Qt.QDialogButtonBox.ButtonRole"""
        self.buttonBox.addButton(button, role)

    def setIcon(self, icon, size=64):
        """Sets the icon to the dialog

        :param icon: the icon
        :type icon: PyQt4.QtGui.QIcon"""
        pixmap = icon.pixmap(size)
        self.iconLabel.setPixmap(pixmap)

    def setText(self, text):
        """Sets the text of this panel

        :param text: the new text
        :type text: str"""
        self.textLabel.setText(text)

    def getText(self):
        """Returns the current text of this panel

        :return: the text for this panel
        :rtype: str"""
        return self.textLabel.text()

    def setDetailedText(self, text):
        """Sets the detailed text of the dialog

        :param text: the new text
        :type text: str"""
        self.detailsTextEdit.setPlainText(text)

    def setDetailedHtml(self, html):
        """Sets the detailed HTML of the dialog

        :param html: the new HTML text
        :type html: str"""
        self.detailsTextEdit.setHtml(html)

    def getDetailedText(self):
        """Returns the current detailed text of this panel

        :return: the detailed text for this panel
        :rtype: str"""
        return self.detailsTextEdit.toPlainText()

    def getDetailedHtml(self):
        """Returns the current detailed HTML of this panel

        :return: the detailed HTML for this panel
        :rtype: str"""
        return self.detailsTextEdit.toHtml()

    def setOriginText(self, text):
        """Sets the origin text of the dialog

        :param text: the new text
        :type text: str"""
        self.originTextEdit.setPlainText(text)

    def setOriginHtml(self, html):
        """Sets the origin HTML of the dialog

        :param html: the new HTML text
        :type html: str"""
        self.originTextEdit.setHtml(html)

    def getOriginText(self):
        """Returns the current origin text of this panel

        :return: the origin text for this panel
        :rtype: str"""
        return self.originTextEdit.toPlainText()

    def getOriginHtml(self):
        """Returns the current origin HTML of this panel

        :return: the origin HTML for this panel
        :rtype: str"""
        return self.originTextEdit.toHtml()

    def setError(self, err_type=None, err_value=None, err_traceback=None):
        """Sets the exception object.
        Example usage::

            l = [1, 2, 3]
            exc_info = None
            try:
                print(l[3])
            except IndexError:
                exc_info = sys.exc_info()

            if exc_info:
                msgbox = ErrorWidget()
                msgbox.setError(*exc_info)
                msgbox.show()

        :param err_type: the exception type of the exception being handled
                         (a class object)
        :type error: class object
        :param err_value: exception object
        :type err_value: object
        :param err_traceback: a traceback object which encapsulates the call
                              stack at the point where the exception originally
                              occurred
        :type err_traceback: traceback"""
        i = sys.exc_info()
        self._exc_info = [
            err_type or i[0], err_value or i[1], err_traceback or i[2]
        ]

        formatter_klass = self.findErrorFormatter(self._exc_info[0])
        formatter = formatter_klass()
        error_data = formatter.translateError(*self.getError())
        title, error, detailed_error, origin = error_data
        self.setWindowTitle(title)
        self.setText(error)
        self.setDetailedHtml(detailed_error)
        self.setOriginHtml(origin)

    def getError(self):
        """Returns the current exception information of this panel

        :return: the current exception information (same as type as returned by
                 :func:`sys.exc_info`)
        :rtype: tuple<type, value, traceback>"""
        return self._exc_info

    @staticmethod
    def getErrorFormatters():
        result = {}
        try:
            import PyTango
            result[PyTango.DevFailed] = TangoErrorFormatterPlugin
        except ImportError:
            pass
        return result

    @classmethod
    def registerErrorHandler(klass, err_type, err_handler):
        klass.getErrorFormatters()[err_type] = err_handler

    @classmethod
    def findErrorFormatter(klass, err_type):
        """Finds the proper error handler class for the given error

        :param err_type: error class
        :type err_type: class object
        :return: a message box error handler
        :rtype: TaurusMessageBoxErrorHandler class object"""

        for exc, h_klass in klass.getErrorFormatters().items():
            if issubclass(err_type, exc):
                return h_klass
        return BaseErrorFormatterPlugin
Example #12
0
class Axis(QtCore.QObject):

    # : position changed signal
    # :
    # : emitted when the axis position has changed
    # : the signal is emitted with the axis name and position value
    positionChanged = QtCore.Signal(str, float)

    # : position changed signal
    # :
    # : emitted when the axis minimum allowed position has changed
    # : the signal is emitted with the axis name and minimum position value
    limitsChanged = QtCore.Signal(str, list)

    # : step sizes changed signal
    # :
    # : emitted when the allowed axis step sizes has changed
    # : the signal is emitted with the axis name and step sizes
    stepsChanged = QtCore.Signal(str, object)

    # : current step changed signal
    # :
    # : emitted when the current step size has changed
    # : the signal is emitted with the axis name and current step size
    currentStepChanged = QtCore.Signal(str, float)

    # : state changed signal
    # :
    # : emitted when the axis state has changed
    # : the signal is emitted with the axis name, old state and new state
    stateChanged = QtCore.Signal(str, object, object)

    # : label changed signal
    # :
    # : emitted when the axis label has changed
    # : the signal is emitted with the axis name and label value
    labelChanged = QtCore.Signal(str, str)

    # : units changed signal
    # :
    # : emitted when the axis units has changed
    # : the signal is emitted with the axis name and units value
    unitChanged = QtCore.Signal(str, str)

    def __init__(self, axis_info, axes, parent=None):
        super(Axis, self).__init__(parent)
        self._axes = weakref.ref(axes)
        self.name = axis_info['name']
        self.index = axis_info['index']
        self.role = axis_info.get('role', str(self.index))
        self._label = axis_info.get('username', self.name)

        self._position = None  # float('nan')
        self._limits = None  # float('-inf'), float('+inf')
        self._state = None
        self._steps = None
        self._current_step = None
        self._unit = None

    @property
    def axes(self):
        return self._axes()

    def refresh(self):
        self.state = self.getState(cache=False)
        self.limits = self.getLimits(cache=False)
        self.position = self.getPosition(cache=False)

    def getPosition(self, cache=True):
        if cache and self._position is not None:
            result = self._position
        else:
            self._position = result = self.axes.position(self.name)
        return result

    def setPosition(self, position, emit=True):
        self._position = position
        if emit:
            self.positionChanged.emit(self.name, position)

    #: This property contains the axis position
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getPosition`
    #:     * :meth:`Axis.setPosition`
    position = QtCore.Property(str, getPosition, setPosition)

    def getLimits(self, cache=True):
        if cache and self._limits is not None:
            result = self._limits
        else:
            self._limits = result = list(self.axes.limits(self.name))
        return result

    def setLimits(self, limits, emit=True):
        self._limits = list(limits)
        if emit:
            self.limitsChanged.emit(self.name, limits)

    #: This property contains the axis limits
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getLimits`
    #:     * :meth:`Axis.setLimits`
    limits = QtCore.Property(list, getLimits, setLimits)

    def getState(self, cache=True):
        if cache and self._state is not None:
            result = self._state
        else:
            self._state = result = self.axes.state(self.name)
        return result

    def setState(self, state, emit=True):
        old_state = self._state
        if state is None:
            state = State._Invalid
        self._state = state
        if emit:
            self.stateChanged.emit(self.name, old_state, state)

    #: This property contains the axis state
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getState`
    #:     * :meth:`Axis.setState`
    state = QtCore.Property(object, getState, setState)

    def getLabel(self):
        return self._label

    def setLabel(self, label, emit=True):
        if label is None:
            label = ""
        self._label = label
        if emit:
            self.labelChanged.emit(self.name, label)

    #: This property contains the axis label
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getLabel`
    #:     * :meth:`Axis.setLabel`
    label = QtCore.Property(str, getLabel, setLabel)

    def getSteps(self):
        return self._steps

    def setSteps(self, steps, emit=True):
        if steps is None:
            steps = []
        self._steps = steps
        if emit:
            self.stepsChanged.emit(self.name, steps)

    #: This property contains the axis steps
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getSteps`
    #:     * :meth:`Axis.setSteps`
    steps = QtCore.Property(str, getSteps, setSteps)

    def getCurrentStep(self):
        return self._current_step

    def setCurrentStep(self, current_step, emit=True):
        self._current_step = current_step
        if emit:
            self.currentStepChanged.emit(self.name, current_step)

    #: This property contains the axis current step size
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getCurrentStep`
    #:     * :meth:`Axis.setCurrentStep`
    currentStep = QtCore.Property(float, getCurrentStep, setCurrentStep)

    def getUnit(self):
        return self._unit

    def setUnit(self, unit, emit=True):
        if unit is None:
            unit = ""
        self._unit = unit
        if emit:
            self.unitChanged.emit(self.name, unit)

    #: This property contains the axis unit
    #:
    #: **Access functions:**
    #:
    #:     * :meth:`Axis.getUnit`
    #:     * :meth:`Axis.setUnit`
    unit = QtCore.Property(float, getUnit, setUnit)

    def move(self, absolute_position):
        self.axes.move(self.name, absolute_position)

    def moveRelative(self, relative_position):
        self.move(self.position + relative_position)

    def moveUp(self):
        self.moveRelative(+self.currentStep)

    def moveDown(self):
        self.moveRelative(-self.currentStep)

    stepUp = moveUp
    stepDown = moveDown

    def stop(self):
        self.axes.abort(self.name)

    ToolTipTemplate = """<html>axis <u>{axis.label}</u> is in \
<b>{axis.state.name}</b> state, at position <b>{axis.position}</b><br/>
Limits set to <b>[{axis.limits[0]}, {axis.limits[1]}]</b><br/>
(the hardware name for this axis is: <i>{axis.name}</i>)"""

    def toolTip(self):
        return self.ToolTipTemplate.format(axis=self)
Example #13
0
class ValueSpinBox(QtGui.QDoubleSpinBox):

    SpinStyleT = 'ValueSpinBox {font-family: "Monospace"; %s}'

    # : value applied signal
    # :
    # : emitted when the spinbox enter/return key is pressed
    valueApplied = QtCore.Signal()

    def __init__(self, axis, parent=None):
        super(ValueSpinBox, self).__init__(parent)
        self.axis = axis
        self.setAccelerated(True)
        # self.setButtonSymbols(self.PlusMinus)
        # self.setFrame(False)
        self.setDecimals(3)
        self.setMinimum(float("-inf"))
        self.setMaximum(float("+inf"))
        self.setAlignment(QtCore.Qt.AlignLeft)
        self.setStyleSheet(self.SpinStyleT % "")

    def setValue(self, value, emit=True):
        if value is None:
            value = float('nan')
        if emit:
            return super(ValueSpinBox, self).setValue(value)

        blocked = self.signalsBlocked()
        try:
            self.blockSignals(True)
            result = super(ValueSpinBox, self).setValue(value)
        finally:
            self.blockSignals(blocked)
        return result

    def setUnit(self, unit):
        if unit is None or not len(unit):
            unit = ""
        elif not unit.startswith(" "):
            unit = " " + unit
        self.setSuffix(unit)

    def setState(self, state):
        if state is None:
            state = State._Invalid
        styleSheet = getCSSColorFromState(state)
        self.setStyleSheet(self.SpinStyleT % styleSheet)

    def setSingleStep(self, value):
        if value is None:
            return
        return super(ValueSpinBox, self).setSingleStep(value)

    def setMinimum(self, value):
        if value is None:
            value = float('-inf')
        return super(ValueSpinBox, self).setMinimum(value)

    def setMaximum(self, value):
        if value is None:
            value = float('+inf')
        return super(ValueSpinBox, self).setMaximum(value)

    def sizeHint(self):
        size = super(ValueSpinBox, self).sizeHint()
        size.setHeight(get_height_hint())
        return size

    def minimumSizeHint(self):
        size = super(ValueSpinBox, self).minimumSizeHint()
        size = QtCore.QSize(size.width(), get_minimum_height_hint())
        return size

    def keyPressEvent(self, event):
        key = event.key()
        if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
            self.valueApplied.emit()
        elif key == QtCore.Qt.Key_Escape:
            self.axis.refresh()
        elif key == QtCore.Qt.Key_F5:
            self.axis.refresh()
        else:
            return super(ValueSpinBox, self).keyPressEvent(event)