Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c27e185

Browse files
committed
Interactive setting of savefig rcParams (Qt only).
An additional window pops after selecting the filename to allow setting of savefig-related rcParams. For simplicity and consistency, the "ps.usedistiller" rcParam is now normalized to `None` when not set.
1 parent 0084e4a commit c27e185

File tree

3 files changed

+112
-23
lines changed

3 files changed

+112
-23
lines changed

lib/matplotlib/backends/backend_qt5.py

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@
1515
from matplotlib.backend_bases import (
1616
_Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2,
1717
TimerBase, cursors)
18-
import matplotlib.backends.qt_editor.figureoptions as figureoptions
19-
from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
20-
from matplotlib.figure import Figure
2118

22-
from .qt_compat import (
23-
QtCore, QtGui, QtWidgets, _getSaveFileName, is_pyqt5, __version__, QT_API)
19+
from .qt_compat import (QtCore, QtGui, QtWidgets, _getSaveFileName,
20+
__version__, is_pyqt5, QT_API)
21+
from .qt_editor import figureoptions, formlayout
22+
from .qt_editor.formsubplottool import UiSubplotTool
2423

2524
backend_version = __version__
2625

@@ -726,24 +725,43 @@ def save_figure(self, *args):
726725
startpath = os.path.expanduser(
727726
matplotlib.rcParams['savefig.directory'])
728727
start = os.path.join(startpath, self.canvas.get_default_filename())
728+
729729
filters = []
730-
selectedFilter = None
730+
selected_filter = None
731731
for name, exts in sorted_filetypes:
732-
exts_list = " ".join(['*.%s' % ext for ext in exts])
733-
filter = '%s (%s)' % (name, exts_list)
732+
filters.append(
733+
'{} ({})'.format(name, ' '.join(map('*.{}'.format, exts))))
734734
if default_filetype in exts:
735-
selectedFilter = filter
736-
filters.append(filter)
735+
selected_filter = filters[-1]
737736
filters = ';;'.join(filters)
738737

739-
fname, filter = _getSaveFileName(self.parent,
740-
"Choose a filename to save to",
741-
start, filters, selectedFilter)
738+
fname, _ = _getSaveFileName(
739+
self.parent, "Choose a filename to save to",
740+
start, filters, selected_filter)
742741
if fname:
743742
# Save dir for next time, unless empty str (i.e., use cwd).
744743
if startpath != "":
745744
matplotlib.rcParams['savefig.directory'] = (
746745
os.path.dirname(six.text_type(fname)))
746+
options = _default_savefig_options
747+
try:
748+
options = (options
749+
+ [None]
750+
+ _extra_savefig_options[
751+
os.path.splitext(fname)[1].lower()])
752+
except KeyError:
753+
pass
754+
fedit_arg = []
755+
for option in options:
756+
if option is None:
757+
fedit_arg.append((None, None))
758+
else:
759+
fedit_arg.append(option.make_fedit_entry())
760+
fedit_res = formlayout.fedit(fedit_arg, "Options")
761+
if not fedit_res:
762+
return
763+
for option, res in zip(filter(None, options), fedit_res):
764+
option.setter(res)
747765
try:
748766
self.canvas.figure.savefig(six.text_type(fname))
749767
except Exception as e:
@@ -752,6 +770,79 @@ def save_figure(self, *args):
752770
QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)
753771

754772

