~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/common/plugin-browser.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This is a plug-in for the GIMP.
 
5
 *
 
6
 * Copyright (C) 1999 Andy Thomas  alt@picnic.demon.co.uk
 
7
 *
 
8
 * Note some portions of the UI comes from the dbbrowser plugin.
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 2 of the License, or
 
12
 * (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software
 
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
22
 */
 
23
 
 
24
#include "config.h"
 
25
 
 
26
#include <string.h>
 
27
#include <time.h>
 
28
 
 
29
#include <gtk/gtk.h>
 
30
 
 
31
#include <libgimp/gimp.h>
 
32
#include <libgimp/gimpui.h>
 
33
 
 
34
#include "libgimp/stdplugins-intl.h"
 
35
 
 
36
 
 
37
#define PLUG_IN_PROC    "plug-in-plug-in-details"
 
38
#define PLUG_IN_BINARY  "plugin-browser"
 
39
#define DBL_LIST_WIDTH  250
 
40
#define DBL_WIDTH       (DBL_LIST_WIDTH + 400)
 
41
#define DBL_HEIGHT      250
 
42
 
 
43
 
 
44
enum
 
45
{
 
46
  LIST_COLUMN_NAME,
 
47
  LIST_COLUMN_DATE,
 
48
  LIST_COLUMN_DATE_STRING,
 
49
  LIST_COLUMN_PATH,
 
50
  LIST_COLUMN_IMAGE_TYPES,
 
51
  LIST_COLUMN_PINFO,
 
52
  N_LIST_COLUMNS
 
53
};
 
54
 
 
55
enum
 
56
{
 
57
  TREE_COLUMN_PATH_NAME,
 
58
  TREE_COLUMN_DATE,
 
59
  TREE_COLUMN_DATE_STRING,
 
60
  TREE_COLUMN_IMAGE_TYPES,
 
61
  TREE_COLUMN_MPATH,
 
62
  TREE_COLUMN_PINFO,
 
63
  N_TREE_OLUMNS
 
64
};
 
65
 
 
66
typedef struct
 
67
{
 
68
  GtkWidget   *dialog;
 
69
 
 
70
  GtkWidget   *browser;
 
71
 
 
72
  GtkTreeView *list_view;
 
73
  GtkTreeView *tree_view;
 
74
} PluginBrowser;
 
75
 
 
76
typedef struct
 
77
{
 
78
  gchar *menu;
 
79
  gchar *accel;
 
80
  gchar *prog;
 
81
  gchar *types;
 
82
  gchar *realname;
 
83
  gint  instime;
 
84
} PInfo;
 
85
 
 
86
 
 
87
/* Declare some local functions.
 
88
 */
 
89
static void        query (void);
 
90
static void        run   (const gchar      *name,
 
91
                          gint              nparams,
 
92
                          const GimpParam  *param,
 
93
                          gint             *nreturn_vals,
 
94
                          GimpParam       **return_vals);
 
95
 
 
96
 
 
97
static GtkWidget * browser_dialog_new             (void);
 
98
static void        browser_dialog_response        (GtkWidget        *widget,
 
99
                                                   gint              response_id,
 
100
                                                   PluginBrowser    *browser);
 
101
static void        browser_list_selection_changed (GtkTreeSelection *selection,
 
102
                                                   PluginBrowser    *browser);
 
103
static void        browser_tree_selection_changed (GtkTreeSelection *selection,
 
104
                                                   PluginBrowser    *browser);
 
105
static void        browser_show_plugin            (PluginBrowser    *browser,
 
106
                                                   PInfo            *pinfo);
 
107
 
 
108
static gboolean    find_existing_mpath            (GtkTreeModel     *model,
 
109
                                                   const gchar      *mpath,
 
110
                                                   GtkTreeIter      *return_iter);
 
111
 
 
112
 
 
113
const GimpPlugInInfo PLUG_IN_INFO =
 
114
{
 
115
  NULL,  /* init_proc  */
 
116
  NULL,  /* quit_proc  */
 
117
  query, /* query_proc */
 
118
  run,   /* run_proc   */
 
119
};
 
120
 
 
121
 
 
122
MAIN ()
 
123
 
 
124
 
 
125
static void
 
126
query (void)
 
127
{
 
128
  static const GimpParamDef args[] =
 
129
  {
 
130
    { GIMP_PDB_INT32, "run-mode", "Interactive, [non-interactive]" }
 
131
  };
 
132
 
 
133
  gimp_install_procedure (PLUG_IN_PROC,
 
134
                          N_("Display information about plug-ins"),
 
135
                          "Allows to browse the plug-in menus system. You can "
 
136
                          "search for plug-in names, sort by name or menu "
 
137
                          "location and you can view a tree representation "
 
138
                          "of the plug-in menus. Can also be of help to find "
 
139
                          "where new plug-ins have installed themselves in "
 
140
                          "the menus.",
 
141
                          "Andy Thomas",
 
142
                          "Andy Thomas",
 
143
                          "1999",
 
144
                          N_("_Plug-In Browser"),
 
145
                          "",
 
146
                          GIMP_PLUGIN,
 
147
                          G_N_ELEMENTS (args), 0,
 
148
                          args, NULL);
 
149
 
 
150
  gimp_plugin_menu_register (PLUG_IN_PROC, "<Toolbox>/Xtns/Extensions");
 
151
  gimp_plugin_icon_register (PLUG_IN_PROC, GIMP_ICON_TYPE_STOCK_ID,
 
152
                             (const guint8 *) GIMP_STOCK_PLUGIN);
 
153
}
 
154
 
 
155
static void
 
156
run (const gchar      *name,
 
157
     gint              nparams,
 
158
     const GimpParam  *param,
 
159
     gint             *nreturn_vals,
 
160
     GimpParam       **return_vals)
 
161
{
 
162
  static GimpParam  values[2];
 
163
  GimpRunMode       run_mode;
 
164
 
 
165
  run_mode = param[0].data.d_int32;
 
166
 
 
167
  *nreturn_vals = 1;
 
168
  *return_vals  = values;
 
169
 
 
170
  values[0].type          = GIMP_PDB_STATUS;
 
171
  values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
 
172
 
 
173
  INIT_I18N ();
 
174
 
 
175
  if (strcmp (name, PLUG_IN_PROC) == 0)
 
176
    {
 
177
      *nreturn_vals = 1;
 
178
 
 
179
      values[0].data.d_status = GIMP_PDB_SUCCESS;
 
180
 
 
181
      browser_dialog_new ();
 
182
      gtk_main ();
 
183
    }
 
184
}
 
185
 
 
186
static gboolean
 
187
find_existing_mpath_helper (GtkTreeModel *model,
 
188
                            GtkTreeIter  *iter,
 
189
                            GtkTreePath  *path,
 
190
                            const gchar  *mpath,
 
191
                            GtkTreeIter  *return_iter)
 
192
{
 
193
  do
 
194
    {
 
195
      GtkTreeIter  child;
 
196
      gchar       *picked_mpath;
 
197
 
 
198
      gtk_tree_model_get (model, iter,
 
199
                          TREE_COLUMN_MPATH, &picked_mpath,
 
200
                          -1);
 
201
 
 
202
      if (! strcmp (mpath, picked_mpath))
 
203
        {
 
204
          *return_iter = *iter;
 
205
          g_free (picked_mpath);
 
206
          return TRUE;
 
207
        }
 
208
 
 
209
      if (gtk_tree_model_iter_children (model, &child, iter))
 
210
        {
 
211
          gtk_tree_path_down (path);
 
212
 
 
213
          if (find_existing_mpath_helper (model, &child, path,
 
214
                                          mpath, return_iter))
 
215
            {
 
216
              g_free (picked_mpath);
 
217
              return TRUE;
 
218
            }
 
219
 
 
220
          gtk_tree_path_up (path);
 
221
        }
 
222
 
 
223
      gtk_tree_path_next (path);
 
224
      g_free (picked_mpath);
 
225
    }
 
226
  while (gtk_tree_model_iter_next (model, iter));
 
227
 
 
228
  return FALSE;
 
229
}
 
230
 
 
231
static gboolean
 
232
find_existing_mpath (GtkTreeModel *model,
 
233
                     const gchar  *mpath,
 
234
                     GtkTreeIter  *return_iter)
 
235
{
 
236
  GtkTreePath *path = gtk_tree_path_new_first ();
 
237
  GtkTreeIter  parent;
 
238
  gboolean     found;
 
239
 
 
240
  if (! gtk_tree_model_get_iter (model, &parent, path))
 
241
    {
 
242
      gtk_tree_path_free (path);
 
243
      return FALSE;
 
244
    }
 
245
 
 
246
  found = find_existing_mpath_helper (model, &parent, path, mpath, return_iter);
 
247
 
 
248
  gtk_tree_path_free (path);
 
249
 
 
250
  return found;
 
251
}
 
252
 
 
253
static void
 
254
get_parent (PluginBrowser *browser,
 
255
            const gchar   *mpath,
 
256
            GtkTreeIter   *parent)
 
257
{
 
258
  GtkTreeIter   last_parent;
 
259
  gchar        *tmp_ptr;
 
260
  gchar        *str_ptr;
 
261
  const gchar  *leaf_ptr;
 
262
  GtkTreeStore *tree_store;
 
263
 
 
264
  if (! mpath)
 
265
    return;
 
266
 
 
267
  tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view));
 
