50#include <gdk/gdkkeysyms.h>
110#define LIMIT_RESULT 5
118 const char **attribute_names,
const gchar **attribute_values,
119 gpointer user_data, GError **
error);
125 return _(
"find location");
130 static const char *
v[] = {
"map", NULL};
143 gtk_entry_set_text(lib->
search,
"");
163 lib->
search = GTK_ENTRY(gtk_entry_new());
183 if(event->type == GDK_ENTER_NOTIFY)
184 gtk_widget_set_state_flags(widget, GTK_STATE_FLAG_PRELIGHT,
FALSE);
186 gtk_widget_unset_state_flags(widget, GTK_STATE_FLAG_PRELIGHT);
194 eb = gtk_event_box_new();
195 gtk_widget_set_name(eb,
"dt-map-location");
202 w = gtk_label_new(place->
name);
203 gtk_label_set_line_wrap(GTK_LABEL(w),
TRUE);
204 gtk_widget_set_halign(w, GTK_ALIGN_START);
205 g_object_set(G_OBJECT(w),
"xalign", 0.0, (gchar *)0);
206 gtk_box_pack_start(GTK_BOX(vb), w,
FALSE,
FALSE, 0);
211 gchar *location = g_strconcat(
lat,
", ",
lon, NULL);
212 w = gtk_label_new(location);
216 gtk_label_set_line_wrap(GTK_LABEL(w),
TRUE);
217 gtk_widget_set_halign(w, GTK_ALIGN_START);
218 gtk_box_pack_start(GTK_BOX(vb), w,
FALSE,
FALSE, 0);
221 gtk_container_add(GTK_CONTAINER(eb), vb);
223 gtk_widget_show_all(eb);
283 g_object_unref(lib->
marker);
314 if(isnan(
p->bbox.lon1) || isnan(
p->bbox.lat1) || isnan(
p->bbox.lon2) || isnan(
p->bbox.lat2))
345 for(
const GList *item = lib->
places; item; item = g_list_next(item))
349 gtk_widget_show(lib->
result);
363 GMarkupParseContext *ctx = NULL;
370 gchar *query = NULL, *text = NULL;
373 text = g_uri_escape_string(gtk_entry_get_text(lib->
search), NULL,
FALSE);
375 if(!(text && *text))
goto bail_out;
382 query = g_strdup_printf(search_url, text,
LIMIT_RESULT);
384 curl = curl_easy_init();
389 curl_easy_setopt(curl, CURLOPT_URL, query);
390 curl_easy_setopt(curl, CURLOPT_WRITEDATA, lib);
393 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
395 res = curl_easy_perform(curl);
396 if(
res != 0)
goto bail_out;
403 if(err)
goto bail_out;
406 GList *item = lib->
places;
420 fprintf(stderr,
"location search: %s\n", err->message);
424 if(curl) curl_easy_cleanup(curl);
429 if(ctx) g_markup_parse_context_free(ctx);
432 gtk_widget_set_sensitive(GTK_WIDGET(lib->
search),
TRUE);
451 const gchar *text = gtk_entry_get_text(lib->
search);
455 gtk_widget_set_sensitive(GTK_WIDGET(lib->
search),
FALSE);
464 const char **attribute_names,
const gchar **attribute_values,
465 gpointer user_data, GError **e)
470 if(strcmp(element_name,
"place") != 0)
return;
489 int max_outline_nodes =
dt_conf_get_int(
"plugins/map/max_outline_nodes");
492 const gchar **aname = attribute_names;
493 const gchar **avalue = attribute_values;
498 if(strcmp(*aname,
"display_name") == 0)
500 place->
name = g_strdup(*avalue);
501 if(!(place->
name))
goto bail_out;
503 else if(strcmp(*aname,
"lon") == 0)
504 place->
lon = g_strtod(*avalue, NULL);
505 else if(strcmp(*aname,
"lat") == 0)
506 place->
lat = g_strtod(*avalue, NULL);
507 else if(strcmp(*aname,
"boundingbox") == 0)
510 float lon1, lat1, lon2, lat2;
512 lat1 = g_ascii_strtod(*avalue, &endptr);
513 if(*endptr !=
',')
goto broken_bbox;
516 lat2 = g_ascii_strtod(endptr, &endptr);
517 if(*endptr !=
',')
goto broken_bbox;
520 lon1 = g_ascii_strtod(endptr, &endptr);
521 if(*endptr !=
',')
goto broken_bbox;
524 lon2 = g_ascii_strtod(endptr, &endptr);
525 if(*endptr !=
'\0')
goto broken_bbox;
535 else if(show_outline &&
536 strcmp(*aname,
"geotext") == 0 &&
539 if(g_str_has_prefix(*avalue,
"POINT"))
542 float lon = g_ascii_strtod(*avalue + strlen(
"POINT("), &endptr);
543 float lat = g_ascii_strtod(endptr, &endptr);
553 else if(g_str_has_prefix(*avalue,
"LINESTRING")
554#ifdef HAVE_OSMGPSMAP_110_OR_NEWER
555 || g_str_has_prefix(*avalue,
"POLYGON")
556 || g_str_has_prefix(*avalue,
"MULTIPOLYGON")
561 const char *startptr = *avalue;
563 while(startptr && (*startptr ==
' ' || *startptr ==
'(' || (*startptr >=
'A' && *startptr <=
'Z')))
569 float lon = g_ascii_strtod(startptr, &endptr);
570 float lat = g_ascii_strtod(endptr, &endptr);
577 if(g_str_has_prefix(endptr,
")),((") || g_str_has_prefix(endptr,
"),("))
587 startptr = endptr + (g_str_has_prefix(endptr,
")),((") ? 5 : 3);
606 if(*endptr !=
',' ||
i > max_outline_nodes)
631 gchar *s = g_strndup(*avalue, 100);
632 fprintf(stderr,
"unsupported outline: %s%s\n", s, strlen(s) == strlen(*avalue) ?
"" :
" ...");
636 else if(strcmp(*aname,
"type") == 0)
639 if(strcmp(*avalue,
"village") == 0)
641 else if(strcmp(*avalue,
"hamlet") == 0)
643 else if(strcmp(*avalue,
"city") == 0)
645 else if(strcmp(*avalue,
"administrative") == 0)
647 else if(strcmp(*avalue,
"residental") == 0)
649 else if(strcmp(*avalue,
"residential") == 0)
659 if(isnan(place->
lon) || isnan(place->
lat))
goto bail_out;
690 const size_t size_name = strlen(location->
name) + 1;
691 const size_t size_points = 2 *
sizeof(float) * g_list_length(location->
marker_points);
692 const size_t size_total = size_fixed + size_name + size_points;
694 void *params = malloc(size_total);
697 params_fixed->
type = location->
type;
698 params_fixed->
lon = location->
lon;
699 params_fixed->
lat = location->
lat;
706 memcpy((uint8_t *)params + size_fixed, location->
name, size_name);
708 float *points = (
float *)((uint8_t *)params + size_fixed + size_name);
709 for(GList *iter = location->
marker_points; iter; iter = g_list_next(iter), points += 2)
712 points[0] =
point->lat;
713 points[1] =
point->lon;
726 if(
size < size_fixed)
return 1;
729 const char *
name = (
char *)((uint8_t *)params + size_fixed);
730 const size_t size_name = strlen(
name) + 1;
732 if(size_fixed + size_name >
size)
return 1;
734 const size_t size_points =
size - (size_fixed + size_name);
736 if(size_points % 2 *
sizeof(
float) != 0)
return 1;
741 location->
type = params_fixed->
type;
742 location->
lon = params_fixed->
lon;
743 location->
lat = params_fixed->
lat;
752 for(
const float *points = (
float *)((uint8_t *)params + size_fixed + size_name); (uint8_t *)points < (uint8_t *)params +
size; points += 2)
763 gtk_entry_set_text(lib->
search,
"");
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnect accels while a text or search entry has the focus, and reconnect them when it loses it....
Handle default and user-set shortcuts (accelerators)
static void error(char *msg)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
int dt_conf_get_bool(const char *name)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
const char darktable_package_string[]
void dt_gui_container_destroy_children(GtkContainer *container)
struct dt_view_manager_t * dt_view_manager_get_global(void)
#define g_list_is_singleton(list)
static void _show_location(dt_lib_location_t *lib, _lib_location_result_t *p)
void gui_reset(dt_lib_module_t *self)
int set_params(dt_lib_module_t *self, const void *params, int size)
static void clear_search(dt_lib_location_t *lib)
void * get_params(dt_lib_module_t *self, int *size)
static void _clear_markers(dt_lib_location_t *lib)
static size_t _lib_location_curl_write_data(void *buffer, size_t size, size_t nmemb, void *userp)
void gui_cleanup(dt_lib_module_t *self)
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)
static void _lib_location_entry_activated(GtkButton *button, gpointer user_data)
static GMarkupParser _lib_location_parser
uint32_t container(dt_lib_module_t *self)
static gboolean _lib_location_result_item_activated(GtkButton *button, GdkEventButton *ev, gpointer user_data)
static void _lib_location_search_finish(gpointer user_data)
static gboolean _event_box_enter_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static void free_location(_lib_location_result_t *location)
void gui_init(dt_lib_module_t *self)
const char ** views(dt_lib_module_t *self)
@ LOCATION_TYPE_ADMINISTRATIVE
@ LOCATION_TYPE_RESIDENTIAL
static int32_t _lib_location_place_get_zoom(_lib_location_result_t *place)
static gboolean _lib_location_search(gpointer user_data)
static GtkWidget * _lib_location_place_widget_new(dt_lib_location_t *lib, _lib_location_result_t *place)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_LOCATION_CHANGED
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
const float const float param
_lib_location_result_t * result
dt_geo_map_display_t marker_type
_lib_location_type_t type
_lib_location_result_t * selected_location
dt_geo_map_display_t marker_type
dt_geo_map_display_t marker_type
_lib_location_type_t type
gchar * dt_util_longitude_str(float longitude)
gchar * dt_util_latitude_str(float latitude)
void dt_view_map_center_on_location(const dt_view_manager_t *vm, gdouble lon, gdouble lat, gdouble zoom)
GObject * dt_view_map_add_marker(const dt_view_manager_t *vm, dt_geo_map_display_t type, GList *points)
void dt_view_map_center_on_bbox(const dt_view_manager_t *vm, gdouble lon1, gdouble lat1, gdouble lon2, gdouble lat2)
gboolean dt_view_map_remove_marker(const dt_view_manager_t *vm, dt_geo_map_display_t type, GObject *marker)
@ DT_UI_CONTAINER_PANEL_RIGHT_CENTER