~ubuntu-branches/debian/experimental/xfce4-panel/experimental

« back to all changes in this revision

Viewing changes to panel/panel-item-dialog.c

  • Committer: Bazaar Package Importer
  • Author(s): Yves-Alexis Perez, Lionel Le Folgoc, Yves-Alexis Perez
  • Date: 2011-02-06 18:10:07 UTC
  • mfrom: (1.3.13 upstream) (5.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110206181007-vpw5z3xnm3hdvybx
Tags: 4.8.1-1
[ Lionel Le Folgoc ]
* New upstream bugfix release.
* debian/control:
  - refreshed (b-)deps for this new major release
  - add myself to Uploaders
  - bump Standards-Version to 3.9.1.
* debian/NEWS: dropped, unneeded.
* debian/xfce4-panel.shlibs: refreshed, bump to (>= 4.7.2).
* debian/xfce4-panel.lintian-overrides: refreshed, new lib name.
* debian/xfce4-panel.preinst: added, handles removal of old conffiles.
* debian/xfce4-panel.postinst: explicitly set -e.
* debian/*.install: refreshed.
* debian/rules:
  - call dpkg-buildflags
  - dropped rc files mangling as they don't exist anymore
  - updated removal of *.{l,}a files.
  - drop overrides for dh_auto_{configure,clean}, obsolete.
* debian/xfce4-panel.{preinst,postinst,prerm}: use dpkg-maintscript-helper
  to remove pre-xfconf config files.
* Bugs fixed by 4.7.x/4.8.x series:
  - rgba support                                                  lp: #586012
  - disappearing menus                                             lp: #53897
  - xrandr support                               lp: #176174, Closes: #432914
  - Fails to reap children, creating zombies                      lp: #420187
  - DND of desktop-files on the panel to create new launchers Closes: #480380
* Bumped shlibs to >= 4.7.7, abi break for external plugins.

[ Yves-Alexis Perez ]
* New upstream development release
* debian/xfce4-panel.install:
  - install wrapper and migrate tools in xfce4-panel package
  - update plugins paths
* debian/rules:
  - update path when removing .a/.la files for plugins.
  - add hardening flags to {C,LD}FLAGS
* debian/control:
  - add build-dep on hardening-includes
  - update build-dep on garcon to 0.1.4.
* debian/copyright updated for new release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008-2010 Nick Schermer <nick@xfce.org>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along
 
15
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
17
 */
 
18
 
 
19
#ifdef HAVE_CONFIG_H
 
20
#include <config.h>
 
21
#endif
 
22
 
 
23
#ifdef HAVE_STRING_H
 
24
#include <string.h>
 
25
#endif
 
26
 
 
27
#include <exo/exo.h>
 
28
#include <libxfce4ui/libxfce4ui.h>
 
29
#include <libxfce4util/libxfce4util.h>
 
30
 
 
31
#include <common/panel-private.h>
 
32
#include <common/panel-utils.h>
 
33
#include <libxfce4panel/libxfce4panel.h>
 
34
 
 
35
#include <panel/panel-application.h>
 
36
#include <panel/panel-item-dialog.h>
 
37
#include <panel/panel-dialogs.h>
 
38
#include <panel/panel-module.h>
 
39
#include <panel/panel-module-factory.h>
 
40
#include <panel/panel-preferences-dialog.h>
 
41
 
 
42
 
 
43
 
 
44
#define BORDER         (6)
 
45
#define ITEMS_HELP_URL "http://www.xfce.org"
 
46
 
 
47
 
 
48
 
 
49
static void         panel_item_dialog_finalize               (GObject            *object);
 
50
static void         panel_item_dialog_response               (GtkDialog          *dialog,
 
51
                                                              gint                response_id);
 
52
static void         panel_item_dialog_unique_changed         (PanelModuleFactory *factory,
 
53
                                                              PanelModule        *module,
 
54
                                                              PanelItemDialog    *dialog);
 
55
static gboolean     panel_item_dialog_unique_changed_foreach (GtkTreeModel       *model,
 
56
                                                              GtkTreePath        *path,
 
57
                                                              GtkTreeIter        *iter,
 
58
                                                              gpointer            user_data);
 
59
static gboolean     panel_item_dialog_separator_func         (GtkTreeModel       *model,
 
60
                                                              GtkTreeIter        *iter,
 
61
                                                              gpointer            user_data);
 
62
static void         panel_item_dialog_selection_changed      (GtkTreeSelection   *selection,
 
63
                                                              PanelItemDialog    *dialog);
 
64
static PanelModule *panel_item_dialog_get_selected_module    (GtkTreeView        *treeview);
 
65
static void         panel_item_dialog_drag_begin             (GtkWidget          *treeview,
 
66
                                                              GdkDragContext     *context,
 
67
                                                              PanelItemDialog    *dialog);
 
68
static void         panel_item_dialog_drag_data_get          (GtkWidget          *treeview,
 
69
                                                              GdkDragContext     *context,
 
70
                                                              GtkSelectionData   *selection_data,
 
71
                                                              guint               info,
 
72
                                                              guint               drag_time,
 
73
                                                              PanelItemDialog    *dialog);
 
74
static void         panel_item_dialog_drag_data_received     (GtkWidget          *treeview,
 
75
                                                              GdkDragContext     *context,
 
76
                                                              gint                x,
 
77
                                                              gint                y,
 
78
                                                              GtkSelectionData   *selection_data,
 
79
                                                              guint               info,
 
80
                                                              guint               drag_time,
 
81
                                                              PanelItemDialog    *dialog);
 
82
static void         panel_item_dialog_populate_store         (PanelItemDialog    *dialog);
 
83
static gint         panel_item_dialog_compare_func           (GtkTreeModel       *model,
 
84
                                                              GtkTreeIter        *a,
 
85
                                                              GtkTreeIter        *b,
 
86
                                                              gpointer            user_data);
 
87
static gboolean     panel_item_dialog_visible_func           (GtkTreeModel       *model,
 
88
                                                              GtkTreeIter        *iter,
 
89
                                                              gpointer            user_data);
 
90
static void         panel_item_dialog_text_renderer          (GtkTreeViewColumn  *column,
 
91
                                                              GtkCellRenderer    *renderer,
 
92
                                                              GtkTreeModel       *model,
 
93
                                                              GtkTreeIter        *iter,
 
94
                                                              gpointer            user_data);
 
95
 
 
96
 
 
97
 
 
98
struct _PanelItemDialogClass
 
99
{
 
100
  XfceTitledDialogClass __parent__;
 
101
};
 
102
 
 
103
struct _PanelItemDialog
 
104
{
 
105
  XfceTitledDialog  __parent__;
 
106
 
 
107
  PanelApplication   *application;
 
108
 
 
109
  PanelModuleFactory *factory;
 
110
 
 
111
  /* pointers to list */
 
112
  GtkListStore       *store;
 
113
  GtkTreeView        *treeview;
 
114
  GtkWidget          *add_button;
 
115
};
 
116
 
 
117
enum
 
118
{
 
119
  COLUMN_ICON_NAME,
 
120
  COLUMN_MODULE,
 
121
  COLUMN_SENSITIVE,
 
122
  N_COLUMNS
 
123
};
 
124
 
 
125
static const GtkTargetEntry drag_targets[] =
 
126
{
 
127
  { "xfce-panel/plugin-name", 0, 0 }
 
128
};
 
129
 
 
130
static const GtkTargetEntry drop_targets[] =
 
131
{
 
132
  { "xfce-panel/plugin-widget", GTK_TARGET_SAME_APP, 0 }
 
133
};
 
134
 
 
135
 
 
136
 
 
137
G_DEFINE_TYPE (PanelItemDialog, panel_item_dialog, XFCE_TYPE_TITLED_DIALOG)
 
138
 
 
139
 
 
140
 
 
141
static PanelItemDialog *dialog_singleton = NULL;
 
142
 
 
143
 
 
144
 
 
145
static void
 
146
panel_item_dialog_class_init (PanelItemDialogClass *klass)
 
147
{
 
148
  GObjectClass   *gobject_class;
 
149
  GtkDialogClass *gtkdialog_class;
 
150
 
 
151
  gobject_class = G_OBJECT_CLASS (klass);
 
152
  gobject_class->finalize = panel_item_dialog_finalize;
 
153
 
 
154
  gtkdialog_class = GTK_DIALOG_CLASS (klass);
 
155
  gtkdialog_class->response = panel_item_dialog_response;
 
156
}
 
157
 
 
158
 
 
159
 
 
160
static void
 
161
panel_item_dialog_init (PanelItemDialog *dialog)
 
162
{
 
163
  GtkWidget         *main_vbox;
 
164
  GtkWidget         *hbox;
 
165
  GtkWidget         *label;
 
166
  GtkWidget         *entry;
 
167
  GtkWidget         *scroll;
 
168
  GtkWidget         *treeview;
 
169
  GtkTreeModel      *filter;
 
170
  GtkTreeViewColumn *column;
 
171
  GtkCellRenderer   *renderer;
 
172
  GtkTreeSelection  *selection;
 
173
 
 
174
  dialog->application = panel_application_get ();
 
175
 
 
176
  /* register the window in the application */
 
177
  panel_application_take_dialog (dialog->application, GTK_WINDOW (dialog));
 
178
 
 
179
  /* make the application windows insensitive */
 
180
  panel_application_windows_sensitive (dialog->application, FALSE);
 
181
 
 
182
  dialog->factory = panel_module_factory_get ();
 
183
 
 
184
  /* monitor unique changes */
 
185
  g_signal_connect (G_OBJECT (dialog->factory), "unique-changed",
 
186
      G_CALLBACK (panel_item_dialog_unique_changed), dialog);
 
187
 
 
188
  gtk_window_set_title (GTK_WINDOW (dialog), _("Add New Items"));
 
189
  xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (dialog),
 
190
      _("Add new plugins to the panel"));
 
191
  gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_ADD);
 
