1 /*
2     Copyright 2007, 2008, 2009, 2010 Geyer Klaus
3 
4     This file is part of Cat'sEyE.
5 
6     Cat'sEyE is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     Cat'sEyE is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with Cat'sEyE.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <gtk/gtk.h>
21 #ifndef NO_GIO
22 #include <gio/gio.h>
23 #endif
24 #include <string.h>
25 
26 #include "helpers.h"
27 #include "globalDefinitions.h"
28 #include "Lists.h"
29 #include "listitems.h"
30 #include "userdata.h"
31 #include "myfm.h"
32 #include "fileshelf.h"
33 #include "threads.h"
34 
35 #include "mytrace.h"
36 
37 #include "allInclude.h"
38 
39 void DNDSignal_dragdataget (GtkWidget *widget, GdkDragContext *drag_context, GtkSelectionData *selection_data, guint info, guint time, gpointer user_data);
40 void DNDSignal_dragdatereceive (GtkWidget *widget, GdkDragContext   *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data);
41 gboolean DNDSignal_dragdrop (GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data);
42 
43 extern GtkWidget 		*Notebooks[SIDE_BOTH];
44 extern GtkNotebook      *g_FileShelfNotebook;
45 extern GtkWindow 		*win;
46 
47 enum {
48         TARGET_LISTVIEW, //treeview, basic DnD for sideviews and fileshelfs
49         TARGET_MARKEDITEMSASTEXT
50         //TARGET_FROMNOTEBOOK //for getting tabs from notebooks, we have this target
51 };
52 
53 // text/uri-list text/plain     application/x-moz-file
54 static GtkTargetEntry targets[] = {
55    /* { "widget(listview)",       GTK_TARGET_SAME_APP,    TARGET_LISTVIEW },*/
56     { "STRING",                 GTK_TARGET_SAME_APP,   TARGET_MARKEDITEMSASTEXT },
57     { "STRING",                 GTK_TARGET_OTHER_APP,   TARGET_MARKEDITEMSASTEXT },
58     { "text/plain",             GTK_TARGET_OTHER_APP,   TARGET_MARKEDITEMSASTEXT },
59   	{ "text/uri-list",          GTK_TARGET_OTHER_APP,   TARGET_MARKEDITEMSASTEXT }/*,
60   	{ "application/x-moz-file", GTK_TARGET_OTHER_APP, TARGET_MARKEDITEMSASTEXT },
61     { "GTK_NOTEBOOK_TAB",    GTK_TARGET_SAME_APP, TARGET_LISTVIEW }  */ //look at 'http://library.gnome.org/devel/gtk/unstable/GtkNotebook.html', search for 'gtk_notebook_set_tab_detachable'
62 };
63 
64 
65 
66 /*
67 static GtkTargetEntry NoteBookTargets[] = {
68     { "GTK_NOTEBOOK_TAB",    GTK_TARGET_SAME_APP, TARGET_LISTVIEW }   //look at 'http://library.gnome.org/devel/gtk/unstable/GtkNotebook.html', search for 'gtk_notebook_set_tab_detachable'
69 };
70 */
71 /*
72 int prepareWidgetForDragnDrop (GtkWidget *widget, int enableNoteBookDest){    //enables dragndrop for the widget and connects signals
73     //this is our standard dragndrop for copying items from/to view/Shelf
74     //enableNoteBookDest: 0:no, 1:yes, the widget can be achieve a ntebook-tab
75     TRACEIT(10,"prepareWidgetForDragnDrop		start");
76     if (widget == NULL){
77         TRACEIT(2,"prepareWidgetForDragnDrop		end, widget NULL");
78         return -1;
79     }
80     if (enableNoteBookDest==1){
81         gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, NoteBookTargets, 1, GDK_ACTION_COPY|GDK_ACTION_MOVE);
82     }
83     else{
84         gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, targets, 1, GDK_ACTION_COPY);
85     }
86     gtk_drag_source_set (widget, GDK_BUTTON1_MASK, targets, 1, GDK_ACTION_COPY);    //Mind that only destinations who can handle Notebooktabs are allowd to get the target for notebooks
87 
88     //g_signal_connect(widget,"drag-drop",G_CALLBACK(DNDSignal_dragdrop),NULL); //Do you remember the problem that we end up in the drag-data-get and receive signal handler twice
89     //after comment this out we did not have this Problem again
90     g_signal_connect(widget,"drag-data-get",G_CALLBACK(DNDSignal_dragdataget),NULL);
91     g_signal_connect(widget,"drag-data-received",G_CALLBACK(DNDSignal_dragdatereceive),NULL);
92 
93     TRACEIT(10,"prepareWidgetForDragnDrop		end");
94     return 0;
95 }
96 */
prepareWidgetForDrag(GtkWidget * widget)97 int prepareWidgetForDrag (GtkWidget *widget){    //enables the Drag in dragndrop for the widget and connects signals
98     //this is our standard dragndrop for copying items from/to view/Shelf
99 
100     TRACEIT(10,"prepareWidgetForDrag		start");
101     if (widget == NULL){
102         TRACEIT(2,"prepareWidgetForDrag		end, widget NULL");
103         return -1;
104     }
105     gtk_drag_source_set (widget, GDK_BUTTON1_MASK, targets, sizeof(targets) / sizeof(targets[0]), GDK_ACTION_COPY);    //Mind that only destinations who can handle Notebooktabs are allowd to get the target for notebooks
106 
107     //g_signal_connect(widget,"drag-drop",G_CALLBACK(DNDSignal_dragdrop),NULL); //Do you remember the problem that we end up in the drag-data-get and receive signal handler twice
108     //after comment this out we did not have this Problem again
109     g_signal_connect(widget,"drag-data-get",G_CALLBACK(DNDSignal_dragdataget),NULL);
110 
111 
112     TRACEIT(10,"prepareWidgetForDrag		end");
113     return 0;
114 }
115 
116 
prepareWidgetForDrop(GtkWidget * widget,int enableNoteBookDest,void (* functionStartNotification)(),void * UserData)117 int prepareWidgetForDrop (GtkWidget *widget, int enableNoteBookDest, void (*functionStartNotification)(), void *UserData){    //enables Drop for dragndrop for the widget and connects signals
118     //this is our standard dragndrop for copying items from/to view/Shelf
119     //enableNoteBookDest: 0:no, 1:yes, the widget can be achieve a ntebook-tab
120     //functionStartNotification: the function to connect to the receiv-signal
121     TRACEIT(10,"prepareWidgetForDrop		start");
122     if (widget == NULL){
123         TRACEIT(2,"prepareWidgetForDrop		end, widget NULL");
124         return -1;
125     }
126     if (enableNoteBookDest==1){
127         gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, targets, sizeof(targets)/sizeof(targets[0]), GDK_ACTION_COPY);//  GDK_ACTION_COPY|GDK_ACTION_MOVE
128     }
129     else{
130         gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, targets, sizeof(targets)/sizeof(targets[0]), GDK_ACTION_COPY);
131     }
132 
133     //g_signal_connect(widget,"drag-drop",G_CALLBACK(DNDSignal_dragdrop),NULL); //Do you remember the problem that we end up in the drag-data-get and receive signal handler twice
134     //after comment this out we did not have this Problem again
135 
136 
137     g_signal_connect(widget,"drag-data-received",G_CALLBACK(functionStartNotification), UserData);
138 
139     TRACEIT(10,"prepareWidgetForDrop		end");
140     return 0;
141 }
142 ////////////////// signal handler ////////////////////
143 
144 /*
145 gboolean DNDSignal_dragdrop (GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data){
146 	printf ("DID NOT THINK WE CAN COME UP HERE\n");
147 
148     return FALSE;
149 }
150 */
151 
152 //"drag-data-get" signal (source side)
153 //the source sets the data
DNDSignal_dragdataget(GtkWidget * widget,GdkDragContext * drag_context,GtkSelectionData * selection_data,guint info,guint time,gpointer user_data)154 void DNDSignal_dragdataget (GtkWidget *widget, GdkDragContext *drag_context, GtkSelectionData *selection_data, guint info, guint time, gpointer user_data){
155     TRACEIT(10,"DNDSignal_dragdataget		start");
156     //GtkTreeSelection *selection=NULL;
157 	if (info == TARGET_MARKEDITEMSASTEXT){
158 		GString *gstrDataToSend = g_string_sized_new (10);
159 		GString *gstrBuf = g_string_sized_new (10);
160 		struct CopyReMoveList *FirstItem = NULL;
161 		struct CopyReMoveList *BufItem = NULL;
162 		//The only widgets connected to this functions are the listviews from the sideObjects and the fileshelfs
163 
164 		GtkTreeSelection	*selection;
165 		struct SideObjectList *me_sideObject=NULL;
166 	    struct FileShelfObjectList *me_fileshelfObject=NULL;
167 	    int side;
168 	    int iWeAre=0;   //1=sideObject, 2=fileshelf
169 	    char *cpConvertedString = NULL;
170 	    GError *error=NULL;
171 		SideObjectList_GetObjectByChildListView(&me_sideObject, (GtkTreeView *)widget, &side);
172         if (me_sideObject == NULL){    //maybe we are a FileshelfObject
173             //FileShelfObjectList_GetActiveObject(&me_fileshelfObject);
174             FileShelfObjectList_GetObjectByChildListView(&me_fileshelfObject, (GtkTreeView *)widget);
175             //if (me_fileshelfObject!=NULL && me_fileshelfObject->listView == widget){
176             if (me_fileshelfObject!=NULL){
177                 iWeAre=2;
178             }
179         }
180         else{
181             iWeAre=1;
182         }
183 		if (iWeAre == 1){
184 			iWeAre = SOURCE_SIDEOBJECT;
185 		}
186 		else if (iWeAre == 2){
187 			iWeAre = SOURCE_FILESHELF;
188 		}
189 		else{
190 			TRACEIT (4, "DNDSignal_dragdataget		unable to determine the source widget, isnt it a listview?");
191 			return;
192 		}
193 
194 		selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
195 		g_string_assign (gstrDataToSend, "/NoPathHere");	//we will never use this, so it doesn't matter
196 		g_string_assign (gstrBuf, "/JustAnotherPath");
197 		if (0 == MakeList (iWeAre, &FirstItem, selection, (iWeAre==SOURCE_SIDEOBJECT)?me_sideObject->gstrPath:gstrDataToSend, gstrBuf)){	// all is good
198 			BufItem = FirstItem;
199 			g_string_erase (gstrDataToSend, 0, -1);
200 			while (BufItem){
201 			    cutCharFromGString (BufItem->string1, '\"', 0);
202 			    cpConvertedString = g_locale_to_utf8 (BufItem->string1->str, strlen (BufItem->string1->str), NULL, NULL, &error);
203 			    if (error != NULL){
204                     TRACEIT (3, "DNDSignal_dragdataget error:");
205                     TRACEIT (3, error->message);
206                     g_error_free (error);
207                     error=NULL;
208                     //BufItem = BufItem->NextItem;  //do not cancel on that error
209                     //continue;
210 			    }
211 
212 				//g_string_append (gstrDataToSend, "file://");	//we only have this type in our views
213                 if (cpConvertedString != NULL){
214                     g_string_assign (gstrBuf, cpConvertedString);
215                     g_free (cpConvertedString);
216                 }
217                 else{   //a fall back if the encoding failed
218                     g_string_assign (gstrBuf, BufItem->string1->str);
219                 }
220                 cpConvertedString = g_filename_to_uri (gstrBuf->str, NULL, &error);
221                 if (error != NULL){
222                     TRACEIT (3, "DNDSignal_dragdataget error:");
223                     TRACEIT (3, error->message);
224                     g_error_free (error);
225                     error = NULL;
226                 }
227                 if (cpConvertedString != NULL){
228                     g_string_append (gstrDataToSend, cpConvertedString);
229                     g_string_append_c (gstrDataToSend, '\r'); //Carriage return, Ctrl-m, ASCII code 13, 0xD
230                     g_string_append_c (gstrDataToSend, '\n');
231                     g_free (cpConvertedString);
232                 }
233                 else{
234                     g_string_erase (gstrDataToSend, 0, -1);
235                 }
236 
237 				BufItem = BufItem->NextItem;
238 			}
239 
240 			if (0 < strlen (gstrDataToSend->str)){
241 				//data will be copied from gtk_selection_data_set.
242 				gtk_selection_data_set (selection_data, selection_data->target, 8, (guchar *)gstrDataToSend->str, strlen (gstrDataToSend->str));
243 			}
244 		}
245 		g_string_free (gstrDataToSend, TRUE);
246 		g_string_free (gstrBuf, TRUE);
247 		if (FirstItem != NULL){
248 			CopyReMoveList_DeleteList (FirstItem);
249 			FirstItem = NULL;
250 		}
251 	}
252 
253     if (info == TARGET_LISTVIEW){
254         int *testpointer = (int *)widget;
255 
256         //selection  = gtk_tree_view_get_selection((GtkTreeView *)widget /*ListView*/);
257 
258         //gtk_selection_data_set (selection_data, selection_data->target, 8,(guchar *)&widget, sizeof(GtkWidget*));
259         gtk_selection_data_set (selection_data, selection_data->target, 1,(guchar *)&testpointer, sizeof(int*));
260 
261     }
262     TRACEIT(10,"DNDSignal_dragdataget		end");
263 }
264 
265 
266 //"drag-data-received" signal (drop side) for SideObjects and FileShelfs
DNDSignal_dragdatereceive_forSideObjectAndFileShelf(GtkWidget * widget,GdkDragContext * drag_context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint time,gpointer user_data)267 void DNDSignal_dragdatereceive_forSideObjectAndFileShelf (GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, gpointer user_data){
268     TRACEIT(10,"DNDSignal_dragdatereceive_forSideObjectAndFileShelf		start");
269     //GtkTreeSelection	*selection;
270     struct SideObjectList *me_sideObject=NULL;
271     struct FileShelfObjectList *me_fileshelfObject=NULL;
272     //struct SideObjectList *source_sideObject=NULL;
273     //struct FileShelfObjectList *source_fileshelfObject=NULL;
274     int side;
275     int iWeAre=0;   //1=sideObject, 2=fileshelf, 3=ViewNotebook, 4=FSNotebook
276     //int iSourceIs=0;//1=sideObject, 2=fileshelf, 3=ViewNotebook
277     //GtkWidget *sourceWidget=NULL;
278     gboolean DND_Done = FALSE;
279     //GtkWidget **NotebookChild=NULL;
280     GString *gstrPath=NULL;
281     GString *gstrName=NULL;
282     GError *error = NULL;
283     gchar *cpConvertedString=NULL;
284     gchar *cpConvertedString2=NULL;
285     gchar *cpHostName=NULL;
286 
287     if((selection_data != NULL) && (selection_data->length >= 0)){
288     	//determine own type (the widget is from sideObject or Fileshelf)
289         if (widget == Notebooks[SIDE_LEFT] || widget == Notebooks[SIDE_RIGHT]){  //find viewNotebooks
290             SideObjectList_GetActiveObject((GtkNotebook *)widget, &me_sideObject);
291             if (me_sideObject){
292                 iWeAre=3;    //3=ViewNotebook
293             }
294             if (widget == Notebooks[SIDE_LEFT]){
295                 side=SIDE_LEFT;
296             }
297             else if (widget == Notebooks[SIDE_RIGHT]){
298                 side=SIDE_RIGHT;
299             }
300         }
301         else if (widget == (GtkWidget *)g_FileShelfNotebook){
302             FileShelfObjectList_GetActiveObject(&me_fileshelfObject);
303             if (me_fileshelfObject!=NULL){
304                 iWeAre=4;
305             }
306         }
307         else{
308             SideObjectList_GetObjectByChildListView(&me_sideObject, (GtkTreeView *)widget, &side);
309             if (me_sideObject == NULL){    //maybe we are a FileshelfObject
310                 FileShelfObjectList_GetActiveObject(&me_fileshelfObject);
311                 if (me_fileshelfObject!=NULL && me_fileshelfObject->listView == widget){
312                     iWeAre=2;
313                 }
314             }
315             else{
316                 iWeAre=1;
317             }
318         }
319         if (iWeAre==0){
320             TRACEIT(2,"DNDSignal_dragdatereceive_forSideObjectAndFileShelf		end, could not determine own type.");
321             DND_Done = FALSE;
322             gtk_drag_finish (drag_context, DND_Done, FALSE, time);
323             return;
324         }
325         if (me_sideObject!=NULL && me_sideObject->bReadOnly == TRUE){
326         	MyMessageWidget(win, "Read only Tab", "The tab is marked as read only.\nPlease remove this flag to\nperform this action.\n(tab context menu)");
327 			TRACEIT(2,"DNDSignal_dragdatereceive_forSideObjectAndFileShelf		end, could not determine own type.");
328 			DND_Done = FALSE;
329             gtk_drag_finish (drag_context, DND_Done, FALSE, time);
330             return;
331         }
332 
333     	if (info == TARGET_MARKEDITEMSASTEXT){
334     		//we only handle "file://<PATHWITHFILE>" objects in here, this is a filebrowser.
335     		char *cpBuf = (char *)selection_data->data;
336     		gstrPath = g_string_sized_new (10);
337     		gstrName = g_string_sized_new (10);
338     		int iCopyToSideObject = 0;
339     		struct CopyReMoveList *FirstItem = NULL;
340     		for (cpBuf = strtok (cpBuf, "\r\n"); cpBuf!=NULL; cpBuf = strtok (NULL, "\r\n") ){
341 
342     		    cpConvertedString = g_locale_from_utf8 (cpBuf, strlen (cpBuf), NULL, NULL, &error);
343     		    if (error != NULL){
344                     TRACEIT (2, "DNDSignal_dragdatereceive_forSideObjectAndFileShelf error from locale_from_utf8:");
345                     TRACEIT (2, error->message);
346                     g_error_free (error);
347                     error = NULL;
348     		    }
349     		    if (cpConvertedString == NULL){
350                     //do not stop here, we will have a fall back for this case
351                     cpConvertedString2 = g_filename_from_uri (cpBuf, &cpHostName, &error);
352     		    }
353     		    else{
354                     cpConvertedString2 = g_filename_from_uri (cpConvertedString, &cpHostName, &error);
355                     g_free (cpConvertedString);
356                     cpConvertedString=NULL;
357     		    }
358     		    if (error != NULL){
359                     TRACEIT (2, "DNDSignal_dragdatereceive_forSideObjectAndFileShelf error from g_filename_from_uri:");
360                     TRACEIT (2, error->message);
361                     g_error_free (error);
362                     error = NULL;
363     		    }
364     		    if (cpConvertedString2 == NULL){
365                     continue;
366     		    }
367 
368     			if (cpHostName != NULL && strcmp (cpHostName, "file://")!=0){
369     			    g_free(cpConvertedString2);
370     			    cpConvertedString2=NULL;
371     				continue;
372     			}
373     			else if (cpHostName != NULL){
374                     g_free (cpHostName);
375     			}
376 
377     			if (iWeAre==1 || iWeAre==3){	//sideobject copy
378     				//we create a CopyReMoveList and let others do the work
379     				g_string_assign (gstrPath, cpConvertedString2);
380 					GetPathFromPathWithName(gstrPath, 1);
381 					if (0 == strcmp (gstrPath->str, me_sideObject->gstrPath->str)){
382 					    g_free(cpConvertedString2);
383                         cpConvertedString2=NULL;
384 						continue;
385 					}
386     				CopyReMoveList_AddItem ( &FirstItem, cpConvertedString2, me_sideObject->gstrPath->str, NULL, me_sideObject, NULL);
387 
388     				iCopyToSideObject = 1;
389     			}
390     			else if (iWeAre==2 || iWeAre==4){	//fileshelf add
391     				g_string_assign (gstrPath, cpConvertedString2);
392     				g_string_assign (gstrName, cpConvertedString2);
393 
394     				getLastStringInPath(gstrName);
395 					GetPathFromPathWithName(gstrPath, 1);
396 
397     				AddItemToFileshelf (me_fileshelfObject, gstrName->str, gstrPath->str, TRUE, 1);
398     				DND_Done = TRUE;
399     			}
400     			if (cpConvertedString2!=NULL){
401                     g_free(cpConvertedString2);
402                     cpConvertedString2=NULL;
403     			}
404     		}
405     		if (iCopyToSideObject == 1){	//sideobject copy
406     			ProcessItemsViaListWrap(FirstItem, 1);
407     			DND_Done = TRUE;
408     		}
409 
410     		g_string_free (gstrPath, TRUE);
411     		g_string_free (gstrName, TRUE);
412     		DND_Done = FALSE;
413     	}
414         /*else if (info == TARGET_LISTVIEW){
415             sourceWidget = gtk_drag_get_source_widget (drag_context);
416 
417             //find source type
418             if (sourceWidget == Notebooks[0] || sourceWidget == Notebooks[1]){  //find viewNotebooks
419                 NotebookChild = (void *)selection_data->data;
420                 SideObjectList_GetObjectByChildVBox(&source_sideObject, (GtkWidget *)*NotebookChild, &side);
421                 if (source_sideObject){
422                     iSourceIs=3;    //3=Notebook
423                 }
424             }
425             else{
426                 SideObjectList_GetObjectByChildListView(&source_sideObject, (GtkTreeView *)sourceWidget, &side);
427                 if (source_sideObject == NULL){    //maybe we are a FileshelfObject
428                     FileShelfObjectList_GetObjectByChildListView(&source_fileshelfObject, (GtkTreeView *)sourceWidget);
429                     if (source_fileshelfObject){
430                         iSourceIs=2;
431                     }
432                 }
433                 else{
434                     iSourceIs=1;
435                 }
436             }
437             if (iSourceIs==0){
438                 TRACEIT(2,"DNDSignal_dragdatereceive		end, could not determine source type.");
439                 gtk_drag_finish (drag_context, DND_Done, FALSE, time);
440                 return;
441             }
442 
443             //printf("found iWeAre=%d\tiSourceIs=%d\n",iWeAre,iSourceIs);
444 
445             if ( (iWeAre==1||iWeAre==3) && iSourceIs == 1){ //From sideObject to sideObject
446                 //printf("View2View\n");
447                 if (source_sideObject != me_sideObject){
448                     copyToAnOtherPannel( source_sideObject, me_sideObject);
449                     DND_Done=TRUE;
450                 }
451             }
452             else if ( (iWeAre==2||iWeAre==4) && iSourceIs==1){ //From sideObject to FileShelf
453                 //printf("View2FS\n");
454                 MenuAddItemToFileshelf(NULL, (void *) source_sideObject);
455                 DND_Done=TRUE;
456             }
457             else if ( (iWeAre==1||iWeAre==3) && iSourceIs == 2){ //From fileshelf to sideObject
458                 //printf("FS2View\n");
459                 if (side == SIDE_RIGHT){
460                     copyFileShelfToRightPannel(NULL, source_fileshelfObject);
461                     DND_Done=TRUE;
462                 }
463                 else if (side == SIDE_LEFT){
464                     copyFileShelfToLeftPannel(NULL, source_fileshelfObject);
465                     DND_Done=TRUE;
466                 }
467             }
468             else if ( (iWeAre==2||iWeAre==4) && iSourceIs == 2){    //From Fileshelf to FileShelf
469                 //printf("FS2FS\n");
470                 if (source_fileshelfObject != me_fileshelfObject){
471                     selection  = gtk_tree_view_get_selection(GTK_TREE_VIEW(source_fileshelfObject->listView));
472                     gtk_tree_selection_selected_foreach(selection, addItemsFromFileshelfToFileshelf_Helper, source_fileshelfObject);
473                     DND_Done=TRUE;
474                 }
475             }
476             else if ( (iWeAre==2||iWeAre==4) && iSourceIs == 3){    //notbook tab to Fileshelf (we put the directory viewed from the notebook to the shelf as item)
477                 //printf("ViewTab2FS\n");
478                 gstrPath = g_string_new (source_sideObject->gstrPath->str);
479                 gstrName = g_string_new (source_sideObject->gstrPath->str);
480 
481                 getLastStringInPath(gstrName);
482                 GetPathFromPathWithName(gstrPath, 1);
483 
484                 AddItemToFileshelf (me_fileshelfObject, gstrName->str, gstrPath->str, 0, 1);
485 
486                 g_string_free(gstrPath, TRUE);
487                 g_string_free(gstrName, TRUE);
488                 DND_Done=TRUE;
489             }
490         }*/
491     }
492 
493     gtk_drag_finish (drag_context, DND_Done, FALSE, time);
494     //gtk_drag_finish (drag_context, TRUE, TRUE, time);
495 
496     TRACEIT(10,"DNDSignal_dragdatereceive_forSideObjectAndFileShelf		end");
497 }
498 
499 
500 
DNDSignal_dragdatereceive_forCopyReMoveWidget(GtkWidget * widget,GdkDragContext * drag_context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint time,void * user_data)501 void DNDSignal_dragdatereceive_forCopyReMoveWidget (GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, void *user_data){
502     TRACEIT(10,"DNDSignal_dragdatereceive_forCopyReMoveWidget		start");
503     // user_data is of type     struct ListWidgetCommunicationStruct
504     GString *gstrPath = g_string_sized_new (10);
505     GString *gstrName = g_string_sized_new (10);
506     //int iCopyToSideObject = 0;
507     char *cpBuf = NULL;
508     struct CopyReMoveList *FirstItem = NULL;
509     struct CopyReMoveList *AllreadyExistingList = NULL;
510     struct ListWidgetCommunicationStruct *CommStru = NULL;
511     GError *error = NULL;
512     gchar *cpConvertedString=NULL;
513     gchar *cpConvertedString2=NULL;
514     gboolean DND_Done = FALSE;
515     gchar *cpHostName=NULL;
516     GtkTreeIter iter;
517     int iListCreated=0;
518     int iItemColumn=0;
519 
520     CommStru = (struct ListWidgetCommunicationStruct *)user_data;
521     AllreadyExistingList = CommStru->firstItem;
522     if (NULL == CommStru){
523         gtk_drag_finish (drag_context, DND_Done, FALSE, time);
524         TRACEIT(2, "DNDSignal_dragdatereceive_forCopyReMoveWidget		PARAMETER NULL (1)");
525         return;
526     }
527 
528     AllreadyExistingList = CommStru->firstItem;
529     if (NULL == AllreadyExistingList){
530         gtk_drag_finish (drag_context, DND_Done, FALSE, time);
531         TRACEIT(2, "DNDSignal_dragdatereceive_forCopyReMoveWidget		PARAMETER NULL");
532         return;
533     }
534 
535     if((selection_data != NULL) && (selection_data->length >= 0)){
536     	//determine own type (the widget is from sideObject or Fileshelf)
537 
538     	if (info == TARGET_MARKEDITEMSASTEXT){
539     		//we only handle "file://<PATHWITHFILE>" objects in here, this is a filebrowser.
540     		cpBuf = (char *)selection_data->data;
541 
542     		for (cpBuf = strtok (cpBuf, "\r\n"); cpBuf!=NULL; cpBuf = strtok (NULL, "\r\n") ){
543 
544     		    cpConvertedString = g_locale_from_utf8 (cpBuf, strlen (cpBuf), NULL, NULL, &error);
545     		    if (error != NULL){
546                     TRACEIT (2, "DNDSignal_dragdatereceive_forSideObjectAndFileShelf error from locale_from_utf8:");
547                     TRACEIT (2, error->message);
548                     g_error_free (error);
549                     error = NULL;
550     		    }
551     		    if (cpConvertedString == NULL){
552                     //do not stop here, we will have a fall back for this case
553                     cpConvertedString2 = g_filename_from_uri (cpBuf, &cpHostName, &error);
554     		    }
555     		    else{
556                     cpConvertedString2 = g_filename_from_uri (cpConvertedString, &cpHostName, &error);
557                     g_free (cpConvertedString);
558                     cpConvertedString=NULL;
559     		    }
560     		    if (error != NULL){
561                     TRACEIT (2, "DNDSignal_dragdatereceive_forSideObjectAndFileShelf error from g_filename_from_uri:");
562                     TRACEIT (2, error->message);
563                     g_error_free (error);
564                     error = NULL;
565     		    }
566     		    if (cpConvertedString2 == NULL){
567                     continue;
568     		    }
569 
570     			if (cpHostName != NULL && strcmp (cpHostName, "file://")!=0){
571     			    g_free(cpConvertedString2);
572     			    cpConvertedString2=NULL;
573     				continue;
574     			}
575     			else if (cpHostName != NULL){
576                     g_free (cpHostName);
577     			}
578 
579                 //we create a CopyReMoveList and let others do the work
580                 g_string_assign (gstrPath, cpConvertedString2);
581                 GetPathFromPathWithName(gstrPath, 1);
582                 if (NULL!=AllreadyExistingList->DestObject && 0 == strcmp (gstrPath->str, AllreadyExistingList->DestObject->gstrPath->str)){
583                     g_free(cpConvertedString2);
584                     cpConvertedString2=NULL;
585                     continue;
586                 }
587 
588                 //copy unknown parameter from the 'old' list
589                 CopyReMoveList_AddItem (    &FirstItem, cpConvertedString2,
590                                             (AllreadyExistingList->DestObject==NULL)?NULL:AllreadyExistingList->DestObject->gstrPath->str,
591                                             AllreadyExistingList->SrcObject,
592                                             AllreadyExistingList->DestObject,
593                                             AllreadyExistingList->FileShelfObject);
594                 iListCreated = 1;
595 
596     			if (cpConvertedString2!=NULL){
597                     g_free(cpConvertedString2);
598                     cpConvertedString2=NULL;
599     			}
600     		}
601 
602             //now we want to connect the old list in AllreadyExistingList with the new one in FirstItem
603             struct CopyReMoveList *listbuf = NULL;
604             //int iListCounter = 0;
605 
606             /*
607             listbuf = AllreadyExistingList;
608             iListCounter = 0;
609             do{
610                 iListCounter++;
611                 listbuf = listbuf->NextItem;
612             }while(listbuf!= NULL);
613 
614             listbuf = FirstItem;
615             do{
616                 iListCounter++;
617                 listbuf = listbuf->NextItem;
618             }while(listbuf!= NULL);
619             */
620 
621             if (CommStru->ThreadStartStruct != NULL){
622                 iItemColumn = 1;
623             }
624             else{
625                 iItemColumn = 2;
626             }
627 
628             if (iListCreated == 1){
629                 listbuf = FirstItem;
630                 do{
631                     gtk_list_store_append( CommStru->listStore, &iter);
632                     gtk_list_store_set ( CommStru->listStore, &iter, iItemColumn, listbuf->string1->str,-1);
633 
634                     CopyReMoveList_initializeMemberTo (listbuf,  CommStru->listStore, iter, &(CommStru->ui64TotalBytesProcessed), &(CommStru->i64StartTotalBytesCopied), &(CommStru->timeStartTimeForBytesCopied), &(CommStru->timeStartTimeForBytesCopiedSingleItem), &(CommStru->ui64TotalBytes), &(CommStru->iTotalBytesValid), (GtkProgressBar *)CommStru->progressBar, AllreadyExistingList->CopyMoveOrRemove, &(CommStru->dCopySpeed) );
635 
636 
637 
638                     if (CommStru->ThreadStartStruct != NULL){
639                         //We are in the usercommand via list widget
640                         //we have to add the new items to some more lists for the usercommand:
641                         g_string_assign (gstrPath, listbuf->string1->str);
642                         g_string_assign (gstrName, listbuf->string1->str);
643 
644                         getLastStringInPath(gstrName);
645                         //GetPathFromPathWithName(gstrPath, 1);
646 
647                         CommStru->ThreadStartStruct->glistItemsWithPath = g_list_append (CommStru->ThreadStartStruct->glistItemsWithPath, g_string_new (gstrPath->str));
648                         CommStru->ThreadStartStruct->glistItemsWithoutPath = g_list_append (CommStru->ThreadStartStruct->glistItemsWithoutPath, g_string_new(gstrName->str));
649                         CommStru->ThreadStartStruct->uiSizeOfLists = g_list_length (CommStru->ThreadStartStruct->glistItemsWithPath);
650                     }
651 
652 
653                     listbuf = listbuf->NextItem;
654                 }while(listbuf!= NULL);
655 
656                 //find the last item in the list
657                 for (listbuf=AllreadyExistingList; listbuf->NextItem; listbuf=listbuf->NextItem);
658 
659                 //connect the two lists
660                 listbuf->NextItem = FirstItem;
661                 FirstItem->PrevItem = listbuf;
662 
663 
664                 copyReMoveWidget_updateItemCounterColumn(FirstItem);
665 
666                 if (CommStru->ThreadStartStruct == NULL){
667                     //means, that we are in the CopyReMoveWidget
668                     if (CommStru->iTotalBytesValid==1){
669                         if (FirstItem->CopyMoveOrRemove != 3){    //do not calculate this when deleting
670                             g_thread_create((GThreadFunc)CopyReMoveItemsViaList_SizeCalc, (void *)CommStru , FALSE, NULL);
671                         }
672                     }
673                 }
674             }
675 
676     		DND_Done=TRUE;
677     	}
678     }
679 
680     g_string_free (gstrPath, TRUE);
681     g_string_free (gstrName, TRUE);
682 
683     gtk_drag_finish (drag_context, DND_Done, FALSE, time);
684 
685     //fired automaticly via signal drag-leave
686     //gtk_button_clicked (CommStru->continueButton);
687 
688     TRACEIT(10,"DNDSignal_dragdatereceive_forCopyReMoveWidget		end");
689 }
690 
691 
692 
693 
694 ////////////////////////////////////////////////////////////////////////////////////////////
695 /*
696 void                gtk_drag_dest_set                   (GtkWidget *widget,
697                                                          GtkDestDefaults flags,
698                                                          const GtkTargetEntry *targets,
699                                                          gint n_targets,
700                                                          GdkDragAction actions);
701 
702 typedef struct {
703   gchar *target;
704   guint  flags;     //GTK_TARGET_SAME_APP
705   guint  info;
706 } GtkTargetEntry;
707 
708 typedef enum
709 {
710   GDK_ACTION_DEFAULT = 1 << 0,
711   GDK_ACTION_COPY    = 1 << 1,
712   GDK_ACTION_MOVE    = 1 << 2,
713   GDK_ACTION_LINK    = 1 << 3,
714   GDK_ACTION_PRIVATE = 1 << 4,
715   GDK_ACTION_ASK     = 1 << 5
716 } GdkDragAction;
717 
718 
719 //some signals
720   "drag-begin"                                     : Run Last
721   "drag-data-delete"                               : Run Last
722   "drag-data-get"                                  : Run Last
723   "drag-data-received"                             : Run Last
724   "drag-drop"                                      : Run Last
725   "drag-end"                                       : Run Last
726   "drag-failed"                                    : Run Last
727   "drag-leave"                                     : Run Last
728   "drag-motion"
729 */
730 
731