desktop item editing



Hey,

I've taken a stab at adding desktop item editing to the property window.
I changed the current custom icon stuff to set the 'Name' field in the
desktop item instead of using the nautilus metadata API.  There is also
a nautilus extension that provides property pages for 'Link' and
'Application' desktop items which allows you to edit their properties.
Screenshots here:

http://www.snorp.net/files/screenshots/ditem-launcher-edit.png
http://www.snorp.net/files/screenshots/ditem-link-edit.png

The desktop item saving is done synchronously, which sucks, but there
doesn't seem to be any async API for it.

James
Index: src/nautilus-application.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-application.c,v
retrieving revision 1.220
diff -u -r1.220 nautilus-application.c
--- src/nautilus-application.c	14 Apr 2004 15:35:24 -0000	1.220
+++ src/nautilus-application.c	4 May 2004 21:01:24 -0000
@@ -30,6 +30,7 @@
 
 
 #include "file-manager/fm-bonobo-provider.h"
+#include "file-manager/fm-ditem-page.h"
 #include "file-manager/fm-desktop-icon-view.h"
 #include "file-manager/fm-icon-view.h"
 #include "file-manager/fm-list-view.h"
@@ -404,6 +405,7 @@
 	nautilus_module_init ();
 
 	nautilus_module_add_type (FM_TYPE_BONOBO_PROVIDER);
+	nautilus_module_add_type (FM_TYPE_DITEM_PAGE);
 	
 	/* initialize the sound machinery */
 	nautilus_sound_init ();
Index: src/file-manager/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/Makefile.am,v
retrieving revision 1.77
diff -u -r1.77 Makefile.am
--- src/file-manager/Makefile.am	13 Jan 2004 12:29:10 -0000	1.77
+++ src/file-manager/Makefile.am	4 May 2004 21:01:24 -0000
@@ -18,6 +18,7 @@
 	fm-bonobo-provider.c            \
 	fm-desktop-icon-view.c		\
 	fm-directory-view.c		\
+	fm-ditem-page.c			\
 	fm-error-reporting.c		\
 	fm-icon-container.c		\
 	fm-icon-view.c			\
@@ -31,6 +32,7 @@
 	fm-bonobo-provider.h 		\
 	fm-desktop-icon-view.h 		\
 	fm-directory-view.h 		\
+	fm-ditem-page.h			\
 	fm-error-reporting.h 		\
 	fm-icon-container.h		\
 	fm-icon-view.h 			\
Index: src/file-manager/fm-bonobo-provider.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-bonobo-provider.c,v
retrieving revision 1.3
diff -u -r1.3 fm-bonobo-provider.c
--- src/file-manager/fm-bonobo-provider.c	5 Feb 2004 06:26:08 -0000	1.3
+++ src/file-manager/fm-bonobo-provider.c	4 May 2004 21:01:24 -0000
@@ -18,7 +18,7 @@
  *  License along with this library; if not, write to the Free
  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  Authors: James Willcox <james gnome org>
+ *  Authors: James Willcox <jwillcox gnome org>
  *           Dave Camp <dave ximian com>
  *
  */
Index: src/file-manager/fm-bonobo-provider.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-bonobo-provider.h,v
retrieving revision 1.2
diff -u -r1.2 fm-bonobo-provider.h
--- src/file-manager/fm-bonobo-provider.h	11 Jan 2004 20:34:52 -0000	1.2
+++ src/file-manager/fm-bonobo-provider.h	4 May 2004 21:01:24 -0000
@@ -19,7 +19,7 @@
  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  Authors: Dave Camp <dave ximian com>
- *           James Willcox <james gnome org>
+ *           James Willcox <jwillcox gnome org>
  * 
  */
 
Index: src/file-manager/fm-properties-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.c,v
retrieving revision 1.199
diff -u -r1.199 fm-properties-window.c
--- src/file-manager/fm-properties-window.c	30 Mar 2004 16:35:28 -0000	1.199
+++ src/file-manager/fm-properties-window.c	4 May 2004 21:01:24 -0000
@@ -3691,6 +3691,8 @@
 {
 	NautilusFile *file;
 	char *icon_uri;
+	GnomeDesktopItem *ditem;
+	char *file_uri;
 	
 	g_return_if_fail (properties_window != NULL);
 	g_return_if_fail (FM_IS_PROPERTIES_WINDOW (properties_window));
@@ -3701,10 +3703,23 @@
 		icon_uri = gnome_vfs_get_uri_from_local_path (icon_path);
 		for (l = properties_window->details->original_files; l != NULL; l = l->next) {
 			file = NAUTILUS_FILE (l->data);
+			file_uri = nautilus_file_get_uri (file);
+			ditem = gnome_desktop_item_new_from_uri (file_uri,
+								 GNOME_DESKTOP_ITEM_LOAD_ONLY_IF_EXISTS,
+								 NULL);
+			if (ditem != NULL) {
+				gnome_desktop_item_set_string (ditem,
+							       GNOME_DESKTOP_ITEM_ICON,
+							       icon_path);
+				gnome_desktop_item_save (ditem, NULL, TRUE, NULL);
+				gnome_desktop_item_unref (ditem);
+			} else {
 			
-			nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL, icon_uri);
-			nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_ICON_SCALE, NULL, NULL);
+				nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL, icon_uri);
+				nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_ICON_SCALE, NULL, NULL);
+			}
 