192
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
 
193
  gtk_window_set_default_size (GTK_WINDOW (dialog), 350, 450);
 
194
 
 
195
  dialog->add_button = gtk_button_new_from_stock (GTK_STOCK_ADD);
 
196
  gtk_widget_show (dialog->add_button);
 
197
 
 
198
  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_HELP, GTK_RESPONSE_HELP);
 
199
  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), dialog->add_button, GTK_RESPONSE_OK);
 
200
  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
 
201
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
 
202
 
 
203
  main_vbox = gtk_vbox_new (FALSE, BORDER * 2);
 
204
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), main_vbox);
 
205
  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), BORDER);
 
206
  gtk_widget_show (main_vbox);
 
207
 
 
208
  /* search widget */
 
209
  hbox = gtk_hbox_new (FALSE, BORDER);
 
210
  gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
 
211
  gtk_widget_show (hbox);
 
212
 
 
213
  label = gtk_label_new_with_mnemonic (_("_Search:"));
 
214
  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
 
215
  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
 
216
  gtk_widget_show (label);
 
217
 
 
218
  entry = gtk_entry_new ();
 
219
  gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
 
220
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
 
221
  gtk_widget_set_tooltip_text (entry, _("Enter search phrase here"));
 
222
#if GTK_CHECK_VERSION (2, 16, 0)
 
