1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3 * Pan - A Newsreader for Gtk+
4 * Copyright (C) 2002-2006 Charles Kerr <charles@rebelbase.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include <config.h>
21 #include <glib/gi18n.h>
22 #include <glib.h>
23 #include "gtk-compat.h"
24 #ifdef HAVE_GTKSPELL
25 #include <enchant/enchant.h>
26 #endif
27 #include <pan/general/debug.h>
28 #include <pan/general/macros.h>
29 #include <pan/data/data.h>
30 #include "e-charset-combo-box.h"
31 #include "group-prefs-dialog.h"
32 #include "hig.h"
33 #include "pad.h"
34 #include "pan-file-entry.h"
35 #include "gtk-compat.h"
36 #include "pan-colors.h"
37
38 #include <iostream>
39
40 using namespace pan;
41
42
43 namespace
44 {
45
46 struct Langs
47 {
48 GList* langs;
49 };
50
51 static void
dict_describe_cb(const char * const lang_tag,const char * const provider_name,const char * const provider_desc,const char * const provider_file,void * user_data)52 dict_describe_cb(const char * const lang_tag,
53 const char * const provider_name,
54 const char * const provider_desc,
55 const char * const provider_file,
56 void * user_data)
57 {
58 Langs *langs = (Langs *)user_data;
59 langs->langs = g_list_insert_sorted(langs->langs, g_strdup(lang_tag), (GCompareFunc) strcmp);
60 }
61
62 #ifdef HAVE_GTKSPELL
63 static EnchantBroker *broker = NULL;
64 static GList *langs = NULL;
65 static GtkTextView* view = NULL;
66 Langs l;
67 #endif
init_spell()68 void init_spell()
69 {
70 #ifdef HAVE_GTKSPELL
71 view = GTK_TEXT_VIEW(gtk_text_view_new());
72 broker = enchant_broker_init();
73 l.langs = langs;
74 enchant_broker_list_dicts(broker, dict_describe_cb, &l);
75 #endif
76 }
77
deinit_spell()78 void deinit_spell()
79 {
80 #ifdef HAVE_GTKSPELL
81 if (view) g_object_ref_sink(view);
82 if (broker) enchant_broker_free(broker);
83 #endif
84 }
85
delete_dialog(gpointer castme)86 void delete_dialog (gpointer castme)
87 {
88 delete static_cast<GroupPrefsDialog*>(castme);
89 }
90 }
91
92 void
save_from_gui()93 GroupPrefsDialog :: save_from_gui ()
94 {
95 // charset...
96 const char * tmp = e_charset_combo_box_get_charset (E_CHARSET_COMBO_BOX(_charset));
97 foreach_const (quarks_v, _groups, it)
98 _group_prefs.set_string (*it, "character-encoding", tmp);
99
100 // posting profile...
101 std::string profile;
102 if (gtk_widget_get_sensitive (_profile)) {
103 char * pch (gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT(_profile)));
104 foreach_const (quarks_v, _groups, it)
105 _group_prefs.set_string (*it, "posting-profile", pch);
106 g_free (pch);
107 }
108
109 // save path...
110 const char * pch (file_entry_get (_save_path));
111 foreach_const (quarks_v, _groups, it)
112 _group_prefs.set_string (*it, "default-group-save-path", pch);
113
114 // spellchecker language
115 #ifdef HAVE_GTKSPELL
116 GtkTreeIter iter;
117 if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX(_spellchecker_language), &iter))
118 return;
119
120 gchar* name(0);
121 GtkTreeModel* model = gtk_combo_box_get_model (GTK_COMBO_BOX(_spellchecker_language));
122 gtk_tree_model_get (model, &iter, 0, &name, -1);
123
124 if (name)
125 {
126 foreach_const (quarks_v, _groups, it)
127 _group_prefs.set_string (*it, "spellcheck-language", name);
128 g_free(name);
129 }
130 #endif
131
132 _group_prefs.save () ;
133
134 }
135
136 void
response_cb(GtkDialog * dialog,int,gpointer user_data)137 GroupPrefsDialog :: response_cb (GtkDialog * dialog,
138 int ,
139 gpointer user_data)
140 {
141 static_cast<GroupPrefsDialog*>(user_data)->save_from_gui ();
142 gtk_widget_destroy (GTK_WIDGET(dialog));
143 }
144
145 namespace
146 {
147 GtkWidget*
create_profiles_combo_box(const Data & data,const quarks_v & groups,const GroupPrefs & group_prefs)148 create_profiles_combo_box (const Data & data,
149 const quarks_v & groups,
150 const GroupPrefs & group_prefs)
151 {
152 GtkWidget * w = gtk_combo_box_text_new ();
153 GtkComboBoxText * combo (GTK_COMBO_BOX_TEXT (w));
154
155 typedef std::set<std::string> unique_strings_t;
156 const unique_strings_t profiles (data.get_profile_names ());
157
158 if (profiles.empty())
159 {
160 gtk_combo_box_text_append_text (combo, _("No Profiles defined in Edit → Posting Profiles."));
161 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
162 gtk_widget_set_sensitive (w, false);
163 }
164 else
165 {
166 const std::string s (group_prefs.get_string (groups[0], "posting-profile", ""));
167 int i(0), sel_index (0);
168 foreach_const (unique_strings_t, profiles, it) {
169 if (*it == s)
170 sel_index = i;
171 ++i;
172 gtk_combo_box_text_append_text (combo, it->c_str());
173 }
174 gtk_combo_box_set_active (GTK_COMBO_BOX(combo), sel_index);
175 }
176
177 return w;
178 }
179
180 GtkWidget*
create_spellcheck_combo_box(const Quark & group,const GroupPrefs & group_prefs)181 create_spellcheck_combo_box ( const Quark & group,
182 const GroupPrefs & group_prefs)
183 {
184 GtkWidget * w(NULL);
185
186 #ifdef HAVE_GTKSPELL
187 init_spell();
188 deinit_spell();
189
190 GtkTreeModel *model;
191 GtkListStore * store = gtk_list_store_new (1, G_TYPE_STRING);
192 GtkTreeIter iter, storeit;
193 bool valid(false);
194
195
196 std::string lang = group_prefs.get_string(group, "spellcheck-language","");
197
198 while (l.langs)
199 {
200 gchar* data = (gchar*)l.langs->data;
201 if (data)
202 {
203 gtk_list_store_append (store, &iter);
204 gtk_list_store_set (store, &iter, 0, data, -1);
205 if (g_strcmp0 ((const char*)l.langs->data,lang.c_str())==0) { storeit = iter; valid=true; }
206 }
207 l.langs = l.langs->next;
208 }
209 model = GTK_TREE_MODEL(store);
210 w = gtk_combo_box_new_with_model (model);
211 g_object_unref(store);
212
213 GtkCellRenderer * renderer (gtk_cell_renderer_text_new ());
214 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), renderer, TRUE);
215 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (w), renderer, "text", 0, NULL);
216
217 if (valid) gtk_combo_box_set_active_iter (GTK_COMBO_BOX(w), &storeit);
218
219 if (l.langs) g_list_free(l.langs);
220 #endif
221 return w;
222 }
223
224 // void color_set_cb (GtkColorButton* b, gpointer p)
225 // {
226 // GroupPrefsDialog* dialog = static_cast<GroupPrefsDialog*>(p);
227 // GdkColor col;
228 // gtk_color_button_get_color (b, &col);
229 // dialog->_color = col;
230 // }
231
color_set_cb(GtkColorButton * b,gpointer p)232 void color_set_cb (GtkColorButton* b, gpointer p)
233 {
234 GroupPrefsDialog* dialog = static_cast<GroupPrefsDialog*>(p);
235 GdkColor val;
236 gtk_color_button_get_color (b, &val);
237 {
238 foreach_const (quarks_v, dialog->get_groups(), it)
239 dialog->get_prefs().set_group_color(*it, val);
240 }
241 }
242
243
new_color_button(const Quark & group,Prefs & prefs,GroupPrefs & gprefs,GroupPrefsDialog * dialog,GtkWidget * w)244 GtkWidget* new_color_button (const Quark& group, Prefs& prefs, GroupPrefs& gprefs, GroupPrefsDialog* dialog, GtkWidget* w)
245 {
246
247 const PanColors& colors (PanColors::get());
248 const std::string& def_fg (colors.def_fg);
249 const std::string& fg (prefs.get_color_str("group-pane-color-fg", def_fg));
250 const GdkColor& val (gprefs.get_group_color (group, fg));
251
252 GtkWidget * b = gtk_color_button_new_with_color (&val);
253 g_signal_connect (b, "color-set", G_CALLBACK(color_set_cb), dialog);
254
255 return b;
256 }
257
258 }
259
260
GroupPrefsDialog(Data & data,const quarks_v & groups,Prefs & prefs,GroupPrefs & group_prefs,GtkWindow * parent_window)261 GroupPrefsDialog :: GroupPrefsDialog (Data & data,
262 const quarks_v & groups,
263 Prefs & prefs,
264 GroupPrefs & group_prefs,
265 GtkWindow * parent_window):
266 _groups (groups),
267 _prefs(prefs),
268 _group_prefs (group_prefs)
269 {
270
271 GtkWidget * dialog = gtk_dialog_new_with_buttons (_("Pan: Group Preferences"),
272 parent_window,
273 GTK_DIALOG_DESTROY_WITH_PARENT,
274 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
275 NULL);
276 gtk_window_set_role (GTK_WINDOW(dialog), "pan-group-dialog");
277 g_signal_connect (dialog, "response", G_CALLBACK(response_cb), this);
278 g_signal_connect_swapped (dialog, "destroy", G_CALLBACK(delete_dialog), this);
279
280 int row (0);
281 GtkWidget *t, *w, *l;
282 t = HIG :: workarea_create ();
283
284 char buf[512];
285 if (groups.size() != 1)
286 g_snprintf (buf, sizeof(buf), _("Properties for Groups"));
287 else
288 g_snprintf (buf, sizeof(buf), _("Properties for %s"), groups[0].c_str());
289
290 HIG::workarea_add_section_title (t, &row, buf);
291 HIG :: workarea_add_section_spacer (t, row, 4);
292 w = _charset = e_charset_combo_box_new( );
293 const char* cs = _group_prefs.get_string (groups[0], "character-encoding", "UTF-8").c_str();
294 e_charset_combo_box_set_charset( E_CHARSET_COMBO_BOX(w), cs ? cs : "");
295
296 HIG :: workarea_add_row (t, &row, _("Character _encoding:"), w);
297
298 w = _save_path = file_entry_new (_("Directory for Saving Attachments"));
299 char * pch = g_build_filename (g_get_home_dir(), "News", NULL);
300 std::string dir (_prefs.get_string ("default-save-attachments-path", pch));
301 if (groups.size() == 1)
302 dir = _group_prefs.get_string (groups[0], "default-group-save-path", dir);
303 g_free (pch);
304 file_entry_set (w, dir.c_str());
305
306 HIG :: workarea_add_row (t, &row, _("Directory for _saving attachments:"), w);
307 w = _profile = create_profiles_combo_box (data, groups, group_prefs);
308 l = HIG :: workarea_add_row (t, &row, _("Posting _profile:"), w);
309
310 gtk_widget_set_sensitive (l, gtk_widget_get_sensitive(w));
311 #ifdef HAVE_GTKSPELL
312 w = _spellchecker_language = create_spellcheck_combo_box ( groups[0], group_prefs);
313 HIG :: workarea_add_row (t, &row, _("Spellchecker _language:"), w);
314 #endif
315 w = _group_color = new_color_button (groups[0], _prefs, _group_prefs, this, dialog);
316 HIG :: workarea_add_row(t, &row, _("Group color:"), w);
317
318 gtk_box_pack_start ( GTK_BOX( gtk_dialog_get_content_area( GTK_DIALOG( dialog))), t, true, true, 0);
319 _root = dialog;
320 gtk_widget_show_all (t);
321
322 }
323