268
 
 
269
  /* Lookup for existing mpath */
 
270
  if (find_existing_mpath (GTK_TREE_MODEL (tree_store), mpath, parent))
 
271
    return;
 
272
 
 
273
  tmp_ptr = g_strdup (mpath);
 
274
 
 
275
  /* Strip off trailing ellipsis */
 
276
  str_ptr = strstr (mpath, "...");
 
277
  if (str_ptr && str_ptr == (mpath + strlen (mpath) - 3))
 
278
    *str_ptr = '\0';
 
279
 
 
280
  str_ptr = strrchr (tmp_ptr, '/');
 
281
 
 
282
  if (str_ptr == NULL)
 
283
    {
 
284
      leaf_ptr = mpath;
 
285
      gtk_tree_store_append (tree_store, parent, NULL);
 
286
      gtk_tree_store_set (tree_store, parent,
 
287
                          TREE_COLUMN_MPATH,     mpath,
 
288
                          TREE_COLUMN_PATH_NAME, mpath,
 
289
                          -1);
 
290
    }
 
291
  else
 
292
    {
 
293
      leaf_ptr = g_strdup (str_ptr + 1);
 
294
 
 
295
      *str_ptr = '\0';
 
296
 
 
297
      get_parent (browser, tmp_ptr, &last_parent);
 
298
      gtk_tree_store_append (tree_store, parent, &last_parent);
 
299
      gtk_tree_store_set (tree_store, parent,
 
300
                          TREE_COLUMN_MPATH,     mpath,
 
301
                          TREE_COLUMN_PATH_NAME, leaf_ptr,
 
302
                          -1);
 
303
    }
 