223
  gtk_entry_set_icon_from_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
 
224
#endif
 
225
  gtk_widget_show (entry);
 
226
 
 
227
  /* scroller */
 
228
  scroll = gtk_scrolled_window_new (NULL, NULL);
 
229
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
230
  gtk_box_pack_start (GTK_BOX (main_vbox), scroll, TRUE, TRUE, 0);
 
231
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
 
232
  gtk_widget_show (scroll);
 
233
 
 
234
  /* create the store and automatically sort it */
 
235
  dialog->store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_OBJECT, G_TYPE_BOOLEAN);
 
236
  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (dialog->store), COLUMN_MODULE, panel_item_dialog_compare_func, NULL, NULL);
 
237
  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->store), COLUMN_MODULE, GTK_SORT_ASCENDING);
 
238
 
 
239
  /* create treemodel with filter */
 
240
  filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->store), NULL);
 
241
  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter), panel_item_dialog_visible_func, entry, NULL);
 
242
  g_signal_connect_swapped (G_OBJECT (entry), "changed", G_CALLBACK (gtk_tree_model_filter_refilter), filter);
 
243
 
 
244
  /* treeview */
 
245
  treeview = gtk_tree_view_new_with_model (filter);
 
246
  dialog->treeview = GTK_TREE_VIEW (treeview);
 
247
  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
 
248
  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), FALSE);
 
249
  gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (treeview), panel_item_dialog_separator_func, NULL, NULL);
 
250
  g_signal_connect_swapped (G_OBJECT (treeview), "start-interactive-search", G_CALLBACK (gtk_widget_grab_focus), entry);
 
251
  gtk_container_add (GTK_CONTAINER (scroll), treeview);
 
252
  gtk_widget_show (treeview);
 
253
 
 
254
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
 
255
  g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (panel_item_dialog_selection_changed), dialog);
 
256
 
 
257
  g_object_unref (G_OBJECT (filter));
 
258
 
 
259
  /* signals for treeview dnd */
 
260
  gtk_drag_source_set (treeview, GDK_BUTTON1_MASK, drag_targets, G_N_ELEMENTS (drag_targets), GDK_ACTION_COPY);
 
261
  g_signal_connect (G_OBJECT (treeview), "drag-begin", G_CALLBACK (panel_item_dialog_drag_begin), dialog);
 