+			g_free (file_uri);
 		}
 		g_free (icon_uri);	
 		
/*
 *  fm-ditem-page.c: Desktop item editing support
 * 
 *  Copyright (C) 2004 James Willcox
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Authors: James Willcox <jwillcox gnome org>
 *
 */

/* This object exports the bonobo context menus and property pages
 * using the new extension interface. */ 

#include <config.h>
#include "fm-ditem-page.h"

#include <string.h>

#include <eel/eel-glib-extensions.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtktable.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkalignment.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkdnd.h>
#include <gtk/gtkfilechooserdialog.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-uidefs.h>
#include <libnautilus-extension/nautilus-extension-types.h>
#include <libnautilus-extension/nautilus-file-info.h>
#include <libnautilus-extension/nautilus-property-page-provider.h>
#include <libgnome/gnome-desktop-item.h>
#include <eel/eel-vfs-extensions.h>
#include <libgnomevfs/gnome-vfs-utils.h>

static void fm_ditem_page_instance_init            (FMDitemPage               *provider);
static void fm_ditem_page_class_init               (FMDitemPageClass          *class);

static GObjectClass *parent_class;

typedef struct ItemEntry {
	const char *field;
	const char *description;
	gboolean localized;
	gboolean filename;
} ItemEntry;

enum {
	TARGET_URI_LIST
};

static GtkTargetEntry target_table[] = {
        { "text/uri-list",  0, TARGET_URI_LIST }
};


static ItemEntry *
item_entry_new (const char *field,
		const char *description,
		gboolean localized,
		gboolean filename)
{
	ItemEntry *entry = g_malloc (sizeof (ItemEntry));
	entry->field = field;
	entry->description = description;
	entry->localized = localized;
	entry->filename = filename;
	
	return entry;
}

static void
item_entry_free (ItemEntry *entry)
{
	g_free (entry);
}

static void
entry_text_changed_cb (GtkEntry *entry,
		       GnomeDesktopItem *item)
{
	ItemEntry *item_entry = g_object_get_data (G_OBJECT (entry), "item_entry");
	const char *val = gtk_entry_get_text (entry);

	if (item_entry->localized) {
		gnome_desktop_item_set_localestring (item, item_entry->field, val);
	} else {
		gnome_desktop_item_set_string (item, item_entry->field, val);
	}
}

static void
box_unrealize_cb (GObject *box, GnomeDesktopItem *item)
{
	GError *error = NULL;
	char *uri;

	uri = g_object_get_data (G_OBJECT (box), "uri");

	if (!gnome_desktop_item_save (item, uri, TRUE, &error)) {
		g_warning (error->message);
		g_error_free (error);
	}
	
	gnome_desktop_item_unref (item);
}

static void
fm_ditem_page_url_drag_data_received (GtkWidget *widget, GdkDragContext *context,
				      int x, int y,
				      GtkSelectionData *selection_data,
				      guint info, guint time,
				      GtkEntry *entry)
{
	char **uris;
	gboolean exactly_one;
	char *path;
	
	uris = g_strsplit (selection_data->data, "\r\n", 0);
        exactly_one = uris[0] != NULL && (uris[1] == NULL || uris[1][0] == '\0');

	if (!exactly_one) {
		g_strfreev (uris);
		return;
	}

	path = gnome_vfs_get_local_path_from_uri (uris[0]);
	if (path != NULL) {
		gtk_entry_set_text (entry, path);
		g_free (path);
	} else {
		gtk_entry_set_text (entry, uris[0]);
	}
	
	g_strfreev (uris);
}

