glade-catalog.c 23.7 KB
Newer Older
Jose Maria Celorio's avatar
Jose Maria Celorio committed
1 2
/*
 * Copyright (C) 2001 Ximian, Inc.
3
 * Copyright (C) 2004 Imendio AB
Jose Maria Celorio's avatar
Jose Maria Celorio committed
4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * 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
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Jose Maria Celorio's avatar
Jose Maria Celorio committed
18 19 20 21 22
 *
 * Authors:
 *   Chema Celorio <chema@celorio.com>
 */

23
#include <config.h>
Jose Maria Celorio's avatar
Jose Maria Celorio committed
24 25 26

#include "glade.h"
#include "glade-catalog.h"
27
#include "glade-widget-adaptor.h"
28 29
#include "glade-private.h"
#include "glade-tsort.h"
Jose Maria Celorio's avatar
Jose Maria Celorio committed
30

31 32 33 34 35 36
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <glib.h>
#include <glib/gi18n-lib.h>

37
struct _GladeCatalog
Joaquín Cuenca Abela's avatar
Joaquín Cuenca Abela committed
38
{
39 40
  guint16 major_version;        /* The catalog version               */
  guint16 minor_version;
41

42
  GList *targetable_versions;   /* list of suitable version targets */
43

44
  gchar *library;               /* Library name for backend support  */
Jose Maria Celorio's avatar
Jose Maria Celorio committed
45

46
  gchar *name;                  /* Symbolic catalog name             */
47

48 49
  gchar *dep_catalog;           /* Symbolic name of the catalog that
                                 * this catalog depends on           */
50

51 52 53 54
  gchar *domain;                /* The domain to be used to translate
                                 * strings from this catalog (otherwise this 
                                 * defaults to the library name)
                                 */
55

56
  gchar *book;                  /* Devhelp search domain */
Vincent Geddes's avatar
Vincent Geddes committed
57

58
  gchar *icon_prefix;           /* the prefix for icons */
59

60 61 62 63 64 65 66 67 68 69
  GList *widget_groups;         /* List of widget groups (palette)   */
  GList *adaptors;              /* List of widget class adaptors (all)  */

  GladeXmlContext *context;     /* Xml context is stored after open
                                 * before classes are loaded         */

  GModule *module;

  gchar *init_function_name;    /* Catalog's init function name */
  GladeCatalogInitFunc init_function;
70 71
};

72 73
struct _GladeWidgetGroup
{
74 75
  gchar *name;                  /* Group name */
  gchar *title;                 /* Group name in the palette */
76

77
  gboolean expanded;            /* Whether group is expanded in the palette */
78

79
  GList *adaptors;              /* List of class adaptors in the palette    */
80 81
};

82
/* List of catalogs successfully loaded. */
83
static GList *loaded_catalogs = NULL;
84

85 86 87
/* Extra paths to load catalogs from */
static GList *catalog_paths = NULL;

88
static gboolean
89
catalog_get_function (GladeCatalog *catalog,
90 91
                      const gchar  *symbol_name,
                      gpointer     *symbol_ptr)
92
{
93 94
  if (catalog->module == NULL)
    catalog->module = glade_util_load_library (catalog->library);
95

96 97 98 99
  if (catalog->module)
    return g_module_symbol (catalog->module, symbol_name, symbol_ptr);

  return FALSE;
100 101
}

102 103 104
static GladeCatalog *
catalog_allocate (void)
{
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
  GladeCatalog *catalog;

  catalog = g_slice_new0 (GladeCatalog);

  catalog->library = NULL;
  catalog->name = NULL;
  catalog->dep_catalog = NULL;
  catalog->domain = NULL;
  catalog->book = NULL;
  catalog->icon_prefix = NULL;
  catalog->init_function_name = NULL;
  catalog->module = NULL;

  catalog->context = NULL;
  catalog->adaptors = NULL;
  catalog->widget_groups = NULL;

  return catalog;
123 124
}

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
static void
widget_group_destroy (GladeWidgetGroup *group)
{
  g_return_if_fail (GLADE_IS_WIDGET_GROUP (group));

  g_free (group->name);
  g_free (group->title);
  g_list_free (group->adaptors);

  g_slice_free (GladeWidgetGroup, group);
}

