hythmbox-2.98/sources/sync/rb-sync-state-ui.c

No issues found

  1 /*
  2  *  Copyright (C) 2010 Jonathan Matthew <jonathan@d14n.org>
  3  *
  4  *  This program is free software; you can redistribute it and/or modify
  5  *  it under the terms of the GNU General Public License as published by
  6  *  the Free Software Foundation; either version 2 of the License, or
  7  *  (at your option) any later version.
  8  *
  9  *  The Rhythmbox authors hereby grant permission for non-GPL compatible
 10  *  GStreamer plugins to be used and distributed together with GStreamer
 11  *  and Rhythmbox. This permission is above and beyond the permissions granted
 12  *  by the GPL license by which Rhythmbox is covered. If you modify this code
 13  *  you may extend this exception to your version of the code, but you are not
 14  *  obligated to do so. If you do not wish to do so, delete this exception
 15  *  statement from your version.
 16  *
 17  *  This program 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 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 the Free Software
 24  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
 25  *
 26  */
 27 
 28 #include "config.h"
 29 
 30 #include <glib/gi18n.h>
 31 
 32 #include "rb-sync-state-ui.h"
 33 #include "rb-debug.h"
 34 #include "rb-util.h"
 35 #include "rb-file-helpers.h"
 36 #include "rb-builder-helpers.h"
 37 
 38 #include "rb-segmented-bar.h"
 39 
 40 struct _RBSyncStateUIPrivate
 41 {
 42 	/* we don't own a reference on this (maybe we should?) */
 43 	RBSyncState *state;
 44 
 45 	/* or any of these */
 46 	GtkWidget *add_count;
 47 	GtkWidget *remove_count;
 48 	RBSyncBarData sync_before;
 49 	RBSyncBarData sync_after;
 50 };
 51 
 52 enum {
 53 	PROP_0,
 54 	PROP_SYNC_STATE
 55 };
 56 
 57 G_DEFINE_TYPE (RBSyncStateUI, rb_sync_state_ui, GTK_TYPE_VBOX)
 58 
 59 
 60 static char *
 61 value_formatter (gdouble percent, RBSyncBarData *bar)
 62 {
 63 	return g_format_size (percent * bar->capacity);
 64 }
 65 
 66 void
 67 rb_sync_state_ui_create_bar (RBSyncBarData *bar, guint64 capacity, GtkWidget *label)
 68 {
 69 	bar->widget = rb_segmented_bar_new ();
 70 	bar->capacity = capacity;
 71 	g_object_set (bar->widget, "show-labels", TRUE, NULL);
 72 
 73 	rb_segmented_bar_set_value_formatter (RB_SEGMENTED_BAR (bar->widget),
 74 					      (RBSegmentedBarValueFormatter) value_formatter,
 75 					      bar);
 76 
 77 	bar->music_segment = rb_segmented_bar_add_segment (RB_SEGMENTED_BAR (bar->widget),_("Music"), 0.0, 0.2, 0.4, 0.65, 1.0);
 78 	bar->podcast_segment = rb_segmented_bar_add_segment (RB_SEGMENTED_BAR (bar->widget), _("Podcasts"), 0.0, 0.96, 0.47, 0.0, 1.0);
 79 	bar->other_segment = rb_segmented_bar_add_segment (RB_SEGMENTED_BAR (bar->widget), _("Other"), 0.0, 0.45, 0.82, 0.08, 1.0);
 80 	bar->free_segment = rb_segmented_bar_add_segment_default_color (RB_SEGMENTED_BAR (bar->widget), _("Available"), 1.0);
 81 
 82 	/* set up label relationship */
 83 	if (label != NULL) {
 84 		AtkObject *lobj;
 85 		AtkObject *robj;
 86 
 87 		lobj = gtk_widget_get_accessible (label);
 88 		robj = gtk_widget_get_accessible (bar->widget);
 89 
 90 		atk_object_add_relationship (lobj, ATK_RELATION_LABEL_FOR, robj);
 91 		atk_object_add_relationship (robj, ATK_RELATION_LABELLED_BY, lobj);
 92 	}
 93 }
 94 
 95 
 96 void
 97 rb_sync_state_ui_update_volume_usage (RBSyncBarData *bar, RBSyncState *state)
 98 {
 99 	RBMediaPlayerSource *source;
100 	double fraction;
101 	guint64 total_other;
102 	guint64 free_space;
103 
104 	g_object_get (state, "source", &source, NULL);
105 	free_space = rb_media_player_source_get_free_space (source);
106 	g_object_unref (source);
107 
108 	total_other = bar->capacity - (free_space + state->total_music_size + state->total_podcast_size);
109 
110 	fraction = (double)state->total_music_size/(double)bar->capacity;
111 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
112 					 bar->music_segment,
113 					 fraction);
114 	fraction = (double)state->total_podcast_size/(double)bar->capacity;
115 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
116 					 bar->podcast_segment,
117 					 fraction);
118 	fraction = (double)total_other/(double)bar->capacity;
119 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
120 					 bar->other_segment,
121 					 fraction);
122 	fraction = (double)free_space/(double)bar->capacity;
123 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
124 					 bar->free_segment,
125 					 fraction);
126 }
127 
128 static void
129 update_sync_after_bar (RBSyncBarData *bar, RBSyncState *state)
130 {
131 	RBMediaPlayerSource *source;
132 	RBSyncSettings *settings;
133 	double music_fraction;
134 	double podcast_fraction;
135 	double other_fraction;
136 	double free_fraction;
137 	guint64 total_other_size;
138 
139 	g_object_get (state,
140 		      "source", &source,
141 		      "sync-settings", &settings,
142 		      NULL);
143 
144 	if (rb_sync_settings_has_enabled_groups (settings, SYNC_CATEGORY_MUSIC) ||
145 	    rb_sync_settings_sync_category (settings, SYNC_CATEGORY_MUSIC)) {
146 		music_fraction = (double)state->sync_music_size / (double)bar->capacity;
147 	} else {
148 		music_fraction = (double)state->total_music_size / (double)bar->capacity;
149 	}
150 	if (rb_sync_settings_has_enabled_groups (settings, SYNC_CATEGORY_PODCAST) ||
151 	    rb_sync_settings_sync_category (settings, SYNC_CATEGORY_PODCAST)) {
152 		podcast_fraction = (double)state->sync_podcast_size / (double)bar->capacity;
153 	} else {
154 		podcast_fraction = (double)state->total_podcast_size / (double)bar->capacity;
155 	}
156 
157 	total_other_size = bar->capacity - (rb_media_player_source_get_free_space (source) + state->total_music_size + state->total_podcast_size);
158 	other_fraction = (double)total_other_size / (double)bar->capacity;
159 
160 	free_fraction = 1.0 - (music_fraction + podcast_fraction + other_fraction);
161 	if (free_fraction < 0.0) {
162 		free_fraction = 0.0;
163 	}
164 
165 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
166 					 bar->music_segment,
167 					 music_fraction);
168 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
169 					 bar->podcast_segment,
170 					 podcast_fraction);
171 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
172 					 bar->other_segment,
173 					 other_fraction);
174 	rb_segmented_bar_update_segment (RB_SEGMENTED_BAR (bar->widget),
175 					 bar->free_segment,
176 					 free_fraction);
177 
178 	g_object_unref (source);
179 	g_object_unref (settings);
180 }
181 
182 static void
183 sync_state_updated (RBSyncState *state, RBSyncStateUI *ui)
184 {
185 	char *text;
186 	rb_debug ("sync state updated");
187 
188 	/* sync before state */
189 	rb_sync_state_ui_update_volume_usage (&ui->priv->sync_before, state);
190 	update_sync_after_bar (&ui->priv->sync_after, state);
191 
192 	/* other stuff */
193 	text = g_strdup_printf ("%d", state->sync_add_count);
194 	gtk_label_set_text (GTK_LABEL (ui->priv->add_count), text);
195 	g_free (text);
196 
197 	text = g_strdup_printf ("%d", state->sync_remove_count);
198 	gtk_label_set_text (GTK_LABEL (ui->priv->remove_count), text);
199 	g_free (text);
200 }
201 
202 
203 GtkWidget *
204 rb_sync_state_ui_new (RBSyncState *state)
205 {
206 	GObject *ui;
207 	ui = g_object_new (RB_TYPE_SYNC_STATE_UI,
208 			   "sync-state", state,
209 			   NULL);
210 	return GTK_WIDGET (ui);
211 }
212 
213 static void
214 rb_sync_state_ui_init (RBSyncStateUI *ui)
215 {
216 	ui->priv = G_TYPE_INSTANCE_GET_PRIVATE (ui, RB_TYPE_SYNC_STATE_UI, RBSyncStateUIPrivate);
217 }
218 
219 static void
220 build_ui (RBSyncStateUI *ui)
221 {
222 	RBMediaPlayerSource *source;
223 	GtkWidget *widget;
224 	GtkWidget *container;
225 	guint64 capacity;
226 	GtkBuilder *builder;
227 	const char *ui_file;
228 
229 	g_object_get (ui->priv->state, "source", &source, NULL);
230 	capacity = rb_media_player_source_get_capacity (source);
231 	g_object_unref (source);
232 
233 	ui_file = rb_file ("sync-state.ui");
234 	if (ui_file == NULL) {
235 		g_warning ("Couldn't find sync-state.ui");
236 		return;
237 	}
238 
239 	builder = rb_builder_load (ui_file, NULL);
240 	if (builder == NULL) {
241 		g_warning ("Couldn't load sync-state.ui");
242 		return;
243 	}
244 
245 	container = GTK_WIDGET (gtk_builder_get_object (builder, "sync-state-ui"));
246 	gtk_box_pack_start (GTK_BOX (ui), container, TRUE, TRUE, 0);
247 
248 	ui->priv->add_count = GTK_WIDGET (gtk_builder_get_object (builder, "added-tracks"));
249 	ui->priv->remove_count = GTK_WIDGET (gtk_builder_get_object (builder, "removed-tracks"));
250 
251 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "sync-before-label"));
252 	rb_sync_state_ui_create_bar (&ui->priv->sync_before, capacity, widget);
253 	container = GTK_WIDGET (gtk_builder_get_object (builder, "sync-before-container"));
254 	gtk_container_add (GTK_CONTAINER (container), ui->priv->sync_before.widget);
255 
256 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "sync-after-label"));
257 	rb_sync_state_ui_create_bar (&ui->priv->sync_after, capacity, widget);
258 	container = GTK_WIDGET (gtk_builder_get_object (builder, "sync-after-container"));
259 	gtk_container_add (GTK_CONTAINER (container), ui->priv->sync_after.widget);
260 
261 	g_object_unref (builder);
262 }
263 
264 static void
265 impl_constructed (GObject *object)
266 {
267 	RBSyncStateUI *ui = RB_SYNC_STATE_UI (object);
268 
269 	build_ui (ui);
270 	sync_state_updated (ui->priv->state, ui);
271 
272 	g_signal_connect_object (ui->priv->state,
273 				 "updated",
274 				 G_CALLBACK (sync_state_updated),
275 				 ui, 0);
276 
277 	RB_CHAIN_GOBJECT_METHOD(rb_sync_state_ui_parent_class, constructed, object);
278 }
279 
280 
281 static void
282 impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
283 {
284 	RBSyncStateUI *ui = RB_SYNC_STATE_UI (object);
285 	switch (prop_id) {
286 	case PROP_SYNC_STATE:
287 		ui->priv->state = g_value_get_object (value);
288 		break;
289 	default:
290 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
291 		break;
292 	}
293 }
294 
295 static void
296 impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
297 {
298 	RBSyncStateUI *ui = RB_SYNC_STATE_UI (object);
299 	switch (prop_id) {
300 	case PROP_SYNC_STATE:
301 		g_value_set_object (value, ui->priv->state);
302 		break;
303 	default:
304 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
305 		break;
306 	}
307 }
308 
309 
310 static void
311 rb_sync_state_ui_class_init (RBSyncStateUIClass *klass)
312 {
313 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
314 
315 	object_class->constructed = impl_constructed;
316 	object_class->set_property = impl_set_property;
317 	object_class->get_property = impl_get_property;
318 
319 	g_object_class_install_property (object_class,
320 					 PROP_SYNC_STATE,
321 					 g_param_spec_object ("sync-state",
322 							      "sync-state",
323 							      "RBSyncState instance",
324 							      RB_TYPE_SYNC_STATE,
325 							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
326 
327 	g_type_class_add_private (object_class, sizeof (RBSyncStateUIPrivate));
328 }