evolution-3.6.4/modules/cal-config-google/e-google-chooser-dialog.c

No issues found

  1 /*
  2  * e-google-chooser-dialog.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <webcal://www.gnu.org/licenses/>
 16  *
 17  */
 18 
 19 #include "e-google-chooser-dialog.h"
 20 
 21 #include <config.h>
 22 #include <glib/gi18n-lib.h>
 23 
 24 #define E_GOOGLE_CHOOSER_DIALOG_GET_PRIVATE(obj) \
 25 	(G_TYPE_INSTANCE_GET_PRIVATE \
 26 	((obj), E_TYPE_GOOGLE_CHOOSER_DIALOG, EGoogleChooserDialogPrivate))
 27 
 28 struct _EGoogleChooserDialogPrivate {
 29 	EGoogleChooser *chooser;
 30 	GCancellable *cancellable;
 31 
 32 	GtkWidget *info_bar;		/* not referenced */
 33 	GtkWidget *info_bar_label;	/* not referenced */
 34 };
 35 
 36 enum {
 37 	PROP_0,
 38 	PROP_CHOOSER
 39 };
 40 
 41 G_DEFINE_DYNAMIC_TYPE (
 42 	EGoogleChooserDialog,
 43 	e_google_chooser_dialog,
 44 	GTK_TYPE_DIALOG)
 45 
 46 static void
 47 google_chooser_dialog_populated_cb (EGoogleChooser *chooser,
 48                                     GAsyncResult *result,
 49                                     EGoogleChooserDialog *dialog)
 50 {
 51 	GdkWindow *window;
 52 	GError *error = NULL;
 53 
 54 	e_google_chooser_populate_finish (chooser, result, &error);
 55 
 56 	/* Ignore cancellations, and leave the mouse cursor alone
 57 	 * since the GdkWindow may have already been destroyed. */
 58 	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 59 		goto exit;
 60 
 61 	/* Reset the mouse cursor to normal. */
 62 	window = gtk_widget_get_window (GTK_WIDGET (dialog));
 63 	gdk_window_set_cursor (window, NULL);
 64 
 65 	if (error != NULL) {
 66 		GtkLabel *label;
 67 
 68 		label = GTK_LABEL (dialog->priv->info_bar_label);
 69 		gtk_label_set_text (label, error->message);
 70 		gtk_widget_show (dialog->priv->info_bar);
 71 
 72 		g_error_free (error);
 73 		goto exit;
 74 	}
 75 
 76 exit:
 77 	g_object_unref (dialog);
 78 }
 79 
 80 static void
 81 google_chooser_dialog_row_activated_cb (GtkTreeView *tree_view,
 82                                         GtkTreePath *path,
 83                                         GtkTreeViewColumn *column,
 84                                         GtkDialog *dialog)
 85 {
 86 	gtk_dialog_response (dialog, GTK_RESPONSE_APPLY);
 87 }
 88 
 89 static void
 90 google_chooser_dialog_selection_changed_cb (GtkTreeSelection *selection,
 91                                             GtkDialog *dialog)
 92 {
 93 	gboolean sensitive;
 94 
 95 	sensitive = (gtk_tree_selection_count_selected_rows (selection) > 0);
 96 
 97 	gtk_dialog_set_response_sensitive (
 98 		dialog, GTK_RESPONSE_APPLY, sensitive);
 99 }
