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
24
#include <glib/gstdio.h>
25
#include <glib/gi18n.h>
28
#include "cairo-dock-modules.h"
29
#include "cairo-dock-log.h"
30
#include "cairo-dock-gui-factory.h"
31
#include "cairo-dock-keyfile-utilities.h"
32
#include "cairo-dock-animations.h"
33
#include "cairo-dock-draw.h"
34
#include "cairo-dock-dock-manager.h"
35
#include "cairo-dock-container.h"
36
#include "cairo-dock-applications-manager.h"
37
#include "cairo-dock-launcher-manager.h"
38
#include "cairo-dock-load.h"
39
#include "cairo-dock-internal-icons.h"
40
#include "cairo-dock-desktop-file-factory.h"
41
#include "cairo-dock-gui-manager.h"
42
#include "cairo-dock-gui-launcher.h"
44
#define CAIRO_DOCK_FRAME_MARGIN 6
45
#define CAIRO_DOCK_LAUNCHER_PANEL_WIDTH 1000
46
#define CAIRO_DOCK_LAUNCHER_PANEL_HEIGHT 500
48
extern gchar *g_cCurrentLaunchersPath;
50
static GtkWidget *s_pLauncherWindow = NULL;
51
static GtkWidget *s_pCurrentLauncherWidget = NULL;
52
static GtkWidget *s_pLauncherTreeView = NULL;
53
static GtkWidget *s_pLauncherPane = NULL;
54
static GtkWidget *s_pLauncherScrolledWindow = NULL;
55
static guint s_iSidRefreshGUI = 0;
61
static void _free_launcher_gui (void)
63
s_pLauncherWindow = NULL;
64
s_pCurrentLauncherWidget = NULL;
65
s_pLauncherPane = NULL;
66
s_pLauncherTreeView = NULL;
67
s_pLauncherScrolledWindow = NULL;
70
static void _delete_current_launcher_widget (void)
72
g_return_if_fail (s_pLauncherWindow != NULL);
74
if (s_pCurrentLauncherWidget != NULL)
76
gtk_widget_destroy (s_pCurrentLauncherWidget);
77
s_pCurrentLauncherWidget = NULL;
79
GSList *pWidgetList = g_object_get_data (G_OBJECT (s_pLauncherWindow), "widget-list");
80
if (pWidgetList != NULL)
82
cairo_dock_free_generated_widget_list (pWidgetList);
83
g_object_set_data (G_OBJECT (s_pLauncherWindow), "widget-list", NULL);
85
GPtrArray *pDataGarbage = g_object_get_data (G_OBJECT (s_pLauncherWindow), "garbage");
86
if (pDataGarbage != NULL)
89
g_object_set_data (G_OBJECT (s_pLauncherWindow), "garbage", NULL);
92
g_object_set_data (G_OBJECT (s_pLauncherWindow), "current-icon", NULL);
96
static gboolean on_delete_launcher_gui (GtkWidget *pWidget, GdkEvent *event, gpointer data)
98
GSList *pWidgetList = g_object_get_data (G_OBJECT (pWidget), "widget-list");
99
cairo_dock_free_generated_widget_list (pWidgetList);
101
GPtrArray *pDataGarbage = g_object_get_data (G_OBJECT (pWidget), "garbage");
104
cairo_dock_dialog_window_destroyed ();
106
_free_launcher_gui ();
111
static void on_click_launcher_apply (GtkButton *button, GtkWidget *pWindow)
113
//g_print ("%s ()\n", __func__);
115
Icon *pIcon = g_object_get_data (G_OBJECT (pWindow), "current-icon");
116
if (pIcon == NULL) // ligne correspondante a un dock principal.
118
GSList *pWidgetList = g_object_get_data (G_OBJECT (pWindow), "widget-list");
120
gchar *cConfFilePath;
121
if (pIcon->cDesktopFileName != NULL)
122
cConfFilePath = (*pIcon->cDesktopFileName == '/' ? g_strdup (pIcon->cDesktopFileName) : g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, pIcon->cDesktopFileName));
123
else if (CAIRO_DOCK_IS_APPLET (pIcon))
124
cConfFilePath = g_strdup (pIcon->pModuleInstance->cConfFilePath);
128
GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
129
g_return_if_fail (pKeyFile != NULL);
131
cairo_dock_update_keyfile_from_widget_list (pKeyFile, pWidgetList);
132
cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
133
g_key_file_free (pKeyFile);
134
g_free (cConfFilePath);
136
if (pIcon->cDesktopFileName != NULL)
137
cairo_dock_reload_launcher (pIcon); // prend tout en compte, y compris le redessin et le rechargement de l'IHM.
139
cairo_dock_reload_module_instance (pIcon->pModuleInstance, TRUE); // idem
142
static void on_click_launcher_quit (GtkButton *button, GtkWidget *pWindow)
144
//g_print ("%s ()\n", __func__);
145
on_delete_launcher_gui (pWindow, NULL, NULL);
146
gtk_widget_destroy (pWindow);
154
static gboolean _search_icon_in_line (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer *data)
157
gtk_tree_model_get (model, iter,
159
if (pIcon == data[0])
161
//g_print (" found !\n");
162
memcpy (data[1], iter, sizeof (GtkTreeIter));
163
data[2] = GINT_TO_POINTER (TRUE);
164
return TRUE; // stop iterating.
168
static gboolean _search_icon_in_model (GtkWidget *pTreeView, Icon *pIcon, GtkTreeIter *iter)
172
//g_print ("%s (%s)\n", __func__, pIcon->cName);
173
GtkTreeModel * model = gtk_tree_view_get_model (GTK_TREE_VIEW (pTreeView));
174
gpointer data[3] = {pIcon, iter, GINT_TO_POINTER (FALSE)};
175
gtk_tree_model_foreach (model,
176
(GtkTreeModelForeachFunc) _search_icon_in_line,
178
return GPOINTER_TO_INT (data[2]);
181
static gboolean _select_one_launcher_in_tree (GtkTreeSelection * selection, GtkTreeModel * model, GtkTreePath * path, gboolean path_currently_selected, gpointer data)
183
//g_print ("%s (path_currently_selected:%d)\n", __func__, path_currently_selected);
184
if (path_currently_selected)
186
g_object_set_data (G_OBJECT (s_pLauncherWindow), "current-icon", NULL);
188
if (! gtk_tree_model_get_iter (model, &iter, path))
191
_delete_current_launcher_widget ();
195
gtk_tree_model_get (model, &iter,
198
gtk_window_set_title (GTK_WINDOW (s_pLauncherWindow), cName);
200
if (pIcon == NULL) // ligne correspondante a un dock principal.
203
// on charge son .conf
204
if (pIcon->cDesktopFileName != NULL)
206
//g_print ("on presente %s...\n", pIcon->cDesktopFileName);
207
gchar *cConfFilePath = (*pIcon->cDesktopFileName == '/' ? g_strdup (pIcon->cDesktopFileName) : g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, pIcon->cDesktopFileName));
209
CairoDockDesktopFileType iLauncherType;
210
if (CAIRO_DOCK_IS_URI_LAUNCHER (pIcon))
211
iLauncherType = CAIRO_DOCK_DESKTOP_FILE_FOR_FILE;
212
else if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
213
iLauncherType = CAIRO_DOCK_DESKTOP_FILE_FOR_SEPARATOR;
214
else if (pIcon->pSubDock != NULL && pIcon->cClass == NULL)
215
iLauncherType = CAIRO_DOCK_DESKTOP_FILE_FOR_CONTAINER;
217
iLauncherType = CAIRO_DOCK_DESKTOP_FILE_FOR_LAUNCHER;
218
cairo_dock_update_launcher_desktop_file (cConfFilePath, iLauncherType);
220
GSList *pWidgetList = NULL;
221
GPtrArray *pDataGarbage = g_ptr_array_new ();
222
s_pCurrentLauncherWidget = cairo_dock_build_conf_file_widget (cConfFilePath,
229
gtk_paned_pack2 (GTK_PANED (s_pLauncherPane), s_pCurrentLauncherWidget, TRUE, FALSE);
231
g_object_set_data (G_OBJECT (s_pLauncherWindow), "widget-list", pWidgetList);
232
g_object_set_data (G_OBJECT (s_pLauncherWindow), "garbage", pDataGarbage);
233
g_object_set_data (G_OBJECT (s_pLauncherWindow), "current-icon", pIcon);
235
g_free (cConfFilePath);
236
gtk_widget_show_all (s_pCurrentLauncherWidget);
238
else if (CAIRO_DOCK_IS_APPLET (pIcon))
240
GSList *pWidgetList = NULL;
241
GPtrArray *pDataGarbage = g_ptr_array_new ();
243
GKeyFile* pKeyFile = cairo_dock_open_key_file (pIcon->pModuleInstance->cConfFilePath);
244
g_return_val_if_fail (pKeyFile != NULL, FALSE);
246
gchar *cOriginalConfFilePath = g_strdup_printf ("%s/%s", pIcon->pModuleInstance->pModule->pVisitCard->cShareDataDir, pIcon->pModuleInstance->pModule->pVisitCard->cConfFileName);
247
s_pCurrentLauncherWidget = cairo_dock_build_group_widget (pKeyFile, "Icon", pIcon->pModuleInstance->pModule->pVisitCard->cGettextDomain, s_pLauncherWindow, &pWidgetList, pDataGarbage, cOriginalConfFilePath);
248
g_free (cOriginalConfFilePath);
250
gtk_paned_pack2 (GTK_PANED (s_pLauncherPane), s_pCurrentLauncherWidget, TRUE, FALSE);
252
g_object_set_data (G_OBJECT (s_pLauncherWindow), "widget-list", pWidgetList);
253
g_object_set_data (G_OBJECT (s_pLauncherWindow), "garbage", pDataGarbage);
254
g_object_set_data (G_OBJECT (s_pLauncherWindow), "current-icon", pIcon);
255
gtk_widget_show_all (s_pCurrentLauncherWidget);
260
static void _add_one_sub_dock_to_model (CairoDock *pDock, GtkTreeStore *model, GtkTreeIter *pParentIter)
265
GError *erreur = NULL;
266
GdkPixbuf *pixbuf = NULL;
267
gchar *cImagePath = NULL;
269
for (ic = pDock->icons; ic != NULL; ic = ic->next)
272
if (! CAIRO_DOCK_IS_LAUNCHER (pIcon) && ! CAIRO_DOCK_IS_USER_SEPARATOR (pIcon) && ! CAIRO_DOCK_IS_APPLET (pIcon))
275
if (cairo_dock_icon_is_being_removed (pIcon))
279
if (pIcon->cFileName != NULL)
281
cImagePath = cairo_dock_search_icon_s_path (pIcon->cFileName);
283
if (cImagePath == NULL || ! g_file_test (cImagePath, G_FILE_TEST_EXISTS))
286
if (CAIRO_DOCK_IS_SEPARATOR (pIcon))
288
cImagePath = cairo_dock_search_image_s_path (myIcons.cSeparatorImage);
290
else if (CAIRO_DOCK_IS_APPLET (pIcon))
292
cImagePath = g_strdup (pIcon->pModuleInstance->pModule->pVisitCard->cIconFilePath);
296
cImagePath = cairo_dock_search_image_s_path (CAIRO_DOCK_DEFAULT_ICON_NAME);
297
if (cImagePath == NULL || ! g_file_test (cImagePath, G_FILE_TEST_EXISTS))
300
cImagePath = g_strdup (CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_DEFAULT_ICON_NAME);
305
if (cImagePath != NULL)
307
pixbuf = gdk_pixbuf_new_from_file_at_size (cImagePath, 32, 32, &erreur);
310
cd_warning (erreur->message);
311
g_error_free (erreur);
317
if (CAIRO_DOCK_IS_USER_SEPARATOR (pIcon)) // separator
319
else if (CAIRO_DOCK_IS_APPLET (pIcon)) // applet
320
cName = dgettext (pIcon->pModuleInstance->pModule->pVisitCard->cGettextDomain, pIcon->pModuleInstance->pModule->pVisitCard->cTitle);
322
cName = (pIcon->cInitialName ? pIcon->cInitialName : pIcon->cName);
324
// add an entry in the tree view.
325
gtk_tree_store_append (model, &iter, pParentIter);
326
gtk_tree_store_set (model, &iter,
332
if (CAIRO_DOCK_IS_LAUNCHER (pIcon) && pIcon->pSubDock != NULL && ! CAIRO_DOCK_IS_URI_LAUNCHER (pIcon))
334
_add_one_sub_dock_to_model (pIcon->pSubDock, model, &iter);
337
// reset all for the next round.
341
g_object_unref (pixbuf);
345
static void _add_one_root_dock_to_model (const gchar *cName, CairoDock *pDock, GtkTreeStore *model)
347
if (pDock->iRefCount != 0)
351
// on ajoute une ligne pour le dock.
352
gtk_tree_store_append (model, &iter, NULL);
353
gtk_tree_store_set (model, &iter,
358
// on ajoute chaque lanceur.
359
_add_one_sub_dock_to_model (pDock, model, &iter);
361
static GtkTreeModel *_build_tree_model (void)
363
GtkTreeStore *model = gtk_tree_store_new (3,
366
G_TYPE_POINTER); // nom du lanceur, image, Icon.
367
cairo_dock_foreach_docks ((GHFunc) _add_one_root_dock_to_model, model);
368
return GTK_TREE_MODEL (model);
371
static inline gboolean _select_item (Icon *pIcon)
374
if (_search_icon_in_model (s_pLauncherTreeView, pIcon, &iter))
376
GtkTreeModel * model = gtk_tree_view_get_model (GTK_TREE_VIEW (s_pLauncherTreeView));
377
GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
378
gtk_tree_view_expand_to_path (GTK_TREE_VIEW (s_pLauncherTreeView), path);
379
gtk_tree_path_free (path);
381
GtkTreeSelection *pSelection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s_pLauncherTreeView));
382
gtk_tree_selection_select_iter (pSelection, &iter);
383
g_object_set_data (G_OBJECT (s_pLauncherWindow), "current-icon", pIcon);
388
gtk_window_set_title (GTK_WINDOW (s_pLauncherWindow), _("Launcher configuration"));
389
g_object_set_data (G_OBJECT (s_pLauncherWindow), "current-icon", NULL);
399
static GtkWidget *show_gui (Icon *pIcon)
401
//g_print ("%s ()\n", __func__);
402
//\_____________ On construit la fenetre.
403
if (s_pLauncherWindow != NULL)
405
_delete_current_launcher_widget ();
407
_select_item (pIcon);
409
gtk_window_present (GTK_WINDOW (s_pLauncherWindow));
410
return s_pLauncherWindow;
412
s_pLauncherWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
413
gtk_window_set_icon_from_file (GTK_WINDOW (s_pLauncherWindow), CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON, NULL);
415
GtkWidget *pMainVBox = gtk_vbox_new (FALSE, CAIRO_DOCK_FRAME_MARGIN);
416
gtk_container_add (GTK_CONTAINER (s_pLauncherWindow), pMainVBox);
418
s_pLauncherPane = gtk_hpaned_new ();
419
gtk_box_pack_start (GTK_BOX (pMainVBox),
425
//\_____________ On construit l'arbre des launceurs.
426
GtkTreeModel *model = _build_tree_model();
428
//\_____________ On construit le tree-view avec.
429
s_pLauncherTreeView = gtk_tree_view_new_with_model (model);
430
g_object_unref (model);
431
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (s_pLauncherTreeView), FALSE);
432
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (s_pLauncherTreeView), TRUE);
434
GtkTreeSelection *pSelection = gtk_tree_view_get_selection (GTK_TREE_VIEW (s_pLauncherTreeView));
435
gtk_tree_selection_set_mode (pSelection, GTK_SELECTION_SINGLE);
436
gtk_tree_selection_set_select_function (pSelection,
437
(GtkTreeSelectionFunc) _select_one_launcher_in_tree,
441
GtkCellRenderer *rend;
442
rend = gtk_cell_renderer_text_new ();
443
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (s_pLauncherTreeView), -1, NULL, rend, "text", 0, NULL);
444
rend = gtk_cell_renderer_pixbuf_new ();
445
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (s_pLauncherTreeView), -1, NULL, rend, "pixbuf", 1, NULL);
447
s_pLauncherScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
448
gtk_widget_set (s_pLauncherScrolledWindow, "height-request", CAIRO_DOCK_LAUNCHER_PANEL_HEIGHT - 30, NULL);
449
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (s_pLauncherScrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
450
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (s_pLauncherScrolledWindow), s_pLauncherTreeView);
451
gtk_paned_pack1 (GTK_PANED (s_pLauncherPane), s_pLauncherScrolledWindow, TRUE, FALSE);
453
//\_____________ On ajoute les boutons.
454
GtkWidget *pButtonsHBox = gtk_hbox_new (FALSE, CAIRO_DOCK_FRAME_MARGIN*2);
455
gtk_box_pack_end (GTK_BOX (pMainVBox),
461
GtkWidget *pQuitButton = gtk_button_new_from_stock (GTK_STOCK_QUIT);
462
g_signal_connect (G_OBJECT (pQuitButton), "clicked", G_CALLBACK(on_click_launcher_quit), s_pLauncherWindow);
463
gtk_box_pack_end (GTK_BOX (pButtonsHBox),
469
GtkWidget *pApplyButton = gtk_button_new_from_stock (GTK_STOCK_APPLY);
470
g_signal_connect (G_OBJECT (pApplyButton), "clicked", G_CALLBACK(on_click_launcher_apply), s_pLauncherWindow);
471
gtk_box_pack_end (GTK_BOX (pButtonsHBox),
477
//\_____________ On ajoute la barre d'etat.
478
GtkWidget *pStatusBar = gtk_statusbar_new ();
479
gtk_box_pack_start (GTK_BOX (pButtonsHBox), // pMainVBox
484
g_object_set_data (G_OBJECT (s_pLauncherWindow), "status-bar", pStatusBar);
486
gtk_window_resize (GTK_WINDOW (s_pLauncherWindow), CAIRO_DOCK_LAUNCHER_PANEL_WIDTH, CAIRO_DOCK_LAUNCHER_PANEL_HEIGHT);
488
gtk_widget_show_all (s_pLauncherWindow);
489
cairo_dock_dialog_window_created ();
491
g_signal_connect (G_OBJECT (s_pLauncherWindow),
493
G_CALLBACK (on_delete_launcher_gui),
496
//\_____________ On selectionne l'entree courante.
497
_select_item (pIcon);
499
return s_pLauncherWindow;
503
static void refresh_gui (void)
505
if (s_pLauncherWindow == NULL)
507
Icon *pCurrentIcon = g_object_get_data (G_OBJECT (s_pLauncherWindow), "current-icon");
509
_delete_current_launcher_widget ();
511
GtkTreeModel *model = _build_tree_model();
513
gtk_tree_view_set_model (GTK_TREE_VIEW (s_pLauncherTreeView), GTK_TREE_MODEL (model));
514
g_object_unref (model);
516
_select_item (pCurrentIcon);
518
gtk_widget_show_all (s_pLauncherWindow);
522
void cairo_dock_register_default_launcher_gui_backend (void)
524
CairoDockLauncherGuiBackend *pBackend = g_new0 (CairoDockLauncherGuiBackend, 1);
526
pBackend->show_gui = show_gui;
527
pBackend->refresh_gui = refresh_gui;
529
cairo_dock_register_launcher_gui_backend (pBackend);