Mercurial > pidgin.yaz
comparison src/gtkft.c @ 4514:7521e29658bc
[gaim-migrate @ 4792]
Of course, file transfer wasn't really gone..
I'm trying my hardest to bring on the end of the world (see the roadmap at
http://gaim.sf.net/roadmap.png). File transfer is being rewritten. This
isn't the finished implementation, but it's enough to let us get the prpls
working.
There is now a file transfer dialog, which will appear when you get a new
transfer request or when you go to Tools -> File Transfers.
This is of course core/UI split. I'll also be working on documentation on
how to write FT support in a prpl. Oh, and I'll get resumes and transfer
batches done when school isn't breathing down my back.
Only DCC receive in IRC currently works. Sorry. We'll get the other prpls
working soon, as well as send.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Tue, 04 Feb 2003 06:57:35 +0000 |
parents | |
children | a2b2cce63fb8 |
comparison
equal
deleted
inserted
replaced
4513:adb0245e1dfc | 4514:7521e29658bc |
---|---|
1 /** | |
2 * @file gtkft.c The GTK+ file transfer UI | |
3 * | |
4 * gaim | |
5 * | |
6 * Copyright (C) 2003, Christian Hammond <chipx86@gnupdate.org> | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
23 #include "gaim.h" | |
24 #include "prpl.h" | |
25 #include <sys/types.h> | |
26 #include <sys/stat.h> | |
27 #include <unistd.h> | |
28 #include <string.h> | |
29 #include "gtkcellrendererprogress.h" | |
30 | |
31 struct gaim_gtkxfer_dialog | |
32 { | |
33 GtkWidget *window; | |
34 GtkWidget *tree; | |
35 GtkListStore *model; | |
36 }; | |
37 | |
38 struct gaim_gtkxfer_ui_data | |
39 { | |
40 GtkWidget *filesel; | |
41 GtkTreeIter iter; | |
42 time_t start_time; | |
43 | |
44 char *name; | |
45 }; | |
46 | |
47 static struct gaim_gtkxfer_dialog *xfer_dialog = NULL; | |
48 | |
49 enum | |
50 { | |
51 COLUMN_STATUS = 0, | |
52 COLUMN_USER, | |
53 COLUMN_FILENAME, | |
54 COLUMN_PROGRESS, | |
55 COLUMN_SIZE, | |
56 COLUMN_REMAINING, | |
57 COLUMN_ESTIMATE, | |
58 COLUMN_SPEED, | |
59 NUM_COLUMNS | |
60 }; | |
61 | |
62 static gint | |
63 delete_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d) | |
64 { | |
65 gaim_gtkxfer_dialog_hide(); | |
66 | |
67 return TRUE; | |
68 } | |
69 | |
70 static void | |
71 close_win_cb(GtkButton *button, gpointer user_data) | |
72 { | |
73 gaim_gtkxfer_dialog_hide(); | |
74 } | |
75 | |
76 static struct gaim_gtkxfer_dialog * | |
77 build_xfer_dialog(void) | |
78 { | |
79 struct gaim_gtkxfer_dialog *dialog; | |
80 GtkWidget *window; | |
81 GtkWidget *vbox; | |
82 GtkWidget *hbox; | |
83 GtkWidget *frame; | |
84 GtkWidget *sw; | |
85 GtkWidget *sep; | |
86 GtkWidget *button; | |
87 GtkWidget *tree; | |
88 GtkTreeViewColumn *column; | |
89 GtkListStore *model; | |
90 GtkCellRenderer *renderer; | |
91 GtkSizeGroup *sg; | |
92 | |
93 dialog = g_malloc0(sizeof(struct gaim_gtkxfer_dialog)); | |
94 | |
95 /* Create the window. */ | |
96 dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
97 gtk_window_set_role(GTK_WINDOW(window), "file transfer"); | |
98 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE); | |
99 gtk_window_set_default_size(GTK_WINDOW(window), 550, 250); | |
100 gtk_container_border_width(GTK_CONTAINER(window), 0); | |
101 gtk_widget_realize(window); | |
102 | |
103 g_signal_connect(G_OBJECT(window), "delete_event", | |
104 G_CALLBACK(delete_win_cb), dialog); | |
105 | |
106 /* Create the parent vbox for everything. */ | |
107 vbox = gtk_vbox_new(FALSE, 6); | |
108 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6); | |
109 gtk_container_add(GTK_CONTAINER(window), vbox); | |
110 gtk_widget_show(vbox); | |
111 | |
112 /* Create the scrolled window. */ | |
113 sw = gtk_scrolled_window_new(0, 0); | |
114 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
115 GTK_POLICY_AUTOMATIC, | |
116 GTK_POLICY_ALWAYS); | |
117 gtk_widget_show(sw); | |
118 | |
119 /* Build the tree model */ | |
120 /* Transfer type, User, Filename, Progress Bar, Size, Remaining */ | |
121 dialog->model = model = gtk_list_store_new(NUM_COLUMNS, | |
122 GDK_TYPE_PIXBUF, G_TYPE_STRING, | |
123 G_TYPE_STRING, G_TYPE_DOUBLE, | |
124 G_TYPE_LONG, G_TYPE_LONG, | |
125 G_TYPE_STRING, G_TYPE_STRING); | |
126 | |
127 /* Create the treeview */ | |
128 dialog->tree = tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model)); | |
129 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE); | |
130 gtk_tree_selection_set_mode( | |
131 gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)), | |
132 GTK_SELECTION_MULTIPLE); | |
133 gtk_widget_show(tree); | |
134 | |
135 g_object_unref(G_OBJECT(model)); | |
136 | |
137 | |
138 /* Columns */ | |
139 | |
140 /* Transfer Type column */ | |
141 renderer = gtk_cell_renderer_pixbuf_new(); | |
142 column = gtk_tree_view_column_new_with_attributes(NULL, renderer, | |
143 "pixbuf", COLUMN_STATUS, NULL); | |
144 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), | |
145 GTK_TREE_VIEW_COLUMN_FIXED); | |
146 gtk_tree_view_column_set_fixed_width(GTK_TREE_VIEW_COLUMN(column), 25); | |
147 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
148 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
149 | |
150 /* User column */ | |
151 renderer = gtk_cell_renderer_text_new(); | |
152 column = gtk_tree_view_column_new_with_attributes(_("User"), renderer, | |
153 "text", COLUMN_USER, NULL); | |
154 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
155 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
156 | |
157 /* Filename column */ | |
158 renderer = gtk_cell_renderer_text_new(); | |
159 column = gtk_tree_view_column_new_with_attributes(_("Filename"), renderer, | |
160 "text", COLUMN_FILENAME, NULL); | |
161 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
162 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
163 | |
164 /* Progress bar column */ | |
165 renderer = gtk_cell_renderer_progress_new(); | |
166 column = gtk_tree_view_column_new_with_attributes(_("Progress"), renderer, | |
167 "percentage", COLUMN_PROGRESS, NULL); | |
168 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
169 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
170 | |
171 /* File Size column */ | |
172 renderer = gtk_cell_renderer_text_new(); | |
173 column = gtk_tree_view_column_new_with_attributes(_("Size"), renderer, | |
174 "text", COLUMN_SIZE, NULL); | |
175 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
176 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
177 | |
178 /* Bytes Remaining column */ | |
179 renderer = gtk_cell_renderer_text_new(); | |
180 column = gtk_tree_view_column_new_with_attributes(_("Remaining"), | |
181 renderer, "text", COLUMN_REMAINING, NULL); | |
182 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
183 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
184 | |
185 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree)); | |
186 | |
187 /* ETA column */ | |
188 renderer = gtk_cell_renderer_text_new(); | |
189 column = gtk_tree_view_column_new_with_attributes(_("ETA"), | |
190 renderer, "text", COLUMN_ESTIMATE, NULL); | |
191 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
192 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
193 | |
194 /* Speed column */ | |
195 renderer = gtk_cell_renderer_text_new(); | |
196 column = gtk_tree_view_column_new_with_attributes(_("Speed"), | |
197 renderer, "text", COLUMN_SPEED, NULL); | |
198 gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); | |
199 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); | |
200 | |
201 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree)); | |
202 | |
203 gtk_container_add(GTK_CONTAINER(sw), tree); | |
204 gtk_widget_show(tree); | |
205 | |
206 /* Create the outer frame for the scrolled window. */ | |
207 frame = gtk_frame_new(NULL), | |
208 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); | |
209 gtk_container_add(GTK_CONTAINER(frame), sw); | |
210 gtk_widget_show(frame); | |
211 | |
212 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); | |
213 | |
214 /* Separator */ | |
215 sep = gtk_hseparator_new(); | |
216 gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0); | |
217 gtk_widget_show(sep); | |
218 | |
219 /* Now the hbox for the buttons */ | |
220 hbox = gtk_hbox_new(FALSE, 6); | |
221 gtk_container_set_border_width(GTK_CONTAINER(hbox), 6); | |
222 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
223 gtk_widget_show(hbox); | |
224 | |
225 sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); | |
226 | |
227 /* Close button */ | |
228 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
229 g_signal_connect(G_OBJECT(button), "clicked", | |
230 G_CALLBACK(close_win_cb), NULL); | |
231 gtk_size_group_add_widget(sg, button); | |
232 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
233 gtk_widget_show(button); | |
234 | |
235 #if 0 | |
236 /* Cancel button */ | |
237 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL); | |
238 gtk_size_group_add_widget(sg, button); | |
239 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); | |
240 gtk_widget_show(button); | |
241 #endif | |
242 | |
243 return dialog; | |
244 } | |
245 | |
246 static void | |
247 gaim_gtkxfer_destroy(struct gaim_xfer *xfer) | |
248 { | |
249 struct gaim_gtkxfer_ui_data *data; | |
250 | |
251 data = xfer->ui_data; | |
252 | |
253 if (data == NULL) | |
254 return; | |
255 } | |
256 | |
257 static gboolean | |
258 choose_file_close_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) | |
259 { | |
260 gaim_xfer_request_denied((struct gaim_xfer *)user_data); | |
261 | |
262 return FALSE; | |
263 } | |
264 | |
265 static void | |
266 choose_file_cancel_cb(GtkButton *button, gpointer user_data) | |
267 { | |
268 struct gaim_xfer *xfer = (struct gaim_xfer *)user_data; | |
269 struct gaim_gtkxfer_ui_data *data; | |
270 | |
271 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
272 | |
273 gaim_xfer_request_denied(xfer); | |
274 | |
275 gtk_widget_destroy(data->filesel); | |
276 data->filesel = NULL; | |
277 } | |
278 | |
279 static int | |
280 do_overwrite_cb(struct gaim_xfer *xfer) | |
281 { | |
282 struct gaim_gtkxfer_ui_data *data; | |
283 | |
284 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
285 | |
286 gaim_xfer_request_accepted(xfer, data->name); | |
287 | |
288 /* | |
289 * No, we don't want to free data->name. gaim_xfer_request_accepted | |
290 * will deal with it. | |
291 */ | |
292 data->name = NULL; | |
293 | |
294 return 0; | |
295 } | |
296 | |
297 static int | |
298 dont_overwrite_cb(struct gaim_xfer *xfer) | |
299 { | |
300 struct gaim_gtkxfer_ui_data *data; | |
301 | |
302 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
303 | |
304 g_free(data->name); | |
305 data->name = NULL; | |
306 | |
307 gaim_xfer_request_denied(xfer); | |
308 | |
309 return 0; | |
310 } | |
311 | |
312 static void | |
313 choose_file_ok_cb(GtkButton *button, gpointer user_data) | |
314 { | |
315 struct gaim_xfer *xfer; | |
316 struct gaim_gtkxfer_ui_data *data; | |
317 struct stat st; | |
318 const char *name; | |
319 | |
320 xfer = (struct gaim_xfer *)user_data; | |
321 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
322 | |
323 name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(data->filesel)); | |
324 | |
325 if (stat(name, &st) == 0) { | |
326 if (S_ISDIR(st.st_mode)) { | |
327 /* XXX */ | |
328 gaim_xfer_request_denied(xfer); | |
329 } | |
330 else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
331 data->name = g_strdup(name); | |
332 | |
333 do_ask_dialog(_("That file already exists. " | |
334 "Would you like to overwrite it?"), | |
335 NULL, xfer, | |
336 _("Yes"), do_overwrite_cb, | |
337 _("No"), dont_overwrite_cb, | |
338 NULL, FALSE); | |
339 } | |
340 else { | |
341 gaim_xfer_request_accepted(xfer, g_strdup(name)); | |
342 } | |
343 } | |
344 else { | |
345 /* File not found. */ | |
346 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
347 gaim_xfer_request_accepted(xfer, g_strdup(name)); | |
348 } | |
349 else { | |
350 do_error_dialog(_("That file does not exist."), | |
351 NULL, GAIM_ERROR); | |
352 | |
353 gaim_xfer_request_denied(xfer); | |
354 } | |
355 } | |
356 | |
357 gtk_widget_destroy(data->filesel); | |
358 data->filesel = NULL; | |
359 } | |
360 | |
361 static int | |
362 choose_file(struct gaim_xfer *xfer) | |
363 { | |
364 char *cur_dir, *init_str; | |
365 struct gaim_gtkxfer_ui_data *data; | |
366 | |
367 cur_dir = g_get_current_dir(); | |
368 | |
369 /* This is where we're setting xfer->ui_data for the first time. */ | |
370 data = g_malloc0(sizeof(struct gaim_gtkxfer_ui_data)); | |
371 xfer->ui_data = data; | |
372 | |
373 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) | |
374 data->filesel = gtk_file_selection_new(_("Gaim - Open...")); | |
375 else | |
376 data->filesel = gtk_file_selection_new(_("Gaim - Save As...")); | |
377 | |
378 if (gaim_xfer_get_filename(xfer) == NULL) | |
379 init_str = g_strdup(cur_dir); | |
380 else | |
381 init_str = g_build_filename(cur_dir, gaim_xfer_get_filename(xfer), | |
382 NULL); | |
383 | |
384 g_free(cur_dir); | |
385 | |
386 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data->filesel), | |
387 init_str); | |
388 | |
389 g_free(init_str); | |
390 | |
391 g_signal_connect(G_OBJECT(data->filesel), "delete_event", | |
392 G_CALLBACK(choose_file_close_cb), xfer); | |
393 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(data->filesel)->cancel_button), | |
394 "clicked", | |
395 G_CALLBACK(choose_file_cancel_cb), xfer); | |
396 g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(data->filesel)->ok_button), | |
397 "clicked", | |
398 G_CALLBACK(choose_file_ok_cb), xfer); | |
399 | |
400 gtk_widget_show(data->filesel); | |
401 | |
402 return 0; | |
403 } | |
404 | |
405 static int | |
406 cancel_recv_cb(struct gaim_xfer *xfer) | |
407 { | |
408 gaim_xfer_request_denied(xfer); | |
409 | |
410 return 0; | |
411 } | |
412 | |
413 static void | |
414 gaim_gtkxfer_ask_recv(struct gaim_xfer *xfer) | |
415 { | |
416 static const char *size_str[4] = { "bytes", "KB", "MB", "GB" }; | |
417 char *buf; | |
418 char *size_buf; | |
419 float size_mag; | |
420 size_t size; | |
421 int size_index = 0; | |
422 | |
423 size = gaim_xfer_get_size(xfer); | |
424 size_mag = (float)size; | |
425 | |
426 while ((size_index < 4) && (size_mag > 1024)) { | |
427 size_mag /= 1024; | |
428 size_index++; | |
429 } | |
430 | |
431 if (size == -1) | |
432 size_buf = g_strdup_printf(_("Unknown size")); | |
433 else | |
434 size_buf = g_strdup_printf("%.3g %s", size_mag, size_str[size_index]); | |
435 | |
436 buf = g_strdup_printf(_("%s wants to send you %s (%s)"), | |
437 xfer->who, gaim_xfer_get_filename(xfer), size_buf); | |
438 | |
439 g_free(size_buf); | |
440 | |
441 do_ask_dialog(buf, NULL, xfer, | |
442 _("Accept"), choose_file, | |
443 _("Cancel"), cancel_recv_cb, | |
444 NULL, FALSE); | |
445 | |
446 g_free(buf); | |
447 } | |
448 | |
449 static void | |
450 gaim_gtkxfer_request_file(struct gaim_xfer *xfer) | |
451 { | |
452 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) | |
453 { | |
454 gaim_gtkxfer_ask_recv(xfer); | |
455 } | |
456 else | |
457 { | |
458 choose_file(xfer); | |
459 } | |
460 } | |
461 | |
462 static void | |
463 gaim_gtkxfer_ask_cancel(struct gaim_xfer *xfer) | |
464 { | |
465 } | |
466 | |
467 static void | |
468 gaim_gtkxfer_add_xfer(struct gaim_xfer *xfer) | |
469 { | |
470 struct gaim_gtkxfer_ui_data *data; | |
471 GaimXferType type; | |
472 GdkPixbuf *pixbuf; | |
473 | |
474 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
475 | |
476 gaim_gtkxfer_dialog_show(); | |
477 | |
478 data->start_time = time(NULL); | |
479 | |
480 type = gaim_xfer_get_type(xfer); | |
481 | |
482 pixbuf = gtk_widget_render_icon(xfer_dialog->window, | |
483 (type == GAIM_XFER_RECEIVE | |
484 ? GAIM_STOCK_DOWNLOAD | |
485 : GAIM_STOCK_UPLOAD), | |
486 GTK_ICON_SIZE_MENU, NULL); | |
487 | |
488 gtk_list_store_append(xfer_dialog->model, &data->iter); | |
489 gtk_list_store_set(xfer_dialog->model, &data->iter, | |
490 COLUMN_STATUS, pixbuf, | |
491 COLUMN_USER, xfer->who, | |
492 COLUMN_FILENAME, gaim_xfer_get_filename(xfer), | |
493 COLUMN_PROGRESS, 0.0, | |
494 COLUMN_SIZE, gaim_xfer_get_size(xfer), | |
495 COLUMN_REMAINING, gaim_xfer_get_bytes_remaining(xfer), | |
496 COLUMN_ESTIMATE, NULL, | |
497 COLUMN_SPEED, NULL, | |
498 -1); | |
499 | |
500 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(xfer_dialog->tree)); | |
501 | |
502 g_object_unref(pixbuf); | |
503 } | |
504 | |
505 static void | |
506 gaim_gtkxfer_update_progress(struct gaim_xfer *xfer, double percent) | |
507 { | |
508 struct gaim_gtkxfer_ui_data *data; | |
509 time_t now; | |
510 char speed_buf[256]; | |
511 char estimate_buf[256]; | |
512 double kb_sent, kb_rem; | |
513 double kbps = 0.0; | |
514 time_t elapsed; | |
515 int secs_remaining; | |
516 | |
517 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
518 | |
519 now = time(NULL); | |
520 kb_rem = gaim_xfer_get_bytes_remaining(xfer) / 1024.0; | |
521 kb_sent = gaim_xfer_get_bytes_sent(xfer) / 1024.0; | |
522 elapsed = (now - data->start_time); | |
523 kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); | |
524 | |
525 secs_remaining = (int)(kb_rem / kbps); | |
526 | |
527 if (secs_remaining <= 0) { | |
528 GdkPixbuf *pixbuf = NULL; | |
529 | |
530 *speed_buf = '\0'; | |
531 strncpy(estimate_buf, _("Done."), sizeof(estimate_buf)); | |
532 | |
533 pixbuf = gtk_widget_render_icon(xfer_dialog->window, | |
534 GAIM_STOCK_FILE_DONE, | |
535 GTK_ICON_SIZE_MENU, NULL); | |
536 | |
537 gtk_list_store_set(xfer_dialog->model, &data->iter, | |
538 COLUMN_STATUS, pixbuf, | |
539 -1); | |
540 | |
541 g_object_unref(pixbuf); | |
542 } | |
543 else { | |
544 int h = secs_remaining / 3600; | |
545 int m = (secs_remaining % 3600) / 60; | |
546 int s = secs_remaining % 60; | |
547 | |
548 g_snprintf(estimate_buf, sizeof(estimate_buf), | |
549 _("%d:%02d:%02d"), h, m, s); | |
550 g_snprintf(speed_buf, sizeof(speed_buf), | |
551 _("%.2f KB/s"), kbps); | |
552 } | |
553 | |
554 gtk_list_store_set(xfer_dialog->model, &data->iter, | |
555 COLUMN_REMAINING, gaim_xfer_get_bytes_remaining(xfer), | |
556 COLUMN_PROGRESS, percent, | |
557 COLUMN_ESTIMATE, estimate_buf, | |
558 COLUMN_SPEED, speed_buf, | |
559 -1); | |
560 } | |
561 | |
562 static void | |
563 gaim_gtkxfer_cancel(struct gaim_xfer *xfer) | |
564 { | |
565 struct gaim_gtkxfer_ui_data *data; | |
566 GdkPixbuf *pixbuf; | |
567 | |
568 data = (struct gaim_gtkxfer_ui_data *)xfer->ui_data; | |
569 | |
570 pixbuf = gtk_widget_render_icon(xfer_dialog->window, | |
571 GAIM_STOCK_FILE_CANCELED, | |
572 GTK_ICON_SIZE_MENU, NULL); | |
573 | |
574 gtk_list_store_set(xfer_dialog->model, &data->iter, | |
575 COLUMN_STATUS, pixbuf, | |
576 -1); | |
577 | |
578 g_object_unref(pixbuf); | |
579 } | |
580 | |
581 struct gaim_xfer_ui_ops ops = | |
582 { | |
583 gaim_gtkxfer_destroy, | |
584 gaim_gtkxfer_request_file, | |
585 gaim_gtkxfer_ask_cancel, | |
586 gaim_gtkxfer_add_xfer, | |
587 gaim_gtkxfer_update_progress, | |
588 gaim_gtkxfer_cancel | |
589 }; | |
590 | |
591 void | |
592 gaim_gtkxfer_dialog_show(void) | |
593 { | |
594 if (xfer_dialog == NULL) | |
595 xfer_dialog = build_xfer_dialog(); | |
596 | |
597 gtk_widget_show(xfer_dialog->window); | |
598 } | |
599 | |
600 void | |
601 gaim_gtkxfer_dialog_hide(void) | |
602 { | |
603 gtk_widget_hide(xfer_dialog->window); | |
604 } | |
605 | |
606 struct gaim_xfer_ui_ops * | |
607 gaim_get_gtk_xfer_ui_ops(void) | |
608 { | |
609 return &ops; | |
610 } |