static void
fm_ditem_page_exec_drag_data_received (GtkWidget *widget, GdkDragContext *context,
				       int x, int y,
				       GtkSelectionData *selection_data,
				       guint info, guint time,
				       GtkEntry *entry)
{
	char **uris;
	gboolean exactly_one;
	GnomeDesktopItem *item;
	
	uris = g_strsplit (selection_data->data, "\r\n", 0);
        exactly_one = uris[0] != NULL && (uris[1] == NULL || uris[1][0] == '\0');

	if (!exactly_one) {
		g_strfreev (uris);
		return;
	}

	item = gnome_desktop_item_new_from_uri (uris[0],
						GNOME_DESKTOP_ITEM_LOAD_ONLY_IF_EXISTS,
						NULL);
	if (item != NULL &&
	    gnome_desktop_item_get_entry_type (item) == GNOME_DESKTOP_ITEM_TYPE_APPLICATION) {
		gtk_entry_set_text (entry,
				    gnome_desktop_item_get_string (item,
								   GNOME_DESKTOP_ITEM_EXEC));
		gnome_desktop_item_unref (item);
	}
	
	g_strfreev (uris);
}

static GtkWidget *
build_table (GnomeDesktopItem *item,
	     GList *entries,
	     int length) {
	GtkWidget *table;
	GtkWidget *label;
	GtkWidget *entry;
	GList *l;
	const char *val;
	int i;
	
	table = gtk_table_new (length, 2, FALSE);
	i = 0;
	
	for (l = entries; l; l = l->next) {
		ItemEntry *item_entry = (ItemEntry *)l->data;
		char *label_text;

		label_text = g_strdup_printf ("<b>%s:</b>", item_entry->description);
		label = gtk_label_new (label_text);
		gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
		g_free (label_text);
		gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);

		entry = gtk_entry_new ();

		if (item_entry->localized) {
			val = gnome_desktop_item_get_localestring (item,
								   item_entry->field);
		} else {
			val = gnome_desktop_item_get_string (item, item_entry->field);
		}
		
		gtk_entry_set_text (GTK_ENTRY (entry), val);

		gtk_table_attach (GTK_TABLE (table), label,
				  0, 1, i, i+1, GTK_FILL, GTK_FILL,
				  6, 6);
		gtk_table_attach (GTK_TABLE (table), entry,
				  1, 2, i, i+1, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL,
				  6, 6);
		g_signal_connect (entry, "changed",
				  G_CALLBACK (entry_text_changed_cb),
				  item);
		g_object_set_data_full (G_OBJECT (entry), "item_entry", item_entry,
					(GDestroyNotify)item_entry_free);

		if (item_entry->filename) {
			gtk_drag_dest_set (GTK_WIDGET (entry),
					   GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
					   target_table, G_N_ELEMENTS (target_table),
					   GDK_ACTION_COPY | GDK_ACTION_MOVE);
			
			g_signal_connect (entry, "drag_data_received",
					  G_CALLBACK (fm_ditem_page_url_drag_data_received),
					  entry);
		} else if (strcmp (item_entry->field,
				   GNOME_DESKTOP_ITEM_EXEC) == 0) {
			gtk_drag_dest_set (GTK_WIDGET (entry),
					   GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
					   target_table, G_N_ELEMENTS (target_table),
					   GDK_ACTION_COPY | GDK_ACTION_MOVE);
			
			g_signal_connect (entry, "drag_data_received",
					  G_CALLBACK (fm_ditem_page_exec_drag_data_received),
					  entry);
		}
		
		i++;
	}


	gtk_widget_show_all (table);
	return table;
}

static void
create_page (GnomeDesktopItem *item, GtkWidget *box, gboolean link)
{
	GtkWidget *table;
	GList *entries = NULL;

	if (link) {
		entries = g_list_prepend (entries,
					  item_entry_new (GNOME_DESKTOP_ITEM_COMMENT,
							  _("Comment"), TRUE, FALSE));
		entries = g_list_prepend (entries,
					  item_entry_new (GNOME_DESKTOP_ITEM_URL,
							  _("URL"), FALSE, TRUE));
		entries = g_list_prepend (entries,
					  item_entry_new (GNOME_DESKTOP_ITEM_GENERIC_NAME,
							  _("Description"), TRUE, FALSE));
	} else {
		entries = g_list_prepend (entries,
					  item_entry_new (GNOME_DESKTOP_ITEM_COMMENT,
							  _("Comments"), TRUE, FALSE));
		entries = g_list_prepend (entries,
					  item_entry_new (GNOME_DESKTOP_ITEM_EXEC,
							  _("Command"), FALSE, FALSE));
		entries = g_list_prepend (entries,
					  item_entry_new (GNOME_DESKTOP_ITEM_GENERIC_NAME,
							  _("Description"), TRUE, FALSE));
	}
	

	table = build_table (item, entries, 2);
	gtk_box_pack_start (GTK_BOX (box), table, FALSE, TRUE, 0);
	gtk_widget_show_all (GTK_WIDGET (box));
}

