plugin-browser.c 30.8 KB
Newer Older
1
2
3
4
5
6
7
/*
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This is a plug-in for the GIMP.
 *
 * Copyright (C) 1999 Andy Thomas  alt@picnic.demon.co.uk
 *
8
 * Note some portions of the UI comes from the dbbrowser plugin.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

24
25
#include "config.h"

26
27
28
29
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
30
31
32

#include <gtk/gtk.h>

33
34
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
35

36
37
#include "gimpprocview.h"

38
#include "libgimp/stdplugins-intl.h"
39

40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
enum
{
  LIST_NAME_COLUMN,
  LIST_DATE_COLUMN,
  LIST_PATH_COLUMN,
  LIST_IMAGE_TYPES_COLUMN,
  LIST_PINFO_COLUMN,
  LIST_N_COLUMNS
};

enum
{
  TREE_PATH_NAME_COLUMN,
  TREE_DATE_COLUMN,
  TREE_IMAGE_TYPES_COLUMN,
  TREE_MPATH_COLUMN,
  TREE_PINFO_COLUMN,
  TREE_N_COLUMNS
};

61
#define DBL_LIST_WIDTH  250
62
63
#define DBL_WIDTH       (DBL_LIST_WIDTH + 400)
#define DBL_HEIGHT      250
64

65
typedef struct
66
{
67
68
  GtkWidget   *dialog;

69
70
  GtkTreeView *list_view;
  GtkTreeView *tree_view;
71
72

  GtkWidget   *count_label;
73
74
75
76
  GtkWidget   *search_entry;
  GtkWidget   *descr_scroll;
  GtkWidget   *info_table;
  gint         num_plugins;
77
78
79
80
81
82
83
84
85
86
87
88
} PDesc;

typedef struct
{
  gchar *menu;
  gchar *accel;
  gchar *prog;
  gchar *types;
  gchar *realname;
  gint  instime;
} PInfo;

89
90
91
92

/* Declare some local functions.
 */
static void   query      (void);
93
94
95
96
97
static void   run        (const gchar      *name,
                          gint              nparams,
                          const GimpParam  *param,
                          gint             *nreturn_vals,
                          GimpParam       **return_vals);
98

99

100
static GtkWidget * gimp_plugin_desc           (void);
101

102
103
104
static gboolean    find_existing_mpath        (GtkTreeModel     *model,
                                               gchar            *mpath,
                                               GtkTreeIter      *return_iter);
105

106
static void        list_store_select_callback (GtkTreeSelection *selection,
107
                                               PDesc            *browser);
108
static void        tree_store_select_callback (GtkTreeSelection *selection,
109
110
111
                                               PDesc            *browser);
static void        browser_show_plugin        (PDesc            *browser,
                                               PInfo            *pinfo);
112
113


114
static PDesc *browser = NULL;
115

116
GimpPlugInInfo PLUG_IN_INFO =
117
{
118
119
120
121
  NULL,  /* init_proc  */
  NULL,  /* quit_proc  */
  query, /* query_proc */
  run,   /* run_proc   */
122
123
124
125
126
};


MAIN ()

127

128
static void
129
query (void)
130
{
131
  static GimpParamDef args[] =
132
  {
133
    { GIMP_PDB_INT32, "run_mode", "Interactive, [non-interactive]" }
134
  };
135

136
  gimp_install_procedure ("plug_in_plug_in_details",
Marc Lehmann's avatar
Marc Lehmann committed
137
                          "Displays plugin details",
138
                          "Helps browse the plugin menus system. You can "
139
140
141
142
143
                          "search for plugin names, sort by name or menu "
                          "location and you can view a tree representation "
                          "of the plugin menus. Can also be of help to find "
                          "where new plugins have installed themselves in "
                          "the menuing system",
144
145
146
                          "Andy Thomas",
                          "Andy Thomas",
                          "1999",
147
                          N_("_Plugin Browser"),
148
                          "",
149
                          GIMP_PLUGIN,
150
                          G_N_ELEMENTS (args), 0,
151
                          args, NULL);
152
153
154

  gimp_plugin_menu_register ("plug_in_plug_in_details",
                             N_("<Toolbox>/Xtns/Extensions"));
155
  gimp_plugin_icon_register ("plug_in_plug_in_details",
156
                             GIMP_ICON_TYPE_STOCK_ID, GIMP_STOCK_PLUGIN);
157
158
159
}