304
}
 
305
 
 
306
static void
 
307
insert_into_tree_view (PluginBrowser *browser,
 
308
                       const gchar   *name,
 
309
                       gint64         xtime,
 
310
                       const gchar   *xtimestr,
 
311
                       const gchar   *menu_str,
 
312
                       const gchar   *types_str,
 
313
                       PInfo         *pinfo)
 
314
{
 
315
  gchar        *labels[3];
 
316
  gchar        *str_ptr;
 
317
  gchar        *tmp_ptr;
 
318
  gchar        *leaf_ptr;
 
319
  GtkTreeIter   parent, iter;
 
320
  GtkTreeStore *tree_store;
 
321
 
 
322
  /* Find all nodes */
 
323
  /* Last one is the leaf part */
 
324
 
 
325
  tmp_ptr = g_strdup (menu_str);
 
326
 
 
327
  str_ptr = strrchr (tmp_ptr, '/');
 
328
 
 
329
  if (str_ptr == NULL)
 
330
    return; /* No node */
 
331
 
 
332
  leaf_ptr = g_strdup (str_ptr + 1);
 
333
 
 
334
  *str_ptr = '\0';
 
335
 
 
336
  /*   printf("inserting %s...\n",menu_str); */
 
337
 
 
338
  get_parent (browser, tmp_ptr, &parent);
 
339
 
 
340
  /* Last was a leaf */
 
341
  /*   printf("found leaf %s parent = %p\n",leaf_ptr,parent); */
 
342
  labels[0] = g_strdup (name);
 
343
  labels[1] = g_strdup (xtimestr);
 
344
  labels[2] = g_strdup (types_str);
 
345
 
 
346
  tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view));
 
347
  gtk_tree_store_append (tree_store, &iter, &parent);
 
348
  gtk_tree_store_set (tree_store, &iter,
 
349
                      TREE_COLUMN_MPATH,       menu_str,
 
350
                      TREE_COLUMN_PATH_NAME,   name,
 
351
                      TREE_COLUMN_IMAGE_TYPES, types_str,
 
352
                      TREE_COLUMN_DATE,        xtime,
 
353
                      TREE_COLUMN_DATE_STRING, xtimestr,
 
354
                      TREE_COLUMN_PINFO,       pinfo,
 
355
                      -1);
 
356
}
 
357
 
 
358
static void
 
359
browser_search (GimpBrowser   *gimp_browser,
 
360
                const gchar   *search_text,
 
361
                gint           search_type,
 
362
                PluginBrowser *browser)
 
