As reported by Liam, apparently for someone with a lot of filters, these
node creations just to check the aux input may add up noticeable time on
boot (it may also depend on the OS too? I didn't have any noticeable
delay personally).
Unfortunately we cannot know the presence of an aux input just with
class introspection because they can be registered by the op at runtime.
This optimization is therefore twofold:
* Since we know which filters have an aux input among all the ones with
hardcoded actions, we also hardcode this data. It means we only do the
actual check on non-hardcoded operations (third-party filters but also
GEGL operations which are not specifically listed in our code).
* I only do these checks once, stored by name in a hash table, because
filters_actions_setup() is actually run several times (for different
menus).
This should improve startup time a lot for people who experienced this
delay.
Though I can't reproduce on Linux, the performance log seems to show we
spend too much time inside filters_actions_update(). Instead of creating
nodes at each update, let's just store the information about which
filter action has pad, since this should not change within the timespan
of a given session.
Remove most of the per-action special-casing. This won't scale, and in
fact it already doesn't work well with all generated actions from GEGL
operations. Considering that any third-party operation will generate an
action too, this just can't work.
Instead we know that:
- Filters on group, vector and link layers must always be run
non-destructively.
- Non-interactive filters are always run destructively and therefore
cannot be run on group, vector or link layers.
- GEGL graph as well, unless a specific environment is set.
- All operations with auxiliary inputs cannot be run non-destructively
(yet) either and therefore must also be deactivated on these layer
types.
A few more actions are still special-cased (in particular regarding
being used on grayscale drawable or on formats with an alpha channel),
though it would be nice if we could generalize these somehow eventually
too.
In an upcoming commit a new user of gimp_gegl_get_op_classes will expect
a list of all operations supported/allowed in GIMP and not just the ones
that are not exposed in the GUI.
In an upcoming commit a new user of gimp_gegl_get_op_classes will expect
a list of all operations supported/allowed in GIMP and not just the ones
that are not exposed in the GUI.
With the same change, this switches from maintaining a list of
operations exposed as an action, this now uses the actions themselves
for the filtering. During this I found some operations that were in the
"exposed in GUI sub-list" were in-fact not exposed but were straight up
blocked. I moved them to the appropriate sub-list along with the
justifications I found in the commit history.
This is an alternative implementation for issue #12825, replacing commit
424ef17bac, after further discussion with Jacob.
Basically we don't need a new key "gimp:help-id" anymore. Instead, for
every action we add through a "gimp:menu-path" key AND when its name is
prefixed with "gegl:", we generate a help ID from the operation name.
The first few operations in such case already have a help page for them,
with corresponding help ID, in gimp-help repository.
In the future, we may expand this help ID generation rule to any
core operation (i.e. any operation prefixed with "gegl:") but for the
time being, we only do for the ones with a menu path, otherwise we'd
have too many missing pages.
Also fix again gimp_gegl_procedure_get_help_id() so that it searches a
help ID within all existing operations in the "filters" group, as I
realized that this was still broken in some cases.
Resolves #12160
Currently, GEGL Graph and filters with Aux nodes can only be
applied destructively. Therefore, we need to add a restriction so
they can't be applied when a layer group is selected.
Even though it's just for 3 dots, this may actually be formatted differently in
different languages. Let's not assume we all share this punctuation mark.
For all the test-ops thus far in gegl, gimp:menu-label has been
the same as title + "..", to keep the number of duplicate strings
that need to be translated and the number of needed boiler-plate
lines of meta-data in GEGL down, this is the default behavior when
a title key exists.
Instead of unconditionally add all the non-special-cased GEGL operations into
the menu, only insert the ones which explicitly use the new "gimp:menu-path"
GEGL key.
See new operation "gegl:adaptive-threshold" added in commit 7c2a70eee for such
an example.
Note that the other operations will still get their own generated action (which
means for instance that you can still search them through the action search and
that you can create custom shortcuts for your favorite actions). But now you
won't get an overlong generic list of non-organized actions in a single submenu.
Some people were finding this messy when they had a lot of custom GEGL ops.
Also it means that GIMP doesn't assume that any custom GEGL op is usable in
GIMP. Indeed some ops are really not meant to be used as filters, which is why
we have the gimp_gegl_op_blacklisted() internal function; but this cannot apply
to custom operations. Therefore from now on, instead of GIMP guessing, operation
developers will have the say on whether their op should show in menus and in
which menu path exactly!
Moreover the "gimp:menu-label" key will be used as short label, i.e. the label
which is used in menus in particular, where the menu path is a helpful context
(hence allowing to use shorter menu labels).
The main "title" will still be used as long label, for places where there is no
such context, for instance the action search.
When reverting commit d51c64ec06 and reimplementing as fa2e9adc29, the code to
make sure the generated per-op action name is unique disappeared. This code
ensures that the action name is indeed unique, otherwise the action will
override a previously registed action, which could be made from a plug-in, or
even by another GEGL operation. Indeed, while GEGL operation names are supposed
to be unique, they are post-processed to be valid GIO action names. So it is
totally possible to have 2 GEGL ops with different GEGL names, yet the same
GAction name.
With our old code, we needed dummy actions for every submenu. This is not needed
anymore. Actions are only for end menu items (items which actually do something,
not just open a submenu).
Get rid of them all, as well as the code to ignore any action ending with such
suffixes in action-listing pieces of code.
All Gimp*ActionEntry (except GimpProcedureActionEntry) now have a short_label
member.
This commit doesn't add any new short label yet. It just fixes the struct usage,
and fixes a few localization contexts here and there when I saw such broken
strings.
I also fixed a few gradient editor action strings which were not proper labels
(like "splitmidpoint" or "splituniform", or missing uppercase, etc.).
Since we now generate actions for GEGL ops, we might as well generate menu items
for these too.
What I did:
- Move the "GEGL Operation…" tool (generic dialog with a drop-down list of all
non-ignored GEGL ops) to Tools menu.
- Create a "GEGL Operations" submenu in Filters > Generic.
- Move "GEGL Graph" to the top of this new submenu.
- Generate a new menu item for each generated action tied to a GEGL plug-in,
alphabetically sorted.
- The `accelerator` variable is a NULL-terminated array, allowing up to 3
accelerators per action (so far, none has more than 2).
- Only the struct GimpProcedureActionEntry still has a single accelerator as I
don't think it makes sense that we change the plug-in API to allow a plug-in
to register more than 1 shortcut for a procedure (e.g. we don't want a plug-in
to just register all possible keys for their procedure!).
Of course, users will still be allowed to register more shortcuts for plug-in
actions through the shortcut dialog. It's only the initialization which
1-shortcut max for procedure actions.
- Remove all actions ending up in "-accel" as these were only a trick to
register more shortcut for a same action. Now we just have the real
possibility (rather than creating bogus duplicate actions). As a consequence,
these actions accelerators have been moved as secondary accelerator to their
main action.
The deleted actions are: "view-zoom-out-accel", "view-zoom-in-accel",
"view-zoom-16-1-accel", "view-zoom-4-1-accel", "view-zoom-2-1-accel" and
"view-zoom-1-1-accel".
In particular, if painting on a layer whose parent's pixels are locked,
we were blinking an empty lock spot, which is confusing. Now
gimp_item_is_content_locked() will also return the proper item (when
relevant, i.e. when returning TRUE) which is locked. It may or may not
the same item as passed in (it may also be a parent item in particular).
In some cases, in particular for actions generated from plug-in
procedure right now, we were displaying the reason of the insensitivity
(typically right now, only the drawable type is cited). This was done by
appending the reason to the tooltip, separated by 2 newlines, which
resulted in extra ugly design, no nice way to style this info directly
(with pango for instance if the widget display allows it, or on a
separate info widget in a possible future, or whatnot).
Also it would mean that the action search could match a disabled action
by mistake if a search word happens to be in the reason message.
This improves the situation with the following changes:
* gimp_action_set_sensitive() now takes an optional reason string to set
the reason message.
* Same for gimp_action_group_set_action_sensitive().
* gimp_action_get_sensitive() returns an optional reason string.
* gimp_procedure_get_sensitive()'s tooltip return value now becomes a
reason (it won't contain anymore the tooltip and the reason
concatenated, only the reason for separate processing).
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.
gegl:focus-blur blurs the image around a focal point. It can be
used to create fake depth-of-field effects.
Add a prop-gui constructor which uses a FOCUS controller to control
the focus geometry.
Don't disable color-to-alpha for grayscale drawable, since the
operation is applicable to grayscale images (in particular, it
doesn't add color where there was none), and since we no longer
distinguish between layers and channels according to the drawable
format when updating the filters actions.
... (used to add one automatically)
In GimpFilterTool and gimp_drawable_apply_operation(), use
gimp_drawable_filter_set_add_alpha() to add an alpha channel when
applying an operation that specifies "needs-alpha" to a drawable
that can have alpha.
Don't disable gegl:color-to-alpha (which has "needs-alpha") when
the drawable doesn't have an alpha channel, if one can be added.
Change all action callbacks so they can be invoked by a GAction:
- add GimpActionCallback typedef:
void (* cb) (GimpAction*, GVariant*, gpointer)
- change all action callbacks to the GimpActionCallback signature
- add "gimp-activate" and "gimp-change-state" signals to GimpAction,
with the same signature as the resp. GAction signals
- remove all other custom action signals and only use the new
GimpAction signals
- pass around appropriate GVariants containing booleans, int32,
strings
- badly hack around to force a GimpProcedure pointer into a
uint64 variant
- remove all G_CALLBACK() casts from all action callbacks,
they all have the same signature now
Step one: get rid of all those deprecation warnings that make
it hard to see any other warnings:
- add a lot of dummy API to GimpAction, GimpActionGroup, GimpUIManager
etc. which simply forwards to the deprecated GTK functions, they
will all go away again later
- rename GimpAction to GimpActionImpl
- add interface GimpAction that is implemented by all action classes,
creates a common interface and allows to remove some duplicated
logic from GimpToggleAction and GimpRadioAction, and at the same
time adds more features
Add a new Offset filter tool, as a front-end to gimp:offset. The
tool replaces, and provides the same interface as, the drawable-
offset dialog, while also providing live preview and on-canvas
interaction.
Note that we don't simply use a custom propgui constructor for
gimp:offset, since we need a little more control.
Return an optional tooltip from gimp_procedure_get_sensitive(), in
GimpPlugInProcedure, build that tooltip from the image types the
procedure works on.