static void
160
161
162
163
164
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
165
{
166
  static GimpParam  values[2];
167
  GimpRunMode       run_mode;
168
169
170
171

  run_mode = param[0].data.d_int32;

  *nreturn_vals = 1;
172
  *return_vals  = values;
173

174
175
  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
176

177
  INIT_I18N ();
178

179
  if (strcmp (name, "plug_in_plug_in_details") == 0)
180
    {
181
182
      GtkWidget *plugin_dialog;

183
184
      *nreturn_vals = 1;

185
      values[0].data.d_status = GIMP_PDB_SUCCESS;
186

187
188
      plugin_dialog = gimp_plugin_desc ();

189
190
191
192
193
      gtk_main ();
    }
}

static void
194
195
browser_show_plugin (PDesc *browser,
                     PInfo *pinfo)
196
{
197
  gchar           *selected_proc_blurb;
198
  gchar           *selected_proc_help;
199
200
201
  gchar           *selected_proc_author;
  gchar           *selected_proc_copyright;
  gchar           *selected_proc_date;
202
  GimpPDBProcType  selected_proc_type;
203
204
205
206
  gint             selected_nparams;
  gint             selected_nreturn_vals;
  GimpParamDef    *selected_params;
  GimpParamDef    *selected_return_vals;
207
  GtkWidget       *old_table;
208
209

  g_return_if_fail (browser != NULL);
210
  g_return_if_fail (pinfo != NULL);
211

212
  if (browser->descr_scroll == NULL)
213
    return;
214

215
216
217
  selected_proc_blurb     = NULL;
  selected_proc_help      = NULL;
  selected_proc_author    = NULL;
218
  selected_proc_copyright = NULL;
219
220
221
222
223
224
  selected_proc_date      = NULL;
  selected_proc_type      = 0;
  selected_nparams        = 0;
  selected_nreturn_vals   = 0;
  selected_params         = NULL;
  selected_return_vals    = NULL;
225

226
  gimp_procedural_db_proc_info (pinfo->realname,
227
228
229
230
231
232
233
234
                                &selected_proc_blurb,
                                &selected_proc_help,
                                &selected_proc_author,
                                &selected_proc_copyright,
                                &selected_proc_date,
                                &selected_proc_type,
                                &selected_nparams, &selected_nreturn_vals,
                                &selected_params,  &selected_return_vals);
235

236
  old_table = browser->info_table;
237

238
239
240
241
242
243
244
245
246
247
248
249
  browser->info_table = gimp_proc_view_new (pinfo->realname,
                                            pinfo->menu,
                                            selected_proc_blurb,
                                            selected_proc_help,
                                            selected_proc_author,
                                            selected_proc_copyright,
                                            selected_proc_date,
                                            selected_proc_type,
                                            selected_nparams,
                                            selected_nreturn_vals,
                                            selected_params,
                                            selected_return_vals);
250

251
  gtk_container_set_border_width (GTK_CONTAINER (browser->info_table), 12);
252

253
254
  if (old_table)
    gtk_widget_destroy (old_table);
255

256
257
258
259
260
261
262
263
264
265
266
267
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (browser->descr_scroll),
                                         browser->info_table);

  gtk_widget_show (browser->info_table);

  g_free (selected_proc_blurb);
  g_free (selected_proc_help);
  g_free (selected_proc_author);
  g_free (selected_proc_copyright);
  g_free (selected_proc_date);
  g_free (selected_params);
  g_free (selected_return_vals);
268
269
}

270
static void
271
list_store_select_callback (GtkTreeSelection *selection,
272
                            PDesc            *browser)
