ops... lot of changes... read the changelog.

This commit is contained in:
Joaquín Cuenca Abela 2003-08-07 20:09:23 +00:00
parent 3e58c96f31
commit a1c3b8eaab
12 changed files with 828 additions and 267 deletions

View File

@ -1,3 +1,19 @@
2003-08-07 Joaquin Cuenca Abela <e98cuenc@yahoo.com>
* src/glade-catalog.[ch], glade-palette.c: Specify the order in which
the catalogs should appear on the palette (read it from
widgets/glade-palette.xml). Also changed a bit the format of
the catalogs.
* src/glade-parameter.[ch], glade-property-class.[ch], glade-widget-class.[ch],
glade-widget.c, glade-xml-utils.h: Inherit properties specified on a
xml file from a base class to an inherited class. It makes possible
to specify something special for (for instance) GtkWidget, and
make it inherit for each GtkWidget.
* widgets/glade-palette.xml: specify the order of the catalogs.
* widgets/gtkwidget.xml, gtkbox.xml: specify common properties for
gtkwidgets and gtkboxes. Coupled with the above changes, it
makes almost every xml file obsolete.
2003-08-07 Paolo BOrelli <pborelli@katamail.com>
* src/glade-utils.[ch]: remove dependency on glade-project-window.h.

View File

