diff --git a/data/geany.glade b/data/geany.glade index d2c44f72e..99cbe40fc 100644 --- a/data/geany.glade +++ b/data/geany.glade @@ -433,12 +433,6 @@ - - - - - - @@ -4368,12 +4362,8 @@ True False - encoding_list - - - 0 - + @@ -4434,12 +4424,8 @@ True False - encoding_list - - - 0 - + diff --git a/src/dialogs.c b/src/dialogs.c index 02976e7db..fa520b9f6 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -125,8 +125,6 @@ static void open_file_dialog_handle_response(GtkWidget *dialog, gint response) if (response == GTK_RESPONSE_ACCEPT || response == GEANY_RESPONSE_VIEW) { GSList *filelist; - GtkTreeModel *encoding_model; - GtkTreeIter encoding_iter; GeanyFiletype *ft = NULL; const gchar *charset = NULL; GtkWidget *expander = ui_lookup_widget(dialog, "more_options_expander"); @@ -142,9 +140,7 @@ static void open_file_dialog_handle_response(GtkWidget *dialog, gint response) if (filesel_state.open.filetype_idx > 0) ft = g_slist_nth_data(filetypes_by_title, (guint) filesel_state.open.filetype_idx); - encoding_model = gtk_combo_box_get_model(GTK_COMBO_BOX(encoding_combo)); - gtk_combo_box_get_active_iter(GTK_COMBO_BOX(encoding_combo), &encoding_iter); - gtk_tree_model_get(encoding_model, &encoding_iter, 0, &filesel_state.open.encoding_idx, -1); + filesel_state.open.encoding_idx = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(encoding_combo)); if (filesel_state.open.encoding_idx >= 0 && filesel_state.open.encoding_idx < GEANY_ENCODINGS_MAX) charset = encodings[filesel_state.open.encoding_idx].charset; @@ -182,97 +178,6 @@ on_file_open_check_hidden_toggled(GtkToggleButton *togglebutton, GtkWidget *dial } -static gint encoding_combo_store_sort_func(GtkTreeModel *model, - GtkTreeIter *a, - GtkTreeIter *b, - gpointer data) -{ - gboolean a_has_child = gtk_tree_model_iter_has_child(model, a); - gboolean b_has_child = gtk_tree_model_iter_has_child(model, b); - gchar *a_string; - gchar *b_string; - gint cmp_res; - - if (a_has_child != b_has_child) - return a_has_child ? -1 : 1; - - gtk_tree_model_get(model, a, 1, &a_string, -1); - gtk_tree_model_get(model, b, 1, &b_string, -1); - cmp_res = strcmp(a_string, b_string); - g_free(a_string); - g_free(b_string); - return cmp_res; -} - - -static GtkTreeStore *create_encoding_combo_store(GtkTreeIter *iter_detect) -{ - GtkTreeStore *store; - GtkTreeIter iter_current, iter_westeuro, iter_easteuro, iter_eastasian, iter_asian, - iter_utf8, iter_middleeast; - GtkTreeIter *iter_parent; - gchar *encoding_string; - gint i; - - store = gtk_tree_store_new(2, G_TYPE_INT, G_TYPE_STRING); - - gtk_tree_store_append(store, iter_detect, NULL); - gtk_tree_store_set(store, iter_detect, 0, GEANY_ENCODINGS_MAX, 1, _("Detect from file"), -1); - - gtk_tree_store_append(store, &iter_westeuro, NULL); - gtk_tree_store_set(store, &iter_westeuro, 0, -1, 1, _("West European"), -1); - gtk_tree_store_append(store, &iter_easteuro, NULL); - gtk_tree_store_set(store, &iter_easteuro, 0, -1, 1, _("East European"), -1); - gtk_tree_store_append(store, &iter_eastasian, NULL); - gtk_tree_store_set(store, &iter_eastasian, 0, -1, 1, _("East Asian"), -1); - gtk_tree_store_append(store, &iter_asian, NULL); - gtk_tree_store_set(store, &iter_asian, 0, -1, 1, _("SE & SW Asian"), -1); - gtk_tree_store_append(store, &iter_middleeast, NULL); - gtk_tree_store_set(store, &iter_middleeast, 0, -1, 1, _("Middle Eastern"), -1); - gtk_tree_store_append(store, &iter_utf8, NULL); - gtk_tree_store_set(store, &iter_utf8, 0, -1, 1, _("Unicode"), -1); - - for (i = 0; i < GEANY_ENCODINGS_MAX; i++) - { - switch (encodings[i].group) - { - case WESTEUROPEAN: iter_parent = &iter_westeuro; break; - case EASTEUROPEAN: iter_parent = &iter_easteuro; break; - case EASTASIAN: iter_parent = &iter_eastasian; break; - case ASIAN: iter_parent = &iter_asian; break; - case MIDDLEEASTERN: iter_parent = &iter_middleeast; break; - case UNICODE: iter_parent = &iter_utf8; break; - case NONE: - default: iter_parent = NULL; - } - gtk_tree_store_append(store, &iter_current, iter_parent); - encoding_string = encodings_to_string(&encodings[i]); - gtk_tree_store_set(store, &iter_current, 0, i, 1, encoding_string, -1); - g_free(encoding_string); - /* restore the saved state */ - if (i == filesel_state.open.encoding_idx) - *iter_detect = iter_current; - } - - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), 1, GTK_SORT_ASCENDING); - gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), 1, encoding_combo_store_sort_func, NULL, NULL); - - return store; -} - - -static void encoding_combo_cell_data_func(GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer data) -{ - gboolean sensitive = !gtk_tree_model_iter_has_child(tree_model, iter); - - g_object_set(cell, "sensitive", sensitive, NULL); -} - - static GtkWidget *add_file_open_extra_widget(GtkWidget *dialog) { GtkWidget *expander, *vbox, *table, *check_hidden; @@ -304,7 +209,7 @@ static GtkWidget *add_file_open_extra_widget(GtkWidget *dialog) (GtkAttachOptions) (0), 4, 5); /* the ebox is for the tooltip, because gtk_combo_box can't show tooltips */ encoding_ebox = gtk_event_box_new(); - encoding_combo = gtk_combo_box_new(); + encoding_combo = ui_create_encodings_combo_box(TRUE, GEANY_ENCODINGS_MAX); gtk_widget_set_tooltip_text(encoding_ebox, _("Explicitly defines an encoding for the file, if it would not be detected. This is useful when you know that the encoding of a file cannot be detected correctly by Geany.\nNote if you choose multiple files, they will all be opened with the chosen encoding.")); gtk_container_add(GTK_CONTAINER(encoding_ebox), encoding_combo); @@ -345,10 +250,8 @@ static GtkWidget *add_file_open_extra_widget(GtkWidget *dialog) static GtkWidget *create_open_file_dialog(void) { GtkWidget *dialog; - GtkWidget *filetype_combo, *encoding_combo; + GtkWidget *filetype_combo; GtkWidget *viewbtn; - GtkCellRenderer *encoding_renderer; - GtkTreeIter encoding_iter; GSList *node; dialog = gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window), @@ -396,17 +299,6 @@ static GtkWidget *create_open_file_dialog(void) gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(filetype_combo), 3); gtk_combo_box_set_active(GTK_COMBO_BOX(filetype_combo), 0); - /* fill encoding combo box */ - encoding_combo = ui_lookup_widget(dialog, "encoding_combo"); - gtk_combo_box_set_model(GTK_COMBO_BOX(encoding_combo), GTK_TREE_MODEL( - create_encoding_combo_store(&encoding_iter))); - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(encoding_combo), &encoding_iter); - encoding_renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(encoding_combo), encoding_renderer, TRUE); - gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(encoding_combo), encoding_renderer, "text", 1); - gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(encoding_combo), encoding_renderer, - encoding_combo_cell_data_func, NULL, NULL); - g_signal_connect(dialog, "notify::show-hidden", G_CALLBACK(on_file_open_show_hidden_notify), NULL); @@ -419,6 +311,7 @@ static void open_file_dialog_apply_settings(GtkWidget *dialog) static gboolean initialized = FALSE; GtkWidget *check_hidden = ui_lookup_widget(dialog, "check_hidden"); GtkWidget *filetype_combo = ui_lookup_widget(dialog, "filetype_combo"); + GtkWidget *encoding_combo = ui_lookup_widget(dialog, "encoding_combo"); GtkWidget *expander = ui_lookup_widget(dialog, "more_options_expander"); /* we can't know the initial position of combo boxes, so retreive it the first time */ @@ -436,7 +329,7 @@ static void open_file_dialog_apply_settings(GtkWidget *dialog) } gtk_expander_set_expanded(GTK_EXPANDER(expander), filesel_state.open.more_options_visible); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_hidden), filesel_state.open.show_hidden); - /* encoding combo is restored at creating time, see create_encoding_combo_store() */ + ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(encoding_combo), filesel_state.open.encoding_idx); } diff --git a/src/encodings.c b/src/encodings.c index 8a15eb7fd..baf93ba8d 100644 --- a/src/encodings.c +++ b/src/encodings.c @@ -497,6 +497,123 @@ void encodings_init(void) } +static gint encoding_combo_store_sort_func(GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer data) +{ + gboolean a_has_child = gtk_tree_model_iter_has_child(model, a); + gboolean b_has_child = gtk_tree_model_iter_has_child(model, b); + gchar *a_string; + gchar *b_string; + gint cmp_res; + + if (a_has_child != b_has_child) + return a_has_child ? -1 : 1; + + gtk_tree_model_get(model, a, 1, &a_string, -1); + gtk_tree_model_get(model, b, 1, &b_string, -1); + cmp_res = strcmp(a_string, b_string); + g_free(a_string); + g_free(b_string); + return cmp_res; +} + + +GtkTreeStore *encodings_encoding_store_new(gboolean has_detect) +{ + GtkTreeStore *store; + GtkTreeIter iter_current, iter_westeuro, iter_easteuro, iter_eastasian, + iter_asian, iter_utf8, iter_middleeast; + GtkTreeIter *iter_parent; + gchar *encoding_string; + gint i; + + store = gtk_tree_store_new(2, G_TYPE_INT, G_TYPE_STRING); + + if (has_detect) + { + gtk_tree_store_append(store, &iter_current, NULL); + gtk_tree_store_set(store, &iter_current, 0, GEANY_ENCODINGS_MAX, 1, _("Detect from file"), -1); + } + + gtk_tree_store_append(store, &iter_westeuro, NULL); + gtk_tree_store_set(store, &iter_westeuro, 0, -1, 1, _("West European"), -1); + gtk_tree_store_append(store, &iter_easteuro, NULL); + gtk_tree_store_set(store, &iter_easteuro, 0, -1, 1, _("East European"), -1); + gtk_tree_store_append(store, &iter_eastasian, NULL); + gtk_tree_store_set(store, &iter_eastasian, 0, -1, 1, _("East Asian"), -1); + gtk_tree_store_append(store, &iter_asian, NULL); + gtk_tree_store_set(store, &iter_asian, 0, -1, 1, _("SE & SW Asian"), -1); + gtk_tree_store_append(store, &iter_middleeast, NULL); + gtk_tree_store_set(store, &iter_middleeast, 0, -1, 1, _("Middle Eastern"), -1); + gtk_tree_store_append(store, &iter_utf8, NULL); + gtk_tree_store_set(store, &iter_utf8, 0, -1, 1, _("Unicode"), -1); + + for (i = 0; i < GEANY_ENCODINGS_MAX; i++) + { + switch (encodings[i].group) + { + case WESTEUROPEAN: iter_parent = &iter_westeuro; break; + case EASTEUROPEAN: iter_parent = &iter_easteuro; break; + case EASTASIAN: iter_parent = &iter_eastasian; break; + case ASIAN: iter_parent = &iter_asian; break; + case MIDDLEEASTERN: iter_parent = &iter_middleeast; break; + case UNICODE: iter_parent = &iter_utf8; break; + case NONE: + default: iter_parent = NULL; + } + gtk_tree_store_append(store, &iter_current, iter_parent); + encoding_string = encodings_to_string(&encodings[i]); + gtk_tree_store_set(store, &iter_current, 0, i, 1, encoding_string, -1); + g_free(encoding_string); + } + + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), 1, GTK_SORT_ASCENDING); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), 1, encoding_combo_store_sort_func, NULL, NULL); + + return store; +} + + +gint encodings_encoding_store_get_encoding(GtkTreeStore *store, GtkTreeIter *iter) +{ + gint enc; + gtk_tree_model_get(GTK_TREE_MODEL(store), iter, 0, &enc, -1); + return enc; +} + + +gboolean encodings_encoding_store_get_iter(GtkTreeStore *store, GtkTreeIter *iter, gint enc) +{ + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), iter)) + { + do + { + if (encodings_encoding_store_get_encoding(store, iter) == enc) + return TRUE; + } + while (ui_tree_model_iter_any_next(GTK_TREE_MODEL(store), iter, TRUE)); + } + return FALSE; +} + + +void encodings_encoding_store_cell_data_func(GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + gboolean sensitive = !gtk_tree_model_iter_has_child(tree_model, iter); + gchar *text; + + gtk_tree_model_get(tree_model, iter, 1, &text, -1); + g_object_set(cell, "sensitive", sensitive, "text", text, NULL); + g_free(text); +} + + /** * Tries to convert @a buffer into UTF-8 encoding from the encoding specified with @a charset. * If @a fast is not set, additional checks to validate the converted string are performed. diff --git a/src/encodings.h b/src/encodings.h index ead4026c2..645d39e5c 100644 --- a/src/encodings.h +++ b/src/encodings.h @@ -80,6 +80,15 @@ void encodings_select_radio_item(const gchar *charset); void encodings_init(void); void encodings_finalize(void); +GtkTreeStore *encodings_encoding_store_new(gboolean has_detect); + +gint encodings_encoding_store_get_encoding(GtkTreeStore *store, GtkTreeIter *iter); + +gboolean encodings_encoding_store_get_iter(GtkTreeStore *store, GtkTreeIter *iter, gint enc); + +void encodings_encoding_store_cell_data_func(GtkCellLayout *cell_layout, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data); + gchar *encodings_convert_to_utf8(const gchar *buffer, gssize size, gchar **used_encoding); /* Converts a string from the given charset to UTF-8. diff --git a/src/prefs.c b/src/prefs.c index 6b7ad8a13..f24a49b8c 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -547,8 +547,7 @@ static void prefs_init_dialog(void) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), file_prefs.tab_order_beside); widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding"); - /* luckily the index of the combo box items match the index of the encodings array */ - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), file_prefs.default_new_encoding); + ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_new_encoding); widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), @@ -558,10 +557,10 @@ static void prefs_init_dialog(void) widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding"); if (file_prefs.default_open_encoding >= 0) { - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), file_prefs.default_open_encoding); + ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), file_prefs.default_open_encoding); } else - gtk_combo_box_set_active(GTK_COMBO_BOX(widget), GEANY_ENCODING_UTF_8); + ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(widget), GEANY_ENCODING_UTF_8); widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_eol"); if (file_prefs.default_eol_character >= 0 && file_prefs.default_eol_character < 3) @@ -1020,13 +1019,13 @@ on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data) file_prefs.tab_order_beside = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding"); - file_prefs.default_new_encoding = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + file_prefs.default_new_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget)); widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_open_encoding"); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding"); - file_prefs.default_open_encoding = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + file_prefs.default_open_encoding = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(widget)); } else file_prefs.default_open_encoding = -1; @@ -1663,22 +1662,34 @@ void prefs_show_dialog(void) { if (ui_widgets.prefs_dialog == NULL) { - GtkListStore *encoding_list, *eol_list; - GtkWidget *label, *widget; - guint i; - gchar *encoding_string; + GtkListStore *eol_list; + GtkWidget *label; ui_widgets.prefs_dialog = create_prefs_dialog(); gtk_widget_set_name(ui_widgets.prefs_dialog, "GeanyPrefsDialog"); gtk_window_set_transient_for(GTK_WINDOW(ui_widgets.prefs_dialog), GTK_WINDOW(main_widgets.window)); /* init the file encoding combo boxes */ - encoding_list = ui_builder_get_object("encoding_list"); - for (i = 0; i < GEANY_ENCODINGS_MAX; i++) { - encoding_string = encodings_to_string(&encodings[i]); - list_store_append_text(encoding_list, encoding_string); - g_free(encoding_string); + struct { + const gchar *combo, *renderer; + } names[] = { + { "combo_new_encoding", "combo_new_encoding_renderer" }, + { "combo_open_encoding", "combo_open_encoding_renderer" } + }; + guint i; + GtkTreeStore *encoding_list = encodings_encoding_store_new(FALSE); + + for (i = 0; i < G_N_ELEMENTS(names); i++) + { + GtkWidget *combo = ui_lookup_widget(ui_widgets.prefs_dialog, names[i].combo); + + gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo), + ui_builder_get_object(names[i].renderer), + encodings_encoding_store_cell_data_func, NULL, NULL); + gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(encoding_list)); + } + g_object_unref(encoding_list); } /* init the eol character combo box */ @@ -1687,12 +1698,6 @@ void prefs_show_dialog(void) list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_CR)); list_store_append_text(eol_list, utils_get_eol_name(SC_EOL_LF)); - /* wet combo box wrap width after having filled the encoding to workaround - * GTK bug https://bugzilla.gnome.org/show_bug.cgi?id=722388 */ - widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_new_encoding"); - gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(widget), 3); - widget = ui_lookup_widget(ui_widgets.prefs_dialog, "combo_open_encoding"); - gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(widget), 3); /* add manually GeanyWrapLabels because they can't be added with Glade */ /* page Tools */ diff --git a/src/search.c b/src/search.c index 6710f079b..e43faa2f4 100644 --- a/src/search.c +++ b/src/search.c @@ -853,8 +853,6 @@ static void create_fif_dialog(void) *check_recursive, *check_extra, *entry_extra, *check_regexp, *combo_files_mode; GtkWidget *dbox, *sbox, *lbox, *rbox, *hbox, *vbox, *ebox; GtkSizeGroup *size_group; - gchar *encoding_string; - guint i; fif_dlg.dialog = gtk_dialog_new_with_buttons( _("Find in Files"), GTK_WINDOW(main_widgets.window), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -931,14 +929,7 @@ static void create_fif_dialog(void) label2 = gtk_label_new_with_mnemonic(_("E_ncoding:")); gtk_misc_set_alignment(GTK_MISC(label2), 0, 0.5); - e_combo = gtk_combo_box_text_new(); - for (i = 0; i < GEANY_ENCODINGS_MAX; i++) - { - encoding_string = encodings_to_string(&encodings[i]); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(e_combo), encoding_string); - g_free(encoding_string); - } - gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(e_combo), 3); + e_combo = ui_create_encodings_combo_box(FALSE, GEANY_ENCODING_UTF_8); gtk_label_set_mnemonic_widget(GTK_LABEL(label2), e_combo); fif_dlg.encoding_combo = e_combo; @@ -1118,7 +1109,7 @@ void search_show_find_in_files_dialog_full(const gchar *text, const gchar *dir) /* set the encoding of the current file */ if (doc != NULL) enc_idx = encodings_get_idx_from_charset(doc->encoding); - gtk_combo_box_set_active(GTK_COMBO_BOX(fif_dlg.encoding_combo), enc_idx); + ui_encodings_combo_box_set_active_encoding(GTK_COMBO_BOX(fif_dlg.encoding_combo), enc_idx); /* put the focus to the directory entry if it is empty */ if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(entry)), "")) @@ -1600,8 +1591,8 @@ on_find_in_files_dialog_response(GtkDialog *dialog, gint response, GtkWidget *dir_combo = fif_dlg.dir_combo; const gchar *utf8_dir = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(dir_combo)))); - GeanyEncodingIndex enc_idx = gtk_combo_box_get_active( - GTK_COMBO_BOX(fif_dlg.encoding_combo)); + GeanyEncodingIndex enc_idx = + ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(fif_dlg.encoding_combo)); if (G_UNLIKELY(EMPTY(utf8_dir))) ui_set_statusbar(FALSE, _("Invalid directory for find in files.")); diff --git a/src/symbols.c b/src/symbols.c index f03626fd1..0d002e8da 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -568,45 +568,6 @@ static GdkPixbuf *get_tag_icon(const gchar *icon_name) } -/* finds the next iter at any level - * @param iter in/out, the current iter, will be changed to the next one - * @param down whether to try the child iter - * @return TRUE if there @p iter was set, or FALSE if there is no next iter */ -static gboolean next_iter(GtkTreeModel *model, GtkTreeIter *iter, gboolean down) -{ - GtkTreeIter guess; - GtkTreeIter copy = *iter; - - /* go down if the item has children */ - if (down && gtk_tree_model_iter_children(model, &guess, iter)) - *iter = guess; - /* or to the next item at the same level */ - else if (gtk_tree_model_iter_next(model, ©)) - *iter = copy; - /* or to the next item at a parent level */ - else if (gtk_tree_model_iter_parent(model, &guess, iter)) - { - copy = guess; - while(TRUE) - { - if (gtk_tree_model_iter_next(model, ©)) - { - *iter = copy; - return TRUE; - } - else if (gtk_tree_model_iter_parent(model, ©, &guess)) - guess = copy; - else - return FALSE; - } - } - else - return FALSE; - - return TRUE; -} - - static gboolean find_toplevel_iter(GtkTreeStore *store, GtkTreeIter *iter, const gchar *title) { GtkTreeModel *model = GTK_TREE_MODEL(store); @@ -1304,7 +1265,7 @@ static gboolean tree_store_remove_row(GtkTreeStore *store, GtkTreeIter *iter) if (! cont && has_parent) { *iter = parent; - cont = next_iter(GTK_TREE_MODEL(store), iter, FALSE); + cont = ui_tree_model_iter_any_next(GTK_TREE_MODEL(store), iter, FALSE); } return cont; @@ -1484,7 +1445,7 @@ static void update_tree_tags(GeanyDocument *doc, GList **tags) gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_TAG, &tag, -1); if (! tag) /* most probably a toplevel, skip it */ - cont = next_iter(model, &iter, TRUE); + cont = ui_tree_model_iter_any_next(model, &iter, TRUE); else { GList *found_item; @@ -1517,7 +1478,7 @@ static void update_tree_tags(GeanyDocument *doc, GList **tags) tags_table_remove(tags_table, found); *tags = g_list_delete_link(*tags, found_item); - cont = next_iter(model, &iter, TRUE); + cont = ui_tree_model_iter_any_next(model, &iter, TRUE); } tm_tag_unref(tag); diff --git a/src/ui_utils.c b/src/ui_utils.c index f1f31cdcc..32f310f38 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -2768,3 +2768,94 @@ const gchar *ui_lookup_stock_label(const gchar *stock_id) g_warning("No stock id '%s'!", stock_id); return NULL; } + + +/* finds the next iter at any level + * @param iter in/out, the current iter, will be changed to the next one + * @param down whether to try the child iter + * @return TRUE if there @p iter was set, or FALSE if there is no next iter */ +gboolean ui_tree_model_iter_any_next(GtkTreeModel *model, GtkTreeIter *iter, gboolean down) +{ + GtkTreeIter guess; + GtkTreeIter copy = *iter; + + /* go down if the item has children */ + if (down && gtk_tree_model_iter_children(model, &guess, iter)) + *iter = guess; + /* or to the next item at the same level */ + else if (gtk_tree_model_iter_next(model, ©)) + *iter = copy; + /* or to the next item at a parent level */ + else if (gtk_tree_model_iter_parent(model, &guess, iter)) + { + copy = guess; + while (TRUE) + { + if (gtk_tree_model_iter_next(model, ©)) + { + *iter = copy; + return TRUE; + } + else if (gtk_tree_model_iter_parent(model, ©, &guess)) + guess = copy; + else + return FALSE; + } + } + else + return FALSE; + + return TRUE; +} + + +GtkWidget *ui_create_encodings_combo_box(gboolean has_detect, gint default_enc) +{ + GtkCellRenderer *renderer; + GtkTreeIter iter; + GtkWidget *combo = gtk_combo_box_new(); + GtkTreeStore *store = encodings_encoding_store_new(has_detect); + + if (default_enc < 0 || default_enc >= GEANY_ENCODINGS_MAX) + default_enc = has_detect ? GEANY_ENCODINGS_MAX : GEANY_ENCODING_NONE; + + gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(store)); + if (encodings_encoding_store_get_iter(store, &iter, default_enc)) + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter); + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE); + gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(combo), renderer, + encodings_encoding_store_cell_data_func, NULL, NULL); + + return combo; +} + + +gint ui_encodings_combo_box_get_active_encoding(GtkComboBox *combo) +{ + GtkTreeIter iter; + gint enc = GEANY_ENCODING_NONE; + + /* there should always be an active iter anyway, but we check just in case */ + if (gtk_combo_box_get_active_iter(combo, &iter)) + { + GtkTreeModel *model = gtk_combo_box_get_model(combo); + enc = encodings_encoding_store_get_encoding(GTK_TREE_STORE(model), &iter); + } + + return enc; +} + + +gboolean ui_encodings_combo_box_set_active_encoding(GtkComboBox *combo, gint enc) +{ + GtkTreeIter iter; + GtkTreeModel *model = gtk_combo_box_get_model(combo); + + if (encodings_encoding_store_get_iter(GTK_TREE_STORE(model), &iter, enc)) + { + gtk_combo_box_set_active_iter(combo, &iter); + return TRUE; + } + return FALSE; +} diff --git a/src/ui_utils.h b/src/ui_utils.h index 9cee58621..aff049652 100644 --- a/src/ui_utils.h +++ b/src/ui_utils.h @@ -315,6 +315,7 @@ gboolean ui_tree_view_find_next(GtkTreeView *treeview, TVMatchCallback cb); gboolean ui_tree_view_find_previous(GtkTreeView *treeview, TVMatchCallback cb); +gboolean ui_tree_model_iter_any_next(GtkTreeModel *model, GtkTreeIter *iter, gboolean down); void ui_statusbar_showhide(gboolean state); @@ -338,6 +339,12 @@ GdkPixbuf *ui_get_mime_icon(const gchar *mime_type, GtkIconSize size); void ui_focus_current_document(void); +GtkWidget *ui_create_encodings_combo_box(gboolean has_detect, gint default_enc); + +gint ui_encodings_combo_box_get_active_encoding(GtkComboBox *combo); + +gboolean ui_encodings_combo_box_set_active_encoding(GtkComboBox *combo, gint enc); + G_END_DECLS #endif