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

Skip to content

Commit 173a197

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 ab98852 commit 173a197

File tree

3 files changed

+106
-19
lines changed

3 files changed

+106
-19
lines changed

lib/matplotlib/backends/backend_qt5.py

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
unicode_literals)
33
import six
44

5+
from collections import namedtuple
56
import os
67
import re
78
import signal
@@ -27,7 +28,8 @@
2728

2829
from .qt_compat import (QtCore, QtGui, QtWidgets, _getSaveFileName,
2930
__version__, is_pyqt5)
30-
from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool
31+
from .qt_editor import formlayout
32+
from .qt_editor.formsubplottool import UiSubplotTool
3133

3234
backend_version = __version__
3335

@@ -725,19 +727,19 @@ def save_figure(self, *args):
725727
startpath = matplotlib.rcParams.get('savefig.directory', '')
726728
startpath = os.path.expanduser(startpath)
727729
start = os.path.join(startpath, self.canvas.get_default_filename())
730+
728731
filters = []
729-
selectedFilter = None
732+
selected_filter = None
730733
for name, exts in sorted_filetypes:
731-
exts_list = " ".join(['*.%s' % ext for ext in exts])
732-
filter = '%s (%s)' % (name, exts_list)
734+
filters.append(
735+
'{} ({})'.format(name, ' '.join(map('*.{}'.format, exts))))
733736
if default_filetype in exts:
734-
selectedFilter = filter
735-
filters.append(filter)
737+
selected_filter = filters[-1]
736738
filters = ';;'.join(filters)
737739

738-
fname, filter = _getSaveFileName(self.parent,
739-
"Choose a filename to save to",
740-
start, filters, selectedFilter)
740+
fname, selected_filter = _getSaveFileName(
741+
self.parent, "Choose a filename to save to",
742+
start, filters, selected_filter)
741743
if fname:
742744
if startpath == '':
743745
# explicitly missing key or empty str signals to use cwd
@@ -746,6 +748,26 @@ def save_figure(self, *args):
746748
# save dir for next time
747749
savefig_dir = os.path.dirname(six.text_type(fname))
748750
matplotlib.rcParams['savefig.directory'] = savefig_dir
751+
options = _default_savefig_options
752+
try:
753+
options = (
754+
options
755+
+ [None]
756+
+ _extra_savefig_options[
757+
os.path.splitext(fname)[1].lower()])
758+
except KeyError:
759+
pass
760+
fedit_arg = []
761+
for option in options:
762+
if option == None:
763+
fedit_arg.append((None, None))
764+
else:
765+
fedit_arg.append(option.gen_fedit_entry())
766+
fedit_res = formlayout.fedit(fedit_arg, "Options")
767+
if not fedit_res:
768+
return
769+
for option, res in zip(filter(None, options), fedit_res):
770+
option.setter(res)
749771
try:
750772
self.canvas.print_figure(six.text_type(fname))
751773
except Exception as e:
@@ -754,6 +776,73 @@ def save_figure(self, *args):
754776
QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton)
755777

756778

779+
_Option = namedtuple("_Option", "name gen_fedit_entry setter")
780+
def _option(name, rc_key=None, getter=None, setter=None):
781+
if rc_key and not (getter or setter):
782+
def gen_fedit_entry():
783+
return (name, matplotlib.rcParams[rc_key])
784+
def setter(val):
785+
matplotlib.rcParams[rc_key] = val
786+
return _Option(name, gen_fedit_entry, setter)
787+
elif getter and setter and not rc_key:
788+
def gen_fedit_entry():
789+
return (name, getter())
790+
return _Option(name, gen_fedit_entry, setter)
791+
else:
792+
raise ValueError("Invalid entry")
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+
757846
class SubplotToolQt(SubplotTool, UiSubplotTool):
758847
def __init__(self, targetfig, parent):
759848
UiSubplotTool.__init__(self, None)

lib/matplotlib/rcsetup.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,8 @@ def update_savefig_format(value):
504504
def validate_ps_distiller(s):
505505
if isinstance(s, six.string_types):
506506
s = s.lower()
507-
if s in ('none', None):
507+
if s in ('none', None, 'false', False):
508508
return None
509-
elif s in ('false', False):
510-
return False
511509
elif s in ('ghostscript', 'xpdf'):
512510
return s
513511
else:
@@ -1269,7 +1267,7 @@ def validate_animation_writer_path(p):
12691267
'ps.papersize': ['letter', validate_ps_papersize],
12701268
'ps.useafm': [False, validate_bool], # Set PYTHONINSPECT
12711269
# use ghostscript or xpdf to distill ps output
1272-
'ps.usedistiller': [False, validate_ps_distiller],
1270+
'ps.usedistiller': [None, validate_ps_distiller],
12731271
'ps.distiller.res': [6000, validate_int], # dpi
12741272
'ps.fonttype': [3, validate_fonttype], # 3 (Type3) or 42 (Truetype)
12751273
# 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
@@ -538,12 +538,12 @@ backend : $TEMPLATE_BACKEND
538538
# ps backend params
539539
#ps.papersize : letter # auto, letter, legal, ledger, A0-A10, B0-B10
540540
#ps.useafm : False # use of afm fonts, results in small files
541-
#ps.usedistiller : False # can be: None, ghostscript or xpdf
542-
# Experimental: may produce smaller files.
543-
# xpdf intended for production of publication quality files,
544-
# but requires ghostscript, xpdf and ps2eps
545-
#ps.distiller.res : 6000 # dpi
546-
#ps.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
541+
#ps.usedistiller : None # can be: None, ghostscript or xpdf
542+
# Experimental: may produce smaller files.
543+
# xpdf intended for production of publication quality files,
544+
# but requires ghostscript, xpdf and ps2eps
545+
#ps.distiller.res : 6000 # dpi
546+
#ps.fonttype : 3 # Output Type 3 (Type3) or Type 42 (TrueType)
547547

548548
# pdf backend params
549549
#pdf.compression : 6 # integer from 0 to 9

0 commit comments

Comments
 (0)