gnome-control-center/capplets/background/gnome-wp-item.c
Rodney Dawes f69be2bd96 Add an Apply button
2006-01-26  Rodney Dawes  <dobey@novell.com>

	* gnome-background-properties.glade: Add an Apply button

	* gnome-wp-capplet.[ch]: Replace old_filename with an old_item struct
	(gnome_wp_props_wp_set): Set the filename key to empty string when
	setting the background to "No Wallpaper"
	(gnome_wp_props_revert): New method to revert changes in the dialog
	when the Cancel button is clicked
	(gnome_wp_main_quit): Free the old_item structure
	(wallpaper_properties_clicked): Handle the Apply button
	Handle closing the dialog for OK separately from Cancel/delete_event
	Revert the settings when Cancel or wm "x" or ESC are clicked
	(gnome_wp_load_stuffs): Set the old_item to the currently selected
	background setting, whether it be an image or "No Wallpaper"

	* gnome-wp-info.c (gnome_wp_info_dup): If info is NULL, just return
	NULL rather than trying to access members of an empty struct

	* gnome-wp-item.[ch] (gnome_wp_item_dup): New method to create a
	duplicate and newly allocated GnomeWPItem structure

	Fixes #327335
2006-01-27 03:01:58 +00:00

354 lines
10 KiB
C

