~ubuntu-branches/ubuntu/karmic/mergeant/karmic

« back to all changes in this revision

Viewing changes to src/query-fields-editor.c

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo R. Montesino
  • Date: 2007-11-29 08:44:48 UTC
  • mfrom: (2.1.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20071129084448-6aon73d22bv6hzfw
Tags: 0.67-3
* Re-enable installation of the mime files in mergeant.install
* mergeant.dirs: create usr/share/mime/packages to make dh_installmime add
  the update-mime-database code snippets

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* query-fields-editor.c
 
2
 *
 
3
 * Copyright (C) 2004 - 2007 Vivien Malerba
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 * USA
 
19
 */
 
20
 
 
21
#include "query-fields-editor.h"
 
22
#include "query-fields-menu.h"
 
23
#include <glib/gi18n-lib.h>
 
24
 
 
25
static void query_fields_editor_class_init (QueryFieldsEditorClass * class);
 
26
static void query_fields_editor_init (QueryFieldsEditor * wid);
 
27
static void query_fields_editor_dispose (GObject   * object);
 
28
 
 
29
 
 
30
struct _QueryFieldsEditorPriv
 
31
{
 
32
        GdaQuery     *query;
 
33
        
 
34
        GtkTreeModel *model;
 
35
        GtkTreeView  *view;
 
36
        guint         mode;
 
37
        GtkWidget    *del_button;
 
38
        GtkWidget    *up_button;
 
39
        GtkWidget    *down_button;
 
40
};
 
41
 
 
42
/* get a pointer to the parents to be able to call their destructor */
 
43
static GObjectClass *parent_class = NULL;
 
44
 
 
45
GType
 
46
query_fields_editor_get_type (void)
 
47
{
 
48
        static GType type = 0;
 
49
 
 
50
        if (!type) {
 
51
                static const GTypeInfo info = {
 
52
                        sizeof (QueryFieldsEditorClass),
 
53
                        (GBaseInitFunc) NULL,
 
54
                        (GBaseFinalizeFunc) NULL,
 
55
                        (GClassInitFunc) query_fields_editor_class_init,
 
56
                        NULL,
 
57
                        NULL,
 
58
                        sizeof (QueryFieldsEditor),
 
59
                        0,
 
60
                        (GInstanceInitFunc) query_fields_editor_init
 
61
                };              
 
62
                
 
63
                type = g_type_register_static (GTK_TYPE_VBOX, "QueryFieldsEditor", &info, 0);
 
64
        }
 
65
 
 
66
        return type;
 
67
}
 
68
 
 
69
static void
 
70
query_fields_editor_class_init (QueryFieldsEditorClass * class)
 
71
{
 
72
        GObjectClass   *object_class = G_OBJECT_CLASS (class);
 
73
        
 
74
        parent_class = g_type_class_peek_parent (class);
 
75
 
 
76
        object_class->dispose = query_fields_editor_dispose;
 
77
}
 
78
 
 
79
enum {
 
80
        COLUMN_FIELD_PTR,   /* pointer to GnomeDbQField obj */
 
81
        COLUMN_FIELD_TXT,
 
82
        COLUMN_FIELD_EDIT,  /* TRUE if field text can be edited: for GdaQueryFieldValue, GdaQueryFieldFunc, etc */
 
83
        COLUMN_SHOWN,       /* TRUE if field visible && not internal */
 
84
        COLUMN_ALIAS,
 
85
        COLUMN_FILTER,
 
86
        COLUMN_FILTER_ENABLE, /* TRUE if the WHERE condition is composed of AND'ed individual conditions */
 
87
        COLUMN_FILTER_COND,   /* GdaQueryCondition pointer if COLUMN_FILTER does have some text */
 
88
        COLUMN_ORDER_NUMBER, /* -1 if not ordered */
 
89
        COLUMN_ORDER_ENABLE, /* TRUE if field is in the ORDER BY */
 
90
        COLUMN_ORDER_ASC,
 
91
        COLUMN_ERROR,
 
92
        N_COLUMNS
 
93
};
 
94
 
 
95
static void
 
96
query_fields_editor_init (QueryFieldsEditor * wid)
 
97
{
 
98
        wid->priv = g_new0 (QueryFieldsEditorPriv, 1);
 
99
        wid->priv->query = NULL;
 
100
        wid->priv->model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
 
101
                                                               G_TYPE_POINTER,
 
102
                                                               G_TYPE_STRING,
 
103
                                                               G_TYPE_BOOLEAN,
 
104
                                                               G_TYPE_BOOLEAN,
 
105
                                                               G_TYPE_STRING,
 
106
                                                               G_TYPE_STRING,
 
107
                                                               G_TYPE_BOOLEAN,
 
108
                                                               G_TYPE_POINTER,
 
109
                                                               G_TYPE_STRING,
 
110
                                                               G_TYPE_BOOLEAN,
 
111
                                                               G_TYPE_STRING,
 
112
                                                               G_TYPE_BOOLEAN));
 
