Skip to content

Commit 6aaa7c6

Browse files
authored
Merge pull request #2210 from ales-erjavec/pdf-export
[ENH] Add PDF format to image exporters
2 parents 62ddfaf + 589f403 commit 6aaa7c6

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

Orange/widgets/io.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import os
2+
import tempfile
3+
14
from AnyQt import QtGui, QtCore, QtSvg
25
from AnyQt.QtCore import QMimeData
36
from AnyQt.QtWidgets import (
@@ -59,8 +62,8 @@ def write_image(cls, filename, scene):
5962
scene.render(painter, target, rect)
6063
except TypeError:
6164
scene.render(painter) # QWidget.render() takes different params
62-
cls._save_buffer(buffer, filename)
6365
painter.end()
66+
cls._save_buffer(buffer, filename)
6467

6568
@classmethod
6669
def write(cls, filename, scene):
@@ -139,6 +142,9 @@ def _get_target(scene, painter, buffer, source):
139142

140143
@staticmethod
141144
def _save_buffer(buffer, filename):
145+
dev = buffer.outputDevice()
146+
if dev is not None:
147+
dev.flush()
142148
pass
143149

144150
@staticmethod
@@ -164,3 +170,38 @@ def write_image(cls, filename, scene):
164170
pass
165171

166172
super().write_image(filename, scene)
173+
174+
175+
if hasattr(QtGui, "QPdfWriter"):
176+
class PdfFormat(ImgFormat):
177+
EXTENSIONS = ('.pdf', )
178+
DESCRIPTION = 'Portable Document Format'
179+
PRIORITY = 110
180+
181+
@classmethod
182+
def write_image(cls, filename, scene):
183+
# export via svg to temp file then print that
184+
# NOTE: can't use NamedTemporaryFile with delete = True
185+
# (see https://bugs.python.org/issue14243)
186+
fd, tmpname = tempfile.mkstemp(suffix=".svg")
187+
os.close(fd)
188+
try:
189+
SvgFormat.write_image(tmpname, scene)
190+
with open(tmpname, "rb") as f:
191+
svgcontents = f.read()
192+
finally:
193+
os.unlink(tmpname)
194+
195+
svgrend = QtSvg.QSvgRenderer(QtCore.QByteArray(svgcontents))
196+
vbox = svgrend.viewBox()
197+
if not vbox.isValid():
198+
size = svgrend.defaultSize()
199+
else:
200+
size = vbox.size()
201+
writer = QtGui.QPdfWriter(filename)
202+
writer.setPageSizeMM(QtCore.QSizeF(size) * 0.282)
203+
painter = QtGui.QPainter(writer)
204+
svgrend.render(painter)
205+
painter.end()
206+
del svgrend
207+
del painter

Orange/widgets/tests/test_io.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import os
2+
import tempfile
3+
import unittest
4+
5+
from AnyQt.QtWidgets import QGraphicsScene, QGraphicsRectItem
6+
from Orange.widgets.tests.base import GuiTest
7+
8+
from Orange.widgets import io as imgio
9+
10+
@unittest.skipUnless(hasattr(imgio, "PdfFormat"), "QPdfWriter not available")
11+
class TestIO(GuiTest):
12+
def test_pdf(self):
13+
sc = QGraphicsScene()
14+
sc.addItem(QGraphicsRectItem(0, 0, 20, 20))
15+
fd, fname = tempfile.mkstemp()
16+
os.close(fd)
17+
try:
18+
imgio.PdfFormat.write_image(fname, sc)
19+
finally:
20+
os.unlink(fname)

Orange/widgets/utils/saveplot.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os.path
2+
import traceback
23

34
from AnyQt.QtWidgets import QMessageBox
45
from AnyQt.QtCore import QSettings
@@ -24,8 +25,13 @@ def save_plot(data, file_formats, filename=""):
2425
try:
2526
writer.write(filename, data)
2627
except Exception as e:
27-
QMessageBox.critical(
28-
None, "Error", 'Error occurred while saving file "{}": {}'.format(filename, e))
28+
mb = QMessageBox(
29+
None,
30+
windowTitle="Error",
31+
text='Error occurred while saving file "{}": {}'.format(filename, e),
32+
detailedText=traceback.format_exc(),
33+
icon=QMessageBox.Critical)
34+
mb.exec_()
2935
else:
3036
settings.setValue(_LAST_DIR_KEY, os.path.split(filename)[0])
3137
settings.setValue(_LAST_FILTER_KEY, filter)

0 commit comments

Comments
 (0)