@ -35,8 +35,10 @@
#include "glade-catalog.h"
#include "glade-widget-class.h"
GList *glade_catalog_list = NULL; /* A list of GladeCatalog items */
GList *widget_class_list = NULL; /* A list of all the GladeWidgetClass objects loaded */
#define GLADE_TAG_PALETTE "GladePalette"
static GList *glade_catalog_list = NULL; /* A list of GladeCatalog items */
static GList *widget_class_list = NULL; /* A list of all the GladeWidgetClass objects loaded */
GList *
glade_catalog_get_widgets (void)
@ -44,146 +46,172 @@ glade_catalog_get_widgets (void)
return widget_class_list;
}
static GladeCatalog *
glade_catalog_new (void)
{
GladeCatalog *catalog;
catalog = g_new0 (GladeCatalog, 1);
catalog->names = NULL;
catalog->widgets = NULL;
return catalog;
}
static void
void
glade_catalog_delete (GladeCatalog *catalog)
{
g_return_if_fail (catalog);
GList *list;
if (catalog == NULL)
return;
g_free (catalog->title);
list = catalog->widget_classes;
while (list != NULL)
{
glade_widget_class_free ((GladeWidgetClass*) list->data);
list = list->next;
}
g_list_free (catalog->widget_classes);
g_free (catalog);
}
static GList *
glade_catalog_load_names_from_node (GladeXmlContext *context, GladeXmlNode *node)
static GladeCatalog *
glade_catalog_load (const char *base_catalog_filename)
{
GladeXmlNode *child;
GList *list;
gchar *name;
GladeWidgetClass *widget_class = NULL;
GladeXmlContext *context = NULL;
GladeXmlNode *root = NULL;
GladeXmlNode *widget_node = NULL;
GladeXmlDoc *doc = NULL;
GladeCatalog *catalog = NULL;
char *name = NULL;
char *generic_name = NULL;
char *catalog_filename = NULL;
char *base_filename = NULL;
GList *last_widget_class = NULL;
if (!glade_xml_node_verify (node, GLADE_TAG_CATALOG))
return NULL;
list = NULL;
child = glade_xml_node_get_children (node);
for (; child; child = glade_xml_node_next (child)) {
if (!glade_xml_node_verify (child, GLADE_TAG_GLADE_WIDGET))
return NULL;
name = glade_xml_get_content (child);
if (name == NULL)
return NULL;
list = g_list_prepend (list, name);
catalog_filename = g_strdup_printf ("%s%c%s", CATALOGS_DIR, G_DIR_SEPARATOR, base_catalog_filename);
if (catalog_filename == NULL)
{
g_critical ("Not enough memory.");
goto lblError;
}
list = g_list_reverse (list);
return list;
}
static gboolean
glade_catalog_load_names_from_file (GladeCatalog *catalog, const gchar *file_name)
{
GladeXmlContext *context;
GladeXmlNode *root;
GladeXmlDoc *doc;
context = glade_xml_context_new_from_path (file_name, NULL, GLADE_TAG_CATALOG);
/* get the context & root node of the catalog file */
context = glade_xml_context_new_from_path (catalog_filename, NULL, GLADE_TAG_CATALOG);
if (context == NULL)
return FALSE;
{
g_warning ("Impossible to open the catalog [%s].", catalog_filename);
goto lblError;
}
doc = glade_xml_context_get_doc (context);
root = glade_xml_doc_get_root (doc);
catalog->title = glade_xml_get_property_string_required (root, "Title", NULL);
catalog->names = glade_catalog_load_names_from_node (context, root);
glade_xml_context_free (context);
return TRUE;
}
static GladeCatalog *
glade_catalog_new_from_file (const gchar *file)
{
GladeCatalog *catalog;
catalog = glade_catalog_new ();
if (!glade_catalog_load_names_from_file (catalog, file)) {
glade_catalog_delete (catalog);
return NULL;
}
return catalog;
}
GladeCatalog *
glade_catalog_load (const gchar *file_name)
{
GladeWidgetClass *class;
GladeCatalog *catalog;
GList *list;
GList *new_list;
gchar *name;
catalog = glade_catalog_new_from_file (file_name);
/* allocate the catalog */
catalog = g_new0 (GladeCatalog, 1);
if (catalog == NULL)
return NULL;
list = catalog->names;
new_list = NULL;
for (; list != NULL; list = list->next) {
name = list->data;
class = glade_widget_class_new_from_name (name);
if (class == NULL) continue;
new_list = g_list_prepend (new_list, class);
widget_class_list = g_list_prepend (widget_class_list, class);
/* We keep a list per catalog (group) and a general list of
* all widgets loaded
*/
{
g_critical ("Not enough memory.");
goto lblError;
}
catalog->widgets = g_list_reverse (new_list);
last_widget_class = NULL;
glade_catalog_list = g_list_prepend (glade_catalog_list, catalog);
/* read the title of this catalog */
catalog->title = glade_xml_get_property_string_required (root, "Title", NULL);
if (!glade_xml_node_verify (root, GLADE_TAG_CATALOG))
{
g_warning ("The root node of [%s] has a name different from %s.", catalog_filename, GLADE_TAG_CATALOG);
goto lblError;
}
/* build all the GladeWidgetClass'es associated with this catalog */
widget_node = glade_xml_node_get_children (root);
for (; widget_node != NULL; widget_node = glade_xml_node_next (widget_node))
{
if (!glade_xml_node_verify (widget_node, GLADE_TAG_GLADE_WIDGET))
continue;
name = glade_xml_get_property_string_required (widget_node, "name", NULL);
if (name == NULL)
continue;
generic_name = glade_xml_get_property_string (widget_node, "generic_name");
base_filename = glade_xml_get_property_string (widget_node, "filename");
widget_class = glade_widget_class_new_from_name2 (name, generic_name, base_filename);
if (widget_class)
{
last_widget_class = g_list_append (last_widget_class, widget_class);
if (last_widget_class->next != NULL)
last_widget_class = last_widget_class->next;
else
catalog->widget_classes = last_widget_class;
}
g_free (name);
g_free (generic_name);
g_free (base_filename);
}
glade_xml_context_free (context);
g_free (catalog_filename);
return catalog;
lblError:
glade_xml_context_free (context);
g_free (catalog_filename);
g_free (catalog);
return NULL;
}
GList *
glade_catalog_load_all (void)
{
GDir *catalogsdir = NULL;
static const char * const filename = CATALOGS_DIR G_DIR_SEPARATOR_S "glade-palette.xml";
GladeXmlContext *context;
GladeXmlNode *root;
GladeXmlNode *xml_catalogs;
GladeXmlDoc *doc;
GList *catalogs = NULL;
GladeCatalog *gcatalog = NULL;
const char *base_filename = NULL;
char *filename = NULL;
GladeCatalog *catalog;
catalogsdir = g_dir_open (CATALOGS_DIR, 0, NULL);
if (!catalogsdir) {
g_warning ("Could not open catalogs from %s\n", CATALOGS_DIR);
context = glade_xml_context_new_from_path (filename, NULL, GLADE_TAG_PALETTE);
if (context == NULL)
{
g_critical ("Unable to open %s.\n", filename);
return NULL;
}
while ((base_filename = g_dir_read_name (catalogsdir)) != NULL) {
filename = g_strdup_printf ("%s/%s", CATALOGS_DIR, base_filename);
gcatalog = glade_catalog_load (filename);
if (gcatalog)
catalogs = g_list_append (catalogs, gcatalog);
doc = glade_xml_context_get_doc (context);
root = glade_xml_doc_get_root (doc);
xml_catalogs = glade_xml_node_get_children (root);
while (xml_catalogs != NULL) {
char *name = glade_xml_get_property_string_required (xml_catalogs, "filename", NULL);
g_free (filename);
if (!strcmp(glade_xml_node_get_name (xml_catalogs), GLADE_TAG_CATALOG))
{
catalog = glade_catalog_load (name);
if (catalog)
catalogs = g_list_append (catalogs, catalog);
else
g_warning ("Unable to open the catalog %s.\n", name);
}
else
g_warning ("The palette file \"glade-palette.xml\" has "
"a node with name %s instead of " GLADE_TAG_CATALOG "\n", name);
xml_catalogs = glade_xml_node_next (xml_catalogs);
g_free (name);
}
g_dir_close (catalogsdir);
glade_xml_context_free (context);
return catalogs;
}
const char *glade_catalog_get_title (GladeCatalog *catalog)
{
g_return_val_if_fail (catalog != NULL, NULL);
return catalog->title;
}
GList *glade_catalog_get_widget_classes (GladeCatalog *catalog)
{
g_return_val_if_fail (catalog != NULL, NULL);
return catalog->widget_classes;
}

View File

@ -12,20 +12,14 @@ G_BEGIN_DECLS
struct _GladeCatalog
{
gchar *title; /* Title for this catalog */
GList *names; /* Contains the list of names that we are going
* to try to load. This is basically a memory
* representation of catalog.xml
*/
GList *widgets; /* Contains the list of GladeWidgetClass objects
* that where successfully loaded from disk
*/
GList *widget_classes; /* list of widget classes contained on this catalog */
};
GladeCatalog * glade_catalog_load (const gchar *file_name);
GladeCatalog * glade_catalog_get (void);
void glade_catalog_delete (GladeCatalog *catalog);
GList * glade_catalog_load_all (void);
GList * glade_catalog_get_widgets (void); /* This prolly should be in glade-widget-class.c */
GList *glade_catalog_get_widgets (void); /* This probally should be in glade-widget-class.c */
const char *glade_catalog_get_title (GladeCatalog *catalog);
GList *glade_catalog_get_widget_classes (GladeCatalog *catalog);
G_END_DECLS

View File

@ -189,7 +189,7 @@ glade_palette_widget_table_create (GladePalette *palette, GladeCatalog *catalog)
gint cols = 4;
gint i;
list = catalog->widgets;
list = glade_catalog_get_widget_classes (catalog);
while (list) {
if (((GladeWidgetClass*) list->data)->in_palette)
@ -198,7 +198,7 @@ glade_palette_widget_table_create (GladePalette *palette, GladeCatalog *catalog)
list = list->next;
}
list = catalog->widgets;
list = glade_catalog_get_widget_classes (catalog);
num = g_list_length (list);
rows = (gint)((num_visible - 1)/ cols) + 1;

View File

@ -100,16 +100,14 @@ glade_parameter_get_string (GList *parameters, const gchar *key, gchar **value)
}
}
static void
void
glade_parameter_free (GladeParameter *parameter)
{
g_return_if_fail (parameter->key);
g_return_if_fail (parameter->value);
if (!parameter)
return;
g_free (parameter->key);
g_free (parameter->value);
parameter->key = NULL;
parameter->value = NULL;
g_free (parameter);
}
@ -123,6 +121,21 @@ glade_parameter_new (void)
return parameter;
}
GladeParameter *
glade_parameter_clone (GladeParameter *parameter)
{
GladeParameter *clon;
if (parameter == NULL)
return NULL;
clon = glade_parameter_new ();
clon->key = g_strdup (parameter->key);
clon->value = g_strdup (parameter->value);
return clon;
}
static GladeParameter *
glade_parameter_new_from_node (GladeXmlNode *node)
{

View File

@ -32,6 +32,8 @@ struct _GladeParameter {
};
GladeParameter * glade_parameter_new (void);
GladeParameter *glade_parameter_clone (GladeParameter *parameter);
void glade_parameter_free (GladeParameter *parameter);
void glade_parameter_get_float (GList *parameters, const gchar *key, gfloat *value);
void glade_parameter_get_integer (GList *parameters, const gchar *key, gint *value);

View File

@ -48,6 +48,103 @@ typedef struct GladePropertyTypeTable {
/* #warning Implement me. */
#endif
static GladeChoice *
glade_property_class_choice_new_from_value (GEnumValue value)
{
GladeChoice *choice;
choice = glade_choice_new ();
choice->name = g_strdup (value.value_nick);
choice->id = g_strdup (value.value_name);
/*
g_debug(("Choice Id is %s\n", choice->id));
choice->symbol = g_strdup (value.value_name);
*/
choice->value = value.value;
return choice;
}
static GList *
glade_property_class_get_choices_from_spec (GParamSpec *spec)
{
GladeChoice *choice;
GEnumClass *class;
GEnumValue value;
GList *list = NULL;
gint num;
gint i;
class = G_PARAM_SPEC_ENUM (spec)->enum_class;
num = class->n_values;
for (i = 0; i < num; i++) {
value = class->values[i];
choice = glade_property_class_choice_new_from_value (value);
if (choice)
list = g_list_prepend (list, choice);
}
list = g_list_reverse (list);
return list;
}
static GladeChoice *
glade_property_class_choice_clone (GladeChoice *choice)
{
GladeChoice *clon;
clon = glade_choice_new ();
clon->id = g_strdup (choice->id);
clon->name = g_strdup (choice->name);
clon->type = choice->type;
clon->value = choice->value;
return clon;
}
static void
glade_property_class_choice_free (GladeChoice *choice)
{
if (choice == NULL)
return;
g_free (choice->name);
g_free (choice->id);
g_free (choice);
}
#if 0
static gchar *
glade_property_get_default_choice (GParamSpec *spec,
GladePropertyClass *class)
{
GladeChoice *choice = NULL;
GList *list;
gint def;
g_return_val_if_fail (G_IS_PARAM_SPEC_ENUM (spec), NULL);
def = (gint) G_PARAM_SPEC_ENUM (spec)->default_value;
list = class->choices;
for (; list != NULL; list = list->next) {
choice = list->data;
if (choice->value == def)
break;
}
if (list == NULL) {
g_warning ("Could not find the default value for %s\n", spec->nick);
if (class->choices == NULL)
return NULL;
choice = class->choices->data;
}
return g_strdup (choice->symbol);
}
#endif
GladePropertyType
glade_property_type_str_to_enum (const gchar *str)
{
@ -138,6 +235,32 @@ glade_query_new_from_node (GladeXmlNode *node)
return query;
}
static GladePropertyQuery *
glade_property_query_clone (GladePropertyQuery *query)
{
GladePropertyQuery *clon;
if (query == NULL)
return NULL;
clon = glade_property_query_new ();
clon->window_title = g_strdup (query->window_title);
clon->question = g_strdup (clon->question);
return clon;
}
static void
glade_property_query_free (GladePropertyQuery *query)
{
if (query == NULL)
return;
g_free (query->window_title);
g_free (query->question);
g_free (query);
}
GladePropertyClass *
glade_property_class_new (void)
{
@ -161,12 +284,80 @@ glade_property_class_new (void)
property_class->common = FALSE;
property_class->packing = FALSE;
property_class->get_default = FALSE;
property_class->is_modified = FALSE;
property_class->query = NULL;
property_class->set_function = NULL;
property_class->get_function = NULL;
return property_class;
}
GladePropertyClass *
glade_property_class_clone (GladePropertyClass *property_class)
{
GladePropertyClass *clon;
if (property_class == NULL)
return NULL;
clon = g_new0 (GladePropertyClass, 1);
if (clon == NULL)
{
g_warning ("Out of memory.");
return NULL;
}
memcpy (clon, property_class, sizeof(GladePropertyClass));
clon->id = g_strdup (clon->id);
clon->name = g_strdup (clon->name);
clon->tooltip = g_strdup (clon->tooltip);
if (G_IS_VALUE (property_class->def))
{
clon->def = g_new0 (GValue, 1);
g_value_init (clon->def, G_VALUE_TYPE (property_class->def));
g_value_copy (property_class->def, clon->def);
}
if (clon->parameters)
{
GList *parameter;
clon->parameters = g_list_copy (clon->parameters);
for (parameter = clon->parameters; parameter != NULL; parameter = parameter->next)
parameter->data = glade_parameter_clone ((GladeParameter*) parameter->data);
}
if (clon->choices)
{
GList *choice;
clon->choices = g_list_copy (clon->choices);
for (choice = clon->choices; choice != NULL; choice = choice->next)
choice->data = glade_property_class_choice_clone ((GladeChoice*) choice->data);
}
clon->query = glade_property_query_clone (clon->query);
/* ok, wtf? what is the child member for? */
/* if (clon->child)
clon->child = glade_widget_class_clone (clon->child); */
if (clon->update_signals)
{
GList *signals;
clon->update_signals = g_list_copy (clon->update_signals);
for (signals = clon->update_signals; signals != NULL; signals = signals->next)
signals->data = g_strdup ((const char *) signals->data);
}
return clon;
}
void
glade_property_class_free (GladePropertyClass *class)
{
@ -175,11 +366,19 @@ glade_property_class_free (GladePropertyClass *class)
g_return_if_fail (GLADE_IS_PROPERTY_CLASS (class));
g_free (class->name);
g_free (class->id);
g_free (class->tooltip);
g_free (class->name);
g_free (class->def);
g_list_foreach (class->parameters, (GFunc) glade_parameter_free, NULL);
g_list_free (class->parameters);
g_list_foreach (class->choices, (GFunc) glade_property_class_choice_free, NULL);
g_list_free (class->choices);
glade_property_query_free (class->query);
glade_widget_class_free (class->child);
g_list_foreach (class->update_signals, (GFunc) g_free, NULL);
g_list_free (class->update_signals);
g_free (class);
class = NULL;
}
static GladePropertyType
@ -285,78 +484,6 @@ glade_property_class_get_default_from_spec (GParamSpec *spec,
return value;
}
static GladeChoice *
glade_property_class_choice_new_from_value (GEnumValue value)
{
GladeChoice *choice;
choice = glade_choice_new ();
choice->name = g_strdup (value.value_nick);
choice->id = g_strdup (value.value_name);
/*
g_debug(("Choice Id is %s\n", choice->id));
choice->symbol = g_strdup (value.value_name);
*/
choice->value = value.value;
return choice;
}
static GList *
glade_property_class_get_choices_from_spec (GParamSpec *spec)
{
GladeChoice *choice;
GEnumClass *class;
GEnumValue value;
GList *list = NULL;
gint num;
gint i;
class = G_PARAM_SPEC_ENUM (spec)->enum_class;
num = class->n_values;
for (i = 0; i < num; i++) {
value = class->values[i];
choice = glade_property_class_choice_new_from_value (value);
if (choice)
list = g_list_prepend (list, choice);
}
list = g_list_reverse (list);
return list;
}
#if 0
static gchar *
glade_property_get_default_choice (GParamSpec *spec,
GladePropertyClass *class)
{
GladeChoice *choice = NULL;
GList *list;
gint def;
g_return_val_if_fail (G_IS_PARAM_SPEC_ENUM (spec), NULL);
def = (gint) G_PARAM_SPEC_ENUM (spec)->default_value;
list = class->choices;
for (; list != NULL; list = list->next) {
choice = list->data;
if (choice->value == def)
break;
}
if (list == NULL) {
g_warning ("Could not find the default value for %s\n", spec->nick);
if (class->choices == NULL)
return NULL;
choice = class->choices->data;
}
return g_strdup (choice->symbol);
}
#endif
gchar *
glade_property_class_make_string_from_gvalue (GladePropertyClass *property_class,
const GValue *value)
@ -785,8 +912,7 @@ glade_property_class_update_from_node (GladeXmlNode *node,
gchar *id;
gchar *name;
if (!glade_xml_node_verify (node, GLADE_TAG_PROPERTY))
return;
g_return_if_fail (glade_xml_node_verify (node, GLADE_TAG_PROPERTY));
/* If we have a property like ... Disabled="TRUE"> we should
* remove this property
@ -878,7 +1004,8 @@ glade_property_class_update_from_node (GladeXmlNode *node,
pproperty_class->def = gvalue;
glade_property_class_free (*property_class);
*property_class = pproperty_class;
} else {
}
else {
/* If the property is an object Load it */
if (pproperty_class->type == GLADE_PROPERTY_TYPE_OBJECT) {
child = glade_xml_search_child_required (node, GLADE_TAG_GLADE_WIDGET_CLASS);
@ -905,6 +1032,9 @@ glade_property_class_update_from_node (GladeXmlNode *node,
}
}
/* we're modifying the default values of this property */
pproperty_class->is_modified = TRUE;
/* Get the Query */
child = glade_xml_search_child (node, GLADE_TAG_QUERY);
if (child != NULL)
@ -967,7 +1097,8 @@ glade_property_class_list_add_from_node (GladeXmlNode *node,
list_element = g_list_last (*properties);
buff = glade_xml_get_property_string (child, GLADE_TAG_ID);
while (list_element != NULL && property_class == NULL) {
if (!g_ascii_strcasecmp (((GladePropertyClass *) list_element->data)->id, buff))
const char *id = ((GladePropertyClass *) list_element->data)->id;
if (!g_ascii_strcasecmp (id, buff))
property_class = (GladePropertyClass *) list_element->data;
else
list_element = g_list_previous (list_element);

View File

@ -19,7 +19,7 @@ typedef enum {
GLADE_PROPERTY_TYPE_ERROR
} GladePropertyType;
/* The GladeProperty object describes a settable paramter of a widget.
/* The GladeProperty object describes a settable parameter of a widget.
* All entries that the user can change in the first page of the GladeEditor
* make are a GladeProperty (except for the widget name)
* GladeProperties can be of any type of GladePropertyType
@ -170,6 +170,8 @@ struct _GladePropertyClass
* add the widget, then we query the property to get the position it
* was added into.
*/
gboolean is_modified; /* If true, this property_class has been "modified" from the
* the standard property by a xml file. */
void (*set_function) (GObject *object,
const GValue *value);
@ -189,6 +191,7 @@ struct _GladePropertyClass
GladePropertyClass * glade_property_class_new (void);
GladePropertyClass * glade_property_class_new_from_spec (GParamSpec *spec);
GladePropertyClass *glade_property_class_clone (GladePropertyClass *property_class);
void glade_property_class_free (GladePropertyClass *class);

View File

@ -45,7 +45,10 @@
#include "glade-choice.h"
#include "glade-parameter.h"
#include "glade-gtk.h"
#include "glade-debug.h"
/* hash table that will contain all the GtkWidgetClass'es created, indexed by its name */
static GHashTable *widget_classes = NULL;
static gchar *
glade_widget_class_compose_get_type_func (GladeWidgetClass *class)
@ -73,9 +76,8 @@ glade_widget_class_compose_get_type_func (GladeWidgetClass *class)
i++;
}
tmp = g_string_append (tmp, "_get_type");
retval = g_ascii_strdown (tmp->str, tmp->len);
retval = g_strconcat (tmp->str, "_get_type", NULL);
g_strdown (retval);
g_string_free (tmp, TRUE);
return retval;
@ -96,6 +98,28 @@ glade_widget_class_new (void)
return class;
}
void
glade_widget_class_free (GladeWidgetClass *widget_class)
{
if (widget_class == NULL)
return;
g_free (widget_class->generic_name);
g_free (widget_class->name);
/* delete the list holding the properties */
g_list_foreach (widget_class->properties, (GFunc) g_free, NULL);
g_list_free (widget_class->properties);
/* delete the list holding the child properties */
g_list_foreach (widget_class->child_properties, (GFunc) g_free, NULL);
g_list_free (widget_class->child_properties);
/* delete the list holding the signals */
g_list_foreach (widget_class->signals, (GFunc) g_free, NULL);
g_list_free (widget_class->signals);
}
static GList *
glade_widget_class_list_properties (GladeWidgetClass *class)
{
@ -375,6 +399,309 @@ glade_widget_class_create_icon (GladeWidgetClass *class)
return icon;
}
/**
* glade_widget_class_extend_with_file:
* @filename: complete path name of the xml file with the description of the GladeWidgetClass
*
* This function extends an existing GladeWidgetClass with the data found on the file
* with name @filename (if it exists). Notably, it will add new properties to the
* GladeWidgetClass, or modify existing ones, in function of the contents of the file.
*
* @returns: TRUE if the file exists and its format is correct, FALSE otherwise.
**/
static gboolean
glade_widget_class_extend_with_file (GladeWidgetClass *widget_class, const char *filename)
{
GladeXmlContext *context;
GladeXmlDoc *doc;
GladeXmlNode *properties;
GladeXmlNode *node;
g_return_val_if_fail (filename != NULL, FALSE);
context = glade_xml_context_new_from_path (filename, NULL, GLADE_TAG_GLADE_WIDGET_CLASS);
if (context != NULL)
{
doc = glade_xml_context_get_doc (context);
node = glade_xml_doc_get_root (doc);
properties = glade_xml_search_child (node, GLADE_TAG_PROPERTIES);
/* if we found a <properties> tag on the xml file, we add the properties
* that we read from the xml file to the class */
if (properties != NULL)
glade_property_class_list_add_from_node (properties, widget_class, &widget_class->properties);
return TRUE;
}
return FALSE;
}
/**
* glade_widget_class_store_with_name:
* @widget_class: widget class to store
*
* Store the GladeWidgetClass on the cache, indexed by its name
**/
static void
glade_widget_class_store_with_name (GladeWidgetClass *widget_class)
{
/* if it's the first time we store a widget class, then initialize the widget_classes hash */
if (widget_classes == NULL)
widget_classes = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (widget_classes, widget_class->name, widget_class);
return;
}
/**
* glade_widget_class_get_from_name:
* @name: name of the widget class (for instance: GtkButton)
*
* Returns an already created GladeWidgetClass with the name passed as argument.
*
* If we have not yet created any GladeWidgetClass, this function will return %NULL.
*
* Return Value: An existing GladeWidgetClass with the name passed as argument,
* or %NULL if such a class doesn't exist.
**/
GladeWidgetClass *
glade_widget_class_get_from_name (const char *name)
{
if (widget_classes != NULL)
return g_hash_table_lookup (widget_classes, name);
else
return NULL;
}
/**
* glade_widget_class_merge:
* @widget_class: main class.
* @parent_class: secondary class.
*
* Merges the contents of the parent_class on the widget_class. It doesn't handles
* the duplicated properties / signals. I.e., if you have the same property / signal
* on parent_class and on widget_class, widget_class will end having two times
* this property. You will have to remove the duplicates to ensure a consistent
* widget_class. The properties / signals of the parent_class will be appended to
* those of widget_class.
**/
static void
glade_widget_class_merge (GladeWidgetClass *widget_class, GladeWidgetClass *parent_class)
{
GList *last_property;
GList *parent_properties;
GList *tmp1;
g_return_if_fail (GLADE_IS_WIDGET_CLASS (widget_class));
g_return_if_fail (GLADE_IS_WIDGET_CLASS (parent_class));
if (GLADE_WIDGET_CLASS_FLAGS (widget_class) == 0)
widget_class->flags = parent_class->flags;
if (widget_class->post_create_function == NULL)
widget_class->post_create_function = parent_class->post_create_function;
tmp1 = widget_class->properties;
while (tmp1 != NULL)
{
GladePropertyClass *property_class = (GladePropertyClass*) tmp1->data;
g_debug (("%s from %s\n", property_class->id, widget_class->name));
tmp1 = g_list_next (tmp1);
}
tmp1 = parent_class->properties;
while (tmp1 != NULL)
{
GladePropertyClass *property_class = (GladePropertyClass*) tmp1->data;
g_debug (("%s from %s\n", property_class->id, parent_class->name));
tmp1 = g_list_next (tmp1);
}
last_property = g_list_last (widget_class->properties);
for (parent_properties = parent_class->properties; parent_properties != NULL; parent_properties = parent_properties->next)
{
GladePropertyClass *property_class = (GladePropertyClass*) parent_properties->data;
GList *list = g_list_append (last_property, glade_property_class_clone (property_class));
if (!last_property)
{
widget_class->properties = list;
last_property = list;
}
else
last_property = list->next;
}
tmp1 = widget_class->properties;
while (tmp1 != NULL)
{
GladePropertyClass *property_class = (GladePropertyClass*) tmp1->data;
g_debug (("Result %s\n", property_class->id));
tmp1 = g_list_next (tmp1);
}
}
/**
* glade_widget_class_remove_duplicated_properties:
* @widget_class: class of the widget that contains the properties.
*
* Takes the list of properties of the widget class, and removes the duplicated properties.
* The properties modified are prefered over the non modified ones, and the properties
* that appear first on the list are prefered over these that appear later on the list.
* (the first rule is more important than the second one).
**/
static void
glade_widget_class_remove_duplicated_properties (GladeWidgetClass *widget_class)
{
GHashTable *hash_properties = g_hash_table_new (g_str_hash, g_str_equal);
GList *properties_classes = widget_class->properties;
while (properties_classes != NULL)
{
GladePropertyClass *property_class = (GladePropertyClass*) properties_classes->data;
GList *old_property;
/* if it's the first time we see this property, then we add it to the list of
* properties that we will keep for this widget. Idem if the last time we saw
* this property, it was not modified, and this time the property is modified
* (ie, we change the non modified property by the modified one). */
if ((old_property = g_hash_table_lookup (hash_properties, property_class->id)) == NULL ||
(!((GladePropertyClass*) old_property->data)->is_modified && property_class->is_modified))
{
/* remove the old property */
if (old_property != NULL)
g_list_remove_link (widget_class->properties, old_property);
g_hash_table_insert (hash_properties, property_class->id, properties_classes);
properties_classes = g_list_next (properties_classes);
}
else
{
GList *tmp = properties_classes;
properties_classes = g_list_next (properties_classes);
g_list_remove_link (widget_class->properties, tmp);
}
}
g_hash_table_destroy (hash_properties);
}
/**
* glade_widget_class_new_from_name2:
* @name: name of the widget class (for instance: GtkButton)
* @generic_name: base of the name for the widgets of this class (for instance: button).
* This parameter is optional. For abstract classes there is no need to supply a generic_name.
* @base_filename: filename containing a further description of the widget, without
* the directory (optional).
*
* Creates a new GladeWidgetClass, initializing it with the
* name, generic_name and base_filename.
*
* The widget class will be first build using the information that the GLib object system
* returns, and then it will be expanded (optionally) with the information contained on
* the xml filename.
*
* Return Value: The new GladeWidgetClass, or %NULL if there are any errors.
**/
GladeWidgetClass *
glade_widget_class_new_from_name2 (const char *name, const char *generic_name, const char *base_filename)
{
GladeWidgetClass *widget_class = NULL;
char *filename = NULL;
char *init_function_name = NULL;
GType parent_type;
g_return_val_if_fail (name != NULL, NULL);
if (glade_widget_class_get_from_name (name) != NULL)
{
g_warning ("The widget class [%s] has at least two different definitions.\n", name);
goto lblError;
}
if (base_filename != NULL)
{
filename = g_strconcat (WIDGETS_DIR, "/", base_filename, NULL);
if (filename == NULL)
{
g_warning ("Not enough memory.");
goto lblError;
}
}
widget_class = glade_widget_class_new ();
if (widget_class == NULL)
{
g_warning ("Not enough memory.");
goto lblError;
}
widget_class->generic_name = generic_name ? g_strdup (generic_name) : NULL;
widget_class->name = g_strdup (name);
widget_class->in_palette = generic_name ? TRUE : FALSE;
/* we can't just call g_type_from_name (name) to get the type, because
* that only works for registered types, and the only way to register the
* type is to call foo_bar_get_type() */
init_function_name = glade_widget_class_compose_get_type_func (widget_class);
if (!init_function_name)
{
g_warning ("Not enough memory.");
goto lblError;
}
widget_class->type = glade_util_get_type_from_name (init_function_name);
if (widget_class->type == 0)
goto lblError;
widget_class->properties = glade_widget_class_list_properties (widget_class);
widget_class->signals = glade_widget_class_list_signals (widget_class);
/* is the widget a toplevel? TODO: We're going away from this flag, and
* just doing this test each time that we want to know if it's a toplevel */
if (g_type_is_a (widget_class->type, GTK_TYPE_WINDOW))
GLADE_WIDGET_CLASS_SET_FLAGS (widget_class, GLADE_TOPLEVEL);
/* is the widget a container? TODO: We're going away from this flag, and
* just doing this test each time that we want to know if it's a container */
if (g_type_is_a (widget_class->type, GTK_TYPE_CONTAINER))
GLADE_WIDGET_CLASS_SET_FLAGS (widget_class, GLADE_ADD_PLACEHOLDER);
widget_class->icon = glade_widget_class_create_icon (widget_class);
/* if there is an associated filename, then open and parse it */
if (filename != NULL)
glade_widget_class_extend_with_file (widget_class, filename);
glade_widget_class_add_virtual_methods (widget_class);
g_free (filename);
g_free (init_function_name);
for (parent_type = g_type_parent (widget_class->type);
parent_type != 0;
parent_type = g_type_parent (parent_type))
{
GladeWidgetClass *parent_class = glade_widget_class_get_from_name (g_type_name (parent_type));
if (parent_class != NULL)
glade_widget_class_merge (widget_class, parent_class);
}
/* remove the duplicate properties on widget_class */
glade_widget_class_remove_duplicated_properties (widget_class);
/* store the GladeWidgetClass on the cache */
glade_widget_class_store_with_name (widget_class);
return widget_class;
lblError:
g_free (filename);
g_free (init_function_name);
glade_widget_class_free (widget_class);
return NULL;
}
GladeWidgetClass *
glade_widget_class_new_from_name (const gchar *name)
{
@ -452,6 +779,61 @@ glade_widget_class_has_property (GladeWidgetClass *class, const gchar *name)
return FALSE;
}
/* ParamSpec stuff */
void
glade_widget_class_get_specs (GladeWidgetClass *class, GParamSpec ***specs, gint *n_specs)
{
GObjectClass *object_class;
GType type;
type = glade_widget_class_get_type (class);
g_type_class_ref (type); /* hmm */
/* We count on the fact we have an instance, or else we'd have
* touse g_type_class_ref ();
*/
object_class = g_type_class_peek (type);
if (object_class == NULL) {
g_warning ("Class peek failed\n");
*specs = NULL;
*n_specs = 0;
return;
}
*specs = g_object_class_list_properties (object_class, n_specs);
}
GParamSpec *
glade_widget_class_find_spec (GladeWidgetClass *class, const gchar *name)
{
GParamSpec **specs = NULL;
GParamSpec *spec;
gint n_specs = 0;
gint i;
glade_widget_class_get_specs (class, &specs, &n_specs);
for (i = 0; i < n_specs; i++) {
spec = specs[i];
if (!spec || !spec->name) {
g_warning ("Spec does not have a valid name, or invalid spec");
g_free (specs);
return NULL;
}
if (strcmp (spec->name, name) == 0) {
GParamSpec *return_me;
return_me = g_param_spec_ref (spec);
g_free (specs);
return return_me;
}
}
g_free (specs);
return NULL;
}
/**
* glade_widget_class_dump_param_specs:
* @class:

View File

@ -84,19 +84,24 @@ struct _GladeWidgetClassSignal
* eg GtkButton */
};
GladeWidgetClass *glade_widget_class_new_from_name (const gchar *name);
GladeWidgetClass *glade_widget_class_new_from_name (const char *name);
GladeWidgetClass *glade_widget_class_new_from_name2 (const char *name, const char *generic_name, const char *base_filename);
GladeWidgetClass *glade_widget_class_new_from_node (GladeXmlNode *node);
GladeWidgetClass *glade_widget_class_get_by_name (const gchar *name);
void glade_widget_class_free (GladeWidgetClass *widget_class);
GladeWidgetClass *glade_widget_class_get_by_name (const char *name);
const gchar *glade_widget_class_get_name (GladeWidgetClass *class);
GType glade_widget_class_get_type (GladeWidgetClass *class);
gboolean glade_widget_class_has_queries (GladeWidgetClass *class);
gboolean glade_widget_class_is (GladeWidgetClass *class, const gchar *name);
gboolean glade_widget_class_has_property (GladeWidgetClass *class, const gchar *name);
gboolean glade_widget_class_is (GladeWidgetClass *class, const char *name);
/* ParamSpec stuff */
void glade_widget_class_get_specs (GladeWidgetClass *class,
GParamSpec ***specs, gint *n_specs);
GParamSpec *glade_widget_class_find_spec (GladeWidgetClass *class, const gchar *name);
void glade_widget_class_dump_param_specs (GladeWidgetClass *class);
gboolean glade_widget_class_has_property (GladeWidgetClass *class, const gchar *name);
G_END_DECLS

View File

@ -48,7 +48,7 @@
* Allocates a new name for a specific GladeWidgetClass.
*
* Return Value: a newly allocated name for the widget. Caller must g_free it
*/
**/
gchar *
glade_widget_new_name (GladeProject *project, GladeWidgetClass *class)
{
@ -82,6 +82,14 @@ glade_widget_properties_from_list (GList *list, GladeWidget *widget)
return new_list;
}
/**
* glade_widget_new:
* @class: The GladeWidgeClass of the GladeWidget
*
* Allocates a new GladeWidget structure and fills in the required memebers.
*
* Return Value:
**/
static GladeWidget *
glade_widget_new (GladeWidgetClass *class)
{
@ -110,7 +118,7 @@ glade_widget_new (GladeWidgetClass *class)
*
* Return Value: a GladeWidget pointer for @widget, NULL if the widget does not
* have a GladeWidget counterpart.
*/
**/
GladeWidget *
glade_widget_get_from_gtk_widget (GtkWidget *widget)
{
@ -171,7 +179,7 @@ glade_widget_find_inside_container (GtkWidget *widget, gpointer data_in)
* clicked
*
* Return Value:
*/
**/
static GladeWidget *
glade_widget_get_from_event_widget (GtkWidget *event_widget, GdkEventButton *event)
{
@ -264,7 +272,7 @@ glade_widget_get_from_event_widget (GtkWidget *event_widget, GdkEventButton *eve
* Handle the button press event for every GladeWidget
*
* Return Value:
*/
**/
static gboolean
glade_widget_button_press (GtkWidget *event_widget,
GdkEventButton *event,
@ -340,10 +348,14 @@ glade_widget_set_default_options (GladeWidget *widget)
}
/**
* glade_widget_set_default_packing_options:
* @widget:
*
* We need to have a different function for setting packing options
* because we need to add the widget to the container before we
* apply the packing options.
*/
*
**/
void
glade_widget_set_default_packing_options (GladeWidget *widget)
{
@ -417,7 +429,7 @@ glade_widget_connect_keyboard_signals (GladeWidget *glade_widget)
* Loads the name of the widget. For example a button will have the
* "button1" text in it, or a label will have "label4". right after
* it is created.
*/
**/
void
glade_widget_set_contents (GladeWidget *widget)
{
@ -514,8 +526,6 @@ glade_widget_connect_other_signals (GladeWidget *widget)
static void
glade_widget_free (GladeWidget *widget)
{
GList *list;
widget->class = NULL;
widget->project = NULL;
widget->widget = NULL;
@ -525,42 +535,16 @@ glade_widget_free (GladeWidget *widget)
g_free (widget->name);
widget->name = NULL;
list = widget->properties;
for (; list; list = list->next)
glade_property_free (list->data);
widget->properties = NULL;
list = widget->packing_properties;
for (; list; list = list->next)
glade_property_free (list->data);
widget->properties = NULL;
list = widget->signals;
for (; list; list = list->next)
glade_signal_free (list->data);
widget->signals = NULL;
g_list_foreach(widget->properties, (GFunc) glade_property_free, NULL);
g_list_free (widget->properties);
g_list_foreach(widget->packing_properties, (GFunc) glade_property_free, NULL);
g_list_free (widget->packing_properties);
g_list_foreach(widget->signals, (GFunc) glade_signal_free, NULL);
g_list_free (widget->signals);
g_free (widget);
}
#if 0
/* Sigh.
* Fix, Fix, fix. Turn this off to see why this is here.
* Add a gtkwindow and a gtkvbox to reproduce
* Some werid redraw problems that i can't figure out.
* Chema
*/
static gint
glade_widget_ugly_hack (gpointer data)
{
GladeWidget *widget = data;
gtk_widget_queue_resize (widget->widget);
return FALSE;
}
#endif
static GtkWidget *
glade_widget_create_gtk_widget (GladeWidgetClass *class)
{
@ -764,7 +748,7 @@ glade_widget_query_properties_set (gpointer key_,
* of columns he wants.
*
* Return Value: FALSE if the query was canceled
*/
**/
gboolean
glade_widget_query_properties (GladeWidgetClass *class,
GladePropertyQueryResult *result)
@ -874,7 +858,7 @@ glade_widget_apply_queried_properties (GladeWidget *widget,
* if needed.
*
* Return Value: A newly creatred GladeWidget, NULL on user cancel or error
*/
**/
GladeWidget *
glade_widget_new_from_class (GladeWidgetClass *class,
GladeProject *project,
@ -924,11 +908,13 @@ glade_widget_get_class (GladeWidget *widget)
* glade_widget_get_property_from_list:
* @list: The list of GladeProperty
* @class: The Class that we are trying to match with GladeProperty
* @silent: True if we shuold warn when a property is not included in the list
* @silent: True if we should warn when a property is not included in the list
*
* Given a list of GladeProperties find the one that has ->class = to @class.
* Give a list of GladeProperties find the one that has ->class = to @class.
* This function recurses into child objects if needed.
*/
*
* Return Value:
**/
static GladeProperty *
glade_widget_get_property_from_list (GList *list,
GladePropertyClass *class,
@ -970,7 +956,7 @@ glade_widget_get_property_from_list (GList *list,
* Given a glade Widget, it returns the property that correspons to @property_class
*
* Return Value:
*/
**/
GladeProperty *
glade_widget_get_property_from_class (GladeWidget *widget,
GladePropertyClass *property_class)
@ -998,7 +984,7 @@ glade_widget_get_property_from_class (GladeWidget *widget,
* @name:
*
* Sets the name of a widget
*/
**/
void
glade_widget_set_name (GladeWidget *widget, const gchar *name)
{
@ -1092,7 +1078,7 @@ glade_widget_find_signal (GladeWidget *widget, GladeSignal *signal)
* @signal
*
* Add @signal to the widget's signal list.
*/
**/
void
glade_widget_add_signal (GladeWidget *widget, GladeSignal *signal)
{
@ -1117,7 +1103,7 @@ glade_widget_add_signal (GladeWidget *widget, GladeSignal *signal)
* @signal
*
* Remove @signal from the widget's signal list.
*/
**/
void
glade_widget_remove_signal (GladeWidget *widget, GladeSignal *signal)
{
@ -1214,7 +1200,8 @@ glade_widget_write (GladeXmlContext *context, GladeWidget *widget)
glade_xml_node_append_child (packing, packing_property);
glade_xml_node_append_child (child_tag, packing);
}
} else {
}
else {
/* a placeholder */
child = glade_xml_node_new (context, GLADE_XML_TAG_PLACEHOLDER);
glade_xml_node_append_child (child_tag, child);

View File

@ -14,7 +14,7 @@ typedef struct _GladeXmlDoc GladeXmlDoc;
/* search child */
GladeXmlNode * glade_xml_search_child (GladeXmlNode * node, const char *name);
GladeXmlNode * glade_xml_search_child_required (GladeXmlNode * tree, const gchar* name);
GladeXmlNode * glade_xml_search_child_required (GladeXmlNode * tree, const char* name);
/* content */