~helene-verhaeghe27/cairo-dock-core/bugfix

« back to all changes in this revision

Viewing changes to src/cairo-dock-gui-items.c

  • Committer: Fabrice Rey
  • Date: 2012-08-04 22:44:55 UTC
  • Revision ID: fabounet03@gmail.com-20120804224455-i4qtut3p9cv1f4si
GUI: finished to implement the reload of the GUI

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
 
#include <string.h>
21
 
#include <unistd.h>
22
 
#define __USE_XOPEN_EXTENDED
23
 
#include <stdlib.h>
24
 
#include <sys/time.h>
25
 
#include <glib/gstdio.h>
26
 
#include <glib/gi18n.h>
27
 
 
28
 
#include "config.h"
29
 
#include "cairo-dock-module-factory.h"
30
 
#include "cairo-dock-log.h"
31
 
#include "cairo-dock-icon-facility.h"
32
 
#include "cairo-dock-gui-factory.h"
33
 
#include "cairo-dock-keyfile-utilities.h"
34
 
#include "cairo-dock-animations.h"
35
 
#include "cairo-dock-draw.h"
36
 
#include "cairo-dock-dock-manager.h"
37
 
#include "cairo-dock-container.h"
38
 
#include "cairo-dock-applications-manager.h"
39
 
#include "cairo-dock-launcher-manager.h"
40
 
#include "cairo-dock-desktop-file-factory.h"
41
 
#include "cairo-dock-X-manager.h"
42
 
#include "cairo-dock-gui-manager.h"
43
 
#include "cairo-dock-gui-commons.h"
44
 
#include "cairo-dock-gui-backend.h"
45
 
#include "cairo-dock-gui-items.h"
46
 
 
47
 
#define CAIRO_DOCK_LAUNCHER_PANEL_WIDTH 1200
48
 
#define CAIRO_DOCK_LAUNCHER_PANEL_HEIGHT 700
49
 
#define CAIRO_DOCK_LEFT_PANE_MIN_WIDTH 100
50
 
#define CAIRO_DOCK_LEFT_PANE_DEFAULT_WIDTH 340
51
 
#define CAIRO_DOCK_RIGHT_PANE_MIN_WIDTH 800
52
 
 
53
 
extern gchar *g_cCurrentLaunchersPath;
54
 
extern gchar *g_cCurrentThemePath;
55
 
extern CairoDockDesktopGeometry g_desktopGeometry;
56
 
extern CairoDock *g_pMainDock;
57
 
 
58
 
static GtkWidget *s_pLauncherWindow = NULL;  // partage avec le backend 'simple'.
59
 
static GtkWidget *s_pCurrentLauncherWidget = NULL;
60
 
static GtkWidget *s_pLauncherTreeView = NULL;
61
 
static GtkWidget *s_pLauncherPane = NULL;
62
 
static gchar *cPrevPath = NULL;
63
 
 
64
 
static void _add_one_dock_to_model (CairoDock *pDock, GtkTreeStore *model, GtkTreeIter *pParentIter);
65
 
static void reload_items (void);
66
 
static void on_row_inserted (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
67
 
static void on_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data);
68
 
 
69
 
typedef enum {
70
 
        CD_MODEL_NAME = 0,  // displayed name
71
 
        CD_MODEL_PIXBUF,  // icon image
72
 
        CD_MODEL_ICON,  // Icon (for launcher/separator/sub-dock/applet)
73
 
        CD_MODEL_CONTAINER,  // CairoContainer (for main docks)
74
 
        CD_MODEL_MODULE,  // CairoDockModuleInstance (for plug-ins with no icon)
75
 
        CD_MODEL_NB_COLUMNS
76
 
        } CDModelColumns;
77
 
 
78
 
 
79
 
  ///////////
80
 
 // MODEL //
81
 
///////////
82
 
 
83
 
static gboolean _search_item_in_line (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer *data)
84
 
{
85
 
        gpointer pItem = NULL;
86
 
        gtk_tree_model_get (model, iter,
87
 
                GPOINTER_TO_INT (data[1]), &pItem, -1);
88
 
        if (pItem == data[0])
89
 
        {
90
 
                //g_print (" found !\n");
91
 
                memcpy (data[2], iter, sizeof (GtkTreeIter));
92
 
                data[3] = GINT_TO_POINTER (TRUE);
93
 
                return TRUE;  // stop iterating.
94
 
        }
95
 
        return FALSE;
96
 
}
97
 
static gboolean _search_item_in_model (GtkWidget *pTreeView, gpointer pItem, CDModelColumns iItemType, GtkTreeIter *iter)
98
 
{
99
 
        if (pItem == NULL)
100
 
                return FALSE;
101
 
        //g_print ("%s (%s)\n", __func__, ((Icon*)pItem)->cName);
102
 
        GtkTreeModel * model = gtk_tree_view_get_model (GTK_TREE_VIEW (pTreeView));
103
 
        gpointer data[4] = {pItem, GINT_TO_POINTER (iItemType), iter, GINT_TO_POINTER (FALSE)};
104
 
        gtk_tree_model_foreach (model,
105
 
                (GtkTreeModelForeachFunc) _search_item_in_line,
106
 
                data);
107
 
        return GPOINTER_TO_INT (data[3]);
108
 
}
109
 
 
110
 
static void _delete_current_launcher_widget (GtkWidget *pLauncherWindow)
111
 
{
112
 
        g_return_if_fail (pLauncherWindow != NULL);
113
 
        
114
 
        if (s_pCurrentLauncherWidget != NULL)
115
 
        {
116
 
                gtk_widget_destroy (s_pCurrentLauncherWidget);
117
 
                s_pCurrentLauncherWidget = NULL;
118
 
        }
119
 
        GSList *pWidgetList = g_object_get_data (G_OBJECT (pLauncherWindow), "widget-list");
120
 
        if (pWidgetList != NULL)
121
 
        {
122
 
                cairo_dock_free_generated_widget_list (pWidgetList);
123
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "widget-list", NULL);
124
 
        }
125
 
        GPtrArray *pDataGarbage = g_object_get_data (G_OBJECT (pLauncherWindow), "garbage");
126
 
        if (pDataGarbage != NULL)
127
 
        {
128
 
                cd_debug ("free garbage...");
129
 
                g_ptr_array_free (pDataGarbage, TRUE);
130
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "garbage", NULL);
131
 
        }
132
 
        
133
 
        g_object_set_data (G_OBJECT (pLauncherWindow), "current-icon", NULL);
134
 
        g_object_set_data (G_OBJECT (pLauncherWindow), "current-container", NULL);
135
 
        g_object_set_data (G_OBJECT (pLauncherWindow), "current-module", NULL);
136
 
}
137
 
 
138
 
static gboolean _on_select_one_item_in_tree (GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, GtkWidget *pLauncherWindow)
139
 
