/* * * Copyright (c) 2008-2009 Erich Hoover * * libr GTK support - Convenience functions for using resources in GTK applications * * This program 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.1 of the License, or * (at your option) any later version. * * 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 Place, Suite 330, Boston, MA 02111-1307 USA * * To provide feedback, report bugs, or otherwise contact me: * ehoover at mines dot edu * */ /* Include compile-time parameters */ #include "config.h" #include "libr.h" #include "libr-gtk.h" #include "libr-icons.h" #include "tempfiles.h" /* For loading GTK/GDK images */ #include #include /* For loading GLADE files */ #include /* For loading GTK+ Builder files */ #include /* For malloc/free */ #include /* For string handling */ #include typedef gchar * (*GladeFileCallback)(GladeXML *, const gchar *, guint *); GladeFileCallback glade_set_file_callback(GladeFileCallback callback, gpointer user_data); /* Use weak binding for all glade and GTK+ requirements */ #pragma weak glade_set_file_callback #pragma weak gtk_window_set_default_icon_list #pragma weak gdk_pixbuf_loader_get_pixbuf #pragma weak gtk_builder_add_from_string #pragma weak gdk_pixbuf_loader_set_size #pragma weak g_type_check_instance_cast #pragma weak gtk_builder_add_from_file #pragma weak glade_xml_new_from_buffer #pragma weak gdk_pixbuf_loader_write #pragma weak gdk_pixbuf_loader_close #pragma weak gdk_pixbuf_loader_new #pragma weak g_signal_connect_data #pragma weak g_signal_connect #pragma weak gtk_builder_new #pragma weak g_object_unref #pragma weak glade_xml_new #pragma weak g_list_append #pragma weak glade_init #pragma weak gtk_init #pragma weak g_free #define GLADE_SECTION ".glade" #define BUILDER_SECTION ".ui" /* * Handle the resource request from libglade */ gchar *libr_glade_read_resource(GladeXML *gladefile, const gchar *filename, guint *size, gpointer user_data) { return libr_malloc((libr_file *) user_data, (char *) filename, (size_t *) size); } /* * Handle the resource request from GtkBuilder */ gboolean libr_gtk_read_resource(GtkBuilder *builder, const gchar *filename, gchar **data, gsize *size, GError **error, gpointer user_data) { if(data == NULL) return FALSE; *data = libr_malloc((libr_file *) user_data, (char *) filename, (size_t *) size); if(*data == NULL) return FALSE; return TRUE; } /* * Load the libglade resource appropriately for the currently installed version * (AKA, hurray hacks!) */ GladeXML *libr_new_glade(libr_file *handle, char *gladefile, size_t gladefile_size) { if(glade_set_file_callback) /* The not-yet (ever?) existing way */ { /* Register a callback for libglade to load our resources */ if(glade_set_file_callback((GladeFileCallback) libr_glade_read_resource, handle) != NULL) printf("warning: over-wrote an application callback!\n"); /* Initialize libglade almost as usual, just use a buffer instead of a file */ return glade_xml_new_from_buffer(gladefile, gladefile_size, NULL, NULL); } else /* The hacky way */ { char *glade_file[PATH_MAX]; GladeXML *ret = NULL; char *temp_folder; temp_folder = libr_extract_resources(handle); if(temp_folder == NULL) return NULL; strcpy((char*)glade_file, temp_folder); strcat((char*)glade_file, "/"); strcat((char*)glade_file, GLADE_SECTION); ret = glade_xml_new((char*)glade_file, NULL, NULL); if(ret == NULL) cleanup_folder(temp_folder); else register_folder_cleanup(temp_folder); return ret; } } /* * Load the GtkBuilder resource appropriately for the currently installed version * (AKA, hurray hacks!) */ int libr_new_builder(libr_file *handle, char *builderfile, size_t builderfile_size, GtkBuilder *builder) { /* Register a callback for GtkBuilder to load our resources */ if(g_signal_connect(builder, "load-resource", (GCallback) libr_gtk_read_resource, handle)) { /* Initialize GtkBuilder almost as usual, just use a buffer instead of a file */ if(gtk_builder_add_from_string(builder, builderfile, builderfile_size, NULL) == 0) return false; return true; } else /* The hacky way */ { char *builder_file[PATH_MAX]; char *temp_folder; int ret = false; temp_folder = libr_extract_resources(handle); if(temp_folder == NULL) return false; strcpy((char*)builder_file, temp_folder); strcat((char*)builder_file, "/"); strcat((char*)builder_file, BUILDER_SECTION); ret = gtk_builder_add_from_file(builder, (char*)builder_file, NULL); if(ret == 0) cleanup_folder(temp_folder); else register_folder_cleanup(temp_folder); g_free(temp_folder); return (ret != 0); } } /* * Return a GTK icon list */ EXPORT_FN IconList *libr_gtk_iconlist(libr_file *handle) { int sizes[] = {16, 32, 48, 96, 128}; IconList *icons = NULL; GdkPixbuf *icon = NULL; int sizes_len = 5, i; if(handle == NULL) { /* Must pass a file handle to obtain the icons from */ return NULL; } if(gtk_init == NULL) { /* GTK+ was not linked with the application */ return false; } /* Go through the list of GTK "required" image sizes and build the icons */ for(i=0;i