/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- * * Copyright (C) 2012 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include "cc-background-chooser-dialog.h" #include "bg-wallpapers-source.h" #include "bg-pictures-source.h" #include "bg-colors-source.h" #ifdef HAVE_LIBSOCIALWEB #include "bg-flickr-source.h" #endif #include "cc-background-item.h" #include "cc-background-xml.h" #define WP_PATH_ID "org.gnome.desktop.background" #define WP_URI_KEY "picture-uri" #define WP_OPTIONS_KEY "picture-options" #define WP_SHADING_KEY "color-shading-type" #define WP_PCOLOR_KEY "primary-color" #define WP_SCOLOR_KEY "secondary-color" enum { SOURCE_WALLPAPERS, SOURCE_PICTURES, SOURCE_COLORS, #ifdef HAVE_LIBSOCIALWEB SOURCE_FLICKR #endif }; struct _CcBackgroundChooserDialogPrivate { GtkListStore *sources; GtkWidget *icon_view; BgWallpapersSource *wallpapers_source; BgPicturesSource *pictures_source; BgColorsSource *colors_source; #ifdef HAVE_LIBSOCIALWEB BgFlickrSource *flickr_source; #endif GnomeDesktopThumbnailFactory *thumb_factory; gint current_source; GCancellable *copy_cancellable; GtkWidget *spinner; }; #define CC_CHOOSER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CC_TYPE_BACKGROUND_CHOOSER_DIALOG, CcBackgroundChooserDialogPrivate)) enum { PROP_0, }; G_DEFINE_TYPE (CcBackgroundChooserDialog, cc_background_chooser_dialog, GTK_TYPE_DIALOG) static void cc_background_chooser_dialog_realize (GtkWidget *widget) { CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (widget); GtkWindow *parent; parent = gtk_window_get_transient_for (GTK_WINDOW (chooser)); if (parent != NULL) { gint width; gint height; gtk_window_get_size (parent, &width, &height); gtk_widget_set_size_request (GTK_WIDGET (chooser), (gint) (0.5 * width), (gint) (0.9 * height)); } gtk_icon_view_set_model (GTK_ICON_VIEW (chooser->priv->icon_view), GTK_TREE_MODEL (bg_source_get_liststore (BG_SOURCE (chooser->priv->wallpapers_source)))); GTK_WIDGET_CLASS (cc_background_chooser_dialog_parent_class)->realize (widget); } static void cc_background_chooser_dialog_dispose (GObject *object) { CcBackgroundChooserDialog *chooser = CC_BACKGROUND_CHOOSER_DIALOG (object); CcBackgroundChooserDialogPrivate *priv = chooser->priv; if (priv->copy_cancellable) { /* cancel any copy operation */ g_cancellable_cancel (priv->copy_cancellable); g_clear_object (&priv->copy_cancellable); } g_clear_object (&priv->pictures_source); g_clear_object (&priv->colors_source); g_clear_object (&priv->wallpapers_source); g_clear_object (&priv->thumb_factory); G_OBJECT_CLASS (cc_background_chooser_dialog_parent_class)->dispose (object); } static void cc_background_chooser_dialog_finalize (GObject *object) { G_OBJECT_CLASS (cc_background_chooser_dialog_parent_class)->finalize (object); } static void on_view_toggled (GtkToggleButton *button, CcBackgroundChooserDialog *chooser) { BgSource *source; if (!gtk_toggle_button_get_active (button)) return; source = g_object_get_data (G_OBJECT (button), "source"); gtk_icon_view_set_model (GTK_ICON_VIEW (chooser->priv->icon_view), GTK_TREE_MODEL (bg_source_get_liststore (source))); } static void on_selection_changed (GtkIconView *icon_view, CcBackgroundChooserDialog *chooser) { GList *list; list = gtk_icon_view_get_selected_items (icon_view); gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, (list != NULL)); g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); } static void on_item_activated (GtkIconView *icon_view, GtkTreePath *path, CcBackgroundChooserDialog *chooser) { gtk_dialog_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK); } static void cc_background_chooser_dialog_init (CcBackgroundChooserDialog *chooser) { CcBackgroundChooserDialogPrivate *priv; GtkCellRenderer *renderer; GtkWidget *sw_content; GtkWidget *vbox; GtkWidget *button1; GtkWidget *button; GtkWidget *hbox; GtkWidget *grid; GtkStyleContext *context; chooser->priv = CC_CHOOSER_DIALOG_GET_PRIVATE (chooser); priv = chooser->priv; priv->wallpapers_source = bg_wallpapers_source_new (); priv->pictures_source = bg_pictures_source_new (); priv->colors_source = bg_colors_source_new (); #ifdef HAVE_LIBSOCIALWEB priv->flickr_source = bg_flickr_source_new (); #endif gtk_container_set_border_width (GTK_CONTAINER (chooser), 6); gtk_window_set_modal (GTK_WINDOW (chooser), TRUE); gtk_window_set_resizable (GTK_WINDOW (chooser), FALSE); /* translators: This is the title of the wallpaper chooser dialog. */ gtk_window_set_title (GTK_WINDOW (chooser), _("Select Background")); vbox = gtk_dialog_get_content_area (GTK_DIALOG (chooser)); grid = gtk_grid_new (); gtk_container_set_border_width (GTK_CONTAINER (grid), 5); gtk_widget_set_margin_bottom (grid, 6); gtk_orientable_set_orientation (GTK_ORIENTABLE (grid), GTK_ORIENTATION_VERTICAL); gtk_grid_set_row_spacing (GTK_GRID (grid), 12); gtk_grid_set_column_spacing (GTK_GRID (grid), 0); gtk_container_add (GTK_CONTAINER (vbox), grid); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE); gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER); gtk_widget_set_hexpand (hbox, TRUE); gtk_container_add (GTK_CONTAINER (grid), hbox); context = gtk_widget_get_style_context (hbox); gtk_style_context_add_class (context, "linked"); button1 = gtk_radio_button_new_with_label (NULL, _("Wallpapers")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE); context = gtk_widget_get_style_context (button1); gtk_style_context_add_class (context, "raised"); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button1), FALSE); gtk_container_add (GTK_CONTAINER (hbox), button1); g_signal_connect (button1, "toggled", G_CALLBACK (on_view_toggled), chooser); g_object_set_data (G_OBJECT (button1), "source", priv->wallpapers_source); button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button1), _("Pictures")); context = gtk_widget_get_style_context (button); gtk_style_context_add_class (context, "raised"); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); gtk_container_add (GTK_CONTAINER (hbox), button); g_signal_connect (button, "toggled", G_CALLBACK (on_view_toggled), chooser); g_object_set_data (G_OBJECT (button), "source", priv->pictures_source); button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button1), _("Colors")); context = gtk_widget_get_style_context (button); gtk_style_context_add_class (context, "raised"); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); gtk_container_add (GTK_CONTAINER (hbox), button); g_signal_connect (button, "toggled", G_CALLBACK (on_view_toggled), chooser); g_object_set_data (G_OBJECT (button), "source", priv->colors_source); #ifdef HAVE_LIBSOCIALWEB button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button1), _("Flickr")); context = gtk_widget_get_style_context (button); gtk_style_context_add_class (context, "raised"); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); gtk_container_add (GTK_CONTAINER (hbox), button); g_signal_connect (button, "toggled", G_CALLBACK (on_view_toggled), chooser); g_object_set_data (G_OBJECT (button), "source", priv->flickr_source); #endif sw_content = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw_content), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw_content), GTK_SHADOW_IN); gtk_widget_set_hexpand (sw_content, TRUE); gtk_widget_set_vexpand (sw_content, TRUE); gtk_container_add (GTK_CONTAINER (grid), sw_content); g_object_set (sw_content, "width-request", 860, "height-request", 550, NULL); priv->icon_view = gtk_icon_view_new (); gtk_widget_set_hexpand (priv->icon_view, TRUE); gtk_container_add (GTK_CONTAINER (sw_content), priv->icon_view); g_signal_connect (priv->icon_view, "selection-changed", G_CALLBACK (on_selection_changed), chooser); g_signal_connect (priv->icon_view, "item-activated", G_CALLBACK (on_item_activated), chooser); renderer = gtk_cell_renderer_pixbuf_new (); /* set stock size to 32px so that emblems render at 16px. see: * https://bugzilla.gnome.org/show_bug.cgi?id=682123#c4 */ g_object_set (renderer, "stock-size", GTK_ICON_SIZE_DND, NULL); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->icon_view), renderer, FALSE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->icon_view), renderer, "gicon", 0, NULL); gtk_dialog_add_button (GTK_DIALOG (chooser), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button (GTK_DIALOG (chooser), _("Select"), GTK_RESPONSE_OK); gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, FALSE); gtk_widget_show_all (vbox); } static void cc_background_chooser_dialog_class_init (CcBackgroundChooserDialogClass *klass) { GObjectClass *object_class; GtkWidgetClass *widget_class; object_class = G_OBJECT_CLASS (klass); object_class->dispose = cc_background_chooser_dialog_dispose; object_class->finalize = cc_background_chooser_dialog_finalize; widget_class = GTK_WIDGET_CLASS (klass); widget_class->realize = cc_background_chooser_dialog_realize; g_type_class_add_private (object_class, sizeof (CcBackgroundChooserDialogPrivate)); } GtkWidget * cc_background_chooser_dialog_new (void) { return g_object_new (CC_TYPE_BACKGROUND_CHOOSER_DIALOG, NULL); } CcBackgroundItem * cc_background_chooser_dialog_get_item (CcBackgroundChooserDialog *chooser) { CcBackgroundChooserDialogPrivate *priv = chooser->priv; GtkTreeIter iter; GtkTreeModel *model; GList *list; CcBackgroundItem *item; item = NULL; list = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (priv->icon_view)); if (!list) return NULL; model = gtk_icon_view_get_model (GTK_ICON_VIEW (priv->icon_view)); if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) list->data) == FALSE) goto bail; gtk_tree_model_get (model, &iter, 1, &item, -1); bail: g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); return item; }