1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * pluma-spell-language-dialog.c
4  * This file is part of pluma
5  *
6  * Copyright (C) 2002 Paolo Maggi
7  * Copyright (C) 2012-2021 MATE Developers
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 /*
26  * Modified by the pluma Team, 2002. See the AUTHORS file for a
27  * list of people on the pluma Team.
28  * See the ChangeLog files for a list of changes.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 #include <glib/gi18n.h>
36 #include <gtk/gtk.h>
37 #include <pluma/pluma-utils.h>
38 #include <pluma/pluma-help.h>
39 #include "pluma-spell-language-dialog.h"
40 #include "pluma-spell-checker-language.h"
41 
42 
43 enum
44 {
45 	COLUMN_LANGUAGE_NAME = 0,
46 	COLUMN_LANGUAGE_POINTER,
47 	ENCODING_NUM_COLS
48 };
49 
50 
51 struct _PlumaSpellLanguageDialog
52 {
53 	GtkDialog dialog;
54 
55 	GtkWidget *languages_treeview;
56 	GtkTreeModel *model;
57 };
58 
G_DEFINE_TYPE(PlumaSpellLanguageDialog,pluma_spell_language_dialog,GTK_TYPE_DIALOG)59 G_DEFINE_TYPE(PlumaSpellLanguageDialog, pluma_spell_language_dialog, GTK_TYPE_DIALOG)
60 
61 
62 static void
63 pluma_spell_language_dialog_class_init (PlumaSpellLanguageDialogClass *klass)
64 {
65 	/* GObjectClass *object_class = G_OBJECT_CLASS (klass); */
66 }
67 
68 static void
dialog_response_handler(GtkDialog * dlg,gint res_id)69 dialog_response_handler (GtkDialog *dlg,
70 			 gint       res_id)
71 {
72 	if (res_id == GTK_RESPONSE_HELP)
73 	{
74 		pluma_help_display (GTK_WINDOW (dlg),
75 				    NULL,
76 				    "pluma-spell-checker-plugin");
77 
78 		g_signal_stop_emission_by_name (dlg, "response");
79 	}
80 }
81 
82 static void
scroll_to_selected(GtkTreeView * tree_view)83 scroll_to_selected (GtkTreeView *tree_view)
84 {
85 	GtkTreeModel *model;
86 	GtkTreeSelection *selection;
87 	GtkTreeIter iter;
88 
89 	model = gtk_tree_view_get_model (tree_view);
90 	g_return_if_fail (model != NULL);
91 
92 	/* Scroll to selected */
93 	selection = gtk_tree_view_get_selection (tree_view);
94 	g_return_if_fail (selection != NULL);
95 
96 	if (gtk_tree_selection_get_selected (selection, NULL, &iter))
97 	{
98 		GtkTreePath* path;
99 
100 		path = gtk_tree_model_get_path (model, &iter);
101 		g_return_if_fail (path != NULL);
102 
103 		gtk_tree_view_scroll_to_cell (tree_view,
104 					      path, NULL, TRUE, 1.0, 0.0);
105 		gtk_tree_path_free (path);
106 	}
107 }
108 
109 static void
language_row_activated(GtkTreeView * tree_view,GtkTreePath * path,GtkTreeViewColumn * column,PlumaSpellLanguageDialog * dialog)110 language_row_activated (GtkTreeView *tree_view,
111 			GtkTreePath *path,
112 			GtkTreeViewColumn *column,
113 			PlumaSpellLanguageDialog *dialog)
114 {
115 	gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
116 }
117 
118 static void
create_dialog(PlumaSpellLanguageDialog * dlg,const gchar * data_dir)119 create_dialog (PlumaSpellLanguageDialog *dlg,
120 	       const gchar *data_dir)
121 {
122 	GtkWidget *error_widget;
123 	GtkWidget *content;
124 	gboolean ret;
125 	GtkCellRenderer *cell;
126 	GtkTreeViewColumn *column;
127 	gchar *ui_file;
128 	gchar *root_objects[] = {
129 		"content",
130 		NULL
131 	};
132 
133 	pluma_dialog_add_button (GTK_DIALOG (dlg), _("_Cancel"), "process-stop", GTK_RESPONSE_CANCEL);
134 	pluma_dialog_add_button (GTK_DIALOG (dlg), _("_OK"), "gtk-ok", GTK_RESPONSE_OK);
135 	pluma_dialog_add_button (GTK_DIALOG (dlg), _("_Help"), "help-browser", GTK_RESPONSE_HELP);
136 
137 	gtk_window_set_title (GTK_WINDOW (dlg), _("Set language"));
138 	gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
139 	gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
140 
141 	/* HIG defaults */
142 	gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
143 	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
144 			     2); /* 2 * 5 + 2 = 12 */
145 
146 	g_signal_connect (dlg,
147 			  "response",
148 			  G_CALLBACK (dialog_response_handler),
149 			  NULL);
150 
151 	ui_file = g_build_filename (data_dir, "languages-dialog.ui", NULL);
152 	ret = pluma_utils_get_ui_objects (ui_file,
153 					  root_objects,
154 					  &error_widget,
155 					  "content", &content,
156 					  "languages_treeview", &dlg->languages_treeview,
157 					  NULL);
158 	g_free (ui_file);
159 
160 	if (!ret)
161 	{
162 		gtk_widget_show (error_widget);
163 
164 		gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
165 		                    error_widget,
166 		                    TRUE, TRUE, 0);
167 
168 		return;
169 	}
170 
171 	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
172 			    content, TRUE, TRUE, 0);
173 	g_object_unref (content);
174 	gtk_container_set_border_width (GTK_CONTAINER (content), 5);
175 
176 	dlg->model = GTK_TREE_MODEL (gtk_list_store_new (ENCODING_NUM_COLS,
177 							 G_TYPE_STRING,
178 							 G_TYPE_POINTER));
179 
180 	gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->languages_treeview),
181 				 dlg->model);
182 
183 	g_object_unref (dlg->model);
184 
185 	/* Add the encoding column */
186 	cell = gtk_cell_renderer_text_new ();
187 	column = gtk_tree_view_column_new_with_attributes (_("Languages"),
188 							   cell,
189 							   "text",
190 							   COLUMN_LANGUAGE_NAME,
191 							   NULL);
192 
193 	gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->languages_treeview),
194 				     column);
195 
196 	gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->languages_treeview),
197 					 COLUMN_LANGUAGE_NAME);
198 
199 	g_signal_connect (dlg->languages_treeview,
200 			  "realize",
201 			  G_CALLBACK (scroll_to_selected),
202 			  dlg);
203 	g_signal_connect (dlg->languages_treeview,
204 			  "row-activated",
205 			  G_CALLBACK (language_row_activated),
206 			  dlg);
207 }
208 
209 static void
pluma_spell_language_dialog_init(PlumaSpellLanguageDialog * dlg)210 pluma_spell_language_dialog_init (PlumaSpellLanguageDialog *dlg)
211 {
212 
213 }
214 
215 static void
populate_language_list(PlumaSpellLanguageDialog * dlg,const PlumaSpellCheckerLanguage * cur_lang)216 populate_language_list (PlumaSpellLanguageDialog        *dlg,
217 			const PlumaSpellCheckerLanguage *cur_lang)
218 {
219 	GtkListStore *store;
220 	GtkTreeIter iter;
221 
222 	const GSList* langs;
223 
224 	/* create list store */
225 	store = GTK_LIST_STORE (dlg->model);
226 
227 	langs = pluma_spell_checker_get_available_languages ();
228 
229 	while (langs)
230 	{
231 		const gchar *name;
232 
233 		name = pluma_spell_checker_language_to_string ((const PlumaSpellCheckerLanguage*)langs->data);
234 
235 		gtk_list_store_append (store, &iter);
236 		gtk_list_store_set (store, &iter,
237 				    COLUMN_LANGUAGE_NAME, name,
238 				    COLUMN_LANGUAGE_POINTER, langs->data,
239 				    -1);
240 
241 		if (langs->data == cur_lang)
242 		{
243 			GtkTreeSelection *selection;
244 
245 			selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview));
246 			g_return_if_fail (selection != NULL);
247 
248 			gtk_tree_selection_select_iter (selection, &iter);
249 		}
250 
251 		langs = g_slist_next (langs);
252 	}
253 }
254 
255 GtkWidget *
pluma_spell_language_dialog_new(GtkWindow * parent,const PlumaSpellCheckerLanguage * cur_lang,const gchar * data_dir)256 pluma_spell_language_dialog_new (GtkWindow                       *parent,
257 				 const PlumaSpellCheckerLanguage *cur_lang,
258 				 const gchar *data_dir)
259 {
260 	PlumaSpellLanguageDialog *dlg;
261 
262 	g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
263 
264 	dlg = g_object_new (PLUMA_TYPE_SPELL_LANGUAGE_DIALOG, NULL);
265 
266 	create_dialog (dlg, data_dir);
267 
268 	populate_language_list (dlg, cur_lang);
269 
270 	gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
271 	gtk_widget_grab_focus (dlg->languages_treeview);
272 
273 	return GTK_WIDGET (dlg);
274 }
275 
276 const PlumaSpellCheckerLanguage *
pluma_spell_language_get_selected_language(PlumaSpellLanguageDialog * dlg)277 pluma_spell_language_get_selected_language (PlumaSpellLanguageDialog *dlg)
278 {
279 	GValue value = {0, };
280 	const PlumaSpellCheckerLanguage* lang;
281 
282 	GtkTreeIter iter;
283 	GtkTreeSelection *selection;
284 
285 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview));
286 	g_return_val_if_fail (selection != NULL, NULL);
287 
288 	if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
289 		return NULL;
290 
291 	gtk_tree_model_get_value (dlg->model,
292 				  &iter,
293 				  COLUMN_LANGUAGE_POINTER,
294 				  &value);
295 
296 	lang = (const PlumaSpellCheckerLanguage* ) g_value_get_pointer (&value);
297 
298 	return lang;
299 }
300 
301