273
{
274
275
276
277
  PInfo        *pinfo = NULL;
  GtkTreeIter   iter;
  GtkTreeModel *model;
  gchar        *mpath = NULL;
278

279
  g_return_if_fail (browser != NULL);
280

281
282
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
    {
283
      gtk_tree_model_get (model, &iter,
284
285
286
287
                          LIST_PINFO_COLUMN, &pinfo,
                          LIST_PATH_COLUMN,  &mpath,
                          -1);
    }
288

289
  if (!pinfo || !mpath)
290
    return;
291

292
293
  model = gtk_tree_view_get_model (browser->tree_view);

294
  if (find_existing_mpath (model, mpath, &iter))
295
    {
296
      GtkTreeSelection *tree_selection;
297
      GtkTreePath      *tree_path;
298
299

      tree_path = gtk_tree_model_get_path (model, &iter);
300
301
      gtk_tree_view_expand_to_path (browser->tree_view, tree_path);
      tree_selection = gtk_tree_view_get_selection (browser->tree_view);
302
303
      g_signal_handlers_block_by_func (tree_selection,
                                       G_CALLBACK (tree_store_select_callback),
304
                                       browser);
305
306
307
      gtk_tree_selection_select_iter (tree_selection, &iter);
      g_signal_handlers_unblock_by_func (tree_selection,
                                         G_CALLBACK (tree_store_select_callback),
308
309
                                         browser);
      gtk_tree_view_scroll_to_cell (browser->tree_view,
310
311
                                    tree_path, NULL,
                                    TRUE, 0.5, 0.0);
312
313
314
    }
  else
    {
315
      g_warning ("Failed to find node in tree");
316
    }
317

318
  g_free (mpath);
319
320

  browser_show_plugin (browser, pinfo);
321
322
}

323
static void
324
tree_store_select_callback (GtkTreeSelection *selection,
325
                            PDesc            *browser)
326
{
327
328
329
330
331
332
  PInfo        *pinfo = NULL;
  GtkTreeIter   iter;
  GtkTreeModel *model;
  gchar        *mpath = NULL;
  gboolean      valid, found;

333
  g_return_if_fail (browser != NULL);
334
335

  if (gtk_tree_selection_get_selected (selection, &model, &iter))
336
    {
337
      gtk_tree_model_get (model, &iter,
338
                          TREE_PINFO_COLUMN, &pinfo,
Manish Singh's avatar
Manish Singh committed
339
                          TREE_MPATH_COLUMN, &mpath,
340
                          -1);
341
    }
342

343
  if (!pinfo || !mpath)
344
    return;
345

346
  /* Get the first iter in the list */
347
  model = gtk_tree_view_get_model (browser->list_view);
348
349
  valid = gtk_tree_model_get_iter_first (model, &iter);
  found = FALSE;
350

351
352
353
354
  while (valid)
    {
      /* Walk through the list, reading each row */
      gchar *picked_mpath;
355

356
      gtk_tree_model_get (model, &iter,
357
358
359
                          LIST_PATH_COLUMN, &picked_mpath,
                          -1);
      if (picked_mpath && !strcmp (mpath, picked_mpath))
360
361
362
363
        {
          found = TRUE;
          break;
        }
364
365
366
367
      g_free (picked_mpath);
      valid = gtk_tree_model_iter_next (model, &iter);
    }
  g_free (mpath);
368

369
370
371
372
373
374
  if (found)
    {
      GtkTreeSelection *list_selection;
      GtkTreePath      *tree_path;

      tree_path = gtk_tree_model_get_path (model, &iter);
375
      list_selection = gtk_tree_view_get_selection (browser->list_view);
376
377
      g_signal_handlers_block_by_func (list_selection,
                                       G_CALLBACK (list_store_select_callback),
378
                                       browser);
379
380
381
      gtk_tree_selection_select_iter (list_selection, &iter);
      g_signal_handlers_unblock_by_func (list_selection,
                                         G_CALLBACK (list_store_select_callback),
382
383
                                         browser);
      gtk_tree_view_scroll_to_cell (browser->list_view,
384
385
386
387
388
389
390
                                    tree_path, NULL,
                                    TRUE, 0.5, 0.0);
    }
  else
    {
      g_warning ("Failed to find node in list");
    }
391

392
  browser_show_plugin (browser, pinfo);
393
394
}