{
140
 
        cd_debug ("%s (path_currently_selected:%d, %s)", __func__, path_currently_selected, gtk_tree_path_to_string(path));
141
 
        if (path_currently_selected)
142
 
                return TRUE;
143
 
        
144
 
        GtkTreeIter iter;
145
 
        if (! gtk_tree_model_get_iter (model, &iter, path))
146
 
                return FALSE;
147
 
        gchar *cPath = gtk_tree_path_to_string (path);
148
 
        if (cPath && cPrevPath && strcmp (cPrevPath, cPath) == 0)
149
 
        {
150
 
                g_free (cPath);
151
 
                return TRUE;
152
 
        }
153
 
        g_free (cPrevPath);
154
 
        cPrevPath = cPath;
155
 
        
156
 
        cd_debug ("load widgets");
157
 
        // delete previous widgets
158
 
        _delete_current_launcher_widget (pLauncherWindow);  // remove all gobject data
159
 
        
160
 
        // get new current item
161
 
        gchar *cName = NULL;
162
 
        Icon *pIcon = NULL;
163
 
        CairoContainer *pContainer = NULL;
164
 
        CairoDockModuleInstance *pInstance = NULL;
165
 
        gtk_tree_model_get (model, &iter,
166
 
                CD_MODEL_NAME, &cName,
167
 
                CD_MODEL_ICON, &pIcon,
168
 
                CD_MODEL_CONTAINER, &pContainer,
169
 
                CD_MODEL_MODULE, &pInstance, -1);
170
 
        if (CAIRO_DOCK_IS_APPLET (pIcon))
171
 
                pInstance = pIcon->pModuleInstance;
172
 
        gtk_window_set_title (GTK_WINDOW (pLauncherWindow), cName);
173
 
        g_free (cName);
174
 
        
175
 
        GSList *pWidgetList = NULL;
176
 
        GPtrArray *pDataGarbage = NULL;
177
 
        
178
 
        // load conf file.
179
 
        if (pInstance != NULL)
180
 
        {
181
 
                // open applet's conf file.
182
 
                GKeyFile* pKeyFile = cairo_dock_open_key_file (pInstance->cConfFilePath);
183
 
                g_return_val_if_fail (pKeyFile != NULL, FALSE);
184
 
                
185
 
                // build applet's widgets.
186
 
                pDataGarbage = g_ptr_array_new ();
187
 
                gchar *cOriginalConfFilePath = g_strdup_printf ("%s/%s", pInstance->pModule->pVisitCard->cShareDataDir, pInstance->pModule->pVisitCard->cConfFileName);
188
 
                s_pCurrentLauncherWidget = cairo_dock_build_key_file_widget (pKeyFile,
189
 
                        pInstance->pModule->pVisitCard->cGettextDomain,
190
 
                        pLauncherWindow,
191
 
                        &pWidgetList,
192
 
                        pDataGarbage,
193
 
                        cOriginalConfFilePath);  // don't free 'cOriginalConfFilePath', it is taken by the function. TODO: find a better way...
194
 
                
195
 
                // load custom widgets
196
 
                if (pInstance->pModule->pInterface->load_custom_widget != NULL)
197
 
                {
198
 
                        g_object_set_data (G_OBJECT (pLauncherWindow), "widget-list", pWidgetList);
199
 
                        g_object_set_data (G_OBJECT (pLauncherWindow), "garbage", pDataGarbage);
200
 
                        pInstance->pModule->pInterface->load_custom_widget (pInstance, pKeyFile);
201
 
                }
202
 
                
203
 
                if (pIcon != NULL)
204
 
                        g_object_set_data (G_OBJECT (pLauncherWindow), "current-icon", pIcon);
205
 
                else
206
 
                        g_object_set_data (G_OBJECT (pLauncherWindow), "current-module", pInstance);
207
 
                
208
 
                g_key_file_free (pKeyFile);
209
 
        }
210
 
        else if (CAIRO_DOCK_IS_DOCK (pContainer))  // ligne correspondante a un dock principal
211
 
        {
212
 
                CairoDock *pDock = CAIRO_DOCK (pContainer);
213
 
                if (!pDock->bIsMainDock)  // pour l'instant le main dock n'a pas de fichier de conf
214
 
                {
215
 
                        // build dock's widgets
216
 
                        const gchar *cDockName = cairo_dock_search_dock_name (pDock);  // CD_MODEL_NAME contient le nom affiche, qui peut differer.
217
 
                        g_return_val_if_fail (cDockName != NULL, FALSE);
218
 
                        cd_message ("%s (%s)", __func__, cDockName);
219
 
                        
220
 
                        gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName);
221
 
                        if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))  // ne devrait pas arriver mais au cas ou.
222
 
                        {
223
 
                                cairo_dock_add_root_dock_config_for_name (cDockName);
224
 
                        }
225
 
                        
226
 
                        pDataGarbage = g_ptr_array_new ();
227
 
                        s_pCurrentLauncherWidget = cairo_dock_build_conf_file_widget (cConfFilePath,
228
 
                                NULL,
229
 
                                pLauncherWindow,
230
 
                                &pWidgetList,
231
 
                                pDataGarbage,
232
 
                                NULL);
233
 
                        
234
 
                        g_object_set_data (G_OBJECT (pLauncherWindow), "current-container", pDock);
235
 
                        
236
 
                        g_free (cConfFilePath);
237
 
                }
238
 
                else  // main dock, we display a message
239
 
                {
240
 
                        pDataGarbage = g_ptr_array_new ();
241
 
                        gchar *cDefaultMessage = g_strdup_printf ("<b><big>%s</big></b>", _("Main dock's parameters are available in the main configuration window."));
242
 
                        s_pCurrentLauncherWidget = cairo_dock_gui_make_preview_box (pLauncherWindow,
243
 
                                NULL,  // no selection widget
244
 
                                FALSE,  // vertical packaging
245
 
                                0,  // no info bar
246
 
                                cDefaultMessage,
247
 
                                CAIRO_DOCK_SHARE_DATA_DIR"/images/"CAIRO_DOCK_LOGO,
248
 
                                pDataGarbage);
249
 
                        g_free (cDefaultMessage);
250
 
                }
251
 
        }
252
 
        else if (pIcon && pIcon->cDesktopFileName != NULL)
253
 
        {
254
 
                //g_print ("on presente %s...\n", pIcon->cDesktopFileName);
255
 
                gchar *cConfFilePath = (*pIcon->cDesktopFileName == '/' ? g_strdup (pIcon->cDesktopFileName) : g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, pIcon->cDesktopFileName));
256
 
                
257
 
                // build launcher's widgets
258
 
                pDataGarbage = g_ptr_array_new ();
259
 
                s_pCurrentLauncherWidget = cairo_dock_build_conf_file_widget (cConfFilePath,
260
 
                        NULL,
261
 
                        pLauncherWindow,
262
 
                        &pWidgetList,
263
 
                        pDataGarbage,
264
 
                        NULL);
265
 
                
266
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "current-icon", pIcon);
267
 
                
268
 
                g_free (cConfFilePath);
269
 
        }
270
 
        
271
 
        // set widgets in the main window.
272
 
        if (s_pCurrentLauncherWidget != NULL)
273
 
        {
274
 
                gtk_paned_pack2 (GTK_PANED (s_pLauncherPane), s_pCurrentLauncherWidget, TRUE, FALSE);
275
 
                
276
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "widget-list", pWidgetList);
277
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "garbage", pDataGarbage);
278
 
                
279
 
                gtk_widget_show_all (s_pCurrentLauncherWidget);
280
 
        }
281
 
        return TRUE;
282
 
}
283
 
 
284
 
static void _add_one_icon_to_model (Icon *pIcon, GtkTreeStore *model, GtkTreeIter *pParentIter)
285
 
