1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Libbrasero-burn
4 * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5 *
6 * Libbrasero-burn is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12 * GStreamer plugins to be used and distributed together with GStreamer
13 * and Libbrasero-burn. This permission is above and beyond the permissions granted
14 * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15 * you may extend this exception to your version of the code, but you are not
16 * obligated to do so. If you do not wish to do so, delete this exception
17 * statement from your version.
18 *
19 * Libbrasero-burn is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to:
26 * The Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor
28 * Boston, MA 02110-1301, USA.
29 */
30
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #include <glib.h>
36 #include <glib/gi18n-lib.h>
37
38 #include <gtk/gtk.h>
39
40 #include "brasero-tool-dialog.h"
41 #include "brasero-tool-dialog-private.h"
42
43 #include "brasero-progress.h"
44 #include "brasero-medium-selection.h"
45
46 #include "brasero-misc.h"
47
48 #include "brasero-burn.h"
49
50 #include "brasero-medium.h"
51 #include "brasero-drive.h"
52
53 G_DEFINE_TYPE (BraseroToolDialog, brasero_tool_dialog, GTK_TYPE_DIALOG);
54
55 typedef struct _BraseroToolDialogPrivate BraseroToolDialogPrivate;
56 struct _BraseroToolDialogPrivate {
57 GtkWidget *upper_box;
58 GtkWidget *lower_box;
59 GtkWidget *selector;
60 GtkWidget *progress;
61 GtkWidget *button;
62 GtkWidget *options;
63 GtkWidget *cancel;
64
65 BraseroBurn *burn;
66
67 gboolean running;
68 };
69
70 #define BRASERO_TOOL_DIALOG_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_TOOL_DIALOG, BraseroToolDialogPrivate))
71
72 static GtkDialogClass *parent_class = NULL;
73
74 static void
brasero_tool_dialog_media_error(BraseroToolDialog * self)75 brasero_tool_dialog_media_error (BraseroToolDialog *self)
76 {
77 brasero_utils_message_dialog (GTK_WIDGET (self),
78 _("The operation cannot be performed."),
79 _("The disc is not supported"),
80 GTK_MESSAGE_ERROR);
81 }
82
83 static void
brasero_tool_dialog_media_busy(BraseroToolDialog * self)84 brasero_tool_dialog_media_busy (BraseroToolDialog *self)
85 {
86 gchar *string;
87
88 string = g_strdup_printf ("%s. %s",
89 _("The drive is busy"),
90 _("Make sure another application is not using it"));
91 brasero_utils_message_dialog (GTK_WIDGET (self),
92 _("The operation cannot be performed."),
93 string,
94 GTK_MESSAGE_ERROR);
95 g_free (string);
96 }
97
98 static void
brasero_tool_dialog_no_media(BraseroToolDialog * self)99 brasero_tool_dialog_no_media (BraseroToolDialog *self)
100 {
101 brasero_utils_message_dialog (GTK_WIDGET (self),
102 _("The operation cannot be performed."),
103 _("The drive is empty"),
104 GTK_MESSAGE_ERROR);
105 }
106
107 void
brasero_tool_dialog_set_progress(BraseroToolDialog * self,gdouble overall_progress,gdouble task_progress,glong remaining,gint size_mb,gint written_mb)108 brasero_tool_dialog_set_progress (BraseroToolDialog *self,
109 gdouble overall_progress,
110 gdouble task_progress,
111 glong remaining,
112 gint size_mb,
113 gint written_mb)
114 {
115 BraseroToolDialogPrivate *priv;
116
117 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
118 brasero_burn_progress_set_status (BRASERO_BURN_PROGRESS (priv->progress),
119 FALSE, /* no need for the media here since speed is not specified */
120 overall_progress,
121 task_progress,
122 remaining,
123 -1,
124 -1,
125 -1);
126 }
127
128 void
brasero_tool_dialog_set_action(BraseroToolDialog * self,BraseroBurnAction action,const gchar * string)129 brasero_tool_dialog_set_action (BraseroToolDialog *self,
130 BraseroBurnAction action,
131 const gchar *string)
132 {
133 BraseroToolDialogPrivate *priv;
134
135 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
136 brasero_burn_progress_set_action (BRASERO_BURN_PROGRESS (priv->progress),
137 action,
138 string);
139 }
140
141 static void
brasero_tool_dialog_progress_changed(BraseroBurn * burn,gdouble overall_progress,gdouble progress,glong time_remaining,BraseroToolDialog * self)142 brasero_tool_dialog_progress_changed (BraseroBurn *burn,
143 gdouble overall_progress,
144 gdouble progress,
145 glong time_remaining,
146 BraseroToolDialog *self)
147 {
148 brasero_tool_dialog_set_progress (self,
149 -1.0,
150 progress,
151 -1,
152 -1,
153 -1);
154 }
155
156 static void
brasero_tool_dialog_action_changed(BraseroBurn * burn,BraseroBurnAction action,BraseroToolDialog * self)157 brasero_tool_dialog_action_changed (BraseroBurn *burn,
158 BraseroBurnAction action,
159 BraseroToolDialog *self)
160 {
161 gchar *string;
162
163 brasero_burn_get_action_string (burn, action, &string);
164 brasero_tool_dialog_set_action (self,
165 action,
166 string);
167 g_free (string);
168 }
169
170 BraseroBurn *
brasero_tool_dialog_get_burn(BraseroToolDialog * self)171 brasero_tool_dialog_get_burn (BraseroToolDialog *self)
172 {
173 BraseroToolDialogPrivate *priv;
174
175 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
176
177 if (priv->burn) {
178 brasero_burn_cancel (priv->burn, FALSE);
179 g_object_unref (priv->burn);
180 }
181
182 priv->burn = brasero_burn_new ();
183 g_signal_connect (priv->burn,
184 "progress-changed",
185 G_CALLBACK (brasero_tool_dialog_progress_changed),
186 self);
187 g_signal_connect (priv->burn,
188 "action-changed",
189 G_CALLBACK (brasero_tool_dialog_action_changed),
190 self);
191
192 return priv->burn;
193 }
194
195 static gboolean
brasero_tool_dialog_run(BraseroToolDialog * self)196 brasero_tool_dialog_run (BraseroToolDialog *self)
197 {
198 BraseroToolDialogPrivate *priv;
199 BraseroToolDialogClass *klass;
200 gboolean close = FALSE;
201 BraseroMedium *medium;
202 BraseroMedia media;
203 GdkCursor *cursor;
204 GdkWindow *window;
205
206 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
207 medium = brasero_medium_selection_get_active (BRASERO_MEDIUM_SELECTION (priv->selector));
208
209 /* set up */
210 gtk_widget_set_sensitive (priv->upper_box, FALSE);
211 gtk_widget_set_sensitive (priv->lower_box, TRUE);
212 gtk_widget_set_sensitive (GTK_WIDGET (priv->button), FALSE);
213
214 cursor = gdk_cursor_new (GDK_WATCH);
215 window = gtk_widget_get_window (GTK_WIDGET (self));
216 gdk_window_set_cursor (window, cursor);
217 g_object_unref (cursor);
218
219 gtk_button_set_label (GTK_BUTTON (priv->cancel), GTK_STOCK_CANCEL);
220
221 /* check the contents of the drive */
222 media = brasero_medium_get_status (medium);
223 if (media == BRASERO_MEDIUM_NONE) {
224 brasero_tool_dialog_no_media (self);
225 gtk_widget_set_sensitive (GTK_WIDGET (priv->button), TRUE);
226 goto end;
227 }
228 else if (media == BRASERO_MEDIUM_UNSUPPORTED) {
229 /* error out */
230 gtk_widget_set_sensitive (GTK_WIDGET (priv->button), TRUE);
231 brasero_tool_dialog_media_error (self);
232 goto end;
233 }
234 else if (media == BRASERO_MEDIUM_BUSY) {
235 gtk_widget_set_sensitive (GTK_WIDGET (priv->button), TRUE);
236 brasero_tool_dialog_media_busy (self);
237 goto end;
238 }
239
240 priv->running = TRUE;
241
242 klass = BRASERO_TOOL_DIALOG_GET_CLASS (self);
243 if (klass->activate)
244 close = klass->activate (self, medium);
245
246 priv->running = FALSE;
247
248 if (medium)
249 g_object_unref (medium);
250
251 if (close)
252 return TRUE;
253
254 end:
255
256 gdk_window_set_cursor (window, NULL);
257 gtk_button_set_label (GTK_BUTTON (priv->cancel), GTK_STOCK_CLOSE);
258
259 gtk_widget_set_sensitive (priv->upper_box, TRUE);
260 gtk_widget_set_sensitive (priv->lower_box, FALSE);
261
262 brasero_burn_progress_reset (BRASERO_BURN_PROGRESS (priv->progress));
263
264 return FALSE;
265 }
266
267 void
brasero_tool_dialog_pack_options(BraseroToolDialog * self,...)268 brasero_tool_dialog_pack_options (BraseroToolDialog *self,
269 ...)
270 {
271 gchar *title;
272 va_list vlist;
273 GtkWidget *child;
274 GSList *list = NULL;
275 BraseroToolDialogPrivate *priv;
276
277 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
278
279 va_start (vlist, self);
280 while ((child = va_arg (vlist, GtkWidget *)))
281 list = g_slist_prepend (list, child);
282 va_end (vlist);
283
284 title = g_strdup_printf ("<b>%s</b>", _("Options"));
285 priv->options = brasero_utils_pack_properties_list (title, list);
286 g_free (title);
287
288 g_slist_free (list);
289
290 gtk_widget_show_all (priv->options);
291 gtk_box_pack_start (GTK_BOX (priv->upper_box),
292 priv->options,
293 FALSE,
294 FALSE,
295 0);
296 }
297
298 void
brasero_tool_dialog_set_button(BraseroToolDialog * self,const gchar * text,const gchar * image,const gchar * theme)299 brasero_tool_dialog_set_button (BraseroToolDialog *self,
300 const gchar *text,
301 const gchar *image,
302 const gchar *theme)
303 {
304 GtkWidget *button;
305 BraseroToolDialogPrivate *priv;
306
307 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
308
309 if (priv->button)
310 g_object_unref (priv->button);
311
312 button = brasero_utils_make_button (text,
313 image,
314 theme,
315 GTK_ICON_SIZE_BUTTON);
316 gtk_widget_show_all (button);
317 gtk_dialog_add_action_widget (GTK_DIALOG (self),
318 button,
319 GTK_RESPONSE_OK);
320
321 priv->button = button;
322 }
323
324 void
brasero_tool_dialog_set_valid(BraseroToolDialog * self,gboolean valid)325 brasero_tool_dialog_set_valid (BraseroToolDialog *self,
326 gboolean valid)
327 {
328 BraseroToolDialogPrivate *priv;
329
330 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
331 gtk_widget_set_sensitive (priv->button, valid);
332 }
333
334 void
brasero_tool_dialog_set_medium_type_shown(BraseroToolDialog * self,BraseroMediaType media_type)335 brasero_tool_dialog_set_medium_type_shown (BraseroToolDialog *self,
336 BraseroMediaType media_type)
337 {
338 BraseroToolDialogPrivate *priv;
339
340 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
341 brasero_medium_selection_show_media_type (BRASERO_MEDIUM_SELECTION (priv->selector),
342 media_type);
343 }
344
345 /**
346 * brasero_tool_dialog_get_medium:
347 * @dialog: a #BraseroToolDialog
348 *
349 * This function returns the currently selected medium.
350 *
351 * Return value: a #BraseroMedium or NULL if none is set.
352 **/
353
354 BraseroMedium *
brasero_tool_dialog_get_medium(BraseroToolDialog * self)355 brasero_tool_dialog_get_medium (BraseroToolDialog *self)
356 {
357 BraseroToolDialogPrivate *priv;
358
359 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
360 return brasero_medium_selection_get_active (BRASERO_MEDIUM_SELECTION (priv->selector));
361 }
362
363 /**
364 * brasero_tool_dialog_set_medium:
365 * @dialog: a #BraseroToolDialog
366 * @medium: a #BraseroMedium
367 *
368 * Selects the medium that should be currently selected.
369 *
370 * Return value: a #gboolean. TRUE if it was successful.
371 **/
372
373 gboolean
brasero_tool_dialog_set_medium(BraseroToolDialog * self,BraseroMedium * medium)374 brasero_tool_dialog_set_medium (BraseroToolDialog *self,
375 BraseroMedium *medium)
376 {
377 BraseroToolDialogPrivate *priv;
378
379 if (!medium)
380 return FALSE;
381
382 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
383
384 return brasero_medium_selection_set_active (BRASERO_MEDIUM_SELECTION (priv->selector), medium);
385 }
386
387 static void
brasero_tool_dialog_drive_changed_cb(BraseroMediumSelection * selection,BraseroMedium * medium,BraseroToolDialog * self)388 brasero_tool_dialog_drive_changed_cb (BraseroMediumSelection *selection,
389 BraseroMedium *medium,
390 BraseroToolDialog *self)
391 {
392 BraseroToolDialogClass *klass;
393
394 klass = BRASERO_TOOL_DIALOG_GET_CLASS (self);
395 if (klass->medium_changed)
396 klass->medium_changed (self, medium);
397 }
398
399 static gboolean
brasero_tool_dialog_cancel_dialog(GtkWidget * toplevel)400 brasero_tool_dialog_cancel_dialog (GtkWidget *toplevel)
401 {
402 gint result;
403 GtkWidget *button;
404 GtkWidget *message;
405
406 message = gtk_message_dialog_new (GTK_WINDOW (toplevel),
407 GTK_DIALOG_DESTROY_WITH_PARENT|
408 GTK_DIALOG_MODAL,
409 GTK_MESSAGE_WARNING,
410 GTK_BUTTONS_NONE,
411 _("Do you really want to quit?"));
412
413 gtk_window_set_icon_name (GTK_WINDOW (message),
414 gtk_window_get_icon_name (GTK_WINDOW (toplevel)));
415
416 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message),
417 _("Interrupting the process may make disc unusable."));
418 gtk_dialog_add_buttons (GTK_DIALOG (message),
419 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
420 NULL);
421
422 button = brasero_utils_make_button (_("_Continue"),
423 GTK_STOCK_OK,
424 NULL,
425 GTK_ICON_SIZE_BUTTON);
426 gtk_widget_show_all (button);
427 gtk_dialog_add_action_widget (GTK_DIALOG (message),
428 button, GTK_RESPONSE_OK);
429
430 result = gtk_dialog_run (GTK_DIALOG (message));
431 gtk_widget_destroy (message);
432
433 if (result != GTK_RESPONSE_OK)
434 return TRUE;
435
436 return FALSE;
437 }
438
439 /**
440 * brasero_tool_dialog_cancel:
441 * @dialog: a #BraseroToolDialog
442 *
443 * Cancels any ongoing operation.
444 *
445 * Return value: a #gboolean. TRUE when cancellation was successful. FALSE otherwise.
446 **/
447
448 gboolean
brasero_tool_dialog_cancel(BraseroToolDialog * self)449 brasero_tool_dialog_cancel (BraseroToolDialog *self)
450 {
451 BraseroToolDialogClass *klass;
452 BraseroToolDialogPrivate *priv;
453
454 klass = BRASERO_TOOL_DIALOG_GET_CLASS (self);
455 if (klass->cancel) {
456 gboolean res;
457
458 res = klass->cancel (self);
459 if (!res)
460 return FALSE;
461 }
462
463 priv = BRASERO_TOOL_DIALOG_PRIVATE (self);
464 if (!priv->burn)
465 return TRUE;
466
467 if (brasero_burn_cancel (priv->burn, TRUE) == BRASERO_BURN_DANGEROUS) {
468 if (!brasero_tool_dialog_cancel_dialog (GTK_WIDGET (self)))
469 return FALSE;
470
471 brasero_burn_cancel (priv->burn, FALSE);
472 }
473
474 return TRUE;
475 }
476
477 static gboolean
brasero_tool_dialog_delete(GtkWidget * widget,GdkEventAny * event)478 brasero_tool_dialog_delete (GtkWidget *widget, GdkEventAny *event)
479 {
480 BraseroToolDialog *self;
481
482 self = BRASERO_TOOL_DIALOG (widget);
483
484 return (brasero_tool_dialog_cancel (self) != TRUE);
485 }
486
487 static void
brasero_tool_dialog_response(GtkDialog * dialog,GtkResponseType response,gpointer NULL_data)488 brasero_tool_dialog_response (GtkDialog *dialog,
489 GtkResponseType response,
490 gpointer NULL_data)
491 {
492 if (response == GTK_RESPONSE_CANCEL) {
493 if (!brasero_tool_dialog_cancel (BRASERO_TOOL_DIALOG (dialog)))
494 g_signal_stop_emission_by_name (dialog, "response");
495 }
496 else if (response == GTK_RESPONSE_OK) {
497 if (!brasero_tool_dialog_run (BRASERO_TOOL_DIALOG (dialog)))
498 g_signal_stop_emission_by_name (dialog, "response");
499 }
500 }
501
502 static void
brasero_tool_dialog_finalize(GObject * object)503 brasero_tool_dialog_finalize (GObject *object)
504 {
505 G_OBJECT_CLASS (parent_class)->finalize (object);
506 }
507
508 static void
brasero_tool_dialog_constructed(GObject * object)509 brasero_tool_dialog_constructed (GObject *object)
510 {
511 BraseroToolDialogPrivate *priv;
512
513 G_OBJECT_CLASS (brasero_tool_dialog_parent_class)->constructed (object);
514
515 priv = BRASERO_TOOL_DIALOG_PRIVATE (object);
516
517 brasero_medium_selection_show_media_type (BRASERO_MEDIUM_SELECTION (priv->selector),
518 BRASERO_MEDIA_TYPE_REWRITABLE |
519 BRASERO_MEDIA_TYPE_WRITABLE |
520 BRASERO_MEDIA_TYPE_AUDIO |
521 BRASERO_MEDIA_TYPE_DATA);
522 }
523
524 static void
brasero_tool_dialog_class_init(BraseroToolDialogClass * klass)525 brasero_tool_dialog_class_init (BraseroToolDialogClass *klass)
526 {
527 GObjectClass *object_class = G_OBJECT_CLASS (klass);
528 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
529
530 g_type_class_add_private (klass, sizeof (BraseroToolDialogPrivate));
531
532 parent_class = g_type_class_peek_parent(klass);
533 object_class->finalize = brasero_tool_dialog_finalize;
534 object_class->constructed = brasero_tool_dialog_constructed;
535
536 widget_class->delete_event = brasero_tool_dialog_delete;
537 }
538
539 static void
brasero_tool_dialog_init(BraseroToolDialog * obj)540 brasero_tool_dialog_init (BraseroToolDialog *obj)
541 {
542 GtkWidget *title;
543 GtkWidget *content_area;
544 gchar *title_str;
545 BraseroToolDialogPrivate *priv;
546
547 priv = BRASERO_TOOL_DIALOG_PRIVATE (obj);
548
549 /* upper part */
550 priv->upper_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
551 gtk_widget_show (GTK_WIDGET (priv->upper_box));
552
553 priv->selector = brasero_medium_selection_new ();
554 gtk_widget_show (GTK_WIDGET (priv->selector));
555
556 title_str = g_strdup_printf ("<b>%s</b>", _("Select a disc"));
557 gtk_box_pack_start (GTK_BOX (priv->upper_box),
558 brasero_utils_pack_properties (title_str,
559 priv->selector,
560 NULL),
561 FALSE, FALSE, 0);
562 g_free (title_str);
563
564 content_area = gtk_dialog_get_content_area (GTK_DIALOG (obj));
565 gtk_box_pack_start (GTK_BOX (content_area),
566 priv->upper_box,
567 FALSE,
568 FALSE,
569 0);
570
571 /* lower part */
572 priv->lower_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
573 gtk_container_set_border_width (GTK_CONTAINER (priv->lower_box), 12);
574 gtk_widget_set_sensitive (priv->lower_box, FALSE);
575 gtk_widget_show (priv->lower_box);
576
577 gtk_box_pack_start (GTK_BOX (content_area),
578 priv->lower_box,
579 FALSE,
580 FALSE,
581 0);
582
583 title_str = g_strdup_printf ("<b>%s</b>", _("Progress"));
584 title = gtk_label_new (title_str);
585 g_free (title_str);
586
587 gtk_label_set_use_markup (GTK_LABEL (title), TRUE);
588 gtk_misc_set_alignment (GTK_MISC (title), 0.0, 0.5);
589 gtk_misc_set_padding(GTK_MISC (title), 0, 6);
590 gtk_widget_show (title);
591 gtk_box_pack_start (GTK_BOX (priv->lower_box),
592 title,
593 FALSE,
594 FALSE,
595 0);
596
597 priv->progress = brasero_burn_progress_new ();
598 gtk_widget_show (priv->progress);
599 g_object_set (G_OBJECT (priv->progress),
600 "show-info", FALSE,
601 NULL);
602
603 gtk_box_pack_start (GTK_BOX (content_area),
604 priv->progress,
605 FALSE,
606 FALSE,
607 0);
608
609 /* buttons */
610 priv->cancel = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
611 gtk_widget_show (priv->cancel);
612 gtk_dialog_add_action_widget (GTK_DIALOG (obj),
613 priv->cancel,
614 GTK_RESPONSE_CANCEL);
615
616 g_signal_connect (G_OBJECT (priv->selector),
617 "medium-changed",
618 G_CALLBACK (brasero_tool_dialog_drive_changed_cb),
619 obj);
620
621 g_signal_connect (obj,
622 "response",
623 G_CALLBACK (brasero_tool_dialog_response),
624 NULL);
625
626 gtk_window_resize (GTK_WINDOW (obj), 10, 10);
627 }
628