FileChooserDialog and response signal



Hi,

here is a program which works in Gtk but fails in Gtkmm.  The aim is
to be able to mangle the filename of a file chooser used for saving
and still get the canonical overwrite confirmation dialog.  The
problem is a combination of the following:

* FileChooser does not yet support file format extensions very well, see
  for example: http://bugzilla.gnome.org/show_bug.cgi?id=135901

* The confirm-overwrite signal is only emitted *after* Gtk detected a
  file overwrite.  Thus, the confirm-overwrite signal seems useless
  here.

* FileChooserDialog connects early to the response signal of the
  dialog, because it really, really wants to run its callback first.
  I don't know a way to squeeze a signal handler before its own
  handler.  See gtkfilechooserdialog.c:

  /* We do a signal connection here rather than overriding the method in
   * class_init because GtkDialog::response is a RUN_LAST signal.  We want *our*
   * handler to be run *first*, regardless of whether the user installs response
   * handlers of his own.
   */
  g_signal_connect (dialog, "response",
                    G_CALLBACK (response_cb), NULL);

Additional note: This Gtk::FileChooserDialog behaviour exposes a bug
in Bakery 2.4.4: If in the save or save as dialog you enter the
filename without the application extension, and the file with
extension already exists, that file is silently overwritten.  It was
my motivation to fix/work around this bug that lead me to this.

Work around in C: The attached program fc.c installs a signal handler
for the dialog's response signal which, in case the filename needs to
be mangled, updates the current name, stops the emission of the
response signal, and then emits the response signal again.  Although
this is kinda hackish, it currently seems to be the only way to
achieve this functionality without a medium sized coding effort.  This
feature was deemed important enough to add a fix when it was broken in
Gtk 2.10.  See http://bugzilla.gnome.org/show_bug.cgi?id=347883 and
the following quote:

  "I'd say this is definitely a valid use of the API since it's the
  *only* way of allowing entering filenames without extensions. You
  can do that in many apps, and the apps simply append the extension
  in their response() callbacks. The only way of getting the changed
  filename properly checked is running response() again." -- Michael Natterer

How to compile and run the test:

$ gcc -o fc fc.c `pkg-config --cflags --libs gtk+-2.0 `
$ touch example.xcf
$ ./fc
<Enter "example" in the filename field, without extension, and click Save>
** (fc:28341): DEBUG: -3
** (fc:28341): DEBUG: example.xcf
<Confirm by clicking Replace>
** (fc:28341): DEBUG: -3
** (fc:28341): DEBUG: done: -3

Work around in C++: The attached program fc2.cc is a 1:1 translation
of the C test case.  I even used a ptr function to handle the signal,
but notice that I also tried other variations.

$ g++ -o fc2 fc2.cc `pkg-config --cflags --libs gtkmm-2.4 `
$ touch example.xcf
$ ./fc
<Enter "example" in the filename field, without extension, and click Save>
Response: -3
Name: example.xcf
done: -3

Note the lack of an overwrite confirmation.

I have a more complex test case in the context of a complete
application where a similar approach leads to a segfault in
gtkfilechooserdialog.c:confirm_dialog_should_accept_filename() because
toplevel is NULL.  In that case it seems as if the
GtkFileChooserDefault widget is de-parented (removed from the dialog)
before the response signal is emitted again.  I can not reproduce this
in the simple fc2.cc, and I am not sure that information helps.  In
any case, there is something wrong here.

I would appreciate it if you could advise me on how to proceed.

Thanks,
Marcus

Attachment: fc.c
Description: Binary data

Attachment: fc2.cc
Description: Binary data



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]