{
286
 
        if (!pIcon->cDesktopFileName && ! CAIRO_DOCK_IS_APPLET (pIcon))
287
 
                return;
288
 
        
289
 
        if (cairo_dock_icon_is_being_removed (pIcon))
290
 
                return;
291
 
        
292
 
        GtkTreeIter iter;
293
 
        GError *erreur = NULL;
294
 
        GdkPixbuf *pixbuf = NULL;
295
 
        gchar *cImagePath = NULL;
296
 
        const gchar *cName;
297
 
        gint iDesiredIconSize = cairo_dock_search_icon_size (GTK_ICON_SIZE_DND); // default is 32
298
 
        
299
 
        // set an image.
300
 
        if (pIcon->cFileName != NULL)
301
 
        {
302
 
                cImagePath = cairo_dock_search_icon_s_path (pIcon->cFileName, iDesiredIconSize);
303
 
        }
304
 
        if (cImagePath == NULL || ! g_file_test (cImagePath, G_FILE_TEST_EXISTS))
305
 
        {
306
 
                g_free (cImagePath);
307
 
                if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
308
 
                {
309
 
                        if (myIconsParam.cSeparatorImage)
310
 
                                cImagePath = cairo_dock_search_image_s_path (myIconsParam.cSeparatorImage);
311
 
                }
312
 
                else if (CAIRO_DOCK_IS_APPLET (pIcon))
313
 
                {
314
 
                        cImagePath = g_strdup (pIcon->pModuleInstance->pModule->pVisitCard->cIconFilePath);
315
 
                }
316
 
                else
317
 
                {
318
 
                        cImagePath = cairo_dock_search_image_s_path (CAIRO_DOCK_DEFAULT_ICON_NAME);
319
 
                        if (cImagePath == NULL || ! g_file_test (cImagePath, G_FILE_TEST_EXISTS))
320
 
                        {
321
 
                                g_free (cImagePath);
322
 
                                cImagePath = g_strdup (CAIRO_DOCK_SHARE_DATA_DIR"/icons/"CAIRO_DOCK_DEFAULT_ICON_NAME);
323
 
                        }
324
 
                }
325
 
        }
326
 
        
327
 
        if (cImagePath != NULL)
328
 
        {
329
 
                pixbuf = gdk_pixbuf_new_from_file_at_size (cImagePath, iDesiredIconSize, iDesiredIconSize, &erreur);
330
 
                if (erreur != NULL)
331
 
                {
332
 
                        cd_warning (erreur->message);
333
 
                        g_error_free (erreur);
334
 
                        erreur = NULL;
335
 
                }
336
 
        }
337
 
        
338
 
        // set a name
339
 
        if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon))  // separator
340
 
                cName = "---------";
341
 
        else if (CAIRO_DOCK_IS_APPLET (pIcon))  // applet
342
 
                cName = pIcon->pModuleInstance->pModule->pVisitCard->cTitle;
343
 
        else  // launcher
344
 
                cName = (pIcon->cInitialName ? pIcon->cInitialName : pIcon->cName);
345
 
        
346
 
        // add an entry in the tree view.
347
 
        gtk_tree_store_append (model, &iter, pParentIter);
348
 
        gtk_tree_store_set (model, &iter,
349
 
                CD_MODEL_NAME, cName,
350
 
                CD_MODEL_PIXBUF, pixbuf,
351
 
                CD_MODEL_ICON, pIcon,
352
 
                -1);
353
 
        
354
 
        // recursively add the sub-icons.
355
 
        if (CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon) && pIcon->pSubDock != NULL)
356
 
        {
357
 
                _add_one_dock_to_model (pIcon->pSubDock, model, &iter);
358
 
        }
359
 
        
360
 
        // reset all.
361
 
        g_free (cImagePath);
362
 
        if (pixbuf)
363
 
                g_object_unref (pixbuf);
364
 
}
365
 
static void _add_one_dock_to_model (CairoDock *pDock, GtkTreeStore *model, GtkTreeIter *pParentIter)
366
 
{
367
 
        GList *ic;
368
 
        Icon *pIcon;
369
 
        for (ic = pDock->icons; ic != NULL; ic = ic->next)  // add each icons.
370
 
        {
371
 
                pIcon = ic->data;
372
 
                _add_one_icon_to_model (pIcon, model, pParentIter);
373
 
        }
374
 
}
375
 
 
376
 
static void _add_one_root_dock_to_model (const gchar *cName, CairoDock *pDock, GtkTreeStore *model)
377
 
{
378
 
        if (pDock->iRefCount != 0)
379
 
                return ;
380
 
        GtkTreeIter iter;
381
 
        
382
 
        // on ajoute une ligne pour le dock.
383
 
        gtk_tree_store_append (model, &iter, NULL);
384
 
        gchar *cUserName = cairo_dock_get_readable_name_for_fock (pDock);
385
 
        gtk_tree_store_set (model, &iter,
386
 
                CD_MODEL_NAME, cUserName ? cUserName : cName,
387
 
                CD_MODEL_CONTAINER, pDock,
388
 
                -1);
389
 
        g_free (cUserName);
390
 
        
391
 
        // on ajoute chaque lanceur.
392
 
        _add_one_dock_to_model (pDock, model, &iter);
393
 
}
394
 
 
395
 
static gboolean _add_one_desklet_to_model (CairoDesklet *pDesklet, GtkTreeStore *model)
396
 
{
397
 
        if (pDesklet->pIcon == NULL)
398
 
                return FALSE;
399
 
        
400
 
        // on ajoute l'icone du desklet.
401
 
        _add_one_icon_to_model (pDesklet->pIcon, model, NULL);  // les sous-icones du desklet ne nous interessent pas.
402
 
        
403
 
        return FALSE; // FALSE => keep going
404
 
}
405
 
 
406
 
static inline void _add_one_module (const gchar *cModuleName, CairoDockModuleInstance *pModuleInstance, GtkTreeStore *model)
407
 
{
408
 
        GtkTreeIter iter;
409
 
        gtk_tree_store_append (model, &iter, NULL);
410
 
        
411
 
        GdkPixbuf *pixbuf = NULL;
412
 
        gchar *cImagePath = g_strdup (pModuleInstance->pModule->pVisitCard->cIconFilePath);
413
 
        if (cImagePath != NULL)
414
 
                pixbuf = gdk_pixbuf_new_from_file_at_size (cImagePath, 32, 32, NULL);
415
 
        gtk_tree_store_set (model, &iter,
416
 
                CD_MODEL_NAME, cModuleName,
417
 
                CD_MODEL_PIXBUF, pixbuf,
418
 
                CD_MODEL_MODULE, pModuleInstance,
419
 
                -1);
420
 
        g_free (cImagePath);
421
 
        if (pixbuf)
422
 
                g_object_unref (pixbuf);
423
 
}
424
 
static gboolean _add_one_module_to_model (const gchar *cModuleName, CairoDockModule *pModule, GtkTreeStore *model)
425
 
{
426
 
        if (pModule->pVisitCard->iCategory != CAIRO_DOCK_CATEGORY_BEHAVIOR && pModule->pVisitCard->iCategory != CAIRO_DOCK_CATEGORY_THEME && ! cairo_dock_module_is_auto_loaded (pModule) && pModule->pInstancesList != NULL)
427
 
        {
428
 
                CairoDockModuleInstance *pModuleInstance = pModule->pInstancesList->data;
429
 
                if (pModuleInstance->pIcon == NULL || (pModuleInstance->pDock && !pModuleInstance->pIcon->cParentDockName))
430
 
                {
431
 
                        // on ajoute une ligne pour l'applet.
432
 
                        _add_one_module (cModuleName, pModuleInstance, model);
433
 
                }
434
 
        }
435
 
        return FALSE; // FALSE => keep going
436
 
}
437
 
 
438
 
static void _select_item (Icon *pIcon, CairoContainer *pContainer, CairoDockModuleInstance *pModuleInstance, GtkWidget *pLauncherWindow)
439
 
{
440
 
        g_free (cPrevPath);
441
 
        cPrevPath = NULL;
442
 
        GtkTreeIter iter;
443
 
        if (_search_item_in_model (s_pLauncherTreeView, pIcon ? (gpointer)pIcon : pContainer ? (gpointer)pContainer : (gpointer)pModuleInstance, pIcon ? CD_MODEL_ICON : pContainer ? CD_MODEL_CONTAINER : CD_MODEL_MODULE, &iter))
444
 
        {
445
 
                GtkTreeModel * model = gtk_tree_view_get_model (GTK_TREE_VIEW (s_pLauncherTreeView));
446
 
                GtkTreePath *path =  gtk_tree_model_get_path (model, &iter);
447
 
                gtk_tree_view_expand_to_path (GTK_TREE_VIEW (s_pLauncherTreeView), path);
448
 
                gtk_tree_path_free (path);
449
 
                
450
 
                GtkTreeSelection *pSelection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s_pLauncherTreeView));
