1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
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 3 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, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #include "claws-features.h"
23 #endif
24 
25 #include <glib.h>
26 #include <glib/gi18n.h>
27 #include <gtk/gtk.h>
28 
29 #include "progressdialog.h"
30 #include "gtkutils.h"
31 #include "utils.h"
32 #include "prefs_common.h"
33 
34 enum {
35 	PROGRESS_IMAGE,
36 	PROGRESS_ACCOUNT,
37 	PROGRESS_STATE,
38 	N_PROGRESS_COLUMNS
39 };
40 
41 static gint progress_dialog_insert_account(ProgressDialog *progress,
42 					   gint	 	   row,
43 					   const gchar	  *account,
44 					   const gchar	  *status,
45 					   GdkPixbuf	  *image);
46 
47 static void progress_dialog_hide_btn_cb(GtkWidget *widget, gpointer data);
48 static void progress_dialog_delete_event_btn_cb(GtkWidget *widget, gpointer data);
49 
progress_dialog_create(void)50 ProgressDialog *progress_dialog_create(void)
51 {
52 	ProgressDialog *progress;
53 	GtkWidget *dialog;
54 	GtkWidget *hbox;
55 	GtkWidget *vbox;
56 	GtkWidget *label;
57 	GtkWidget *hide_btn;
58 	GtkWidget *showlog_btn;
59 	GtkWidget *cancel_btn;
60 	GtkWidget *progressbar;
61 	GtkWidget *scrolledwin;
62 	GtkWidget *treeview;
63 	GtkListStore *store;
64 	GtkTreeSelection *selection;
65 	GtkTreeViewColumn *column;
66 	GtkCellRenderer *renderer;
67 
68 	debug_print("Creating progress dialog...\n");
69 	progress = g_new0(ProgressDialog, 1);
70 
71 	dialog = gtk_dialog_new();
72 	gtk_container_set_border_width(GTK_CONTAINER(dialog), 8);
73 	gtk_window_set_resizable(GTK_WINDOW(dialog), TRUE);
74 	gtk_widget_realize(dialog);
75 
76 	gtk_container_set_border_width
77 		(GTK_CONTAINER(gtk_dialog_get_action_area(GTK_DIALOG(dialog))), 0);
78 	vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
79 	gtk_box_set_spacing(GTK_BOX(vbox), 8);
80 
81 	hbox = gtk_hbox_new(FALSE, 0);
82 	gtk_box_pack_start(GTK_BOX(vbox), hbox,
83 			   FALSE, FALSE, 8);
84 	gtk_widget_show(hbox);
85 
86 	label = gtk_label_new("");
87 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8);
88 	gtk_widget_show(label);
89 
90 	hide_btn = gtk_dialog_add_button(GTK_DIALOG(dialog),
91 					   _("_Hide"),
92 					   GTK_RESPONSE_NONE);
93 	showlog_btn = gtk_dialog_add_button(GTK_DIALOG(dialog),
94 					   _("_View log"),
95 					   GTK_RESPONSE_NONE);
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(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(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 	store = gtk_list_store_new(N_PROGRESS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
116 				   G_TYPE_STRING, G_TYPE_POINTER);
117 
118 	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
119 	g_object_unref(G_OBJECT(store));
120 	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE);
121 	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview),
122 				     prefs_common.use_stripes_everywhere);
123 	gtk_widget_show(treeview);
124 	gtk_container_add(GTK_CONTAINER(scrolledwin), treeview);
125 	gtk_widget_set_size_request(treeview, -1, 120);
126 
127 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
128 	gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
129 
130 	renderer = gtk_cell_renderer_pixbuf_new();
131 	g_object_set(renderer, "xalign", 0.5, NULL);
132 	column = gtk_tree_view_column_new_with_attributes
133 		(NULL, renderer, "pixbuf", PROGRESS_IMAGE, NULL);
134 	gtk_tree_view_column_set_alignment(column, 0.5);
135 	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
136 	gtk_tree_view_column_set_fixed_width(column, 20);
137 	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
138 
139 	renderer = gtk_cell_renderer_text_new();
140 	column = gtk_tree_view_column_new_with_attributes
141 		(_("Account"), renderer, "text", PROGRESS_ACCOUNT, NULL);
142 	gtk_tree_view_column_set_resizable(column, TRUE);
143 	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
144 	gtk_tree_view_column_set_fixed_width(column, 160);
145 	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
146 
147 	renderer = gtk_cell_renderer_text_new();
148 	column = gtk_tree_view_column_new_with_attributes
149 		(_("Status"), renderer, "text", PROGRESS_STATE, NULL);
150 	gtk_tree_view_column_set_resizable(column, TRUE);
151 	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
152 	gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
153 
154 	/* the WM close and hide buttons are handled internally and not published to caller */
155 	g_signal_connect(G_OBJECT(dialog), "delete_event",
156 				G_CALLBACK(progress_dialog_delete_event_btn_cb), NULL);
157 	g_signal_connect(G_OBJECT(hide_btn), "clicked",
158 				G_CALLBACK(progress_dialog_hide_btn_cb), dialog);
159 
160 	progress->window      = dialog;
161 	progress->label       = label;
162 	progress->showlog_btn  = showlog_btn;
163 	progress->cancel_btn  = cancel_btn;
164 	progress->progressbar = progressbar;
165 	progress->treeview    = treeview;
166 	progress->store       = store;
167 
168 	return progress;
169 }
170 
progress_dialog_set_label(ProgressDialog * progress,gchar * str)171 void progress_dialog_set_label(ProgressDialog *progress, gchar *str)
172 {
173 	gtk_label_set_text(GTK_LABEL(progress->label), str);
174 }
175 
progress_dialog_get_fraction(ProgressDialog * progress)176 void progress_dialog_get_fraction(ProgressDialog *progress)
177 {
178 	gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progress->progressbar));
179 }
180 
progress_dialog_set_fraction(ProgressDialog * progress,gfloat percentage)181 void progress_dialog_set_fraction(ProgressDialog *progress,
182 				  gfloat percentage)
183 {
184 	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->progressbar),
185 				      percentage);
186 }
187 
progress_dialog_destroy(ProgressDialog * progress)188 void progress_dialog_destroy(ProgressDialog *progress)
189 {
190 	if (progress) {
191 		gtk_widget_destroy(progress->window);
192 		g_free(progress);
193 	}
194 }
195 
196 /*!
197  *\return	gint Row where status was set
198  */
progress_dialog_list_set_status(ProgressDialog * progress,gint row,const gchar * status)199 gint progress_dialog_list_set_status(ProgressDialog *progress,
200 				     gint	     row,
201 				     const gchar    *status)
202 {
203 	return progress_dialog_insert_account(progress, row, NULL,
204 					      status, NULL);
205 }
206 
207 /*!
208  *\return	gint Row where data were set
209  */
progress_dialog_list_set(ProgressDialog * progress,gint row,GdkPixbuf * image,const gchar * account_name,const gchar * status)210 gint progress_dialog_list_set(ProgressDialog	*progress,
211 			      gint		 row,
212 			      GdkPixbuf		*image,
213 			      const gchar	*account_name,
214 			      const gchar	*status)
215 {
216 	return progress_dialog_insert_account(progress, row, account_name,
217 					      status, image);
218 }
219 
progress_dialog_scroll_to_row(ProgressDialog * progress,gint row)220 void progress_dialog_scroll_to_row(ProgressDialog *progress, gint row)
221 {
222 	GtkTreeModel *model = GTK_TREE_MODEL(progress->store);
223 	GtkTreeIter iter;
224 	GtkTreePath *path;
225 
226 	if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row))
227 		return;
228 
229 	path = gtk_tree_model_get_path(model, &iter);
230 	gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(progress->treeview),
231 				     path, NULL, FALSE, 0.0, 0.0);
232 	gtk_tree_path_free(path);
233 }
234 
progress_dialog_insert_account(ProgressDialog * progress,gint row,const gchar * account,const gchar * status,GdkPixbuf * image)235 static gint progress_dialog_insert_account(ProgressDialog *progress,
236 					   gint	 	   row,
237 					   const gchar 	  *account,
238 					   const gchar 	  *status,
239 					   GdkPixbuf	  *image)
240 {
241 	GtkTreeIter iter;
242 	GtkListStore *store = progress->store;
243 	gint result = -1;
244 
245 	if (account == NULL && status == NULL && image == NULL)
246 		return -1;
247 
248 	/* see if row exists, if not append */
249 	if (row < 0 || !gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store),
250 						      &iter, NULL, row)) {
251 		result = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store),
252 							NULL);
253 		gtk_list_store_append(store, &iter);
254 	} else
255 		result = row;
256 
257 	/*
258 	 * XXX: uhm, when does the iter invalidate? sure not while
259 	 * just setting a row's column i hope?
260 	 */
261 
262 	if (account)
263 		gtk_list_store_set(store, &iter,
264 				   PROGRESS_ACCOUNT, account,
265 				   -1);
266 	if (status)
267 		gtk_list_store_set(store, &iter,
268 				   PROGRESS_STATE, status,
269 				   -1);
270 	if (image)
271 		gtk_list_store_set(store, &iter,
272 				   PROGRESS_IMAGE, image,
273 				   -1);
274 
275 	return result;
276 }
277 
progress_dialog_hide_btn_cb(GtkWidget * widget,gpointer data)278 static void progress_dialog_hide_btn_cb(GtkWidget *widget, gpointer data)
279 {
280 		gtk_widget_hide(GTK_WIDGET(data));
281 }
282 
progress_dialog_delete_event_btn_cb(GtkWidget * widget,gpointer data)283 static void progress_dialog_delete_event_btn_cb(GtkWidget *widget, gpointer data)
284 {
285 		gtk_widget_hide(widget);
286 }
287