395
#if 0
396
static void
397
pinfo_free (gpointer p)
398
{
399
  PInfo *pinfo = p;
400

401
402
403
404
405
406
  g_free (pinfo->menu);
  g_free (pinfo->accel);
  g_free (pinfo->prog);
  g_free (pinfo->types);
  g_free (pinfo->realname);
  g_free (pinfo);
407
}
408
#endif
409

410
411
412
413
414
415
static gboolean
find_existing_mpath_helper (GtkTreeModel *model,
                            GtkTreeIter  *iter,
                            GtkTreePath  *path,
                            gchar        *mpath,
                            GtkTreeIter  *return_iter)
416
{
417
418
419
420
  do
    {
      GtkTreeIter  child;
      gchar       *picked_mpath;
421

422
      gtk_tree_model_get (model, iter,
423
424
                          TREE_MPATH_COLUMN, &picked_mpath,
                          -1);
425
426
427
428
429
430
431

      if (! strcmp (mpath, picked_mpath))
        {
          *return_iter = *iter;
          g_free (picked_mpath);
          return TRUE;
        }
432
433
434
435

      if (gtk_tree_model_iter_children (model, &child, iter))
        {
          gtk_tree_path_down (path);
436

437
          if (find_existing_mpath_helper (model, &child, path,
438
439
440
441
442
443
                                          mpath, return_iter))
            {
              g_free (picked_mpath);
              return TRUE;
            }

444
445
          gtk_tree_path_up (path);
        }
446

447
448
449
450
      gtk_tree_path_next (path);
      g_free (picked_mpath);
    }
  while (gtk_tree_model_iter_next (model, iter));
451

452
453
454
455
456
457
458
459
460
461
462
463
  return FALSE;
}

static gboolean
find_existing_mpath (GtkTreeModel *model,
                     gchar        *mpath,
                     GtkTreeIter  *return_iter)
{
  GtkTreePath *path;
  GtkTreeIter  parent;

  path = gtk_tree_path_new_first ();
464

465
  if (gtk_tree_model_get_iter (model, &parent, path) == FALSE)
466
    {
467
468
      gtk_tree_path_free (path);
      return FALSE;
469
470
    }

471
472
473
474
475
476
477
  return find_existing_mpath_helper (model, &parent, path,
                                     mpath, return_iter);
  gtk_tree_path_free (path);
}


static void
478
get_parent (PDesc       *browser,
479
480
481
482
483
484
485
486
487
488
489
490
            gchar       *mpath,
            GtkTreeIter *parent)
{
  GtkTreeIter   last_parent;
  gchar        *tmp_ptr;
  gchar        *str_ptr;
  gchar        *leaf_ptr;
  GtkTreeStore *tree_store;

  if (mpath == NULL)
    return;

491
  tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view));
492
493
494
495
496

  /* Lookup for existing mpath */
  if (find_existing_mpath (GTK_TREE_MODEL (tree_store), mpath, parent))
    return;

497
  /* Next one up */
498
  tmp_ptr = g_strdup (mpath);
499

500
  str_ptr = strrchr (tmp_ptr,'/');
501

502
  if (str_ptr == NULL)
503
504
    {
      leaf_ptr = mpath;
505
506
507
508
509
      gtk_tree_store_append (tree_store, parent, NULL);
      gtk_tree_store_set (tree_store, parent,
                          TREE_MPATH_COLUMN, mpath,
                          TREE_PATH_NAME_COLUMN, mpath,
                          -1);
510
511
512
513
    }
  else
    {
      leaf_ptr = g_strdup(str_ptr+1);
514

515
      *str_ptr = '\000';
516

517
      get_parent (browser, tmp_ptr, &last_parent);
518
519
520
521
522
      gtk_tree_store_append (tree_store, parent, &last_parent);
      gtk_tree_store_set (tree_store, parent,
                          TREE_MPATH_COLUMN, mpath,
                          TREE_PATH_NAME_COLUMN, leaf_ptr,
                          -1);
523
524
525
526
    }
}

static void
527
insert_into_tree_view (PDesc *browser,
528
529
530
531
532
                       gchar *name,
                       gchar *xtimestr,
                       gchar *menu_str,
                       gchar *types_str,
                       PInfo *pinfo)
