diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-01-19 22:45:53 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-01-19 22:45:53 +0100 |
commit | 6dfafa176e35f24268f1224f5cb499c27b3ad578 (patch) | |
tree | 63d9d5570b9d094ae40e37f271383dcf5602bdc9 | |
parent | f60427ebc5369faa43b9ad721d15dbbd6e92baf8 (diff) | |
download | anastasis-gtk-6dfafa176e35f24268f1224f5cb499c27b3ad578.tar.gz anastasis-gtk-6dfafa176e35f24268f1224f5cb499c27b3ad578.zip |
-wip
-rw-r--r-- | TODO | 26 | ||||
-rw-r--r-- | src/anastasis/Makefile.am | 2 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk.c | 10 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk.h | 5 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk_action.c | 205 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk_handle-main-window-back-clicked.c | 5 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c | 50 | ||||
-rw-r--r-- | src/anastasis/anastasis-gtk_helper.h | 37 |
8 files changed, 206 insertions, 134 deletions
@@ -0,0 +1,26 @@ | |||
1 | - add 'more' button to download 'more' policies | ||
2 | when selecting secret for recovery (needs cursor implementation!) | ||
3 | - implement 'add provider' button to add additional providers | ||
4 | when selecting secret for recovery (check with reducer if | ||
5 | the needed transition is supported!) | ||
6 | => implement 'anastasis_gtk_add_provider_button_clicked_cb' | ||
7 | |||
8 | - check if transitions done with new secret selection logic | ||
9 | are actually OK! | ||
10 | => after adding personal information, we currently immediately | ||
11 | jump into downloading some/all/many policies | ||
12 | => change that logic in the reducer! | ||
13 | => new state with personal information attributes and | ||
14 | list of providers, transitions: 'next' with provider+version+mask | ||
15 | or 'add_provider' with provider_url! | ||
16 | - implement 'mask' in reducer logic of anastasis.git! | ||
17 | (mask field is currently set, but then not used!) | ||
18 | |||
19 | |||
20 | Bugs: | ||
21 | |||
22 | 2022-01-19T22:41:46.983703+0100 anastasis-gtk-44468 ERROR Widget `anastasis_gtk_secret_identification_vbox' not found, cannot hide it! | ||
23 | [=> renamed?] | ||
24 | |||
25 | 2022-01-19T22:41:46.983735+0100 anastasis-gtk-44468 ERROR Assertion failed at anastasis_api_discovery.c:279. | ||
26 | [=> diagnose!] \ No newline at end of file | ||
diff --git a/src/anastasis/Makefile.am b/src/anastasis/Makefile.am index cf0bbcf..6827f8e 100644 --- a/src/anastasis/Makefile.am +++ b/src/anastasis/Makefile.am | |||
@@ -48,7 +48,7 @@ anastasis_gtk_SOURCES = \ | |||
48 | anastasis-gtk_handle-policy-activate.c \ | 48 | anastasis-gtk_handle-policy-activate.c \ |
49 | anastasis-gtk_handle-policy-button.c \ | 49 | anastasis-gtk_handle-policy-button.c \ |
50 | anastasis-gtk_handle-policy-meta.c \ | 50 | anastasis-gtk_handle-policy-meta.c \ |
51 | anastasis-gtk_handle-policy-version-changed.c \ | 51 | anastasis-gtk_handle-policy-selection-changed.c \ |
52 | anastasis-gtk_handle-recovery-button-clicked.c \ | 52 | anastasis-gtk_handle-recovery-button-clicked.c \ |
53 | anastasis-gtk_handle-secret-buttons.c \ | 53 | anastasis-gtk_handle-secret-buttons.c \ |
54 | anastasis-gtk_helper.c anastasis-gtk_helper.h \ | 54 | anastasis-gtk_helper.c anastasis-gtk_helper.h \ |
diff --git a/src/anastasis/anastasis-gtk.c b/src/anastasis/anastasis-gtk.c index 13e92a2..7d0a990 100644 --- a/src/anastasis/anastasis-gtk.c +++ b/src/anastasis/anastasis-gtk.c | |||
@@ -36,6 +36,11 @@ | |||
36 | struct GNUNET_GTK_MainLoop *AG_ml; | 36 | struct GNUNET_GTK_MainLoop *AG_ml; |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Active policy discovery job, or NULL. | ||
40 | */ | ||
41 | struct ANASTASIS_PolicyDiscovery *AG_pd; | ||
42 | |||
43 | /** | ||
39 | * Our configuration. | 44 | * Our configuration. |
40 | */ | 45 | */ |
41 | const struct GNUNET_CONFIGURATION_Handle *AG_cfg; | 46 | const struct GNUNET_CONFIGURATION_Handle *AG_cfg; |
@@ -104,6 +109,11 @@ shutdown_task (void *cls) | |||
104 | (void) cls; | 109 | (void) cls; |
105 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 110 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
106 | "Shutdown initiated\n"); | 111 | "Shutdown initiated\n"); |
112 | if (NULL != AG_pd) | ||
113 | { | ||
114 | ANASTASIS_policy_discovery_stop (AG_pd); | ||
115 | AG_pd = NULL; | ||
116 | } | ||
107 | ANASTASIS_redux_done (); | 117 | ANASTASIS_redux_done (); |
108 | if (NULL != AG_ra) | 118 | if (NULL != AG_ra) |
109 | { | 119 | { |
diff --git a/src/anastasis/anastasis-gtk.h b/src/anastasis/anastasis-gtk.h index 5151383..7497223 100644 --- a/src/anastasis/anastasis-gtk.h +++ b/src/anastasis/anastasis-gtk.h | |||
@@ -37,6 +37,11 @@ | |||
37 | extern struct GNUNET_GTK_MainLoop *AG_ml; | 37 | extern struct GNUNET_GTK_MainLoop *AG_ml; |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * Active policy discovery job, or NULL. | ||
41 | */ | ||
42 | extern struct ANASTASIS_PolicyDiscovery *AG_pd; | ||
43 | |||
44 | /** | ||
40 | * Our configuration. | 45 | * Our configuration. |
41 | */ | 46 | */ |
42 | extern const struct GNUNET_CONFIGURATION_Handle *AG_cfg; | 47 | extern const struct GNUNET_CONFIGURATION_Handle *AG_cfg; |
diff --git a/src/anastasis/anastasis-gtk_action.c b/src/anastasis/anastasis-gtk_action.c index df6edb0..7ab6149 100644 --- a/src/anastasis/anastasis-gtk_action.c +++ b/src/anastasis/anastasis-gtk_action.c | |||
@@ -1893,13 +1893,73 @@ show_challenge_feedback (const char *uuid, | |||
1893 | 1893 | ||
1894 | 1894 | ||
1895 | /** | 1895 | /** |
1896 | * FIXME. | 1896 | * Function called on each discovered recovery policy. Called |
1897 | * with all arguments NULL if we have received all policies that | ||
1898 | * we could possibly receive for the current operation. | ||
1899 | * | ||
1900 | * The client can then start a new policy discovery process, using the | ||
1901 | * smallest (also most recent) @a version received per @a provider_url | ||
1902 | * in the cursor to resume. Note that in this case, the application | ||
1903 | * logic is responsible for de-duplication using @a hcpd, or it may show | ||
1904 | * policies again if they are at different providers under versions not | ||
1905 | * queried up to the cursor. | ||
1906 | * | ||
1907 | * @param cls closure with the `GtkListStore` to update. | ||
1908 | * @param hcpd hash of the compressed policy document (unique per policy) | ||
1909 | * @param provider_url which provider claims to have this policy | ||
1910 | * @param version version of the policy at this provider | ||
1911 | * @param attribute_mask combination of optional identity attributes | ||
1912 | * present in the state that was used to locate this version | ||
1913 | * @param server_time when did the provider receive the upload | ||
1914 | * @param secret_name name the user assigned to the backup | ||
1915 | */ | ||
1916 | static void | ||
1917 | expand_policy_list (void *cls, | ||
1918 | const struct GNUNET_HashCode *hcpd, | ||
1919 | const char *provider_url, | ||
1920 | uint32_t version, | ||
1921 | json_int_t attribute_mask, | ||
1922 | struct GNUNET_TIME_Timestamp server_time, | ||
1923 | const char *secret_name) | ||
1924 | { | ||
1925 | GtkListStore *ls = cls; | ||
1926 | GtkTreeIter iter; | ||
1927 | bool first; | ||
1928 | |||
1929 | first = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (ls), | ||
1930 | &iter); | ||
1931 | gtk_list_store_insert_with_values ( | ||
1932 | ls, | ||
1933 | &iter, | ||
1934 | -1, /* append */ | ||
1935 | AG_SSMC_PROVIDER_URL, provider_url, | ||
1936 | AG_SSMC_POLICY_VERSION, (gint) version, | ||
1937 | AG_SSMC_ATTRIBUTE_MASK, (gint) attribute_mask, | ||
1938 | AG_SSMC_SECRET_NAME, secret_name, | ||
1939 | AG_SSMC_POLICY_DATE_STRING, GNUNET_TIME_timestamp2s (server_time), | ||
1940 | AG_SSMC_POLICY_DATE_NUMERIC, (guint64) server_time.abs_time.abs_value_us, | ||
1941 | -1); | ||
1942 | if (first) | ||
1943 | { | ||
1944 | GtkTreeSelection *selection; | ||
1945 | |||
1946 | selection = GTK_TREE_SELECTION ( | ||
1947 | GCG_get_main_window_object ( | ||
1948 | "anastasis_gtk_secret_selection_treeselection")); | ||
1949 | gtk_tree_selection_select_iter (selection, | ||
1950 | &iter); | ||
1951 | } | ||
1952 | } | ||
1953 | |||
1954 | |||
1955 | /** | ||
1956 | * Function called when it is time for the user to select a secret | ||
1957 | * from the list of secrets. Builds the respective tree model. | ||
1897 | */ | 1958 | */ |
1898 | static void | 1959 | static void |
1899 | action_secret_selecting (void) | 1960 | action_secret_selecting (void) |
1900 | { | 1961 | { |
1901 | json_t *ri; | 1962 | GtkListStore *ls; |
1902 | json_t *re; | ||
1903 | 1963 | ||
1904 | AG_hide ("anastasis_gtk_start_frame"); | 1964 | AG_hide ("anastasis_gtk_start_frame"); |
1905 | if (AG_have_error) | 1965 | if (AG_have_error) |
@@ -1907,134 +1967,15 @@ action_secret_selecting (void) | |||
1907 | AG_hide ("anastasis_gtk_challenge_frame"); | 1967 | AG_hide ("anastasis_gtk_challenge_frame"); |
1908 | AG_hide ("anastasis_gtk_identity_frame"); | 1968 | AG_hide ("anastasis_gtk_identity_frame"); |
1909 | AG_hide ("anastasis_gtk_secret_identification_vbox"); | 1969 | AG_hide ("anastasis_gtk_secret_identification_vbox"); |
1910 | re = json_object_get (AG_redux_state, | 1970 | ls = GTK_LIST_STORE (GCG_get_main_window_object ( |
1911 | "recovery_error"); | 1971 | "secret_selection_liststore")); |
1912 | if (NULL != re) | 1972 | gtk_list_store_clear (ls); |
1913 | { | 1973 | GNUNET_assert (NULL != ls); |
1914 | bool offline; | 1974 | GNUNET_assert (NULL == AG_pd); |
1915 | const char *hint; | 1975 | AG_pd = ANASTASIS_policy_discovery_start (AG_redux_state, |
1916 | struct GNUNET_JSON_Specification espec[] = { | 1976 | NULL, |
1917 | GNUNET_JSON_spec_bool ("offline", | 1977 | &expand_policy_list, |
1918 | &offline), | 1978 | ls); |
1919 | GNUNET_JSON_spec_string ("hint", | ||
1920 | &hint), | ||
1921 | GNUNET_JSON_spec_end () | ||
1922 | }; | ||
1923 | |||
1924 | AG_insensitive ("anastasis_gtk_main_window_forward_button"); | ||
1925 | if (GNUNET_OK != | ||
1926 | GNUNET_JSON_parse (re, | ||
1927 | espec, | ||
1928 | NULL, NULL)) | ||
1929 | { | ||
1930 | GNUNET_break_op (0); | ||
1931 | AG_error ("'recovery_error' did not parse correctly"); | ||
1932 | return; | ||
1933 | } | ||
1934 | AG_error ("%s", | ||
1935 | dgettext ("taler-exchange", | ||
1936 | hint)); | ||
1937 | AG_show ("anastasis_gtk_progress_vbox"); | ||
1938 | AG_progress_update (); | ||
1939 | AG_show ("anastasis_gtk_recovery_progress_scrolled_window"); | ||
1940 | AG_hide ("anastasis_gtk_backup_progress_scrolled_window"); | ||
1941 | AG_show ("anastasis_gtk_main_control_vbox"); | ||
1942 | AG_show ("anastasis_gtk_main_window_save_as_button"); | ||
1943 | AG_show ("anastasis_gtk_select_secret_frame"); | ||
1944 | AG_show ("anastasis_gtk_main_window_prev_button"); | ||
1945 | AG_hide ("anastasis_gtk_main_window_quit_button"); | ||
1946 | return; | ||
1947 | } | ||
1948 | else | ||
1949 | { | ||
1950 | json_t *aps; | ||
1951 | GtkComboBoxText *bt; | ||
1952 | const json_t *ap; | ||
1953 | const char *provider_url; | ||
1954 | |||
1955 | bt = GTK_COMBO_BOX_TEXT (GCG_get_main_window_object ( | ||
1956 | "anastasis_gtk_provider_url_combo_box_text")); | ||
1957 | gtk_combo_box_text_remove_all (bt); | ||
1958 | aps = json_object_get (AG_redux_state, | ||
1959 | "authentication_providers"); | ||
1960 | json_object_foreach (aps, | ||
1961 | provider_url, | ||
1962 | ap) | ||
1963 | { | ||
1964 | gtk_combo_box_text_insert_text (bt, | ||
1965 | -1, /* append */ | ||
1966 | provider_url); | ||
1967 | } | ||
1968 | } | ||
1969 | ri = json_object_get (AG_redux_state, | ||
1970 | "recovery_information"); | ||
1971 | if (NULL != ri) | ||
1972 | { | ||
1973 | uint64_t version; | ||
1974 | const char *provider_url; | ||
1975 | struct GNUNET_JSON_Specification vspec[] = { | ||
1976 | GNUNET_JSON_spec_uint64 ("version", | ||
1977 | &version), | ||
1978 | GNUNET_JSON_spec_string ("provider_url", | ||
1979 | &provider_url), | ||
1980 | GNUNET_JSON_spec_end () | ||
1981 | }; | ||
1982 | GtkSpinButton *sb; | ||
1983 | |||
1984 | if (GNUNET_OK != | ||
1985 | GNUNET_JSON_parse (ri, | ||
1986 | vspec, | ||
1987 | NULL, NULL)) | ||
1988 | { | ||
1989 | GNUNET_break_op (0); | ||
1990 | AG_error ("'recovery_information' did not parse correctly"); | ||
1991 | return; | ||
1992 | } | ||
1993 | sb = GTK_SPIN_BUTTON (GCG_get_main_window_object ( | ||
1994 | "anastasis_gtk_policy_version_spin_button")); | ||
1995 | gtk_spin_button_set_value (sb, | ||
1996 | version); | ||
1997 | if (NULL == re) | ||
1998 | update_entry ("anastasis_gtk_provider_url_entry", | ||
1999 | provider_url); | ||
2000 | } | ||
2001 | else | ||
2002 | { | ||
2003 | GtkWidget *ge; | ||
2004 | |||
2005 | ge = GTK_WIDGET (GCG_get_main_window_object ( | ||
2006 | "anastasis_gtk_provider_url_entry")); | ||
2007 | if (! gtk_widget_has_focus (ge)) | ||
2008 | gtk_widget_grab_focus (ge); | ||
2009 | } | ||
2010 | { | ||
2011 | json_t *rd; | ||
2012 | const char *sn; | ||
2013 | |||
2014 | rd = json_object_get (AG_redux_state, | ||
2015 | "recovery_document"); | ||
2016 | if (NULL == rd) | ||
2017 | { | ||
2018 | AG_insensitive ("anastasis_gtk_main_window_forward_button"); | ||
2019 | } | ||
2020 | else | ||
2021 | { | ||
2022 | AG_enable_next (); | ||
2023 | sn = json_string_value (json_object_get (rd, | ||
2024 | "secret_name")); | ||
2025 | if (NULL != sn) | ||
2026 | { | ||
2027 | update_label ("anastasis_gtk_secret_name_label", | ||
2028 | sn); | ||
2029 | } | ||
2030 | else | ||
2031 | { | ||
2032 | update_label ("anastasis_gtk_secret_name_label", | ||
2033 | _ ("<not set>")); | ||
2034 | } | ||
2035 | AG_show ("anastasis_gtk_secret_identification_vbox"); | ||
2036 | } | ||
2037 | } | ||
2038 | AG_show ("anastasis_gtk_progress_vbox"); | 1979 | AG_show ("anastasis_gtk_progress_vbox"); |
2039 | AG_progress_update (); | 1980 | AG_progress_update (); |
2040 | AG_show ("anastasis_gtk_recovery_progress_scrolled_window"); | 1981 | AG_show ("anastasis_gtk_recovery_progress_scrolled_window"); |
@@ -2044,7 +1985,7 @@ action_secret_selecting (void) | |||
2044 | AG_show ("anastasis_gtk_select_secret_frame"); | 1985 | AG_show ("anastasis_gtk_select_secret_frame"); |
2045 | AG_show ("anastasis_gtk_main_window_prev_button"); | 1986 | AG_show ("anastasis_gtk_main_window_prev_button"); |
2046 | AG_hide ("anastasis_gtk_main_window_quit_button"); | 1987 | AG_hide ("anastasis_gtk_main_window_quit_button"); |
2047 | AG_enable_next (); | 1988 | AG_insensitive ("anastasis_gtk_main_window_forward_button"); |
2048 | } | 1989 | } |
2049 | 1990 | ||
2050 | 1991 | ||
diff --git a/src/anastasis/anastasis-gtk_handle-main-window-back-clicked.c b/src/anastasis/anastasis-gtk_handle-main-window-back-clicked.c index ed3fb85..a0f76a5 100644 --- a/src/anastasis/anastasis-gtk_handle-main-window-back-clicked.c +++ b/src/anastasis/anastasis-gtk_handle-main-window-back-clicked.c | |||
@@ -69,6 +69,11 @@ anastasis_gtk_main_window_back_clicked (GObject *object, | |||
69 | ANASTASIS_redux_action_cancel (AG_ra); | 69 | ANASTASIS_redux_action_cancel (AG_ra); |
70 | AG_ra = NULL; | 70 | AG_ra = NULL; |
71 | } | 71 | } |
72 | if (NULL != AG_pd) | ||
73 | { | ||
74 | ANASTASIS_policy_discovery_stop (AG_pd); | ||
75 | AG_pd = NULL; | ||
76 | } | ||
72 | state = json_string_value (json_object_get (AG_redux_state, | 77 | state = json_string_value (json_object_get (AG_redux_state, |
73 | "recovery_state")); | 78 | "recovery_state")); |
74 | if (NULL == state) | 79 | if (NULL == state) |
diff --git a/src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c b/src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c index 8ce8e3b..c3e78f3 100644 --- a/src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c +++ b/src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c | |||
@@ -435,15 +435,63 @@ forward_secret_editing (void) | |||
435 | } | 435 | } |
436 | 436 | ||
437 | 437 | ||
438 | /** | ||
439 | * The user has pressed 'next' after selecting a secret to recover. | ||
440 | */ | ||
438 | static void | 441 | static void |
439 | forward_secret_selecting (void) | 442 | forward_secret_selecting (void) |
440 | { | 443 | { |
444 | GtkTreeSelection *selection; | ||
445 | GtkTreeModel *model; | ||
446 | GtkTreeIter iter; | ||
447 | json_t *args; | ||
448 | char *provider_url; | ||
449 | gint version; | ||
450 | gint mask; | ||
451 | |||
441 | AG_freeze (); | 452 | AG_freeze (); |
453 | if (NULL != AG_pd) | ||
454 | { | ||
455 | ANASTASIS_policy_discovery_stop (AG_pd); | ||
456 | AG_pd = NULL; | ||
457 | } | ||
458 | selection = GTK_TREE_SELECTION ( | ||
459 | GCG_get_main_window_object ( | ||
460 | "anastasis_gtk_secret_selection_treeselection")); | ||
461 | |||
462 | if (! gtk_tree_selection_get_selected (selection, | ||
463 | &model, | ||
464 | &iter)) | ||
465 | { | ||
466 | GNUNET_break (0); | ||
467 | AG_insensitive ("anastasis_gtk_main_window_forward_button"); | ||
468 | return; | ||
469 | } | ||
470 | gtk_tree_model_get (model, | ||
471 | &iter, | ||
472 | AG_SSMC_PROVIDER_URL, &provider_url, | ||
473 | AG_SSMC_POLICY_VERSION, &version, | ||
474 | AG_SSMC_ATTRIBUTE_MASK, &mask, | ||
475 | -1); | ||
476 | args = GNUNET_JSON_PACK ( | ||
477 | GNUNET_JSON_pack_string ("provider_url", | ||
478 | provider_url), | ||
479 | GNUNET_JSON_pack_uint64 ("version", | ||
480 | version), | ||
481 | GNUNET_JSON_pack_uint64 ("mask", | ||
482 | mask) | ||
483 | ); | ||
484 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
485 | "Proceeding with policy version %u at provider %s\n", | ||
486 | (unsigned int) version, | ||
487 | provider_url); | ||
488 | g_free (provider_url); | ||
442 | AG_ra = ANASTASIS_redux_action (AG_redux_state, | 489 | AG_ra = ANASTASIS_redux_action (AG_redux_state, |
443 | "next", | 490 | "next", |
444 | NULL, | 491 | args, |
445 | &AG_action_cb, | 492 | &AG_action_cb, |
446 | NULL); | 493 | NULL); |
494 | json_decref (args); | ||
447 | } | 495 | } |
448 | 496 | ||
449 | 497 | ||
diff --git a/src/anastasis/anastasis-gtk_helper.h b/src/anastasis/anastasis-gtk_helper.h index 2cd3d7a..b19e6dd 100644 --- a/src/anastasis/anastasis-gtk_helper.h +++ b/src/anastasis/anastasis-gtk_helper.h | |||
@@ -58,6 +58,43 @@ enum AG_ContinentsModelColumns | |||
58 | 58 | ||
59 | 59 | ||
60 | /** | 60 | /** |
61 | * Columns of the secret_selection_liststore. | ||
62 | */ | ||
63 | enum AG_SecretSelectionModelColumns | ||
64 | { | ||
65 | /** | ||
66 | * A gchararray. | ||
67 | */ | ||
68 | AG_SSMC_PROVIDER_URL = 0, | ||
69 | |||
70 | /** | ||
71 | * A gint. | ||
72 | */ | ||
73 | AG_SSMC_POLICY_VERSION = 1, | ||
74 | |||
75 | /** | ||
76 | * A gint. | ||
77 | */ | ||
78 | AG_SSMC_ATTRIBUTE_MASK = 2, | ||
79 | |||
80 | /** | ||
81 | * A gchararray. | ||
82 | */ | ||
83 | AG_SSMC_SECRET_NAME = 3, | ||
84 | |||
85 | /** | ||
86 | * A gchararray. | ||
87 | */ | ||
88 | AG_SSMC_POLICY_DATE_STRING = 4, | ||
89 | |||
90 | /** | ||
91 | * A guint64. | ||
92 | */ | ||
93 | AG_SSMC_POLICY_DATE_NUMERIC = 5 | ||
94 | }; | ||
95 | |||
96 | |||
97 | /** | ||
61 | * Columns of the currency_liststore. | 98 | * Columns of the currency_liststore. |
62 | */ | 99 | */ |
63 | enum AG_CurrencyModelColumns | 100 | enum AG_CurrencyModelColumns |