113
        wid->priv->del_button = NULL;
 
114
}
 
115
 
 
116
static void query_fields_editor_initialize (QueryFieldsEditor *mgsel);
 
117
 
 
118
 
 
119
static void query_destroyed_cb (GdaQuery *query, QueryFieldsEditor *mgsel);
 
120
static void query_changed_cb (GdaQuery *query, QueryFieldsEditor *fedit);
 
121
 
 
122
/**
 
123
 * query_fields_editor_new
 
124
 * @query: a #GdaQuery object
 
125
 *
 
126
 * Creates a new #QueryFieldsEditor widget.
 
127
 *
 
128
 * Returns: the new widget
 
129
 */
 
130
GtkWidget *
 
131
query_fields_editor_new (GdaQuery *query, guint mode)
 
132
{
 
133
        GObject    *obj;
 
134
        QueryFieldsEditor *fedit;
 
135
 
 
136
        g_return_val_if_fail (query && GDA_IS_QUERY (query), NULL);
 
137
                
 
138
        obj = g_object_new (QUERY_FIELDS_EDITOR_TYPE, NULL);
 
139
        fedit = QUERY_FIELDS_EDITOR (obj);
 
140
 
 
141
        fedit->priv->query = query;
 
142
        fedit->priv->mode = mode;
 
143
 
 
144
        gda_object_connect_destroy (fedit->priv->query,
 
145
                                 G_CALLBACK (query_destroyed_cb), fedit);
 
146
        g_signal_connect (G_OBJECT (fedit->priv->query), "changed",
 
147
                          G_CALLBACK (query_changed_cb), fedit);
 
148
        
 
149
        query_fields_editor_initialize (fedit);
 
150
 
 
151
        return GTK_WIDGET (obj);
 
152
}
 
153
 
 
154
static void
 
155
query_destroyed_cb (GdaQuery *query, QueryFieldsEditor *mgsel)
 
156
{
 
157
        gtk_widget_destroy (GTK_WIDGET (mgsel));
 
158
}
 
159
 
 
160
static void
 
161
query_fields_editor_dispose (GObject *object)
 
162
{
 
163
        QueryFieldsEditor *fedit;
 
164
 
 
165
        g_return_if_fail (object != NULL);
 
166
        g_return_if_fail (IS_QUERY_FIELDS_EDITOR (object));
 
167
        fedit = QUERY_FIELDS_EDITOR (object);
 
168
 
 
169
        if (fedit->priv) {
 
170
                /* Weak unref the GdaQuery if necessary */
 
171
                if (fedit->priv->query) {
 
172
                        g_signal_handlers_disconnect_by_func (G_OBJECT (fedit->priv->query),
 
173
                                                              G_CALLBACK (query_destroyed_cb), fedit);
 
174
                        g_signal_handlers_disconnect_by_func (G_OBJECT (fedit->priv->query),
 
175
                                                              G_CALLBACK (query_changed_cb), fedit);
 
176
                }
 
177
 
 
178
                if (fedit->priv->model)
 
179
                        g_object_unref (fedit->priv->model);
 
180
 
 
181
                /* the private area itself */
 
182
                g_free (fedit->priv);
 
183
                fedit->priv = NULL;
 
184
        }
 
185
 
 
186
        /* for the parent class */
 
187
        parent_class->dispose (object);
 
188
}
 
189
 
 
190
static void renderer_field_txt_edited_cb      (GtkCellRendererText *renderer, 
 
191
                                               gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit);
 
192
static void renderer_field_shown_toggled_cb   (GtkCellRendererToggle *renderer,
 
193
                                               gchar *tree_path, QueryFieldsEditor *fedit);
 
194
static void renderer_field_alias_edited_cb    (GtkCellRendererText *renderer, 
 
195
                                               gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit);
 
196
static void renderer_field_filter_edited_cb    (GtkCellRendererText *renderer, 
 
197
                                               gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit);
 
198
static void renderer_field_orderno_edited_cb  (GtkCellRendererText *renderer, 
 
199
                                               gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit);
 
200
static void renderer_field_orderty_edited_cb  (GtkCellRendererText *renderer, 
 
201
                                               gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit);
 
202
static void field_selection_changed_cb        (GtkTreeSelection *selection, QueryFieldsEditor *fedit);
 
203
static void action_drop_field_cb              (GtkButton *button, QueryFieldsEditor *fedit);
 
204
static void action_up_field_cb                (GtkButton *button, QueryFieldsEditor *fedit);
 
205
static void action_down_field_cb              (GtkButton *button, QueryFieldsEditor *fedit);
 
206
static void
 
207
query_fields_editor_initialize (QueryFieldsEditor *fedit)
 