363
{
 
364
  GimpParam    *return_vals;
 
365
  gint          nreturn_vals;
 
366
  gint          num_plugins;
 
367
  gchar        *str;
 
368
  GtkListStore *list_store;
 
369
  GtkTreeStore *tree_store;
 
370
 
 
371
  gimp_browser_show_message (GIMP_BROWSER (browser->browser),
 
372
                             _("Searching by name"));
 
373
 
 
374
  return_vals = gimp_run_procedure ("gimp-plugins-query",
 
375
                                    &nreturn_vals,
 
376
                                    GIMP_PDB_STRING, search_text,
 
377
                                    GIMP_PDB_END);
 
378
 
 
379
  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
 
380
    num_plugins = return_vals[1].data.d_int32;
 
381
  else
 
382
    num_plugins = 0;
 
383
 
 
384
  if (! search_text || strlen (search_text) == 0)
 
385
    {
 
386
      str = g_strdup_printf (ngettext ("%d plug-in", "%d plug-ins",
 
387
                                       num_plugins),
 
388
                             num_plugins);
 
389
    }
 
390
  else
 
391
    {
 
392
      switch (num_plugins)
 
393
        {
 
394
        case 0:
 
395
          str = g_strdup (_("No matches for your query"));
 
396
          break;
 
397
        default:
 
398
          str = g_strdup_printf (ngettext ("%d plug-in matches your query",
 
399
                                           "%d plug-ins match your query",
 
400
                                           num_plugins), num_plugins);
 
401
          break;
 
402
        }
 
403
    }
 
404
 
 
405
  gtk_label_set_text (GTK_LABEL (gimp_browser->count_label), str);
 
406
  g_free (str);
 
407
 
 
408
  list_store = GTK_LIST_STORE (gtk_tree_view_get_model (browser->list_view));
 
409
  gtk_list_store_clear (list_store);
 
410
 
 
411
  tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view));
 
412
  gtk_tree_store_clear (tree_store);
 
413
 
 
414
  if (num_plugins > 0)
 
415
    {
 
416
      GtkTreeSelection  *sel;
 
417
      GtkTreeIter        iter;
 
418
      gchar            **menu_strs;
 
419
      gchar            **accel_strs;
 
420
      gchar            **prog_strs;
 
421
      gchar            **types_strs;
 
422
      gchar            **realname_strs;
 
423
      gint              *time_ints;
 
424
      gint               i;
 
425
 
 
426
      menu_strs     = return_vals[2].data.d_stringarray;
 
427
      accel_strs    = return_vals[4].data.d_stringarray;
 
428
      prog_strs     = return_vals[6].data.d_stringarray;
 
429
      types_strs    = return_vals[8].data.d_stringarray;
 
430
      time_ints     = return_vals[10].data.d_int32array;
 
431
      realname_strs = return_vals[12].data.d_stringarray;
 
432
 
 
433
      for (i = 0; i < num_plugins; i++)
 
434
        {
 
435
          PInfo     *pinfo;
 
436
          gchar     *name;
 
437
          gchar      xtimestr[50];
 
438
          struct tm *x;
 
439
          time_t     tx;
 
440
          gint       ret;
 
441
 
 
442
          /* Strip off trailing ellipsis */
 
443
          name = strstr (menu_strs[i], "...");
 
444
          if (name && name == (menu_strs[i] + strlen (menu_strs[i]) - 3))
 
445
            *name = '\0';
 
446
 
 
447
          name = strrchr (menu_strs[i], '/');
 
448
 
 
449
          if (name)
 
450
            {
 
451
              *name = '\0';
 
452
              name = name + 1;
 
453
            }
 
454
          else
 
455
            {
 
456
              name = menu_strs[i];
 
457
            }
 
458
 
 
459
          tx = time_ints[i];
 
460
          if (tx)
 
461
            {
 
462
              const gchar *format = "%c";  /* gcc workaround to avoid warning */
 
463
              gchar       *utf8;
 
464
 
 
465
              x = localtime (&tx);
 
466
              ret = strftime (xtimestr, sizeof (xtimestr), format, x);
 
467
              xtimestr[ret] = 0;
 
468
 
 
469
              if ((utf8 = g_locale_to_utf8 (xtimestr, -1, NULL, NULL, NULL)))
 
470
                {
 
471
                  strncpy (xtimestr, utf8, sizeof (xtimestr));
 
472
                  xtimestr[sizeof (xtimestr) - 1] = 0;
 
473
                  g_free (utf8);
 
474
                }
 
475
            }
 
476
          else
 
477
            {
 
478
              strcpy (xtimestr, "");
 
479
            }
 
480
 
 
481
          pinfo = g_new0 (PInfo, 1);
 
482
 
 
483
          pinfo->menu     = g_strdup (menu_strs[i]);
 
484
          pinfo->accel    = g_strdup (accel_strs[i]);
 
485
          pinfo->prog     = g_strdup (prog_strs[i]);
 
486
          pinfo->types    = g_strdup (types_strs[i]);
 
487
          pinfo->instime  = time_ints[i];
 
488
          pinfo->realname = g_strdup (realname_strs[i]);
 
489
 
 
490
          gtk_list_store_append (list_store, &iter);
 
491
          gtk_list_store_set (list_store, &iter,
 
492
                              LIST_COLUMN_NAME,        name,
 
493
                              LIST_COLUMN_DATE,        (gint64) tx,
 
494
                              LIST_COLUMN_DATE_STRING, xtimestr,
 
495
                              LIST_COLUMN_PATH,        menu_strs[i],
 
496
                              LIST_COLUMN_IMAGE_TYPES, types_strs[i],
 
497
                              LIST_COLUMN_PINFO,       pinfo,
 
498
                              -1);
 
499
 
 
500
          /* Now do the tree view.... */
 
501
          insert_into_tree_view (browser,
 
502
                                 name,
 
503
                                 (gint64) tx,
 
504
                                 xtimestr,
 
505
                                 menu_strs[i],
 
506
                                 types_strs[i],
 
507
                                 pinfo);
 
508
        }
 
509
 
 
510
      gtk_tree_view_columns_autosize (GTK_TREE_VIEW (browser->list_view));
 
511
      gtk_tree_view_columns_autosize (GTK_TREE_VIEW (browser->tree_view));
 
512
 
 
513
      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store),
 
