source: orange/Orange/OrangeWidgets/OWTreeViewer2D.py @ 9671:a7b056375472

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

Moved orange to Orange (part 2)

Line 
1import orange, orngTree, OWGUI, OWColorPalette
2from OWWidget import *
3
4from PyQt4.QtCore import *
5from PyQt4.QtGui import *
6
7DefDroppletRadiust=7
8DefNodeWidth=30
9DefNodeHeight=20
10DefDroppletBrush=QBrush(Qt.darkGray)
11
12class graph_node(object):
13    def __init__(self, *args, **kwargs):
14        self.edges = kwargs.get("edges", set())
15       
16    def graph_edges(self):
17        return self.edges
18   
19    def graph_add_edge(self, edge):
20        self.edges.add(edge)
21       
22    def __iter__(self):
23        for edge in self.edges:
24            yield edge.node2
25           
26    def graph_nodes(self, type=1):
27        pass
28           
29class graph_edge(object):
30       
31    def __init__(self, node1=None, node2=None, type=1):
32        self.node1 = node1
33        self.node2 = node2
34        self.type = type
35        node1.graph_add_edge(self)
36        node2.graph_add_edge(self)
37       
38class GraphicsDroplet(QGraphicsEllipseItem):
39   
40    def __init__(self, *args):
41        QGraphicsEllipseItem.__init__(self, *args)
42        self.setAcceptHoverEvents(True)
43        self.setAcceptedMouseButtons(Qt.LeftButton)
44        self.setBrush(QBrush(Qt.gray))
45       
46    def hoverEnterEvent(self, event):
47        QGraphicsEllipseItem.hoverEnterEvent(self, event)
48        self.setBrush(QBrush(QColor(100, 100, 100)))
49        self.update()
50       
51    def hoverLeaveEvent(self, event):
52        QGraphicsEllipseItem.hoverLeaveEvent(self, event)
53        self.setBrush(QBrush(QColor(200, 200, 200)))
54        self.update()
55       
56    def mousePressEvent(self, event):
57        QGraphicsEllipseItem.mousePressEvent(self, event)
58        self.parentItem().setOpen(not self.parentItem().isOpen)
59        if self.scene():
60            self.scene().fixPos()
61       
62class TextTreeNode(QGraphicsTextItem, graph_node):
63   
64    borderRadius = pyqtProperty("int",
65                lambda self: getattr(self, "_borderRadius", 0),
66                lambda self, val: (setattr(self, "_borderRadius", val), self.update()) and None,
67                doc="Rounded rect's border radius"
68                )
69    backgroundBrush = pyqtProperty("QBrush",
70                lambda self: getattr(self, "_backgroundBrush", getattr(self.scene(), "defaultItemBrush", Qt.NoBrush)),
71                lambda self, brush: (setattr(self, "_backgroundBrush", brush), self.update()) and None,
72                doc="Background brush"
73                )
74    truncateText = pyqtProperty("bool",
75                lambda self: getattr(self, "_truncateText", False),
76                lambda self, val: (setattr(self, "_truncateText", val), self.updateContents()),
77                doc="Truncate text")
78   
79    def __init__(self, tree, parent, *args, **kwargs):
80        QGraphicsTextItem.__init__(self, *args)
81        graph_node.__init__(self, **kwargs)
82        self.tree = tree
83        self.parent = parent
84        font = self.font()
85        font.setPointSize(10)
86        self.setFont(font)
87        self.droplet = GraphicsDroplet(-5, 0, 10, 10, self, self.scene())
88       
89        self.droplet.setPos(self.rect().center().x(), self.rect().height())
90       
91        self.connect(self.document(), SIGNAL("contentsChanged()"), self.updateContents)
92        self.isOpen = True
93        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
94       
95    def setHtml(self, html):
96        if qVersion() < "4.5":
97            html = html.replace("<hr>", "<hr width=200>") #bug in Qt4.4 (need width = 200)
98        return QGraphicsTextItem.setHtml(self, "<body>" + html + "</body>") 
99   
100    def updateContents(self):
101        if getattr(self, "_rect", QRectF()).isValid() and not self.truncateText:
102            self.setTextWidth(self._rect.width())
103        else:
104            self.setTextWidth(-1)
105            self.setTextWidth(self.document().idealWidth())
106        self.droplet.setPos(self.rect().center().x(), self.rect().height())
107        self.droplet.setVisible(bool(self.branches))
108       
109    def setRect(self, rect):
110        self.prepareGeometryChange()
111        rect = QRectF() if rect is None else rect
112        self._rect = rect
113        self.updateContents()
114        self.update()
115       
116    def shape(self):
117        path = QPainterPath()
118        path.addRect(self.boundingRect())
119        return path
120   
121    def rect(self):
122        if self.truncateText and getattr(self, "_rect", QRectF()).isValid():
123            return self._rect
124        else:
125            return QRectF(QPointF(0,0), self.document().size()) | getattr(self, "_rect", QRectF(0, 0, 1, 1))
126       
127    def boundingRect(self):
128        if self.truncateText and getattr(self, "_rect", QRectF()).isValid():
129            return self._rect
130        else:
131            return QGraphicsTextItem.boundingRect(self)
132   
133    @property 
134    def branches(self):
135        return [edge.node2 for edge in self.graph_edges() if edge.node1 is self]
136   
137    def paint(self, painter, option, widget=0):
138        painter.save()
139        painter.setBrush(self.backgroundBrush)
140        rect = self.rect()
141        painter.drawRoundedRect(rect, self.borderRadius, self.borderRadius)
142        painter.restore()
143        painter.setClipRect(rect)
144        return QGraphicsTextItem.paint(self, painter, option, widget)
145       
146def graph_traverse_bf(nodes, level=None, test=None):
147    visited = set()
148    queue = list(nodes)
149    while queue:
150        node = queue.pop(0)
151        if node not in visited:
152            yield node
153            visited.add(node)
154            if not test or test(node):
155                queue.extend(list(node))
156               
157class GraphicsNode(TextTreeNode):
158    def setOpen(self, open, level=1):
159        self.isOpen = open
160        for node in graph_traverse_bf(self, test=lambda node: node.isOpen):
161            if node is not self:
162                node.setVisible(open)
163               
164    def itemChange(self, change, value):
165        if change == QGraphicsItem.ItemPositionHasChanged:
166            self.updateEdge()
167        elif change == QGraphicsItem.ItemVisibleHasChanged:
168            self.updateEdge()
169           
170        return TextTreeNode.itemChange(self, change, value)
171   
172    def updateEdge(self):
173        for edge in self.edges:
174            if edge.node1 is self:
175                QTimer.singleShot(0, edge.updateEnds)
176            elif edge.node2 is self:
177                edge.setVisible(self.isVisible())
178               
179    def edgeInPoint(self, edge):
180        return edge.mapFromItem(self, QPointF(self.rect().center().x(), self.rect().y()))
181
182    def edgeOutPoint(self, edge):
183        return edge.mapFromItem(self.droplet, self.droplet.rect().center())
184   
185    def paint(self, painter, option, widget=0):
186        if self.isSelected():
187            option.state = option.state.__xor__(QStyle.State_Selected)
188        if self.isSelected():
189            rect = self.rect()
190            painter.save()
191#            painter.setBrush(QBrush(QColor(100, 0, 255, 100)))
192            painter.setBrush(QBrush(QColor(125, 162, 206, 192)))
193            painter.drawRoundedRect(rect.adjusted(-4, -4, 4, 4), self.borderRadius, self.borderRadius)
194            painter.restore()
195        TextTreeNode.paint(self, painter, option, widget)
196       
197    def boundingRect(self):
198        return TextTreeNode.boundingRect(self).adjusted(-5, -5, 5, 5)
199           
200    def mousePressEvent(self, event):
201        return TextTreeNode.mousePressEvent(self, event)
202   
203class GraphicsEdge(QGraphicsLineItem, graph_edge):
204    def __init__(self, *args, **kwargs):
205        QGraphicsLineItem.__init__(self, *args)
206        graph_edge.__init__(self, **kwargs)
207        self.setZValue(-30)
208       
209    def updateEnds(self):
210        try:
211            self.prepareGeometryChange()
212            self.setLine(QLineF(self.node1.edgeOutPoint(self), self.node2.edgeInPoint(self)))
213        except RuntimeError: # this gets called through QTimer.singleShot and might already be deleted by Qt
214            pass 
215
216class TreeGraphicsView(QGraphicsView):
217    def __init__(self, master, scene, *args):
218        QGraphicsView.__init__(self, scene, *args)
219#        try:
220#            import PyQt4.QtOpenGL as gl
221#            fmt = gl.QGLFormat()
222#            fmt.setSampleBuffers(True)
223#            fmt.setSamples(32)
224#            print fmt.sampleBuffers()
225#            self.setViewport(gl.QGLWidget(fmt, self))
226#        except Exception, ex:
227#            print ex
228        self.viewport().setMouseTracking(True)
229        self.setFocusPolicy(Qt.WheelFocus)
230        self.setRenderHint(QPainter.Antialiasing)
231        self.setRenderHint(QPainter.TextAntialiasing)
232        self.setRenderHint(QPainter.HighQualityAntialiasing)
233
234    def resizeEvent(self, event):
235        QGraphicsView.resizeEvent(self, event)
236        self.emit(SIGNAL("resized(QSize)"), self.size())
237
238class TreeGraphicsScene(QGraphicsScene):
239    def __init__(self, master, *args):
240        QGraphicsScene.__init__(self, *args)
241        self.HSpacing=10
242        self.VSpacing=10
243        self.master=master
244        self.nodeList=[]
245        self.edgeList=[]
246
247    def fixPos(self, node=None, x=10, y=10):
248        self.gx=x
249        self.gy=y
250        if not node:
251            if self.nodes():
252                node = [node for node in self.nodes() if not node.parent][0]
253            else:
254                return
255        if not x or not y: x, y= self.HSpacing, self.VSpacing
256        self._fixPos(node,x,y)
257       
258        self.setSceneRect(reduce(QRectF.united, [item.sceneBoundingRect() for item in self.items() if item.isVisible()], QRectF(0, 0, 10, 10)).adjusted(0, 0, 100, 100))
259#        print self.sceneRect()
260        self.update()
261       
262    def _fixPos(self, node, x, y):
263        ox=x
264       
265        def bRect(node):
266            return node.boundingRect() | node.childrenBoundingRect()
267        if node.branches and node.isOpen:
268            for n in node.branches:
269                (x,ry)=self._fixPos(n,x,y+self.VSpacing + bRect(node).height())
270            x=(node.branches[0].pos().x() + node.branches[-1].pos().x())/2
271#            print x,y
272            node.setPos(x,y)
273            for e in node.edges:
274                e.updateEnds()
275        else:
276#            print self.gx, y
277            node.setPos(self.gx,y)
278            self.gx+=self.HSpacing + bRect(node).width()
279            x+=self.HSpacing + bRect(node).width()
280            self.gy=max([y,self.gy])
281
282        return (x,y)
283
284    def mouseMoveEvent(self,event):
285        return QGraphicsScene.mouseMoveEvent(self, event)
286
287    def mousePressEvent(self, event):
288        return QGraphicsScene.mousePressEvent(self, event)
289   
290    def edges(self):
291        return [item for item in self.items() if isinstance(item, graph_edge)]
292   
293    def nodes(self):
294        return [item for item in self.items() if isinstance(item, graph_node)]     
295
296class TreeNavigator(QGraphicsView):
297
298    def __init__(self, masterView, *args):
299        QGraphicsView.__init__(self)
300        self.masterView = masterView
301        self.setScene(self.masterView.scene())
302        self.connect(self.scene(), SIGNAL("sceneRectChanged(QRectF)"), self.updateSceneRect)
303        self.connect(self.masterView, SIGNAL("resized(QSize)"), self.updateView)
304        self.setRenderHint(QPainter.Antialiasing)
305
306    def mousePressEvent(self, event):
307        if event.buttons() & Qt.LeftButton:
308            self.masterView.centerOn(self.mapToScene(event.pos()))
309            self.updateView()
310        return QGraphicsView.mousePressEvent(self, event)
311
312    def mouseMoveEvent(self, event):
313        if event.buttons() & Qt.LeftButton:
314            self.masterView.centerOn(self.mapToScene(event.pos()))
315            self.updateView()
316        return QGraphicsView.mouseMoveEvent(self, event)
317
318    def resizeEvent(self, event):
319        QGraphicsView.resizeEvent(self, event)
320        self.updateView()
321#
322    def resizeView(self):
323        self.updateView()
324
325    def updateSceneRect(self, rect):
326        QGraphicsView.updateSceneRect(self, rect)
327        self.updateView()
328       
329    def updateView(self, *args):
330        if self.scene():
331            self.fitInView(self.scene().sceneRect())
332
333    def paintEvent(self, event):
334        QGraphicsView.paintEvent(self, event)
335        painter = QPainter(self.viewport())
336        painter.setBrush(QColor(100, 100, 100, 100))
337        painter.setRenderHints(self.renderHints())
338        painter.drawPolygon(self.viewPolygon())
339       
340    def viewPolygon(self):
341        return self.mapFromScene(self.masterView.mapToScene(self.masterView.viewport().rect()))
342
343
344class OWTreeViewer2D(OWWidget):
345    settingsList = ["ZoomAutoRefresh", "AutoArrange", "ToolTipsEnabled",
346                    "Zoom", "VSpacing", "HSpacing", "MaxTreeDepth", "MaxTreeDepthB",
347                    "LineWidth", "LineWidthMethod",
348                    "MaxNodeWidth", "LimitNodeWidth", "NodeInfo", "NodeColorMethod",
349                    "TruncateText"]
350
351    def __init__(self, parent=None, signalManager = None, name='TreeViewer2D'):
352        OWWidget.__init__(self, parent, signalManager, name, wantGraph=True)
353        self.root = None
354        self.selectedNode = None
355
356        self.inputs = [("Classification Tree", orange.TreeClassifier, self.ctree)]
357        self.outputs = [("Examples", ExampleTable)]
358
359        #set default settings
360        self.ZoomAutoRefresh = 0
361        self.AutoArrange = 0
362        self.ToolTipsEnabled = 1
363        self.MaxTreeDepth = 5; self.MaxTreeDepthB = 0
364        self.LineWidth = 5; self.LineWidthMethod = 2
365        self.NodeSize = 5
366        self.MaxNodeWidth = 150
367        self.LimitNodeWidth = True
368        self.NodeInfo = [0, 1]
369
370        self.Zoom = 5
371        self.VSpacing = 5; self.HSpacing = 5
372        self.TruncateText = 1
373       
374        self.loadSettings()
375        self.NodeInfo.sort()
376
377# Changed when the GUI was simplified - added here to override any saved settings
378        self.VSpacing = 1; self.HSpacing = 1
379        self.ToolTipsEnabled = 1
380        self.LineWidth = 15  # Also reset when the LineWidthMethod is changed!
381       
382        # GUI definition
383#        self.tabs = OWGUI.tabWidget(self.controlArea)
384
385        # GENERAL TAB
386        # GeneralTab = OWGUI.createTabPage(self.tabs, "General")
387#        GeneralTab = TreeTab = OWGUI.createTabPage(self.tabs, "Tree")
388#        NodeTab = OWGUI.createTabPage(self.tabs, "Node")
389
390        GeneralTab = NodeTab = TreeTab = self.controlArea
391       
392        self.infBox = OWGUI.widgetBox(GeneralTab, 'Info', sizePolicy = QSizePolicy(QSizePolicy.Minimum , QSizePolicy.Fixed ), addSpace=True)
393        self.infoa = OWGUI.widgetLabel(self.infBox, 'No tree.')
394        self.infob = OWGUI.widgetLabel(self.infBox, " ")
395
396        self.sizebox = OWGUI.widgetBox(GeneralTab, "Size", addSpace=True)
397        OWGUI.hSlider(self.sizebox, self, 'Zoom', label='Zoom', minValue=1, maxValue=10, step=1,
398                      callback=self.toggleZoomSlider, ticks=1)
399        OWGUI.separator(self.sizebox)
400       
401        cb, sb = OWGUI.checkWithSpin(self.sizebox, self, "Max node width:", 50, 200, "LimitNodeWidth", "MaxNodeWidth",
402                                     tooltip="Limit the width of tree nodes",
403                                     checkCallback=self.toggleNodeSize,
404                                     spinCallback=self.toggleNodeSize,
405                                     step=10)
406        b = OWGUI.checkBox(OWGUI.indentedBox(self.sizebox, sep=OWGUI.checkButtonOffsetHint(cb)), self, "TruncateText", "Truncate text", callback=self.toggleTruncateText)
407        cb.disables.append(b)
408        cb.makeConsistent() 
409
410        OWGUI.checkWithSpin(self.sizebox, self, 'Max tree depth:', 1, 20, 'MaxTreeDepthB', "MaxTreeDepth",
411                            tooltip='Defines the depth of the tree displayed',
412                            checkCallback=self.toggleTreeDepth,
413                            spinCallback=self.toggleTreeDepth)
414       
415       
416        self.edgebox = OWGUI.widgetBox(GeneralTab, "Edge Widths", addSpace=True)
417        OWGUI.comboBox(self.edgebox, self,  'LineWidthMethod',
418                                items=['Equal width', 'Root node', 'Parent node'],
419                                callback=self.toggleLineWidth)
420        # Node information
421        grid = QGridLayout()
422        grid.setContentsMargins(*self.controlArea.layout().getContentsMargins())
423       
424        navButton = OWGUI.button(self.controlArea, self, "Navigator", self.toggleNavigator, debuggingEnabled = 0, addToLayout=False)
425#        findbox = OWGUI.widgetBox(self.controlArea, orientation = "horizontal")
426        self.centerRootButton=OWGUI.button(self.controlArea, self, "Find Root", addToLayout=False,
427                                           callback=lambda :self.rootNode and \
428                                           self.sceneView.centerOn(self.rootNode.x(), self.rootNode.y()))
429        self.centerNodeButton=OWGUI.button(self.controlArea, self, "Find Selected", addToLayout=False,
430                                           callback=lambda :self.selectedNode and \
431                                           self.sceneView.centerOn(self.selectedNode.scenePos()))
432        grid.addWidget(navButton, 0, 0, 1, 2)
433        grid.addWidget(self.centerRootButton, 1, 0)
434        grid.addWidget(self.centerNodeButton, 1, 1)
435        self.leftWidgetPart.layout().insertLayout(1, grid)
436       
437        self.NodeTab=NodeTab
438        self.TreeTab=TreeTab
439        self.GeneralTab=GeneralTab
440#        OWGUI.rubber(NodeTab)
441        self.rootNode=None
442        self.tree=None
443        self.resize(800, 500)
444       
445        self.connect(self.graphButton, SIGNAL("clicked()"), self.saveGraph)
446
447    def sendReport(self):
448        from PyQt4.QtSvg import QSvgGenerator
449        if self.tree:
450            self.reportSection("Tree")
451            urlfn, filefn = self.getUniqueImageName(ext=".svg")
452            svg = QSvgGenerator()
453            svg.setFileName(filefn)
454            ssize = self.scene.sceneRect().size()
455            w, h = ssize.width(), ssize.height()
456            fact = 600/w
457            svg.setSize(QSize(600, h*fact))
458            painter = QPainter()
459            painter.begin(svg)
460            self.scene.render(painter)
461            painter.end()
462       
463#            buffer = QPixmap(QSize(600, h*fact))
464#            painter.begin(buffer)
465#            painter.fillRect(buffer.rect(), QBrush(QColor(255, 255, 255)))
466#            self.scene.render(painter)
467#            painter.end()
468#            self.reportImage(lambda filename: buffer.save(filename, os.path.splitext(filename)[1][1:]))
469            from OWDlgs import OWChooseImageSizeDlg
470            self.reportImage(OWChooseImageSizeDlg(self.scene).saveImage)
471            self.reportRaw('<!--browsercode<br/>(Click <a href="%s">here</a> to view or download this image in a scalable vector format)-->' % urlfn)
472            #self.reportObject(self.svg_type, urlfn, width="600", height=str(h*fact))
473
474    def toggleZoomSlider(self):
475        k = 0.0028 * (self.Zoom ** 2) + 0.2583 * self.Zoom + 1.1389
476        self.sceneView.setTransform(QTransform().scale(k/2, k/2))
477        self.scene.update()
478
479    def toggleVSpacing(self):
480        self.rescaleTree()
481        self.scene.fixPos(self.rootNode,10,10)
482        self.scene.update()
483
484    def toggleHSpacing(self):
485        self.rescaleTree()
486        self.scene.fixPos(self.rootNode,10,10)
487        self.scene.update()
488
489    def toggleTreeDepth(self):
490        self.walkupdate(self.rootNode)
491        self.scene.fixPos(self.rootNode,10,10)
492        self.scene.update()
493
494    def toggleLineWidth(self):
495        for edge in self.scene.edges():
496            if self.LineWidthMethod==0:
497                width=5 # self.LineWidth
498            elif self.LineWidthMethod == 1:
499                width = (edge.node2.tree.distribution.cases/self.tree.distribution.cases) * 20 # self.LineWidth
500            elif self.LineWidthMethod == 2:
501                width = (edge.node2.tree.distribution.cases/edge.node1.tree.distribution.cases) * 10 # self.LineWidth
502
503            edge.setPen(QPen(Qt.gray, width, Qt.SolidLine, Qt.RoundCap))
504        self.scene.update()
505       
506    def toggleNodeSize(self):
507        pass
508   
509    def toggleTruncateText(self):
510        for n in self.scene.nodes():
511            n.truncateText = self.TruncateText
512        self.scene.fixPos(self.rootNode, 10, 10)
513
514    def toggleNavigator(self):
515        self.navWidget.setHidden(not self.navWidget.isHidden())
516
517    def activateLoadedSettings(self):
518        if not self.tree:
519            return
520        self.rescaleTree()
521        self.scene.fixPos(self.rootNode,10,10)
522        self.scene.update()
523        self.toggleTreeDepth()
524        self.toggleLineWidth()
525#        self.toggleNodeSize()
526
527    def ctree(self, tree=None):
528        self.clear()
529        if not tree:
530            self.centerRootButton.setDisabled(1)
531            self.centerNodeButton.setDisabled(0)
532            self.infoa.setText('No tree.')
533            self.infob.setText('')
534            self.tree=None
535            self.rootNode = None
536        else:
537            self.tree=tree.tree
538            self.infoa.setText('Number of nodes: ' + str(orngTree.countNodes(tree)))
539            self.infob.setText('Number of leaves: ' + str(orngTree.countLeaves(tree)))
540            if hasattr(self.scene, "colorPalette"):
541                self.scene.colorPalette.setNumberOfColors(len(self.tree.distribution))
542#            self.scene.setDataModel(GraphicsTree(self.tree))
543            self.rootNode=self.walkcreate(self.tree, None)
544#            self.scene.addItem(self.rootNode)
545            self.scene.fixPos(self.rootNode,self.HSpacing,self.VSpacing)
546            self.activateLoadedSettings()
547            self.sceneView.centerOn(self.rootNode.x(), self.rootNode.y())
548            self.updateNodeToolTips()
549            self.centerRootButton.setDisabled(0)
550            self.centerNodeButton.setDisabled(1)
551
552        self.scene.update()
553
554    def walkcreate(self, tree, parent=None, level=0):
555        node = GraphicsNode(tree, parent, None, self.scene)
556        node.borderRadius = 10
557        if parent:
558            parent.graph_add_edge(GraphicsEdge(None, self.scene, node1=parent, node2=node))
559        if tree.branches:
560            for i in range(len(tree.branches)):
561                if tree.branches[i]:
562                    self.walkcreate(tree.branches[i],node,level+1)
563        return node
564
565    def walkupdate(self, node, level=0):
566        if not node: return
567        if self.MaxTreeDepthB and self.MaxTreeDepth<=level+1:
568            node.setOpen(False)
569            return
570        else:
571            node.setOpen(True,1)
572        for n in node.branches:
573            self.walkupdate(n,level+1)
574
575    def clear(self):
576        self.tree=None
577        self.scene.clear()
578
579    def updateNodeToolTips(self):
580       
581        for node in self.scene.nodes():
582            node.setToolTip(self.nodeToolTip(node) if self.ToolTipsEnabled else "")
583           
584    def nodeToolTip(self, tree):
585        return "tree node"
586   
587    def rescaleTree(self):
588        NodeHeight = DefNodeHeight
589        NodeWidth = DefNodeWidth * ((self.NodeSize -1) * (1.5 / 9.0) + 0.5)
590        k = 1.0
591        self.scene.VSpacing=int(NodeHeight*k*(0.3+self.VSpacing*0.15))
592        self.scene.HSpacing=int(NodeWidth*k*(0.3+self.HSpacing*0.20))
593        for r in self.scene.nodeList:
594            r.setRect(r.rect().x(), r.rect().y(), int(NodeWidth*k), int(NodeHeight*k))
595       
596        self.scene.fixPos() #self.rootNode, 10, 10)
597
598    def updateSelection(self):
599        self.selectedNode = (self.scene.selectedItems() + [None])[0]
600        self.centerNodeButton.setDisabled(not self.selectedNode)
601        self.send("Data", self.selectedNode.tree.examples if self.selectedNode else None)
602
603    def saveGraph(self, fileName = None):
604        from OWDlgs import OWChooseImageSizeDlg
605        dlg = OWChooseImageSizeDlg(self.scene, [("Save as Dot Tree File (.dot)", self.saveDot)], parent=self)
606        dlg.exec_()
607       
608    def saveDot(self, filename=None):
609        if filename==None:
610            filename = str(QFileDialog.getSaveFileName(self, "Save to ...", "tree.dot", "Dot Tree File (.DOT)"))
611            if not filename:
612                return
613        orngTree.printDot(self.tree, filename)
614       
615class OWDefTreeViewer2D(OWTreeViewer2D):
616    def __init__(self, parent=None, signalManager = None, name='DefTreeViewer2D'):
617        OWTreeViewer2D.__init__(self, parent, signalManager, name)
618        self.settingsList=self.settingsList+["ShowPie"]
619
620        self.scene = TreeGraphicsScene(self)
621        self.sceneView = TreeGraphicsView(self, self.scene, self.mainArea)
622        self.mainArea.layout().addWidget(self.sceneView)
623#        self.scene.setSceneRect(0,0,800,800)
624        self.navWidget = QWidget(None)
625        self.navWidget.setLayout(QVBoxLayout(self.navWidget))
626        scene = TreeGraphicsScene(self.navWidget)
627        self.treeNav = TreeNavigator(self.sceneView)
628#        self.treeNav.setScene(scene)
629        self.navWidget.layout().addWidget(self.treeNav)
630#        self.sceneView.setNavigator(self.treeNav)
631        self.navWidget.resize(400,400)
632#        OWGUI.button(self.TreeTab,self,"Navigator",self.toggleNavigator)
633
634if __name__=="__main__":
635    a = QApplication(sys.argv)
636    ow = OWDefTreeViewer2D()
637
638    #data = orange.ExampleTable('../../doc/datasets/voting.tab')
639    data = orange.ExampleTable(r"..//doc//datasets//zoo.tab")
640    data = orange.ExampleTable(r"..//doc//datasets//iris.tab")
641    tree = orange.TreeLearner(data, storeExamples = 1)
642    ow.activateLoadedSettings()
643    ow.ctree(None)
644    ow.ctree(tree)
645
646    # here you can test setting some stuff
647    ow.show()
648    a.exec_()
649    ow.saveSettings()
650
Note: See TracBrowser for help on using the repository browser.