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

Skip to content

Fix broken "save figure" with GTK4 on mac #26558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 42 additions & 44 deletions lib/matplotlib/backends/backend_gtk4.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import functools
import io
import os

Expand Down Expand Up @@ -331,66 +330,65 @@
_NavigationToolbar2GTK.__init__(self, canvas)

def save_figure(self, *args):
dialog = Gtk.FileChooserNative(
print(Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION)
dialog = Gtk.FileDialog(

Check warning on line 334 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L333-L334

Added lines #L333 - L334 were not covered by tests
title='Save the figure',
transient_for=self.canvas.get_root(),
action=Gtk.FileChooserAction.SAVE,
modal=True)

self._save_dialog = dialog # Must keep a reference.
filters = Gio.ListStore.new(Gtk.FileFilter)

Check warning on line 339 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L339

Added line #L339 was not covered by tests

ff = Gtk.FileFilter()
ff.set_name('All files')
ff.add_pattern('*')
dialog.add_filter(ff)
dialog.set_filter(ff)
filters.append(ff)

Check warning on line 344 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L344

Added line #L344 was not covered by tests

formats = []
default_format = None
for i, (name, fmts) in enumerate(
self.canvas.get_supported_filetypes_grouped().items()):
ff = Gtk.FileFilter()
ff.set_name(name)
for fmt in fmts:
ff.add_pattern(f'*.{fmt}')
dialog.add_filter(ff)
formats.append(name)
filters.append(ff)

Check warning on line 352 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L352

Added line #L352 was not covered by tests
if self.canvas.get_default_filetype() in fmts:
default_format = i
# Setting the choice doesn't always work, so make sure the default
# format is first.
formats = [formats[default_format], *formats[:default_format],
*formats[default_format+1:]]
dialog.add_choice('format', 'File format', formats, formats)
dialog.set_choice('format', formats[default_format])

dialog.set_current_folder(Gio.File.new_for_path(
dialog.set_default_filter(ff)

Check warning on line 354 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L354

Added line #L354 was not covered by tests

dialog.set_filters(filters)

Check warning on line 356 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L356

Added line #L356 was not covered by tests

dialog.set_initial_folder(Gio.File.new_for_path(

Check warning on line 358 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L358

Added line #L358 was not covered by tests
os.path.expanduser(mpl.rcParams['savefig.directory'])))
dialog.set_current_name(self.canvas.get_default_filename())

@functools.partial(dialog.connect, 'response')
def on_response(dialog, response):
file = dialog.get_file()
fmt = dialog.get_choice('format')
fmt = self.canvas.get_supported_filetypes_grouped()[fmt][0]
dialog.destroy()
self._save_dialog = None
if response != Gtk.ResponseType.ACCEPT:
return
# Save dir for next time, unless empty str (which means use cwd).
if mpl.rcParams['savefig.directory']:
parent = file.get_parent()
mpl.rcParams['savefig.directory'] = parent.get_path()
dialog.set_initial_name(self.canvas.get_default_filename())

Check warning on line 360 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L360

Added line #L360 was not covered by tests

def dialog_save_callback(dialog, result):

Check warning on line 362 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L362

Added line #L362 was not covered by tests
try:
self.canvas.figure.savefig(file.get_path(), format=fmt)
except Exception as e:
msg = Gtk.MessageDialog(
transient_for=self.canvas.get_root(),
message_type=Gtk.MessageType.ERROR,
buttons=Gtk.ButtonsType.OK, modal=True,
text=str(e))
msg.show()

dialog.show()
file = dialog.save_finish(result)
print(file)

Check warning on line 365 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L364-L365

Added lines #L364 - L365 were not covered by tests
if file is not None:
# we only use file name to save the figure.
# let savefig decide if the format extension isn't in the name
print(f"File path is {file.get_path()}")

Check warning on line 369 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L369

Added line #L369 was not covered by tests
# Save dir for next time, unless empty str (which means use cwd).
if mpl.rcParams['savefig.directory']:
parent = file.get_parent()
mpl.rcParams['savefig.directory'] = parent.get_path()
try:
self.canvas.figure.savefig(file.get_path())
self.canvas.draw() # canvas may become blank after saving

Check warning on line 376 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L372-L376

Added lines #L372 - L376 were not covered by tests

except Exception as e:
msg = Gtk.MessageDialog(

Check warning on line 379 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L378-L379

Added lines #L378 - L379 were not covered by tests
transient_for=self.canvas.get_root(),
message_type=Gtk.MessageType.ERROR,
buttons=Gtk.ButtonsType.OK, modal=True,
text=str(e))
msg.show()

Check warning on line 384 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L384

Added line #L384 was not covered by tests

except GLib.Error as error:
print(f"Error opening file: {error.message}")

Check warning on line 387 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L386-L387

Added lines #L386 - L387 were not covered by tests

# self.canvas.draw_idle()

dialog.save(None, None, dialog_save_callback)

Check warning on line 391 in lib/matplotlib/backends/backend_gtk4.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/backends/backend_gtk4.py#L391

Added line #L391 was not covered by tests


class ToolbarGTK4(ToolContainerBase, Gtk.Box):
Expand Down