1 /*
2 * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2010 David King <davidk@openismus.com>
4 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include <glib/gi18n-lib.h>
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <gdk/gdkkeysyms.h>
25 #include <libgda/gda-tree.h>
26 #include "table-info.h"
27 #include "table-relations.h"
28 #include <libgda-ui/gdaui-tree-store.h>
29 #include "../support.h"
30 #include "../gdaui-bar.h"
31 #include "schema-browser-perspective.h"
32 #include "../canvas/browser-canvas-db-relations.h"
33
34 struct _TableRelationsPrivate {
35 BrowserConnection *bcnc;
36 TableInfo *tinfo;
37 GtkWidget *canvas;
38 gboolean all_schemas;
39 };
40
41 static void table_relations_class_init (TableRelationsClass *klass);
42 static void table_relations_init (TableRelations *trels, TableRelationsClass *klass);
43 static void table_relations_dispose (GObject *object);
44
45 static void meta_changed_cb (BrowserConnection *bcnc, GdaMetaStruct *mstruct, TableRelations *trels);
46
47 static GObjectClass *parent_class = NULL;
48
49
50 /*
51 * TableRelations class implementation
52 */
53
54 static void
table_relations_class_init(TableRelationsClass * klass)55 table_relations_class_init (TableRelationsClass *klass)
56 {
57 GObjectClass *object_class = G_OBJECT_CLASS (klass);
58
59 parent_class = g_type_class_peek_parent (klass);
60
61 object_class->dispose = table_relations_dispose;
62 }
63
64
65 static void
table_relations_init(TableRelations * trels,G_GNUC_UNUSED TableRelationsClass * klass)66 table_relations_init (TableRelations *trels, G_GNUC_UNUSED TableRelationsClass *klass)
67 {
68 trels->priv = g_new0 (TableRelationsPrivate, 1);
69 trels->priv->all_schemas = FALSE;
70
71 gtk_orientable_set_orientation (GTK_ORIENTABLE (trels), GTK_ORIENTATION_VERTICAL);
72 }
73
74 static void
table_relations_dispose(GObject * object)75 table_relations_dispose (GObject *object)
76 {
77 TableRelations *trels = (TableRelations *) object;
78
79 /* free memory */
80 if (trels->priv) {
81 if (trels->priv->bcnc) {
82 g_signal_handlers_disconnect_by_func (trels->priv->bcnc,
83 G_CALLBACK (meta_changed_cb), trels);
84 g_object_unref (trels->priv->bcnc);
85 }
86 g_free (trels->priv);
87 trels->priv = NULL;
88 }
89
90 parent_class->dispose (object);
91 }
92
93 GType
table_relations_get_type(void)94 table_relations_get_type (void)
95 {
96 static GType type = 0;
97
98 if (G_UNLIKELY (type == 0)) {
99 static const GTypeInfo relations = {
100 sizeof (TableRelationsClass),
101 (GBaseInitFunc) NULL,
102 (GBaseFinalizeFunc) NULL,
103 (GClassInitFunc) table_relations_class_init,
104 NULL,
105 NULL,
106 sizeof (TableRelations),
107 0,
108 (GInstanceInitFunc) table_relations_init,
109 0
110 };
111 type = g_type_register_static (GTK_TYPE_BOX, "TableRelations", &relations, 0);
112 }
113 return type;
114 }
115
116 static void
meta_changed_cb(G_GNUC_UNUSED BrowserConnection * bcnc,GdaMetaStruct * mstruct,TableRelations * trels)117 meta_changed_cb (G_GNUC_UNUSED BrowserConnection *bcnc, GdaMetaStruct *mstruct, TableRelations *trels)
118 {
119 GdaMetaDbObject *dbo;
120 GValue *tname, *tschema;
121 BrowserCanvasTable *ctable;
122
123 g_object_set (G_OBJECT (trels->priv->canvas), "meta-struct", mstruct, NULL);
124
125 g_value_set_string ((tschema = gda_value_new (G_TYPE_STRING)),
126 table_info_get_table_schema (trels->priv->tinfo));
127 g_value_set_string ((tname = gda_value_new (G_TYPE_STRING)),
128 table_info_get_table_name (trels->priv->tinfo));
129 ctable = browser_canvas_db_relations_add_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas), NULL,
130 tschema, tname);
131 browser_canvas_db_relations_select_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas),
132 ctable);
133
134 dbo = gda_meta_struct_get_db_object (mstruct, NULL, tschema, tname);
135
136 if (dbo && (dbo->obj_type == GDA_META_DB_TABLE)) {
137 GdaMetaTable *table;
138 table = GDA_META_TABLE (dbo);
139
140 GSList *list;
141 for (list = table->reverse_fk_list; list; list = list->next) {
142 GdaMetaTableForeignKey *fkey = (GdaMetaTableForeignKey*) list->data;
143 if (! trels->priv->all_schemas &&
144 ! strcmp (fkey->meta_table->obj_short_name, fkey->meta_table->obj_full_name))
145 continue;
146 g_value_set_string (tname, fkey->meta_table->obj_name);
147 g_value_set_string (tschema, fkey->meta_table->obj_schema);
148 browser_canvas_db_relations_add_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas),
149 NULL,
150 tschema, tname);
151 }
152
153 for (list = table->fk_list; list; list = list->next) {
154 GdaMetaTableForeignKey *fkey = (GdaMetaTableForeignKey*) list->data;
155
156 if (! trels->priv->all_schemas &&
157 (fkey->depend_on->obj_type != GDA_META_DB_UNKNOWN) &&
158 ! strcmp (fkey->depend_on->obj_short_name, fkey->depend_on->obj_full_name))
159 continue;
160
161 g_value_set_string (tname, fkey->depend_on->obj_name);
162 g_value_set_string (tschema, fkey->depend_on->obj_schema);
163 browser_canvas_db_relations_add_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas),
164 NULL,
165 tschema, tname);
166 }
167 }
168 gda_value_free (tschema);
169 gda_value_free (tname);
170
171 browser_canvas_perform_auto_layout (BROWSER_CANVAS (trels->priv->canvas), TRUE,
172 BROWSER_CANVAS_LAYOUT_DEFAULT);
173 }
174
175 /**
176 * table_relations_new
177 *
178 * Returns: a new #GtkWidget
179 */
180 GtkWidget *
table_relations_new(TableInfo * tinfo)181 table_relations_new (TableInfo *tinfo)
182 {
183 TableRelations *trels;
184
185 g_return_val_if_fail (IS_TABLE_INFO (tinfo), NULL);
186
187 trels = TABLE_RELATIONS (g_object_new (TABLE_RELATIONS_TYPE, NULL));
188
189 trels->priv->tinfo = tinfo;
190 trels->priv->bcnc = g_object_ref (table_info_get_connection (tinfo));
191 g_signal_connect (trels->priv->bcnc, "meta-changed",
192 G_CALLBACK (meta_changed_cb), trels);
193
194 /*
195 * Relations
196 */
197 trels->priv->canvas = browser_canvas_db_relations_new (NULL);
198 gtk_box_pack_start (GTK_BOX (trels), trels->priv->canvas, TRUE, TRUE, 0);
199 gtk_widget_show (GTK_WIDGET (trels));
200
201 /*
202 * initial update
203 */
204 GdaMetaStruct *mstruct;
205 mstruct = browser_connection_get_meta_struct (trels->priv->bcnc);
206 if (mstruct)
207 meta_changed_cb (trels->priv->bcnc, mstruct, trels);
208
209 return (GtkWidget*) trels;
210 }
211
212