514
                                            LIST_COLUMN_NAME,
 
515
                                            GTK_SORT_ASCENDING);
 
516
      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (tree_store),
 
517
                                            TREE_COLUMN_PATH_NAME,
 
518
                                            GTK_SORT_ASCENDING);
 
519
 
 
520
      sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (browser->list_view));
 
521
 
 
522
      gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store),
 
523
                                     &iter);
 
524
      gtk_tree_selection_select_iter (sel, &iter);
 
525
    }
 
526
  else
 
527
    {
 
528
      gimp_browser_show_message (GIMP_BROWSER (browser->browser),
 
529
                                 _("No matches"));
 
530
    }
 
531
 
 
532
  gimp_destroy_params (return_vals, nreturn_vals);
 
533
}
 
534
 
 
535
static GtkWidget *
 
536
browser_dialog_new (void)
 
537
{
 
538
  PluginBrowser     *browser;
 
539
  GtkWidget         *label, *notebook;
 
540
  GtkWidget         *scrolled_window;
 
541
  GtkListStore      *list_store;
 
542
  GtkTreeStore      *tree_store;
 
543
  GtkWidget         *list_view;
 
544
  GtkWidget         *tree_view;
 
545
  GtkTreeViewColumn *column;
 
546
  GtkCellRenderer   *renderer;
 
547
  GtkTreeSelection  *selection;
 
548
  GtkTreeIter        iter;
 
549
 
 
550
  gimp_ui_init (PLUG_IN_BINARY, FALSE);
 
551
 
 
552
  browser = g_new0 (PluginBrowser, 1);
 
553
 
 
554
  browser->dialog = gimp_dialog_new (_("Plug-In Browser"), PLUG_IN_BINARY,
 
555
                                     NULL, 0,
 
556
                                     gimp_standard_help_func, PLUG_IN_PROC,
 
557
 
 
558
                                     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
 
559
 
 
560
                                     NULL);
 
561
 
 
562
  g_signal_connect (browser->dialog, "response",
 
563
                    G_CALLBACK (browser_dialog_response),
 
564
                    browser);
 
565
 
 
566
  browser->browser = gimp_browser_new ();
 
567
  gtk_container_set_border_width (GTK_CONTAINER (browser->browser), 12);
 
568
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (browser->dialog)->vbox),
 
569
                     browser->browser);
 
570
  gtk_widget_show (browser->browser);
 
571
 
 
572
  g_signal_connect (browser->browser, "search",
 
573
                    G_CALLBACK (browser_search),
 
574
                    browser);
 
575
 
 
576
  /* left = notebook */
 
577
 
 
578
  notebook = gtk_notebook_new ();
 
579
  gtk_box_pack_start (GTK_BOX (GIMP_BROWSER (browser->browser)->left_vbox),
 
580
                      notebook, TRUE, TRUE, 0);
 
581
 
 
582
  /* list : list in a scrolled_win */
 