262
  g_signal_connect (G_OBJECT (treeview), "drag-data-get", G_CALLBACK (panel_item_dialog_drag_data_get), dialog);
 
263
 
 
264
  /* remove plugin when dropping it back in the treeview */
 
265
  gtk_drag_dest_set (GTK_WIDGET (treeview), GTK_DEST_DEFAULT_ALL,
 
266
      drop_targets, G_N_ELEMENTS (drop_targets), GDK_ACTION_MOVE);
 
267
  g_signal_connect (G_OBJECT (treeview), "drag-data-received", G_CALLBACK (panel_item_dialog_drag_data_received), dialog);
 
268
 
 
269
  /* icon renderer */
 
270
  renderer = gtk_cell_renderer_pixbuf_new ();
 
271
  column = gtk_tree_view_column_new_with_attributes ("", renderer, "icon-name", COLUMN_ICON_NAME, "sensitive", COLUMN_SENSITIVE, NULL);
 
272
  g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_DND, NULL);
 
273
  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
274
 
 
275
  /* text renderer */
 
276
  renderer = gtk_cell_renderer_text_new ();
 
277
  column = gtk_tree_view_column_new ();
 
278
  gtk_tree_view_column_pack_start (column, renderer, TRUE);
 
279
  gtk_tree_view_column_set_cell_data_func (column, renderer, panel_item_dialog_text_renderer, NULL, NULL);
 
280
  gtk_tree_view_column_set_attributes (column, renderer, "sensitive", COLUMN_SENSITIVE, NULL);
 
281
  g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 
282
  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
283
 
 
284
  panel_item_dialog_populate_store (dialog);
 
285
}
 
286
 
 
287
 
 
288
 
 
289
static void
 
290
panel_item_dialog_finalize (GObject *object)
 
291
{
 
292
  PanelItemDialog *dialog = PANEL_ITEM_DIALOG (object);
 
293
 
 
294
  /* disconnect unique-changed signal */
 
295
  g_signal_handlers_disconnect_by_func (G_OBJECT (dialog->factory),
 
296
      panel_item_dialog_unique_changed, dialog);
 
297
 
 
298
  /* make the windows sensitive again */
 
299
  panel_application_windows_sensitive (dialog->application, TRUE);
 
300
 
 
301
  g_object_unref (G_OBJECT (dialog->store));
 
302
  g_object_unref (G_OBJECT (dialog->factory));
 
303
  g_object_unref (G_OBJECT (dialog->application));
 
304
 
 
305
  (*G_OBJECT_CLASS (panel_item_dialog_parent_class)->finalize) (object);
 
306
}
 
307
 
 
308
 
 
309
 
 
310
static void
 
311
panel_item_dialog_response (GtkDialog *gtk_dialog,
 
312
                            gint       response_id)
 
313
{
 
314
  PanelItemDialog *dialog = PANEL_ITEM_DIALOG (gtk_dialog);
 
315
  PanelModule     *module;
 
316
 
 
317
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
318
  panel_return_if_fail (GTK_IS_TREE_VIEW (dialog->treeview));
 
319
  panel_return_if_fail (PANEL_IS_APPLICATION (dialog->application));
 
320
 
 
321
  if (response_id == GTK_RESPONSE_HELP)
 
322
    {
 
323
      panel_utils_show_help (GTK_WINDOW (gtk_dialog), "add-new-items", NULL);
 
324
    }
 
325
  else if (response_id == GTK_RESPONSE_OK)
 
326
    {
 
327
      module = panel_item_dialog_get_selected_module (dialog->treeview);
 
328
      if (G_LIKELY (module != NULL))
 
329
        {
 
330
          panel_application_add_new_item (dialog->application,
 
331
              panel_module_get_name (module), NULL);
 
332
          g_object_unref (G_OBJECT (module));
 
333
        }
 
334
    }
 
335
  else
 
336
    {
 
337
      if (!panel_preferences_dialog_visible ())
 
338
        panel_application_window_select (dialog->application, NULL);
 
339
 
 
340
      gtk_widget_destroy (GTK_WIDGET (gtk_dialog));
 
341
    }
 
342
}
 
343
 
 
344
 
 
345
 
 
346
static void
 
347
panel_item_dialog_unique_changed (PanelModuleFactory *factory,
 
348
                                  PanelModule        *module,
 
349
                                  PanelItemDialog    *dialog)
 
350
{
 
351
  panel_return_if_fail (PANEL_IS_MODULE_FACTORY (factory));
 
352
  panel_return_if_fail (PANEL_IS_MODULE (module));
 
353
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
354
  panel_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
 
355
 
 
356
  /* search the module and update its sensitivity */
 
357
  g_object_set_data (G_OBJECT (dialog->store), "dialog", dialog);
 
358
  gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->store),
 
