2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
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.
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/>.
22
#define __USE_XOPEN_EXTENDED
25
#include <glib/gstdio.h>
26
#include <glib/gi18n.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"
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
53
extern gchar *g_cCurrentLaunchersPath;
54
extern gchar *g_cCurrentThemePath;
55
extern CairoDockDesktopGeometry g_desktopGeometry;
56
extern CairoDock *g_pMainDock;
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;
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);
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)
83
static gboolean _search_item_in_line (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer *data)
85
gpointer pItem = NULL;
86
gtk_tree_model_get (model, iter,
87
GPOINTER_TO_INT (data[1]), &pItem, -1);
90
//g_print (" found !\n");
91
memcpy (data[2], iter, sizeof (GtkTreeIter));
92
data[3] = GINT_TO_POINTER (TRUE);
93
return TRUE; // stop iterating.
97
static gboolean _search_item_in_model (GtkWidget *pTreeView, gpointer pItem, CDModelColumns iItemType, GtkTreeIter *iter)
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,
107
return GPOINTER_TO_INT (data[3]);
110
static void _delete_current_launcher_widget (GtkWidget *pLauncherWindow)
112
g_return_if_fail (pLauncherWindow != NULL);
114
if (s_pCurrentLauncherWidget != NULL)
116
gtk_widget_destroy (s_pCurrentLauncherWidget);
117
s_pCurrentLauncherWidget = NULL;
119
GSList *pWidgetList = g_object_get_data (G_OBJECT (pLauncherWindow), "widget-list");
120
if (pWidgetList != NULL)
122
cairo_dock_free_generated_widget_list (pWidgetList);
123
g_object_set_data (G_OBJECT (pLauncherWindow), "widget-list", NULL);
125
GPtrArray *pDataGarbage = g_object_get_data (G_OBJECT (pLauncherWindow), "garbage");
126
if (pDataGarbage != NULL)
128
cd_debug ("free garbage...");
129
g_ptr_array_free (pDataGarbage, TRUE);
130
g_object_set_data (G_OBJECT (pLauncherWindow), "garbage", NULL);
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);
138
static gboolean _on_select_one_item_in_tree (GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, GtkWidget *pLauncherWindow)
140
cd_debug ("%s (path_currently_selected:%d, %s)", __func__, path_currently_selected, gtk_tree_path_to_string(path));
141
if (path_currently_selected)
145
if (! gtk_tree_model_get_iter (model, &iter, path))
147
gchar *cPath = gtk_tree_path_to_string (path);
148
if (cPath && cPrevPath && strcmp (cPrevPath, cPath) == 0)
156
cd_debug ("load widgets");
157
// delete previous widgets
158
_delete_current_launcher_widget (pLauncherWindow); // remove all gobject data
160
// get new current item
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);
175
GSList *pWidgetList = NULL;
176
GPtrArray *pDataGarbage = NULL;
179
if (pInstance != NULL)
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);
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,
193
cOriginalConfFilePath); // don't free 'cOriginalConfFilePath', it is taken by the function. TODO: find a better way...
195
// load custom widgets
196
if (pInstance->pModule->pInterface->load_custom_widget != NULL)
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);
204
g_object_set_data (G_OBJECT (pLauncherWindow), "current-icon", pIcon);
206
g_object_set_data (G_OBJECT (pLauncherWindow), "current-module", pInstance);
208
g_key_file_free (pKeyFile);
210
else if (CAIRO_DOCK_IS_DOCK (pContainer)) // ligne correspondante a un dock principal
212
CairoDock *pDock = CAIRO_DOCK (pContainer);
213
if (!pDock->bIsMainDock) // pour l'instant le main dock n'a pas de fichier de conf
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);
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.
223
cairo_dock_add_root_dock_config_for_name (cDockName);
226
pDataGarbage = g_ptr_array_new ();
227
s_pCurrentLauncherWidget = cairo_dock_build_conf_file_widget (cConfFilePath,
234
g_object_set_data (G_OBJECT (pLauncherWindow), "current-container", pDock);
236
g_free (cConfFilePath);
238
else // main dock, we display a message
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
247
CAIRO_DOCK_SHARE_DATA_DIR"/images/"CAIRO_DOCK_LOGO,
249
g_free (cDefaultMessage);
252
else if (pIcon && pIcon->cDesktopFileName != NULL)
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));
257
// build launcher's widgets
258
pDataGarbage = g_ptr_array_new ();
259
s_pCurrentLauncherWidget = cairo_dock_build_conf_file_widget (cConfFilePath,
266
g_object_set_data (G_OBJECT (pLauncherWindow), "current-icon", pIcon);
268
g_free (cConfFilePath);
271
// set widgets in the main window.
272
if (s_pCurrentLauncherWidget != NULL)
274
gtk_paned_pack2 (GTK_PANED (s_pLauncherPane), s_pCurrentLauncherWidget, TRUE, FALSE);
276
g_object_set_data (G_OBJECT (pLauncherWindow), "widget-list", pWidgetList);
277
g_object_set_data (G_OBJECT (pLauncherWindow), "garbage", pDataGarbage);
279
gtk_widget_show_all (s_pCurrentLauncherWidget);
284
static void _add_one_icon_to_model (Icon *pIcon, GtkTreeStore *model, GtkTreeIter *pParentIter)
286
if (!pIcon->cDesktopFileName && ! CAIRO_DOCK_IS_APPLET (pIcon))
289
if (cairo_dock_icon_is_being_removed (pIcon))
293
GError *erreur = NULL;
294
GdkPixbuf *pixbuf = NULL;
295
gchar *cImagePath = NULL;
297
gint iDesiredIconSize = cairo_dock_search_icon_size (GTK_ICON_SIZE_DND); // default is 32
300
if (pIcon->cFileName != NULL)
302
cImagePath = cairo_dock_search_icon_s_path (pIcon->cFileName, iDesiredIconSize);
304
if (cImagePath == NULL || ! g_file_test (cImagePath, G_FILE_TEST_EXISTS))
307
if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
309
if (myIconsParam.cSeparatorImage)
310
cImagePath = cairo_dock_search_image_s_path (myIconsParam.cSeparatorImage);
312
else if (CAIRO_DOCK_IS_APPLET (pIcon))
314
cImagePath = g_strdup (pIcon->pModuleInstance->pModule->pVisitCard->cIconFilePath);
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))
322
cImagePath = g_strdup (CAIRO_DOCK_SHARE_DATA_DIR"/icons/"CAIRO_DOCK_DEFAULT_ICON_NAME);
327
if (cImagePath != NULL)
329
pixbuf = gdk_pixbuf_new_from_file_at_size (cImagePath, iDesiredIconSize, iDesiredIconSize, &erreur);
332
cd_warning (erreur->message);
333
g_error_free (erreur);
339
if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon)) // separator
341
else if (CAIRO_DOCK_IS_APPLET (pIcon)) // applet
342
cName = pIcon->pModuleInstance->pModule->pVisitCard->cTitle;
344
cName = (pIcon->cInitialName ? pIcon->cInitialName : pIcon->cName);
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,
354
// recursively add the sub-icons.
355
if (CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon) && pIcon->pSubDock != NULL)
357
_add_one_dock_to_model (pIcon->pSubDock, model, &iter);
363
g_object_unref (pixbuf);
365
static void _add_one_dock_to_model (CairoDock *pDock, GtkTreeStore *model, GtkTreeIter *pParentIter)
369
for (ic = pDock->icons; ic != NULL; ic = ic->next) // add each icons.
372
_add_one_icon_to_model (pIcon, model, pParentIter);
376
static void _add_one_root_dock_to_model (const gchar *cName, CairoDock *pDock, GtkTreeStore *model)
378
if (pDock->iRefCount != 0)
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,
391
// on ajoute chaque lanceur.
392
_add_one_dock_to_model (pDock, model, &iter);
395
static gboolean _add_one_desklet_to_model (CairoDesklet *pDesklet, GtkTreeStore *model)
397
if (pDesklet->pIcon == NULL)
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.
403
return FALSE; // FALSE => keep going
406
static inline void _add_one_module (const gchar *cModuleName, CairoDockModuleInstance *pModuleInstance, GtkTreeStore *model)
409
gtk_tree_store_append (model, &iter, NULL);
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,
422
g_object_unref (pixbuf);
424
static gboolean _add_one_module_to_model (const gchar *cModuleName, CairoDockModule *pModule, GtkTreeStore *model)
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)
428
CairoDockModuleInstance *pModuleInstance = pModule->pInstancesList->data;
429
if (pModuleInstance->pIcon == NULL || (pModuleInstance->pDock && !pModuleInstance->pIcon->cParentDockName))
431
// on ajoute une ligne pour l'applet.
432
_add_one_module (cModuleName, pModuleInstance, model);
435
return FALSE; // FALSE => keep going
438
static void _select_item (Icon *pIcon, CairoContainer *pContainer, CairoDockModuleInstance *pModuleInstance, GtkWidget *pLauncherWindow)
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))
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);
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);
456
cd_warning ("item not found");
457
_delete_current_launcher_widget (pLauncherWindow);
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);
466
static GtkTreeModel *_build_tree_model (void)
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");
480
if (pModule->pInstancesList == NULL) // Help is not active, so is not already in the icons list.
482
///CairoDockModuleInstance *pModuleInstance = pModule->pInstancesList->data;
483
///_add_one_module ("Help", pModuleInstance, model);
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);
497
static GtkTreeIter lastInsertedIter;
498
static gboolean s_bHasPendingInsertion = FALSE;
499
static struct timeval lastTime = {0, 0};
501
static void on_row_inserted (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
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;
510
static void on_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data)
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)
517
struct timeval current_time;
518
gettimeofday (¤t_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).
521
// get the item that has been moved.
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);
533
if (pIcon) // launcher/separator/sub-dock-icon or applet
535
// get the icon and container.
536
/**if (pIcon == NULL)
537
pIcon = pInstance->pIcon;*/
538
if (pContainer == NULL)
540
if (pInstance != NULL)
541
pContainer = pInstance->pContainer;
542
else if (pIcon != NULL)
544
pContainer = CAIRO_CONTAINER (cairo_dock_search_dock_from_name (pIcon->cParentDockName));
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))
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);
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.
564
if (CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pParentIcon)) // put our item in the sub-dock
566
pParentContainer = CAIRO_CONTAINER (pParentIcon->pSubDock);
568
else // not an icon that can contain our item, so place it next to it.
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);
577
if (CAIRO_DOCK_IS_DOCK (pParentContainer)) // not nul and dock-type.
579
// if it has changed, update the conf file and the icon.
580
if (pParentContainer != pContainer)
582
// g_print (" parent has changed\n");
583
const gchar *cNewParentDockName = cairo_dock_search_dock_name (CAIRO_DOCK (pParentContainer));
584
if (cNewParentDockName != NULL)
586
cairo_dock_write_container_name_in_conf_file (pIcon, cNewParentDockName);
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.
595
cairo_dock_reload_launcher (pIcon);
597
else if (CAIRO_DOCK_IS_APPLET (pIcon))
599
cairo_dock_reload_module_instance (pIcon->pModuleInstance, TRUE); // TRUE <=> reload config.
603
// find the new order of the row in the tree
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);
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.
613
// g_print (" got first iter\n");
614
// iterate on the rows until we reach our row.
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
621
//g_print (" reached our row, break\n");
624
else // not yet our row, let's remember the left icon.
627
gtk_tree_model_get (model, &it,
628
CD_MODEL_NAME, &name,
629
CD_MODEL_ICON, &pLeftIcon, -1);
630
// g_print (" (%s)\n", name);
633
while (gtk_tree_model_iter_next (model, &it));
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);
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.
645
} // else this row has no parent, so it was either a main dock or a desklet, and we have nothing to do.
651
else // no icon (for instance a plug-in like Remote-control)
657
s_bHasPendingInsertion = FALSE;
661
static void _cairo_dock_remove_item (GtkMenuItem *pMenuItem, GtkWidget *pTreeView)
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;
671
if (! gtk_tree_model_get_iter (pModel, &iter, path))
674
g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
677
// get the corresponding item, and the next line.
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);
686
if (!gtk_tree_model_iter_next (pModel, &iter))
687
gtk_tree_model_get_iter_first (pModel, &iter);
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
694
cairo_dock_trigger_icon_removal_from_dock (pIcon);
696
else if (CAIRO_DOCK_IS_APPLET (pIcon)) // applet
698
cairo_dock_trigger_icon_removal_from_dock (pIcon);
700
else if (pInstance != NULL) // plug-in
702
cairo_dock_remove_module_instance (pInstance);
704
else if (CAIRO_DOCK_IS_DOCK (pContainer)) // main-dock
706
CairoDock *pDock = CAIRO_DOCK (pContainer);
707
if (! pDock->bIsMainDock)
709
cairo_dock_remove_icons_from_dock (pDock, NULL, NULL);
711
const gchar *cDockName = cairo_dock_search_dock_name (pDock);
712
cairo_dock_destroy_dock (pDock, cDockName);
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);
722
static void _free_launcher_gui (void)
724
s_pLauncherWindow = NULL;
725
s_pCurrentLauncherWidget = NULL;
726
s_pLauncherPane = NULL;
727
s_pLauncherTreeView = NULL;
729
static gboolean on_delete_launcher_gui (GtkWidget *pWidget, GdkEvent *event, gpointer data)
731
GSList *pWidgetList = g_object_get_data (G_OBJECT (pWidget), "widget-list");
732
cairo_dock_free_generated_widget_list (pWidgetList);
734
GPtrArray *pDataGarbage = g_object_get_data (G_OBJECT (pWidget), "garbage");
737
_free_launcher_gui ();
742
static void on_click_launcher_apply (GtkButton *button, GtkWidget *pWindow)
744
//g_print ("%s ()\n", __func__);
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");
750
if (CAIRO_DOCK_IS_APPLET (pIcon))
751
pModuleInstance = pIcon->pModuleInstance;
753
GSList *pWidgetList = g_object_get_data (G_OBJECT (pWindow), "widget-list");
757
// open the conf file.
758
GKeyFile *pKeyFile = cairo_dock_open_key_file (pModuleInstance->cConfFilePath);
759
g_return_if_fail (pKeyFile != NULL);
761
// update the keys with the widgets.
762
cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
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))
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);
771
CairoDock *pDock = cairo_dock_search_dock_from_name (cDockName);
774
gchar *cNewDockName = cairo_dock_add_root_dock_config ();
775
g_key_file_set_string (pKeyFile, "Icon", "dock name", cNewDockName);
776
g_free (cNewDockName);
782
if (pModuleInstance->pModule->pInterface->save_custom_widget != NULL)
783
pModuleInstance->pModule->pInterface->save_custom_widget (pModuleInstance, pKeyFile);
785
// write everything in the conf file.
786
cairo_dock_write_keys_to_file (pKeyFile, pModuleInstance->cConfFilePath);
787
g_key_file_free (pKeyFile);
790
cairo_dock_reload_module_instance (pModuleInstance, TRUE);
792
else if (CAIRO_DOCK_IS_DOCK (pContainer))
794
CairoDock *pDock = CAIRO_DOCK (pContainer);
795
if (!pDock->bIsMainDock) // pour l'instant le main dock n'a pas de fichier de conf
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);
800
gchar *cConfFilePath = g_strdup_printf ("%s/%s.conf", g_cCurrentThemePath, cDockName);
802
// open the conf file.
803
GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
804
g_return_if_fail (pKeyFile != NULL);
806
// update the keys with the widgets.
807
cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
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);
814
// reload dock's config.
815
cairo_dock_reload_one_root_dock (cDockName, pDock);
820
gchar *cConfFilePath = (*pIcon->cDesktopFileName == '/' ? g_strdup (pIcon->cDesktopFileName) : g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, pIcon->cDesktopFileName));
822
// open the conf file.
823
GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
824
g_return_if_fail (pKeyFile != NULL);
826
// update the keys with the widgets.
827
cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
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))
832
gchar *cDockName = g_key_file_get_string (pKeyFile, "Desktop Entry", "Container", NULL);
833
CairoDock *pDock = cairo_dock_search_dock_from_name (cDockName);
836
gchar *cNewDockName = cairo_dock_add_root_dock_config ();
837
g_key_file_set_string (pKeyFile, "Icon", "dock name", cNewDockName);
838
g_free (cNewDockName);
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);
849
cairo_dock_reload_launcher (pIcon); // prend tout en compte, y compris le redessin et declenche le rechargement de l'IHM.
854
static void on_click_launcher_quit (GtkButton *button, GtkWidget *pWindow)
856
//g_print ("%s ()\n", __func__);
857
on_delete_launcher_gui (pWindow, NULL, NULL);
858
gtk_widget_destroy (pWindow);
866
static gboolean on_button_press_event (GtkWidget *pWidget,
867
GdkEventButton *pButton,
870
if (pButton->button == 3) // clic droit.
872
GtkWidget *pMenu = gtk_menu_new ();
874
GtkWidget *pMenuItem;
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);
879
gtk_widget_show_all (pMenu);
881
gtk_menu_popup (GTK_MENU (pMenu),
887
gtk_get_current_event_time ());
891
static GtkWidget *show_gui (Icon *pIcon, CairoContainer *pContainer, CairoDockModuleInstance *pModuleInstance, int iShowPage)
893
//g_print ("%s (%x)\n", __func__, pIcon);
894
//\_____________ On recharge la fenetre si elle existe deja.
895
if (s_pLauncherWindow != NULL)
897
_delete_current_launcher_widget (s_pLauncherWindow);
899
_select_item (pIcon, pContainer, pModuleInstance, s_pLauncherWindow);
901
gtk_window_present (GTK_WINDOW (s_pLauncherWindow));
902
return s_pLauncherWindow;
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);
909
GtkWidget *pMainVBox = _gtk_vbox_new (CAIRO_DOCK_FRAME_MARGIN);
910
gtk_container_add (GTK_CONTAINER (s_pLauncherWindow), pMainVBox);
912
#if (GTK_MAJOR_VERSION < 3)
913
s_pLauncherPane = gtk_hpaned_new ();
915
s_pLauncherPane = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
918
gtk_box_pack_start (GTK_BOX (pMainVBox),
924
//\_____________ On construit l'arbre des launceurs.
925
GtkTreeModel *model = _build_tree_model();
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),
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,
946
GtkCellRenderer *rend;
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);
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);
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);
959
//\_____________ We add boutons.
960
GtkWidget *pButtonsHBox = _gtk_hbox_new (CAIRO_DOCK_FRAME_MARGIN*2);
961
gtk_box_pack_end (GTK_BOX (pMainVBox),
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),
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),
983
//\_____________ On ajoute la barre d'etat.
984
GtkWidget *pStatusBar = gtk_statusbar_new ();
985
gtk_box_pack_start (GTK_BOX (pButtonsHBox), // pMainVBox
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));
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),
997
MIN (CAIRO_DOCK_LAUNCHER_PANEL_HEIGHT, g_desktopGeometry.iXScreenHeight[CAIRO_DOCK_HORIZONTAL] - (g_pMainDock && g_pMainDock->container.bIsHorizontal ? g_pMainDock->iMaxDockHeight : 0)));
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);
1004
gtk_widget_show_all (s_pLauncherWindow);
1006
g_signal_connect (G_OBJECT (s_pLauncherWindow),
1008
G_CALLBACK (on_delete_launcher_gui),
1011
//\_____________ On selectionne l'entree courante.
1012
_select_item (pIcon, pContainer, pModuleInstance, s_pLauncherWindow);
1014
return s_pLauncherWindow;
1017
static void reload_items (void)
1019
if (s_pLauncherWindow == NULL)
1022
cd_debug ("%s ()", __func__);
1024
if (s_pCurrentLauncherWidget && GTK_IS_NOTEBOOK (s_pCurrentLauncherWidget))
1025
iNotebookPage = gtk_notebook_get_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget));
1029
// reload the tree-view
1030
GtkTreeModel *model = _build_tree_model();
1032
gtk_tree_view_set_model (GTK_TREE_VIEW (s_pLauncherTreeView), GTK_TREE_MODEL (model));
1033
g_object_unref (model);
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");
1040
_delete_current_launcher_widget (s_pLauncherWindow); // s_pCurrentLauncherWidget <- 0
1042
_select_item (pCurrentIcon, pCurrentContainer, pCurrentModuleInstance, s_pLauncherWindow); // set s_pCurrentLauncherWidget
1044
if (s_pCurrentLauncherWidget && GTK_IS_NOTEBOOK (s_pCurrentLauncherWidget) && iNotebookPage != -1)
1045
gtk_notebook_set_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget), iNotebookPage);
1047
gtk_widget_show_all (s_pLauncherWindow);
1050
void cairo_dock_register_default_items_gui_backend (void)
1052
CairoDockItemsGuiBackend *pBackend = g_new0 (CairoDockItemsGuiBackend, 1);
1054
pBackend->show_gui = show_gui;
1055
pBackend->reload_items = reload_items;
1057
cairo_dock_register_items_gui_backend (pBackend);
1061
////////////////////
1062
// ACTIONS ON GUI //
1063
////////////////////
1065
CairoDockGroupKeyWidget *cairo_dock_gui_items_get_widget_from_name (CairoDockModuleInstance *pInstance, const gchar *cGroupName, const gchar *cKeyName)
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);
1072
void cairo_dock_gui_items_update_desklet_params (CairoDesklet *pDesklet)
1074
if (s_pLauncherWindow == NULL || pDesklet == NULL || pDesklet->pIcon == NULL)
1077
Icon *pIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1078
if (pIcon != pDesklet->pIcon)
1081
GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
1082
cairo_dock_update_desklet_widgets (pDesklet, pWidgetList);
1085
void cairo_dock_update_desklet_visibility_params (CairoDesklet *pDesklet)
1087
if (s_pLauncherWindow == NULL || pDesklet == NULL || pDesklet->pIcon == NULL)
1090
Icon *pIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
1091
if (pIcon != pDesklet->pIcon)
1094
GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
1095
cairo_dock_update_desklet_visibility_widgets (pDesklet, pWidgetList);
1098
void cairo_dock_gui_items_update_module_instance_container (CairoDockModuleInstance *pInstance, gboolean bDetached)
1100
if (s_pLauncherWindow == NULL || pInstance == NULL)
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.
1107
GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
1108
cairo_dock_update_is_detached_widget (bDetached, pWidgetList);
1111
void cairo_dock_gui_items_reload_current_widget (CairoDockModuleInstance *pInstance, int iShowPage)
1113
g_return_if_fail (s_pLauncherWindow != NULL && s_pLauncherTreeView != NULL);
1114
cd_debug ("%s ()", __func__);
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");
1122
if (pIcon->pModuleInstance != pInstance)
1125
else if (pModuleInstance)
1127
if (pModuleInstance != pInstance)
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;
1139
if ((GTK_IS_NOTEBOOK (s_pCurrentLauncherWidget)))
1141
if (iShowPage == -1)
1142
iNotebookPage = gtk_notebook_get_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget));
1144
iNotebookPage = iShowPage;
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.
1153
if (iNotebookPage != -1)
1155
gtk_notebook_set_current_page (GTK_NOTEBOOK (s_pCurrentLauncherWidget), iNotebookPage);
1158
g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
1159
g_list_free (paths);
1162
void cairo_dock_gui_items_set_status_message_on_gui (const gchar *cMessage)
1164
GtkWidget *pStatusBar = NULL;
1165
if (s_pLauncherWindow != NULL)
1167
pStatusBar = g_object_get_data (G_OBJECT (s_pLauncherWindow), "status-bar");
1169
if (pStatusBar == NULL)
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);