451
 
                gtk_tree_selection_unselect_all (pSelection);
452
 
                gtk_tree_selection_select_iter (pSelection, &iter);
453
 
        }
454
 
        else
455
 
        {
456
 
                cd_warning ("item not found");
457
 
                _delete_current_launcher_widget (pLauncherWindow);
458
 
                
459
 
                gtk_window_set_title (GTK_WINDOW (pLauncherWindow), _("Launcher configuration"));
460
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "current-icon", NULL);
461
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "current-container", NULL);
462
 
                g_object_set_data (G_OBJECT (pLauncherWindow), "current-module", NULL);
463
 
        }
464
 
}
465
 
 
466
 
static GtkTreeModel *_build_tree_model (void)
467
 
{
468
 
        GtkTreeStore *model = gtk_tree_store_new (CD_MODEL_NB_COLUMNS,
469
 
                G_TYPE_STRING,  // displayed name
470
 
                GDK_TYPE_PIXBUF,  // displayed icon
471
 
                G_TYPE_POINTER,  // Icon
472
 
                G_TYPE_POINTER,  // Container
473
 
                G_TYPE_POINTER);  // Module
474
 
        cairo_dock_foreach_docks ((GHFunc) _add_one_root_dock_to_model, model);  // on n'utilise pas cairo_dock_foreach_root_docks(), de facon a avoir le nom du dock.
475
 
        cairo_dock_foreach_desklet ((CairoDockForeachDeskletFunc) _add_one_desklet_to_model, model);
476
 
        cairo_dock_foreach_module ((GHRFunc)_add_one_module_to_model, model);
477
 
        CairoDockModule *pModule = cairo_dock_find_module_from_name ("Help");
478
 
        if (pModule != NULL)
479
 
        {
480
 
                if (pModule->pInstancesList == NULL)  // Help is not active, so is not already in the icons list.
481
 
                {
482
 
                        ///CairoDockModuleInstance *pModuleInstance = pModule->pInstancesList->data;
483
 
                        ///_add_one_module ("Help", pModuleInstance, model);
484
 
                        /// add it ...
485
 
                }
486
 
        }
487
 
        g_signal_connect (G_OBJECT (model), "row-inserted", G_CALLBACK (on_row_inserted), NULL);
488
 
        g_signal_connect (G_OBJECT (model), "row-deleted", G_CALLBACK (on_row_deleted), NULL);
489
 
        return GTK_TREE_MODEL (model);
490
 
}
491
 
 
492
 
 
493
 
  //////////////////
494
 
 // USER ACTIONS //
495
 
//////////////////
496
 
 
497
 
static GtkTreeIter lastInsertedIter;
498
 
static gboolean s_bHasPendingInsertion = FALSE;
499
 
static struct timeval lastTime = {0, 0};
500
 
 
501
 
static void on_row_inserted (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
502
 
{
503
 
        // we only receive this event from an intern drag'n'drop
504
 
        // when we receive this event, the row is still empty, so we can't perform any task here.
505
 
        // so we just remember the event, and treat it later (when we receive the "row-deleted" signal).
506
 
        memcpy (&lastInsertedIter, iter, sizeof (GtkTreeIter));
507
 
        gettimeofday (&lastTime, NULL);
508
 
        s_bHasPendingInsertion = TRUE;
509
 
}
510
 
static void on_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data)
511
 
{
512
 
        // g_print ("- row\n");
513
 
        // when drag'n'droping a row, the "row-deleted" signal is emitted after the "row-inserted"
514
 
        // however the row pointed by 'path' is already invalid, but the previously inserted iter is now filled, and we remembered it, so we can use it now.
515
 
        if (s_bHasPendingInsertion)
516
 
        {
517
 
                struct timeval current_time;
518
 
                gettimeofday (&current_time, NULL);
519
 
                if ((current_time.tv_sec + current_time.tv_usec / 1.e6) - (lastTime.tv_sec + lastTime.tv_usec / 1.e6) < .3)  // just to be sure we don't get a "row-deleted" that has no link with a drag'n'drop (it's a rough precaution, I've never seen this case happen).
520
 
                {
521
 
                        // get the item that has been moved.
522
 
                        gchar *cName = NULL;
523
 
                        Icon *pIcon = NULL;
524
 
                        CairoContainer *pContainer = NULL;
525
 
                        CairoDockModuleInstance *pInstance = NULL;
526
 
                        gtk_tree_model_get (model, &lastInsertedIter,
527
 
                                CD_MODEL_NAME, &cName,
528
 
                                CD_MODEL_ICON, &pIcon,
529
 
                                CD_MODEL_CONTAINER, &pContainer,
530
 
                                CD_MODEL_MODULE, &pInstance, -1);
531
 
                        // g_print ("+ row %s\n", cName);
532
 
                        
533
 
                        if (pIcon)  // launcher/separator/sub-dock-icon or applet
534
 
                        {
535
 
                                // get the icon and container.
536
 
                                /**if (pIcon == NULL)
537
 
                                        pIcon = pInstance->pIcon;*/
538
 
                                if (pContainer == NULL)
539
 
                                {
540
 
                                        if (pInstance != NULL)
541
 
                                                pContainer = pInstance->pContainer;
542
 
                                        else if (pIcon != NULL)
543
 
                                        {
544
 
                                                pContainer = CAIRO_CONTAINER (cairo_dock_search_dock_from_name (pIcon->cParentDockName));
545
 
                                        }
546
 
                                }
547
 
                                
548
 
                                // get the new parent in the tree, hence the possibly new container
549
 
                                GtkTreeIter parent_iter;
550
 
                                if (CAIRO_DOCK_IS_DOCK (pContainer)  // with this, we prevent from moving desklets; we may add this possibility it later.
551
 
                                && gtk_tree_model_iter_parent (model, &parent_iter, &lastInsertedIter))
552
 
                                {
553
 
                                        gchar *cParentName = NULL;
554
 
                                        Icon *pParentIcon = NULL;
555
 
                                        CairoContainer *pParentContainer = NULL;
556
 
                                        gtk_tree_model_get (model, &parent_iter,
557
 
                                                CD_MODEL_NAME, &cParentName,
558
 
                                                CD_MODEL_ICON, &pParentIcon,
559
 
                                                CD_MODEL_CONTAINER, &pParentContainer, -1);
560
 
                                        // g_print (" parent: %s, %p, %p\n", cParentName, pParentIcon, pParentContainer);
561
 
                                        
562
 
                                        if (pParentContainer == NULL && pParentIcon != NULL)  // dropped on an icon, if it's a sub-dock icon, insert into the sub-dock, else do as if we dropped next to the icon.
563
 
                                        {
564
 
                                                if (CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pParentIcon))  // put our item in the sub-dock
565
 
                                                {
566
 
                                                        pParentContainer = CAIRO_CONTAINER (pParentIcon->pSubDock);
567
 
                                                }
568
 
                                                else  // not an icon that can contain our item, so place it next to it.
569
 
                                                {
570
 
                                                        pParentContainer = CAIRO_CONTAINER (cairo_dock_search_dock_from_name (pParentIcon->cParentDockName));
571
 
                                                        // we'll search the parent instead.
572
 
                                                        lastInsertedIter = parent_iter;
573
 
                                                        gtk_tree_model_iter_parent (model, &parent_iter, &lastInsertedIter);
574
 
                                                        // g_print (" search parent %s\n", pParentIcon->cParentDockName);
575
 
                                                }
576
 
                                        }
577
 
                                        if (CAIRO_DOCK_IS_DOCK (pParentContainer))  // not nul and dock-type.
578
 
                                        {
579
 
                                                // if it has changed, update the conf file and the icon.
580
 
                                                if (pParentContainer != pContainer)
581
 
                                                {
582
 
                                                        // g_print (" parent has changed\n");
583
 
                                                        const gchar *cNewParentDockName = cairo_dock_search_dock_name (CAIRO_DOCK (pParentContainer));
584
 
                                                        if (cNewParentDockName != NULL)
585
 
                                                        {
586
 
                                                                cairo_dock_write_container_name_in_conf_file (pIcon, cNewParentDockName);
587
 
                                                        }
588
 
                                                        
589
 
                                                        // g_print (" reload the icon...\n");
590
 
                                                        if ((CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
591
 
                                                                || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon)
592
 
                                                                || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
593
 
                                                        && pIcon->cDesktopFileName != NULL)  // user icon.
594
 
                                                        {
595
 
                                                                cairo_dock_reload_launcher (pIcon);
596
 
                                                        }
597
 
                                                        else if (CAIRO_DOCK_IS_APPLET (pIcon))
598
 
                                                        {
599
 
                                                                cairo_dock_reload_module_instance (pIcon->pModuleInstance, TRUE);  // TRUE <=> reload config.
600
 
                                                        }
601
 
                                                }
602
 
                                                
603
 
                                                // find the new order of the row in the tree
604
 
                                                double fOrder = 0;
605
 
                                                GtkTreeIter it;
606
 
                                                Icon *pLeftIcon = NULL;
607
 
                                                gchar *last_iter_s = gtk_tree_model_get_string_from_iter (model, &lastInsertedIter);
608
 
                                                // g_print ("search for '%s'\n", last_iter_s);
609
 
                                                
610
 
                                                ///gtk_tree_model_get_iter_first (model, &iter);
611
 
                                                if (gtk_tree_model_iter_children (model, &it, &parent_iter))  // point on the first iter.
612
 
                                                {
613
 
                                                        // g_print (" got first iter\n");
614
 
                                                        // iterate on the rows until we reach our row.
615
 
                                                        do
616
 
                                                        {
617
 
                                                                gchar *iter_s = gtk_tree_model_get_string_from_iter (model, &it);
618
 
                                                                // g_print (" test iter %s / %s\n", iter_s, last_iter_s);
619
 
                                                                if (strcmp (last_iter_s, iter_s) == 0)  // it's our row
620
 
                                                                {
621
 
                                                                        //g_print (" reached our row, break\n");
622
 
                                                                        break;
623
 
                                                                }
624
 
                                                                else  // not yet our row, let's remember the left icon.
625
 
                                                                {
626
 
                                                                        gchar *name=NULL;
627
 
                                                                        gtk_tree_model_get (model, &it,
628
 
                                                                                CD_MODEL_NAME, &name,
629
 
                                                                                CD_MODEL_ICON, &pLeftIcon, -1);
630
 
                                                                        // g_print ("  (%s)\n", name);
631
 
                                                                }
632
 
                                                        }
633
 
                                                        while (gtk_tree_model_iter_next (model, &it));
634
 
                                                }
635
 
                                                
636
 
                                                // move the icon (will update the conf file and trigger the signal to reload the GUI).
637
 
                                                // g_print (" move the icon...\n");
638
 
                                                cairo_dock_move_icon_after_icon (CAIRO_DOCK (pParentContainer), pIcon, pLeftIcon);
639
 
                                        }
640
 
                                        else  // the row may have been dropped on a launcher or a desklet, in which case we must reload the model because this has no meaning.
641
 
                                        {
642
 
                                                reload_items ();
643
 
                                        }
644
 
                                        
645
 
                                }  // else this row has no parent, so it was either a main dock or a desklet, and we have nothing to do.
646
 
                                else
647
 
                                {
648
 
                                        reload_items ();
649
 
                                }
650
 
                        }
651
 
                        else  // no icon (for instance a plug-in like Remote-control)
652
 
                        {
653
 
                                reload_items ();
654
 
                        }
655
 
                }
656
 
                
657
 
                s_bHasPendingInsertion = FALSE;
658
 
        }