static void
catalog_destroy (GladeCatalog *catalog)
{
  g_return_if_fail (GLADE_IS_CATALOG (catalog));

  g_free (catalog->name);
  g_free (catalog->library);
  g_free (catalog->dep_catalog);
  g_free (catalog->domain);
  g_free (catalog->book);
  g_free (catalog->icon_prefix);
  g_free (catalog->init_function_name);

  if (catalog->adaptors)
    {
      g_list_free (catalog->adaptors);
    }

  if (catalog->widget_groups)
    {
      g_list_foreach (catalog->widget_groups, (GFunc) widget_group_destroy,
                      NULL);
      g_list_free (catalog->widget_groups);
    }

  if (catalog->context)
    glade_xml_context_free (catalog->context);

  g_slice_free (GladeCatalog, catalog);
}

168
static GladeCatalog *
169
catalog_open (const gchar *filename)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
170
{
171 172 173 174 175
  GladeTargetableVersion *version;
  GladeCatalog *catalog;
  GladeXmlContext *context;
  GladeXmlDoc *doc;
  GladeXmlNode *root;
176
  gchar *name;
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

  /* get the context & root node of the catalog file */
  context = glade_xml_context_new_from_path (filename,
                                             NULL, GLADE_TAG_GLADE_CATALOG);
  if (!context)
    {
      g_warning ("Couldn't open catalog [%s].", filename);
      return NULL;
    }

  doc = glade_xml_context_get_doc (context);
  root = glade_xml_doc_get_root (doc);

  if (!glade_xml_node_verify (root, GLADE_TAG_GLADE_CATALOG))
    {
      g_warning ("Catalog root node is not '%s', skipping %s",
                 GLADE_TAG_GLADE_CATALOG, filename);
      glade_xml_context_free (context);
      return NULL;
    }

198 199 200
  if (!(name = glade_xml_get_property_string_required (root, GLADE_TAG_NAME, NULL)))
    return NULL;

201 202
  catalog = catalog_allocate ();
  catalog->context = context;
203
  catalog->name = name;
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

  glade_xml_get_property_version (root, GLADE_TAG_VERSION,
                                  &catalog->major_version,
                                  &catalog->minor_version);

  /* Make one default suitable target */
  version = g_new (GladeTargetableVersion, 1);
  version->major = catalog->major_version;
  version->minor = catalog->minor_version;

  catalog->targetable_versions =
      glade_xml_get_property_targetable_versions (root, GLADE_TAG_TARGETABLE);

  catalog->targetable_versions =
      g_list_prepend (catalog->targetable_versions, version);

  catalog->library = glade_xml_get_property_string (root, GLADE_TAG_LIBRARY);
  catalog->dep_catalog =
      glade_xml_get_property_string (root, GLADE_TAG_DEPENDS);
  catalog->domain = glade_xml_get_property_string (root, GLADE_TAG_DOMAIN);
  catalog->book = glade_xml_get_property_string (root, GLADE_TAG_BOOK);
  catalog->icon_prefix =
      glade_xml_get_property_string (root, GLADE_TAG_ICON_PREFIX);
  catalog->init_function_name =
      glade_xml_get_value_string (root, GLADE_TAG_INIT_FUNCTION);

  if (!catalog->domain)
    catalog->domain = g_strdup (catalog->library);

  /* catalog->icon_prefix defaults to catalog->name */
  if (!catalog->icon_prefix)
    catalog->icon_prefix = g_strdup (catalog->name);

  if (catalog->init_function_name)
238 239 240 241 242 243 244
    {
      if (!catalog_get_function (catalog, catalog->init_function_name,
                                 (gpointer) & catalog->init_function))
        g_warning ("Failed to find and execute catalog '%s' init function '%s'",
                   glade_catalog_get_name (catalog),
                   catalog->init_function_name);
    }
245 246

  return catalog;
247
}
Jose Maria Celorio's avatar
Jose Maria Celorio committed
248

249 250 251
static GHashTable *modules = NULL;

