diff options
Diffstat (limited to 'gedit/gedit-encodings-combo-box.c')
-rw-r--r-- | gedit/gedit-encodings-combo-box.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/gedit/gedit-encodings-combo-box.c b/gedit/gedit-encodings-combo-box.c new file mode 100644 index 0000000..af2088f --- /dev/null +++ b/gedit/gedit-encodings-combo-box.c @@ -0,0 +1,439 @@ +/* + * gedit-encodings-combo-box.c + * This file is part of gedit + * + * Copyright (C) 2003-2005 - Paolo Maggi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "gedit-encodings-combo-box.h" +#include <glib/gi18n.h> +#include "gedit-encoding-items.h" +#include "gedit-encodings-dialog.h" + +struct _GeditEncodingsComboBox +{ + GtkComboBox parent_instance; + + GtkListStore *store; + glong changed_id; + + guint activated_item; + + guint save_mode : 1; +}; + +enum +{ + COLUMN_NAME, + COLUMN_ENCODING, + COLUMN_CONFIGURE_ROW, /* TRUE for the "Add or Remove..." row. */ + N_COLUMNS +}; + +enum +{ + PROP_0, + PROP_SAVE_MODE, + LAST_PROP +}; + +static GParamSpec *properties[LAST_PROP]; + +G_DEFINE_TYPE (GeditEncodingsComboBox, gedit_encodings_combo_box, GTK_TYPE_COMBO_BOX) + +static void update_menu (GeditEncodingsComboBox *combo_box); + +static void +gedit_encodings_combo_box_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeditEncodingsComboBox *combo; + + combo = GEDIT_ENCODINGS_COMBO_BOX (object); + + switch (prop_id) + { + case PROP_SAVE_MODE: + combo->save_mode = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_encodings_combo_box_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GeditEncodingsComboBox *combo; + + combo = GEDIT_ENCODINGS_COMBO_BOX (object); + + switch (prop_id) + { + case PROP_SAVE_MODE: + g_value_set_boolean (value, combo->save_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gedit_encodings_combo_box_dispose (GObject *object) +{ + GeditEncodingsComboBox *combo = GEDIT_ENCODINGS_COMBO_BOX (object); + + g_clear_object (&combo->store); + + G_OBJECT_CLASS (gedit_encodings_combo_box_parent_class)->dispose (object); +} + +static void +gedit_encodings_combo_box_constructed (GObject *object) +{ + GeditEncodingsComboBox *combo = GEDIT_ENCODINGS_COMBO_BOX (object); + GtkCellRenderer *text_renderer; + + G_OBJECT_CLASS (gedit_encodings_combo_box_parent_class)->constructed (object); + + /* Setup up the cells */ + text_renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (combo), + text_renderer, TRUE); + + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), + text_renderer, + "text", + COLUMN_NAME, + NULL); + + update_menu (combo); +} + +static void +gedit_encodings_combo_box_class_init (GeditEncodingsComboBoxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = gedit_encodings_combo_box_set_property; + object_class->get_property = gedit_encodings_combo_box_get_property; + object_class->dispose = gedit_encodings_combo_box_dispose; + object_class->constructed = gedit_encodings_combo_box_constructed; + + /** + * GeditEncodingsComboBox:save-mode: + * + * Whether the combo box should be used for saving a content. If + * %FALSE, the combo box is used for loading a content (e.g. a file) + * and the row "Automatically Detected" is added. + */ + /* TODO It'd be clearer if "save-mode" is renamed as "mode" with an + * enum: loading, saving. Or something like that. + */ + properties[PROP_SAVE_MODE] = + g_param_spec_boolean ("save-mode", + "Save Mode", + "Save Mode", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, LAST_PROP, properties); +} + +static void +dialog_response_cb (GtkDialog *dialog, + gint response_id, + GeditEncodingsComboBox *menu) +{ + update_menu (menu); + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +configure_encodings (GeditEncodingsComboBox *menu) +{ + GtkWidget *dialog; + + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu)); + + if (!gtk_widget_is_toplevel (toplevel)) + { + toplevel = NULL; + } + + g_signal_handler_block (menu, menu->changed_id); + gtk_combo_box_set_active (GTK_COMBO_BOX (menu), + menu->activated_item); + g_signal_handler_unblock (menu, menu->changed_id); + + dialog = gedit_encodings_dialog_new (); + + if (toplevel != NULL) + { + GtkWindowGroup *wg; + + gtk_window_set_transient_for (GTK_WINDOW (dialog), + GTK_WINDOW (toplevel)); + + if (gtk_window_has_group (GTK_WINDOW (toplevel))) + { + wg = gtk_window_get_group (GTK_WINDOW (toplevel)); + } + else + { + wg = gtk_window_group_new (); + gtk_window_group_add_window (wg, GTK_WINDOW (toplevel)); + } + + gtk_window_group_add_window (wg, GTK_WINDOW (dialog)); + } + + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + g_signal_connect_after (dialog, + "response", + G_CALLBACK (dialog_response_cb), + menu); + + gtk_widget_show (dialog); +} + +static void +changed_cb (GeditEncodingsComboBox *menu, + GtkTreeModel *model) +{ + GtkTreeIter iter; + gboolean configure = FALSE; + + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (menu), &iter)) + { + gtk_tree_model_get (model, &iter, + COLUMN_CONFIGURE_ROW, &configure, + -1); + } + + if (configure) + { + configure_encodings (menu); + } + else + { + menu->activated_item = gtk_combo_box_get_active (GTK_COMBO_BOX (menu)); + } +} + +static gboolean +separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + gchar *str; + gboolean ret; + + gtk_tree_model_get (model, iter, COLUMN_NAME, &str, -1); + ret = (str == NULL || str[0] == '\0'); + g_free (str); + + return ret; +} + +static void +add_separator (GtkListStore *store) +{ + GtkTreeIter iter; + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_NAME, "", + COLUMN_ENCODING, NULL, + COLUMN_CONFIGURE_ROW, FALSE, + -1); +} + +static void +update_menu (GeditEncodingsComboBox *menu) +{ + GtkListStore *store; + GtkTreeIter iter; + GSList *encodings; + + store = menu->store; + + /* Unset the previous model */ + g_signal_handler_block (menu, menu->changed_id); + gtk_list_store_clear (store); + gtk_combo_box_set_model (GTK_COMBO_BOX (menu), NULL); + + if (!menu->save_mode) + { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_NAME, _("Automatically Detected"), + COLUMN_ENCODING, NULL, + COLUMN_CONFIGURE_ROW, FALSE, + -1); + + add_separator (store); + } + + encodings = gedit_encoding_items_get (); + + while (encodings) + { + GeditEncodingItem *item = encodings->data; + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_NAME, gedit_encoding_item_get_name (item), + COLUMN_ENCODING, gedit_encoding_item_get_encoding (item), + COLUMN_CONFIGURE_ROW, FALSE, + -1); + + gedit_encoding_item_free (item); + encodings = g_slist_delete_link (encodings, encodings); + } + + add_separator (store); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_NAME, _("Add or Remove…"), + COLUMN_ENCODING, NULL, + COLUMN_CONFIGURE_ROW, TRUE, + -1); + + /* set the model back */ + gtk_combo_box_set_model (GTK_COMBO_BOX (menu), + GTK_TREE_MODEL (menu->store)); + gtk_combo_box_set_active (GTK_COMBO_BOX (menu), 0); + + g_signal_handler_unblock (menu, menu->changed_id); +} + +static void +gedit_encodings_combo_box_init (GeditEncodingsComboBox *menu) +{ + menu->store = gtk_list_store_new (N_COLUMNS, + G_TYPE_STRING, + G_TYPE_POINTER, + G_TYPE_BOOLEAN); + + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (menu), + separator_func, NULL, + NULL); + + menu->changed_id = g_signal_connect (menu, + "changed", + G_CALLBACK (changed_cb), + menu->store); +} + +/** + * gedit_encodings_combo_box_new: + * @save_mode: whether the combo box is used for saving a content. + * + * Creates a new encodings combo box object. If @save_mode is %FALSE, it means + * that the combo box is used for loading a content (e.g. a file), so the row + * "Automatically Detected" is added. For saving a content, the encoding must be + * provided. + * + * Returns: a new #GeditEncodingsComboBox object. + */ +GtkWidget * +gedit_encodings_combo_box_new (gboolean save_mode) +{ + return g_object_new (GEDIT_TYPE_ENCODINGS_COMBO_BOX, + "save_mode", save_mode, + NULL); +} + +/** + * gedit_encodings_combo_box_get_selected_encoding: + * @menu: a #GeditEncodingsComboBox. + * + * Returns: the selected #GtkSourceEncoding, or %NULL if the encoding should be + * auto-detected (only for loading mode, not for saving). + */ +const GtkSourceEncoding * +gedit_encodings_combo_box_get_selected_encoding (GeditEncodingsComboBox *menu) +{ + GtkTreeIter iter; + + g_return_val_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (menu), NULL); + + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (menu), &iter)) + { + const GtkSourceEncoding *ret; + GtkTreeModel *model; + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (menu)); + + gtk_tree_model_get (model, &iter, + COLUMN_ENCODING, &ret, + -1); + + return ret; + } + + return NULL; +} + +/** + * gedit_encodings_combo_box_set_selected_encoding: + * @menu: a #GeditEncodingsComboBox. + * @encoding: the #GtkSourceEncoding. + * + * Sets the selected encoding. + */ +void +gedit_encodings_combo_box_set_selected_encoding (GeditEncodingsComboBox *menu, + const GtkSourceEncoding *encoding) +{ + GtkTreeIter iter; + GtkTreeModel *model; + gboolean b; + + g_return_if_fail (GEDIT_IS_ENCODINGS_COMBO_BOX (menu)); + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (menu)); + b = gtk_tree_model_get_iter_first (model, &iter); + + while (b) + { + const GtkSourceEncoding *enc; + + gtk_tree_model_get (model, &iter, + COLUMN_ENCODING, &enc, + -1); + + if (enc == encoding) + { + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (menu), &iter); + return; + } + + b = gtk_tree_model_iter_next (model, &iter); + } +} + +/* ex:set ts=8 noet: */ |