1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21 #include <math.h>
22
23 #include <cairo-dock.h>
24
25 #include "applet-struct.h"
26 #include "applet-bookmarks.h"
27 #include "applet-disk-usage.h"
28 #include "applet-drives.h"
29 #include "applet-load-icons.h"
30
31
cd_shortcuts_set_icon_order_by_name(Icon * pNewIcon,GList * pIconsList)32 void cd_shortcuts_set_icon_order_by_name (Icon *pNewIcon, GList *pIconsList)
33 {
34 GList *ic;
35 Icon *pIcon;
36 for (ic = pIconsList; ic != NULL; ic = ic->next)
37 {
38 pIcon = ic->data;
39 if (pIcon->iGroup == pNewIcon->iGroup)
40 break;
41 }
42 GList *ic0 = ic;
43 if (! ic0)
44 {
45 pNewIcon->fOrder = 0;
46 return;
47 }
48
49 pIcon = ic0->data;
50 if (cairo_dock_compare_icons_name (pNewIcon, pIcon) <= 0)
51 {
52 pNewIcon->fOrder = pIcon->fOrder - 1;
53 //g_print ("name : %s <= %s -> %.2f\n", pNewIcon->cName, pIcon->cName, pNewIcon->fOrder);
54 return;
55 }
56
57 pNewIcon->fOrder = 0;
58 for (ic = ic0; ic != NULL; ic = ic->next)
59 {
60 pIcon = ic->data;
61 if (pIcon->iGroup != pNewIcon->iGroup)
62 break;
63 if (cairo_dock_compare_icons_name (pNewIcon, pIcon) < 0)
64 {
65 if (ic->prev == NULL)
66 pNewIcon->fOrder = pIcon->fOrder - 1;
67 else
68 {
69 Icon *pPrevIcon = ic->prev->data;
70 pNewIcon->fOrder = (pIcon->fOrder + pPrevIcon->fOrder) / 2;
71 }
72 //g_print (" name : %s < %s -> %.2f\n", pNewIcon->cName, pIcon->cName, pNewIcon->fOrder);
73 break;
74 }
75 pNewIcon->fOrder = pIcon->fOrder + 1;
76 }
77 }
78
79
_cd_shortcuts_on_network_event(CairoDockFMEventType iEventType,const gchar * cURI,GldiModuleInstance * myApplet)80 static void _cd_shortcuts_on_network_event (CairoDockFMEventType iEventType, const gchar *cURI, GldiModuleInstance *myApplet)
81 {
82 CD_APPLET_ENTER;
83
84 //g_print (" * event %d on network '%s'\n", iEventType, cURI);
85 GList *pIconsList = CD_APPLET_MY_ICONS_LIST;
86 GldiContainer *pContainer = CD_APPLET_MY_ICONS_LIST_CONTAINER;
87 CD_APPLET_LEAVE_IF_FAIL (pContainer != NULL);
88
89 switch (iEventType)
90 {
91 case CAIRO_DOCK_FILE_DELETED : // un reseau a ete deconnecte.
92 {
93 Icon *pConcernedIcon = cairo_dock_get_icon_with_base_uri (pIconsList, cURI);
94 if (pConcernedIcon == NULL) // on cherche par nom.
95 {
96 pConcernedIcon = cairo_dock_get_icon_with_name (pIconsList, cURI);
97 }
98 if (pConcernedIcon == NULL)
99 {
100 cd_warning (" an unknown network was removed");
101 return ;
102 }
103 //g_print (" %s will be removed\n", pConcernedIcon->cName);
104
105 CD_APPLET_REMOVE_ICON_FROM_MY_ICONS_LIST (pConcernedIcon);
106 }
107 break ;
108
109 case CAIRO_DOCK_FILE_CREATED : // un reseau a ete connecte.
110 {
111 //\_______________________ on verifie qu'elle n'existe pas deja.
112 Icon *pSameIcon = cairo_dock_get_icon_with_base_uri (pIconsList, cURI);
113 if (pSameIcon != NULL)
114 {
115 cd_warning ("this mount point (%s) already exists.", pSameIcon->cName);
116 return; // on decide de ne rien faire, c'est surement un signal inutile.
117 }
118
119 //\_______________________ on cree une icone pour cette nouvelle URI.
120 Icon *pNewIcon = cairo_dock_fm_create_icon_from_URI (cURI, pContainer, CAIRO_DOCK_FM_SORT_BY_NAME);
121 if (pNewIcon == NULL)
122 {
123 cd_warning ("couldn't create an icon for this network");
124 return ;
125 }
126 pNewIcon->iGroup = CD_NETWORK_GROUP;
127
128 //\_______________________ on la place au bon endroit suivant son nom.
129 cd_shortcuts_set_icon_order_by_name (pNewIcon, pIconsList);
130 //g_print (" new network : %s, order = %.2f\n", pNewIcon->cName, pNewIcon->fOrder);
131
132 //\_______________________ on l'insere dans la liste.
133 CD_APPLET_ADD_ICON_IN_MY_ICONS_LIST (pNewIcon);
134
135 //\_______________________ on affiche un message.
136 gldi_dialog_show_temporary_with_icon_printf (
137 D_("%s has been connected"),
138 pNewIcon, pContainer,
139 4000,
140 NULL, // son icone n'est pas encore chargee
141 pNewIcon->cName);
142 }
143 break ;
144
145 case CAIRO_DOCK_FILE_MODIFIED : // un point de montage a ete (de)monte
146 {
147 //\_______________________ on cherche l'icone concernee.
148 Icon *pConcernedIcon = cairo_dock_get_icon_with_base_uri (pIconsList, cURI);
149 if (pConcernedIcon == NULL) // on cherche par nom.
150 {
151 pConcernedIcon = cairo_dock_get_icon_with_name (pIconsList, cURI);
152 }
153 if (pConcernedIcon == NULL)
154 {
155 cd_warning (" an unknown network was modified");
156 return ;
157 }
158 //g_print (" %s is modified\n", pConcernedIcon->cName);
159
160 //\_______________________ on recupere les infos actuelles.
161 Icon *pNewIcon = cairo_dock_fm_create_icon_from_URI (cURI, pContainer, CAIRO_DOCK_FM_SORT_BY_NAME);
162 if (pNewIcon == NULL)
163 {
164 cd_warning ("couldn't create an icon for this network");
165 return ;
166 }
167 pNewIcon->iGroup = CD_NETWORK_GROUP;
168
169 //\_______________________ on remplace l'icone si des choses ont change.
170 if (cairo_dock_strings_differ (pConcernedIcon->cName, pNewIcon->cName) || cairo_dock_strings_differ (pConcernedIcon->cFileName, pNewIcon->cFileName))
171 {
172 //g_print (" '%s' -> '%s'\n'%s' -> '%s'\n", pConcernedIcon->cName, pNewIcon->cName, pConcernedIcon->cFileName, pNewIcon->cFileName);
173
174 CD_APPLET_REMOVE_ICON_FROM_MY_ICONS_LIST (pConcernedIcon);
175 pIconsList = CD_APPLET_MY_ICONS_LIST;
176
177 cd_shortcuts_set_icon_order_by_name (pNewIcon, pIconsList);
178 CD_APPLET_ADD_ICON_IN_MY_ICONS_LIST (pNewIcon);
179 }
180 else
181 {
182 gldi_object_unref (GLDI_OBJECT (pNewIcon));
183 }
184 }
185 break ;
186
187 case CAIRO_DOCK_NB_EVENT_ON_FILES :
188 break ;
189 }
190 CD_APPLET_LEAVE();
191 }
192
193
_load_icons(CDSharedMemory * pSharedMemory)194 static inline GList * _load_icons (CDSharedMemory *pSharedMemory)
195 {
196 GList *pIconList = NULL;
197
198 if (pSharedMemory->bListDrives)
199 {
200 pIconList = cd_shortcuts_list_drives (pSharedMemory);
201 }
202
203 if (pSharedMemory->bListNetwork)
204 {
205 gchar *cFullURI = NULL;
206 GList *pIconList2 = cairo_dock_fm_list_directory (CAIRO_DOCK_FM_NETWORK, CAIRO_DOCK_FM_SORT_BY_NAME, CD_NETWORK_GROUP, FALSE, 100, &cFullURI);
207 cd_message (" cFullURI : %s", cFullURI);
208
209 pIconList = g_list_concat (pIconList, pIconList2);
210
211 pSharedMemory->cNetworkURI = cFullURI;
212 }
213
214 if (pSharedMemory->bListBookmarks)
215 {
216 // guess the file we should use (from GTK 3.6, the new one should be used, but some system (like Mint-14) didn't switch on time and still use the old one...)
217 gchar *cBookmarkFilePath = NULL;
218 #if GTK_CHECK_VERSION (3, 6, 0)
219 gchar *cBookmarkFilePathNew = g_strdup_printf ("%s/"GTK_BOOKMARKS_PATH, g_getenv ("HOME"));
220 gchar *cBookmarkFilePathOld = g_strdup_printf ("%s/"GTK_BOOKMARKS_PATH_OLD, g_getenv ("HOME"));
221 if (! g_file_test (cBookmarkFilePathNew, G_FILE_TEST_EXISTS)) // the new file doesn't exist yet, it's either that the old one is used, or that none is used
222 {
223 if (g_file_test (cBookmarkFilePathOld, G_FILE_TEST_EXISTS))
224 {
225 cBookmarkFilePath = cBookmarkFilePathOld;
226 cBookmarkFilePathOld = NULL;
227 }
228 else // none are used, use the new one
229 {
230 cBookmarkFilePath = cBookmarkFilePathNew;
231 cBookmarkFilePathNew = NULL;
232 }
233 }
234 else // the new one exists -> take it, unless it's empty and the old one exists too (may happen if we created the new one when the old one was still used, in version 3.3.1)
235 {
236 if (cairo_dock_get_file_size (cBookmarkFilePathNew) == 0 && g_file_test (cBookmarkFilePathOld, G_FILE_TEST_EXISTS) && cairo_dock_get_file_size (cBookmarkFilePathOld) != 0)
237 {
238 cBookmarkFilePath = cBookmarkFilePathOld;
239 cBookmarkFilePathOld = NULL;
240 }
241 else // none are used, use the new one
242 {
243 cBookmarkFilePath = cBookmarkFilePathNew;
244 cBookmarkFilePathNew = NULL;
245 }
246 }
247 g_free (cBookmarkFilePathOld);
248 g_free (cBookmarkFilePathNew);
249 #else
250 cBookmarkFilePath = g_strdup_printf ("%s/"GTK_BOOKMARKS_PATH_OLD, g_getenv ("HOME"));
251 #endif
252 // we create this file if it doesn't exist in order to be able to add bookmarks later
253 if (! g_file_test (cBookmarkFilePath, G_FILE_TEST_EXISTS))
254 {
255 // first, we need to be sure that its directory exists
256 char *str = strrchr (cBookmarkFilePath, '/'); // last occurrence of '/'
257 *str = '\0';
258 g_mkdir_with_parents (cBookmarkFilePath, 7*8*8+7*8+5);
259 *str = '/';
260 // create the empty file
261 FILE *f = fopen (cBookmarkFilePath, "a");
262 if (f)
263 fclose (f);
264 }
265
266 GList *pIconList2 = cd_shortcuts_list_bookmarks (cBookmarkFilePath, pSharedMemory->pApplet);
267
268 pIconList = g_list_concat (pIconList, pIconList2);
269
270 pSharedMemory->cBookmarksURI = cBookmarkFilePath;
271 }
272
273 return pIconList;
274 }
cd_shortcuts_get_shortcuts_data(CDSharedMemory * pSharedMemory)275 static void cd_shortcuts_get_shortcuts_data (CDSharedMemory *pSharedMemory)
276 {
277 pSharedMemory->pIconList = _load_icons (pSharedMemory);
278 }
279
cd_shortcuts_build_shortcuts_from_data(CDSharedMemory * pSharedMemory)280 static gboolean cd_shortcuts_build_shortcuts_from_data (CDSharedMemory *pSharedMemory)
281 {
282 GldiModuleInstance *myApplet = pSharedMemory->pApplet;
283 g_return_val_if_fail (myIcon != NULL, FALSE); // paranoia
284 CD_APPLET_ENTER;
285
286 //\_______________________ get the result of the thread.
287 GList *pIconList = pSharedMemory->pIconList;
288 pSharedMemory->pIconList = NULL;
289 myData.cDisksURI = pSharedMemory->cDisksURI;
290 pSharedMemory->cDisksURI = NULL;
291 myData.cNetworkURI = pSharedMemory->cNetworkURI;
292 pSharedMemory->cNetworkURI = NULL;
293 myData.cBookmarksURI = pSharedMemory->cBookmarksURI;
294 pSharedMemory->cBookmarksURI = NULL;
295
296 //\_______________________ monitor the sets.
297 if (myData.cDisksURI)
298 {
299 if (! cairo_dock_fm_add_monitor_full (myData.cDisksURI, TRUE, NULL, (CairoDockFMMonitorCallback) cd_shortcuts_on_drive_event, myApplet))
300 cd_warning ("Shortcuts : can't monitor drives");
301 }
302 if (myData.cNetworkURI)
303 {
304 if (! cairo_dock_fm_add_monitor_full (myData.cNetworkURI, TRUE, NULL, (CairoDockFMMonitorCallback) _cd_shortcuts_on_network_event, myApplet))
305 cd_warning ("Shortcuts : can't monitor network");
306 }
307 if (myData.cBookmarksURI)
308 {
309 if (! cairo_dock_fm_add_monitor_full (myData.cBookmarksURI, FALSE, NULL, (CairoDockFMMonitorCallback) cd_shortcuts_on_bookmarks_event, myApplet))
310 cd_warning ("Shortcuts : can't monitor bookmarks");
311 }
312
313 //\_______________________ On efface l'ancienne liste.
314 CD_APPLET_DELETE_MY_ICONS_LIST;
315
316 //\_______________________ On charge la nouvelle liste.
317 const gchar *cDeskletRendererName = NULL;
318 switch (myConfig.iDeskletRendererType)
319 {
320 case CD_DESKLET_SLIDE :
321 default :
322 cDeskletRendererName = "Viewport";
323 break ;
324
325 case CD_DESKLET_TREE :
326 cDeskletRendererName = "Tree";
327 break ;
328 }
329 CD_APPLET_LOAD_MY_ICONS_LIST (pIconList, myConfig.cRenderer, cDeskletRendererName, NULL); // takes ownership of 'pIconList'
330
331 //\_______________________ add a progress bar on disk volumes (must be done after inserting the icons into a container)
332 pIconList = CD_APPLET_MY_ICONS_LIST;
333 Icon *pIcon;
334 GList *ic;
335 for (ic = pIconList; ic != NULL; ic = ic->next)
336 {
337 pIcon = ic->data;
338 if (CD_APPLET_GET_MY_ICON_DATA (pIcon) != NULL) // drive
339 cd_shortcuts_add_progress_bar (pIcon, myApplet);
340 }
341
342 //\_______________________ On lance la tache de mesure des disques.
343 cd_shortcuts_launch_disk_periodic_task (myApplet);
344
345 if (myData.bShowMenuPending)
346 {
347 gldi_object_notify (myContainer, NOTIFICATION_CLICK_ICON, myIcon, myDock, GDK_BUTTON1_MASK);
348 myData.bShowMenuPending = FALSE;
349 }
350
351 gldi_task_discard (myData.pTask);
352 myData.pTask = NULL;
353
354 CD_APPLET_LEAVE (TRUE);
355 }
356
_free_shared_memory(CDSharedMemory * pSharedMemory)357 static void _free_shared_memory (CDSharedMemory *pSharedMemory)
358 {
359 g_free (pSharedMemory->cDisksURI);
360 g_free (pSharedMemory->cNetworkURI);
361 g_free (pSharedMemory->cBookmarksURI);
362 g_list_foreach (pSharedMemory->pIconList, (GFunc)g_free, NULL);
363 g_list_free (pSharedMemory->pIconList);
364 g_free (pSharedMemory);
365 }
cd_shortcuts_start(GldiModuleInstance * myApplet)366 void cd_shortcuts_start (GldiModuleInstance *myApplet)
367 {
368 if (myData.pTask != NULL)
369 {
370 gldi_task_discard (myData.pTask);
371 myData.pTask = NULL;
372 }
373
374 CDSharedMemory *pSharedMemory = g_new0 (CDSharedMemory, 1);
375 pSharedMemory->bListDrives = myConfig.bListDrives;
376 pSharedMemory->bListNetwork = myConfig.bListNetwork;
377 pSharedMemory->bListBookmarks = myConfig.bListBookmarks;
378 pSharedMemory->pApplet = myApplet;
379
380 myData.pTask = gldi_task_new_full (0,
381 (GldiGetDataAsyncFunc) cd_shortcuts_get_shortcuts_data,
382 (GldiUpdateSyncFunc) cd_shortcuts_build_shortcuts_from_data,
383 (GFreeFunc) _free_shared_memory,
384 pSharedMemory);
385
386 if (cairo_dock_is_loading ())
387 gldi_task_launch_delayed (myData.pTask, 0); // 0 <=> g_idle
388 else
389 gldi_task_launch (myData.pTask);
390 }
391
392