source: orange/Orange/OrangeCanvas/orngCanvasItems.py @ 9671:a7b056375472

Revision 9671:a7b056375472, 28.1 KB checked in by anze <anze.staric@…>, 2 years ago (diff)

Moved orange to Orange (part 2)

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