359
      panel_item_dialog_unique_changed_foreach, module);
 
360
  g_object_set_data (G_OBJECT (dialog->store), "dialog", NULL);
 
361
 
 
362
  /* update button sensitivity */
 
363
  panel_item_dialog_selection_changed (gtk_tree_view_get_selection (dialog->treeview), dialog);
 
364
}
 
365
 
 
366
 
 
367
 
 
368
static gboolean
 
369
panel_item_dialog_unique_changed_foreach (GtkTreeModel *model,
 
370
                                          GtkTreePath  *path,
 
371
                                          GtkTreeIter  *iter,
 
372
                                          gpointer      user_data)
 
373
{
 
374
  PanelModule *module;
 
375
  gboolean     result;
 
376
  GtkWidget   *dialog;
 
377
 
 
378
  panel_return_val_if_fail (PANEL_IS_MODULE (user_data), FALSE);
 
379
 
 
380
  /* get the module of this iter */
 
381
  gtk_tree_model_get (model, iter, COLUMN_MODULE, &module, -1);
 
382
 
 
383
  /* skip the separator */
 
384
  if (G_UNLIKELY (module == NULL))
 
385
    return FALSE;
 
386
 
 
387
  /* check if this is the module we're looking for */
 
388
  result = !!(module == PANEL_MODULE (user_data));
 
389
 
 
390
  if (result)
 
391
    {
 
392
      dialog = g_object_get_data (G_OBJECT (model), "dialog");
 
393
      panel_return_val_if_fail (PANEL_IS_ITEM_DIALOG (dialog), FALSE);
 
394
 
 
395
      /* update the module unique status */
 
396
      gtk_list_store_set (GTK_LIST_STORE (model), iter,
 
397
                          COLUMN_SENSITIVE, panel_module_is_usable (module,
 
398
                              gtk_widget_get_screen (dialog)), -1);
 
399
    }
 
400
 
 
401
  g_object_unref (G_OBJECT (module));
 
402
 
 
403
  /* continue searching or break if the module was found */
 
404
  return result;
 
405
}
 
406
 
 
407
 
 
408
 
 
409
static gboolean
 
410
panel_item_dialog_separator_func (GtkTreeModel *model,
 
411
                                  GtkTreeIter  *iter,
 
412
                                  gpointer      user_data)
 
413
{
 
414
  PanelModule *module;
 
415
 
 
416
  /* it's a separator if the module is null */
 
417
  gtk_tree_model_get (model, iter, COLUMN_MODULE, &module, -1);
 
418
  if (G_UNLIKELY (module == NULL))
 
419
    return TRUE;
 
420
  g_object_unref (G_OBJECT (module));
 
421
 
 
422
  return FALSE;
 
423
}
 
424
 
 
425
 
 
426
 
 
427
static void
 
428
panel_item_dialog_selection_changed (GtkTreeSelection *selection,
 
429
                                     PanelItemDialog  *dialog)
 
430
{
 
431
  PanelModule *module;
 
432
  gboolean     sensitive = FALSE;
 
433
 
 
434
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
435
  panel_return_if_fail (GTK_IS_TREE_SELECTION (selection));
 
436
 
 
437
  module = panel_item_dialog_get_selected_module (dialog->treeview);
 
438
  if (module != NULL)
 
439
    {
 
440
      sensitive = panel_module_is_usable (module, gtk_widget_get_screen (GTK_WIDGET (dialog)));
 
441
      g_object_unref (G_OBJECT (module));
 
442
    }
 
443
 
 
444
  gtk_widget_set_sensitive (dialog->add_button, sensitive);
 
445
}
 
446
 
 
447
 
 
448
 
 
449
static PanelModule *
 
450
panel_item_dialog_get_selected_module (GtkTreeView *treeview)
 
451
{
 
452
  GtkTreeSelection *selection;
 
453
  GtkTreeModel     *model;
 
454
  GtkTreeIter       iter;
 
455
  PanelModule      *module = NULL;
 
456
 
 
457
  panel_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), NULL);
 
458
 
 
459
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
 
460
  if (G_LIKELY (selection != NULL))
 
461
    {
 
462
      if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
463
        {
 
464
          gtk_tree_model_get (model, &iter, COLUMN_MODULE, &module, -1);
 
465
          if (G_LIKELY (module != NULL))
 
466
            {
 
467
              /* check if the module is still valid */
 
468
              if (!panel_module_is_valid (module))
 
469
                {
 
470
                  g_object_unref (G_OBJECT (module));
 
471
 
 
472
                  /* no, cannot add it, return null */
 
473
                  module = NULL;
 
474
                }
 
475
            }
 
476
        }
 
477
    }
 
