1 /*
2 * Copyright (C) 2008 Tristan Van Berkom.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * Authors:
19 * Tristan Van Berkom <tvb@gnome.org>
20 */
21
22 #include <config.h>
23 #include <glib/gi18n-lib.h>
24 #include "glade.h"
25 #include "gladeui-enum-types.h"
26
27 #include "glade-editor-table.h"
28
29
30 #define BLOCK_NAME_ENTRY_CB(table) \
31 do { if (table->priv->name_entry) \
32 g_signal_handlers_block_by_func (G_OBJECT (table->priv->name_entry), \
33 G_CALLBACK (widget_name_edited), table); \
34 } while (0);
35
36 #define UNBLOCK_NAME_ENTRY_CB(table) \
37 do { if (table->priv->name_entry) \
38 g_signal_handlers_unblock_by_func (G_OBJECT (table->priv->name_entry), \
39 G_CALLBACK (widget_name_edited), table); \
40 } while (0);
41
42
43
44 static void glade_editor_table_init (GladeEditorTable * self);
45 static void glade_editor_table_class_init (GladeEditorTableClass * klass);
46
47 static void glade_editor_table_dispose (GObject *object);
48 static void glade_editor_table_set_property (GObject *object,
49 guint prop_id,
50 const GValue *value,
51 GParamSpec *pspec);
52
53 static void glade_editor_table_editable_init (GladeEditableIface * iface);
54 static void glade_editor_table_realize (GtkWidget * widget);
55 static void glade_editor_table_grab_focus (GtkWidget * widget);
56
57 static void append_name_field (GladeEditorTable *table);
58 static void append_items (GladeEditorTable *table,
59 GladeWidgetAdaptor *adaptor,
60 GladeEditorPageType type);
61
62
63 struct _GladeEditorTablePrivate
64 {
65 GladeWidgetAdaptor *adaptor; /* The GladeWidgetAdaptor this
66 * table was created for.
67 */
68
69 GladeWidget *loaded_widget; /* A pointer to the currently loaded GladeWidget
70 */
71
72 GtkWidget *name_label; /* A pointer to the "Name:" label (for show/hide) */
73 GtkWidget *name_entry; /* A pointer to the gtk_entry that holds
74 * the name of the widget. This is the
75 * first item _pack'ed to the table_widget.
76 * We have a pointer here because it is an
77 * entry which will not be created from a
78 * GladeProperty but rather from code.
79 */
80 GtkWidget *composite_check; /* A pointer to the composite check button */
81 GtkWidget *name_field; /* A box containing the name entry and composite check */
82
83 GList *properties; /* A list of GladeEditorPropery items.
84 * For each row in the gtk_table, there is a
85 * corrsponding GladeEditorProperty struct.
86 */
87
88 GladeEditorPageType type; /* Is this table to be used in the common tab, ?
89 * the general tab, a packing tab or the query popup ?
90 */
91
92 gint rows;
93
94 gboolean show_name;
95 };
96
97 enum {
98 PROP_0,
99 PROP_PAGE_TYPE,
100 };
101
102 G_DEFINE_TYPE_WITH_CODE (GladeEditorTable, glade_editor_table, GTK_TYPE_GRID,
103 G_ADD_PRIVATE (GladeEditorTable)
104 G_IMPLEMENT_INTERFACE (GLADE_TYPE_EDITABLE,
105 glade_editor_table_editable_init));
106
107 static void
glade_editor_table_class_init(GladeEditorTableClass * klass)108 glade_editor_table_class_init (GladeEditorTableClass *klass)
109 {
110 GObjectClass *object_class = G_OBJECT_CLASS (klass);
111 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
112
113 object_class->dispose = glade_editor_table_dispose;
114 object_class->set_property = glade_editor_table_set_property;
115
116 widget_class->realize = glade_editor_table_realize;
117 widget_class->grab_focus = glade_editor_table_grab_focus;
118
119 g_object_class_install_property
120 (object_class, PROP_PAGE_TYPE,
121 g_param_spec_enum ("page-type", _("Page Type"),
122 _("The editor page type to create this GladeEditorTable for"),
123 GLADE_TYPE_EDITOR_PAGE_TYPE, GLADE_PAGE_GENERAL,
124 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
125 }
126
127 static void
glade_editor_table_init(GladeEditorTable * self)128 glade_editor_table_init (GladeEditorTable *self)
129 {
130 self->priv = glade_editor_table_get_instance_private (self);
131
132 gtk_orientable_set_orientation (GTK_ORIENTABLE (self),
133 GTK_ORIENTATION_VERTICAL);
134 gtk_grid_set_row_spacing (GTK_GRID (self), 2);
135 gtk_grid_set_column_spacing (GTK_GRID (self), 6);
136
137 /* Show name by default */
138 self->priv->show_name = TRUE;
139 }
140
141 static void
glade_editor_table_dispose(GObject * object)142 glade_editor_table_dispose (GObject *object)
143 {
144 GladeEditorTable *table = GLADE_EDITOR_TABLE (object);
145
146 table->priv->properties = (g_list_free (table->priv->properties), NULL);
147
148 /* the entry is finalized anyway, just avoid setting
149 * text in it from _load();
150 */
151 table->priv->name_entry = NULL;
152
153 glade_editable_load (GLADE_EDITABLE (table), NULL);
154
155 G_OBJECT_CLASS (glade_editor_table_parent_class)->dispose (object);
156 }
157
158 static void
glade_editor_table_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)159 glade_editor_table_set_property (GObject *object,
160 guint prop_id,
161 const GValue *value,
162 GParamSpec *pspec)
163 {
164 GladeEditorTable *table = GLADE_EDITOR_TABLE (object);
165
166 switch (prop_id)
167 {
168 case PROP_PAGE_TYPE:
169 table->priv->type = g_value_get_enum (value);
170 break;
171 default:
172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
173 break;
174 }
175 }
176
177 static void
glade_editor_table_realize(GtkWidget * widget)178 glade_editor_table_realize (GtkWidget *widget)
179 {
180 GladeEditorTable *table = GLADE_EDITOR_TABLE (widget);
181 GList *list;
182 GladeEditorProperty *property;
183
184 GTK_WIDGET_CLASS (glade_editor_table_parent_class)->realize (widget);
185
186 /* Sync up properties, even if widget is NULL */
187 for (list = table->priv->properties; list; list = list->next)
188 {
189 property = list->data;
190 glade_editor_property_load_by_widget (property, table->priv->loaded_widget);
191 }
192 }
193
194 static void
glade_editor_table_grab_focus(GtkWidget * widget)195 glade_editor_table_grab_focus (GtkWidget *widget)
196 {
197 GladeEditorTable *editor_table = GLADE_EDITOR_TABLE (widget);
198
199 if (editor_table->priv->name_entry &&
200 gtk_widget_get_mapped (editor_table->priv->name_entry))
201 gtk_widget_grab_focus (editor_table->priv->name_entry);
202 else if (editor_table->priv->properties)
203 gtk_widget_grab_focus (GTK_WIDGET (editor_table->priv->properties->data));
204 else
205 GTK_WIDGET_CLASS (glade_editor_table_parent_class)->grab_focus (widget);
206 }
207
208 static void
widget_name_edited(GtkWidget * editable,GladeEditorTable * table)209 widget_name_edited (GtkWidget *editable, GladeEditorTable *table)
210 {
211 GladeWidget *widget;
212 gchar *new_name;
213
214 g_return_if_fail (GTK_IS_EDITABLE (editable));
215 g_return_if_fail (GLADE_IS_EDITOR_TABLE (table));
216
217 if (table->priv->loaded_widget == NULL)
218 {
219 g_warning ("Name entry edited with no loaded widget in editor %p!\n",
220 table);
221 return;
222 }
223
224 widget = table->priv->loaded_widget;
225 new_name = gtk_editable_get_chars (GTK_EDITABLE (editable), 0, -1);
226
227 if (new_name == NULL || new_name[0] == '\0')
228 {
229 /* If we are explicitly trying to set the widget name to be empty,
230 * then we must not allow it there are any active references to
231 * the widget which would otherwise break.
232 *
233 * Otherwise, we need to allocate a new unnamed prefix name for the widget
234 */
235 if (!glade_widget_has_prop_refs (widget))
236 {
237 gchar *unnamed_name = glade_project_new_widget_name (glade_widget_get_project (widget), NULL, GLADE_UNNAMED_PREFIX);
238 glade_command_set_name (widget, unnamed_name);
239 g_free (unnamed_name);
240 }
241 }
242 else if (glade_project_available_widget_name (glade_widget_get_project (widget),
243 widget, new_name))
244 glade_command_set_name (widget, new_name);
245
246 g_free (new_name);
247 }
248
249 static void
widget_composite_toggled(GtkToggleButton * composite_check,GladeEditorTable * table)250 widget_composite_toggled (GtkToggleButton *composite_check,
251 GladeEditorTable *table)
252 {
253 GladeProject *project;
254
255 if (table->priv->loaded_widget == NULL)
256 {
257 g_warning ("Name entry edited with no loaded widget in editor %p!\n",
258 table);
259 return;
260 }
261
262 project = glade_widget_get_project (table->priv->loaded_widget);
263
264 if (project)
265 {
266 if (gtk_toggle_button_get_active (composite_check))
267 glade_command_set_project_template (project, table->priv->loaded_widget);
268 else
269 glade_command_set_project_template (project, NULL);
270 }
271 }
272
273 static void
widget_name_changed(GladeWidget * widget,GParamSpec * pspec,GladeEditorTable * table)274 widget_name_changed (GladeWidget *widget,
275 GParamSpec *pspec,
276 GladeEditorTable *table)
277 {
278 if (!gtk_widget_get_mapped (GTK_WIDGET (table)))
279 return;
280
281 if (table->priv->name_entry)
282 {
283 BLOCK_NAME_ENTRY_CB (table);
284
285 if (glade_widget_has_name (table->priv->loaded_widget))
286 gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), glade_widget_get_name (table->priv->loaded_widget));
287 else
288 gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), "");
289
290 UNBLOCK_NAME_ENTRY_CB (table);
291 }
292 }
293
294 static void
widget_composite_changed(GladeWidget * widget,GParamSpec * pspec,GladeEditorTable * table)295 widget_composite_changed (GladeWidget *widget,
296 GParamSpec *pspec,
297 GladeEditorTable *table)
298 {
299 if (!gtk_widget_get_mapped (GTK_WIDGET (table)))
300 return;
301
302 if (table->priv->name_label)
303 gtk_label_set_text (GTK_LABEL (table->priv->name_label),
304 glade_widget_get_is_composite (table->priv->loaded_widget) ?
305 _("Class Name:") : _("ID:"));
306
307 if (table->priv->composite_check)
308 {
309 g_signal_handlers_block_by_func (G_OBJECT (table->priv->composite_check),
310 G_CALLBACK (widget_composite_toggled), table);
311 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (table->priv->composite_check),
312 glade_widget_get_is_composite (table->priv->loaded_widget));
313 g_signal_handlers_unblock_by_func (G_OBJECT (table->priv->composite_check),
314 G_CALLBACK (widget_composite_toggled), table);
315 }
316 }
317
318 static void
widget_finalized(GladeEditorTable * table,GladeWidget * where_widget_was)319 widget_finalized (GladeEditorTable *table, GladeWidget *where_widget_was)
320 {
321 table->priv->loaded_widget = NULL;
322
323 glade_editable_load (GLADE_EDITABLE (table), NULL);
324 }
325
326
327 static void
glade_editor_table_load(GladeEditable * editable,GladeWidget * widget)328 glade_editor_table_load (GladeEditable *editable, GladeWidget *widget)
329 {
330 GladeEditorTable *table = GLADE_EDITOR_TABLE (editable);
331 GladeEditorProperty *property;
332 GList *list;
333
334 /* Setup the table the first time the widget is loaded */
335 if (widget && table->priv->adaptor == NULL)
336 {
337 table->priv->adaptor = glade_widget_get_adaptor (widget);
338
339 if (table->priv->type == GLADE_PAGE_GENERAL)
340 append_name_field (table);
341
342 append_items (table, table->priv->adaptor, table->priv->type);
343 }
344
345 /* abort mission */
346 if (table->priv->loaded_widget == widget)
347 return;
348
349 if (table->priv->loaded_widget)
350 {
351 g_signal_handlers_disconnect_by_func (G_OBJECT (table->priv->loaded_widget),
352 G_CALLBACK (widget_name_changed),
353 table);
354 g_signal_handlers_disconnect_by_func (G_OBJECT (table->priv->loaded_widget),
355 G_CALLBACK (widget_composite_changed),
356 table);
357
358 /* The widget could die unexpectedly... */
359 g_object_weak_unref (G_OBJECT (table->priv->loaded_widget),
360 (GWeakNotify) widget_finalized, table);
361 }
362
363 table->priv->loaded_widget = widget;
364
365 BLOCK_NAME_ENTRY_CB (table);
366
367 if (table->priv->loaded_widget)
368 {
369 g_signal_connect (G_OBJECT (table->priv->loaded_widget), "notify::name",
370 G_CALLBACK (widget_name_changed), table);
371
372 g_signal_connect (G_OBJECT (table->priv->loaded_widget), "notify::composite",
373 G_CALLBACK (widget_composite_changed), table);
374
375 /* The widget could die unexpectedly... */
376 g_object_weak_ref (G_OBJECT (table->priv->loaded_widget),
377 (GWeakNotify) widget_finalized, table);
378
379 if (table->priv->composite_check)
380 {
381 GObject *object = glade_widget_get_object (table->priv->loaded_widget);
382
383 if (GTK_IS_WIDGET (object) &&
384 glade_widget_get_parent (table->priv->loaded_widget) == NULL)
385 gtk_widget_show (table->priv->composite_check);
386 else
387 gtk_widget_hide (table->priv->composite_check);
388 }
389
390 if (table->priv->name_entry)
391 {
392 if (glade_widget_has_name (widget))
393 gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), glade_widget_get_name (widget));
394 else
395 gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), "");
396 }
397
398 if (table->priv->name_label)
399 widget_composite_changed (widget, NULL, table);
400 }
401 else if (table->priv->name_entry)
402 gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), "");
403
404 UNBLOCK_NAME_ENTRY_CB (table);
405
406 /* Sync up properties, even if widget is NULL */
407 for (list = table->priv->properties; list; list = list->next)
408 {
409 property = list->data;
410 glade_editor_property_load_by_widget (property, widget);
411 }
412 }
413
414 static void
glade_editor_table_set_show_name(GladeEditable * editable,gboolean show_name)415 glade_editor_table_set_show_name (GladeEditable *editable, gboolean show_name)
416 {
417 GladeEditorTable *table = GLADE_EDITOR_TABLE (editable);
418
419 if (table->priv->show_name != show_name)
420 {
421 table->priv->show_name = show_name;
422
423 if (table->priv->name_label)
424 {
425 gtk_widget_set_visible (table->priv->name_label, show_name);
426 gtk_widget_set_visible (table->priv->name_field, show_name);
427 }
428 }
429 }
430
431 static void
glade_editor_table_editable_init(GladeEditableIface * iface)432 glade_editor_table_editable_init (GladeEditableIface *iface)
433 {
434 iface->load = glade_editor_table_load;
435 iface->set_show_name = glade_editor_table_set_show_name;
436 }
437
438 static void
glade_editor_table_attach(GladeEditorTable * table,GtkWidget * child,gint pos,gint row)439 glade_editor_table_attach (GladeEditorTable * table,
440 GtkWidget * child, gint pos, gint row)
441 {
442 gtk_grid_attach (GTK_GRID (table), child, pos, row, 1, 1);
443
444 if (pos)
445 gtk_widget_set_hexpand (child, TRUE);
446 }
447
448 static gint
property_class_comp(gconstpointer a,gconstpointer b)449 property_class_comp (gconstpointer a, gconstpointer b)
450 {
451 GladePropertyClass *ca = (GladePropertyClass *)a, *cb = (GladePropertyClass *)b;
452 GParamSpec *pa, *pb;
453 const gchar *name_a, *name_b;
454
455 pa = glade_property_class_get_pspec (ca);
456 pb = glade_property_class_get_pspec (cb);
457
458 name_a = glade_property_class_id (ca);
459 name_b = glade_property_class_id (cb);
460
461 /* Special case for the 'name' property, it *always* comes first. */
462 if (strcmp (name_a, "name") == 0)
463 return -1;
464 else if (strcmp (name_b, "name") == 0)
465 return 1;
466 /* Properties of the same class are sorted in the same level */
467 else if (pa->owner_type == pb->owner_type)
468 {
469 gdouble result = glade_property_class_weight (ca) - glade_property_class_weight (cb);
470 /* Avoid cast to int */
471 if (result < 0.0)
472 return -1;
473 else if (result > 0.0)
474 return 1;
475 else
476 return 0;
477 }
478 /* Group properties by thier class hierarchy */
479 else
480 {
481 if (g_type_is_a (pa->owner_type, pb->owner_type))
482 return (glade_property_class_common (ca) || glade_property_class_get_is_packing (ca)) ? 1 : -1;
483 else
484 return (glade_property_class_common (ca) || glade_property_class_get_is_packing (ca)) ? -1 : 1;
485 }
486 }
487
488 static GList *
get_sorted_properties(GladeWidgetAdaptor * adaptor,GladeEditorPageType type)489 get_sorted_properties (GladeWidgetAdaptor *adaptor, GladeEditorPageType type)
490 {
491 const GList *l, *properties;
492 GList *list = NULL;
493
494 properties =
495 (type == GLADE_PAGE_PACKING) ?
496 glade_widget_adaptor_get_packing_props (adaptor) :
497 glade_widget_adaptor_get_properties (adaptor);
498
499 for (l = properties; l; l = g_list_next (l))
500 {
501 GladePropertyClass *klass = l->data;
502
503 /* Collect properties in our domain, query dialogs are allowed editor
504 * invisible (or custom-layout) properties, allow adaptors to filter
505 * out properties from the GladeEditorTable using the "custom-layout" attribute.
506 */
507 if (GLADE_PROPERTY_CLASS_IS_TYPE (klass, type) &&
508 (type == GLADE_PAGE_QUERY ||
509 (!glade_property_class_custom_layout (klass) &&
510 glade_property_class_is_visible (klass))))
511 {
512 list = g_list_prepend (list, klass);
513 }
514
515 }
516 return g_list_sort (list, property_class_comp);
517 }
518
519 static GladeEditorProperty *
append_item(GladeEditorTable * table,GladePropertyClass * klass,gboolean from_query_dialog)520 append_item (GladeEditorTable *table,
521 GladePropertyClass *klass,
522 gboolean from_query_dialog)
523 {
524 GladeEditorProperty *property;
525 GtkWidget *label;
526
527 if (!(property = glade_widget_adaptor_create_eprop
528 (glade_property_class_get_adaptor (klass), klass, from_query_dialog == FALSE)))
529 {
530 g_critical ("Unable to create editor for property '%s' of class '%s'",
531 glade_property_class_id (klass),
532 glade_widget_adaptor_get_name (glade_property_class_get_adaptor (klass)));
533 return NULL;
534 }
535
536 gtk_widget_show (GTK_WIDGET (property));
537 gtk_widget_show_all (glade_editor_property_get_item_label (property));
538
539 label = glade_editor_property_get_item_label (property);
540 gtk_widget_set_hexpand (label, FALSE);
541
542 glade_editor_table_attach (table, label, 0, table->priv->rows);
543 glade_editor_table_attach (table, GTK_WIDGET (property), 1, table->priv->rows);
544
545 table->priv->rows++;
546
547 return property;
548 }
549
550 static void
append_items(GladeEditorTable * table,GladeWidgetAdaptor * adaptor,GladeEditorPageType type)551 append_items (GladeEditorTable *table,
552 GladeWidgetAdaptor *adaptor,
553 GladeEditorPageType type)
554 {
555 GladeEditorProperty *property;
556 GladePropertyClass *property_class;
557 GList *list, *sorted_list;
558
559 sorted_list = get_sorted_properties (adaptor, type);
560 for (list = sorted_list; list != NULL; list = list->next)
561 {
562 property_class = (GladePropertyClass *) list->data;
563
564 property = append_item (table, property_class, type == GLADE_PAGE_QUERY);
565 table->priv->properties = g_list_prepend (table->priv->properties, property);
566 }
567 g_list_free (sorted_list);
568
569 table->priv->properties = g_list_reverse (table->priv->properties);
570 }
571
572 static void
append_name_field(GladeEditorTable * table)573 append_name_field (GladeEditorTable *table)
574 {
575 gchar *text = _("The object's unique identifier");
576
577 /* translators: The unique identifier of an object in the project */
578 table->priv->name_label = gtk_label_new (_("ID:"));
579 gtk_widget_set_halign (table->priv->name_label, GTK_ALIGN_START);
580 gtk_widget_show (table->priv->name_label);
581 gtk_widget_set_no_show_all (table->priv->name_label, TRUE);
582
583 table->priv->name_field = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
584 gtk_widget_set_no_show_all (table->priv->name_field, TRUE);
585 gtk_widget_show (table->priv->name_field);
586
587 table->priv->composite_check = gtk_check_button_new_with_label (_("Composite"));
588 gtk_widget_set_hexpand (table->priv->composite_check, FALSE);
589 gtk_widget_set_tooltip_text (table->priv->composite_check, _("Whether this widget is a composite template"));
590 gtk_widget_set_no_show_all (table->priv->composite_check, TRUE);
591
592 table->priv->name_entry = gtk_entry_new ();
593 gtk_widget_show (table->priv->name_entry);
594
595 gtk_widget_set_tooltip_text (table->priv->name_label, text);
596 gtk_widget_set_tooltip_text (table->priv->name_entry, text);
597
598 g_signal_connect (G_OBJECT (table->priv->name_entry), "activate",
599 G_CALLBACK (widget_name_edited), table);
600 g_signal_connect (G_OBJECT (table->priv->name_entry), "changed",
601 G_CALLBACK (widget_name_edited), table);
602 g_signal_connect (G_OBJECT (table->priv->composite_check), "toggled",
603 G_CALLBACK (widget_composite_toggled), table);
604
605 gtk_box_pack_start (GTK_BOX (table->priv->name_field), table->priv->name_entry, TRUE, TRUE, 0);
606 gtk_box_pack_start (GTK_BOX (table->priv->name_field), table->priv->composite_check, FALSE, FALSE, 0);
607
608 glade_editor_table_attach (table, table->priv->name_label, 0, table->priv->rows);
609 glade_editor_table_attach (table, table->priv->name_field, 1, table->priv->rows);
610
611 /* Set initial visiblity */
612 gtk_widget_set_visible (table->priv->name_label, table->priv->show_name);
613 gtk_widget_set_visible (table->priv->name_field, table->priv->show_name);
614
615 table->priv->rows++;
616 }
617
618 /**
619 * glade_editor_table_new:
620 * @adaptor: A #GladeWidgetAdaptor
621 * @type: The #GladeEditorPageType
622 *
623 * Creates a new #GladeEditorTable.
624 *
625 * Returns: a new #GladeEditorTable
626 *
627 */
628 GtkWidget *
glade_editor_table_new(GladeWidgetAdaptor * adaptor,GladeEditorPageType type)629 glade_editor_table_new (GladeWidgetAdaptor *adaptor, GladeEditorPageType type)
630 {
631 GladeEditorTable *table;
632
633 g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
634
635 table = g_object_new (GLADE_TYPE_EDITOR_TABLE, "page-type", type, NULL);
636 table->priv->adaptor = adaptor;
637
638 if (table->priv->type == GLADE_PAGE_GENERAL)
639 append_name_field (table);
640
641 append_items (table, table->priv->adaptor, table->priv->type);
642
643 return (GtkWidget *)table;
644 }
645