static GModule *
252
catalog_load_library (GladeCatalog *catalog)
253
{
254 255 256 257 258 259
  GModule *module;

  if (modules == NULL)
    modules = g_hash_table_new_full (g_str_hash,
                                     g_str_equal,
                                     (GDestroyNotify) g_free,
260
                                     (GDestroyNotify) g_module_close);
261 262 263 264 265 266 267 268 269 270

  if (catalog->library == NULL)
    return NULL;

  if ((module = g_hash_table_lookup (modules, catalog->library)))
    return module;

  if ((module = glade_util_load_library (catalog->library)))
    g_hash_table_insert (modules, g_strdup (catalog->library), module);
  else
271 272 273
    g_warning ("Failed to load external library '%s' for catalog '%s'",
               catalog->library,
               glade_catalog_get_name (catalog));
274 275

  return module;
276
}
277

278
static gboolean
279
catalog_load_classes (GladeCatalog *catalog, GladeXmlNode *widgets_node)
280
{
281 282 283 284 285 286
  GladeXmlNode *node;
  GModule *module = catalog_load_library (catalog);

  node = glade_xml_node_get_children (widgets_node);
  for (; node; node = glade_xml_node_next (node))
    {
287
      const gchar *node_name;
288 289 290 291 292 293 294 295 296 297 298 299
      GladeWidgetAdaptor *adaptor;

      node_name = glade_xml_node_get_name (node);
      if (strcmp (node_name, GLADE_TAG_GLADE_WIDGET_CLASS) != 0)
        continue;

      adaptor = glade_widget_adaptor_from_catalog (catalog, node, module);

      catalog->adaptors = g_list_prepend (catalog->adaptors, adaptor);
    }

  return TRUE;
300 301 302
}

static gboolean
303
catalog_load_group (GladeCatalog *catalog, GladeXmlNode *group_node)
304
{
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
  GladeWidgetGroup *group;
  GladeXmlNode *node;
  char *title, *translated_title;

  group = g_slice_new0 (GladeWidgetGroup);

  group->name = glade_xml_get_property_string (group_node, GLADE_TAG_NAME);

  if (!group->name)
    {
      g_warning ("Required property 'name' not found in group node");
      widget_group_destroy (group);
      return FALSE;
    }

  title = glade_xml_get_property_string (group_node, GLADE_TAG_TITLE);
  if (!title)
    {
      g_warning ("Required property 'title' not found in group node");
      widget_group_destroy (group);
      return FALSE;
    }

  /* by default, group is expanded in palette  */
  group->expanded = TRUE;

  /* Translate it */
  translated_title = dgettext (catalog->domain, title);
  if (translated_title != title)
    {
      group->title = g_strdup (translated_title);
      g_free (title);
    }
  else
    {
      group->title = title;
    }

  group->adaptors = NULL;

  node = glade_xml_node_get_children (group_node);
  for (; node; node = glade_xml_node_next (node))
    {
      const gchar *node_name;
      GladeWidgetAdaptor *adaptor;
      gchar *name;

      node_name = glade_xml_node_get_name (node);

      if (strcmp (node_name, GLADE_TAG_GLADE_WIDGET_CLASS_REF) == 0)
355
        {
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
          if ((name =
               glade_xml_get_property_string (node, GLADE_TAG_NAME)) == NULL)
            {
              g_warning ("Couldn't find required property on %s",
                         GLADE_TAG_GLADE_WIDGET_CLASS);
              continue;
            }

          if ((adaptor = glade_widget_adaptor_get_by_name (name)) == NULL)
            {
              g_warning ("Tried to include undefined widget "
                         "class '%s' in a widget group", name);
              g_free (name);
              continue;
            }
          g_free (name);

          group->adaptors = g_list_prepend (group->adaptors, adaptor);

375
        }
376
      else if (strcmp (node_name, GLADE_TAG_DEFAULT_PALETTE_STATE) == 0)
377
        {
378 379 380
          group->expanded =
              glade_xml_get_property_boolean
              (node, GLADE_TAG_EXPANDED, group->expanded);
381
        }
382
    }
383

384 385 386 387 388
  group->adaptors = g_list_reverse (group->adaptors);

  catalog->widget_groups = g_list_prepend (catalog->widget_groups, group);

  return TRUE;
Jose Maria Celorio's avatar
Jose Maria Celorio committed
389
}
390

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
static void
catalog_load (GladeCatalog *catalog)
{
  GladeXmlDoc *doc;
  GladeXmlNode *root;
  GladeXmlNode *node;

  g_return_if_fail (catalog->context != NULL);

  doc = glade_xml_context_get_doc (catalog->context);
  root = glade_xml_doc_get_root (doc);
  node = glade_xml_node_get_children (root);

  for (; node; node = glade_xml_node_next (node))
    {
      const gchar *node_name;

      node_name = glade_xml_node_get_name (node);
      if (strcmp (node_name, GLADE_TAG_GLADE_WIDGET_CLASSES) == 0)
        {
          catalog_load_classes (catalog, node);
        }
      else if (strcmp (node_name, GLADE_TAG_GLADE_WIDGET_GROUP) == 0)
        {
          catalog_load_group (catalog, node);
        }
      else
        continue;
    }

  catalog->widget_groups = g_list_reverse (catalog->widget_groups);
  catalog->context = (glade_xml_context_free (catalog->context), NULL);

  return;
}

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
static GladeCatalog *
catalog_find_by_name (GList *catalogs, const gchar *name)
{
  if (name)
    {
      GList *l;
      for (l = catalogs; l; l = g_list_next (l))
        {
          GladeCatalog *catalog = l->data;
          if (g_strcmp0 (catalog->name, name) == 0)
            return catalog;
        }
    }
  
  return NULL;
}

