[libgda] GdaBrowser: improved Data Manager perspective
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] GdaBrowser: improved Data Manager perspective
- Date: Sun, 5 Sep 2010 13:12:31 +0000 (UTC)
commit e825358dc3eab0938f6e3778cf20db3f072fd292
Author: Vivien Malerba <malerba gnome-db org>
Date: Sun Sep 5 15:00:24 2010 +0200
GdaBrowser: improved Data Manager perspective
tools/browser/Makefile.am | 3 +-
tools/browser/browser-connection.c | 18 +
tools/browser/browser-connection.h | 2 +
tools/browser/browser-window.c | 20 +-
tools/browser/browser-window.h | 8 +-
tools/browser/canvas/browser-canvas-db-relations.c | 4 -
tools/browser/data-manager/data-console.c | 90 +--
tools/browser/data-manager/data-source-manager.c | 58 ++-
tools/browser/data-manager/data-source.c | 106 +++-
tools/browser/data-manager/data-widget.c | 650 ++++++++++++++++----
tools/browser/data-manager/data-widget.h | 3 +-
tools/browser/doc/gda-browser-sections.txt | 1 +
tools/browser/doc/tmpl/browser-connection.sgml | 11 +
tools/browser/doc/tmpl/browser-window.sgml | 2 +
tools/browser/gda-browser-menu-ind.png | Bin 0 -> 472 bytes
tools/browser/query-exec/query-console.c | 15 +-
tools/browser/schema-browser/table-info.c | 5 +-
tools/browser/support.c | 14 +-
tools/browser/support.h | 2 +
19 files changed, 780 insertions(+), 232 deletions(-)
---
diff --git a/tools/browser/Makefile.am b/tools/browser/Makefile.am
index 7a3013b..b0f3695 100644
--- a/tools/browser/Makefile.am
+++ b/tools/browser/Makefile.am
@@ -149,7 +149,8 @@ icons_DATA= \
gda-browser-diagram.png \
gda-browser-query.png \
gda-browser-form.png \
- gda-browser-grid.png
+ gda-browser-grid.png \
+ gda-browser-menu-ind.png
# app icon
appiconsdir=$(datadir)/pixmaps
diff --git a/tools/browser/browser-connection.c b/tools/browser/browser-connection.c
index b04b735..6ed0495 100644
--- a/tools/browser/browser-connection.c
+++ b/tools/browser/browser-connection.c
@@ -1376,6 +1376,24 @@ browser_connection_normalize_sql_statement (BrowserConnection *bcnc,
return gda_sql_statement_normalize (sqlst, bcnc->priv->cnc, error);
}
+/**
+ * browser_connection_check_sql_statement_validify
+ */
+gboolean
+browser_connection_check_sql_statement_validify (BrowserConnection *bcnc,
+ GdaSqlStatement *sqlst, GError **error)
+{
+ g_return_val_if_fail (sqlst, FALSE);
+ g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), FALSE);
+
+ /* check the structure first */
+ if (!gda_sql_statement_check_structure (sqlst, error))
+ return FALSE;
+
+ return gda_sql_statement_check_validity_m (sqlst, bcnc->priv->mstruct, error);
+}
+
+
/*
* DOES NOT emit any signal
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index 763d80f..8908ffc 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -94,6 +94,8 @@ GObject *browser_connection_execution_get_result (BrowserConnection
GdaSet **last_insert_row, GError **error);
gboolean browser_connection_normalize_sql_statement(BrowserConnection *bcnc,
GdaSqlStatement *sqlst, GError **error);
+gboolean browser_connection_check_sql_statement_validify (BrowserConnection *bcnc,
+ GdaSqlStatement *sqlst, GError **error);
/**
* BrowserConnectionExecuteCallback
*
diff --git a/tools/browser/browser-window.c b/tools/browser/browser-window.c
index 3a9b6db..4b81bd4 100644
--- a/tools/browser/browser-window.c
+++ b/tools/browser/browser-window.c
@@ -913,9 +913,9 @@ window_fullscreen_cb (GtkToggleAction *action, BrowserWindow *bwin)
{
if (gtk_toggle_action_get_active (action)) {
gtk_window_fullscreen (GTK_WINDOW (bwin));
- browser_window_show_notice_printf (bwin,
- "fullscreen-esc",
- _("Hit the Escape key to leave the fullscreen mode"));
+ browser_window_show_notice_printf (bwin, GTK_MESSAGE_INFO,
+ "fullscreen-esc",
+ _("Hit the Escape key to leave the fullscreen mode"));
}
else
gtk_window_unfullscreen (GTK_WINDOW (bwin));
@@ -1271,7 +1271,7 @@ browser_window_pop_status (BrowserWindow *bwin, const gchar *context)
* Make @bwin display a notice
*/
void
-browser_window_show_notice_printf (BrowserWindow *bwin, const gchar *context,
+browser_window_show_notice_printf (BrowserWindow *bwin, GtkMessageType type, const gchar *context,
const gchar *format, ...)
{
va_list args;
@@ -1283,7 +1283,7 @@ browser_window_show_notice_printf (BrowserWindow *bwin, const gchar *context,
va_start (args, format);
vsnprintf (sz, sizeof (sz), format, args);
va_end (args);
- browser_window_show_notice (bwin, context, sz);
+ browser_window_show_notice (bwin, type, context, sz);
}
@@ -1318,12 +1318,12 @@ hide_notice_toggled_cb (GtkToggleButton *toggle, gchar *context)
* Makes @bwin display a notice
*/
void
-browser_window_show_notice (BrowserWindow *bwin, const gchar *context, const gchar *text)
+browser_window_show_notice (BrowserWindow *bwin, GtkMessageType type, const gchar *context, const gchar *text)
{
g_return_if_fail (BROWSER_IS_WINDOW (bwin));
gboolean hide = FALSE;
- if (context) {
+ if ((type != GTK_MESSAGE_ERROR) && context) {
if (!hidden_contexts)
hidden_contexts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
hide = GPOINTER_TO_INT (g_hash_table_lookup (hidden_contexts, context));
@@ -1344,7 +1344,7 @@ browser_window_show_notice (BrowserWindow *bwin, const gchar *context, const gch
}
else {
GtkWidget *cb = NULL;
- if (context) {
+ if (context && (type == GTK_MESSAGE_INFO)) {
cb = gtk_check_button_new_with_label (_("Don't show this message again"));
g_signal_connect_data (cb, "toggled",
G_CALLBACK (hide_notice_toggled_cb), g_strdup (context),
@@ -1356,7 +1356,7 @@ browser_window_show_notice (BrowserWindow *bwin, const gchar *context, const gch
GtkWidget *ibar, *content_area, *label;
ibar = gtk_info_bar_new_with_buttons (GTK_STOCK_CLOSE, 1, NULL);
- gtk_info_bar_set_message_type (GTK_INFO_BAR (ibar), GTK_MESSAGE_INFO);
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (ibar), type);
label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL (label), text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -1511,7 +1511,7 @@ browser_window_change_perspective (BrowserWindow *bwin, const gchar *perspective
current_pdata->factory->menu_shortcut);
- browser_window_show_notice (bwin, "Perspective change", tmp);
+ browser_window_show_notice (bwin, GTK_MESSAGE_INFO, "Perspective change", tmp);
g_free (tmp);
return bpers;
diff --git a/tools/browser/browser-window.h b/tools/browser/browser-window.h
index ee79e9c..4797953 100644
--- a/tools/browser/browser-window.h
+++ b/tools/browser/browser-window.h
@@ -58,10 +58,10 @@ BrowserConnection *browser_window_get_connection (BrowserWindow *bwin);
guint browser_window_push_status (BrowserWindow *bwin, const gchar *context,
const gchar *text, gboolean auto_clear);
void browser_window_pop_status (BrowserWindow *bwin, const gchar *context);
-void browser_window_show_notice (BrowserWindow *bwin, const gchar *context,
- const gchar *text);
-void browser_window_show_notice_printf (BrowserWindow *bwin, const gchar *context,
- const gchar *format, ...);
+void browser_window_show_notice (BrowserWindow *bwin, GtkMessageType type,
+ const gchar *context, const gchar *text);
+void browser_window_show_notice_printf (BrowserWindow *bwin, GtkMessageType type,
+ const gchar *context, const gchar *format, ...);
void browser_window_customize_perspective_ui (BrowserWindow *bwin, BrowserPerspective *bpers,
GtkActionGroup *actions_group,
diff --git a/tools/browser/canvas/browser-canvas-db-relations.c b/tools/browser/canvas/browser-canvas-db-relations.c
index 619313b..6ba01ea 100644
--- a/tools/browser/canvas/browser-canvas-db-relations.c
+++ b/tools/browser/canvas/browser-canvas-db-relations.c
@@ -612,10 +612,6 @@ browser_canvas_db_relations_add_table (BrowserCanvasDbRelations *canvas,
goocanvas = BROWSER_CANVAS (canvas)->priv->goocanvas;
mtable = (GdaMetaTable *) gda_meta_struct_complement (canvas->priv->mstruct, GDA_META_DB_TABLE,
table_catalog, table_schema, table_name, &lerror);
- g_print ("%s () mstruct=%p (%s,%s,%s)=>%p\n", __FUNCTION__, canvas->priv->mstruct,
- g_value_get_string (table_catalog),
- g_value_get_string (table_schema),
- g_value_get_string (table_name), mtable);
if (mtable) {
gdouble x = 0, y = 0;
GooCanvasItem *table_item;
diff --git a/tools/browser/data-manager/data-console.c b/tools/browser/data-manager/data-console.c
index a4a64ab..7dc6886 100644
--- a/tools/browser/data-manager/data-console.c
+++ b/tools/browser/data-manager/data-console.c
@@ -794,34 +794,6 @@ add_source_clicked_cb (GtkButton *button, DataConsole *dconsole)
gtk_get_current_event_time ());
}
-static GtkWidget *
-create_widget (DataConsole *dconsole, GArray *sources_array, GError **error)
-{
- GtkWidget *sw, *vp, *dwid;
-
- if (! sources_array) {
- g_set_error (error, 0, 0,
- _("No data source defined"));
- return NULL;
- }
-
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_NONE);
-
- vp = gtk_viewport_new (NULL, NULL);
- gtk_viewport_set_shadow_type (GTK_VIEWPORT (vp), GTK_SHADOW_NONE);
- gtk_container_add (GTK_CONTAINER (sw), vp);
-
- dwid = data_widget_new (sources_array);
- gtk_container_add (GTK_CONTAINER (vp), dwid);
- g_object_set_data ((GObject*) sw, "data-widget", dwid);
-
- gtk_widget_show_all (vp);
- return sw;
-}
-
/*
* UI actions
*/
@@ -843,36 +815,33 @@ compose_mode_toggled_cb (GtkToggleAction *action, DataConsole *dconsole)
pagenb = gtk_notebook_get_current_page (GTK_NOTEBOOK (dconsole->priv->main_notebook));
if (pagenb == MAIN_PAGE_EDITORS) {
/* Get Data sources */
- GArray *sources_array;
- GError *lerror = NULL;
- sources_array = data_source_manager_get_sources_array (dconsole->priv->mgr, &lerror);
- if (sources_array) {
- if (dconsole->priv->data) {
- /* destroy existing data widgets */
- gtk_widget_destroy (dconsole->priv->data);
- dconsole->priv->data = NULL;
- }
-
- GtkWidget *wid;
- wid = create_widget (dconsole, sources_array, &lerror);
- data_source_manager_destroy_sources_array (sources_array);
- if (wid) {
- dconsole->priv->data = wid;
- gtk_box_pack_start (GTK_BOX (dconsole->priv->data_box), wid, TRUE, TRUE, 0);
- gtk_widget_show (wid);
- pagenb = MAIN_PAGE_DATA;
- }
- }
- if (lerror) {
- browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) dconsole),
- lerror && lerror->message ? lerror->message :
- _("Error parsing XML specifications"));
- g_clear_error (&lerror);
- }
- if (pagenb == MAIN_PAGE_EDITORS) {
- dconsole->priv->toggling = TRUE;
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+ pagenb = MAIN_PAGE_DATA;
+ if (dconsole->priv->data) {
+ /* destroy existing data widgets */
+ gtk_widget_destroy (dconsole->priv->data);
+ dconsole->priv->data = NULL;
}
+
+ GtkWidget *sw, *vp, *dwid;
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_NONE);
+
+ vp = gtk_viewport_new (NULL, NULL);
+ gtk_viewport_set_shadow_type (GTK_VIEWPORT (vp), GTK_SHADOW_NONE);
+ gtk_container_add (GTK_CONTAINER (sw), vp);
+
+ dwid = data_widget_new (dconsole->priv->mgr);
+ gtk_container_add (GTK_CONTAINER (vp), dwid);
+ g_object_set_data ((GObject*) sw, "data-widget", dwid);
+
+ gtk_widget_show_all (vp);
+
+ dconsole->priv->data = sw;
+ gtk_box_pack_start (GTK_BOX (dconsole->priv->data_box), sw, TRUE, TRUE, 0);
+ gtk_widget_show (sw);
}
else {
/* simply change the current page */
@@ -881,9 +850,10 @@ compose_mode_toggled_cb (GtkToggleAction *action, DataConsole *dconsole)
if (pagenb == MAIN_PAGE_DATA)
browser_window_show_notice_printf (BROWSER_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) dconsole)),
- "data-manager-exec-mode-switched",
- _("Switching to execution mode. Hit the Escape key "
- "to return to the compose mode"));
+ GTK_MESSAGE_INFO,
+ "data-manager-exec-mode-switched",
+ _("Switching to execution mode. Hit the Escape key "
+ "to return to the compose mode"));
gtk_notebook_set_current_page (GTK_NOTEBOOK (dconsole->priv->main_notebook), pagenb);
}
diff --git a/tools/browser/data-manager/data-source-manager.c b/tools/browser/data-manager/data-source-manager.c
index 0986773..375c67b 100644
--- a/tools/browser/data-manager/data-source-manager.c
+++ b/tools/browser/data-manager/data-source-manager.c
@@ -47,6 +47,8 @@ static void data_source_manager_class_init (DataSourceManagerClass *klass);
static void data_source_manager_init (DataSourceManager *mgr);
static void data_source_manager_dispose (GObject *object);
+static void ensure_source_unique_id (DataSourceManager *mgr, DataSource *source);
+
/* get a pointer to the parents to be able to call their destructor */
static GObjectClass *parent_class = NULL;
@@ -120,13 +122,64 @@ data_source_manager_init (DataSourceManager *mgr)
mgr->priv->emit_changes = TRUE;
}
+/*
+ * find_data_source
+ *
+ * Finds a data source which id is @id, exclusing @excl_source if not %NULL
+ */
+static DataSource *
+find_data_source (DataSourceManager *mgr, const gchar *id, DataSource *excl_source)
+{
+ GSList *list;
+ g_return_val_if_fail (id && *id, NULL);
+ for (list = mgr->priv->sources_list; list; list = list->next) {
+ DataSource *source = (DataSource *) list->data;
+ if (excl_source && (source == excl_source))
+ continue;
+ const gchar *sid = data_source_get_id (source);
+ if (!sid) {
+ g_warning ("Data source has no ID!");
+ continue;
+ }
+ if (!strcmp (id, sid))
+ return source;
+ }
+ return NULL;
+}
+
static void
source_changed_cb (DataSource *source, DataSourceManager *mgr)
{
+ ensure_source_unique_id (mgr, source);
g_signal_emit (mgr, data_source_manager_signals[SOURCE_CHANGED], 0, source);
}
static void
+ensure_source_unique_id (DataSourceManager *mgr, DataSource *source)
+{
+ /* make sure the source's ID is unique among @mgr's data sources */
+ DataSource *es;
+ es = find_data_source (mgr, data_source_get_id (source), source);
+ if (es) {
+ gint i;
+ for (i = 1; ; i++) {
+ gchar *tmp;
+ tmp = g_strdup_printf ("%s_%d", data_source_get_id (source), i);
+ if (! find_data_source (mgr, tmp, NULL)) {
+ g_signal_handlers_block_by_func (source,
+ G_CALLBACK (source_changed_cb), mgr);
+ data_source_set_id (source, tmp);
+ g_signal_handlers_unblock_by_func (source,
+ G_CALLBACK (source_changed_cb), mgr);
+ g_free (tmp);
+ break;
+ }
+ g_free (tmp);
+ }
+ }
+}
+
+static void
data_source_manager_dispose (GObject *object)
{
DataSourceManager *mgr;
@@ -225,6 +278,8 @@ source_depends_on (DataSource *source1, DataSource *source2)
* data_source_manager_add_source
* @mgr:
* @source:
+ *
+ * @source is referenced by @mgr
*/
void
data_source_manager_add_source (DataSourceManager *mgr, DataSource *source)
@@ -237,6 +292,7 @@ data_source_manager_add_source (DataSourceManager *mgr, DataSource *source)
#ifdef DEBUG_SOURCES_SORT
g_print ("Adding source [%s]\n", data_source_get_title (source));
#endif
+ ensure_source_unique_id (mgr, source);
if (! mgr->priv->sources_list)
mgr->priv->sources_list = g_slist_append (NULL, g_object_ref (source));
else {
@@ -319,7 +375,7 @@ data_source_manager_add_source (DataSourceManager *mgr, DataSource *source)
void
data_source_manager_replace_all (DataSourceManager *mgr, const GSList *sources_list)
{
- GSList *list;
+ const GSList *list;
g_return_if_fail (IS_DATA_SOURCE_MANAGER (mgr));
mgr->priv->emit_changes = FALSE;
diff --git a/tools/browser/data-manager/data-source.c b/tools/browser/data-manager/data-source.c
index b53efaf..fa0c246 100644
--- a/tools/browser/data-manager/data-source.c
+++ b/tools/browser/data-manager/data-source.c
@@ -303,11 +303,13 @@ data_source_new_from_xml_node (BrowserConnection *bcnc, xmlNodePtr node, GError
xmlChar *prop;
prop = xmlGetProp (node, BAD_CAST "title");
if (prop) {
+ g_free (source->priv->title);
source->priv->title = g_strdup ((gchar*) prop);
xmlFree (prop);
}
prop = xmlGetProp (node, BAD_CAST "id");
if (prop) {
+ g_free (source->priv->id);
source->priv->id = g_strdup ((gchar*) prop);
xmlFree (prop);
}
@@ -421,8 +423,11 @@ init_from_table_node (DataSource *source, xmlNodePtr node, GError **error)
fk_table = xmlGetProp (subnode, BAD_CAST "foreign_key_table");
id = xmlGetProp (subnode, BAD_CAST "id");
- data_source_add_dependendency (source, (gchar *) fk_table, (gchar*) id, error);
- xmlFree (fk_table);
+ if (fk_table &&
+ ! data_source_add_dependendency (source, (gchar *) fk_table, (gchar*) id, error))
+ retval = FALSE;
+ if (fk_table)
+ xmlFree (fk_table);
if (id)
xmlFree (id);
break;
@@ -464,6 +469,7 @@ data_source_add_dependendency (DataSource *source, const gchar *table,
/* find foreign key to linked table */
GdaMetaTableForeignKey *fk = NULL;
GSList *list;
+ gboolean reverse = FALSE;
for (list = mtable->fk_list; list; list = list->next) {
if (GDA_META_TABLE_FOREIGN_KEY (list->data)->depend_on == GDA_META_DB_OBJECT (mlinked)) {
fk = GDA_META_TABLE_FOREIGN_KEY (list->data);
@@ -471,6 +477,15 @@ data_source_add_dependendency (DataSource *source, const gchar *table,
}
}
if (!fk) {
+ for (list = mlinked->fk_list; list; list = list->next) {
+ if (GDA_META_TABLE_FOREIGN_KEY (list->data)->depend_on == GDA_META_DB_OBJECT (mtable)) {
+ fk = GDA_META_TABLE_FOREIGN_KEY (list->data);
+ reverse = TRUE;
+ break;
+ }
+ }
+ }
+ if (!fk) {
g_set_error (error, 0, 0,
_("Could not find any foreign key to \"%s\""), table);
return FALSE;
@@ -484,19 +499,33 @@ data_source_add_dependendency (DataSource *source, const gchar *table,
else if (fk->cols_nb == 1) {
gchar *tmp;
GdaMetaTableColumn *col;
- const GdaSqlBuilderId id1 = gda_sql_builder_add_id (source->priv->builder,
- fk->fk_names_array [0]);
- tmp = g_strdup_printf ("%s %s", id ? id : table, fk->ref_pk_names_array [0]);
-
- col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
- fk->ref_pk_cols_array [0] - 1));
- g_assert (col);
- const GdaSqlBuilderId id2 = gda_sql_builder_add_param (source->priv->builder, tmp,
- col->gtype, FALSE);
- g_free (tmp);
- const GdaSqlBuilderId id_cond = gda_sql_builder_add_cond (source->priv->builder,
- GDA_SQL_OPERATOR_TYPE_EQ,
- id1, id2, 0);
+ GdaSqlBuilderId id1, id2, id_cond;
+ if (reverse) {
+ id1 = gda_sql_builder_add_id (source->priv->builder, fk->ref_pk_names_array [0]);
+ tmp = g_strdup_printf ("%s %s", id ? id : table, fk->fk_names_array [0]);
+
+ col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
+ fk->fk_cols_array [0] - 1));
+ g_assert (col);
+ id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
+ g_free (tmp);
+ }
+ else {
+ id1 = gda_sql_builder_add_id (source->priv->builder, fk->fk_names_array [0]);
+ tmp = g_strdup_printf ("%s %s", id ? id : table, fk->ref_pk_names_array [0]);
+
+ col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
+ fk->ref_pk_cols_array [0] - 1));
+ g_assert (col);
+ id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
+ g_free (tmp);
+ id_cond = gda_sql_builder_add_cond (source->priv->builder,
+ GDA_SQL_OPERATOR_TYPE_EQ,
+ id1, id2, 0);
+ }
+ id_cond = gda_sql_builder_add_cond (source->priv->builder,
+ GDA_SQL_OPERATOR_TYPE_EQ,
+ id1, id2, 0);
gda_sql_builder_set_where (source->priv->builder, id_cond);
}
else {
@@ -505,20 +534,32 @@ data_source_add_dependendency (DataSource *source, const gchar *table,
GdaMetaTableColumn *col;
GdaSqlBuilderId andid;
GdaSqlBuilderId *op_ids;
+ GdaSqlBuilderId id1, id2;
op_ids = g_new (GdaSqlBuilderId, fk->cols_nb);
for (i = 0; i < fk->cols_nb; i++) {
- const GdaSqlBuilderId id1 = gda_sql_builder_add_id (source->priv->builder,
- fk->fk_names_array [i]);
- tmp = g_strdup_printf ("%s %s", id ? id : table, fk->ref_pk_names_array [i]);
-
- col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
- fk->ref_pk_cols_array [i] - 1));
- g_assert (col);
- const GdaSqlBuilderId id2 = gda_sql_builder_add_param (source->priv->builder,
- tmp, col->gtype, FALSE);
- g_free (tmp);
- op_ids [i] = gda_sql_builder_add_cond (source->priv->builder, GDA_SQL_OPERATOR_TYPE_EQ,
+ if (reverse) {
+ id1 = gda_sql_builder_add_id (source->priv->builder, fk->ref_pk_names_array [i]);
+ tmp = g_strdup_printf ("%s %s", id ? id : table, fk->fk_names_array [i]);
+
+ col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
+ fk->fk_cols_array [i] - 1));
+ g_assert (col);
+ id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
+ g_free (tmp);
+ }
+ else {
+ id1 = gda_sql_builder_add_id (source->priv->builder, fk->fk_names_array [i]);
+ tmp = g_strdup_printf ("%s %s", id ? id : table, fk->ref_pk_names_array [i]);
+
+ col = GDA_META_TABLE_COLUMN (g_slist_nth_data (mlinked->columns,
+ fk->ref_pk_cols_array [i] - 1));
+ g_assert (col);
+ id2 = gda_sql_builder_add_param (source->priv->builder, tmp, col->gtype, FALSE);
+ g_free (tmp);
+ }
+ op_ids [i] = gda_sql_builder_add_cond (source->priv->builder,
+ GDA_SQL_OPERATOR_TYPE_EQ,
id1, id2, 0);
}
andid = gda_sql_builder_add_cond_v (source->priv->builder, GDA_SQL_OPERATOR_TYPE_AND,
@@ -888,6 +929,8 @@ data_source_set_id (DataSource *source, const gchar * id)
g_free (source->priv->id);
if (id)
source->priv->id = g_strdup (id);
+ else
+ source->priv->id = NULL;
g_signal_emit (source, data_source_signals [CHANGED], 0);
}
@@ -922,6 +965,8 @@ data_source_set_title (DataSource *source, const gchar * title)
g_free (source->priv->title);
if (title)
source->priv->title = g_strdup (title);
+ else
+ source->priv->title = NULL;
g_signal_emit (source, data_source_signals [CHANGED], 0);
}
@@ -971,8 +1016,8 @@ data_source_set_table (DataSource *source, const gchar *table, GError **error)
g_free (source->priv->impl_title);
source->priv->impl_title = g_strdup_printf (_("Contents of '%s'"), table);
- g_free (source->priv->id);
- source->priv->id = g_strdup ((gchar*) table);
+ if (! source->priv->id)
+ source->priv->id = g_strdup ((gchar*) table);
/* build statement */
GSList *list;
@@ -1148,6 +1193,11 @@ compute_stmt_and_params (DataSource *source)
g_object_unref (source->priv->stmt);
source->priv->stmt = gda_sql_builder_get_statement (source->priv->builder, NULL);
compute_import_params (source);
+
+ gchar *sql;
+ sql = gda_statement_to_sql (source->priv->stmt, NULL, NULL);
+ g_print ("[%s]\n", sql);
+ g_free (sql);
}
static void
diff --git a/tools/browser/data-manager/data-widget.c b/tools/browser/data-manager/data-widget.c
index a20667d..9cc8483 100644
--- a/tools/browser/data-manager/data-widget.c
+++ b/tools/browser/data-manager/data-widget.c
@@ -27,7 +27,11 @@
#include "../browser-spinner.h"
#include "../common/ui-formgrid.h"
#include "../browser-window.h"
+#include "../support.h"
+/*
+ * The DataPart structure represents the execution of a single DataSource
+ */
typedef struct {
DataWidget *dwid;
DataSource *source;
@@ -44,14 +48,19 @@ typedef struct {
GSList *dep_parts; /* list of DataPart which need to be re-run when anything in @export_data
* changes */
+ GtkWidget *menu;
} DataPart;
#define DATA_PART(x) ((DataPart*)(x))
static DataPart *data_part_find (DataWidget *dwid, DataSource *source);
-static void data_part_free (DataPart *part);
+static void data_part_free (DataPart *part, GSList *all_parts);
struct _DataWidgetPrivate {
- GtkWidget *hpaned;
+ DataSourceManager *mgr;
+ GtkWidget *top_nb; /* page 0 => error, page 1 => contents */
+ GtkWidget *info_label;
+ GtkWidget *contents_page_vbox;
+ GtkWidget *contents_page;
GSList *parts;
};
@@ -59,6 +68,8 @@ static void data_widget_class_init (DataWidgetClass *klass);
static void data_widget_init (DataWidget *dwid, DataWidgetClass *klass);
static void data_widget_dispose (GObject *object);
+static void mgr_list_changed_cb (DataSourceManager *mgr, DataWidget *dwid);
+
static GObjectClass *parent_class = NULL;
/*
@@ -82,6 +93,36 @@ data_widget_init (DataWidget *dwid, DataWidgetClass *klass)
/* allocate private structure */
dwid->priv = g_new0 (DataWidgetPrivate, 1);
+
+ /* init Widgets's structure */
+ dwid->priv->top_nb = gtk_notebook_new ();
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (dwid->priv->top_nb), FALSE);
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (dwid->priv->top_nb), FALSE);
+ gtk_box_pack_start (GTK_BOX (dwid), dwid->priv->top_nb, TRUE, TRUE, 0);
+
+ /* error page */
+#if GTK_CHECK_VERSION (2,18,0)
+ GtkWidget *info;
+ info = gtk_info_bar_new ();
+ gtk_notebook_append_page (GTK_NOTEBOOK (dwid->priv->top_nb), info, NULL);
+ dwid->priv->info_label = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (dwid->priv->info_label), 0., -1);
+ gtk_label_set_ellipsize (GTK_LABEL (dwid->priv->info_label), PANGO_ELLIPSIZE_END);
+ gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (info))),
+ dwid->priv->info_label);
+#else
+ dwid->priv->info = gtk_label_new ("");
+ gtk_notebook_append_page (GTK_NOTEBOOK (dwid->priv->top_nb), info);
+ dwid->priv->info_label = dwid->priv->info;
+#endif
+
+ /* contents page */
+ GtkWidget *vbox;
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_notebook_append_page (GTK_NOTEBOOK (dwid->priv->top_nb), vbox, NULL);
+ dwid->priv->contents_page_vbox = vbox;
+
+ gtk_widget_show_all (dwid->priv->top_nb);
}
GType
@@ -107,12 +148,23 @@ data_widget_get_type (void)
}
static void
+data_part_free_func (DataPart *part)
+{
+ data_part_free (part, NULL);
+}
+
+static void
data_widget_dispose (GObject *object)
{
DataWidget *dwid = (DataWidget*) object;
if (dwid->priv) {
+ if (dwid->priv->mgr) {
+ g_signal_handlers_disconnect_by_func (dwid->priv->mgr,
+ G_CALLBACK (mgr_list_changed_cb), dwid);
+ g_object_unref (dwid->priv->mgr);
+ }
if (dwid->priv->parts) {
- g_slist_foreach (dwid->priv->parts, (GFunc) data_part_free, NULL);
+ g_slist_foreach (dwid->priv->parts, (GFunc) data_part_free_func, NULL);
g_slist_free (dwid->priv->parts);
}
g_free (dwid->priv);
@@ -123,11 +175,27 @@ data_widget_dispose (GObject *object)
static void source_exec_started_cb (DataSource *source, DataPart *part);
static void source_exec_finished_cb (DataSource *source, GError *error, DataPart *part);
+static void data_source_menu_clicked_cb (GtkButton *button, DataPart *part);
static DataPart *
-create_part (DataWidget *dwid, DataSource *source)
+create_or_reuse_part (DataWidget *dwid, DataSource *source, gboolean *out_reused)
{
+
DataPart *part;
+ *out_reused = FALSE;
+
+ part = data_part_find (dwid, source);
+ if (part) {
+ GtkWidget *parent;
+ parent = gtk_widget_get_parent (part->top);
+ if (parent) {
+ g_object_ref ((GObject*) part->top);
+ gtk_container_remove (GTK_CONTAINER (parent), part->top);
+ }
+ *out_reused = TRUE;
+ return part;
+ }
+
part = g_new0 (DataPart, 1);
part->dwid = dwid;
part->source = g_object_ref (source);
@@ -141,23 +209,41 @@ create_part (DataWidget *dwid, DataSource *source)
GtkWidget *vbox;
vbox = gtk_vbox_new (FALSE, 0);
part->top = vbox;
+ g_object_ref_sink ((GObject*) part->top);
- GtkWidget *header;
+ GtkWidget *header, *label, *button, *image;
const gchar *cstr;
- header = gtk_label_new ("");
+
+ header = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), header, FALSE, FALSE, 0);
+
+ label = gtk_label_new ("");
cstr = data_source_get_title (source);
if (cstr) {
gchar *tmp;
tmp = g_markup_printf_escaped ("<b><small>%s</small></b>", cstr);
- gtk_label_set_markup (GTK_LABEL (header), tmp);
+ gtk_label_set_markup (GTK_LABEL (label), tmp);
g_free (tmp);
}
else
- gtk_label_set_markup (GTK_LABEL (header), "<b><small> </small></b>");
- gtk_misc_set_alignment (GTK_MISC (header), 0., -1);
- gtk_widget_set_size_request (header, 150, -1);
- gtk_label_set_ellipsize (GTK_LABEL (header), PANGO_ELLIPSIZE_END);
- gtk_box_pack_start (GTK_BOX (vbox), header, FALSE, FALSE, 0);
+ gtk_label_set_markup (GTK_LABEL (label), "<b><small> </small></b>");
+ gtk_misc_set_alignment (GTK_MISC (label), 0., -1);
+ gtk_widget_set_size_request (label, 150, -1);
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+ gtk_box_pack_start (GTK_BOX (header), label, TRUE, TRUE, 0);
+
+ image = gtk_image_new_from_pixbuf (browser_get_pixbuf_icon (BROWSER_ICON_MENU_INDICATOR));
+ button = gtk_button_new ();
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
+ gtk_widget_set_name (button, "browser-tab-close-button");
+ gtk_widget_set_tooltip_text (button, _("Link to other data"));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (data_source_menu_clicked_cb), part);
+
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_container_set_border_width (GTK_CONTAINER (button), 0);
+ gtk_box_pack_start (GTK_BOX (header), button, FALSE, FALSE, 0);
GtkWidget *nb, *page;
nb = gtk_notebook_new ();
@@ -222,43 +308,313 @@ pack_in_paned_list (GSList *paned_list, gint length, gint pos, GtkWidget *wid)
}
}
-/**
- * data_widget_new
- *
- * Returns: the newly created widget.
+static void
+remove_data_source_mitem_activated_cb (GtkMenuItem *mitem, DataPart *part)
+{
+ data_source_manager_remove_source (part->dwid->priv->mgr, part->source);
+}
+
+static void
+add_data_source_mitem_activated_cb (GtkMenuItem *mitem, DataPart *part)
+{
+ DataSource *source;
+ GError *lerror = NULL;
+ xmlNodePtr sourcespec;
+ BrowserConnection *bcnc;
+
+ bcnc = data_source_manager_get_browser_cnc (part->dwid->priv->mgr);
+ sourcespec = (xmlNodePtr) g_object_get_data ((GObject*) mitem, "xml");
+ source = data_source_new_from_xml_node (bcnc, sourcespec, &lerror);
+ if (source) {
+ data_source_manager_add_source (part->dwid->priv->mgr, source);
+ g_object_unref (source);
+ g_print ("Source Added!\n");
+ }
+ else {
+ BrowserWindow *bwin;
+ bwin = BROWSER_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (part->dwid)));
+ browser_window_show_notice_printf (bwin, GTK_MESSAGE_ERROR, "data-widget-add-new-source",
+ _("Error adding new data source: %s"),
+ lerror && lerror->message ? lerror->message :
+ _("No detail"));
+ g_clear_error (&lerror);
+ }
+
+#ifdef GDA_DEBUG_NO
+ xmlBufferPtr buffer;
+ buffer = xmlBufferCreate ();
+ xmlNodeDump (buffer, NULL, sourcespec, 0, 1);
+ g_print ("Source to ADD: [%s]\n", (gchar *) xmlBufferContent (buffer));
+ xmlBufferFree (buffer);
+#endif
+}
+
+static gchar *compute_fk_dependency (GdaMetaTableForeignKey *fkey, GSList *selfields, gboolean reverse,
+ DataPart *part, xmlNodePtr *out_sourcespec);
+static void
+data_source_menu_clicked_cb (GtkButton *button, DataPart *part)
+{
+ if (! part->menu) {
+ GtkWidget *menu, *mitem;
+ menu = gtk_menu_new ();
+ part->menu = menu;
+
+ mitem = gtk_menu_item_new_with_label (_("Remove data source"));
+ g_signal_connect (mitem, "activate",
+ G_CALLBACK (remove_data_source_mitem_activated_cb), part);
+ gtk_widget_show (mitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mitem);
+
+ GdaStatement *stmt;
+ stmt = data_source_get_statement (part->source);
+ if (gda_statement_get_statement_type (stmt) == GDA_SQL_STATEMENT_SELECT) {
+ GSList *fields = NULL, *flist;
+ GdaSqlStatement *sql_statement;
+ BrowserConnection *bcnc;
+ GHashTable *hash; /* key = a menu string, value= 0x1 */
+
+ g_object_get (G_OBJECT (stmt), "structure", &sql_statement, NULL);
+
+ bcnc = data_source_manager_get_browser_cnc (part->dwid->priv->mgr);
+ if (browser_connection_check_sql_statement_validify (bcnc, sql_statement, NULL))
+ fields = ((GdaSqlStatementSelect *) sql_statement->contents)->expr_list;
+
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ for (flist = fields; flist; flist = flist->next) {
+ GdaSqlSelectField *select_field = (GdaSqlSelectField*) flist->data;
+ if (!select_field->validity_meta_table_column)
+ continue;
+ GdaMetaDbObject *dbo;
+ GdaMetaTableColumn *field;
+ dbo = select_field->validity_meta_object;
+ field = select_field->validity_meta_table_column;
+ if (dbo->obj_type == GDA_META_DB_TABLE) {
+ GdaMetaTable *mtable;
+ mtable = GDA_META_TABLE (dbo);
+
+ GSList *fklist;
+ for (fklist = mtable->reverse_fk_list; fklist; fklist = fklist->next) {
+ GdaMetaTableForeignKey *fkey;
+ fkey = (GdaMetaTableForeignKey *) fklist->data;
+ gchar *tmp;
+ xmlNodePtr sourcespec = NULL;
+ if (fkey->meta_table->obj_type != GDA_META_DB_TABLE)
+ continue;
+ tmp = compute_fk_dependency (fkey, fields, FALSE,
+ part, &sourcespec);
+ if (!tmp)
+ continue;
+ if (g_hash_table_lookup (hash, tmp)) {
+ g_free (tmp);
+ continue;
+ }
+
+ mitem = gtk_menu_item_new_with_label (tmp);
+ g_object_set_data_full ((GObject*) mitem, "xml", sourcespec,
+ (GDestroyNotify) xmlFreeNode);
+ g_signal_connect (mitem, "activate",
+ G_CALLBACK (add_data_source_mitem_activated_cb),
+ part);
+ gtk_widget_show (mitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mitem);
+ g_hash_table_insert (hash, tmp, (gpointer) 0x1);
+ }
+ for (fklist = mtable->fk_list; fklist; fklist = fklist->next) {
+ GdaMetaTableForeignKey *fkey;
+ fkey = (GdaMetaTableForeignKey *) fklist->data;
+ gchar *tmp;
+ xmlNodePtr sourcespec = NULL;
+ if (fkey->depend_on->obj_type != GDA_META_DB_TABLE)
+ continue;
+ tmp = compute_fk_dependency (fkey, fields, TRUE,
+ part, &sourcespec);
+ if (!tmp)
+ continue;
+ if (g_hash_table_lookup (hash, tmp)) {
+ g_free (tmp);
+ continue;
+ }
+ mitem = gtk_menu_item_new_with_label (tmp);
+ g_object_set_data_full ((GObject*) mitem, "xml", sourcespec,
+ (GDestroyNotify) xmlFreeNode);
+ g_signal_connect (mitem, "activate",
+ G_CALLBACK (add_data_source_mitem_activated_cb),
+ part);
+ gtk_widget_show (mitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mitem);
+ g_hash_table_insert (hash, tmp, (gpointer) 0x1);
+ }
+ }
+ }
+ g_hash_table_destroy (hash);
+ gda_sql_statement_free (sql_statement);
+ }
+ }
+ gtk_menu_popup (GTK_MENU (part->menu), NULL, NULL,
+ NULL, NULL, 0,
+ gtk_get_current_event_time ());
+}
+
+/*
+ * Returns: a new list of #GdaSqlSelectField (which are already listed in @selfields), or %NULL
*/
-GtkWidget *
-data_widget_new (GArray *sources_array)
+static gchar *
+compute_fk_dependency (GdaMetaTableForeignKey *fkey, GSList *selfields, gboolean reverse,
+ DataPart *part, xmlNodePtr *out_sourcespec)
{
- DataWidget *dwid;
+ GString *string = NULL;
+ gint i;
+ gint *index_array;
+ GdaMetaTable *table;
- g_return_val_if_fail (sources_array, NULL);
- dwid = g_object_new (DATA_WIDGET_TYPE, NULL);
+ *out_sourcespec = NULL;
+
+ if (reverse) {
+ table = GDA_META_TABLE (fkey->meta_table);
+ index_array = fkey->fk_cols_array;
+ }
+ else {
+ table = GDA_META_TABLE (fkey->depend_on);
+ index_array = fkey->ref_pk_cols_array;
+ }
+ for (i = 0; i < fkey->cols_nb; i++) {
+ gint pos;
+ GdaMetaTableColumn *col;
+ pos = index_array[i] - 1;
+ col = g_slist_nth_data (table->columns, pos);
+
+ /* make sure @col is among @selfields */
+ GSList *flist;
+ gboolean found = FALSE;
+ for (flist = selfields; flist; flist = flist->next) {
+ GdaSqlSelectField *select_field = (GdaSqlSelectField*) flist->data;
+ if (!select_field->validity_meta_object ||
+ !select_field->validity_meta_table_column)
+ continue;
+ GdaMetaTableColumn *field;
+ field = select_field->validity_meta_table_column;
+ if (field == col) {
+ found = TRUE;
+ if (reverse) {
+ if (!string) {
+ string = g_string_new (_("Obtain referenced data in table "));
+ g_string_append_printf (string, "%s from ",
+ fkey->depend_on->obj_short_name);
+ }
+ else
+ g_string_append (string, ", ");
+ g_string_append_printf (string, "column n.%d (",
+ g_slist_position (selfields, flist) + 1);
+ if (select_field->as)
+ g_string_append (string, select_field->as);
+ else
+ g_string_append (string,
+ select_field->validity_meta_table_column->column_name);
+ g_string_append_c (string, ')');
+ }
+ else {
+ if (!string) {
+ string = g_string_new (_("List referencing data in "));
+ g_string_append_printf (string, "%s.",
+ fkey->meta_table->obj_short_name);
+ }
+ else
+ g_string_append (string, ", ");
+ g_string_append (string, fkey->fk_names_array [i]);
+ }
+ break;
+ }
+ }
+
+ if (! found) {
+ if (string) {
+ g_string_free (string, TRUE);
+ string = NULL;
+ }
+ break;
+ }
+ }
+
+ if (string) {
+ xmlNodePtr node, snode;
+ node = xmlNewNode (NULL, BAD_CAST "table");
+ xmlSetProp (node, BAD_CAST "name",
+ BAD_CAST (reverse ? GDA_META_DB_OBJECT (fkey->depend_on)->obj_short_name :
+ GDA_META_DB_OBJECT (fkey->meta_table)->obj_short_name));
+
+ snode = xmlNewChild (node, NULL, BAD_CAST "depend", NULL);
+ xmlSetProp (snode, BAD_CAST "foreign_key_table",
+ BAD_CAST GDA_META_DB_OBJECT (table)->obj_short_name);
+
+ xmlSetProp (snode, BAD_CAST "id", BAD_CAST data_source_get_id (part->source));
+ *out_sourcespec = node;
+ return g_string_free (string, FALSE);
+ }
+ else
+ return NULL;
+}
+
+static void
+update_layout (DataWidget *dwid)
+{
+ GSList *newparts_list = NULL;
+ GArray *sources_array;
+ GError *lerror = NULL;
+ GtkWidget *new_contents;
+
+ new_contents = gtk_vbox_new (FALSE, 0);
+
+ sources_array = data_source_manager_get_sources_array (dwid->priv->mgr, &lerror);
+ if (!sources_array) {
+ gchar *str;
+ if (lerror && lerror->message)
+ str = g_strdup_printf (_("Error: %s"), lerror->message);
+ else {
+ const GSList *list;
+ list = data_source_manager_get_sources (dwid->priv->mgr);
+ if (list)
+ str = g_strdup_printf (_("Error: %s"), _("No detail"));
+ else
+ str = g_strdup_printf (_("Error: %s"), _("No data source defined"));
+ }
+ g_clear_error (&lerror);
+ gtk_label_set_text (GTK_LABEL (dwid->priv->info_label), str);
+ g_free (str);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (dwid->priv->top_nb), 0);
+ goto cleanups;
+ }
if (sources_array->len == 1) {
GArray *subarray = g_array_index (sources_array, GArray*, 0);
if (subarray->len == 1) {
DataPart *part;
+ gboolean reused;
DataSource *source;
source = g_array_index (subarray, DataSource*, 0);
- part = create_part (dwid, source);
- gtk_box_pack_start (GTK_BOX (dwid), part->top, TRUE, TRUE, 0);
-
- data_source_execute (source, NULL);
+ part = create_or_reuse_part (dwid, source, &reused);
+ gtk_box_pack_start (GTK_BOX (new_contents), part->top, TRUE, TRUE, 0);
+ g_object_unref ((GObject*) part->top);
+ newparts_list = g_slist_prepend (newparts_list, part);
+ if (!reused)
+ data_source_execute (source, NULL);
}
else {
GSList *paned_list;
gint i;
paned_list = make_paned_list (subarray->len, FALSE);
- gtk_box_pack_start (GTK_BOX (dwid), GTK_WIDGET (paned_list->data), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (new_contents),
+ GTK_WIDGET (paned_list->data), TRUE, TRUE, 0);
for (i = 0; i < subarray->len; i++) {
DataPart *part;
+ gboolean reused;
DataSource *source;
source = g_array_index (subarray, DataSource*, i);
- part = create_part (dwid, source);
+ part = create_or_reuse_part (dwid, source, &reused);
pack_in_paned_list (paned_list, subarray->len, i, part->top);
-
- data_source_execute (source, NULL);
+ g_object_unref ((GObject*) part->top);
+ newparts_list = g_slist_prepend (newparts_list, part);
+ if (!reused)
+ data_source_execute (source, NULL);
}
g_slist_free (paned_list);
}
@@ -266,20 +622,24 @@ data_widget_new (GArray *sources_array)
else {
GSList *top_paned_list;
gint j;
-
+
top_paned_list = make_paned_list (sources_array->len, TRUE);
- gtk_box_pack_start (GTK_BOX (dwid), GTK_WIDGET (top_paned_list->data), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (new_contents),
+ GTK_WIDGET (top_paned_list->data), TRUE, TRUE, 0);
for (j = 0; j < sources_array->len; j++) {
GArray *subarray = g_array_index (sources_array, GArray*, j);
DataSource *source;
-
+
if (subarray->len == 1) {
DataPart *part;
+ gboolean reused;
source = g_array_index (subarray, DataSource*, 0);
- part = create_part (dwid, source);
+ part = create_or_reuse_part (dwid, source, &reused);
pack_in_paned_list (top_paned_list, sources_array->len, j, part->top);
-
- data_source_execute (source, NULL);
+ g_object_unref ((GObject*) part->top);
+ newparts_list = g_slist_prepend (newparts_list, part);
+ if (!reused)
+ data_source_execute (source, NULL);
}
else {
GSList *paned_list;
@@ -289,24 +649,90 @@ data_widget_new (GArray *sources_array)
GTK_WIDGET (paned_list->data));
for (i = 0; i < subarray->len; i++) {
DataPart *part;
+ gboolean reused;
source = g_array_index (subarray, DataSource*, i);
- part = create_part (dwid, source);
+ part = create_or_reuse_part (dwid, source, &reused);
pack_in_paned_list (paned_list, subarray->len, i, part->top);
-
- data_source_execute (source, NULL);
+ g_object_unref ((GObject*) part->top);
+ newparts_list = g_slist_prepend (newparts_list, part);
+ if (!reused)
+ data_source_execute (source, NULL);
}
g_slist_free (paned_list);
}
}
g_slist_free (top_paned_list);
}
+ data_source_manager_destroy_sources_array (sources_array);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (dwid->priv->top_nb), 1);
+
+ cleanups:
+ {
+ GSList *list, *nlist = NULL;
+ for (list = dwid->priv->parts; list; list = list->next) {
+ if (!g_slist_find (newparts_list, list->data)) {
+ /* useless part */
+ data_part_free ((DataPart *) list->data, dwid->priv->parts);
+ }
+ else
+ nlist = g_slist_prepend (nlist, list->data);
+ }
+ g_slist_free (newparts_list);
+ g_slist_free (dwid->priv->parts);
+ dwid->priv->parts = g_slist_reverse (nlist);
+ }
+
+ gtk_box_pack_start (GTK_BOX (dwid->priv->contents_page_vbox), new_contents, TRUE, TRUE, 0);
+ gtk_widget_show_all (new_contents);
+ if (dwid->priv->contents_page)
+ gtk_widget_destroy (dwid->priv->contents_page);
+ dwid->priv->contents_page = new_contents;
+}
+static void
+mgr_list_changed_cb (DataSourceManager *mgr, DataWidget *dwid)
+{
+ update_layout (dwid);
+}
+
+/**
+ * data_widget_new
+ *
+ * Returns: the newly created widget.
+ */
+GtkWidget *
+data_widget_new (DataSourceManager *mgr)
+{
+ DataWidget *dwid;
+
+ g_return_val_if_fail (IS_DATA_SOURCE_MANAGER (mgr), NULL);
+
+ dwid = g_object_new (DATA_WIDGET_TYPE, NULL);
+ dwid->priv->mgr = DATA_SOURCE_MANAGER (mgr);
+ g_object_ref ((GObject*) dwid->priv->mgr);
+ g_signal_connect (mgr, "list_changed",
+ G_CALLBACK (mgr_list_changed_cb), dwid);
+
+ update_layout (dwid);
return GTK_WIDGET (dwid);
}
static void
-data_part_free (DataPart *part)
+data_part_free (DataPart *part, GSList *all_parts)
{
+ if (all_parts) {
+ GSList *list;
+ for (list = all_parts; list; list = list->next) {
+ DataPart *apart = (DataPart *) list->data;
+ if (apart == part)
+ continue;
+ apart->dep_parts = g_slist_remove_all (apart->dep_parts, part);
+ }
+ }
+
+ if (part->top)
+ gtk_widget_destroy (part->top);
+
if (part->source) {
g_signal_handlers_disconnect_by_func (part->source,
G_CALLBACK (source_exec_started_cb), part);
@@ -319,6 +745,8 @@ data_part_free (DataPart *part)
g_object_unref (part->export_data);
if (part->dep_parts)
g_slist_free (part->dep_parts);
+ if (part->menu)
+ gtk_widget_destroy (part->menu);
g_free (part);
}
@@ -351,89 +779,89 @@ source_exec_finished_cb (DataSource *source, GError *error, DataPart *part)
#ifdef GDA_DEBUG_NO
g_print ("==== Execution of source [%s] finished\n", data_source_get_title (part->source));*/
#endif
- if (error) {
- gchar *tmp;
- tmp = g_markup_printf_escaped ("\n<b>Error:\n</b>%s",
- error->message ? error->message : _("Error: no detail"));
- if (! part->error_widget) {
- part->error_widget = gtk_label_new ("");
- gtk_misc_set_alignment (GTK_MISC (part->error_widget), 0., 0.);
- part->error_widget_page = gtk_notebook_append_page (part->nb, part->error_widget,
- NULL);
- gtk_widget_show (part->error_widget);
+ if (error) {
+ gchar *tmp;
+ tmp = g_markup_printf_escaped ("\n<b>Error:\n</b>%s",
+ error->message ? error->message : _("Error: no detail"));
+ if (! part->error_widget) {
+ part->error_widget = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (part->error_widget), 0., 0.);
+ part->error_widget_page = gtk_notebook_append_page (part->nb, part->error_widget,
+ NULL);
+ gtk_widget_show (part->error_widget);
+ }
+ gtk_label_set_markup (GTK_LABEL (part->error_widget), tmp);
+ g_free (tmp);
+ gtk_notebook_set_current_page (part->nb, part->error_widget_page);
+ return;
}
- gtk_label_set_markup (GTK_LABEL (part->error_widget), tmp);
- g_free (tmp);
- gtk_notebook_set_current_page (part->nb, part->error_widget_page);
- return;
- }
- if (! part->data_widget) {
- GtkWidget *cwid;
- BrowserConnection *bcnc;
- bcnc = browser_window_get_connection ((BrowserWindow*) gtk_widget_get_toplevel ((GtkWidget*) part->dwid));
- cwid = (GtkWidget*) data_source_create_grid (part->source);
- ui_formgrid_handle_user_prefs (UI_FORMGRID (cwid), bcnc,
- data_source_get_statement (part->source));
-
- wid = (GtkWidget*) ui_formgrid_get_grid_widget (UI_FORMGRID (cwid));
- part->data_widget = wid;
- part->data_widget_page = gtk_notebook_append_page (part->nb, cwid, NULL);
- gtk_widget_show (cwid);
+ if (! part->data_widget) {
+ GtkWidget *cwid;
+ BrowserConnection *bcnc;
+ bcnc = browser_window_get_connection ((BrowserWindow*) gtk_widget_get_toplevel ((GtkWidget*) part->dwid));
+ cwid = (GtkWidget*) data_source_create_grid (part->source);
+ ui_formgrid_handle_user_prefs (UI_FORMGRID (cwid), bcnc,
+ data_source_get_statement (part->source));
+
+ wid = (GtkWidget*) ui_formgrid_get_grid_widget (UI_FORMGRID (cwid));
+ part->data_widget = wid;
+ part->data_widget_page = gtk_notebook_append_page (part->nb, cwid, NULL);
+ gtk_widget_show (cwid);
#ifdef GDA_DEBUG_NO
- g_print ("Creating data widget for source [%s]\n",
- data_source_get_title (part->source));
+ g_print ("Creating data widget for source [%s]\n",
+ data_source_get_title (part->source));
#endif
- /* compute part->export_data */
- GArray *export_names;
- export_names = data_source_get_export_names (part->source);
- if (export_names && (export_names->len > 0)) {
- GSList *holders = NULL;
- GdaDataModel *model;
- GHashTable *export_columns;
- gint i;
- GdaDataModelIter *iter;
-
- iter = gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (wid));
- g_object_get (wid, "model", &model, NULL);
-
- export_columns = data_source_get_export_columns (part->source);
- for (i = 0; i < export_names->len; i++) {
- gint col;
- GdaHolder *bindto;
- col = GPOINTER_TO_INT (g_hash_table_lookup (export_columns,
- g_array_index (export_names,
- gchar*, i))) - 1;
- bindto = gda_data_model_iter_get_holder_for_field (iter, col);
- if (bindto) {
- GdaHolder *holder;
- holder = gda_holder_copy (bindto);
- g_object_set ((GObject*) holder, "id",
- g_array_index (export_names, gchar*, i), NULL);
- holders = g_slist_prepend (holders, holder);
+ /* compute part->export_data */
+ GArray *export_names;
+ export_names = data_source_get_export_names (part->source);
+ if (export_names && (export_names->len > 0)) {
+ GSList *holders = NULL;
+ GdaDataModel *model;
+ GHashTable *export_columns;
+ gint i;
+ GdaDataModelIter *iter;
+
+ iter = gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (wid));
+ g_object_get (wid, "model", &model, NULL);
+
+ export_columns = data_source_get_export_columns (part->source);
+ for (i = 0; i < export_names->len; i++) {
+ gint col;
+ GdaHolder *bindto;
+ col = GPOINTER_TO_INT (g_hash_table_lookup (export_columns,
+ g_array_index (export_names,
+ gchar*, i))) - 1;
+ bindto = gda_data_model_iter_get_holder_for_field (iter, col);
+ if (bindto) {
+ GdaHolder *holder;
+ holder = gda_holder_copy (bindto);
+ g_object_set ((GObject*) holder, "id",
+ g_array_index (export_names, gchar*, i), NULL);
+ holders = g_slist_prepend (holders, holder);
#ifdef DEBUG_NO
- g_print ("HOLDER [%s::%s]\n",
- gda_holder_get_id (holder),
- g_type_name (gda_holder_get_g_type (holder)));
+ g_print ("HOLDER [%s::%s]\n",
+ gda_holder_get_id (holder),
+ g_type_name (gda_holder_get_g_type (holder)));
#endif
- g_assert (gda_holder_set_bind (holder, bindto, NULL));
+ g_assert (gda_holder_set_bind (holder, bindto, NULL));
+ }
}
- }
- g_object_unref (model);
- if (holders) {
- part->export_data = gda_set_new (holders);
- g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
- g_slist_free (holders);
-
- g_signal_connect (wid, "selection-changed",
- G_CALLBACK (data_part_selection_changed_cb), part);
+ g_object_unref (model);
+ if (holders) {
+ part->export_data = gda_set_new (holders);
+ g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
+ g_slist_free (holders);
+
+ g_signal_connect (wid, "selection-changed",
+ G_CALLBACK (data_part_selection_changed_cb), part);
+ }
}
}
- }
- gtk_notebook_set_current_page (part->nb, part->data_widget_page);
- compute_sources_dependencies (part);
+ gtk_notebook_set_current_page (part->nb, part->data_widget_page);
+ compute_sources_dependencies (part);
}
static void
diff --git a/tools/browser/data-manager/data-widget.h b/tools/browser/data-manager/data-widget.h
index 82d79ff..8756cd0 100644
--- a/tools/browser/data-manager/data-widget.h
+++ b/tools/browser/data-manager/data-widget.h
@@ -26,6 +26,7 @@
#include <gtk/gtk.h>
#include <libgda/libgda.h>
#include "data-source.h"
+#include "data-source-manager.h"
G_BEGIN_DECLS
@@ -51,7 +52,7 @@ struct _DataWidgetClass {
GType data_widget_get_type (void) G_GNUC_CONST;
-GtkWidget *data_widget_new (GArray *sources_array);
+GtkWidget *data_widget_new (DataSourceManager *mgr);
GdaSet *data_widget_get_export (DataWidget *dwid, DataSource *source);
void data_widget_rerun (DataWidget *dwid);
diff --git a/tools/browser/doc/gda-browser-sections.txt b/tools/browser/doc/gda-browser-sections.txt
index d05208d..ca20544 100644
--- a/tools/browser/doc/gda-browser-sections.txt
+++ b/tools/browser/doc/gda-browser-sections.txt
@@ -93,6 +93,7 @@ browser_connection_execution_get_result
BrowserConnectionExecuteCallback
browser_connection_execute_statement_cb
browser_connection_normalize_sql_statement
+browser_connection_check_sql_statement_validify
browser_connection_rerun_select
browser_connection_rerun_select_cb
<SUBSECTION>
diff --git a/tools/browser/doc/tmpl/browser-connection.sgml b/tools/browser/doc/tmpl/browser-connection.sgml
index 2c9a52f..a393308 100644
--- a/tools/browser/doc/tmpl/browser-connection.sgml
+++ b/tools/browser/doc/tmpl/browser-connection.sgml
@@ -282,6 +282,17 @@ An opened connection
@Returns:
+<!-- ##### FUNCTION browser_connection_check_sql_statement_validify ##### -->
+<para>
+
+</para>
+
+ bcnc:
+ sqlst:
+ error:
+ Returns:
+
+
<!-- ##### FUNCTION browser_connection_rerun_select ##### -->
<para>
diff --git a/tools/browser/doc/tmpl/browser-window.sgml b/tools/browser/doc/tmpl/browser-window.sgml
index 32634b7..3746160 100644
--- a/tools/browser/doc/tmpl/browser-window.sgml
+++ b/tools/browser/doc/tmpl/browser-window.sgml
@@ -87,6 +87,7 @@ Top level browser window
</para>
@bwin:
+ type:
@context:
@text:
@@ -97,6 +98,7 @@ Top level browser window
</para>
@bwin:
+ type:
@context:
@format:
@Varargs:
diff --git a/tools/browser/gda-browser-menu-ind.png b/tools/browser/gda-browser-menu-ind.png
new file mode 100644
index 0000000..de0ac6e
Binary files /dev/null and b/tools/browser/gda-browser-menu-ind.png differ
diff --git a/tools/browser/query-exec/query-console.c b/tools/browser/query-exec/query-console.c
index 74dd0ab..a741625 100644
--- a/tools/browser/query-exec/query-console.c
+++ b/tools/browser/query-exec/query-console.c
@@ -935,13 +935,14 @@ query_exec_fetch_cb (QueryConsole *tconsole)
browser_connection_get_transaction_status (tconsole->priv->bcnc) &&
gda_statement_get_statement_type (estmt->stmt) != GDA_SQL_STATEMENT_BEGIN) {
browser_window_show_notice_printf (BROWSER_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tconsole)),
- "QueryExecTransactionStarted",
- "%s", _("A transaction has automatically been started\n"
- "during this statement's execution, this usually\n"
- "happens when blobs are selected (and the transaction\n"
- "will have to remain opened while the blobs are still\n"
- "accessible, clear the corresponding history item before\n"
- "closing the transaction)."));
+ GTK_MESSAGE_INFO,
+ "QueryExecTransactionStarted",
+ "%s", _("A transaction has automatically been started\n"
+ "during this statement's execution, this usually\n"
+ "happens when blobs are selected (and the transaction\n"
+ "will have to remain opened while the blobs are still\n"
+ "accessible, clear the corresponding history item before\n"
+ "closing the transaction)."));
}
query_editor_add_history_item (tconsole->priv->history, history);
diff --git a/tools/browser/schema-browser/table-info.c b/tools/browser/schema-browser/table-info.c
index 271c160..3668c91 100644
--- a/tools/browser/schema-browser/table-info.c
+++ b/tools/browser/schema-browser/table-info.c
@@ -522,8 +522,9 @@ static void statement_executed_cb (BrowserConnection *bcnc,
error->message : _("No detail"));
else
browser_window_show_notice_printf (BROWSER_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tinfo)),
- "DataInsertQuery",
- _("Data successfully inserted"));
+ GTK_MESSAGE_INFO,
+ "DataInsertQuery",
+ _("Data successfully inserted"));
}
static void
diff --git a/tools/browser/support.c b/tools/browser/support.c
index ec1131e..750f4eb 100644
--- a/tools/browser/support.c
+++ b/tools/browser/support.c
@@ -122,7 +122,8 @@ browser_connection_close (GtkWindow *parent, BrowserConnection *bcnc)
* @format: printf() style format string
* @...: arguments for @format
*
- * Displays a modal error until the user aknowledges it.
+ * Displays an error message until the user aknowledges it. I @parent is a #BrowserWindow, then
+ * the error message is displayed in the window if possible
*/
void
browser_show_error (GtkWindow *parent, const gchar *format, ...)
@@ -137,6 +138,12 @@ browser_show_error (GtkWindow *parent, const gchar *format, ...)
vsnprintf (sz, sizeof (sz), format, args);
va_end (args);
+ if (BROWSER_IS_WINDOW (parent)) {
+ browser_window_show_notice (BROWSER_WINDOW (parent), GTK_MESSAGE_ERROR,
+ NULL, sz);
+ return;
+ }
+
/* create the error message dialog */
dialog = gtk_message_dialog_new (parent,
GTK_DIALOG_DESTROY_WITH_PARENT |
@@ -230,8 +237,8 @@ browser_show_help (GtkWindow *parent, const gchar *topic)
g_error_free (error);
}
else
- browser_window_show_notice (BROWSER_WINDOW (parent),
- "show-help", _("Help is being loaded, please wait..."));
+ browser_window_show_notice (BROWSER_WINDOW (parent), GTK_MESSAGE_INFO,
+ "show-help", _("Help is being loaded, please wait..."));
g_free (uri);
}
@@ -342,6 +349,7 @@ browser_get_pixbuf_icon (BrowserIconType type)
"gda-browser-query.png",
"gda-browser-grid.png",
"gda-browser-form.png",
+ "gda-browser-menu-ind.png",
};
if (!array)
diff --git a/tools/browser/support.h b/tools/browser/support.h
index 4b9b470..f6c7100 100644
--- a/tools/browser/support.h
+++ b/tools/browser/support.h
@@ -75,6 +75,8 @@ typedef enum {
BROWSER_ICON_GRID,
BROWSER_ICON_FORM,
+ BROWSER_ICON_MENU_INDICATOR,
+
BROWSER_ICON_LAST
} BrowserIconType;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]