3
* Copyright (C) 2004 Vivien Malerba
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22
#include "mg-work-layout.h"
23
#include "mg-work-widget.h"
24
#include "mg-custom-layout.h"
25
#include "mg-referer.h"
26
#include "mg-target.h"
27
#include "mg-db-table.h"
28
#include "mg-work-grid.h"
29
#include "mg-work-form.h"
30
#include "mg-work-matrix.h"
31
#include "mg-qfield.h"
33
static void mg_work_layout_class_init (MgWorkLayoutClass * class);
34
static void mg_work_layout_init (MgWorkLayout * wid);
35
static void mg_work_layout_dispose (GObject * object);
37
static void mg_work_layout_set_property (GObject *object,
41
static void mg_work_layout_get_property (GObject *object,
46
static void mg_work_layout_initialize (MgWorkLayout *form);
48
static void nullified_custom_layout_cb (MgCustomLayout *layout, MgWorkLayout *form);
50
/* MgWorkWidget interface */
51
static void mg_work_layout_widget_init (MgWorkWidgetIface *iface);
52
static void mg_work_layout_run (MgWorkWidget *iface, guint mode);
53
static void mg_work_layout_show_global_actions (MgWorkWidget *iface, gboolean show_actions);
54
static MgParameter *mg_work_layout_get_param_for_field (MgWorkWidget *iface, MgQfield *field, const gchar *field_name,
55
gboolean in_exec_context);
56
static MgContext *mg_work_layout_get_exec_context (MgWorkWidget *iface);
58
struct _MgWorkLayoutPrivate {
59
MgCustomLayout *layout;
62
MgContext *exec_context; /* garbage of parameters not dependant on each others */
65
GSList *work_widgets; /* list of MgWorkLayout widgets */
68
GladeXML *glade_instance;
71
/* get a pointer to the parents to be able to call their destructor */
72
static GObjectClass *parent_class = NULL;
81
mg_work_layout_get_type (void)
83
static GType type = 0;
86
static const GTypeInfo info = {
87
sizeof (MgWorkLayoutClass),
89
(GBaseFinalizeFunc) NULL,
90
(GClassInitFunc) mg_work_layout_class_init,
93
sizeof (MgWorkLayout),
95
(GInstanceInitFunc) mg_work_layout_init
98
static const GInterfaceInfo work_widget_info = {
99
(GInterfaceInitFunc) mg_work_layout_widget_init,
104
type = g_type_register_static (GTK_TYPE_VBOX, "MgWorkLayout", &info, 0);
105
g_type_add_interface_static (type, MG_WORK_WIDGET_TYPE, &work_widget_info);
112
mg_work_layout_widget_init (MgWorkWidgetIface *iface)
114
iface->run = mg_work_layout_run;
115
iface->set_mode = NULL;
116
iface->set_entry_editable = NULL;
117
iface->show_entry_actions = NULL;
118
iface->show_global_actions = mg_work_layout_show_global_actions;
119
iface->get_param_for_field = mg_work_layout_get_param_for_field;
120
iface->has_been_changed = NULL;
121
iface->get_exec_context = mg_work_layout_get_exec_context;
122
iface->get_actions_group = NULL;
127
mg_work_layout_class_init (MgWorkLayoutClass * class)
129
GObjectClass *object_class = G_OBJECT_CLASS (class);
131
parent_class = g_type_class_peek_parent (class);
132
object_class->dispose = mg_work_layout_dispose;
135
object_class->set_property = mg_work_layout_set_property;
136
object_class->get_property = mg_work_layout_get_property;
140
mg_work_layout_init (MgWorkLayout * wid)
142
wid->priv = g_new0 (MgWorkLayoutPrivate, 1);
147
* @layout: a #MgWorkLayout object
149
* Creates a new #MgWorkLayout widget.
151
* Returns: the new widget
154
mg_work_layout_new (MgCustomLayout *layout)
159
g_return_val_if_fail (layout && IS_MG_CUSTOM_LAYOUT (layout), NULL);
161
obj = g_object_new (MG_WORK_LAYOUT_TYPE, NULL);
162
wl = MG_WORK_LAYOUT (obj);
164
wl->priv->layout = layout;
165
g_object_ref (layout);
166
g_signal_connect (G_OBJECT (wl->priv->layout), "nullified",
167
G_CALLBACK (nullified_custom_layout_cb), wl);
169
mg_work_layout_initialize (wl);
171
return GTK_WIDGET (obj);
175
nullified_custom_layout_cb (MgCustomLayout *layout, MgWorkLayout *wl)
177
g_signal_handlers_disconnect_by_func (G_OBJECT (layout),
178
G_CALLBACK (nullified_custom_layout_cb), wl);
180
g_object_unref (G_OBJECT (wl->priv->layout));
181
wl->priv->layout = NULL;
185
mg_work_layout_dispose (GObject *object)
189
g_return_if_fail (object != NULL);
190
g_return_if_fail (IS_MG_WORK_LAYOUT (object));
191
wl = MG_WORK_LAYOUT (object);
195
if (wl->priv->layout)
196
nullified_custom_layout_cb (wl->priv->layout, wl);
198
if (wl->priv->exec_context)
199
g_object_unref (wl->priv->exec_context);
201
g_slist_free (wl->priv->work_widgets);
203
if (wl->priv->glade_instance)
204
g_object_unref (wl->priv->glade_instance);
206
/* the private area itself */
211
/* for the parent class */
212
parent_class->dispose (object);
216
mg_work_layout_set_property (GObject *object,
223
wl = MG_WORK_LAYOUT (object);
227
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
234
mg_work_layout_get_property (GObject *object,
241
wl = MG_WORK_LAYOUT (object);
245
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
254
* Real initialization
256
static void init_work_form_grid (MgWorkLayout *wl);
257
static void init_work_matrix (MgWorkLayout *wl);
258
static void init_super_layout (MgWorkLayout *wl);
260
mg_work_layout_initialize (MgWorkLayout *wl)
262
if (! mg_referer_activate (MG_REFERER (wl->priv->layout))) {
263
GtkWidget *wid = gtk_label_new (_("missing required objects!"));
264
gtk_box_pack_start (GTK_BOX (wl), wid, TRUE, TRUE, 0);
265
gtk_widget_show (wid);
268
switch (mg_custom_layout_get_layout_type (wl->priv->layout)) {
269
case MG_CUSTOM_LAYOUT_LAYOUT:
270
init_super_layout (wl);
272
case MG_CUSTOM_LAYOUT_GRID:
273
case MG_CUSTOM_LAYOUT_FORM:
274
init_work_form_grid (wl);
276
case MG_CUSTOM_LAYOUT_MATRIX:
277
init_work_matrix (wl);
284
init_work_form_grid (MgWorkLayout *wl)
286
GtkWidget *wid, *root;
287
MgCustomLayout *cl = wl->priv->layout;
289
GHashTable *hash = NULL;
290
GError *error = NULL;
291
MgCustomLayoutData *cldata;
292
MgTarget *target = NULL;
293
gboolean err = FALSE;
295
glade = mg_custom_layout_get_glade_instance (cl, &root, &hash, &error);
296
wl->priv->glade_instance = glade;
298
g_warning ("Error building GladeXML file: %s", error->message);
299
g_error_free (error);
303
cldata = mg_custom_layout_get_data (cl, &error);
305
g_warning ("Error using MgCustomLayout: %s", error->message);
306
g_error_free (error);
311
if (!cldata->contents.work_iface.query ||
312
! mg_query_is_select_query (cldata->contents.work_iface.query))
316
target = (MgTarget *) cldata->contents.work_iface.modified;
317
if (!IS_MG_TARGET (target) ||
318
(mg_target_get_query (target) != cldata->contents.work_iface.query))
323
/* actual widget creation */
324
if (cldata->type == MG_CUSTOM_LAYOUT_GRID)
325
wid = mg_work_grid_new (cldata->contents.work_iface.query, target);
327
wid = mg_work_form_new_in_layout (cldata->contents.work_iface.query, target, root, hash);
328
wl->priv->work_widgets = g_slist_prepend (wl->priv->work_widgets, wid);
329
mg_work_widget_set_mode (MG_WORK_WIDGET (wid), cldata->contents.work_iface.mode);
330
g_object_set (G_OBJECT (wid), "title_visible", FALSE, NULL);
333
wid = gtk_label_new (_("Error creating widget"));
335
gtk_box_pack_start (GTK_BOX (wl), wid, TRUE, TRUE, 0);
336
gtk_widget_show (wid);
338
g_hash_table_destroy (hash);
343
init_work_matrix (MgWorkLayout *wl)
346
MgConf *conf = mg_base_get_conf (MG_BASE (wl->priv->layout));
347
MgCustomLayout *cl = wl->priv->layout;
348
MgCustomLayoutData *cldata;
351
gboolean err = FALSE;
352
GError *error = NULL;
354
cldata = mg_custom_layout_get_data (cl, &error);
356
g_warning ("Error using MgCustomLayout: %s", error->message);
357
g_error_free (error);
363
table = (MgDbTable *) cldata->contents.work_iface.modified;
364
if (!IS_MG_DB_TABLE (table))
367
if (!cldata->contents.work_iface.query ||
368
! mg_query_is_select_query (cldata->contents.work_iface.query))
371
if (!cldata->contents.work_iface.query_extra ||
372
! mg_query_is_select_query (cldata->contents.work_iface.query_extra))
377
target = cldata->contents.work_iface.rows_target;
378
if (!IS_MG_TARGET (target) ||
379
(mg_target_get_query (target) != cldata->contents.work_iface.query))
384
target = cldata->contents.work_iface.cols_target;
385
if (!IS_MG_TARGET (target) ||
386
(mg_target_get_query (target) != cldata->contents.work_iface.query_extra))
390
/* actual widget creation */
392
wid = mg_work_matrix_new (conf,
393
cldata->contents.work_iface.query,
394
cldata->contents.work_iface.rows_target,
395
cldata->contents.work_iface.query_extra,
396
cldata->contents.work_iface.cols_target,
397
(MgDbTable *) cldata->contents.work_iface.modified,
399
mg_work_matrix_set_view_type (MG_WORK_MATRIX (wid), cldata->contents.work_iface.view_type);
400
wl->priv->work_widgets = g_slist_prepend (wl->priv->work_widgets, wid);
401
mg_work_widget_set_mode (MG_WORK_WIDGET (wid), cldata->contents.work_iface.mode);
402
g_object_set (G_OBJECT (wid), "title_visible", FALSE, NULL);
405
wid = gtk_label_new (_("Error creating widget"));
407
gtk_box_pack_start (GTK_BOX (wl), wid, TRUE, TRUE, 0);
408
gtk_widget_show (wid);
412
static MgWorkLayout *
413
find_by_custom_layout (MgWorkLayout *super_layout, MgCustomLayout *cl)
415
MgWorkLayout *retval = NULL;
416
GSList *list = super_layout->priv->work_widgets;
417
while (list && !retval) {
418
if (MG_WORK_LAYOUT (list->data)->priv->layout == cl)
419
retval = MG_WORK_LAYOUT (list->data);
421
list = g_slist_next (list);
428
init_super_layout (MgWorkLayout *wl)
430
GtkWidget *wid, *box, *root;
431
MgCustomLayout *cl = wl->priv->layout;
433
GHashTable *hash = NULL;
434
GError *error = NULL;
435
MgCustomLayoutData *cldata;
438
glade = mg_custom_layout_get_glade_instance (cl, &root, &hash, &error);
439
wl->priv->glade_instance = glade;
441
g_warning ("Error building GladeXML file: %s", error->message);
442
g_error_free (error);
447
/* If there is no Glade layout, or if there was an error, then we use
452
cldata = mg_custom_layout_get_data (cl, &error);
454
g_warning ("Error using MgCustomLayout: %s", error->message);
455
g_error_free (error);
459
/* actual widget creation */
460
list = cldata->contents.layout.children;
462
wid = mg_work_layout_new (MG_CUSTOM_LAYOUT (list->data));
465
box = g_hash_table_lookup (hash, list->data);
466
gtk_box_pack_start (GTK_BOX (box), wid, TRUE, TRUE, 0);
467
gtk_widget_show (wid);
468
if (! g_object_get_data (G_OBJECT (box), "show_actions"))
469
mg_work_widget_alldata_show_actions (MG_WORK_WIDGET (wid), FALSE);
475
wl->priv->work_widgets = g_slist_prepend (wl->priv->work_widgets, wid);
476
list = g_slist_next (list);
479
list = cldata->contents.layout.connects;
481
MgCustomLayoutConnect *lc = (MgCustomLayoutConnect*) list->data;
482
MgWorkWidget *src, *dest;
483
MgParameter *param_src, *param_dest;
486
tmp = find_by_custom_layout (wl, lc->src_layout);
487
g_assert (tmp->priv && (g_slist_length (tmp->priv->work_widgets) == 1));
488
src = MG_WORK_WIDGET (tmp->priv->work_widgets->data);
490
tmp = find_by_custom_layout (wl, lc->dest_layout);
491
g_assert (tmp->priv && (g_slist_length (tmp->priv->work_widgets) == 1));
492
dest = MG_WORK_WIDGET (tmp->priv->work_widgets->data);
494
param_src = mg_work_widget_get_param_for_field_data (src, MG_QFIELD (lc->src_field));
496
g_warning (_("Cannot find a parameter for source field connection"));
497
param_dest = mg_work_widget_get_param_for_field_exec (dest, MG_QFIELD (lc->dest_field));
499
g_warning (_("Cannot find a parameter for destination field connection"));
501
if (param_src && param_dest)
502
mg_parameter_bind_to_param (param_dest, param_src);
504
list = g_slist_next (list);
507
gtk_box_pack_start (GTK_BOX (wl), root, TRUE, TRUE, 0);
508
gtk_widget_show (root);
510
g_hash_table_destroy (hash);
515
* mg_work_layout_lookup_widget
516
* @layout: a #MgWorkLayout widget
517
* @widget_name: a string
519
* Retreives the #GtkWidget which name is @widget_name, if @layout
520
* uses a Glade file as layout.
522
* Returns: the requested #GtkWidget, or %NULL if not found
525
mg_work_layout_lookup_widget (MgWorkLayout *layout, const gchar *widget_name)
527
GtkWidget *retval = NULL;
529
g_return_val_if_fail (layout && IS_MG_WORK_LAYOUT (layout), NULL);
530
g_return_val_if_fail (layout->priv, NULL);
532
if (layout->priv->glade_instance)
533
retval = glade_xml_get_widget (layout->priv->glade_instance, widget_name);
539
* MgWorkWidget interface implementation
542
mg_work_layout_run (MgWorkWidget *iface, guint mode)
547
g_return_if_fail (iface && IS_MG_WORK_LAYOUT (iface));
548
wl = MG_WORK_LAYOUT (iface);
549
g_return_if_fail (wl->priv);
551
list = wl->priv->work_widgets;
553
mg_work_widget_run (MG_WORK_WIDGET (list->data), 0); /* don't change previous mode */
554
list = g_slist_next (list);
559
mg_work_layout_show_global_actions (MgWorkWidget *iface, gboolean show_actions)
564
g_return_if_fail (iface && IS_MG_WORK_LAYOUT (iface));
565
wl = MG_WORK_LAYOUT (iface);
566
g_return_if_fail (wl->priv);
568
list = wl->priv->work_widgets;
570
mg_work_widget_alldata_show_actions (MG_WORK_WIDGET (list->data), show_actions);
571
list = g_slist_next (list);
576
mg_work_layout_get_param_for_field (MgWorkWidget *iface, MgQfield *field, const gchar *field_name, gboolean in_exec_context)
579
MgParameter *param = NULL;
581
g_return_val_if_fail (iface && IS_MG_WORK_LAYOUT (iface), NULL);
582
wl = MG_WORK_LAYOUT (iface);
583
g_return_val_if_fail (wl->priv, NULL);
584
g_return_val_if_fail (field || (field_name && *field_name), NULL);
592
mg_work_layout_get_exec_context (MgWorkWidget *iface)
596
g_return_val_if_fail (iface && IS_MG_WORK_LAYOUT (iface), NULL);
597
wl = MG_WORK_LAYOUT (iface);
598
g_return_val_if_fail (wl->priv, NULL);
600
return wl->priv->exec_context;