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 >e, 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