208
{
 
209
        GtkWidget *sw, *tv, *hbox, *bbox, *button, *wid;
 
210
        GtkCellRenderer *renderer;
 
211
        GtkTreeViewColumn *column;
 
212
        GtkTreeSelection *select;
 
213
 
 
214
        hbox = gtk_hbox_new (FALSE, 0);
 
215
        gtk_box_pack_start (GTK_BOX (fedit), hbox, TRUE, TRUE, 0);
 
216
        gtk_widget_show (hbox);
 
217
 
 
218
        /*
 
219
         * TreeView initialization
 
220
         */
 
221
        sw = gtk_scrolled_window_new (NULL, NULL);
 
222
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
 
223
                                        GTK_POLICY_AUTOMATIC,
 
224
                                        GTK_POLICY_AUTOMATIC);
 
225
        gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0);
 
226
        gtk_widget_show (sw);
 
227
 
 
228
        tv = gtk_tree_view_new_with_model (fedit->priv->model);
 
229
        gtk_container_add (GTK_CONTAINER (sw), tv);
 
230
        gtk_widget_show (tv);
 
231
        fedit->priv->view = GTK_TREE_VIEW (tv);
 
232
 
 
233
        select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
 
234
        gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
 
235
        g_signal_connect (G_OBJECT (select), "changed",
 
236
                          G_CALLBACK (field_selection_changed_cb), fedit);
 
237
 
 
238
        
 
239
        /* field TXT */
 
240
        renderer = gtk_cell_renderer_text_new ();
 
241
        g_signal_connect (G_OBJECT (renderer), "edited",
 
242
                          G_CALLBACK (renderer_field_txt_edited_cb), fedit);
 
243
        g_object_set (G_OBJECT (renderer), "strikethrough", TRUE, NULL);
 
244
        column = gtk_tree_view_column_new_with_attributes (_("Field"),
 
245
                                                           renderer,
 
246
                                                           "text", COLUMN_FIELD_TXT,
 
247
                                                           "editable", COLUMN_FIELD_EDIT,
 
248
                                                           "strikethrough-set", COLUMN_ERROR,
 
249
                                                           NULL);
 
250
        gtk_tree_view_append_column (GTK_TREE_VIEW (tv), column);
 
251
 
 
252
        /* shown / alias */
 
253
        if (fedit->priv->mode & QEF_SHOW_OPTION) {
 
254
                renderer = gtk_cell_renderer_toggle_new ();
 
255
                g_signal_connect (G_OBJECT (renderer), "toggled",
 
256
                                  G_CALLBACK (renderer_field_shown_toggled_cb), fedit);
 
257
                column = gtk_tree_view_column_new_with_attributes (_("Shown & alias"),
 
258
                                                                   renderer,
 
259
                                                                   "active", COLUMN_SHOWN,
 
260
                                                                   NULL);
 
261
                renderer = gtk_cell_renderer_text_new ();
 
262
                g_signal_connect (G_OBJECT (renderer), "edited",
 
263
                                  G_CALLBACK (renderer_field_alias_edited_cb), fedit);
 
264
                g_object_set (G_OBJECT (renderer), "strikethrough", TRUE, NULL);
 
265
                gtk_tree_view_column_pack_start (column, renderer, TRUE);
 
266
                gtk_tree_view_column_set_attributes (column, renderer, 
 
267
                                                     "text", COLUMN_ALIAS,
 
268
                                                     "editable", COLUMN_SHOWN,
 
269
                                                     "strikethrough-set", COLUMN_ERROR,
 
270
                                                     NULL);
 
271
                gtk_tree_view_append_column (GTK_TREE_VIEW (tv), column);
 
272
        }
 
273
 
 
274
        /* filter column */
 
275
        if (fedit->priv->mode & QEF_FILTER_OPTION) {
 
276
                renderer = gtk_cell_renderer_text_new ();
 
277
                g_signal_connect (G_OBJECT (renderer), "edited",
 
278
                                  G_CALLBACK (renderer_field_filter_edited_cb), fedit);
 
279
                g_object_set (G_OBJECT (renderer), "strikethrough", TRUE, NULL);
 
280
                column = gtk_tree_view_column_new_with_attributes (_("Filter"),
 
281
                                                                   renderer,
 
282
                                                                   "text", COLUMN_FILTER,
 
283
                                                                   "editable", COLUMN_FILTER_ENABLE,
 
284
                                                                   "strikethrough-set", COLUMN_ERROR,
 
285
                                                                   NULL);
 
286
                gtk_tree_view_append_column (GTK_TREE_VIEW (tv), column);
 
287
                gtk_tree_view_column_set_expand (column, TRUE);
 
288
        }
 
289
 
 
290
        /* GROUP By */
 
291
        
 
292
        /* ORDER By */
 