659
 
}
660
 
 
661
 
static void _cairo_dock_remove_item (GtkMenuItem *pMenuItem, GtkWidget *pTreeView)
662
 
{
663
 
        // get the selected line
664
 
        GtkTreeSelection *pSelection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pTreeView));
665
 
        GtkTreeModel *pModel = NULL;
666
 
        GList *paths = gtk_tree_selection_get_selected_rows (pSelection, &pModel);
667
 
        g_return_if_fail (paths != NULL && pModel != NULL);
668
 
        GtkTreePath *path = paths->data;
669
 
        
670
 
        GtkTreeIter iter;
671
 
        if (! gtk_tree_model_get_iter (pModel, &iter, path))
672
 
                return;
673
 
        
674
 
        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
675
 
        g_list_free (paths);
676
 
        
677
 
        // get the corresponding item, and the next line.
678
 
        Icon *pIcon = NULL;
679
 
        CairoContainer *pContainer = NULL;
680
 
        CairoDockModuleInstance *pInstance = NULL;
681
 
        gtk_tree_model_get (pModel, &iter,
682
 
                CD_MODEL_ICON, &pIcon,
683
 
                CD_MODEL_CONTAINER, &pContainer,
684
 
                CD_MODEL_MODULE, &pInstance, -1);
685
 
        
686
 
        if (!gtk_tree_model_iter_next (pModel, &iter))
687
 
                gtk_tree_model_get_iter_first (pModel, &iter);
688
 
        
689
 
        // remove it.
690
 
        if (CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
691
 
                || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon)
692
 
                || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))  // launcher/separator/sub-dock
693
 
        {
694
 
                cairo_dock_trigger_icon_removal_from_dock (pIcon);
695
 
        }
696
 
        else if (CAIRO_DOCK_IS_APPLET (pIcon))  // applet
697
 
        {
698
 
                cairo_dock_trigger_icon_removal_from_dock (pIcon);
699
 
        }
700
 
        else if (pInstance != NULL)  // plug-in
701
 
        {
702
 
                cairo_dock_remove_module_instance (pInstance);
703
 
        }
704
 
        else if (CAIRO_DOCK_IS_DOCK (pContainer))  // main-dock
705
 
        {
706
 
                CairoDock *pDock = CAIRO_DOCK (pContainer);
707
 
                if (! pDock->bIsMainDock)
708
 
                {
709
 
                        cairo_dock_remove_icons_from_dock (pDock, NULL, NULL);
710
 
                
711
 
                        const gchar *cDockName = cairo_dock_search_dock_name (pDock);
712
 
                        cairo_dock_destroy_dock (pDock, cDockName);
713
 
                }
714
 
        }
715
 
        
716
 
        // select the next item to avoid having no selection
717
 
        gtk_tree_selection_unselect_all (pSelection);
718
 
        gtk_tree_selection_select_iter (pSelection, &iter);
719
 
}
720
 
 
721
 
 
722
 
static void _free_launcher_gui (void)
723
 
{
724
 
        s_pLauncherWindow = NULL;
725
 
        s_pCurrentLauncherWidget = NULL;
726
 
        s_pLauncherPane = NULL;
727
 
        s_pLauncherTreeView = NULL;
728
 
}
729
 
static gboolean on_delete_launcher_gui (GtkWidget *pWidget, GdkEvent *event, gpointer data)
730
 
{
731
 
        GSList *pWidgetList = g_object_get_data (G_OBJECT (pWidget), "widget-list");
732
 
        cairo_dock_free_generated_widget_list (pWidgetList);
733
 
        
734
 
        GPtrArray *pDataGarbage = g_object_get_data (G_OBJECT (pWidget), "garbage");
735
 
        /// nettoyer.
736
 
        
737
 
        _free_launcher_gui ();
738
 
        
739
 
        return FALSE;
740
 
}
741
 
 
742
 
