~ubuntu-branches/ubuntu/natty/xfce4-panel/natty

« back to all changes in this revision

Viewing changes to plugins/launcher/launcher-dialog.c

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Le Folgoc
  • Date: 2010-12-04 15:45:53 UTC
  • mfrom: (1.1.25 upstream)
  • Revision ID: james.westby@ubuntu.com-20101204154553-c1k0n2p2j83chld0
Tags: 4.7.5-0ubuntu1
Upload to natty (pkg-xfce svn r4611).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  $Id$
2
 
 *
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>
6
 
 *
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.
11
 
 *
12
 
 *  This program is distributed in the hope that it will be useful,
13
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *  GNU Library General Public License for more details.
16
 
 *
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.
 
1
/*
 
2
 * Copyright (C) 2008-2009 Nick Schermer <nick@xfce.org>
 
3
 *
 
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)
 
7
 * any later version.
 
8
 *
 
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
 
12
 * more details.
 
13
 *
 
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
20
17
 */
21
18
 
22
19
#ifdef HAVE_CONFIG_H
23
20
#include <config.h>
24
21
#endif
25
 
#ifdef HAVE_MEMORY_H
26
 
#include <memory.h>
27
 
#endif
 
22
 
28
23
#ifdef HAVE_STRING_H
29
24
#include <string.h>
30
25
#endif
31
26
 
32
 
#include <libxfcegui4/xfce-titled-dialog.h>
33
 
#include <libxfce4panel/xfce-panel-plugin.h>
 
27
#include <exo/exo.h>
 
28
#include <libxfce4ui/libxfce4ui.h>
 
29
#include <libxfce4util/libxfce4util.h>
 
30
#include <garcon/garcon.h>
 
31
#include <xfconf/xfconf.h>
 
32
#include <gio/gio.h>
 
33
#include <gdk/gdkkeysyms.h>
 
34
 
 
35
#include <common/panel-private.h>
 
36
#include <common/panel-utils.h>
34
37
 
35
38
#include "launcher.h"
36
39
#include "launcher-dialog.h"
37
 
 
 
40
#include "launcher-dialog_ui.h"
 
41
 
 
42
#ifdef GDK_WINDOWING_X11
 
43
#include <gdk/gdkx.h>
 
44
#define LAUNCHER_WIDGET_XID(widget) ((gint) GDK_WINDOW_XID (GDK_WINDOW ((widget)->window)))
 
45
#else
 
46
#define LAUNCHER_WIDGET_XID(widget) (0)
 
47
#endif
 
48
 
 
49
 
 
50
 
 
51
typedef struct
 
52
{
 
53
  LauncherPlugin *plugin;
 
54
  GtkBuilder     *builder;
 
55
  guint           idle_populate_id;
 
56
  GSList         *items;
 
57
}
 
58
LauncherPluginDialog;
38
59
 
39
60
enum
40
61
{
41
 
    COLUMN_ICON = 0,
42
 
    COLUMN_NAME
43
 
};
44
 
 
45
 
typedef struct _LauncherDialog LauncherDialog;
46
 
 
47
 
struct _LauncherDialog
48
 
{
49
 
    LauncherPlugin *launcher;
50
 
 
51
 
    /* stored setting */
52
 
    guint           stored_move_first : 1;
53
 
 
54
 
    /* arrow position */
55
 
    GtkWidget      *arrow_position;
56
 
 
57
 
    /* entries list */
58
 
    GtkWidget      *treeview;
59
 
    GtkListStore   *store;
60
 
 
61
 
    /* tree buttons */
62
 
    GtkWidget      *up;
63
 
    GtkWidget      *down;
64
 
    GtkWidget      *add;
65
 
    GtkWidget      *remove;
66
 
 
67
 
    /* lock */
68
 
    guint           updating : 1;
69
 
 
70
 
    /* active entry */
71
 
    LauncherEntry  *entry;
72
 
 
73
 
    /* entry widgets */
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;
82
 
#endif
83
 
};
84
 
 
85
 
 
86
 
 
87
 
/**
88
 
 * Prototypes
89
 
 **/
90
 
static void        launcher_dialog_g_list_swap               (GList                 *li_a,
91
 
                                                              GList                 *li_b);
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,
96
 
                                                              gint                   x,
97
 
                                                              gint                   y,
98
 
                                                              GtkSelectionData      *selection_data,
99
 
                                                              guint                  info,
100
 
                                                              guint                  time,
101
 
                                                              LauncherDialog        *ld);
102
 
static void        launcher_dialog_frame_drag_data_received  (GtkWidget             *widget,
103
 
                                                              GdkDragContext        *context,
104
 
                                                              gint                   x,
105
 
                                                              gint                   y,
106
 
                                                              GtkSelectionData      *selection_data,
107
 
                                                              guint                  info,
108
 
                                                              guint                  time,
109
 
                                                              LauncherDialog        *ld);
110
 
static void        launcher_dialog_save_entry                (GtkWidget             *entry,
111
 
                                                               LauncherDialog        *ld);
112
 
static void        launcher_dialog_save_button               (GtkWidget             *button,
113
 
                                                              LauncherDialog        *ld);
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,
119
 
                                                              gint                   column);
120
 
static void        launcher_dialog_tree_selection_changed    (LauncherDialog        *ld,
121
 
                                                              GtkTreeSelection      *selection);
122
 
static void        launcher_dialog_tree_button_clicked       (GtkWidget             *button,
123
 
                                                              LauncherDialog        *ld);
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,
128
 
                                                              gint                   response,
129
 
                                                              LauncherDialog        *ld);
130
 
 
131
 
 
132
 
 
133
 
/**
134
 
 * .Desktop entry
135
 
 **/
136
 
static void
137
 
launcher_dialog_g_list_swap (GList *li_a,
138
 
                             GList *li_b)
139
 
{
140
 
    gpointer data;
141
 
 
142
 
    /* swap the data pointers */
143
 
    data = li_a->data;
144
 
    li_a->data = li_b->data;
145
 
    li_b->data = data;
146
 
}
 
62
  COL_ICON,
 
63
  COL_NAME,
 
64
  COL_ITEM,
 
65
  COL_SEARCH,
 
66
  COL_TOOLTIP
 
67
};
 
68
 
 
69
 
 
70
 
 
71
static void     launcher_dialog_items_set_item         (GtkTreeModel         *model,
 
72
                                                        GtkTreeIter          *iter,
 
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);
 
81
 
 
82
 
 
83
 
 
84
/* dnd for items in and from the treeviews */
 
85
static const GtkTargetEntry dnd_targets[] =
 
86
{
 
87
  { "text/uri-list", 0, 0, },
 
88
};
 
89
 
147
90
 
148
91
 
149
92
static gboolean
150
 
launcher_dialog_read_desktop_file (const gchar   *path,
151
 
                                   LauncherEntry *entry)
 
93
launcher_dialog_add_visible_function (GtkTreeModel *model,
 
94
                                      GtkTreeIter  *iter,
 
95
                                      gpointer      user_data)
152
96
{
153
 
    XfceRc      *rc = NULL;
154
 
    const gchar *value = NULL;
155
 
    const gchar *p;
156
 
 
157
 
    /* we only support .desktop files */
158
 
    if (G_UNLIKELY (g_str_has_suffix (path, ".desktop") == FALSE ||
159
 
                    g_path_is_absolute (path) == FALSE))
160
 
        return FALSE;
161
 
 
162
 
    /* open de .desktop file */
163
 
    rc = xfce_rc_simple_open (path, TRUE);
164
 
    if (G_UNLIKELY (rc == NULL))
165
 
        return FALSE;
166
 
 
167
 
    /* set the desktop entry group */
168
 
    xfce_rc_set_group (rc, "Desktop Entry");
169
 
 
170
 
    /* name */
171
 
    value = xfce_rc_read_entry (rc, "Name", NULL);
172
 
    if (G_LIKELY (value != NULL))
173
 
    {
174
 
        g_free (entry->name);
175
 
        entry->name = g_strdup (value);
176
 
    }
177
 
 
178
 
    /* comment */
179
 
    value = xfce_rc_read_entry (rc, "Comment", NULL);
180
 
    if (G_LIKELY (value != NULL))
181
 
    {
182
 
        g_free (entry->comment);
183
 
        entry->comment = g_strdup (value);
184
 
    }
185
 
 
186
 
    /* icon */
187
 
    value = xfce_rc_read_entry_untranslated (rc, "Icon", NULL);
188
 
    if (G_LIKELY (value != NULL))
189
 
    {
190
 
        g_free (entry->icon);
191
 
 
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);
196
 
        else
197
 
            entry->icon = g_strdup (value);
198
 
            
199
 
#if LAUNCHER_NEW_TOOLTIP_API
200
 
        /* release the cached icon */
201
 
        if (entry->tooltip_cache)
202
 
        {
203
 
            g_object_unref (G_OBJECT (entry->tooltip_cache));
204
 
            entry->tooltip_cache = NULL;
205
 
        }
206
 
#endif
207
 
    }
208
 
 
209
 
    /* exec */
210
 
    value = xfce_rc_read_entry_untranslated (rc, "Exec", NULL);
211
 
    if (G_LIKELY (value != NULL))
212
 
    {
213
 
        g_free (entry->exec);
214
 
 
215
 
        /* expand and quote command and store */
216
 
        entry->exec = xfce_expand_variables (value, NULL);
217
 
    }
218
 
 
219
 
    /* working directory */
220
 
    value = xfce_rc_read_entry_untranslated (rc, "Path", NULL);
221
 
    if (G_UNLIKELY (value != NULL))
222
 
    {
223
 
        g_free (entry->path);
224
 
 
225
 
        /* expand variables and store */
226
 
        entry->path = xfce_expand_variables (value, NULL);
227
 
    }
228
 
 
229
 
    /* terminal */
230
 
    entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
231
 
 
232
 
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
233
 
    /* startup notification */
234
 
    entry->startup = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE);
235
 
#endif
236
 
 
237
 
    /* release rc file */
238
 
    xfce_rc_close (rc);
239
 
 
 
