When running tests, the data are not meant to be necessarily installed.
Therefore icons won't be found when calling gimp_widgets_init().
Add some special-casing to find them relatively to the install
directory.
Fixes the patch from !470 which is mostly right, except that
g_param_spec_sink() may possibly lead to finalizing the GParamSpec
(typically if it was a just-created floating spec). We don't want to
return pointer to freed data. Let's return NULL instead.
Also looking closer at the memory handling here, it looks the right
annotation for @pspec is (transfer floating). Basically we are sinking a
floating object into a full object and taking ownership of this sunk
object. But if the object was already sunk, we are reffing it and
keeping this additional reference, not the passed argument's. Hopefully
it's right since the annotation and handling of floating object with
GObject Introspection seems very unclear to me (even in core GObject
code, I see what looks like contradictory annotations).
In the normal flow, pspec is persisted in the arguments array, and is
g_param_spec_ref_sink()'d in order to sink a possible floating ref. To
avoid a leak in the error case, we need to add some g_param_spec_sink().
Saving a thumbnail is closely related to the other metadata preferences,
but so far this was the only one that didn't have a preference for a
default user value.
This commit adds a preference in the metadata section where a user can
select whether thumbnail saving is enabled by default or not.
Since it appeared with GLib 2.68.0, we could not change this until we
bumped the dependency which has only become possible a few days ago
(since Debian testing is our baseline for dependency bumps). Cf.
previous commit.
As this is a drop-in replacement (just a guint parameter changed to
gsize to avoid integer overflow), search-and-replace with:
> sed -i 's/g_memdup\>/g_memdup2/g' `grep -rIl 'g_memdup\>' *`
… followed by a few manual alignment tweaks when necessary.
This gets rid of the many deprecation warnings which we had lately when
building with a recent GLib version.
It is now discouraged to create constructor-type _new() functions with
custom code, which would make them behave differently that simply
calling g_object_new() with the GType and relevant properties. The main
reason is that some bindings would create objects with g_object_new() so
it should create expected code too.
See: https://gi.readthedocs.io/en/latest/writingbindableapis.html#custom-code-in-constructors
Here it was complicated for a few reasons:
- We hack "title" property to use the procedure's menu label by default
(without the mnemonic). For this, I overrode the GtkWindow property.
- We want "use-header-bar" to follow the application general settings by
default. Since it is a CONSTRUCT_ONLY property, g_object_set() is not
possible in _init() and _constructed(). Instead I had to override the
constructor() method to set this at construction time (yet still allow
API users to override this with the property at creation).
- Similarly, "help-func" is a CONSTRUCT_ONLY property, so I used the
same trick.
- As for "help-id", I now just set it in _constructed(). This was the
easy one.
All objects of subclass GtkWindow are special as they are actually owned
by GTK which keeps a list of all top-level windows. So we cannot
actually give ownership to the caller. With GObject Introspection in
particular, it will mean a double-free of the dialog object (by GTK,
then by the GI layer).
See also gobject-introspection#394.
As explained in GtkSizeGroup docs, all objects inside a size group holds
a reference to it. So once we destroy the last object inside these, it
will be freed too and we should drop the initial reference after adding
the objects.
Only the main size group reference is kept until the end, because we are
adding and removing objects from it regularly, so it is possible that it
is empty again at some intermediary states. Yet we don't want to free it
when this happens.
All the widgets with label inside GimpProcedureDialog have same
GtkSizeGroup (dialog->priv->label_group), which result in wrong sizes of
widget if any of the label is long. In this commit, a new GtkSizeGroup
is made for each of the container, so that labels are aligned but size
of widget in one container do not affect size of widgets in other
containers.
For the widget not belonging to any of the container, default
GtkSizeGroup (dialog->priv->label_group) is used.
Added an option for exporting thumbnail in WebP Export dialogbox.
Additionally, introduced a function gimp_procedure_dialog_fill_expander.
The function is similar to gimp_procedure_dialog_fill_frame but allows
adding GtkExpander instead of GtkFrame.
When GIMP_PROCEDURE_SENSITIVE_NO_IMAGE is set on a GimpImageProcedure,
add GIMP_PARAM_NO_VALIDATE to the param spec flags, allowing to pass a
NULL image.
Somehow the callback doesn't work for bindings (at least Python binding,
python plug-ins crash when the callback is called), so we'll still want
to have a closer look at this.
When a selection exists, we are copying then pasting the selection
contents. In particular, with multi-layer selection, it means pasting a
merged result of the selected layers (like a sample merged but limited
to selected layers).
Yet when no selection exists, with a single layer selected, a cut in
particular would remove the layer fully, then a paste would copy it
elsewhere (in the same image or even on a different image). This was
still working, but not with multiple layers. This is now fixed and we
can now copy/cut then paste several layers (without merge), which is
sometimes a very practical way to move layers (sometimes simpler than
drag'n drop, especially between images).
As a consequence, the PDB function gimp_edit_paste() now also returns an
array of layers (not a single layer).
Though the previous implementation worked fine on C plug-ins, I realized
it was problematic on bindings. In particular, the Python binding at
least was somehow freeing returned floating objects, unless assigned to
a variable.
For instance, the widget returned by the following code:
> dialog.get_color_widget('color', True, GimpUi.ColorAreaType.FLAT)
… was freed by the PyGObject binding when it was floating, even though
(transfer none) was set (hence telling the binding it should not free
the returned object). The workaround was to assign it to some variable,
even though I was not planning to use it.
Making sure all references are full fixes it.
GObject docs also notes:
> **Note**: Floating references are a C convenience API and should not
> be used in modern GObject code. Language bindings in particular find
> the concept highly problematic, as floating references are not
> identifiable through annotations, and neither are deviations from the
> floating reference behavior, like types that inherit from
> GInitiallyUnowned and still return a full reference from
> g_object_new().
… GimpProcedureDialog.
Technically I added:
- New gimp_prop_color_select_new() property widget to create a
GimpColorButton for a given GimpRGB property.
- gimp_procedure_dialog_get_widget() now supports a GimpRGB property and
will create a GimpColorArea by default.
- When the default doesn't suit you, a new function
gimp_procedure_dialog_get_color_widget() allows to create either a
GimpColorArea or a GimpColorButton (editable = TRUE), as well as
choose the area type (small or large checks, as well as flat area,
i.e. no alpha support).
Still the same problem as ever with the Python binding where we have a
hard time creating GParamSpec, hence we make them from object
properties.
See: https://gitlab.gnome.org/GNOME/pygobject/-/issues/227#note_570031
But then again, the Python binding way to create GObject properties does
not seem to give us a way to use our custom param types (or I didn't
find how). So when I create a property with Gimp.RGB type in Python, it
doesn't appear as a GIMP_PARAM_SPEC_RGB to our C code, but as a
G_PARAM_SPEC_BOXED. So my trick is to check the value type instead.
Note that I check the default value, but in reality it doesn't seem to
work much either. Better than no support at all anyway.
… with the updated API with one more argument (n_drawables + drawables
instead of single drawable).
This went unnoticed as most plug-ins use a config with named properties
instead of ordered GimpValueArray now.
New function to set some procedure dialog's widget sensitive, either
with a constant value, or by binding it to a boolean property (or its
inverse) of a config object.
The gimp_drawable_type() is an issue though as gimp_drawable_get_type()
is already defined as a common GObject API.
Though I'm actually wondering if GimpImageType is well called. Rather
than Type, shouldn't we go with ColorModel?
sed -i 's/\<gimp_drawable_bpp\>/gimp_drawable_get_bpp/g' "$@"
sed -i 's/\<gimp_drawable_width\>/gimp_drawable_get_width/g' "$@"
sed -i 's/\<gimp_drawable_height\>/gimp_drawable_get_height/g' "$@"
sed -i 's/\<gimp_drawable_offsets\>/gimp_drawable_get_offsets/g' "$@"
… the public API.
This was initially proposed by Niels De Graef in !101, and though I
still think this is much less practical for day-to-day development, it
is actually much nicer for the public part of the API. So let's use
these only in public libgimp* API only, not in core.
I actually already started to use these for some of the libgimpwidgets
classes and am now moving libgimp main classes to these macros.
* It doesn't expose the priv member (which is completely useless for
plug-in developers, only to be used for core development).
* It forces us to never have any variable members in the public API
(which we were doing fine so far in newest API, but it's nice to be
enforced with these macros).
* When using G_DECLARE_FINAL_TYPE in particular, it adds flexibility as
we can change the structure size and the members order as these are
not exposed. And if some day, we make the class derivable with some
signals to handle, only then will we expose the class with some
_gimp_reserved* padding (instead of from the start when none is
needed). Therefore we will allow for further extension far in the
future.
Moreover most of these libgimp classes were so far not using any private
values, so we were declaring a `priv` member with a bogus contents just
"in case we needed it in future" (as we couldn't change the struct
size). So even the easiness of having a priv member was very relative
for this public API so far (unlike in core code where we actually have
much more complex interactions and using priv data all the time).
s/gimp_image_base_type/gimp_image_get_base_type/
s/gimp_image_width/gimp_image_get_width/
s/gimp_image_height/gimp_image_get_height/
Sorry plug-in developers, more porting work! But really this seems like
the right thing to do in order not to get stuck with inconsistent naming
for many more years to come.
As the docs says, this was always allowed and would just imply we want a
dialog with all properties in order of declaration.
Yet this usage would output this warning:
> plug-ins/file-fli/fli-gimp.c:976:3: warning: not enough variable arguments to fit a sentinel [-Wformat=]
This commit take care of this warning.
There was at least a case when gimp_procedure_create_config() was called
twice, hence so was gimp_save_procedure_add_metadata() when a plug-in
was run.
It was happening when calling a procedure with less arguments than the
procedure had. In such case, gimp_procedure_run() would create a config
to fill it with defaults.
Fixes warnings such as:
> LibGimp-WARNING **: 01:29:57.044: Auxiliary argument with name 'save-exif' already exists on procedure 'file-png-save'
I always found the docs misleading because when it says "Returns the
list of layers contained in the specified image", I really read "all the
layers, at any level", except it doesn't. It only returns the root
layers and it is up to the plug-in developer to loop through these if
one needs to go deeper.
So let's make the function docs clearer.
We heavily rely on GError in libgimp to retrieve plug-in error messages.
In a lot of our code, we just use domain=0 for g_set_error*() functions
and alike, but this is actually forbidden and results in GLib warnings.
Some plug-ins instead create their own domain, other use G_FILE_ERROR
nearly everywhere, even in some cases where the choice is really
questionable. Since anyway this is mostly useful for passing the error
message through, it is much nicer to provide a generic domain
GIMP_PLUG_IN_ERROR, which can be used by all plug-ins when they don't
want to bother with the error domain.
… drawable array instead of a single drawable.
Instead of expecting a single drawable, GimpImageProcedure's run()
function will now have an array of drawable as parameter.
As a consequence, all existing plug-ins are broken again. I am going to
fix them in the next commit so that this change can be easily reviewed
and examined if needed later.
I only fix the Vala demo plug-in now (or rather, I just use the first
layer in the array for now) because otherwise the build fails.
The new function gimp_procedure_set_sensitivity_mask() allows plug-ins
to tell when a procedure should be marked as sensitive or not.
gimp_procedure_get_sensitivity_mask() retrieves this information.
Currently plug-ins are automatically marked as sensitive when an image
is present and a single drawable is selected. Nowadays, we can have
multiple selected layers so we should allow plug-ins to tell us if they
support working on multiple drawables. Actually we could even imagine
new plug-ins which would be made to work only on multiple drawables.
Oppositely, there are a lot of plug-ins which don't care at all if any
drawable is selected at all (so we should allow no drawable selected).
Finally why not even imagine plug-ins which don't care if no image is
shown? E.g. plug-ins to create new images or whatnot. This new API
allows our core to know all this and show procedure sensitivity
accordingly. By default, when the function is not called, the 1 image
with 1 drawable selected case is the default, allowing existing plug-ins
easier update.
Note: this only handles the sensitivity part right now. A plug-in which
would advertize working on several layer would still not work, because
the core won't allow sending several layers. It's coming in further
commits.
Since version 0.27.3 exiv2 has changed how it returns
comments for Exif.Photo.UserComment. We now get
the comment including the charset=Ascii value.
Let's remove anything that's not part of the actual
comment. To not complicate things we will only
handle charset=Ascii for now since I've never seen
any other charset used.
1. Convert xmp /Iptc4xmpExt tag parts to /iptcExt because
exiv2 fails when we try to use the default namespace.
2. Don't only set structs from a fixed list but find all
xmp array elements and check what the best struct
type is: bag or seq.
3. Work around a sorting issue in (g)exiv2 by using a natural
sorting algorithm ourselves.
4. Added some g_debug statements to make it easier to
determine the cause of issues.
This fixes the following warning (and 4 similar others):
> libgimp/gimpimagecombobox.c:133: Warning: GimpUi: "destroy" annotation needs one option, none given
Brought by commit df766d5443. It's my fault for not properly reviewing
the patch as I failed to notice the new warnings.