583
  list_store = gtk_list_store_new (N_LIST_COLUMNS,
 
584
                                   G_TYPE_STRING,
 
585
                                   G_TYPE_INT64,
 
586
                                   G_TYPE_STRING,
 
587
                                   G_TYPE_STRING,
 
588
                                   G_TYPE_STRING,
 
589
                                   G_TYPE_POINTER);
 
590
 
 
591
  list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
 
592
  g_object_unref (list_store);
 
593
 
 
594
  browser->list_view = GTK_TREE_VIEW (list_view);
 
595
 
 
596
  renderer = gtk_cell_renderer_text_new ();
 
597
  column = gtk_tree_view_column_new_with_attributes (_("Name"),
 
598
                                                     renderer,
 
599
                                                     "text", LIST_COLUMN_NAME,
 
600
                                                     NULL);
 
601
  gtk_tree_view_column_set_sort_column_id  (column, LIST_COLUMN_NAME);
 
602
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);
 
603
 
 
604
  renderer = gtk_cell_renderer_text_new ();
 
605
  column = gtk_tree_view_column_new_with_attributes (_("Menu Path"),
 
606
                                                     renderer,
 
607
                                                     "text", LIST_COLUMN_PATH,
 
608
                                                     NULL);
 
609
  gtk_tree_view_column_set_sort_column_id  (column, LIST_COLUMN_PATH);
 
610
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);
 
611
 
 
612
  renderer = gtk_cell_renderer_text_new ();
 
613
  column = gtk_tree_view_column_new_with_attributes (_("Image Types"),
 
614
                                                     renderer,
 
615
                                                     "text",
 
616
                                                     LIST_COLUMN_IMAGE_TYPES,
 
617
                                                     NULL);
 
618
  gtk_tree_view_column_set_sort_column_id  (column, LIST_COLUMN_IMAGE_TYPES);
 
619
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);
 
620
 
 
621
  renderer = gtk_cell_renderer_text_new ();
 
622
 
 
623
  column = gtk_tree_view_column_new_with_attributes (_("Installation Date"),
 
624
                                                     renderer,
 
625
                                                     "text",
 
626
                                                     LIST_COLUMN_DATE_STRING,
 
627
                                                     NULL);
 
628
  gtk_tree_view_column_set_sort_column_id  (column, LIST_COLUMN_DATE);
 
629
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);
 
630
 
 
631
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
 
632
  gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 2);
 
633
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
 
634
                                       GTK_SHADOW_IN);
 
635
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
 
636
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
637
 
 
638
  gtk_widget_set_size_request (list_view, DBL_LIST_WIDTH, DBL_HEIGHT);
 
639
 
 
640
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view));
 
641
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
 
642
 
 
643
  g_signal_connect (selection, "changed",
 
644
                    G_CALLBACK (browser_list_selection_changed),
 
645
                    browser);
 
646
 
 
647
  label = gtk_label_new (_("List View"));
 
648
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_window, label);
 
649
  gtk_container_add (GTK_CONTAINER (scrolled_window), list_view);
 
650
  gtk_widget_show (list_view);
 
651
  gtk_widget_show (scrolled_window);
 
652
 
 
653
  /* notebook->ctree */
 
654
  tree_store = gtk_tree_store_new (N_LIST_COLUMNS,
 
655
                                   G_TYPE_STRING,
 
656
                                   G_TYPE_INT64,
 
657
                                   G_TYPE_STRING,
 
658
                                   G_TYPE_STRING,
 
659
                                   G_TYPE_STRING,
 
660
                                   G_TYPE_POINTER);
 
661
 
 
662
  tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store));
 
663
  g_object_unref (tree_store);
 
664
 
 
665
  browser->tree_view = GTK_TREE_VIEW (tree_view);
 
666
 
 
667
  renderer = gtk_cell_renderer_text_new ();
 
668
  column = gtk_tree_view_column_new_with_attributes (_("Menu Path"),
 
669
                                                     renderer,
 
670
                                                     "text",
 
671
                                                     TREE_COLUMN_PATH_NAME,
 
672
                                                     NULL);
 
673
  gtk_tree_view_column_set_sort_column_id  (column, TREE_COLUMN_PATH_NAME);
 
674
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
 
675
 
 
676
  renderer = gtk_cell_renderer_text_new ();
 
677
  column = gtk_tree_view_column_new_with_attributes (_("Image Types"),
 
678
                                                     renderer,
 
679
                                                     "text",
 
680
                                                     TREE_COLUMN_IMAGE_TYPES,
 
681
                                                     NULL);
 
682
  gtk_tree_view_column_set_sort_column_id  (column, TREE_COLUMN_IMAGE_TYPES);
 
683
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
 
