/* * moousertools-prefs.c * * Copyright (C) 2004-2008 by Yevgen Muntyan * * This file is part of medit. medit is free software; you can * redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public * License along with medit. If not, see . */ #include "mooedit/moousertools-prefs.h" #include "mooedit/moousertools.h" #include "mooedit/moocommand.h" #include "mooedit/moocommanddisplay.h" #include "mooutils/mooprefspage.h" #include "mooutils/mooi18n.h" #include "mooutils/mooutils-treeview.h" #include "mooutils/moohelp.h" #include "glade/moousertools-gxml.h" #include "help-sections.h" #include enum { COLUMN_INFO, N_COLUMNS }; static MooUserToolType page_get_type (MooPrefsPage *page) { return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "moo-user-tool-type")); } static void page_set_type (MooPrefsPage *page, MooUserToolType type) { g_object_set_data (G_OBJECT (page), "moo-user-tool-type", GINT_TO_POINTER (type)); } static gboolean get_changed (MooPrefsPage *page) { return g_object_get_data (G_OBJECT (page), "moo-changed") != NULL; } static void set_changed (MooPrefsPage *page, gboolean changed) { g_object_set_data (G_OBJECT (page), "moo-changed", GINT_TO_POINTER (changed)); } static MooCommandDisplay * get_helper (MooPrefsPage *page) { return g_object_get_data (G_OBJECT (page), "moo-tree-helper"); } static void populate_store (GtkListStore *store, MooUserToolType type) { GtkTreeIter iter; GSList *list; list = _moo_edit_parse_user_tools (type, FALSE); while (list) { MooUserToolInfo *info = list->data; if (info->os_type == MOO_USER_TOOL_THIS_OS) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_INFO, info, -1); } _moo_user_tool_info_unref (info); list = g_slist_delete_link (list, list); } } static gboolean new_row (MooPrefsPage *page, GtkTreeModel *model, GtkTreePath *path) { GtkTreeIter iter; MooUserToolInfo *info; GtkTreeViewColumn *column; CommandXml *gxml; gxml = g_object_get_data (G_OBJECT (page), "moo-user-tools-prefs-xml"); info = _moo_user_tool_info_new (); info->cmd_factory = moo_command_factory_lookup ("lua"); info->cmd_data = info->cmd_factory ? moo_command_data_new (info->cmd_factory->n_keys) : NULL; info->name = g_strdup (_("New Command")); info->options = g_strdup ("need-doc"); info->enabled = TRUE; set_changed (page, TRUE); gtk_list_store_insert (GTK_LIST_STORE (model), &iter, gtk_tree_path_get_indices(path)[0]); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_INFO, info, -1); column = gtk_tree_view_get_column (gxml->treeview, 0); gtk_tree_view_set_cursor (gxml->treeview, path, column, TRUE); _moo_user_tool_info_unref (info); return TRUE; } static gboolean delete_row (MooPrefsPage *page) { set_changed (page, TRUE); return FALSE; } static gboolean move_row (MooPrefsPage *page) { set_changed (page, TRUE); return FALSE; } static void update_widgets (MooPrefsPage *page, GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter) { MooCommandDisplay *helper; CommandXml *gxml; gxml = g_object_get_data (G_OBJECT (page), "moo-user-tools-prefs-xml"); helper = get_helper (page); if (path) { MooUserToolInfo *info; gtk_tree_model_get (model, iter, COLUMN_INFO, &info, -1); g_return_if_fail (info != NULL); _moo_command_display_set (helper, info->cmd_factory, info->cmd_data); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gxml->enabled), info->enabled); gtk_entry_set_text (gxml->filter, info->filter ? info->filter : ""); gtk_entry_set_text (gxml->options, info->options ? info->options : ""); _moo_user_tool_info_unref (info); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gxml->enabled), FALSE); gtk_entry_set_text (gxml->filter, ""); gtk_entry_set_text (gxml->options, ""); _moo_command_display_set (helper, NULL, NULL); } gtk_widget_set_sensitive (GTK_WIDGET (gxml->tool_vbox), path != NULL); } static gboolean get_text (GtkEntry *entry, char **dest) { const char *text = gtk_entry_get_text (entry); if (strcmp (*dest ? *dest : "", text) != 0) { g_free (*dest); *dest = text[0] ? g_strdup (text) : NULL; return TRUE; } else { return FALSE; } } static void update_model (MooPrefsPage *page, GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path, GtkTreeIter *iter) { MooCommandDisplay *helper; MooCommandFactory *factory; MooCommandData *data; MooUserToolInfo *info; gboolean changed = FALSE; CommandXml *gxml; gxml = g_object_get_data (G_OBJECT (page), "moo-user-tools-prefs-xml"); helper = get_helper (page); gtk_tree_model_get (model, iter, COLUMN_INFO, &info, -1); g_return_if_fail (info != NULL); if (_moo_command_display_get (helper, &factory, &data)) { moo_command_data_unref (info->cmd_data); info->cmd_data = moo_command_data_ref (data); info->cmd_factory = factory; gtk_list_store_set (GTK_LIST_STORE (model), iter, COLUMN_INFO, info, -1); changed = TRUE; } if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gxml->enabled)) != info->enabled) { info->enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gxml->enabled)); changed = TRUE; } changed = get_text (gxml->filter, &info->filter) || changed; changed = get_text (gxml->options, &info->options) || changed; if (changed) { info->builtin = FALSE; set_changed (page, TRUE); } _moo_user_tool_info_unref (info); } static void name_data_func (G_GNUC_UNUSED GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter) { MooUserToolInfo *info = NULL; gtk_tree_model_get (model, iter, COLUMN_INFO, &info, -1); g_return_if_fail (info != NULL); g_object_set (cell, "text", info->name, NULL); _moo_user_tool_info_unref (info); } static void name_cell_edited (MooPrefsPage *page, char *path_string, char *text) { GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; MooUserToolInfo *info = NULL; CommandXml *gxml; gxml = g_object_get_data (G_OBJECT (page), "moo-user-tools-prefs-xml"); path = gtk_tree_path_new_from_string (path_string); model = gtk_tree_view_get_model (gxml->treeview); if (gtk_tree_model_get_iter (model, &iter, path)) { gtk_tree_model_get (model, &iter, COLUMN_INFO, &info, -1); g_return_if_fail (info != NULL); if (strcmp (info->name ? info->name : "", text) != 0) { set_changed (page, TRUE); g_free (info->name); info->name = g_strdup (text); } } gtk_tree_path_free (path); } static void command_page_init (MooPrefsPage *page, MooUserToolType type) { GtkListStore *store; GtkTreeViewColumn *column; GtkCellRenderer *cell; MooCommandDisplay *helper; CommandXml *gxml; gxml = g_object_get_data (G_OBJECT (page), "moo-user-tools-prefs-xml"); page_set_type (page, type); store = gtk_list_store_new (N_COLUMNS, MOO_TYPE_USER_TOOL_INFO); cell = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new (); gtk_tree_view_column_pack_start (column, cell, TRUE); gtk_tree_view_column_set_cell_data_func (column, cell, (GtkTreeCellDataFunc) name_data_func, NULL, NULL); gtk_tree_view_append_column (gxml->treeview, column); g_object_set (cell, "editable", TRUE, NULL); g_signal_connect_swapped (cell, "edited", G_CALLBACK (name_cell_edited), page); populate_store (store, type); helper = _moo_command_display_new (gxml->type_combo, gxml->type_notebook, GTK_WIDGET (gxml->treeview), GTK_WIDGET (gxml->new_), GTK_WIDGET (gxml->delete_), GTK_WIDGET (gxml->up), GTK_WIDGET (gxml->down)); g_object_set_data_full (G_OBJECT (page), "moo-tree-helper", helper, g_object_unref); g_signal_connect_swapped (page, "destroy", G_CALLBACK (gtk_object_destroy), helper); g_signal_connect_swapped (helper, "new-row", G_CALLBACK (new_row), page); g_signal_connect_swapped (helper, "delete-row", G_CALLBACK (delete_row), page); g_signal_connect_swapped (helper, "move-row", G_CALLBACK (move_row), page); g_signal_connect_swapped (helper, "update-widgets", G_CALLBACK (update_widgets), page); g_signal_connect_swapped (helper, "update-model", G_CALLBACK (update_model), page); gtk_tree_view_set_model (gxml->treeview, GTK_TREE_MODEL (store)); _moo_tree_view_select_first (gxml->treeview); _moo_tree_helper_update_widgets (MOO_TREE_HELPER (helper)); g_object_unref (store); } static void command_page_apply (MooPrefsPage *page) { MooTreeHelper *helper; GtkTreeModel *model; GtkTreeIter iter; GSList *list = NULL; CommandXml *gxml; gxml = g_object_get_data (G_OBJECT (page), "moo-user-tools-prefs-xml"); helper = g_object_get_data (G_OBJECT (page), "moo-tree-helper"); _moo_tree_helper_update_model (helper, NULL, NULL); if (!get_changed (page)) return; model = gtk_tree_view_get_model (gxml->treeview); if (gtk_tree_model_get_iter_first (model, &iter)) { do { MooUserToolInfo *info; gtk_tree_model_get (model, &iter, COLUMN_INFO, &info, -1); list = g_slist_prepend (list, info); } while (gtk_tree_model_iter_next (model, &iter)); } list = g_slist_reverse (list); _moo_edit_save_user_tools (page_get_type (page), list); _moo_edit_load_user_tools_type (page_get_type (page)); g_slist_foreach (list, (GFunc) _moo_user_tool_info_unref, NULL); g_slist_free (list); set_changed (page, FALSE); } static void main_page_init (PrefsPageXml *gxml) { command_page_init (gxml->page_menu, MOO_USER_TOOL_MENU); command_page_init (gxml->page_context, MOO_USER_TOOL_CONTEXT); } static void main_page_apply (PrefsPageXml *gxml) { command_page_apply (gxml->page_menu); command_page_apply (gxml->page_context); } GtkWidget * moo_user_tools_prefs_page_new (void) { GtkWidget *page; PrefsPageXml *gxml; CommandXml *cxml; page = moo_prefs_page_new (_("Tools"), GTK_STOCK_EXECUTE); gxml = prefs_page_xml_new_with_root (page); g_signal_connect_swapped (page, "init", G_CALLBACK (main_page_init), gxml); g_signal_connect_swapped (page, "apply", G_CALLBACK (main_page_apply), gxml); moo_help_set_id (page, HELP_SECTION_PREFS_USER_TOOLS); cxml = command_xml_new_with_root (GTK_WIDGET (gxml->page_menu)); g_object_set_data (G_OBJECT (gxml->page_menu), "moo-user-tools-prefs-xml", cxml); cxml = command_xml_new_with_root (GTK_WIDGET (gxml->page_context)); g_object_set_data (G_OBJECT (gxml->page_context), "moo-user-tools-prefs-xml", cxml); return page; }