[libgda] GdaBrowser: misc improvements
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Subject: [libgda] GdaBrowser: misc improvements
- Date: Thu, 16 Jul 2009 19:37:17 +0000 (UTC)
commit de77a744b8f3815ec1ad64fd21acdab30448d073
Author: Vivien Malerba <malerba gnome-db org>
Date: Mon Jul 13 20:55:03 2009 +0200
GdaBrowser: misc improvements
* reworked menu
* re-wrote favorites management
* prepared work to create diagrams
libgda-ui/data-entries/gdaui-entry-common-time.c | 5 +-
po/POTFILES.in | 2 +
tools/browser/.gitignore | 1 +
tools/browser/Makefile.am | 18 +-
tools/browser/browser-connection.c | 400 +---------
tools/browser/browser-connection.h | 21 +-
tools/browser/browser-favorites.c | 874 ++++++++++++++++++++
tools/browser/browser-favorites.h | 82 ++
tools/browser/canvas/browser-canvas-db-relations.c | 82 ++-
tools/browser/canvas/browser-canvas-db-relations.h | 2 +
tools/browser/canvas/browser-canvas-table.c | 79 +-
tools/browser/canvas/browser-canvas-table.h | 1 +
tools/browser/canvas/browser-canvas-utility.c | 8 +-
tools/browser/canvas/browser-canvas.c | 101 +++-
tools/browser/canvas/browser-canvas.h | 3 +
tools/browser/decl.h | 4 +-
tools/browser/favorites-test.c | 260 ++++++
tools/browser/gda-browser-diagram.png | Bin 0 -> 229 bytes
tools/browser/mgr-favorites.c | 114 ++-
tools/browser/mgr-favorites.h | 2 +
tools/browser/schema-browser/Makefile.am | 4 +-
tools/browser/schema-browser/favorite-selector.c | 33 +-
tools/browser/schema-browser/relations-diagram.c | 462 +++++++++++
tools/browser/schema-browser/relations-diagram.h | 55 ++
.../schema-browser/schema-browser-perspective.c | 102 +--
tools/browser/schema-browser/table-columns.c | 4 +-
tools/browser/schema-browser/table-info.c | 12 -
tools/browser/schema-browser/table-relations.c | 9 +-
tools/browser/support.c | 21 +-
tools/browser/support.h | 6 +
30 files changed, 2186 insertions(+), 581 deletions(-)
---
diff --git a/libgda-ui/data-entries/gdaui-entry-common-time.c b/libgda-ui/data-entries/gdaui-entry-common-time.c
index cc3af6d..5f6031b 100644
--- a/libgda-ui/data-entries/gdaui-entry-common-time.c
+++ b/libgda-ui/data-entries/gdaui-entry-common-time.c
@@ -203,7 +203,10 @@ gdaui_entry_common_time_dispose (GObject * object)
gdaui_entry_common_time = GDAUI_ENTRY_COMMON_TIME (object);
if (gdaui_entry_common_time->priv) {
-
+ if (gdaui_entry_common_time->priv->window) {
+ gtk_widget_destroy (gdaui_entry_common_time->priv->window);
+ gdaui_entry_common_time->priv->window = NULL;
+ }
}
/* parent class */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 804a88d..d6bcf2f 100755
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -196,6 +196,7 @@ testing/gdaui-test-data-entries.c
tools/browser/auth-dialog.c
tools/browser/browser-connection.c
tools/browser/browser-connections-list.c
+tools/browser/browser-favorites.c
tools/browser/browser-window.c
tools/browser/gda-browser-4.0.desktop.in
tools/browser/login-dialog.c
@@ -212,6 +213,7 @@ tools/browser/schema-browser/favorite-selector.c
tools/browser/schema-browser/mgr-columns.c
tools/browser/schema-browser/objects-index.c
tools/browser/schema-browser/perspective-main.c
+tools/browser/schema-browser/relations-diagram.c
tools/browser/schema-browser/schema-browser-perspective.c
tools/browser/schema-browser/table-columns.c
tools/browser/schema-browser/table-info.c
diff --git a/tools/browser/.gitignore b/tools/browser/.gitignore
index b6f4891..1b1762b 100644
--- a/tools/browser/.gitignore
+++ b/tools/browser/.gitignore
@@ -3,3 +3,4 @@ gda-browser-4.*.desktop
canvas-example
marshal.c
marshal.h
+favorites-test
diff --git a/tools/browser/Makefile.am b/tools/browser/Makefile.am
index 9a55bac..d4ea7eb 100644
--- a/tools/browser/Makefile.am
+++ b/tools/browser/Makefile.am
@@ -1,5 +1,5 @@
bin_PROGRAMS=gda-browser-4.0
-noinst_PROGRAMS =
+noinst_PROGRAMS = favorites-test
SUBDIRS = schema-browser dummy-perspective
if HAVE_GOOCANVAS
@@ -45,6 +45,8 @@ gda_browser_4_0_SOURCES=\
browser-spinner.h \
browser-connection.c \
browser-connection.h \
+ browser-favorites.c \
+ browser-favorites.h \
browser-variable.c \
browser-variable.h \
browser-window.c \
@@ -83,6 +85,17 @@ gda_browser_4_0_LDADD+= \
$(top_builddir)/tools/browser/canvas/libcanvas.la
endif
+favorites_test_SOURCES=\
+ browser-favorites.c \
+ browser-favorites.h \
+ favorites-test.c
+
+favorites_test_LDADD=\
+ $(top_builddir)/tools/browser/schema-browser/libperspective.la \
+ $(top_builddir)/tools/browser/dummy-perspective/libperspective.la \
+ $(top_builddir)/libgda/libgda-4.0.la \
+ $(LIBGDA_LIBS)
+
@INTLTOOL_DESKTOP_RULE@
desktopdir=$(datadir)/applications
@@ -121,7 +134,8 @@ icons_DATA= \
gda-browser-column-fk.png \
gda-browser-column-nn.png \
gda-browser-column-pk.png \
- gda-browser-reference.png
+ gda-browser-reference.png \
+ gda-browser-diagram.png
EXTRA_DIST = \
marshal.list \
diff --git a/tools/browser/browser-connection.c b/tools/browser/browser-connection.c
index b70bd85..45959ce 100644
--- a/tools/browser/browser-connection.c
+++ b/tools/browser/browser-connection.c
@@ -24,6 +24,7 @@
#include "support.h"
#include "marshal.h"
#include <sql-parser/gda-sql-parser.h>
+#include <libgda/gda-sql-builder.h>
/* code inclusion */
#include "../dict-file-name.c"
@@ -44,7 +45,7 @@ struct _BrowserConnectionPrivate {
GdaMetaStruct *p_mstruct; /* private GdaMetaStruct: while it is being created */
GdaMetaStruct *mstruct; /* public GdaMetaStruct: once it has been created and is no more modified */
- gboolean meta_store_addons_init_done;
+ BrowserFavorites *bfav;
};
@@ -170,7 +171,7 @@ browser_connection_class_init (BrowserConnectionClass *klass)
browser_connection_signals [FAV_CHANGED] =
g_signal_new ("favorites-changed",
G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+ G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (BrowserConnectionClass, favorites_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
@@ -201,7 +202,7 @@ browser_connection_init (BrowserConnection *bcnc)
bcnc->priv->p_mstruct = NULL;
bcnc->priv->mstruct = NULL;
- bcnc->priv->meta_store_addons_init_done = FALSE;
+ bcnc->priv->bfav = NULL;
}
static void
@@ -224,6 +225,12 @@ clear_dsn_info (BrowserConnection *bcnc)
}
static void
+fav_changed_cb (BrowserFavorites *bfav, BrowserConnection *bcnc)
+{
+ g_signal_emit (bcnc, browser_connection_signals [FAV_CHANGED], 0);
+}
+
+static void
browser_connection_dispose (GObject *object)
{
BrowserConnection *bcnc;
@@ -261,6 +268,11 @@ browser_connection_dispose (GObject *object)
g_slist_foreach (bcnc->priv->variables, (GFunc) g_object_unref, NULL);
g_slist_free (bcnc->priv->variables);
}
+ if (bcnc->priv->bfav) {
+ g_signal_handlers_disconnect_by_func (bcnc->priv->bfav,
+ G_CALLBACK (fav_changed_cb), bcnc);
+ g_object_unref (bcnc->priv->bfav);
+ }
g_free (bcnc->priv);
bcnc->priv = NULL;
@@ -602,382 +614,20 @@ browser_connection_get_dictionary_file (BrowserConnection *bcnc)
return bcnc->priv->dict_file_name;
}
-#define FAVORITES_TABLE_NAME "gda_sql_favorites"
-#define FAVORITES_TABLE_DESC \
- "<table name=\"" FAVORITES_TABLE_NAME "\"> " \
- " <column name=\"session\" type=\"gint\" pkey=\"TRUE\"/>" \
- " <column name=\"type\" pkey=\"TRUE\"/>" \
- " <column name=\"contents\" pkey=\"TRUE\"/>" \
- " <column name=\"descr\" nullok=\"TRUE\"/>" \
- " <column name=\"rank\" type=\"gint\"/>" \
- " <unique>" \
- " <column name=\"type\"/>" \
- " <column name=\"rank\"/>" \
- " </unique>" \
- "</table>"
-#define FAVORITE_DELETE \
- "DELETE FROM " FAVORITES_TABLE_NAME " WHERE session = ##session::gint AND type= ##type::string AND " \
- "contents = ##contents::string"
-#define FAVORITE_SHIFT \
- "UPDATE " FAVORITES_TABLE_NAME " SET rank = rank + 1 WHERE rank >= ##rank::gint"
-#define FAVORITE_INSERT \
- "INSERT INTO " FAVORITES_TABLE_NAME " (session, type, contents, rank, descr) VALUES (##session::gint, " \
- "##type::string, ##contents::string, ##rank::gint, ##descr::string)"
-#define FAVORITE_SELECT \
- "SELECT contents, descr, rank FROM " FAVORITES_TABLE_NAME " WHERE session = ##session::gint " \
- "AND type = ##type::string ORDER by rank"
-#define FAVORITE_UPDATE_RANK \
- "UPDATE " FAVORITES_TABLE_NAME " SET rank = ##newrank::gint WHERE rank = ##rank::gint AND " \
- "session = ##session::gint AND type = ##type::string"
-
-static gboolean
-meta_store_addons_init (BrowserConnection *bcnc, GError **error)
-{
- GdaMetaStore *mstore;
- GError *lerror = NULL;
- mstore = gda_connection_get_meta_store (bcnc->priv->cnc);
- if (!gda_meta_store_schema_add_custom_object (mstore, FAVORITES_TABLE_DESC, &lerror)) {
- g_set_error (error, 0, 0, "%s",
- _("Can't initialize dictionary to store favorites"));
- g_warning ("Can't initialize dictionary to store favorites :%s",
- lerror && lerror->message ? lerror->message : "No detail");
- if (lerror)
- g_error_free (lerror);
- return FALSE;
- }
-
- bcnc->priv->meta_store_addons_init_done = TRUE;
- return TRUE;
-}
-
-static const gchar *
-favorite_type_to_string (BrowserFavoritesType type)
-{
- switch (type) {
- case BROWSER_FAVORITES_TABLES:
- return "TABLE";
- default:
- g_warning ("Unknow type of favorite");
- }
-
- return "";
-}
-
/**
- * browser_connection_add_favorite
- */
-gboolean
-browser_connection_add_favorite (BrowserConnection *bcnc, guint session_id, BrowserConnectionFavorite *fav,
- gint pos, GError **error)
-{
- GdaMetaStore *mstore;
- GdaConnection *store_cnc;
- GdaStatement *stmt;
- GdaSqlParser *parser = NULL;
- GdaSet *params = NULL;
-
- g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), FALSE);
- g_return_val_if_fail (fav && fav->contents, FALSE);
-
- if (! bcnc->priv->meta_store_addons_init_done &&
- ! meta_store_addons_init (bcnc, error))
- return FALSE;
-
- mstore = gda_connection_get_meta_store (bcnc->priv->cnc);
- store_cnc = gda_meta_store_get_internal_connection (mstore);
-
- if (! gda_lockable_trylock (GDA_LOCKABLE (store_cnc))) {
- g_set_error (error, 0, 0, "%s",
- _("Can't initialize transaction to access favorites"));
- return FALSE;
- }
- /* begin a transaction */
- if (! gda_connection_begin_transaction (store_cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL)) {
- g_set_error (error, 0, 0, "%s",
- _("Can't initialize transaction to access favorites"));
- gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
- return FALSE;
- }
-
- /* create parser */
- parser = gda_connection_create_parser (store_cnc);
- if (!parser)
- parser = gda_sql_parser_new ();
-
- /* DELETE any favorite existing */
- if (pos < 0)
- pos = 0;
- params = gda_set_new_inline (6,
- "session", G_TYPE_INT, session_id,
- "type", G_TYPE_STRING, favorite_type_to_string (fav->type),
- "contents", G_TYPE_STRING, fav->contents,
- "rank", G_TYPE_INT, pos,
- "newrank", G_TYPE_INT, 0,
- "descr", G_TYPE_STRING, fav->descr);
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_DELETE, NULL, error);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_DELETE);
- goto err;
- }
- if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
- g_object_unref (stmt);
- goto err;
- }
- g_object_unref (stmt);
- stmt = NULL;
-
- /* renumber favorites */
- GdaDataModel *model;
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_SELECT, NULL, NULL);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_SELECT);
- goto err;
- }
- model = gda_connection_statement_execute_select (store_cnc, stmt, params, error);
- g_object_unref (stmt);
- stmt = NULL;
- if (!model)
- goto err;
-
- gint i, nrows;
- nrows = gda_data_model_get_n_rows (model);
- for (i = 0; i < nrows; i++) {
- const GValue *rank;
-
- rank = gda_data_model_get_value_at (model, 2, i, error);
- if (!rank) {
- g_set_error (error, 0, 0, "%s",
- _("Can't get current favorites"));
- g_object_unref (model);
- goto err;
- }
- if (g_value_get_int (rank) != i) {
- if (!stmt) {
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_UPDATE_RANK, NULL, NULL);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_UPDATE_RANK);
- g_object_unref (model);
- goto err;
- }
- }
- gda_set_set_holder_value (params, NULL, "newrank", i);
- gda_set_set_holder_value (params, NULL, "rank", g_value_get_int (rank));
- if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
- g_object_unref (stmt);
- g_object_unref (model);
- goto err;
- }
- }
- }
- if (stmt)
- g_object_unref (stmt);
- stmt = NULL;
- g_object_unref (model);
- if (pos > nrows)
- pos = nrows;
- gda_set_set_holder_value (params, NULL, "rank", pos);
-
- /* SHIFT favorites */
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_SHIFT, NULL, error);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_SHIFT);
- goto err;
- }
- if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
- g_object_unref (stmt);
- goto err;
- }
- g_object_unref (stmt);
- stmt = NULL;
-
- /* ADD new favorite */
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_INSERT, NULL, error);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_INSERT);
- goto err;
- }
- if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
- g_object_unref (stmt);
- goto err;
- }
- g_object_unref (stmt);
- stmt = NULL;
-
- if (! gda_connection_commit_transaction (store_cnc, NULL, NULL)) {
- g_set_error (error, 0, 0, "%s",
- _("Can't commit transaction to access favorites"));
- goto err;
- }
-
- if (params)
- g_object_unref (params);
- if (parser)
- g_object_unref (parser);
- gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
- g_signal_emit (bcnc, browser_connection_signals [FAV_CHANGED],
- g_quark_from_string (favorite_type_to_string (fav->type)));
- return TRUE;
-
- err:
- if (params)
- g_object_unref (params);
- if (parser)
- g_object_unref (parser);
- gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
- gda_connection_rollback_transaction (store_cnc, NULL, NULL);
- return FALSE;
-}
-
-/**
- * browser_connection_free_favorites_list
- */
-void
-browser_connection_free_favorites_list (GSList *fav_list)
-{
- GSList *list;
- if (!fav_list)
- return;
- for (list = fav_list; list; list = list->next) {
- BrowserConnectionFavorite *fav = (BrowserConnectionFavorite*) list->data;
- g_free (fav->contents);
- g_free (fav->descr);
- g_free (fav);
- }
- g_slist_free (fav_list);
-}
-
-/**
- * browser_connection_list_favorites
+ * browser_connection_get_favorites
*
- * Returns: a new list of #BrowserConnectionFavorite pointers. The list has to
- * be freed using browser_connection_free_favorites_list()
+ * Get the favorites handler
*/
-GSList *
-browser_connection_list_favorites (BrowserConnection *bcnc, guint session_id, BrowserFavoritesType type, GError **error)
+BrowserFavorites *
+browser_connection_get_favorites (BrowserConnection *bcnc)
{
- GdaMetaStore *mstore;
- GdaConnection *store_cnc;
- GdaStatement *stmt;
- GdaSqlParser *parser = NULL;
- GdaSet *params = NULL;
- GSList *fav_list = NULL;
- GdaDataModel *model;
-
- g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), FALSE);
- if (! bcnc->priv->meta_store_addons_init_done &&
- ! meta_store_addons_init (bcnc, NULL))
- return NULL;
-
- mstore = gda_connection_get_meta_store (bcnc->priv->cnc);
- store_cnc = gda_meta_store_get_internal_connection (mstore);
-
- if (! gda_lockable_trylock (GDA_LOCKABLE (store_cnc))) {
- g_set_error (error, 0, 0, "%s",
- _("Can't initialize transaction to access favorites"));
- return NULL;
- }
-
- /* create parser */
- parser = gda_connection_create_parser (store_cnc);
- if (!parser)
- parser = gda_sql_parser_new ();
-
- /* SELECT favorites */
- params = gda_set_new_inline (2,
- "session", G_TYPE_INT, session_id,
- "type", G_TYPE_STRING, favorite_type_to_string (type));
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_SELECT, NULL, NULL);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_SELECT);
- goto out;
- }
- model = gda_connection_statement_execute_select (store_cnc, stmt, params, error);
- g_object_unref (stmt);
- if (!model)
- goto out;
-
- gint i, nrows;
- nrows = gda_data_model_get_n_rows (model);
- for (i = 0; i < nrows; i++) {
- const GValue *contents, *descr;
-
- contents = gda_data_model_get_value_at (model, 0, i, error);
- if (contents)
- descr = gda_data_model_get_value_at (model, 1, i, error);
- if (contents && descr) {
- BrowserConnectionFavorite *fav;
- fav = g_new0 (BrowserConnectionFavorite, 1);
- fav->type = type;
- if (G_VALUE_TYPE (descr) == G_TYPE_STRING)
- fav->descr = g_value_dup_string (descr);
- fav->contents = g_value_dup_string (contents);
- fav_list = g_slist_prepend (fav_list, fav);
- }
- else {
- browser_connection_free_favorites_list (fav_list);
- fav_list = NULL;
- goto out;
- }
+ g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+ if (!bcnc->priv->bfav) {
+ bcnc->priv->bfav = browser_favorites_new (gda_connection_get_meta_store (bcnc->priv->cnc));
+ g_signal_connect (bcnc->priv->bfav, "favorites-changed",
+ G_CALLBACK (fav_changed_cb), bcnc);
}
-
- out:
- g_object_unref (parser);
- gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
- return g_slist_reverse (fav_list);
+ return bcnc->priv->bfav;
}
-
-/**
- * browser_connection_delete_favorite
- */
-gboolean
-browser_connection_delete_favorite (BrowserConnection *bcnc, guint session_id,
- BrowserConnectionFavorite *fav, GError **error)
-{
- GdaMetaStore *mstore;
- GdaConnection *store_cnc;
- GdaStatement *stmt;
- GdaSqlParser *parser = NULL;
- GdaSet *params = NULL;
- gboolean retval = FALSE;
-
- g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), FALSE);
- if (! bcnc->priv->meta_store_addons_init_done &&
- ! meta_store_addons_init (bcnc, NULL))
- return NULL;
-
- mstore = gda_connection_get_meta_store (bcnc->priv->cnc);
- store_cnc = gda_meta_store_get_internal_connection (mstore);
-
- gda_lockable_lock (GDA_LOCKABLE (store_cnc));
-
- /* create parser */
- parser = gda_connection_create_parser (store_cnc);
- if (!parser)
- parser = gda_sql_parser_new ();
-
- /* DELETE any favorite existing */
- params = gda_set_new_inline (3,
- "session", G_TYPE_INT, session_id,
- "type", G_TYPE_STRING, favorite_type_to_string (fav->type),
- "contents", G_TYPE_STRING, fav->contents);
- stmt = gda_sql_parser_parse_string (parser, FAVORITE_DELETE, NULL, error);
- if (!stmt) {
- g_warning ("Could not parse internal statement: %s", FAVORITE_DELETE);
- goto out;
- }
- if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
- g_object_unref (stmt);
- goto out;
- }
- g_object_unref (stmt);
- stmt = NULL;
- retval = TRUE;
- g_signal_emit (bcnc, browser_connection_signals [FAV_CHANGED],
- g_quark_from_string (favorite_type_to_string (fav->type)));
-
- out:
- g_object_unref (parser);
- gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
- return retval;
-}
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index fb3d0ef..ed934ec 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -22,6 +22,7 @@
#define __BROWSER_CONNECTION_H_
#include <libgda/libgda.h>
+#include "browser-favorites.h"
#include "decl.h"
G_BEGIN_DECLS
@@ -64,27 +65,13 @@ GdaMetaStruct *browser_connection_get_meta_struct (BrowserConnection
GdaMetaStore *browser_connection_get_meta_store (BrowserConnection *bcnc);
const gchar *browser_connection_get_dictionary_file (BrowserConnection *bcnc);
+BrowserFavorites *browser_connection_get_favorites (BrowserConnection *bcnc);
+
/*
* statements's execution
*/
+/* TODO */
-
-/*
- * Favorites management
- */
-typedef struct {
- BrowserFavoritesType type;
- gchar *descr;
- gchar *contents;
-} BrowserConnectionFavorite;
-gboolean browser_connection_add_favorite (BrowserConnection *bcnc, guint session_id,
- BrowserConnectionFavorite *fav, gint pos,
- GError **error);
-GSList *browser_connection_list_favorites (BrowserConnection *bcnc, guint session_id,
- BrowserFavoritesType type, GError **error);
-gboolean browser_connection_delete_favorite (BrowserConnection *bcnc, guint session_id,
- BrowserConnectionFavorite *fav, GError **error);
-void browser_connection_free_favorites_list (GSList *fav_list);
G_END_DECLS
#endif
diff --git a/tools/browser/browser-favorites.c b/tools/browser/browser-favorites.c
new file mode 100644
index 0000000..4d37ce8
--- /dev/null
+++ b/tools/browser/browser-favorites.c
@@ -0,0 +1,874 @@
+/*
+ * Copyright (C) 2009 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include "browser-favorites.h"
+#include <libgda/thread-wrapper/gda-thread-wrapper.h>
+#include "support.h"
+#include "marshal.h"
+#include <libgda/gda-sql-builder.h>
+
+struct _BrowserFavoritesPrivate {
+ GdaMetaStore *store;
+ GdaConnection *store_cnc;
+};
+
+
+/*
+ * Main static functions
+ */
+static void browser_favorites_class_init (BrowserFavoritesClass *klass);
+static void browser_favorites_init (BrowserFavorites *bfav);
+static void browser_favorites_dispose (GObject *object);
+
+/* get a pointer to the parents to be able to call their destructor */
+static GObjectClass *parent_class = NULL;
+
+/* signals */
+enum {
+ FAV_CHANGED,
+ LAST_SIGNAL
+};
+
+gint browser_favorites_signals [LAST_SIGNAL] = { 0 };
+
+GType
+browser_favorites_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+ static const GTypeInfo info = {
+ sizeof (BrowserFavoritesClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) browser_favorites_class_init,
+ NULL,
+ NULL,
+ sizeof (BrowserFavorites),
+ 0,
+ (GInstanceInitFunc) browser_favorites_init
+ };
+
+
+ g_static_mutex_lock (®istering);
+ if (type == 0)
+ type = g_type_register_static (G_TYPE_OBJECT, "BrowserFavorites", &info, 0);
+ g_static_mutex_unlock (®istering);
+ }
+ return type;
+}
+
+static void
+browser_favorites_class_init (BrowserFavoritesClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ parent_class = g_type_class_peek_parent (klass);
+
+ browser_favorites_signals [FAV_CHANGED] =
+ g_signal_new ("favorites-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET (BrowserFavoritesClass, favorites_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE,
+ 0);
+
+ klass->favorites_changed = NULL;
+
+ object_class->dispose = browser_favorites_dispose;
+}
+
+static void
+browser_favorites_init (BrowserFavorites *bfav)
+{
+ bfav->priv = g_new0 (BrowserFavoritesPrivate, 1);
+ bfav->priv->store = NULL;
+ bfav->priv->store_cnc = NULL;
+}
+
+static void
+browser_favorites_dispose (GObject *object)
+{
+ BrowserFavorites *bfav;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (BROWSER_IS_FAVORITES (object));
+
+ bfav = BROWSER_FAVORITES (object);
+ if (bfav->priv) {
+ if (bfav->priv->store)
+ g_object_unref (bfav->priv->store);
+ if (bfav->priv->store_cnc)
+ g_object_unref (bfav->priv->store_cnc);
+
+ g_free (bfav->priv);
+ bfav->priv = NULL;
+ }
+
+ /* parent class */
+ parent_class->dispose (object);
+}
+
+/**
+ * browser_favorites_new
+ *
+ * Creates a new #BrowserFavorites object
+ *
+ * Returns: the new object
+ */
+BrowserFavorites*
+browser_favorites_new (GdaMetaStore *store)
+{
+ BrowserFavorites *bfav;
+
+ g_return_val_if_fail (GDA_IS_META_STORE (store), NULL);
+
+ bfav = BROWSER_FAVORITES (g_object_new (BROWSER_TYPE_FAVORITES, NULL));
+ bfav->priv->store = g_object_ref (store);
+
+ return bfav;
+}
+
+#define FAVORITES_TABLE_NAME "gda_sql_favorites"
+#define FAVORITES_TABLE_DESC \
+ "<table name=\"" FAVORITES_TABLE_NAME "\"> " \
+ " <column name=\"id\" type=\"gint\" pkey=\"TRUE\" autoinc=\"TRUE\"/>" \
+ " <column name=\"session\" type=\"gint\"/>" \
+ " <column name=\"type\"/>" \
+ " <column name=\"name\" nullok=\"TRUE\"/>" \
+ " <column name=\"contents\"/>" \
+ " <column name=\"descr\" nullok=\"TRUE\"/>" \
+ " <unique>" \
+ " <column name=\"session\"/>" \
+ " <column name=\"type\"/>" \
+ " <column name=\"contents\"/>" \
+ " </unique>" \
+ "</table>"
+#define FAVORDER_TABLE_NAME "gda_sql_favorder"
+#define FAVORDER_TABLE_DESC \
+ "<table name=\"" FAVORDER_TABLE_NAME "\"> " \
+ " <column name=\"order_key\" type=\"gint\" pkey=\"TRUE\"/>" \
+ " <column name=\"fav_id\" type=\"gint\" pkey=\"TRUE\"/>" \
+ " <column name=\"rank\" type=\"gint\"/>" \
+ "</table>"
+
+static gboolean
+meta_store_addons_init (BrowserFavorites *bfav, GError **error)
+{
+ GError *lerror = NULL;
+
+ if (!gda_meta_store_schema_add_custom_object (bfav->priv->store, FAVORITES_TABLE_DESC, &lerror)) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't initialize dictionary to store favorites"));
+ g_warning ("Can't initialize dictionary to store favorites :%s",
+ lerror && lerror->message ? lerror->message : "No detail");
+ if (lerror)
+ g_error_free (lerror);
+ return FALSE;
+ }
+ if (!gda_meta_store_schema_add_custom_object (bfav->priv->store, FAVORDER_TABLE_DESC, &lerror)) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't initialize dictionary to store favorites"));
+ g_warning ("Can't initialize dictionary to store favorites :%s",
+ lerror && lerror->message ? lerror->message : "No detail");
+ if (lerror)
+ g_error_free (lerror);
+ return FALSE;
+ }
+
+ bfav->priv->store_cnc = g_object_ref (gda_meta_store_get_internal_connection (bfav->priv->store));
+ return TRUE;
+}
+
+static const gchar *
+favorite_type_to_string (BrowserFavoritesType type)
+{
+ switch (type) {
+ case BROWSER_FAVORITES_TABLES:
+ return "TABLE";
+ case BROWSER_FAVORITES_DIAGRAMS:
+ return "DIAGRAM";
+ default:
+ g_warning ("Unknow type of favorite");
+ }
+
+ return "";
+}
+
+static BrowserFavoritesType
+favorite_string_to_type (const gchar *str)
+{
+ if (*str == 'T')
+ return BROWSER_FAVORITES_TABLES;
+ else if (*str == 'D')
+ return BROWSER_FAVORITES_DIAGRAMS;
+ else
+ g_warning ("Unknow type '%s' of favorite", str);
+ return 0;
+}
+
+
+/*
+ * Find a favorite ID from its ID or from its contents
+ *
+ * Returns: the ID or -1 if not found (and sets ERROR)
+ */
+static gint
+find_favorite (BrowserFavorites *bfav, guint session_id, gint id, const gchar *contents, GError **error)
+{
+ GdaSqlBuilder *b;
+ GdaStatement *stmt;
+ GdaSet *params = NULL;
+ GdaDataModel *model;
+ gint favid = -1;
+
+ g_return_val_if_fail ((id >= 0) || contents, -1);
+
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "id"), 0);
+ gda_sql_builder_select_add_target (b, 0,
+ gda_sql_builder_literal (b, 0, FAVORITES_TABLE_NAME),
+ NULL);
+
+ if (id >= 0) {
+ /* lookup from ID */
+ gda_sql_builder_set_where (b,
+ gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "id"),
+ gda_sql_builder_param (b, 0, "id", G_TYPE_INT, FALSE), 0));
+ }
+ else {
+ /* lookup using session and contents */
+ gda_sql_builder_set_where (b,
+ gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_AND,
+ gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "session"),
+ gda_sql_builder_param (b, 0, "session", G_TYPE_INT, FALSE), 0),
+ gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "contents"),
+ gda_sql_builder_param (b, 0, "contents", G_TYPE_INT, FALSE), 0), 0));
+ }
+ stmt = gda_sql_builder_get_statement (b, error);
+ g_object_unref (G_OBJECT (b));
+ if (!stmt)
+ return -1;
+ params = gda_set_new_inline (3,
+ "session", G_TYPE_INT, session_id,
+ "id", G_TYPE_INT, id,
+ "contents", G_TYPE_STRING, contents);
+ model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
+ g_object_unref (stmt);
+ g_object_unref (params);
+
+ if (!model)
+ return -1;
+
+ gint nrows;
+ nrows = gda_data_model_get_n_rows (model);
+ if (nrows == 1) {
+ const GValue *cvalue;
+ cvalue = gda_data_model_get_value_at (model, 0, 0, error);
+ if (cvalue)
+ favid = g_value_get_int (cvalue);
+ }
+
+ g_object_unref (G_OBJECT (model));
+ return favid;
+}
+
+/*
+ * Reorders the favorites for @order_key, making sure @id is at position @new_pos
+ */
+static gboolean
+favorites_reorder (BrowserFavorites *bfav, gint order_key, gint id, gint new_pos, GError **error)
+{
+ GdaSqlBuilder *b;
+ GdaStatement *stmt;
+ GdaSet *params = NULL;
+ GdaDataModel *model;
+
+ g_assert (id >= 0);
+ g_assert (order_key >= 0);
+
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+ gda_sql_builder_add_field (b, gda_sql_builder_literal (b, 0, "fav_id"), 0);
+
+ gda_sql_builder_select_add_target (b, 0,
+ gda_sql_builder_literal (b, 0, FAVORDER_TABLE_NAME),
+ NULL);
+
+ gda_sql_builder_set_where (b, gda_sql_builder_cond (b, 1, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "order_key"),
+ gda_sql_builder_param (b, 0, "orderkey", G_TYPE_INT, FALSE), 0));
+ gda_sql_builder_select_order_by (b,
+ gda_sql_builder_literal (b, 0, "rank"), TRUE, NULL);
+ stmt = gda_sql_builder_get_statement (b, error);
+ g_object_unref (G_OBJECT (b));
+ if (!stmt)
+ return FALSE;
+ params = gda_set_new_inline (3,
+ "orderkey", G_TYPE_INT, order_key,
+ "rank", G_TYPE_INT, 0,
+ "id", G_TYPE_INT, id);
+ model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
+ g_object_unref (stmt);
+ if (!model) {
+ g_object_unref (params);
+ return FALSE;
+ }
+
+ gint i, nrows;
+ gboolean retval = TRUE;
+ nrows = gda_data_model_get_n_rows (model);
+ if (new_pos < 0)
+ new_pos = 0;
+ else if (new_pos > nrows)
+ new_pos = nrows;
+
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_UPDATE);
+ gda_sql_builder_set_table (b, FAVORDER_TABLE_NAME);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "rank"),
+ gda_sql_builder_param (b, 0, "rank", G_TYPE_INT, FALSE));
+ gda_sql_builder_cond (b, 1, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "fav_id"),
+ gda_sql_builder_param (b, 0, "id", G_TYPE_INT, FALSE),
+ 0);
+ gda_sql_builder_cond (b, 2, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "order_key"),
+ gda_sql_builder_param (b, 0, "orderkey", G_TYPE_INT, FALSE),
+ 0);
+ gda_sql_builder_set_where (b, gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_AND, 1, 2, 0));
+ stmt = gda_sql_builder_get_statement (b, error);
+ if (!stmt) {
+ retval = FALSE;
+ goto out;
+ }
+
+ /* reodering the rows */
+ for (i = 0; i < nrows; i++) {
+ const GValue *v;
+ v = gda_data_model_get_value_at (model, 0, i, error);
+ if (v) {
+ g_assert (gda_holder_set_value (gda_set_get_holder (params, "id"), v, NULL));
+ if (g_value_get_int (v) == id)
+ g_assert (gda_set_set_holder_value (params, NULL, "rank", new_pos));
+ else
+ g_assert (gda_set_set_holder_value (params, NULL, "rank", i < new_pos ? i : i + 1));
+ if (gda_connection_statement_execute_non_select (bfav->priv->store_cnc, stmt,
+ params, NULL, error) == -1) {
+ retval = FALSE;
+ goto out;
+ }
+ }
+ else {
+ retval = FALSE;
+ goto out;
+ }
+ }
+
+ out:
+ g_object_unref (b);
+ g_object_unref (params);
+ g_object_unref (model);
+ if (stmt)
+ g_object_unref (stmt);
+ return retval;
+}
+
+/**
+ * browser_favorites_add
+ *
+ * Add a new favorite, or replace an existing one.
+ * NOTE:
+ * - if @fav->id is NULL then it's either an update or an insert (depending if fav->contents exists)
+ * and if it's not it is an UPDATE
+ * - @fav->type can't be 0
+ * - @fav->contents can't be %NULL
+ *
+ * if @order_key is negative, then no ordering is done and @pos is ignored.
+ */
+gint
+browser_favorites_add (BrowserFavorites *bfav, guint session_id,
+ BrowserFavoritesAttributes *fav,
+ gint order_key, gint pos,
+ GError **error)
+{
+ GdaConnection *store_cnc;
+ GdaSet *params = NULL;
+ gint favid = -1;
+
+ g_return_val_if_fail (BROWSER_IS_FAVORITES (bfav), FALSE);
+ g_return_val_if_fail (fav, FALSE);
+ g_return_val_if_fail (fav->contents, FALSE);
+ g_return_val_if_fail (fav->type, FALSE);
+
+ if (! bfav->priv->store_cnc &&
+ ! meta_store_addons_init (bfav, error))
+ return FALSE;
+
+ store_cnc = bfav->priv->store_cnc;
+ if (! gda_lockable_trylock (GDA_LOCKABLE (store_cnc))) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't initialize transaction to access favorites"));
+ return FALSE;
+ }
+ /* begin a transaction */
+ if (! gda_connection_begin_transaction (store_cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL)) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't initialize transaction to access favorites"));
+ gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
+ return FALSE;
+ }
+
+ params = gda_set_new_inline (8,
+ "session", G_TYPE_INT, session_id,
+ "id", G_TYPE_INT, fav->id,
+ "type", G_TYPE_STRING, favorite_type_to_string (fav->type),
+ "name", G_TYPE_STRING, fav->name,
+ "contents", G_TYPE_STRING, fav->contents,
+ "rank", G_TYPE_INT, pos,
+ "orderkey", G_TYPE_INT, order_key,
+ "descr", G_TYPE_STRING, fav->descr);
+
+ favid = find_favorite (bfav, session_id, fav->id, fav->contents, NULL);
+ if (favid == -1) {
+ /* insert a favorite */
+ GdaSqlBuilder *builder;
+ GdaStatement *stmt;
+ builder = gda_sql_builder_new (GDA_SQL_STATEMENT_INSERT);
+ gda_sql_builder_set_table (builder, FAVORITES_TABLE_NAME);
+
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "session"),
+ gda_sql_builder_param (builder, 0, "session", G_TYPE_INT, FALSE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "type"),
+ gda_sql_builder_param (builder, 0, "type", G_TYPE_INT, FALSE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "name"),
+ gda_sql_builder_param (builder, 0, "name", G_TYPE_STRING, TRUE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "contents"),
+ gda_sql_builder_param (builder, 0, "contents", G_TYPE_STRING, FALSE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "descr"),
+ gda_sql_builder_param (builder, 0, "descr", G_TYPE_STRING, TRUE));
+ stmt = gda_sql_builder_get_statement (builder, error);
+ g_object_unref (G_OBJECT (builder));
+ if (!stmt)
+ goto err;
+ if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
+ g_object_unref (stmt);
+ goto err;
+ }
+ g_object_unref (stmt);
+ }
+ else {
+ /* update favorite's contents */
+ GdaSqlBuilder *builder;
+ GdaStatement *stmt;
+
+ gda_set_set_holder_value (params, NULL, "id", favid);
+ builder = gda_sql_builder_new (GDA_SQL_STATEMENT_UPDATE);
+ gda_sql_builder_set_table (builder, FAVORITES_TABLE_NAME);
+
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "name"),
+ gda_sql_builder_param (builder, 0, "name", G_TYPE_STRING, TRUE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "contents"),
+ gda_sql_builder_param (builder, 0, "contents", G_TYPE_STRING, FALSE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "descr"),
+ gda_sql_builder_param (builder, 0, "descr", G_TYPE_STRING, TRUE));
+
+ gda_sql_builder_set_where (builder,
+ gda_sql_builder_cond (builder, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (builder, 0, "id"),
+ gda_sql_builder_param (builder, 0, "id", G_TYPE_INT, FALSE),
+ 0));
+ stmt = gda_sql_builder_get_statement (builder, error);
+ g_object_unref (G_OBJECT (builder));
+ if (!stmt)
+ goto err;
+ if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
+ g_object_unref (stmt);
+ goto err;
+ }
+ g_object_unref (stmt);
+ }
+
+ if (order_key >= 0) {
+ GdaSqlBuilder *builder;
+ GdaStatement *stmt;
+
+ /* delete and insert favorite in orders table */
+ favid = find_favorite (bfav, session_id, fav->id, fav->contents, error);
+ if (favid < 0) {
+ g_warning ("Could not identify favorite by its ID, make sure it's correct");
+ goto err;
+ }
+
+ gda_set_set_holder_value (params, NULL, "id", favid);
+
+ builder = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
+ gda_sql_builder_set_table (builder, FAVORDER_TABLE_NAME);
+ gda_sql_builder_set_where (builder,
+ gda_sql_builder_cond (builder, 0, GDA_SQL_OPERATOR_TYPE_AND,
+ gda_sql_builder_cond (builder, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (builder, 0, "fav_id"),
+ gda_sql_builder_param (builder, 0, "id", G_TYPE_INT, FALSE),
+ 0),
+ gda_sql_builder_cond (builder, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (builder, 0, "order_key"),
+ gda_sql_builder_param (builder, 0, "orderkey", G_TYPE_INT, FALSE),
+ 0), 0));
+ stmt = gda_sql_builder_get_statement (builder, error);
+ g_object_unref (G_OBJECT (builder));
+ if (!stmt)
+ goto err;
+ if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
+ g_object_unref (stmt);
+ goto err;
+ }
+ g_object_unref (stmt);
+
+ builder = gda_sql_builder_new (GDA_SQL_STATEMENT_INSERT);
+ gda_sql_builder_set_table (builder, FAVORDER_TABLE_NAME);
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "fav_id"),
+ gda_sql_builder_param (builder, 0, "id", G_TYPE_INT, FALSE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "rank"),
+ gda_sql_builder_param (builder, 0, "rank", G_TYPE_INT, FALSE));
+ gda_sql_builder_add_field (builder,
+ gda_sql_builder_literal (builder, 0, "order_key"),
+ gda_sql_builder_param (builder, 0, "orderkey", G_TYPE_STRING, TRUE));
+ stmt = gda_sql_builder_get_statement (builder, error);
+ g_object_unref (G_OBJECT (builder));
+ if (!stmt)
+ goto err;
+ if (gda_connection_statement_execute_non_select (store_cnc, stmt, params, NULL, error) == -1) {
+ g_object_unref (stmt);
+ goto err;
+ }
+ g_object_unref (stmt);
+
+ /* reorder */
+ if (!favorites_reorder (bfav, order_key, favid, pos, error))
+ goto err;
+ }
+
+ if (! gda_connection_commit_transaction (store_cnc, NULL, NULL)) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't commit transaction to access favorites"));
+ goto err;
+ }
+
+ if (params)
+ g_object_unref (params);
+ gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
+ g_signal_emit (bfav, browser_favorites_signals [FAV_CHANGED],
+ g_quark_from_string (favorite_type_to_string (fav->type)));
+ return TRUE;
+
+ err:
+ if (params)
+ g_object_unref (params);
+ gda_lockable_unlock (GDA_LOCKABLE (store_cnc));
+ gda_connection_rollback_transaction (store_cnc, NULL, NULL);
+ return FALSE;
+}
+
+/**
+ * browser_favorites_free_list
+ */
+void
+browser_favorites_free_list (GSList *fav_list)
+{
+ GSList *list;
+ if (!fav_list)
+ return;
+ for (list = fav_list; list; list = list->next) {
+ BrowserFavoritesAttributes *fav = (BrowserFavoritesAttributes*) list->data;
+ g_free (fav->contents);
+ g_free (fav->descr);
+ g_free (fav);
+ }
+ g_slist_free (fav_list);
+}
+
+/**
+ * browser_favorites_list
+ *
+ * Returns: a new list of #BrowserFavoritesAttributes pointers. The list has to
+ * be freed using browser_favorites_free_list()
+ */
+GSList *
+browser_favorites_list (BrowserFavorites *bfav, guint session_id, BrowserFavoritesType type,
+ gint order_key, GError **error)
+{
+ GdaSqlBuilder *b;
+ GdaSet *params = NULL;
+ GdaStatement *stmt;
+ guint t1, t2;
+ GdaDataModel *model = NULL;
+ GSList *fav_list = NULL;
+
+ guint and_cond_ids [3];
+ int and_cond_size = 0;
+ guint or_cond_ids [BROWSER_FAVORITES_NB_TYPES];
+ int or_cond_size = 0;
+
+ g_return_val_if_fail (BROWSER_IS_FAVORITES (bfav), NULL);
+ g_return_val_if_fail ((type != 0) || (order_key >= 0), NULL);
+
+ if (! bfav->priv->store_cnc &&
+ ! meta_store_addons_init (bfav, error))
+ return NULL;
+
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "fav.contents"), 0);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "fav.descr"), 0);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "fav.name"), 0);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "fav.type"), 0);
+ gda_sql_builder_add_field (b,
+ gda_sql_builder_literal (b, 0, "fav.id"), 0);
+
+ t1 = gda_sql_builder_select_add_target (b, 0,
+ gda_sql_builder_literal (b, 0, FAVORITES_TABLE_NAME),
+ "fav");
+ if (order_key > 0) {
+ t2 = gda_sql_builder_select_add_target (b, 0,
+ gda_sql_builder_literal (b, 0, FAVORDER_TABLE_NAME),
+ "o");
+ gda_sql_builder_select_join_targets (b, 0, t1, t2, GDA_SQL_SELECT_JOIN_LEFT,
+ gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "fav.id"),
+ gda_sql_builder_literal (b, 0, "o.fav_id"),
+ 0));
+ gda_sql_builder_select_order_by (b,
+ gda_sql_builder_literal (b, 0, "o.rank"), TRUE, NULL);
+
+ and_cond_ids [and_cond_size] = gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "o.order_key"),
+ gda_sql_builder_param (b, 0, "okey", G_TYPE_INT, FALSE),
+ 0);
+ and_cond_size++;
+ }
+
+ and_cond_ids [and_cond_size] = gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "fav.session"),
+ gda_sql_builder_param (b, 0, "session", G_TYPE_INT, FALSE), 0);
+ and_cond_size++;
+
+ gint i;
+ gint flag;
+ for (i = 0, flag = 1; i < BROWSER_FAVORITES_NB_TYPES; i++, flag <<= 1) {
+ if (type & flag) {
+ gchar *str;
+ str = g_strdup_printf ("'%s'", favorite_type_to_string (flag));
+ or_cond_ids [or_cond_size] = gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "fav.type"),
+ gda_sql_builder_literal (b, 0, str),
+ 0);
+ g_free (str);
+ or_cond_size++;
+ }
+ }
+ if (or_cond_size >= 1) {
+ and_cond_ids [and_cond_size] = gda_sql_builder_cond_v (b, 0, GDA_SQL_OPERATOR_TYPE_OR,
+ or_cond_ids, or_cond_size);
+ and_cond_size++;
+ }
+
+ gda_sql_builder_set_where (b,
+ gda_sql_builder_cond_v (b, 0, GDA_SQL_OPERATOR_TYPE_AND, and_cond_ids, and_cond_size));
+
+ {
+ GdaSqlStatement *sqlst;
+ sqlst = gda_sql_builder_get_sql_statement (b, TRUE);
+ g_print ("=>%s\n", gda_sql_statement_serialize (sqlst));
+ }
+
+ stmt = gda_sql_builder_get_statement (b, error);
+ g_object_unref (G_OBJECT (b));
+ if (!stmt)
+ goto out;
+
+ params = gda_set_new_inline (2,
+ "session", G_TYPE_INT, session_id,
+ "okey", G_TYPE_INT, order_key);
+
+ model = gda_connection_statement_execute_select (bfav->priv->store_cnc, stmt, params, error);
+ g_object_unref (stmt);
+ if (!model)
+ goto out;
+
+ gint nrows;
+ nrows = gda_data_model_get_n_rows (model);
+ for (i = 0; i < nrows; i++) {
+ const GValue *contents, *descr = NULL, *name = NULL, *type = NULL, *id = NULL;
+
+ contents = gda_data_model_get_value_at (model, 0, i, error);
+ if (contents)
+ descr = gda_data_model_get_value_at (model, 1, i, error);
+ if (descr)
+ name = gda_data_model_get_value_at (model, 2, i, error);
+ if (name)
+ type = gda_data_model_get_value_at (model, 3, i, error);
+ if (type)
+ id = gda_data_model_get_value_at (model, 4, i, error);
+ if (id) {
+ BrowserFavoritesAttributes *fav;
+ fav = g_new0 (BrowserFavoritesAttributes, 1);
+ fav->id = g_value_get_int (id);
+ fav->type = favorite_string_to_type (g_value_get_string (type));
+ if (G_VALUE_TYPE (descr) == G_TYPE_STRING)
+ fav->descr = g_value_dup_string (descr);
+ if (G_VALUE_TYPE (name) == G_TYPE_STRING)
+ fav->name = g_value_dup_string (name);
+ fav->contents = g_value_dup_string (contents);
+ fav_list = g_slist_prepend (fav_list, fav);
+ }
+ else {
+ browser_favorites_free_list (fav_list);
+ fav_list = NULL;
+ goto out;
+ }
+ }
+
+ out:
+ if (params)
+ g_object_unref (G_OBJECT (params));
+ if (model)
+ g_object_unref (G_OBJECT (model));
+
+ return g_slist_reverse (fav_list);
+}
+
+
+/**
+ * browser_favorites_delete_favorite
+ */
+gboolean
+browser_favorites_delete (BrowserFavorites *bfav, guint session_id,
+ BrowserFavoritesAttributes *fav, GError **error)
+{
+ GdaSqlBuilder *b;
+ GdaSet *params = NULL;
+ GdaStatement *stmt;
+ gboolean retval = FALSE;
+ gint favid;
+
+ g_return_val_if_fail (BROWSER_IS_FAVORITES (bfav), FALSE);
+ g_return_val_if_fail (fav, FALSE);
+ g_return_val_if_fail ((fav->id >= 0) || fav->contents, FALSE);
+
+ if (! bfav->priv->store_cnc &&
+ ! meta_store_addons_init (bfav, error))
+ return FALSE;
+
+ if (! gda_lockable_trylock (GDA_LOCKABLE (bfav->priv->store_cnc))) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't initialize transaction to access favorites"));
+ return FALSE;
+ }
+ /* begin a transaction */
+ if (! gda_connection_begin_transaction (bfav->priv->store_cnc, NULL,
+ GDA_TRANSACTION_ISOLATION_UNKNOWN, NULL)) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't initialize transaction to access favorites"));
+ gda_lockable_unlock (GDA_LOCKABLE (bfav->priv->store_cnc));
+ return FALSE;
+ }
+
+ favid = find_favorite (bfav, session_id, fav->id, fav->contents, error);
+ if (favid < 0)
+ goto out;
+
+ /* remove entry from favorites' list */
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
+ gda_sql_builder_set_table (b, FAVORITES_TABLE_NAME);
+ gda_sql_builder_set_where (b, gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "id"),
+ gda_sql_builder_param (b, 0, "id", G_TYPE_INT, FALSE),
+ 0));
+
+ stmt = gda_sql_builder_get_statement (b, error);
+ g_object_unref (G_OBJECT (b));
+ if (!stmt)
+ goto out;
+
+ params = gda_set_new_inline (1,
+ "id", G_TYPE_INT, favid);
+
+ if (gda_connection_statement_execute_non_select (bfav->priv->store_cnc, stmt, params, NULL, error) == -1) {
+ g_object_unref (stmt);
+ goto out;
+ }
+ g_object_unref (stmt);
+
+ /* remove entry from favorites' order */
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_DELETE);
+ gda_sql_builder_set_table (b, FAVORDER_TABLE_NAME);
+ gda_sql_builder_set_where (b, gda_sql_builder_cond (b, 0, GDA_SQL_OPERATOR_TYPE_EQ,
+ gda_sql_builder_literal (b, 0, "fav_id"),
+ gda_sql_builder_param (b, 0, "id", G_TYPE_INT, FALSE),
+ 0));
+
+ stmt = gda_sql_builder_get_statement (b, error);
+ g_object_unref (G_OBJECT (b));
+ if (!stmt)
+ goto out;
+ if (gda_connection_statement_execute_non_select (bfav->priv->store_cnc, stmt, params, NULL, error) == -1) {
+ g_object_unref (stmt);
+ goto out;
+ }
+ g_object_unref (stmt);
+
+ if (! gda_connection_commit_transaction (bfav->priv->store_cnc, NULL, NULL)) {
+ g_set_error (error, 0, 0, "%s",
+ _("Can't commit transaction to access favorites"));
+ goto out;
+ }
+ retval = TRUE;
+
+ out:
+ if (!retval)
+ gda_connection_rollback_transaction (bfav->priv->store_cnc, NULL, NULL);
+
+ gda_lockable_unlock (GDA_LOCKABLE (bfav->priv->store_cnc));
+ if (retval)
+ g_signal_emit (bfav, browser_favorites_signals [FAV_CHANGED],
+ g_quark_from_string (favorite_type_to_string (fav->type)));
+ if (params)
+ g_object_unref (G_OBJECT (params));
+
+ return retval;
+}
diff --git a/tools/browser/browser-favorites.h b/tools/browser/browser-favorites.h
new file mode 100644
index 0000000..bd8e6ea
--- /dev/null
+++ b/tools/browser/browser-favorites.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2009 Vivien Malerba
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __BROWSER_FAVORITES_H_
+#define __BROWSER_FAVORITES_H_
+
+#include <libgda/libgda.h>
+#include "decl.h"
+
+G_BEGIN_DECLS
+
+#define BROWSER_TYPE_FAVORITES (browser_favorites_get_type())
+#define BROWSER_FAVORITES(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, browser_favorites_get_type(), BrowserFavorites)
+#define BROWSER_FAVORITES_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, browser_favorites_get_type (), BrowserFavoritesClass)
+#define BROWSER_IS_FAVORITES(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, browser_favorites_get_type ())
+
+typedef struct _BrowserFavorites BrowserFavorites;
+typedef struct _BrowserFavoritesClass BrowserFavoritesClass;
+typedef struct _BrowserFavoritesPrivate BrowserFavoritesPrivate;
+
+typedef enum {
+ BROWSER_FAVORITES_TABLES = 1 << 0,
+ BROWSER_FAVORITES_DIAGRAMS = 1 << 1
+} BrowserFavoritesType;
+#define BROWSER_FAVORITES_NB_TYPES 2
+
+typedef struct {
+ gint id;
+ BrowserFavoritesType type;
+ gchar *name;
+ gchar *descr;
+ gchar *contents;
+} BrowserFavoritesAttributes;
+
+/* struct for the object's data */
+struct _BrowserFavorites
+{
+ GObject object;
+ BrowserFavoritesPrivate *priv;
+};
+
+/* struct for the object's class */
+struct _BrowserFavoritesClass
+{
+ GObjectClass parent_class;
+
+ void (*favorites_changed) (BrowserFavorites *bfav);
+};
+
+GType browser_favorites_get_type (void) G_GNUC_CONST;
+
+BrowserFavorites *browser_favorites_new (GdaMetaStore *store);
+
+gint browser_favorites_add (BrowserFavorites *bfav, guint session_id,
+ BrowserFavoritesAttributes *fav,
+ gint order_key, gint pos,
+ GError **error);
+GSList *browser_favorites_list (BrowserFavorites *bcnc, guint session_id,
+ BrowserFavoritesType type, gint order_key, GError **error);
+gboolean browser_favorites_delete (BrowserFavorites *bcnc, guint session_id,
+ BrowserFavoritesAttributes *fav, GError **error);
+void browser_favorites_free_list (GSList *fav_list);
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/canvas/browser-canvas-db-relations.c b/tools/browser/canvas/browser-canvas-db-relations.c
index 805219e..7894854 100644
--- a/tools/browser/canvas/browser-canvas-db-relations.c
+++ b/tools/browser/canvas/browser-canvas-db-relations.c
@@ -44,6 +44,7 @@ static void browser_canvas_db_relations_get_property (GObject *object,
/* virtual functions */
static void clean_canvas_items (BrowserCanvas *canvas);
static GtkWidget *build_context_menu (BrowserCanvas *canvas);
+static GSList *get_layout_items (BrowserCanvas *canvas);
/* get a pointer to the parents to be able to call their destructor */
static GObjectClass *parent_class = NULL;
@@ -60,7 +61,7 @@ struct _BrowserCanvasDbRelationsPrivate
GHashTable *hash_fkeys; /* key = GdaMetaTableForeignKey, value = BrowserCanvasFkey */
GdaMetaStruct *mstruct;
- GooCanvasItem *level_separator; /* all tables will be above this item and FK lines below */
+ GooCanvasItem *level_separator; /* all tables items will be above this item and FK lines below */
};
GType
@@ -104,6 +105,7 @@ browser_canvas_db_relations_class_init (BrowserCanvasDbRelationsClass * class)
/* BrowserCanvas virtual functions */
BROWSER_CANVAS_CLASS (class)->clean_canvas_items = clean_canvas_items;
BROWSER_CANVAS_CLASS (class)->build_context_menu = build_context_menu;
+ BROWSER_CANVAS_CLASS (class)->get_layout_items = get_layout_items;
object_class->dispose = browser_canvas_db_relations_dispose;
/* properties */
@@ -323,6 +325,68 @@ popup_func_add_depend_cb (GtkMenuItem *mitem, BrowserCanvasTable *ce)
}
}
+static GSList *
+complement_layout_items (BrowserCanvasDbRelations *dbrel, BrowserCanvasItem *current, GSList *elist)
+{
+ GSList *items = elist;
+ GdaMetaTable *mtable;
+ mtable = g_hash_table_lookup (dbrel->priv->hash_tables, current);
+ if (!mtable)
+ return items;
+
+ GSList *list;
+ for (list = mtable->fk_list; list; list = list->next) {
+ GdaMetaTableForeignKey *fk = (GdaMetaTableForeignKey*) list->data;
+ BrowserCanvasItem *item;
+
+ item = g_hash_table_lookup (dbrel->priv->hash_fkeys, fk);
+ if (item && !g_slist_find (items, item)) {
+ items = g_slist_prepend (items, item);
+ items = complement_layout_items (dbrel, item, items);
+ }
+ }
+
+ for (list = mtable->reverse_fk_list; list; list = list->next) {
+ GdaMetaTableForeignKey *fk = (GdaMetaTableForeignKey*) list->data;
+ BrowserCanvasItem *item;
+
+ item = g_hash_table_lookup (dbrel->priv->hash_fkeys, fk);
+ if (item && !g_slist_find (items, item)) {
+ items = g_slist_prepend (items, item);
+ items = complement_layout_items (dbrel, item, items);
+ }
+ }
+
+ return items;
+}
+
+static GSList *
+get_layout_items (BrowserCanvas *canvas)
+{
+ GSList *items = NULL;
+ BrowserCanvasDbRelations *dbrel = BROWSER_CANVAS_DB_RELATIONS (canvas);
+
+ if (!canvas->priv->current_selected_item)
+ return g_slist_copy (canvas->priv->items);
+
+ GdaMetaTable *mtable;
+ mtable = g_hash_table_lookup (dbrel->priv->hash_tables, canvas->priv->current_selected_item);
+ if (!mtable)
+ return g_slist_copy (canvas->priv->items);
+
+ items = g_slist_prepend (NULL, canvas->priv->current_selected_item);
+ items = complement_layout_items (dbrel, canvas->priv->current_selected_item, items);
+
+ /* add non related items */
+ GSList *list;
+ for (list = canvas->priv->items; list; list = list->next) {
+ if (!g_slist_find (items, list->data))
+ items = g_slist_prepend (items, list->data);
+ }
+
+ return g_slist_reverse (items);
+}
+
static void popup_add_table_cb (GtkMenuItem *mitem, BrowserCanvasDbRelations *canvas);
static GtkWidget *
build_context_menu (BrowserCanvas *canvas)
@@ -448,7 +512,6 @@ browser_canvas_db_relations_add_table (BrowserCanvasDbRelations *canvas,
const GValue *table_name)
{
g_return_val_if_fail (IS_BROWSER_CANVAS_DB_RELATIONS (canvas), NULL);
- g_return_val_if_fail (canvas->priv, NULL);
GdaMetaTable *mtable;
GooCanvas *goocanvas;
@@ -523,4 +586,17 @@ browser_canvas_db_relations_add_table (BrowserCanvasDbRelations *canvas,
else
return NULL;
}
-
+
+/**
+ * browser_canvas_db_relations_select_table
+ */
+void
+browser_canvas_db_relations_select_table (BrowserCanvasDbRelations *canvas,
+ BrowserCanvasTable *table)
+{
+ g_return_if_fail (IS_BROWSER_CANVAS_DB_RELATIONS (canvas));
+ g_return_if_fail (!table || IS_BROWSER_CANVAS_ITEM (table));
+
+ browser_canvas_item_toggle_select (BROWSER_CANVAS (canvas), (BrowserCanvasItem*) table);
+}
+
diff --git a/tools/browser/canvas/browser-canvas-db-relations.h b/tools/browser/canvas/browser-canvas-db-relations.h
index bcbefc8..b9270f7 100644
--- a/tools/browser/canvas/browser-canvas-db-relations.h
+++ b/tools/browser/canvas/browser-canvas-db-relations.h
@@ -60,6 +60,8 @@ BrowserCanvasTable *browser_canvas_db_relations_add_table (BrowserCanvasDbRelat
const GValue *table_catalog,
const GValue *table_schema,
const GValue *table_name);
+void browser_canvas_db_relations_select_table (BrowserCanvasDbRelations *canvas,
+ BrowserCanvasTable *table);
G_END_DECLS
diff --git a/tools/browser/canvas/browser-canvas-table.c b/tools/browser/canvas/browser-canvas-table.c
index 9d9139d..342f225 100644
--- a/tools/browser/canvas/browser-canvas-table.c
+++ b/tools/browser/canvas/browser-canvas-table.c
@@ -21,6 +21,7 @@
#include <gtk/gtk.h>
#include <libgda/libgda.h>
#include "browser-canvas.h"
+#include "browser-canvas-priv.h"
#include "browser-canvas-table.h"
#include "browser-canvas-column.h"
#include <glib/gi18n-lib.h>
@@ -63,10 +64,6 @@ struct _BrowserCanvasTablePrivate
gdouble *column_ypos; /* array for each column's Y position in this canvas group */
GtkWidget *(*popup_menu_func) (BrowserCanvasTable *ce);
- /* presentation parameters */
- gdouble x_text_space;
- gdouble y_text_space;
-
GooCanvasItem *selection_mark;
};
@@ -143,9 +140,6 @@ browser_canvas_table_init (BrowserCanvasTable *table)
table->priv->column_ypos = NULL;
table->priv->popup_menu_func = NULL;
- table->priv->x_text_space = 3.;
- table->priv->y_text_space = 3.;
-
table->priv->selection_mark = NULL;
g_signal_connect (G_OBJECT (table), "button-press-event",
@@ -292,6 +286,7 @@ create_items (BrowserCanvasTable *ce)
#define RADIUS_X 5.
#define RADIUS_Y 5.
#define MIN_HEIGHT 70.
+#define SELECTION_SIZE 4.
GooCanvasBounds border_bounds;
GooCanvasBounds bounds;
const gchar *cstr;
@@ -363,6 +358,17 @@ create_items (BrowserCanvasTable *ce)
NULL);
ce->priv->other_items = g_slist_prepend (ce->priv->other_items, frame);
+ ce->priv->selection_mark = goo_canvas_rect_new (GOO_CANVAS_ITEM (ce), border_bounds.x1 - SELECTION_SIZE,
+ border_bounds.y1 - SELECTION_SIZE,
+ border_bounds.x2 + 2 * SELECTION_SIZE,
+ border_bounds.y2 + 2 * SELECTION_SIZE,
+ "radius-x", RADIUS_X,
+ "radius-y", RADIUS_Y,
+ "fill-color", "#11d155",//"#ffea08",
+ "stroke-color", "#11d155",//"#ffea08",
+ NULL);
+ g_object_set (G_OBJECT (ce->priv->selection_mark), "visibility", GOO_CANVAS_ITEM_HIDDEN, NULL);
+
/* title's background */
gchar *cpath;
cpath = g_strdup_printf ("M %d %d H %d V %d H %d Z",
@@ -386,6 +392,7 @@ create_items (BrowserCanvasTable *ce)
ce->priv->other_items = g_slist_prepend (ce->priv->other_items, item);
goo_canvas_item_lower (frame, NULL);
+ goo_canvas_item_lower (ce->priv->selection_mark, NULL);
/* setting the columns' background width to be the same for all */
for (list = ce->priv->column_items; list; list = list->next)
@@ -532,41 +539,25 @@ browser_canvas_table_drag_data_get (BrowserCanvasItem *citem, GdkDragContext *dr
static void
browser_canvas_table_set_selected (BrowserCanvasItem *citem, gboolean selected)
{
- GooCanvasBounds bounds;
-
- if (selected) {
- if (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark)
- g_object_set (G_OBJECT (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark),
- "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL);
- else {
- GooCanvasItem *root;
- GooCanvasItem *rect;
-
- //root = goo_canvas_get_root_item (goo_canvas_item_get_canvas (GOO_CANVAS_ITEM (citem)));
- root = GOO_CANVAS_ITEM (citem);
- goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (citem), &bounds);
- rect = goo_canvas_rect_new (root, - 1., - 1.,
- bounds.x2 - bounds.x1 + 2.,
- bounds.y2 - bounds.y1 + 2.,
- "radius-x", RADIUS_X,
- "radius-y", RADIUS_Y,
- "stroke-color", "#ffea08",
- NULL);
- /*
- rect = goo_canvas_rect_new (root, bounds.x1 - 1., bounds.y1 - 1.,
- bounds.x2 - bounds.x1 + 2.,
- bounds.y2 - bounds.y1 + 2.,
- "radius-x", RADIUS_X,
- "radius-y", RADIUS_Y,
- "stroke-color", "#ffea08",
- NULL);
- */
- BROWSER_CANVAS_TABLE (citem)->priv->selection_mark = rect;
- }
- }
- else {
- if (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark)
- g_object_set (G_OBJECT (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark),
- "visibility", GOO_CANVAS_ITEM_HIDDEN, NULL);
- }
+ g_object_set (G_OBJECT (BROWSER_CANVAS_TABLE (citem)->priv->selection_mark),
+ "visibility", selected ? GOO_CANVAS_ITEM_VISIBLE : GOO_CANVAS_ITEM_HIDDEN, NULL);
+}
+
+/**
+ * browser_canvas_table_get_anchor_bounds
+ *
+ * Get the bounds to be used to compute anchors, ie. without the selection mark or any other
+ * artefact not part of the table's rectangle.
+ */
+void
+browser_canvas_table_get_anchor_bounds (BrowserCanvasTable *ce, GooCanvasBounds *bounds)
+{
+ g_return_if_fail (IS_BROWSER_CANVAS_TABLE (ce));
+ g_return_if_fail (bounds);
+
+ goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (ce), bounds);
+ bounds->x1 += SELECTION_SIZE;
+ bounds->y1 += SELECTION_SIZE;
+ bounds->x2 -= SELECTION_SIZE;
+ bounds->y2 -= SELECTION_SIZE;
}
diff --git a/tools/browser/canvas/browser-canvas-table.h b/tools/browser/canvas/browser-canvas-table.h
index 13aad1a..67d663c 100644
--- a/tools/browser/canvas/browser-canvas-table.h
+++ b/tools/browser/canvas/browser-canvas-table.h
@@ -61,6 +61,7 @@ GooCanvasItem *browser_canvas_table_new (GooCanvasItem *parent
gdouble x, gdouble y, ...);
BrowserCanvasColumn *browser_canvas_table_get_column_item (BrowserCanvasTable *ce, GdaMetaTableColumn *column);
gdouble browser_canvas_table_get_column_ypos (BrowserCanvasTable *ce, GdaMetaTableColumn *column);
+void browser_canvas_table_get_anchor_bounds (BrowserCanvasTable *ce, GooCanvasBounds *bounds);
G_END_DECLS
diff --git a/tools/browser/canvas/browser-canvas-utility.c b/tools/browser/canvas/browser-canvas-utility.c
index 5c541ea..4435b3c 100644
--- a/tools/browser/canvas/browser-canvas-utility.c
+++ b/tools/browser/canvas/browser-canvas-utility.c
@@ -68,12 +68,12 @@ browser_canvas_util_compute_anchor_shapes (GooCanvasItem *parent, GSList *shapes
g_return_val_if_fail (nb_anchors > 0, NULL);
- goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (fk_ent), &bounds);
+ browser_canvas_table_get_anchor_bounds (fk_ent, &bounds);
fx1 = bounds.x1;
fy1 = bounds.y1;
fx2 = bounds.x2;
fy2 = bounds.y2;
- goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (ref_pk_ent), &bounds);
+ browser_canvas_table_get_anchor_bounds (ref_pk_ent, &bounds);
rx1 = bounds.x1;
ry1 = bounds.y1;
rx2 = bounds.x2;
@@ -553,11 +553,11 @@ browser_canvas_util_compute_connect_shapes (GooCanvasItem *parent, GSList *shape
/* line made of 4 points */
points = goo_canvas_points_new (4);
- goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (ent1), &bounds);
+ browser_canvas_table_get_anchor_bounds (ent1, &bounds);
xl1 = bounds.x1;
yt1 = bounds.y1;
xr1 = bounds.x2;
- goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (ent2), &bounds);
+ browser_canvas_table_get_anchor_bounds (ent2, &bounds);
xl2 = bounds.x1;
yt2 = bounds.y1;
xr2 = bounds.x2;
diff --git a/tools/browser/canvas/browser-canvas.c b/tools/browser/canvas/browser-canvas.c
index fdfa06a..f77f84f 100644
--- a/tools/browser/canvas/browser-canvas.c
+++ b/tools/browser/canvas/browser-canvas.c
@@ -234,13 +234,22 @@ static gboolean
canvas_scroll_event_cb (GooCanvas *gcanvas, GdkEvent *event, BrowserCanvas *canvas)
{
gboolean done = TRUE;
+ GdkEventScroll *ev = (GdkEventScroll *) event;
switch (event->type) {
case GDK_SCROLL:
- if (((GdkEventScroll *) event)->direction == GDK_SCROLL_UP)
- browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) + .03);
- else if (((GdkEventScroll *) event)->direction == GDK_SCROLL_DOWN)
- browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) - .03);
+ if (ev->state & GDK_SHIFT_MASK) {
+ if (ev->direction == GDK_SCROLL_UP)
+ browser_canvas_scale_layout (canvas, 1.05);
+ else
+ browser_canvas_scale_layout (canvas, .95);
+ }
+ else {
+ if (ev->direction == GDK_SCROLL_UP)
+ browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) + .03);
+ else if (ev->direction == GDK_SCROLL_DOWN)
+ browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) - .03);
+ }
done = TRUE;
break;
default:
@@ -294,6 +303,8 @@ motion_notify_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanv
return done;
}
+static void popup_layout_default_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
+static void popup_layout_radial_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_zoom_in_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_zoom_out_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
static void popup_zoom_fit_cb (GtkMenuItem *mitem, BrowserCanvas *canvas);
@@ -348,6 +359,22 @@ canvas_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas)
mitem = gtk_separator_menu_item_new ();
gtk_widget_show (mitem);
gtk_menu_append (menu, mitem);
+
+#ifdef HAVE_GRAPHVIZ
+ mitem = gtk_menu_item_new_with_label (_("Linear layout"));
+ gtk_widget_show (mitem);
+ gtk_menu_append (menu, mitem);
+ g_signal_connect (G_OBJECT (mitem), "activate", G_CALLBACK (popup_layout_default_cb), canvas);
+
+ mitem = gtk_menu_item_new_with_label (_("Radial layout"));
+ gtk_widget_show (mitem);
+ gtk_menu_append (menu, mitem);
+ g_signal_connect (G_OBJECT (mitem), "activate", G_CALLBACK (popup_layout_radial_cb), canvas);
+
+ mitem = gtk_separator_menu_item_new ();
+ gtk_widget_show (mitem);
+ gtk_menu_append (menu, mitem);
+#endif
mitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL);
gtk_widget_show (mitem);
@@ -402,6 +429,18 @@ canvas_event_cb (BrowserCanvas *canvas, GdkEvent *event, GooCanvas *gcanvas)
}
static void
+popup_layout_default_cb (GtkMenuItem *mitem, BrowserCanvas *canvas)
+{
+ browser_canvas_perform_auto_layout (canvas, TRUE, BROWSER_CANVAS_LAYOUT_DEFAULT);
+}
+
+static void
+popup_layout_radial_cb (GtkMenuItem *mitem, BrowserCanvas *canvas)
+{
+ browser_canvas_perform_auto_layout (canvas, TRUE, BROWSER_CANVAS_LAYOUT_RADIAL);
+}
+
+static void
popup_zoom_in_cb (GtkMenuItem *mitem, BrowserCanvas *canvas)
{
browser_canvas_set_zoom_factor (canvas, browser_canvas_get_zoom_factor (canvas) + .05);
@@ -835,7 +874,8 @@ browser_canvas_perform_auto_layout (BrowserCanvas *canvas, gboolean animate, Bro
g_message ("GraphViz library support not compiled, cannot do graph layout...\n");
return FALSE;
#else
- GSList *list;
+ BrowserCanvasClass *class = BROWSER_CANVAS_CLASS (G_OBJECT_GET_CLASS (canvas));
+ GSList *list, *layout_items;
Agraph_t *graph;
GHashTable *nodes_hash; /* key = BrowserCanvasItem, value = Agnode_t *node */
GSList *nodes_list = NULL; /* list of NodeLayout structures */
@@ -843,7 +883,7 @@ browser_canvas_perform_auto_layout (BrowserCanvas *canvas, gboolean animate, Bro
if (!gvc)
gvc = gvContext ();
- graph = agopen ("BrowserCanvasLayout", AGDIGRAPHSTRICT);
+ graph = agopen ("BrowserCanvasLayout", AGRAPH);
agnodeattr (graph, "shape", "box");
agnodeattr (graph, "height", ".1");
agnodeattr (graph, "width", ".1");
@@ -851,9 +891,15 @@ browser_canvas_perform_auto_layout (BrowserCanvas *canvas, gboolean animate, Bro
agnodeattr (graph, "pack", "true");
agnodeattr (graph, "packmode", "node");
+
+ if (class->get_layout_items)
+ layout_items = class->get_layout_items (canvas);
+ else
+ layout_items = canvas->priv->items;
+
/* Graph nodes creation */
nodes_hash = g_hash_table_new (NULL, NULL);
- for (list = canvas->priv->items; list; list = list->next) {
+ for (list = layout_items; list; list = list->next) {
BrowserCanvasItem *item = BROWSER_CANVAS_ITEM (list->data);
Agnode_t *node;
gchar *tmp;
@@ -900,7 +946,7 @@ browser_canvas_perform_auto_layout (BrowserCanvas *canvas, gboolean animate, Bro
(bounds.x2 - bounds.x1) / GV_SCALE);*/
}
/* Graph edges creation */
- for (list = canvas->priv->items; list; list = list->next) {
+ for (list = layout_items; list; list = list->next) {
BrowserCanvasItem *item = BROWSER_CANVAS_ITEM (list->data);
BrowserCanvasItem *from, *to;
gboolean moving;
@@ -919,6 +965,9 @@ browser_canvas_perform_auto_layout (BrowserCanvas *canvas, gboolean animate, Bro
}
}
+ if (layout_items != canvas->priv->items)
+ g_slist_free (layout_items);
+
switch (algorithm) {
default:
case BROWSER_CANVAS_LAYOUT_DEFAULT:
@@ -1032,6 +1081,40 @@ canvas_animate_to (GraphLayout *gl)
#endif
/**
+ * browser_canvas_scale_layout
+ */
+void
+browser_canvas_scale_layout (BrowserCanvas *canvas, gdouble scale)
+{
+ GSList *list;
+ GooCanvasBounds ref_bounds;
+ gdouble refx, refy;
+
+ g_return_if_fail (IS_BROWSER_CANVAS (canvas));
+ if (!canvas->priv->items)
+ return;
+
+ goo_canvas_get_bounds (canvas->priv->goocanvas, &ref_bounds.x1, &ref_bounds.y1,
+ &ref_bounds.x2, &ref_bounds.y2);
+ refx = (ref_bounds.x2 - ref_bounds.x1) / 2.;
+ refy = (ref_bounds.y2 - ref_bounds.y1) / 2.;
+ for (list = canvas->priv->items; list; list = list->next) {
+ gboolean can_move;
+ g_object_get ((GObject*) list->data, "allow-move", &can_move, NULL);
+ if (can_move) {
+ BrowserCanvasItem *item = BROWSER_CANVAS_ITEM (list->data);
+ GooCanvasBounds bounds;
+ gdouble tx, ty;
+
+ goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (item), &bounds);
+ tx = (scale - 1.) * (bounds.x1 - refx);
+ ty = (scale - 1.) * (bounds.y1 - refy);
+ browser_canvas_item_translate (item, tx, ty);
+ }
+ }
+}
+
+/**
* browser_canvas_serialize_items
*/
gchar *
@@ -1044,6 +1127,8 @@ browser_canvas_serialize_items (BrowserCanvas *canvas)
BrowserCanvasItem *item = BROWSER_CANVAS_ITEM (list->data);
TO_IMPLEMENT;
}
+
+ return NULL;
}
/**
diff --git a/tools/browser/canvas/browser-canvas.h b/tools/browser/canvas/browser-canvas.h
index e3e109b..151e006 100644
--- a/tools/browser/canvas/browser-canvas.h
+++ b/tools/browser/canvas/browser-canvas.h
@@ -60,6 +60,7 @@ struct _BrowserCanvasClass
/* virtual functions */
void (*clean_canvas_items) (BrowserCanvas *canvas); /* clean any extra structure, not the individual items */
+ GSList *(*get_layout_items) (BrowserCanvas *canvas);
GtkWidget *(*build_context_menu) (BrowserCanvas *canvas);
};
@@ -75,6 +76,8 @@ gboolean browser_canvas_auto_layout_enabled (BrowserCanvas *canvas
void browser_canvas_perform_auto_layout (BrowserCanvas *canvas, gboolean animate,
BrowserCanvasLayoutAlgorithm algorithm);
void browser_canvas_center (BrowserCanvas *canvas);
+void browser_canvas_scale_layout (BrowserCanvas *canvas, gdouble scale);
+
gchar *browser_canvas_serialize_items (BrowserCanvas *canvas);
void browser_canvas_item_toggle_select (BrowserCanvas *canvas, BrowserCanvasItem *item);
diff --git a/tools/browser/decl.h b/tools/browser/decl.h
index e8841f6..401fa75 100644
--- a/tools/browser/decl.h
+++ b/tools/browser/decl.h
@@ -41,9 +41,7 @@ typedef struct {
} BrowserPerspectiveFactory;
#define BROWSER_PERSPECTIVE_FACTORY(x) ((BrowserPerspectiveFactory*)(x))
-typedef enum {
- BROWSER_FAVORITES_TABLES
-} BrowserFavoritesType;
+#define ORDER_KEY_SCHEMA 1
G_END_DECLS
diff --git a/tools/browser/favorites-test.c b/tools/browser/favorites-test.c
new file mode 100644
index 0000000..b3fbcf2
--- /dev/null
+++ b/tools/browser/favorites-test.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <libgda/libgda.h>
+#include "browser-favorites.h"
+#include <string.h>
+
+static void
+dump_favorite (BrowserFavoritesAttributes *f)
+{
+ g_print ("Favorite: ID=>%d\n", f->id);
+ g_print (" Type=>%d\n", f->type);
+ g_print (" Name=>%s\n", f->name);
+ g_print (" Descr=>%s\n", f->descr);
+ g_print (" Contents=>%s\n", f->contents);
+}
+
+static void
+dump_favorites_in_db (GdaConnection *cnc)
+{
+ GdaDataModel *model;
+ GError *error = NULL;
+
+ g_print ("\n*********** contents of gda_sql_favorites ***********\n");
+ model = gda_meta_store_extract (gda_connection_get_meta_store (cnc), "SELECT * FROM gda_sql_favorites", &error,
+ NULL);
+ if (!model) {
+ g_print ("Could not extract list of favorites: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ gda_data_model_dump (model, NULL);
+ g_object_unref (model);
+
+ g_print ("\n************ contents of gda_sql_favorder ***********\n");
+ model = gda_meta_store_extract (gda_connection_get_meta_store (cnc), "SELECT * FROM gda_sql_favorder", &error,
+ NULL);
+ if (!model) {
+ g_print ("Could not extract list of favorites: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ gda_data_model_dump (model, NULL);
+ g_object_unref (model);
+}
+
+static void test1 (GdaConnection *cnc, BrowserFavorites *bfav);
+static void test2 (GdaConnection *cnc, BrowserFavorites *bfav);
+static void test3 (GdaConnection *cnc, BrowserFavorites *bfav);
+int
+main (int argc, char *argv[])
+{
+ BrowserFavorites *bfav;
+ GdaConnection *cnc;
+ GError *error = NULL;
+
+ gda_init ();
+
+ cnc = gda_connection_open_from_dsn ("SalesTest", NULL,
+ GDA_CONNECTION_OPTIONS_NONE,
+ &error);
+ if (!cnc) {
+ g_print ("Could not open connection: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ bfav = browser_favorites_new (gda_connection_get_meta_store (cnc));
+ test1 (cnc, bfav);
+ test2 (cnc, bfav);
+ test3 (cnc, bfav);
+ g_object_unref (G_OBJECT (bfav));
+ g_object_unref (G_OBJECT (cnc));
+
+ g_print ("OK!\n");
+ return 0;
+}
+
+static void
+test1 (GdaConnection *cnc, BrowserFavorites *bfav)
+{
+ gint favid, i;
+ GError *error = NULL;
+ BrowserFavoritesAttributes fav_array[]= {
+ {-1, BROWSER_FAVORITES_TABLES, "table1", "fav1-descr", "fav1 contents"},
+ {-1, BROWSER_FAVORITES_DIAGRAMS, "diagram1", "fav2-descr", "fav2 contents"}
+ };
+ for (i = 0; i < G_N_ELEMENTS (fav_array); i++) {
+ BrowserFavoritesAttributes *f = (BrowserFavoritesAttributes*) &(fav_array[i]);
+ favid = browser_favorites_add (bfav, 0, f, -1, 0, &error);
+ if (!favid < 0) {
+ g_print ("Could not create favorite: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ }
+ //dump_favorites_in_db (cnc);
+
+ GSList *favlist, *list;
+ favlist = browser_favorites_list (bfav, 0, BROWSER_FAVORITES_TABLES, -1, &error);
+ if (!favlist && error) {
+ g_print ("Could not list favorites: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ for (i = 0, list = favlist; (i < G_N_ELEMENTS (fav_array)) && list; i++, list = list -> next) {
+ BrowserFavoritesAttributes *f1 = (BrowserFavoritesAttributes*) &(fav_array[i]);
+ BrowserFavoritesAttributes *f2 = (BrowserFavoritesAttributes*) list->data;
+ if (f2->id == 0) {
+ g_print ("ID should not be 0:\n");
+ dump_favorite (f1);
+ dump_favorite (f2);
+ exit (1);
+ }
+ if ((f2->type != f1->type) ||
+ strcmp (f2->contents, f1->contents) ||
+ strcmp (f2->descr, f1->descr) ||
+ strcmp (f2->name, f1->name)) {
+ g_print ("Favorites differ:\n");
+ dump_favorite (f1);
+ dump_favorite (f2);
+ exit (1);
+ }
+ }
+ if (list || (i != G_N_ELEMENTS (fav_array))) {
+ g_print ("Wrong number of favorites reported\n");
+ exit (1);
+ }
+ browser_favorites_free_list (favlist);
+}
+
+static void
+test2 (GdaConnection *cnc, BrowserFavorites *bfav)
+{
+ gint favid, i;
+ GError *error = NULL;
+ BrowserFavoritesAttributes fav_array[]= {
+ {-1, BROWSER_FAVORITES_TABLES, "table2", "fav1-descr", "fav1 contents SEPARATE"},
+ {-1, BROWSER_FAVORITES_DIAGRAMS, "diagram2", "fav2-descr", "fav2 contents SEPARATE"},
+ {-1, BROWSER_FAVORITES_TABLES, "table2", "Another description for table2", "fav1 contents SEPARATE"},
+ };
+ BrowserFavoritesAttributes res_fav_array[]= {
+ {-1, BROWSER_FAVORITES_TABLES, "table2", "Another description for table2", "fav1 contents SEPARATE"},
+ {-1, BROWSER_FAVORITES_DIAGRAMS, "diagram2", "fav2-descr", "fav2 contents SEPARATE"},
+ };
+ for (i = 0; i < G_N_ELEMENTS (fav_array); i++) {
+ BrowserFavoritesAttributes *f = (BrowserFavoritesAttributes*) &(fav_array[i]);
+ favid = browser_favorites_add (bfav, 0, f, 1, 0, &error);
+ if (!favid < 0) {
+ g_print ("Could not create favorite: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ }
+ dump_favorites_in_db (cnc);
+
+ GSList *favlist, *list;
+ favlist = browser_favorites_list (bfav, 0, BROWSER_FAVORITES_TABLES, 1, &error);
+ if (!favlist && error) {
+ g_print ("Could not list favorites: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ for (i = 0, list = favlist; (i < G_N_ELEMENTS (res_fav_array)) && list; i++, list = list -> next) {
+ BrowserFavoritesAttributes *f1 = (BrowserFavoritesAttributes*) &(res_fav_array[i]);
+ BrowserFavoritesAttributes *f2 = (BrowserFavoritesAttributes*) list->data;
+ if (f2->id == 0) {
+ g_print ("ID should not be 0:\n");
+ dump_favorite (f1);
+ dump_favorite (f2);
+ exit (1);
+ }
+ if ((f2->type != f1->type) ||
+ strcmp (f2->contents, f1->contents) ||
+ strcmp (f2->descr, f1->descr) ||
+ strcmp (f2->name, f1->name)) {
+ g_print ("Favorites differ:\n");
+ dump_favorite (f1);
+ dump_favorite (f2);
+ exit (1);
+ }
+ }
+ if (list || (i != G_N_ELEMENTS (res_fav_array))) {
+ g_print ("Wrong number of favorites reported\n");
+ exit (1);
+ }
+ browser_favorites_free_list (favlist);
+}
+
+static void
+test3 (GdaConnection *cnc, BrowserFavorites *bfav)
+{
+ gint favid, i;
+ GError *error = NULL;
+ BrowserFavoritesAttributes fav_array[]= {
+ {-1, BROWSER_FAVORITES_DIAGRAMS, "diagram2", "fav2-descr", "fav2 contents SEPARATE"},
+ };
+ BrowserFavoritesAttributes res_fav_array[]= {
+ {-1, BROWSER_FAVORITES_TABLES, "table2", "Another description for table2", "fav1 contents SEPARATE"},
+ };
+ for (i = 0; i < G_N_ELEMENTS (fav_array); i++) {
+ BrowserFavoritesAttributes *f = (BrowserFavoritesAttributes*) &(fav_array[i]);
+ favid = browser_favorites_delete (bfav, 0, f, &error);
+ if (!favid < 0) {
+ g_print ("Could not delete favorite: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ }
+ dump_favorites_in_db (cnc);
+
+ GSList *favlist, *list;
+ favlist = browser_favorites_list (bfav, 0, BROWSER_FAVORITES_TABLES, 1, &error);
+ if (!favlist && error) {
+ g_print ("Could not list favorites: %s\n",
+ error && error->message ? error->message : "No detail");
+ exit (1);
+ }
+ for (i = 0, list = favlist; (i < G_N_ELEMENTS (res_fav_array)) && list; i++, list = list -> next) {
+ BrowserFavoritesAttributes *f1 = (BrowserFavoritesAttributes*) &(res_fav_array[i]);
+ BrowserFavoritesAttributes *f2 = (BrowserFavoritesAttributes*) list->data;
+ if (f2->id == 0) {
+ g_print ("ID should not be 0:\n");
+ dump_favorite (f1);
+ dump_favorite (f2);
+ exit (1);
+ }
+ if ((f2->type != f1->type) ||
+ strcmp (f2->contents, f1->contents) ||
+ strcmp (f2->descr, f1->descr) ||
+ strcmp (f2->name, f1->name)) {
+ g_print ("Favorites differ:\n");
+ dump_favorite (f1);
+ dump_favorite (f2);
+ exit (1);
+ }
+ }
+ if (list || (i != G_N_ELEMENTS (res_fav_array))) {
+ g_print ("Wrong number of favorites reported\n");
+ exit (1);
+ }
+ browser_favorites_free_list (favlist);
+}
diff --git a/tools/browser/gda-browser-diagram.png b/tools/browser/gda-browser-diagram.png
new file mode 100644
index 0000000..c8d9e65
Binary files /dev/null and b/tools/browser/gda-browser-diagram.png differ
diff --git a/tools/browser/mgr-favorites.c b/tools/browser/mgr-favorites.c
index 60a4849..8d89f33 100644
--- a/tools/browser/mgr-favorites.c
+++ b/tools/browser/mgr-favorites.c
@@ -205,14 +205,18 @@ hash_for_existing_nodes (const GSList *nodes)
GHashTable *hash;
const GSList *list;
- hash = g_hash_table_new (g_str_hash, g_str_equal);
+ hash = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL);
for (list = nodes; list; list = list->next) {
const GValue *cvalue;
- cvalue = gda_tree_node_get_node_attribute ((GdaTreeNode*) list->data, MGR_FAVORITES_CONTENTS_ATT_NAME);
- if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING)) {
- const gchar *str = g_value_get_string (cvalue);
- if (str)
- g_hash_table_insert (hash, (gpointer) str, list->data);
+ cvalue = gda_tree_node_get_node_attribute ((GdaTreeNode*) list->data, MGR_FAVORITES_ID_ATT_NAME);
+ if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_INT)) {
+ gint id;
+ id = g_value_get_int (cvalue);
+ if (id >= 0) {
+ gint *key = g_new0 (gint, 1);
+ *key = id;
+ g_hash_table_insert (hash, (gpointer) key, list->data);
+ }
}
}
return hash;
@@ -234,53 +238,103 @@ mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const
if (children_nodes)
ehash = hash_for_existing_nodes (children_nodes);
- fav_list = browser_connection_list_favorites (mgr->priv->bcnc, 0, BROWSER_FAVORITES_TABLES, &lerror);
+ fav_list = browser_favorites_list (browser_connection_get_favorites (mgr->priv->bcnc),
+ 0, BROWSER_FAVORITES_TABLES | BROWSER_FAVORITES_DIAGRAMS,
+ ORDER_KEY_SCHEMA, &lerror);
if (fav_list) {
GSList *list;
for (list = fav_list; list; list = list->next) {
- BrowserConnectionFavorite *fav = (BrowserConnectionFavorite *) list->data;
+ BrowserFavoritesAttributes *fav = (BrowserFavoritesAttributes *) list->data;
GdaTreeNode* snode = NULL;
+ GValue *av;
if (ehash)
- snode = g_hash_table_lookup (ehash, fav->contents);
- if (snode) {
+ snode = g_hash_table_lookup (ehash, &(fav->id));
+
+
+ if (snode)
/* use the same node */
g_object_ref (G_OBJECT (snode));
- }
- else {
- GValue *av;
- GdaQuarkList *ql;
- const gchar *fname = NULL;
-
- ql = gda_quark_list_new_from_string (fav->contents);
- if (!ql || !(fname = gda_quark_list_find (ql, "OBJ_SHORT_NAME"))) {
- g_warning ("Invalid TABLE favorite format: %s", fav->contents);
+
+ if (fav->type == BROWSER_FAVORITES_TABLES) {
+ if (!snode) {
+ GdaQuarkList *ql;
+ const gchar *fname = NULL;
+
+ ql = gda_quark_list_new_from_string (fav->contents);
+ if (!ql || !(fname = gda_quark_list_find (ql, "OBJ_SHORT_NAME"))) {
+ g_warning ("Invalid TABLE favorite format: %s", fav->contents);
+ }
+ else {
+ snode = gda_tree_manager_create_node (manager, node, NULL);
+ g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fname);
+ gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
+ gda_value_free (av);
+
+ g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
+ fav->contents);
+ gda_tree_node_set_node_attribute (snode,
+ MGR_FAVORITES_CONTENTS_ATT_NAME,
+ av, NULL);
+ gda_value_free (av);
+
+
+ g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
+ gda_tree_node_set_node_attribute (snode,
+ MGR_FAVORITES_ID_ATT_NAME,
+ av, NULL);
+ gda_value_free (av);
+
+ /* icon */
+ GdkPixbuf *pixbuf;
+ pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_TABLE);
+ av = gda_value_new (G_TYPE_OBJECT);
+ g_value_set_object (av, pixbuf);
+ gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
+ gda_value_free (av);
+ }
+ if (ql)
+ gda_quark_list_free (ql);
}
- else {
+ }
+ else if (fav->type == BROWSER_FAVORITES_DIAGRAMS) {
+ if (!snode) {
snode = gda_tree_manager_create_node (manager, node, NULL);
- g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fname);
- gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
- gda_value_free (av);
-
- g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fav->contents);
- gda_tree_node_set_node_attribute (snode, MGR_FAVORITES_CONTENTS_ATT_NAME, av, NULL);
+
+ g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
+ gda_tree_node_set_node_attribute (snode,
+ MGR_FAVORITES_ID_ATT_NAME,
+ av, NULL);
gda_value_free (av);
/* icon */
GdkPixbuf *pixbuf;
- pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_TABLE);
+ pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_DIAGRAM);
av = gda_value_new (G_TYPE_OBJECT);
g_value_set_object (av, pixbuf);
gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
gda_value_free (av);
}
- if (ql)
- gda_quark_list_free (ql);
+
+ g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
+ fav->contents);
+ gda_tree_node_set_node_attribute (snode,
+ MGR_FAVORITES_CONTENTS_ATT_NAME,
+ av, NULL);
+ gda_value_free (av);
+
+ g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fav->name);
+ gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
+ gda_value_free (av);
+ }
+
+ else {
+
}
if (snode)
nodes_list = g_slist_prepend (nodes_list, snode);
}
- browser_connection_free_favorites_list (fav_list);
+ browser_favorites_free_list (fav_list);
}
else if (lerror) {
if (out_error)
diff --git a/tools/browser/mgr-favorites.h b/tools/browser/mgr-favorites.h
index b002af5..ecb85b7 100644
--- a/tools/browser/mgr-favorites.h
+++ b/tools/browser/mgr-favorites.h
@@ -52,6 +52,8 @@ GdaTreeManager* mgr_favorites_new (BrowserConnection *bcnc,
/* name of the attribute which stores the favorite's contents */
#define MGR_FAVORITES_CONTENTS_ATT_NAME "fav_contents"
+/* name of the attribute which stores the favorite's id */
+#define MGR_FAVORITES_ID_ATT_NAME "fav_id"
G_END_DECLS
diff --git a/tools/browser/schema-browser/Makefile.am b/tools/browser/schema-browser/Makefile.am
index aea39bb..c55c42c 100644
--- a/tools/browser/schema-browser/Makefile.am
+++ b/tools/browser/schema-browser/Makefile.am
@@ -27,5 +27,7 @@ libperspective_la_SOURCES = \
if HAVE_GOOCANVAS
libperspective_la_SOURCES += \
table-relations.c \
- table-relations.h
+ table-relations.h \
+ relations-diagram.c \
+ relations-diagram.h
endif
diff --git a/tools/browser/schema-browser/favorite-selector.c b/tools/browser/schema-browser/favorite-selector.c
index 8d903e1..99e8e6f 100644
--- a/tools/browser/schema-browser/favorite-selector.c
+++ b/tools/browser/schema-browser/favorite-selector.c
@@ -30,6 +30,7 @@
#include "../dnd.h"
#include "../support.h"
#include "../cc-gray-bar.h"
+#include "../browser-favorites.h"
struct _FavoriteSelectorPrivate {
BrowserConnection *bcnc;
@@ -42,7 +43,7 @@ static void favorite_selector_init (FavoriteSelector *tsel,
FavoriteSelectorClass *klass);
static void favorite_selector_dispose (GObject *object);
-static void favorites_changed_cb (BrowserConnection *bcnc, FavoriteSelector *tsel);
+static void favorites_changed_cb (BrowserFavorites *bfav, FavoriteSelector *tsel);
enum {
SELECTION_CHANGED,
@@ -99,7 +100,7 @@ favorite_selector_dispose (GObject *object)
g_object_unref (tsel->priv->tree);
if (tsel->priv->bcnc) {
- g_signal_handlers_disconnect_by_func (tsel->priv->bcnc,
+ g_signal_handlers_disconnect_by_func (browser_connection_get_favorites (tsel->priv->bcnc),
G_CALLBACK (favorites_changed_cb), tsel);
g_object_unref (tsel->priv->bcnc);
}
@@ -178,7 +179,7 @@ favorite_selector_new (BrowserConnection *bcnc)
tsel = FAVORITE_SELECTOR (g_object_new (FAVORITE_SELECTOR_TYPE, NULL));
tsel->priv->bcnc = g_object_ref (bcnc);
- g_signal_connect (tsel->priv->bcnc, "favorites-changed::TABLE",
+ g_signal_connect (browser_connection_get_favorites (tsel->priv->bcnc), "favorites-changed",
G_CALLBACK (favorites_changed_cb), tsel);
/* create tree managers */
@@ -258,8 +259,8 @@ favorite_selector_new (BrowserConnection *bcnc)
G_CALLBACK (tree_store_drag_can_drag_cb), tsel);
g_signal_connect (model, "drag-get",
G_CALLBACK (tree_store_drag_get_cb), tsel);
- g_signal_connect (model, "drag-delete",
- G_CALLBACK (tree_store_drag_delete_cb), tsel);
+ //g_signal_connect (model, "drag-delete",
+ // G_CALLBACK (tree_store_drag_delete_cb), tsel);
/* delete favorite */
GtkWidget *image;
@@ -300,19 +301,23 @@ static gboolean
tree_store_drag_drop_cb (GdauiTreeStore *store, const gchar *path, GtkSelectionData *selection_data,
FavoriteSelector *tsel)
{
- BrowserConnectionFavorite fav;
+ BrowserFavorites *bfav;
+ BrowserFavoritesAttributes fav;
GError *error = NULL;
gint pos;
-
+ memset (&fav, 0, sizeof (BrowserFavoritesAttributes));
+ fav.id = -1;
fav.type = BROWSER_FAVORITES_TABLES;
+ fav.name = NULL;
fav.descr = NULL;
fav.contents = (gchar*) selection_data->data;
pos = atoi (path);
g_print ("%s() path => %s, pos: %d\n", __FUNCTION__, path, pos);
- if (! browser_connection_add_favorite (tsel->priv->bcnc, 0, &fav, pos, &error)) {
+ bfav = browser_connection_get_favorites (tsel->priv->bcnc);
+ if (! browser_favorites_add (bfav, 0, &fav, ORDER_KEY_SCHEMA, pos, &error)) {
browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) tsel),
_("Could not add favorite: %s"),
error && error->message ? error->message : _("No detail"));
@@ -369,12 +374,16 @@ tree_store_drag_delete_cb (GdauiTreeStore *store, const gchar *path,
cvalue = gda_tree_node_get_node_attribute (node, "fav_contents");
if (cvalue) {
GError *lerror = NULL;
- BrowserConnectionFavorite fav;
- memset (&fav, 0, sizeof (BrowserConnectionFavorite));
+ BrowserFavorites *bfav;
+ BrowserFavoritesAttributes fav;
+
+ bfav = browser_connection_get_favorites (tsel->priv->bcnc);
+ memset (&fav, 0, sizeof (BrowserFavoritesAttributes));
+ fav.id = -1;
fav.type = BROWSER_FAVORITES_TABLES;
fav.descr = NULL;
fav.contents = (gchar*) g_value_get_string (cvalue);
- if (! browser_connection_delete_favorite (tsel->priv->bcnc, 0, &fav, &lerror)) {
+ if (! browser_favorites_delete (bfav, 0, &fav, &lerror)) {
browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*)tsel),
_("Could not remove favorite: %s"),
lerror && lerror->message ? lerror->message : _("No detail"));
@@ -390,7 +399,7 @@ tree_store_drag_delete_cb (GdauiTreeStore *store, const gchar *path,
static void
-favorites_changed_cb (BrowserConnection *bcnc, FavoriteSelector *tsel)
+favorites_changed_cb (BrowserFavorites *bfav, FavoriteSelector *tsel)
{
if (! gda_tree_update_all (tsel->priv->tree, NULL)) {
if (tsel->priv->idle_update_favorites == 0)
diff --git a/tools/browser/schema-browser/relations-diagram.c b/tools/browser/schema-browser/relations-diagram.c
new file mode 100644
index 0000000..e0f481e
--- /dev/null
+++ b/tools/browser/schema-browser/relations-diagram.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2009 The GNOME Foundation
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include "relations-diagram.h"
+#include "../support.h"
+#include "../cc-gray-bar.h"
+#include "../canvas/browser-canvas-db-relations.h"
+#include <gdk/gdkkeysyms.h>
+
+struct _RelationsDiagramPrivate {
+ BrowserConnection *bcnc;
+ gchar *name; /* diagram's name */
+
+ CcGrayBar *header;
+ GtkWidget *canvas;
+ GtkWidget *save_button;
+
+ GtkWidget *window; /* to enter canvas's name */
+ GtkWidget *name_entry;
+ GtkWidget *real_save_button;
+};
+
+static void relations_diagram_class_init (RelationsDiagramClass *klass);
+static void relations_diagram_init (RelationsDiagram *diagram, RelationsDiagramClass *klass);
+static void relations_diagram_dispose (GObject *object);
+static void relations_diagram_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void relations_diagram_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void meta_changed_cb (BrowserConnection *bcnc, GdaMetaStruct *mstruct, RelationsDiagram *diagram);
+
+/* properties */
+enum {
+ PROP_0,
+};
+
+enum {
+ SELECTION_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint relations_diagram_signals[LAST_SIGNAL] = { 0 };
+static GObjectClass *parent_class = NULL;
+
+
+/*
+ * RelationsDiagram class implementation
+ */
+
+static void
+relations_diagram_class_init (RelationsDiagramClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ /* Properties */
+ object_class->set_property = relations_diagram_set_property;
+ object_class->get_property = relations_diagram_get_property;
+
+ object_class->dispose = relations_diagram_dispose;
+}
+
+
+static void
+relations_diagram_init (RelationsDiagram *diagram, RelationsDiagramClass *klass)
+{
+ diagram->priv = g_new0 (RelationsDiagramPrivate, 1);
+ diagram->priv->name = NULL;
+ diagram->priv->window = NULL;
+}
+
+static void
+relations_diagram_dispose (GObject *object)
+{
+ RelationsDiagram *diagram = (RelationsDiagram *) object;
+
+ /* free memory */
+ if (diagram->priv) {
+ if (diagram->priv->bcnc) {
+ g_signal_handlers_disconnect_by_func (diagram->priv->bcnc,
+ G_CALLBACK (meta_changed_cb), diagram);
+ g_object_unref (diagram->priv->bcnc);
+ }
+
+ if (diagram->priv->window)
+ gtk_widget_destroy (diagram->priv->window);
+
+ g_free (diagram->priv->name);
+ g_free (diagram->priv);
+ diagram->priv = NULL;
+ }
+
+ parent_class->dispose (object);
+}
+
+GType
+relations_diagram_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo info = {
+ sizeof (RelationsDiagramClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) relations_diagram_class_init,
+ NULL,
+ NULL,
+ sizeof (RelationsDiagram),
+ 0,
+ (GInstanceInitFunc) relations_diagram_init
+ };
+ type = g_type_register_static (GTK_TYPE_VBOX, "RelationsDiagram", &info, 0);
+ }
+ return type;
+}
+
+static void
+relations_diagram_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RelationsDiagram *diagram;
+ diagram = RELATIONS_DIAGRAM (object);
+ switch (param_id) {
+ }
+}
+
+static void
+relations_diagram_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RelationsDiagram *diagram;
+ diagram = RELATIONS_DIAGRAM (object);
+ switch (param_id) {
+ }
+}
+
+static void
+meta_changed_cb (BrowserConnection *bcnc, GdaMetaStruct *mstruct, RelationsDiagram *diagram)
+{
+ g_object_set (G_OBJECT (diagram->priv->canvas), "meta-struct", mstruct, NULL);
+}
+
+
+/*
+ * POPUP
+ */
+static void
+position_popup (RelationsDiagram *diagram)
+{
+ gint x, y;
+ gint bwidth, bheight;
+ GtkRequisition req;
+
+ gtk_widget_size_request (diagram->priv->window, &req);
+
+ gdk_window_get_origin (diagram->priv->save_button->window, &x, &y);
+
+ x += diagram->priv->save_button->allocation.x;
+ y += diagram->priv->save_button->allocation.y;
+ bwidth = diagram->priv->save_button->allocation.width;
+ bheight = diagram->priv->save_button->allocation.height;
+
+ x += bwidth - req.width;
+ y += bheight;
+
+ if (x < 0)
+ x = 0;
+
+ if (y < 0)
+ y = 0;
+
+ gtk_window_move (GTK_WINDOW (diagram->priv->window), x, y);
+}
+
+
+
+static gboolean
+popup_grab_on_window (GdkWindow *window, guint32 activate_time)
+{
+ if ((gdk_pointer_grab (window, TRUE,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK,
+ NULL, NULL, activate_time) == 0)) {
+ if (gdk_keyboard_grab (window, TRUE,
+ activate_time) == 0)
+ return TRUE;
+ else {
+ gdk_pointer_ungrab (activate_time);
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+
+static gboolean
+delete_popup (GtkWidget *widget, RelationsDiagram *diagram)
+{
+ gtk_widget_hide (diagram->priv->window);
+ gtk_grab_remove (diagram->priv->window);
+ return TRUE;
+}
+
+static gboolean
+key_press_popup (GtkWidget *widget, GdkEventKey *event, RelationsDiagram *diagram)
+{
+ if (event->keyval != GDK_Escape)
+ return FALSE;
+
+ g_signal_stop_emission_by_name (widget, "key_press_event");
+ gtk_widget_hide (diagram->priv->window);
+ gtk_grab_remove (diagram->priv->window);
+ return TRUE;
+}
+
+static gboolean
+button_press_popup (GtkWidget *widget, GdkEventButton *event, RelationsDiagram *diagram)
+{
+ GtkWidget *child;
+
+ child = gtk_get_event_widget ((GdkEvent *) event);
+
+ /* We don't ask for button press events on the grab widget, so
+ * if an event is reported directly to the grab widget, it must
+ * be on a window outside the application (and thus we remove
+ * the popup window). Otherwise, we check if the widget is a child
+ * of the grab widget, and only remove the popup window if it
+ * is not.
+ */
+ if (child != widget) {
+ while (child) {
+ if (child == widget)
+ return FALSE;
+ child = child->parent;
+ }
+ }
+ gtk_widget_hide (diagram->priv->window);
+ gtk_grab_remove (diagram->priv->window);
+ return TRUE;
+}
+
+
+static void
+real_save_clicked_cb (GtkWidget *button, RelationsDiagram *diagram)
+{
+ gchar *str;
+
+ //str = browser_canvas_serialize_items (BROWSER_CANVAS (diagram->priv->canvas));
+ str = g_strdup ("OOOOO");
+
+ GError *lerror = NULL;
+ BrowserFavorites *bfav;
+ BrowserFavoritesAttributes fav;
+
+ memset (&fav, 0, sizeof (BrowserFavoritesAttributes));
+ fav.id = -1;
+ fav.type = BROWSER_FAVORITES_DIAGRAMS;
+ fav.name = gtk_editable_get_chars (GTK_EDITABLE (diagram->priv->name_entry), 0, -1);
+ if (!*fav.name) {
+ g_free (fav.name);
+ fav.name = g_strdup ("Diagram #0");
+ }
+ fav.contents = str;
+
+ gtk_widget_hide (diagram->priv->window);
+ gtk_grab_remove (diagram->priv->window);
+
+ bfav = browser_connection_get_favorites (diagram->priv->bcnc);
+ if (! browser_favorites_add (bfav, 0, &fav, ORDER_KEY_SCHEMA, G_MAXINT, &lerror)) {
+ browser_show_error ((GtkWindow*) gtk_widget_get_toplevel (button),
+ "<b>%s:</b>\n%s",
+ _("Could not save diagram"),
+ lerror && lerror->message ? lerror->message : _("No detail"));
+ if (lerror)
+ g_error_free (lerror);
+ }
+ g_free (fav.name);
+ g_free (str);
+}
+
+static void
+save_clicked_cb (GtkWidget *button, RelationsDiagram *diagram)
+{
+ gchar *str;
+
+ if (!diagram->priv->window) {
+ GtkWidget *window, *wid, *hbox;
+
+ window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_widget_set_events (window, gtk_widget_get_events (window) | GDK_KEY_PRESS_MASK);
+ gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 5);
+ g_signal_connect (G_OBJECT (window), "delete_event",
+ G_CALLBACK (delete_popup), diagram);
+ g_signal_connect (G_OBJECT (window), "key_press_event",
+ G_CALLBACK (key_press_popup), diagram);
+ g_signal_connect (G_OBJECT (window), "button_press_event",
+ G_CALLBACK (button_press_popup), diagram);
+ diagram->priv->window = window;
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), hbox);
+ wid = gtk_label_new ("");
+ str = g_strdup_printf ("%s:", _("Canvas's name"));
+ gtk_label_set_markup (GTK_LABEL (wid), str);
+ g_free (str);
+ gtk_box_pack_start (GTK_BOX (hbox), wid, FALSE, FALSE, 0);
+
+ wid = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), wid, FALSE, FALSE, 5);
+ diagram->priv->name_entry = wid;
+
+ wid = gtk_button_new_with_label (_("Save"));
+ gtk_box_pack_start (GTK_BOX (hbox), wid, FALSE, FALSE, 0);
+ g_signal_connect (wid, "clicked",
+ G_CALLBACK (real_save_clicked_cb), diagram);
+ diagram->priv->real_save_button = wid;
+
+ gtk_widget_show_all (hbox);
+ }
+
+ if (!popup_grab_on_window (button->window, gtk_get_current_event_time ()))
+ return;
+ position_popup (diagram);
+ gtk_grab_add (diagram->priv->window);
+ gtk_widget_show (diagram->priv->window);
+
+ GdkScreen *screen;
+ gint swidth, sheight;
+ gint root_x, root_y;
+ gint wwidth, wheight;
+ gboolean do_move = FALSE;
+ screen = gtk_window_get_screen (GTK_WINDOW (diagram->priv->window));
+ if (screen) {
+ swidth = gdk_screen_get_width (screen);
+ sheight = gdk_screen_get_height (screen);
+ }
+ else {
+ swidth = gdk_screen_width ();
+ sheight = gdk_screen_height ();
+ }
+ gtk_window_get_position (GTK_WINDOW (diagram->priv->window), &root_x, &root_y);
+ gtk_window_get_size (GTK_WINDOW (diagram->priv->window), &wwidth, &wheight);
+ if (root_x + wwidth > swidth) {
+ do_move = TRUE;
+ root_x = swidth - wwidth;
+ }
+ else if (root_x < 0) {
+ do_move = TRUE;
+ root_x = 0;
+ }
+ if (root_y + wheight > sheight) {
+ do_move = TRUE;
+ root_y = sheight - wheight;
+ }
+ else if (root_y < 0) {
+ do_move = TRUE;
+ root_y = 0;
+ }
+ if (do_move)
+ gtk_window_move (GTK_WINDOW (diagram->priv->window), root_x, root_y);
+
+ str = gtk_editable_get_chars (GTK_EDITABLE (diagram->priv->name_entry), 0, -1);
+ if (!*str)
+ gtk_widget_grab_focus (diagram->priv->name_entry);
+ else
+ gtk_widget_grab_focus (diagram->priv->real_save_button);
+ g_free (str);
+ popup_grab_on_window (diagram->priv->window->window,
+ gtk_get_current_event_time ());
+}
+
+
+/**
+ * relations_diagram_new
+ *
+ * Returns: a new #GtkWidget
+ */
+GtkWidget *
+relations_diagram_new (BrowserConnection *bcnc)
+{
+ RelationsDiagram *diagram;
+
+ g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+
+ diagram = RELATIONS_DIAGRAM (g_object_new (RELATIONS_DIAGRAM_TYPE, NULL));
+
+ diagram->priv->bcnc = g_object_ref (bcnc);
+ g_signal_connect (diagram->priv->bcnc, "meta-changed",
+ G_CALLBACK (meta_changed_cb), diagram);
+
+ /* header */
+ GtkWidget *hbox, *wid;
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (diagram), hbox, FALSE, FALSE, 0);
+
+ GtkWidget *label;
+ gchar *str;
+ str = g_strdup_printf ("<b>%s</b>\n%s", _("Relations diagram"), _("Unsaved diagram"));
+ label = cc_gray_bar_new (str);
+ g_free (str);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ diagram->priv->header = CC_GRAY_BAR (label);
+
+ wid = gtk_button_new ();
+ label = gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_BUTTON);
+ gtk_container_add (GTK_CONTAINER (wid), label);
+ gtk_box_pack_start (GTK_BOX (hbox), wid, FALSE, FALSE, 0);
+ g_object_set (G_OBJECT (wid), "label", NULL, NULL);
+ diagram->priv->save_button = wid;
+
+ g_signal_connect (wid, "clicked",
+ G_CALLBACK (save_clicked_cb), diagram);
+
+ gtk_widget_show_all (hbox);
+
+ /* main contents */
+ wid = browser_canvas_db_relations_new (NULL);
+ diagram->priv->canvas = wid;
+ gtk_box_pack_start (GTK_BOX (diagram), wid, TRUE, TRUE, 0);
+ gtk_widget_show_all (wid);
+
+ GdaMetaStruct *mstruct;
+ mstruct = browser_connection_get_meta_struct (diagram->priv->bcnc);
+ if (mstruct)
+ meta_changed_cb (diagram->priv->bcnc, mstruct, diagram);
+
+ return (GtkWidget*) diagram;
+}
diff --git a/tools/browser/schema-browser/relations-diagram.h b/tools/browser/schema-browser/relations-diagram.h
new file mode 100644
index 0000000..d757805
--- /dev/null
+++ b/tools/browser/schema-browser/relations-diagram.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 The GNOME Foundation
+ *
+ * AUTHORS:
+ * Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __RELATIONS_DIAGRAM_H__
+#define __RELATIONS_DIAGRAM_H__
+
+#include <gtk/gtkvbox.h>
+#include "../browser-connection.h"
+
+G_BEGIN_DECLS
+
+#define RELATIONS_DIAGRAM_TYPE (relations_diagram_get_type())
+#define RELATIONS_DIAGRAM(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, RELATIONS_DIAGRAM_TYPE, RelationsDiagram))
+#define RELATIONS_DIAGRAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, RELATIONS_DIAGRAM_TYPE, RelationsDiagramClass))
+#define IS_RELATIONS_DIAGRAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, RELATIONS_DIAGRAM_TYPE))
+#define IS_RELATIONS_DIAGRAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RELATIONS_DIAGRAM_TYPE))
+
+typedef struct _RelationsDiagram RelationsDiagram;
+typedef struct _RelationsDiagramClass RelationsDiagramClass;
+typedef struct _RelationsDiagramPrivate RelationsDiagramPrivate;
+
+struct _RelationsDiagram {
+ GtkVBox parent;
+ RelationsDiagramPrivate *priv;
+};
+
+struct _RelationsDiagramClass {
+ GtkVBoxClass parent_class;
+};
+
+GType relations_diagram_get_type (void) G_GNUC_CONST;
+GtkWidget *relations_diagram_new (BrowserConnection *bcnc);
+
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/schema-browser/schema-browser-perspective.c b/tools/browser/schema-browser/schema-browser-perspective.c
index a57c78e..75c251c 100644
--- a/tools/browser/schema-browser/schema-browser-perspective.c
+++ b/tools/browser/schema-browser/schema-browser-perspective.c
@@ -25,6 +25,9 @@
#include "../browser-window.h"
#include "table-info.h"
#include "../support.h"
+#ifdef HAVE_GOOCANVAS
+#include "relations-diagram.h"
+#endif
/*
* Main static functions
@@ -229,57 +232,46 @@ schema_browser_perspective_dispose (GObject *object)
parent_class->dispose (object);
}
+#ifdef HAVE_GOOCANVAS
static void
-action_create_table_cb (GtkAction *action, BrowserPerspective *bpers)
+action_create_diagram_cb (GtkAction *action, SchemaBrowserPerspective *bpers)
{
- TO_IMPLEMENT;
-}
-
-static void
-action_drop_table_cb (GtkAction *action, BrowserPerspective *bpers)
-{
- TO_IMPLEMENT;
-}
-
-static void
-action_rename_table_cb (GtkAction *action, BrowserPerspective *bpers)
-{
- TO_IMPLEMENT;
-}
-
-static void
-action_add_column_cb (GtkAction *action, BrowserPerspective *bpers)
-{
- TO_IMPLEMENT;
-}
-
-static void
-action_drop_column_cb (GtkAction *action, BrowserPerspective *bpers)
-{
- TO_IMPLEMENT;
-}
-
-static void
-action_table_contents_cb (GtkAction *action, BrowserPerspective *bpers)
-{
- TO_IMPLEMENT;
+ GtkWidget *diagram;
+ diagram = relations_diagram_new (browser_window_get_connection (bpers->priv->bwin));
+ if (diagram) {
+ GtkWidget *close_btn;
+ GdkPixbuf *diagram_pixbuf;
+ gint i;
+
+ diagram_pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_DIAGRAM);
+ i = gtk_notebook_append_page (GTK_NOTEBOOK (bpers->priv->notebook), diagram,
+ browser_make_tab_label_with_pixbuf (_("Diagram"),
+ diagram_pixbuf,
+ TRUE, &close_btn));
+ g_signal_connect (close_btn, "clicked",
+ G_CALLBACK (close_button_clicked_cb), diagram);
+
+ gtk_widget_show (diagram);
+ gtk_notebook_set_menu_label (GTK_NOTEBOOK (bpers->priv->notebook), diagram,
+ browser_make_tab_label_with_pixbuf (_("Diagram"),
+ diagram_pixbuf,
+ FALSE, NULL));
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (bpers->priv->notebook), i);
+ gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (bpers->priv->notebook), diagram,
+ TRUE);
+ gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (bpers->priv->notebook), diagram,
+ TRUE);
+ }
}
+#endif
static GtkActionEntry ui_actions[] = {
+#ifdef HAVE_GOOCANVAS
{ "Schema", NULL, "_Schema", NULL, "Schema", NULL },
- { "CREATE_TABLE", GTK_STOCK_ADD, "_New table", NULL, "Create a new table",
- G_CALLBACK (action_create_table_cb)},
- { "DROP_TABLE", GTK_STOCK_DELETE, "_Delete", NULL, "Delete the selected table",
- G_CALLBACK (action_drop_table_cb)},
- { "RENAME_TABLE", NULL, "_Rename", NULL, "Rename the selected table",
- G_CALLBACK (action_rename_table_cb)},
- { "ADD_COLUMN", NULL, "_Add column", NULL, "Add a column to the selected table",
- G_CALLBACK (action_add_column_cb)},
- { "DROP_COLUMN", NULL, "_Delete column", NULL, "Delete a column from the selected table",
- G_CALLBACK (action_drop_column_cb)},
- { "TableContents", GTK_STOCK_EDIT, "_Contents", NULL, "Display the contents of the selected table",
- G_CALLBACK (action_table_contents_cb)},
+ { "NewDiagram", GTK_STOCK_ADD, "_New Diagram", NULL, "Create a new diagram",
+ G_CALLBACK (action_create_diagram_cb)},
+#endif
};
static const gchar *ui_actions_info =
@@ -287,23 +279,13 @@ static const gchar *ui_actions_info =
" <menubar name='MenuBar'>"
" <placeholder name='MenuExtension'>"
" <menu name='Schema' action='Schema'>"
- " <menuitem name='CREATE_TABLE' action= 'CREATE_TABLE'/>"
- " <menuitem name='DROP_TABLE' action= 'DROP_TABLE'/>"
- " <menuitem name='RENAME_TABLE' action= 'RENAME_TABLE'/>"
- " <separator/>"
- " <menuitem name='ADD_COLUMN' action= 'ADD_COLUMN'/>"
- " <menuitem name='DROP_COLUMN' action= 'DROP_COLUMN'/>"
- " <separator/>"
- " <menuitem name='TableContents' action= 'TableContents'/>"
+ " <menuitem name='NewDiagram' action= 'NewDiagram'/>"
" </menu>"
" </placeholder>"
" </menubar>"
" <toolbar name='ToolBar'>"
" <separator/>"
- " <toolitem action='CREATE_TABLE'/>"
- " <toolitem action='DROP_TABLE'/>"
- " <separator/>"
- " <toolitem action='TableContents'/>"
+ " <toolitem action='NewDiagram'/>"
" </toolbar>"
"</ui>";
@@ -313,13 +295,6 @@ schema_browser_perspective_get_actions_group (BrowserPerspective *bpers)
GtkActionGroup *agroup;
agroup = gtk_action_group_new ("SchemaBrowserActions");
gtk_action_group_add_actions (agroup, ui_actions, G_N_ELEMENTS (ui_actions), bpers);
-
- gtk_action_set_sensitive (gtk_action_group_get_action (agroup, "CREATE_TABLE"), TRUE);
- gtk_action_set_sensitive (gtk_action_group_get_action (agroup, "DROP_TABLE"), FALSE);
- gtk_action_set_sensitive (gtk_action_group_get_action (agroup, "RENAME_TABLE"), FALSE);
- gtk_action_set_sensitive (gtk_action_group_get_action (agroup, "ADD_COLUMN"), FALSE);
- gtk_action_set_sensitive (gtk_action_group_get_action (agroup, "DROP_COLUMN"), FALSE);
- gtk_action_set_sensitive (gtk_action_group_get_action (agroup, "TableContents"), FALSE);
return agroup;
}
@@ -364,7 +339,6 @@ schema_browser_perspective_display_table_info (SchemaBrowserPerspective *bpers,
const gchar *tab_name;
GdkPixbuf *table_pixbuf;
- g_object_set (G_OBJECT (ti), "perspective", bpers, NULL);
table_pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_TABLE);
tab_name = table_short_name ? table_short_name : table_name;
i = gtk_notebook_append_page (GTK_NOTEBOOK (bpers->priv->notebook), ti,
diff --git a/tools/browser/schema-browser/table-columns.c b/tools/browser/schema-browser/table-columns.c
index d557379..8156f72 100644
--- a/tools/browser/schema-browser/table-columns.c
+++ b/tools/browser/schema-browser/table-columns.c
@@ -597,7 +597,9 @@ follow_if_link (GtkWidget *text_view, GtkTextIter *iter, TableColumns *tcolumns)
table_schema = g_object_get_data (G_OBJECT (tag), "table_schema");
table_name = g_object_get_data (G_OBJECT (tag), "table_name");
table_short_name = g_object_get_data (G_OBJECT (tag), "table_short_name");
- g_object_get (tcolumns->priv->tinfo, "perspective", &bpers, NULL);
+
+ bpers = browser_find_parent_widget (GTK_WIDGET (tcolumns),
+ TYPE_SCHEMA_BROWSER_PERSPECTIVE);
if (table_name && table_schema && table_short_name && bpers) {
schema_browser_perspective_display_table_info (bpers,
table_schema,
diff --git a/tools/browser/schema-browser/table-info.c b/tools/browser/schema-browser/table-info.c
index 6fc0610..9de12ba 100644
--- a/tools/browser/schema-browser/table-info.c
+++ b/tools/browser/schema-browser/table-info.c
@@ -35,7 +35,6 @@
struct _TableInfoPrivate {
BrowserConnection *bcnc;
- SchemaBrowserPerspective *bpers; /* perspective into which tinfo will be */
gchar *schema;
gchar *table_name;
@@ -64,7 +63,6 @@ static void meta_changed_cb (BrowserConnection *bcnc, GdaMetaStruct *mstruct, Ta
/* properties */
enum {
PROP_0,
- PROP_PERSPECTIVE
};
enum {
@@ -91,10 +89,6 @@ table_info_class_init (TableInfoClass *klass)
object_class->set_property = table_info_set_property;
object_class->get_property = table_info_get_property;
- g_object_class_install_property (object_class, PROP_PERSPECTIVE,
- g_param_spec_pointer ("perspective", NULL, NULL,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
-
object_class->dispose = table_info_dispose;
}
@@ -159,9 +153,6 @@ table_info_set_property (GObject *object,
TableInfo *tinfo;
tinfo = TABLE_INFO (object);
switch (param_id) {
- case PROP_PERSPECTIVE:
- tinfo->priv->bpers = g_value_get_pointer (value);
- break;
}
}
@@ -174,9 +165,6 @@ table_info_get_property (GObject *object,
TableInfo *tinfo;
tinfo = TABLE_INFO (object);
switch (param_id) {
- case PROP_PERSPECTIVE:
- g_value_set_pointer (value, tinfo->priv->bpers);
- break;
}
}
diff --git a/tools/browser/schema-browser/table-relations.c b/tools/browser/schema-browser/table-relations.c
index 6e0ec6b..414671f 100644
--- a/tools/browser/schema-browser/table-relations.c
+++ b/tools/browser/schema-browser/table-relations.c
@@ -121,6 +121,7 @@ meta_changed_cb (BrowserConnection *bcnc, GdaMetaStruct *mstruct, TableRelations
{
GdaMetaDbObject *dbo;
GValue *tname, *tschema;
+ BrowserCanvasTable *ctable;
g_object_set (G_OBJECT (trels->priv->canvas), "meta-struct", mstruct, NULL);
@@ -128,8 +129,10 @@ meta_changed_cb (BrowserConnection *bcnc, GdaMetaStruct *mstruct, TableRelations
table_info_get_table_schema (trels->priv->tinfo));
g_value_set_string ((tname = gda_value_new (G_TYPE_STRING)),
table_info_get_table_name (trels->priv->tinfo));
- browser_canvas_db_relations_add_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas), NULL,
- tschema, tname);
+ ctable = browser_canvas_db_relations_add_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas), NULL,
+ tschema, tname);
+ browser_canvas_db_relations_select_table (BROWSER_CANVAS_DB_RELATIONS (trels->priv->canvas),
+ ctable);
dbo = gda_meta_struct_get_db_object (mstruct, NULL, tschema, tname);
@@ -195,7 +198,7 @@ table_relations_new (TableInfo *tinfo)
*/
trels->priv->canvas = browser_canvas_db_relations_new (NULL);
gtk_box_pack_start (GTK_BOX (trels), trels->priv->canvas, TRUE, TRUE, 0);
- gtk_widget_show (trels);
+ gtk_widget_show (GTK_WIDGET (trels));
/*
* initial update
diff --git a/tools/browser/support.c b/tools/browser/support.c
index 01e3062..83dff6a 100644
--- a/tools/browser/support.c
+++ b/tools/browser/support.c
@@ -228,7 +228,8 @@ browser_get_pixbuf_icon (BrowserIconType type)
"gda-browser-column-fk.png",
"gda-browser-column-fknn.png",
"gda-browser-column-nn.png",
- "gda-browser-reference.png"
+ "gda-browser-reference.png",
+ "gda-browser-diagram.png"
};
if (!array)
@@ -247,3 +248,21 @@ browser_get_pixbuf_icon (BrowserIconType type)
else
return array [type];
}
+
+/**
+ * browser_find_parent_widget
+ *
+ * Finds the 1st parent widget of @current which is of the @requested_type type.
+ */
+GtkWidget *
+browser_find_parent_widget (GtkWidget *current, GType requested_type)
+{
+ GtkWidget *wid;
+ g_return_val_if_fail (GTK_IS_WIDGET (current), NULL);
+
+ for (wid = gtk_widget_get_parent (current); wid; wid = gtk_widget_get_parent (wid)) {
+ if (G_OBJECT_TYPE (wid) == requested_type)
+ return wid;
+ }
+ return NULL;
+}
diff --git a/tools/browser/support.h b/tools/browser/support.h
index cdc1245..264fd67 100644
--- a/tools/browser/support.h
+++ b/tools/browser/support.h
@@ -40,6 +40,11 @@ GtkWidget* browser_make_tab_label_with_pixbuf (const gchar *label,
GtkWidget **out_close_button);
/*
+ * Widgets navigation
+ */
+GtkWidget *browser_find_parent_widget (GtkWidget *current, GType requested_type);
+
+/*
* icons
*/
typedef enum {
@@ -52,6 +57,7 @@ typedef enum {
BROWSER_ICON_COLUMN_FK_NN,
BROWSER_ICON_COLUMN_NN,
BROWSER_ICON_REFERENCE,
+ BROWSER_ICON_DIAGRAM,
BROWSER_ICON_LAST
} BrowserIconType;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]