444
static gint
445
catalog_name_cmp (gconstpointer a, gconstpointer b)
446
{
447
  return (a && b) ? g_strcmp0 (GLADE_CATALOG(a)->name, GLADE_CATALOG(b)->name) : 0;
448 449
}

450
static GList *
451
glade_catalog_tsort (GList *catalogs, gboolean loading)
452
{
453 454 455 456 457
  GList *l, *sorted = NULL;
  GList *deps = NULL;

  /* Sort alphabetically first */
  catalogs = g_list_sort (catalogs, catalog_name_cmp);
458

459 460
  /* Generate dependency graph edges */
  for (l = catalogs; l; l = g_list_next (l))
461
    {
462
      GladeCatalog *catalog = l->data, *dep;
463

464 465
      if (!catalog->dep_catalog)
        continue;
466

467 468 469 470 471 472 473
      if ((dep = catalog_find_by_name ((loading) ? catalogs : loaded_catalogs,
                                       catalog->dep_catalog)))
        deps = _node_edge_prepend (deps, dep, catalog);
      else
        g_critical ("Catalog %s depends on catalog %s, not found",
                    catalog->name, catalog->dep_catalog);
    }
474

475
  sorted = _glade_tsort (&catalogs, &deps);
476

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
  if (deps)
    {
      GList *l, *cycles = NULL;
      
      g_warning ("Circular dependency detected loading catalogs, they will be ignored");

      for (l = deps; l; l = g_list_next (l))
        {
          _NodeEdge *edge = l->data;

          g_message ("\t%s depends on %s",
                     GLADE_CATALOG (edge->successor)->name,
                     GLADE_CATALOG (edge->successor)->dep_catalog);
          
          if (loading && !g_list_find (cycles, edge->successor))
            cycles = g_list_prepend (cycles, edge->successor);
493 494
        }

495 496 497 498 499
      if (cycles)
        g_list_free_full (cycles, (GDestroyNotify) catalog_destroy);

      _node_edge_list_free (deps);
    }
500 501 502 503 504 505

  return sorted;
}

