source: orange/Orange/OrangeCanvas/orngCanvasItems.py @ 10732:84df67a76a4e

Revision 10732:84df67a76a4e, 28.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 2 years ago (diff)

No drop shadow offset for canvas lines.

Line 
1# Author: Gregor Leban (gregor.leban@fri.uni-lj.si)
2# Description:
3#    two main objects that are shown in the canvas; Line and Widget
4#
5from PyQt4.QtCore import *
6from PyQt4.QtGui import *
7import os, sys, math
8ERROR = 0
9WARNING = 1
10
11def getDropShadow(item):
12    if hasattr(item, "graphicsEffect"):
13        return item.graphicsEffect()
14    else:
15        return None
16   
17def setDropShadow(self, offset=QPointF(0.3, 0.5), blur_radius=5):
18    if qVersion() >= "4.6" and self.canvasDlg.settings["enableCanvasDropShadows"]:
19        effect = QGraphicsDropShadowEffect(self.scene())
20        effect.setOffset(offset)
21        effect.setBlurRadius(blur_radius)
22        self.setGraphicsEffect(effect)
23   
24class TempCanvasLine(QGraphicsPathItem):
25    def __init__(self, canvasDlg, canvas):
26        QGraphicsLineItem.__init__(self, None, canvas)
27        self.setZValue(-10)
28        self.canvasDlg = canvasDlg
29        self.startWidget = None
30        self.endWidget = None
31        self.widget = None
32
33        self.setPen(QPen(QColor(180, 180, 180), 3, Qt.SolidLine))
34       
35        self.setDropShadow(offset=QPointF(0.0, 0.0))
36   
37    setDropShadow = setDropShadow
38    getDropShadow = getDropShadow
39   
40    def setStartWidget(self, widget):
41        self.startWidget = widget
42        pos = widget.getRightEdgePoint()
43        endX, endY = startX, startY = pos.x(), pos.y()
44#        self.setLine(pos.x(), pos.y(), pos.x(), pos.y())
45       
46    def setEndWidget(self, widget):
47        self.endWidget = widget
48        pos = widget.getLeftEdgePoint()
49        endX, endY = startX, startY = pos.x(), pos.y()
50#        self.setLine(pos.x(), pos.y(), pos.x(), pos.y())
51       
52    def updateLinePos(self, newPos):
53        if self.startWidget == None and self.endWidget == None:
54            return
55       
56        if self.startWidget != None:
57            func = "getDistToLeftEdgePoint"
58        else:
59            func = "getDistToRightEdgePoint"
60       
61        schema = self.canvasDlg.schema
62        view = schema.canvasView
63       
64        self.widget = None
65        widgets = view.getItemsAtPos(newPos, CanvasWidget)
66        if widgets:
67            self.widget = widgets[0]
68        else:
69            dists = [(getattr(w, func)(newPos), w) for w in schema.widgets]
70            dists.sort()
71            if dists and dists[0][0] < 20:
72                self.widget = dists[0][1]
73       
74        if self.startWidget:
75            pos = self.startWidget.getRightEdgePoint()
76        else:
77            pos = self.endWidget.getLeftEdgePoint()
78
79        if self.widget not in [self.startWidget, self.endWidget]: 
80            if self.startWidget == None and self.widget.widgetInfo.outputs:
81                newPos = self.widget.getRightEdgePoint()
82            elif self.endWidget == None and self.widget.widgetInfo.inputs:
83                newPos = self.widget.getLeftEdgePoint()
84       
85        path = QPainterPath(pos)
86        if self.startWidget != None:
87            path.cubicTo(pos.x()+60, pos.y(), newPos.x()-60, newPos.y(), newPos.x(),newPos.y())
88        else:
89            path.cubicTo(pos.x()-60, pos.y(), newPos.x()+60, newPos.y(), newPos.x(),newPos.y())
90        self.setPath(path)
91#        self.setLine(pos.x(), pos.y(), newPos.x(), newPos.y())
92       
93    def remove(self):
94        self.hide()
95        self.startWidget = None
96        self.endWidget = None
97       
98        self.prepareGeometryChange()
99       
100        if self.getDropShadow():
101            self.setGraphicsEffect(None)
102             
103        for child in self.childItems():
104            child.hide()
105            child.setParentItem(None)
106            self.scene().removeItem(child)
107           
108        self.hide()
109        self.scene().removeItem(self)
110
111# #######################################
112# # CANVAS LINE
113# #######################################
114       
115class CanvasLine(QGraphicsPathItem):
116    def __init__(self, signalManager, canvasDlg, view, outWidget, inWidget, scene, *args):
117        self.outWidget = outWidget
118        self.inWidget = inWidget
119       
120        QGraphicsPathItem.__init__(self, None, None)
121        self.signalManager = signalManager
122        self.canvasDlg = canvasDlg
123        self.view = view
124        self.setZValue(-10)
125       
126        self.caption = ""
127        self.captionItem = QGraphicsTextItem(self)
128        self.captionItem.setDefaultTextColor(QColor(80, 80, 192))
129        self.captionItem.setHtml("<center>%s</center>" % self.caption)
130        self.captionItem.setAcceptHoverEvents(False)
131        self.captionItem.setVisible(bool(self.canvasDlg.settings["showSignalNames"]))
132        self.captionItem.setAcceptedMouseButtons(Qt.NoButton)
133       
134        self.updateTooltip()
135       
136        # this might seem unnecessary, but the pen size 20 is used for collision detection, when we want to see whether to to show the line menu or not
137        self.setPen(QPen(QColor(200, 200, 200), 20, Qt.SolidLine))
138        self.setAcceptHoverEvents(True)
139        self.hoverState = False
140           
141        if scene is not None:
142            scene.addItem(self)
143           
144        self._dyn_enabled = False
145           
146        QObject.connect(self.outWidget.instance, SIGNAL("dynamicLinkEnabledChanged(PyQt_PyObject, bool)"), self.updateDynamicEnableState)
147       
148        self.setDropShadow(offset=QPointF(0.0, 0.0))
149       
150    setDropShadow = setDropShadow
151    getDropShadow = getDropShadow
152   
153    def remove(self):
154        self.hide()
155        self.setToolTip("")
156        self.outWidget = None
157        self.inWidget = None
158       
159        self.prepareGeometryChange()
160       
161        if self.getDropShadow():
162            self.setGraphicsEffect(None)
163           
164        for child in self.childItems():
165            child.hide()
166            child.setParentItem(None)
167            self.scene().removeItem(child)
168           
169        self.hide()
170        self.scene().removeItem(self)
171        QApplication.instance().processEvents(QEventLoop.ExcludeUserInputEvents)
172       
173    def getEnabled(self):
174        signals = self.signalManager.findSignals(self.outWidget.instance, self.inWidget.instance)
175        if not signals: return 0
176        return int(self.signalManager.isSignalEnabled(self.outWidget.instance, self.inWidget.instance, signals[0][0], signals[0][1]))
177
178    def getSignals(self):
179        signals = []
180        for link in self.signalManager.getLinks(self.outWidget.instance, self.inWidget.instance):
181            signals.append((link.signalNameFrom, link.signalNameTo))
182#        for (inWidgetInstance, outName, inName, X) in self.signalManager.links.get(self.outWidget.instance, []):
183#            if inWidgetInstance == self.inWidget.instance:
184#                signals.append((outName, inName))
185        return signals
186   
187    def isDynamic(self):
188        links = self.signalManager.getLinks(self.outWidget.instance, self.inWidget.instance)
189        return any(link.dynamic for link in links)
190   
191    def updateDynamicEnableState(self, link, enabled):
192        """ Call when dynamic signal state changes
193        """
194        links = self.signalManager.getLinks(self.outWidget.instance, self.inWidget.instance)
195        if link not in links:
196            return
197       
198        if self.isDynamic():
199            if enabled:
200                self._dyn_enabled = True
201            else:
202                self._dyn_enabled = False
203        self.update()
204       
205   
206    def updatePainterPath(self):
207        p1 = self.outWidget.getRightEdgePoint()
208        p2 = self.inWidget.getLeftEdgePoint()
209        path = QPainterPath(p1)
210        path.cubicTo(p1.x() + 60, p1.y(), p2.x() - 60, p2.y(), p2.x(), p2.y())
211        self.setPath(path)
212        metrics = QFontMetrics(self.captionItem.font())
213        oddLineOffset = -metrics.lineSpacing() / 2 * (len(self.caption.strip().splitlines()) % 2)
214        mid = self.path().pointAtPercent(0.5)
215        rect = self.captionItem.boundingRect()
216        self.captionItem.setPos(mid + QPointF(-rect.width() / 2.0, -rect.height() / 2.0 + oddLineOffset))
217        self.update()
218       
219    def shape(self):
220        stroke = QPainterPathStroker()
221        stroke.setWidth(6)
222        return stroke.createStroke(self.path())
223   
224    def boundingRect(self):
225        rect = QGraphicsPathItem.boundingRect(self)
226        if self.getDropShadow():
227            textRect = self.captionItem.boundingRect() ## Should work without this but for some reason if using graphics effects the text gets clipped
228            textRect.moveTo(self.captionItem.pos())
229            return rect.united(textRect)
230        else:
231            return rect
232
233    def paint(self, painter, option, widget = None):
234        if self.isDynamic():
235            color2 = QColor(Qt.blue if self._dyn_enabled else Qt.red)
236            color1 = color2.lighter(150)
237        else:
238            color1 = QColor(200, 200, 200)
239            color2 = QColor(160, 160, 160)
240        painter.setPen(QPen(color1, 6 if self.hoverState == True else 4 , self.getEnabled() and Qt.SolidLine or Qt.DashLine, Qt.RoundCap))
241        painter.drawPath(self.path())
242        painter.setPen(QPen(color2, 2 , self.getEnabled() and Qt.SolidLine or Qt.DashLine, Qt.RoundCap))
243        painter.drawPath(self.path())
244
245    def updateTooltip(self):
246        if self.inWidget and self.outWidget:
247            status = self.getEnabled() == 0 and " (Disabled)" or ""
248            string = "<nobr><b>" + self.outWidget.caption + "</b> --> <b>" + self.inWidget.caption + "</b>" + status + "</nobr><hr>Signals:<br>"
249            for (outSignal, inSignal) in self.getSignals():
250                string += "<nobr> &nbsp; &nbsp; - " + outSignal + " --> " + inSignal + "</nobr><br>"
251            string = string[:-4]
252            self.setToolTip(string)
253   
254            # print the text with the signals
255            self.caption = "\n".join([outSignal for (outSignal, inSignal) in self.getSignals()])
256            self.captionItem.setHtml("<center>%s</center>" % self.caption.replace("\n", "<br/>"))
257            self.updatePainterPath()
258
259    def hoverEnterEvent(self, event):
260        self.hoverState = True
261        self.update()
262   
263    def hoverLeaveEvent(self, event):
264        self.hoverState = False
265        self.update()
266       
267
268# #######################################
269# # CANVAS WIDGET
270# #######################################
271class CanvasWidget(QGraphicsRectItem):
272    def __init__(self, signalManager, scene, view, widgetInfo, defaultPic, canvasDlg, widgetSettings = {}):
273        # import widget class and create a class instance
274        m = __import__(widgetInfo.fileName)
275        self.instance = m.__dict__[widgetInfo.fileName].__new__(m.__dict__[widgetInfo.fileName], _owInfo=canvasDlg.settings["owInfo"],
276                                                                _owWarning = canvasDlg.settings["owWarning"], _owError=canvasDlg.settings["owError"],
277                                                                _owShowStatus = canvasDlg.settings["owShow"], _useContexts = canvasDlg.settings["useContexts"],
278                                                                _category = widgetInfo.category, _settingsFromSchema = widgetSettings)
279        self.instance.__init__(signalManager=signalManager)
280        self.instance.__dict__["widgetInfo"] = widgetInfo
281        self.isProcessing = 0   # is this widget currently processing signals
282        self.progressBarShown = 0
283        self.progressBarValue = -1
284        self.widgetSize = QSizeF(0, 0)
285        self.widgetState = {}
286        self.caption = widgetInfo.name
287        self.selected = False
288        self.inLines = []               # list of connected lines on input
289        self.outLines = []              # list of connected lines on output
290        self.icon = canvasDlg.getWidgetIcon(widgetInfo)
291       
292        self.instance.setProgressBarHandler(view.progressBarHandler)   # set progress bar event handler
293        self.instance.setProcessingHandler(view.processingHandler)
294        self.instance.setWidgetStateHandler(self.updateWidgetState)
295        self.instance.setEventHandler(canvasDlg.output.widgetEvents)
296        self.instance.setWidgetIcon(canvasDlg.getFullWidgetIconName(widgetInfo))
297        #self.instance.updateStatusBarState()
298
299        QGraphicsRectItem.__init__(self, None, None)
300        self.signalManager = signalManager
301        self.widgetInfo = widgetInfo
302        self.view = view
303        self.canvasDlg = canvasDlg
304        canvasPicsDir  = os.path.join(canvasDlg.canvasDir, "icons")
305        self.imageLeftEdge = QPixmap(os.path.join(canvasPicsDir,"leftEdge.png"))
306        self.imageRightEdge = QPixmap(os.path.join(canvasPicsDir,"rightEdge.png"))
307        self.imageLeftEdgeG = QPixmap(os.path.join(canvasPicsDir,"leftEdgeG.png"))
308        self.imageRightEdgeG = QPixmap(os.path.join(canvasPicsDir,"rightEdgeG.png"))
309        self.imageLeftEdgeR = QPixmap(os.path.join(canvasPicsDir,"leftEdgeR.png"))
310        self.imageRightEdgeR = QPixmap(os.path.join(canvasPicsDir,"rightEdgeR.png"))
311        self.shownLeftEdge, self.shownRightEdge = self.imageLeftEdge, self.imageRightEdge
312        self.imageFrame = QIcon(QPixmap(os.path.join(canvasPicsDir, "frame.png")))
313        self.edgeSize = QSizeF(self.imageLeftEdge.size())
314        self.resetWidgetSize()
315       
316        self.oldPos = self.pos()
317       
318        self.infoIcon = QGraphicsPixmapItem(self.canvasDlg.widgetIcons["Info"], self)
319        self.warningIcon = QGraphicsPixmapItem(self.canvasDlg.widgetIcons["Warning"], self)
320        self.errorIcon = QGraphicsPixmapItem(self.canvasDlg.widgetIcons["Error"], self)
321        self.infoIcon.hide()
322        self.warningIcon.hide()
323        self.errorIcon.hide()
324       
325        self.captionItem = QGraphicsTextItem(self)
326        self.captionItem.setHtml("<center>%s</center>" % self.caption)
327        self.captionItem.document().setTextWidth(min(self.captionItem.document().idealWidth(), 200))
328       
329        self.captionItem.setPos(-self.captionItem.boundingRect().width()/2.0 + self.widgetSize.width() / 2.0, self.widgetSize.height() + 2)
330        self.captionItem.setAcceptHoverEvents(False)
331       
332        # do we want to restore last position and size of the widget
333        if self.canvasDlg.settings["saveWidgetsPosition"]:
334            self.instance.restoreWidgetPosition()
335           
336        self.setAcceptHoverEvents(True)
337        self.hoverState = False
338        self.setFlags(QGraphicsItem.ItemIsSelectable)# | QGraphicsItem.ItemIsMovable)
339       
340        if scene is not None:
341            scene.addItem(self)
342           
343        self.setDropShadow()
344
345    setDropShadow = setDropShadow
346    getDropShadow = getDropShadow
347   
348    def resetWidgetSize(self):
349        size = self.canvasDlg.schemeIconSizeList[self.canvasDlg.settings['schemeIconSize']]
350        self.setRect(0,0, size, size)
351        self.widgetSize = QSizeF(size, size)
352        self.update()
353
354    # get the list of connected signal names
355    def getInConnectedSignalNames(self):
356        signals = []
357        for line in self.inLines:
358            for (outSignal, inSignal) in line.getSignals():
359                if inSignal not in signals: signals.append(inSignal)
360        return signals
361
362    # get the list of connected signal names
363    def getOutConnectedSignalNames(self):
364        signals = []
365        for line in self.outLines:
366            for (outSignal, inSignal) in line.getSignals():
367                if outSignal not in signals: signals.append(outSignal)
368        return signals
369
370    def remove(self):
371        self.hide()
372        self.errorIcon.hide()
373        self.warningIcon.hide()
374        self.infoIcon.hide()
375
376        # save settings
377        if (self.instance != None):
378            if self.canvasDlg.menuSaveSettings == 1 and not self.instance._settingsFromSchema:       
379                # save settings only if checked in the main menu, and the widget settings were not loaded from
380                # a schema file (i.e it is a new widget, this prevents the overriding of the the global .ini file)
381                try:
382                    self.instance.saveSettings()
383                except:
384                    print "Unable to save settings for %s widget" % (self.instance.captionTitle)
385                    type, val, traceback = sys.exc_info()
386                    sys.excepthook(type, val, traceback)  # we pretend that we handled the exception, so that it doesn't crash canvas
387            self.instance.close()
388            self.instance.linksOut.clear()      # this helps python to more quickly delete the unused objects
389            self.instance.linksIn.clear()
390            self.instance.setProgressBarHandler(None)   # set progress bar event handler
391            self.instance.setProcessingHandler(None)
392            self.instance.setWidgetStateHandler(None)
393            self.instance.setEventHandler(None)
394            self.instance.onDeleteWidget()      # this is a cleanup function that can take care of deleting some unused objects
395           
396            # Schedule the widget instance for deletion
397            self.instance.deleteLater()
398            self.instance = None
399           
400        self.prepareGeometryChange()
401       
402        if self.getDropShadow():
403            self.setGraphicsEffect(None)
404       
405        for child in self.childItems():
406            child.hide()
407            child.setParentItem(None)
408            self.scene().removeItem(child)
409       
410        self.hide()
411        self.scene().removeItem(self)
412       
413    def savePosition(self):
414        self.oldPos = self.pos()
415
416    def restorePosition(self):
417        self.setPos(self.oldPos)
418
419    def updateText(self, text):
420        self.caption = str(text)
421        self.prepareGeometryChange()
422        self.captionItem.setHtml("<center>%s</center>" % self.caption)
423        self.captionItem.document().adjustSize()
424        self.captionItem.document().setTextWidth(min(self.captionItem.document().idealWidth(), 200))
425       
426        self.captionItem.setPos(-self.captionItem.boundingRect().width()/2.0 + self.widgetSize.width() / 2.0, self.widgetSize.height() + 2)
427        self.updateTooltip()
428        self.update()
429
430    def updateWidgetState(self):
431        widgetState = self.instance.widgetState
432
433        self.infoIcon.hide()
434        self.warningIcon.hide()
435        self.errorIcon.hide()
436
437        yPos = - 21 - self.progressBarShown * 20
438        iconNum = sum([widgetState.get("Info", {}).values() != [],  widgetState.get("Warning", {}).values() != [], widgetState.get("Error", {}).values() != []])
439
440        if self.canvasDlg.settings["ocShow"]:        # if show icons is enabled in canvas options dialog
441            startX = (self.rect().width()/2) - ((iconNum*(self.canvasDlg.widgetIcons["Info"].width()+2))/2)
442            off  = 0
443            if len(widgetState.get("Info", {}).values()) > 0 and self.canvasDlg.settings["ocInfo"]:
444                off  = self.updateWidgetStateIcon(self.infoIcon, startX, yPos, widgetState["Info"])
445            if len(widgetState.get("Warning", {}).values()) > 0 and self.canvasDlg.settings["ocWarning"]:
446                off += self.updateWidgetStateIcon(self.warningIcon, startX+off, yPos, widgetState["Warning"])
447            if len(widgetState.get("Error", {}).values()) > 0 and self.canvasDlg.settings["ocError"]:
448                off += self.updateWidgetStateIcon(self.errorIcon, startX+off, yPos, widgetState["Error"])
449
450
451    def updateWidgetStateIcon(self, icon, x, y, stateDict):
452        icon.setPos(x,y)
453        icon.show()
454        icon.setToolTip(reduce(lambda x,y: x+'<br>'+y, stateDict.values()))
455        return icon.pixmap().width() + 3
456
457    # set coordinates of the widget
458    def setCoords(self, x, y):
459        if self.canvasDlg.settings["snapToGrid"]:
460            x = round(x/10)*10
461            y = round(y/10)*10
462        self.setPos(x, y)
463        self.updateWidgetState()
464       
465    def setPos(self, *args):
466        QGraphicsRectItem.setPos(self, *args)
467        for line in self.inLines + self.outLines:
468            line.updatePainterPath()
469           
470
471    # we have to increase the default bounding rect so that we also repaint the name of the widget and input/output boxes
472    def boundingRect(self):
473        rect = QRectF(QPointF(0, 0), self.widgetSize).adjusted(-11, -6, 11, 6)#.adjusted(-100, -100, 100, 100) #(-10-width, -4, +10+width, +25)
474        rect.setTop(rect.top() - 20 - 21) ## Room for progress bar and warning, error, info icons
475        if self.getDropShadow():
476            textRect = self.captionItem.boundingRect() ## Should work without this but for some reason if using graphics effects the text gets clipped
477            textRect.moveTo(self.captionItem.pos()) 
478            return rect.united(textRect)
479        else:
480            return rect
481
482    # is mouse position inside the left signal channel
483    def mouseInsideLeftChannel(self, pos):
484        if self.widgetInfo.inputs == []: return False
485
486        boxRect = QRectF(self.x()-self.edgeSize.width(), self.y() + (self.widgetSize.height()-self.edgeSize.height())/2, self.edgeSize.width(), self.edgeSize.height())
487        boxRect.adjust(-10,-10,5,10)       # enlarge the rectangle
488        if isinstance(pos, QPointF) and boxRect.contains(pos): return True
489        elif isinstance(pos, QRectF) and boxRect.intersects(pos): return True
490        else: return False
491
492    # is mouse position inside the right signal channel
493    def mouseInsideRightChannel(self, pos):
494        if self.widgetInfo.outputs == []: return False
495
496        boxRect = QRectF(self.x()+self.widgetSize.width(), self.y() + (self.widgetSize.height()-self.edgeSize.height())/2, self.edgeSize.width(), self.edgeSize.height())
497        boxRect.adjust(-5,-10,10,10)       # enlarge the rectangle
498        if isinstance(pos, QPointF) and boxRect.contains(pos): return True
499        elif isinstance(pos, QRectF) and boxRect.intersects(pos): return True
500        else: return False
501       
502    def canConnect(self, outWidget, inWidget, dynamic=False):
503        if outWidget == inWidget:
504            return
505       
506        canConnect = self.signalManager.canConnect(outWidget.instance, inWidget.instance, dynamic=dynamic)
507       
508#        outputs = [outWidget.instance.getOutputType(output.name) for output in outWidget.widgetInfo.outputs]
509#        inputs = [inWidget.instance.getInputType(input.name) for input in inWidget.widgetInfo.inputs]
510#        canConnect = 0
511#        for outtype in outputs:
512#            if any(issubclass(outtype, intype) for intype in inputs):
513#                canConnect = 1
514#                break
515#            elif dynamic and any(issubclass(intype, outtype) for intype in inputs):
516#                canConnect = 2
517#                break
518
519        if outWidget == self:
520            self.shownRightEdge = canConnect and self.imageRightEdgeG or self.imageRightEdgeR
521        else:
522            self.shownLeftEdge = canConnect and self.imageLeftEdgeG or self.imageLeftEdgeR
523
524    def resetLeftRightEdges(self):
525        self.shownLeftEdge = self.imageLeftEdge
526        self.shownRightEdge = self.imageRightEdge
527   
528   
529    # we know that the mouse was pressed inside a channel box. We only need to find
530    # inside which one it was
531    def getEdgePoint(self, pos):
532        if self.mouseInsideLeftChannel(pos):
533            return self.getLeftEdgePoint()
534        elif self.mouseInsideRightChannel(pos):
535            return self.getRightEdgePoint()
536
537    def getLeftEdgePoint(self):
538        return QPointF(self.x()+2- self.edgeSize.width(), self.y() + self.widgetSize.height()/2)
539
540    def getRightEdgePoint(self):
541        return QPointF(self.x()-2+ self.widgetSize.width() + self.edgeSize.width(), self.y() + self.widgetSize.height()/2)
542
543    def getDistToLeftEdgePoint(self, point):
544        p = self.getLeftEdgePoint()
545        diff = point-p
546        return math.sqrt(diff.x()**2 + diff.y()**2)
547   
548    def getDistToRightEdgePoint(self, point):
549        p = self.getRightEdgePoint()
550        diff = point-p
551        return math.sqrt(diff.x()**2 + diff.y()**2)
552
553
554    # draw the widget
555    def paint(self, painter, option, widget = None):
556        if self.isProcessing or self.isSelected() or getattr(self, "invalidPosition", False):
557            painter.setPen(QPen(QBrush(QColor(125, 162, 206, 192)), 1, Qt.SolidLine, Qt.RoundCap))
558            painter.setBrush(QBrush(QColor(217, 232, 252, 192)))
559            painter.drawRoundedRect(-10, -5, self.widgetSize.width()+20, self.widgetSize.height()+10, 5, 5)
560
561        if self.widgetInfo.inputs != []:
562            painter.drawPixmap(-self.edgeSize.width()+1, (self.widgetSize.height()-self.edgeSize.height())/2, self.shownLeftEdge)
563        if self.widgetInfo.outputs != []:
564            painter.drawPixmap(self.widgetSize.width()-2, (self.widgetSize.height()-self.edgeSize.height())/2, self.shownRightEdge)
565           
566        if self.hoverState:
567            color = QColor(125, 162, 206)
568            painter.setPen(Qt.NoPen)
569            painter.setBrush(color)
570            painter.drawRoundedRect(-2, -2, self.widgetSize.width() + 4, self.widgetSize.height() + 4, 5, 5)
571           
572        painter.drawPixmap(0,0, self.icon.pixmap(self.widgetSize.width(), self.widgetSize.height()))
573       
574        yPos = -22
575        if self.progressBarValue >= 0 and self.progressBarValue <= 100:
576            rect = QRectF(0, yPos, self.widgetSize.width(), 16)
577            painter.setPen(QPen(QColor(0,0,0)))
578            painter.setBrush(QBrush(QColor(255,255,255)))
579            painter.drawRect(rect)
580
581            painter.setBrush(QBrush(QColor(0,128,255)))
582            painter.drawRect(QRectF(0, yPos, self.widgetSize.width()*self.progressBarValue/100., 16))
583            painter.drawText(rect, Qt.AlignCenter, "%d %%" % (self.progressBarValue))
584
585
586    def addOutLine(self, line):
587        self.outLines.append(line)
588
589    def addInLine(self,line):
590        self.inLines.append(line)
591
592    def removeLine(self, line):
593        if line in self.inLines:
594            self.inLines.remove(line)
595        elif line in self.outLines:
596            self.outLines.remove(line)
597        else:
598            print "Orange Canvas: Error. Unable to remove line"
599
600        self.updateTooltip()
601
602
603    def setAllLinesFinished(self, finished):
604        for line in self.inLines: line.finished = finished
605        for line in self.outLines: line.finished = finished
606
607
608    def updateTooltip(self):
609        string = "<nobr><b>" + self.caption + "</b></nobr><hr>Inputs:<br>"
610
611        if self.widgetInfo.inputs == []: string += "&nbsp; &nbsp; None<br>"
612        else:
613            for signal in self.widgetInfo.inputs:
614                widgets = self.signalManager.getLinkWidgetsIn(self.instance, signal.name)
615                if len(widgets) > 0:
616                    string += "<nobr> &nbsp; &nbsp; - <b>" + signal.name + "</b> (from "
617                    for i in range(len(widgets)-1):
618                        string += self.view.doc.getWidgetCaption(widgets[i]) + ", "
619                    string += self.view.doc.getWidgetCaption(widgets[-1]) + ")</nobr><br>"
620                else:
621                    string += "<nobr> &nbsp; &nbsp; - " + signal.name + "</nobr><br>"
622
623        string = string[:-4]
624        string += "<hr>Outputs:<br>"
625        if self.widgetInfo.outputs == []: string += "&nbsp; &nbsp; None<br>"
626        else:
627            for signal in self.widgetInfo.outputs:
628                widgets = self.signalManager.getLinkWidgetsOut(self.instance, signal.name)
629                if len(widgets) > 0:
630                    string += "<nobr> &nbsp; &nbsp; - <b>" + signal.name + "</b> (to "
631                    for i in range(len(widgets)-1):
632                        string += self.view.doc.getWidgetCaption(widgets[i]) + ", "
633                    string += self.view.doc.getWidgetCaption(widgets[-1]) + ")</nobr><br>"
634                else:
635                    string += "<nobr> &nbsp; &nbsp; - " + signal.name + "</nobr><br>"
636        string = string[:-4]
637        self.setToolTip(string)
638
639    def setProgressBarValue(self, value):
640        self.progressBarValue = value
641        if value < 0 or value > 100:
642            self.updateWidgetState()
643        self.update()
644
645    def setProcessing(self, value):
646        self.isProcessing = value
647        self.update()
648
649    def hoverEnterEvent(self, event):
650        self.hoverState = True
651        self.update()
652        return QGraphicsRectItem.hoverEnterEvent(self, event)
653       
654    def hoverLeaveEvent(self, event):
655        self.hoverState = False
656        self.update()
657        return QGraphicsRectItem.hoverLeaveEvent(self, event)       
658
659class MyCanvasText(QGraphicsSimpleTextItem):
660    def __init__(self, canvas, text, x, y, flags=Qt.AlignLeft, bold=0, show=1):
661        QGraphicsSimpleTextItem.__init__(self, text, None, canvas)
662        self.setPos(x,y)
663        self.setPen(QPen(Qt.black))
664        self.flags = flags
665        if bold:
666            font = self.font();
667            font.setBold(1);
668            self.setFont(font)
669        if show:
670            self.show()
671
672    def paint(self, painter, option, widget = None):
673        #painter.resetMatrix()
674        painter.setPen(self.pen())
675        painter.setFont(self.font())
676
677        xOff = 0; yOff = 0
678        rect = painter.boundingRect(QRectF(0,0,2000,2000), self.flags, self.text())
679        if self.flags & Qt.AlignHCenter: xOff = rect.width()/2.
680        elif self.flags & Qt.AlignRight: xOff = rect.width()
681        if self.flags & Qt.AlignVCenter: yOff = rect.height()/2.
682        elif self.flags & Qt.AlignBottom:yOff = rect.height()
683        #painter.drawText(self.pos().x()-xOff, self.pos().y()-yOff, rect.width(), rect.height(), self.flags, self.text())
684        painter.drawText(-xOff, -yOff, rect.width(), rect.height(), self.flags, self.text())
685       
Note: See TracBrowser for help on using the repository browser.