533
{
534
535
536
537
538
  gchar        *labels[3];
  gchar        *str_ptr;
  gchar        *tmp_ptr;
  gchar        *leaf_ptr;
  GtkTreeIter   parent, iter;
539
  GtkTreeStore *tree_store;
540
541
542
543

  /* Find all nodes */
  /* Last one is the leaf part */

544
545
546
547
548
  tmp_ptr = g_strdup (menu_str);

  str_ptr = strrchr (tmp_ptr, '/');

  if (str_ptr == NULL)
549
550
    return; /* No node */

551
  leaf_ptr = g_strdup (str_ptr + 1);
552
553
554
555
556

  *str_ptr = '\000';

  /*   printf("inserting %s...\n",menu_str); */

557
  get_parent (browser, tmp_ptr, &parent);
558
559
560

  /* Last was a leaf */
  /*   printf("found leaf %s parent = %p\n",leaf_ptr,parent); */
561
562
563
564
  labels[0] = g_strdup (name);
  labels[1] = g_strdup (xtimestr);
  labels[2] = g_strdup (types_str);

565
  tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view));
566
567
568
569
570
571
572
573
  gtk_tree_store_append (tree_store, &iter, &parent);
  gtk_tree_store_set (tree_store, &iter,
                      TREE_MPATH_COLUMN, menu_str,
                      TREE_PATH_NAME_COLUMN, name,
                      TREE_PINFO_COLUMN, pinfo,
                      TREE_IMAGE_TYPES_COLUMN, types_str,
                      TREE_DATE_COLUMN, xtimestr,
                      -1);
574
575
576
}

static void
577
get_plugin_info (PDesc       *browser,
578
                 const gchar *search_text)
579
{
580
581
582
583
584
585
586
587
588
589
590
  GimpParam    *return_vals;
  gint          nreturn_vals;
  gchar       **menu_strs;
  gchar       **accel_strs;
  gchar       **prog_strs;
  gchar       **types_strs;
  gchar       **realname_strs;
  gint         *time_ints;
  GtkListStore *list_store;
  GtkTreeStore *tree_store;
  GtkTreeIter   iter;
591

592
  if (!search_text)
593
594
595
596
    search_text = "";

  return_vals = gimp_run_procedure ("gimp_plugins_query",
                                    &nreturn_vals,
597
                                    GIMP_PDB_STRING, search_text,
Sven Neumann's avatar
Sven Neumann committed
598
                                    GIMP_PDB_END);
599

Sven Neumann's avatar
Sven Neumann committed
600
  if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
601
    {
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
      gchar *str;
      gint   loop;

      browser->num_plugins = return_vals[1].data.d_int32;
      menu_strs            = return_vals[2].data.d_stringarray;
      accel_strs           = return_vals[4].data.d_stringarray;
      prog_strs            = return_vals[6].data.d_stringarray;
      types_strs           = return_vals[8].data.d_stringarray;
      time_ints            = return_vals[10].data.d_int32array;
      realname_strs        = return_vals[12].data.d_stringarray;

      str = g_strdup_printf (_("%d Plugin Interfaces"), browser->num_plugins);
      gtk_label_set_text (GTK_LABEL (browser->count_label), str);
      g_free (str);

      list_store = GTK_LIST_STORE (gtk_tree_view_get_model (browser->list_view));
618
619
      gtk_list_store_clear (list_store);

620
      tree_store = GTK_TREE_STORE (gtk_tree_view_get_model (browser->tree_view));
621
622
      gtk_tree_store_clear (tree_store);

623
      for (loop = 0; loop < return_vals[1].data.d_int32; loop++)
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
        {
          PInfo     *pinfo;
          gchar     *name;
          gchar      xtimestr[50];
          struct tm *x;
          time_t     tx;
          int        ret;

          name = strrchr (menu_strs[loop], '/');

          if (name)
            name = name + 1;
          else
            name = menu_strs[loop];

          pinfo = g_new0 (PInfo, 1);

          tx = time_ints[loop];
          if (tx)
            {
644
              const gchar *format = "%c";  /* gcc workaround to avoid warning */
645
              gchar       *utf8;
646

647
              x = localtime (&tx);
648
              ret = strftime (xtimestr, sizeof (xtimestr), format, x);
649
              xtimestr[ret] = 0;
650
651
652
653
654
655
656

              if ((utf8 = g_locale_to_utf8 (xtimestr, -1, NULL, NULL, NULL)))
                {
                  strncpy (xtimestr, utf8, sizeof (xtimestr));
                  xtimestr[sizeof (xtimestr) - 1] = 0;
                  g_free (utf8);
                }
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
            }
          else
            strcpy (xtimestr,"");

          pinfo->menu     = g_strdup (menu_strs[loop]);
          pinfo->accel    = g_strdup (accel_strs[loop]);
          pinfo->prog     = g_strdup (prog_strs[loop]);
          pinfo->types    = g_strdup (types_strs[loop]);
          pinfo->instime  = time_ints[loop];
          pinfo->realname = g_strdup (realname_strs[loop]);

          gtk_list_store_append (list_store, &iter);
          gtk_list_store_set (list_store, &iter,
                              LIST_NAME_COLUMN,        name,
                              LIST_DATE_COLUMN,        xtimestr,
                              LIST_PATH_COLUMN,        menu_strs[loop],
                              LIST_IMAGE_TYPES_COLUMN, types_strs[loop],
                              LIST_PINFO_COLUMN,       pinfo,
                              -1);

          /* Now do the tree view.... */
678
          insert_into_tree_view (browser,
679
680
681
682
683
684
685
686
687
                                 name,
                                 xtimestr,
                                 menu_strs[loop],
                                 types_strs[loop],
                                 pinfo);
        }
      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store),
                                            LIST_NAME_COLUMN,
                                            GTK_SORT_ASCENDING);