97
  gchar       *string, *escaped;
 
98
  gboolean     visible = FALSE;
 
99
  const gchar *text;
 
100
  gchar       *normalized;
 
101
  gchar       *text_casefolded;
 
102
  gchar       *name_casefolded;
 
103
 
 
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)))
240
107
    return TRUE;
241
 
}
242
 
 
243
 
 
244
 
 
245
 
static void
246
 
launcher_dialog_tree_drag_data_received (GtkWidget        *widget,
247
 
                                         GdkDragContext   *context,
248
 
                                         gint              x,
249
 
                                         gint              y,
250
 
                                         GtkSelectionData *selection_data,
251
 
                                         guint             info,
252
 
                                         guint             time_,
253
 
                                         LauncherDialog   *ld)
254
 
{
255
 
    GtkTreePath             *path = NULL;
256
 
    GtkTreeViewDropPosition  position;
257
 
    GtkTreeModel            *model;
258
 
    GtkTreeIter              iter_a;
259
 
    GtkTreeIter              iter_b;
260
 
    GSList                  *filenames = NULL;
261
 
    GSList                  *li;
262
 
    const gchar             *file;
263
 
    gboolean                 insert_before = FALSE;
264
 
    gboolean                 update_icon = FALSE;
265
 
    gint                     i = 0;
266
 
    LauncherEntry           *entry;
267
 
    GdkPixbuf               *pixbuf;
268
 
 
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)
272
 
    {
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;
276
 
    }
277
 
 
278
 
    if (G_LIKELY (path != NULL))
279
 
    {
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);
283
 
 
284
 
        /* array position or current item */
285
 
        i = gtk_tree_path_get_indices (path)[0];
286
 
 
287
 
        /* insert position, array correction and the path we select afterwards */
288
 
        switch (position)
289
 
        {
290
 
            case GTK_TREE_VIEW_DROP_BEFORE:
291
 
            case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
292
 
                insert_before = TRUE;
293
 
                break;
294
 
 
295
 
            case GTK_TREE_VIEW_DROP_AFTER:
296
 
            case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
297
 
                gtk_tree_path_next (path);
298
 
                ++i;
299
 
                insert_before = FALSE;
300
 
                break;
301
 
         }
302
 
 
303
 
        /* we need to update the button icon afterwards */
304
 
        if (i == 0)
305
 
            update_icon = TRUE;
306
 
 
307
 
        /* create list from selection data */
308
 
        filenames = launcher_utility_filenames_from_selection_data (selection_data);
309
 
    }
310
 
 
311
 
    if (G_LIKELY (filenames != NULL))
312
 
    {
313
 
        for (li = filenames; li != NULL; li = li->next)
314
 
        {
315
 
            file = li->data;
316
 
 
317
 
            /* create new entry */
318
 
            entry = launcher_entry_new ();
319
 
 
320
 
            /* try to parse desktop file */
321
 
            if (G_LIKELY (launcher_dialog_read_desktop_file (file, entry) == TRUE))
322
 
            {
323
 
                /* insert new row in store */
324
 
                if (insert_before)
325
 
                    gtk_list_store_insert_before (ld->store, &iter_b, &iter_a);
326
 
                else
327
 
                    gtk_list_store_insert_after (ld->store, &iter_b, &iter_a);
328
 
 
329
 
                /* try to load the pixbuf */
330
 
                pixbuf = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
331
 
 
332
 
                /* set tree data */
333
 
                gtk_list_store_set (ld->store, &iter_b,
334
 
                                    COLUMN_ICON, pixbuf,
335
 
                                    COLUMN_NAME, entry->name,
336
 
                                    -1);
337
 
 
338
 
                /* release pixbuf */
339
 
                if (G_LIKELY (pixbuf != NULL))
340
 
                    g_object_unref (G_OBJECT (pixbuf));
341
 
 
342
 
                /* insert in list */
343
 
                ld->launcher->entries = g_list_insert (ld->launcher->entries, entry, i);
344
 
 
345
 
                /* copy iter, so we add after last item */
346
 
                iter_a = iter_b;
347
 
 
348
 
                /* raise position counter */
349
 
                ++i;
350
 
 
351
 
                /* 1st item is inserted before existing item, after
352
 
                 * that we insert after the 1st item */
353
 
                insert_before = FALSE;
354
 
            }
355
 
            else
356
 
            {
357
 
                /* desktop file pasring failed, free new entry */
358
 
                launcher_entry_free (entry, NULL);
359
 
            }
360
 
        }
361
 
 
362
 
        /* select the new item (also updates treeview buttons) */
363
 
        gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
364
 
 
365
 
        /* update the panel */
366
 
        launcher_plugin_rebuild (ld->launcher, update_icon);
367
 
 
368
 
        /* cleanup */
369
 
        launcher_free_filenames (filenames);
370
 
    }
371
 
 
372
 
    /* free path */
373
 
    if (G_LIKELY (path != NULL))
374
 
        gtk_tree_path_free (path);
375
 
 
376
 
    /* finish drag */
377
 
    gtk_drag_finish (context, TRUE, FALSE, time_);
378
 
}
379
 
 
380
 
 
381
 
 
382
 
static void
383
 
launcher_dialog_frame_drag_data_received (GtkWidget        *widget,
384
 
                                          GdkDragContext   *context,
385
 
                                          gint              x,
386
 
                                          gint              y,
387
 
                                          GtkSelectionData *selection_data,
388
 
                                          guint             info,
389
 
                                          guint             time_,
390
 
                                          LauncherDialog   *ld)
391
 
{
392
 
    GSList   *filenames, *li;
393
 
    gchar    *file;
394
 
    gboolean  update_icon = FALSE;
395
 
 
396
 
    /* create list from all the uri list */
397
 
    filenames = launcher_utility_filenames_from_selection_data (selection_data);
398
 
 
399
 
    if (G_LIKELY (filenames != NULL))
400
 
    {
401
 
        for (li = filenames; li != NULL; li = li->next)
402
 
        {
403
 
            file = (gchar *) li->data;
404
 
 
405
 
            /* try to update the current entry settings */
406
 
            if (G_LIKELY (launcher_dialog_read_desktop_file (file, ld->entry) == TRUE))
407
 
            {
408
 
                /* update the widgets */
409
 
                launcher_dialog_update_entries (ld);
410
 
 
411
 
                /* update the tree */
412
 
                launcher_dialog_tree_update_row (ld, COLUMN_NAME);
413
 
                launcher_dialog_tree_update_row (ld, COLUMN_ICON);
414
 
 
415
 
                /* also update the panel button icon */
416
 
                if (g_list_index (ld->launcher->entries, ld->entry) == 0)
417
 
                    update_icon = TRUE;
418
 
 
419
 
                /* update the panel */
420
 
                launcher_plugin_rebuild (ld->launcher, update_icon);
421
 
 
422
 
                /* stop trying */
423
 
                break;
424
 
            }
425
 
        }
426
 
 
427
 
        /* cleanup */
428
 
        launcher_free_filenames (filenames);
429
 
    }
430
 
 
431
 
    /* finish drag */
432
 
    gtk_drag_finish (context, TRUE, FALSE, time_);
433
 
}
434
 
 
435
 
 
436
 
 
437
 
/**
438
 
 * Properties update and save functions
439
 
 **/
440
 
static void
441
 
launcher_dialog_save_entry (GtkWidget      *entry,
442
 
                            LauncherDialog *ld)
443
 
{
444
 
    const gchar *text;
445
 
    gchar       *filename;
446
 
 
447
 
    /* quit if locked or no active entry set */
448
 
    if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
449
 
        return;
450
 
 
451
 
    /* handle working directory changes */
452
 
    if (entry == ld->entry_path)
453
 
    {
454
 
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (ld->entry_path));
455
 
        if (exo_str_is_equal (ld->entry->path, filename) == FALSE)
456
 
        {
457
 
            g_free (ld->entry->path);
458
 
            ld->entry->path = filename;
459
 
        }
460
 
        else
461
 
        {
462
 
            g_free (filename);
463
 
            return;
464
 
        }
465
 
    }
466
 
    else
467
 
    {
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'))
471
 
            text = NULL;
472
 
 
473
 
        /* save new value */
474
 
        if (entry == ld->entry_name)
475
 
        {
476
 
            g_free (ld->entry->name);
477
 
            ld->entry->name = g_strdup (text);
478
 
 
479
 
            /* update tree, when triggered by widget */
480
 
            launcher_dialog_tree_update_row (ld, COLUMN_NAME);
481
 
        }
482
 
        else if (entry == ld->entry_comment)
483
 
        {
484
 
            g_free (ld->entry->comment);
485
 
            ld->entry->comment = g_strdup (text);
486
 
        }
487
 
        else if (entry == ld->entry_exec)
488
 
        {
489
 
            g_free (ld->entry->exec);
490
 
            ld->entry->exec = text ? xfce_expand_variables (text, NULL) : NULL;
491
 
        }
492
 
    }
493
 
 
494
 
    /* update panel */
495
 
    launcher_plugin_rebuild (ld->launcher, FALSE);
496
 
}
497
 
 
498
 
 
499
 
 
500
 
static void
501
 
launcher_dialog_save_button (GtkWidget      *button,
502
 
                             LauncherDialog *ld)
503
 
{
504
 
    gboolean active;
505
 
 
506
 
    /* quit if locked or no active entry set */
507
 
    if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
508
 
        return;
509
 
 
510
 
    /* get toggle button state */
511
 
    active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
512
 
 
513
 
    /* update entry or global setting */
514
 
    if (button == ld->entry_terminal)
515
 
    {
516
 
        ld->entry->terminal = active;
517
 
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
518
 
        gtk_widget_set_sensitive (ld->entry_startup, !active);
519
 
#endif
520
 
    }
521
 
#ifdef HAVE_LIBSTARTUP_NOTIFICATION
522
 
    else if (button == ld->entry_startup)
523
 
        ld->entry->startup = active;
524
 
#endif
525
 
}
526
 
 
527
 
 
528
 
 
529
 
static void
530
 
launcher_dialog_update_entries (LauncherDialog *ld)
531
 
