1 /*
2 	download_list_view.h
3 
4 
5 	2003  Plus Huang
6  */
7 
8 #include "download_list_view.h"
9 #include "setting_view_icons.h"
10 #include "urlgfe.h"
11 #include "dnd_data.h"
12 
dtoa_unit(double d,gchar * tail_str)13 static gchar* dtoa_unit (double d, gchar* tail_str)
14 {
15 	const static gchar* unit_str[4] = {"", " KB", " MB", " GB"};
16 	guint  index;
17 	gint   precision = 0;
18 
19 	for (index=0; index < 3; index++) {
20 		if (d > 1024.0) {
21 			d /= 1024.0;
22 			precision = 2;
23 		}
24 		else
25 			break;
26 	}
27 
28 	return g_strdup_printf ("%.*f%s%s", precision, d, unit_str[index], tail_str);
29 }
30 
31 // data set function for GtkCellRenderer
col_set_icon(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)32 static void col_set_icon (GtkTreeViewColumn *tree_column,
33                           GtkCellRenderer   *cell,
34                           GtkTreeModel      *model,
35                           GtkTreeIter       *iter,
36                           gpointer           data)
37 {
38 	DownloadSetting* setting;
39 
40 	gtk_tree_model_get (model, iter,
41 	                    DOWNLOAD_COL_DATA,
42 	                    &setting,
43 	                    -1);
44 	if (setting->state >= DOWNLOAD_N_STATE)
45 		setting->state = DOWNLOAD_STATE_ERROR;
46 
47 	g_object_set ((GtkCellRenderer*)cell,
48 	              "pixbuf",
49 	              download_state_icons[setting->state],
50 	              NULL);
51 }
52 
col_set_filename(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)53 static void col_set_filename (GtkTreeViewColumn *tree_column,
54                               GtkCellRenderer   *cell,
55                               GtkTreeModel      *model,
56                               GtkTreeIter       *iter,
57                               gpointer           data)
58 {
59 	DownloadSetting* dd;
60 
61 	gtk_tree_model_get (model, iter,
62 	                    DOWNLOAD_COL_DATA, &dd,
63 	                    -1);
64 	g_object_set ((GtkCellRenderer*)cell,
65 	              "text",
66 	              dd->filename,
67 	              NULL);
68 }
69 
col_set_completed(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)70 static void col_set_completed (GtkTreeViewColumn *tree_column,
71                                GtkCellRenderer   *cell,
72                                GtkTreeModel      *model,
73                                GtkTreeIter       *iter,
74                                gpointer           data)
75 {
76 	Download* dl_data;
77 	gpointer  thread;
78 	gchar*    string = NULL;
79 
80 	gtk_tree_model_get (model, iter,
81 	                    DOWNLOAD_COL_DATA, &dl_data,
82 	                    DOWNLOAD_COL_THREAD, &thread,
83 	                    -1);
84 
85 	if (thread && dl_data->info_valid)
86 		string = dtoa_unit (dl_data->completed, "");
87 
88 	g_object_set ((GtkCellRenderer*)cell,
89 	              "text",
90 	              string,
91 	              NULL);
92 	g_free (string);
93 }
94 
col_set_total(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)95 static void col_set_total (GtkTreeViewColumn *tree_column,
96                            GtkCellRenderer   *cell,
97                            GtkTreeModel      *model,
98                            GtkTreeIter       *iter,
99                            gpointer           data)
100 {
101 	Download* dl_data;
102 	gpointer  thread;
103 	gchar*    string = NULL;
104 
105 	gtk_tree_model_get (model, iter,
106 	                    DOWNLOAD_COL_DATA, &dl_data,
107 	                    DOWNLOAD_COL_THREAD, &thread,
108 	                    -1);
109 
110 	if (thread && dl_data->info_valid)
111 		string = dtoa_unit (dl_data->total, "");
112 
113 	g_object_set ((GtkCellRenderer*)cell,
114 	              "text",
115 	              string,
116 	              NULL);
117 	g_free (string);
118 }
119 
col_set_percent(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)120 static void col_set_percent (GtkTreeViewColumn *tree_column,
121                              GtkCellRenderer   *cell,
122                              GtkTreeModel      *model,
123                              GtkTreeIter       *iter,
124                              gpointer           data)
125 {
126 	Download* dl_data;
127 	gpointer  thread;
128 	gchar*    string = NULL;
129 
130 	gtk_tree_model_get (model, iter,
131 	                    DOWNLOAD_COL_DATA, &dl_data,
132 	                    DOWNLOAD_COL_THREAD, &thread,
133 	                    -1);
134 
135 	if (thread && dl_data->info_valid)
136 		string = g_strdup_printf ("%.1f%%", dl_data->percent);
137 
138 	g_object_set ((GtkCellRenderer*)cell,
139 	              "text",
140 	              string,
141 	              NULL);
142 	g_free (string);
143 }
144 
col_set_speed(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)145 static void col_set_speed (GtkTreeViewColumn *tree_column,
146                            GtkCellRenderer   *cell,
147                            GtkTreeModel      *model,
148                            GtkTreeIter       *iter,
149                            gpointer           data)
150 {
151 	Download* dl_data;
152 	gpointer  thread;
153 	gchar*    string = NULL;
154 
155 	gtk_tree_model_get (model, iter,
156 	                    DOWNLOAD_COL_DATA, &dl_data,
157 	                    DOWNLOAD_COL_THREAD, &thread,
158 	                    -1);
159 
160 	if (thread && dl_data->info_valid)
161 		string = dtoa_unit (dl_data->speed, "/s");
162 
163 	g_object_set ((GtkCellRenderer*)cell,
164 	              "text",
165 	              string,
166 	              NULL);
167 	g_free (string);
168 }
169 
col_set_retry(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)170 static void col_set_retry (GtkTreeViewColumn *tree_column,
171                            GtkCellRenderer   *cell,
172                            GtkTreeModel      *model,
173                            GtkTreeIter       *iter,
174                            gpointer           data)
175 {
176 	Download* dl_data;
177 	gpointer  thread;
178 	gchar*    string = NULL;
179 
180 	gtk_tree_model_get (model, iter,
181 	                    DOWNLOAD_COL_DATA, &dl_data,
182 	                    DOWNLOAD_COL_THREAD, &thread,
183 	                    -1);
184 
185 	if (thread && dl_data->info_valid)
186 		string = g_strdup_printf ("%d", dl_data->n_retries);
187 
188 	g_object_set ((GtkCellRenderer*)cell,
189 	              "text",
190 	              string,
191 	              NULL);
192 	g_free (string);
193 }
194 
col_set_url(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)195 static void col_set_url (GtkTreeViewColumn *tree_column,
196                          GtkCellRenderer   *cell,
197                          GtkTreeModel      *model,
198                          GtkTreeIter       *iter,
199                          gpointer           data)
200 {
201 	DownloadSetting* dd;
202 
203 	gtk_tree_model_get (model, iter,
204 	                    DOWNLOAD_COL_DATA, &dd,
205 	                    -1);
206 	g_object_set ((GtkCellRenderer*)cell,
207 	              "text",
208 	              dd->url,
209 	              NULL);
210 }
211 
212 
213 // Drag and drop - start ---------------------------------------
214 /*
215 static void on_drag_data_rcv (GtkWidget *widget,
216                               GdkDragContext *dc,
217                               guint x, guint y,
218                               GtkSelectionData *sd,
219                               guint info, guint t,
220                               gpointer user_data)
221 {
222 	if (sd->target == gdk_atom_intern(DND_DOWNLOAD_DATA_TARGET, FALSE) &&
223 	    sd->data)
224 	{
225 		puts (DND_DOWNLOAD_DATA_TARGET);
226 	}
227 }
228 */
229 
on_drag_data_get(GtkWidget * widget,GdkDragContext * dc,GtkSelectionData * data,guint info,guint time,DownloadListView * dlv)230 static void on_drag_data_get (GtkWidget*        widget,
231                               GdkDragContext*   dc,
232                               GtkSelectionData* data,
233                               guint info,
234                               guint time,
235                               DownloadListView* dlv)
236 {
237 	if (data->target == gdk_atom_intern(DND_DOWNLOAD_DATA_TARGET, FALSE)) {
238 		gtk_selection_data_set (data,
239 		                        gdk_atom_intern (DND_DOWNLOAD_DATA_TARGET, FALSE),
240 		                        8, /* bits */
241 		                        (void*)&dlv,
242 		                        sizeof (dlv));
243 	}
244 }
245 
246 // Drag and drop - end ---------------------------------------
247 
248 
download_list_view_init(DownloadListView * dlv,DownloadStore * ds)249 void download_list_view_init (DownloadListView* dlv,
250                               DownloadStore* ds)
251 {
252 	GtkCellRenderer*   renderer;
253 	GtkTreeViewColumn* column;
254 	GtkTreeSelection*  selection;
255 
256 	// for DnD
257 	GtkTargetEntry     gte = {
258 		DND_DOWNLOAD_DATA_TARGET,
259 		DND_DOWNLOAD_DATA_FLAG,
260 		DND_DOWNLOAD_DATA_INFO
261 	};
262 
263 	// data set
264 	dlv->store = ds;
265 
266 	// initial tree view.
267 	dlv->self = (GtkTreeView*)gtk_tree_view_new ();
268 	dlv->container = (GtkScrolledWindow*)gtk_scrolled_window_new (NULL, NULL);
269 	gtk_tree_view_set_model (dlv->self,
270 	                         GTK_TREE_MODEL(ds->list_store));
271 	gtk_tree_view_set_rules_hint (dlv->self, TRUE);
272 
273 	// for GTK2 "floating" reference count.
274 	g_object_ref (G_OBJECT (dlv->container));
275 	gtk_object_sink (GTK_OBJECT (dlv->container));
276 
277 	gtk_scrolled_window_set_policy (dlv->container,
278 	                                GTK_POLICY_AUTOMATIC,
279 	                                GTK_POLICY_AUTOMATIC);
280 	gtk_scrolled_window_set_shadow_type (dlv->container,
281 	                                     GTK_SHADOW_IN);
282 
283 	gtk_container_add (GTK_CONTAINER(dlv->container),
284 	                   GTK_WIDGET(dlv->self));
285 
286 	// DnD support
287 	gtk_tree_view_enable_model_drag_source (dlv->self,
288 	                                        GDK_BUTTON2_MASK,
289 	                                        &gte, 1,
290 	                                        GDK_ACTION_COPY);
291 	g_signal_connect (G_OBJECT(dlv->self), "drag-data-get",
292 	                  G_CALLBACK(on_drag_data_get), dlv);
293 /*
294 	gtk_tree_view_enable_model_drag_dest (dlv->self,
295 	                                      gte, 1,
296 	                                      GDK_ACTION_COPY | GDK_ACTION_MOVE);
297 	g_signal_connect (G_OBJECT(dlv->self), "drag-data-received",
298 	                  G_CALLBACK(on_drag_data_rcv), dlv);
299 */
300 
301 	// set tree view selection
302 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dlv->self));
303 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
304 
305 	// initial icons for tree view
306 	download_state_icons_render ((GtkWidget*)dlv->self);
307 
308 	/* add columns to GtkTreeView */
309 
310 	// column filename
311 	column = gtk_tree_view_column_new ();
312 	gtk_tree_view_column_set_title (column, _("Filename"));
313 	renderer = gtk_cell_renderer_pixbuf_new ();
314 	gtk_tree_view_column_pack_start (column, renderer, FALSE);
315 	gtk_tree_view_column_set_cell_data_func (column,
316 	                                         renderer,
317 	                                         col_set_icon,
318 	                                         NULL, NULL);
319 	renderer = gtk_cell_renderer_text_new ();
320 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
321 	gtk_tree_view_column_set_cell_data_func (column,
322 	                                         renderer,
323 	                                         col_set_filename,
324 	                                         NULL, NULL);
325 	gtk_tree_view_column_set_resizable (column, TRUE);
326 	gtk_tree_view_append_column (dlv->self, column);
327 
328 	// column completed
329 	renderer = gtk_cell_renderer_text_new ();
330 
331 	dlv->col_completed = gtk_tree_view_column_new ();
332 	gtk_tree_view_column_set_title (dlv->col_completed, _("Completed"));
333 	gtk_tree_view_column_pack_start (dlv->col_completed, renderer, TRUE);
334 	gtk_tree_view_column_set_cell_data_func (dlv->col_completed,
335 	                                         renderer,
336 	                                         col_set_completed,
337 	                                         NULL, NULL);
338 	gtk_tree_view_column_set_resizable (dlv->col_completed, TRUE);
339 	gtk_tree_view_append_column (dlv->self, dlv->col_completed);
340 
341 	// column total
342 	dlv->col_total = gtk_tree_view_column_new ();
343 	gtk_tree_view_column_set_title (dlv->col_total, _("Total"));
344 	gtk_tree_view_column_pack_start (dlv->col_total, renderer, TRUE);
345 	gtk_tree_view_column_set_cell_data_func (dlv->col_total,
346 	                                         renderer,
347 	                                         col_set_total,
348 	                                         NULL, NULL);
349 	gtk_tree_view_column_set_resizable (dlv->col_total, TRUE);
350 	gtk_tree_view_column_set_min_width (dlv->col_total, 60);
351 	gtk_tree_view_append_column (dlv->self, dlv->col_total);
352 
353 	// column percent
354 	dlv->col_percent = gtk_tree_view_column_new ();
355 	gtk_tree_view_column_set_title (dlv->col_percent, _("%"));
356 	gtk_tree_view_column_pack_start (dlv->col_percent, renderer, TRUE);
357 	gtk_tree_view_column_set_cell_data_func (dlv->col_percent,
358 	                                         renderer,
359 	                                         col_set_percent,
360 	                                         NULL, NULL);
361 	gtk_tree_view_column_set_resizable (dlv->col_percent, TRUE);
362 	gtk_tree_view_column_set_min_width (dlv->col_percent, 50);
363 	gtk_tree_view_append_column (dlv->self, dlv->col_percent);
364 
365 	// columns speed
366 	dlv->col_speed = gtk_tree_view_column_new ();
367 	gtk_tree_view_column_set_title (dlv->col_speed, _("Speed"));
368 	gtk_tree_view_column_pack_start (dlv->col_speed, renderer, TRUE);
369 	gtk_tree_view_column_set_cell_data_func (dlv->col_speed,
370 	                                         renderer,
371 	                                         col_set_speed,
372 	                                         NULL, NULL);
373 	gtk_tree_view_column_set_resizable (dlv->col_speed, TRUE);
374 	gtk_tree_view_column_set_min_width (dlv->col_speed, 60);
375 	gtk_tree_view_append_column (dlv->self, dlv->col_speed);
376 
377 	// column retries
378 	dlv->col_retry = gtk_tree_view_column_new ();
379 	gtk_tree_view_column_set_title (dlv->col_retry, _("Retry"));
380 	gtk_tree_view_column_pack_start (dlv->col_retry, renderer, TRUE);
381 	gtk_tree_view_column_set_cell_data_func (dlv->col_retry,
382 	                                         renderer,
383 	                                         col_set_retry,
384 	                                         NULL, NULL);
385 //	gtk_tree_view_column_set_sizing (dlv->col_retry, GTK_TREE_VIEW_COLUMN_FIXED);
386 	gtk_tree_view_column_set_resizable (dlv->col_retry, TRUE);
387 	gtk_tree_view_append_column (dlv->self, dlv->col_retry);
388 
389 	// column url
390 	dlv->col_url = gtk_tree_view_column_new ();
391 	gtk_tree_view_column_set_title (dlv->col_url, _("URL"));
392 	renderer = gtk_cell_renderer_text_new ();
393 	gtk_tree_view_column_pack_start (dlv->col_url, renderer, TRUE);
394 	gtk_tree_view_column_set_cell_data_func (dlv->col_url,
395 	                                         renderer,
396 	                                         col_set_url,
397 	                                         NULL, NULL);
398 	gtk_tree_view_column_set_resizable (dlv->col_url, TRUE);
399 	gtk_tree_view_append_column (dlv->self, dlv->col_url);
400 
401 	// show all widget
402 	gtk_widget_show_all ((GtkWidget*)dlv->container);
403 }
404 
download_list_view_clear(DownloadListView * dlv)405 void download_list_view_clear (DownloadListView* dlv)
406 {
407 	gtk_widget_hide ((GtkWidget*)dlv->container);
408 
409 	g_object_unref (dlv->container);
410 }
411 
download_list_view_hide_runtime_state(DownloadListView * dlv)412 void download_list_view_hide_runtime_state (DownloadListView* dlv)
413 {
414 	gtk_tree_view_column_set_visible (dlv->col_completed, FALSE);
415 	gtk_tree_view_column_set_visible (dlv->col_percent, FALSE);
416 	gtk_tree_view_column_set_visible (dlv->col_retry, FALSE);
417 	gtk_tree_view_column_set_visible (dlv->col_speed, FALSE);
418 	gtk_tree_view_column_set_visible (dlv->col_total, FALSE);
419 }
420 
download_list_view_selected_list_copy(DownloadListView * dlv,gint * n_selected)421 GList* download_list_view_selected_list_copy (DownloadListView* dlv, gint* n_selected)
422 {
423 	GtkTreeSelection* selection;
424 	GtkTreeModel*     model;
425 	GtkTreeIter       iter;
426 	GList*            selected_list = NULL;
427 	GList*            node;
428 	Download*         dl_data;
429 	guint             n_iter;
430 
431 	selection = gtk_tree_view_get_selection (dlv->self);
432 	download_store_lock (dlv->store);
433 	if (n_iter = gtk_tree_selection_count_selected_rows (selection)) {
434 		selected_list = gtk_tree_selection_get_selected_rows (selection, &model);
435 		for (node=selected_list; node; node=node->next) {
436 			gtk_tree_model_get_iter (model, &iter, node->data);
437 			gtk_tree_model_get (model, &iter, DOWNLOAD_COL_DATA, &dl_data, -1);
438 			gtk_tree_path_free (node->data);
439 			node->data = dl_data;
440 			download_ref (dl_data);
441 		}
442 	}
443 	download_store_unlock (dlv->store);
444 
445 	if (n_selected)
446 		*n_selected = n_iter;
447 
448 	return selected_list;
449 }
450 
download_list_view_selected_list_free(GList * list)451 void  download_list_view_selected_list_free (GList* list)
452 {
453 	g_list_foreach (list, (GFunc)download_unref, NULL);
454 	g_list_free (list);
455 }
456 
457