static void
ditem_read_cb (GnomeVFSResult result,
	       GnomeVFSFileSize file_size,
	       char *file_contents,
	       gpointer user_data)
{
	GnomeDesktopItem *item;
	GtkWidget *box = user_data;
	GtkLabel *label;
	GnomeDesktopItemType item_type;

	item = gnome_desktop_item_new_from_string (g_object_get_data (G_OBJECT (box),
								      "uri"),
						   file_contents,
						   file_size,
						   0, NULL);

	if (item == NULL)
		return;

	g_signal_connect (box, "unrealize", G_CALLBACK (box_unrealize_cb), item);

	label = g_object_get_data (G_OBJECT (box), "label");
	
	item_type = gnome_desktop_item_get_entry_type (item);
	if (item_type == GNOME_DESKTOP_ITEM_TYPE_APPLICATION) {
		gtk_label_set_text (label, _("Launcher"));
		create_page (item, box, FALSE);
	} else if (item_type == GNOME_DESKTOP_ITEM_TYPE_LINK) {
		gtk_label_set_text (label, _("Link"));
		create_page (item, box, TRUE);
	} else {
		return;
	}
}

static void
fm_ditem_page_create_begin (FMDitemPage *page,
			    const char *uri,
			    GtkWidget *box)
{
	g_object_set_data_full (G_OBJECT (box), "uri", g_strdup (uri), g_free);
	eel_read_entire_file_async (uri, 0, ditem_read_cb, box);
}

static GList *
fm_ditem_page_get_pages (NautilusPropertyPageProvider *provider,
			 GList *files)
{
	GList *pages = NULL;
	NautilusPropertyPage *page;
	NautilusFileInfo *info;
	char *mime;
	char *uri;
	GtkWidget *box;
	GtkWidget *label;

	if (g_list_length (files) > 1)
		return NULL;

	info = NAUTILUS_FILE_INFO (files->data);
	mime = nautilus_file_info_get_mime_type (info);

	if (strcmp (mime, "application/x-desktop") != 0) {
		g_free (mime);
		return NULL;
	}

	box = gtk_vbox_new (FALSE, 6);
	label = gtk_label_new ("");
	g_object_set_data (G_OBJECT (box), "label", label);
	
	uri = nautilus_file_info_get_uri (info);
	fm_ditem_page_create_begin (FM_DITEM_PAGE (provider),
				    uri, box);
	g_free (uri);
	
	page = nautilus_property_page_new ("Desktop Item Page",
					   label,
					   box);
	
		
	pages = g_list_prepend (pages, page);

	g_free (mime);
	return pages;
}

static void 
fm_ditem_page_property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface)
{
	iface->get_pages = fm_ditem_page_get_pages;
}

static void 
fm_ditem_page_instance_init (FMDitemPage *provider)
{
}

static void
fm_ditem_page_class_init (FMDitemPageClass *class)
{
	parent_class = g_type_class_peek_parent (class);
}

GType
fm_ditem_page_get_type (void) 
{
	static GType provider_type = 0;

	if (!provider_type) {
		static const GTypeInfo type_info = {
			sizeof (FMDitemPageClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) fm_ditem_page_class_init,
			NULL, 
			NULL,
			sizeof (FMDitemPage),
			0,
			(GInstanceInitFunc) fm_ditem_page_instance_init,
		};

		static const GInterfaceInfo property_page_provider_iface_info = {
			(GInterfaceInitFunc) fm_ditem_page_property_page_provider_iface_init,
			NULL,
			NULL
		};
		
		provider_type = g_type_register_static (G_TYPE_OBJECT,
							"FMDitemPage",
							&type_info, 0);

		g_type_add_interface_static (provider_type,
					     NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER,
					     &property_page_provider_iface_info);
	}

	return provider_type;
}

/*
 *  fm-ditem-page.h - A property page for desktop items
 * 
 *  Copyright (C) 2004 James Willcox
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Authors: James Willcox <james gnome org>
 * 
 */

#ifndef FM_DITEM_PAGE_H
#define FM_DITEM_PAGE_H

#include <glib-object.h>

G_BEGIN_DECLS

#define FM_TYPE_DITEM_PAGE  (fm_ditem_page_get_type ())
#define FM_DITEM_PAGE(o)    (G_TYPE_CHECK_INSTANCE_CAST ((o), FM_TYPE_DITEM_PAGE, FMDitemPage))
#define FM_IS_DITEM_PAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FM_TYPE_DITEM_PAGE))
typedef struct _FMDitemPage       FMDitemPage;
typedef struct _FMDitemPageClass  FMDitemPageClass;

struct _FMDitemPage {
	GObject parent_slot;
};

struct _FMDitemPageClass {
	GObjectClass parent_slot;
};

GType fm_ditem_page_get_type      (void);

G_END_DECLS

#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]