478
 
 
479
  return module;
 
480
}
 
481
 
 
482
 
 
483
 
 
484
static void
 
485
panel_item_dialog_drag_begin (GtkWidget       *treeview,
 
486
                              GdkDragContext  *context,
 
487
                              PanelItemDialog *dialog)
 
488
{
 
489
  PanelModule  *module;
 
490
  const gchar  *icon_name;
 
491
  GtkIconTheme *theme;
 
492
 
 
493
  panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
 
494
  panel_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
495
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
496
 
 
497
  module = panel_item_dialog_get_selected_module (GTK_TREE_VIEW (treeview));
 
498
  if (G_LIKELY (module != NULL))
 
499
    {
 
500
      if (panel_module_is_usable (module, gtk_widget_get_screen (GTK_WIDGET (dialog))))
 
501
        {
 
502
          /* set the drag icon */
 
503
          icon_name = panel_module_get_icon_name (module);
 
504
          theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (treeview));
 
505
          if (!exo_str_is_empty (icon_name)
 
506
              && gtk_icon_theme_has_icon (theme, icon_name))
 
507
            gtk_drag_set_icon_name (context, icon_name, 0, 0);
 
508
          else
 
509
            gtk_drag_set_icon_default (context);
 
510
        }
 
511
      else
 
512
        {
 
513
          /* plugin is not usable */
 
514
          gtk_drag_set_icon_name (context, GTK_STOCK_CANCEL, 0, 0);
 
515
        }
 
516
 
 
517
      g_object_unref (G_OBJECT (module));
 
518
    }
 
519
}
 
520
 
 
521
 
 
522
 
 
523
static void
 
524
panel_item_dialog_drag_data_get (GtkWidget        *treeview,
 
525
                                 GdkDragContext   *context,
 
526
                                 GtkSelectionData *selection_data,
 
527
                                 guint             drag_info,
 
528
                                 guint             drag_time,
 
529
                                 PanelItemDialog  *dialog)
 
530
{
 
531
  PanelModule *module;
 
532
  const gchar *internal_name;
 
533
 
 
534
  panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
 
535
  panel_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
536
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
537
 
 
538
  module = panel_item_dialog_get_selected_module (GTK_TREE_VIEW (treeview));
 
539
  if (G_LIKELY (module != NULL))
 
540
    {
 
541
      /* set the internal module name as selection data */
 
542
      internal_name = panel_module_get_name (module);
 
543
      gtk_selection_data_set (selection_data, selection_data->target, 8,
 
544
          (guchar *) internal_name, strlen (internal_name));
 
545
      g_object_unref (G_OBJECT (module));
 
546
    }
 
547
}
 
548
 
 
549
 
 
550
 
 
551
static void
 
552
panel_item_dialog_drag_data_received (GtkWidget        *treeview,
 
553
                                      GdkDragContext   *context,
 
554
                                      gint              x,
 
555
                                      gint              y,
 
556
                                      GtkSelectionData *selection_data,
 
557
                                      guint             info,
 
558
                                      guint             drag_time,
 
559
                                      PanelItemDialog  *dialog)
 
560
{
 
561
  GtkWidget *widget;
 
562
 
 
563
  panel_return_if_fail (GTK_IS_TREE_VIEW (treeview));
 
564
  panel_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
 
565
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
566
 
 
567
  /* ask the plugin to cleanup when we destroy a panel window */
 
568
  widget = gtk_drag_get_source_widget (context);
 
569
  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (widget));
 
570
  xfce_panel_plugin_provider_ask_remove (XFCE_PANEL_PLUGIN_PROVIDER (widget));
 
571
 
 
572
  gtk_drag_finish (context, TRUE, FALSE, drag_time);
 
573
 
 
574
  g_signal_stop_emission_by_name (G_OBJECT (treeview), "drag-data-received");
 
575
}
 
576
 
 
577
 
 
578
 
 
579
static void
 
580
panel_item_dialog_populate_store (PanelItemDialog *dialog)
 