684
 
 
685
  renderer = gtk_cell_renderer_text_new ();
 
686
  column = gtk_tree_view_column_new_with_attributes (_("Installation Date"),
 
687
                                                     renderer,
 
688
                                                     "text",
 
689
                                                     TREE_COLUMN_DATE_STRING,
 
690
                                                     NULL);
 
691
  gtk_tree_view_column_set_sort_column_id  (column, TREE_COLUMN_DATE);
 
692
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
 
693
 
 
694
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
 
695
  gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 2);
 
696
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
 
697
                                       GTK_SHADOW_IN);
 
698
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
 
699
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
700
  gtk_widget_set_size_request (tree_view, DBL_LIST_WIDTH, DBL_HEIGHT);
 
701
 
 
702
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
 
703
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
 
704
 
 
705
  g_signal_connect (selection, "changed",
 
706
                    G_CALLBACK (browser_tree_selection_changed),
 
707
                    browser);
 
708
 
 
709
  label = gtk_label_new (_("Tree View"));
 
710
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_window, label);
 
711
  gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
 
712
 
 
713
  gtk_widget_show (tree_view);
 
714
  gtk_widget_show (scrolled_window);
 
715
  gtk_widget_show (notebook);
 
716
 
 
717
  gtk_widget_set_size_request (GIMP_BROWSER (browser->browser)->right_vbox->parent->parent,
 
718
                               DBL_WIDTH - DBL_LIST_WIDTH, -1);
 
719
 
 
720
  /* now build the list */
 
721
  browser_search (GIMP_BROWSER (browser->browser), "", 0, browser);
 
722
 
 
723
  gtk_widget_show (browser->dialog);
 
724
 
 
725
  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter))
 
726
    gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view)),
 
727
                                    &iter);
 
728
 
 
729
  return browser->dialog;
 
730
}
 
731
 
 
732
static void
 
733
browser_dialog_response (GtkWidget     *widget,
 
734
                         gint           response_id,
 
735
                         PluginBrowser *browser)
 
736
{
 
737
  gtk_widget_destroy (browser->dialog);
 
738
  gtk_main_quit ();
 
739
}
 
740
 
 
741
static void
 
742
browser_list_selection_changed (GtkTreeSelection *selection,
 
743
                                PluginBrowser    *browser)
 
744
{
 
745
  PInfo        *pinfo = NULL;
 
746
  GtkTreeIter   iter;
 
747
  GtkTreeModel *model;
 
748
  gchar        *mpath = NULL;
 
749
 
 
750
  g_return_if_fail (browser != NULL);
 
751
 
 
752
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
753
    {
 
754
      gtk_tree_model_get (model, &iter,
 
755
                          LIST_COLUMN_PINFO, &pinfo,
 
756
                          LIST_COLUMN_PATH,  &mpath,
 
757
                          -1);
 
758
    }
 
759
 
 
760
  if (!pinfo || !mpath)
 
761
    return;
 
762
 
 
763
  model = gtk_tree_view_get_model (browser->tree_view);
 
764
 
 
765
  if (find_existing_mpath (model, mpath, &iter))
 
766
    {
 
767
      GtkTreeSelection *tree_selection;
 
768
      GtkTreePath      *tree_path;
 
769
 
 
770
      tree_path = gtk_tree_model_get_path (model, &iter);
 
771
      gtk_tree_view_expand_to_path (browser->tree_view, tree_path);
 
772
      tree_selection = gtk_tree_view_get_selection (browser->tree_view);
 
773
 
 
774
      g_signal_handlers_block_by_func (tree_selection,
 
775
                                       browser_tree_selection_changed,
 
776
                                       browser);
 
777
      gtk_tree_selection_select_iter (tree_selection, &iter);
 
778
      g_signal_handlers_unblock_by_func (tree_selection,
 
779
                                         browser_tree_selection_changed,
 
780
                                         browser);
 
781
 
 
782
      gtk_tree_view_scroll_to_cell (browser->tree_view,
 
783
                                    tree_path, NULL,
 
784
                                    TRUE, 0.5, 0.0);
 
785
    }
 
786
  else
 
787
    {
 
788
      g_warning ("Failed to find node in tree");
 
789
    }
 
790
 
 
791
  g_free (mpath);
 
792
 
 
793
  browser_show_plugin (browser, pinfo);
 
794
}
 
795
 
 
796
static void
 
797
browser_tree_selection_changed (GtkTreeSelection *selection,
 
798
                                PluginBrowser    *browser)
 
