2005-06-15 [paul] 1.9.11cvs70
[claws.git] / src / gtk / progressdialog.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2005 Hiroyuki Yamamoto
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
17  * Foundation, 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 <glib.h>
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27 #include <gtk/gtkdialog.h>
28 #include <gtk/gtkhbox.h>
29 #include <gtk/gtklabel.h>
30 #include <gtk/gtkprogressbar.h>
31 #include <gtk/gtkscrolledwindow.h>
32 #include <gtk/gtkbutton.h>
33 #include <gtk/gtkstock.h>
34
35 #include "progressdialog.h"
36 #include "gtkutils.h"
37 #include "utils.h"
38 #include "prefs_common.h"
39
40 enum {
41         PROGRESS_IMAGE,
42         PROGRESS_ACCOUNT,
43         PROGRESS_STATE,
44         N_PROGRESS_COLUMNS
45 };
46
47
48 static GtkListStore* progress_dialog_create_data_store(void);
49 static gint progress_dialog_list_view_insert_account(GtkWidget   *list_view,
50                                                      gint         row,
51                                                      const gchar *account,
52                                                      const gchar *status,
53                                                      GdkPixbuf   *image);
54 static GtkWidget *progress_dialog_list_view_create(void);
55 static void progress_dialog_create_list_view_columns(GtkTreeView *list_view);
56
57 ProgressDialog *progress_dialog_create(void)
58 {
59         ProgressDialog *progress;
60         GtkWidget *dialog;
61         GtkWidget *hbox;
62         GtkWidget *label;
63         GtkWidget *cancel_btn;
64         GtkWidget *progressbar;
65         GtkWidget *scrolledwin;
66         GtkWidget *clist;
67         GtkWidget *list_view;
68         gchar *text[] = {NULL, NULL, NULL};
69
70         text[1] = _("Account");
71         text[2] = _("Status");
72
73         debug_print("Creating progress dialog...\n");
74         progress = g_new0(ProgressDialog, 1);
75
76         dialog = gtk_dialog_new();
77         gtk_widget_set_size_request(dialog, 460, -1);
78         gtk_container_set_border_width(GTK_CONTAINER(dialog), 8);
79         gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, TRUE, TRUE);
80         gtk_widget_realize(dialog);
81
82         gtk_container_set_border_width
83                 (GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 0);
84         gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), 8);
85         gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
86
87         hbox = gtk_hbox_new(FALSE, 0);
88         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox,
89                            FALSE, FALSE, 8);
90         gtk_widget_show(hbox);
91
92         label = gtk_label_new("");
93         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
94         gtk_widget_show(label);
95
96         cancel_btn = gtk_dialog_add_button(GTK_DIALOG(dialog),
97                                            GTK_STOCK_CANCEL,
98                                            GTK_RESPONSE_NONE);
99         gtk_widget_grab_default(cancel_btn);
100         gtk_widget_grab_focus(cancel_btn);
101
102         progressbar = gtk_progress_bar_new();
103         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), progressbar,
104                            FALSE, FALSE, 0);
105         gtk_widget_show(progressbar);
106
107         scrolledwin = gtk_scrolled_window_new(NULL, NULL);
108         gtk_widget_show(scrolledwin);
109         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolledwin,
110                            TRUE, TRUE, 0);
111         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
112                                        GTK_POLICY_AUTOMATIC,
113                                        GTK_POLICY_AUTOMATIC);
114
115         /* GTK2: we hide the clist, but it is available for migration
116          * purposes. now if there only was a way to catch "set clist 
117          * things"!.. */
118         clist = gtk_clist_new_with_titles(3, text);
119         gtk_widget_hide(clist);
120         /* gtk_container_add(GTK_CONTAINER(scrolledwin), clist); */
121         /* gtk_widget_set_size_request(clist, -1, 120); */
122         gtk_clist_set_column_justification(GTK_CLIST(clist), 0,
123                                            GTK_JUSTIFY_CENTER);
124         gtk_clist_set_column_width(GTK_CLIST(clist), 0, 16);
125         gtk_clist_set_column_width(GTK_CLIST(clist), 1, 160);
126
127         list_view = progress_dialog_list_view_create();
128         gtk_widget_show(list_view);
129         gtk_container_add(GTK_CONTAINER(scrolledwin), list_view);
130         gtk_widget_set_size_request(list_view, -1, 120);
131
132         progress->window      = dialog;
133         progress->label       = label;
134         progress->cancel_btn  = cancel_btn;
135         progress->progressbar = progressbar;
136         progress->clist       = clist;
137         progress->list_view   = list_view;
138
139         return progress;
140 }
141
142 void progress_dialog_set_label(ProgressDialog *progress, gchar *str)
143 {
144         gtk_label_set_text(GTK_LABEL(progress->label), str);
145 }
146
147 void progress_dialog_get_fraction(ProgressDialog *progress)
148 {
149         gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progress->progressbar));
150 }
151
152 void progress_dialog_set_fraction(ProgressDialog *progress,
153                                   gfloat percentage)
154 {
155         gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->progressbar),
156                                       percentage);
157 }
158
159 void progress_dialog_destroy(ProgressDialog *progress)
160 {
161         if (progress) {
162                 gtk_widget_destroy(progress->window);
163                 g_free(progress);
164         }
165 }
166
167 /*!
168  *\return       gint Row where account was set
169  */
170 gint progress_dialog_list_set_account(ProgressDialog *progress,
171                                       gint            row,
172                                       const gchar    *account_name)
173 {
174         return progress_dialog_list_view_insert_account(progress->list_view,
175                                                         row, account_name, NULL, 
176                                                         NULL);
177 }
178
179 /*!
180  *\return       gint Row where image was set
181  */
182 gint progress_dialog_list_set_image(ProgressDialog *progress,
183                                     gint            row,
184                                     GdkPixbuf      *image)
185 {
186         return progress_dialog_list_view_insert_account(progress->list_view,
187                                                         row, NULL, NULL, 
188                                                         image);
189 }
190
191 /*!
192  *\return       gint Row where status was set
193  */
194 gint progress_dialog_list_set_status(ProgressDialog *progress,
195                                      gint            row,
196                                      const gchar    *status)
197 {
198         return progress_dialog_list_view_insert_account(progress->list_view,
199                                                         row, NULL, status, 
200                                                         NULL);
201 }
202
203 /*!
204  *\return       gint Row where data were set 
205  */
206 gint progress_dialog_list_set(ProgressDialog    *progress,
207                               gint               row,
208                               GdkPixbuf         *image,
209                               const gchar       *account_name,
210                               const gchar       *status)
211 {
212         return progress_dialog_list_view_insert_account(progress->list_view,
213                                                         row,  account_name, 
214                                                         status, image);
215 }
216
217 /* XXX: maybe scroll into view, but leaving that for someone else to
218  * pickup: I don't have that many accounts... */
219 gboolean progress_dialog_list_select_row(ProgressDialog *progress,
220                                          gint            row)
221 {
222         GtkTreeSelection *selection = gtk_tree_view_get_selection
223                                         (GTK_TREE_VIEW(progress->list_view));
224         GtkTreeIter iter;
225         GtkTreeModel *model;
226
227         model = gtk_tree_view_get_model(GTK_TREE_VIEW(progress->list_view));
228
229         if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row))
230                 return FALSE;
231
232         gtk_tree_selection_select_iter(selection, &iter);               
233
234         return TRUE;
235 }
236
237 static GtkListStore* progress_dialog_create_data_store(void)
238 {
239         return gtk_list_store_new(N_PROGRESS_COLUMNS,
240                                   GDK_TYPE_PIXBUF,
241                                   G_TYPE_STRING,
242                                   G_TYPE_STRING,        
243                                   -1);
244 }
245
246 static gint progress_dialog_list_view_insert_account(GtkWidget   *list_view,
247                                                      gint         row,
248                                                      const gchar *account,
249                                                      const gchar *status,
250                                                      GdkPixbuf   *image)
251 {
252         GtkTreeIter iter;
253         GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model
254                                         (GTK_TREE_VIEW(list_view)));
255         gint result = -1;                                       
256         
257         if (account == NULL && status == NULL && image == NULL)
258                 return -1;
259
260         /* see if row exists, if not append */
261         if (row < 0 || !gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), 
262                                                       &iter, NULL, row)) {
263                 result = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store),
264                                                         NULL);
265                 gtk_list_store_append(store, &iter);
266         } else
267                 result = row;
268
269         /*
270          * XXX: uhm, when does the iter invalidate? sure not while
271          * just setting a row's column i hope?
272          */
273         
274         if (account)
275                 gtk_list_store_set(store, &iter, 
276                                    PROGRESS_ACCOUNT, account,
277                                    -1);
278         if (status)
279                 gtk_list_store_set(store, &iter,
280                                    PROGRESS_STATE, status,
281                                    -1);
282         if (image)
283                 gtk_list_store_set(store, &iter,
284                                    PROGRESS_IMAGE, image,
285                                    -1);
286
287         return result;
288 }
289
290 static GtkWidget *progress_dialog_list_view_create(void)
291 {
292         GtkTreeView *list_view;
293         GtkTreeModel *model;
294
295         model = GTK_TREE_MODEL(progress_dialog_create_data_store());
296         list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
297         g_object_unref(model);  
298         
299         gtk_tree_view_set_rules_hint(list_view, prefs_common.enable_rules_hint);
300         
301         /* create the columns */
302         progress_dialog_create_list_view_columns(list_view);
303
304         return GTK_WIDGET(list_view);
305 }
306
307 static void progress_dialog_create_list_view_columns(GtkTreeView *list_view)
308 {
309         GtkTreeViewColumn *column;
310         GtkCellRenderer *renderer;
311
312         renderer = gtk_cell_renderer_pixbuf_new();
313         column = gtk_tree_view_column_new_with_attributes
314                         ("", renderer, 
315                          "pixbuf", PROGRESS_IMAGE,
316                          NULL);
317         gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);                   
318
319         renderer = gtk_cell_renderer_text_new();
320         column = gtk_tree_view_column_new_with_attributes
321                 (_("Account"),
322                  renderer,
323                  "text", PROGRESS_ACCOUNT,
324                  NULL);
325         gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
326
327         renderer = gtk_cell_renderer_text_new();
328         column = gtk_tree_view_column_new_with_attributes
329                 (_("Status"),
330                  renderer,
331                  "text", PROGRESS_STATE,
332                  NULL);
333         gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
334 }
335