darktable-org / darktable-org/darktable
Feature request: expose Lua events for tag / geotag / metadata / rating / color-label changes
@wpferguson is already working on this.
Since Jul 3, 2026.
- Dominant language
- C
- Stars
- 13.1k
- Forks
- 1.4k
- Avg merge
- 22h 14m
- Merged PRs (30d)
- 198
Description
Feature request: expose Lua events for tag / geotag / metadata / rating / color-label changes
Is your feature request related to a problem? Please describe.
The Lua scripting API (src/lua/events.c) exposes events for selection, collection,
grouping, darkroom history, image-group info, etc., but nothing fires when any of the
five per-image attributes an image is directly edited on in the lighttable change:
tags, GPS location, metadata fields (title, description, creator, rights,
...), star rating, or color labels. All five already have an internal C
signal for exactly this, but none of them are wired to dt_lua_event_add anywhere in
src/lua/*.c:
DT_SIGNAL_TAG_CHANGED(src/control/signal.h) — refreshes the native keywords
GUI, but isn't raised from the actual attach/detach write path
(dt_tag_attach_images/dt_tag_detach_images,src/common/tags.c~L470-600),
only from tag creation, tag-file import, and undo/redo.DT_SIGNAL_GEOTAG_CHANGED— the shared write functiondt_image_set_locations
(src/common/image.c:784) — used by both the lighttable "geotagging" module's
date/time-offset apply and the map module's drag-a-pin write (src/views/map.c:3034, 3139) — only raisesDT_SIGNAL_MOUSE_OVER_IMAGE_CHANGE, not
DT_SIGNAL_GEOTAG_CHANGED; that signal is instead raised piecemeal from a handful of
other call sites (src/libs/image.c:377,src/common/image.c:1884,2104, etc.).DT_SIGNAL_METADATA_CHANGED— the shared write functionsdt_metadata_set_list/
dt_metadata_set_list_id(src/common/metadata.c:739,822) — called by the
lighttable "metadata editor" module's apply handler_write_metadata
(src/libs/metadata.c:372-391) — don't raise it either; only the undo/redo path
(src/common/metadata.c:362) does.- Star ratings — the shared write function
dt_ratings_apply_on_list
(src/common/ratings.c:195), used by both the lighttable star widget and the rating
keyboard shortcuts, raises no Lua-relevant signal; again only the undo/redo pop path
raisesDT_SIGNAL_METADATA_CHANGED. - Color labels — same gap in the shared write function
dt_colorlabels_set_labels
(src/common/colorlabels.c:236), the click-a-color-dot write path.
This makes it impossible for a Lua storage/export script to react live when a user
edits any of these on an already-selected image — e.g. to refresh a panel that
mirrors that image's state against an external service. Scripts can only resync on
selection-changed, forcing users to reselect the image or click a manual refresh
button after every such edit.
Describe the solution you'd like
Add tag-changed, geotag-changed, metadata-changed, rating-changed, and
colorlabel-changed Lua events, following the existing pattern used for
image-group-information-changed in src/common/grouping.c. For each, raise the
event at the single shared write function so every caller (lighttable module, map
drag, GPX import, XMP import, keyboard shortcut, etc.) is covered by one hook instead
of many:
- tags —
dt_tag_attach_images/dt_tag_detach_imagesinsrc/common/tags.c. - geotag —
dt_image_set_locationsinsrc/common/image.c:784. - metadata —
dt_metadata_set_list/dt_metadata_set_list_idin
src/common/metadata.c:739,822. - rating —
dt_ratings_apply_on_listinsrc/common/ratings.c:195. - color label —
dt_colorlabels_set_labelsinsrc/common/colorlabels.c:236.
Guard with #ifdef USE_LUA (#include "lua/events.h" / "lua/image.h"), passing the
affected image id(s), which are already parameters of all of the above:
#ifdef USE_LUA
dt_lua_async_call_alien(dt_lua_event_trigger_wrapper,
0, NULL, NULL,
LUA_ASYNC_TYPENAME, "const char*", "tag-changed",
LUA_ASYNC_TYPENAME, "const char*", "attach",
LUA_ASYNC_TYPENAME, "dt_lua_image_t", GINT_TO_POINTER(imgid),
LUA_ASYNC_DONE);
#endif
Then register each event name once in src/lua/events.c, next to the other
multi-instance events (selection-changed, collection-changed, etc.):
dt_lua_event_add(L, "tag-changed");
dt_lua_event_add(L, "geotag-changed");
dt_lua_event_add(L, "metadata-changed");
dt_lua_event_add(L, "rating-changed");
dt_lua_event_add(L, "colorlabel-changed");
Each is a small, self-contained change (roughly the shape/size of the existing
image-group-information-changed wiring) and none requires a new DT_SIGNAL_* enum
value, since they trigger the Lua event directly at the call site. They could land as
one PR or five small independent ones.
Describe alternatives you've considered
- Polling: a script can re-read
image.tags/ GPS / metadata fields / rating /
color labels on a timer, but that's wasteful and adds latency. - Reacting to
selection-changedonly: works, but misses edits made while the same
image stays selected (the common case when editing one image at a time). - A "refresh" button as a manual workaround: functional, but pushes a
discoverability/UX burden onto the user for something native events could solve.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.