1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #include <gmerlin/utils.h>
27
28
29 #include "gtk_dialog.h"
30 #include <gui_gtk/gtkutils.h>
31
32 enum
33 {
34 COLUMN_DEVICE,
35 NUM_COLUMNS
36 };
37
38 typedef struct
39 {
40 GtkWidget * treeview;
41
42 GtkWidget * add_button;
43 GtkWidget * delete_button;
44 GtkWidget * scrolled;
45 GtkWidget * fileselect;
46 int selected;
47 } device_t;
48
get_value(bg_gtk_widget_t * w)49 static void get_value(bg_gtk_widget_t * w)
50 {
51 int i;
52 device_t * priv;
53 GtkTreeSelection * selection;
54 GtkTreeIter iter;
55 GtkTreeModel * model;
56 char ** tmp_items;
57
58 priv = (device_t*)(w->priv);
59
60 model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview));
61 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
62
63 gtk_list_store_clear(GTK_LIST_STORE(model));
64
65 if(!w->value.val_str || (*w->value.val_str == '\0'))
66 return;
67
68 tmp_items = bg_strbreak(w->value.val_str, ' ');
69
70
71 i = 0;
72
73 while(tmp_items[i])
74 {
75 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
76 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
77 COLUMN_DEVICE,
78 tmp_items[i],
79 -1);
80 if(!i)
81 gtk_tree_selection_select_iter(selection, &iter);
82
83 i++;
84 }
85 bg_strbreak_free(tmp_items);
86 }
87
set_value(bg_gtk_widget_t * w)88 static void set_value(bg_gtk_widget_t * w)
89 {
90 device_t * priv;
91 GtkTreeSelection * selection;
92 GtkTreeIter iter;
93 GtkTreeModel * model;
94
95 int num_entries;
96 int selected;
97 char ** strings;
98 int len;
99 int index;
100 int i, imax;
101
102 priv = (device_t*)(w->priv);
103
104 model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview));
105
106 if(!gtk_tree_model_get_iter_first(model, &iter))
107 {
108 if(w->value.val_str)
109 {
110 free(w->value.val_str);
111 w->value.val_str = NULL;
112 }
113 return;
114 }
115 num_entries = 1;
116 while(gtk_tree_model_iter_next(model, &iter))
117 num_entries++;
118
119 /* Copy the strings */
120
121 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
122
123 strings = malloc(num_entries * sizeof(char*));
124
125 len = 0;
126 selected = -1;
127
128 gtk_tree_model_get_iter_first(model, &iter);
129 for(i = 0; i < num_entries; i++)
130 {
131 gtk_tree_model_get(model, &iter,
132 COLUMN_DEVICE,
133 &strings[i],
134 -1);
135 if(gtk_tree_selection_iter_is_selected(selection,
136 &iter))
137 {
138 selected = i;
139 }
140 gtk_tree_model_iter_next(model, &iter);
141 len += strlen(strings[i])+1;
142 }
143
144 /* Copy to the value */
145
146 if(w->value.val_str)
147 free(w->value.val_str);
148 w->value.val_str = malloc(len);
149 w->value.val_str[0] = '\0';
150
151
152 if(selected >= 0)
153 {
154 strcat(w->value.val_str, strings[selected]);
155 if(num_entries > 1)
156 strcat(w->value.val_str, " ");
157 imax = num_entries-1;
158 }
159 else
160 imax = num_entries;
161 index = 0;
162
163 for(i = 0; i < imax; i++)
164 {
165 if(index == selected)
166 index++;
167 strcat(w->value.val_str, strings[index]);
168 if(i < imax - 1)
169 strcat(w->value.val_str, ":");
170 index++;
171 }
172 for(i = 0; i < num_entries; i++)
173 {
174 g_free(strings[i]);
175 }
176 free(strings);
177 }
178
destroy(bg_gtk_widget_t * w)179 static void destroy(bg_gtk_widget_t * w)
180 {
181 device_t * priv = (device_t*)w->priv;
182 if(priv->fileselect)
183 gtk_widget_destroy(priv->fileselect);
184 free(priv);
185 }
186
attach(void * priv,GtkWidget * table,int * row,int * num_columns)187 static void attach(void * priv, GtkWidget * table,
188 int * row,
189 int * num_columns)
190 {
191 device_t * f = (device_t*)priv;
192 if(*num_columns < 3)
193 *num_columns = 3;
194
195 gtk_table_resize(GTK_TABLE(table), *row+3, *num_columns);
196
197 gtk_table_attach_defaults(GTK_TABLE(table), f->scrolled,
198 0, 2, *row, *row+3);
199
200 gtk_table_attach(GTK_TABLE(table), f->add_button,
201 2, 3, *row, *row+1, GTK_FILL, GTK_SHRINK, 0, 0);
202
203 gtk_table_attach(GTK_TABLE(table), f->delete_button,
204 2, 3, *row+1, *row+2, GTK_FILL, GTK_SHRINK, 0, 0);
205 *row += 3;
206 }
207
208 static const gtk_widget_funcs_t funcs =
209 {
210 .get_value = get_value,
211 .set_value = set_value,
212 .destroy = destroy,
213 .attach = attach
214 };
215
216 static void
fileselect_callback(GtkWidget * chooser,gint response_id,gpointer data)217 fileselect_callback(GtkWidget *chooser,
218 gint response_id,
219 gpointer data)
220 {
221 device_t * priv;
222 GtkTreeIter iter;
223 gchar *uri;
224 priv = (device_t*)data;
225
226 if(response_id == GTK_RESPONSE_OK)
227 {
228 GtkTreeModel * model;
229 uri = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (chooser));
230
231 model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview));
232
233 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
234 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
235 COLUMN_DEVICE,
236 uri,
237 -1);
238 g_free (uri);
239 }
240 // gtk_widget_destroy (chooser);
241
242 gtk_widget_hide(priv->fileselect);
243 gtk_main_quit();
244 }
245
246 static gboolean
fileselect_delete_callback(GtkWidget * w,GdkEventAny * event,gpointer data)247 fileselect_delete_callback(GtkWidget * w, GdkEventAny * event,
248 gpointer data)
249 {
250 fileselect_callback(w, GTK_RESPONSE_CANCEL, data);
251 return TRUE;
252 }
253
button_callback(GtkWidget * w,gpointer data)254 static void button_callback(GtkWidget * w, gpointer data)
255 {
256 device_t * priv;
257 GtkTreeSelection * selection;
258 GtkTreeModel * model;
259 GtkWidget * toplevel;
260 GtkTreeIter iter;
261
262 priv = (device_t*)data;
263
264 if(w == priv->add_button)
265 {
266 if(!priv->fileselect)
267 {
268 toplevel = bg_gtk_get_toplevel(w);
269
270 priv->fileselect =
271 gtk_file_chooser_dialog_new (TRD("Select a device", PACKAGE),
272 GTK_WINDOW(toplevel),
273 GTK_FILE_CHOOSER_ACTION_OPEN,
274 GTK_STOCK_CANCEL,
275 GTK_RESPONSE_CANCEL,
276 GTK_STOCK_OK, GTK_RESPONSE_OK,
277 NULL);
278
279 gtk_window_set_modal(GTK_WINDOW(priv->fileselect), TRUE);
280
281 g_signal_connect(priv->fileselect, "response",
282 G_CALLBACK(fileselect_callback),
283 (gpointer)priv);
284 g_signal_connect(G_OBJECT(priv->fileselect), "delete_event",
285 G_CALLBACK(fileselect_delete_callback),
286 (gpointer)priv);
287 }
288 gtk_widget_show(priv->fileselect);
289 gtk_main();
290 }
291 else if(w == priv->delete_button)
292 {
293 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
294 if(!gtk_tree_selection_get_selected(selection, &model, &iter))
295 return;
296 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
297 }
298 }
299
bg_gtk_create_device(bg_gtk_widget_t * w,const char * translation_domain)300 void bg_gtk_create_device(bg_gtk_widget_t * w,
301 const char * translation_domain)
302 {
303 GtkListStore *store;
304 GtkCellRenderer *renderer;
305 GtkTreeViewColumn *column;
306 GtkTreeSelection * selection;
307 device_t * priv = calloc(1, sizeof(*priv));
308
309 priv->selected = -1;
310
311 store = gtk_list_store_new (NUM_COLUMNS,
312 G_TYPE_STRING);
313
314 priv->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
315
316 if(w->info->help_string)
317 {
318 bg_gtk_tooltips_set_tip(priv->treeview,
319 w->info->help_string, translation_domain);
320 }
321
322
323 /* Add the columns */
324
325 renderer = gtk_cell_renderer_text_new ();
326 column = gtk_tree_view_column_new_with_attributes ("Devices",
327 renderer,
328 "text",
329 COLUMN_DEVICE,
330 NULL);
331 gtk_tree_view_column_set_sort_column_id (column, COLUMN_DEVICE);
332 gtk_tree_view_append_column (GTK_TREE_VIEW(priv->treeview), column);
333
334 /* Set Selection mode */
335
336 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview));
337 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
338
339 priv->add_button = gtk_button_new_with_label(TR("Add..."));
340 priv->delete_button = gtk_button_new_with_label(TR("Delete"));
341
342 g_signal_connect(G_OBJECT(priv->add_button), "clicked",
343 G_CALLBACK(button_callback),
344 (gpointer)priv);
345 g_signal_connect(G_OBJECT(priv->delete_button), "clicked",
346 G_CALLBACK(button_callback),
347 (gpointer)priv);
348
349 gtk_widget_show(priv->add_button);
350 gtk_widget_show(priv->delete_button);
351
352 gtk_widget_show(priv->treeview);
353
354 priv->scrolled =
355 gtk_scrolled_window_new(gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(priv->treeview)),
356 gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(priv->treeview)));
357
358 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(priv->scrolled),
359 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
360 gtk_container_add(GTK_CONTAINER(priv->scrolled), priv->treeview);
361 gtk_widget_show(priv->scrolled);
362 w->funcs = &funcs;
363 w->priv = priv;
364 }
365