{
532
 
    gchar *dir;
533
 
    
534
 
    /* quit if locked or no active entry set */
535
 
    if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
536
 
        return;
537
 
 
538
 
    /* lock the save functions */
539
 
    ld->updating = TRUE;
540
 
 
541
 
    /* set new entry values */
542
 
    gtk_entry_set_text (GTK_ENTRY (ld->entry_name),
543
 
                        (ld->entry->name != NULL) ? ld->entry->name : "");
544
 
 
545
 
    gtk_entry_set_text (GTK_ENTRY (ld->entry_comment),
546
 
                        (ld->entry->comment != NULL) ? ld->entry->comment : "");
547
 
 
548
 
    gtk_entry_set_text (GTK_ENTRY (ld->entry_exec),
549
 
                        (ld->entry->exec != NULL) ? ld->entry->exec : "");
550
 
 
551
 
    if (ld->entry->path != NULL)
552
 
      dir = ld->entry->path;
553
 
    else
554
 
      dir = g_get_current_dir ();
555
 
 
556
 
    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (ld->entry_path), dir);
557
 
 
558
 
    if (dir != ld->entry->path)
559
 
      g_free (dir);
560
 
 
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),
566
 
                                  ld->entry->startup);
567
 
 
568
 
    gtk_widget_set_sensitive (ld->entry_startup, !ld->entry->terminal);
569
 
#endif
570
 
 
571
 
    /* update icon button */
572
 
    launcher_dialog_update_icon (ld);
573
 
 
574
 
    /* unlock */
575
 
    ld->updating = FALSE;
576
 
}
577
 
 
578
 
 
579
 
 
580
 
static void
581
 
launcher_dialog_update_icon (LauncherDialog *ld)
582
 
{
583
 
    GdkPixbuf *icon = NULL;
584
 
    GtkWidget *child;
585
 
 
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);
589
 
 
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);
592
 
 
593
 
    /* create icon button */
594
 
    if (G_LIKELY (icon != NULL))
595
 
    {
596
 
        /* create image from pixbuf */
597
 
        child = gtk_image_new_from_pixbuf (icon);
598
 
 
599
 
        /* release icon */
600
 
        g_object_unref (G_OBJECT (icon));
601
 
 
602
 
        gtk_widget_set_size_request (child, LAUNCHER_CHOOSER_ICON_SIZE, LAUNCHER_CHOOSER_ICON_SIZE);
603
 
    }
604
 
    else
605
 
    {
606
 
        child = gtk_label_new (_("No icon"));
607
 
 
608
 
        gtk_widget_set_size_request (child, -1, LAUNCHER_CHOOSER_ICON_SIZE);
609
 
    }
610
 
 
611
 
    gtk_container_add (GTK_CONTAINER (ld->entry_icon), child);
612
 
    gtk_widget_show (child);
613
 
}
614
 
 
615
 
 
616
 
 
617
 
/**
618
 
 * Icon and command search dialogs
619
 
 **/
620
 
static void
621
 
launcher_dialog_command_chooser (LauncherDialog *ld)
622
 
{
623
 
    GtkFileFilter *filter;
624
 
    GtkWidget     *chooser;
625
 
    gchar         *filename;
626
 
    gchar         *s;
627
 
 
628
 
    chooser = gtk_file_chooser_dialog_new (_("Select an Application"),
629
 
                                           NULL,
630
 
                                           GTK_FILE_CHOOSER_ACTION_OPEN,
631
 
                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
632
 
                                           GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
633
 
                                           NULL);
634
 
    gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
635
 
 
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);
641
 
 
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);
656
 
 
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);
662
 
 
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);
668
 
 
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);
674
 
 
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);
681
 
 
682
 
    /* use the bindir as default folder */
683
 
    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), BINDIR);
684
 
 
685
 
    /* get the current command */
686
 
    filename = gtk_editable_get_chars (GTK_EDITABLE (ld->entry_exec), 0, -1);
687
 
    if (G_LIKELY (filename != NULL))
688
 
    {
689
 
        /* use only the first argument */
690
 
        s = strchr (filename, ' ');
691
 
        if (G_UNLIKELY (s != NULL))
692
 
            *s = '\0';
693
 
 
694
 
        /* check if we have a file name */
695
 
        if (G_LIKELY (*filename != '\0'))
696
 
        {
697
 
            /* check if the filename is not an absolute path */
698
 
            if (G_LIKELY (!g_path_is_absolute (filename)))
699
 
            {
700
 
                /* try to lookup the filename in $PATH */
701
 
                s = g_find_program_in_path (filename);
702
 
                if (G_LIKELY (s != NULL))
 
108
 
 
109
  /* casefold the search text */
 
110
  normalized = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
 
111
  text_casefolded = g_utf8_casefold (normalized, -1);
 
112
  g_free (normalized);
 
113
 
 
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))
 
117
    {
 
118
      /* search */
 
119
      visible = (strstr (string, text_casefolded) != NULL);
 
120
    }
 
121
  else
 
122
    {
 
123
      /* get the name */
 
124
      gtk_tree_model_get (model, iter, COL_NAME, &string, -1);
 
125
      if (!exo_str_is_empty (string))
 
126
        {
 
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);
 
131
          g_free (normalized);
 
132
          g_free (escaped);
 
133
 
 
134
          /* search */
 
135
          visible = (strstr (name_casefolded, text_casefolded) != NULL);
 
136
 
 
137
          /* store the generated search string */
 
138
          gtk_list_store_set (GTK_LIST_STORE (model), iter, COL_SEARCH,
 
139
                              name_casefolded, -1);
 
140
 
 
141
          g_free (name_casefolded);
 
142
        }
 
143
    }
 
144
 
 
145
  g_free (text_casefolded);
 
146
  g_free (string);
 
147
 
 
148
  return visible;
 
149
}
 
150
 
 
151
 
 
152
 
 
153
static void
 
154
launcher_dialog_add_store_insert (gpointer key,
 
155
                                  gpointer value,
 
156
                                  gpointer user_data)
 
157
{
 
158
  GtkTreeIter     iter;
 
159
  gchar          *tooltip;
 
160
  GFile          *gfile;
 
161
  GarconMenuItem *item = GARCON_MENU_ITEM (value);
 
162
  GtkTreeModel   *model = GTK_TREE_MODEL (user_data);
 
163
 
 
164
  panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
165
  panel_return_if_fail (GTK_IS_LIST_STORE (model));
 
166
 
 
167
  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
168
  launcher_dialog_items_set_item (model, &iter, item);
 
169
 
 
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));
 
175
  g_free (tooltip);
 
176
}
 
177
 
 
178
 
 
179
 
 
180
static gboolean
 
181
launcher_dialog_add_populate_model_idle (gpointer user_data)
 
182
{
 
183
  LauncherPluginDialog *dialog = user_data;
 
184
  GObject              *store;
 
185
  GHashTable           *pool;
 
186
 
 
187
  panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
 
188
 
 
189
  GDK_THREADS_ENTER ();
 
190
 
 
191
  /* load the item pool */
 
192
  pool = launcher_plugin_garcon_menu_pool ();
 
193
 
 
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);
 
197
 
 
198
  g_hash_table_destroy (pool);
 
199
 
 
200
  GDK_THREADS_LEAVE ();
 
201
 
 
202
  return FALSE;
 
203
}
 
204
 
 
205
 
 
206
 
 
207
static void
 
208
launcher_dialog_add_populate_model_idle_destroyed (gpointer user_data)
 
209
{
 
210
  ((LauncherPluginDialog *) user_data)->idle_populate_id = 0;
 
211
}
 
212
 
 
213
 
 
214
 
 
215
static void
 
216
launcher_dialog_add_populate_model (LauncherPluginDialog *dialog)
 
217
{
 
218
  GObject *store;
 
219
 
 
220
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
221
 
 
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));
 
225
 
 
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);
 
232
}
 
233
 
 
234
 
 
235
 
 
236
static void
 
237
launcher_dialog_add_drag_data_get (GtkWidget            *treeview,
 
238
                                   GdkDragContext       *drag_context,
 
239
                                   GtkSelectionData     *data,
 
240
                                   guint                 info,
 
241
                                   guint                 timestamp,
 
242
                                   LauncherPluginDialog *dialog)
 
243
{
 
244
  GtkTreeSelection  *selection;
 
245
  GList             *rows, *li;
 
246
  GtkTreeModel      *model;
 
247
  gchar            **uris;
 
248
  GarconMenuItem    *item;
 
249
  guint              i;
 
250
  GtkTreeIter        iter;
 
251
 
 
252
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
253
  panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
 
254
 
 
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))
 
258
    return;
 
259
 
 
260
  uris = g_new0 (gchar *, g_list_length (rows) + 1);
 
261
  for (li = rows, i = 0; li != NULL; li = li->next)
 
262
    {
 
263
      if (!gtk_tree_model_get_iter (model, &iter, li->data))
 
264
        continue;
 
265
 
 
266
      gtk_tree_model_get (model, &iter, COL_ITEM, &item, -1);
 
267
      if (G_UNLIKELY (item == NULL))
 
268
        continue;
 
269
 
 
270
      uris[i++] = garcon_menu_item_get_uri (item);
 
271
      g_object_unref (G_OBJECT (item));
 
272
    }
 
273
 
 
274
  gtk_selection_data_set_uris (data, uris);
 
275
  g_list_free (rows);
 
276
  g_strfreev (uris);
 
277
}
 
278
 
 
279
 
 
280
 
 
281
static void
 
282
launcher_dialog_add_selection_changed (GtkTreeSelection     *selection,
 
283
                                       LauncherPluginDialog *dialog)
 
284
{
 
285
  GObject  *object;
 
286
  gboolean  sensitive;
 
287
 
 
288
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
289
  panel_return_if_fail (GTK_IS_TREE_SELECTION (selection));
 
290
 
 
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);
 
294
}
 
295
 
 
296
 
 
297
 
 
298
static gboolean
 
