1 /**
2  * @file ui_common.c  UI helper functions
3  *
4  * Copyright (C) 2008-2014 Lars Windolf <lars.windolf@gmx.de>
5  * Copyright (C) 2009 Hubert Figuiere <hub@figuiere.net>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 
22 #include "ui/ui_common.h"
23 
24 #include "common.h"
25 #include "conf.h"
26 #include "ui/liferea_shell.h"
27 
28 void
ui_common_setup_combo_menu(GtkWidget * widget,const gchar ** options,GCallback callback,gint defaultValue)29 ui_common_setup_combo_menu (GtkWidget *widget,
30                      const gchar **options,
31                      GCallback callback,
32                      gint defaultValue)
33 {
34 	GtkListStore	*listStore;
35 	GtkTreeIter	treeiter;
36 	guint		i;
37 
38 	listStore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
39 	g_assert (NULL != widget);
40 	for (i = 0; options[i] != NULL; i++) {
41 		gtk_list_store_append (listStore, &treeiter);
42 		gtk_list_store_set (listStore, &treeiter, 0, _(options[i]), 1, i, -1);
43 	}
44 	gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (listStore));
45 	if (-1 <= defaultValue)
46 		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), defaultValue);
47 
48 	if (callback)
49 		g_signal_connect (G_OBJECT (widget), "changed", callback, widget);
50 }
51 
52 void
ui_common_setup_combo_text(GtkComboBox * combo,gint col)53 ui_common_setup_combo_text (GtkComboBox *combo, gint col)
54 {
55 	GtkCellRenderer *rend = gtk_cell_renderer_text_new ();
56 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), rend, TRUE);
57 	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), rend, "text", col);
58 }
59 
60 void
ui_common_treeview_move_cursor(GtkTreeView * treeview,gint step)61 ui_common_treeview_move_cursor (GtkTreeView *treeview, gint step)
62 {
63 	gboolean	ret;
64 
65 	gtk_widget_grab_focus (GTK_WIDGET (treeview));
66 	g_signal_emit_by_name (treeview, "move-cursor", GTK_MOVEMENT_DISPLAY_LINES, step, &ret);
67 }
68 
69 void
ui_common_treeview_move_cursor_to_first(GtkTreeView * treeview)70 ui_common_treeview_move_cursor_to_first (GtkTreeView *treeview)
71 {
72 	GtkTreePath	*path;
73 
74 	path = gtk_tree_path_new_first ();
75 	gtk_tree_view_set_cursor (treeview, path, NULL, FALSE);
76 	gtk_tree_path_free(path);
77 }
78 
79 void
ui_show_error_box(const char * format,...)80 ui_show_error_box (const char *format, ...)
81 {
82 	GtkWidget	*dialog;
83 	va_list		args;
84 	gchar		*msg;
85 
86 	g_return_if_fail (format != NULL);
87 
88 	va_start (args, format);
89 	msg = g_strdup_vprintf (format, args);
90 	va_end (args);
91 
92 	dialog = gtk_message_dialog_new (GTK_WINDOW (liferea_shell_get_window ()),
93                   GTK_DIALOG_DESTROY_WITH_PARENT,
94                   GTK_MESSAGE_ERROR,
95                   GTK_BUTTONS_CLOSE,
96                   "%s", msg);
97 	(void)gtk_dialog_run (GTK_DIALOG (dialog));
98 	gtk_widget_destroy (dialog);
99 	g_free (msg);
100 }
101 
102 void
ui_show_info_box(const char * format,...)103 ui_show_info_box (const char *format, ...)
104 {
105 	GtkWidget	*dialog;
106 	va_list		args;
107 	gchar		*msg;
108 
109 	g_return_if_fail (format != NULL);
110 
111 	va_start (args, format);
112 	msg = g_strdup_vprintf (format, args);
113 	va_end (args);
114 
115 	dialog = gtk_message_dialog_new (GTK_WINDOW (liferea_shell_get_window ()),
116                   GTK_DIALOG_DESTROY_WITH_PARENT,
117                   GTK_MESSAGE_INFO,
118                   GTK_BUTTONS_CLOSE,
119                   "%s", msg);
120 	(void)gtk_dialog_run (GTK_DIALOG (dialog));
121 	gtk_widget_destroy (dialog);
122 	g_free (msg);
123 }
124 
125 struct file_chooser_tuple {
126 	GtkWidget *dialog;
127 	fileChoosenCallback func;
128 	gpointer user_data;
129 };
130 
131 static void
ui_choose_file_save_cb(GtkDialog * dialog,gint response_id,gpointer user_data)132 ui_choose_file_save_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
133 {
134 	struct file_chooser_tuple *tuple = (struct file_chooser_tuple*)user_data;
135 	gchar *filename;
136 
137 	if (response_id == GTK_RESPONSE_ACCEPT) {
138 		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
139 		tuple->func (filename, tuple->user_data);
140 		g_free (filename);
141 	} else {
142 		tuple->func (NULL, tuple->user_data);
143 	}
144 
145 	gtk_widget_destroy (GTK_WIDGET (dialog));
146 	g_free (tuple);
147 }
148 
149 static void
ui_choose_file_or_dir(gchar * title,const gchar * buttonName,gboolean saving,gboolean directory,fileChoosenCallback callback,const gchar * currentPath,const gchar * defaultFilename,const char * filterstring,const char * filtername,gpointer user_data)150 ui_choose_file_or_dir(gchar *title, const gchar *buttonName, gboolean saving, gboolean directory, fileChoosenCallback callback, const gchar *currentPath, const gchar *defaultFilename, const char *filterstring, const char *filtername, gpointer user_data)
151 {
152 	GtkWidget			*dialog;
153 	struct file_chooser_tuple	*tuple;
154 	GtkWidget			*button;
155 	gchar				*path = NULL;
156 
157 	g_assert (!(saving & directory));
158 	g_assert (!(defaultFilename && !saving));
159 
160 	if (!currentPath)
161 		path = g_strdup (g_get_home_dir ());
162 	else
163 		path = g_strdup (currentPath);
164 
165 	dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW (liferea_shell_get_window ()),
166 	                                      (directory?GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
167 					       (saving ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN)),
168 	                                      _("_Cancel"), GTK_RESPONSE_CANCEL,
169 	                                      NULL);
170 	if (saving)
171 		gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
172 	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
173 
174 	tuple = g_new0 (struct file_chooser_tuple, 1);
175 	tuple->dialog = dialog;
176 	tuple->func = callback;
177 	tuple->user_data = user_data;
178 
179 	button = gtk_dialog_add_button (GTK_DIALOG (dialog), buttonName, GTK_RESPONSE_ACCEPT);
180 	gtk_widget_set_can_default (button, TRUE);
181 	gtk_widget_grab_default (button);
182 
183 	g_signal_connect (G_OBJECT (dialog), "response",
184 	                  G_CALLBACK (ui_choose_file_save_cb), tuple);
185 
186 	if (path && g_file_test (path, G_FILE_TEST_EXISTS)) {
187 		if (directory || defaultFilename)
188 			gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path);
189 		else
190 			gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), path);
191 	}
192 	if (defaultFilename)
193 		gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), defaultFilename);
194 
195 	if (filterstring && filtername) {
196 		GtkFileFilter *filter, *allfiles;
197 		gchar **filterstrings, **f;
198 
199 		filter = gtk_file_filter_new ();
200 
201 		filterstrings = g_strsplit (filterstring, "|", 0);
202 		for (f = filterstrings; *f != NULL; f++)
203 			gtk_file_filter_add_pattern (filter, *f);
204 		g_strfreev (filterstrings);
205 
206 		gtk_file_filter_set_name (filter, filtername);
207 		gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
208 
209 		allfiles = gtk_file_filter_new ();
210 		gtk_file_filter_add_pattern (allfiles, "*");
211 		gtk_file_filter_set_name (allfiles, _("All Files"));
212 		gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), allfiles);
213 	}
214 
215 	gtk_widget_show_all (dialog);
216 	g_free (path);
217 }
218 
219 void
ui_choose_file(gchar * title,const gchar * buttonName,gboolean saving,fileChoosenCallback callback,const gchar * currentPath,const gchar * defaultFilename,const char * filterstring,const char * filtername,gpointer user_data)220 ui_choose_file (gchar *title, const gchar *buttonName, gboolean saving, fileChoosenCallback callback, const gchar *currentPath, const gchar *defaultFilename, const char *filterstring, const char *filtername, gpointer user_data)
221 {
222 	ui_choose_file_or_dir (title, buttonName, saving, FALSE, callback, currentPath, defaultFilename, filterstring, filtername, user_data);
223 }
224 
225 void
ui_common_simple_action_group_set_enabled(GActionGroup * group,gboolean enabled)226 ui_common_simple_action_group_set_enabled (GActionGroup *group, gboolean enabled)
227 {
228 	gchar **actions_list = g_action_group_list_actions (group);
229 	gint i;
230 	for (i=0;actions_list[i] != NULL;i++) {
231 		g_simple_action_set_enabled (G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP (group), actions_list [i])), enabled);
232 	}
233 	g_strfreev (actions_list);
234 }
235 
236 void
ui_common_add_action_group_to_map(GActionGroup * group,GActionMap * map)237 ui_common_add_action_group_to_map (GActionGroup *group, GActionMap *map)
238 {
239 	gchar **actions_list = g_action_group_list_actions (group);
240 	gint i;
241 	for (i=0;actions_list[i] != NULL;i++) {
242 		g_action_map_add_action (map, g_action_map_lookup_action (G_ACTION_MAP (group), actions_list [i]));
243 	}
244 	g_strfreev (actions_list);
245 
246 }
247