~ubuntu-branches/ubuntu/saucy/cairo-dock-plug-ins/saucy

« back to all changes in this revision

Viewing changes to quick-browser/src/applet-menu.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2009-08-26 21:07:39 UTC
  • Revision ID: james.westby@ubuntu.com-20090826210739-gyjuuqezrzuluao4
Tags: upstream-2.0.8.1
ImportĀ upstreamĀ versionĀ 2.0.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/******************************************************************************
 
21
 
 
22
This file is a part of the cairo-dock program, 
 
23
released under the terms of the GNU General Public License.
 
24
 
 
25
Written by Fabrice Rey (for any bug report, please mail me to fabounet@users.berlios.de)
 
26
 
 
27
******************************************************************************/
 
28
 
 
29
#include <string.h>
 
30
 
 
31
#include "applet-struct.h"
 
32
#include "applet-menu.h"
 
33
 
 
34
static GList *s_pItemList = NULL;
 
35
 
 
36
static void _on_activate_item (GtkWidget *pMenuItem, CDQuickBrowserItem *pItem);
 
37
 
 
38
static int _sort_item (CDQuickBrowserItem *pItem1, CDQuickBrowserItem *pItem2)
 
39
{
 
40
        if (pItem1 == NULL)
 
41
                return -1;
 
42
        if (pItem2 == NULL)
 
43
                return 1;
 
44
        CairoDockModuleInstance *myApplet = pItem2->pApplet;
 
45
        if (myConfig.bFoldersFirst)
 
46
        {
 
47
                if (pItem1->pSubMenu && ! pItem2->pSubMenu)
 
48
                        return -1;
 
49
                if (! pItem1->pSubMenu && pItem2->pSubMenu)
 
50
                        return 1;
 
51
        }
 
52
        if (myConfig.bCaseUnsensitive)
 
53
                return g_ascii_strcasecmp (pItem1->cTmpFileName, pItem2->cTmpFileName);
 
54
        else
 
55
                return strcmp (pItem1->cTmpFileName, pItem2->cTmpFileName);
 
56
}
 
57
static GList *_list_dir (const gchar *cDirPath, CairoDockModuleInstance *myApplet)
 
58
{
 
59
        //\______________ On ouvre le repertoire en lecture.
 
60
        GError *erreur = NULL;
 
61
        GDir *dir = g_dir_open (cDirPath, 0, &erreur);
 
62
        if (erreur != NULL)
 
63
        {
 
64
                cd_warning (erreur->message);
 
65
                g_error_free (erreur);
 
66
                return NULL;
 
67
        }
 
68
        
 
69
        //\______________ On recupere chaque item, qu'on classe dans une liste temporaire.
 
70
        CDQuickBrowserItem *pItem;
 
71
        const gchar *cFileName;
 
72
        GList *pLocalItemList = NULL;
 
73
        do
 
74
        {
 
75
                cFileName = g_dir_read_name (dir);
 
76
                if (cFileName == NULL)
 
77
                        break ;
 
78
                if (! myConfig.bShowHiddenFiles && *cFileName == '.')
 
79
                        continue;
 
80
                pItem = g_new0 (CDQuickBrowserItem, 1);
 
81
                pItem->cPath = g_strdup_printf ("%s/%s", cDirPath, cFileName);
 
82
                pItem->cTmpFileName = cFileName;  // valable uniquement dans cette boucle, ca tombe bien le classement se fait ici.
 
83
                pItem->pApplet = myApplet;
 
84
                if (g_file_test (pItem->cPath, G_FILE_TEST_IS_DIR))
 
85
                        pItem->pSubMenu = gtk_menu_new ();
 
86
                
 
87
                pLocalItemList = g_list_insert_sorted (pLocalItemList,
 
88
                        pItem,
 
89
                        (GCompareFunc)_sort_item);
 
90
        }
 
91
        while (1);
 
92
        g_dir_close (dir);
 
93
        
 
94
        return pLocalItemList;
 
95
}
 
96
static void _init_fill_menu_from_dir (CDQuickBrowserItem *pItem)
 
