66#ifdef GDK_WINDOWING_QUARTZ
70#include <gdk/gdkkeysyms.h>
71#include <glib/gstdio.h>
87#define DT_GEOTAG_PARTS_NB 7
181 return _(
"Datetime and GPS");
187 static const char *
v[] = {
"lighttable",
"map",
"studio_capture", NULL};
189 static const char *
v[] = {
"lighttable",
"studio_capture", NULL};
226 if(!g_ascii_strcasecmp(filter_info->mime_type,
"application/gpx+xml"))
return TRUE;
228 const gchar *filename = filter_info->filename;
229 const char *cc = filename + strlen(filename);
230 for(; *cc !=
'.' && cc > filename; cc--)
233 if(!g_ascii_strcasecmp(cc,
".gpx"))
return TRUE;
239 const int col,
const int line,
const int ellipsize)
242 gtk_label_set_ellipsize(GTK_LABEL(label), ellipsize);
243 if(ellipsize != PANGO_ELLIPSIZE_NONE)
244 gtk_widget_set_visible(label,
TRUE);
245 gtk_widget_set_halign(label, align);
246 gtk_widget_set_hexpand(label,
TRUE);
247 gtk_grid_attach(GTK_GRID(grid), label, col, line, 1, 1);
254 GDateTime *local_dt = g_date_time_to_timezone(utc_dt, tz_camera);
255 gchar *dts = g_date_time_format(local_dt, full ?
"%Y:%m:%d %H:%M:%S" :
"%H:%M:%S");
256 g_date_time_unref(local_dt);
261 GTimeZone *tz_camera, GTimeZone *tz_utc,
265 GDateTime *dt_offset = g_date_time_add(exif_time, offset);
266 GDateTime *utc_time = g_date_time_to_timezone(dt_offset, tz_utc);
268 g_date_time_unref(exif_time);
269 g_date_time_unref(dt_offset);
279 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
285 if((g_date_time_compare(dt,
t->start_dt) >= 0
286 && g_date_time_compare(dt,
t->end_dt) <= 0)
287 || (
n && g_date_time_compare(dt,
t->end_dt) >= 0
288 && g_date_time_compare(dt,
n->start_dt) <= 0))
293 g_date_time_unref(dt);
302 gchar *dts = g_date_time_format(utc_dt, full ?
"%Y:%m:%d %H:%M:%S" :
"%H:%M:%S");
312 gchar *
res = g_strdup_printf(
"%s -> %s LT\n%s -> %s UTC", dtsl, dtel, dtsu, dteu);
323 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
337 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
340 if(im->
segid == segid && active)
345 g_date_time_unref(dt);
347 else if(im->
segid == segid && !active && im->
image)
355 for(GList *
i =
d->imgs; active &&
i;
i = g_list_next(
i))
367 struct {int32_t imgid;
float latitude;
float longitude;
int count;}
p;
371 p.count = count == 1 ? 0 : count;
372 GList *img = g_list_prepend(NULL, &
p);
385 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
387 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
389 for(
int segid = 0; valid && segid <
d->map.nb_tracks; segid++)
397 valid = gtk_tree_model_iter_next(
model, &iter);
399 d->map.nb_imgs = nb_imgs;
400 gchar *nb = g_strdup_printf(
"%d/%d", nb_imgs,
d->nb_imgs);
401 gtk_label_set_text(GTK_LABEL(
d->map.nb_imgs_label), nb);
408 gtk_widget_set_sensitive(
d->map.preview_button,
d->map.nb_tracks);
409 GtkWidget *label = gtk_bin_get_child(GTK_BIN(
d->map.apply_gpx_button));
410 gtk_label_set_text(GTK_LABEL(label),
d->offset ? _(
"apply offset and geo-location")
411 : _(
"apply geo-location"));
412 gtk_widget_set_tooltip_text(
d->map.apply_gpx_button,
413 d->offset ? _(
"apply offset and geo-location to matching images"
414 "\ndouble operation: two ctrl-Z to undo")
415 : _(
"apply geo-location to matching images"));
416 gtk_widget_set_sensitive(
d->map.apply_gpx_button,
d->map.nb_imgs);
417 gtk_widget_set_sensitive(
d->map.select_button,
418 d->map.nb_imgs &&
d->map.nb_imgs !=
d->nb_imgs);
425 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
429 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
436 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
439 if(im->
segid == segid)
440 imgs = g_list_prepend(imgs, GINT_TO_POINTER(im->
imgid));
443 valid = gtk_tree_model_iter_next(
model, &iter);
452 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
454 const gboolean
preview = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->map.preview_button));
455 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
456 for(
int segid = 0; valid && segid <
d->map.nb_tracks; segid++)
461 valid = gtk_tree_model_iter_next(
model, &iter);
471 d->map.tracks->td[segid].map_box.lon1 = 180.0;
472 d->map.tracks->td[segid].map_box.lon2 = -180.0;
473 d->map.tracks->td[segid].map_box.lat1 = -90.0;
474 d->map.tracks->td[segid].map_box.lat2 = 90.0;
475 for(GList *pt = pts; pt; pt = g_list_next(pt))
478 if(
p->lon <
d->map.tracks->td[segid].map_box.lon1)
479 d->map.tracks->td[segid].map_box.lon1 =
MAX(-180.0,
p->lon);
480 if(
p->lon >
d->map.tracks->td[segid].map_box.lon2)
481 d->map.tracks->td[segid].map_box.lon2 =
MIN(180.0,
p->lon);
482 if(
p->lat >
d->map.tracks->td[segid].map_box.lat1)
483 d->map.tracks->td[segid].map_box.lat1 =
MIN(90.0,
p->lat);
484 if(
p->lat <
d->map.tracks->td[segid].map_box.lat2)
485 d->map.tracks->td[segid].map_box.lat2 =
MAX(-90.0,
p->lat);
494 for(
int i = 0;
i <
d->map.nb_tracks;
i++)
496 if(
d->map.tracks->td[
i].track)
498 if(
d->map.tracks->td[
i].map_box.lon1 < lon1)
499 lon1 =
d->map.tracks->td[
i].map_box.lon1;
500 if(
d->map.tracks->td[
i].map_box.lon2 > lon2)
501 lon2 =
d->map.tracks->td[
i].map_box.lon2;
502 if(
d->map.tracks->td[
i].map_box.lat1 > lat1)
503 lat1 =
d->map.tracks->td[
i].map_box.lat1;
504 if(
d->map.tracks->td[
i].map_box.lat2 < lat2)
505 lat2 =
d->map.tracks->td[
i].map_box.lat2;
508 const gboolean grow = lon1 <
d->map.map_box.lon1 || lon2 >
d->map.map_box.lon1 ||
509 lat1 >
d->map.map_box.lat1 || lat2 <
d->map.map_box.lat2;
510 d->map.map_box.lon1 = lon1;
511 d->map.map_box.lon2 = lon2;
512 d->map.map_box.lat1 = lat1;
513 d->map.map_box.lat2 = lat2;
523 for(
int i = 0;
i <
d->map.nb_tracks;
i++)
525 if(
d->map.tracks->td[
i].track)
528 d->
map.tracks->td[
i].track);
529 d->map.tracks->td[
i].track = NULL;
541GdkRGBA
color[] = {(GdkRGBA){.red = 1.0, .green = 0.0, .blue = 0.0, .alpha = 0.5 },
542 (GdkRGBA){.red = 0.0, .green = 1.0, .blue = 1.0, .alpha = 0.5 },
543 (GdkRGBA){.red = 0.0, .green = 0.0, .blue = 1.0, .alpha = 0.5 },
544 (GdkRGBA){.red = 1.0, .green = 1.0, .blue = 0.0, .alpha = 0.5 },
545 (GdkRGBA){.red = 0.0, .green = 1.0, .blue = 0.0, .alpha = 0.5 },
546 (GdkRGBA){.red = 1.0, .green = 0.0, .blue = 1.0, .alpha = 0.5 }};
551 gboolean grow =
FALSE;
555 if(!
d->map.tracks->td[segid].track)
558 osm_gps_map_track_set_color((OsmGpsMapTrack *)
d->map.tracks->td[segid].track, &
color[segid % 6]);
565 if(
d->map.tracks->td[segid].track != NULL)
567 d->
map.tracks->td[segid].track);
568 d->map.tracks->td[segid].track = NULL;
577 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
579 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
580 gboolean grow =
FALSE;
581 for(
int segid = 0; valid && segid <
d->map.nb_tracks; segid++)
586 valid = gtk_tree_model_iter_next(
model, &iter);
592 d->
map.map_box.lon2,
d->
map.map_box.lat2);
600 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
602 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
606 gtk_tree_model_get_iter(
model, &iter, path);
610 gtk_tree_path_free(path);
616 d->
map.map_box.lon2,
d->
map.map_box.lat2);
619 const gboolean
preview = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->map.preview_button));
628 GtkWidget *toggle = gtk_tree_view_column_get_widget(column);
629 gboolean active = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle));
630 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), active);
632 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
634 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
635 gboolean grow =
FALSE;
636 for(
int segid = 0; valid && segid <
d->map.nb_tracks; segid++)
638 gtk_list_store_set(GTK_LIST_STORE(
model), &iter,
641 valid = gtk_tree_model_iter_next(
model, &iter);
646 d->
map.map_box.lon2,
d->
map.map_box.lat2);
674 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
677 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
679 gboolean valid = gtk_tree_model_get_iter_first(
model, &iter);
680 for(GList *ts = trkseg; ts && valid; ts = g_list_next(ts))
688 gtk_list_store_set(GTK_LIST_STORE(
model), &iter,
696 valid = gtk_tree_model_iter_next(
model, &iter);
707 d->map.gpx =
dt_gpx_new(gtk_label_get_text(GTK_LABEL(
d->map.gpx_file)));
708 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
d->map.gpx_view));
710 gtk_tree_view_set_model(GTK_TREE_VIEW(
d->map.gpx_view), NULL);
711 gtk_list_store_clear(GTK_LIST_STORE(
model));
714 d->map.nb_tracks = g_list_length(trkseg);
718 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
722 const gboolean active = gtk_toggle_button_get_active(
723 GTK_TOGGLE_BUTTON(gtk_tree_view_column_get_widget(
d->map.sel_tracks)));
725 for(GList *ts = trkseg; ts; ts = g_list_next(ts))
731 gtk_list_store_append(GTK_LIST_STORE(
model), &iter);
732 gtk_list_store_set(GTK_LIST_STORE(
model), &iter,
744 gtk_tree_view_set_model(GTK_TREE_VIEW(
d->map.gpx_view),
model);
745 g_object_unref(
model);
747 gtk_tree_view_column_set_clickable(
d->map.sel_tracks,
TRUE);
762 GList *imgs2 = g_list_copy(imgs);
768 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
d->map.preview_button),
FALSE);
774 gtk_widget_set_visible(
d->gpx_button, !
d->map.view);
775 gtk_widget_set_visible(
d->map.gpx_section,
d->map.view);
782 if(old_view != new_view)
797 if(
d->map.view && !locid)
808 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
822 GtkTreePath *path = NULL;
823 GtkTreeViewColumn *column = NULL;
826 gtk_tree_view_convert_widget_to_bin_window_coords(GTK_TREE_VIEW(
view),
x, y, &tx, &ty);
827 if(gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(
view), tx, ty, &path, &column, NULL, NULL))
829 GtkTreeModel *
model = gtk_tree_view_get_model(GTK_TREE_VIEW(
view));
831 if(gtk_tree_model_get_iter(
model, &iter, path))
835 if(text && text[0] !=
'\0')
837 gtk_tooltip_set_text(
tooltip, text);
843 gtk_tree_path_free(path);
852 GtkWidget *dialog = gtk_dialog_new_with_buttons(
853 _(
"GPX file track segments"), GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT,
854 _(
"done"), GTK_RESPONSE_CANCEL, NULL);
856 gchar *filedir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
860 GtkWidget *area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
861 GtkWidget *w = gtk_scrolled_window_new(NULL, NULL);
863 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
864 gtk_box_pack_start(GTK_BOX(area), w,
TRUE,
TRUE, 0);
872 _set_up_label(_(
"name"), GTK_ALIGN_START, grid, 0, line, PANGO_ELLIPSIZE_NONE);
873 _set_up_label(_(
"start time"), GTK_ALIGN_START, grid, 1, line, PANGO_ELLIPSIZE_NONE);
874 _set_up_label(_(
"end time"), GTK_ALIGN_START, grid, 2, line, PANGO_ELLIPSIZE_NONE);
875 _set_up_label(_(
"points"), GTK_ALIGN_CENTER, grid, 3, line, PANGO_ELLIPSIZE_NONE);
876 _set_up_label(_(
"images"), GTK_ALIGN_CENTER, grid, 4, line, PANGO_ELLIPSIZE_NONE);
878 for(GList *
i =
d->imgs;
i;
i = g_list_next(
i))
883 for(GList *ts = trkseg; ts; ts = g_list_next(ts))
890 total_imgs += nb_imgs;
892 _set_up_label(
t->name, GTK_ALIGN_START, grid, 0, line, PANGO_ELLIPSIZE_NONE);
893 _set_up_label(dts, GTK_ALIGN_START, grid, 1, line, PANGO_ELLIPSIZE_NONE);
894 _set_up_label(dte, GTK_ALIGN_START, grid, 2, line, PANGO_ELLIPSIZE_NONE);
895 char *nb = g_strdup_printf(
"%d",
t->nb_trkpt);
896 _set_up_label(nb, GTK_ALIGN_CENTER, grid, 3, line, PANGO_ELLIPSIZE_NONE);
898 nb = g_strdup_printf(
"%d", nb_imgs);
899 _set_up_label(nb, GTK_ALIGN_CENTER, grid, 4, line, PANGO_ELLIPSIZE_NONE);
902 total_pts +=
t->nb_trkpt;
907 char *nb = g_strdup_printf(
"%d", total_pts);
908 _set_up_label(nb, GTK_ALIGN_CENTER, grid, 3, line, PANGO_ELLIPSIZE_NONE);
910 nb = g_strdup_printf(
"%d / %d", total_imgs,
d->nb_imgs);
911 _set_up_label(nb, GTK_ALIGN_CENTER, grid, 4, line, PANGO_ELLIPSIZE_NONE);
916 gtk_container_add(GTK_CONTAINER(w), grid);
918#ifdef GDK_WINDOWING_QUARTZ
921 gtk_widget_show_all(dialog);
922 gtk_dialog_run(GTK_DIALOG(dialog));
924 gtk_widget_destroy(dialog);
929 return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
957 for(GList *l =
selected; l; l = g_list_next(l))
959 const int32_t imgid = GPOINTER_TO_INT(l->data);
970 d->imgs = g_list_prepend(
d->imgs, img);
981 GtkWidget *filechooser = gtk_file_chooser_dialog_new(
982 _(
"open GPX file"), GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
983 _(
"preview"), GTK_RESPONSE_ACCEPT,
984 _(
"_cancel"), GTK_RESPONSE_CANCEL,
985 _(
"_open"), GTK_RESPONSE_OK, (
char *)NULL);
986#ifdef GDK_WINDOWING_QUARTZ
992 GtkFileFilter *filter;
993 filter = GTK_FILE_FILTER(gtk_file_filter_new());
994 gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME | GTK_FILE_FILTER_MIME_TYPE,
996 gtk_file_filter_set_name(filter, _(
"GPS data exchange format"));
997 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
999 filter = GTK_FILE_FILTER(gtk_file_filter_new());
1000 gtk_file_filter_add_pattern(filter,
"*");
1001 gtk_file_filter_set_name(filter, _(
"all files"));
1002 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
1007 int res = gtk_dialog_run(GTK_DIALOG(filechooser));
1008 while(
res == GTK_RESPONSE_ACCEPT)
1011 res = gtk_dialog_run(GTK_DIALOG(filechooser));
1013 if(
res == GTK_RESPONSE_OK)
1017 gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
1022 gtk_label_set_text(GTK_LABEL(
d->map.gpx_file), filename);
1024 gtk_widget_set_visible(
d->map.gpx_view,
d->map.view);
1039 gtk_widget_destroy(filechooser);
1049 gboolean utc_neg_a = g_str_has_prefix(tz_a->
display,
"(UTC-");
1050 gboolean utc_neg_b = g_str_has_prefix(tz_b->
display,
"(UTC-");
1052 gboolean utc_pos_a = g_str_has_prefix(tz_a->
display,
"(UTC+");
1053 gboolean utc_pos_b = g_str_has_prefix(tz_b->
display,
"(UTC+");
1055 if(utc_neg_a && utc_neg_b)
1057 char *iter_a = tz_a->
display + strlen(
"(UTC-");
1058 char *iter_b = tz_b->
display + strlen(
"(UTC-");
1060 while(((*iter_a >=
'0' && *iter_a <=
'9') || *iter_a ==
':') &&
1061 ((*iter_b >=
'0' && *iter_b <=
'9') || *iter_b ==
':'))
1063 if(*iter_a != *iter_b)
return *iter_b - *iter_a;
1068 else if(utc_neg_a && utc_pos_b)
return -1;
1069 else if(utc_pos_a && utc_neg_b)
return 1;
1078 GList *timezones = NULL;
1087#define MAX_LINE_LENGTH 256
1092 gchar *zone_tab = g_strdup(
"/usr/share/zoneinfo/zone.tab");
1093 if(!g_file_test(zone_tab, G_FILE_TEST_IS_REGULAR))
1096 zone_tab = g_strdup(
"/usr/lib/zoneinfo/zone.tab");
1097 if(!g_file_test(zone_tab, G_FILE_TEST_IS_REGULAR))
1100 zone_tab = g_build_filename(g_getenv(
"TZDIR"),
"zone.tab", NULL);
1101 if(!g_file_test(zone_tab, G_FILE_TEST_IS_REGULAR))
1106 zone_tab = g_build_filename(datadir,
"zone.tab", NULL);
1107 if(!g_file_test(zone_tab, G_FILE_TEST_IS_REGULAR))
1118 fp = g_fopen(zone_tab,
"r");
1125 if(line[0] ==
'#' || line[0] ==
'\0')
continue;
1126 gchar **tokens = g_strsplit_set(line,
" \t\n", 0);
1129 int n_found = -1,
i;
1130 for(
i = 0; tokens[
i] && n_found < 2;
i++)
if(*tokens[
i]) n_found++;
1136 gchar *
name = g_strdup(tokens[
i - 1]);
1143 size_t last_char = strlen(
name) - 1;
1144 if(
name[last_char] ==
'\n')
name[last_char] =
'\0';
1148 timezones = g_list_prepend(timezones, tz_tuple);
1158 utc->name =
utc->display;
1159 timezones = g_list_prepend(timezones,
utc);
1161#undef MAX_LINE_LENGTH
1165 char *keypath =
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
1168 if(RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1172 &hKey) == ERROR_SUCCESS)
1174 DWORD n_subkeys, max_subkey_len;
1176 if(RegQueryInfoKey(hKey,
1187 NULL) == ERROR_SUCCESS)
1189 wchar_t *subkeyname = (
wchar_t *)malloc(
sizeof(
wchar_t) * (max_subkey_len + 1));
1191 for(DWORD
i = 1;
i < n_subkeys;
i++)
1193 DWORD subkeyname_length = max_subkey_len + 1;
1194 if(RegEnumKeyExW(hKey,
1201 NULL) == ERROR_SUCCESS)
1204 char *subkeyname_utf8 = g_utf16_to_utf8(subkeyname, -1, NULL, NULL, NULL);
1205 char *subkeypath_utf8 = g_strconcat(keypath,
"\\", subkeyname_utf8, NULL);
1206 wchar_t *subkeypath = g_utf8_to_utf16(subkeypath_utf8, -1, NULL, NULL, NULL);
1207 if(RegGetValueW(HKEY_LOCAL_MACHINE,
1213 &buffer_size) == ERROR_SUCCESS)
1215 wchar_t *display_name = (
wchar_t *)malloc(buffer_size);
1216 if(RegGetValueW(HKEY_LOCAL_MACHINE,
1222 &buffer_size) == ERROR_SUCCESS)
1226 tz->
name = subkeyname_utf8;
1227 tz->
display = g_utf16_to_utf8(display_name, -1, NULL, NULL, NULL);
1228 timezones = g_list_prepend(timezones, tz);
1230 subkeyname_utf8 = NULL;
1258 const gboolean neg = offset_int < 0;
1259 gtk_label_set_text(GTK_LABEL(
d->of.sign), neg ?
"- " :
"");
1261 GTimeSpan off = neg ? -offset_int : offset_int;
1264 gint64 total_ms = off / 1000;
1267 gint ms = total_ms % 1000;
1268 gint64 total_s = total_ms / 1000;
1270 gint s = total_s % 60;
1271 gint64 total_m = total_s / 60;
1273 gint
m = total_m % 60;
1274 gint64 total_h = total_m / 60;
1276 gint h = total_h % 24;
1277 gint64 total_d = total_h / 24;
1279 gint D = total_d % 100;
1284 g_snprintf(text,
sizeof(text),
"%03d", ms);
1285 gtk_entry_set_text(GTK_ENTRY(
d->of.widget[6]), text);
1287 g_snprintf(text,
sizeof(text),
"%02d", s);
1288 gtk_entry_set_text(GTK_ENTRY(
d->of.widget[5]), text);
1290 g_snprintf(text,
sizeof(text),
"%02d",
m);
1291 gtk_entry_set_text(GTK_ENTRY(
d->of.widget[4]), text);
1293 g_snprintf(text,
sizeof(text),
"%02d", h);
1294 gtk_entry_set_text(GTK_ENTRY(
d->of.widget[3]), text);
1296 g_snprintf(text,
sizeof(text),
"%02d", D);
1297 gtk_entry_set_text(GTK_ENTRY(
d->of.widget[2]), text);
1301 gtk_label_set_text(GTK_LABEL(
d->of.sign),
"");
1303 gtk_entry_set_text(GTK_ENTRY(
d->of.widget[
i]),
"-");
1305 const gboolean locked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->lock_offset));
1306 gtk_widget_set_sensitive(
d->apply_offset,
d->imgid && valid && !off2 && offset_int);
1307 gtk_widget_set_sensitive(
d->lock_offset, locked || (
d->imgid && valid && !off2 && offset_int));
1308 gtk_widget_set_sensitive(
d->apply_datetime,
d->imgid && !locked);
1323 char value[8] = {0};
1324 snprintf(
value,
sizeof(
value),
"%04d", g_date_time_get_year(datetime));
1325 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[0]),
value);
1326 snprintf(
value,
sizeof(
value),
"%02d", g_date_time_get_month(datetime));
1327 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[1]),
value);
1328 snprintf(
value,
sizeof(
value),
"%02d", g_date_time_get_day_of_month(datetime));
1329 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[2]),
value);
1330 snprintf(
value,
sizeof(
value),
"%02d", g_date_time_get_hour(datetime));
1331 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[3]),
value);
1332 snprintf(
value,
sizeof(
value),
"%02d", g_date_time_get_minute(datetime));
1333 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[4]),
value);
1334 snprintf(
value,
sizeof(
value),
"%02d", g_date_time_get_second(datetime));
1335 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[5]),
value);
1336 snprintf(
value,
sizeof(
value),
"%03d", (
int)(g_date_time_get_microsecond(datetime) * 0.001));
1337 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[6]),
value);
1342 gtk_entry_set_text(GTK_ENTRY(dtw->
widget[
i]),
"-");
1353 const int year = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[0])));
1354 const int month = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[1])));
1355 const int day = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[2])));
1356 const int hour = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[3])));
1357 const int minute = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[4])));
1358 const int second = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[5])));
1359 const int millisecond = atoi(gtk_entry_get_text(GTK_ENTRY(
d->dt.widget[6])));
1360 const gdouble second2 = (gdouble)second + (gdouble)millisecond * 0.001;
1373 g_date_time_unref(
d->datetime);
1374 d->datetime = datetime;
1375 d->offset = g_date_time_difference(
d->datetime,
d->datetime0);
1399 if(imgid < 0)
return NULL;
1400 GDateTime *datetime = NULL;
1405 if(datetime_s[0] !=
'\0')
1417 const gboolean locked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
d->lock_offset));
1420 g_date_time_unref(
d->datetime0);
1421 d->datetime0 = datetime;
1425 GDateTime *datetime2 = g_date_time_add(datetime,
d->offset);
1433 g_date_time_ref(datetime);
1442 for(GList *
i = imgs;
i;
i = g_list_next(
i))
1444 if(GPOINTER_TO_INT(
i->data) ==
d->imgid)
1489 if(w ==
d->dt.widget[
i])
break;
1495 if (delta_y < 0) increment = 1;
1496 else if (delta_y > 0) increment = -1;
1502 GDateTime *datetime;
1506 datetime = g_date_time_add_years(
d->datetime, increment);
1509 datetime = g_date_time_add_months(
d->datetime, increment);
1512 datetime = g_date_time_add_days(
d->datetime, increment);
1515 datetime = g_date_time_add_hours(
d->datetime, increment);
1518 datetime = g_date_time_add_minutes(
d->datetime, increment);
1521 datetime = g_date_time_add_seconds(
d->datetime, increment);
1524 datetime = g_date_time_add(
d->datetime, increment * 1000);
1540 gtk_flow_box_set_max_children_per_line(GTK_FLOW_BOX(flow), 2);
1548 if(
i == 0 &&
type == 2)
1550 dt->
sign = gtk_label_new(
"");
1553 if(
i >= 2 ||
type != 2)
1555 dt->
widget[
i] = gtk_entry_new();
1557 gtk_entry_set_width_chars(GTK_ENTRY(dt->
widget[
i]),
i == 0 ? 4 :
i == 6 ? 3 : 2);
1558 gtk_entry_set_alignment(GTK_ENTRY(dt->
widget[
i]), 0.5);
1570 if(
i == 2 ||
i == 6)
1572 gtk_widget_set_halign(GTK_WIDGET(box), GTK_ALIGN_END);
1573 gtk_widget_set_hexpand(GTK_WIDGET(box),
TRUE);
1574 gtk_container_add(GTK_CONTAINER(flow), GTK_WIDGET(box));
1577 else if(
i > 2 ||
type != 2)
1579 GtkWidget *label = gtk_label_new(
i < 2 ?
"-" :
i == 5 ?
"." :
":");
1581 g_object_set_data(G_OBJECT(dt->
widget[
i]),
"msec_label", label);
1582 gtk_box_pack_start(box, label,
FALSE,
FALSE, 0);
1598 case GDK_KEY_Escape:
1621 case GDK_KEY_Delete:
1622 case GDK_KEY_BackSpace:
1631 case GDK_KEY_ISO_Left_Tab:
1632 case GDK_KEY_Return:
1634 g_signal_emit_by_name(
d->dt.widget[0],
"changed");
1645 const gchar *tz = gtk_entry_get_text(GTK_ENTRY(
d->timezone));
1648 for(GList *iter =
d->timezones; iter; iter = g_list_next(iter))
1651 if(!strcmp(tz_tuple->
display, tz))
1654 if(
d->tz_camera) g_time_zone_unref(
d->tz_camera);
1655 d->tz_camera = !
name ? g_time_zone_new_utc() : g_time_zone_new(
name);
1657 gtk_entry_set_text(GTK_ENTRY(
d->timezone),
name ?
name :
"UTC");
1658 gtk_label_set_text(GTK_LABEL (
d->timezone_changed),
"");
1673 case GDK_KEY_Return:
1677 case GDK_KEY_Escape:
1682 gtk_label_set_text(GTK_LABEL (
d->timezone_changed),
" *");
1699 GtkEditable *e = (GtkEditable *)gtk_entry_completion_get_entry(completion);
1700 if(!GTK_IS_EDITABLE(e))
1703 GtkTreeModel *
model = gtk_entry_completion_get_model(completion);
1704 const int column = gtk_entry_completion_get_text_column(completion);
1706 if(gtk_tree_model_get_column_type(
model, column) != G_TYPE_STRING)
1710 gtk_tree_model_get(
model, iter, column, &tag, -1);
1713 char *normalized = g_utf8_normalize(tag, -1, G_NORMALIZE_ALL);
1716 char *casefold = g_utf8_casefold(normalized, -1);
1719 res = g_strstr_len(casefold, -1,
key) != NULL;
1733 const gboolean locked = gtk_toggle_button_get_active(button);
1736 gtk_widget_set_sensitive(
d->dt.widget[
i], !locked);
1738 gtk_widget_set_sensitive(
d->apply_datetime,
d->imgid && !locked);
1742 const float xalign,
const int m_col,
1743 const int ellipsize)
1745 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1746 GtkTreeViewColumn *column = gtk_tree_view_column_new();
1747 gtk_tree_view_column_pack_start(column, renderer,
TRUE);
1748 gtk_tree_view_column_set_attributes(column, renderer,
"text", m_col, NULL);
1749 gtk_tree_view_column_set_expand(column, expand);
1751 gtk_widget_show(label);
1752 gtk_tree_view_column_set_widget(column, label);
1753 gtk_label_set_ellipsize(GTK_LABEL(label), expand ? PANGO_ELLIPSIZE_MIDDLE : PANGO_ELLIPSIZE_NONE);
1754 g_object_set(renderer,
"xalign", xalign,
"ellipsize", ellipsize, NULL);
1760 const gboolean milliseconds =
dt_conf_get_bool(
"lighttable/ui/milliseconds");
1761 gtk_widget_set_visible(
d->dt.widget[6], milliseconds);
1762 gtk_widget_set_visible(
d->dt0.widget[6], milliseconds);
1763 gtk_widget_set_visible(
d->of.widget[6], milliseconds);
1764 gtk_widget_set_visible(g_object_get_data(G_OBJECT(
d->dt.widget[5]),
"msec_label"), milliseconds);
1765 gtk_widget_set_visible(g_object_get_data(G_OBJECT(
d->dt0.widget[5]),
"msec_label"), milliseconds);
1766 gtk_widget_set_visible(g_object_get_data(G_OBJECT(
d->of.widget[5]),
"msec_label"), milliseconds);
1777 self->
data = (
void *)
d;
1781 GtkGrid *grid = GTK_GRID(gtk_grid_new());
1786 gtk_grid_attach(grid, label, 0, line, 2, 1);
1787 gtk_widget_set_tooltip_text(label, _(
"enter the new date/time (YYYY:MM:DD hh:mm:ss[.sss])"
1788 "\nkey in the new numbers or scroll over the cell"));
1791 gtk_grid_attach(grid, box, 2, line++, 2, 1);
1794 gtk_grid_attach(grid, label, 0, line, 2, 1);
1797 gtk_grid_attach(grid, box, 2, line++, 2, 1);
1800 gtk_grid_attach(grid, label, 0, line, 2, 1);
1801 gtk_widget_set_tooltip_text(label, _(
"offset or difference ([-]dd hh:mm:ss[.sss])"));
1804 gtk_widget_set_tooltip_text(
d->lock_offset, _(
"lock date/time offset value to apply it onto another selection"));
1805 gtk_widget_set_halign(
d->lock_offset, GTK_ALIGN_START);
1806 gtk_grid_attach(grid,
d->lock_offset, 2, line, 1, 1);
1810 gtk_grid_attach(grid, box, 3, line++, 1, 1);
1814 _(
"apply offset to selected images"), 0, 0);
1815 gtk_grid_attach(grid,
d->apply_offset , 0, line, 2, 1);
1818 _(
"apply the same date/time to selected images"), 0, 0);
1819 gtk_grid_attach(grid,
d->apply_datetime , 2, line++, 2, 1);
1825 gtk_grid_attach(grid, label, 0, line, 2, 1);
1827 d->timezone = gtk_entry_new();
1829 gtk_widget_set_tooltip_text(
d->timezone, _(
"start typing to show a list of permitted values and select your timezone.\npress enter to confirm, so that the asterisk * disappears"));
1833 gtk_box_pack_start(GTK_BOX(timezone_box),
d->timezone,
TRUE,
TRUE, 0);
1834 gtk_box_pack_end(GTK_BOX(timezone_box),
d->timezone_changed,
FALSE,
FALSE, 0);
1836 gtk_grid_attach(grid, timezone_box, 2, line++, 2, 1);
1838 GtkCellRenderer *renderer;
1839 GtkTreeIter tree_iter;
1840 GtkListStore *
model = gtk_list_store_new(2, G_TYPE_STRING , G_TYPE_STRING );
1841 GtkWidget *tz_selection = gtk_combo_box_new_with_model(GTK_TREE_MODEL(
model));
1842 renderer = gtk_cell_renderer_text_new();
1843 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(tz_selection), renderer,
FALSE);
1844 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(tz_selection), renderer,
"text", 0, NULL);
1847 d->tz_camera = (
IS_NULL_PTR(tz)) ? g_time_zone_new_utc() : g_time_zone_new(tz);
1848 for(GList *iter =
d->timezones; iter; iter = g_list_next(iter))
1851 gtk_list_store_append(
model, &tree_iter);
1852 gtk_list_store_set(
model, &tree_iter, 0, tz_tuple->
display, 1, tz_tuple->
name, -1);
1853 if(!strcmp(tz_tuple->
name, tz))
1854 gtk_entry_set_text(GTK_ENTRY(
d->timezone), tz_tuple->
display);
1859 GtkEntryCompletion *completion = gtk_entry_completion_new();
1860 gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(
model));
1861 gtk_entry_completion_set_text_column(completion, 0);
1862 gtk_entry_completion_set_inline_completion(completion,
TRUE);
1863 gtk_entry_completion_set_popup_set_width(completion,
FALSE);
1865 gtk_entry_completion_set_minimum_key_length(completion, 0);
1866 gtk_entry_set_completion(GTK_ENTRY(
d->timezone), completion);
1868 g_signal_connect(G_OBJECT(
d->timezone),
"focus-out-event", G_CALLBACK(
_timezone_focus_out), self);
1872 _(
"parses a GPX file and updates location of selected images"), 0, 0);
1873 gtk_grid_attach(grid,
d->gpx_button, 0, line++, 4, 1);
1874 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(grid),
TRUE,
TRUE, 0);
1878 grid = GTK_GRID(gtk_grid_new());
1883 gtk_box_pack_start(GTK_BOX(self->
widget), GTK_WIDGET(
d->map.gpx_section),
TRUE,
TRUE, 0);
1886 gtk_grid_attach(grid, label, 0, line++, 4, 1);
1889 gtk_widget_set_hexpand(
d->map.gpx_button,
FALSE);
1890 gtk_widget_set_halign(
d->map.gpx_button, GTK_ALIGN_START);
1891 gtk_widget_set_tooltip_text(
d->map.gpx_button, _(
"select a GPX track file..."));
1892 gtk_grid_attach(grid,
d->map.gpx_button, 0, line, 1, 1);
1896 gtk_label_set_ellipsize(GTK_LABEL(
d->map.gpx_file ), PANGO_ELLIPSIZE_MIDDLE);
1897 gtk_widget_set_hexpand(
d->map.gpx_file,
TRUE);
1898 gtk_grid_attach(grid,
d->map.gpx_file, 1, line++, 3, 1);
1899 gtk_box_pack_start(GTK_BOX(
d->map.gpx_section), GTK_WIDGET(grid),
TRUE,
TRUE, 0);
1902 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING);
1904 d->map.gpx_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(
model));
1905 g_object_unref(
model);
1906 gtk_widget_set_name(
d->map.gpx_view,
"gpx_list");
1907 gtk_widget_set_tooltip_text(GTK_WIDGET(
d->map.gpx_view),
1908 _(
"list of track segments in the GPX file, for each segment:"
1909 "\n- the start date/time in local time (LT)"
1910 "\n- the number of track points"
1911 "\n- the number of matching images"
1912 " based on images date/time, offset and time zone"
1913 "\n- more detailed time information hovering the row"));
1914 renderer = gtk_cell_renderer_toggle_new();
1916 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
"", renderer,
"active",
DT_GEO_TRACKS_ACTIVE, NULL);
1917 gtk_tree_view_append_column(GTK_TREE_VIEW(
d->map.gpx_view), column);
1918 d->map.sel_tracks = column;
1919 GtkWidget *button = gtk_check_button_new();
1920 gtk_widget_show(button);
1921 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
FALSE);
1922 gtk_tree_view_column_set_widget(column, button);
1923 gtk_tree_view_column_set_alignment(column, 0.5);
1927 gtk_tree_view_append_column(GTK_TREE_VIEW(
d->map.gpx_view), column);
1929 gtk_tree_view_append_column(GTK_TREE_VIEW(
d->map.gpx_view), column);
1931 gtk_tree_view_append_column(GTK_TREE_VIEW(
d->map.gpx_view), column);
1933 g_object_set(G_OBJECT(
d->map.gpx_view),
"has-tooltip",
TRUE, NULL);
1934 g_signal_connect(G_OBJECT(
d->map.gpx_view),
"query-tooltip", G_CALLBACK(
_row_tooltip_setup), self);
1937 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(
d->map.gpx_view),
FALSE);
1940 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(
d->map.gpx_view),
TRUE);
1941 gtk_box_pack_start(GTK_BOX(
d->map.gpx_section), w,
TRUE,
TRUE, 0);
1943 grid = GTK_GRID(gtk_grid_new());
1947 d->map.preview_button = gtk_check_button_new_with_label(_(
"preview images"));
1948 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
d->map.preview_button),
TRUE);
1949 gtk_widget_set_sensitive(
d->map.preview_button,
FALSE);
1950 gtk_label_set_ellipsize(GTK_LABEL(gtk_bin_get_child(GTK_BIN(
d->map.preview_button))), PANGO_ELLIPSIZE_END);
1951 gtk_grid_attach(grid,
d->map.preview_button, 0, line, 1, 1);
1952 gtk_widget_set_tooltip_text(
d->map.preview_button, _(
"show on map matching images"));
1956 _(
"select matching images"), 0, 0);
1957 gtk_widget_set_hexpand(
d->map.select_button,
TRUE);
1958 gtk_widget_set_sensitive(
d->map.select_button,
FALSE);
1959 gtk_grid_attach(grid,
d->map.select_button, 1, line, 1, 1);
1962 gtk_widget_set_halign(
d->map.nb_imgs_label, GTK_ALIGN_END);
1963 gtk_widget_set_tooltip_text(GTK_WIDGET(
d->map.nb_imgs_label),
1964 _(
"number of matching images versus selected images"));
1965 gtk_grid_attach(grid,
d->map.nb_imgs_label, 2, line++, 1, 1);
1968 _(
"apply geo-location to matching images"), 0, 0);
1969 gtk_widget_set_hexpand(
d->map.apply_gpx_button,
TRUE);
1970 gtk_widget_set_sensitive(
d->map.apply_gpx_button,
FALSE);
1971 gtk_grid_attach(grid,
d->map.apply_gpx_button, 0, line++, 3, 1);
1973 gtk_box_pack_start(GTK_BOX(
d->map.gpx_section), GTK_WIDGET(grid),
TRUE,
TRUE, 0);
1976 gtk_widget_show_all(self->
widget);
1977 gtk_widget_set_no_show_all(self->
widget,
TRUE);
1984 g_date_time_ref(
d->datetime);
2015 gtk_widget_show_all(self->
widget);
2016 gtk_widget_set_no_show_all(self->
widget,
TRUE);
2033 d->timezones = NULL;
2034 g_time_zone_unref(
d->tz_camera);
2036 g_date_time_unref(
d->datetime);
2038 g_date_time_unref(
d->datetime0);
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)
int32_t dt_act_on_get_first_image()
GtkWidget * dt_gui_main_window(void)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
int dt_conf_get_bool(const char *name)
const char * dt_confgen_get_tooltip(const char *name)
Translated long description of name, borrowed and valid for the process lifetime. NULL when name is n...
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
void dt_conf_set_string(const char *name, const char *val)
void dt_conf_set_folder_from_file_chooser(const char *name, GtkFileChooser *chooser)
const char * dt_confgen_get_label(const char *name)
Translated short description of name, borrowed and valid for the process lifetime....
gboolean dt_conf_get_folder_to_file_chooser(const char *name, GtkFileChooser *chooser)
void dt_image_get_datetime(const int32_t imgid, char *datetime)
void dt_gui_flow_box_as_layout(GtkFlowBox *box)
int32_t dt_control_get_mouse_over_id()
void dt_control_gpx_apply(const gchar *filename, int32_t filmid, const gchar *tz, GList *imgs)
void dt_control_datetime(const GTimeSpan offset, const char *datetime, GList *imgs)
struct dt_view_manager_t * dt_view_manager_get_global(void)
gboolean dt_datetime_img_to_exif(char *exif, const size_t exif_size, const dt_image_t *img)
gboolean dt_datetime_gdatetime_to_exif(char *exif, const size_t exif_size, GDateTime *gdt)
GDateTime * dt_datetime_exif_to_gdatetime(const char *exif, const GTimeZone *tz)
GTimeZone * dt_datetime_utc_tz(void)
#define DT_DATETIME_LENGTH
GtkWidget * preview
what the selected row actually captures
GHashTable * selected
set of checked row labels, mirrored to conf on every change
GtkWidget * view
the tree view
void dt_loc_get_datadir(char *datadir, size_t bufsize)
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
static gboolean _timezone_focus_out(GtkWidget *entry, GdkEventKey *event, dt_lib_module_t *self)
static void _apply_gpx(GtkWidget *widget, dt_lib_module_t *self)
static GDateTime * _localtime_text_to_utc_timeval(const char *date_time, GTimeZone *tz_camera, GTimeZone *tz_utc, GTimeSpan offset)
static void _choose_gpx_callback(GtkWidget *widget, dt_lib_module_t *self)
static void _refresh_display_all_tracks(dt_lib_module_t *self)
static void free_tz_tuple(gpointer data)
static void _setup_selected_images_list(dt_lib_module_t *self)
static void _view_changed(gpointer instance, dt_view_t *old_view, dt_view_t *new_view, dt_lib_module_t *self)
static gboolean _update_map_box(const guint segid, GList *pts, dt_lib_module_t *self)
static gboolean _row_tooltip_setup(GtkWidget *view, gint x, gint y, gboolean kb_mode, GtkTooltip *tooltip, dt_lib_module_t *self)
static gboolean _timezone_key_pressed(GtkWidget *entry, GdkEventKey *event, dt_lib_module_t *self)
static void _show_milliseconds(dt_lib_geotagging_t *d)
static int _sort_timezones(gconstpointer a, gconstpointer b)
static void _refresh_selected_images_datetime(dt_lib_module_t *self)
static void _select_images(GtkWidget *widget, dt_lib_module_t *self)
static void _apply_offset_callback(GtkWidget *widget, dt_lib_module_t *self)
static GtkWidget * _gui_init_datetime(dt_lib_datetime_t *dt, const int type, dt_lib_module_t *self)
static void _refresh_displayed_images(dt_lib_module_t *self)
static GDateTime * _get_image_datetime(dt_lib_module_t *self)
static void _refresh_track_list(dt_lib_module_t *self)
static void _update_layout(dt_lib_module_t *self)
static void _track_seg_toggled(GtkCellRendererToggle *cell_renderer, gchar *path_str, dt_lib_module_t *self)
static void _display_datetime(dt_lib_datetime_t *dtw, GDateTime *datetime, const gboolean lock, dt_lib_module_t *self)
static GtkWidget * _set_up_label(const char *name, const int align, GtkWidget *grid, const int col, const int line, const int ellipsize)
void gui_cleanup(dt_lib_module_t *self)
static void _preview_gpx_file(GtkWidget *widget, dt_lib_module_t *self)
static void _selection_changed_callback(gpointer instance, dt_lib_module_t *self)
static void _datetime_entry_changed(GtkWidget *entry, dt_lib_module_t *self)
static gchar * _utc_timeval_to_utc_text(GDateTime *utc_dt, const gboolean full)
static gboolean _datetime_scroll_over(GtkWidget *w, GdkEventScroll *event, dt_lib_module_t *self)
static void _display_offset(const GTimeSpan offset_int, const gboolean valid, dt_lib_module_t *self)
static void _apply_datetime_callback(GtkWidget *widget, dt_lib_module_t *self)
static gchar * _datetime_tooltip(GDateTime *start, GDateTime *end, GTimeZone *tz)
static void _mouse_over_image_callback(gpointer instance, dt_lib_module_t *self)
static void _images_preview_toggled(GtkToggleButton *button, dt_lib_module_t *self)
static void _dt_pref_change_callback(gpointer instance, dt_lib_module_t *self)
static gint _cmp_imgid_asc(gconstpointer a, gconstpointer b)
static void _show_gpx_tracks(dt_lib_module_t *self)
static gboolean _completion_match_func(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer user_data)
#define DT_GEOTAG_PARTS_NB
static GDateTime * _read_datetime_entry(dt_lib_module_t *self)
static void _geotag_changed(gpointer instance, GList *imgs, const int locid, dt_lib_module_t *self)
static GList * _lib_geotagging_get_timezones(void)
uint32_t container(dt_lib_module_t *self)
GtkTreeViewColumn * _new_tree_text_column(const char *name, const gboolean expand, const float xalign, const int m_col, const int ellipsize)
static GList * _get_images_on_active_tracks(dt_lib_module_t *self)
static void _update_buttons(dt_lib_module_t *self)
static void _remove_images_from_map(dt_lib_module_t *self)
static void _refresh_images_displayed_on_track(const int segid, const gboolean active, dt_lib_module_t *self)
static void _refresh_image_datetime(dt_lib_module_t *self)
static void _update_nb_images(dt_lib_module_t *self)
void gui_init(dt_lib_module_t *self)
static int _count_images_per_track(dt_gpx_track_segment_t *t, dt_gpx_track_segment_t *n, dt_lib_module_t *self)
static void _image_info_changed(gpointer instance, gpointer imgs, dt_lib_module_t *self)
const char ** views(dt_lib_module_t *self)
static gboolean _lib_geotagging_filter_gpx(const GtkFileFilterInfo *filter_info, gpointer data)
static void _all_tracks_toggled(GtkTreeViewColumn *column, dt_lib_module_t *self)
static gchar * _utc_timeval_to_localtime_text(GDateTime *utc_dt, GTimeZone *tz_camera, const gboolean full)
static void _toggle_lock_button_callback(GtkToggleButton *button, dt_lib_module_t *self)
static gboolean _refresh_display_track(const gboolean active, const int segid, dt_lib_module_t *self)
static void _remove_tracks_from_map(dt_lib_module_t *self)
static void _new_datetime(GDateTime *datetime, dt_lib_module_t *self)
static void _timezone_save(dt_lib_module_t *self)
static gboolean _datetime_key_pressed(GtkWidget *entry, GdkEventKey *event, dt_lib_module_t *self)
void dt_gpx_destroy(struct dt_gpx_t *gpx)
GList * dt_gpx_get_trkpts(struct dt_gpx_t *gpx, const guint segid)
gboolean dt_gpx_get_location(struct dt_gpx_t *gpx, GDateTime *timestamp, dt_image_geoloc_t *geoloc)
dt_gpx_t * dt_gpx_new(const gchar *filename)
GList * dt_gpx_get_trkseg(struct dt_gpx_t *gpx)
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
GtkWidget * dt_ui_section_label_new(const gchar *str)
GtkWidget * dt_ui_label_new(const gchar *str)
GtkWidget * dt_action_button_new(dt_lib_module_t *self, const gchar *label, gpointer callback, gpointer data, const gchar *tooltip, guint accel_key, GdkModifierType mods)
_lib_location_type_t type
#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,...
void dt_osx_disallow_fullscreen(GtkWidget *widget)
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
struct dt_selection_t * dt_selection_get_global(void)
GList * dt_selection_get_list(struct dt_selection_t *selection)
void dt_selection_select_list(struct dt_selection_t *selection, const GList *const l)
void dt_selection_clear(dt_selection_t *selection)
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_GEOTAG_CHANGED
This signal is raised when a geotag is added/deleted/changed
@ DT_SIGNAL_MOUSE_OVER_IMAGE_CHANGE
This signal is raised when mouse hovers over image thumbs both on lighttable and in the filmstrip....
@ DT_SIGNAL_IMAGE_INFO_CHANGED
This signal is raised when any of image info has changed
@ DT_SIGNAL_PREFERENCES_CHANGE
This signal is raised after preferences have been changed no parameters no return.
@ DT_SIGNAL_SELECTION_CHANGED
This signal is raised when the selection is changed no param, no returned value.
@ DT_SIGNAL_VIEWMANAGER_VIEW_CHANGED
This signal is raised by viewmanager when a view has changed. 1 : dt_view_t * the old view 2 : dt_vie...
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
static const dt_aligned_pixel_simd_t value
static const char *const day[7]
GtkWidget * apply_datetime
GtkWidget * select_button
struct dt_lib_geotagging_t::@50 map
GtkWidget * preview_button
GtkTreeViewColumn * sel_tracks
GtkWidget * apply_gpx_button
GtkWidget * nb_imgs_label
GtkWidget * timezone_changed
dt_lib_tracks_data_t td[1]
gchar dt[DT_DATETIME_LENGTH]
struct dt_view_manager_t::@60::@64 map
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_LEFT_CENTER