100 
101 static void
102 google_chooser_dialog_set_chooser (EGoogleChooserDialog *dialog,
103                                    EGoogleChooser *chooser)
104 {
105 	g_return_if_fail (E_IS_GOOGLE_CHOOSER (chooser));
106 	g_return_if_fail (dialog->priv->chooser == NULL);
107 
108 	dialog->priv->chooser = g_object_ref_sink (chooser);
109 }
110 
111 static void
112 google_chooser_dialog_set_property (GObject *object,
113                                     guint property_id,
114                                     const GValue *value,
115                                     GParamSpec *pspec)
116 {
117 	switch (property_id) {
118 		case PROP_CHOOSER:
119 			google_chooser_dialog_set_chooser (
120 				E_GOOGLE_CHOOSER_DIALOG (object),
121 				g_value_get_object (value));
122 			return;
123 	}
124 
125 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
126 }
127 
128 static void
129 google_chooser_dialog_get_property (GObject *object,
130                                     guint property_id,
131                                     GValue *value,
132                                     GParamSpec *pspec)
133 {
134 	switch (property_id) {
135 		case PROP_CHOOSER:
136 			g_value_set_object (
137 				value,
138 				e_google_chooser_dialog_get_chooser (
139 				E_GOOGLE_CHOOSER_DIALOG (object)));
140 			return;
141 	}
142 
143 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
144 }
145 
146 static void
147 google_chooser_dialog_dispose (GObject *object)
148 {
149 	EGoogleChooserDialogPrivate *priv;
150 
151 	priv = E_GOOGLE_CHOOSER_DIALOG_GET_PRIVATE (object);
152 
153 	if (priv->chooser != NULL) {
154 		g_signal_handlers_disconnect_by_func (
155 			priv->chooser, google_chooser_dialog_row_activated_cb,
156 			object);
157 		g_object_unref (priv->chooser);
158 		priv->chooser = NULL;
159 	}
160 
161 	if (priv->cancellable != NULL) {
162 		g_cancellable_cancel (priv->cancellable);
163 		g_object_unref (priv->cancellable);
164 		priv->cancellable = NULL;
165 	}
166 
167 	/* Chain up to parent's dispose() method. */
168 	G_OBJECT_CLASS (e_google_chooser_dialog_parent_class)->dispose (object);
169 }
170 
171 static void
172 google_chooser_dialog_constructed (GObject *object)
173 {
174 	EGoogleChooserDialog *dialog;
175 	GtkTreeSelection *selection;
176 	GtkWidget *container;
177 	GtkWidget *widget;
178 	GtkWidget *vbox;
179 	const gchar *title;
180 
181 	dialog = E_GOOGLE_CHOOSER_DIALOG (object);
182 
183 	/* Chain up to parent's constructed() method. */
184 	G_OBJECT_CLASS (e_google_chooser_dialog_parent_class)->
185 		constructed (object);
186 
187 	gtk_dialog_add_button (
188 		GTK_DIALOG (dialog),
189 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
190 
191 	gtk_dialog_add_button (
192 		GTK_DIALOG (dialog),
193 		GTK_STOCK_APPLY, GTK_RESPONSE_APPLY);
194 
195 	gtk_dialog_set_default_response (
196 		GTK_DIALOG (dialog), GTK_RESPONSE_APPLY);
197 	gtk_dialog_set_response_sensitive (
198 		GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, FALSE);
199 
200 	title = _("Choose a Calendar");
201 	gtk_window_set_title (GTK_WINDOW (dialog), title);
202 	gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 400);
203 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
204 
205 	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
206 
207 	widget = gtk_vbox_new (FALSE, 6);
208 	gtk_container_set_border_width (GTK_CONTAINER (widget), 5);
209 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
210 	gtk_widget_show (widget);
211 
212 	container = vbox = widget;
213 
214 	widget = gtk_scrolled_window_new (NULL, NULL);
215 	gtk_scrolled_window_set_policy (
216 		GTK_SCROLLED_WINDOW (widget),
217 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
218 	gtk_scrolled_window_set_shadow_type (
219 		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
220 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
221 	gtk_widget_show (widget);
222 
223 	container = widget;
224 
225 	widget = GTK_WIDGET (dialog->priv->chooser);
226 	gtk_container_add (GTK_CONTAINER (container), widget);
227 	gtk_widget_show (widget);
228 
229 	g_signal_connect (
230 		widget, "row-activated",
231 		G_CALLBACK (google_chooser_dialog_row_activated_cb), dialog);
232 
233 	/* Build the info bar, but hide it initially. */
234 
235 	container = vbox;
236 
237 	widget = gtk_info_bar_new ();
238 	gtk_info_bar_set_message_type (
239 		GTK_INFO_BAR (widget), GTK_MESSAGE_WARNING);
240 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
241 	dialog->priv->info_bar = widget;  /* do not reference */
242 	gtk_widget_hide (widget);
243 
244 	container = gtk_info_bar_get_content_area (GTK_INFO_BAR (widget));
245 
246 	widget = gtk_hbox_new (FALSE, 6);
247 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
248 	gtk_widget_show (widget);
249 
250 	container = widget;
251 
252 	widget = gtk_image_new_from_stock (
253 		GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU);
254 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
255 	gtk_widget_show (widget);
256 
257 	widget = gtk_label_new ("");
258 	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
259 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
260 	dialog->priv->info_bar_label = widget;  /* do not reference */
261 	gtk_widget_show (widget);
262 
263 	/* Listen for tree view selection changes. */
264 
265 	selection = gtk_tree_view_get_selection (
266 		GTK_TREE_VIEW (dialog->priv->chooser));
267 
268 	g_signal_connect (
269 		selection, "changed",
270 		G_CALLBACK (google_chooser_dialog_selection_changed_cb),
271 		dialog);
272 }
273 
274 static void
275 google_chooser_dialog_realize (GtkWidget *widget)
276 {
277 	EGoogleChooserDialogPrivate *priv;
278 	GdkCursor *cursor;
279 	GdkWindow *window;
280 	GdkDisplay *display;
281 
282 	priv = E_GOOGLE_CHOOSER_DIALOG_GET_PRIVATE (widget);
283 
284 	/* Chain up to parent's realize() method. */
285 	GTK_WIDGET_CLASS (e_google_chooser_dialog_parent_class)->
286 		realize (widget);
287 
288 	g_return_if_fail (priv->cancellable == NULL);
289 	priv->cancellable = g_cancellable_new ();
290 
291 	/* Show a busy mouse cursor while populating. */
292 	window = gtk_widget_get_window (widget);
293 	display = gtk_widget_get_display (widget);
294 	cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
295 	gdk_window_set_cursor (window, cursor);
296 	gdk_cursor_unref (cursor);
297 
298 	e_google_chooser_populate (
299 		priv->chooser, priv->cancellable, (GAsyncReadyCallback)
300 		google_chooser_dialog_populated_cb, g_object_ref (widget));
301 }
302 
303 static void
304 google_chooser_dialog_response (GtkDialog *dialog,
305                                 gint response_id)
306 {
307 	EGoogleChooserDialogPrivate *priv;
308 
309 	priv = E_GOOGLE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
310 
311 	if (response_id == GTK_RESPONSE_APPLY)
312 		e_google_chooser_apply_selected (priv->chooser);
313 }
314 
315 static void
316 e_google_chooser_dialog_class_init (EGoogleChooserDialogClass *class)
317 {
318 	GObjectClass *object_class;
319 	GtkWidgetClass *widget_class;
320 	GtkDialogClass *dialog_class;
321 
322 	g_type_class_add_private (class, sizeof (EGoogleChooserDialogPrivate));
323 
324 	object_class = G_OBJECT_CLASS (class);
325 	object_class->set_property = google_chooser_dialog_set_property;
326 	object_class->get_property = google_chooser_dialog_get_property;
327 	object_class->dispose = google_chooser_dialog_dispose;
328 	object_class->constructed = google_chooser_dialog_constructed;
329 
330 	widget_class = GTK_WIDGET_CLASS (class);
331 	widget_class->realize = google_chooser_dialog_realize;
332 
333 	dialog_class = GTK_DIALOG_CLASS (class);
334 	dialog_class->response = google_chooser_dialog_response;
335 
336 	g_object_class_install_property (
337 		object_class,
338 		PROP_CHOOSER,
339 		g_param_spec_object (
340 			"chooser",
341 			NULL,
342 			NULL,
343 			E_TYPE_GOOGLE_CHOOSER,
344 			G_PARAM_READWRITE |
345 			G_PARAM_CONSTRUCT_ONLY));
346 }
347 
348 static void
349 e_google_chooser_dialog_class_finalize (EGoogleChooserDialogClass *class)
350 {
351 }
352 
353 static void
354 e_google_chooser_dialog_init (EGoogleChooserDialog *dialog)
355 {
356 	dialog->priv = E_GOOGLE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
357 }
358 
359 void
360 e_google_chooser_dialog_type_register (GTypeModule *type_module)
361 {
362 	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
363 	 *     function, so we have to wrap it with a public function in
364 	 *     order to register types from a separate compilation unit. */
365 	e_google_chooser_dialog_register_type (type_module);
366 }
367 
368 GtkWidget *
369 e_google_chooser_dialog_new (EGoogleChooser *chooser,
370                              GtkWindow *parent)
371 {
372 	g_return_val_if_fail (E_IS_GOOGLE_CHOOSER (chooser), NULL);
373 	g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
374 
375 	return g_object_new (
376 		E_TYPE_GOOGLE_CHOOSER_DIALOG,
377 		"chooser", chooser, "transient-for", parent, NULL);
378 }
379 
380 EGoogleChooser *
381 e_google_chooser_dialog_get_chooser (EGoogleChooserDialog *dialog)
382 {
383 	g_return_val_if_fail (E_IS_GOOGLE_CHOOSER_DIALOG (dialog), NULL);
384 
385 	return dialog->priv->chooser;
386 }