[rhythmbox] media-player: display dialog to allow user to correct sync settings



commit 67d9571388384f98c2de96d3185461b865f346ab
Author: Jonathan Matthew <jonathan d14n org>
Date:   Fri Jun 4 16:00:59 2010 +1000

    media-player: display dialog to allow user to correct sync settings
    
    If the user hasn't selected anything to sync or the selected items
    would not fit on the device, we now display a sync settings dialog when
    the user tries to sync.  This allows the user to fix the settings and
    then continue or alternatively cancel the sync.

 data/ui/Makefile.am              |    1 +
 data/ui/sync-dialog.ui           |  113 ++++++++++++++++++++++
 po/POTFILES.in                   |    1 +
 sources/rb-media-player-source.c |  193 ++++++++++++++++++++++++++++++++------
 4 files changed, 279 insertions(+), 29 deletions(-)
---
diff --git a/data/ui/Makefile.am b/data/ui/Makefile.am
index ff94ff3..01d57be 100644
--- a/data/ui/Makefile.am
+++ b/data/ui/Makefile.am
@@ -15,6 +15,7 @@ GTK_BUILDER_FILES =					\
 	podcast-properties.ui				\
 	song-info.ui					\
 	song-info-multiple.ui				\
+	sync-dialog.ui					\
 	sync-state.ui					\
 	uri-new.ui
 
diff --git a/data/ui/sync-dialog.ui b/data/ui/sync-dialog.ui
new file mode 100644
index 0000000..fe0b411
--- /dev/null
+++ b/data/ui/sync-dialog.ui
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkVBox" id="sync-dialog">
+    <property name="visible">True</property>
+    <property name="border_width">12</property>
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkFrame" id="frame4">
+        <property name="visible">True</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">none</property>
+        <child>
+          <object class="GtkVBox" id="vbox4">
+            <property name="visible">True</property>
+            <property name="border_width">12</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkScrolledWindow" id="sync-settings-ui-container">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="label-frame-sync">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">&lt;b&gt;Sync Preferences&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkFrame" id="frame7">
+        <property name="visible">True</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">none</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="left_padding">12</property>
+            <child>
+              <object class="GtkHBox" id="sync-state-ui-container">
+                <property name="visible">True</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">&lt;b&gt;Sync Preview&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkHBox" id="sync-dialog-message">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkImage" id="error-image">
+            <property name="visible">True</property>
+            <property name="xpad">6</property>
+            <property name="stock">gtk-dialog-error</property>
+            <property name="icon-size">6</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="padding">12</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="sync-dialog-reason">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="padding">6</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bb41ce7..cad07e6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -15,6 +15,7 @@ backends/rb-player.c
 [type: gettext/glade]data/ui/podcast-properties.ui
 [type: gettext/glade]data/ui/song-info-multiple.ui
 [type: gettext/glade]data/ui/song-info.ui
+[type: gettext/glade]data/ui/sync-dialog.ui
 [type: gettext/glade]data/ui/sync-state.ui
 [type: gettext/glade]data/ui/uri-new.ui
 data/playlists.xml.in
diff --git a/sources/rb-media-player-source.c b/sources/rb-media-player-source.c
index 31bed7e..5f61f4e 100644
--- a/sources/rb-media-player-source.c
+++ b/sources/rb-media-player-source.c
@@ -58,16 +58,11 @@ typedef struct {
 	GtkDialog *properties_dialog;
 	RBSyncBarData volume_usage;
 
-	/* segmented bars used in various places */
-	SegmentedBarData volume_usage;
-	SegmentedBarData sync_before;		/* probably the same as volume usage? */
-	SegmentedBarData sync_after;
-
-	/* other bits of device state */
-	guint64 total_music_size;
-	guint64 total_podcast_size;
-	guint64 sync_music_size;
-	guint64 sync_podcast_size;
+	/* sync settings dialog bits */
+	GtkWidget *sync_dialog;
+	GtkWidget *sync_dialog_label;
+	GtkWidget *sync_dialog_error_box;
+	guint sync_dialog_update_id;
 
 	/* sync state */
 	RBSyncState *sync_state;
@@ -591,38 +586,178 @@ sync_delete_done_cb (RBMediaPlayerSource *source, gpointer dontcare)
 }
 
 static gboolean