688
689
690
691
692
    }

  gimp_destroy_params (return_vals, nreturn_vals);
}

693
#if 0
694
static gint
695
date_sort (GtkCList      *clist,
696
697
           gconstpointer  ptr1,
           gconstpointer  ptr2)
698
699
700
701
702
{
  GtkCListRow *row1 = (GtkCListRow *) ptr1;
  GtkCListRow *row2 = (GtkCListRow *) ptr2;

  /* Get the data for the row */
703
704
  PInfo *row1_pinfo = row1->data;
  PInfo *row2_pinfo = row2->data;
705
706
707

  /* Want to sort on the date field */

708
  if (row2_pinfo->instime < row1_pinfo->instime)
709
    {
710
      return -1;
711
    }
712
713

  if (row2_pinfo->instime > row1_pinfo->instime)
714
    {
715
      return 1;
716
    }
717
  return 0;
718
}
719
#endif
720

721
#if 0
722
723
static void
clist_click_column (GtkCList *clist,
724
725
                    gint      column,
                    gpointer  data)
726
727
728
{
  if (column == 1)
    {
729
      gtk_clist_set_compare_func (clist, date_sort);
730
731
732
    }
  else
    {
733
      gtk_clist_set_compare_func (clist, NULL); /* Set back to default */
734
735
736
737
738
    }

  if (column == clist->sort_column)
    {
      if (clist->sort_type == GTK_SORT_ASCENDING)
739
        clist->sort_type = GTK_SORT_DESCENDING;
740
      else
741
        clist->sort_type = GTK_SORT_ASCENDING;
742
743
744
    }
  else
    gtk_clist_set_sort_column (clist, column);
745

746
747
  gtk_clist_sort (clist);
}
748
#endif
749

750
751
752
static void
dialog_response (GtkWidget *widget,
                 gint       response_id,
753
                 PDesc     *browser)
754
{
755
  const gchar *search_text = NULL;
756

757
758
759
  switch (response_id)
    {
    case GTK_RESPONSE_OK:
760
761
762
763
      if (widget != NULL)
        {
          /* The result of a button press... read entry data */
          search_text =
764
            gtk_entry_get_text (GTK_ENTRY (browser->search_entry));
765
        }
766

767
      get_plugin_info (browser, search_text);
768
769
770
      break;

    default:
771
      gtk_widget_destroy (browser->dialog);
772
773
774
775
      gtk_main_quit ();
      break;
    }
}
776
777