293
        if (fedit->priv->mode & QEF_ORDER_OPTION) {
 
294
                renderer = gtk_cell_renderer_text_new ();
 
295
                g_signal_connect (G_OBJECT (renderer), "edited",
 
296
                                  G_CALLBACK (renderer_field_orderno_edited_cb), fedit);
 
297
                g_object_set (G_OBJECT (renderer), "strikethrough", TRUE, NULL);
 
298
                column = gtk_tree_view_column_new_with_attributes (_("Ordering"),
 
299
                                                                   renderer,
 
300
                                                                   "text", COLUMN_ORDER_NUMBER,
 
301
                                                                   "strikethrough-set", COLUMN_ERROR,
 
302
                                                                   NULL);
 
303
                g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
 
304
                renderer = gtk_cell_renderer_text_new ();
 
305
                g_signal_connect (G_OBJECT (renderer), "edited",
 
306
                                  G_CALLBACK (renderer_field_orderty_edited_cb), fedit);
 
307
                g_object_set (G_OBJECT (renderer), "strikethrough", TRUE, NULL);
 
308
                gtk_tree_view_column_pack_start (column, renderer, TRUE);
 
309
                gtk_tree_view_column_set_attributes (column, renderer, 
 
310
                                                     "text", COLUMN_ORDER_ASC,
 
311
                                                     "editable", COLUMN_ORDER_ENABLE,
 
312
                                                     "strikethrough-set", COLUMN_ERROR,
 
313
                                                     NULL);
 
314
                gtk_tree_view_append_column (GTK_TREE_VIEW (tv), column);
 
315
        }
 
316
 
 
317
        /*
 
318
         * Buttons
 
319
         */
 
320
        if (fedit->priv->mode & QEF_ACTION_BUTTONS) {
 
321
                bbox = gtk_vbutton_box_new ();
 
322
                gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
 
323
                gtk_box_pack_start (GTK_BOX (hbox), bbox, FALSE, FALSE, 6);
 
324
                gtk_widget_show (bbox);
 
325
                
 
326
                button = query_fields_menu_new (fedit->priv->query);
 
327
                gtk_container_add (GTK_CONTAINER (bbox), button);
 
328
                gtk_widget_show (button);
 
329
                
 
330
                button = gtk_button_new ();
 
331
                wid = gtk_image_new_from_stock (GTK_STOCK_DELETE, GTK_ICON_SIZE_BUTTON);
 
332
                gtk_widget_show (wid);
 
333
                gtk_container_add (GTK_CONTAINER (button), wid);
 
334
                gtk_container_add (GTK_CONTAINER (bbox), button);
 
335
                gtk_widget_show (button);
 
336
                gtk_widget_set_sensitive (button, FALSE);
 
337
                fedit->priv->del_button = button;
 
338
                g_signal_connect (G_OBJECT (button), "clicked",
 
339
                                  G_CALLBACK (action_drop_field_cb), fedit);
 
340
 
 
341
                button = gtk_button_new ();
 
342
                wid = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
 
343
                gtk_widget_show (wid);
 
344
                gtk_container_add (GTK_CONTAINER (button), wid);
 
345
                gtk_container_add (GTK_CONTAINER (bbox), button);
 
346
                gtk_widget_show (button);
 
347
                gtk_widget_set_sensitive (button, FALSE);
 
348
                fedit->priv->up_button = button;
 
349
                g_signal_connect (G_OBJECT (button), "clicked",
 
350
                                  G_CALLBACK (action_up_field_cb), fedit);
 
351
 
 
352
                button = gtk_button_new ();
 
353
                wid = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_BUTTON);
 
354
                gtk_widget_show (wid);
 
355
                gtk_container_add (GTK_CONTAINER (button), wid);
 
356
                gtk_container_add (GTK_CONTAINER (bbox), button);
 
357
                gtk_widget_show (button);
 
358
                gtk_widget_set_sensitive (button, FALSE);
 
359
                fedit->priv->down_button = button;
 
360
                g_signal_connect (G_OBJECT (button), "clicked",
 
361
                                  G_CALLBACK (action_down_field_cb), fedit);
 
362
        }
 
363
 
 
364
        /*
 
365
         * Model initialization
 
366
         */
 
367
        query_changed_cb (fedit->priv->query, fedit);
 
368
}
 
369
 
 
370
/*
 
371
 * Fetch the GdaQueryField held at row described by @tree_path. if @iter is not NULL, then sets
 
372
 * it to represent the corresponding row
 
373
 */
 
374
static GdaQueryField *
 
375
model_get_field_from_path (GtkTreeModel *model, GtkTreeIter *iter, const gchar *tree_path)
 
376
{
 
377
        GtkTreeIter tmpiter;
 
378
        GtkTreePath *path;
 
379
        GdaQueryField *field = NULL;    
 
380
 
 
381
        path = gtk_tree_path_new_from_string (tree_path);
 
382
        if (gtk_tree_model_get_iter (model, &tmpiter, path)) {
 
383
                gtk_tree_model_get (model, &tmpiter, COLUMN_FIELD_PTR, &field, -1);
 
384
                if (iter)
 
385
                        *iter = tmpiter;
 
386
        }
 
387
        gtk_tree_path_free (path);
 
388
 
 
389
        return field;
 
390
}
 
391
 
 
392
/*
 
393
 * Sets @iter to point to the row representing @field
 
394
 */
 
395
static gboolean get_iter_for_field (QueryFieldsEditor *fedit, GtkTreeIter *iter, GdaEntityField *field)
 