static void on_click_launcher_apply (GtkButton *button, GtkWidget *pWindow)
743
 
{
744
 
        //g_print ("%s ()\n", __func__);
745
 
        
746
 
        Icon *pIcon = g_object_get_data (G_OBJECT (pWindow), "current-icon");
747
 
        CairoContainer *pContainer = g_object_get_data (G_OBJECT (pWindow), "current-container");
748
 
        CairoDockModuleInstance *pModuleInstance = g_object_get_data (G_OBJECT (pWindow), "current-module");
749
 
        
750
 
        if (CAIRO_DOCK_IS_APPLET (pIcon))
751
 
                pModuleInstance = pIcon->pModuleInstance;
752
 
        
753
 
        GSList *pWidgetList = g_object_get_data (G_OBJECT (pWindow), "widget-list");
754
 
        
755
 
        if (pModuleInstance)
756
 
        {
757
 
                // open the conf file.
758
 
                GKeyFile *pKeyFile = cairo_dock_open_key_file (pModuleInstance->cConfFilePath);
759
 
                g_return_if_fail (pKeyFile != NULL);
760
 
                
761
 
                // update the keys with the widgets.
762
 
                cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
763
 
                
764
 
                // if the parent dock doesn't exist (new dock), add a conf file for it with a nominal name.
765
 
                if (g_key_file_has_key (pKeyFile, "Icon", "dock name", NULL))
766
 
                {
767
 
                        gchar *cDockName = g_key_file_get_string (pKeyFile, "Icon", "dock name", NULL);
768
 
                        gboolean bIsDetached = g_key_file_get_boolean (pKeyFile, "Desklet", "initially detached", NULL);
769
 
                        if (!bIsDetached)
770
 
                        {
771
 
                                CairoDock *pDock = cairo_dock_search_dock_from_name (cDockName);
772
 
                                if (pDock == NULL)
773
 
                                {
774
 
                                        gchar *cNewDockName = cairo_dock_add_root_dock_config ();
775
 
                                        g_key_file_set_string (pKeyFile, "Icon", "dock name", cNewDockName);
776
 
                                        g_free (cNewDockName);
777
 
                                }
778
 
                        }
779
 
                        g_free (cDockName);
780
 
                }
781
 
                
782
 
                if (pModuleInstance->pModule->pInterface->save_custom_widget != NULL)
783
 
                        pModuleInstance->pModule->pInterface->save_custom_widget (pModuleInstance, pKeyFile);
784
 
                
785
 
                // write everything in the conf file.
786
 
                cairo_dock_write_keys_to_file (pKeyFile, pModuleInstance->cConfFilePath);
787
 
                g_key_file_free (pKeyFile);
788
 
                
789
 
                // reload module.
790
 
                cairo_dock_reload_module_instance (pModuleInstance, TRUE);
791
 
        }
792
 
        else if (CAIRO_DOCK_IS_DOCK (pContainer))
793
 
        {
794
 
                CairoDock *pDock = CAIRO_DOCK (pContainer);
795
 
                if (!pDock->bIsMainDock)  // pour l'instant le main dock n'a pas de fichier de conf
796
 
                {
797
 
                        const gchar *cDockName = cairo_dock_search_dock_name (pDock);  // CD_MODEL_NAME contient le nom affiche, qui peut differer.
798
 
                        g_return_if_fail (cDockName != NULL);
799
 
                        
800
 
                        gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName);
801
 
                        
802
 
                        // open the conf file.
803
 
                        GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
804
 
                        g_return_if_fail (pKeyFile != NULL);
805
 
                        
806
 
                        // update the keys with the widgets.
807
 
                        cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
808
 
                        
809
 
                        // write everything in the conf file.
810
 
                        cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
811
 
                        g_key_file_free (pKeyFile);
812
 
                        g_free (cConfFilePath);
813
 
                        
814
 
                        // reload dock's config.
815
 
                        cairo_dock_reload_one_root_dock (cDockName, pDock);
816
 
                }
817
 
        }
818
 
        else if (pIcon)
819
 
        {
820
 
                gchar *cConfFilePath = (*pIcon->cDesktopFileName == '/' ? g_strdup (pIcon->cDesktopFileName) : g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, pIcon->cDesktopFileName));
821
 
                
822
 
                // open the conf file.
823
 
                GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
824
 
                g_return_if_fail (pKeyFile != NULL);
825
 
                
826
 
                // update the keys with the widgets.
827
 
                cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
828
 
                
829
 
                // if the parent dock doesn't exist (new dock), add a conf file for it with a nominal name.
830
 
                if (g_key_file_has_key (pKeyFile, "Desktop Entry", "Container", NULL))
831
 
                {
832
 
                        gchar *cDockName = g_key_file_get_string (pKeyFile, "Desktop Entry", "Container", NULL);
833
 
                        CairoDock *pDock = cairo_dock_search_dock_from_name (cDockName);
834
 
                        if (pDock == NULL)
835
 
                        {
836
 
                                gchar *cNewDockName = cairo_dock_add_root_dock_config ();
837
 
                                g_key_file_set_string (pKeyFile, "Icon", "dock name", cNewDockName);
838
 
                                g_free (cNewDockName);
839
 
                        }
840
 
                        g_free (cDockName);
841
 
                }
842
 
                
843
 
                // write everything in the conf file.
844
 
                cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
845
 
                g_key_file_free (pKeyFile);
846
 
                g_free (cConfFilePath);
847
 
                
848
 
                // reload widgets.
849
 
                cairo_dock_reload_launcher (pIcon);  // prend tout en compte, y compris le redessin et declenche le rechargement de l'IHM.
850
 
        }
851
 
        reload_items ();
852
 
}
853
 
 
854
 
static void on_click_launcher_quit (GtkButton *button, GtkWidget *pWindow)
855
 
{
856
 
        //g_print ("%s ()\n", __func__);
857
 
        on_delete_launcher_gui (pWindow, NULL, NULL);
858
 
        gtk_widget_destroy (pWindow);
859
 
}
860
 
 
861
 
 
862
 
  /////////////////
863
 
 // GUI BACKEND //
864
 
/////////////////
865
 
 
866
 
static gboolean on_button_press_event (GtkWidget *pWidget,
867
 
        GdkEventButton *pButton,
868
 
        gpointer data)
869
 
{
870
 
        if (pButton->button == 3)  // clic droit.
871
 
        {
872
 
                GtkWidget *pMenu = gtk_menu_new ();
873
 
                        
874
 
                GtkWidget *pMenuItem;
875
 
                
876
 
                /// TODO: check that we can actually remove it (ex.: not the main dock), and maybe display the item's name...
877
 
                pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Remove this item"), GTK_STOCK_REMOVE, G_CALLBACK (_cairo_dock_remove_item), pMenu, pWidget);
878
 
                
879
 
                gtk_widget_show_all (pMenu);
880
 
                
881
 
                gtk_menu_popup (GTK_MENU (pMenu),
882
 
                        NULL,
883
 
                        NULL,
884
 
                        NULL,
885
 
                        NULL,
886
 
                        pButton->button,
887
 
                        gtk_get_current_event_time ());
888
 
        }
889
 
        return FALSE;
890
 
}
891
 
static GtkWidget *show_gui (Icon *pIcon, CairoContainer *pContainer, CairoDockModuleInstance *pModuleInstance, int iShowPage)
892
 