299
launcher_dialog_add_button_press_event (GtkTreeView          *treeview,
 
300
                                        GdkEventButton       *event,
 
301
                                        LauncherPluginDialog *dialog)
 
302
{
 
303
  panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
 
304
  panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
 
305
 
 
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");
 
312
 
 
313
  return FALSE;
 
314
}
 
315
 
 
316
 
 
317
 
 
318
static gboolean
 
319
launcher_dialog_add_key_press_event (GtkTreeView          *treeview,
 
320
                                     GdkEventKey          *event,
 
321
                                     LauncherPluginDialog *dialog)
 
322
{
 
323
  panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
 
324
  panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
 
325
 
 
326
  if (event->keyval == GDK_Return
 
327
      || event->keyval == GDK_KP_Enter)
 
328
    return launcher_dialog_press_event (dialog, "button-add");
 
329
 
 
330
  return FALSE;
 
331
}
 
332
 
 
333
 
 
334
 
 
335
static void
 
336
launcher_dialog_add_response (GtkWidget            *widget,
 
337
                              gint                  response_id,
 
338
                              LauncherPluginDialog *dialog)
 
339
{
 
340
  GObject          *treeview, *store;
 
341
  GtkTreeSelection *selection;
 
342
  GtkTreeModel     *item_model, *add_model;
 
343
  GtkTreeIter       iter, sibling, tmp;
 
344
  GarconMenuItem   *item;
 
345
  GList            *list, *li;
 
346
 
 
347
  panel_return_if_fail (GTK_IS_DIALOG (widget));
 
348
  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (dialog->plugin));
 
349
 
 
350
  if (response_id != 0)
 
351
    {
 
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);
 
356
 
 
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),
 
363
                                     &iter, &sibling);
 
364
      else
 
365
        gtk_list_store_append (GTK_LIST_STORE (item_model), &iter);
 
366
 
 
367
      for (li = list; li != NULL; li = g_list_next (li))
 
368
        {
 
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);
 
372
 
 
373
          /* insert the item in the item store */
 
374
          if (G_LIKELY (item != NULL))
 
375
            {
 
376
              launcher_dialog_items_set_item (item_model, &iter, item);
 
377
              g_object_unref (G_OBJECT (item));
 
378
 
 
379
              /* select the first item */
 
380
              if (li == list)
 
381
                gtk_tree_selection_select_iter (selection, &iter);
 
382
            }
 
383
 
 
384
          gtk_tree_path_free (li->data);
 
385
 
 
386
          if (g_list_next (li) != NULL)
 
387
            {
 
388
              /* insert a new iter after the new added item */
 
389
              sibling = iter;
 
390
              gtk_list_store_insert_after (GTK_LIST_STORE (item_model),
 
391
                                           &iter, &sibling);
 
392
            }
 
393
        }
 
394
 
 
395
      g_list_free (list);
 
396
 
 
397
      /* write the model to xfconf */
 
398
      launcher_dialog_tree_save (dialog);
 
399
 
 
400
      /* update the selection */
 
401
      launcher_dialog_tree_selection_changed (selection, dialog);
 
402
    }
 
403
 
 
404
  /* empty the store */
 
405
  store = gtk_builder_get_object (dialog->builder, "add-store");
 
406
  gtk_list_store_clear (GTK_LIST_STORE (store));
 
407
 
 
408
  /* hide the dialog, since it's owned by gtkbuilder */
 
409
  gtk_widget_hide (widget);
 
410
}
 
411
 
 
412
 
 
413
 
 
414
static gboolean
 
415
launcher_dialog_tree_save_foreach (GtkTreeModel *model,
 
416
                                   GtkTreePath  *path,
 
417
                                   GtkTreeIter  *iter,
 
418
                                   gpointer      user_data)
 
419
{
 
420
  GPtrArray      *array = user_data;
 
421
  GValue         *value;
 
422
  GarconMenuItem *item;
 
423
 
 
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))
 
427
    {
 
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));
 
432
 
 
433
      /* put it in the array and release */
 
434
      g_ptr_array_add (array, value);
 
435
      g_object_unref (G_OBJECT (item));
 
436
    }
 
437
 
 
438
  return FALSE;
 
439
}
 
440
 
 
441
 
 
442
 
 
443
static void
 
444
launcher_dialog_tree_save (LauncherPluginDialog *dialog)
 
445
{
 
446
  GObject   *store;
 
447
  GPtrArray *array;
 
448
 
 
449
  store = gtk_builder_get_object (dialog->builder, "item-store");
 
450
 
 
451
  array = g_ptr_array_new ();
 
452
  gtk_tree_model_foreach (GTK_TREE_MODEL (store),
 
453
                          launcher_dialog_tree_save_foreach, array);
 
454
 
 
455
  g_object_set (dialog->plugin, "items", array, NULL);
 
456
  xfconf_array_free (array);
 
457
}
 
458
 
 
459
 
 
460
 
 
461
static void
 
462
launcher_dialog_tree_drag_data_received (GtkWidget            *treeview,
 
463
                                         GdkDragContext       *context,
 
464
                                         gint                  x,
 
465
                                         gint                  y,
 
466
                                         GtkSelectionData     *data,
 
467
                                         guint                 info,
 
468
                                         guint                 timestamp,
 
469
                                         LauncherPluginDialog *dialog)
 
470
{
 
471
  GtkTreePath              *path;
 
472
  GtkTreeViewDropPosition   drop_pos;
 
473
  gchar                   **uris;
 
474
  GtkTreeIter               iter;
 
475
  GtkTreeModel             *model;
 
476
  gint                      position;
 
477
  GarconMenuItem           *item;
 
478
  guint                     i;
 
479
 
 
480
  panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
 
481
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
482
 
 
483
  uris = gtk_selection_data_get_uris (data);
 
484
  if (G_LIKELY (uris == NULL))
 
485
    {
 
486
      gtk_drag_finish (context, FALSE, FALSE, timestamp);
 
487
      return;
 
488
    }
 
489
 
 
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))
 
494
    {
 
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)
 
499
        position++;
 
500
    }
 
501
  else
 
502
    {
 
503
      /* prepend at the end of the model */
 
504
      position = gtk_tree_model_iter_n_children (model, NULL);
 
505
    }
 
506
 
 
507
  /* insert the uris */
 
508
  for (i = 0; uris[i] != NULL; i++)
 
509
    {
 
510
      if (!g_str_has_suffix (uris[i], ".desktop"))
 
511
        continue;
 
512
 
 
513
      item = garcon_menu_item_new_for_uri (uris[i]);
 
514
      if (G_UNLIKELY (item == NULL))
 
515
        continue;
 
516
 
 
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));
 
520
    }
 
521
 
 
522
  g_strfreev (uris);
 
523
 
 
524
  launcher_dialog_tree_save (dialog);
 
525
 
 
526
  gtk_drag_finish (context, TRUE, FALSE, timestamp);
 
527
}
 
528
 
 
529
 
 
530
 
 
531
static void
 
532
launcher_dialog_tree_selection_changed (GtkTreeSelection     *selection,
 
533
                                        LauncherPluginDialog *dialog)
 
534
{
 
535
  GObject        *object;
 
536
  GtkTreeModel   *model;
 
537
  GtkTreeIter     iter;
 
538
  gint            n_children = -1;
 
539
  gint            position = 0;
 
540
  GtkTreePath    *path;
 
541
  gboolean        sensitive;
 
542
  GarconMenuItem *item = NULL;
 
543
  gboolean        editable = FALSE;
 
544
 
 
545
  panel_return_if_fail (GTK_IS_TREE_SELECTION (selection));
 
546
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
547
 
 
548
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
549
    {
 
550
      /* get the number of launchers in the tree */
 
551
      n_children = gtk_tree_model_iter_n_children (model, NULL);
 
552
 
 
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);
 
557
 
 
558
      gtk_tree_model_get (model, &iter, COL_ITEM, &item, -1);
 
559
      if (G_LIKELY (item != NULL))
 
560
        {
 
561
          editable = launcher_plugin_item_is_editable (dialog->plugin, item, NULL);
 
562
          g_object_unref (G_OBJECT (item));
 
563
        }
 
564
    }
 
565
 
 
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));
 
569
 
 
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);
 
573
 
 
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);
 
577
 
 
578
  object = gtk_builder_get_object (dialog->builder, "item-edit");
 
579
  gtk_widget_set_sensitive (GTK_WIDGET (object), editable);
 
580
 
 
581
  object = gtk_builder_get_object (dialog->builder, "arrow-position");
 
582
  gtk_widget_set_sensitive (GTK_WIDGET (object), n_children > 1);
 
583
 
 
584
  object = gtk_builder_get_object (dialog->builder, "move-first");
 
585
  gtk_widget_set_sensitive (GTK_WIDGET (object), n_children > 1);
 
586
 
 
587
  object = gtk_builder_get_object (dialog->builder, "arrow-position-label");
 
588
  gtk_widget_set_sensitive (GTK_WIDGET (object), n_children > 1);
 
589
}
 
590
 
 
591
 
 
592
 
 
593
static gboolean
 
594
launcher_dialog_press_event (LauncherPluginDialog *dialog,
 
595
                             const gchar          *object_name)
 
596
{
 
597
  GObject *object;
 
598
 
 
599
  panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
 
600
 
 
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))
 
604
    {
 
605
      gtk_button_clicked (GTK_BUTTON (object));
 
606
      return TRUE;
 
607
    }
 
608
 
 
609
  return FALSE;
 
610
}
 
611
 
 
612
 
 
613
 
 
614
static gboolean
 
615
launcher_dialog_tree_button_press_event (GtkTreeView          *treeview,
 
616
                                         GdkEventButton       *event,
 
617
                                         LauncherPluginDialog *dialog)
 
618
{
 
619
  panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
 
620
  panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
 
621
 
 
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");
 
627
 
 
628
  return FALSE;
 
629
}
 
630
 
 
631
 
 
632
 
 
633
static gboolean
 
634
launcher_dialog_tree_key_press_event (GtkTreeView          *treeview,
 
635
                                      GdkEventKey          *event,
 
636
                                      LauncherPluginDialog *dialog)
 
