factorize treeview columns creation
[omnplay] / src / ui.c
1 /*
2 * ui.c -- GTK+ 2 omnplay
3 * Copyright (C) 2011 Maksym Veremeyenko <verem@m1stereo.tv>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 #include <gdk/gdkkeysyms.h>
31 #include <gtk/gtk.h>
32
33 #include "ui.h"
34 #include "ui_utils.h"
35 #include "ui_buttons.h"
36 #include "support.h"
37
38 typedef struct column_desc
39 {
40 char* title;
41 GType type;
42 } column_desc_t;
43
44 const static column_desc_t playlist_columns[] =
45 {
46 {
47 "REM",
48 G_TYPE_STRING
49 },
50 {
51 "B",
52 G_TYPE_STRING
53 },
54 {
55 "CH",
56 G_TYPE_STRING
57 },
58 {
59 "ID",
60 G_TYPE_STRING
61 },
62 {
63 "IN",
64 G_TYPE_STRING
65 },
66 {
67 "DUR",
68 G_TYPE_STRING
69 },
70 {
71 "TITLE",
72 G_TYPE_STRING
73 },
74 {
75 NULL,
76 G_TYPE_STRING
77 }
78 };
79
80 const static column_desc_t library_columns[] =
81 {
82 {
83 "ID",
84 G_TYPE_STRING
85 },
86 {
87 "DUR",
88 G_TYPE_STRING
89 },
90 {
91 "TITLE",
92 G_TYPE_STRING
93 },
94 {
95 NULL,
96 G_TYPE_STRING
97 }
98 };
99
100
101 static GtkWidget* create_label(GtkWidget* top, char* text, char* reg, GtkJustification jtype)
102 {
103 GtkWidget* label;
104
105 label = gtk_label_new ("");
106 gtk_widget_show (label);
107
108 gtk_label_set_justify (GTK_LABEL (label), jtype);
109
110 if(reg)
111 GLADE_HOOKUP_OBJECT (top, label, reg);
112
113 if(text)
114 gtk_label_set_text(GTK_LABEL (label), text);
115
116 return label;
117 };
118
119 static GtkWidget* create_treeview(GtkWidget* top, char* name, const column_desc_t columns[])
120 {
121 int i, count;
122
123 GtkWidget *treeview;
124 GtkCellRenderer *renderer;
125 GtkTreeViewColumn *column;
126 GtkListStore *list_store;
127 GType list_store_types[32];
128
129 treeview = gtk_tree_view_new ();
130 gtk_widget_show (treeview);
131
132 for(i = 0, count = 0; columns[i].title; i++, count++)
133 list_store_types[i] = columns[i].type;
134
135 list_store = gtk_list_store_newv(count, list_store_types);
136 gtk_tree_view_set_model( GTK_TREE_VIEW( treeview ), GTK_TREE_MODEL( list_store ) );
137
138 for(i = 0; columns[i].title; i++)
139 {
140 renderer = gtk_cell_renderer_toggle_new();
141 column = gtk_tree_view_column_new_with_attributes(
142 columns[i].title, renderer, "text", i, NULL);
143 gtk_tree_view_append_column(GTK_TREE_VIEW( treeview ), column);
144 };
145
146 g_object_unref(list_store);
147
148 GLADE_HOOKUP_OBJECT (top, treeview, name);
149
150 return treeview;
151 };
152
153 static GtkWidget* pane_library_grid(GtkWidget* top, omnplay_instance_t* app)
154 {
155 GtkWidget *scrolledwindow;
156
157 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
158 gtk_widget_show (scrolledwindow);
159 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
160 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
161
162 gtk_container_add (GTK_CONTAINER (scrolledwindow),
163 app->library_grid = create_treeview(top, "treeview_library", library_columns));
164
165 return scrolledwindow;
166 }
167
168 static GtkWidget* pane_library_buttons(GtkWidget* top, omnplay_instance_t* app)
169 {
170 GtkWidget* hbox;
171
172 hbox = gtk_hbox_new (FALSE, 0);
173 gtk_widget_show (hbox);
174
175 /* playlist modify buttons */
176 gtk_box_pack_start (GTK_BOX (hbox),
177 ui_create_button(top, app, BUTTON_LIBRARY_ADD),
178 FALSE, FALSE, 0);
179 gtk_box_pack_start (GTK_BOX (hbox),
180 ui_create_button(top, app, BUTTON_LIBRARY_REFRESH),
181 FALSE, FALSE, 0);
182
183 /* spacer */
184 gtk_box_pack_start (GTK_BOX (hbox),
185 create_label(top, NULL, NULL, GTK_JUSTIFY_CENTER),
186 TRUE, TRUE, 0);
187
188 return hbox;
189 }
190
191 static GtkWidget* pane_library(GtkWidget* top, omnplay_instance_t* app)
192 {
193 GtkWidget* vbox;
194
195 vbox = gtk_vbox_new (FALSE, 0);
196 gtk_widget_show (vbox);
197 gtk_widget_set_size_request(vbox, 300, -1);
198
199 /* add buttons box */
200 gtk_box_pack_start (GTK_BOX (vbox),
201 pane_library_buttons(top, app),
202 FALSE, FALSE, 0);
203
204 /* add buttons box */
205 gtk_box_pack_start (GTK_BOX (vbox),
206 pane_library_grid(top, app),
207 TRUE, TRUE, 0);
208
209 return vbox;
210 }
211
212 static GtkWidget* create_channel_status(GtkWidget* top, omnplay_instance_t* app, int idx)
213 {
214 GtkWidget* vbox;
215 GtkWidget* hbox;
216 GtkWidget* frame;
217 omnplay_player_t* player;
218
219 player = &app->players.item[idx];
220
221 frame = gtk_frame_new(player->name);
222 gtk_widget_show(frame);
223
224 vbox = gtk_vbox_new(FALSE, 0);
225 gtk_container_add(GTK_CONTAINER(frame), vbox);
226 gtk_widget_show(vbox);
227
228 /* status label */
229 gtk_box_pack_start(GTK_BOX (vbox),
230 player->label_status = create_label(top, "OFFLINE", NULL, GTK_JUSTIFY_LEFT),
231 FALSE, FALSE, 0);
232
233 /* spacel label */
234 gtk_box_pack_start(GTK_BOX (vbox),
235 create_label(top, " ", NULL, GTK_JUSTIFY_CENTER),
236 FALSE, FALSE, 0);
237
238 /* clip label */
239 gtk_box_pack_start (GTK_BOX (vbox),
240 player->label_clip = create_label(top, "U0002323", NULL, GTK_JUSTIFY_LEFT),
241 FALSE, FALSE, 0);
242
243 /* block state/current timecode */
244 gtk_box_pack_start(GTK_BOX (vbox),
245 hbox = gtk_hbox_new(TRUE, 0),
246 FALSE, FALSE, 0);
247 gtk_widget_show(hbox);
248
249 {
250 /* clip state */
251 gtk_box_pack_start(GTK_BOX (hbox),
252 player->label_state = create_label(top, "PLAYING", NULL, GTK_JUSTIFY_LEFT),
253 TRUE, TRUE, 0);
254
255 /* current timecode */
256 gtk_box_pack_start(GTK_BOX (hbox),
257 player->label_tc_cur = create_label(top, "00:00:00:00", NULL, GTK_JUSTIFY_LEFT),
258 TRUE, TRUE, 0);
259 };
260
261 /* block remain label/remain timecode */
262 gtk_box_pack_start(GTK_BOX (vbox),
263 hbox = gtk_hbox_new(TRUE, 0),
264 FALSE, FALSE, 0);
265 gtk_widget_show (hbox);
266
267 {
268 /* label */
269 gtk_box_pack_start(GTK_BOX (hbox),
270 create_label(top, "remain:", NULL, GTK_JUSTIFY_LEFT),
271 TRUE, TRUE, 0);
272
273 /* remaining timecode */
274 gtk_box_pack_start(GTK_BOX (hbox),
275 player->label_tc_rem = create_label(top, "00:00:00:00", NULL, GTK_JUSTIFY_LEFT),
276 TRUE, TRUE, 0);
277 };
278
279 return frame;
280 }
281
282 static GtkWidget* pane_operate_status(GtkWidget* top, omnplay_instance_t* app)
283 {
284 int i;
285 GtkWidget* vbox;
286
287 vbox = gtk_vbox_new (FALSE, 0);
288 gtk_widget_show (vbox);
289 gtk_widget_set_size_request(vbox, 250, -1);
290
291 for(i = 0; i < app->players.count; i++)
292 {
293 gtk_box_pack_start (GTK_BOX (vbox),
294 create_channel_status(top, app, i),
295 FALSE, FALSE, 0);
296
297 /* spacer */
298 gtk_box_pack_start (GTK_BOX (vbox),
299 create_label(top, NULL, NULL, GTK_JUSTIFY_CENTER),
300 FALSE, FALSE, 0);
301 }
302
303 /* spacer */
304 gtk_box_pack_start (GTK_BOX (vbox),
305 create_label(top, NULL, NULL, GTK_JUSTIFY_CENTER),
306 TRUE, TRUE, 0);
307
308 return vbox;
309 }
310
311 static GtkWidget* pane_operate_buttons_playlist(GtkWidget* top, omnplay_instance_t* app)
312 {
313 GtkWidget* hbox;
314
315 hbox = gtk_hbox_new (FALSE, 0);
316 gtk_widget_show (hbox);
317
318 /* playlist load/save buttons */
319 gtk_box_pack_start (GTK_BOX (hbox),
320 ui_create_button(top, app, BUTTON_PLAYLIST_LOAD),
321 FALSE, FALSE, 0);
322 gtk_box_pack_start (GTK_BOX (hbox),
323 ui_create_button(top, app, BUTTON_PLAYLIST_SAVE),
324 FALSE, FALSE, 0);
325
326 /* spacer */
327 gtk_box_pack_start (GTK_BOX (hbox),
328 create_label(top, " ", NULL, GTK_JUSTIFY_CENTER),
329 FALSE, FALSE, 0);
330
331 /* playlist modify buttons */
332 gtk_box_pack_start (GTK_BOX (hbox),
333 ui_create_button(top, app, BUTTON_PLAYLIST_ITEM_ADD),
334 FALSE, FALSE, 0);
335 gtk_box_pack_start (GTK_BOX (hbox),
336 ui_create_button(top, app, BUTTON_PLAYLIST_ITEM_EDIT),
337 FALSE, FALSE, 0);
338 gtk_box_pack_start (GTK_BOX (hbox),
339 ui_create_button(top, app, BUTTON_PLAYLIST_ITEM_DEL),
340 FALSE, FALSE, 0);
341
342 /* spacer */
343 gtk_box_pack_start (GTK_BOX (hbox),
344 create_label(top, " ", NULL, GTK_JUSTIFY_CENTER),
345 FALSE, FALSE, 0);
346
347 /* playlist block buttons */
348 gtk_box_pack_start (GTK_BOX (hbox),
349 ui_create_button(top, app, BUTTON_PLAYLIST_BLOCK_SINGLE),
350 FALSE, FALSE, 0);
351 gtk_box_pack_start (GTK_BOX (hbox),
352 ui_create_button(top, app, BUTTON_PLAYLIST_BLOCK_LOOP),
353 FALSE, FALSE, 0);
354
355 /* spacer */
356 gtk_box_pack_start (GTK_BOX (hbox),
357 create_label(top, " ", NULL, GTK_JUSTIFY_CENTER),
358 FALSE, FALSE, 0);
359
360 /* playlist move items buttons */
361 gtk_box_pack_start (GTK_BOX (hbox),
362 ui_create_button(top, app, BUTTON_PLAYLIST_ITEM_UP),
363 FALSE, FALSE, 0);
364 gtk_box_pack_start (GTK_BOX (hbox),
365 ui_create_button(top, app, BUTTON_PLAYLIST_ITEM_DOWN),
366 FALSE, FALSE, 0);
367
368 return hbox;
369 }
370
371 static GtkWidget* pane_operate_grid(GtkWidget* top, omnplay_instance_t* app)
372 {
373 GtkWidget *scrolledwindow;
374
375 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
376 gtk_widget_show (scrolledwindow);
377 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
378 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
379
380 gtk_container_add (GTK_CONTAINER (scrolledwindow),
381 app->playlist_grid = create_treeview(top, "treeview_playlist", playlist_columns));
382
383 return scrolledwindow;
384 }
385
386 static GtkWidget* pane_operate_buttons_operate(GtkWidget* top, omnplay_instance_t* app)
387 {
388 GtkWidget* hbox;
389
390 hbox = gtk_hbox_new (FALSE, 0);
391 gtk_widget_show (hbox);
392
393 /* spacer */
394 gtk_box_pack_start (GTK_BOX (hbox),
395 create_label(top, NULL, NULL, GTK_JUSTIFY_CENTER),
396 TRUE, TRUE, 0);
397
398 /* playlist modify buttons */
399 gtk_box_pack_start (GTK_BOX (hbox),
400 ui_create_button(top, app, BUTTON_PLAYER_CUE),
401 FALSE, FALSE, 0);
402 gtk_box_pack_start (GTK_BOX (hbox),
403 ui_create_button(top, app, BUTTON_PLAYER_PLAY),
404 FALSE, FALSE, 0);
405 gtk_box_pack_start (GTK_BOX (hbox),
406 ui_create_button(top, app, BUTTON_PLAYER_PAUSE),
407 FALSE, FALSE, 0);
408 gtk_box_pack_start (GTK_BOX (hbox),
409 ui_create_button(top, app, BUTTON_PLAYER_STOP),
410 FALSE, FALSE, 0);
411
412 /* spacer */
413 gtk_box_pack_start (GTK_BOX (hbox),
414 create_label(top, NULL, NULL, GTK_JUSTIFY_CENTER),
415 TRUE, TRUE, 0);
416
417 return hbox;
418 }
419
420 static GtkWidget* pane_operate_operate(GtkWidget* top, omnplay_instance_t* app)
421 {
422 GtkWidget* vbox;
423
424 vbox = gtk_vbox_new (FALSE, 0);
425 gtk_widget_show (vbox);
426
427 /* add buttons box #1 */
428 gtk_box_pack_start (GTK_BOX (vbox),
429 pane_operate_buttons_playlist(top, app),
430 FALSE, FALSE, 0);
431
432 /* add buttons box */
433 gtk_box_pack_start (GTK_BOX (vbox),
434 pane_operate_grid(top, app),
435 TRUE, TRUE, 0);
436
437 /* add buttons box #1 */
438 gtk_box_pack_start (GTK_BOX (vbox),
439 pane_operate_buttons_operate(top, app),
440 FALSE, FALSE, 0);
441
442 return vbox;
443
444 }
445
446 static GtkWidget* pane_operate(GtkWidget* top, omnplay_instance_t* app)
447 {
448 GtkWidget* hbox;
449
450 hbox = gtk_hbox_new (FALSE, 0);
451 gtk_widget_show (hbox);
452
453 /* add buttons box */
454 gtk_box_pack_start (GTK_BOX (hbox),
455 pane_operate_status(top, app),
456 FALSE, FALSE, 0);
457
458 /* add buttons box */
459 gtk_box_pack_start (GTK_BOX (hbox),
460 pane_operate_operate(top, app),
461 TRUE, TRUE, 0);
462
463 return hbox;
464
465 };
466
467 static GtkWidget* pane_top(GtkWidget* top, omnplay_instance_t* app)
468 {
469 GtkWidget* pane;
470
471 pane = gtk_hpaned_new ();
472 gtk_widget_show (pane);
473
474 gtk_paned_set_position (GTK_PANED (pane), 800);
475
476 gtk_paned_pack1 (GTK_PANED (pane),
477 pane_operate(top, app),
478 TRUE, FALSE);
479
480 gtk_paned_pack2 (GTK_PANED (pane),
481 pane_library(top, app),
482 FALSE, FALSE);
483
484 return pane;
485 }
486
487 GtkWidget* ui_omnplay (omnplay_instance_t* app)
488 {
489 GtkWidget *wnd;
490
491 wnd = gtk_window_new (GTK_WINDOW_TOPLEVEL);
492 GLADE_HOOKUP_OBJECT_NO_REF (wnd, wnd, "omnplay_window");
493
494 gtk_window_set_title (GTK_WINDOW (wnd), _("Omneon Player"));
495 gtk_window_set_default_size (GTK_WINDOW (wnd), 1024, 768);
496
497 gtk_container_add (GTK_CONTAINER (wnd),
498 pane_top(wnd, app));
499
500 return wnd;
501 }