def mouseReleaseEvent(self, event): """ Calls realeseMouse() to make sure the widget does not grab the mouse. Necessary because ConnectableWidgetOwner.propagateEventUnderConnectionWidget() may call grabMouse() on this widget. """ logging.debug(self.__class__.__name__ +": mouseReleaseEvent()") self.releaseMouse() if self._dragablePort: if self._aimConnection: self._aimConnection.hide() # don't appear as childWidget() self._aimConnection.delete() self._aimConnection = None moduleParentPosition = self.mapTo(self.moduleParent(), event.pos()) #widget = self.moduleParent().childAt(moduleParentPosition) widget = None for child in reversed(self.moduleParent().children()): if isinstance(child,QWidget) and child.isVisible() and child.geometry().contains(moduleParentPosition) and not isinstance(child, PortConnection): widget = child break if hasattr(widget, "dropAreaPort"): localPosition = widget.mapFrom(self.moduleParent(), moduleParentPosition) self.moduleParent().addPortConnection(self, widget.dropAreaPort(localPosition)) elif isinstance(widget, PortWidget): self.moduleParent().addPortConnection(self, widget) VispaWidget.mouseReleaseEvent(self, event)
def mouseMoveEvent(self, event): if bool(event.buttons() & Qt.LeftButton): VispaWidget.mouseMoveEvent(self, event) elif self._menuWidget: self.positionizeMenuWidget() self.showMenu()
def __init__(self, parent=None, associatedWidget=None, orientation=Qt.Horizontal): """ Constructor """ logging.debug("%s: Constructor" % self.__class__.__name__) self._cursorEntered = False self._menuEntryTextFields = [] self._menuEntrySlots = [] self._hoverEntry = None self._spacer = TextField() VispaWidget.__init__(self, parent) self.hide() self._associatedWidget = associatedWidget self.setMouseTracking(True) self.setDragable(False) #self._hoverBrush = QBrush(self.HOVER_COLOR1) self._hoverGradient = QRadialGradient() self._hoverGradient.setColorAt(0, self.HOVER_COLOR1) self._hoverGradient.setColorAt(1, self.HOVER_COLOR2) #self._hoverBrush = QBrush(self.HOVER_COLOR1) self._spacer.setFontSizeRange(self.TEXTFIELD_FONTSIZE_MIN, self.TEXTFIELD_FONTSIZE_MAX) #self._textField.setDefaultWidth(self.getDistance('textFieldWidth', 1, True)) #entry.setDefaultHeight(self.getDistance('textFieldHeight', 1, True)) self._spacer.setDefaultFontSize(self.TEXTFIELD_FONTSIZE) self._spacer.setAutosizeFont(self.TEXTFIELD_AUTOSIZE_FONT_FLAG) self._spacer.setAutotruncate(self.TEXTFIELD_AUTOTRUNCATE_TEXT_FLAG) self._spacer.setAutoscale(True, False) self._spacer.setPenColor(self.TITLE_COLOR) self._spacer.setFont(self.font()) self._spacer.setText(" | ") self._spacer.calculateDimensions()
def mousePressEvent(self, event): VispaWidget.mousePressEvent(self, event) for i, entry in enumerate(self._menuEntryTextFields): if self._menuEntrySlots[i] and entry.getDrawRect(self.zoomFactor()).contains(event.pos()): self.hide() self._menuEntrySlots[i]() break
def mousePressEvent(self, event): """ Registers position for starting drag. """ logging.debug("%s: mousePressEvent()" % self.__class__.__name__) if self._dragablePort and event.button() == Qt.LeftButton: self._startDragPosition = QPoint(event.pos()) VispaWidget.mousePressEvent(self, event)
def mouseReleaseEvent(self, event): """ Calls realeseMouse() to make sure the widget does not grab the mouse. Necessary because ConnectableWidgetOwner.propagateEventUnderConnectionWidget() may call grabMouse() on this widget. """ #logging.debug(self.__class__.__name__ +": mouseReleaseEvent()") self.releaseMouse() VispaWidget.mouseReleaseEvent(self, event)
def mouseMoveEvent(self, event): if bool(event.buttons() & Qt.LeftButton): VispaWidget.mouseMoveEvent(self, event) return for entry in self._menuEntryTextFields: if entry.getDrawRect(self.zoomFactor()).contains(event.pos()): self._hoverEntry = entry self.update() break
def __init__(self, parent=None, name='default'): """ Constructor. """ VispaWidget.__init__(self, parent) self.setName(name) self._connectionDirection = self.CONNECTION_DIRECTION self._startDragPosition = None self.setDragable(True) self._aimConnection = None self._attachedConnections = []
def mouseMoveEvent(self, event): if bool(event.buttons() & Qt.LeftButton): VispaWidget.mouseMoveEvent(self, event) elif self.menu(): self.positionizeMenuWidget() if event.pos().y() <= self.getDistance("titleFieldBottom"): self.showMenu() elif self.menu(): self.menu().hide()
def mousePressEvent(self, event): """ Makes sure event is forwarded to both base classes. If position of event is within the dropArea of a port a QMouseEvent is sent to the port. See dropArea(). """ dropAreaPort = self.dropAreaPort(event.pos()) if dropAreaPort and dropAreaPort.isDragable(): dropAreaPort.grabMouse() newEvent = QMouseEvent(event.type(), dropAreaPort.mapFromParent(event.pos()), event.button(), event.buttons(), event.modifiers()) QCoreApplication.instance().sendEvent(dropAreaPort, newEvent) else: VispaWidgetOwner.mousePressEvent(self, event) VispaWidget.mousePressEvent(self, event)
def __init__(self, parent): self._descriptionWidgets = [] self._descriptionActiveRects = [QRect(), QRect(), QRect()] # descriptions will be visible if mouse cursor is in the rect VispaWidget.__init__(self, parent) self._filenewIcon = QIcon(QPixmap(":/resources/filenew.svg")) self._fileopenIcon = QIcon(QPixmap(":/resources/fileopen.svg")) self.setImage(QSvgRenderer(":/resources/startup_development_cycle.svg")) self.setDragable(False) self.setMouseTracking(True) # receive mouse events even if no button is pressed self._hideDescriptions = False self.createPrototypingWidget() self.createExecutionWidget() self.createVerifyingWidget()
def __init__(self, parent=None, name=None): """ Constructor. """ self._ports = [] self._showPortNames = False self._portNamesPosition = None self._showPortLines = False self._menuWidget = None VispaWidget.__init__(self, parent) self.setShowPortNames(self.SHOW_PORT_NAMES) self.setPortNamesPosition(self.PORT_NAMES_POSITION) self.setShowPortLines(self.SHOW_PORT_LINES) if name: self.setTitle(name)
def defineDistances(self, keepDefaultRatio=False): """ Extends distances of VispaWidget by the additionally needed distances for displaying ports. """ #if scale == None: # scale = self.scale() scale = 1.0 if not VispaWidget.defineDistances(self, keepDefaultRatio): return False if len(self.sinkPorts()) > 0: self.distances()['textFieldX'] += PortWidget.WIDTH * scale + self.distances()['leftMargin'] self.distances()['textFieldRight'] = self.distances()['textFieldX'] + self.distances()['textFieldWidth'] if self._showPortNames: self.distances()['textFieldX'] += self._getMaxSinkTitleWidth() + self.distances()['leftMargin'] self.distances()['textFieldRight'] += self._getMaxSinkTitleWidth() + self.distances()['leftMargin'] firstPortY = self.distances()['height'] - self.distances()['bottomMargin'] - PortWidget.HEIGHT * scale self.distances()['firstSinkX'] = self.distances()['leftMargin'] self.distances()['firstSinkY'] = firstPortY if self.textFieldIsSet(): self.distances()['firstSourceX'] = self.distances()['textFieldRight'] + self.distances()['leftMargin'] #else: self.distances()['firstSourceX'] = self.distances()['width'] - self.distances()['leftMargin'] - PortWidget.WIDTH * scale self.distances()['firstSourceY'] = firstPortY return True
class ZoomableWidgetTestCase(unittest.TestCase): def testExample(self): logging.debug(self.__class__.__name__ + ': testExample()') self.app = QApplication(sys.argv) self.window = QMainWindow() self.window.setWindowTitle("test ZoomableWidget") self.window.resize(300,300) self.app.setActiveWindow(self.window) self.window.show() self.scrollArea = ZoomableScrollArea(self.window) self.window.setCentralWidget(self.scrollArea) self.zoomableWidget = ZoomableWidget() self.scrollArea.setWidget(self.zoomableWidget) self.widget=VispaWidget(self.zoomableWidget) self.widget.move(10,10) self.widget.show() if not hasattr(unittest,"NO_GUI_TEST"): self.app.exec_()
def mouseMoveEvent(self, event): """ If minimum distance from mousePressEvent is reached initiates dragging. """ #logging.debug(self.__class__.__name__ +": mouseMoveEvent()") if self._dragablePort and self._startDragPosition and bool(event.buttons() & Qt.LeftButton): if not self._aimConnection and (event.pos() - self._startDragPosition).manhattanLength() >= QApplication.startDragDistance(): self._aimConnection = PointToPointConnection(self.moduleParent(), self.connectionPoint(), self.mapTo(self.moduleParent(), event.pos())) self._aimConnection.setSourceDirection(self.CONNECTION_DIRECTION) self.connect(self._aimConnection, SIGNAL("connectionDeleted"), self.resetAimConnection) if self.CONNECTION_DIRECTION == PointToPointConnection.ConnectionDirection.RIGHT: self._aimConnection.setTargetDirection(PointToPointConnection.ConnectionDirection.LEFT) elif self.CONNECTION_DIRECTION == PointToPointConnection.ConnectionDirection.LEFT: self._aimConnection.setTargetDirection(PointToPointConnection.ConnectionDirection.RIGHT) self._aimConnection.show() elif self._aimConnection: self._aimConnection.updateTargetPoint(self.mapTo(self.moduleParent(), event.pos())) VispaWidget.mouseMoveEvent(self, event)
def autosize(self): """ Overwrite VispaWidget's function. This adds size and position handling for left and top sides of container. VispaWidget only takes care of right and bottom sides as widget position remains constant. This function also adjusts the container's position as needed to include all children. """ if self._autolayoutChildrenEnabled and self._childrenVisible: self.autolayoutChildren() self.updateConnections() childrenRect = WidgetContainer.childrenRect(self) if self._autosizeAdjustContainerPositionFlag and self._childrenVisible and (childrenRect.width() != 0 or childrenRect.height() != 0): # increase / decrease size of container on left and top side # round to prevent drifting wehen zoom != 100% xMargin = round(self.contentStartX()) yMargin = round(self.contentStartY()) childrenRectX = childrenRect.x() childrenRectY = childrenRect.y() xOffset = 0 yOffset = 0 if childrenRectX != xMargin: xOffset = - childrenRectX + xMargin if childrenRectY != yMargin: yOffset = - childrenRectY + yMargin if xOffset != 0 or yOffset != 0: self.move(self.x() - xOffset , self.y() - yOffset) for child in self.children(): #if isinstance(child,QWidget): # needed for PyQt4.5 if hasattr(child, "move"): child.move(child.x() + xOffset, child.y() + yOffset) VispaWidget.autosize(self) self.emit(SIGNAL("sizeChanged"), self)
def sizeHint(self): """ Calculates needed space for content. """ #logging.debug(__name__ +": sizeHint()") childrenRect = self.childrenRect() width = childrenRect.bottomRight().x() + self.getDistance('rightMargin') height = childrenRect.bottomRight().y() + self.getDistance('bottomMargin') # make zoom independent width = 1.0 / self.zoomFactor() * width height = 1.0 / self.zoomFactor() * height # from now on in 100% dimensions superClassNeededSpace = VispaWidget.sizeHint(self) width = max(width, superClassNeededSpace.width(), WidgetContainer.WIDTH) height = max(height, superClassNeededSpace.height(), WidgetContainer.HEIGHT) return QSize(width, height)
def setVisible(self, visible): VispaWidget.setVisible(self, visible) self._executionDescriptionWidget.setVisible(visible and not self._hideDescriptions) self._prototypingDescriptionWidget.setVisible(visible and not self._hideDescriptions) self._verifyingDescriptionWidget.setVisible(visible and not self._hideDescriptions)
def boundingRect(self): br = VispaWidget.boundingRect(self) for w in self._descriptionWidgets: br = br.united(w.boundingRect()) return br
def rearangeContent(self): VispaWidget.rearangeContent(self) self.rearangeDescriptionWidgets()
def moveEvent(self, event): VispaWidget.moveEvent(self, event) self.rearangeDescriptionWidgets()
def mouseMoveEvent(self, event): if bool(event.buttons()): VispaWidget.mouseMoveEvent(self, event) elif self._hideDescriptions: for i in range(len(self._descriptionWidgets)): self._descriptionWidgets[i].setVisible(self._descriptionActiveRects[i].contains(event.pos()))
def showEvent(self, event): VispaWidget.showEvent(self, event) self._cursorEntered = False
def mousePressEvent(self, event): """ Makes sure event is forwarded to both base classes. """ ConnectableWidgetOwner.mousePressEvent(self, event) VispaWidget.mousePressEvent(self, event)
def paint(self, painter, event=None): """ Takes care of painting widget content on given painter. """ VispaWidget.paint(self, painter, event) self.drawMenuEntries(painter)
def rearangeContent(self): """ Arranges ports after content is rearranged by VispaWidget. """ VispaWidget.rearangeContent(self) self.arrangePorts() # has to be after rearangeContent(), prevents infinite loop (..getDistance())
def deleteLater(self): if self._menuWidget: self.removeMenu() for port in self._ports: port.deleteAttachedConnections() VispaWidget.deleteLater(self)
def createDescriptionWidget(self, arrowDirection, description): widget = VispaWidget(self.parent()) widget.enableAutosizing(True, False) widget.setSelectable(False) widget.setArrowShape(arrowDirection) widget.setVisible(not self._hideDescriptions) widget.setDragable(False) self._descriptionWidgets.append(widget) return widget
def dragWidget(self, pPos): VispaWidget.dragWidget(self, pPos) self.positionizeMenuWidget()
def setZoom(self, zoom): """ Arranges ports when zoom has changed. """ VispaWidget.setZoom(self, zoom)
def setDragable(self, dragable, recursive=False): """ Set whether user can grab the port and connect it to others. """ VispaWidget.setDragable(self, False, recursive) self._dragablePort = dragable self.setAcceptDrops(dragable)
def hide(self): VispaWidget.hide(self) self._hoverEntry = None
def move(self, *target): VispaWidget.move(self, *target) if self._menuWidget: self._menuWidget.hide() self.updateAttachedConnections()
def select(self, sel=True, multiSelect=False): VispaWidget.select(self, sel, multiSelect) if not sel and self._menuWidget: self._menuWidget.hide()