diff --git a/lib/matplotlib/backends/qt_editor/_formlayout.py b/lib/matplotlib/backends/qt_editor/_formlayout.py index e2b371f1652d..2f690a8e109c 100644 --- a/lib/matplotlib/backends/qt_editor/_formlayout.py +++ b/lib/matplotlib/backends/qt_editor/_formlayout.py @@ -342,9 +342,17 @@ def get(self): elif isinstance(value, Real): value = float(str(field.text())) elif isinstance(value, datetime.datetime): - value = field.dateTime().toPyDateTime() + datetime_ = field.dateTime() + if hasattr(datetime_, "toPyDateTime"): + value = datetime_.toPyDateTime() + else: + value = datetime_.toPython() elif isinstance(value, datetime.date): - value = field.date().toPyDate() + date_ = field.date() + if hasattr(date_, "toPyDate"): + value = date_.toPyDate() + else: + value = date_.toPython() else: value = eval(str(field.text())) valuelist.append(value) diff --git a/lib/matplotlib/backends/qt_editor/figureoptions.py b/lib/matplotlib/backends/qt_editor/figureoptions.py index c0ea7e2ea302..8fc02f4b141b 100644 --- a/lib/matplotlib/backends/qt_editor/figureoptions.py +++ b/lib/matplotlib/backends/qt_editor/figureoptions.py @@ -10,7 +10,7 @@ from matplotlib import cbook, cm, colors as mcolors, markers, image as mimage from matplotlib.backends.qt_compat import QtGui from matplotlib.backends.qt_editor import _formlayout - +from matplotlib.dates import DateConverter, num2date LINESTYLES = {'-': 'Solid', '--': 'Dashed', @@ -33,9 +33,17 @@ def figure_edit(axes, parent=None): sep = (None, None) # separator # Get / General - # Cast to builtin floats as they have nicer reprs. - xmin, xmax = map(float, axes.get_xlim()) - ymin, ymax = map(float, axes.get_ylim()) + def convert_limits(lim, converter): + """Convert axis limits for correct input editors.""" + if isinstance(converter, DateConverter): + return map(num2date, lim) + # Cast to builtin floats as they have nicer reprs. + return map(float, lim) + + xconverter = axes.xaxis.converter + xmin, xmax = convert_limits(axes.get_xlim(), xconverter) + yconverter = axes.yaxis.converter + ymin, ymax = convert_limits(axes.get_ylim(), yconverter) general = [('Title', axes.get_title()), sep, (None, "X-Axis"), @@ -54,8 +62,6 @@ def figure_edit(axes, parent=None): ] # Save the unit data - xconverter = axes.xaxis.converter - yconverter = axes.yaxis.converter xunits = axes.xaxis.get_units() yunits = axes.yaxis.get_units() diff --git a/lib/matplotlib/tests/test_backend_qt.py b/lib/matplotlib/tests/test_backend_qt.py index da52dc21e2f2..95ef41d97978 100644 --- a/lib/matplotlib/tests/test_backend_qt.py +++ b/lib/matplotlib/tests/test_backend_qt.py @@ -1,4 +1,5 @@ import copy +from datetime import date, datetime import signal from unittest import mock @@ -10,7 +11,8 @@ try: - from matplotlib.backends.qt_compat import QtGui + from matplotlib.backends.qt_compat import QtGui, QtWidgets + from matplotlib.backends.qt_editor import _formlayout except ImportError: pytestmark = pytest.mark.skip('No usable Qt5 bindings') @@ -245,6 +247,20 @@ def test_figureoptions(): fig.canvas.manager.toolbar.edit_parameters() +@pytest.mark.backend('Qt5Agg', skip_on_importerror=True) +def test_figureoptions_with_datetime_axes(): + fig, ax = plt.subplots() + xydata = [ + datetime(year=2021, month=1, day=1), + datetime(year=2021, month=2, day=1) + ] + ax.plot(xydata, xydata) + with mock.patch( + "matplotlib.backends.qt_editor._formlayout.FormDialog.exec_", + lambda self: None): + fig.canvas.manager.toolbar.edit_parameters() + + @pytest.mark.backend('Qt5Agg', skip_on_importerror=True) def test_double_resize(): # Check that resizing a figure twice keeps the same window size @@ -282,3 +298,20 @@ def crashing_callback(fig, stale): canvas = FigureCanvasQTAgg(fig) fig.stale = True assert called + + +@pytest.mark.backend('Qt5Agg', skip_on_importerror=True) +def test_form_widget_get_with_datetime_and_date_fields(): + if not QtWidgets.QApplication.instance(): + QtWidgets.QApplication() + form = [ + ("Datetime field", datetime(year=2021, month=3, day=11)), + ("Date field", date(year=2021, month=3, day=11)) + ] + widget = _formlayout.FormWidget(form) + widget.setup() + values = widget.get() + assert values == [ + datetime(year=2021, month=3, day=11), + date(year=2021, month=3, day=11) + ]