medit/moo/mooedit/mooeditprefspage.c

1149 lines
34 KiB
C

/*
* mooeditprefspage.c
*
* Copyright (C) 2004-2010 by Yevgen Muntyan <emuntyan@sourceforge.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#define MOOEDIT_COMPILATION
#include "mooedit/mooedit-impl.h"
#include "mooedit/mooeditor-impl.h"
#include "mooedit/mooeditprefs.h"
#include "mooedit/moolangmgr.h"
#include "mooedit/mooeditfiltersettings.h"
#include "mooutils/mooprefsdialog.h"
#include "mooutils/moostock.h"
#include "mooutils/mooglade.h"
#include "mooutils/moofontsel.h"
#include "mooutils/mooutils-treeview.h"
#include "mooutils/mooutils-misc.h"
#include "mooutils/mooencodings.h"
#include "mooutils/mooi18n.h"
#include "mooutils/moohelp.h"
#include "mooeditprefs-file-gxml.h"
#include "mooeditprefs-filters-gxml.h"
#include "mooeditprefs-general-gxml.h"
#include "mooeditprefs-langs-gxml.h"
#include "mooeditprefs-view-gxml.h"
#include "help-sections.h"
#include <string.h>
typedef struct PrefsPage PrefsPage;
static void prefs_page_apply_lang_prefs (MooPrefsPage *page);
static void apply_filter_settings (PrefsFiltersXml *gxml);
static void scheme_combo_init (GtkComboBox *combo);
static void scheme_combo_data_func (GtkCellLayout *layout,
GtkCellRenderer *cell,
GtkTreeModel *model,
GtkTreeIter *iter);
static void scheme_combo_set_scheme (GtkComboBox *combo,
MooTextStyleScheme *scheme);
static void default_lang_combo_init (GtkComboBox *combo,
MooPrefsPage *page);
static void default_lang_combo_set_lang (GtkComboBox *combo,
const char *id);
static void lang_combo_init (GtkComboBox *combo,
MooPrefsPage *page,
PrefsLangsXml *gxml);
static void filter_treeview_init (PrefsFiltersXml *gxml);
static GtkTreeModel *create_lang_model (void);
static void save_encoding_combo_init (PrefsFileXml *gxml);
static void save_encoding_combo_apply (PrefsFileXml *gxml);
static GtkTreeModel *page_get_lang_model (MooPrefsPage *page);
static MooTextStyleScheme *page_get_scheme (PrefsGeneralXml *gxml);
static char *page_get_default_lang (PrefsLangsXml *gxml);
static void
add_page (GtkWidget *page,
GtkWidget *notebook,
GtkWidget *subpage)
{
GtkWidget *label = gtk_label_new (MOO_PREFS_PAGE (subpage)->label);
gtk_widget_show (subpage);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), subpage, label);
moo_prefs_page_add_page (MOO_PREFS_PAGE (page), MOO_PREFS_PAGE (subpage));
}
GtkWidget *
moo_edit_prefs_page_new (MooEditor *editor)
{
GtkWidget *page, *notebook;
page = moo_prefs_page_new ("Editor", GTK_STOCK_EDIT);
notebook = gtk_notebook_new ();
gtk_container_add (GTK_CONTAINER (page), notebook);
gtk_widget_show_all (page);
add_page (page, notebook, moo_edit_prefs_page_new_1 (editor));
add_page (page, notebook, moo_edit_prefs_page_new_2 (editor));
add_page (page, notebook, moo_edit_prefs_page_new_3 (editor));
add_page (page, notebook, moo_edit_prefs_page_new_4 (editor));
return page;
}
static GtkWidget *
prefs_page_new (MooEditor *editor,
const char *label,
const char *stock_id,
MooPrefsPageInitUi init_ui,
MooPrefsPageInit init,
MooPrefsPageApply apply)
{
GtkWidget *prefs_page;
g_return_val_if_fail (MOO_IS_EDITOR (editor), NULL);
_moo_edit_init_config ();
prefs_page = moo_prefs_page_new (label, stock_id);
moo_prefs_page_set_callbacks (MOO_PREFS_PAGE (prefs_page),
init_ui, init, apply);
g_signal_connect_swapped (prefs_page, "apply",
G_CALLBACK (_moo_editor_queue_apply_prefs),
editor);
return prefs_page;
}
#define BIND_SETTING(wid,setting) \
moo_prefs_page_bind_setting (page, GTK_WIDGET (gxml->wid), \
moo_edit_setting (setting))
#define BIND_SENSITIVE(btn, wid) \
moo_bind_sensitive (GTK_WIDGET (gxml->btn), GTK_WIDGET (gxml->wid), FALSE)
static void
page_general_init_ui (MooPrefsPage *page)
{
PrefsGeneralXml *gxml;
gxml = prefs_general_xml_new_with_root (GTK_WIDGET (page));
g_object_set_data (G_OBJECT (page), "moo-edit-prefs-page-xml", gxml);
BIND_SETTING (smarthome, MOO_EDIT_PREFS_SMART_HOME_END);
BIND_SETTING (enable_auto_indent, MOO_EDIT_PREFS_AUTO_INDENT);
BIND_SETTING (usespaces, MOO_EDIT_PREFS_SPACES_NO_TABS);
BIND_SETTING (backspace_indents, MOO_EDIT_PREFS_BACKSPACE_INDENTS);
BIND_SETTING (tab_indents, MOO_EDIT_PREFS_TAB_INDENTS);
BIND_SETTING (tab_width, MOO_EDIT_PREFS_TAB_WIDTH);
BIND_SETTING (indent_width, MOO_EDIT_PREFS_INDENT_WIDTH);
BIND_SETTING (fontbutton, MOO_EDIT_PREFS_FONT);
}
static void
tab_width_changed (GtkSpinButton *tab_width,
GtkSpinButton *indent_width)
{
gtk_spin_button_set_value (indent_width,
gtk_spin_button_get_value_as_int (tab_width));
}
static void
page_general_init (MooPrefsPage *page)
{
PrefsGeneralXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
g_signal_connect (gxml->tab_width, "value-changed",
G_CALLBACK (tab_width_changed),
gxml->indent_width);
{
MooTextStyleScheme *scheme;
g_object_set (gxml->fontbutton, "monospace", TRUE, NULL);
scheme = moo_lang_mgr_get_active_scheme (moo_lang_mgr_default ());
g_return_if_fail (scheme != NULL);
scheme_combo_init (gxml->color_scheme_combo);
scheme_combo_set_scheme (gxml->color_scheme_combo, scheme);
}
}
static void
page_general_apply (MooPrefsPage *page)
{
PrefsGeneralXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
MooTextStyleScheme *scheme = page_get_scheme (gxml);
if (scheme)
{
moo_prefs_set_string (moo_edit_setting (MOO_EDIT_PREFS_COLOR_SCHEME),
moo_text_style_scheme_get_id (scheme));
g_object_unref (scheme);
}
}
GtkWidget *
moo_edit_prefs_page_new_1 (MooEditor *editor)
{
return prefs_page_new (editor,
/* Translators: this one is temporary, don't translate */
Q_("PreferencesPage|General"),
GTK_STOCK_EDIT,
page_general_init_ui,
page_general_init,
page_general_apply);
}
static void
page_filters_init_ui (MooPrefsPage *page)
{
PrefsFiltersXml *gxml;
gxml = prefs_filters_xml_new_with_root (GTK_WIDGET (page));
g_object_set_data (G_OBJECT (page), "moo-edit-prefs-page-xml", gxml);
}
static void
page_filters_init (MooPrefsPage *page)
{
PrefsFiltersXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
filter_treeview_init (gxml);
}
static void
page_filters_apply (MooPrefsPage *page)
{
PrefsFiltersXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
apply_filter_settings (gxml);
}
GtkWidget *
moo_edit_prefs_page_new_5 (MooEditor *editor)
{
return prefs_page_new (editor,
/* Translators: this one is temporary, don't translate */
Q_("PreferencesPage|Filters"),
GTK_STOCK_EDIT,
page_filters_init_ui,
page_filters_init,
page_filters_apply);
}
static void
page_view_init_ui (MooPrefsPage *page)
{
PrefsViewXml *gxml;
gxml = prefs_view_xml_new_with_root (GTK_WIDGET (page));
g_object_set_data (G_OBJECT (page), "moo-edit-prefs-page-xml", gxml);
BIND_SENSITIVE (enable_wrapping, dont_split_words);
BIND_SENSITIVE (draw_rigth_margin, right_margin_box);
BIND_SETTING (enable_wrapping, MOO_EDIT_PREFS_WRAP_ENABLE);
BIND_SETTING (dont_split_words, MOO_EDIT_PREFS_WRAP_WORDS);
BIND_SETTING (check_enable_highlighting, MOO_EDIT_PREFS_ENABLE_HIGHLIGHTING);
BIND_SETTING (check_highlight_matching_brackets, MOO_EDIT_PREFS_HIGHLIGHT_MATCHING);
BIND_SETTING (check_highlight_mismatching_brackets, MOO_EDIT_PREFS_HIGHLIGHT_MISMATCHING);
BIND_SETTING (check_highlight_current_line, MOO_EDIT_PREFS_HIGHLIGHT_CURRENT_LINE);
BIND_SETTING (show_line_numbers, MOO_EDIT_PREFS_SHOW_LINE_NUMBERS);
BIND_SETTING (check_show_tabs, MOO_EDIT_PREFS_SHOW_TABS);
BIND_SETTING (check_show_spaces, MOO_EDIT_PREFS_SHOW_SPACES);
BIND_SETTING (check_show_trailing_spaces, MOO_EDIT_PREFS_SHOW_TRAILING_SPACES);
BIND_SETTING (draw_rigth_margin, MOO_EDIT_PREFS_DRAW_RIGHT_MARGIN);
BIND_SETTING (spin_right_margin_offset, MOO_EDIT_PREFS_RIGHT_MARGIN_OFFSET);
}
static void
page_view_init (MooPrefsPage *page)
{
PrefsViewXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
MOO_UNUSED (gxml);
}
static void
page_view_apply (MooPrefsPage *page)
{
PrefsViewXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
MOO_UNUSED (gxml);
}
GtkWidget *
moo_edit_prefs_page_new_2 (MooEditor *editor)
{
return prefs_page_new (editor,
/* Translators: this one is temporary, don't translate */
Q_("PreferencesPage|View"),
GTK_STOCK_EDIT,
page_view_init_ui,
page_view_init,
page_view_apply);
}
static void
page_file_init_ui (MooPrefsPage *page)
{
PrefsFileXml *gxml;
gxml = prefs_file_xml_new_with_root (GTK_WIDGET (page));
g_object_set_data (G_OBJECT (page), "moo-edit-prefs-page-xml", gxml);
BIND_SETTING (entry_encodings, MOO_EDIT_PREFS_ENCODINGS);
BIND_SETTING (check_strip, MOO_EDIT_PREFS_STRIP);
BIND_SETTING (check_add_newline, MOO_EDIT_PREFS_ADD_NEWLINE);
BIND_SETTING (check_make_backups, MOO_EDIT_PREFS_MAKE_BACKUPS);
BIND_SETTING (check_save_session, MOO_EDIT_PREFS_SAVE_SESSION);
BIND_SETTING (check_open_dialog_follows_doc, MOO_EDIT_PREFS_DIALOGS_OPEN_FOLLOWS_DOC);
}
static void
page_file_init (MooPrefsPage *page)
{
PrefsFileXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
save_encoding_combo_init (gxml);
}
static void
page_file_apply (MooPrefsPage *page)
{
PrefsFileXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
save_encoding_combo_apply (gxml);
}
GtkWidget *
moo_edit_prefs_page_new_3 (MooEditor *editor)
{
return prefs_page_new (editor,
/* Translators: this one is temporary, don't translate */
Q_("PreferencesPage|File"),
GTK_STOCK_EDIT,
page_file_init_ui,
page_file_init,
page_file_apply);
}
static void
page_langs_init_ui (MooPrefsPage *page)
{
PrefsLangsXml *gxml;
gxml = prefs_langs_xml_new_with_root (GTK_WIDGET (page));
g_object_set_data (G_OBJECT (page), "moo-edit-prefs-page-xml", gxml);
}
static void
page_langs_init (MooPrefsPage *page)
{
PrefsLangsXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
MooTreeHelper *helper;
const char *lang;
moo_help_set_id (GTK_WIDGET (page), HELP_SECTION_PREFS_LANGS_AND_FILTERS);
lang_combo_init (gxml->lang_combo, page, gxml);
helper = g_object_get_data (G_OBJECT (page), "moo-tree-helper");
_moo_tree_helper_update_widgets (helper);
default_lang_combo_init (gxml->default_lang_combo, page);
lang = moo_prefs_get_string (moo_edit_setting (MOO_EDIT_PREFS_DEFAULT_LANG));
default_lang_combo_set_lang (gxml->default_lang_combo, lang);
}
static void
page_langs_apply (MooPrefsPage *page)
{
char *lang;
PrefsLangsXml *gxml = g_object_get_data (G_OBJECT (page), "moo-edit-prefs-page-xml");
prefs_page_apply_lang_prefs (page);
lang = page_get_default_lang (gxml);
moo_prefs_set_string (moo_edit_setting (MOO_EDIT_PREFS_DEFAULT_LANG), lang);
g_free (lang);
}
GtkWidget *
moo_edit_prefs_page_new_4 (MooEditor *editor)
{
return prefs_page_new (editor,
/* Translators: this one is temporary, don't translate */
Q_("PreferencesPage|Langs"),
GTK_STOCK_EDIT,
page_langs_init_ui,
page_langs_init,
page_langs_apply);
}
static void
scheme_combo_init (GtkComboBox *combo)
{
GtkListStore *store;
MooLangMgr *mgr;
GSList *list, *l;
GtkCellRenderer *cell;
mgr = moo_lang_mgr_default ();
list = moo_lang_mgr_list_schemes (mgr);
g_return_if_fail (list != NULL);
store = gtk_list_store_new (1, MOO_TYPE_TEXT_STYLE_SCHEME);
for (l = list; l != NULL; l = l->next)
{
GtkTreeIter iter;
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, l->data, -1);
}
gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
cell = gtk_cell_renderer_text_new ();
gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo));
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
(GtkCellLayoutDataFunc) scheme_combo_data_func,
NULL, NULL);
g_object_unref (store);
g_slist_foreach (list, (GFunc) g_object_unref, NULL);
g_slist_free (list);
}
static void
scheme_combo_data_func (G_GNUC_UNUSED GtkCellLayout *layout,
GtkCellRenderer *cell,
GtkTreeModel *model,
GtkTreeIter *iter)
{
MooTextStyleScheme *scheme = NULL;
gtk_tree_model_get (model, iter, 0, &scheme, -1);
g_return_if_fail (scheme != NULL);
g_object_set (cell, "text", moo_text_style_scheme_get_name (scheme), NULL);
g_object_unref (scheme);
}
static GtkTreeModel *
page_get_lang_model (MooPrefsPage *page)
{
GtkTreeModel *model;
model = g_object_get_data (G_OBJECT (page), "moo-lang-model");
if (!model)
{
model = create_lang_model ();
g_object_set_data_full (G_OBJECT (page), "moo-lang-model",
model, g_object_unref);
}
return model;
}
static void
scheme_combo_set_scheme (GtkComboBox *combo,
MooTextStyleScheme *scheme)
{
GtkTreeModel *model = gtk_combo_box_get_model (combo);
gboolean found = FALSE;
GtkTreeIter iter;
gtk_tree_model_get_iter_first (model, &iter);
do {
MooTextStyleScheme *s;
gtk_tree_model_get (model, &iter, 0, &s, -1);
g_object_unref (s);
if (scheme == s)
{
found = TRUE;
break;
}
}
while (gtk_tree_model_iter_next (model, &iter));
g_return_if_fail (found);
gtk_combo_box_set_active_iter (combo, &iter);
}
static MooTextStyleScheme *
page_get_scheme (PrefsGeneralXml *gxml)
{
GtkTreeModel *model;
GtkTreeIter iter;
MooTextStyleScheme *scheme = NULL;
if (!gtk_combo_box_get_active_iter (gxml->color_scheme_combo, &iter))
return NULL;
model = gtk_combo_box_get_model (gxml->color_scheme_combo);
gtk_tree_model_get (model, &iter, 0, &scheme, -1);
return scheme;
}
/*********************************************************************/
/* Language combo
*/
static void
fix_style (G_GNUC_UNUSED GtkWidget *combo)
{
#ifdef __WIN32__
static gboolean been_here = FALSE;
gtk_widget_set_name (combo, "moo-lang-combo");
if (!been_here)
{
been_here = TRUE;
gtk_rc_parse_string ("style \"moo-lang-combo\"\n"
"{\n"
" GtkComboBox::appears-as-list = 0\n"
"}\n"
"widget \"*.moo-lang-combo\" style \"moo-lang-combo\"\n");
}
#endif
}
enum {
COLUMN_ID,
COLUMN_NAME,
COLUMN_LANG,
COLUMN_EXTENSIONS,
COLUMN_MIMETYPES,
COLUMN_CONFIG
};
static char *
list_to_string (GSList *list,
gboolean free_list)
{
GSList *l;
GString *string = g_string_new (NULL);
for (l = list; l != NULL; l = l->next)
{
g_string_append (string, l->data);
if (l->next)
g_string_append_c (string, ';');
}
if (free_list)
{
g_slist_foreach (list, (GFunc) g_free, NULL);
g_slist_free (list);
}
return g_string_free (string, FALSE);
}
static int
lang_cmp (MooLang *lang1,
MooLang *lang2)
{
const char *name1, *name2;
name1 = _moo_lang_display_name (lang1);
name2 = _moo_lang_display_name (lang2);
return g_utf8_collate (name1, name2);
}
static GtkTreeModel *
create_lang_model (void)
{
GtkTreeStore *store;
MooLangMgr *mgr;
GSList *langs, *sections, *l;
GtkTreeIter iter;
const char *config;
char *ext, *mime;
mgr = moo_lang_mgr_default ();
langs = g_slist_sort (moo_lang_mgr_get_available_langs (mgr), (GCompareFunc) lang_cmp);
sections = moo_lang_mgr_get_sections (mgr);
store = gtk_tree_store_new (6, G_TYPE_STRING, G_TYPE_STRING, MOO_TYPE_LANG,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_store_append (store, &iter, NULL);
config = _moo_lang_mgr_get_config (mgr, MOO_LANG_NONE);
ext = list_to_string (_moo_lang_mgr_get_globs (mgr, NULL), TRUE);
mime = list_to_string (_moo_lang_mgr_get_mime_types (mgr, NULL), TRUE);
gtk_tree_store_set (store, &iter,
COLUMN_ID, MOO_LANG_NONE,
COLUMN_NAME, "None",
COLUMN_CONFIG, config,
COLUMN_MIMETYPES, mime,
COLUMN_EXTENSIONS, ext,
-1);
g_free (ext);
g_free (mime);
while (sections)
{
char *section = sections->data;
gtk_tree_store_append (store, &iter, NULL);
gtk_tree_store_set (store, &iter, COLUMN_NAME, section, -1);
for (l = langs; l != NULL; l = l->next)
{
MooLang *lang = l->data;
if (!_moo_lang_get_hidden (lang) &&
!strcmp (_moo_lang_get_section (lang), section))
{
GtkTreeIter child;
ext = list_to_string (_moo_lang_mgr_get_globs (mgr, _moo_lang_id (lang)), TRUE);
mime = list_to_string (_moo_lang_mgr_get_mime_types (mgr, _moo_lang_id (lang)), TRUE);
config = _moo_lang_mgr_get_config (mgr, _moo_lang_id (lang));
gtk_tree_store_append (store, &child, &iter);
gtk_tree_store_set (store, &child,
COLUMN_ID, _moo_lang_id (lang),
COLUMN_NAME, _moo_lang_display_name (lang),
COLUMN_LANG, lang,
COLUMN_CONFIG, config,
COLUMN_MIMETYPES, mime,
COLUMN_EXTENSIONS, ext,
-1);
g_free (ext);
g_free (mime);
}
}
g_free (section);
sections = g_slist_delete_link (sections, sections);
}
g_slist_foreach (langs, (GFunc) g_object_unref, NULL);
g_slist_free (langs);
return GTK_TREE_MODEL (store);
}
#if 0
static gboolean
separator_func (GtkTreeModel *model,
GtkTreeIter *iter,
G_GNUC_UNUSED gpointer data)
{
char *name = NULL;
gtk_tree_model_get (model, iter, COLUMN_NAME, &name, -1);
if (!name)
return TRUE;
g_free (name);
return FALSE;
}
#endif
static void
set_sensitive (G_GNUC_UNUSED GtkCellLayout *cell_layout,
GtkCellRenderer *cell,
GtkTreeModel *model,
GtkTreeIter *iter,
G_GNUC_UNUSED gpointer data)
{
g_object_set (cell, "sensitive",
!gtk_tree_model_iter_has_child (model, iter),
NULL);
}
static void
default_lang_combo_init (GtkComboBox *combo,
MooPrefsPage *page)
{
GtkTreeModel *model;
GtkCellRenderer *cell;
fix_style (GTK_WIDGET (combo));
model = page_get_lang_model (page);
g_return_if_fail (model != NULL);
cell = gtk_cell_renderer_text_new ();
gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo));
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
"text", COLUMN_NAME, NULL);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
set_sensitive, NULL, NULL);
gtk_combo_box_set_model (combo, model);
}
static gboolean
find_lang_by_id (GtkTreeModel *model,
G_GNUC_UNUSED GtkTreePath *path,
GtkTreeIter *iter,
gpointer user_data)
{
struct {
gboolean found;
GtkTreeIter iter;
const char *id;
} *data = user_data;
char *lang_id = NULL;
gtk_tree_model_get (model, iter, COLUMN_ID, &lang_id, -1);
if (_moo_str_equal(data->id, lang_id))
{
data->found = TRUE;
data->iter = *iter;
g_free (lang_id);
return TRUE;
}
g_free (lang_id);
return FALSE;
}
static void
default_lang_combo_set_lang (GtkComboBox *combo,
const char *id)
{
GtkTreeModel *model;
struct {
gboolean found;
GtkTreeIter iter;
const char *id;
} data;
g_return_if_fail (GTK_IS_COMBO_BOX (combo));
model = gtk_combo_box_get_model (combo);
data.found = FALSE;
data.id = id ? id : MOO_LANG_NONE;
gtk_tree_model_foreach (model,
(GtkTreeModelForeachFunc) find_lang_by_id,
&data);
g_return_if_fail (data.found);
gtk_combo_box_set_active_iter (combo, &data.iter);
}
static char *
page_get_default_lang (PrefsLangsXml *gxml)
{
GtkTreeModel *model;
GtkTreeIter iter;
char *lang = NULL;
if (!gtk_combo_box_get_active_iter (gxml->default_lang_combo, &iter))
{
g_critical ("%s: oops", G_STRLOC);
return NULL;
}
model = gtk_combo_box_get_model (gxml->default_lang_combo);
gtk_tree_model_get (model, &iter, COLUMN_ID, &lang, -1);
return lang;
}
/*********************************************************************/
/* Per-lang settings
*/
static void
helper_update_widgets (PrefsLangsXml *gxml,
GtkTreeModel *model,
G_GNUC_UNUSED GtkTreePath *path,
GtkTreeIter *iter)
{
MooLang *lang = NULL;
char *ext = NULL, *mime = NULL, *id = NULL, *conf = NULL;
g_return_if_fail (iter != NULL);
gtk_tree_model_get (model, iter,
COLUMN_LANG, &lang,
COLUMN_MIMETYPES, &mime,
COLUMN_EXTENSIONS, &ext,
COLUMN_CONFIG, &conf,
COLUMN_ID, &id,
-1);
g_return_if_fail (id != NULL);
gtk_entry_set_text (gxml->extensions, ext ? ext : "");
gtk_entry_set_text (gxml->mimetypes, mime ? mime : "");
gtk_entry_set_text (gxml->config, conf ? conf : "");
gtk_widget_set_sensitive (GTK_WIDGET (gxml->mimetypes), lang != NULL);
gtk_widget_set_sensitive (GTK_WIDGET (gxml->label_mimetypes), lang != NULL);
if (lang)
g_object_unref (lang);
g_free (conf);
g_free (ext);
g_free (mime);
g_free (id);
}
static void
helper_update_model (PrefsLangsXml *gxml,
GtkTreeModel *model,
G_GNUC_UNUSED GtkTreePath *path,
GtkTreeIter *iter)
{
const char *ext, *mime, *conf;
ext = gtk_entry_get_text (gxml->extensions);
mime = gtk_entry_get_text (gxml->mimetypes);
conf = gtk_entry_get_text (gxml->config);
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
COLUMN_MIMETYPES, mime,
COLUMN_EXTENSIONS, ext,
COLUMN_CONFIG, conf, -1);
}
static void
lang_combo_init (GtkComboBox *combo,
MooPrefsPage *page,
PrefsLangsXml *gxml)
{
GtkTreeModel *model;
GtkCellRenderer *cell;
MooTreeHelper *helper;
fix_style (GTK_WIDGET (combo));
model = page_get_lang_model (page);
g_return_if_fail (model != NULL);
cell = gtk_cell_renderer_text_new ();
gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo));
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
"text", COLUMN_NAME, NULL);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo), cell,
set_sensitive, NULL, NULL);
gtk_combo_box_set_model (combo, model);
_moo_combo_box_select_first (combo);
helper = _moo_tree_helper_new (GTK_WIDGET (combo), NULL, NULL, NULL, NULL);
g_return_if_fail (helper != NULL);
g_object_set_data_full (G_OBJECT (page), "moo-tree-helper",
helper, g_object_unref);
g_signal_connect_swapped (helper, "update-widgets",
G_CALLBACK (helper_update_widgets), gxml);
g_signal_connect_swapped (helper, "update-model",
G_CALLBACK (helper_update_model), gxml);
_moo_tree_helper_update_widgets (helper);
}
static gboolean
apply_one_lang (GtkTreeModel *model,
G_GNUC_UNUSED GtkTreePath *path,
GtkTreeIter *iter,
MooLangMgr *mgr)
{
MooLang *lang = NULL;
char *config = NULL, *id = NULL;
char *mime, *ext;
gtk_tree_model_get (model, iter,
COLUMN_LANG, &lang,
COLUMN_ID, &id,
COLUMN_CONFIG, &config, -1);
if (!id)
return FALSE;
gtk_tree_model_get (model, iter,
COLUMN_MIMETYPES, &mime,
COLUMN_EXTENSIONS, &ext, -1);
_moo_lang_mgr_set_mime_types (mgr, id, mime);
_moo_lang_mgr_set_globs (mgr, id, ext);
_moo_lang_mgr_set_config (mgr, id, config);
if (lang)
g_object_unref (lang);
g_free (mime);
g_free (ext);
g_free (config);
g_free (id);
return FALSE;
}
static void
prefs_page_apply_lang_prefs (MooPrefsPage *page)
{
GtkTreeModel *model;
MooTreeHelper *helper;
MooLangMgr *mgr;
helper = g_object_get_data (G_OBJECT (page), "moo-tree-helper");
_moo_tree_helper_update_model (helper, NULL, NULL);
model = page_get_lang_model (page);
g_return_if_fail (model != NULL);
mgr = moo_lang_mgr_default ();
gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc) apply_one_lang, mgr);
_moo_lang_mgr_save_config (mgr);
_moo_edit_update_lang_config ();
}
/*********************************************************************/
/* Filters
*/
enum {
FILTER_COLUMN_FILTER,
FILTER_COLUMN_CONFIG,
FILTER_NUM_COLUMNS
};
static void
filter_store_set_modified (gpointer store,
gboolean modified)
{
g_return_if_fail (GTK_IS_LIST_STORE (store));
g_object_set_data (store, "filter-store-modified",
GINT_TO_POINTER (modified));
_moo_tree_helper_set_modified (g_object_get_data (store, "tree-helper"), FALSE);
}
static gboolean
filter_store_get_modified (gpointer store)
{
g_return_val_if_fail (GTK_IS_LIST_STORE (store), FALSE);
return g_object_get_data (store, "filter-store-modified") != NULL ||
_moo_tree_helper_get_modified (g_object_get_data (store, "tree-helper"));
}
static void
populate_filter_settings_store (GtkListStore *store)
{
GSList *strings, *l;
_moo_edit_filter_settings_load ();
l = strings = _moo_edit_filter_settings_get_strings ();
while (l)
{
GtkTreeIter iter;
g_return_if_fail (l->next != NULL);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
FILTER_COLUMN_FILTER, l->data,
FILTER_COLUMN_CONFIG, l->next->data,
-1);
l = l->next->next;
}
g_slist_foreach (strings, (GFunc) g_free, NULL);
g_slist_free (strings);
}
static void
filter_cell_edited (GtkCellRendererText *cell,
const char *path_string,
const char *text,
GtkListStore *store)
{
GtkTreeIter iter;
GtkTreePath *path;
int column;
char *old_text;
g_return_if_fail (GTK_IS_LIST_STORE (store));
column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "filter-store-column-id"));
g_return_if_fail (column >= 0 && column < FILTER_NUM_COLUMNS);
path = gtk_tree_path_new_from_string (path_string);
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
{
gtk_tree_path_free (path);
return;
}
gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, column, &old_text, -1);
if (!_moo_str_equal (old_text, text))
{
gtk_list_store_set (store, &iter, column, text, -1);
filter_store_set_modified (store, TRUE);
}
g_free (old_text);
gtk_tree_path_free (path);
}
static void
create_filter_cell (GtkTreeView *treeview,
GtkListStore *store,
const char *title,
int column_id)
{
GtkTreeViewColumn *column;
GtkCellRenderer *cell;
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (title, cell, "text", column_id, NULL);
gtk_tree_view_append_column (treeview, column);
g_object_set (cell, "editable", TRUE, NULL);
g_object_set_data (G_OBJECT (cell), "filter-store-column-id", GINT_TO_POINTER (column_id));
g_signal_connect (cell, "edited", G_CALLBACK (filter_cell_edited), store);
}
static void
filter_treeview_init (PrefsFiltersXml *gxml)
{
GtkListStore *store;
MooTreeHelper *helper;
store = gtk_list_store_new (FILTER_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
populate_filter_settings_store (store);
gtk_tree_view_set_model (gxml->filter_treeview, GTK_TREE_MODEL (store));
create_filter_cell (gxml->filter_treeview, store, "Filter", FILTER_COLUMN_FILTER);
create_filter_cell (gxml->filter_treeview, store, "Options", FILTER_COLUMN_CONFIG);
helper = _moo_tree_helper_new (GTK_WIDGET (gxml->filter_treeview),
GTK_WIDGET (gxml->new_filter_setting),
GTK_WIDGET (gxml->delete_filter_setting),
GTK_WIDGET (gxml->filter_setting_up),
GTK_WIDGET (gxml->filter_setting_down));
g_object_set_data_full (G_OBJECT (gxml->filter_treeview), "tree-helper", helper, g_object_unref);
g_object_set_data (G_OBJECT (store), "tree-helper", helper);
_moo_tree_helper_update_widgets (helper);
g_object_unref (store);
}
static gboolean
prepend_filter_and_config (GtkTreeModel *model,
G_GNUC_UNUSED GtkTreePath *path,
GtkTreeIter *iter,
GSList **list)
{
char *filter = NULL, *config = NULL;
gtk_tree_model_get (model, iter,
FILTER_COLUMN_FILTER, &filter,
FILTER_COLUMN_CONFIG, &config,
-1);
*list = g_slist_prepend (*list, filter ? filter : g_strdup (""));
*list = g_slist_prepend (*list, config ? config : g_strdup (""));
return FALSE;
}
static void
apply_filter_settings (PrefsFiltersXml *gxml)
{
GSList *strings = NULL;
GtkTreeModel *model;
model = gtk_tree_view_get_model (gxml->filter_treeview);
if (!filter_store_get_modified (model))
return;
gtk_tree_model_foreach (model,
(GtkTreeModelForeachFunc) prepend_filter_and_config,
&strings);
strings = g_slist_reverse (strings);
_moo_edit_filter_settings_set_strings (strings);
filter_store_set_modified (model, FALSE);
g_slist_foreach (strings, (GFunc) g_free, NULL);
g_slist_free (strings);
}
/**************************************************************************/
/* Encoding combos
*/
static void
save_encoding_combo_init (PrefsFileXml *gxml)
{
const char *enc;
_moo_encodings_combo_init (GTK_COMBO_BOX (gxml->encoding_save),
MOO_ENCODING_COMBO_SAVE, TRUE);
enc = moo_prefs_get_string (moo_edit_setting (MOO_EDIT_PREFS_ENCODING_SAVE));
_moo_encodings_combo_set_enc (GTK_COMBO_BOX (gxml->encoding_save),
enc, MOO_ENCODING_COMBO_SAVE);
}
static void
save_encoding_combo_apply (PrefsFileXml *gxml)
{
const char *enc;
enc = _moo_encodings_combo_get_enc (GTK_COMBO_BOX (gxml->encoding_save),
MOO_ENCODING_COMBO_SAVE);
moo_prefs_set_string (moo_edit_setting (MOO_EDIT_PREFS_ENCODING_SAVE), enc);
}