581
{
 
582
  GList       *modules, *li;
 
583
  gint         n;
 
584
  GtkTreeIter  iter;
 
585
  PanelModule *module;
 
586
 
 
587
  panel_return_if_fail (PANEL_IS_ITEM_DIALOG (dialog));
 
588
  panel_return_if_fail (PANEL_IS_MODULE_FACTORY (dialog->factory));
 
589
  panel_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
 
590
 
 
591
  /* add all known modules in the factory */
 
592
  modules = panel_module_factory_get_modules (dialog->factory);
 
593
  for (li = modules, n = 0; li != NULL; li = li->next, n++)
 
594
    {
 
595
      module = PANEL_MODULE (li->data);
 
596
 
 
597
      gtk_list_store_insert_with_values (dialog->store, &iter, n,
 
598
          COLUMN_MODULE, module,
 
599
          COLUMN_ICON_NAME, panel_module_get_icon_name (module),
 
600
          COLUMN_SENSITIVE, panel_module_is_usable (module,
 
601
              gtk_widget_get_screen (GTK_WIDGET (dialog))), -1);
 
602
    }
 
603
 
 
604
  g_list_free (modules);
 
605
 
 
606
  /* add an empty item for separator in 2nd position */
 
607
  if (panel_module_factory_has_launcher (dialog->factory))
 
608
    gtk_list_store_insert_with_values (dialog->store, &iter, 1,
 
609
                                       COLUMN_MODULE, NULL, -1);
 
610
}
 
611
 
 
612
 
 
613
 
 
614
static gint
 
615
panel_item_dialog_compare_func (GtkTreeModel *model,
 
616
                                GtkTreeIter  *a,
 
617
                                GtkTreeIter  *b,
 
618
                                gpointer      user_data)
 
619
{
 
620
  PanelModule *module_a;
 
621
  PanelModule *module_b;
 
622
  const gchar *name_a;
 
623
  const gchar *name_b;
 
624
  gint         result;
 
625
 
 
626
  /* get modules a name */
 
627
  gtk_tree_model_get (model, a, COLUMN_MODULE, &module_a, -1);
 
628
  gtk_tree_model_get (model, b, COLUMN_MODULE, &module_b, -1);
 
629
 
 
630
  if (G_UNLIKELY (module_a == NULL || module_b == NULL))
 
631
    {
 
632
      /* don't move the separator */
 
633
      result = 0;
 
634
    }
 
635
  else if (exo_str_is_equal (LAUNCHER_PLUGIN_NAME,
 
636
                             panel_module_get_name (module_a)))
 
637
    {
 
638
      /* move the launcher to the first position */
 
639
      result = -1;
 
640
    }
 
641
  else if (exo_str_is_equal (LAUNCHER_PLUGIN_NAME,
 
642
                             panel_module_get_name (module_b)))
 
643
    {
 
644
      /* move the launcher to the first position */
 
645
      result = 1;
 
646
    }
 
647
  else
 
648
    {
 
649
      /* get the visible module names */
 
650
      name_a = panel_module_get_display_name (module_a);
 
651
      name_b = panel_module_get_display_name (module_b);
 
652
 
 
653
      /* get sort order */
 
654
      if (G_LIKELY (name_a && name_b))
 
655
        result = g_utf8_collate (name_a, name_b);
 
656
      else if (name_a == name_b)
 
657
        result = 0;
 
658
      else
 
659
        result = name_a == NULL ? 1 : -1;
 
660
    }
 
661
 
 
662
  if (G_LIKELY (module_a))
 
663
    g_object_unref (G_OBJECT (module_a));
 
664
  if (G_LIKELY (module_b))
 
665
    g_object_unref (G_OBJECT (module_b));
 
666
 
 
667
  return result;
 
668
}
 
669
 
 
670
 
 
671
 
 
672
static gboolean
 
673
panel_item_dialog_visible_func (GtkTreeModel *model,
 
674
                                GtkTreeIter  *iter,
 
675
                                gpointer      user_data)
 
