r4895: New MIME type for Jar archives.
[rox-filer.git] / ROX-Filer / src / dropbox.c
blob5f986bee7fff8418f3321ce72cb707ae9ae570fc
1 /*
2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
20 /* drop_box.c - the "drop something here" widget */
22 #include "config.h"
24 #include <gtk/gtk.h>
25 #include <errno.h>
26 #include <string.h>
28 #include "global.h"
30 #include "dropbox.h"
31 #include "main.h"
32 #include "type.h"
33 #include "pixmaps.h"
34 #include "support.h"
35 #include "gui_support.h"
36 #include "run.h"
38 struct _DropBoxClass {
39 GtkFrameClass parent;
41 void (*path_dropped)(GtkWidget *drop_box, const guchar *path);
42 void (*clear)(GtkWidget *drop_box);
45 struct _DropBox {
46 GtkFrame frame;
48 GtkWidget *buttons;
49 GtkWidget *label;
50 gchar *path;
53 /* Static prototypes */
54 static void drop_box_class_init(gpointer gclass, gpointer data);
55 static void drop_box_init(GTypeInstance *object, gpointer gclass);
56 static void open_dir_clicked(GtkWidget *button, DropBox *drop_box);
57 static void clear_clicked(GtkWidget *button, DropBox *drop_box);
58 static void drop_box_drag_data_received(GtkWidget *drop_box,
59 GdkDragContext *context,
60 gint x,
61 gint y,
62 GtkSelectionData *selection_data,
63 guint drag_info,
64 guint32 time);
67 /****************************************************************
68 * EXTERNAL INTERFACE *
69 ****************************************************************/
71 GtkWidget *drop_box_new(const char *message)
73 GtkWidget *button, *label, *vbox, *icon;
74 MaskedPixmap *mp;
75 DropBox *drop_box;
76 GtkTargetEntry targets[] = {
77 {"text/uri-list", 0, 0},
80 drop_box = g_object_new(drop_box_get_type(), NULL);
82 gtk_frame_set_shadow_type(GTK_FRAME(drop_box), GTK_SHADOW_IN);
83 gtk_container_set_border_width(GTK_CONTAINER(drop_box), 4);
85 gtk_drag_dest_set(GTK_WIDGET(drop_box), GTK_DEST_DEFAULT_ALL,
86 targets, sizeof(targets) / sizeof(*targets),
87 GDK_ACTION_COPY);
89 vbox = gtk_vbox_new(FALSE, 0);
90 gtk_container_add(GTK_CONTAINER(drop_box), vbox);
92 label = gtk_label_new(message);
93 gtk_misc_set_padding(GTK_MISC(label), 10, 10);
94 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
96 drop_box->label = gtk_label_new(NULL);
97 gtk_box_pack_start(GTK_BOX(vbox), drop_box->label, FALSE, TRUE, 0);
98 gtk_misc_set_padding(GTK_MISC(drop_box->label), 2, 2);
100 drop_box->buttons = gtk_hbutton_box_new();
101 gtk_box_pack_start(GTK_BOX(vbox), drop_box->buttons, FALSE, TRUE, 0);
103 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
104 gtk_box_pack_start(GTK_BOX(drop_box->buttons), button, FALSE, TRUE, 0);
105 g_signal_connect(button, "clicked",
106 G_CALLBACK(clear_clicked), drop_box);
108 mp = type_to_icon(inode_directory);
109 pixmap_make_small(mp);
110 icon = gtk_image_new_from_pixbuf(mp->sm_pixbuf);
111 g_object_unref(mp);
112 button = button_new_image_text(icon, _("Show"));
113 gtk_box_pack_start(GTK_BOX(drop_box->buttons), button, FALSE, TRUE, 0);
114 g_signal_connect(button, "clicked",
115 G_CALLBACK(open_dir_clicked), drop_box);
117 gtk_tooltips_set_tip(tooltips, button,
118 _("Show the current choice in a filer window"), NULL);
120 drop_box_set_path(drop_box, NULL);
122 gtk_widget_show_all(vbox);
124 return GTK_WIDGET(drop_box);
127 GType drop_box_get_type(void)
129 static GType type = 0;
131 if (!type)
133 static const GTypeInfo info =
135 sizeof (DropBoxClass),
136 NULL, /* base_init */
137 NULL, /* base_finalise */
138 drop_box_class_init,
139 NULL, /* class_finalise */
140 NULL, /* class_data */
141 sizeof(DropBox),
142 0, /* n_preallocs */
143 drop_box_init
146 type = g_type_register_static(gtk_frame_get_type(),
147 "DropBox", &info, 0);
150 return type;
153 void drop_box_set_path(DropBox *drop_box, const guchar *path)
155 char *copy;
157 null_g_free(&drop_box->path);
158 drop_box->path = g_strdup(path);
160 if (path)
162 int l;
163 l = strlen(path);
164 if (l > 40)
165 copy = g_strdup_printf("...%s", path + l - 38);
166 else
167 copy = g_strdup(path);
168 gtk_widget_set_sensitive(drop_box->buttons, TRUE);
170 else
172 copy = g_strdup(_("<nothing>"));
173 gtk_widget_set_sensitive(drop_box->buttons, FALSE);
176 gtk_label_set_text(GTK_LABEL(drop_box->label), copy);
177 g_free(copy);
180 const gchar *drop_box_get_path(DropBox *drop_box)
182 g_return_val_if_fail(drop_box != NULL, NULL);
184 return drop_box->path;
187 /****************************************************************
188 * INTERNAL FUNCTIONS *
189 ****************************************************************/
191 static void drop_box_class_init(gpointer gclass, gpointer data)
193 GtkWidgetClass *widget = (GtkWidgetClass *) gclass;
194 DropBoxClass *drop_box = (DropBoxClass *) gclass;
196 drop_box->path_dropped = NULL;
197 drop_box->clear = NULL;
199 widget->drag_data_received = drop_box_drag_data_received;
201 g_signal_new("path_dropped",
202 G_TYPE_FROM_CLASS(gclass),
203 G_SIGNAL_RUN_LAST,
204 G_STRUCT_OFFSET(DropBoxClass, path_dropped),
205 NULL, NULL,
206 g_cclosure_marshal_VOID__STRING,
207 G_TYPE_NONE, 1, G_TYPE_STRING);
209 g_signal_new("clear",
210 G_TYPE_FROM_CLASS(gclass),
211 G_SIGNAL_RUN_LAST,
212 G_STRUCT_OFFSET(DropBoxClass, clear),
213 NULL, NULL,
214 g_cclosure_marshal_VOID__VOID,
215 G_TYPE_NONE, 0);
218 static void drop_box_init(GTypeInstance *object, gpointer gclass)
220 DropBox *drop_box = (DropBox *) object;
222 drop_box->path = NULL;
223 drop_box->label = NULL;
224 drop_box->buttons = NULL;
227 static void clear_clicked(GtkWidget *button, DropBox *drop_box)
229 g_signal_emit_by_name(drop_box, "clear");
232 static void open_dir_clicked(GtkWidget *button, DropBox *drop_box)
234 if (drop_box->path)
235 open_to_show(drop_box->path);
236 else
237 delayed_error(_("I can't show you the currently set item, "
238 "because nothing is currently set. Drag "
239 "something onto me!"));
242 static void drop_box_drag_data_received(GtkWidget *drop_box,
243 GdkDragContext *context,
244 gint x,
245 gint y,
246 GtkSelectionData *selection_data,
247 guint drag_info,
248 guint32 time)
250 GList *uris = NULL;
251 guchar *path = NULL;
252 gboolean success = FALSE;
254 if (!selection_data->data)
255 goto err; /* Timeout? */
257 uris = uri_list_to_glist(selection_data->data);
259 if (g_list_length(uris) != 1)
261 delayed_error(_("Sorry, you need to drop exactly one file "
262 "onto the drop area."));
263 goto err;
266 path = get_local_path((EscapedPath *) uris->data);
268 if (!path)
270 delayed_error(
271 _("Sorry, I can't use '%s' because it's not a local "
272 "file."), (guchar *) uris->data);
273 goto err;
276 if (!file_exists(path))
278 delayed_error(_("Can't access '%s':\n%s"), path,
279 g_strerror(errno));
280 goto err;
283 g_signal_emit_by_name(drop_box, "path_dropped", path);
285 success = TRUE;
286 err:
287 if (path)
288 g_free(path);
290 if (uris)
291 g_list_free(uris);
292 gtk_drag_finish(context, success, FALSE, time); /* Failure */