97
{
 
98
        const gchar *cDirPath = pItem->cPath;
 
99
        GtkWidget *pMenu = pItem->pSubMenu;
 
100
        CairoDockModuleInstance *myApplet = pItem->pApplet;
 
101
        
 
102
        //\______________ On recupere les items du repertoire.
 
103
        GList *pLocalItemList = _list_dir (cDirPath, myApplet);
 
104
        
 
105
        //\______________ On rajoute en premier une entree pour ouvrir le repertoire.
 
106
        CDQuickBrowserItem *pOpenDirItem = g_new0 (CDQuickBrowserItem, 1);
 
107
        pOpenDirItem->cPath = g_strdup (cDirPath);
 
108
        pOpenDirItem->pApplet = myApplet;
 
109
        pItem->pLocalItemList = g_list_prepend (pLocalItemList, pOpenDirItem);
 
110
        pItem->pCurrentItem = pItem->pLocalItemList->next;  // on la rajoute au menu ici, pas en meme temps que les autres.
 
111
        
 
112
        //\______________ On ajoute cette entree dans le menu des maintenant.
 
113
        GtkWidget *pMenuItem;
 
114
        if (myConfig.bHasIcons)
 
115
        {
 
116
                pMenuItem = gtk_image_menu_item_new_with_label (D_("Open this folder"));
 
117
                GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
 
118
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (pMenuItem), image);
 
119
        }
 
120
        else
 
121
        {
 
122
                pMenuItem = gtk_menu_item_new_with_label (D_("Open this folder"));
 
123
        }
 
124
        gtk_menu_shell_append  (GTK_MENU_SHELL (pMenu), pMenuItem);
 
125
        g_signal_connect (G_OBJECT (pMenuItem), "activate", G_CALLBACK(_on_activate_item), pOpenDirItem);
 
126
}
 
127
static void _fill_submenu_with_items (CDQuickBrowserItem *pRootItem, int iNbSubItemsAtOnce)
 
128
{
 
129
        CairoDockModuleInstance *myApplet = pRootItem->pApplet;
 
130
        GtkWidget *pMenu = pRootItem->pSubMenu;
 
131
        GList *pFirstItem = pRootItem->pCurrentItem;
 
132
        
 
133
        CDQuickBrowserItem *pItem;
 
134
        gchar *cFileName;
 
135
        GtkWidget *pMenuItem;
 
136
        gboolean bSetImage;
 
137
        gchar *cName = NULL, *cURI = NULL, *cIconName = NULL;
 
138
        gboolean bIsDirectory;
 
139
        int iVolumeID;
 
140
        double fOrder;
 
141
        GList *l;
 
142
        int i;
 
143
        for (l = pFirstItem, i = 0; l != NULL && i < iNbSubItemsAtOnce; l = l->next, i ++)
 
144
        {
 
145
                pItem = l->data;
 
146
                
 
147
                //\______________ On cree l'entree avec son icone si necessaire.
 
148
                bSetImage = FALSE;
 
149
                if (myConfig.bHasIcons)
 
150
                {
 
151
                        cairo_dock_fm_get_file_info (pItem->cPath, &cName, &cURI, &cIconName, &bIsDirectory, &iVolumeID, &fOrder, 0);
 
152
                        g_free (cName);
 
153
                        cName = NULL;
 
154
                        g_free (cURI);
 
155
                        cURI = NULL;
 
156
                }
 
157
                cFileName = strrchr (pItem->cPath, '/');
 
158
                if (cFileName)
 
159
                        cFileName ++;
 
160
                if (cIconName != NULL)
 
161
                {
 
162
                        pMenuItem = gtk_image_menu_item_new_with_label (cFileName);
 
163
                        GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (cIconName, 32, 32, NULL);
 
164
                        GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
 
165
                        g_object_unref (pixbuf);
 
166
                        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (pMenuItem), image);
 
167
                        g_free (cIconName);
 
168
                        cIconName = NULL;
 
169
                }
 
170
                else
 
171
                {
 
172
                        pMenuItem = gtk_menu_item_new_with_label (cFileName);
 
173
                }
 
174
                
 
175
                //\______________ On l'insere dans le menu.
 
176
                gtk_menu_shell_append  (GTK_MENU_SHELL (pMenu), pMenuItem);
 
177
                g_signal_connect (G_OBJECT (pMenuItem), "activate", G_CALLBACK(_on_activate_item), pItem);
 
178
                
 
179
                if (pItem->pSubMenu != NULL)
 
180
                {
 
181
                        gtk_menu_item_set_submenu (GTK_MENU_ITEM (pMenuItem), pItem->pSubMenu);
 
182
                }
 
183
        }
 
184
        pRootItem->pCurrentItem = l;
 
185
}
 
186
static gboolean _fill_submenu_idle (CDQuickBrowserItem *pItem)
 