/*
* Authors: Rodney Dawes <dobey@ximian.com>
*
* Copyright 2003-2006 Novell, Inc. (www.novell.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*
*/
#include <config.h>
#include <gconf/gconf-client.h>
#include <gnome.h>
#include <string.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include "gnome-wp-item.h"
#include "gnome-wp-utils.h"
GnomeWPItem * gnome_wp_item_new (const gchar * filename,
GHashTable * wallpapers,
GnomeThumbnailFactory * thumbnails) {
GnomeWPItem * item = NULL;
GdkColor color1, color2;
GConfClient * client;
client = gconf_client_get_default ();
item = g_new0 (GnomeWPItem, 1);
item->filename = gnome_vfs_unescape_string_for_display (filename);
item->fileinfo = gnome_wp_info_new (item->filename, thumbnails);
item->shade_type = gconf_client_get_string (client, WP_SHADING_KEY, NULL);
item->pri_color = gconf_client_get_string (client, WP_PCOLOR_KEY, NULL);
item->sec_color = gconf_client_get_string (client, WP_SCOLOR_KEY, NULL);
gdk_color_parse (item->pri_color, &color1);
gdk_color_parse (item->sec_color, &color2);
item->pcolor = gdk_color_copy (&color1);
item->scolor = gdk_color_copy (&color2);
if (item->fileinfo != NULL &&
!strncmp (item->fileinfo->mime_type, "image/", strlen ("image/"))) {
if (item->name == NULL) {
if (g_utf8_validate (item->fileinfo->name, -1, NULL))
item->name = g_strdup (item->fileinfo->name);
else
item->name = g_filename_to_utf8 (item->fileinfo->name, -1, NULL,
NULL, NULL);
}
item->options = gconf_client_get_string (client, WP_OPTIONS_KEY, NULL);
if (!strcmp (item->options, "none")) {
item->options = g_strdup ("scaled");
}
gnome_wp_item_update_description (item);
g_hash_table_insert (wallpapers, g_strdup (item->filename), item);
} else {
gnome_wp_item_free (item);
item = NULL;
}
g_object_unref (client);
return item;
}
void gnome_wp_item_free (GnomeWPItem * item) {
if (item == NULL) {
return;
}
g_free (item->name);
g_free (item->filename);
g_free (item->description);
g_free (item->imguri);
g_free (item->options);
g_free (item->shade_type);
g_free (item->pri_color);
g_free (item->sec_color);
if (item->pcolor != NULL)
gdk_color_free (item->pcolor);
if (item->scolor != NULL)
gdk_color_free (item->scolor);
gnome_wp_info_free (item->fileinfo);
gnome_wp_info_free (item->uriinfo);
gtk_tree_row_reference_free (item->rowref);
item = NULL;
}
GnomeWPItem * gnome_wp_item_dup (GnomeWPItem * item) {
GnomeWPItem * new_item;
GdkColor color1, color2;
if (item == NULL) {
return NULL;
}
new_item = g_new0 (GnomeWPItem, 1);
new_item->name = g_strdup (item->name);
new_item->filename = g_strdup (item->filename);
new_item->description = g_strdup (item->description);
new_item->imguri = g_strdup (item->imguri);
new_item->options = g_strdup (item->options);
new_item->shade_type = g_strdup (item->shade_type);
new_item->pri_color = g_strdup (item->pri_color);
new_item->sec_color = g_strdup (item->sec_color);
gdk_color_parse (item->pri_color, &color1);
gdk_color_parse (item->sec_color, &color2);
item->pcolor = gdk_color_copy (&color1);
item->scolor = gdk_color_copy (&color2);
new_item->fileinfo = gnome_wp_info_dup (item->fileinfo);
new_item->uriinfo = gnome_wp_info_dup (item->uriinfo);
new_item->rowref = gtk_tree_row_reference_copy (item->rowref);
new_item->deleted = item->deleted;
new_item->width = item->width;
new_item->height = item->height;
return new_item;
}
static void collect_save_options (GdkPixbuf * pixbuf,
gchar *** keys,
gchar *** vals,
gint width,
gint height) {
gchar ** options;
gint n, count;
count = 0;
options = g_object_get_qdata (G_OBJECT (pixbuf),
g_quark_from_static_string ("gdk_pixbuf_options"));
if (options) {
for (n = 0; options[2 * n]; n++) {
++count;
*keys = g_realloc (*keys, sizeof (gchar *) * (count + 1));
*vals = g_realloc (*vals, sizeof (gchar *) * (count + 1));
(*keys)[count - 1] = g_strdup (options[2 * n]);
(*vals)[count - 1] = g_strdup (options[2 * n + 1]);
(*keys)[count] = NULL;
(*vals)[count] = NULL;
}
}
++count;
*keys = g_realloc (*keys, sizeof (gchar *) * (count + 1));
*vals = g_realloc (*vals, sizeof (gchar *) * (count + 1));
(*keys)[count - 1] = g_strdup ("tEXt::Thumb::Image::Width");
(*vals)[count - 1] = g_strdup_printf ("%d", width);
(*keys)[count] = NULL;
(*vals)[count] = NULL;
++count;
*keys = g_realloc (*keys, sizeof (gchar *) * (count + 1));
*vals = g_realloc (*vals, sizeof (gchar *) * (count + 1));
(*keys)[count - 1] = g_strdup ("tEXt::Thumb::Image::Height");
(*vals)[count - 1] = g_strdup_printf ("%d", height);
(*keys)[count] = NULL;
(*vals)[count] = NULL;
}
#define LIST_IMAGE_WIDTH 64
GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item,
GnomeThumbnailFactory * thumbs) {
GdkPixbuf * pixbuf, * bgpixbuf;
GdkPixbuf * tmpbuf;
GdkPixbuf * scaled = NULL;
gint sw, sh, bw, bh, pw, ph, tw, th;
gdouble ratio;
sw = sh = bw = bh = pw = ph = tw = th = 0;
/*
Get the size of the screen and calculate our aspect ratio divisor
We do this, so that images are thumbnailed as they would look on
the screen in reality
*/
sw = gdk_screen_get_width (gdk_screen_get_default ());
sh = gdk_screen_get_height (gdk_screen_get_default ());
ratio = (gdouble) sw / (gdouble) LIST_IMAGE_WIDTH;
bw = sw / ratio;
bh = sh / ratio;
/*
Create the pixbuf for the background colors, which will show up for
oddly sized images, smaller images that are centered, or alpha images
*/
if (!strcmp (item->shade_type, "solid")) {
bgpixbuf = gnome_wp_pixbuf_new_solid (item->pcolor, bw, bh);
} else if (!strcmp (item->shade_type, "vertical-gradient")) {
bgpixbuf = gnome_wp_pixbuf_new_gradient (GTK_ORIENTATION_VERTICAL,
item->pcolor, item->scolor,
bw, bh);
} else {
bgpixbuf = gnome_wp_pixbuf_new_gradient (GTK_ORIENTATION_HORIZONTAL,
item->pcolor, item->scolor,
bw, bh);
}
/*
Load up the thumbnail image using the thumbnail spec
If the image doesn't exist, we create it
If we are creating the thumbnail for "No Wallpaper", then we just copy
the background colors pixbuf we created above, here
*/
if (item->fileinfo->thumburi != NULL &&
g_file_test (item->fileinfo->thumburi, G_FILE_TEST_EXISTS)) {
pixbuf = gdk_pixbuf_new_from_file (item->fileinfo->thumburi, NULL);
} else if (!strcmp (item->filename, "(none)")) {
return bgpixbuf;
} else {
gchar * escaped_path;
escaped_path = gnome_vfs_escape_path_string (item->filename);
pixbuf = gnome_thumbnail_factory_generate_thumbnail (thumbs,
escaped_path,
item->fileinfo->mime_type);
gnome_thumbnail_factory_save_thumbnail (thumbs, pixbuf,
escaped_path,
item->fileinfo->mtime);
g_free (escaped_path);
}
if (pixbuf != NULL) {
const gchar * w_val, * h_val;
w_val = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Width");
h_val = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Height");
if (item->width <= 0 || item->height <= 0) {
if (w_val && h_val) {
item->width = atoi (w_val);
item->height = atoi (h_val);
} else {
gchar ** keys = NULL;
gchar ** vals = NULL;
tmpbuf = gdk_pixbuf_new_from_file (item->filename, NULL);
item->width = gdk_pixbuf_get_width (tmpbuf);
item->height = gdk_pixbuf_get_height (tmpbuf);
collect_save_options (pixbuf, &keys, &vals, item->width, item->height);
gdk_pixbuf_savev (pixbuf, item->fileinfo->thumburi, "png",
keys, vals, NULL);
g_object_unref (tmpbuf);
g_strfreev (keys);
g_strfreev (vals);
}
}
pw = gdk_pixbuf_get_width (pixbuf);
ph = gdk_pixbuf_get_height (pixbuf);
if (item->width <= bw && item->height <= bh)
ratio = 1.0;
tw = item->width / ratio;
th = item->height / ratio;
if (!strcmp (item->options, "wallpaper")) {
scaled = gnome_wp_pixbuf_tile (pixbuf, bgpixbuf, tw, th);
} else if (!strcmp (item->options, "centered")) {
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th);
} else if (!strcmp (item->options, "stretched")) {
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, bw, bh);
} else if (!strcmp (item->options, "scaled")) {
if ((gdouble) ph * (gdouble) bw > (gdouble) pw * (gdouble) bh) {
tw = 0.5 + (gdouble) pw * (gdouble) bh / (gdouble) ph;
th = bh;
} else {
th = 0.5 + (gdouble) ph * (gdouble) bw / (gdouble) pw;
tw = bw;
}
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th);
} else if (!strcmp (item->options, "zoom")) {
if ((gdouble) ph * (gdouble) bw < (gdouble) pw * (gdouble) bh) {
tw = 0.5 + (gdouble) pw * (gdouble) bh / (gdouble) ph;
th = bh;
} else {
th = 0.5 + (gdouble) ph * (gdouble) bw / (gdouble) pw;
tw = bw;
}
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th);
}
}
g_object_unref (pixbuf);
g_object_unref (bgpixbuf);
return scaled;
}
void gnome_wp_item_update_description (GnomeWPItem * item) {
if (!strcmp (item->filename, "(none)")) {
item->description = g_strdup_printf ("<b>%s</b>", item->name);
} else {
gchar * info;
info = g_strdup_printf ("%s, %d %s x %d %s",
gnome_vfs_mime_get_description (item->fileinfo->mime_type),
item->width,
ngettext ("pixel", "pixels", item->width),
item->height,
ngettext ("pixel", "pixels", item->height));
item->description = g_markup_printf_escaped ("<b>%s</b>\n"
"%s",
item->name,
info);
g_free (info);
}
}