396
{
 
397
        GdaEntityField *tmpfield;
 
398
 
 
399
        g_return_val_if_fail (iter, FALSE);
 
400
        g_return_val_if_fail (field, FALSE);
 
401
 
 
402
        if (! gtk_tree_model_get_iter_first (fedit->priv->model, iter))
 
403
                return FALSE;
 
404
 
 
405
        gtk_tree_model_get (fedit->priv->model, iter, COLUMN_FIELD_PTR, &tmpfield, -1);
 
406
        if (field == tmpfield)
 
407
                return TRUE;
 
408
 
 
409
        while (gtk_tree_model_iter_next (fedit->priv->model, iter)) {
 
410
                gtk_tree_model_get (fedit->priv->model, iter, COLUMN_FIELD_PTR, &tmpfield, -1);
 
411
                if (field == tmpfield)
 
412
                        return TRUE;
 
413
        }
 
414
 
 
415
        return FALSE;
 
416
}
 
417
 
 
418
 
 
419
static void
 
420
renderer_field_txt_edited_cb (GtkCellRendererText *renderer, 
 
421
                              gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit)
 
422
{
 
423
        GdaQueryField *field;
 
424
 
 
425
        field = model_get_field_from_path (fedit->priv->model, NULL, tree_path);
 
426
        if (GDA_IS_QUERY_FIELD_VALUE (field)) {
 
427
                GValue *value;
 
428
                GType gtype;
 
429
                GdaDataHandler *dh;
 
430
 
 
431
                g_object_get (G_OBJECT (field), "gda-type", &gtype, NULL);
 
432
                dh = gda_dict_get_default_handler (gda_object_get_dict ((GdaObject *) field), gtype);
 
433
                value = gda_data_handler_get_value_from_sql (dh, new_text, 
 
434
                                                             gda_entity_field_get_g_type (GDA_ENTITY_FIELD (field)));
 
435
                if (value) {
 
436
                        gda_query_field_value_set_value (GDA_QUERY_FIELD_VALUE (field), value);
 
437
                        gda_value_free (value);
 
438
                }
 
439
        }
 
440
}
 
441
 
 
442
static void
 
443
renderer_field_shown_toggled_cb (GtkCellRendererToggle *renderer,
 
444
                                 gchar *tree_path, QueryFieldsEditor *fedit)
 
445
{
 
446
        GdaQueryField *field;
 
447
 
 
448
        field = model_get_field_from_path (fedit->priv->model, NULL, tree_path);
 
449
        gda_query_field_set_visible (field, !gtk_cell_renderer_toggle_get_active (renderer));
 
450
}
 
451
 
 
452
static void
 
453
renderer_field_alias_edited_cb (GtkCellRendererText *renderer, 
 
454
                                gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit)
 
455
{
 
456
        GdaQueryField *field;
 
457
 
 
458
        field = model_get_field_from_path (fedit->priv->model, NULL, tree_path);
 
459
        gda_query_field_set_alias (field, new_text);
 
460
}
 
461
 
 
462
static void
 
463
renderer_field_filter_edited_cb (GtkCellRendererText *renderer, 
 
464
                                 gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit)
 
465
{
 
466
        GdaQueryField *field;
 
467
        GdaQueryCondition *newcond, *cond;
 
468
        GtkTreeIter iter;
 
469
 
 
470
        field = model_get_field_from_path (fedit->priv->model, &iter, tree_path);
 
471
        gtk_tree_model_get (fedit->priv->model, &iter, COLUMN_FILTER_COND, &cond, -1);
 
472
 
 
473
        if (new_text && *new_text) {
 
474
                GError *error = NULL;
 
475
 
 
476
                newcond = gda_query_condition_new_from_sql (fedit->priv->query, new_text, NULL, &error);
 
477
                if (!newcond) {
 
478
                        gchar *sql;
 
479
                        sql = gda_renderer_render_as_sql (GDA_RENDERER (field), NULL, NULL, 0, NULL);
 
480
                        if (sql) {
 
481
                                gchar *text = g_strdup_printf ("%s %s", sql, new_text);
 
482
                                g_free (sql);
 
483
                                newcond = gda_query_condition_new_from_sql (fedit->priv->query, text, NULL, NULL);
 
484
                                g_free (text);
 
485
                        }
 
486
                }
 
487
 
 
488
                if (!newcond) {
 
489
                        GtkWidget *dlg;
 
490
                        gchar *msg;
 
491
 
 
492
                        if (error) {
 
493
                                msg = g_strdup_printf ("<b>%s</b>\n%s '%s':\n\n%s",
 
494
                                                       _("Error parsing/analysing condition expression:"),
 
495
                                                       _("while parsing"),
 
496
                                                       new_text,
 
497
                                                       error->message);
 
498
                                
 
499
                                g_error_free (error);
 
500
                        }
 
501
                        else
 
502
                                msg = g_strdup_printf ("<b>%s</b>\n%s '%s'",
 
503
                                                       _("Error parsing/analysing condition expression:"),
 
504
                                                       _("while parsing"),
 
505
                                                       new_text);
 
506
                        
 
507
                        dlg = gtk_message_dialog_new_with_markup (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
 
508
                                                                  GTK_BUTTONS_CLOSE, msg);
 
509
                        g_free (msg);
 
510
                        gtk_dialog_run (GTK_DIALOG (dlg));
 
511
                        gtk_widget_destroy (dlg);
 
512
                        return;
 
513
                }
 
514
        }
 
515
        else
 
516
                newcond = NULL;
 
517
 
 
518
        if (newcond) {
 
519
                if (cond) {
 
520
                        /* there was a previous condition */
 
521
                        GdaQueryCondition *parent = gda_query_condition_get_parent (cond);
 
522
                        if (parent) {
 
523
                                GHashTable *repl;
 
524
 
 
525
                                repl = g_hash_table_new (NULL, NULL);
 
526
                                g_hash_table_insert (repl, cond, newcond);
 
527
                                gda_referer_replace_refs (GDA_REFERER (parent), repl);
 
528
                                g_hash_table_destroy (repl);
 
529
                        }
 
530
                        else 
 
531
                                gda_query_set_condition (fedit->priv->query, newcond);
 
532
                }
 
533
                else 
 
534
                        /* 'append' with an AND the new condition to the already existing one */
 
535
                        gda_query_append_condition (fedit->priv->query, newcond, TRUE);
 
536
 
 
537
                g_object_unref (newcond);
 
538
        }
 
539
        else {
 
540
                if (cond) 
 
541
                        gda_object_destroy (GDA_OBJECT (cond));
 
542
        }
 
543
}
 
