Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
location.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011-2014 Henrik Andersson.
4 Copyright (C) 2012 Robert Bieber.
5 Copyright (C) 2012, 2014, 2016-2018 Tobias Ellinghaus.
6 Copyright (C) 2013 johannes hanika.
7 Copyright (C) 2013-2016 Roman Lebedev.
8 Copyright (C) 2013 Simon Spannagel.
9 Copyright (C) 2018 Benoit Brummer.
10 Copyright (C) 2018 Maurizio Paglia.
11 Copyright (C) 2018 rawfiner.
12 Copyright (C) 2019, 2025 Aurélien PIERRE.
13 Copyright (C) 2019-2021 Pascal Obry.
14 Copyright (C) 2019 Peter Budai.
15 Copyright (C) 2020 Aldric Renaudin.
16 Copyright (C) 2021-2022 Diederik Ter Rahe.
17 Copyright (C) 2021 Philippe Weyland.
18 Copyright (C) 2021 Ralf Brown.
19 Copyright (C) 2022 luzpaz.
20 Copyright (C) 2022 Martin Bařinka.
21 Copyright (C) 2022 Miloš Komarčević.
22
23 darktable is free software: you can redistribute it and/or modify
24 it under the terms of the GNU General Public License as published by
25 the Free Software Foundation, either version 3 of the License, or
26 (at your option) any later version.
27
28 darktable is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
32
33 You should have received a copy of the GNU General Public License
34 along with darktable. If not, see <http://www.gnu.org/licenses/>.
35*/
36
37#include "common/darktable.h"
38#include "common/geo.h"
39#include "common/curl_tools.h"
40#include "control/conf.h"
41#include "control/control.h"
42#include "control/jobs.h"
43#include "dtgtk/icon.h"
44#include "gui/gtk.h"
45#include "libs/lib.h"
46#include "libs/lib_api.h"
47#include <curl/curl.h>
48#include <gdk/gdkkeysyms.h>
49
50DT_MODULE(1)
51
61
73
74typedef struct dt_lib_location_t
75{
76 GtkEntry *search;
79
80 GList *places;
81
82 /* result buffer written to by */
83 gchar *response;
85
86 /* pin, track or polygon currently shown on the map */
87 GObject *marker;
89
90 /* remember the currently selected search result so we can put it into a preset */
92
93 // place used to keep biggest polygon
96
102
103#define LIMIT_RESULT 5
104
105/* entry value committed, perform a search */
106static void _lib_location_entry_activated(GtkButton *button, gpointer user_data);
107
108static gboolean _lib_location_result_item_activated(GtkButton *button, GdkEventButton *ev, gpointer user_data);
109
110static void _lib_location_parser_start_element(GMarkupParseContext *cxt, const char *element_name,
111 const char **attribute_names, const gchar **attribute_values,
112 gpointer user_data, GError **error);
113
114static void clear_search(dt_lib_location_t *lib);
115
116const char *name(struct dt_lib_module_t *self)
117{
118 return _("find location");
119}
120
121const char **views(dt_lib_module_t *self)
122{
123 static const char *v[] = {"map", NULL};
124 return v;
125}
126
131
132
134{
136 gtk_entry_set_text(lib->search, "");
137 clear_search(lib);
138}
139
141{
142 return 999;
143}
144
145/*
146 https://nominatim.openstreetmap.org/search/norrköping?format=xml&limit=5
147 */
149{
150 self->data = calloc(1, sizeof(dt_lib_location_t));
151 dt_lib_location_t *lib = self->data;
152
153 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
154
155 /* add search box */
156 lib->search = GTK_ENTRY(gtk_entry_new());
158 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(lib->search), FALSE, FALSE, 0);
159
160 g_signal_connect(G_OBJECT(lib->search), "activate", G_CALLBACK(_lib_location_entry_activated),
161 (gpointer)self);
162
163 /* add result vbox */
164 lib->result = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
165 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(lib->result), TRUE, FALSE, 0);
166}
167
169{
170 if(IS_NULL_PTR(self->data)) return;
171 dt_free(self->data);
172}
173
174static gboolean _event_box_enter_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
175{
176 if(event->type == GDK_ENTER_NOTIFY)
177 gtk_widget_set_state_flags(widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
178 else
179 gtk_widget_unset_state_flags(widget, GTK_STATE_FLAG_PRELIGHT);
180
181 return FALSE;
182}
183
185{
186 GtkWidget *eb, *vb, *w;
187 eb = gtk_event_box_new();
188 gtk_widget_set_name(eb, "dt-map-location");
189 g_signal_connect(G_OBJECT(eb), "enter-notify-event", G_CALLBACK(_event_box_enter_leave), NULL);
190 g_signal_connect(G_OBJECT(eb), "leave-notify-event", G_CALLBACK(_event_box_enter_leave), NULL);
191
192 vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
193
194 /* add name */
195 w = gtk_label_new(place->name);
196 gtk_label_set_line_wrap(GTK_LABEL(w), TRUE);
197 gtk_widget_set_halign(w, GTK_ALIGN_START);
198 g_object_set(G_OBJECT(w), "xalign", 0.0, (gchar *)0);
199 gtk_box_pack_start(GTK_BOX(vb), w, FALSE, FALSE, 0);
200
201 /* add location coord */
202 gchar *lat = dt_util_latitude_str(place->lat);
203 gchar *lon = dt_util_longitude_str(place->lon);
204 gchar *location = g_strconcat(lat, ", ", lon, NULL);
205 w = gtk_label_new(location);
206 dt_free(lat);
207 dt_free(lon);
208 dt_free(location);
209 gtk_label_set_line_wrap(GTK_LABEL(w), TRUE);
210 gtk_widget_set_halign(w, GTK_ALIGN_START);
211 gtk_box_pack_start(GTK_BOX(vb), w, FALSE, FALSE, 0);
212
213 /* setup layout */
214 gtk_container_add(GTK_CONTAINER(eb), vb);
215
216 gtk_widget_show_all(eb);
217
218 /* connect button press signal for result item */
220 lib->callback_params = g_list_append(lib->callback_params, param);
221 param->lib = lib;
222 param->result = place;
223 g_signal_connect(G_OBJECT(eb), "button-press-event", G_CALLBACK(_lib_location_result_item_activated),
224 (gpointer)param);
225
226
227 return eb;
228}
229
230static size_t _lib_location_curl_write_data(void *buffer, size_t size, size_t nmemb, void *userp)
231{
232 dt_lib_location_t *lib = (dt_lib_location_t *)userp;
233
234 char *newdata = g_malloc0(lib->response_size + nmemb + 1);
235 if(!IS_NULL_PTR(lib->response)) memcpy(newdata, lib->response, lib->response_size);
236 memcpy(newdata + lib->response_size, buffer, nmemb);
237 dt_free(lib->response);
238 lib->response = newdata;
239 lib->response_size += nmemb;
240
241 return nmemb;
242}
243
244
245static GMarkupParser _lib_location_parser = { _lib_location_parser_start_element, NULL, NULL, NULL, NULL };
246
247
249{
250 switch(place->type)
251 {
253 return 18;
254
256 return 17;
257
259 return 12;
260
264 default:
265 return 8;
266 }
267
268 /* should never get here */
269 return 0;
270}
271
273{
274 if(lib->marker_type == MAP_DISPLAY_NONE) return;
275 dt_view_map_remove_marker(darktable.view_manager, lib->marker_type, lib->marker);
276 g_object_unref(lib->marker);
277 lib->marker = NULL;
279}
280
282{
283 dt_free(location->name);
284 g_list_free_full(location->marker_points, dt_free_gpointer);
285 location->marker_points = NULL;
286 dt_free(location);
287}
288
290{
291 dt_free(lib->response);
292 lib->response_size = 0;
293 lib->selected_location = NULL;
294
295 g_list_free_full(lib->places, (GDestroyNotify)free_location);
296 lib->places = NULL;
297
298 dt_gui_container_destroy_children(GTK_CONTAINER(lib->result));
299 g_list_free_full(lib->callback_params, dt_free_gpointer);
300 lib->callback_params = NULL;
301
302 _clear_markers(lib);
303}
304
306{
307 if(isnan(p->bbox.lon1) || isnan(p->bbox.lat1) || isnan(p->bbox.lon2) || isnan(p->bbox.lat2))
308 {
309 int32_t zoom = _lib_location_place_get_zoom(p);
310 dt_view_map_center_on_location(darktable.view_manager, p->lon, p->lat, zoom);
311 }
312 else
313 {
314 dt_view_map_center_on_bbox(darktable.view_manager, p->bbox.lon1, p->bbox.lat1, p->bbox.lon2, p->bbox.lat2);
315 }
316
317 _clear_markers(lib);
318
319 lib->marker = dt_view_map_add_marker(darktable.view_manager, p->marker_type, p->marker_points);
320 lib->marker_type = p->marker_type;
321 lib->selected_location = p;
322
324 p->marker_type == MAP_DISPLAY_POLYGON ? p->marker_points : NULL);
325}
326
327/* called when search job has been processed and
328 result has been parsed */
329static void _lib_location_search_finish(gpointer user_data)
330{
331 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
333
334 /* check if search gave us some result */
335 if(IS_NULL_PTR(lib->places)) return;
336
337 /* for each location found populate the result list */
338 for(const GList *item = lib->places; item; item = g_list_next(item))
339 {
340 _lib_location_result_t *place = (_lib_location_result_t *)item->data;
341 gtk_box_pack_start(GTK_BOX(lib->result), _lib_location_place_widget_new(lib, place), TRUE, TRUE, 0);
342 gtk_widget_show(lib->result);
343 }
344
345 /* if we only got one search result back lets
346 set center location and zoom based on place type */
348 {
350 _show_location(lib, place);
351 }
352}
353
354static gboolean _lib_location_search(gpointer user_data)
355{
356 GMarkupParseContext *ctx = NULL;
357 CURL *curl = NULL;
358 CURLcode res;
359 GError *err = NULL;
360
361 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
363 gchar *query = NULL, *text = NULL;
364
365 /* get escaped search text */
366 text = g_uri_escape_string(gtk_entry_get_text(lib->search), NULL, FALSE);
367
368 if(!(text && *text)) goto bail_out;
369
370 /* clean up previous results before adding new */
371 clear_search(lib);
372
373 /* build the query url */
374 const char *search_url = dt_conf_get_string_const("plugins/map/geotagging_search_url");
375 query = g_strdup_printf(search_url, text, LIMIT_RESULT);
376 /* load url */
377 curl = curl_easy_init();
378 if(IS_NULL_PTR(curl)) goto bail_out;
379
380 dt_curl_init(curl, FALSE);
381
382 curl_easy_setopt(curl, CURLOPT_URL, query);
383 curl_easy_setopt(curl, CURLOPT_WRITEDATA, lib);
384 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _lib_location_curl_write_data);
385 curl_easy_setopt(curl, CURLOPT_USERAGENT, (char *)darktable_package_string);
386 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
387
388 res = curl_easy_perform(curl);
389 if(res != 0) goto bail_out;
390
391 if(!lib->response) goto bail_out;
392
393 /* parse xml response and populate the result list */
394 ctx = g_markup_parse_context_new(&_lib_location_parser, 0, lib, NULL);
395 g_markup_parse_context_parse(ctx, lib->response, lib->response_size, &err);
396 if(err) goto bail_out;
397
398 /* add the places into the result list */
399 GList *item = lib->places;
400 if(IS_NULL_PTR(item)) goto bail_out;
401
402// while(item)
403// {
404// _lib_location_result_t *p = (_lib_location_result_t *)item->data;
405// fprintf(stderr, "(%f,%f) %s\n", p->lon, p->lat, p->name);
406// item = g_list_next(item);
407// }
408
409/* cleanup an exit search job */
410bail_out:
411 if(err)
412 {
413 fprintf(stderr, "location search: %s\n", err->message);
414 g_error_free(err);
415 }
416
417 if(curl) curl_easy_cleanup(curl);
418
419 dt_free(text);
420 dt_free(query);
421
422 if(ctx) g_markup_parse_context_free(ctx);
423
424 /* enable the widgets */
425 gtk_widget_set_sensitive(GTK_WIDGET(lib->search), TRUE);
426 // gtk_widget_set_sensitive(lib->result, FALSE);
427
428 return FALSE;
429}
430
431gboolean _lib_location_result_item_activated(GtkButton *button, GdkEventButton *ev, gpointer user_data)
432{
434 dt_lib_location_t *lib = param->lib;
435 _lib_location_result_t *result = param->result;
436 _show_location(lib, result);
437 return TRUE;
438}
439
440void _lib_location_entry_activated(GtkButton *button, gpointer user_data)
441{
442 dt_lib_module_t *self = (dt_lib_module_t *)user_data;
444 const gchar *text = gtk_entry_get_text(lib->search);
445 if(IS_NULL_PTR(text) || text[0] == '\0') return;
446
447 /* lock the widget while search job is performing */
448 gtk_widget_set_sensitive(GTK_WIDGET(lib->search), FALSE);
449 // gtk_widget_set_sensitive(lib->result, FALSE);
450
451 /* start a bg job for fetching results of a search */
452 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, _lib_location_search, user_data, _lib_location_search_finish);
453}
454
455
456static void _lib_location_parser_start_element(GMarkupParseContext *cxt, const char *element_name,
457 const char **attribute_names, const gchar **attribute_values,
458 gpointer user_data, GError **e)
459{
460 dt_lib_location_t *lib = (dt_lib_location_t *)user_data;
461
462 /* only interested in place element */
463 if(strcmp(element_name, "place") != 0) return;
464
465 // used to keep the biggest polygon
466 lib->marker_points = NULL;
467
468 /* create new place */
469 _lib_location_result_t *place = g_malloc0(sizeof(_lib_location_result_t));
470 if(IS_NULL_PTR(place)) return;
471
472 place->lon = NAN;
473 place->lat = NAN;
474 place->bbox.lon1 = NAN;
475 place->bbox.lat1 = NAN;
476 place->bbox.lon2 = NAN;
477 place->bbox.lat2 = NAN;
479 place->marker_points = NULL;
480
481 gboolean show_outline = dt_conf_get_bool("plugins/map/show_outline");
482 int max_outline_nodes = dt_conf_get_int("plugins/map/max_outline_nodes");
483
484 /* handle the element attribute values */
485 const gchar **aname = attribute_names;
486 const gchar **avalue = attribute_values;
487 if(*aname)
488 {
489 while(*aname)
490 {
491 if(strcmp(*aname, "display_name") == 0)
492 {
493 place->name = g_strdup(*avalue);
494 if(!(place->name)) goto bail_out;
495 }
496 else if(strcmp(*aname, "lon") == 0)
497 place->lon = g_strtod(*avalue, NULL);
498 else if(strcmp(*aname, "lat") == 0)
499 place->lat = g_strtod(*avalue, NULL);
500 else if(strcmp(*aname, "boundingbox") == 0)
501 {
502 char *endptr;
503 float lon1, lat1, lon2, lat2;
504
505 lat1 = g_ascii_strtod(*avalue, &endptr);
506 if(*endptr != ',') goto broken_bbox;
507 endptr++;
508
509 lat2 = g_ascii_strtod(endptr, &endptr);
510 if(*endptr != ',') goto broken_bbox;
511 endptr++;
512
513 lon1 = g_ascii_strtod(endptr, &endptr);
514 if(*endptr != ',') goto broken_bbox;
515 endptr++;
516
517 lon2 = g_ascii_strtod(endptr, &endptr);
518 if(*endptr != '\0') goto broken_bbox;
519
520 place->bbox.lon1 = lon1;
521 place->bbox.lat1 = lat1;
522 place->bbox.lon2 = lon2;
523 place->bbox.lat2 = lat2;
524broken_bbox:
525 ;
526 }
527 // only use the first 'geotext' entry
528 else if(show_outline &&
529 strcmp(*aname, "geotext") == 0 &&
531 {
532 if(g_str_has_prefix(*avalue, "POINT"))
533 {
534 char *endptr;
535 float lon = g_ascii_strtod(*avalue + strlen("POINT("), &endptr);
536 float lat = g_ascii_strtod(endptr, &endptr);
537 if(*endptr == ')')
538 {
541 p->lon = lon;
542 p->lat = lat;
543 place->marker_points = g_list_append(place->marker_points, p);
544 }
545 }
546 else if(g_str_has_prefix(*avalue, "LINESTRING")
547#ifdef HAVE_OSMGPSMAP_110_OR_NEWER
548 || g_str_has_prefix(*avalue, "POLYGON")
549 || g_str_has_prefix(*avalue, "MULTIPOLYGON")
550#endif
551 )
552 {
553 gboolean error = FALSE;
554 const char *startptr = *avalue;
555 char *endptr;
556 while(startptr && (*startptr == ' ' || *startptr == '(' || (*startptr >= 'A' && *startptr <= 'Z')))
557 startptr++;
558
559 int i = 0;
560 while(1)
561 {
562 float lon = g_ascii_strtod(startptr, &endptr);
563 float lat = g_ascii_strtod(endptr, &endptr);
564
565 if(*endptr == ')') // TODO: support holes in POLYGON and several forms in MULTIPOLYGON?
566 {
567 // doesn't really support MULTIPOLYGON, just keeps the biggect one
568 const int old_mp = g_list_length(lib->marker_points);
569 const int new_mp = g_list_length(place->marker_points);
570 if(g_str_has_prefix(endptr, ")),((") || g_str_has_prefix(endptr, "),("))
571 {
572 if(new_mp > old_mp)
573 {
574 g_list_free_full(lib->marker_points, dt_free_gpointer);
575 lib->marker_points = place->marker_points;
576 }
577 else
578 g_list_free_full(place->marker_points, dt_free_gpointer);
579 place->marker_points = NULL;
580 startptr = endptr + (g_str_has_prefix(endptr, ")),((") ? 5 : 3);
581 continue;
582 }
583 else
584 {
585 if(new_mp > old_mp)
586 {
587 g_list_free_full(lib->marker_points, dt_free_gpointer);
588 lib->marker_points = NULL;
589 }
590 else
591 {
592 g_list_free_full(place->marker_points, dt_free_gpointer);
593 place->marker_points = lib->marker_points;
594 }
595 lib->marker_points = NULL;
596 break;
597 }
598 }
599 if(*endptr != ',' || i > max_outline_nodes) // don't go too big for speed reasons
600 {
601 error = TRUE;
602 break;
603 }
605 p->lon = lon;
606 p->lat = lat;
607 place->marker_points = g_list_prepend(place->marker_points, p);
608 startptr = endptr+1;
609 i++;
610 }
611 place->marker_points = g_list_reverse(place->marker_points);
612 if(error)
613 {
614 g_list_free_full(place->marker_points, dt_free_gpointer);
615 place->marker_points = NULL;
616 }
617 else
618 {
619 place->marker_type = g_str_has_prefix(*avalue, "LINESTRING") ? MAP_DISPLAY_TRACK : MAP_DISPLAY_POLYGON;
620 }
621 }
622 else
623 {
624 gchar *s = g_strndup(*avalue, 100);
625 fprintf(stderr, "unsupported outline: %s%s\n", s, strlen(s) == strlen(*avalue) ? "" : " ...");
626 dt_free(s);
627 }
628 }
629 else if(strcmp(*aname, "type") == 0)
630 {
631
632 if(strcmp(*avalue, "village") == 0)
634 else if(strcmp(*avalue, "hamlet") == 0)
635 place->type = LOCATION_TYPE_HAMLET;
636 else if(strcmp(*avalue, "city") == 0)
637 place->type = LOCATION_TYPE_CITY;
638 else if(strcmp(*avalue, "administrative") == 0)
640 else if(strcmp(*avalue, "residental") == 0) // for backward compatibility
642 else if(strcmp(*avalue, "residential") == 0)
644 }
645
646 aname++;
647 avalue++;
648 }
649 }
650
651 /* check if we got sane data */
652 if(isnan(place->lon) || isnan(place->lat)) goto bail_out;
653
654 /* add place to result list */
655 lib->places = g_list_append(lib->places, place);
656
657 return;
658
659bail_out:
660 dt_free(place->name);
661 dt_free(place);
662}
663
673
675{
678
679 // we have nothing to store when the user hasn't picked a search result
680 if(IS_NULL_PTR(location)) return NULL;
681
682 const size_t size_fixed = sizeof(struct params_fixed_t);
683 const size_t size_name = strlen(location->name) + 1;
684 const size_t size_points = 2 * sizeof(float) * g_list_length(location->marker_points);
685 const size_t size_total = size_fixed + size_name + size_points;
686
687 void *params = malloc(size_total);
688 struct params_fixed_t *params_fixed = (struct params_fixed_t *)params;
689 params_fixed->relevance = location->relevance;
690 params_fixed->type = location->type;
691 params_fixed->lon = location->lon;
692 params_fixed->lat = location->lat;
693 params_fixed->bbox.lon1 = location->bbox.lon1;
694 params_fixed->bbox.lat1 = location->bbox.lat1;
695 params_fixed->bbox.lon2 = location->bbox.lon2;
696 params_fixed->bbox.lat2 = location->bbox.lat2;
697 params_fixed->marker_type = location->marker_type;
698
699 memcpy((uint8_t *)params + size_fixed, location->name, size_name);
700
701 float *points = (float *)((uint8_t *)params + size_fixed + size_name);
702 for(GList *iter = location->marker_points; iter; iter = g_list_next(iter), points += 2)
703 {
705 points[0] = point->lat;
706 points[1] = point->lon;
707 }
708
709 *size = size_total;
710 return params;
711}
712
713int set_params(dt_lib_module_t *self, const void *params, int size)
714{
716
717 const size_t size_fixed = sizeof(struct params_fixed_t);
718
719 if(size < size_fixed) return 1;
720
721 const struct params_fixed_t *params_fixed = (struct params_fixed_t *)params;
722 const char *name = (char *)((uint8_t *)params + size_fixed);
723 const size_t size_name = strlen(name) + 1;
724
725 if(size_fixed + size_name > size) return 1;
726
727 const size_t size_points = size - (size_fixed + size_name);
728
729 if(size_points % 2 * sizeof(float) != 0) return 1;
730
732
733 location->relevance = params_fixed->relevance;
734 location->type = params_fixed->type;
735 location->lon = params_fixed->lon;
736 location->lat = params_fixed->lat;
737 location->bbox.lon1 = params_fixed->bbox.lon1;
738 location->bbox.lat1 = params_fixed->bbox.lat1;
739 location->bbox.lon2 = params_fixed->bbox.lon2;
740 location->bbox.lat2 = params_fixed->bbox.lat2;
741 location->marker_type = params_fixed->marker_type;
742 location->name = g_strdup(name);
743 location->marker_points = NULL;
744
745 for(const float *points = (float *)((uint8_t *)params + size_fixed + size_name); (uint8_t *)points < (uint8_t *)params + size; points += 2)
746 {
748 p->lat = points[0];
749 p->lon = points[1];
750 location->marker_points = g_list_prepend(location->marker_points, p);
751 }
752 location->marker_points = g_list_reverse(location->marker_points);
753
754 clear_search(lib);
755 lib->places = g_list_append(lib->places, location);
756 gtk_entry_set_text(lib->search, "");
758
759 return 0;
760}
761
762// clang-format off
763// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
764// vim: shiftwidth=2 expandtab tabstop=2 cindent
765// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
766// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
char * name
const char darktable_package_string[]
int dt_conf_get_bool(const char *name)
int dt_conf_get_int(const char *name)
const char * dt_conf_get_string_const(const char *name)
void dt_curl_init(CURL *curl, gboolean verbose)
Definition curl_tools.c:35
darktable_t darktable
Definition darktable.c:181
#define g_list_is_singleton(list)
Definition darktable.h:938
#define DT_MODULE(MODVER)
Definition darktable.h:140
static void dt_free_gpointer(gpointer ptr)
Definition darktable.h:463
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
Definition darktable.h:524
#define dt_free(ptr)
Definition darktable.h:456
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
dt_geo_map_display_t
Definition geo.h:25
@ MAP_DISPLAY_POLYGON
Definition geo.h:29
@ MAP_DISPLAY_NONE
Definition geo.h:26
@ MAP_DISPLAY_POINT
Definition geo.h:27
@ MAP_DISPLAY_TRACK
Definition geo.h:28
void dt_gui_container_destroy_children(GtkContainer *container)
Definition gtk.c:2919
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnects accels when a text or search entry gets the focus, and reconnects them when it looses it....
Definition gtk.c:3225
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
const float v
static void _show_location(dt_lib_location_t *lib, _lib_location_result_t *p)
Definition location.c:305
void gui_reset(dt_lib_module_t *self)
Definition location.c:133
int set_params(dt_lib_module_t *self, const void *params, int size)
Definition location.c:713
static void clear_search(dt_lib_location_t *lib)
Definition location.c:289
void * get_params(dt_lib_module_t *self, int *size)
Definition location.c:674
static void _clear_markers(dt_lib_location_t *lib)
Definition location.c:272
static size_t _lib_location_curl_write_data(void *buffer, size_t size, size_t nmemb, void *userp)
Definition location.c:230
#define LIMIT_RESULT
Definition location.c:103
void gui_cleanup(dt_lib_module_t *self)
Definition location.c:168
static void _lib_location_parser_start_element(GMarkupParseContext *cxt, const char *element_name, const char **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error)
Definition location.c:456
static void _lib_location_entry_activated(GtkButton *button, gpointer user_data)
Definition location.c:440
static GMarkupParser _lib_location_parser
Definition location.c:245
uint32_t container(dt_lib_module_t *self)
Definition location.c:127
static gboolean _lib_location_result_item_activated(GtkButton *button, GdkEventButton *ev, gpointer user_data)
Definition location.c:431
static void _lib_location_search_finish(gpointer user_data)
Definition location.c:329
static gboolean _event_box_enter_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
Definition location.c:174
static void free_location(_lib_location_result_t *location)
Definition location.c:281
void gui_init(dt_lib_module_t *self)
Definition location.c:148
int position()
Definition location.c:140
const char ** views(dt_lib_module_t *self)
Definition location.c:121
_lib_location_type_t
Definition location.c:53
@ LOCATION_TYPE_UNKNOWN
Definition location.c:59
@ LOCATION_TYPE_VILLAGE
Definition location.c:54
@ LOCATION_TYPE_ADMINISTRATIVE
Definition location.c:57
@ LOCATION_TYPE_RESIDENTIAL
Definition location.c:58
@ LOCATION_TYPE_CITY
Definition location.c:56
@ LOCATION_TYPE_HAMLET
Definition location.c:55
float lat
Definition location.c:3
static int32_t _lib_location_place_get_zoom(_lib_location_result_t *place)
Definition location.c:248
static gboolean _lib_location_search(gpointer user_data)
Definition location.c:354
static GtkWidget * _lib_location_place_widget_new(dt_lib_location_t *lib, _lib_location_result_t *place)
Definition location.c:184
float lon
Definition location.c:2
size_t size
Definition mipmap_cache.c:3
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:347
@ DT_SIGNAL_LOCATION_CHANGED
Definition signal.h:299
struct _GtkWidget GtkWidget
Definition splash.h:29
const float const float param
dt_lib_location_t * lib
Definition location.c:99
_lib_location_result_t * result
Definition location.c:100
dt_geo_map_display_t marker_type
Definition location.c:69
_lib_location_type_t type
Definition location.c:65
dt_map_box_t bbox
Definition location.c:68
struct dt_control_signal_t * signals
Definition darktable.h:774
struct dt_view_manager_t * view_manager
Definition darktable.h:772
gchar * response
Definition location.c:83
size_t response_size
Definition location.c:84
_lib_location_result_t * selected_location
Definition location.c:91
GtkWidget * result
Definition location.c:77
dt_geo_map_display_t marker_type
Definition location.c:88
GObject * marker
Definition location.c:87
GtkEntry * search
Definition location.c:76
GList * callback_params
Definition location.c:78
GList * marker_points
Definition location.c:94
GModule *void * data
Definition lib.h:80
GtkWidget * widget
Definition lib.h:84
float lon1
Definition geo.h:40
float lat2
Definition geo.h:43
float lat1
Definition geo.h:41
float lon2
Definition geo.h:42
dt_map_box_t bbox
Definition location.c:670
dt_geo_map_display_t marker_type
Definition location.c:671
int32_t relevance
Definition location.c:666
_lib_location_type_t type
Definition location.c:667
gchar * dt_util_longitude_str(float longitude)
Definition utility.c:569
gchar * dt_util_latitude_str(float latitude)
Definition utility.c:551
@ DT_UI_CONTAINER_PANEL_RIGHT_CENTER