637
{
 
638
  panel_return_val_if_fail (GTK_IS_BUILDER (dialog->builder), FALSE);
 
639
  panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
 
640
 
 
641
  if (event->keyval == GDK_Return
 
642
      || event->keyval == GDK_KP_Enter)
 
643
    return launcher_dialog_press_event (dialog, "item-edit");
 
644
 
 
645
  return FALSE;
 
646
}
 
647
 
 
648
 
 
649
 
 
650
static void
 
651
launcher_dialog_item_button_clicked (GtkWidget            *button,
 
652
                                     LauncherPluginDialog *dialog)
 
653
{
 
654
  const gchar      *name;
 
655
  const gchar      *display_name = NULL;
 
656
  GObject          *object;
 
657
  GObject          *treeview;
 
658
  GtkTreeSelection *selection;
 
659
  GtkTreeModel     *model;
 
660
  GtkTreeIter       iter_a, iter_b;
 
661
  GtkTreePath      *path;
 
662
  gchar            *command, *uri;
 
663
  GdkScreen        *screen;
 
664
  GError           *error = NULL;
 
665
  GarconMenuItem   *item;
 
666
  GtkWidget        *toplevel;
 
667
  gchar            *filename;
 
668
  gboolean          can_delete;
 
669
  GFile            *item_file;
 
670
 
 
671
  panel_return_if_fail (GTK_IS_BUILDABLE (button));
 
672
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
673
 
 
674
  /* name of the button */
 
675
  name = gtk_buildable_get_name (GTK_BUILDABLE (button));
 
676
  if (G_UNLIKELY (name == NULL))
 
677
    return;
 
678
 
 
679
  if (strcmp (name, "item-add") == 0)
 
680
    {
 
681
      object = gtk_builder_get_object (dialog->builder, "dialog-add");
 
682
      launcher_dialog_add_populate_model (dialog);
 
683
      gtk_widget_show (GTK_WIDGET (object));
 
684
    }
 
685
  else
 
686
    {
 
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)
 
692
        return;
 
693
 
 
694
      if (strcmp (name, "item-delete") == 0)
 
695
        {
 
696
          /* get item name */
 
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);
 
700
 
 
701
          /* ask the user */
 
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))
 
707
            {
 
708
              /* remove the item from the store */
 
709
              gtk_list_store_remove (GTK_LIST_STORE (model), &iter_a);
 
710
 
 
711
              /* delete the desktop file if possible */
 
712
              if (item != NULL
 
713
                  && launcher_plugin_item_is_editable (dialog->plugin, item, &can_delete)
 
714
                  && can_delete)
703
715
                {
704
 
                    /* use the absolute path instead */
705
 
                    g_free (filename);
706
 
                    filename = s;
 
716
                  item_file = garcon_menu_item_get_file (item);
 
717
                  if (!g_file_delete (item_file, NULL, &error))
 
718
                    {
 
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);
 
723
                    }
 
724
                  g_object_unref (G_OBJECT (item_file));
707
725
                }
708
726
            }
709
727
 
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);
713
 
        }
714
 
 
715
 
        /* release the filename */
716
 
        g_free (filename);
717
 
    }
718
 
 
719
 
    /* run the chooser dialog */
720
 
    if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
721
 
    {
722
 
        /* get the filename and quote it */
723
 
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
724
 
        s = g_shell_quote (filename);
725
 
        g_free (filename);
726
 
        filename = s;
727
 
 
728
 
        /* set the new entry text */
729
 
        gtk_entry_set_text (GTK_ENTRY (ld->entry_exec), filename);
730
 
 
731
 
        /* cleanup */
732
 
        g_free (filename);
733
 
    }
734
 
 
735
 
    /* destroy dialog */
736
 
    gtk_widget_destroy (chooser);
737
 
}
738
 
 
739
 
 
740
 
 
741
 
static void
742
 
launcher_dialog_icon_chooser (LauncherDialog *ld)
743
 
{
744
 
    const gchar *name;
745
 
    GtkWidget   *chooser;
746
 
    gchar       *title;
747
 
    gboolean     update_icon = FALSE;
748
 
 
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'))
752
 
        name = _("Unnamed");
753
 
 
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,
758
 
                                           NULL);
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);
761
 
    g_free (title);
762
 
 
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);
766
 
 
767
 
    /* run the icon chooser dialog */
768
 
    if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
769
 
    {
770
 
        /* free the old icon name */
771
 
        if (G_LIKELY (ld->entry->icon))
772
 
            g_free (ld->entry->icon);
773
 
 
774
 
        /* set new icon */
775
 
        ld->entry->icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser));
776
 
 
777
 
#if LAUNCHER_NEW_TOOLTIP_API
778
 
        /* release cached tooltip icon */
779
 
        if (ld->entry->tooltip_cache)
780
 
        {
781
 
            g_object_unref (G_OBJECT (ld->entry->tooltip_cache));
782
 
            ld->entry->tooltip_cache = NULL;
783
 
        }
784
 
#endif
785
 
 
786
 
        /* update the icon button */
787
 
        launcher_dialog_update_icon (ld);
788
 
 
789
 
        /* update the icon column in the tree */
790
 
        launcher_dialog_tree_update_row (ld, COLUMN_ICON);
791
 
 
792
 
        /* check if we need to update the icon button image */
793
 
        if (g_list_index (ld->launcher->entries, ld->entry) == 0)
794
 
            update_icon = TRUE;
795
 
 
796
 
        /* update the panel widgets */
797
 
        launcher_plugin_rebuild (ld->launcher, update_icon);
798
 
    }
799
 
 
800
 
    /* destroy the chooser */
801
 
    gtk_widget_destroy (chooser);
802
 
}
803
 
 
804
 
 
805
 
 
806
 
/**
807
 
 * Tree functions
808
 
 **/
809
 
static void
810
 
launcher_dialog_tree_update_row (LauncherDialog *ld,
811
 
                                 gint            column)
812
 
{
813
 
    GtkTreeSelection *selection;
814
 
    GtkTreeIter       iter;
815
 
    GdkPixbuf        *icon = NULL;
816
 
    const gchar      *name;
817
 
 
818
 
    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
819
 
 
820
 
    if (G_LIKELY (gtk_tree_selection_get_selected (selection, NULL, &iter)))
821
 
    {
822
 
        switch (column)
823
 
        {
824
 
            case COLUMN_ICON:
825
 
                /* load entry icon */
826
 
                icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), ld->entry->icon, LAUNCHER_TREE_ICON_SIZE);
827
 
 
828
 
                /* set new icon */
829
 
                gtk_list_store_set (ld->store, &iter,
830
 
                                    COLUMN_ICON, icon,
831
 
                                    -1);
832
 
 
833
 
                /* release icon */
834
 
                if (G_LIKELY (icon != NULL))
835
 
                    g_object_unref (G_OBJECT (icon));
836
 
 
837
 
                break;
838
 
 
839
 
            case COLUMN_NAME:
840
 
                /* TRANSLATORS: Fallback name for a launcher item without a name */
841
 
                name = ld->entry->name ? ld->entry->name : _("Unnamed");
842
 
            
843
 
                /* set new name */
844
 
                gtk_list_store_set (ld->store, &iter,
845
 
                                    COLUMN_NAME, name,
846
 
                                    -1);
847
 
 
848
 
                break;
849
 
        }
850
 
    }
851
 
}
852
 
 
853
 
 
854
 
 
855
 
static void
856
 
launcher_dialog_tree_selection_changed (LauncherDialog   *ld,
857
 
                                        GtkTreeSelection *selection)
858
 
{
859
 
    GtkTreeModel *model;
860
 
    GtkTreePath  *path;
861
 
    GtkTreeIter   iter;
862
 
    gboolean      selected;
863
 
    gint          position = 0;
864
 
    gint          items;
865
 
 
866
 
    if (G_UNLIKELY (ld->updating == TRUE))
867
 
        return;
868
 
 
869
 
    g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
870
 
 
871
 
    /* check if we have currently selected an item */
872
 
    selected = gtk_tree_selection_get_selected (selection, &model, &iter);
873
 
 
874
 
    if (G_LIKELY (selected))
875
 
    {
876
 
        /* determine the path for the selected iter */
877
 
        path = gtk_tree_model_get_path (model, &iter);
878
 
 
879
 
        /* get position */
880
 
        position = gtk_tree_path_get_indices (path)[0];
881
 
 
882
 
        /* set new active entry */
883
 
        ld->entry = (LauncherEntry *) g_list_nth (ld->launcher->entries, position)->data;
884
 
 
885
 
        /* update fields */
886
 
        launcher_dialog_update_entries (ld);
887
 
 
888
 
        /* scroll new item to center of window */
889
 
        gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ld->treeview), path, NULL,
890
 
                                      TRUE, 0.5, 0.0);
891
 
 
892
 
        /* release path */
893
 
        gtk_tree_path_free (path);
894
 
    }
895
 
 
896
 
    /* items in the list */
897
 
    items = gtk_tree_model_iter_n_children (model, NULL);
898
 
 
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));
903
 
}
904
 
 
905
 
 
906
 
 
907
 
static void
908
 
launcher_dialog_tree_button_clicked (GtkWidget      *button,
909
 
                                     LauncherDialog *ld)
910
 