{
893
 
        //g_print ("%s (%x)\n", __func__, pIcon);
894
 
        //\_____________ On recharge la fenetre si elle existe deja.
895
 
        if (s_pLauncherWindow != NULL)
896
 
        {
897
 
                _delete_current_launcher_widget (s_pLauncherWindow);
898
 
                
899
 
                _select_item (pIcon, pContainer, pModuleInstance, s_pLauncherWindow);
900
 
                
901
 
                gtk_window_present (GTK_WINDOW (s_pLauncherWindow));
902
 
                return s_pLauncherWindow;
903
 
        }
904
 
        
905
 
        //\_____________ On construit la fenetre.
906
 
        s_pLauncherWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
907
 
        gtk_window_set_icon_from_file (GTK_WINDOW (s_pLauncherWindow), CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON, NULL);
908
 
 
909
 
        GtkWidget *pMainVBox = _gtk_vbox_new (CAIRO_DOCK_FRAME_MARGIN);
910
 
        gtk_container_add (GTK_CONTAINER (s_pLauncherWindow), pMainVBox);
911
 
        
912
 
        #if (GTK_MAJOR_VERSION < 3)
913
 
        s_pLauncherPane = gtk_hpaned_new ();
914
 
        #else
915
 
        s_pLauncherPane = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
916
 
        #endif
917
 
        
918
 
        gtk_box_pack_start (GTK_BOX (pMainVBox),
919
 
                s_pLauncherPane,
920
 
                TRUE,
921
 
                TRUE,
922
 
                0);
923
 
        
924
 
        //\_____________ On construit l'arbre des launceurs.
925
 
        GtkTreeModel *model = _build_tree_model();
926
 
        
927
 
        //\_____________ On construit le tree-view avec.
928
 
        s_pLauncherTreeView = gtk_tree_view_new_with_model (model);
929
 
        g_object_unref (model);
930
 
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (s_pLauncherTreeView), FALSE);
931
 
        gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (s_pLauncherTreeView), TRUE);
932
 
        gtk_tree_view_set_reorderable (GTK_TREE_VIEW (s_pLauncherTreeView), TRUE);  // enables drag and drop of rows -> row-inserted and row-deleted signals
933
 
        g_signal_connect (G_OBJECT (s_pLauncherTreeView),
934
 
                "button-release-event",  // on release, so that the clicked line is already selected
935
 
                G_CALLBACK (on_button_press_event),
936
 
                NULL);
937
 
        
938
 
        // line selection
939
 
        GtkTreeSelection *pSelection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s_pLauncherTreeView));
940
 
        gtk_tree_selection_set_mode (pSelection, GTK_SELECTION_SINGLE);
941
 
        gtk_tree_selection_set_select_function (pSelection,
942
 
                (GtkTreeSelectionFunc) _on_select_one_item_in_tree,
943
 
                s_pLauncherWindow,
944
 
                NULL);
945
 
        
946
 
        GtkCellRenderer *rend;
947
 
        // column icon
948
 
        rend = gtk_cell_renderer_pixbuf_new ();
949
 
        gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (s_pLauncherTreeView), -1, NULL, rend, "pixbuf", 1, NULL);
950
 
        // column name
951
 
        rend = gtk_cell_renderer_text_new ();
952
 
        gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (s_pLauncherTreeView), -1, NULL, rend, "text", 0, NULL);
953
 
        
954
 
        GtkWidget *pLauncherWindow = gtk_scrolled_window_new (NULL, NULL);
955
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pLauncherWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
956
 
        gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (pLauncherWindow), s_pLauncherTreeView);
957
 
        gtk_paned_pack1 (GTK_PANED (s_pLauncherPane), pLauncherWindow, TRUE, FALSE);
958
 
        
959
 
        //\_____________ We add boutons.
960
 
        GtkWidget *pButtonsHBox = _gtk_hbox_new (CAIRO_DOCK_FRAME_MARGIN*2);
961
 
        gtk_box_pack_end (GTK_BOX (pMainVBox),
962
 
                pButtonsHBox,
963
 
                FALSE,
964
 
                FALSE,
965
 
                0);
966
 
        
967
 
        GtkWidget *pQuitButton = gtk_button_new_from_stock (GTK_STOCK_QUIT);
968
 
        g_signal_connect (G_OBJECT (pQuitButton), "clicked", G_CALLBACK(on_click_launcher_quit), s_pLauncherWindow);
969
 
        gtk_box_pack_end (GTK_BOX (pButtonsHBox),
970
 
                pQuitButton,
971
 
                FALSE,
972
 
                FALSE,
973
 
                0);
974
 
        
975
 
        GtkWidget *pApplyButton = gtk_button_new_from_stock (GTK_STOCK_APPLY);
976
 
        g_signal_connect (G_OBJECT (pApplyButton), "clicked", G_CALLBACK(on_click_launcher_apply), s_pLauncherWindow);
977
 
        gtk_box_pack_end (GTK_BOX (pButtonsHBox),
978
 
                pApplyButton,
979
 
                FALSE,
980
 
                FALSE,
981
 
                0);
982
 
        
983
 
        //\_____________ On ajoute la barre d'etat.
984
 
        GtkWidget *pStatusBar = gtk_statusbar_new ();
985
 
        gtk_box_pack_start (GTK_BOX (pButtonsHBox),  // pMainVBox
986
 
                pStatusBar,
987
 
                TRUE,
988
 
                TRUE,
989
 
                0);
990
 
        g_object_set_data (G_OBJECT (s_pLauncherWindow), "status-bar", pStatusBar);
991
 
        g_object_set_data (G_OBJECT (s_pLauncherWindow), "frame-width", GINT_TO_POINTER (250));
992
 
        
993
 
        //\_____________ On essaie de definir une taille correcte.
994
 
        int w = MIN (CAIRO_DOCK_LAUNCHER_PANEL_WIDTH, g_desktopGeometry.iXScreenWidth[CAIRO_DOCK_HORIZONTAL]);
995
 
        gtk_window_resize (GTK_WINDOW (s_pLauncherWindow),
996
 
                w,
997
 
                MIN (CAIRO_DOCK_LAUNCHER_PANEL_HEIGHT, g_desktopGeometry.iXScreenHeight[CAIRO_DOCK_HORIZONTAL] - (g_pMainDock && g_pMainDock->container.bIsHorizontal ? g_pMainDock->iMaxDockHeight : 0)));
998
 
        
999
 
        if (g_desktopGeometry.iXScreenWidth[CAIRO_DOCK_HORIZONTAL] < CAIRO_DOCK_LAUNCHER_PANEL_WIDTH)  // ecran trop petit, on va essayer de reserver au moins R pixels pour le panneau de droite (avec un minimum de L pixels pour celui de gauche).
1000
 
                gtk_paned_set_position (GTK_PANED (s_pLauncherPane), MAX (CAIRO_DOCK_LEFT_PANE_MIN_WIDTH, w - CAIRO_DOCK_RIGHT_PANE_MIN_WIDTH));
1001
 
        else  // we set a default width rather than letting GTK guess the best, because the right panel is more important than the left one.
1002
 
                gtk_paned_set_position (GTK_PANED (s_pLauncherPane), CAIRO_DOCK_LEFT_PANE_DEFAULT_WIDTH);
1003
 
        
1004
 
        gtk_widget_show_all (s_pLauncherWindow);
1005
 
        
1006
 
        g_signal_connect (G_OBJECT (s_pLauncherWindow),
1007
 
                "delete-event",
1008
 
                G_CALLBACK (on_delete_launcher_gui),
1009
 
                NULL);
1010
 
        
1011
 
        //\_____________ On selectionne l'entree courante.
1012
 
        _select_item (pIcon, pContainer, pModuleInstance, s_pLauncherWindow);
1013
 
        
1014
 
        return s_pLauncherWindow;
1015
 
}
1016
 
 
1017
 
static void reload_items (void)
1018
 