187
{
 
188
        CairoDockModuleInstance *myApplet = pItem->pApplet;
 
189
        if (pItem->pLocalItemList == NULL)
 
190
        {
 
191
                _init_fill_menu_from_dir (pItem);
 
192
                if (pItem->pLocalItemList == NULL)  // cas particulier d'un repertoire vide, inutile de revenir ici pour rien faire.
 
193
                        pItem->bMenuBuilt = TRUE;
 
194
        }
 
195
        else
 
196
        {
 
197
                _fill_submenu_with_items (pItem, myConfig.iNbSubItemsAtOnce);
 
198
                if (pItem->pCurrentItem == NULL)
 
199
                        pItem->bMenuBuilt = TRUE;
 
200
        }
 
201
 
 
202
        if (pItem->bMenuBuilt)
 
203
        {
 
204
                CairoDockModuleInstance *myApplet = pItem->pApplet;
 
205
                myData.iSidFillDirIdle = 0;
 
206
                gtk_widget_show_all (pItem->pSubMenu);
 
207
                return FALSE;
 
208
        }
 
209
        return TRUE;
 
210
}
 
211
static void _on_activate_item (GtkWidget *pMenuItem, CDQuickBrowserItem *pItem)
 
212
{
 
213
        //g_print ("%s (%s, %x)\n", __func__, pItem->cPath, pItem->pSubMenu);
 
214
        CairoDockModuleInstance *myApplet = pItem->pApplet;
 
215
        if (pItem->pSubMenu != NULL)
 
216
        {
 
217
                if (! pItem->bMenuBuilt)
 
218
                {
 
219
                        //g_print ("  c'est un repertoire (tache courante : %d)\n", myData.iSidFillDirIdle);
 
220
                        if (myData.iSidFillDirIdle != 0)
 
221
                                g_source_remove (myData.iSidFillDirIdle);
 
222
                        myData.iSidFillDirIdle = g_idle_add ((GSourceFunc) _fill_submenu_idle, pItem);
 
223
                }
 
224
        }
 
225
        else
 
226
        {
 
227
                cairo_dock_fm_launch_uri (pItem->cPath);
 
228
                cd_quick_browser_destroy_menu (myApplet);
 
229
        }
 
230
}
 
231
 
 
232
 
 
233
CDQuickBrowserItem *cd_quick_browser_make_menu_from_dir (const gchar *cDirPath, CairoDockModuleInstance *myApplet)
 
234
{
 
235
        CDQuickBrowserItem *pRootItem = g_new0 (CDQuickBrowserItem, 1);
 
236
        pRootItem->cPath = g_strdup (cDirPath);
 
237
        pRootItem->pApplet = myApplet;
 
238
        pRootItem->pSubMenu = gtk_menu_new ();
 
239
        
 
240
        _init_fill_menu_from_dir (pRootItem);
 
241
        _fill_submenu_with_items (pRootItem, 1e6);
 
242
        pRootItem->bMenuBuilt = TRUE;
 
243
        gtk_widget_show_all (pRootItem->pSubMenu);
 
244
        
 
245
        return pRootItem;
 
246
}
 
247
 
 
248
static void _free_item (CDQuickBrowserItem *pItem)
 
249
{
 
250
        g_free (pItem->cPath);
 
251
        if (pItem->pLocalItemList != NULL)
 
252
        {
 
253
                g_list_foreach (pItem->pLocalItemList, (GFunc) _free_item, NULL);
 
254
                g_list_free (pItem->pLocalItemList);
 
255
        }
 
256
        g_free (pItem);
 
257
}
 
258
void cd_quick_browser_destroy_menu (CairoDockModuleInstance *myApplet)
 
259
{
 
260
        if (myData.iSidFillDirIdle != 0)
 
261
                g_source_remove (myData.iSidFillDirIdle);
 
262
        myData.iSidFillDirIdle = 0;
 
263
        
 
264
        if (myData.pRootItem != NULL)
 
265
        {
 
266
                gtk_widget_destroy (myData.pRootItem->pSubMenu);  // detruit tous les pSubMenu en cascade.
 
267
                _free_item (myData.pRootItem);
 
268
                myData.pRootItem = NULL;
 
269
        }
 
270
}
 
271
 
 
272
void cd_quick_browser_show_menu (CairoDockModuleInstance *myApplet)
 
273
{
 
274
        cd_quick_browser_destroy_menu (myApplet);
 
275
        
 
276
        myData.pRootItem = cd_quick_browser_make_menu_from_dir (myConfig.cDirPath, myApplet);
 
277
        g_return_if_fail (myData.pRootItem != NULL && myData.pRootItem->pSubMenu != NULL);
 
278
        
 
279
        g_signal_connect (G_OBJECT (myData.pRootItem->pSubMenu),
 
280
                "deactivate",
 
281
                G_CALLBACK (cairo_dock_delete_menu),
 
282
                myContainer);
 
283
        
 
284
        if (myDock)
 
285
                myDock->bMenuVisible = TRUE;
 
286
        gtk_menu_popup (GTK_MENU (myData.pRootItem->pSubMenu),
 
287
                NULL,
 
288
                NULL,
 
289
                NULL,
 
290
                NULL,
 
291
                1,
 
292
                gtk_get_current_event_time ());
 
293
}