799
{
 
800
  PInfo        *pinfo = NULL;
 
801
  GtkTreeIter   iter;
 
802
  GtkTreeModel *model;
 
803
  gchar        *mpath = NULL;
 
804
  gboolean      valid, found;
 
805
 
 
806
  g_return_if_fail (browser != NULL);
 
807
 
 
808
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
809
    {
 
810
      gtk_tree_model_get (model, &iter,
 
811
                          TREE_COLUMN_PINFO, &pinfo,
 
812
                          TREE_COLUMN_MPATH, &mpath,
 
813
                          -1);
 
814
    }
 
815
 
 
816
  if (!pinfo || !mpath)
 
817
    return;
 
818
 
 
819
  /* Get the first iter in the list */
 
820
  model = gtk_tree_view_get_model (browser->list_view);
 
821
  valid = gtk_tree_model_get_iter_first (model, &iter);
 
822
  found = FALSE;
 
823
 
 
824
  while (valid)
 
825
    {
 
826
      /* Walk through the list, reading each row */
 
827
      gchar *picked_mpath;
 
828
 
 
829
      gtk_tree_model_get (model, &iter,
 
830
                          LIST_COLUMN_PATH, &picked_mpath,
 
831
                          -1);
 
832
      if (picked_mpath && !strcmp (mpath, picked_mpath))
 
833
        {
 
834
          found = TRUE;
 
835
          break;
 
836
        }
 
837
 
 
838
      g_free (picked_mpath);
 
839
      valid = gtk_tree_model_iter_next (model, &iter);
 
840
    }
 
841
 
 
842
  g_free (mpath);
 
843
 
 
844
  if (found)
 
845
    {
 
846
      GtkTreeSelection *list_selection;
 
847
      GtkTreePath      *tree_path;
 
848
 
 
849
      tree_path = gtk_tree_model_get_path (model, &iter);
 
850
      list_selection = gtk_tree_view_get_selection (browser->list_view);
 
851
 
 
852
      g_signal_handlers_block_by_func (list_selection,
 
853
                                       browser_list_selection_changed,
 
854
                                       browser);
 
855
      gtk_tree_selection_select_iter (list_selection, &iter);
 
856
      g_signal_handlers_unblock_by_func (list_selection,
 
857
                                         browser_list_selection_changed,
 
858
                                         browser);
 
859
 
 
860
      gtk_tree_view_scroll_to_cell (browser->list_view,
 
861
                                    tree_path, NULL,
 
862
                                    TRUE, 0.5, 0.0);
 
863
    }
 
864
  else
 
865
    {
 
866
      g_warning ("Failed to find node in list");
 
867
    }
 
868
 
 
869
  browser_show_plugin (browser, pinfo);
 
870
}
 
871
 
 
872
static void
 
873
browser_show_plugin (PluginBrowser *browser,
 
874
                     PInfo         *pinfo)
 
875
{
 
876
  gchar           *blurb         = NULL;
 
877
  gchar           *help          = NULL;
 
878
  gchar           *author        = NULL;
 
879
  gchar           *copyright     = NULL;
 
880
  gchar           *date          = NULL;
 
881
  GimpPDBProcType  type          = 0;
 
882
  gint             n_params      = 0;
 
883
  gint             n_return_vals = 0;
 
884
  GimpParamDef    *params        = NULL;
 
885
  GimpParamDef    *return_vals   = NULL;
 
886
 
 
887
  g_return_if_fail (browser != NULL);
 
888
  g_return_if_fail (pinfo != NULL);
 
889
 
 
890
  gimp_procedural_db_proc_info (pinfo->realname,
 
891
                                &blurb,
 
892
                                &help,
 
893
                                &author,
 
894
                                &copyright,
 
895
                                &date,
 
896
                                &type,
 
897
                                &n_params,
 
898
                                &n_return_vals,
 
899
                                &params,
 
900
                                &return_vals);
 
901
 
 
902
  gimp_browser_set_widget (GIMP_BROWSER (browser->browser),
 
903
                           gimp_proc_view_new (pinfo->realname,
 
904
                                               pinfo->menu,
 
905
                                               blurb,
 
906
                                               help,
 
907
                                               author,
 
908
                                               copyright,
 
909
                                               date,
 
910
                                               type,
 
911
                                               n_params,
 
912
                                               n_return_vals,
 
913
                                               params,
 
914
                                               return_vals));
 
915
 
 
916
  g_free (blurb);
 
917
  g_free (help);
 
918
  g_free (author);
 
919
  g_free (copyright);
 
920
  g_free (date);
 
921
 
 
922
  gimp_destroy_paramdefs (params,      n_params);
 
923
  gimp_destroy_paramdefs (return_vals, n_return_vals);
 
924
}