773+
class _Option(object):
774+
775+
def __init__(self, name, rc_key=None, getter=None, setter=None):
776+
if rc_key and not (getter or setter):
777+
def make_fedit_entry():
778+
return (name, matplotlib.rcParams[rc_key])
779+
780+
def setter(val):
781+
matplotlib.rcParams[rc_key] = val
782+
783+
elif getter and setter and not rc_key:
784+
def make_fedit_entry():
785+
return (name, getter())
786+
787+
else:
788+
raise ValueError("Invalid entry")
789+
790+
self.name = name
791+
self.make_fedit_entry = make_fedit_entry
792+
self.setter = setter
793+
794+
795+
_default_savefig_options = [
796+
_Option("DPI", "savefig.dpi"),
797+
_Option("Face color", "savefig.facecolor"),
798+
_Option("Edge color", "savefig.edgecolor"),
799+
_Option("Tight bounding box",
800+
getter=lambda: matplotlib.rcParams["savefig.bbox"] == "tight",
801+
setter=lambda val: matplotlib.rcParams.__setitem__(
802+
"savefig.bbox", "tight" if val else "standard")),
803+
_Option("Tight bounding box padding", "savefig.pad_inches"),
804+
_Option("Transparent background", "savefig.transparent")]
805+
806+
807+
_extra_savefig_options = {
808+
".jpg": [
809+
_Option("JPEG quality", "savefig.jpeg_quality")],
810+
".jpeg": [
811+
_Option("JPEG quality", "savefig.jpeg_quality")],
812+
".pdf": [
813+
_Option("PDF compression", "pdf.compression"),
814+
_Option("PDF font type",
815+
getter=lambda:
816+
[str(matplotlib.rcParams["pdf.fonttype"]),
817+
"3", "42"],
818+
setter=lambda val:
819+
matplotlib.rcParams.__setitem__("pdf.fonttype", val))],
820+
".ps": [
821+
_Option("PS paper size",
822+
getter=lambda:
823+
[matplotlib.rcParams["ps.papersize"]]
824+
+ ["auto", "letter", "legal", "ledger"]
825+
+ ["A{}".format(i) for i in range(11)]
826+
+ ["B{}".format(i) for i in range(11)],
827+
setter=lambda val:
828+
matplotlib.rcParams.__setitem__("ps.papersize", val)),
829+
_Option("PS use AFM font", "ps.useafm"),
830+
_Option("PS distiller",
831+
getter=lambda:
832+
[str(matplotlib.rcParams["ps.usedistiller"])]
833+
+ ["None", "ghostscript", "xpdf"],
834+
setter=lambda val:
835+
matplotlib.rcParams.__setitem__("ps.usedistiller", val)),
836+
_Option("PS distiller resolution", "ps.distiller.res"),
837+
_Option("PS font type",
838+
getter=lambda:
839+
[str(matplotlib.rcParams["ps.fonttype"]),
840+
"3", "42"],
841+
setter=lambda val:
842+
matplotlib.rcParams.__setitem__("ps.fonttype", val))]
843+
}
844+
845+
755846
class SubplotToolQt(UiSubplotTool):
756847
def __init__(self, targetfig, parent):
757848
UiSubplotTool.__init__(self, None)

lib/matplotlib/rcsetup.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,8 @@ def update_savefig_format(value):
500500
def validate_ps_distiller(s):
501501
if isinstance(s, six.string_types):
502502
s = s.lower()
503-
if s in ('none', None):
503+
if s in ('none', None, 'false', False):
504504
return None
505-
elif s in ('false', False):
506-
return False
507505
elif s in ('ghostscript', 'xpdf'):
508506
return s
509507
else:
@@ -1330,7 +1328,7 @@ def _validate_linestyle(ls):
13301328
'ps.papersize': ['letter', validate_ps_papersize],
13311329
'ps.useafm': [False, validate_bool], # Set PYTHONINSPECT
13321330
# use ghostscript or xpdf to distill ps output
1333-
'ps.usedistiller': [False, validate_ps_distiller],
1331+
'ps.usedistiller': [None, validate_ps_distiller],
13341332
'ps.distiller.res': [6000, validate_int], # dpi
13351333
'ps.fonttype': [3, validate_fonttype], # 3 (Type3) or 42 (Truetype)
13361334
# compression level from 0 to 9; 0 to disable

matplotlibrc.template

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,12 +532,12 @@ backend : $TEMPLATE_BACKEND
532532
# ps backend params
533533
#ps.papersize : letter # auto, letter, legal, ledger, A0-A10, B0-B10
534534
#ps.useafm : False # use of afm fonts, results in small files
535-
#ps.usedistiller : False # can be: None, ghostscript or xpdf
536-
# Experimental: may produce smaller files.
537-
# xpdf intended for production of publication quality files,
538-
# but requires ghostscript, xpdf and ps2eps
539-
#ps.distiller.res : 6000 # dpi
540-
#ps.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
535+
#ps.usedistiller : None # can be: None, ghostscript or xpdf
536+
# Experimental: may produce smaller files.
537+
# xpdf intended for production of publication quality files,
538+
# but requires ghostscript, xpdf and ps2eps
539+
#ps.distiller.res : 6000 # dpi
540+
#ps.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
541541

542542
# pdf backend params
543543
#pdf.compression : 6 # integer from 0 to 9

0 commit comments

Comments
 (0)