{
1019
 
        if (s_pLauncherWindow == NULL)
1020
 
                return ;
1021
 
        
1022
 
        cd_debug ("%s ()", __func__);
1023
 
        int iNotebookPage;
1024
 
        if (s_pCurrentLauncherWidget && GTK_IS_NOTEBOOK (s_pCurrentLauncherWidget))
1025
 
                iNotebookPage = gtk_notebook_get_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget));
1026
 
        else
1027
 
                iNotebookPage = -1;
1028
 
        
1029
 
        // reload the tree-view
1030
 
        GtkTreeModel *model = _build_tree_model();
1031
 
        
1032
 
        gtk_tree_view_set_model (GTK_TREE_VIEW (s_pLauncherTreeView), GTK_TREE_MODEL (model));
1033
 
        g_object_unref (model);
1034
 
        
1035
 
        // reload the current icon/container's widgets by reselecting the current line.
1036
 
        Icon *pCurrentIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1037
 
        CairoContainer *pCurrentContainer = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-container");
1038
 
        CairoDockModuleInstance *pCurrentModuleInstance = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-module");
1039
 
        
1040
 
        _delete_current_launcher_widget (s_pLauncherWindow);  // s_pCurrentLauncherWidget <- 0
1041
 
        
1042
 
        _select_item (pCurrentIcon, pCurrentContainer, pCurrentModuleInstance, s_pLauncherWindow);  // set s_pCurrentLauncherWidget
1043
 
        
1044
 
        if (s_pCurrentLauncherWidget && GTK_IS_NOTEBOOK (s_pCurrentLauncherWidget) && iNotebookPage != -1)
1045
 
                gtk_notebook_set_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget), iNotebookPage);
1046
 
        
1047
 
        gtk_widget_show_all (s_pLauncherWindow);
1048
 
}
1049
 
 
1050
 
void cairo_dock_register_default_items_gui_backend (void)
1051
 
{
1052
 
        CairoDockItemsGuiBackend *pBackend = g_new0 (CairoDockItemsGuiBackend, 1);
1053
 
        
1054
 
        pBackend->show_gui                      = show_gui;
1055
 
        pBackend->reload_items          = reload_items;
1056
 
        
1057
 
        cairo_dock_register_items_gui_backend (pBackend);
1058
 
}
1059
 
 
1060
 
 
1061
 
  ////////////////////
1062
 
 // ACTIONS ON GUI //
1063
 
////////////////////
1064
 
 
1065
 
CairoDockGroupKeyWidget *cairo_dock_gui_items_get_widget_from_name (CairoDockModuleInstance *pInstance, const gchar *cGroupName, const gchar *cKeyName)
1066
 
{
1067
 
        g_return_val_if_fail (s_pLauncherWindow != NULL, NULL);
1068
 
        cd_debug ("%s (%s, %s)", __func__, cGroupName, cKeyName);
1069
 
        return cairo_dock_gui_find_group_key_widget (s_pLauncherWindow, cGroupName, cKeyName);
1070
 
}
1071
 
 
1072
 
void cairo_dock_gui_items_update_desklet_params (CairoDesklet *pDesklet)
1073
 
{
1074
 
        if (s_pLauncherWindow == NULL || pDesklet == NULL || pDesklet->pIcon == NULL)
1075
 
                return;
1076
 
        
1077
 
        Icon *pIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1078
 
        if (pIcon != pDesklet->pIcon)
1079
 
                return;
1080
 
        
1081
 
        GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
1082
 
        cairo_dock_update_desklet_widgets (pDesklet, pWidgetList);
1083
 
}
1084
 
 
1085
 
void cairo_dock_update_desklet_visibility_params (CairoDesklet *pDesklet)
1086
 
{
1087
 
        if (s_pLauncherWindow == NULL || pDesklet == NULL || pDesklet->pIcon == NULL)
1088
 
                return;
1089
 
        
1090
 
        Icon *pIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1091
 
        if (pIcon != pDesklet->pIcon)
1092
 
                return;
1093
 
        
1094
 
        GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
1095
 
        cairo_dock_update_desklet_visibility_widgets (pDesklet, pWidgetList);
1096
 
}
1097
 
 
1098
 
void cairo_dock_gui_items_update_module_instance_container (CairoDockModuleInstance *pInstance, gboolean bDetached)
1099
 
{
1100
 
        if (s_pLauncherWindow == NULL || pInstance == NULL)
1101
 
                return;
1102
 
        
1103
 
        Icon *pIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1104
 
        if (pIcon != pInstance->pIcon)  // pour un module qui se detache, il suffit de chercher parmi les applets.
1105
 
                return;
1106
 
        
1107
 
        GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
1108
 
        cairo_dock_update_is_detached_widget (bDetached, pWidgetList);
1109
 
}
1110
 
 
1111
 
void cairo_dock_gui_items_reload_current_widget (CairoDockModuleInstance *pInstance, int iShowPage)
1112
 
{
1113
 
        g_return_if_fail (s_pLauncherWindow != NULL && s_pLauncherTreeView != NULL);
1114
 
        cd_debug ("%s ()", __func__);
1115
 
        
1116
 
        Icon *pIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1117
 
        CairoDockModuleInstance *pModuleInstance = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-module");
1118
 
        if (pInstance)
1119
 
        {
1120
 
                if (pIcon)
1121
 
                {
1122
 
                        if (pIcon->pModuleInstance != pInstance)
1123
 
                                return;
1124
 
                }
1125
 
                else if (pModuleInstance)
1126
 
                {
1127
 
                        if (pModuleInstance != pInstance)
1128
 
                                return;
1129
 
                }
1130
 
        }
1131
 
        
1132
 
        GtkTreeSelection *pSelection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s_pLauncherTreeView));
1133
 
        GtkTreeModel *pModel = NULL;
1134
 
        GList *paths = gtk_tree_selection_get_selected_rows (pSelection, &pModel);
1135
 
        g_return_if_fail (paths != NULL && pModel != NULL);
1136
 
        GtkTreePath *path = paths->data;
1137
 
        
1138
 
        int iNotebookPage;
1139
 
        if ((GTK_IS_NOTEBOOK (s_pCurrentLauncherWidget)))
1140
 
        {
1141
 
                if (iShowPage == -1)
1142
 
                        iNotebookPage = gtk_notebook_get_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget));
1143
 
                else
1144
 
                        iNotebookPage = iShowPage;
1145
 
        }
1146
 
        else
1147
 
                iNotebookPage = -1;
1148
 
        
1149
 
        g_free (cPrevPath);
1150
 
        cPrevPath = NULL;
1151
 
        _on_select_one_item_in_tree (pSelection, pModel, path, FALSE, s_pLauncherWindow);  // on appelle la callback nous-memes, car la ligne est deja selectionnee, donc le parametre 'path_currently_selected' sera a TRUE. de plus on veut pouvoir mettre la page du notebook.
1152
 
        
1153
 
        if (iNotebookPage != -1)
1154
 
        {
1155
 
                gtk_notebook_set_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget), iNotebookPage);
1156
 
        }
1157
 
        
1158
 
        g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
1159
 
        g_list_free (paths);
1160
 
}
1161
 
 
1162
 
void cairo_dock_gui_items_set_status_message_on_gui (const gchar *cMessage)
1163
 
{
1164
 
        GtkWidget *pStatusBar = NULL;
1165
 
        if (s_pLauncherWindow != NULL)
1166
 
        {
1167
 
                pStatusBar = g_object_get_data (G_OBJECT (s_pLauncherWindow), "status-bar");
1168
 
        }
1169
 
        if (pStatusBar == NULL)
1170
 
                return ;
1171
 
        cd_debug ("%s (%s)", __func__, cMessage);
1172
 
        gtk_statusbar_pop (GTK_STATUSBAR (pStatusBar), 0);  // clear any previous message, underflow is allowed.
1173
 
        gtk_statusbar_push (GTK_STATUSBAR (pStatusBar), 0, cMessage);
1174
 
}