{
911
 
    GtkTreeSelection *selection;
912
 
    GtkTreeModel     *model;
913
 
    GtkTreePath      *path;
914
 
    GtkTreeIter       iter_a;
915
 
    GtkTreeIter       iter_b;
916
 
    guint             position;
917
 
    gint              list_length;
918
 
    GList            *li;
919
 
    GdkPixbuf        *icon = NULL;
920
 
    LauncherEntry    *entry;
921
 
    gboolean          update_icon = FALSE;
922
 
 
923
 
    /* get the selected items in the treeview */
924
 
    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
925
 
 
926
 
    /* get selected iter, quit if no iter found */
927
 
    if (G_UNLIKELY (gtk_tree_selection_get_selected (selection, &model, &iter_a) == FALSE))
928
 
        return;
929
 
 
930
 
    /* run the requested button action */
931
 
    if (button == ld->up)
932
 
    {
933
 
        /* get path */
934
 
        path = gtk_tree_model_get_path (model, &iter_a);
935
 
 
936
 
        /* position of the item in the list */
937
 
        position = gtk_tree_path_get_indices (path)[0];
938
 
 
939
 
        /* check if we need to update the icon button image */
940
 
        if (position == 1)
941
 
            update_icon = TRUE;
942
 
 
943
 
        /* get previous path */
944
 
        if (G_LIKELY (gtk_tree_path_prev (path)))
945
 
        {
946
 
            /* get iter for previous item */
947
 
            gtk_tree_model_get_iter (model, &iter_b, path);
948
 
 
949
 
            /* swap the entries */
950
 
            gtk_list_store_swap (ld->store, &iter_a, &iter_b);
951
 
 
952
 
            /* swap items in the list */
953
 
            li = g_list_nth (ld->launcher->entries, position);
954
 
            launcher_dialog_g_list_swap (li, li->prev);
955
 
        }
956
 
 
957
 
        /* release the path */
958
 
        gtk_tree_path_free (path);
959
 
 
960
 
        /* update tree view */
961
 
        launcher_dialog_tree_selection_changed (ld, selection);
962
 
    }
963
 
    else if (button == ld->down)
964
 
    {
965
 
        /* get path of selected item */
966
 
        path = gtk_tree_model_get_path (model, &iter_a);
967
 
 
968
 
        /* get position of item we're going to move */
969
 
        position = gtk_tree_path_get_indices (path)[0];
970
 
 
971
 
        /* check if we need to update the icon button image*/
972
 
        if (position == 0)
973
 
            update_icon = TRUE;
974
 
 
975
 
        /* get next item in the list */
976
 
        gtk_tree_path_next (path);
977
 
 
978
 
        /* get next iter */
979
 
        if (G_LIKELY (gtk_tree_model_get_iter (model, &iter_b, path)))
980
 
        {
981
 
            /* swap the entries */
982
 
            gtk_list_store_swap (ld->store, &iter_a, &iter_b);
983
 
 
984
 
            /* swap items in the list */
985
 
            li = g_list_nth (ld->launcher->entries, position);
986
 
            launcher_dialog_g_list_swap (li, li->next);
987
 
        }
988
 
 
989
 
        /* release the path */
990
 
        gtk_tree_path_free (path);
991
 
 
992
 
        /* update tree view */
993
 
        launcher_dialog_tree_selection_changed (ld, selection);
994
 
    }
995
 
    else if (button == ld->add)
996
 
    {
997
 
        /* create new entry */
998
 
        entry = launcher_entry_new ();
999
 
 
1000
 
        /* load new launcher icon */
1001
 
        icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
1002
 
 
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,
1006
 
                            COLUMN_ICON, icon,
1007
 
                            COLUMN_NAME, entry->name,
1008
 
                            -1);
1009
 
 
1010
 
        /* release the pixbuf */
1011
 
        if (G_LIKELY (icon != NULL))
1012
 
            g_object_unref (G_OBJECT (icon));
1013
 
 
1014
 
        /* get path of new item */
1015
 
        path = gtk_tree_model_get_path (model, &iter_b);
1016
 
 
1017
 
        /* position in the list */
1018
 
        position = gtk_tree_path_get_indices (path)[0];
1019
 
 
1020
 
        /* insert in list */
1021
 
        ld->launcher->entries = g_list_insert (ld->launcher->entries,
1022
 
                                               entry, position);
1023
 
 
1024
 
        /* select the new item (also updates treeview buttons) */
1025
 
        gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
1026
 
 
1027
 
        /* cleanup */
1028
 
        gtk_tree_path_free (path);
1029
 
 
1030
 
        /* allow to set the arrow position */
1031
 
        gtk_widget_set_sensitive (ld->arrow_position, TRUE);
1032
 
 
1033
 
    }
1034
 
    else if (button == ld->remove)
1035
 
    {
1036
 
        /* path from row to remove */
1037
 
        path = gtk_tree_model_get_path (model, &iter_a);
1038
 
 
1039
 
        /* get position of the item to remove */
1040
 
        position = gtk_tree_path_get_indices (path)[0];
1041
 
 
1042
 
        /* check if we need to update the icon button image*/
1043
 
        if (position == 0)
1044
 
            update_icon = TRUE;
1045
 
 
1046
 
        /* lock */
1047
 
        ld->updating = TRUE;
1048
 
 
1049
 
        /* remove active entry */
1050
 
        launcher_entry_free (ld->entry, ld->launcher);
1051
 
        ld->entry = NULL;
1052
 
 
1053
 
        /* remove row from store */
1054
 
        gtk_list_store_remove (ld->store, &iter_a);
1055
 
 
1056
 
        /* unlock */
1057
 
        ld->updating = FALSE;
1058
 
 
1059
 
        /* list length */
1060
 
        list_length = g_list_length (ld->launcher->entries);
1061
 
 
1062
 
        /* select previous item, if last item was removed */
1063
 
        if (position >= (guint) list_length)
1064
 
            gtk_tree_path_prev (path);
1065
 
 
1066
 
        /* select the new item (also updates treeview buttons) */
1067
 
        gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
1068
 
 
1069
 
        /* cleanup */
1070
 
        gtk_tree_path_free (path);
1071
 
 
1072
 
        /* allow to set the arrow position */
1073
 
        gtk_widget_set_sensitive (ld->arrow_position, list_length > 1);
1074
 
 
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);
1078
 
    }
1079
 
 
1080
 
    /* update panel */
1081
 
    launcher_plugin_rebuild (ld->launcher, update_icon);
1082
 
}
1083
 
 
1084
 
 
1085
 
 
1086
 
static void
1087
 
launcher_dialog_arrow_position_changed (GtkComboBox    *combo,
1088
 
                                        LauncherDialog *ld)
1089
 
{
1090
 
    ld->launcher->arrow_position = gtk_combo_box_get_active (combo);
1091
 
 
1092
 
    launcher_plugin_rebuild (ld->launcher, TRUE);
1093
 
}
1094
 
 
1095
 
 
1096
 
 
1097
 
/**
1098
 
 * Launcher dialog widgets
1099
 
 **/
1100
 
static GtkWidget *
1101
 
launcher_dialog_add_properties (LauncherDialog *ld)
1102
 
{
1103
 
    GtkWidget    *frame, *vbox, *hbox;
1104
 
    GtkWidget    *label, *button, *image;
1105
 
    GtkSizeGroup *sg;
1106
 
 
1107
 
    frame = gtk_frame_new (NULL);
1108
 
 
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);
1112
 
 
1113
 
    sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
1114
 
 
1115
 
    /* entry name field */
1116
 
    hbox = gtk_hbox_new (FALSE, BORDER * 2);
1117
 
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1118
 
 
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);
1122
 
 
1123
 
    gtk_size_group_add_widget (sg, label);
1124
 
 
1125
 
    ld->entry_name = gtk_entry_new ();
1126
 
    gtk_box_pack_start (GTK_BOX (hbox), ld->entry_name, TRUE, TRUE, 0);
1127
 
 
1128
 
    gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_name);
1129
 
 
1130
 
    g_signal_connect (G_OBJECT (ld->entry_name), "changed",
1131
 
                      G_CALLBACK (launcher_dialog_save_entry), ld);
1132
 
 
1133
 
    /* entry comment field */
1134
 
    hbox = gtk_hbox_new (FALSE, BORDER * 2);
1135
 
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1136
 
 
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);
1140
 
 
1141
 
    gtk_size_group_add_widget (sg, label);
1142
 
 
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);
1146
 
 
1147
 
    gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_comment);
1148
 
 
1149
 
    g_signal_connect (G_OBJECT (ld->entry_comment), "changed",
1150
 
                      G_CALLBACK (launcher_dialog_save_entry), ld);
1151
 
 
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);
1155
 
 
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);
1159
 
 
1160
 
    gtk_size_group_add_widget (sg, label);
1161
 
 
1162
 
    ld->entry_icon = gtk_button_new ();
1163
 
    gtk_box_pack_start (GTK_BOX (hbox), ld->entry_icon, FALSE, FALSE, 0);
1164
 
 
1165
 
    gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_icon);
1166
 
 
1167
 
    g_signal_connect_swapped (G_OBJECT (ld->entry_icon), "clicked",
1168
 
                              G_CALLBACK (launcher_dialog_icon_chooser), ld);
1169
 
 
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);
1173
 
 
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);
1177
 
 
1178
 
    gtk_size_group_add_widget (sg, label);
1179
 
 
1180
 
    ld->entry_exec = gtk_entry_new ();
1181
 
    gtk_box_pack_start (GTK_BOX (hbox), ld->entry_exec, TRUE, TRUE, 0);
1182
 
 
1183
 
    gtk_label_set_mnemonic_widget (GTK_LABEL (label), ld->entry_exec);
1184
 
 
1185
 
    g_signal_connect (G_OBJECT (ld->entry_exec), "changed",
1186
 
                      G_CALLBACK (launcher_dialog_save_entry), ld);
1187
 
 
1188
 
    button = gtk_button_new ();
1189
 
    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
1190
 
 
1191
 
    g_signal_connect_swapped (G_OBJECT (button), "clicked",
1192
 
                              G_CALLBACK (launcher_dialog_command_chooser), ld);
1193
 
 
1194
 
    image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
1195
 
    gtk_container_add (GTK_CONTAINER (button), image);
1196
 
 
1197
 
    /* working directory field */
1198
 
    hbox = gtk_hbox_new (FALSE, BORDER * 2);
1199
 
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1200
 
 
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);
1204
 
 
1205
 
    gtk_size_group_add_widget (sg, label);
1206
 
 
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);
1210
 
 
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);
1214
 
#else
1215
 
    g_signal_connect (G_OBJECT (ld->entry_path), "selection-changed",
1216
 
                      G_CALLBACK (launcher_dialog_save_entry), ld);
1217
 
#endif
1218
 
 
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);
1222
 
 
1223
 
    label = gtk_alignment_new (0, 0, 0, 0);
