r3247: Experimental extended attributes support for setting MIME types
[rox-filer.git] / ROX-Filer / src / dropbox.c
blobed71033d7df312c9399f4e96d97de379da9fc88b
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2003, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* drop_box.c - the "drop something here" widget */
24 #include "config.h"
26 #include <gtk/gtk.h>
27 #include <errno.h>
28 #include <string.h>
30 #include "global.h"
32 #include "dropbox.h"
33 #include "main.h"
34 #include "type.h"
35 #include "pixmaps.h"
36 #include "support.h"
37 #include "gui_support.h"
38 #include "run.h"
40 static gpointer parent_class = NULL;
42 struct _DropBoxClass {
43 GtkFrameClass parent;
45 void (*path_dropped)(GtkWidget *drop_box, const guchar *path);
46 void (*clear)(GtkWidget *drop_box);
49 struct _DropBox {
50 GtkFrame frame;
52 GtkWidget *buttons;
53 GtkWidget *label;
54 gchar *path;
57 /* Static prototypes */
58 static void drop_box_class_init(gpointer gclass, gpointer data);
59 static void drop_box_init(GTypeInstance *object, gpointer gclass);
60 static void open_dir_clicked(GtkWidget *button, DropBox *drop_box);
61 static void clear_clicked(GtkWidget *button, DropBox *drop_box);
62 static void drop_box_drag_data_received(GtkWidget *drop_box,
63 GdkDragContext *context,
64 gint x,
65 gint y,
66 GtkSelectionData *selection_data,
67 guint drag_info,
68 guint32 time);
71 /****************************************************************
72 * EXTERNAL INTERFACE *
73 ****************************************************************/
75 GtkWidget *drop_box_new(const char *message)
77 GtkWidget *button, *label, *vbox, *icon;
78 MaskedPixmap *mp;
79 DropBox *drop_box;
80 GtkTargetEntry targets[] = {
81 {"text/uri-list", 0, 0},
84 drop_box = g_object_new(drop_box_get_type(), NULL);
86 gtk_frame_set_shadow_type(GTK_FRAME(drop_box), GTK_SHADOW_IN);
87 gtk_container_set_border_width(GTK_CONTAINER(drop_box), 4);
89 gtk_drag_dest_set(GTK_WIDGET(drop_box), GTK_DEST_DEFAULT_ALL,
90 targets, sizeof(targets) / sizeof(*targets),
91 GDK_ACTION_COPY);
93 vbox = gtk_vbox_new(FALSE, 0);
94 gtk_container_add(GTK_CONTAINER(drop_box), vbox);
96 label = gtk_label_new(message);
97 gtk_misc_set_padding(GTK_MISC(label), 10, 10);
98 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
100 drop_box->label = gtk_label_new(NULL);
101 gtk_box_pack_start(GTK_BOX(vbox), drop_box->label, FALSE, TRUE, 0);
102 gtk_misc_set_padding(GTK_MISC(drop_box->label), 2, 2);
104 drop_box->buttons = gtk_hbutton_box_new();
105 gtk_box_pack_start(GTK_BOX(vbox), drop_box->buttons, FALSE, TRUE, 0);
107 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
108 gtk_box_pack_start(GTK_BOX(drop_box->buttons), button, FALSE, TRUE, 0);
109 g_signal_connect(button, "clicked",
110 G_CALLBACK(clear_clicked), drop_box);
112 mp = type_to_icon(inode_directory);
113 pixmap_make_small(mp);
114 icon = gtk_image_new_from_pixbuf(mp->sm_pixbuf);
115 g_object_unref(mp);
116 button = button_new_image_text(icon, _("Show"));
117 gtk_box_pack_start(GTK_BOX(drop_box->buttons), button, FALSE, TRUE, 0);
118 g_signal_connect(button, "clicked",
119 G_CALLBACK(open_dir_clicked), drop_box);
121 gtk_tooltips_set_tip(tooltips, button,
122 _("Show the current choice in a filer window"), NULL);
124 drop_box_set_path(drop_box, NULL);
126 gtk_widget_show_all(vbox);
128 return GTK_WIDGET(drop_box);
131 GType drop_box_get_type(void)
133 static GType type = 0;
135 if (!type)
137 static const GTypeInfo info =
139 sizeof (DropBoxClass),
140 NULL, /* base_init */
141 NULL, /* base_finalise */
142 drop_box_class_init,
143 NULL, /* class_finalise */
144 NULL, /* class_data */
145 sizeof(DropBox),
146 0, /* n_preallocs */
147 drop_box_init
150 type = g_type_register_static(gtk_frame_get_type(),
151 "DropBox", &info, 0);
154 return type;
157 void drop_box_set_path(DropBox *drop_box, const guchar *path)
159 char *copy;
161 null_g_free(&drop_box->path);
162 drop_box->path = g_strdup(path);
164 if (path)
166 int l;
167 l = strlen(path);
168 if (l > 40)
169 copy = g_strdup_printf("...%s", path + l - 38);
170 else
171 copy = g_strdup(path);
172 gtk_widget_set_sensitive(drop_box->buttons, TRUE);
174 else
176 copy = g_strdup(_("<nothing>"));
177 gtk_widget_set_sensitive(drop_box->buttons, FALSE);
180 gtk_label_set_text(GTK_LABEL(drop_box->label), copy);
181 g_free(copy);
184 const gchar *drop_box_get_path(DropBox *drop_box)
186 g_return_val_if_fail(drop_box != NULL, NULL);
188 return drop_box->path;
191 /****************************************************************
192 * INTERNAL FUNCTIONS *
193 ****************************************************************/
195 static void drop_box_class_init(gpointer gclass, gpointer data)
197 GtkWidgetClass *widget = (GtkWidgetClass *) gclass;
198 DropBoxClass *drop_box = (DropBoxClass *) gclass;
200 parent_class = g_type_class_peek_parent(gclass);
202 drop_box->path_dropped = NULL;
204 widget->drag_data_received = drop_box_drag_data_received;
206 g_signal_new("path_dropped",
207 G_TYPE_FROM_CLASS(gclass),
208 G_SIGNAL_RUN_LAST,
209 G_STRUCT_OFFSET(DropBoxClass, path_dropped),
210 NULL, NULL,
211 g_cclosure_marshal_VOID__STRING,
212 G_TYPE_NONE, 1, G_TYPE_STRING);
214 g_signal_new("clear",
215 G_TYPE_FROM_CLASS(gclass),
216 G_SIGNAL_RUN_LAST,
217 G_STRUCT_OFFSET(DropBoxClass, clear),
218 NULL, NULL,
219 g_cclosure_marshal_VOID__VOID,
220 G_TYPE_NONE, 0);
223 static void drop_box_init(GTypeInstance *object, gpointer gclass)
225 DropBox *drop_box = (DropBox *) object;
227 drop_box->path = NULL;
228 drop_box->label = NULL;
229 drop_box->buttons = NULL;
232 static void clear_clicked(GtkWidget *button, DropBox *drop_box)
234 g_signal_emit_by_name(drop_box, "clear");
237 static void open_dir_clicked(GtkWidget *button, DropBox *drop_box)
239 if (drop_box->path)
240 open_to_show(drop_box->path);
241 else
242 delayed_error(_("I can't show you the currently set item, "
243 "because nothing is currently set. Drag "
244 "something onto me!"));
247 static void drop_box_drag_data_received(GtkWidget *drop_box,
248 GdkDragContext *context,
249 gint x,
250 gint y,
251 GtkSelectionData *selection_data,
252 guint drag_info,
253 guint32 time)
255 GList *uris = NULL;
256 guchar *path = NULL;
257 gboolean success = FALSE;
259 if (!selection_data->data)
260 goto err; /* Timeout? */
262 uris = uri_list_to_glist(selection_data->data);
264 if (g_list_length(uris) != 1)
266 delayed_error(_("Sorry, you need to drop exactly one file "
267 "onto the drop area."));
268 goto err;
271 path = get_local_path((guchar *) uris->data);
273 if (!path)
275 delayed_error(
276 _("Sorry, I can't use '%s' because it's not a local "
277 "file."), (guchar *) uris->data);
278 goto err;
281 if (!file_exists(path))
283 delayed_error(_("Can't access '%s':\n%s"), path,
284 g_strerror(errno));
285 goto err;
288 g_signal_emit_by_name(drop_box, "path_dropped", path);
290 success = TRUE;
291 err:
292 if(path)
293 g_free(path);
295 if (uris)
296 g_list_free(uris);
297 gtk_drag_finish(context, success, FALSE, time); /* Failure */