From eece228d8cdef54757a29525d14487533c7146b0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 29 Jun 2012 22:13:18 +0000 Subject: -support for relative expiration time and setting absolute expiration time via cal --- contrib/Makefile.am | 1 + contrib/gnunet_setup_calendar_dialog.glade | 84 ++++++ contrib/gnunet_setup_gtk_main_window.glade | 19 ++ src/setup/gnunet-setup-gns.c | 417 +++++++++++++++-------------- 4 files changed, 316 insertions(+), 205 deletions(-) create mode 100644 contrib/gnunet_setup_calendar_dialog.glade diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 738d4305..2bb565c9 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -45,6 +45,7 @@ pkgdata_DATA = \ gnunet_peerinfo_gtk_main_window.glade \ gnunet_statistics_gtk_about_window.glade \ gnunet_statistics_gtk_main_window.glade \ + gnunet_setup_calendar_dialog.glade \ gnunet_setup_qr_save_as_dialog.glade \ gnunet_setup_gtk_main_window.glade diff --git a/contrib/gnunet_setup_calendar_dialog.glade b/contrib/gnunet_setup_calendar_dialog.glade new file mode 100644 index 00000000..9652c230 --- /dev/null +++ b/contrib/gnunet_setup_calendar_dialog.glade @@ -0,0 +1,84 @@ + + + + + + False + 5 + dialog + + + + True + False + 2 + + + True + False + end + + + gtk-cancel + False + True + True + True + True + + + False + False + 0 + + + + + gtk-ok + False + True + True + True + True + + + False + False + 1 + + + + + False + True + end + 0 + + + + + True + True + 2012 + 5 + 29 + True + False + + + True + True + 1 + + + + + + + + + GNUNET_setup_calendar_cancel_button + GNUNET_setup_calendar_ok_button + + + diff --git a/contrib/gnunet_setup_gtk_main_window.glade b/contrib/gnunet_setup_gtk_main_window.glade index 6f1ccc96..e55dfda5 100644 --- a/contrib/gnunet_setup_gtk_main_window.glade +++ b/contrib/gnunet_setup_gtk_main_window.glade @@ -4878,6 +4878,7 @@ True False 1 day + @@ -4907,6 +4908,24 @@ + + + False + True + False + + + + + False + True + False + Pick expiration date from calendar + Calendar + True + + + diff --git a/src/setup/gnunet-setup-gns.c b/src/setup/gnunet-setup-gns.c index b0c5fdfe..eb0a320f 100644 --- a/src/setup/gnunet-setup-gns.c +++ b/src/setup/gnunet-setup-gns.c @@ -523,12 +523,14 @@ check_name_validity_and_commit (const gchar *path, const char * oldname) } else { - if (FALSE == n_public) - rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; + if (n_public) + rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY; else - rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE; + rd[c].flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_PRIVATE; rd[c].record_type = n_type; rd[c].expiration_time = n_exp_time; + if (n_is_relative) + rd[c].flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION; rd[c].data_size = data_size; rd[c].data = GNUNET_malloc(data_size); memcpy ((void *) rd[c].data, data, data_size); @@ -817,18 +819,18 @@ GNUNET_setup_gns_type_cellrenderercombo_edited_cb (GtkCellRendererCombo *combo, else if ((NULL != name_str) && (0 != strcmp (NEW_NAME_STR, name_str))) { /* Adding a new record */ - gtk_tree_store_insert_with_values(ts, &child , &it, -1, - GNS_TREESTORE_COL_NAME, name_str, - GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE, - GNS_TREESTORE_COL_RECORD_TYPE, type, - GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, new_text, - GNS_TREESTORE_COL_EXP_TIME_AS_STR, EXPIRE_NEVER_STRING, - GNS_TREESTORE_COL_EXP_TIME, GNUNET_TIME_UNIT_FOREVER_ABS, - GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE, - GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, - GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE, - GNS_TREESTORE_COL_VAL_COLOR, "red", - -1); + gtk_tree_store_insert_with_values (ts, &child , &it, -1, + GNS_TREESTORE_COL_NAME, name_str, + GNS_TREESTORE_COL_NAME_IS_VISIBLE, FALSE, + GNS_TREESTORE_COL_RECORD_TYPE, type, + GNS_TREESTORE_COL_RECORD_TYPE_AS_STR, new_text, + GNS_TREESTORE_COL_EXP_TIME_AS_STR, EXPIRE_NEVER_STRING, + GNS_TREESTORE_COL_EXP_TIME, GNUNET_TIME_UNIT_FOREVER_ABS, + GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE, + GNS_TREESTORE_COL_IS_RECORD_ROW, TRUE, + GNS_TREESTORE_COL_NOT_DUMMY_ROW, TRUE, + GNS_TREESTORE_COL_VAL_COLOR, "red", + -1); /* select new row and start editing 'value' */ gtk_tree_view_expand_row (tv, gtk_tree_model_get_path(tm, &it), 0); sel = gtk_tree_view_get_selection (tv); @@ -868,124 +870,13 @@ GNUNET_setup_gns_ispublic_cellrenderertoggle_toggled_cb (GtkCellRendererToggle * GtkTreeIter it; gboolean value; - gtk_tree_model_get_iter_from_string(tm, &it, path); - gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1); - gtk_tree_store_set(ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1); - + gtk_tree_model_get_iter_from_string (tm, &it, path); + gtk_tree_model_get (tm, &it, GNS_TREESTORE_COL_IS_PUBLIC, &value, -1); + gtk_tree_store_set (ts, &it, GNS_TREESTORE_COL_IS_PUBLIC, !value, -1); check_name_validity_and_commit (path, NULL); } -/** - * FIXME: should use routines from gnunet-util (or move this to - * gnunet-util if it doesn't exist there!). - */ -static char * -convert_time_to_string (struct GNUNET_TIME_Absolute t) -{ - time_t tt; - struct tm *time; - char *ret; - - if (t.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) - return GNUNET_strdup (_(EXPIRE_NEVER_STRING)); - if (t.abs_value == GNUNET_TIME_UNIT_ZERO_ABS.abs_value) - return GNUNET_strdup (_(EXPIRE_INVALID_STRING)); - - tt = t.abs_value / 1000; - time = localtime (&tt); - - GNUNET_asprintf(&ret, "%02u/%02u/%04u %02u:%02u",time->tm_mon, time->tm_mday, 1900 + time->tm_year, time->tm_hour, time->tm_min); - return ret; -} - - -/** - * - */ -static int -check_time (const char * text) -{ - unsigned int t_mon; - unsigned int t_day; - unsigned int t_year; - unsigned int t_hrs; - unsigned int t_min; - - int count = SSCANF (text, "%02u/%02u/%04u %02u:%02u", &t_mon, &t_day, &t_year, &t_hrs, &t_min); - if ((EOF == count) || (5 != count)) - { - return GNUNET_SYSERR; - } - - if (t_mon > 12) - return GNUNET_SYSERR; - if (t_day > 31) - return GNUNET_SYSERR; - if (t_hrs > 24) - return GNUNET_SYSERR; - if (t_min > 59) - return GNUNET_SYSERR; - - return GNUNET_OK; -} - - -/** - * - */ -static const struct GNUNET_TIME_Absolute -convert_string_to_abs_time (const char * text) -{ - static struct GNUNET_TIME_Absolute abs_t; - struct tm time; - time_t t; - - int t_mon; - int t_day; - int t_year; - int t_hrs; - int t_min; - - GNUNET_assert (NULL != text); - - if (0 == strcmp(text, EXPIRE_NEVER_STRING)) - return GNUNET_TIME_UNIT_FOREVER_ABS; - - memset (&time, '\0', sizeof (struct tm)); - - if (GNUNET_SYSERR == check_time(text)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Invalid time `%s'\n"), text); - GNUNET_break (0); - return GNUNET_TIME_UNIT_ZERO_ABS; - } - - int count = SSCANF (text, "%02d/%02d/%04d %02d:%02d", &t_mon, &t_day, &t_year, &t_hrs, &t_min); - if ((EOF == count) || (5 != count)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Invalid time `%s', returning 0\n"), text); - return GNUNET_TIME_UNIT_ZERO_ABS; - } - - time.tm_mon = (t_mon - 1); - time.tm_mday = t_day; - time.tm_year = t_year - 1900; - time.tm_hour = (t_hrs); - time.tm_min = t_min; - - t = mktime (&time); - if (-1 == t) - return GNUNET_TIME_UNIT_ZERO_ABS; - - abs_t.abs_value = t * 1000; - - return abs_t; -} - - /** * The user has edited a 'expiration' cell. Update the model. * @@ -1002,56 +893,45 @@ GNUNET_setup_gns_expiration_cellrenderertext_edited_cb (GtkCellRendererText *ren { GtkTreeIter it; struct GNUNET_TIME_Absolute abstime; - gboolean is_rel; - char *old_text; + struct GNUNET_TIME_Relative reltime; if (NULL == new_text) return; /* can this happen? */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New expiration time: `%s'\n", new_text); - gtk_tree_model_get_iter_from_string(tm, &it, path); - gtk_tree_model_get(tm, &it, - GNS_TREESTORE_COL_EXP_TIME_AS_STR, &old_text, - GNS_TREESTORE_COL_EXP_TIME_IS_REL, &is_rel, - -1); - if ( (NULL != old_text) && - (0 == strcmp(new_text, old_text)) ) - return; - - if ((0 == strcmp(new_text,"")) || (0 == strcmp(new_text,EXPIRE_NEVER_STRING))) + gtk_tree_model_get_iter_from_string (tm, &it, path); + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_relative (new_text, + &reltime)) { - new_text = EXPIRE_NEVER_STRING; - abstime = GNUNET_TIME_UNIT_FOREVER_ABS; + gtk_tree_store_set (ts, &it, + GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text, + GNS_TREESTORE_COL_EXP_TIME, reltime.rel_value, + GNS_TREESTORE_COL_EXP_TIME_IS_REL, TRUE, + GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL, + -1); + check_name_validity_and_commit (path, NULL); + return; } - else + if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (new_text, + &abstime)) { - if (GNUNET_SYSERR == check_time(new_text)) - { - gtk_tree_store_set (ts, &it, - GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text, - GNS_TREESTORE_COL_EXP_TIME_COLOR, "red", - GNS_TREESTORE_COL_EXP_TIME, 0, - -1); - abstime = GNUNET_TIME_UNIT_ZERO_ABS; - return; - } - /* TODO: fix this when we have relative time */ - if (TRUE == is_rel) - { - abstime = convert_string_to_abs_time(new_text); - } - else - { - abstime = convert_string_to_abs_time(new_text); - } + gtk_tree_store_set (ts, &it, + GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text, + GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value, + GNS_TREESTORE_COL_EXP_TIME_IS_REL, FALSE, + GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL, + -1); + check_name_validity_and_commit (path, NULL); + return; } gtk_tree_store_set (ts, &it, GNS_TREESTORE_COL_EXP_TIME_AS_STR, new_text, - GNS_TREESTORE_COL_EXP_TIME, abstime.abs_value, - GNS_TREESTORE_COL_EXP_TIME_COLOR, NULL, + GNS_TREESTORE_COL_EXP_TIME_COLOR, "red", + GNS_TREESTORE_COL_EXP_TIME, 0, -1); - check_name_validity_and_commit (path, NULL); } @@ -1125,14 +1005,13 @@ GNUNET_setup_gns_value_cellrenderertext_edited_cb (GtkCellRendererText *renderer */ void GNUNET_setup_gns_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer, - gchar *path, - gchar *new_text, - gpointer user_data) + gchar *path, + gchar *new_text, + gpointer user_data) { GtkTreeIter it; GtkTreeIter child; - GtkTreeModel *tm = GTK_TREE_MODEL(ts); - int not_dummy; + gboolean not_dummy; char *name; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New text for `%s' is `%s'\n", path, new_text); @@ -1143,7 +1022,7 @@ GNUNET_setup_gns_name_cellrenderertext_edited_cb (GtkCellRendererText *renderer, gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NAME, &name, -1); - if (not_dummy == GNUNET_NO) + if (not_dummy) { /* update name */ gtk_tree_store_set (ts, &it, @@ -1303,16 +1182,16 @@ set_relative_expiration_time (struct GNUNET_TIME_Relative reltime) GtkTreeIter it; GtkTreeIter parent; GtkCellRendererText *renderer; - GtkTreeModel *tm; - GtkTreeSelection * ts = gtk_tree_view_get_selection(tv); + GtkTreeSelection * ts; gboolean has_parent; - struct GNUNET_TIME_Absolute abstime; char *path; + char *tstr; int not_dummy; + ts = gtk_tree_view_get_selection(tv); if (! gtk_tree_selection_get_selected (ts, &tm, &it)) return; - gtk_tree_model_get(tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); + gtk_tree_model_get (tm, &it, GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, -1); if (GNUNET_NO == not_dummy) return; @@ -1320,17 +1199,15 @@ set_relative_expiration_time (struct GNUNET_TIME_Relative reltime) has_parent = gtk_tree_model_iter_parent (tm, &parent, &it); if (FALSE == has_parent) return; - - /* FIXME: should keep as relative time! */ - abstime = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), reltime); - /* this is a single record */ renderer = GTK_CELL_RENDERER_TEXT((GNUNET_SETUP_get_object ("GNUNET_setup_gns_name_cellrenderertext"))); path = gtk_tree_model_get_string_from_iter (tm, &it); + tstr = GNUNET_STRINGS_relative_time_to_string (reltime); GNUNET_setup_gns_expiration_cellrenderertext_edited_cb (renderer, path, - convert_time_to_string (abstime), + tstr, NULL); + GNUNET_free (tstr); } @@ -1339,7 +1216,7 @@ set_relative_expiration_time (struct GNUNET_TIME_Relative reltime) */ void GNUNET_setup_gns_popup_1d_exp_button_activate_cb (GtkWidget *widget, - gpointer user_data) + gpointer user_data) { set_relative_expiration_time (GNUNET_TIME_UNIT_DAYS); } @@ -1378,6 +1255,146 @@ GNUNET_setup_gns_popup_forever_exp_button_activate_cb (GtkWidget *widget, } + +/** + * Function called upon completion of the calendar dialog. + * + * @param dialog the dialog + * @param response_id reason for the dialog closing + * @param user_data the 'GtkBuilder' we used to create the dialog + */ +void +GNUNET_setup_calendar_dialog_response_cb (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + GtkBuilder *builder = user_data; + guint year; + guint month; + guint day; + GtkTreeIter it; + GtkTreeIter parent; + GtkCellRendererText *renderer; + GtkTreeSelection * ts; + gboolean has_parent; + char *path; + int not_dummy; + char fancydate[128]; + char *gndate; + struct GNUNET_TIME_Absolute atime; + + if (GTK_RESPONSE_OK != response_id) + { + gtk_widget_destroy (GTK_WIDGET (dialog)); + g_object_unref (G_OBJECT (builder)); + return; + } + gtk_calendar_get_date (GTK_CALENDAR (gtk_builder_get_object (builder, + "GNUNET_setup_calendar")), + &year, &month, &day); + GNUNET_snprintf (fancydate, + sizeof (fancydate), + "%u-%u-%u", + (unsigned int) year, + (unsigned int) month + 1, + (unsigned int) day); + GNUNET_break (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (fancydate, + &atime)); + gndate = GNUNET_STRINGS_absolute_time_to_string (atime); + ts = gtk_tree_view_get_selection(tv); + if (gtk_tree_selection_get_selected (ts, &tm, &it)) + { + gtk_tree_model_get (tm, &it, + GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, + -1); + if (GNUNET_NO != not_dummy) + { + /* Has parent? */ + has_parent = gtk_tree_model_iter_parent (tm, &parent, &it); + if (FALSE != has_parent) + { + /* this is a single record */ + renderer = GTK_CELL_RENDERER_TEXT((GNUNET_SETUP_get_object ("GNUNET_setup_gns_name_cellrenderertext"))); + path = gtk_tree_model_get_string_from_iter (tm, &it); + GNUNET_setup_gns_expiration_cellrenderertext_edited_cb (renderer, + path, + gndate, + NULL); + } + } + } + GNUNET_free (gndate); + gtk_widget_destroy (GTK_WIDGET (dialog)); + g_object_unref (G_OBJECT (builder)); +} + + +/** + * User selected the 'calendar' option in the expiration context menu. + * Popup the calendar dialog and allow the user to select a date. + * + * @param widget unused + * @param user_data unused + */ +void +GNUNET_setup_gns_popup_cal_button_activate_cb (GtkWidget *widget, + gpointer user_data) +{ + GtkBuilder *builder; + GtkWindow *dialog; + GtkTreeSelection * tsel; + gboolean has_parent; + int not_dummy; + guint64 et; + gboolean is_relative; + GtkTreeIter it; + GtkTreeIter parent; + struct GNUNET_TIME_Absolute now; + time_t tp; + struct tm *ymd; + + tsel = gtk_tree_view_get_selection(tv); + if (! gtk_tree_selection_get_selected (tsel, &tm, &it)) + return; + gtk_tree_model_get (tm, &it, + GNS_TREESTORE_COL_NOT_DUMMY_ROW, ¬_dummy, + GNS_TREESTORE_COL_EXP_TIME_IS_REL, &is_relative, + GNS_TREESTORE_COL_EXP_TIME, &et, + -1); + if (! not_dummy) + return; + has_parent = gtk_tree_model_iter_parent (tm, &parent, &it); + if (! has_parent) + return; + now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get (); + if (is_relative) + et = now.abs_value; /* use today as starting point */ + if (et < now.abs_value) + et = now.abs_value; /* no not allow starting point in the past */ + tp = (time_t) (et / 1000LL); /* convert to seconds */ + builder = + GNUNET_GTK_get_new_builder ("gnunet_setup_calendar_dialog.glade", + NULL); + if (NULL == builder) + { + GNUNET_break (0); + return; + } + ymd = gmtime (&tp); + gtk_calendar_select_month (GTK_CALENDAR (gtk_builder_get_object (builder, + "GNUNET_setup_calendar")), + ymd->tm_mon, + ymd->tm_year + 1900); + gtk_calendar_mark_day (GTK_CALENDAR (gtk_builder_get_object (builder, + "GNUNET_setup_calendar")), + ymd->tm_mday); + dialog = GTK_WINDOW (gtk_builder_get_object + (builder, "GNUNET_setup_calendar_dialog")); + gtk_window_present (dialog); +} + + /** * A button was pressed in the GtkTreeView, check for right button and * if applicable create the popup menu. @@ -1515,12 +1532,12 @@ zone_iteration_proc (void *cls, GtkTreeIter iter_record; GtkEntry *pseu_entry; int c; - int time_is_relative; struct GNUNET_CRYPTO_ShortHashAsciiEncoded shenc; char *exp; char *val; char * type_str; - int public; + gboolean time_is_relative; + gboolean public; guint64 exp_t; GNUNET_assert (NULL != zc_ctx); @@ -1569,26 +1586,16 @@ zone_iteration_proc (void *cls, c, rd[c].record_type, rd[c].flags, rd[c].expiration_time, rd[c].data_size); /* Set public toggle */ - if ((rd[c].flags & GNUNET_NAMESTORE_RF_PRIVATE) == GNUNET_NAMESTORE_RF_PRIVATE) - { - public = GNUNET_NO; - } - else - { - public = GNUNET_YES; - } - + public = ((rd[c].flags & GNUNET_NAMESTORE_RF_PRIVATE) != GNUNET_NAMESTORE_RF_PRIVATE); /* Expiration time */ - time_is_relative = GNUNET_NO; - - if (GNUNET_YES == time_is_relative) + time_is_relative = (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); + if (time_is_relative) { - /* TODO: FIX THIS WHEN WE HAVE RELATIVE TIME */ - struct GNUNET_TIME_Relative rel_time = GNUNET_TIME_UNIT_ZERO; - struct GNUNET_TIME_Absolute exp_abs; - exp_abs = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), rel_time); - exp_t = exp_abs.abs_value; - exp = convert_time_to_string (exp_abs); + struct GNUNET_TIME_Relative rel_time; + + rel_time.rel_value = rd[c].expiration_time; + exp_t = rel_time.rel_value; + exp = GNUNET_STRINGS_relative_time_to_string (rel_time); } else { @@ -1596,21 +1603,21 @@ zone_iteration_proc (void *cls, exp_abs.abs_value = rd[c].expiration_time; exp_t = exp_abs.abs_value; - exp = convert_time_to_string (exp_abs); + exp = GNUNET_STRINGS_absolute_time_to_string (exp_abs); } /* value */ val = GNUNET_NAMESTORE_value_to_string (rd[c].record_type, rd[c].data, rd[c].data_size); if (NULL == val) - GNUNET_asprintf(&val, "%s", EXPIRE_INVALID_STRING); + GNUNET_asprintf (&val, "%s", EXPIRE_INVALID_STRING); if (NULL != GNUNET_NAMESTORE_number_to_typename(rd[c].record_type)) type_str = strdup (GNUNET_NAMESTORE_number_to_typename(rd[c].record_type)); else GNUNET_asprintf(&type_str, "%s", EXPIRE_INVALID_STRING); - if ((0 ==strcmp (name, ROOT_STR)) && (GNUNET_NAMESTORE_TYPE_PSEU == rd[c].record_type)) + if ((0 == strcmp (name, ROOT_STR)) && (GNUNET_NAMESTORE_TYPE_PSEU == rd[c].record_type)) { zc_ctx->label = strdup(val); iteration = GNUNET_YES; -- cgit v1.2.3