1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 
3 /***************************************************************************
4  *            brasero-project-manager.c
5  *
6  *  mer mai 24 14:22:56 2006
7  *  Copyright  2006  Rouquier Philippe
8  *  brasero-app@wanadoo.fr
9  ***************************************************************************/
10 
11 /*
12  *  Brasero is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  Brasero is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU Library General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to:
24  * 	The Free Software Foundation, Inc.,
25  * 	51 Franklin Street, Fifth Floor
26  * 	Boston, MA  02110-1301, USA.
27  */
28 
29 #include <string.h>
30 
31 #ifdef HAVE_CONFIG_H
32 #  include <config.h>
33 #endif
34 
35 #include <glib.h>
36 #include <glib-object.h>
37 #include <glib/gi18n-lib.h>
38 
39 #include <gtk/gtk.h>
40 
41 #include "brasero-io.h"
42 
43 #include "brasero-units.h"
44 #include "brasero-medium-monitor.h"
45 
46 #include "brasero-app.h"
47 #include "brasero-utils.h"
48 #include "brasero-project.h"
49 #include "brasero-layout.h"
50 #include "brasero-project-manager.h"
51 #include "brasero-file-chooser.h"
52 #include "brasero-uri-container.h"
53 #include "brasero-project-type-chooser.h"
54 
55 #ifdef BUILD_PLAYLIST
56 #include "brasero-playlist.h"
57 #endif
58 
59 #ifdef BUILD_PREVIEW
60 #include "brasero-preview.h"
61 #endif
62 
63 static void brasero_project_manager_class_init (BraseroProjectManagerClass *klass);
64 static void brasero_project_manager_init (BraseroProjectManager *sp);
65 static void brasero_project_manager_finalize (GObject *object);
66 
67 static void
68 brasero_project_manager_type_changed_cb (BraseroProjectTypeChooser *chooser,
69 					 BraseroProjectType type,
70 					 BraseroProjectManager *manager);
71 
72 static void
73 brasero_project_manager_new_cover_cb (GtkAction *action, BraseroProjectManager *manager);
74 static void
75 brasero_project_manager_new_empty_prj_cb (GtkAction *action, BraseroProjectManager *manager);
76 static void
77 brasero_project_manager_new_audio_prj_cb (GtkAction *action, BraseroProjectManager *manager);
78 static void
79 brasero_project_manager_new_data_prj_cb (GtkAction *action, BraseroProjectManager *manager);
80 static void
81 brasero_project_manager_new_video_prj_cb (GtkAction *action, BraseroProjectManager *manager);
82 static void
83 brasero_project_manager_new_copy_prj_cb (GtkAction *action, BraseroProjectManager *manager);
84 static void
85 brasero_project_manager_new_iso_prj_cb (GtkAction *action, BraseroProjectManager *manager);
86 static void
87 brasero_project_manager_open_cb (GtkAction *action, BraseroProjectManager *manager);
88 
89 static void
90 brasero_project_manager_selected_uris_changed (BraseroURIContainer *container,
91 					       BraseroProjectManager *manager);
92 
93 /* menus */
94 static GtkActionEntry entries [] = {
95 	{"Cover", NULL, N_("_Cover Editor"), NULL,
96 	 N_("Design and print covers for CDs"), G_CALLBACK (brasero_project_manager_new_cover_cb)},
97 	 {"New", GTK_STOCK_NEW, N_("_New Project"), NULL,
98 	 N_("Create a new project"), NULL },
99 	{"NewChoose", GTK_STOCK_NEW, N_("_Empty Project"), NULL,
100 	 N_("Let you choose your new project"), G_CALLBACK (brasero_project_manager_new_empty_prj_cb)},
101 	{"NewAudio", "media-optical-audio-new", N_("New _Audio Project"), NULL,
102 	 N_("Create a traditional audio CD that will be playable on computers and stereos"), G_CALLBACK (brasero_project_manager_new_audio_prj_cb)},
103 	{"NewData", "media-optical-data-new", N_("New _Data Project"), NULL,
104 	 N_("Create a CD/DVD containing any type of data that can only be read on a computer"), G_CALLBACK (brasero_project_manager_new_data_prj_cb)},
105 	{"NewVideo", "media-optical-video-new", N_("New _Video Project"), NULL,
106 	 N_("Create a video DVD or an SVCD that is readable on TV readers"), G_CALLBACK (brasero_project_manager_new_video_prj_cb)},
107 	{"NewCopy", "media-optical-copy", N_("Copy _Disc…"), NULL,
108 	 N_("Create a 1:1 copy of an audio CD or a data CD/DVD on your hard disk or on another CD/DVD"), G_CALLBACK (brasero_project_manager_new_copy_prj_cb)},
109 	{"NewIso", "iso-image-burn", N_("_Burn Image…"), NULL,
110 	 N_("Burn an existing CD/DVD image to disc"), G_CALLBACK (brasero_project_manager_new_iso_prj_cb)},
111 
112 	{"Open", GTK_STOCK_OPEN, N_("_Open…"), NULL,
113 	 N_("Open a project"), G_CALLBACK (brasero_project_manager_open_cb)},
114 };
115 
116 static const char *description = {
117 	"<ui>"
118 	    "<menubar name='menubar' >"
119 		"<menu action='ProjectMenu'>"
120 			"<placeholder name='ProjectPlaceholder'>"
121 				"<menu action='New'>"
122 					"<menuitem action='NewAudio'/>"
123 					"<menuitem action='NewData'/>"
124 					"<menuitem action='NewVideo'/>"
125 					"<menuitem action='NewCopy'/>"
126 					"<menuitem action='NewIso'/>"
127 				"</menu>"
128 			"</placeholder>"
129 
130 			"<placeholder name='ProjectPlaceholder'>"
131 			    "<separator/>"
132 			    "<menuitem action='Open'/>"
133 			    "<menuitem action='RecentProjects'/>"
134 			    "<separator/>"
135 			"</placeholder>"
136 
137 		"</menu>"
138 
139 		"<menu action='ToolMenu'>"
140 
141 			"<placeholder name='DiscPlaceholder'>"
142 			    "<separator/>"
143 			    "<menuitem action='Cover'/>"
144 			    "<separator/>"
145 			"</placeholder>"
146 
147 		"</menu>"
148 	    "</menubar>"
149 	"</ui>"
150 };
151 
152 struct BraseroProjectManagerPrivate {
153 	BraseroProjectType type;
154 	BraseroIOJobBase *size_preview;
155 
156 	GtkWidget *project;
157 	GtkWidget *layout;
158 
159 	gchar **selected;
160 	guint preview_id;
161 
162 	guint status_ctx;
163 
164 	GtkActionGroup *action_group;
165 };
166 
167 #define BRASERO_PROJECT_MANAGER_CONNECT_CHANGED(manager, container)		\
168 	g_signal_connect (container,						\
169 			  "uri-selected",					\
170 			  G_CALLBACK (brasero_project_manager_selected_uris_changed),	\
171 			  manager);
172 
173 static GObjectClass *parent_class = NULL;
174 
175 GType
brasero_project_manager_get_type()176 brasero_project_manager_get_type ()
177 {
178 	static GType type = 0;
179 
180 	if(type == 0) {
181 		static const GTypeInfo our_info = {
182 			sizeof (BraseroProjectManagerClass),
183 			NULL,
184 			NULL,
185 			(GClassInitFunc)brasero_project_manager_class_init,
186 			NULL,
187 			NULL,
188 			sizeof (BraseroProjectManager),
189 			0,
190 			(GInstanceInitFunc)brasero_project_manager_init,
191 		};
192 
193 		type = g_type_register_static (GTK_TYPE_NOTEBOOK,
194 					       "BraseroProjectManager",
195 					       &our_info,
196 					       0);
197 	}
198 
199 	return type;
200 }
201 
202 static void
brasero_project_manager_new_cover_cb(GtkAction * action,BraseroProjectManager * manager)203 brasero_project_manager_new_cover_cb (GtkAction *action,
204 				      BraseroProjectManager *manager)
205 {
206 	BraseroJacketEdit *edit;
207 	GtkWidget *toplevel;
208 	GtkWidget *dialog;
209 
210 	if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO) {
211 		brasero_project_create_audio_cover (BRASERO_PROJECT (manager->priv->project));
212 		return;
213 	}
214 
215 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (manager));
216 	dialog = brasero_jacket_edit_dialog_new (toplevel, &edit);
217 
218 	/* This strange hack is a way to workaround #568358.
219 	 * At one point we'll need to hide the dialog which means it
220 	 * will anwer with a GTK_RESPONSE_NONE */
221 	while (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_NONE)
222 		gtk_widget_show (GTK_WIDGET (dialog));
223 
224 	gtk_widget_destroy (dialog);
225 }
226 
227 static void
brasero_project_manager_set_statusbar(BraseroProjectManager * manager,guint64 files_size,gint invalid_num,gint files_num)228 brasero_project_manager_set_statusbar (BraseroProjectManager *manager,
229 				       guint64 files_size,
230 				       gint invalid_num,
231 				       gint files_num)
232 {
233 	gchar *status_string = NULL;
234 	GtkWidget *status;
235 	gint valid_num;
236 
237 	status = brasero_app_get_statusbar1 (brasero_app_get_default ());
238 
239 	if (!manager->priv->status_ctx)
240 		manager->priv->status_ctx = gtk_statusbar_get_context_id (GTK_STATUSBAR (status),
241 									  "size_info");
242 
243 	gtk_statusbar_pop (GTK_STATUSBAR (status), manager->priv->status_ctx);
244 
245 	valid_num = files_num - invalid_num;
246 	if (!invalid_num && valid_num) {
247 		gchar *size_string;
248 
249 		if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
250 		||  manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO)
251 			size_string = brasero_units_get_time_string (files_size, TRUE, FALSE);
252 		else if (manager->priv->type == BRASERO_PROJECT_TYPE_DATA)
253 			size_string = g_format_size (files_size);
254 		else
255 			return;
256 
257 		/* Translators: the %s is a string representing the total size
258 		 * of the file selection */
259 		status_string = g_strdup_printf (ngettext ("%d file selected (%s)", "%d files selected (%s)", files_num),
260 						 files_num,
261 						 size_string);
262 		g_free (size_string);
263 	}
264 	else if (valid_num) {
265 		gchar *size_string = NULL;
266 
267 		if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
268 		||  manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO) {
269 			size_string = brasero_units_get_time_string (files_size, TRUE, FALSE);
270 			status_string = g_strdup_printf (ngettext ("%d file is supported (%s)", "%d files are supported (%s)", valid_num),
271 							 valid_num,
272 							 size_string);
273 		}
274 		else if (manager->priv->type == BRASERO_PROJECT_TYPE_DATA) {
275 			size_string = g_format_size (files_size);
276 			status_string = g_strdup_printf (ngettext ("%d file can be added (%s)", "%d selected files can be added (%s)", valid_num),
277 							 valid_num,
278 							 size_string);
279 		}
280 		else
281 			return;
282 
283 		g_free (size_string);
284 	}
285 	else if (invalid_num) {
286 		if (manager->priv->type == BRASERO_PROJECT_TYPE_DATA)
287 			status_string = g_strdup_printf (ngettext ("No file can be added (%i selected file)",
288 								   "No file can be added (%i selected files)",
289 								   files_num),
290 							 files_num);
291 		else if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
292 		     ||  manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO)
293 			status_string = g_strdup_printf (ngettext ("No file is supported (%i selected file)",
294 								   "No file is supported (%i selected files)",
295 								   files_num),
296 							 files_num);
297 	}
298 	else
299 		status_string = g_strdup (_("No file selected"));
300 
301 	gtk_statusbar_push (GTK_STATUSBAR (status), manager->priv->status_ctx,
302 			    status_string);
303 	g_free (status_string);
304 }
305 
306 static void
brasero_project_manager_size_preview(GObject * object,GError * error,const gchar * uri,GFileInfo * info,gpointer user_data)307 brasero_project_manager_size_preview (GObject *object,
308 				      GError *error,
309 				      const gchar *uri,
310 				      GFileInfo *info,
311 				      gpointer user_data)
312 {
313 	BraseroProjectManager *manager = BRASERO_PROJECT_MANAGER (object);
314 	guint64 files_size;
315 	gint invalid_num;
316 	gint files_num;
317 
318 	invalid_num = g_file_info_get_attribute_uint32 (info, BRASERO_IO_COUNT_INVALID);
319 	files_size = g_file_info_get_attribute_uint64 (info, BRASERO_IO_COUNT_SIZE);
320 	files_num = g_file_info_get_attribute_uint32 (info, BRASERO_IO_COUNT_NUM);
321 	brasero_project_manager_set_statusbar (manager,
322 					       files_size,
323 					       invalid_num,
324 					       files_num);
325 }
326 /*
327 static void
328 brasero_project_manager_size_preview_progress (GObject *object,
329 					       BraseroIOJobProgress *progress,
330 					       gpointer user_data)
331 {
332 	BraseroProjectManager *manager = BRASERO_PROJECT_MANAGER (object);
333 	guint64 files_size;
334 	gint files_num;
335 
336 	files_size = brasero_io_job_progress_get_total (progress);
337 	files_num = brasero_io_job_progress_get_file_processed (progress);
338 	brasero_project_manager_set_statusbar (manager,
339 					       files_size,
340 					       0,
341 					       files_num);
342 }
343 */
344 static gboolean
brasero_project_manager_selected_uris_preview(gpointer data)345 brasero_project_manager_selected_uris_preview (gpointer data)
346 {
347 	BraseroProjectManager *manager = BRASERO_PROJECT_MANAGER (data);
348 	BraseroIOFlags flags;
349 	GSList *list = NULL;
350 	gchar **iter;
351 
352 	if (!manager->priv->size_preview)
353 		manager->priv->size_preview = brasero_io_register (G_OBJECT (manager),
354 								   brasero_project_manager_size_preview,
355 								   NULL,
356 								   NULL);
357 
358 	for (iter = manager->priv->selected; iter && *iter; iter ++)
359 		list = g_slist_prepend (list, *iter);
360 
361 	flags = BRASERO_IO_INFO_IDLE;
362 	if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
363 	||  manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO)
364 		flags |= BRASERO_IO_INFO_METADATA;
365 	else if (manager->priv->type == BRASERO_PROJECT_TYPE_DATA)
366 		flags |= BRASERO_IO_INFO_RECURSIVE;
367 
368 	brasero_io_get_file_count (list,
369 				   manager->priv->size_preview,
370 				   flags,
371 				   NULL);
372 
373 	g_slist_free (list);
374 	manager->priv->preview_id = 0;
375 	return FALSE;
376 }
377 
378 void
brasero_project_manager_selected_uris_changed(BraseroURIContainer * container,BraseroProjectManager * manager)379 brasero_project_manager_selected_uris_changed (BraseroURIContainer *container,
380 					       BraseroProjectManager *manager)
381 {
382 	gchar **uris;
383 
384 	/* Before cancelling everything, check that the size really changed
385 	 * like in the case of double clicking or if the user selected one
386 	 * file and double clicked on it afterwards.
387 	 * NOTE: the following expects each URI to be unique. */
388 	uris = brasero_uri_container_get_selected_uris (container);
389 	if (uris) {
390 		gchar **iter;
391 		guint num = 0;
392 		gboolean found = FALSE;
393 
394 		for (iter = manager->priv->selected; iter && *iter; iter ++) {
395 			gchar **uri;
396 
397 			found = FALSE;
398 			for (uri = uris; uri && *uri; uri ++) {
399 				if (!strcmp (*uri, *iter)) {
400 					found = TRUE;
401 					break;
402 				}
403 			}
404 
405 			if (!found)
406 				break;
407 
408 			num ++;
409 		}
410 
411 		if (found) {
412 			guint num_new = 0;
413 
414 			for (iter = uris; iter && *iter; iter ++)
415 				num_new ++;
416 
417 			if (num_new == num) {
418 				/* same uris no need to update anything. */
419 				g_strfreev (uris);
420 				return;
421 			}
422 		}
423 	}
424 
425 	/* if we are in the middle of an unfinished size seek then
426 	 * cancel it and re-initialize */
427 	if (manager->priv->size_preview)
428 		brasero_io_cancel_by_base (manager->priv->size_preview);
429 
430 	if (manager->priv->selected) {
431 		g_strfreev (manager->priv->selected);
432 		manager->priv->selected = NULL;
433 	}
434 
435 	if (manager->priv->preview_id) {
436 		g_source_remove (manager->priv->preview_id);
437 		manager->priv->preview_id = 0;
438 	}
439 
440 	manager->priv->selected = uris;
441 	if (!manager->priv->selected) {
442  		GtkWidget *status;
443 
444  		status = brasero_app_get_statusbar1 (brasero_app_get_default ());
445 
446  		if (!manager->priv->status_ctx)
447  			manager->priv->status_ctx = gtk_statusbar_get_context_id (GTK_STATUSBAR (status),
448  										  "size_info");
449 
450  		gtk_statusbar_pop (GTK_STATUSBAR (status), manager->priv->status_ctx);
451  		gtk_statusbar_push (GTK_STATUSBAR (status),
452   				    manager->priv->status_ctx,
453   				    _("No file selected"));
454 		return;
455 	}
456 
457 	manager->priv->preview_id = g_timeout_add (500,
458 						   brasero_project_manager_selected_uris_preview,
459 						   manager);
460 }
461 
462 static void
brasero_project_manager_sidepane_changed(BraseroLayout * layout,gboolean visible,BraseroProjectManager * manager)463 brasero_project_manager_sidepane_changed (BraseroLayout *layout,
464 					  gboolean visible,
465 					  BraseroProjectManager *manager)
466 {
467 	if (!visible) {
468  		GtkWidget *status;
469 
470 		/* If sidepane is disabled, remove any text about selection */
471 		if (manager->priv->size_preview)
472 			brasero_io_cancel_by_base (manager->priv->size_preview);
473 
474  		status = brasero_app_get_statusbar1 (brasero_app_get_default ());
475 
476  		gtk_statusbar_pop (GTK_STATUSBAR (status), manager->priv->status_ctx);
477 
478 		if (manager->priv->selected) {
479 			g_strfreev (manager->priv->selected);
480 			manager->priv->selected = NULL;
481 		}
482 
483 		if (manager->priv->preview_id) {
484 			g_source_remove (manager->priv->preview_id);
485 			manager->priv->preview_id = 0;
486 		}
487 	}
488 }
489 
490 void
brasero_project_manager_register_ui(BraseroProjectManager * manager,GtkUIManager * ui_manager)491 brasero_project_manager_register_ui (BraseroProjectManager *manager,
492 				     GtkUIManager *ui_manager)
493 {
494 	GError *error = NULL;
495 
496 	gtk_ui_manager_insert_action_group (ui_manager, manager->priv->action_group, 0);
497 	if (!gtk_ui_manager_add_ui_from_string (ui_manager, description, -1, &error)) {
498 		g_message ("building UI failed: %s", error->message);
499 		g_error_free (error);
500 	}
501 
502 	brasero_project_register_ui (BRASERO_PROJECT (manager->priv->project), ui_manager);
503    	brasero_layout_register_ui (BRASERO_LAYOUT (manager->priv->layout), ui_manager);
504 }
505 
506 void
brasero_project_manager_switch(BraseroProjectManager * manager,BraseroProjectType type,gboolean reset)507 brasero_project_manager_switch (BraseroProjectManager *manager,
508 				BraseroProjectType type,
509 				gboolean reset)
510 {
511 	GtkWidget *toplevel;
512 	GtkAction *action;
513 
514 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (manager));
515 
516 	if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
517 	||  manager->priv->type == BRASERO_PROJECT_TYPE_DATA
518 	||  manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO) {
519 		BraseroBurnResult result;
520 		gboolean keep_files = FALSE;
521 
522 		if (type == BRASERO_PROJECT_TYPE_AUDIO
523 		||  type == BRASERO_PROJECT_TYPE_DATA
524 		||  type == BRASERO_PROJECT_TYPE_VIDEO) {
525 			if (manager->priv->type != type
526 			&& (((manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO ||
527 			      manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO) &&
528 			     type == BRASERO_PROJECT_TYPE_DATA)
529 			||  manager->priv->type == BRASERO_PROJECT_TYPE_DATA))
530 				keep_files = TRUE;
531 		}
532 
533 		result = brasero_project_confirm_switch (BRASERO_PROJECT (manager->priv->project), keep_files);
534 		if (result == BRASERO_BURN_CANCEL)
535 			return;
536 
537 		if (result == BRASERO_BURN_RETRY) {
538 			if (manager->priv->type == BRASERO_PROJECT_TYPE_AUDIO
539 			||  manager->priv->type == BRASERO_PROJECT_TYPE_VIDEO)
540 				type = brasero_project_convert_to_data (BRASERO_PROJECT (manager->priv->project));
541 			else if (manager->priv->type == BRASERO_PROJECT_TYPE_DATA) {
542 				BraseroProjectType new_type;
543 
544 				/* Keep type untouched */
545 				new_type = brasero_project_convert_to_stream (BRASERO_PROJECT (manager->priv->project),
546 									      type == BRASERO_PROJECT_TYPE_VIDEO);
547 				if (new_type == BRASERO_PROJECT_TYPE_INVALID)
548 					type = new_type;
549 			}
550 
551 			if (type != BRASERO_PROJECT_TYPE_INVALID)
552 				reset = FALSE;
553 			else
554 				reset = TRUE;
555 		}
556 	}
557 
558 	if (manager->priv->status_ctx) {
559 		GtkWidget *status;
560 
561 		status = brasero_app_get_statusbar1 (brasero_app_get_default ());
562 		gtk_statusbar_pop (GTK_STATUSBAR (status), manager->priv->status_ctx);
563 	}
564 
565 	action = gtk_action_group_get_action (manager->priv->action_group, "NewChoose");
566 
567 	manager->priv->type = type;
568 	if (type == BRASERO_PROJECT_TYPE_INVALID) {
569 		brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_NONE);
570 		brasero_project_set_none (BRASERO_PROJECT (manager->priv->project));
571 
572 		gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 0);
573 		gtk_action_set_sensitive (action, FALSE);
574 
575 		if (toplevel)
576 			gtk_window_set_title (GTK_WINDOW (toplevel), "Brasero");
577 	}
578 	else if (type == BRASERO_PROJECT_TYPE_AUDIO) {
579 		brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_AUDIO);
580 
581 		gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 1);
582 		gtk_action_set_sensitive (action, TRUE);
583 
584 		if (reset) {
585 			/* tell the BraseroProject object that we want an audio selection */
586 			brasero_project_set_audio (BRASERO_PROJECT (manager->priv->project));
587 		}
588 
589 		if (toplevel)
590 			gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero — New Audio Disc Project"));
591 	}
592 	else if (type == BRASERO_PROJECT_TYPE_DATA) {
593 		brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_DATA);
594 
595 		gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 1);
596 		gtk_action_set_sensitive (action, TRUE);
597 
598 		if (reset) {
599 			/* tell the BraseroProject object that we want a data selection */
600 			brasero_project_set_data (BRASERO_PROJECT (manager->priv->project));
601 		}
602 
603 		if (toplevel)
604 			gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero — New Data Disc Project"));
605 	}
606 	else if (type == BRASERO_PROJECT_TYPE_VIDEO) {
607 		brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_VIDEO);
608 
609 		gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 1);
610 		gtk_action_set_sensitive (action, TRUE);
611 
612 		if (reset) {
613 			/* tell the BraseroProject object that we want a data selection */
614 			brasero_project_set_video (BRASERO_PROJECT (manager->priv->project));
615 		}
616 
617 		if (toplevel)
618 			gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero — New Video Disc Project"));
619 	}
620 	else if (type == BRASERO_PROJECT_TYPE_ISO) {
621 		brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_NONE);
622 		brasero_project_set_none (BRASERO_PROJECT (manager->priv->project));
623 
624 		gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 0);
625 		gtk_action_set_sensitive (action, FALSE);
626 
627 		if (toplevel)
628 			gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero — New Image File"));
629 
630 		brasero_project_manager_switch (manager,
631 						BRASERO_PROJECT_TYPE_INVALID,
632 						TRUE);
633 		brasero_app_image (brasero_app_get_default (), NULL, NULL, FALSE);
634 	}
635 	else if (type == BRASERO_PROJECT_TYPE_COPY) {
636 		brasero_layout_load (BRASERO_LAYOUT (manager->priv->layout), BRASERO_LAYOUT_NONE);
637 		brasero_project_set_none (BRASERO_PROJECT (manager->priv->project));
638 
639 		gtk_notebook_set_current_page (GTK_NOTEBOOK (manager), 0);
640 		gtk_action_set_sensitive (action, FALSE);
641 
642 		if (toplevel)
643 			gtk_window_set_title (GTK_WINDOW (toplevel), _("Brasero — Disc Copy"));
644 
645 		brasero_project_manager_switch (manager,
646 						BRASERO_PROJECT_TYPE_INVALID,
647 						TRUE);
648 		brasero_app_copy_disc (brasero_app_get_default (), NULL, NULL, NULL, FALSE);
649 	}
650 }
651 
652 static void
brasero_project_manager_type_changed_cb(BraseroProjectTypeChooser * chooser,BraseroProjectType type,BraseroProjectManager * manager)653 brasero_project_manager_type_changed_cb (BraseroProjectTypeChooser *chooser,
654 					 BraseroProjectType type,
655 					 BraseroProjectManager *manager)
656 {
657 	brasero_project_manager_switch (manager, type, TRUE);
658 }
659 
660 static void
brasero_project_manager_new_empty_prj_cb(GtkAction * action,BraseroProjectManager * manager)661 brasero_project_manager_new_empty_prj_cb (GtkAction *action, BraseroProjectManager *manager)
662 {
663 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_INVALID, TRUE);
664 }
665 
666 static void
brasero_project_manager_new_audio_prj_cb(GtkAction * action,BraseroProjectManager * manager)667 brasero_project_manager_new_audio_prj_cb (GtkAction *action, BraseroProjectManager *manager)
668 {
669 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_AUDIO, TRUE);
670 }
671 
672 static void
brasero_project_manager_new_data_prj_cb(GtkAction * action,BraseroProjectManager * manager)673 brasero_project_manager_new_data_prj_cb (GtkAction *action, BraseroProjectManager *manager)
674 {
675 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_DATA, TRUE);
676 }
677 
678 static void
brasero_project_manager_new_video_prj_cb(GtkAction * action,BraseroProjectManager * manager)679 brasero_project_manager_new_video_prj_cb (GtkAction *action, BraseroProjectManager *manager)
680 {
681 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_VIDEO, TRUE);
682 }
683 
684 static void
brasero_project_manager_new_copy_prj_cb(GtkAction * action,BraseroProjectManager * manager)685 brasero_project_manager_new_copy_prj_cb (GtkAction *action, BraseroProjectManager *manager)
686 {
687 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_COPY, TRUE);
688 }
689 
690 static void
brasero_project_manager_new_iso_prj_cb(GtkAction * action,BraseroProjectManager * manager)691 brasero_project_manager_new_iso_prj_cb (GtkAction *action, BraseroProjectManager *manager)
692 {
693 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_ISO, TRUE);
694 }
695 
696 gboolean
brasero_project_manager_open_session(BraseroProjectManager * manager,BraseroSessionCfg * session)697 brasero_project_manager_open_session (BraseroProjectManager *manager,
698                                       BraseroSessionCfg *session)
699 {
700 	GtkAction *action;
701 	BraseroProjectType type;
702 
703 	type = brasero_project_open_session (BRASERO_PROJECT (manager->priv->project), session);
704 	if (type == BRASERO_PROJECT_TYPE_INVALID) {
705 		brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_INVALID, TRUE);
706 		return FALSE;
707 	}
708 
709 	brasero_project_manager_switch (manager,
710 					type,
711 					FALSE);
712 
713 	action = gtk_action_group_get_action (manager->priv->action_group, "NewChoose");
714 	gtk_action_set_sensitive (action, TRUE);
715 	return TRUE;
716 }
717 
718 static void
brasero_project_manager_open_cb(GtkAction * action,BraseroProjectManager * manager)719 brasero_project_manager_open_cb (GtkAction *action, BraseroProjectManager *manager)
720 {
721 	gchar *uri;
722 	gint answer;
723 	GtkWidget *chooser;
724 	GtkWidget *toplevel;
725 
726 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (manager));
727 	chooser = gtk_file_chooser_dialog_new (_("Open Project"),
728 					      GTK_WINDOW (toplevel),
729 					      GTK_FILE_CHOOSER_ACTION_OPEN,
730 					      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
731 					      GTK_STOCK_OPEN, GTK_RESPONSE_OK,
732 					      NULL);
733 	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
734 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
735 					     g_get_home_dir ());
736 
737 	gtk_widget_show (chooser);
738 	answer = gtk_dialog_run (GTK_DIALOG (chooser));
739 	if (answer != GTK_RESPONSE_OK) {
740 		gtk_widget_destroy (chooser);
741 		return;
742 	}
743 
744 	uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
745 	gtk_widget_destroy (chooser);
746 
747 	brasero_app_open_uri (brasero_app_get_default (), uri, TRUE);
748 	g_free (uri);
749 }
750 
751 static void
brasero_project_manager_recent_clicked_cb(BraseroProjectTypeChooser * chooser,const gchar * uri,BraseroProjectManager * manager)752 brasero_project_manager_recent_clicked_cb (BraseroProjectTypeChooser *chooser,
753 					   const gchar *uri,
754 					   BraseroProjectManager *manager)
755 {
756 	brasero_app_open_uri (brasero_app_get_default (), uri, TRUE);
757 }
758 
759 void
brasero_project_manager_empty(BraseroProjectManager * manager)760 brasero_project_manager_empty (BraseroProjectManager *manager)
761 {
762 	brasero_project_manager_switch (manager, BRASERO_PROJECT_TYPE_INVALID, TRUE);
763 }
764 
765 static void
brasero_project_manager_last_saved_clicked_cb(BraseroProjectTypeChooser * chooser,const gchar * path,BraseroProjectManager * manager)766 brasero_project_manager_last_saved_clicked_cb (BraseroProjectTypeChooser *chooser,
767 					       const gchar *path,
768 					       BraseroProjectManager *manager)
769 {
770 	if (path) {
771 		gchar *uri;
772 
773 		uri = g_filename_to_uri (path, NULL, NULL);
774 		brasero_app_open_project (brasero_app_get_default (),
775 					  NULL,
776 		                          uri,
777 		                          FALSE, // not a playlist
778 		                          FALSE, // should work so don't warn user
779 		                          FALSE); // don't burn right away
780 		g_free (uri);
781 	}
782 }
783 
784 gboolean
brasero_project_manager_save_session(BraseroProjectManager * manager,const gchar * path,gchar ** saved_uri,gboolean cancellable)785 brasero_project_manager_save_session (BraseroProjectManager *manager,
786 				      const gchar *path,
787 				      gchar **saved_uri,
788 				      gboolean cancellable)
789 {
790     	gboolean result = FALSE;
791 
792     	if (path) {
793 		gchar *uri;
794 
795 		/* if we want to save the current open project, this need a
796 		 * modification in BraseroProject to bypass ask_status in case
797 	 	 * DataDisc has not finished exploration */
798 		uri = g_filename_to_uri (path, NULL, NULL);
799     		result = brasero_project_save_session (BRASERO_PROJECT (manager->priv->project),
800 						       uri,
801 						       saved_uri,
802 						       cancellable);
803 		g_free (uri);
804 	}
805 
806     	return result;
807 }
808 
809 static void
brasero_project_manager_init(BraseroProjectManager * obj)810 brasero_project_manager_init (BraseroProjectManager *obj)
811 {
812 	GtkWidget *type;
813 	GtkAction *action;
814 	GtkWidget *chooser;
815 
816 	obj->priv = g_new0 (BraseroProjectManagerPrivate, 1);
817 
818 	gtk_notebook_set_show_border (GTK_NOTEBOOK (obj), FALSE);
819 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (obj), FALSE);
820 
821 	obj->priv->action_group = gtk_action_group_new ("ProjectManagerAction");
822 	gtk_action_group_set_translation_domain (obj->priv->action_group, GETTEXT_PACKAGE);
823 	gtk_action_group_add_actions (obj->priv->action_group,
824 				      entries,
825 				      G_N_ELEMENTS (entries),
826 				      obj);
827 
828 	action = gtk_action_group_get_action (obj->priv->action_group, "NewChoose");
829 	g_object_set (action,
830 		      "short-label", _("_New"), /* for toolbar buttons */
831 		      NULL);
832 	action = gtk_action_group_get_action (obj->priv->action_group, "Open");
833 	g_object_set (action,
834 		      "short-label", _("_Open"), /* for toolbar buttons */
835 		      NULL);
836 
837 	/* add the project type chooser to the notebook */
838 	type = brasero_project_type_chooser_new ();
839 	gtk_widget_show (type);
840 	g_signal_connect (type,
841 			  "chosen",
842 			  G_CALLBACK (brasero_project_manager_type_changed_cb),
843 			  obj);
844 	g_signal_connect (type,
845 			  "recent-clicked",
846 			  G_CALLBACK (brasero_project_manager_recent_clicked_cb),
847 			  obj);
848 	g_signal_connect (type,
849 			  "last-saved",
850 			  G_CALLBACK (brasero_project_manager_last_saved_clicked_cb),
851 			  obj);
852 	gtk_notebook_prepend_page (GTK_NOTEBOOK (obj), type, NULL);
853 
854 	/* add the layout */
855 	obj->priv->layout = brasero_layout_new ();
856 	gtk_widget_show (obj->priv->layout);
857 	gtk_notebook_append_page (GTK_NOTEBOOK (obj), obj->priv->layout, NULL);
858 
859 	g_signal_connect (obj->priv->layout,
860 			  "sidepane",
861 			  G_CALLBACK (brasero_project_manager_sidepane_changed),
862 			  obj);
863 
864 	/* create the project for audio and data discs */
865 	obj->priv->project = brasero_project_new ();
866 
867 #ifdef BUILD_PREVIEW
868 
869 	GtkWidget *preview;
870 
871 	preview = brasero_preview_new ();
872 	gtk_widget_show (preview);
873 	brasero_preview_add_source (BRASERO_PREVIEW (preview),
874 				    BRASERO_URI_CONTAINER (obj->priv->project));
875 
876 #endif /* BUILD_PREVIEW */
877 
878 	chooser = brasero_file_chooser_new ();
879     	BRASERO_PROJECT_MANAGER_CONNECT_CHANGED (obj, chooser);
880 
881 	gtk_widget_show_all (chooser);
882 	brasero_layout_add_source (BRASERO_LAYOUT (obj->priv->layout),
883 				   chooser,
884 				   "Chooser",
885 				   _("Browse the file system"),
886 				   GTK_STOCK_DIRECTORY,
887 				   BRASERO_LAYOUT_AUDIO|BRASERO_LAYOUT_DATA|BRASERO_LAYOUT_VIDEO);
888 
889 #ifdef BUILD_PREVIEW
890 	brasero_preview_add_source (BRASERO_PREVIEW (preview),
891 				    BRASERO_URI_CONTAINER (chooser));
892 #endif
893 
894 	brasero_layout_add_project (BRASERO_LAYOUT (obj->priv->layout),
895 				    obj->priv->project);
896 	gtk_widget_show (obj->priv->project);
897 
898 #ifdef BUILD_PLAYLIST
899 	GtkWidget *playlist;
900 
901 	playlist = brasero_playlist_new ();
902     	BRASERO_PROJECT_MANAGER_CONNECT_CHANGED (obj, playlist);
903 	gtk_widget_show_all (playlist);
904 	brasero_layout_add_source (BRASERO_LAYOUT (obj->priv->layout),
905 				   playlist,
906 				   "Playlist",
907 				   _("Display playlists and their contents"),
908 				   "audio-x-generic",
909 				   BRASERO_LAYOUT_AUDIO);
910 
911 #ifdef BUILD_PREVIEW
912 	brasero_preview_add_source (BRASERO_PREVIEW (preview),
913 				    BRASERO_URI_CONTAINER (playlist));
914 #endif
915 
916 #endif /* BUILD_PLAYLIST */
917 
918 #ifdef BUILD_PREVIEW
919 	brasero_layout_add_preview (BRASERO_LAYOUT (obj->priv->layout),
920 				    preview);
921 #endif
922 
923 }
924 
925 static void
brasero_project_manager_finalize(GObject * object)926 brasero_project_manager_finalize (GObject *object)
927 {
928 	BraseroProjectManager *cobj;
929 
930 	cobj = BRASERO_PROJECT_MANAGER (object);
931 
932 	if (cobj->priv->size_preview) {
933 		brasero_io_cancel_by_base (cobj->priv->size_preview);
934 		brasero_io_job_base_free (cobj->priv->size_preview);
935 		cobj->priv->size_preview = NULL;
936 	}
937 
938 	if (cobj->priv->preview_id) {
939 		g_source_remove (cobj->priv->preview_id);
940 		cobj->priv->preview_id = 0;
941 	}
942 
943 	if (cobj->priv->selected) {
944 		g_strfreev (cobj->priv->selected);
945 		cobj->priv->selected = NULL;
946 	}
947 
948 	g_free (cobj->priv);
949 
950 	G_OBJECT_CLASS (parent_class)->finalize (object);
951 }
952 
953 static void
brasero_project_manager_class_init(BraseroProjectManagerClass * klass)954 brasero_project_manager_class_init (BraseroProjectManagerClass *klass)
955 {
956 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
957 
958 	parent_class = g_type_class_peek_parent(klass);
959 	object_class->finalize = brasero_project_manager_finalize;
960 }
961 
962 GtkWidget *
brasero_project_manager_new()963 brasero_project_manager_new ()
964 {
965 	BraseroProjectManager *obj;
966 
967 	obj = BRASERO_PROJECT_MANAGER (g_object_new (BRASERO_TYPE_PROJECT_MANAGER, NULL));
968 
969 	return GTK_WIDGET (obj);
970 }
971