]> git.sur5r.net Git - glabels/blob - src/media-select.c
Initial port to GTK3.
[glabels] / src / media-select.c
1 /*
2  *  media-select.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels 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 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "media-select.h"
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27 #include <string.h>
28
29 #include <libglabels.h>
30 #include "mini-preview-pixbuf-cache.h"
31 #include "prefs.h"
32 #include "message-bar.h"
33 #include "template-history.h"
34 #include "template-designer.h"
35 #include "str-util.h"
36 #include "combo-util.h"
37 #include "builder-util.h"
38 #include "color.h"
39 #include "marshal.h"
40
41 #include "debug.h"
42
43
44 #define HISTORY_SIZE 5
45
46 /*===========================================*/
47 /* Private types                             */
48 /*===========================================*/
49
50 enum {
51         NAME_COLUMN,
52         PREVIEW_COLUMN,
53         PREVIEW_COLUMN_STOCK,
54         PREVIEW_COLUMN_STOCK_SIZE,
55         DESCRIPTION_COLUMN,
56         N_COLUMNS
57 };
58
59 struct _glMediaSelectPrivate {
60
61         gulong        db_notify_id;
62
63         GtkBuilder   *builder;
64
65         GtkWidget    *notebook;
66         guint         current_page_num;
67
68         gint          recent_page_num;
69         GtkWidget    *recent_tab_vbox;
70         GtkWidget    *recent_info_vbox;
71         GtkWidget    *recent_info_bar;
72         GtkWidget    *recent_treeview;
73         GtkListStore *recent_store;
74
75         gint          search_all_page_num;
76         GtkWidget    *search_all_tab_vbox;
77         GtkWidget    *search_all_info_vbox;
78         GtkWidget    *search_all_info_bar;
79         GtkWidget    *brand_combo;
80         GtkWidget    *page_size_combo;
81         GtkWidget    *category_combo;
82         GtkWidget    *search_all_treeview;
83         GtkListStore *search_all_store;
84
85         gint          custom_page_num;
86         GtkWidget    *custom_tab_vbox;
87         GtkWidget    *custom_info_vbox;
88         GtkWidget    *custom_info_bar;
89         GtkWidget    *custom_treeview;
90         GtkListStore *custom_store;
91         GtkWidget    *custom_add_button;
92         GtkWidget    *custom_edit_button;
93         GtkWidget    *custom_delete_button;
94
95         /* Prevent recursion */
96         gboolean    stop_signals;
97 };
98
99 enum {
100         CHANGED,
101         LAST_SIGNAL
102 };
103
104
105 /*===========================================*/
106 /* Private globals                           */
107 /*===========================================*/
108
109 static gint signals[LAST_SIGNAL] = { 0 };
110
111
112 /*===========================================*/
113 /* Local function prototypes                 */
114 /*===========================================*/
115
116 static void   gl_media_select_finalize   (GObject                *object);
117
118 static void   gl_media_select_construct  (glMediaSelect          *this);
119
120 static void   filter_changed_cb          (glMediaSelect          *this);
121
122 static void   selection_changed_cb       (GtkTreeSelection       *selection,
123                                           gpointer                user_data);
124
125 static void   custom_add_clicked_cb      (GtkButton              *button,
126                                           gpointer                user_data);
127
128 static void   custom_edit_clicked_cb     (GtkButton              *button,
129                                           gpointer                user_data);
130
131 static void   custom_delete_clicked_cb   (GtkButton              *button,
132                                           gpointer                user_data);
133
134 static void   page_changed_cb            (GtkNotebook            *notebook,
135                                           GtkWidget              *page,
136                                           guint                   page_num,
137                                           gpointer                user_data);
138
139 static void   db_changed_cb              (glMediaSelect          *this);
140
141 static void   load_recent_list           (glMediaSelect          *this,
142                                           GtkListStore           *store,
143                                           GtkTreeSelection       *selection,
144                                           GList                  *list);
145
146 static void   load_custom_list          (glMediaSelect          *this,
147                                           GtkListStore           *store,
148                                           GtkTreeSelection       *selection,
149                                           GList                  *list);
150
151 static void   load_search_all_list       (glMediaSelect          *this,
152                                           GtkListStore           *store,
153                                           GtkTreeSelection       *selection,
154                                           GList                  *list);
155
156
157 /****************************************************************************/
158 /* Boilerplate Object stuff.                                                */
159 /****************************************************************************/
160 G_DEFINE_TYPE (glMediaSelect, gl_media_select, GTK_TYPE_VBOX);
161
162
163 static void
164 gl_media_select_class_init (glMediaSelectClass *class)
165 {
166         GObjectClass *object_class = G_OBJECT_CLASS (class);
167
168         gl_debug (DEBUG_MEDIA_SELECT, "START");
169
170         gl_media_select_parent_class = g_type_class_peek_parent (class);
171
172         object_class->finalize = gl_media_select_finalize;
173
174         signals[CHANGED] =
175             g_signal_new ("changed",
176                           G_OBJECT_CLASS_TYPE(object_class),
177                           G_SIGNAL_RUN_LAST,
178                           G_STRUCT_OFFSET (glMediaSelectClass, changed),
179                           NULL, NULL,
180                           gl_marshal_VOID__VOID,
181                           G_TYPE_NONE, 0);
182
183         gl_debug (DEBUG_MEDIA_SELECT, "END");
184 }
185
186
187 static void
188 gl_media_select_init (glMediaSelect *this)
189 {
190         gl_debug (DEBUG_MEDIA_SELECT, "START");
191
192         this->priv = g_new0 (glMediaSelectPrivate, 1);
193
194         gl_debug (DEBUG_MEDIA_SELECT, "END");
195 }
196
197
198 static void
199 gl_media_select_finalize (GObject *object)
200 {
201         glMediaSelect *this = GL_MEDIA_SELECT (object);
202
203         gl_debug (DEBUG_MEDIA_SELECT, "START");
204
205         g_return_if_fail (object != NULL);
206         g_return_if_fail (GL_IS_MEDIA_SELECT (object));
207
208         if (this->priv->db_notify_id)
209         {
210                 lgl_db_notify_remove (this->priv->db_notify_id);
211         }
212
213         if (this->priv->builder)
214         {
215                 g_object_unref (this->priv->builder);
216         }
217         g_object_unref (this->priv->recent_store);
218         g_object_unref (this->priv->search_all_store);
219         g_free (this->priv);
220
221         G_OBJECT_CLASS (gl_media_select_parent_class)->finalize (object);
222
223         gl_debug (DEBUG_MEDIA_SELECT, "END");
224 }
225
226
227 GtkWidget *
228 gl_media_select_new (void)
229 {
230         glMediaSelect *this;
231
232         gl_debug (DEBUG_MEDIA_SELECT, "START");
233
234         this = g_object_new (gl_media_select_get_type (), NULL);
235
236         gl_media_select_construct (this);
237
238         gl_debug (DEBUG_MEDIA_SELECT, "END");
239
240         return GTK_WIDGET (this);
241 }
242
243
244 /*--------------------------------------------------------------------------*/
245 /* PRIVATE.  Construct composite widget.                                    */
246 /*--------------------------------------------------------------------------*/
247 static void
248 gl_media_select_construct (glMediaSelect *this)
249 {
250         gchar             *builder_filename;
251         GtkBuilder        *builder;
252         static gchar      *object_ids[] = { "media_select_hbox",
253                                             "custom_buttons_sizegroup",
254                                             NULL };
255         GError            *error = NULL;
256         GtkWidget         *hbox;
257         GList             *recent_list = NULL;
258         GList             *brands = NULL;
259         GList             *page_sizes = NULL;
260         GList             *categories = NULL;
261         GList             *search_all_names = NULL;
262         const gchar       *page_size_id;
263         gchar             *page_size_name;
264         GList             *custom_list = NULL;
265         GtkCellRenderer   *renderer;
266         GtkTreeViewColumn *column;
267         GtkTreeSelection  *recent_selection;
268         GtkTreeSelection  *search_all_selection;
269         GtkTreeSelection  *custom_selection;
270
271         gl_debug (DEBUG_MEDIA_SELECT, "START");
272
273         g_return_if_fail (GL_IS_MEDIA_SELECT (this));
274         g_return_if_fail (this->priv != NULL);
275
276         builder = gtk_builder_new ();
277         builder_filename = g_build_filename (GLABELS_DATA_DIR, "ui", "media-select.ui", NULL);
278         gtk_builder_add_objects_from_file (builder, builder_filename, object_ids, &error);
279         g_free (builder_filename);
280         if (error) {
281                 g_critical ("%s\n\ngLabels may not be installed correctly!", error->message);
282                 g_error_free (error);
283                 return;
284         }
285
286         gl_builder_util_get_widgets (builder,
287                                      "media_select_hbox",      &hbox,
288                                      "notebook",               &this->priv->notebook,
289                                      "recent_tab_vbox",        &this->priv->recent_tab_vbox,
290                                      "recent_info_vbox",       &this->priv->recent_info_vbox,
291                                      "recent_treeview",        &this->priv->recent_treeview,
292                                      "search_all_tab_vbox",    &this->priv->search_all_tab_vbox,
293                                      "brand_combo",            &this->priv->brand_combo,
294                                      "page_size_combo",        &this->priv->page_size_combo,
295                                      "category_combo",         &this->priv->category_combo,
296                                      "search_all_info_vbox",   &this->priv->search_all_info_vbox,
297                                      "search_all_treeview",    &this->priv->search_all_treeview,
298                                      "custom_tab_vbox",        &this->priv->custom_tab_vbox,
299                                      "custom_info_vbox",       &this->priv->custom_info_vbox,
300                                      "custom_treeview",        &this->priv->custom_treeview,
301                                      "custom_add_button",      &this->priv->custom_add_button,
302                                      "custom_edit_button",     &this->priv->custom_edit_button,
303                                      "custom_delete_button",   &this->priv->custom_delete_button,
304                                      NULL);
305
306         gtk_container_add (GTK_CONTAINER (this), hbox);
307         this->priv->builder = builder;
308
309         this->priv->recent_page_num =
310                 gtk_notebook_page_num (GTK_NOTEBOOK (this->priv->notebook),
311                                        this->priv->recent_tab_vbox);
312         this->priv->search_all_page_num =
313                 gtk_notebook_page_num (GTK_NOTEBOOK (this->priv->notebook),
314                                        this->priv->search_all_tab_vbox);
315         this->priv->custom_page_num =
316                 gtk_notebook_page_num (GTK_NOTEBOOK (this->priv->notebook),
317                                        this->priv->custom_tab_vbox);
318
319         gtk_widget_show_all (GTK_WIDGET (this));
320
321         /* Recent templates treeview */
322         this->priv->recent_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
323         gtk_tree_view_set_model (GTK_TREE_VIEW (this->priv->recent_treeview),
324                                  GTK_TREE_MODEL (this->priv->recent_store));
325         renderer = gtk_cell_renderer_pixbuf_new ();
326         column = gtk_tree_view_column_new_with_attributes ("", renderer,
327                                                            "pixbuf", PREVIEW_COLUMN,
328                                                            "stock-id", PREVIEW_COLUMN_STOCK,
329                                                            "stock-size", PREVIEW_COLUMN_STOCK_SIZE,
330                                                            NULL);
331         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
332         gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->recent_treeview), column);
333         renderer = gtk_cell_renderer_text_new ();
334         column = gtk_tree_view_column_new_with_attributes ("", renderer,
335                                                            "markup", DESCRIPTION_COLUMN,
336                                                            NULL);
337         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
338         gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->recent_treeview), column);
339         recent_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->recent_treeview));
340         recent_list = gl_template_history_model_get_name_list (gl_template_history);
341         load_recent_list (this, this->priv->recent_store, recent_selection, recent_list);
342
343         page_size_id = gl_prefs_model_get_default_page_size (gl_prefs);
344         page_size_name = lgl_db_lookup_paper_name_from_id (page_size_id);
345
346         /* Brand selection control */
347         gl_combo_util_add_text_model (GTK_COMBO_BOX (this->priv->brand_combo));
348         brands = lgl_db_get_brand_list (NULL, NULL);
349         brands = g_list_prepend (brands, g_strdup (C_("Brand", "Any")));
350         gl_combo_util_set_strings (GTK_COMBO_BOX (this->priv->brand_combo), brands);
351         lgl_db_free_brand_list (brands);
352         gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->brand_combo),
353                                        C_("Brand", "Any"));
354
355         /* Page size selection control */
356         gl_combo_util_add_text_model (GTK_COMBO_BOX (this->priv->page_size_combo));
357         page_sizes = lgl_db_get_paper_name_list ();
358         page_sizes = g_list_prepend (page_sizes, g_strdup (C_("Page size", "Any")));
359         gl_combo_util_set_strings (GTK_COMBO_BOX (this->priv->page_size_combo), page_sizes);
360         lgl_db_free_paper_name_list (page_sizes);
361         gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->page_size_combo),
362                                        page_size_name);
363
364         /* Category selection control */
365         gl_combo_util_add_text_model (GTK_COMBO_BOX (this->priv->category_combo));
366         categories = lgl_db_get_category_name_list ();
367         categories = g_list_prepend (categories, g_strdup (C_("Category", "Any")));
368         gl_combo_util_set_strings (GTK_COMBO_BOX (this->priv->category_combo), categories);
369         gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->category_combo),
370                                        C_("Category", "Any"));
371         lgl_db_free_category_name_list (categories);
372
373         /* Search all treeview */
374         this->priv->search_all_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
375         gtk_tree_view_set_model (GTK_TREE_VIEW (this->priv->search_all_treeview),
376                                  GTK_TREE_MODEL (this->priv->search_all_store));
377         renderer = gtk_cell_renderer_pixbuf_new ();
378         column = gtk_tree_view_column_new_with_attributes ("", renderer,
379                                                            "pixbuf", PREVIEW_COLUMN,
380                                                            "stock-id", PREVIEW_COLUMN_STOCK,
381                                                            "stock-size", PREVIEW_COLUMN_STOCK_SIZE,
382                                                            NULL);
383         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
384         gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->search_all_treeview), column);
385         renderer = gtk_cell_renderer_text_new ();
386         column = gtk_tree_view_column_new_with_attributes ("", renderer,
387                                                            "markup", DESCRIPTION_COLUMN,
388                                                            NULL);
389         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
390         gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->search_all_treeview), column);
391         search_all_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview));
392         search_all_names = lgl_db_get_template_name_list_all (NULL, page_size_id, NULL);
393         load_search_all_list (this, this->priv->search_all_store, search_all_selection, search_all_names);
394         lgl_db_free_template_name_list (search_all_names);
395
396         /* Custom templates treeview */
397         this->priv->custom_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING);
398         gtk_tree_view_set_model (GTK_TREE_VIEW (this->priv->custom_treeview),
399                                  GTK_TREE_MODEL (this->priv->custom_store));
400         renderer = gtk_cell_renderer_pixbuf_new ();
401         column = gtk_tree_view_column_new_with_attributes ("", renderer,
402                                                            "pixbuf", PREVIEW_COLUMN,
403                                                            "stock-id", PREVIEW_COLUMN_STOCK,
404                                                            "stock-size", PREVIEW_COLUMN_STOCK_SIZE,
405                                                            NULL);
406         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
407         gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->custom_treeview), column);
408         renderer = gtk_cell_renderer_text_new ();
409         column = gtk_tree_view_column_new_with_attributes ("", renderer,
410                                                            "markup", DESCRIPTION_COLUMN,
411                                                            NULL);
412         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
413         gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->custom_treeview), column);
414         custom_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->custom_treeview));
415         custom_list = lgl_db_get_template_name_list_all (NULL, NULL, "user-defined");
416         load_custom_list (this, this->priv->custom_store, custom_selection, custom_list);
417         lgl_db_free_template_name_list (custom_list);
418
419         page_size_id = gl_prefs_model_get_default_page_size (gl_prefs);
420         page_size_name = lgl_db_lookup_paper_name_from_id (page_size_id);
421
422         /* Connect signals to controls */
423         g_signal_connect_swapped (G_OBJECT (this->priv->brand_combo), "changed",
424                                   G_CALLBACK (filter_changed_cb),
425                                   this);
426         g_signal_connect_swapped (G_OBJECT (this->priv->page_size_combo), "changed",
427                                   G_CALLBACK (filter_changed_cb),
428                                   this);
429         g_signal_connect_swapped (G_OBJECT (this->priv->category_combo), "changed",
430                                   G_CALLBACK (filter_changed_cb),
431                                   this);
432         g_signal_connect (G_OBJECT (recent_selection), "changed",
433                           G_CALLBACK (selection_changed_cb),
434                           this);
435         g_signal_connect (G_OBJECT (search_all_selection), "changed",
436                           G_CALLBACK (selection_changed_cb),
437                           this);
438         g_signal_connect (G_OBJECT (custom_selection), "changed",
439                           G_CALLBACK (selection_changed_cb),
440                           this);
441         g_signal_connect (G_OBJECT (this->priv->custom_add_button), "clicked",
442                           G_CALLBACK (custom_add_clicked_cb),
443                           this);
444         g_signal_connect (G_OBJECT (this->priv->custom_edit_button), "clicked",
445                           G_CALLBACK (custom_edit_clicked_cb),
446                           this);
447         g_signal_connect (G_OBJECT (this->priv->custom_delete_button), "clicked",
448                           G_CALLBACK (custom_delete_clicked_cb),
449                           this);
450         g_signal_connect (G_OBJECT (this->priv->notebook), "switch-page",
451                           G_CALLBACK (page_changed_cb),
452                           this);
453
454         g_free (page_size_name);
455
456         if ( recent_list )
457         {
458                 gtk_notebook_set_current_page (GTK_NOTEBOOK (this->priv->notebook),
459                                                this->priv->recent_page_num);
460         }
461         else
462         {
463                 gtk_notebook_set_current_page (GTK_NOTEBOOK (this->priv->notebook),
464                                                this->priv->search_all_page_num);
465         }
466         gl_template_history_model_free_name_list (recent_list);
467
468         this->priv->db_notify_id = lgl_db_notify_add ((lglDbNotifyFunc)db_changed_cb, this);
469
470         gl_debug (DEBUG_MEDIA_SELECT, "END");
471 }
472
473
474 /*--------------------------------------------------------------------------*/
475 /* PRIVATE.  modify widget due to change in selection                       */
476 /*--------------------------------------------------------------------------*/
477 static void
478 filter_changed_cb (glMediaSelect *this)
479 {
480         gchar             *brand;
481         gchar             *page_size_name, *page_size_id;
482         gchar             *category_name, *category_id;
483         GList             *search_all_names;
484         GtkTreeSelection  *selection;
485
486         gl_debug (DEBUG_MEDIA_SELECT, "START");
487
488
489         this->priv->stop_signals = TRUE;
490
491         /* Update template selections for new filter settings */
492         brand = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->brand_combo));
493         page_size_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->page_size_combo));
494         category_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->category_combo));
495         if ( brand && strlen(brand) &&
496              page_size_name && strlen(page_size_name) &&
497              category_name && strlen(category_name) )
498         {
499                 gl_debug (DEBUG_MEDIA_SELECT, "brand = \"%s\"", brand);
500                 gl_debug (DEBUG_MEDIA_SELECT, "page_size_name = \"%s\"", page_size_name);
501                 gl_debug (DEBUG_MEDIA_SELECT, "category_name = \"%s\"", category_name);
502                 if (!g_utf8_collate (brand, C_("Brand", "Any")))
503                 {
504                         g_free (brand);
505                         brand = NULL;
506                 }
507                 page_size_id = lgl_db_lookup_paper_id_from_name (page_size_name);
508                 category_id = lgl_db_lookup_category_id_from_name (category_name);
509                 gl_debug (DEBUG_MEDIA_SELECT, "page_size_id = \"%s\"", page_size_id);
510                 gl_debug (DEBUG_MEDIA_SELECT, "category_id = \"%s\"", category_id);
511                 search_all_names = lgl_db_get_template_name_list_all (brand, page_size_id, category_id);
512                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview));
513                 load_search_all_list (this, this->priv->search_all_store, selection, search_all_names);
514                 lgl_db_free_template_name_list (search_all_names);
515                 g_free (page_size_id);
516                 g_free (category_id);
517
518                 /* Emit our "changed" signal */
519                 g_signal_emit (G_OBJECT (this), signals[CHANGED], 0);
520         }
521         g_free (brand);
522         g_free (page_size_name);
523         g_free (category_name);
524
525
526         this->priv->stop_signals = FALSE;
527
528         gl_debug (DEBUG_MEDIA_SELECT, "END");
529 }
530
531
532 /*--------------------------------------------------------------------------*/
533 /* PRIVATE.  modify widget due to change in selection                       */
534 /*--------------------------------------------------------------------------*/
535 static void
536 selection_changed_cb (GtkTreeSelection       *selection,
537                       gpointer                user_data)
538 {
539         glMediaSelect     *this = GL_MEDIA_SELECT (user_data);
540         GtkTreeSelection  *custom_selection;
541
542         if (this->priv->stop_signals) return;
543
544         gl_debug (DEBUG_MEDIA_SELECT, "START");
545
546         custom_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->custom_treeview));
547         gtk_widget_set_sensitive (GTK_WIDGET (this->priv->custom_edit_button),
548                                   gtk_tree_selection_get_mode (custom_selection) != GTK_SELECTION_NONE );
549         gtk_widget_set_sensitive (GTK_WIDGET (this->priv->custom_delete_button),
550                                   gtk_tree_selection_get_mode (custom_selection) != GTK_SELECTION_NONE );
551
552         /* Emit our "changed" signal */
553         g_signal_emit (G_OBJECT (user_data), signals[CHANGED], 0);
554
555         gl_debug (DEBUG_MEDIA_SELECT, "END");
556 }
557
558
559 /*--------------------------------------------------------------------------*/
560 /* PRIVATE.  Custom add button clicked callback.                            */
561 /*--------------------------------------------------------------------------*/
562 static void
563 custom_add_clicked_cb (GtkButton  *button,
564                        gpointer    user_data)
565 {
566         glMediaSelect *this = GL_MEDIA_SELECT (user_data);
567         GtkWidget     *window;
568         GtkWidget     *dialog;
569
570         window = gtk_widget_get_toplevel (GTK_WIDGET (this));
571         
572         dialog = gl_template_designer_new (GTK_WINDOW (window));
573
574         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
575         gtk_widget_show (dialog);
576 }
577
578
579 /*--------------------------------------------------------------------------*/
580 /* PRIVATE.  Custom edit button clicked callback.                           */
581 /*--------------------------------------------------------------------------*/
582 static void
583 custom_edit_clicked_cb (GtkButton  *button,
584                         gpointer    user_data)
585 {
586         glMediaSelect     *this = GL_MEDIA_SELECT (user_data);
587         GtkTreeSelection  *selection;
588         GtkTreeIter        iter;
589         GtkTreeModel      *model;
590         gchar             *name;
591         GtkWidget         *window;
592         GtkWidget         *dialog;
593
594         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->custom_treeview));
595
596         if (!gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
597         {
598                 gtk_tree_selection_get_selected (selection, &model, &iter);
599                 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1);
600
601                 window = gtk_widget_get_toplevel (GTK_WIDGET (this));
602
603                 dialog = gl_template_designer_new (GTK_WINDOW (window));
604                 gl_template_designer_set_from_name (GL_TEMPLATE_DESIGNER (dialog), name);
605
606                 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
607                 gtk_widget_show (dialog);
608
609                 g_free (name);
610         }
611 }
612
613
614 /*--------------------------------------------------------------------------*/
615 /* PRIVATE.  Custom delete button clicked callback.                         */
616 /*--------------------------------------------------------------------------*/
617 static void
618 custom_delete_clicked_cb (GtkButton  *button,
619                           gpointer    user_data)
620 {
621         glMediaSelect     *this = GL_MEDIA_SELECT (user_data);
622         GtkTreeSelection  *selection;
623         GtkTreeIter        iter;
624         GtkTreeModel      *model;        
625         gchar             *name;
626
627         this->priv->stop_signals = TRUE;
628
629         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->custom_treeview));
630
631         if (!gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
632         {
633                 gtk_tree_selection_get_selected (selection, &model, &iter);
634                 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1);
635
636                 lgl_db_delete_template_by_name (name);
637                 gl_mini_preview_pixbuf_cache_delete_by_name (name);
638
639                 g_free (name);
640         }
641
642         this->priv->stop_signals = FALSE;
643 }
644
645
646 /*--------------------------------------------------------------------------*/
647 /* PRIVATE.  modify widget due to change in selection                       */
648 /*--------------------------------------------------------------------------*/
649 static void
650 page_changed_cb (GtkNotebook            *notebook,
651                  GtkWidget              *page,
652                  guint                   page_num,
653                  gpointer                user_data)
654 {
655         glMediaSelect *this = GL_MEDIA_SELECT (user_data);
656
657         if (this->priv->stop_signals) return;
658
659         gl_debug (DEBUG_MEDIA_SELECT, "START");
660
661         /*
662          * Store new current page, because this signal is emitted before the actual page change.
663          */
664         this->priv->current_page_num = page_num;
665
666         /* Emit our "changed" signal */
667         g_signal_emit (G_OBJECT (user_data), signals[CHANGED], 0);
668
669         gl_debug (DEBUG_MEDIA_SELECT, "END");
670 }
671
672
673 /*--------------------------------------------------------------------------*/
674 /* PRIVATE.  DB changed notification callback.                              */
675 /*--------------------------------------------------------------------------*/
676 static void
677 db_changed_cb (glMediaSelect *this)
678 {
679         gchar             *brand;
680         gchar             *page_size_name, *page_size_id;
681         gchar             *category_name, *category_id;
682         GtkTreeSelection  *selection;
683         GList             *list;
684
685         this->priv->stop_signals = TRUE;
686
687         /* Update recent page. */
688         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->recent_treeview));
689         list = gl_template_history_model_get_name_list (gl_template_history);
690         load_recent_list (this, this->priv->recent_store, selection, list);
691         lgl_db_free_template_name_list (list);
692
693         /* Update search all page. */
694         brand = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->brand_combo));
695         page_size_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->page_size_combo));
696         category_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->category_combo));
697         if ( brand && strlen(brand) &&
698              page_size_name && strlen(page_size_name) &&
699              category_name && strlen(category_name) )
700         {
701                 if (!g_utf8_collate (brand, C_("Brand", "Any")))
702                 {
703                         g_free (brand);
704                         brand = NULL;
705                 }
706                 page_size_id = lgl_db_lookup_paper_id_from_name (page_size_name);
707                 category_id = lgl_db_lookup_category_id_from_name (category_name);
708                 list = lgl_db_get_template_name_list_all (brand, page_size_id, category_id);
709                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview));
710                 load_search_all_list (this, this->priv->search_all_store, selection, list);
711                 lgl_db_free_template_name_list (list);
712                 g_free (page_size_id);
713                 g_free (category_id);
714         }
715         g_free (brand);
716         g_free (page_size_name);
717         g_free (category_name);
718
719         /* Update custom page. */
720         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->custom_treeview));
721         list = lgl_db_get_template_name_list_all (NULL, NULL, "user-defined");
722         load_custom_list (this, this->priv->custom_store, selection, list);
723         lgl_db_free_template_name_list (list);
724
725         this->priv->stop_signals = FALSE;
726
727         /* Emit our "changed" signal */
728         g_signal_emit (G_OBJECT (this), signals[CHANGED], 0);
729
730         filter_changed_cb (this);
731 }
732
733
734 /****************************************************************************/
735 /* query selected label template name.                                      */
736 /****************************************************************************/
737 gchar *
738 gl_media_select_get_name (glMediaSelect *this)
739 {
740         gint               page_num;
741         GtkTreeSelection  *selection;
742         GtkTreeIter        iter;
743         GtkTreeModel      *model;        
744         gchar             *name;
745
746         gl_debug (DEBUG_MEDIA_SELECT, "START");
747
748         page_num = this->priv->current_page_num;
749         if (page_num == this->priv->recent_page_num)
750         {
751                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->recent_treeview));
752         }
753         else if (page_num == this->priv->search_all_page_num)
754         {
755                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview));
756         }
757         else if (page_num == this->priv->custom_page_num)
758         {
759                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->custom_treeview));
760         }
761         else
762         {
763                 g_print ("notebook page = %d\n", page_num);
764                 g_assert_not_reached ();
765         }
766
767         if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
768         {
769                 name = NULL;
770         }
771         else
772         {
773                 gtk_tree_selection_get_selected (selection, &model, &iter);
774                 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1);
775         }
776
777         gl_debug (DEBUG_MEDIA_SELECT, "END");
778         return name;
779 }
780
781
782 /****************************************************************************/
783 /* set selected label template name.                                        */
784 /****************************************************************************/
785 void
786 gl_media_select_set_name (glMediaSelect *this,
787                           gchar         *name)
788 {
789         GtkTreeSelection  *selection;
790         GtkTreeModel      *model;
791         GtkTreeIter        iter;
792         GtkTreePath       *path;
793         gchar             *name_i;
794         gboolean           flag;
795
796         gl_debug (DEBUG_MEDIA_SELECT, "START");
797
798         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview));
799         g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
800
801         model = GTK_TREE_MODEL (this->priv->search_all_store);
802
803         for ( flag = gtk_tree_model_get_iter_first (model, &iter);
804               flag;
805               flag = gtk_tree_model_iter_next(model, &iter) )
806         {
807                 gtk_tree_model_get (model, &iter, NAME_COLUMN, &name_i, -1); 
808                 if (strcasecmp(name, name_i) == 0)
809                 {
810                         gtk_tree_selection_select_iter (selection, &iter);
811                         path = gtk_tree_model_get_path (model, &iter);
812                         gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (this->priv->search_all_treeview),
813                                                       path,
814                                                       NULL,
815                                                       TRUE, 0.5, 0.0);
816                         gtk_tree_path_free (path);
817                         break;
818                 }
819         }
820
821         gl_debug (DEBUG_MEDIA_SELECT, "END");
822 }
823
824
825 /****************************************************************************/
826 /* query current filter parameters.                                         */
827 /****************************************************************************/
828 void
829 gl_media_select_get_filter_parameters (glMediaSelect  *this,
830                                        gchar         **page_size_id,
831                                        gchar         **category_id)
832 {
833         gchar *page_size_name, *category_name;
834
835         gl_debug (DEBUG_MEDIA_SELECT, "");
836
837         g_free (*page_size_id);
838         g_free (*category_id);
839
840         page_size_name =
841                 gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->page_size_combo));
842
843         *page_size_id = lgl_db_lookup_paper_id_from_name (page_size_name);
844
845         category_name =
846                 gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->category_combo));
847
848         *category_id = lgl_db_lookup_category_id_from_name (category_name);
849
850         g_free (page_size_name);
851         g_free (category_name);
852 }
853
854
855 /****************************************************************************/
856 /* set filter parameters.                                                   */
857 /****************************************************************************/
858 void
859 gl_media_select_set_filter_parameters (glMediaSelect  *this,
860                                        const gchar    *page_size_id,
861                                        const gchar    *category_id)
862 {
863         gchar *page_size_name;
864         gchar *category_name;
865
866         gl_debug (DEBUG_MEDIA_SELECT, "START");
867
868         page_size_name = lgl_db_lookup_paper_name_from_id (page_size_id);
869         if (page_size_name == NULL)
870         {
871                 page_size_name = g_strdup (C_("Page size", "Any"));
872         }
873
874         gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->page_size_combo),
875                                        page_size_name);
876
877         category_name = lgl_db_lookup_category_name_from_id (category_id);
878         if (category_name == NULL)
879         {
880                 category_name = g_strdup (C_("Category", "Any"));
881         }
882
883         gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->category_combo),
884                                        category_name);
885         g_free (page_size_name);
886         g_free (category_name);
887
888         gl_debug (DEBUG_MEDIA_SELECT, "END");
889 }
890
891
892 /*--------------------------------------------------------------------------*/
893 /* PRIVATE.  Load list store from template name list.                       */
894 /*--------------------------------------------------------------------------*/
895 static void
896 load_recent_list (glMediaSelect      *this,
897                   GtkListStore       *store,
898                   GtkTreeSelection   *selection,
899                   GList              *list)
900 {
901         GList            *p;
902         GtkTreeIter       iter;
903         lglUnits          units;
904         lglTemplate      *template;
905         lglTemplateFrame *frame;
906         GdkPixbuf        *pixbuf;
907         gchar            *size;
908         gchar            *layout;
909         gchar            *description;
910
911         gl_debug (DEBUG_MEDIA_SELECT, "START");
912
913         gtk_list_store_clear (store);
914
915
916         if ( this->priv->recent_info_bar )
917         {
918                 gtk_container_remove (GTK_CONTAINER (this->priv->recent_info_vbox),
919                                       this->priv->recent_info_bar);
920                 this->priv->recent_info_bar = NULL;
921         }
922
923         if (list)
924         {
925
926                 units = gl_prefs_model_get_units (gl_prefs);
927
928                 for ( p=list; p!=NULL; p=p->next )
929                 {
930
931                         gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data);
932
933                         template = lgl_db_lookup_template_from_name (p->data);
934                         frame    = (lglTemplateFrame *)template->frames->data;
935                         pixbuf   = gl_mini_preview_pixbuf_cache_get_pixbuf (p->data);
936
937                         size     = lgl_template_frame_get_size_description (frame, units);
938                         layout   = lgl_template_frame_get_layout_description (frame);
939                         description = g_strdup_printf ("<b>%s: %s</b>\n%s\n%s",
940                                                        (gchar *)p->data,
941                                                        template->description,
942                                                        size,
943                                                        layout);
944                         g_free (size);
945                         g_free (layout);
946
947                         lgl_template_free (template);
948
949                         gtk_list_store_append (store, &iter);
950                         gtk_list_store_set (store, &iter,
951                                             NAME_COLUMN, p->data,
952                                             PREVIEW_COLUMN, pixbuf,
953                                             DESCRIPTION_COLUMN, description,
954                                             -1);
955
956                         g_object_unref (G_OBJECT (pixbuf));
957                         g_free (description);
958                 }
959
960                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
961                 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
962                 gtk_tree_selection_select_iter (selection, &iter);
963
964         }
965         else
966         {
967                 this->priv->recent_info_bar = gl_message_bar_new (GTK_MESSAGE_INFO, GTK_BUTTONS_NONE,
968                                                                   "%s", _("No recent templates found."));
969                 gl_message_bar_format_secondary_text (GL_MESSAGE_BAR (this->priv->recent_info_bar),
970                                                       "%s", _("Try selecting a template in the \"Search all\" tab."));
971
972                 gtk_box_pack_start (GTK_BOX (this->priv->recent_info_vbox),
973                                     this->priv->recent_info_bar,
974                                     FALSE, FALSE, 0);
975                 gtk_widget_show_all (this->priv->recent_info_bar);
976
977                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
978
979         }
980
981         gl_debug (DEBUG_MEDIA_SELECT, "END");
982 }
983
984
985 /*--------------------------------------------------------------------------*/
986 /* PRIVATE.  Load list store from template name list.                       */
987 /*--------------------------------------------------------------------------*/
988 static void
989 load_search_all_list (glMediaSelect      *this,
990                       GtkListStore       *store,
991                       GtkTreeSelection   *selection,
992                       GList              *list)
993 {
994         GList            *p;
995         GtkTreeIter       iter;
996         lglUnits          units;
997         lglTemplate      *template;
998         lglTemplateFrame *frame;
999         GdkPixbuf        *pixbuf;
1000         gchar            *size;
1001         gchar            *layout;
1002         gchar            *description;
1003
1004         gl_debug (DEBUG_MEDIA_SELECT, "START");
1005
1006         gtk_list_store_clear (store);
1007
1008         if ( this->priv->search_all_info_bar )
1009         {
1010                 gtk_container_remove (GTK_CONTAINER (this->priv->search_all_info_vbox),
1011                                       this->priv->search_all_info_bar);
1012                 this->priv->search_all_info_bar = NULL;
1013         }
1014
1015         if (list)
1016         {
1017
1018                 units = gl_prefs_model_get_units (gl_prefs);
1019
1020                 for ( p=list; p!=NULL; p=p->next )
1021                 {
1022
1023                         gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data);
1024
1025                         template = lgl_db_lookup_template_from_name (p->data);
1026                         frame    = (lglTemplateFrame *)template->frames->data;
1027                         pixbuf   = gl_mini_preview_pixbuf_cache_get_pixbuf (p->data);
1028
1029                         size     = lgl_template_frame_get_size_description (frame, units);
1030                         layout   = lgl_template_frame_get_layout_description (frame);
1031                         description = g_strdup_printf ("<b>%s: %s</b>\n%s\n%s",
1032                                                        (gchar *)p->data,
1033                                                        template->description,
1034                                                        size,
1035                                                        layout);
1036                         g_free (size);
1037                         g_free (layout);
1038
1039                         lgl_template_free (template);
1040
1041                         gtk_list_store_append (store, &iter);
1042                         gtk_list_store_set (store, &iter,
1043                                             NAME_COLUMN, p->data,
1044                                             PREVIEW_COLUMN, pixbuf,
1045                                             DESCRIPTION_COLUMN, description,
1046                                             -1);
1047
1048                         g_object_unref (G_OBJECT (pixbuf));
1049                         g_free (description);
1050                 }
1051
1052                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1053                 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
1054                 gtk_tree_selection_select_iter (selection, &iter);
1055
1056         }
1057         else
1058         {
1059                 /* Translators: "No match" means that for the given template search criteria, there
1060                  * were no matches found. */
1061                 this->priv->search_all_info_bar = gl_message_bar_new (GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, "%s", _("No match."));
1062                 gl_message_bar_format_secondary_text (GL_MESSAGE_BAR (this->priv->search_all_info_bar),
1063                                                       "%s", _("Try selecting a different brand, page size or category."));
1064
1065                 gtk_box_pack_start (GTK_BOX (this->priv->search_all_info_vbox),
1066                                     this->priv->search_all_info_bar,
1067                                     FALSE, FALSE, 0);
1068                 gtk_widget_show_all (this->priv->search_all_info_bar);
1069
1070                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
1071
1072         }
1073
1074         gl_debug (DEBUG_MEDIA_SELECT, "END");
1075 }
1076
1077
1078 /*--------------------------------------------------------------------------*/
1079 /* PRIVATE.  Load list store from template name list.                       */
1080 /*--------------------------------------------------------------------------*/
1081 static void
1082 load_custom_list (glMediaSelect      *this,
1083                   GtkListStore       *store,
1084                   GtkTreeSelection   *selection,
1085                   GList              *list)
1086 {
1087         GList            *p;
1088         GtkTreeIter       iter;
1089         lglUnits          units;
1090         lglTemplate      *template;
1091         lglTemplateFrame *frame;
1092         GdkPixbuf        *pixbuf;
1093         gchar            *size;
1094         gchar            *layout;
1095         gchar            *description;
1096
1097         gl_debug (DEBUG_MEDIA_SELECT, "START");
1098
1099         gtk_list_store_clear (store);
1100
1101
1102         if ( this->priv->custom_info_bar )
1103         {
1104                 gtk_container_remove (GTK_CONTAINER (this->priv->custom_info_vbox),
1105                                       this->priv->custom_info_bar);
1106                 this->priv->custom_info_bar = NULL;
1107         }
1108
1109         if (list)
1110         {
1111
1112                 units = gl_prefs_model_get_units (gl_prefs);
1113
1114                 for ( p=list; p!=NULL; p=p->next )
1115                 {
1116
1117                         gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data);
1118
1119                         template = lgl_db_lookup_template_from_name (p->data);
1120                         frame    = (lglTemplateFrame *)template->frames->data;
1121                         pixbuf   = gl_mini_preview_pixbuf_cache_get_pixbuf (p->data);
1122
1123                         size     = lgl_template_frame_get_size_description (frame, units);
1124                         layout   = lgl_template_frame_get_layout_description (frame);
1125                         description = g_strdup_printf ("<b>%s: %s</b>\n%s\n%s",
1126                                                        (gchar *)p->data,
1127                                                        template->description,
1128                                                        size,
1129                                                        layout);
1130                         g_free (size);
1131                         g_free (layout);
1132
1133                         lgl_template_free (template);
1134
1135                         gtk_list_store_append (store, &iter);
1136                         gtk_list_store_set (store, &iter,
1137                                             NAME_COLUMN, p->data,
1138                                             PREVIEW_COLUMN, pixbuf,
1139                                             DESCRIPTION_COLUMN, description,
1140                                             -1);
1141
1142                         g_object_unref (G_OBJECT (pixbuf));
1143                         g_free (description);
1144                 }
1145
1146                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1147                 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
1148                 gtk_tree_selection_select_iter (selection, &iter);
1149
1150                 gtk_widget_set_sensitive (GTK_WIDGET (this->priv->custom_edit_button), TRUE);
1151                 gtk_widget_set_sensitive (GTK_WIDGET (this->priv->custom_delete_button), TRUE);
1152         }
1153         else
1154         {
1155                 this->priv->custom_info_bar = gl_message_bar_new (GTK_MESSAGE_INFO,
1156                                                                           GTK_BUTTONS_NONE,
1157                                                                           "%s", _("No custom templates found."));
1158                 gl_message_bar_format_secondary_text (GL_MESSAGE_BAR (this->priv->custom_info_bar),
1159                                                       "%s", _("You may create new templates or try searching for pre-defined templates in the \"Search all\" tab."));
1160
1161                 gtk_box_pack_start (GTK_BOX (this->priv->custom_info_vbox),
1162                                     this->priv->custom_info_bar,
1163                                     FALSE, FALSE, 0);
1164                 gtk_widget_show_all (this->priv->custom_info_bar);
1165
1166                 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
1167
1168                 gtk_widget_set_sensitive (GTK_WIDGET (this->priv->custom_edit_button), FALSE);
1169                 gtk_widget_set_sensitive (GTK_WIDGET (this->priv->custom_delete_button), FALSE);
1170         }
1171
1172         gl_debug (DEBUG_MEDIA_SELECT, "END");
1173 }
1174
1175
1176
1177 /*
1178  * Local Variables:       -- emacs
1179  * mode: C                -- emacs
1180  * c-basic-offset: 8      -- emacs
1181  * tab-width: 8           -- emacs
1182  * indent-tabs-mode: nil  -- emacs
1183  * End:                   -- emacs
1184  */