544
 
 
545
static void
 
546
renderer_field_orderno_edited_cb  (GtkCellRendererText *renderer, 
 
547
                                   gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit)
 
548
{
 
549
        GdaQueryField *field;
 
550
        gint order;
 
551
 
 
552
        field = model_get_field_from_path (fedit->priv->model, NULL, tree_path);
 
553
        order = atoi (new_text);
 
554
        if (order > 0) {
 
555
                gboolean asc;
 
556
                if (gda_query_get_order_by_field (fedit->priv->query, field, &asc) < 0)
 
557
                        asc = TRUE;
 
558
                gda_query_set_order_by_field (fedit->priv->query, field, order - 1, asc);
 
559
        }
 
560
        else
 
561
                gda_query_set_order_by_field (fedit->priv->query, field, -1, TRUE);
 
562
                
 
563
}
 
564
 
 
565
static void
 
566
renderer_field_orderty_edited_cb  (GtkCellRendererText *renderer, 
 
567
                                   gchar *tree_path, gchar *new_text, QueryFieldsEditor *fedit)
 
568
{
 
569
        GdaQueryField *field;
 
570
        gint order;
 
571
 
 
572
        field = model_get_field_from_path (fedit->priv->model, NULL, tree_path);
 
573
 
 
574
        order = gda_query_get_order_by_field (fedit->priv->query, field, NULL);
 
575
        gda_query_set_order_by_field (fedit->priv->query, field, order, 
 
576
                                     new_text && ((*new_text == 'A') || (*new_text == 'a')));
 
577
}
 
578
 
 
579
static void 
 
580
field_selection_changed_cb (GtkTreeSelection *selection, QueryFieldsEditor *fedit)
 
581
{
 
582
        gint pos = 0;
 
583
        gboolean has_sel;
 
584
        GtkTreeIter iter;
 
585
        GdaEntityField *ofield = NULL;
 
586
 
 
587
        if (!fedit->priv->del_button)
 
588
                return;
 
589
 
 
590
        has_sel = gtk_tree_selection_get_selected (selection, NULL, &iter);
 
591
        if (has_sel) {
 
592
                GdaEntityField *field;
 
593
 
 
594
                gtk_tree_model_get (fedit->priv->model, &iter, COLUMN_FIELD_PTR, &field, -1);
 
595
                pos = gda_entity_get_field_index (GDA_ENTITY (fedit->priv->query), field);
 
596
                ofield = gda_entity_get_field_by_index (GDA_ENTITY (fedit->priv->query), pos + 1);
 
597
        }
 
598
 
 
599
        gtk_widget_set_sensitive (fedit->priv->del_button, has_sel);
 
600
        gtk_widget_set_sensitive (fedit->priv->up_button, has_sel && (pos > 0));
 
601
        gtk_widget_set_sensitive (fedit->priv->down_button, has_sel && ofield);
 
602
}
 
603
 
 
604
static void
 
605
action_drop_field_cb (GtkButton *button, QueryFieldsEditor *fedit)
 
606
{
 
607
        GtkTreeSelection *select;
 
608
        GtkTreeIter iter;
 
609
 
 
610
        select = gtk_tree_view_get_selection (GTK_TREE_VIEW (fedit->priv->view));
 
611
        if (gtk_tree_selection_get_selected (select, NULL, &iter)) {
 
612
                GdaQueryField *field;
 
613
 
 
614
                gtk_tree_model_get (fedit->priv->model, &iter, COLUMN_FIELD_PTR, &field, -1);
 
615
                gda_entity_remove_field (GDA_ENTITY (fedit->priv->query), GDA_ENTITY_FIELD (field));
 
616
        }
 
617
}
 