-sync_idle_cb_delete_entries (RBMediaPlayerSource *source)
+sync_has_items_enabled (RBMediaPlayerSource *source)
 {
 	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (source);
-	rb_debug ("deleting %d files from media player", priv->sync_state->sync_remove_count);
-	rb_media_player_source_delete_entries (source,
-					       priv->sync_state->sync_to_remove,
-					       (RBMediaPlayerSourceDeleteCallback) sync_delete_done_cb,
-					       NULL,
-					       NULL);
-	return FALSE;
+	if (rb_sync_settings_sync_category (priv->sync_settings, SYNC_CATEGORY_MUSIC) == FALSE &&
+	    rb_sync_settings_has_enabled_groups (priv->sync_settings, SYNC_CATEGORY_MUSIC) == FALSE &&
+	    rb_sync_settings_sync_category (priv->sync_settings, SYNC_CATEGORY_PODCAST) == FALSE &&
+	    rb_sync_settings_has_enabled_groups (priv->sync_settings, SYNC_CATEGORY_PODCAST) == FALSE) {
+		rb_debug ("no sync items are enabled");
+		return FALSE;
+	}
+
+	return TRUE;
 }
 
 static gboolean
-sync_idle_cb_update_sync (RBMediaPlayerSource *source)
+sync_has_enough_space (RBMediaPlayerSource *source)
 {
 	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (source);
+	if (priv->sync_state->sync_space_needed > rb_media_player_source_get_capacity (source)) {
+		rb_debug ("not enough space for selected sync items");
+		return FALSE;
+	}
 
-	update_sync (source);
+	return TRUE;
+}
+
+static void
+update_sync_settings_dialog (RBMediaPlayerSource *source)
+{
+	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (source);
+	gboolean can_continue;
+
+	if (sync_has_items_enabled (source) == FALSE) {
+		can_continue = FALSE;
+		gtk_label_set_text (GTK_LABEL (priv->sync_dialog_label),
+				    _("You have not selected any music, playlists, or podcasts to transfer to this device."));
+	} else if (sync_has_enough_space (source) == FALSE) {
+		can_continue = FALSE;
+		gtk_label_set_text (GTK_LABEL (priv->sync_dialog_label),
+				    _("There is not enough space on the device to transfer the selected music, playlists and podcasts."));
+	} else {
+		can_continue = TRUE;
+	}
+
+	gtk_widget_set_visible (priv->sync_dialog_error_box, !can_continue);
+	gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->sync_dialog), GTK_RESPONSE_YES, can_continue);
+}
+
+static void
+sync_dialog_state_update (RBSyncState *state, RBMediaPlayerSource *source)
+{
+	update_sync_settings_dialog (source);
+}
+
+static void
+sync_confirm_dialog_cb (GtkDialog *dialog,
+			gint response_id,
+			RBMediaPlayerSource *source)
+{
+	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (source);
+
+	g_signal_handler_disconnect (priv->sync_state, priv->sync_dialog_update_id);
+	priv->sync_dialog_update_id = 0;
+
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	priv->sync_dialog = NULL;
+	priv->sync_dialog_label = NULL;
 
-	/* Check we have enough space on the device. */
-	if (priv->sync_space_needed > get_capacity (source)) {
-		rb_debug ("not enough free space on device; need %" G_GINT64_FORMAT ", capacity is %" G_GINT64_FORMAT,
-			  priv->sync_space_needed,
-			  get_capacity (source));
-		rb_error_dialog (NULL,
-				 _("Not enough free space to sync"),
-				 _("There is not enough free space on this device to transfer the selected music, playlists, and podcasts."));
+	if (response_id != GTK_RESPONSE_YES) {
+		rb_debug ("user doesn't want to sync");
 		g_idle_add ((GSourceFunc)sync_idle_cb_cleanup, source);
+	} else {
+		rb_debug ("user wants to sync");
+		g_idle_add ((GSourceFunc) sync_idle_delete_entries, source);
+	}
+}
+
+
+static void
+display_sync_settings_dialog (RBMediaPlayerSource *source)
+{
+	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (source);
+	GtkWidget *content;
+	GtkWidget *widget;
+	GtkBuilder *builder;
+	const char *ui_file;
+	char *name;
+	char *title;
+
+	g_object_get (source, "name", &name, NULL);
+	title = g_strdup_printf (_("%s Sync Settings"), name);
+
+	priv->sync_dialog = gtk_dialog_new_with_buttons (title,
+							 NULL,
+							 0,
+							 _("Sync with the device"),
+							 GTK_RESPONSE_YES,
+							 _("Cancel"),
+							 GTK_RESPONSE_CANCEL,
+							 NULL);
+	g_free (title);
+
+	priv->sync_dialog_update_id = g_signal_connect_object (priv->sync_state,
+							       "updated",
+							       G_CALLBACK (sync_dialog_state_update),
+							       source, 0);
+	g_signal_connect_object (priv->sync_dialog,
+				 "response",
+				 G_CALLBACK (sync_confirm_dialog_cb),
+				 source, 0);
+
+	/* display the sync settings, the sync state, and some helpful text indicating why
+	 * we're not syncing already
+	 */
+	content = gtk_dialog_get_content_area (GTK_DIALOG (priv->sync_dialog));
+
+	ui_file = rb_file ("sync-dialog.ui");
+	if (ui_file == NULL) {
+		g_warning ("Couldn't find sync-state.ui");
+		gtk_widget_show_all (priv->sync_dialog);
+		return;
+	}
+
+	builder = rb_builder_load (ui_file, NULL);
+	if (builder == NULL) {
+		g_warning ("Couldn't load sync-state.ui");
+		gtk_widget_show_all (priv->sync_dialog);
+		return;
+	}
+
+	priv->sync_dialog_label = GTK_WIDGET (gtk_builder_get_object (builder, "sync-dialog-reason"));
+	priv->sync_dialog_error_box = GTK_WIDGET (gtk_builder_get_object (builder, "sync-dialog-message"));
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "sync-settings-ui-container"));
+	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (widget), rb_sync_settings_ui_new (source, priv->sync_settings));
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "sync-state-ui-container"));
+	gtk_box_pack_start (GTK_BOX (widget), rb_sync_state_ui_new (priv->sync_state), TRUE, TRUE, 0);
+
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "sync-dialog"));
+	gtk_box_pack_start (GTK_BOX (content), widget, TRUE, TRUE, 0);
+
+	gtk_widget_show_all (priv->sync_dialog);
+	update_sync_settings_dialog (source);
+	g_object_unref (builder);
+}
+
+static gboolean
+sync_idle_cb_update_sync (RBMediaPlayerSource *source)
+{
+	update_sync (source);
+
+	if (sync_has_items_enabled (source) == FALSE || sync_has_enough_space (source) == FALSE) {
+		rb_debug ("displaying sync settings dialog");
+		display_sync_settings_dialog (source);
 		return FALSE;
 	}
 
-	g_idle_add ((GSourceFunc)sync_idle_cb_delete_entries, source);
+	rb_debug ("sync settings are acceptable");
+	return sync_idle_delete_entries (source);
+}
+
+static gboolean
+sync_idle_delete_entries (RBMediaPlayerSource *source)
+{
+	RBMediaPlayerSourcePrivate *priv = MEDIA_PLAYER_SOURCE_GET_PRIVATE (source);
+	rb_debug ("deleting %d files from media player", priv->sync_state->sync_remove_count);
+	rb_media_player_source_delete_entries (source,
+					       priv->sync_state->sync_to_remove,
+					       (RBMediaPlayerSourceDeleteCallback) sync_delete_done_cb,
+					       NULL,
+					       NULL);
 	return FALSE;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]