[libgda] GdaBrowser: improved history browsing
- From: Vivien Malerba <vivien src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [libgda] GdaBrowser: improved history browsing
- Date: Sun, 13 Sep 2009 13:25:10 +0000 (UTC)
commit 6acd5442fd2bb91b0f474ae853f71f7fcb1c57b1
Author: Vivien Malerba <malerba gnome-db org>
Date: Wed Sep 9 21:17:44 2009 +0200
GdaBrowser: improved history browsing
tools/browser/query-exec/query-console.c | 2 +-
tools/browser/query-exec/query-editor.c | 169 ++++++++++++++++++++++++------
tools/browser/query-exec/query-editor.h | 7 +-
tools/browser/query-exec/query-result.c | 144 ++++++++++++++++++++------
tools/browser/query-exec/query-result.h | 2 +-
5 files changed, 257 insertions(+), 67 deletions(-)
---
diff --git a/tools/browser/query-exec/query-console.c b/tools/browser/query-exec/query-console.c
index c435415..3aa3c3c 100644
--- a/tools/browser/query-exec/query-console.c
+++ b/tools/browser/query-exec/query-console.c
@@ -433,7 +433,7 @@ query_console_new (BrowserConnection *bcnc)
gtk_misc_set_alignment (GTK_MISC (wid), 0., -1);
gtk_box_pack_start (GTK_BOX (vbox), wid, FALSE, FALSE, 0);
- wid = query_result_new ();
+ wid = query_result_new (tconsole->priv->history);
tconsole->priv->query_result = wid;
gtk_box_pack_start (GTK_BOX (vbox), wid, TRUE, TRUE, 6);
diff --git a/tools/browser/query-exec/query-editor.c b/tools/browser/query-exec/query-editor.c
index 3b7bf00..08695e7 100644
--- a/tools/browser/query-exec/query-editor.c
+++ b/tools/browser/query-exec/query-editor.c
@@ -39,6 +39,11 @@
#define COLOR_ALTER_FACTOR 1.8
#define MAX_HISTORY_BATCH_ITEMS 20
+static void query_editor_history_batch_add_item (QueryEditorHistoryBatch *qib,
+ QueryEditorHistoryItem *qih);
+static void query_editor_history_batch_del_item (QueryEditorHistoryBatch *qib,
+ QueryEditorHistoryItem *qih);
+
typedef void (* CreateTagsFunc) (QueryEditor *editor, const gchar *language);
typedef struct {
@@ -59,6 +64,8 @@ struct _QueryEditorPrivate {
GtkWidget *scrolled_window;
GtkWidget *text;
+ GtkTextTag *indent_tag;
+
/* HISTORY mode */
guint ts_timeout_id;
GSList *batches_list; /* list of QueryEditorHistoryBatch, in reverse order, refs held here */
@@ -93,10 +100,11 @@ static gboolean timestamps_update_cb (QueryEditor *editor);
enum
{
CHANGED,
+ HISTORY_ITEM_REMOVED,
LAST_SIGNAL
};
-static gint query_editor_signals[LAST_SIGNAL] = { 0 };
+static gint query_editor_signals[LAST_SIGNAL] = { 0, 0 };
/*
@@ -175,6 +183,14 @@ query_editor_class_init (QueryEditorClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ query_editor_signals[HISTORY_ITEM_REMOVED] =
+ g_signal_new ("history-item-removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (QueryEditorClass, history_item_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+
object_class->finalize = query_editor_finalize;
GTK_WIDGET_CLASS (object_class)->map = query_editor_map;
}
@@ -379,6 +395,24 @@ query_editor_init (QueryEditor *editor, QueryEditorClass *klass)
g_signal_connect (editor->priv->text, "expose-event",
G_CALLBACK (text_view_expose_event), editor);
+ /* create some tags */
+ GtkTextBuffer *buffer;
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+ gtk_text_buffer_create_tag (buffer, "h0",
+ "foreground", "#474A8F",
+ "weight", PANGO_WEIGHT_BOLD,
+ "variant", PANGO_VARIANT_SMALL_CAPS,
+ "scale", PANGO_SCALE_LARGE,
+ "underline", PANGO_UNDERLINE_SINGLE,
+ NULL);
+
+ gtk_text_buffer_create_tag (buffer, "note",
+ "left-margin", 50,
+ "foreground", "black",
+ "weight", PANGO_WEIGHT_NORMAL,
+ "style", PANGO_STYLE_ITALIC,
+ NULL);
+
/* initialize common data */
number_of_objects++;
if (!supported_languages) {
@@ -390,7 +424,7 @@ query_editor_init (QueryEditor *editor, QueryEditorClass *klass)
create_tags_for_sql (editor, QUERY_EDITOR_LANGUAGE_SQL);
- gtk_widget_show (editor->priv->text);
+ gtk_widget_show_all (editor->priv->scrolled_window);
/* timeout function to update timestamps */
editor->priv->ts_timeout_id = 0;
@@ -586,9 +620,8 @@ query_editor_set_mode (QueryEditor *editor, QueryEditorMode mode)
* query_editor_set_text
* @editor: a #QueryEditor widget.
* @text: text to display in the editor.
- * @len: length of @text, or -1.
*
- * Set the contents of the given editor widget.
+ * Set @editor's text, removing any previous one
*/
void
query_editor_set_text (QueryEditor *editor, const gchar *text)
@@ -610,6 +643,79 @@ query_editor_set_text (QueryEditor *editor, const gchar *text)
}
}
+/**
+ * query_editor_append_text
+ * @editor: a #QueryEditor widget.
+ * @text: text to display in the editor.
+ *
+ * Appends some text to @editor.
+ */
+void
+query_editor_append_text (QueryEditor *editor, const gchar *text)
+{
+ GtkTextBuffer *buffer;
+
+ g_return_if_fail (QUERY_IS_EDITOR (editor));
+ g_return_if_fail (editor->priv->mode != QUERY_EDITOR_HISTORY);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+
+ if (text) {
+ GtkTextIter end;
+ gint len;
+ len = strlen (text);
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_buffer_insert (buffer, &end, text, -1);
+
+ if ((len >= 1) && (text [len - 1] != '\n'))
+ gtk_text_buffer_insert (buffer, &end, "\n", 1);
+ }
+}
+
+/**
+ * query_editor_append_note
+ * @editor: a #QueryEditor widget.
+ * @text: text to display in the editor.
+ * @level: 0 for header, 1 for text with marging and in italics
+ *
+ * Appends some text to @editor.
+ */
+void
+query_editor_append_note (QueryEditor *editor, const gchar *text, gint level)
+{
+ GtkTextBuffer *buffer;
+
+ g_return_if_fail (QUERY_IS_EDITOR (editor));
+ g_return_if_fail (editor->priv->mode != QUERY_EDITOR_HISTORY);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+ if (text) {
+ GtkTextIter end;
+ gchar *str;
+
+ switch (level) {
+ case 0:
+ str = g_strdup_printf ("%s\n", text);
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_buffer_insert_with_tags_by_name (buffer, &end,
+ str, -1,
+ "h0", NULL);
+ g_free (str);
+ break;
+ case 1:
+ str = g_strdup_printf ("%s\n", text);
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_buffer_insert_with_tags_by_name (buffer, &end,
+ str, -1,
+ "note", NULL);
+ g_free (str);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+}
+
static void
focus_on_hist_data (QueryEditor *editor, HistItemData *hdata)
{
@@ -693,7 +799,7 @@ get_date_format (time_t time)
}
/* Turn it into days */
tmp = diff / 86400;
- snprintf (timebuf, sizeof(timebuf), ngettext ("%lu days ago\n",
+ snprintf (timebuf, sizeof(timebuf), ngettext ("%lu day ago\n",
"%lu days ago\n", tmp), tmp);
return timebuf;
@@ -968,29 +1074,32 @@ query_editor_del_current_history_item (QueryEditor *editor)
g_hash_table_remove (editor->priv->hash, hdata->item);
g_hash_table_remove (editor->priv->hash, hdata->tag);
- if (hdata->batch) {
- query_editor_history_batch_del_item (hdata->batch, hdata->item);
- if (! hdata->batch->hist_items) {
- /* remove hdata->batch */
- HistItemData *remhdata;
-
- editor->priv->batches_list = g_slist_remove (editor->priv->batches_list, hdata->batch);
- query_editor_history_batch_unref (hdata->batch);
-
- remhdata = g_hash_table_lookup (editor->priv->hash, hdata->batch);
- gtk_text_buffer_get_iter_at_mark (buffer, &start, remhdata->start_mark);
- gtk_text_buffer_get_iter_at_mark (buffer, &end, remhdata->end_mark);
- gtk_text_buffer_delete (buffer, &start, &end);
- gtk_text_buffer_delete_mark (buffer, remhdata->start_mark);
- gtk_text_buffer_delete_mark (buffer, remhdata->end_mark);
-
- g_hash_table_remove (editor->priv->hash, remhdata->batch);
- g_hash_table_remove (editor->priv->hash, remhdata->tag);
-
- if (editor->priv->insert_into_batch == hdata->batch) {
- query_editor_history_batch_unref (editor->priv->insert_into_batch);
- editor->priv->insert_into_batch = NULL;
- }
+ g_assert (hdata->batch);
+ query_editor_history_item_ref (hdata->item);
+ query_editor_history_batch_del_item (hdata->batch, hdata->item);
+ g_signal_emit (editor, query_editor_signals[HISTORY_ITEM_REMOVED], 0, hdata->item);
+ query_editor_history_item_unref (hdata->item);
+
+ if (! hdata->batch->hist_items) {
+ /* remove hdata->batch */
+ HistItemData *remhdata;
+
+ editor->priv->batches_list = g_slist_remove (editor->priv->batches_list, hdata->batch);
+ query_editor_history_batch_unref (hdata->batch);
+
+ remhdata = g_hash_table_lookup (editor->priv->hash, hdata->batch);
+ gtk_text_buffer_get_iter_at_mark (buffer, &start, remhdata->start_mark);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end, remhdata->end_mark);
+ gtk_text_buffer_delete (buffer, &start, &end);
+ gtk_text_buffer_delete_mark (buffer, remhdata->start_mark);
+ gtk_text_buffer_delete_mark (buffer, remhdata->end_mark);
+
+ g_hash_table_remove (editor->priv->hash, remhdata->batch);
+ g_hash_table_remove (editor->priv->hash, remhdata->tag);
+
+ if (editor->priv->insert_into_batch == hdata->batch) {
+ query_editor_history_batch_unref (editor->priv->insert_into_batch);
+ editor->priv->insert_into_batch = NULL;
}
}
hist_item_data_unref (hdata);
@@ -1299,7 +1408,7 @@ query_editor_history_batch_unref (QueryEditorHistoryBatch *qib)
}
}
-void
+static void
query_editor_history_batch_add_item (QueryEditorHistoryBatch *qib, QueryEditorHistoryItem *qih)
{
g_return_if_fail (qib);
@@ -1307,7 +1416,7 @@ query_editor_history_batch_add_item (QueryEditorHistoryBatch *qib, QueryEditorHi
qib->hist_items = g_slist_append (qib->hist_items, query_editor_history_item_ref (qih));
}
-void
+static void
query_editor_history_batch_del_item (QueryEditorHistoryBatch *qib, QueryEditorHistoryItem *qih)
{
g_return_if_fail (qib);
diff --git a/tools/browser/query-exec/query-editor.h b/tools/browser/query-exec/query-editor.h
index bf42bad..c5bdb39 100644
--- a/tools/browser/query-exec/query-editor.h
+++ b/tools/browser/query-exec/query-editor.h
@@ -68,10 +68,6 @@ typedef struct {
QueryEditorHistoryBatch *query_editor_history_batch_new (GTimeVal run_time, GdaSet *params);
QueryEditorHistoryBatch *query_editor_history_batch_ref (QueryEditorHistoryBatch *qib);
void query_editor_history_batch_unref (QueryEditorHistoryBatch *qib);
-void query_editor_history_batch_add_item (QueryEditorHistoryBatch *qib,
- QueryEditorHistoryItem *qih);
-void query_editor_history_batch_del_item (QueryEditorHistoryBatch *qib,
- QueryEditorHistoryItem *qih);
struct _QueryEditor {
@@ -84,6 +80,7 @@ struct _QueryEditorClass {
/* signals */
void (* changed) (QueryEditor *editor);
+ void (* history_item_removed) (QueryEditor *editor, QueryEditorHistoryItem *item);
};
/*
@@ -113,6 +110,8 @@ void query_editor_paste_clipboard (QueryEditor *editor);
/* normal editor's API */
void query_editor_set_text (QueryEditor *editor, const gchar *text);
+void query_editor_append_text (QueryEditor *editor, const gchar *text);
+void query_editor_append_note (QueryEditor *editor, const gchar *text, gint level);
/* history API */
void query_editor_start_history_batch (QueryEditor *editor, QueryEditorHistoryBatch *hist_batch);
diff --git a/tools/browser/query-exec/query-result.c b/tools/browser/query-exec/query-result.c
index 546f9e4..491b579 100644
--- a/tools/browser/query-exec/query-result.c
+++ b/tools/browser/query-exec/query-result.c
@@ -26,9 +26,11 @@
#include <libgda-ui/libgda-ui.h>
struct _QueryResultPrivate {
+ QueryEditor *history;
QueryEditorHistoryBatch *hbatch;
QueryEditorHistoryItem *hitem;
+ GHashTable *hash; /* key = a QueryEditorHistoryItem, value = a #GtkWidget, refed here all the times */
GtkWidget *child;
};
@@ -64,8 +66,10 @@ query_result_init (QueryResult *result, QueryResultClass *klass)
/* allocate private structure */
result->priv = g_new0 (QueryResultPrivate, 1);
+ result->priv->history = NULL;
result->priv->hbatch = NULL;
result->priv->hitem = NULL;
+ result->priv->hash = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
wid = make_widget_for_notice ();
gtk_box_pack_start (GTK_BOX (result), wid, TRUE, TRUE, 0);
@@ -74,6 +78,13 @@ query_result_init (QueryResult *result, QueryResultClass *klass)
}
static void
+history_item_removed_cb (QueryEditor *history, QueryEditorHistoryItem *item, QueryResult *result)
+{
+ g_hash_table_remove (result->priv->hash, item);
+ g_print ("Removed GtkWidget for item %p\n", item);
+}
+
+static void
query_result_finalize (GObject *object)
{
QueryResult *result = (QueryResult *) object;
@@ -81,6 +92,13 @@ query_result_finalize (GObject *object)
g_return_if_fail (IS_QUERY_RESULT (result));
/* free memory */
+ if (result->priv->hash)
+ g_hash_table_destroy (result->priv->hash);
+ if (result->priv->history) {
+ g_signal_handlers_disconnect_by_func (result->priv->history,
+ G_CALLBACK (history_item_removed_cb), result);
+ g_object_unref (result->priv->history);
+ }
if (result->priv->hbatch)
query_editor_history_batch_unref (result->priv->hbatch);
if (result->priv->hitem)
@@ -116,17 +134,23 @@ query_result_get_type (void)
/**
* query_result_new
+ * @history: a #QueryEditor to take history from
*
* Create a new #QueryResult widget
*
* Returns: the newly created widget.
*/
GtkWidget *
-query_result_new (void)
+query_result_new (QueryEditor *history)
{
QueryResult *result;
+ g_return_val_if_fail (QUERY_IS_EDITOR (history), NULL);
result = g_object_new (QUERY_TYPE_RESULT, NULL);
+ g_signal_connect (history, "history-item-removed",
+ G_CALLBACK (history_item_removed_cb), result);
+ result->priv->history = g_object_ref (history);
+
return GTK_WIDGET (result);
}
@@ -141,14 +165,14 @@ query_result_new (void)
void
query_result_show_history_batch (QueryResult *qres, QueryEditorHistoryBatch *hbatch)
{
- GtkWidget *sw, *vbox;
GSList *list;
- GtkWidget *child;
-
+ GtkWidget *child;
+ GtkWidget *vbox;
+ gchar *str;
g_return_if_fail (IS_QUERY_RESULT (qres));
if (qres->priv->child)
- gtk_widget_destroy (qres->priv->child);
+ gtk_container_remove (GTK_CONTAINER (qres), qres->priv->child);
if (!hbatch) {
child = make_widget_for_notice ();
@@ -159,32 +183,83 @@ query_result_show_history_batch (QueryResult *qres, QueryEditorHistoryBatch *hba
}
vbox = gtk_vbox_new (FALSE, 0);
+
+ child = query_editor_new ();
+ query_editor_set_mode (QUERY_EDITOR (child), QUERY_EDITOR_READONLY);
+ gtk_box_pack_start (GTK_BOX (vbox), child, TRUE, TRUE, 0);
for (list = hbatch->hist_items; list; list = list->next) {
QueryEditorHistoryItem *hitem;
-
- hitem = (QueryEditorHistoryItem*) list->data;
+ GString *string;
+ hitem = (QueryEditorHistoryItem *) list->data;
+ if (list != hbatch->hist_items)
+ query_editor_append_text (QUERY_EDITOR (child), "\n");
+ query_editor_append_note (QUERY_EDITOR (child), _("Statement:"), 0);
+ query_editor_append_text (QUERY_EDITOR (child), hitem->sql);
+
+ string = g_string_new ("");
if (hitem->result) {
- if (GDA_IS_DATA_MODEL (hitem->result))
- child = make_widget_for_data_model (GDA_DATA_MODEL (hitem->result));
- else if (GDA_IS_SET (hitem->result))
- child = make_widget_for_set (GDA_SET (hitem->result));
+ if (GDA_IS_DATA_MODEL (hitem->result)) {
+ gint n, c;
+ n = gda_data_model_get_n_rows (GDA_DATA_MODEL (hitem->result));
+ c = gda_data_model_get_n_columns (GDA_DATA_MODEL (hitem->result));
+ g_string_append_printf (string,
+ _("Data set with %d rows and %d columns"),
+ n, c);
+ }
+ else if (GDA_IS_SET (hitem->result)) {
+ GdaSet *set;
+ GSList *list;
+ set = GDA_SET (hitem->result);
+ for (list = set->holders; list; list = list->next) {
+ GdaHolder *h;
+ const GValue *value;
+ const gchar *cstr;
+ gchar *tmp;
+ h = GDA_HOLDER (list->data);
+
+ if (list != set->holders)
+ g_string_append_c (string, '\n');
+
+ cstr = gda_holder_get_id (h);
+ if (!strcmp (cstr, "IMPACTED_ROWS"))
+ g_string_append (string, _("Number of rows impacted"));
+ else
+ g_string_append (string, cstr);
+
+ g_string_append (string, ": ");
+ value = gda_holder_get_value (h);
+ tmp = gda_value_stringify (value);
+ g_string_append_printf (string, "%s", tmp);
+ g_free (tmp);
+ }
+ }
else
g_assert_not_reached ();
}
else
- child = make_widget_for_error (hitem->exec_error);
- gtk_box_pack_start (GTK_BOX (vbox), child, TRUE, TRUE, 10);
+ g_string_append_printf (string, _("Error: %s"),
+ hitem->exec_error && hitem->exec_error->message ?
+ hitem->exec_error->message : _("No detail"));
+ query_editor_append_note (QUERY_EDITOR (child), string->str, 1);
+ g_string_free (string, TRUE);
}
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), vbox);
+ if (hbatch->params) {
+ GtkWidget *exp, *form;
+ str = g_strdup_printf ("<b>%s:</b>", _("Execution Parameters"));
+ exp = gtk_expander_new (str);
+ g_free (str);
+ gtk_expander_set_use_markup (GTK_EXPANDER (exp), TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox), exp, FALSE, FALSE, 0);
+
+ form = gdaui_basic_form_new (hbatch->params);
+ gdaui_basic_form_entry_set_editable (GDAUI_BASIC_FORM (form), NULL, FALSE);
+ gtk_container_add (GTK_CONTAINER (exp), form);
+ }
- gtk_box_pack_start (GTK_BOX (qres), sw, TRUE, TRUE, 0);
- gtk_widget_show_all (sw);
- qres->priv->child = sw;
+ gtk_box_pack_start (GTK_BOX (qres), vbox, TRUE, TRUE, 0);
+ gtk_widget_show_all (vbox);
+ qres->priv->child = vbox;
}
/**
@@ -201,20 +276,27 @@ query_result_show_history_item (QueryResult *qres, QueryEditorHistoryItem *hitem
g_return_if_fail (IS_QUERY_RESULT (qres));
if (qres->priv->child)
- gtk_widget_destroy (qres->priv->child);
+ gtk_container_remove (GTK_CONTAINER (qres), qres->priv->child);
if (!hitem)
child = make_widget_for_notice ();
- else if (hitem->result) {
- if (GDA_IS_DATA_MODEL (hitem->result))
- child = make_widget_for_data_model (GDA_DATA_MODEL (hitem->result));
- else if (GDA_IS_SET (hitem->result))
- child = make_widget_for_set (GDA_SET (hitem->result));
- else
- g_assert_not_reached ();
+ else {
+ child = g_hash_table_lookup (qres->priv->hash, hitem);
+ if (!child) {
+ if (hitem->result) {
+ if (GDA_IS_DATA_MODEL (hitem->result))
+ child = make_widget_for_data_model (GDA_DATA_MODEL (hitem->result));
+ else if (GDA_IS_SET (hitem->result))
+ child = make_widget_for_set (GDA_SET (hitem->result));
+ else
+ g_assert_not_reached ();
+ }
+ else
+ child = make_widget_for_error (hitem->exec_error);
+ g_print ("Inserted GtkWidget %p for item %p\n", child, hitem);
+ g_hash_table_insert (qres->priv->hash, hitem, g_object_ref (G_OBJECT (child)));
+ }
}
- else
- child = make_widget_for_error (hitem->exec_error);
gtk_box_pack_start (GTK_BOX (qres), child, TRUE, TRUE, 0);
gtk_widget_show (child);
diff --git a/tools/browser/query-exec/query-result.h b/tools/browser/query-exec/query-result.h
index 581062f..e000526 100644
--- a/tools/browser/query-exec/query-result.h
+++ b/tools/browser/query-exec/query-result.h
@@ -50,7 +50,7 @@ struct _QueryResultClass {
GType query_result_get_type (void) G_GNUC_CONST;
-GtkWidget *query_result_new (void);
+GtkWidget *query_result_new (QueryEditor *history);
void query_result_show_history_batch (QueryResult *qres, QueryEditorHistoryBatch *hbatch);
void query_result_show_history_item (QueryResult *qres, QueryEditorHistoryItem *hitem);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]