static GtkWidget *
778
gimp_plugin_desc (void)
779
{
780
781
  GtkWidget         *paned;
  GtkWidget         *hbox, *vbox;
782
783
784
785
786
787
788
789
790
  GtkWidget         *label, *notebook, *swindow;
  GtkListStore      *list_store;
  GtkTreeStore      *tree_store;
  GtkWidget         *list_view;
  GtkWidget         *tree_view;
  GtkTreeViewColumn *column;
  GtkCellRenderer   *renderer;
  GtkTreeSelection  *selection;
  GtkTreeIter        iter;
791

792
  gimp_ui_init ("plugindetails", FALSE);
793

794
  browser = g_new0 (PDesc, 1);
795
796

  /* the dialog box */
797
798
  browser->dialog =
    gimp_dialog_new (_("Plugin Browser"), "plugindetails",
799
                     NULL, 0,
800
                     gimp_standard_help_func, "plug-in-plug-in-details",
801

802
803
                     _("Search by _Name"), GTK_RESPONSE_OK,
                     GTK_STOCK_CLOSE,      GTK_RESPONSE_CLOSE,
804

805
                     NULL);
806

807
  g_signal_connect (browser->dialog, "response",
808
                    G_CALLBACK (dialog_response),
809
                    browser);
810

811
  /* paned : left=notebook ; right=description */
812

813
814
815
816
817
  paned = gtk_hpaned_new ();
  gtk_container_set_border_width (GTK_CONTAINER (paned), 12);
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (browser->dialog)->vbox),
                     paned);
  gtk_widget_show (paned);
818

819
  /* left = vbox : the list and the search entry */
820

821
  vbox = gtk_vbox_new (FALSE, 6);
822
  gtk_paned_pack1 (GTK_PANED (paned), vbox, FALSE, TRUE);
823
  gtk_widget_show (vbox);
824

825
826
827
828
829
  browser->count_label = gtk_label_new ("0 Plugin Interfaces");
  gtk_misc_set_alignment (GTK_MISC (browser->count_label), 0.0, 0.5);
  gtk_box_pack_start (GTK_BOX (vbox), browser->count_label, FALSE, FALSE, 0);
  gtk_widget_show (browser->count_label);

830
831
  /* left = notebook */

832
  notebook = gtk_notebook_new ();
833
834
835
  gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);

  /* list : list in a scrolled_win */
836
837
838
839
840
841
842
843
844
845
  list_store = gtk_list_store_new (LIST_N_COLUMNS,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_POINTER);

  list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
  g_object_unref (list_store);

846
  browser->list_view = GTK_TREE_VIEW (list_view);
847
848

  renderer = gtk_cell_renderer_text_new ();
849
850
851
852
853
  column = gtk_tree_view_column_new_with_attributes (_("Name"),
                                                     renderer,
                                                     "text",
                                                     LIST_NAME_COLUMN,
                                                     NULL);
854
855
856
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);

  renderer = gtk_cell_renderer_text_new ();
857
  column = gtk_tree_view_column_new_with_attributes (_("Insertion Date"),
858
859
860
861
                                                     renderer,
                                                     "text",
                                                     LIST_DATE_COLUMN,
                                                     NULL);
862
863
864
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);

  renderer = gtk_cell_renderer_text_new ();
865
  column = gtk_tree_view_column_new_with_attributes (_("Menu Path"),
866
867
868
869
                                                     renderer,
                                                     "text",
                                                     LIST_PATH_COLUMN,
                                                     NULL);
870
871
872
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);

  renderer = gtk_cell_renderer_text_new ();
873
  column = gtk_tree_view_column_new_with_attributes (_("Image Types"),
874
875
876
877
                                                     renderer,
                                                     "text",
                                                     LIST_IMAGE_TYPES_COLUMN,
                                                     NULL);
878
879
  gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), column);

880
  swindow = gtk_scrolled_window_new (NULL, NULL);
881
882
883
  gtk_container_set_border_width (GTK_CONTAINER (swindow), 2);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
                                       GTK_SHADOW_IN);