618
 
 
619
static void
 
620
action_up_field_cb (GtkButton *button, QueryFieldsEditor *fedit)
 
621
{
 
622
        GtkTreeSelection *select;
 
623
        GtkTreeIter iter;
 
624
 
 
625
        select = gtk_tree_view_get_selection (GTK_TREE_VIEW (fedit->priv->view));
 
626
        if (gtk_tree_selection_get_selected (select, NULL, &iter)) {
 
627
                GdaEntityField *field;
 
628
                gint pos;
 
629
 
 
630
                gtk_tree_model_get (fedit->priv->model, &iter, COLUMN_FIELD_PTR, &field, -1);
 
631
                pos = gda_entity_get_field_index (GDA_ENTITY (fedit->priv->query), field);
 
632
                if (pos > 0) {
 
633
                        GdaEntityField *ofield;
 
634
                        ofield = gda_entity_get_field_by_index (GDA_ENTITY (fedit->priv->query), pos - 1);
 
635
                        gda_entity_swap_fields (GDA_ENTITY (fedit->priv->query), field, ofield);
 
636
 
 
637
                        if (get_iter_for_field (fedit, &iter, field))
 
638
                                gtk_tree_selection_select_iter (select, &iter);
 
639
                }
 
640
        }
 
641
}
 
642
 
 
643
static void
 
644
action_down_field_cb (GtkButton *button, QueryFieldsEditor *fedit)
 
645
{
 
646
        GtkTreeSelection *select;
 
647
        GtkTreeIter iter;
 
648
 
 
649
        select = gtk_tree_view_get_selection (GTK_TREE_VIEW (fedit->priv->view));
 
650
        if (gtk_tree_selection_get_selected (select, NULL, &iter)) {
 
651
                GdaEntityField *field, *ofield;
 
652
                gint pos;
 
653
 
 
654
                gtk_tree_model_get (fedit->priv->model, &iter, COLUMN_FIELD_PTR, &field, -1);
 
655
                pos = gda_entity_get_field_index (GDA_ENTITY (fedit->priv->query), field);
 
656
                ofield = gda_entity_get_field_by_index (GDA_ENTITY (fedit->priv->query), pos + 1);
 
657
                if (ofield) {
 
658
                        gda_entity_swap_fields (GDA_ENTITY (fedit->priv->query), field, ofield);
 
659
 
 
660
                        if (get_iter_for_field (fedit, &iter, field))
 
661
                                gtk_tree_selection_select_iter (select, &iter);
 
662
                }
 
663
        }
 
664
}
 
665
 
 
666
static GSList *compute_fields_to_display (QueryFieldsEditor *fedit);
 
667
 
 
668
/*
 
669
 * (re)-write all the rows of the model with the fields which do qualify to be displayed
 
670
 */
 
671
static void
 
672
query_changed_cb (GdaQuery *query, QueryFieldsEditor *fedit)
 
673
{
 
674
        GSList *list, *fields;
 
675
        GtkTreeIter iter;
 
676
        GtkTreeModel *model = fedit->priv->model;
 
677
        gboolean iter_valid = FALSE;
 
678
       
 
679
        fields = compute_fields_to_display (fedit);
 
680
        list = fields;
 
681
        while (list) {
 
682
                GdaQueryField *field = GDA_QUERY_FIELD (list->data);
 
683
                gchar *sql, *order_str = NULL, *asc_str = NULL;
 
684
                gint order;
 
685
                gboolean asc = TRUE;
 
686
                GdaQueryCondition *cond;
 
687
                gchar *cond_sql = NULL;
 
688
                
 
689
                /* fetch a new iter */
 
690
                if (!iter_valid) {
 
691
                        /* fetch first iter, or create a new one */
 
692
                        if (! gtk_tree_model_get_iter_first (model, &iter))
 
693
                                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
694
                        iter_valid = TRUE;
 
695
                }
 
696
                else {
 
697
                        /* fetch next iter, or create a new one */
 
698
                        if (! gtk_tree_model_iter_next (model, &iter))
 
699
                                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
700
                }
 
701
                
 
702
                /* modify the model at iter */
 
703
                sql = gda_renderer_render_as_sql (GDA_RENDERER (field), NULL, NULL, 0, NULL);
 
704
                order = gda_query_get_order_by_field (fedit->priv->query, field, &asc);
 
705
                if (order >= 0) {
 
706
                        order_str = g_strdup_printf ("%d", order + 1);
 
707
                        asc_str = asc ? "ASC" : "DESC";
 
708
                }
 
709
                cond = g_object_get_data (G_OBJECT (field), "qf_filter_cond");
 
710
                g_object_set_data (G_OBJECT (field), "qf_filter_cond", NULL);
 
711
                if (cond) 
 
712
                        cond_sql = gda_renderer_render_as_sql (GDA_RENDERER (cond), NULL, NULL,
 
713
                                                               GDA_RENDERER_PARAMS_AS_DETAILED,
 
714
                                                               NULL);
 
715
                gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
716
                                    COLUMN_FIELD_PTR, field,
 
717
                                    COLUMN_FIELD_TXT, sql ? sql : gda_object_get_name (GDA_OBJECT (field)),
 
718
                                    COLUMN_FIELD_EDIT, GDA_IS_QUERY_FIELD_VALUE (field),
 
719
                                    COLUMN_SHOWN, gda_query_field_is_visible (field),
 
720
                                    COLUMN_ALIAS, gda_query_field_get_alias (field),
 
721
                                    COLUMN_ORDER_NUMBER, order_str,
 
722
                                    COLUMN_ORDER_ENABLE, (order >= 0) ? TRUE : FALSE,
 
723
                                    COLUMN_ORDER_ASC, asc_str,
 
724
                                    COLUMN_FILTER, cond_sql,
 
725
                                    COLUMN_FILTER_COND, cond,
 
726
                                    COLUMN_FILTER_ENABLE, TRUE /*cond ? TRUE : FALSE*/,
 
727
                                    COLUMN_ERROR, sql ? FALSE : TRUE,
 
728
                                    -1);
 
729
                g_free (sql);
 
730
                g_free (order_str);
 
731
                g_free (cond_sql);
 
732
                list = g_slist_next (list);
 
733
        }       
 
