00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00040 #include "progress.h"
00041
00042 #include <string.h>
00043 #include <glib.h>
00044 #include <gdk/gdkkeysyms.h>
00045 #include <gtk/gtk.h>
00046
00047 #include "frontend.h"
00048
00049 #include "fe_gtk.h"
00050 #include "fe_data.h"
00051 #include "ui.h"
00052 #ifdef DI_UDEB
00053 # include "di.h"
00054 #endif
00055
00057 #define PROGRESSBAR_HPADDING 60
00058
00059 #define PROGRESSBAR_VPADDING 60
00060
00065 struct progress_data {
00067 struct frontend * fe;
00068
00070 GtkWidget * progress_bar;
00071
00073 GtkWidget * progress_label;
00074
00076 GtkWidget * progress_box;
00077
00082 GtkWidget * cancel_button;
00083 };
00084
00090 static void create_progress_bar(struct progress_data * progress_data,
00091 GtkWidget * container)
00092 {
00093 GtkWidget * progress_bar;
00094
00095
00096 progress_bar = gtk_progress_bar_new();
00097
00098 gtk_progress_bar_set_ellipsize(GTK_PROGRESS_BAR(progress_bar),
00099 PANGO_ELLIPSIZE_MIDDLE);
00100
00101 gtk_box_pack_start(GTK_BOX(container), progress_bar,
00102 FALSE ,
00103 FALSE , 0 );
00104
00105 g_object_ref(G_OBJECT(progress_bar));
00106 progress_data->progress_bar = progress_bar;
00107 }
00108
00115 static void destroy_progress_bar(struct progress_data * progress_data)
00116 {
00117 GtkWidget * progress_bar = progress_data->progress_bar;
00118
00119 if (NULL != progress_bar) {
00120 progress_data->progress_bar = NULL;
00121 g_object_unref(progress_bar);
00122
00123 }
00124 }
00125
00131 static void create_progress_label(struct progress_data * progress_data,
00132 GtkWidget * container)
00133 {
00134 GtkWidget * progress_label;
00135
00136
00137 progress_label = gtk_label_new(NULL );
00138
00139 gtk_misc_set_alignment(GTK_MISC(progress_label),
00140 0 , 0 );
00141
00142 gtk_box_pack_start(GTK_BOX(container), progress_label,
00143 FALSE , FALSE ,
00144 DEFAULT_PADDING);
00145
00146 g_object_ref(G_OBJECT(progress_label));
00147 progress_data->progress_label = progress_label;
00148 }
00149
00156 static void destroy_progress_label(struct progress_data * progress_data)
00157 {
00158 GtkWidget * progress_label = progress_data->progress_label;
00159
00160 if (NULL != progress_label) {
00161 progress_data->progress_label = NULL;
00162 g_object_unref(progress_label);
00163
00164 }
00165 }
00166
00172 static void create_progress_box(struct progress_data * progress_data)
00173 {
00174 GtkWidget * progress_box;
00175
00176
00177 progress_box = gtk_vbox_new(FALSE ,
00178 0 );
00179
00180 create_progress_bar(progress_data, progress_box);
00181 create_progress_label(progress_data, progress_box);
00182
00183 fe_gtk_center_widget(&progress_box, PROGRESSBAR_HPADDING,
00184 PROGRESSBAR_VPADDING);
00185
00186 g_object_ref(G_OBJECT(progress_box));
00187 progress_data->progress_box = progress_box;
00188 }
00189
00196 static void destroy_progress_box(struct progress_data * progress_data)
00197 {
00198 GtkWidget * progress_box = progress_data->progress_box;
00199
00200 if (NULL != progress_box) {
00201 progress_data->progress_box = NULL;
00202 g_object_unref(progress_box);
00203 gtk_widget_destroy(progress_box);
00204 }
00205 destroy_progress_label(progress_data);
00206 destroy_progress_bar(progress_data);
00207 }
00208
00216 void fe_gtk_show_progress(struct frontend * fe)
00217 {
00218 struct frontend_data * fe_data = fe->data;
00219 struct progress_data * progress_data = fe_data->progress_data;
00220
00221 g_assert(NULL != progress_data);
00222 if (NULL == gtk_widget_get_parent(progress_data->progress_box)) {
00223 gtk_box_pack_start(
00224 GTK_BOX(fe_data->target_box), progress_data->progress_box,
00225 FALSE , FALSE , DEFAULT_PADDING);
00226 }
00227 if (NULL != progress_data->cancel_button &&
00228 NULL == gtk_widget_get_parent(progress_data->cancel_button)) {
00229 gtk_box_pack_start(
00230 GTK_BOX(fe_data->action_box), progress_data->cancel_button,
00231 TRUE , TRUE , DEFAULT_PADDING);
00232 }
00233 gtk_widget_show_all(progress_data->progress_box);
00234 gtk_widget_show_all(fe_data->action_box);
00235 }
00236
00245 void fe_gtk_hide_progress(struct frontend * fe)
00246 {
00247 struct frontend_data * fe_data = fe->data;
00248 struct progress_data * progress_data = fe_data->progress_data;
00249
00250 if (NULL != progress_data) {
00251 if (NULL != progress_data->progress_box) {
00252 g_warning("removing progress_box");
00253 gtk_container_remove(GTK_CONTAINER(fe_data->target_box),
00254 progress_data->progress_box);
00255 }
00256 if (NULL != progress_data->cancel_button) {
00257 g_warning("removing cancel_button");
00258 gtk_container_remove(GTK_CONTAINER(fe_data->target_box),
00259 progress_data->cancel_button);
00260 }
00261 }
00262 }
00263
00271 static gboolean handle_cancel_key(GtkWidget * widget, GdkEventKey * key,
00272 struct frontend * fe)
00273 {
00274 if (GDK_Escape == key->keyval) {
00275 fe_gtk_set_answer_goback(fe);
00276 return TRUE;
00277 }
00278 return FALSE;
00279 }
00280
00286 static void create_cancel_button(struct progress_data * progress_data)
00287 {
00288 struct frontend * fe = progress_data->fe;
00289 GtkWidget * button;
00290 char * label;
00291
00292
00293 label = fe_gtk_get_text(fe, "debconf/button-cancel", "Cancel");
00294 button = gtk_button_new_with_label(label);
00295 g_free(label);
00296
00297 g_signal_connect(G_OBJECT(button), "clicked",
00298 G_CALLBACK(fe_gtk_set_answer_goback), fe);
00299 fe_gtk_add_global_key_handler(fe, button, G_CALLBACK(handle_cancel_key));
00300 fe_gtk_add_button(fe, button);
00301
00302 g_object_ref(G_OBJECT(button));
00303 progress_data->cancel_button = button;
00304 }
00305
00310 static void destroy_cancel_button(struct progress_data * progress_data)
00311 {
00312 GtkWidget * cancel_button = progress_data->cancel_button;
00313
00314 if (NULL != cancel_button) {
00315 progress_data->cancel_button = NULL;
00316 g_object_unref(G_OBJECT(cancel_button));
00317 gtk_widget_destroy(cancel_button);
00318 }
00319 }
00320
00326 bool fe_gtk_can_cancel_progress(struct frontend * fe)
00327 {
00328 return DCF_CAPB_PROGRESSCANCEL ==
00329 (fe->capability & DCF_CAPB_PROGRESSCANCEL);
00330 }
00331
00339 static gboolean init_progress(struct frontend * fe)
00340 {
00341 struct frontend_data * fe_data = fe->data;
00342 struct progress_data * progress_data;
00343
00344 g_assert(NULL == fe_data->progress_data);
00345
00346 if (NULL == (progress_data = g_malloc0(sizeof (struct progress_data)))) {
00347 g_warning("g_malloc0 failed.");
00348 return FALSE;
00349 }
00350 progress_data->fe = fe;
00351 create_progress_box(progress_data);
00352 if (CAN_CANCEL_PROGRESS(fe)) {
00353 create_cancel_button(progress_data);
00354 }
00355 fe_data->progress_data = progress_data;
00356
00357 return TRUE;
00358 }
00359
00364 static void destroy_progress(struct frontend * fe)
00365 {
00366 struct frontend_data * fe_data = fe->data;
00367 struct progress_data * progress_data = fe_data->progress_data;
00368
00369 if (NULL == progress_data) {
00370 return;
00371 }
00372 fe_data->progress_data = NULL;
00373 destroy_cancel_button(progress_data);
00374 destroy_progress_box(progress_data);
00375 g_free(progress_data);
00376 }
00377
00385 static void update_progress_bar(struct frontend * fe, gdouble fraction)
00386 {
00387 struct frontend_data * fe_data = fe->data;
00388 GtkWidget * progress_bar = fe_data->progress_data->progress_bar;
00389
00390 g_assert(NULL != progress_bar);
00391
00392 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar),
00393 fe->progress_title);
00394 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar),
00395 fraction );
00396 }
00397
00405 void fe_gtk_progress_start(struct frontend * fe, int min, int max,
00406 const char * title)
00407 {
00408 struct frontend_data * fe_data = fe->data;
00409
00410 if (NULL != fe_data->setters) {
00411
00412 return;
00413 }
00414 if (NULL != fe_data->progress_data) {
00415
00416 fe_gtk_progress_stop(fe);
00417 }
00418 fe_gtk_set_answer(fe, DC_NO_ANSWER);
00419
00420 gdk_threads_enter();
00421
00422 #ifdef DI_UDEB
00423 fe_gtk_di_run_dialog(fe);
00424 #endif
00425
00426 init_progress(fe);
00427
00428 g_free(fe->progress_title);
00429 fe->progress_title = g_strdup(title);
00430
00431 update_progress_bar(fe, 0.0 );
00432
00433
00434
00435
00436 fe->progress_min = min;
00437 fe->progress_max = max;
00438 fe->progress_cur = min;
00439
00440
00441 fe_gtk_show_progress(fe);
00442
00443 gdk_threads_leave();
00444 }
00445
00453 int fe_gtk_progress_set(struct frontend * fe, int val)
00454 {
00455 struct frontend_data * fe_data = fe->data;
00456 gdouble progress;
00457
00458
00459 if (fe->progress_max < val || fe->progress_min > val) {
00460 return DC_NOTOK;
00461 }
00462 if (NULL == fe_data->progress_data) {
00463
00464 return DC_NOTOK;
00465 }
00466
00467 gdk_threads_enter();
00468 fe->progress_cur = val;
00469 if ((fe->progress_max - fe->progress_min) > 0) {
00470 progress = (gdouble) (fe->progress_cur - fe->progress_min) /
00471 (gdouble) (fe->progress_max - fe->progress_min);
00472 update_progress_bar(fe, progress);
00473 }
00474 fe_gtk_show_progress(fe);
00475 gdk_threads_leave();
00476
00477 return fe_data->answer;
00478 }
00479
00488 int fe_gtk_progress_info(struct frontend * fe, const char * info)
00489 {
00490 struct frontend_data * fe_data = fe->data;
00491 struct progress_data * progress_data = fe_data->progress_data;
00492 char * label;
00493
00494 if (NULL == progress_data) {
00495
00496 return DC_NOTOK;
00497 }
00498
00499 gdk_threads_enter();
00500 label = g_strdup_printf("<i> %s</i>", info);
00501 gtk_label_set_markup(GTK_LABEL(progress_data->progress_label), label);
00502 g_free(label);
00503 gdk_threads_leave();
00504
00505 if (DC_NO_ANSWER == fe_data->answer) {
00506 return DC_OK;
00507 }
00508 return fe_data->answer;
00509 }
00510
00517 void fe_gtk_progress_stop(struct frontend * fe)
00518 {
00519 struct frontend_data * fe_data = fe->data;
00520 struct progress_data * progress_data = fe_data->progress_data;
00521
00522 if (NULL == progress_data) {
00523
00524 return;
00525 }
00526
00527 gdk_threads_enter();
00528 destroy_progress(fe);
00529 gdk_threads_leave();
00530 }
00531
00532
00533