884
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
885
886
887
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

  gtk_widget_set_size_request (list_view, DBL_LIST_WIDTH, DBL_HEIGHT);
888

889
890
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view));
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
891

892
  g_signal_connect (selection, "changed",
893
                    G_CALLBACK (list_store_select_callback),
894
                    browser);
895

896
  label = gtk_label_new (_("List View"));
897
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), swindow, label);
898
899
  gtk_container_add (GTK_CONTAINER (swindow), list_view);
  gtk_widget_show (list_view);
900
  gtk_widget_show (swindow);
901
902

  /* notebook->ctree */
903
904
905
906
907
908
909
910
911
912
  tree_store = gtk_tree_store_new (LIST_N_COLUMNS,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_POINTER);

  tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (tree_store));
  g_object_unref (tree_store);

913
  browser->tree_view = GTK_TREE_VIEW (tree_view);
914
915

  renderer = gtk_cell_renderer_text_new ();
916
  column = gtk_tree_view_column_new_with_attributes (_("Menu Path/Name"),
917
918
919
920
921
922
923
                                                     renderer,
                                                     "text",
                                                     TREE_PATH_NAME_COLUMN,
                                                     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);

  renderer = gtk_cell_renderer_text_new ();
924
  column = gtk_tree_view_column_new_with_attributes (_("Insertion Date"),
925
926
927
928
929
930
931
                                                     renderer,
                                                     "text",
                                                     TREE_DATE_COLUMN,
                                                     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);

  renderer = gtk_cell_renderer_text_new ();
932
  column = gtk_tree_view_column_new_with_attributes (_("Image Types"),
933
934
935
936
937
938
939
                                                     renderer,
                                                     "text",
                                                     TREE_IMAGE_TYPES_COLUMN,
                                                     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);

  swindow = gtk_scrolled_window_new (NULL, NULL);
940
941
942
  gtk_container_set_border_width (GTK_CONTAINER (swindow), 2);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
                                       GTK_SHADOW_IN);
943
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
944
945
946
947
948
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_widget_set_size_request (tree_view, DBL_LIST_WIDTH, DBL_HEIGHT);

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
949

950
  g_signal_connect (selection, "changed",
951
                    G_CALLBACK (tree_store_select_callback),
952
                    browser);
953

954
  label = gtk_label_new (_("Tree view"));
955
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), swindow, label);
956
  gtk_container_add (GTK_CONTAINER (swindow), tree_view);
957

958
  gtk_widget_show (tree_view);
959
960
  gtk_widget_show (swindow);
  gtk_widget_show (notebook);
961
962
963

  /* search entry & details button */

964
965
966
967
968
969
970
971
972
973
974
975
976
977
  hbox = gtk_hbox_new (FALSE, 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new_with_mnemonic (_("_Search:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  browser->search_entry = gtk_entry_new ();
  gtk_entry_set_activates_default (GTK_ENTRY (browser->search_entry), TRUE);
  gtk_box_pack_start (GTK_BOX (hbox), browser->search_entry, TRUE, TRUE, 0);
  gtk_widget_show (browser->search_entry);

  gtk_label_set_mnemonic_widget (GTK_LABEL (label), browser->search_entry);
978
979

  /* right = description */
980
981
982
983
984
985
986
987
988

  browser->descr_scroll = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_set_size_request (browser->descr_scroll,
                               DBL_WIDTH - DBL_LIST_WIDTH, -1);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (browser->descr_scroll),
                                  GTK_POLICY_AUTOMATIC,
                                  GTK_POLICY_ALWAYS);
  gtk_paned_pack2 (GTK_PANED (paned), browser->descr_scroll, TRUE, TRUE);
  gtk_widget_show (browser->descr_scroll);
989

990
  /* now build the list */
991
  dialog_response (NULL, GTK_RESPONSE_OK, browser);
992

993
  gtk_widget_show (browser->dialog);
994

995
  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter))
996
997
    gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (list_view)),
                                    &iter);
998

999
  gtk_widget_grab_focus (browser->search_entry);
1000

1001
  return browser->dialog;
1002
}