3
* Copyright (c) 2005-2007 Jasper Huijsmans <jasper@xfce.org>
4
* Copyright (c) 2006-2007 Nick Schermer <nick@xfce.org>
5
* Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (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 Library General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2
* Copyright (C) 2008-2009 Nick Schermer <nick@xfce.org>
4
* This library is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the Free
6
* Software Foundation; either version 2 of the License, or (at your option)
9
* This library is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
* You should have received a copy of the GNU Library General Public License
15
* along with this library; if not, write to the Free Software Foundation,
16
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22
19
#ifdef HAVE_CONFIG_H
23
20
#include <config.h>
28
23
#ifdef HAVE_STRING_H
29
24
#include <string.h>
32
#include <libxfcegui4/xfce-titled-dialog.h>
33
#include <libxfce4panel/xfce-panel-plugin.h>
28
#include <libxfce4ui/libxfce4ui.h>
29
#include <libxfce4util/libxfce4util.h>
30
#include <garcon/garcon.h>
31
#include <xfconf/xfconf.h>
33
#include <gdk/gdkkeysyms.h>
35
#include <common/panel-private.h>
36
#include <common/panel-utils.h>
35
38
#include "launcher.h"
36
39
#include "launcher-dialog.h"
40
#include "launcher-dialog_ui.h"
42
#ifdef GDK_WINDOWING_X11
44
#define LAUNCHER_WIDGET_XID(widget) ((gint) GDK_WINDOW_XID (GDK_WINDOW ((widget)->window)))
46
#define LAUNCHER_WIDGET_XID(widget) (0)
53
LauncherPlugin *plugin;
55
guint idle_populate_id;
45
typedef struct _LauncherDialog LauncherDialog;
47
struct _LauncherDialog
49
LauncherPlugin *launcher;
52
guint stored_move_first : 1;
55
GtkWidget *arrow_position;
74
GtkWidget *entry_name;
75
GtkWidget *entry_comment;
76
GtkWidget *entry_icon;
77
GtkWidget *entry_exec;
78
GtkWidget *entry_path;
79
GtkWidget *entry_terminal;
80
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
81
GtkWidget *entry_startup;
90
static void launcher_dialog_g_list_swap (GList *li_a,
92
static gboolean launcher_dialog_read_desktop_file (const gchar *file,
93
LauncherEntry *entry);
94
static void launcher_dialog_tree_drag_data_received (GtkWidget *widget,
95
GdkDragContext *context,
98
GtkSelectionData *selection_data,
102
static void launcher_dialog_frame_drag_data_received (GtkWidget *widget,
103
GdkDragContext *context,
106
GtkSelectionData *selection_data,
110
static void launcher_dialog_save_entry (GtkWidget *entry,
112
static void launcher_dialog_save_button (GtkWidget *button,
114
static void launcher_dialog_update_entries (LauncherDialog *ld);
115
static void launcher_dialog_update_icon (LauncherDialog *ld);
116
static void launcher_dialog_command_chooser (LauncherDialog *ld);
117
static void launcher_dialog_icon_chooser (LauncherDialog *ld);
118
static void launcher_dialog_tree_update_row (LauncherDialog *ld,
120
static void launcher_dialog_tree_selection_changed (LauncherDialog *ld,
121
GtkTreeSelection *selection);
122
static void launcher_dialog_tree_button_clicked (GtkWidget *button,
124
static GtkWidget *launcher_dialog_add_properties (LauncherDialog *ld) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
125
static GtkWidget *launcher_dialog_add_tree (LauncherDialog *ld) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
126
static GtkWidget *launcher_dialog_add_tree_buttons (LauncherDialog *ld) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
127
static void launcher_dialog_response (GtkWidget *dialog,
137
launcher_dialog_g_list_swap (GList *li_a,
142
/* swap the data pointers */
144
li_a->data = li_b->data;
71
static void launcher_dialog_items_set_item (GtkTreeModel *model,
73
GarconMenuItem *item);
74
static void launcher_dialog_tree_save (LauncherPluginDialog *dialog);
75
static void launcher_dialog_tree_selection_changed (GtkTreeSelection *selection,
76
LauncherPluginDialog *dialog);
77
static gboolean launcher_dialog_press_event (LauncherPluginDialog *dialog,
78
const gchar *object_name);
79
static void launcher_dialog_items_unload (LauncherPluginDialog *dialog);
80
static void launcher_dialog_items_load (LauncherPluginDialog *dialog);
84
/* dnd for items in and from the treeviews */
85
static const GtkTargetEntry dnd_targets[] =
87
{ "text/uri-list", 0, 0, },
150
launcher_dialog_read_desktop_file (const gchar *path,
151
LauncherEntry *entry)
93
launcher_dialog_add_visible_function (GtkTreeModel *model,
154
const gchar *value = NULL;
157
/* we only support .desktop files */
158
if (G_UNLIKELY (g_str_has_suffix (path, ".desktop") == FALSE ||
159
g_path_is_absolute (path) == FALSE))
162
/* open de .desktop file */
163
rc = xfce_rc_simple_open (path, TRUE);
164
if (G_UNLIKELY (rc == NULL))
167
/* set the desktop entry group */
168
xfce_rc_set_group (rc, "Desktop Entry");
171
value = xfce_rc_read_entry (rc, "Name", NULL);
172
if (G_LIKELY (value != NULL))
174
g_free (entry->name);
175
entry->name = g_strdup (value);
179
value = xfce_rc_read_entry (rc, "Comment", NULL);
180
if (G_LIKELY (value != NULL))
182
g_free (entry->comment);
183
entry->comment = g_strdup (value);
187
value = xfce_rc_read_entry_untranslated (rc, "Icon", NULL);
188
if (G_LIKELY (value != NULL))
190
g_free (entry->icon);
192
/* get rid of extensions in non-absolute names */
193
if (G_UNLIKELY (g_path_is_absolute (value) == FALSE) &&
194
((p = g_strrstr (value, ".")) && strlen (p) < 6))
195
entry->icon = g_strndup (value, p-value);
197
entry->icon = g_strdup (value);
199
#if LAUNCHER_NEW_TOOLTIP_API
200
/* release the cached icon */
201
if (entry->tooltip_cache)
203
g_object_unref (G_OBJECT (entry->tooltip_cache));
204
entry->tooltip_cache = NULL;
210
value = xfce_rc_read_entry_untranslated (rc, "Exec", NULL);
211
if (G_LIKELY (value != NULL))
213
g_free (entry->exec);
215
/* expand and quote command and store */
216
entry->exec = xfce_expand_variables (value, NULL);
219
/* working directory */
220
value = xfce_rc_read_entry_untranslated (rc, "Path", NULL);
221
if (G_UNLIKELY (value != NULL))
223
g_free (entry->path);
225
/* expand variables and store */
226
entry->path = xfce_expand_variables (value, NULL);
230
entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
232
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
233
/* startup notification */
234
entry->startup = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE);
237
/* release rc file */
97
gchar *string, *escaped;
98
gboolean visible = FALSE;
101
gchar *text_casefolded;
102
gchar *name_casefolded;
104
/* get the search string from the item */
105
text = gtk_entry_get_text (GTK_ENTRY (user_data));
106
if (G_UNLIKELY (exo_str_is_empty (text)))
246
launcher_dialog_tree_drag_data_received (GtkWidget *widget,
247
GdkDragContext *context,
250
GtkSelectionData *selection_data,
255
GtkTreePath *path = NULL;
256
GtkTreeViewDropPosition position;
260
GSList *filenames = NULL;
263
gboolean insert_before = FALSE;
264
gboolean update_icon = FALSE;
266
LauncherEntry *entry;
269
/* get drop position in the tree */
270
if (gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (ld->treeview),
271
x, y, &path, &position) == FALSE)
273
/* probably droped in empty tree space, drop after last item */
274
path = gtk_tree_path_new_from_indices (g_list_length (ld->launcher->entries) -1 , -1);
275
position = GTK_TREE_VIEW_DROP_AFTER;
278
if (G_LIKELY (path != NULL))
280
/* get the iter we're going to drop after */
281
model = gtk_tree_view_get_model (GTK_TREE_VIEW (ld->treeview));
282
gtk_tree_model_get_iter (model, &iter_a, path);
284
/* array position or current item */
285
i = gtk_tree_path_get_indices (path)[0];
287
/* insert position, array correction and the path we select afterwards */
290
case GTK_TREE_VIEW_DROP_BEFORE:
291
case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
292
insert_before = TRUE;
295
case GTK_TREE_VIEW_DROP_AFTER:
296
case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
297
gtk_tree_path_next (path);
299
insert_before = FALSE;
303
/* we need to update the button icon afterwards */
307
/* create list from selection data */
308
filenames = launcher_utility_filenames_from_selection_data (selection_data);
311
if (G_LIKELY (filenames != NULL))
313
for (li = filenames; li != NULL; li = li->next)
317
/* create new entry */
318
entry = launcher_entry_new ();
320
/* try to parse desktop file */
321
if (G_LIKELY (launcher_dialog_read_desktop_file (file, entry) == TRUE))
323
/* insert new row in store */
325
gtk_list_store_insert_before (ld->store, &iter_b, &iter_a);
327
gtk_list_store_insert_after (ld->store, &iter_b, &iter_a);
329
/* try to load the pixbuf */
330
pixbuf = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
333
gtk_list_store_set (ld->store, &iter_b,
335
COLUMN_NAME, entry->name,
339
if (G_LIKELY (pixbuf != NULL))
340
g_object_unref (G_OBJECT (pixbuf));
343
ld->launcher->entries = g_list_insert (ld->launcher->entries, entry, i);
345
/* copy iter, so we add after last item */
348
/* raise position counter */
351
/* 1st item is inserted before existing item, after
352
* that we insert after the 1st item */
353
insert_before = FALSE;
357
/* desktop file pasring failed, free new entry */
358
launcher_entry_free (entry, NULL);
362
/* select the new item (also updates treeview buttons) */
363
gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
365
/* update the panel */
366
launcher_plugin_rebuild (ld->launcher, update_icon);
369
launcher_free_filenames (filenames);
373
if (G_LIKELY (path != NULL))
374
gtk_tree_path_free (path);
377
gtk_drag_finish (context, TRUE, FALSE, time_);
383
launcher_dialog_frame_drag_data_received (GtkWidget *widget,
384
GdkDragContext *context,
387
GtkSelectionData *selection_data,
392
GSList *filenames, *li;
394
gboolean update_icon = FALSE;
396
/* create list from all the uri list */
397
filenames = launcher_utility_filenames_from_selection_data (selection_data);
399
if (G_LIKELY (filenames != NULL))
401
for (li = filenames; li != NULL; li = li->next)
403
file = (gchar *) li->data;
405
/* try to update the current entry settings */
406
if (G_LIKELY (launcher_dialog_read_desktop_file (file, ld->entry) == TRUE))
408
/* update the widgets */
409
launcher_dialog_update_entries (ld);
411
/* update the tree */
412
launcher_dialog_tree_update_row (ld, COLUMN_NAME);
413
launcher_dialog_tree_update_row (ld, COLUMN_ICON);
415
/* also update the panel button icon */
416
if (g_list_index (ld->launcher->entries, ld->entry) == 0)
419
/* update the panel */
420
launcher_plugin_rebuild (ld->launcher, update_icon);
428
launcher_free_filenames (filenames);
432
gtk_drag_finish (context, TRUE, FALSE, time_);
438
* Properties update and save functions
441
launcher_dialog_save_entry (GtkWidget *entry,
447
/* quit if locked or no active entry set */
448
if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
451
/* handle working directory changes */
452
if (entry == ld->entry_path)
454
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (ld->entry_path));
455
if (exo_str_is_equal (ld->entry->path, filename) == FALSE)
457
g_free (ld->entry->path);
458
ld->entry->path = filename;
468
/* set text to null, if there is no valid text */
469
text = gtk_entry_get_text (GTK_ENTRY (entry));
470
if (G_UNLIKELY (text == NULL || *text == '\0'))
474
if (entry == ld->entry_name)
476
g_free (ld->entry->name);
477
ld->entry->name = g_strdup (text);
479
/* update tree, when triggered by widget */
480
launcher_dialog_tree_update_row (ld, COLUMN_NAME);
482
else if (entry == ld->entry_comment)
484
g_free (ld->entry->comment);
485
ld->entry->comment = g_strdup (text);
487
else if (entry == ld->entry_exec)
489
g_free (ld->entry->exec);
490
ld->entry->exec = text ? xfce_expand_variables (text, NULL) : NULL;
495
launcher_plugin_rebuild (ld->launcher, FALSE);
501
launcher_dialog_save_button (GtkWidget *button,
506
/* quit if locked or no active entry set */
507
if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
510
/* get toggle button state */
511
active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
513
/* update entry or global setting */
514
if (button == ld->entry_terminal)
516
ld->entry->terminal = active;
517
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
518
gtk_widget_set_sensitive (ld->entry_startup, !active);
521
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
522
else if (button == ld->entry_startup)
523
ld->entry->startup = active;
530
launcher_dialog_update_entries (LauncherDialog *ld)
534
/* quit if locked or no active entry set */
535
if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
538
/* lock the save functions */
541
/* set new entry values */
542
gtk_entry_set_text (GTK_ENTRY (ld->entry_name),
543
(ld->entry->name != NULL) ? ld->entry->name : "");
545
gtk_entry_set_text (GTK_ENTRY (ld->entry_comment),
546
(ld->entry->comment != NULL) ? ld->entry->comment : "");
548
gtk_entry_set_text (GTK_ENTRY (ld->entry_exec),
549
(ld->entry->exec != NULL) ? ld->entry->exec : "");
551
if (ld->entry->path != NULL)
552
dir = ld->entry->path;
554
dir = g_get_current_dir ();
556
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (ld->entry_path), dir);
558
if (dir != ld->entry->path)
561
/* set toggle buttons */
562
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_terminal),
563
ld->entry->terminal);
564
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
565
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_startup),
568
gtk_widget_set_sensitive (ld->entry_startup, !ld->entry->terminal);
571
/* update icon button */
572
launcher_dialog_update_icon (ld);
575
ld->updating = FALSE;
581
launcher_dialog_update_icon (LauncherDialog *ld)
583
GdkPixbuf *icon = NULL;
586
/* drop the previous button child */
587
if (GTK_BIN (ld->entry_icon)->child != NULL)
588
gtk_widget_destroy (GTK_BIN (ld->entry_icon)->child);
590
if (G_LIKELY (ld->entry->icon))
591
icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->entry_icon), ld->entry->icon, LAUNCHER_CHOOSER_ICON_SIZE);
593
/* create icon button */
594
if (G_LIKELY (icon != NULL))
596
/* create image from pixbuf */
597
child = gtk_image_new_from_pixbuf (icon);
600
g_object_unref (G_OBJECT (icon));
602
gtk_widget_set_size_request (child, LAUNCHER_CHOOSER_ICON_SIZE, LAUNCHER_CHOOSER_ICON_SIZE);
606
child = gtk_label_new (_("No icon"));
608
gtk_widget_set_size_request (child, -1, LAUNCHER_CHOOSER_ICON_SIZE);
611
gtk_container_add (GTK_CONTAINER (ld->entry_icon), child);
612
gtk_widget_show (child);
618
* Icon and command search dialogs
621
launcher_dialog_command_chooser (LauncherDialog *ld)
623
GtkFileFilter *filter;
628
chooser = gtk_file_chooser_dialog_new (_("Select an Application"),
630
GTK_FILE_CHOOSER_ACTION_OPEN,
631
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
632
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
634
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
636
/* add file chooser filters */
637
filter = gtk_file_filter_new ();
638
gtk_file_filter_set_name (filter, _("All Files"));
639
gtk_file_filter_add_pattern (filter, "*");
640
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
642
filter = gtk_file_filter_new ();
643
gtk_file_filter_set_name (filter, _("Executable Files"));
644
gtk_file_filter_add_mime_type (filter, "application/x-csh");
645
gtk_file_filter_add_mime_type (filter, "application/x-executable");
646
gtk_file_filter_add_mime_type (filter, "application/x-perl");
647
gtk_file_filter_add_mime_type (filter, "application/x-python");
648
gtk_file_filter_add_mime_type (filter, "application/x-ruby");
649
gtk_file_filter_add_mime_type (filter, "application/x-shellscript");
650
gtk_file_filter_add_pattern (filter, "*.pl");
651
gtk_file_filter_add_pattern (filter, "*.py");
652
gtk_file_filter_add_pattern (filter, "*.rb");
653
gtk_file_filter_add_pattern (filter, "*.sh");
654
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
655
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), filter);
657
filter = gtk_file_filter_new ();
658
gtk_file_filter_set_name (filter, _("Perl Scripts"));
659
gtk_file_filter_add_mime_type (filter, "application/x-perl");
660
gtk_file_filter_add_pattern (filter, "*.pl");
661
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
663
filter = gtk_file_filter_new ();
664
gtk_file_filter_set_name (filter, _("Python Scripts"));
665
gtk_file_filter_add_mime_type (filter, "application/x-python");
666
gtk_file_filter_add_pattern (filter, "*.py");
667
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
669
filter = gtk_file_filter_new ();
670
gtk_file_filter_set_name (filter, _("Ruby Scripts"));
671
gtk_file_filter_add_mime_type (filter, "application/x-ruby");
672
gtk_file_filter_add_pattern (filter, "*.rb");
673
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
675
filter = gtk_file_filter_new ();
676
gtk_file_filter_set_name (filter, _("Shell Scripts"));
677
gtk_file_filter_add_mime_type (filter, "application/x-csh");
678
gtk_file_filter_add_mime_type (filter, "application/x-shellscript");
679
gtk_file_filter_add_pattern (filter, "*.sh");
680
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
682
/* use the bindir as default folder */
683
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), BINDIR);
685
/* get the current command */
686
filename = gtk_editable_get_chars (GTK_EDITABLE (ld->entry_exec), 0, -1);
687
if (G_LIKELY (filename != NULL))
689
/* use only the first argument */
690
s = strchr (filename, ' ');
691
if (G_UNLIKELY (s != NULL))
694
/* check if we have a file name */
695
if (G_LIKELY (*filename != '\0'))
697
/* check if the filename is not an absolute path */
698
if (G_LIKELY (!g_path_is_absolute (filename)))
700
/* try to lookup the filename in $PATH */
701
s = g_find_program_in_path (filename);
702
if (G_LIKELY (s != NULL))
109
/* casefold the search text */
110
normalized = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
111
text_casefolded = g_utf8_casefold (normalized, -1);
114
/* try the pre-build search string first */
115
gtk_tree_model_get (model, iter, COL_SEARCH, &string, -1);
116
if (!exo_str_is_empty (string))
119
visible = (strstr (string, text_casefolded) != NULL);
124
gtk_tree_model_get (model, iter, COL_NAME, &string, -1);
125
if (!exo_str_is_empty (string))
127
/* escape and casefold the name */
128
escaped = g_markup_escape_text (string, -1);
129
normalized = g_utf8_normalize (escaped, -1, G_NORMALIZE_ALL);
130
name_casefolded = g_utf8_casefold (normalized, -1);
135
visible = (strstr (name_casefolded, text_casefolded) != NULL);
137
/* store the generated search string */
138
gtk_list_store_set (GTK_LIST_STORE (model), iter, COL_SEARCH,
139
name_casefolded, -1);
141
g_free (name_casefolded);
145
g_free (text_casefolded);
154
launcher_dialog_add_store_insert (gpointer key,
161
GarconMenuItem *item = GARCON_MENU_ITEM (value);
162
GtkTreeModel *model = GTK_TREE_MODEL (user_data);
164
panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
165
panel_return_if_fail (GTK_IS_LIST_STORE (model));
167
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
168
launcher_dialog_items_set_item (model, &iter, item);
170
gfile = garcon_menu_item_get_file (item);
171
tooltip = g_file_get_parse_name (gfile);
172
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
173
COL_TOOLTIP, tooltip, -1);
174
g_object_unref (G_OBJECT (gfile));
181
launcher_dialog_add_populate_model_idle (gpointer user_data)
183
LauncherPluginDialog *dialog = user_data;
187
panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
189
GDK_THREADS_ENTER ();
191
/* load the item pool */
192
pool = launcher_plugin_garcon_menu_pool ();
194
/* insert the items in the store */
195
store = gtk_builder_get_object (dialog->builder, "add-store");
196
g_hash_table_foreach (pool, launcher_dialog_add_store_insert, store);
198
g_hash_table_destroy (pool);
200
GDK_THREADS_LEAVE ();
208
launcher_dialog_add_populate_model_idle_destroyed (gpointer user_data)
210
((LauncherPluginDialog *) user_data)->idle_populate_id = 0;
216
launcher_dialog_add_populate_model (LauncherPluginDialog *dialog)
220
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
222
/* get the store and make sure it's empty */
223
store = gtk_builder_get_object (dialog->builder, "add-store");
224
gtk_list_store_clear (GTK_LIST_STORE (store));
226
/* fire an idle menu system load */
227
if (G_LIKELY (dialog->idle_populate_id == 0))
228
dialog->idle_populate_id = g_idle_add_full (
229
G_PRIORITY_DEFAULT_IDLE,
230
launcher_dialog_add_populate_model_idle,
231
dialog, launcher_dialog_add_populate_model_idle_destroyed);
237
launcher_dialog_add_drag_data_get (GtkWidget *treeview,
238
GdkDragContext *drag_context,
239
GtkSelectionData *data,
242
LauncherPluginDialog *dialog)
244
GtkTreeSelection *selection;
248
GarconMenuItem *item;
252
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
253
panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
255
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
256
rows = gtk_tree_selection_get_selected_rows (selection, &model);
257
if (G_UNLIKELY (rows == NULL))
260
uris = g_new0 (gchar *, g_list_length (rows) + 1);
261
for (li = rows, i = 0; li != NULL; li = li->next)
263
if (!gtk_tree_model_get_iter (model, &iter, li->data))
266
gtk_tree_model_get (model, &iter, COL_ITEM, &item, -1);
267
if (G_UNLIKELY (item == NULL))
270
uris[i++] = garcon_menu_item_get_uri (item);
271
g_object_unref (G_OBJECT (item));
274
gtk_selection_data_set_uris (data, uris);
282
launcher_dialog_add_selection_changed (GtkTreeSelection *selection,
283
LauncherPluginDialog *dialog)
288
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
289
panel_return_if_fail (GTK_IS_TREE_SELECTION (selection));
291
object = gtk_builder_get_object (dialog->builder, "button-add");
292
sensitive = !!(gtk_tree_selection_count_selected_rows (selection) > 0);
293
gtk_widget_set_sensitive (GTK_WIDGET (object), sensitive);
299
launcher_dialog_add_button_press_event (GtkTreeView *treeview,
300
GdkEventButton *event,
301
LauncherPluginDialog *dialog)
303
panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
304
panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
306
if (event->button == 1
307
&& event->type == GDK_2BUTTON_PRESS
308
&& event->window == gtk_tree_view_get_bin_window (treeview)
309
&& gtk_tree_view_get_path_at_pos (treeview, event->x, event->y,
310
NULL, NULL, NULL, NULL))
311
return launcher_dialog_press_event (dialog, "button-add");
319
launcher_dialog_add_key_press_event (GtkTreeView *treeview,
321
LauncherPluginDialog *dialog)
323
panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
324
panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
326
if (event->keyval == GDK_Return
327
|| event->keyval == GDK_KP_Enter)
328
return launcher_dialog_press_event (dialog, "button-add");
336
launcher_dialog_add_response (GtkWidget *widget,
338
LauncherPluginDialog *dialog)
340
GObject *treeview, *store;
341
GtkTreeSelection *selection;
342
GtkTreeModel *item_model, *add_model;
343
GtkTreeIter iter, sibling, tmp;
344
GarconMenuItem *item;
347
panel_return_if_fail (GTK_IS_DIALOG (widget));
348
panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (dialog->plugin));
350
if (response_id != 0)
352
/* add all the selected rows in the add dialog */
353
treeview = gtk_builder_get_object (dialog->builder, "add-treeview");
354
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
355
list = gtk_tree_selection_get_selected_rows (selection, &add_model);
357
/* append after the selected item in the item dialog */
358
treeview = gtk_builder_get_object (dialog->builder, "item-treeview");
359
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
360
item_model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
361
if (gtk_tree_selection_get_selected (selection, NULL, &sibling))
362
gtk_list_store_insert_after (GTK_LIST_STORE (item_model),
365
gtk_list_store_append (GTK_LIST_STORE (item_model), &iter);
367
for (li = list; li != NULL; li = g_list_next (li))
369
/* get the selected file in the add dialog */
370
gtk_tree_model_get_iter (add_model, &tmp, li->data);
371
gtk_tree_model_get (add_model, &tmp, COL_ITEM, &item, -1);
373
/* insert the item in the item store */
374
if (G_LIKELY (item != NULL))
376
launcher_dialog_items_set_item (item_model, &iter, item);
377
g_object_unref (G_OBJECT (item));
379
/* select the first item */
381
gtk_tree_selection_select_iter (selection, &iter);
384
gtk_tree_path_free (li->data);
386
if (g_list_next (li) != NULL)
388
/* insert a new iter after the new added item */
390
gtk_list_store_insert_after (GTK_LIST_STORE (item_model),
397
/* write the model to xfconf */
398
launcher_dialog_tree_save (dialog);
400
/* update the selection */
401
launcher_dialog_tree_selection_changed (selection, dialog);
404
/* empty the store */
405
store = gtk_builder_get_object (dialog->builder, "add-store");
406
gtk_list_store_clear (GTK_LIST_STORE (store));
408
/* hide the dialog, since it's owned by gtkbuilder */
409
gtk_widget_hide (widget);
415
launcher_dialog_tree_save_foreach (GtkTreeModel *model,
420
GPtrArray *array = user_data;
422
GarconMenuItem *item;
424
/* get the desktop id of the item from the store */
425
gtk_tree_model_get (model, iter, COL_ITEM, &item, -1);
426
if (G_LIKELY (item != NULL))
428
/* create a value with the filename */
429
value = g_new0 (GValue, 1);
430
g_value_init (value, G_TYPE_STRING);
431
g_value_take_string (value, garcon_menu_item_get_uri (item));
433
/* put it in the array and release */
434
g_ptr_array_add (array, value);
435
g_object_unref (G_OBJECT (item));
444
launcher_dialog_tree_save (LauncherPluginDialog *dialog)
449
store = gtk_builder_get_object (dialog->builder, "item-store");
451
array = g_ptr_array_new ();
452
gtk_tree_model_foreach (GTK_TREE_MODEL (store),
453
launcher_dialog_tree_save_foreach, array);
455
g_object_set (dialog->plugin, "items", array, NULL);
456
xfconf_array_free (array);
462
launcher_dialog_tree_drag_data_received (GtkWidget *treeview,
463
GdkDragContext *context,
466
GtkSelectionData *data,
469
LauncherPluginDialog *dialog)
472
GtkTreeViewDropPosition drop_pos;
477
GarconMenuItem *item;
480
panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
481
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
483
uris = gtk_selection_data_get_uris (data);
484
if (G_LIKELY (uris == NULL))
486
gtk_drag_finish (context, FALSE, FALSE, timestamp);
490
/* get the insert position */
491
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
492
if (gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (treeview),
493
x, y, &path, &drop_pos))
495
position = gtk_tree_path_get_indices (path)[0];
496
gtk_tree_path_free (path);
497
if (drop_pos == GTK_TREE_VIEW_DROP_AFTER
498
|| drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
503
/* prepend at the end of the model */
504
position = gtk_tree_model_iter_n_children (model, NULL);
507
/* insert the uris */
508
for (i = 0; uris[i] != NULL; i++)
510
if (!g_str_has_suffix (uris[i], ".desktop"))
513
item = garcon_menu_item_new_for_uri (uris[i]);
514
if (G_UNLIKELY (item == NULL))
517
gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position);
518
launcher_dialog_items_set_item (model, &iter, item);
519
g_object_unref (G_OBJECT (item));
524
launcher_dialog_tree_save (dialog);
526
gtk_drag_finish (context, TRUE, FALSE, timestamp);
532
launcher_dialog_tree_selection_changed (GtkTreeSelection *selection,
533
LauncherPluginDialog *dialog)
538
gint n_children = -1;
542
GarconMenuItem *item = NULL;
543
gboolean editable = FALSE;
545
panel_return_if_fail (GTK_IS_TREE_SELECTION (selection));
546
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
548
if (gtk_tree_selection_get_selected (selection, &model, &iter))
550
/* get the number of launchers in the tree */
551
n_children = gtk_tree_model_iter_n_children (model, NULL);
553
/* get the position of the selected item in the tree */
554
path = gtk_tree_model_get_path (model, &iter);
555
position = gtk_tree_path_get_indices (path)[0];
556
gtk_tree_path_free (path);
558
gtk_tree_model_get (model, &iter, COL_ITEM, &item, -1);
559
if (G_LIKELY (item != NULL))
561
editable = launcher_plugin_item_is_editable (dialog->plugin, item, NULL);
562
g_object_unref (G_OBJECT (item));
566
/* update the sensitivity of the buttons */
567
object = gtk_builder_get_object (dialog->builder, "item-delete");
568
gtk_widget_set_sensitive (GTK_WIDGET (object), !!(n_children > 0));
570
object = gtk_builder_get_object (dialog->builder, "item-move-up");
571
sensitive = !!(position > 0 && position <= n_children);
572
gtk_widget_set_sensitive (GTK_WIDGET (object), sensitive);
574
object = gtk_builder_get_object (dialog->builder, "item-move-down");
575
sensitive = !!(position >= 0 && position < n_children - 1);
576
gtk_widget_set_sensitive (GTK_WIDGET (object), sensitive);
578
object = gtk_builder_get_object (dialog->builder, "item-edit");
579
gtk_widget_set_sensitive (GTK_WIDGET (object), editable);
581
object = gtk_builder_get_object (dialog->builder, "arrow-position");
582
gtk_widget_set_sensitive (GTK_WIDGET (object), n_children > 1);
584
object = gtk_builder_get_object (dialog->builder, "move-first");
585
gtk_widget_set_sensitive (GTK_WIDGET (object), n_children > 1);
587
object = gtk_builder_get_object (dialog->builder, "arrow-position-label");
588
gtk_widget_set_sensitive (GTK_WIDGET (object), n_children > 1);
594
launcher_dialog_press_event (LauncherPluginDialog *dialog,
595
const gchar *object_name)
599
panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
601
object = gtk_builder_get_object (dialog->builder, object_name);
602
panel_return_val_if_fail (GTK_IS_BUTTON (object), FALSE);
603
if (GTK_WIDGET_SENSITIVE (object))
605
gtk_button_clicked (GTK_BUTTON (object));
615
launcher_dialog_tree_button_press_event (GtkTreeView *treeview,
616
GdkEventButton *event,
617
LauncherPluginDialog *dialog)
619
panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
620
panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
622
if (event->button == 1 && event->type == GDK_2BUTTON_PRESS
623
&& event->window == gtk_tree_view_get_bin_window (treeview)
624
&& gtk_tree_view_get_path_at_pos (treeview, event->x, event->y,
625
NULL, NULL, NULL, NULL))
626
return launcher_dialog_press_event (dialog, "item-edit");
634
launcher_dialog_tree_key_press_event (GtkTreeView *treeview,
636
LauncherPluginDialog *dialog)
638
panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
639
panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
641
if (event->keyval == GDK_Return
642
|| event->keyval == GDK_KP_Enter)
643
return launcher_dialog_press_event (dialog, "item-edit");
651
launcher_dialog_item_button_clicked (GtkWidget *button,
652
LauncherPluginDialog *dialog)
655
const gchar *display_name = NULL;
658
GtkTreeSelection *selection;
660
GtkTreeIter iter_a, iter_b;
662
gchar *command, *uri;
664
GError *error = NULL;
665
GarconMenuItem *item;
671
panel_return_if_fail (GTK_IS_BUILDABLE (button));
672
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
674
/* name of the button */
675
name = gtk_buildable_get_name (GTK_BUILDABLE (button));
676
if (G_UNLIKELY (name == NULL))
679
if (strcmp (name, "item-add") == 0)
681
object = gtk_builder_get_object (dialog->builder, "dialog-add");
682
launcher_dialog_add_populate_model (dialog);
683
gtk_widget_show (GTK_WIDGET (object));
687
/* get the selected item in the tree, leave if none is found */
688
treeview = gtk_builder_get_object (dialog->builder, "item-treeview");
689
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
690
if (!gtk_tree_selection_get_selected (selection, &model, &iter_a)
691
&& strcmp (name, "item-new") != 0)
694
if (strcmp (name, "item-delete") == 0)
697
gtk_tree_model_get (model, &iter_a, COL_ITEM, &item, -1);
698
if (G_LIKELY (item != NULL))
699
display_name = garcon_menu_item_get_name (item);
702
toplevel = gtk_widget_get_toplevel (button);
703
if (xfce_dialog_confirm (GTK_WINDOW (toplevel), GTK_STOCK_DELETE, NULL,
704
_("If you delete an item, it will be permanently removed"),
705
_("Are you sure you want to remove \"%s\"?"),
706
exo_str_is_empty (display_name) ? _("Unnamed item") : display_name))
708
/* remove the item from the store */
709
gtk_list_store_remove (GTK_LIST_STORE (model), &iter_a);
711
/* delete the desktop file if possible */
713
&& launcher_plugin_item_is_editable (dialog->plugin, item, &can_delete)
704
/* use the absolute path instead */
716
item_file = garcon_menu_item_get_file (item);
717
if (!g_file_delete (item_file, NULL, &error))
719
toplevel = gtk_widget_get_toplevel (button);
720
xfce_dialog_show_error (GTK_WINDOW (toplevel), error,
721
_("Failed to remove the desktop file from the config directory"));
722
g_error_free (error);
724
g_object_unref (G_OBJECT (item_file));
710
/* check if we have an absolute path now */
711
if (G_LIKELY (g_path_is_absolute (filename)))
712
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), filename);
715
/* release the filename */
719
/* run the chooser dialog */
720
if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
722
/* get the filename and quote it */
723
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
724
s = g_shell_quote (filename);
728
/* set the new entry text */
729
gtk_entry_set_text (GTK_ENTRY (ld->entry_exec), filename);
736
gtk_widget_destroy (chooser);
742
launcher_dialog_icon_chooser (LauncherDialog *ld)
747
gboolean update_icon = FALSE;
749
/* determine the name of the entry being edited */
750
name = gtk_entry_get_text (GTK_ENTRY (ld->entry_name));
751
if (G_UNLIKELY (name == NULL || *name == '\0'))
754
title = g_strdup_printf (_("Select an Icon for \"%s\""), name);
755
chooser = exo_icon_chooser_dialog_new (title, NULL,
756
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
757
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
759
gtk_dialog_set_alternative_button_order (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT, GTK_RESPONSE_CANCEL, -1);
760
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
763
/* set the current icon, if there is any */
764
if (G_LIKELY (ld->entry->icon))
765
exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), ld->entry->icon);
767
/* run the icon chooser dialog */
768
if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
770
/* free the old icon name */
771
if (G_LIKELY (ld->entry->icon))
772
g_free (ld->entry->icon);
775
ld->entry->icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser));
777
#if LAUNCHER_NEW_TOOLTIP_API
778
/* release cached tooltip icon */
779
if (ld->entry->tooltip_cache)
781
g_object_unref (G_OBJECT (ld->entry->tooltip_cache));
782
ld->entry->tooltip_cache = NULL;
786
/* update the icon button */
787
launcher_dialog_update_icon (ld);
789
/* update the icon column in the tree */
790
launcher_dialog_tree_update_row (ld, COLUMN_ICON);
792
/* check if we need to update the icon button image */
793
if (g_list_index (ld->launcher->entries, ld->entry) == 0)
796
/* update the panel widgets */
797
launcher_plugin_rebuild (ld->launcher, update_icon);
800
/* destroy the chooser */
801
gtk_widget_destroy (chooser);
810
launcher_dialog_tree_update_row (LauncherDialog *ld,
813
GtkTreeSelection *selection;
815
GdkPixbuf *icon = NULL;
818
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
820
if (G_LIKELY (gtk_tree_selection_get_selected (selection, NULL, &iter)))
825
/* load entry icon */
826
icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), ld->entry->icon, LAUNCHER_TREE_ICON_SIZE);
829
gtk_list_store_set (ld->store, &iter,
834
if (G_LIKELY (icon != NULL))
835
g_object_unref (G_OBJECT (icon));
840
/* TRANSLATORS: Fallback name for a launcher item without a name */
841
name = ld->entry->name ? ld->entry->name : _("Unnamed");
844
gtk_list_store_set (ld->store, &iter,
856
launcher_dialog_tree_selection_changed (LauncherDialog *ld,
857
GtkTreeSelection *selection)
866
if (G_UNLIKELY (ld->updating == TRUE))
869
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
871
/* check if we have currently selected an item */
872
selected = gtk_tree_selection_get_selected (selection, &model, &iter);
874
if (G_LIKELY (selected))
876
/* determine the path for the selected iter */
877
path = gtk_tree_model_get_path (model, &iter);
880
position = gtk_tree_path_get_indices (path)[0];
882
/* set new active entry */
883
ld->entry = (LauncherEntry *) g_list_nth (ld->launcher->entries, position)->data;
886
launcher_dialog_update_entries (ld);
888
/* scroll new item to center of window */
889
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ld->treeview), path, NULL,
893
gtk_tree_path_free (path);
896
/* items in the list */
897
items = gtk_tree_model_iter_n_children (model, NULL);
899
/* change sensitivity of buttons */
900
gtk_widget_set_sensitive (ld->up, selected && (position > 0));
901
gtk_widget_set_sensitive (ld->down, selected && (position < items - 1));
902
gtk_widget_set_sensitive (ld->remove, selected && (items > 1));
908
launcher_dialog_tree_button_clicked (GtkWidget *button,
911
GtkTreeSelection *selection;
919
GdkPixbuf *icon = NULL;
920
LauncherEntry *entry;
921
gboolean update_icon = FALSE;
923
/* get the selected items in the treeview */
924
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
926
/* get selected iter, quit if no iter found */
927
if (G_UNLIKELY (gtk_tree_selection_get_selected (selection, &model, &iter_a) == FALSE))
930
/* run the requested button action */
931
if (button == ld->up)
934
path = gtk_tree_model_get_path (model, &iter_a);
936
/* position of the item in the list */
937
position = gtk_tree_path_get_indices (path)[0];
939
/* check if we need to update the icon button image */
943
/* get previous path */
944
if (G_LIKELY (gtk_tree_path_prev (path)))
946
/* get iter for previous item */
947
gtk_tree_model_get_iter (model, &iter_b, path);
949
/* swap the entries */
950
gtk_list_store_swap (ld->store, &iter_a, &iter_b);
952
/* swap items in the list */
953
li = g_list_nth (ld->launcher->entries, position);
954
launcher_dialog_g_list_swap (li, li->prev);
957
/* release the path */
958
gtk_tree_path_free (path);
960
/* update tree view */
961
launcher_dialog_tree_selection_changed (ld, selection);
963
else if (button == ld->down)
965
/* get path of selected item */
966
path = gtk_tree_model_get_path (model, &iter_a);
968
/* get position of item we're going to move */
969
position = gtk_tree_path_get_indices (path)[0];
971
/* check if we need to update the icon button image*/
975
/* get next item in the list */
976
gtk_tree_path_next (path);
979
if (G_LIKELY (gtk_tree_model_get_iter (model, &iter_b, path)))
981
/* swap the entries */
982
gtk_list_store_swap (ld->store, &iter_a, &iter_b);
984
/* swap items in the list */
985
li = g_list_nth (ld->launcher->entries, position);
986
launcher_dialog_g_list_swap (li, li->next);
989
/* release the path */
990
gtk_tree_path_free (path);
992
/* update tree view */
993
launcher_dialog_tree_selection_changed (ld, selection);
995
else if (button == ld->add)
997
/* create new entry */
998
entry = launcher_entry_new ();
1000
/* load new launcher icon */
1001
icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
1003
/* append new entry */
1004
gtk_list_store_insert_after (ld->store, &iter_b, &iter_a);
1005
gtk_list_store_set (ld->store, &iter_b,
1007
COLUMN_NAME, entry->name,
1010
/* release the pixbuf */
1011
if (G_LIKELY (icon != NULL))
1012
g_object_unref (G_OBJECT (icon));
1014
/* get path of new item */
1015
path = gtk_tree_model_get_path (model, &iter_b);
1017
/* position in the list */
1018
position = gtk_tree_path_get_indices (path)[0];
1020
/* insert in list */
1021
ld->launcher->entries = g_list_insert (ld->launcher->entries,
1024
/* select the new item (also updates treeview buttons) */
1025
gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
1028
gtk_tree_path_free (path);
1030
/* allow to set the arrow position */
1031
gtk_widget_set_sensitive (ld->arrow_position, TRUE);
1034
else if (button == ld->remove)
1036
/* path from row to remove */
1037
path = gtk_tree_model_get_path (model, &iter_a);
1039
/* get position of the item to remove */
1040
position = gtk_tree_path_get_indices (path)[0];
1042
/* check if we need to update the icon button image*/
1047
ld->updating = TRUE;
1049
/* remove active entry */
1050
launcher_entry_free (ld->entry, ld->launcher);
1053
/* remove row from store */
1054
gtk_list_store_remove (ld->store, &iter_a);
1057
ld->updating = FALSE;
1060
list_length = g_list_length (ld->launcher->entries);
1062
/* select previous item, if last item was removed */
1063
if (position >= (guint) list_length)
1064
gtk_tree_path_prev (path);
1066
/* select the new item (also updates treeview buttons) */
1067
gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
1070
gtk_tree_path_free (path);
1072
/* allow to set the arrow position */
1073
gtk_widget_set_sensitive (ld->arrow_position, list_length > 1);
1075
/* don't allow menu arrows */
1076
if (list_length == 1 && ld->launcher->arrow_position == LAUNCHER_ARROW_INSIDE_BUTTON)
1077
gtk_combo_box_set_active (GTK_COMBO_BOX (ld->arrow_position), LAUNCHER_ARROW_DEFAULT);
1081
launcher_plugin_rebuild (ld->launcher, update_icon);
1087
launcher_dialog_arrow_position_changed (GtkComboBox *combo,
1090
ld->launcher->arrow_position = gtk_combo_box_get_active (combo);
1092
launcher_plugin_rebuild (ld->launcher, TRUE);
1098
* Launcher dialog widgets
1101
launcher_dialog_add_properties (LauncherDialog *ld)
1103
GtkWidget *frame, *vbox, *hbox;
1104
GtkWidget *label, *button, *image;
1107
frame = gtk_frame_new (NULL);
1109
vbox = gtk_vbox_new (FALSE, BORDER);
1110
gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
1111
gtk_container_add (GTK_CONTAINER (frame), vbox);
1113
sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
1115
/* entry name field */
1116
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1117
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1119
label = gtk_label_new_with_mnemonic (_("_Name:"));
1120
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1121
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1123
gtk_size_group_add_widget (sg, label);
1125
ld->entry_name = gtk_entry_new ();
1126
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_name, TRUE, TRUE, 0);
1128
gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_name);
1130
g_signal_connect (G_OBJECT (ld->entry_name), "changed",
1131
G_CALLBACK (launcher_dialog_save_entry), ld);
1133
/* entry comment field */
1134
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1135
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1137
label = gtk_label_new_with_mnemonic (_("_Description:"));
1138
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1139
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1141
gtk_size_group_add_widget (sg, label);
1143
ld->entry_comment = gtk_entry_new ();
1144
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_comment, TRUE, TRUE, 0);
1145
gtk_widget_set_size_request (ld->entry_comment, 300, -1);
1147
gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_comment);
1149
g_signal_connect (G_OBJECT (ld->entry_comment), "changed",
1150
G_CALLBACK (launcher_dialog_save_entry), ld);
1152
/* entry icon chooser button */
1153
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1154
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1156
label = gtk_label_new_with_mnemonic (_("_Icon:"));
1157
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1158
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1160
gtk_size_group_add_widget (sg, label);
1162
ld->entry_icon = gtk_button_new ();
1163
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_icon, FALSE, FALSE, 0);
1165
gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_icon);
1167
g_signal_connect_swapped (G_OBJECT (ld->entry_icon), "clicked",
1168
G_CALLBACK (launcher_dialog_icon_chooser), ld);
1170
/* entry command field and button */
1171
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1172
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1174
label = gtk_label_new_with_mnemonic (_("Co_mmand:"));
1175
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1176
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1178
gtk_size_group_add_widget (sg, label);
1180
ld->entry_exec = gtk_entry_new ();
1181
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_exec, TRUE, TRUE, 0);
1183
gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_exec);
1185
g_signal_connect (G_OBJECT (ld->entry_exec), "changed",
1186
G_CALLBACK (launcher_dialog_save_entry), ld);
1188
button = gtk_button_new ();
1189
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1191
g_signal_connect_swapped (G_OBJECT (button), "clicked",
1192
G_CALLBACK (launcher_dialog_command_chooser), ld);
1194
image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
1195
gtk_container_add (GTK_CONTAINER (button), image);
1197
/* working directory field */
1198
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1199
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1201
label = gtk_label_new_with_mnemonic (_("_Working Directory:"));
1202
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1203
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1205
gtk_size_group_add_widget (sg, label);
1207
ld->entry_path = gtk_file_chooser_button_new (_("Select a Working Directory"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
1208
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_path, TRUE, TRUE, 0);
1209
gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_path);
1211
#if 0 /* GTK_CHECK_VERSION (2, 12, 0) */
1212
g_signal_connect (G_OBJECT (ld->entry_path), "file-set",
1213
G_CALLBACK (launcher_dialog_save_entry), ld);
1215
g_signal_connect (G_OBJECT (ld->entry_path), "selection-changed",
1216
G_CALLBACK (launcher_dialog_save_entry), ld);
1219
/* entry terminal toggle button with spacer */
1220
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1221
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1223
label = gtk_alignment_new (0, 0, 0, 0);
1224
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1226
gtk_size_group_add_widget (sg, label);
1228
ld->entry_terminal = gtk_check_button_new_with_mnemonic (_("Run in _terminal"));
1229
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_terminal, TRUE, TRUE, 0);
1231
g_signal_connect (G_OBJECT (ld->entry_terminal), "toggled",
1232
G_CALLBACK (launcher_dialog_save_button), ld);
1234
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
1235
/* startup notification */
1236
hbox = gtk_hbox_new (FALSE, BORDER * 2);
1237
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1239
label = gtk_alignment_new (0, 0, 0, 0);
1240
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1242
gtk_size_group_add_widget (sg, label);
1244
ld->entry_startup = gtk_check_button_new_with_mnemonic (_("Use _startup notification"));
1245
gtk_box_pack_start (GTK_BOX (hbox), ld->entry_startup, TRUE, TRUE, 0);
1247
g_signal_connect (G_OBJECT (ld->entry_startup), "toggled",
1248
G_CALLBACK (launcher_dialog_save_button), ld);
1251
/* release size group */
1252
g_object_unref (G_OBJECT (sg));
1254
/* setup dnd in frame */
1255
gtk_drag_dest_set (frame, GTK_DEST_DEFAULT_ALL,
1256
drop_targets, G_N_ELEMENTS (drop_targets),
1259
g_signal_connect (frame, "drag-data-received",
1260
G_CALLBACK (launcher_dialog_frame_drag_data_received), ld);
1269
launcher_dialog_add_tree (LauncherDialog *ld)
1272
GtkTreeViewColumn *column;
1273
GtkTreeSelection *selection;
1274
GtkCellRenderer *renderer;
1277
LauncherEntry *entry;
1281
/* scrolled window */
1282
scroll = gtk_scrolled_window_new (NULL, NULL);
1283
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
1285
GTK_POLICY_AUTOMATIC);
1286
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
1289
/* create new list store */
1290
ld->store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
1292
/* create tree view */
1293
ld->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (ld->store));
1294
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ld->treeview), FALSE);
1295
gtk_tree_view_set_search_column (GTK_TREE_VIEW (ld->treeview), COLUMN_NAME);
1296
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (ld->treeview), TRUE);
1297
gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (ld->treeview), TRUE);
1298
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (ld->treeview), TRUE);
1299
gtk_container_add (GTK_CONTAINER (scroll), ld->treeview);
1301
/* create columns and cell renders */
1302
column = gtk_tree_view_column_new ();
1303
gtk_tree_view_column_set_expand (column, TRUE);
1304
gtk_tree_view_column_set_resizable (column, FALSE);
1305
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
1306
gtk_tree_view_append_column (GTK_TREE_VIEW (ld->treeview), column);
1308
renderer = gtk_cell_renderer_pixbuf_new();
1309
gtk_cell_renderer_set_fixed_size (renderer, LAUNCHER_TREE_ICON_SIZE, LAUNCHER_TREE_ICON_SIZE);
1310
gtk_tree_view_column_pack_start (column, renderer, FALSE);
1311
gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COLUMN_ICON, NULL);
1313
renderer = gtk_cell_renderer_text_new ();
1314
gtk_tree_view_column_pack_start (column, renderer, TRUE);
1315
gtk_tree_view_column_set_attributes (column, renderer, "text", COLUMN_NAME, NULL);
1316
g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
1318
/* set selection change signal */
1319
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
1320
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
1321
g_signal_connect_swapped (G_OBJECT (selection), "changed",
1322
G_CALLBACK (launcher_dialog_tree_selection_changed), ld);
1324
/* append current items */
1325
for (li = ld->launcher->entries; li != NULL; li = li->next)
1329
if (G_LIKELY (entry))
1332
icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
1334
name = entry->name ? entry->name : _("Unnamed");
1336
/* create new row and add the data */
1337
gtk_list_store_append (ld->store, &iter);
1338
gtk_list_store_set (ld->store, &iter,
1340
COLUMN_NAME, name, -1);
1342
/* release the pixbuf */
1343
if (G_LIKELY (icon))
1344
g_object_unref (G_OBJECT (icon));
1349
gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (ld->treeview),
1350
drop_targets, G_N_ELEMENTS (drop_targets),
1353
g_signal_connect (G_OBJECT (ld->treeview), "drag-data-received",
1354
G_CALLBACK (launcher_dialog_tree_drag_data_received), ld);
1362
launcher_dialog_add_tree_buttons (LauncherDialog *ld)
1364
GtkWidget *hbox, *button, *align, *image;
1366
hbox = gtk_hbox_new (FALSE, BORDER);
1369
ld->up = button = gtk_button_new ();
1370
gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
1371
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1373
image = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
1374
gtk_container_add (GTK_CONTAINER (button), image);
1376
g_signal_connect (G_OBJECT (button), "clicked",
1377
G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1379
gtk_widget_set_sensitive (button, FALSE);
1382
ld->down = button = gtk_button_new ();
1383
gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
1384
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1386
image = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON);
1387
gtk_container_add (GTK_CONTAINER (button), image);
1389
g_signal_connect (G_OBJECT (button), "clicked",
1390
G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1392
gtk_widget_set_sensitive (button, FALSE);
1394
/* free space between buttons */
1395
align = gtk_alignment_new (0, 0, 0, 0);
1396
gtk_widget_set_size_request (align, 1, 1);
1397
gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0);
1400
ld->add = button = gtk_button_new ();
1401
gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
1402
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1404
image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
1405
gtk_container_add (GTK_CONTAINER (button), image);
1407
g_signal_connect (G_OBJECT (button), "clicked",
1408
G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1411
ld->remove = button = gtk_button_new ();
1412
gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
1413
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1415
image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON);
1416
gtk_container_add (GTK_CONTAINER (button), image);
1418
g_signal_connect (G_OBJECT (button), "clicked",
1419
G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1421
gtk_widget_set_sensitive (button, FALSE);
1432
launcher_dialog_response (GtkWidget *dialog,
1436
LauncherPlugin *launcher = ld->launcher;
1438
/* hide the dialog */
1439
gtk_widget_hide (dialog);
1441
/* lock for further updates */
1442
ld->updating = TRUE;
1445
/* cleanup the store */
1446
gtk_list_store_clear (ld->store);
1447
g_object_unref (G_OBJECT (ld->store));
1449
/* the launcher dialog dataS */
1450
g_object_set_data (G_OBJECT (launcher->panel_plugin), I_("launcher-dialog"), NULL);
1452
/* destroy the dialog */
1453
gtk_widget_destroy (dialog);
1455
/* unlock plugin menu */
1456
xfce_panel_plugin_unblock_menu (launcher->panel_plugin);
1458
/* restore move first */
1459
launcher->move_first = ld->stored_move_first;
1461
/* allow saving again */
1462
launcher->plugin_can_save = TRUE;
1464
if (response == GTK_RESPONSE_OK)
1466
/* write new settings */
1467
launcher_plugin_save (launcher);
1469
else /* revert changes */
1471
/* remove all the entries */
1472
g_list_foreach (launcher->entries, (GFunc) launcher_entry_free, launcher);
1474
/* read the last saved settings */
1475
launcher_plugin_read (launcher);
1477
/* add new item if there are no entries yet */
1478
if (G_UNLIKELY (g_list_length (launcher->entries) == 0))
1479
launcher->entries = g_list_append (launcher->entries, launcher_entry_new ());
1481
/* rebuild the plugin */
1482
launcher_plugin_rebuild (launcher, TRUE);
1485
/* free the panel structure */
1486
panel_slice_free (LauncherDialog, ld);
728
if (G_LIKELY (item != NULL))
729
g_object_unref (G_OBJECT (item));
731
else if (strcmp (name, "item-new") == 0
732
|| strcmp (name, "item-edit") == 0)
734
if (strcmp (name, "item-edit") == 0)
736
gtk_tree_model_get (model, &iter_a, COL_ITEM, &item, -1);
737
if (G_UNLIKELY (item == NULL))
741
uri = garcon_menu_item_get_uri (item);
742
command = g_strdup_printf ("exo-desktop-item-edit --xid=%d '%s'",
743
LAUNCHER_WIDGET_XID (button), uri);
749
filename = launcher_plugin_unique_filename (dialog->plugin);
750
command = g_strdup_printf ("exo-desktop-item-edit -c --xid=%d '%s'",
751
LAUNCHER_WIDGET_XID (button), filename);
755
/* spawn item editor */
756
screen = gtk_widget_get_screen (button);
757
if (!gdk_spawn_command_line_on_screen (screen, command, &error))
759
toplevel = gtk_widget_get_toplevel (button);
760
xfce_dialog_show_error (GTK_WINDOW (toplevel), error,
761
_("Failed to open desktop item editor"));
762
g_error_free (error);
767
else if (strcmp (name, "item-move-up") == 0)
769
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter_a);
770
if (gtk_tree_path_prev (path)
771
&& gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter_b, path))
772
gtk_list_store_swap (GTK_LIST_STORE (model), &iter_a, &iter_b);
773
gtk_tree_path_free (path);
775
else if (strcmp (name, "item-move-down") == 0)
778
if (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter_b))
779
gtk_list_store_swap (GTK_LIST_STORE (model), &iter_a, &iter_b);
783
panel_assert_not_reached ();
786
/* store the new settings */
787
launcher_dialog_tree_save (dialog);
789
/* emit a changed signal to update the button states */
790
launcher_dialog_tree_selection_changed (selection, dialog);
797
launcher_dialog_response (GtkWidget *widget,
799
LauncherPluginDialog *dialog)
803
panel_return_if_fail (GTK_IS_DIALOG (widget));
804
panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (dialog->plugin));
805
panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
807
if (G_UNLIKELY (response_id == 1))
813
/* stop idle if still running */
814
if (G_UNLIKELY (dialog->idle_populate_id != 0))
815
g_source_remove (dialog->idle_populate_id);
817
/* disconnect from items-changed signal */
818
g_signal_handlers_disconnect_by_func (G_OBJECT (dialog->plugin),
819
G_CALLBACK (launcher_dialog_items_load), dialog);
821
/* disconnect from the menu items */
822
launcher_dialog_items_unload (dialog);
824
/* also destroy the add dialog */
825
add_dialog = gtk_builder_get_object (dialog->builder, "dialog-add");
826
gtk_widget_destroy (GTK_WIDGET (add_dialog));
828
/* destroy the dialog */
829
gtk_widget_destroy (widget);
831
g_slice_free (LauncherPluginDialog, dialog);
838
launcher_dialog_item_changed_foreach (GtkTreeModel *model,
843
GarconMenuItem *item;
846
panel_return_val_if_fail (GARCON_IS_MENU_ITEM (user_data), TRUE);
848
/* check if this is the item in the model */
849
gtk_tree_model_get (model, iter, COL_ITEM, &item, -1);
850
found = item == user_data;
852
if (G_UNLIKELY (found))
853
launcher_dialog_items_set_item (model, iter, item);
855
g_object_unref (G_OBJECT (item));
863
launcher_dialog_item_changed (GarconMenuItem *item,
864
LauncherPluginDialog *dialog)
869
panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
871
treeview = gtk_builder_get_object (dialog->builder, "item-treeview");
872
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
874
/* find the item in the model and update it */
875
gtk_tree_model_foreach (model, launcher_dialog_item_changed_foreach, item);
881
launcher_dialog_items_set_item (GtkTreeModel *model,
883
GarconMenuItem *item)
885
const gchar *name, *comment;
888
panel_return_if_fail (GTK_IS_LIST_STORE (model));
889
panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
891
name = garcon_menu_item_get_name (item);
892
comment = garcon_menu_item_get_comment (item);
894
if (!exo_str_is_empty (comment))
895
markup = g_markup_printf_escaped ("<b>%s</b>\n%s", name, comment);
897
markup = g_markup_printf_escaped ("<b>%s</b>", name);
899
gtk_list_store_set (GTK_LIST_STORE (model), iter,
900
COL_ICON, garcon_menu_item_get_icon_name (item),
911
launcher_dialog_items_unload (LauncherPluginDialog *dialog)
915
for (li = dialog->items; li != NULL; li = li->next)
917
panel_return_if_fail (GARCON_IS_MENU_ITEM (li->data));
918
g_signal_handlers_disconnect_by_func (G_OBJECT (li->data),
919
G_CALLBACK (launcher_dialog_item_changed), dialog);
920
g_object_unref (G_OBJECT (li->data));
923
g_slist_free (dialog->items);
924
dialog->items = NULL;
930
launcher_dialog_items_load (LauncherPluginDialog *dialog)
933
GtkTreeSelection *selection;
939
/* get the treeview */
940
treeview = gtk_builder_get_object (dialog->builder, "item-treeview");
941
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
943
/* we try to preserve the current selection */
944
if (gtk_tree_selection_get_selected (selection, &model, &iter))
945
path = gtk_tree_model_get_path (model, &iter);
949
/* clear the old items */
950
launcher_dialog_items_unload (dialog);
951
gtk_list_store_clear (GTK_LIST_STORE (model));
953
/* insert the launcher items */
954
dialog->items = launcher_plugin_get_items (dialog->plugin);
955
for (li = dialog->items; li != NULL; li = li->next)
957
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
958
launcher_dialog_items_set_item (model, &iter, GARCON_MENU_ITEM (li->data));
959
g_signal_connect (G_OBJECT (li->data), "changed",
960
G_CALLBACK (launcher_dialog_item_changed), dialog);
963
if (G_LIKELY (path != NULL))
965
/* restore the old selection */
966
gtk_tree_selection_select_path (selection, path);
967
gtk_tree_path_free (path);
969
else if (gtk_tree_model_get_iter_first (model, &iter))
971
/* select the first item */
972
gtk_tree_selection_select_iter (selection, &iter);
1492
launcher_dialog_show (LauncherPlugin *launcher)
979
launcher_dialog_show (LauncherPlugin *plugin)
1496
GtkWidget *dialog_vbox;
1497
GtkWidget *paned, *vbox, *hbox;
1498
GtkWidget *widget, *label, *combo;
1501
/* create new structure */
1502
ld = panel_slice_new0 (LauncherDialog);
1505
ld->launcher = launcher;
1506
ld->entry = g_list_first (launcher->entries)->data;
1508
/* prevent saving to be able to use the cancel button */
1509
launcher->plugin_can_save = FALSE;
1511
/* lock right-click plugin menu */
1512
xfce_panel_plugin_block_menu (launcher->panel_plugin);
1514
/* disable the auto sort of the list, while working in properties */
1515
ld->stored_move_first = launcher->move_first;
1516
launcher->move_first = FALSE;
1518
dialog = xfce_titled_dialog_new_with_buttons (_("Launcher"),
1520
GTK_DIALOG_NO_SEPARATOR,
1521
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1522
GTK_STOCK_OK, GTK_RESPONSE_OK,
1524
gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (GTK_WIDGET (launcher->panel_plugin)));
1525
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
1526
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
1527
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
1529
/* connect dialog to plugin, so we can destroy it when plugin is closed */
1530
g_object_set_data (G_OBJECT (ld->launcher->panel_plugin), "dialog", dialog);
1532
dialog_vbox = GTK_DIALOG (dialog)->vbox;
1534
/* added the horizontal panes */
1535
paned = gtk_hpaned_new ();
1536
gtk_box_pack_start (GTK_BOX (dialog_vbox), paned, TRUE, TRUE, 0);
1537
gtk_container_set_border_width (GTK_CONTAINER (paned), BORDER);
1539
vbox = gtk_vbox_new (FALSE, BORDER);
1540
gtk_paned_pack1 (GTK_PANED (paned), vbox, FALSE, FALSE);
1542
/* arrow button position */
1543
hbox = gtk_hbox_new (FALSE, BORDER);
1544
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1546
/* TRANSLATORS: Arrow position for a launcher with > 1 item. Keep this
1547
string as short as possible. */
1548
label = gtk_label_new_with_mnemonic (_("A_rrow:"));
1549
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1551
ld->arrow_position = combo = gtk_combo_box_new_text ();
1552
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
1553
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
1554
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Default"));
1555
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Left"));
1556
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Right"));
1557
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Top"));
1558
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Bottom"));
1559
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Inside Button"));
1560
gtk_widget_set_sensitive (combo, g_list_length (launcher->entries) > 1);
1561
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), launcher->arrow_position);
1562
g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (launcher_dialog_arrow_position_changed), ld);
1563
gtk_widget_show (combo);
1565
/* add the entries list */
1566
widget = launcher_dialog_add_tree (ld);
1567
gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
1569
/* add the tree navigation buttons */
1570
widget = launcher_dialog_add_tree_buttons (ld);
1571
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
1573
/* add the entry widgets */
1574
widget = launcher_dialog_add_properties (ld);
1575
gtk_paned_pack2 (GTK_PANED (paned), widget, TRUE, FALSE);
1577
/* show all widgets inside dialog */
1578
gtk_widget_show_all (dialog_vbox);
1580
/* focus the title entry */
1581
gtk_widget_grab_focus (ld->entry_name);
1583
/* select first item in the tree (this also updates the fields) */
1584
path = gtk_tree_path_new_first ();
1585
gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
1586
gtk_tree_path_free (path);
1588
/* connect response signal */
1589
g_signal_connect (G_OBJECT (dialog), "response",
1590
G_CALLBACK (launcher_dialog_response), ld);
1592
/* show the dialog */
1593
gtk_widget_show (dialog);
981
LauncherPluginDialog *dialog;
983
GObject *window, *object, *item;
985
GtkTreeSelection *selection;
986
const gchar *button_names[] = { "item-add", "item-delete",
987
"item-move-up", "item-move-down",
988
"item-edit", "item-new" };
989
const gchar *binding_names[] = { "disable-tooltips", "show-label",
990
"move-first", "arrow-position" };
992
panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
994
/* setup the dialog */
996
builder = panel_utils_builder_new (XFCE_PANEL_PLUGIN (plugin), launcher_dialog_ui,
997
launcher_dialog_ui_length, &window);
998
if (G_UNLIKELY (builder == NULL))
1001
/* create structure */
1002
dialog = g_slice_new0 (LauncherPluginDialog);
1003
dialog->builder = builder;
1004
dialog->plugin = plugin;
1005
dialog->items = NULL;
1007
g_signal_connect (G_OBJECT (window), "response",
1008
G_CALLBACK (launcher_dialog_response), dialog);
1010
/* connect item buttons */
1011
for (i = 0; i < G_N_ELEMENTS (button_names); i++)
1013
object = gtk_builder_get_object (builder, button_names[i]);
1014
panel_return_if_fail (GTK_IS_WIDGET (object));
1015
g_signal_connect (G_OBJECT (object), "clicked",
1016
G_CALLBACK (launcher_dialog_item_button_clicked), dialog);
1019
/* setup treeview selection */
1020
object = gtk_builder_get_object (builder, "item-treeview");
1021
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (object));
1022
gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (object),
1023
dnd_targets, G_N_ELEMENTS (dnd_targets), GDK_ACTION_COPY);
1024
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1025
g_signal_connect (G_OBJECT (object), "drag-data-received",
1026
G_CALLBACK (launcher_dialog_tree_drag_data_received), dialog);
1027
g_signal_connect (G_OBJECT (selection), "changed",
1028
G_CALLBACK (launcher_dialog_tree_selection_changed), dialog);
1029
launcher_dialog_tree_selection_changed (selection, dialog);
1030
g_signal_connect (G_OBJECT (object), "button-press-event",
1031
G_CALLBACK (launcher_dialog_tree_button_press_event), dialog);
1032
g_signal_connect (G_OBJECT (object), "key-press-event",
1033
G_CALLBACK (launcher_dialog_tree_key_press_event), dialog);
1035
/* connect bindings to the advanced properties */
1036
for (i = 0; i < G_N_ELEMENTS (binding_names); i++)
1038
object = gtk_builder_get_object (builder, binding_names[i]);
1039
panel_return_if_fail (GTK_IS_WIDGET (object));
1040
exo_mutual_binding_new (G_OBJECT (plugin), binding_names[i],
1041
G_OBJECT (object), "active");
1044
/* setup responses for the add dialog */
1045
object = gtk_builder_get_object (builder, "dialog-add");
1046
g_signal_connect (G_OBJECT (object), "response",
1047
G_CALLBACK (launcher_dialog_add_response), dialog);
1048
g_signal_connect (G_OBJECT (object), "delete-event",
1049
G_CALLBACK (gtk_widget_hide_on_delete), NULL);
1051
/* setup sorting in the add dialog */
1052
object = gtk_builder_get_object (builder, "add-store");
1053
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (object),
1054
COL_NAME, GTK_SORT_ASCENDING);
1056
/* allow selecting multiple items in the add dialog */
1057
object = gtk_builder_get_object (builder, "add-treeview");
1058
gtk_drag_source_set (GTK_WIDGET (object), GDK_BUTTON1_MASK,
1059
dnd_targets, G_N_ELEMENTS (dnd_targets), GDK_ACTION_COPY);
1060
g_signal_connect (G_OBJECT (object), "drag-data-get",
1061
G_CALLBACK (launcher_dialog_add_drag_data_get), dialog);
1062
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (object));
1063
gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1064
g_signal_connect (G_OBJECT (selection), "changed",
1065
G_CALLBACK (launcher_dialog_add_selection_changed), dialog);
1066
g_signal_connect (G_OBJECT (object), "button-press-event",
1067
G_CALLBACK (launcher_dialog_add_button_press_event), dialog);
1068
g_signal_connect (G_OBJECT (object), "key-press-event",
1069
G_CALLBACK (launcher_dialog_add_key_press_event), dialog);
1071
/* setup search filter in the add dialog */
1072
object = gtk_builder_get_object (builder, "add-store-filter");
1073
item = gtk_builder_get_object (builder, "add-search");
1074
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (object),
1075
launcher_dialog_add_visible_function, item, NULL);
1076
g_signal_connect_swapped (G_OBJECT (item), "changed",
1077
G_CALLBACK (gtk_tree_model_filter_refilter), object);
1079
/* setup the icon size in the icon renderers */
1080
object = gtk_builder_get_object (builder, "addrenderericon");
1081
g_object_set (G_OBJECT (object), "stock-size", GTK_ICON_SIZE_DND, NULL);
1082
object = gtk_builder_get_object (builder, "itemrenderericon");
1083
g_object_set (G_OBJECT (object), "stock-size", GTK_ICON_SIZE_DND, NULL);
1085
/* load the plugin items */
1086
launcher_dialog_items_load (dialog);
1087
g_signal_connect_swapped (G_OBJECT (plugin), "items-changed",
1088
G_CALLBACK (launcher_dialog_items_load), dialog);
1090
/* show the dialog */
1091
gtk_widget_show (GTK_WIDGET (window));