1224
 
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1225
 
 
1226
 
    gtk_size_group_add_widget (sg, label);
1227
 
 
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);
1230
 
 
1231
 
    g_signal_connect (G_OBJECT (ld->entry_terminal), "toggled",
1232
 
                      G_CALLBACK (launcher_dialog_save_button), ld);
1233
 
 
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);
1238
 
 
1239
 
    label = gtk_alignment_new (0, 0, 0, 0);
1240
 
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1241
 
 
1242
 
    gtk_size_group_add_widget (sg, label);
1243
 
 
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);
1246
 
 
1247
 
    g_signal_connect (G_OBJECT (ld->entry_startup), "toggled",
1248
 
                      G_CALLBACK (launcher_dialog_save_button), ld);
1249
 
#endif
1250
 
 
1251
 
    /* release size group */
1252
 
    g_object_unref (G_OBJECT (sg));
1253
 
 
1254
 
    /* setup dnd in frame */
1255
 
    gtk_drag_dest_set (frame, GTK_DEST_DEFAULT_ALL,
1256
 
                       drop_targets, G_N_ELEMENTS (drop_targets),
1257
 
                       GDK_ACTION_COPY);
1258
 
 
1259
 
    g_signal_connect (frame, "drag-data-received",
1260
 
                        G_CALLBACK (launcher_dialog_frame_drag_data_received), ld);
1261
 
 
1262
 
    return frame;
1263
 
}
1264
 
 
1265
 
 
1266
 
 
1267
 
 
1268
 
static GtkWidget *
1269
 
launcher_dialog_add_tree (LauncherDialog *ld)
1270
 
{
1271
 
    GtkWidget         *scroll;
1272
 
    GtkTreeViewColumn *column;
1273
 
    GtkTreeSelection  *selection;
1274
 
    GtkCellRenderer   *renderer;
1275
 
    GtkTreeIter        iter;
1276
 
    GList             *li;
1277
 
    LauncherEntry     *entry;
1278
 
    GdkPixbuf         *icon;
1279
 
    const gchar       *name;
1280
 
 
1281
 
    /* scrolled window */
1282
 
    scroll = gtk_scrolled_window_new (NULL, NULL);
1283
 
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
1284
 
                                    GTK_POLICY_NEVER,
1285
 
                                    GTK_POLICY_AUTOMATIC);
1286
 
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll),
1287
 
                                         GTK_SHADOW_IN);
1288
 
 
1289
 
    /* create new list store */
1290
 
    ld->store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
1291
 
 
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);
1300
 
 
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);
1307
 
 
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);
1312
 
 
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);
1317
 
 
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);
1323
 
 
1324
 
    /* append current items */
1325
 
    for (li = ld->launcher->entries; li != NULL; li = li->next)
1326
 
    {
1327
 
        entry = li->data;
1328
 
 
1329
 
        if (G_LIKELY (entry))
1330
 
        {
1331
 
            /* load icon */
1332
 
            icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
1333
 
            
1334
 
            name = entry->name ? entry->name : _("Unnamed");
1335
 
 
1336
 
            /* create new row and add the data */
1337
 
            gtk_list_store_append (ld->store, &iter);
1338
 
            gtk_list_store_set (ld->store, &iter,
1339
 
                                COLUMN_ICON, icon,
1340
 
                                COLUMN_NAME, name, -1);
1341
 
 
1342
 
            /* release the pixbuf */
1343
 
            if (G_LIKELY (icon))
1344
 
                g_object_unref (G_OBJECT (icon));
1345
 
        }
1346
 
    }
1347
 
 
1348
 
    /* dnd support */
1349
 
    gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (ld->treeview),
1350
 
                                          drop_targets, G_N_ELEMENTS (drop_targets),
1351
 
                                          GDK_ACTION_COPY);
1352
 
 
1353
 
    g_signal_connect (G_OBJECT (ld->treeview), "drag-data-received",
1354
 
                      G_CALLBACK (launcher_dialog_tree_drag_data_received), ld);
1355
 
 
1356
 
    return scroll;
1357
 
}
1358
 
 
1359
 
 
1360
 
 
1361
 
static GtkWidget *
1362
 
launcher_dialog_add_tree_buttons (LauncherDialog *ld)
1363
 
{
1364
 
    GtkWidget *hbox, *button, *align, *image;
1365
 
 
1366
 
    hbox = gtk_hbox_new (FALSE, BORDER);
1367
 
 
1368
 
    /* up button */
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);
1372
 
 
1373
 
    image = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
1374
 
    gtk_container_add (GTK_CONTAINER (button), image);
1375
 
 
1376
 
    g_signal_connect (G_OBJECT (button), "clicked",
1377
 
                      G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1378
 
 
1379
 
    gtk_widget_set_sensitive (button, FALSE);
1380
 
 
1381
 
    /* down button */
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);
1385
 
 
1386
 
    image = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON);
1387
 
    gtk_container_add (GTK_CONTAINER (button), image);
1388
 
 
1389
 
    g_signal_connect (G_OBJECT (button), "clicked",
1390
 
                      G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1391
 
 
1392
 
    gtk_widget_set_sensitive (button, FALSE);
1393
 
 
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);
1398
 
 
1399
 
    /* add button */
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);
1403
 
 
1404
 
    image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
1405
 
    gtk_container_add (GTK_CONTAINER (button), image);
1406
 
 
1407
 
    g_signal_connect (G_OBJECT (button), "clicked",
1408
 
                      G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1409
 
 
1410
 
    /* remove button */
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);
1414
 
 
1415
 
    image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON);
1416
 
    gtk_container_add (GTK_CONTAINER (button), image);
1417
 
 
1418
 
    g_signal_connect (G_OBJECT (button), "clicked",
1419
 
                      G_CALLBACK (launcher_dialog_tree_button_clicked), ld);
1420
 
 
1421
 
    gtk_widget_set_sensitive (button, FALSE);
1422
 
 
1423
 
    return hbox;
1424
 
}
1425
 
 
1426
 
 
1427
 
 
1428
 
/**
1429
 
 * Dialog functions
1430
 
 **/
1431
 
static void
1432
 
launcher_dialog_response (GtkWidget      *dialog,
1433
 
                          gint            response,
1434
 
                          LauncherDialog *ld)
1435
 
{
1436
 
    LauncherPlugin *launcher = ld->launcher;
1437
 
 
1438
 
    /* hide the dialog */
1439
 
    gtk_widget_hide (dialog);
1440
 
 
1441
 
    /* lock for further updates */
1442
 
    ld->updating = TRUE;
1443
 
    ld->entry = NULL;
1444
 
 
1445
 
    /* cleanup the store */
1446
 
    gtk_list_store_clear (ld->store);
1447
 
    g_object_unref (G_OBJECT (ld->store));
1448
 
 
1449
 
    /* the launcher dialog dataS */
1450
 
    g_object_set_data (G_OBJECT (launcher->panel_plugin), I_("launcher-dialog"), NULL);
1451
 
 
1452
 
    /* destroy the dialog */
1453
 
    gtk_widget_destroy (dialog);
1454
 
 
1455
 
    /* unlock plugin menu */
1456
 
    xfce_panel_plugin_unblock_menu (launcher->panel_plugin);
1457
 
 
1458
 
    /* restore move first */
1459
 
    launcher->move_first = ld->stored_move_first;
1460
 
 
1461
 
    /* allow saving again */
1462
 
    launcher->plugin_can_save = TRUE;
1463
 
 
1464
 
    if (response == GTK_RESPONSE_OK)
1465
 
    {
1466
 
        /* write new settings */
1467
 
        launcher_plugin_save (launcher);
1468
 
    }
1469
 
    else /* revert changes */
1470
 
    {
1471
 
        /* remove all the entries */
1472
 
        g_list_foreach (launcher->entries, (GFunc) launcher_entry_free, launcher);
1473
 
 
1474
 
        /* read the last saved settings */
1475
 
        launcher_plugin_read (launcher);
1476
 
 
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 ());
1480
 
        
1481
 
        /* rebuild the plugin */
1482
 
        launcher_plugin_rebuild (launcher, TRUE);
1483
 
    }
1484
 
 
1485
 
    /* free the panel structure */
1486
 
    panel_slice_free (LauncherDialog, ld);
 
728
          if (G_LIKELY (item != NULL))
 
729
            g_object_unref (G_OBJECT (item));
 
730
        }
 
731
      else if (strcmp (name, "item-new") == 0
 
732
               || strcmp (name, "item-edit") == 0)
 
733
        {
 
734
          if (strcmp (name, "item-edit") == 0)
 
735
            {
 
736
              gtk_tree_model_get (model, &iter_a, COL_ITEM, &item, -1);
 
737
              if (G_UNLIKELY (item == NULL))
 
738
                return;
 
739
 
 
740
              /* build command */
 
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);
 
744
              g_free (uri);
 
745
            }
 
746
          else
 
747
            {
 
748
              /* build command */
 
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);
 
752
              g_free (filename);
 
753
            }
 
754
 
 
755
          /* spawn item editor */
 
756
          screen = gtk_widget_get_screen (button);
 
757
          if (!gdk_spawn_command_line_on_screen (screen, command, &error))
 
758
            {
 
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);
 
763
            }
 
764
 
 
765
          g_free (command);
 
766
        }
 
767
      else if (strcmp (name, "item-move-up") == 0)
 
768
        {
 
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);
 
774
        }
 
775
      else if (strcmp (name, "item-move-down") == 0)
 
776
        {
 
777
          iter_b = iter_a;
 
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);
 
780
        }
 
781
      else
 
782
        {
 
783
          panel_assert_not_reached ();
 
784
        }
 
785
 
 
786
      /* store the new settings */
 
787
      launcher_dialog_tree_save (dialog);
 
788
 
 
789
      /* emit a changed signal to update the button states */
 
790
      launcher_dialog_tree_selection_changed (selection, dialog);
 
791
    }
 
792
}
 
793
 
 
794
 
 
795
 
 
796
static void
 