static GList *
catalogs_from_path (GList *catalogs, const gchar *path)
506
{
507 508 509 510 511
  GladeCatalog *catalog;
  GDir *dir;
  GError *error = NULL;
  const gchar *filename;

512 513 514 515
  /* Silent return if the directory didn't exist */
  if (!g_file_test (path, G_FILE_TEST_IS_DIR))
    return catalogs;

516 517 518 519 520 521 522 523 524
  if ((dir = g_dir_open (path, 0, &error)) != NULL)
    {
      while ((filename = g_dir_read_name (dir)))
        {
          gchar *catalog_filename;

          if (!g_str_has_suffix (filename, ".xml"))
            continue;

525 526 527 528 529 530
	  /* Special case, ignore gresource files (which are present
	   * while running tests)
	   */
	  if (g_str_has_suffix (filename, ".gresource.xml"))
	    continue;

531 532 533 534 535 536 537
	  /* If we're running in the bundle, don't ever try to load
	   * anything except the GTK+ catalog
	   */
	  if (g_getenv (GLADE_ENV_BUNDLED) != NULL &&
	      strcmp (filename, "gtk+.xml") != 0)
	    continue;

538 539 540 541 542 543 544 545
          catalog_filename = g_build_filename (path, filename, NULL);
          catalog = catalog_open (catalog_filename);
          g_free (catalog_filename);

          if (catalog)
            {
              /* Verify that we are not loading the same catalog twice !
               */
546
              if (catalog_find_by_name (catalogs, catalog->name))
547
                catalog_destroy (catalog);
548 549
              else
                catalogs = g_list_prepend (catalogs, catalog);
550 551 552 553
            }
          else
            g_warning ("Unable to open the catalog file %s.\n", filename);
        }
554 555

      g_dir_close (dir);
556 557 558 559 560 561 562
    }
  else
    g_warning ("Failed to open catalog directory '%s': %s", path,
               error->message);


  return catalogs;
563 564
}

565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
/**
 * glade_catalog_add_path:
 * @path:
 * 
 * Adds a new path to the list of path to look catalogs for.
 */
void
glade_catalog_add_path (const gchar *path)
{
  g_return_if_fail (path != NULL);

  if (g_list_find_custom (catalog_paths, path, (GCompareFunc) g_strcmp0) == NULL)
	catalog_paths = g_list_append (catalog_paths, g_strdup (path));
}

/**
 * glade_catalog_remove_path:
 * @path:
 * 
 * Remove path from the list of path to look catalogs for.
 * NULL to remove all paths.
 */
void
glade_catalog_remove_path (const gchar *path)
{
  GList *l;
  
  if (path == NULL)
	{
	  g_list_free_full (catalog_paths, g_free);
	  catalog_paths = NULL;
	}
  else if ((l = g_list_find_custom (catalog_paths, path, (GCompareFunc) g_strcmp0)))
	{
	  catalog_paths = g_list_remove_link (catalog_paths, l); 
	}
}

603 604 605 606 607 608 609 610 611 612 613
/**
 * glade_catalog_get_extra_paths:
 *
 * Returns a list paths added by glade_catalog_add_path()
 */
const GList *
glade_catalog_get_extra_paths (void)
{
  return catalog_paths;
}

614 615 616 617 618 619 620 621 622 623
/**
 * glade_catalog_load_all:
 * 
 * Loads all available catalogs in the system.
 * First loads catalogs from GLADE_ENV_CATALOG_PATH,
 * then from glade_app_get_catalogs_dir() and finally from paths specified with
 * glade_catalog_add_path()
 *
 * Returns: the list of loaded GladeCatalog *
 */
