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

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

Moved orange to Orange (part 2)

Line 
1import os
2from OWBaseWidget import *
3import OWGUI
4
5_have_qwt = True
6try:
7    from PyQt4.Qwt5 import *
8except ImportError:
9    _have_qwt = False
10
11_have_gl = True
12try:
13    from PyQt4.QtOpenGL import QGLWidget
14except ImportError:
15    _have_gl = False
16
17from PyQt4.QtGui import QGraphicsScene, QGraphicsView
18from PyQt4.QtSvg import *
19from ColorPalette import *
20import OWQCanvasFuncts
21
22class OWChooseImageSizeDlg(OWBaseWidget):
23    settingsList = ["selectedSize", "customX", "customY", "lastSaveDirName", "penWidthFactor"]
24    def __init__(self, graph, extraButtons = [], defaultName="graph", parent=None):
25        OWBaseWidget.__init__(self, parent, None, "Image settings", modal = TRUE, resizingEnabled = 0)
26
27        self.graph = graph
28        self.selectedSize = 0
29        self.customX = 400
30        self.customY = 400
31        self.saveAllSizes = 0
32        self.penWidthFactor = 1
33        self.lastSaveDirName = "./"
34        self.defaultName = defaultName
35
36        self.loadSettings()
37
38        self.setLayout(QVBoxLayout(self))
39        self.space = OWGUI.widgetBox(self)
40        self.layout().setMargin(8)
41        #self.layout().addWidget(self.space)
42
43        box = OWGUI.widgetBox(self.space, "Image Size")
44
45        global _have_qwt
46        if _have_qwt and isinstance(graph, QwtPlot):
47            size = OWGUI.radioButtonsInBox(box, self, "selectedSize", ["Current size", "400 x 400", "600 x 600", "800 x 800", "Custom:"], callback = self.updateGUI)
48            self.customXEdit = OWGUI.lineEdit(OWGUI.indentedBox(box), self, "customX", "Width: ", orientation = "horizontal", valueType = int)
49            self.customYEdit = OWGUI.lineEdit(OWGUI.indentedBox(box), self, "customY", "Height:", orientation = "horizontal", valueType = int)
50            OWGUI.comboBoxWithCaption(self.space, self, "penWidthFactor", label = 'Factor:   ', box = " Pen width multiplication factor ",  tooltip = "Set the pen width factor for all curves in the plot\n(Useful for example when the lines in the plot look to thin)\nDefault: 1", sendSelectedValue = 1, valueType = int, items = range(1,20))
51        elif isinstance(graph, QGraphicsScene) or isinstance(graph, QGraphicsView) or (_have_gl and isinstance(graph, QGLWidget)):
52            OWGUI.widgetLabel(box, "Image size will be set automatically.")
53
54        box = OWGUI.widgetBox(self.space, 1)
55        #self.printButton =          OWGUI.button(self.space, self, "Print", callback = self.printPic)
56        self.saveImageButton =      OWGUI.button(box, self, "Save Image", callback = self.saveImage)
57        if not (_have_gl and isinstance(graph, QGLWidget)):
58            self.saveMatplotlibButton = OWGUI.button(box, self, "Save Graph as matplotlib Script", callback = self.saveToMatplotlib)
59        for (text, funct) in extraButtons:
60            butt = OWGUI.button(box, self, text, callback = funct)
61            self.connect(butt, SIGNAL("clicked()"), self.accept)        # also connect the button to accept so that we close the dialog
62        OWGUI.button(box, self, "Cancel", callback = self.reject)
63
64        self.resize(250,300)
65        self.updateGUI()
66
67    def saveImage(self, filename = None, size = None, closeDialog = 1):
68        if not filename:
69            filename = self.getFileName(self.defaultName, "Portable Network Graphics (*.PNG);;Windows Bitmap (*.BMP);;Graphics Interchange Format (*.GIF);;Scalable Vector Graphics (*.SVG)", ".png")
70            if not filename: return
71
72        (fil,ext) = os.path.splitext(filename)
73        if ext.lower() not in [".bmp", ".gif", ".png", ".svg"] :
74            ext = ".png"                                        # if no format was specified, we choose png
75        filename = fil + ext
76       
77        if _have_gl and isinstance(self.graph, QGLWidget):
78            img = self.graph.grabFrameBuffer()
79            if size != None:
80                img = img.scaled(size)
81            img.save(filename)
82            if closeDialog:
83                QDialog.accept(self)
84            return
85
86        real_graph = self.graph if isinstance(self.graph, QGraphicsView) else None
87        if real_graph:
88            self.graph = self.graph.scene()           
89
90        if isinstance(self.graph, QGraphicsScene):
91            source = self.getSceneBoundingRect().adjusted(-15, -15, 15, 15)
92            size = source.size()
93        elif isinstance(self.graph, QGraphicsView):
94            source = self.graph.sceneRect()
95            size = source.size()
96        elif not size:
97            size = self.getSize()
98
99        painter = QPainter()
100        if filename.lower().endswith(".svg"):
101            buffer = QSvgGenerator()
102            buffer.setFileName(filename)
103            buffer.setSize(QSize(int(size.width()), int(size.height())))
104        else:
105            buffer = QPixmap(int(size.width()), int(size.height()))
106        painter.begin(buffer)
107        painter.setRenderHint(QPainter.Antialiasing)
108        if not filename.lower().endswith(".svg"):
109            if isinstance(self.graph, QGraphicsScene) or isinstance(self.graph, QGraphicsView):
110                # make background same color as the widget's background
111                brush = self.graph.backgroundBrush()
112                if brush.style() == Qt.NoBrush:
113                    brush = QBrush(self.graph.palette().color(QPalette.Base))
114                painter.fillRect(buffer.rect(), brush)
115            else:
116                painter.fillRect(buffer.rect(), QBrush(Qt.white))
117
118        # qwt plot
119        global _have_qwt
120        if _have_qwt and isinstance(self.graph, QwtPlot):
121
122            if self.penWidthFactor != 1:
123                for curve in self.graph.itemList():
124                    pen = curve.pen(); pen.setWidth(self.penWidthFactor*pen.width()); curve.setPen(pen)
125
126            self.graph.print_(painter, QRect(0,0,size.width(), size.height()))
127
128            if self.penWidthFactor != 1:
129                for curve in self.graph.itemList():
130                    pen = curve.pen(); pen.setWidth(pen.width()/self.penWidthFactor); curve.setPen(pen)
131
132        # QGraphicsScene
133        elif isinstance(self.graph, QGraphicsScene) or isinstance(self.graph, QGraphicsView):
134            target = QRectF(0,0, source.width(), source.height())
135            self.graph.render(painter, target, source)
136
137        if not filename.lower().endswith(".svg"):
138            buffer.save(filename)
139
140        if closeDialog:
141            QDialog.accept(self)
142
143    def getSceneBoundingRect(self):
144        source = QRectF()
145        for item in self.graph.items():
146            if item.isVisible():
147                source = source.united(item.boundingRect().translated(item.pos()))
148        return source
149
150    def saveToMatplotlib(self):
151        filename = self.getFileName(self.defaultName, "Python Script (*.py)", ".py")
152        if filename:
153            global _have_qwt
154            if _have_qwt and isinstance(self.graph, QwtPlot):
155                self.graph.saveToMatplotlib(filename, self.getSize())
156            else:
157                rect = self.getSceneBoundingRect()
158                minx, maxx, miny, maxy = rect.x(), rect.x()+rect.width(), rect.y(), rect.y()+rect.height()
159                f = open(filename, "wt")
160                f.write("# This Python file uses the following encoding: utf-8\n")
161                f.write("from pylab import *\nfrom matplotlib.patches import Rectangle\n\n#constants\nx1 = %f; x2 = %f\ny1 = 0.0; y2 = %f\ndpi = 80\nxsize = %d\nysize = %d\nedgeOffset = 0.01\n\nfigure(facecolor = 'w', figsize = (xsize/float(dpi), ysize/float(dpi)), dpi = dpi)\na = gca()\nhold(True)\n" % (minx, maxx, maxy, maxx-minx, maxy-miny))
162               
163                if isinstance(self.graph, QGraphicsView):
164                    scene = self.graph.scene()
165                else:
166                    scene = self.graph
167               
168                sortedList = [(item.zValue(), item) for item in scene.items()]
169                sortedList.sort()   # sort items by z value
170
171                for (z, item) in sortedList:
172                    # a little compatibility for QT 3.3 (on Mac at least)
173                    if hasattr(item, "isVisible"):
174                        if not item.isVisible(): continue
175                    elif not item.visible(): continue
176                    if item.__class__ in [QGraphicsRectItem, QGraphicsLineItem]:
177                        penc, penAlpha  = self._getColorFromObject(item.pen())
178                        penWidth = item.pen().width()
179
180                        if isinstance(item, QGraphicsRectItem):
181                            x,y,w,h = item.rect().x(), maxy-item.rect().y()-item.rect().height(), item.rect().width(), item.rect().height()
182                            brushc, brushAlpha = self._getColorFromObject(item.brush())
183                            f.write("a.add_patch(Rectangle((%d, %d), %d, %d, edgecolor=%s, facecolor = %s, linewidth = %d, fill = %d))\n" % (x,y,w,h, penc, brushc, penWidth, type(brushc) == tuple))
184                        elif isinstance(item, QGraphicsLineItem):
185                            x1,y1, x2,y2 = item.line().x1(), maxy-item.line().y1(), item.line().x2(), maxy-item.line().y2()
186                            f.write("plot(%s, %s, marker = 'None', linestyle = '-', color = %s, linewidth = %d, alpha = %.3f)\n" % ([x1,x2], [y1,y2], penc, penWidth, penAlpha))
187                    elif item.__class__ in [QGraphicsTextItem, OWQCanvasFuncts.OWCanvasText]:
188                        if item.__class__  == QGraphicsTextItem:
189                            xalign, yalign = "left", "top"
190                            x, y = item.x(), item.y()
191                        else:
192                            align = item.alignment
193                            #xalign = (align & Qt.AlignLeft and "right") or (align & Qt.AlignRight and "left") or (align & Qt.AlignHCenter and "center")
194                            #yalign = (align & Qt.AlignBottom and "top") or (align & Qt.AlignTop and "bottom") or (align & Qt.AlignVCenter and "center")
195                            xalign = (align & Qt.AlignLeft and "left") or (align & Qt.AlignRight and "right") or (align & Qt.AlignHCenter and "center")
196                            yalign = (align & Qt.AlignBottom and "bottom") or (align & Qt.AlignTop and "top") or (align & Qt.AlignVCenter and "center")
197                            x, y = item.x, item.y
198                        vertAlign = (yalign and ", verticalalignment = '%s'" % yalign) or ""
199                        horAlign = (xalign and ", horizontalalignment = '%s'" % xalign) or ""
200                        color = tuple([item.defaultTextColor().red()/255., item.defaultTextColor().green()/255., item.defaultTextColor().blue()/255.])
201                        weight = item.font().bold() and "bold" or "normal"
202                        f.write("text(%f, %f, '%s'%s%s, color = %s, name = '%s', weight = '%s', alpha = %.3f)\n" % (item.x, maxy-item.y, unicode(item.toPlainText()).encode("utf-8"), vertAlign, horAlign, color, str(item.font().family()), weight, item.defaultTextColor().alpha()/float(255)))
203
204                f.write("# disable grid\ngrid(False)\n\n")
205                f.write("#hide axis\naxis('off')\naxis([x1, x2, y1, y2])\ngca().set_position([edgeOffset, edgeOffset, 1 - 2*edgeOffset, 1 - 2*edgeOffset])\n")
206                f.write("show()")
207                f.close()
208
209            try:
210                import matplotlib
211            except:
212                QMessageBox.information(self,'Matplotlib missing',"File was saved, but you will not be able to run it because you don't have matplotlib installed.\nYou can download matplotlib for free at matplotlib.sourceforge.net.", QMessageBox.Ok)
213
214        QDialog.accept(self)
215
216    # ############################################################
217    # EXTRA FUNCTIONS ############################################
218    def getFileName(self, defaultName, mask, extension):
219        fileName = str(QFileDialog.getSaveFileName(self, "Save to..", os.path.join(self.lastSaveDirName, defaultName), mask))
220        if not fileName: return None
221        if not os.path.splitext(fileName)[1][1:]: fileName = fileName + extension
222
223        self.lastSaveDirName = os.path.split(fileName)[0] + "/"
224        self.saveSettings()
225        return fileName
226
227    def getSize(self):
228        if isinstance(self.graph, QGraphicsScene):
229            size = self.getSceneBoundingRect().size()
230        elif self.selectedSize == 0: size = self.graph.size()
231        elif self.selectedSize == 4: size = QSize(self.customX, self.customY)
232        else: size = QSize(200 + self.selectedSize*200, 200 + self.selectedSize*200)
233        return size
234
235    def updateGUI(self):
236        global _have_qwt
237        if _have_qwt and isinstance(self.graph, QwtPlot):
238            self.customXEdit.setEnabled(self.selectedSize == 4)
239            self.customYEdit.setEnabled(self.selectedSize == 4)
240
241    def _getColorFromObject(self, obj):
242        if isinstance(obj, QBrush) and obj.style() == Qt.NoBrush: return "'none'", 1
243        if isinstance(obj, QPen)   and obj.style() == Qt.NoPen: return "'none'", 1
244        col = [obj.color().red(), obj.color().green(), obj.color().blue()];
245        col = tuple([v/float(255) for v in col])
246        return col, obj.color().alpha()/float(255)
Note: See TracBrowser for help on using the repository browser.