797
launcher_dialog_response (GtkWidget            *widget,
 
798
                          gint                  response_id,
 
799
                          LauncherPluginDialog *dialog)
 
800
{
 
801
  GObject *add_dialog;
 
802
 
 
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));
 
806
 
 
807
  if (G_UNLIKELY (response_id == 1))
 
808
    {
 
809
      /* TODO open help */
 
810
    }
 
811
  else
 
812
    {
 
813
      /* stop idle if still running */
 
814
      if (G_UNLIKELY (dialog->idle_populate_id != 0))
 
815
        g_source_remove (dialog->idle_populate_id);
 
816
 
 
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);
 
820
 
 
821
      /* disconnect from the menu items */
 
822
      launcher_dialog_items_unload (dialog);
 
823
 
 
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));
 
827
 
 
828
      /* destroy the dialog */
 
829
      gtk_widget_destroy (widget);
 
830
 
 
831
      g_slice_free (LauncherPluginDialog, dialog);
 
832
    }
 
833
}
 
834
 
 
835
 
 
836
 
 
837
static gboolean
 
838
launcher_dialog_item_changed_foreach (GtkTreeModel *model,
 
839
                                      GtkTreePath  *path,
 
840
                                      GtkTreeIter  *iter,
 
841
                                      gpointer      user_data)
 
842
{
 
843
  GarconMenuItem *item;
 
844
  gboolean        found;
 
845
 
 
846
  panel_return_val_if_fail (GARCON_IS_MENU_ITEM (user_data), TRUE);
 
847
 
 
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;
 
851
 
 
852
  if (G_UNLIKELY (found))
 
853
    launcher_dialog_items_set_item (model, iter, item);
 
854
 
 
855
  g_object_unref (G_OBJECT (item));
 
856
 
 
857
  return found;
 
858
}
 
859
 
 
860
 
 
861
 
 
862
static void
 
863
launcher_dialog_item_changed (GarconMenuItem       *item,
 
864
                              LauncherPluginDialog *dialog)
 
865
{
 
866
  GObject      *treeview;
 
867
  GtkTreeModel *model;
 
868
 
 
869
  panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
870
 
 
871
  treeview = gtk_builder_get_object (dialog->builder, "item-treeview");
 
872
  model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
 
873
 
 
874
  /* find the item in the model and update it */
 
875
  gtk_tree_model_foreach (model, launcher_dialog_item_changed_foreach, item);
 
876
}
 
877
 
 
878
 
 
879
 
 
880
static void
 
881
launcher_dialog_items_set_item (GtkTreeModel   *model,
 
882
                                GtkTreeIter    *iter,
 
883
                                GarconMenuItem *item)
 
884
{
 
885
  const gchar *name, *comment;
 
886
  gchar       *markup;
 
887
 
 
888
  panel_return_if_fail (GTK_IS_LIST_STORE (model));
 
889
  panel_return_if_fail (GARCON_IS_MENU_ITEM (item));
 
890
 
 
891
  name = garcon_menu_item_get_name (item);
 
892
  comment = garcon_menu_item_get_comment (item);
 
893
 
 
894
  if (!exo_str_is_empty (comment))
 
895
    markup = g_markup_printf_escaped ("<b>%s</b>\n%s", name, comment);
 
896
  else
 
897
    markup = g_markup_printf_escaped ("<b>%s</b>", name);
 
898
 
 
899
  gtk_list_store_set (GTK_LIST_STORE (model), iter,
 
900
                      COL_ICON, garcon_menu_item_get_icon_name (item),
 
901
                      COL_NAME, markup,
 
902
                      COL_ITEM, item,
 
903
                      -1);
 
904
 
 
905
  g_free (markup);
 
906
}
 
907
 
 
908
 
 
909
 
 
910
static void
 
911
launcher_dialog_items_unload (LauncherPluginDialog *dialog)
 
912
{
 
913
  GSList *li;
 
914
 
 
915
  for (li = dialog->items; li != NULL; li = li->next)
 
916
    {
 
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));
 
921
    }
 
922
 
 
923
  g_slist_free (dialog->items);
 
924
  dialog->items = NULL;
 
925
}
 
926
 
 
927
 
 
928
 
 
929
static void
 
930
launcher_dialog_items_load (LauncherPluginDialog *dialog)
 
931
{
 
932
  GObject          *treeview;
 
933
  GtkTreeSelection *selection;
 
934
  GtkTreeModel     *model;
 
935
  GSList           *li;
 
936
  GtkTreeIter       iter;
 
937
  GtkTreePath      *path;
 
938
 
 
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));
 
942
 
 
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);
 
946
  else
 
947
    path = NULL;
 
948
 
 
949
  /* clear the old items */
 
950
  launcher_dialog_items_unload (dialog);
 
951
  gtk_list_store_clear (GTK_LIST_STORE (model));
 
952
 
 
953
  /* insert the launcher items */
 
954
  dialog->items = launcher_plugin_get_items (dialog->plugin);
 
955
  for (li = dialog->items; li != NULL; li = li->next)
 
956
    {
 
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);
 
961
    }
 
962
 
 
963
  if (G_LIKELY (path != NULL))
 
964
    {
 
965
      /* restore the old selection */
 
966
      gtk_tree_selection_select_path (selection, path);
 
967
      gtk_tree_path_free (path);
 
968
    }
 
969
  else if (gtk_tree_model_get_iter_first (model, &iter))
 
970
    {
 
971
      /* select the first item */
 
972
      gtk_tree_selection_select_iter (selection, &iter);
 
973
    }
1487
974
}
1488
975
 
1489
976
 
1490
977
 
1491
978
void
1492
 
launcher_dialog_show (LauncherPlugin  *launcher)
 
979
launcher_dialog_show (LauncherPlugin *plugin)
1493
980
{
1494
 
    LauncherDialog *ld;
1495
 
    GtkWidget      *dialog;
1496
 
    GtkWidget      *dialog_vbox;
1497
 
    GtkWidget      *paned, *vbox, *hbox;
1498
 
    GtkWidget      *widget, *label, *combo;
1499
 
    GtkTreePath    *path;
1500
 
 
1501
 
    /* create new structure */
1502
 
    ld = panel_slice_new0 (LauncherDialog);
1503
 
 
1504
 
    /* init */
1505
 
    ld->launcher = launcher;
1506
 
    ld->entry = g_list_first (launcher->entries)->data;
1507
 
 
1508
 
    /* prevent saving to be able to use the cancel button */
1509
 
    launcher->plugin_can_save = FALSE;
1510
 
 
1511
 
    /* lock right-click plugin menu */
1512
 
    xfce_panel_plugin_block_menu (launcher->panel_plugin);
1513
 
 
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;
1517
 
 
1518
 
    dialog = xfce_titled_dialog_new_with_buttons (_("Launcher"),
1519
 
                                                  NULL,
1520
 
                                                  GTK_DIALOG_NO_SEPARATOR,
1521
 
                                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1522
 
                                                  GTK_STOCK_OK, GTK_RESPONSE_OK,
1523
 
                                                  NULL);
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);
1528
 
 
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);
1531
 
 
1532
 
    dialog_vbox = GTK_DIALOG (dialog)->vbox;
1533
 
 
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);
1538
 
 
1539
 
    vbox = gtk_vbox_new (FALSE, BORDER);
1540
 
    gtk_paned_pack1 (GTK_PANED (paned), vbox, FALSE, FALSE);
1541
 
 
1542
 
    /* arrow button position */
1543
 
    hbox = gtk_hbox_new (FALSE, BORDER);
1544
 
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1545
 
 
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);
1550
 
 
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);
1564
 
 
1565
 
    /* add the entries list */
1566
 
    widget = launcher_dialog_add_tree (ld);
1567
 
    gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
1568
 
 
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);
1572
 
 
1573
 
    /* add the entry widgets */
1574
 
    widget = launcher_dialog_add_properties (ld);
1575
 
    gtk_paned_pack2 (GTK_PANED (paned), widget, TRUE, FALSE);
1576
 
 
1577
 
    /* show all widgets inside dialog */
1578
 
    gtk_widget_show_all (dialog_vbox);
1579
 
 
1580
 
    /* focus the title entry */
1581
 
    gtk_widget_grab_focus (ld->entry_name);
1582
 
 
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);
1587
 
 
1588
 
    /* connect response signal */
1589
 
    g_signal_connect (G_OBJECT (dialog), "response",
1590
 
                      G_CALLBACK (launcher_dialog_response), ld);
1591
 
 
1592
 
    /* show the dialog */
1593
 
    gtk_widget_show (dialog);
 
981
  LauncherPluginDialog *dialog;
 
982
  GtkBuilder           *builder;
 
983
  GObject              *window, *object, *item;
 
984
  guint                 i;
 
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" };
 
991
 
 
992
  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
 
993
 
 
994
  /* setup the dialog */
 
995
  PANEL_UTILS_LINK_4UI
 
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))
 
999
    return;
 
1000
 
 
1001
  /* create structure */
 
1002
  dialog = g_slice_new0 (LauncherPluginDialog);
 
1003
  dialog->builder = builder;
 
1004
  dialog->plugin = plugin;
 
1005
  dialog->items = NULL;
 
1006
 
 
1007
  g_signal_connect (G_OBJECT (window), "response",
 
1008
      G_CALLBACK (launcher_dialog_response), dialog);
 
1009
 
 
1010
  /* connect item buttons */
 
1011
  for (i = 0; i < G_N_ELEMENTS (button_names); i++)
 
1012
    {
 
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);
 
1017
    }
 
1018
 
 
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);
 
1034
 
 
1035
  /* connect bindings to the advanced properties */
 
1036
  for (i = 0; i < G_N_ELEMENTS (binding_names); i++)
 
1037
    {
 
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");
 
1042
    }
 
1043
 
 
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);
 
1050
 
 
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);
 
1055
 
 
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);
 
1070
 
 
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);
 
1078
 
 
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);
 
1084
 
 
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);
 
1089
 
 
1090
  /* show the dialog */
 
1091
  gtk_widget_show (GTK_WIDGET (window));
1594
1092
}