624 625 626
const GList *
glade_catalog_load_all (void)
{
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
  GList *catalogs = NULL, *l, *adaptors;
  GladeCatalog *catalog;
  const gchar *search_path;
  gchar **split;
  GString *icon_warning = NULL;
  gint i;


  /* Make sure we don't init the catalogs twice */
  if (loaded_catalogs)
    return loaded_catalogs;

  /* First load catalogs from user specified directories ... */
  if ((search_path = g_getenv (GLADE_ENV_CATALOG_PATH)) != NULL)
    {
      if ((split = g_strsplit (search_path, ":", 0)) != NULL)
        {
          for (i = 0; split[i] != NULL; i++)
            catalogs = catalogs_from_path (catalogs, split[i]);

          g_strfreev (split);
        }
    }

  /* ... Then load catalogs from standard install directory */
652 653
  if (g_getenv (GLADE_ENV_TESTING) == NULL)
    catalogs = catalogs_from_path (catalogs, glade_app_get_catalogs_dir ());
654

655 656 657 658
  /* And then load catalogs from extra paths */
  for (l = catalog_paths; l; l = g_list_next (l))
    catalogs = catalogs_from_path (catalogs, l->data);
  
659 660 661 662
  /* Catalogs need dependancies, most catalogs depend on
   * the gtk+ catalog, but some custom toolkits may depend
   * on the gnome catalog for instance.
   */
663
  catalogs = glade_catalog_tsort (catalogs, TRUE);
664 665

  /* After sorting, execute init function and then load */
666
  for (l = catalogs; l; l = g_list_next (l))
667 668 669 670 671 672
    {
      catalog = l->data;
      if (catalog->init_function)
        catalog->init_function (catalog->name);
    }

673
  for (l = catalogs; l; l = g_list_next (l))
674 675 676 677 678 679 680 681
    {
      catalog = l->data;
      catalog_load (catalog);
    }

  /* Print a summery of widget adaptors missing icons.
   */
  adaptors = glade_widget_adaptor_list_adaptors ();
682
  for (l = adaptors; l; l = g_list_next (l))
683 684 685
    {
      GladeWidgetAdaptor *adaptor = l->data;

686 687 688
      /* Dont print missing icons in unit tests */
      if (glade_widget_adaptor_get_missing_icon (adaptor) &&
	  g_getenv (GLADE_ENV_TESTING) == NULL)
689 690 691 692 693 694
        {
          if (!icon_warning)
            icon_warning = g_string_new ("Glade needs artwork; "
                                         "a default icon will be used for "
                                         "the following classes:");

695 696 697
	  g_string_append_printf (icon_warning,
				  "\n\t%s\tneeds an icon named '%s'",
				  glade_widget_adaptor_get_name (adaptor), 
698
				  glade_widget_adaptor_get_missing_icon (adaptor));
699 700
        }
    }
701

702 703 704 705 706 707 708 709 710 711 712
  g_list_free (adaptors);

  if (icon_warning)
    {
      g_message ("%s", icon_warning->str);
      g_string_free (icon_warning, TRUE);
    }

  loaded_catalogs = catalogs;

  return loaded_catalogs;
713
}
714

715 716 717 718 719 720
/**
 * glade_catalog_get_name:
 * @catalog: a catalog object
 * 
 * Returns: The symbolic catalog name.
 */
721
G_CONST_RETURN gchar *
722
glade_catalog_get_name (GladeCatalog *catalog)
723
{
724
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
725

726
  return catalog->name;
727 728
}

729 730 731 732 733 734
/**
 * glade_catalog_get_book:
 * @catalog: a catalog object
 * 
 * Returns: The Devhelp search domain.
 */
735
G_CONST_RETURN gchar *
736
glade_catalog_get_book (GladeCatalog *catalog)
737
{
738
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
739

740
  return catalog->book;
741 742
}

743 744 745 746 747 748
/**
 * glade_catalog_get_domain:
 * @catalog: a catalog object
 * 
 * Returns: The domain to be used to translate strings from this catalog
 */
749
G_CONST_RETURN gchar *
750
glade_catalog_get_domain (GladeCatalog *catalog)
751
{
752
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
753

754
  return catalog->domain;
755 756
}

757 758 759 760 761 762
/**
 * glade_catalog_get_icon_prefix:
 * @catalog: a catalog object
 * 
 * Returns: The prefix for icons.
 */
763
G_CONST_RETURN gchar *
764
glade_catalog_get_icon_prefix (GladeCatalog *catalog)
765
{
766
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
767

768
  return catalog->icon_prefix;
769 770
}

771 772 773 774 775 776
/**
 * glade_catalog_get_major_version:
 * @catalog: a catalog object
 * 
 * Returns: The catalog version
 */
777
guint16
778
glade_catalog_get_major_version (GladeCatalog *catalog)
779
{
780
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), 0);
781

782
  return catalog->major_version;
783 784
}

785 786 787 788 789 790
/**
 * glade_catalog_get_minor_version:
 * @catalog: a catalog object
 * 
 * Returns: The catalog minor version
 */
791
guint16
792
glade_catalog_get_minor_version (GladeCatalog *catalog)
793
{
794
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), 0);
795

