app_dnd.C

Go to the documentation of this file.
00001 /* Gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  * 
00005  * Copyright (C) 1999,2000,2001,2002,2003 Percy Zahl
00006  *
00007  * Authors: Percy Zahl <zahl@users.sf.net>
00008  * additional features: Andreas Klust <klust@users.sf.net>
00009  * WWW Home: http://gxsm.sf.net
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025 
00026 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 8 c-style: "K&R" -*- */
00027 
00028 #include <locale.h>
00029 #include <libintl.h>
00030 
00031 
00032 #include "gxsm_app.h"
00033 
00034 #include "glbvars.h"
00035 
00036 #include "surface.h"
00037 
00038 #include <errno.h>
00039 #include <sys/types.h>
00040 #include <sys/wait.h>
00041 #include <libgnomevfs/gnome-vfs-uri.h>
00042 
00043 enum {
00044                 TARGET_URI_LIST,
00045                 TARGET_URL
00046 };
00047 
00048 /* The following functions are a quick hack to get URL drops
00049  * from Netscape working. I make no pretense of correctness
00050  * or great security. Plus it leaves files lying in temp.
00051  * but it's fun.
00052  */
00053 
00054 typedef struct {
00055                 gchar *name;
00056                 gint pid;
00057 } ChildData;
00058 
00059 static char *download_dir = NULL;
00060 
00061 /* The following functions are a quick hack to get URL drops
00062  * from Netscape working. I make no pretense of correctness
00063  * or great security. Plus it leaves files lying in temp.
00064  * but it's fun.
00065  */
00066 
00067 /* Called when the child quits */
00068 gboolean App::input_func(GIOChannel *source, GIOCondition condition, gpointer data)
00069 {
00070                 char buf[2];
00071                 ChildData *child_data = (ChildData*)data;
00072                 int status;
00073 
00074                 if (read (g_io_channel_unix_get_fd(source), buf, 2) != 2 ||
00075                         (buf[0] != 'O') || (buf[1] != 'K')) /* failure */
00076                 {
00077                                 g_warning ("Download failed!\n");
00078                 }
00079                 else
00080                 {
00081                                 gapp->xsm->load (child_data->name);
00082                 }
00083 
00084                 waitpid (child_data->pid, &status, 0);
00085 
00086                 g_free (child_data->name);
00087                 g_free (child_data);
00088   
00089                 close(g_io_channel_unix_get_fd(source));
00090 
00091                 return FALSE;
00092 }
00093 
00094 void App::grab_url(const gchar *name)
00095 {
00096                 int pid;
00097                 int fds[2];
00098 
00099                 if (!download_dir)
00100                 {
00101                                 int fd;
00102 #define GXSMTMPPREFIX "/tmp/GxsmTmp"
00103                                 char *buffer = g_strdup(GXSMTMPPREFIX"_XXXXXX");
00104   
00105                                 if (!(fd=mkstemp(buffer)) )
00106                                 {
00107                                                 g_warning ("Could not generate temporary directory: %s\n",
00108                                                                    g_strerror(errno));
00109                                                 return;
00110                                 }
00111                                 close(fd);
00112                                 FILE *cmd = popen("rm -rf " GXSMTMPPREFIX "*", "w");
00113                                 if(cmd)
00114                                                 pclose(cmd);
00115 
00116                                 if ((mkdir(buffer, 0755) != 0))
00117                                 {
00118                                                 g_warning ("Could not generate temporary directory: %s\n",
00119                                                                    g_strerror(errno));
00120                                                 return;
00121                                 }
00122       
00123                                 download_dir = buffer;
00124                 }
00125 
00126                 if (pipe(fds))
00127                 {
00128                                 g_warning ("Could not create pipe: %s\n", g_strerror(errno));
00129                                 return;
00130                 }
00131   
00132                 if (!(pid = fork()))
00133                 {
00134                                 /* Child */
00135 
00136                                 close(fds[0]);
00137       
00138                                 /* Fork off a wget */
00139 
00140                                 if (!(pid = fork()))
00141                                 {
00142                                                 execlp("wget", "wget", "-q", "-P", download_dir, name, NULL);
00143                                                 g_warning("Could not run wget: %s\n", g_strerror(errno));
00144                                                 _exit(0);
00145                                 }
00146                                 else if (pid > 0)
00147                                 {
00148                                                 int status;
00149                                                 waitpid (pid, &status, 0);
00150 
00151                                                 if (!status)
00152                                                                 write (fds[1], "OK", 2);
00153 
00154                                                 _exit(0);
00155                                 }
00156                                 else
00157                                 {
00158                                                 g_warning ("Could not fork!\n");
00159                                                 _exit(0);
00160                                 }
00161                 }
00162                 else if (pid > 0)
00163                 {
00164                                 /* Parent */
00165 
00166                                 char *tail;
00167                                 ChildData *child_data;
00168                                 GIOChannel *ioc;
00169 
00170                                 close(fds[1]);
00171 
00172                                 tail = strrchr(name, '/');
00173                                 child_data = g_new0 (ChildData, 1);
00174 
00175                                 if (tail)
00176                                                 child_data->name = g_strconcat (download_dir, "/", ++tail, NULL);
00177                                 else
00178                                                 child_data->name = g_strconcat (download_dir, "/", name, NULL);
00179       
00180                                 child_data->pid = pid;
00181 
00182                                 ioc = g_io_channel_unix_new (fds[0]);
00183                                 g_io_add_watch(ioc, (GIOCondition)(G_IO_IN|G_IO_HUP|G_IO_NVAL), input_func, child_data);
00184                                 g_io_channel_unref(ioc);
00185                 }
00186                 else
00187                                 g_warning ("Could not fork\n");
00188 }
00189 
00190 void App::process_one_filename (GtkWidget * widget, const gchar *filename)
00191 {
00192                 int ch = (long) gtk_object_get_data  (GTK_OBJECT (widget), "ChNo");
00193                 if(ch){
00194                                 if(ch>0 && ch <= MAX_CHANNELS)
00195                                                 gapp->xsm->ActivateChannel( ch-1 );
00196                 }else
00197                                 if(gapp->xsm->ActivateFreeChannel())
00198                                                 return;
00199 
00200                 if (strncmp (filename, "http://", 7) == 0)
00201                                 grab_url (filename);
00202                 else
00203                                 gapp->xsm->load (filename);
00204 }
00205 
00206 void App::filenames_dropped(GtkWidget * widget,
00207                                                         GdkDragContext   *context,
00208                                                         gint              x,
00209                                                         gint              y,
00210                                                         GtkSelectionData *selection_data,
00211                                                         guint             info,
00212                                                         guint             time)
00213 {
00214                 if (!selection_data->data)
00215                                 return;
00216         
00217                 switch (info){
00218                 case TARGET_URI_LIST:
00219                 {
00220                                 GList *names = gnome_vfs_uri_list_parse ((char *)selection_data->data);
00221                                 if (!names)
00222                                                 return;
00223                 
00224                                 for (; names; names = names->next){
00225                                                 const gchar *filename = gnome_vfs_uri_get_path ((const GnomeVFSURI *)names->data);
00226                                                 process_one_filename (widget, filename);
00227                                 }
00228                                 gnome_vfs_uri_list_free (names);
00229                                 break;
00230                 }
00231                 case TARGET_URL:
00232                                 gchar *url = g_strdup ((gchar *)selection_data->data);
00233                                 gchar *p;
00234                                 if ((p=strchr (url, '\n')) != NULL) // cut "href info" off
00235                                                 *p = 0;
00236                                 process_one_filename (widget, url);
00237                                 g_free (url);
00238                                 break;
00239                 }
00240 }
00241 
00242 void
00243 App::configure_drop_on_widget(GtkWidget * widget)
00244 {
00245                 static GtkTargetEntry drag_types[] =
00246                                 {
00247                                                 { "text/uri-list", 0, TARGET_URI_LIST },
00248                                                 { "_NETSCAPE_URL", 0, TARGET_URL }
00249                                 };
00250                 static gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
00251 
00252                 gtk_drag_dest_set 
00253                                 ( widget,
00254                                   (GtkDestDefaults)(
00255                                                   GTK_DEST_DEFAULT_MOTION | 
00256                                                   GTK_DEST_DEFAULT_HIGHLIGHT | 
00257                                                   GTK_DEST_DEFAULT_DROP
00258                                                   ),
00259                                   drag_types, 
00260                                   n_drag_types,
00261                                   GDK_ACTION_COPY
00262                                                 );
00263 
00264                 gtk_signal_connect(GTK_OBJECT(widget), "drag_data_received",
00265                                                    GTK_SIGNAL_FUNC(filenames_dropped), NULL);
00266 }
00267 
00268 void App::drag_data_get (GtkWidget        *widget,
00269                                                  GdkDragContext   *context,
00270                                                  GtkSelectionData *selection_data,
00271                                                  guint             info,
00272                                                  guint             time)
00273 {
00274                 gchar *file=NULL;
00275                 gchar *uri_list;
00276 
00277                 //  file = ee_image_get_filename(image_display);
00278 
00279                 if (file) /* ignore non-file-images for now */
00280                 {
00281                                 uri_list = g_strconcat ("file:", file, NULL);
00282                                 gtk_selection_data_set (selection_data,
00283                                                                                 selection_data->target, 8,
00284                                                                                 (const guchar*)uri_list, 
00285                                                                                 (int)strlen(uri_list));
00286                                 g_free (uri_list);
00287                 }
00288                 else
00289                 {
00290                                 gtk_selection_data_set (selection_data,
00291                                                                                 selection_data->target, 8,
00292                                                                                 NULL, 0);
00293                 }
00294 }
00295 
00296 void
00297 App::configure_drag_on_widget(GtkWidget * widget)
00298 {
00299                 static GtkTargetEntry drag_types[] =
00300                                 {
00301                                                 { "text/uri-list", 0, TARGET_URI_LIST }
00302                                 };
00303                 static gint n_drag_types = sizeof(drag_types)/sizeof(drag_types[0]);
00304 
00305                 gtk_drag_source_set (widget, 
00306                                                          GDK_BUTTON1_MASK,
00307                                                          drag_types, n_drag_types,
00308                                                          GDK_ACTION_COPY);
00309 
00310                 gtk_signal_connect(GTK_OBJECT(widget), "drag_data_get",
00311                                                    GTK_SIGNAL_FUNC(drag_data_get), NULL);
00312 }
00313 

Generated on Sat Apr 1 09:03:44 2006 for GXSM by  doxygen 1.4.6