734
        g_slist_free (fields);
 
735
 
 
736
        /* clean the remaining rows */
 
737
        if (!iter_valid) {
 
738
                if (gtk_tree_model_get_iter_first (model, &iter))
 
739
                        while (gtk_list_store_remove (GTK_LIST_STORE (model), &iter));
 
740
        }
 
741
        else
 
742
                if (gtk_tree_model_iter_next (model, &iter))
 
743
                        while (gtk_list_store_remove (GTK_LIST_STORE (model), &iter));
 
744
 
 
745
        /* update action buttons' status */
 
746
        field_selection_changed_cb (gtk_tree_view_get_selection (fedit->priv->view), fedit);
 
747
}
 
748
 
 
749
static GSList *
 
750
compute_fields_to_display (QueryFieldsEditor *fedit)
 
751
{
 
752
        GSList *list, *fields;
 
753
        GSList *retval = NULL;
 
754
        GSList *main_conds = NULL;
 
755
        GdaQueryCondition *cond;
 
756
        
 
757
        cond = gda_query_get_condition (fedit->priv->query);
 
758
        if (cond)
 
759
                main_conds = gda_query_condition_get_main_conditions (cond);
 
760
        
 
761
        /* FIXME: add the fields which are GROUPed BY, and the ones in HAVING condition */      
 
762
        /* analyse all query's fields */
 
763
        fields = gda_query_get_all_fields (fedit->priv->query);
 
764
        list = fields;
 
765
        while (list) {
 
766
                GdaQueryField *field = GDA_QUERY_FIELD (list->data);
 
767
                gboolean to_include = FALSE;
 
768
                GSList *clist;
 
769
 
 
770
                /* fields as LEFT op of a main condition are always shown */
 
771
                clist = main_conds;
 
772
                while (clist && !to_include) {
 
773
                        cond = GDA_QUERY_CONDITION (clist->data);
 
774
                        if (gda_query_condition_is_leaf (cond) && 
 
775
                            (gda_query_condition_leaf_get_operator (cond, GDA_QUERY_CONDITION_OP_LEFT) == field)) {
 
776
                                to_include = TRUE;
 
777
                                g_object_set_data (G_OBJECT (field), "qf_filter_cond", cond);
 
778
                        }
 
779
                        clist = g_slist_next (clist);
 
780
                }
 
781
                if (to_include) {
 
782
                        retval = g_slist_prepend (retval, field);
 
783
                        list = g_slist_next (list);
 
784
                        continue;
 
785
                }
 
786
 
 
787
                /* fields in ORDER BY are always shows */
 
788
                if (gda_query_get_order_by_field (fedit->priv->query, field, NULL) >= 0) {
 
789
                        retval = g_slist_prepend (retval, field);
 
790
                        list = g_slist_next (list);
 
791
                        continue;
 
792
                }
 
793
 
 
794
                /* other tests */
 
795
                to_include = TRUE;
 
796
                if (gda_query_field_is_internal (field))
 
797
                        to_include = FALSE;
 
798
                if (to_include && !gda_query_field_is_visible (field))
 
799
                        to_include = FALSE;
 
800
                if (to_include)
 
801
                        retval = g_slist_prepend (retval, field);
 
802
 
 
803
                list = g_slist_next (list);
 
804
        }
 
805
        
 
806
        g_slist_free (main_conds);
 
807
        g_slist_free (fields);
 
808
 
 
809
        return g_slist_reverse (retval);
 
810
}