796
  return catalog->minor_version;
797 798
}

799 800 801 802 803 804
/**
 * glade_catalog_get_targets:
 * @catalog: a catalog object
 * 
 * Returns: the list of suitable version targets.
 */
805
GList *
806
glade_catalog_get_targets (GladeCatalog *catalog)
807
{
808
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
809

810
  return catalog->targetable_versions;
811 812
}

813 814 815 816 817 818
/**
 * glade_catalog_get_widget_groups:
 * @catalog: a catalog object
 * 
 * Returns: the list of widget groups (palette)
 */
819
GList *
820
glade_catalog_get_widget_groups (GladeCatalog *catalog)
821
{
822
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
823

824
  return catalog->widget_groups;
825 826
}

827 828 829 830 831 832
/**
 * glade_catalog_get_adaptors:
 * @catalog: a catalog object
 * 
 * Returns: the list of widget class adaptors
 */
833
GList *
834
glade_catalog_get_adaptors (GladeCatalog *catalog)
835
{
836
  g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL);
837

838
  return catalog->adaptors;
839
}
840

841 842 843 844 845 846
/**
 * glade_catalog_is_loaded:
 * @name: a catalog object
 * 
 * Returns: Whether @name is loaded or not
 */
847
gboolean
848
glade_catalog_is_loaded (const gchar *name)
849
{
850 851
  g_return_val_if_fail (name != NULL, FALSE);
  g_assert (loaded_catalogs != NULL);
852
  return catalog_find_by_name (loaded_catalogs, name) != NULL;
853
}
854

855 856 857 858 859
/**
 * glade_catalog_destroy_all:
 * 
 * Destroy and free all resources related with every loaded catalog.
 */
860 861
void
glade_catalog_destroy_all (void)
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
{
  /* close catalogs */
  if (loaded_catalogs)
    {
      GList *l;
      for (l = loaded_catalogs; l; l = l->next)
        catalog_destroy (GLADE_CATALOG (l->data));
      g_list_free (loaded_catalogs);
      loaded_catalogs = NULL;
    }

  /* close plugin modules */
  if (modules)
    {
      g_hash_table_destroy (modules);
      modules = NULL;
    }
879
}
880

881 882 883 884 885 886
/**
 * glade_widget_group_get_name:
 * @group: a widget group
 * 
 * Returns: the widget group name
 */
887
const gchar *
888
glade_widget_group_get_name (GladeWidgetGroup *group)
889
{
890
  g_return_val_if_fail (group != NULL, NULL);
891

892
  return group->name;
893 894
}

895 896 897 898 899 900
/**
 * glade_widget_group_get_title:
 * @group: a widget group
 * 
 * Returns: the widget group name used in the palette
 */
901
const gchar *
902
glade_widget_group_get_title (GladeWidgetGroup *group)
903
{
904
  g_return_val_if_fail (group != NULL, NULL);
905

906
  return group->title;
907 908
}

909 910 911 912 913 914
/**
 * glade_widget_group_get_expanded:
 * @group: a widget group
 * 
 * Returns: Whether group is expanded in the palette
 */
915
gboolean
916
glade_widget_group_get_expanded (GladeWidgetGroup *group)
917
{
918
  g_return_val_if_fail (group != NULL, FALSE);
919

920
  return group->expanded;
921 922
}

923 924 925 926 927 928
/**
 * glade_widget_group_get_adaptors:
 * @group: a widget group
 * 
 * Returns: a list of class adaptors in the palette
 */
929
const GList *
930
glade_widget_group_get_adaptors (GladeWidgetGroup *group)
931
{
932
  g_return_val_if_fail (group != NULL, NULL);
933

934
  return group->adaptors;
935
}
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952

/* Private API */

GladeCatalog *
_glade_catalog_get_catalog (const gchar *name)
{
  g_return_val_if_fail (name != NULL, NULL);
  g_assert (loaded_catalogs != NULL);

  return catalog_find_by_name (loaded_catalogs, name);
}

GList *
_glade_catalog_tsort (GList *catalogs)
{
  return glade_catalog_tsort (catalogs, FALSE);
}