676
{
 
677
 
 
678
  GtkEntry    *entry = GTK_ENTRY (user_data);
 
679
  const gchar *text, *name, *comment;
 
680
  PanelModule *module;
 
681
  gchar       *normalized;
 
682
  gchar       *text_casefolded;
 
683
  gchar       *name_casefolded;
 
684
  gchar       *comment_casefolded;
 
685
  gboolean     visible = FALSE;
 
686
 
 
687
  /* search string from dialog */
 
688
  text = gtk_entry_get_text (entry);
 
689
  if (G_UNLIKELY (exo_str_is_empty (text)))
 
690
    return TRUE;
 
691
 
 
692
  gtk_tree_model_get (model, iter, COLUMN_MODULE, &module, -1);
 
693
 
 
694
  /* hide separator when searching */
 
695
  if (G_UNLIKELY (module == NULL))
 
696
    return FALSE;
 
697
 
 
698
  /* casefold the search text */
 
699
  normalized = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
 
700
  text_casefolded = g_utf8_casefold (normalized, -1);
 
701
  g_free (normalized);
 
702
 
 
703
  name = panel_module_get_display_name (module);
 
704
  if (G_LIKELY (name != NULL))
 
705
    {
 
706
      /* casefold the name */
 
707
      normalized = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
 
708
      name_casefolded = g_utf8_casefold (normalized, -1);
 
709
      g_free (normalized);
 
710
 
 
711
      /* search */
 
712
      visible = (strstr (name_casefolded, text_casefolded) != NULL);
 
713
 
 
714
      g_free (name_casefolded);
 
715
    }
 
716
 
 
717
  if (!visible)
 
718
    {
 
719
      comment = panel_module_get_comment (module);
 
720
      if (comment != NULL)
 
721
        {
 
722
          /* casefold the comment */
 
723
          normalized = g_utf8_normalize (comment, -1, G_NORMALIZE_ALL);
 
724
          comment_casefolded = g_utf8_casefold (normalized, -1);
 
725
          g_free (normalized);
 
726
 
 
727
          /* search */
 
728
          visible = (strstr (comment_casefolded, text_casefolded) != NULL);
 
729
 
 
730
          g_free (comment_casefolded);
 
731
        }
 
732
    }
 
733
 
 
734
  g_free (text_casefolded);
 
735
  g_object_unref (G_OBJECT (module));
 
736
 
 
737
  return visible;
 
738
}
 
739
 
 
740
 
 
741
 
 
742
static void
 
743
panel_item_dialog_text_renderer (GtkTreeViewColumn *column,
 
744
                                 GtkCellRenderer   *renderer,
 
745
                                 GtkTreeModel      *model,
 
746
                                 GtkTreeIter       *iter,
 
747
                                 gpointer           user_data)
 
748
{
 
749
  PanelModule *module;
 
750
  gchar       *markup;
 
751
  const gchar *name, *comment;
 
752
 
 
753
  gtk_tree_model_get (model, iter, COLUMN_MODULE, &module, -1);
 
754
  if (G_UNLIKELY (module == NULL))
 
755
    return;
 
756
 
 
757
  /* avoid (null) in markup string */
 
758
  comment = panel_module_get_comment (module);
 
759
  if (exo_str_is_empty (comment))
 
760
    comment = "";
 
761
 
 
762
  name = panel_module_get_display_name (module);
 
763
  markup = g_markup_printf_escaped ("<b>%s</b>\n%s", name, comment);
 
764
  g_object_set (G_OBJECT (renderer), "markup", markup, NULL);
 
765
  g_free (markup);
 
766
 
 
767
  g_object_unref (G_OBJECT (module));
 
768
}
 
769
 
 
770
 
 
771
 
 
772
void
 
773
panel_item_dialog_show (PanelWindow *window)
 
774
{
 
775
  GdkScreen        *screen;
 
776
  PanelApplication *application;
 
777
 
 
778
  panel_return_if_fail (window == NULL || PANEL_IS_WINDOW (window));
 
779
 
 
780
  /* check if not the entire application is locked */
 
781
  if (panel_dialogs_kiosk_warning ())
 
782
    return;
 
783
 
 
784
  if (G_LIKELY (dialog_singleton == NULL))
 
785
    {
 
786
      /* create new dialog singleton */
 
787
      dialog_singleton = g_object_new (PANEL_TYPE_ITEM_DIALOG, NULL);
 
788
      g_object_add_weak_pointer (G_OBJECT (dialog_singleton), (gpointer) &dialog_singleton);
 
789
    }
 
790
 
 
791
  /* show the dialog on the same screen as the panel */
 
792
  if (G_UNLIKELY (window != NULL))
 
793
    {
 
794
      /* set the active panel */
 
795
      application = panel_application_get ();
 
796
      panel_application_window_select (application, window);
 
797
      g_object_unref (G_OBJECT (application));
 
798
 
 
799
      screen = gtk_window_get_screen (GTK_WINDOW (window));
 
800
    }
 
801
  else
 
802
    {
 
803
      screen = gdk_screen_get_default ();
 
804
    }
 
805
  gtk_window_set_screen (GTK_WINDOW (dialog_singleton), screen);
 
806
 
 
807
  /* show the dialog */
 
808
  gtk_widget_show (GTK_WIDGET (dialog_singleton));
 
809
 
 
810
  /* focus the window */
 
811
  gtk_window_present (GTK_WINDOW (dialog_singleton));
 
812
}
 
813
 
 
814
 
 
815
 
 
816
gboolean
 
817
panel_item_dialog_visible (void)
 
818
{
 
819
  return !!(dialog_singleton != NULL);
 
820
}