]> git.0d.be Git - empathy.git/commitdiff
Add a webview widget for displaying the log
authorDanielle Madeley <danielle.madeley@collabora.co.uk>
Fri, 29 Jul 2011 04:23:21 +0000 (14:23 +1000)
committerDanielle Madeley <danielle.madeley@collabora.co.uk>
Fri, 29 Jul 2011 04:23:21 +0000 (14:23 +1000)
The widget is currently bolted in alongside the existing log display widget
for comparison. This includes some debugging cruft like showing the secret
notebook tabs.

The webview is populated from the store_events treestore, allowing all of the
existing node-management and ordering code to be used. Attempting to replace
this logic in Javascript was demonstratably too hard. This approach keeps the
Javascript code down to the 4 GtkTreeModel signals.

TODO:
 - icons
 - pretty printed dates
 - expanders
 - supporting smileys, links, etc.
 - using the correct font, etc.
 - removing the debugging

data/Makefile.am
data/empathy-log-window.html [new file with mode: 0644]
libempathy-gtk/empathy-log-window.c

index 88de4f09b35d7af6b1131d7c86be42880c4a0826..d652ca9e5f357c837c4bbbc3615fd44e4fc03471 100644 (file)
@@ -58,7 +58,10 @@ clientfile_DATA = \
        Empathy.FileTransfer.client
 
 htmldir = $(datadir)/empathy
-html_DATA = Template.html
+html_DATA = \
+       Template.html \
+       empathy-log-window.html \
+       $(NULL)
 
 EXTRA_DIST =                           \
        $(convert_DATA)                 \
diff --git a/data/empathy-log-window.html b/data/empathy-log-window.html
new file mode 100644 (file)
index 0000000..ef01df3
--- /dev/null
@@ -0,0 +1,126 @@
+<html>
+  <head>
+    <style type="text/css">
+html, body, div, p {
+  /* FIXME: how do we set the application font? */
+  padding: 0;
+  margin: 0;
+}
+
+div.row {
+  margin-left: 1em;
+}
+    </style>
+    <script type="text/javascript">
+function filterNodes (node, tagName)
+{
+  var out = new Array();
+
+  for (var i = 0; i < node.childNodes.length; i++)
+    {
+      var elem = node.childNodes[i];
+
+      if (elem.tagName == tagName)
+        out.push(elem);
+    }
+
+  return out;
+}
+
+function getNodes(node)
+{
+  return filterNodes(node, 'DIV');
+}
+
+function getContent(node)
+{
+  return filterNodes(node, 'P')[0];
+}
+
+function insertRow (path, text)
+{
+  var treeview = document.getElementById('treeview');
+  var parentnode = treeview;
+  var i;
+
+  // walk the tree
+  for (i = 0; i < path.length - 1; i++)
+    parentnode = getNodes(parentnode)[path[i]];
+
+  // create a new node
+  var newnode = document.createElement('div');
+  newnode.setAttribute('class', 'row');
+
+  // insert the new node into the tree
+  var nodes = getNodes(parentnode);
+
+  // console.log("path = " + path);
+  // console.log("i = " + i + ", path[i] = " + path[i] + ", nodes.length = " +
+  //    nodes.length);
+
+  if (path[i] >= nodes.length)
+    parentnode.appendChild(newnode);
+  else
+    parentnode.insertBefore(newnode, nodes[path[i]]);
+  
+  var contents = document.createElement('p');
+  newnode.appendChild(contents);
+  contents.innerHTML = text;
+}
+
+function changeRow (path, text)
+{
+  var treeview = document.getElementById('treeview');
+  var node = treeview;
+
+  // console.log("path = " + path + ", text = '" + text + "'");
+
+  // walk the tree
+  for (var i = 0; i < path.length; i++)
+    node = getNodes(node)[path[i]];
+
+  // set the contents
+  var contents = getContent(node);
+  contents.innerHTML = text;
+}
+
+function deleteRow (path)
+{
+  var treeview = document.getElementById('treeview');
+  var node = treeview;
+
+  // walk the tree
+  for (var i = 0; i < path.length; i++)
+    node = getNodes(node)[path[i]];
+
+  node.parentNode.removeChild(node);
+}
+
+function reorderRows (path, new_order)
+{
+  var treeview = document.getElementById('treeview');
+  var node = treeview;
+
+  // walk the tree
+  for (var i = 0; i < path.length; i++)
+    node = getNodes(node)[path[i]];
+
+  var nodes = getNodes(node);
+
+  // remove all the nodes from the DOM
+  for (var i = 0; i < nodes.length; i++)
+    node.removeChild(nodes[i]);
+
+  // put them back in the new order
+  // For reference: new_order[new_pos] = old_pos
+  for (var i = 0; i < nodes.length; i++)
+    node.appendChild(nodes[new_order[i]]);
+}
+    </script>
+  </head>
+
+  <body>
+    <div id="treeview">
+    </div>
+  </body>
+</html>
index e5c93501142385f23b4ca4598dc7e08c12159024..04f224290f1ea82178c0b88e7579330450ebe98d 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
+#include <webkit/webkit.h>
 
 #include <telepathy-glib/telepathy-glib.h>
 #include <telepathy-glib/proxy-subclass.h>
@@ -83,6 +84,7 @@ struct _EmpathyLogWindowPriv
   GtkWidget *treeview_what;
   GtkWidget *treeview_when;
   GtkWidget *treeview_events;
+  GtkWidget *webview;
 
   GtkTreeStore *store_events;
 
@@ -360,6 +362,103 @@ toolbutton_av_clicked (GtkToolButton *toolbutton,
       TRUE, video, gtk_get_current_event_time ());
 }
 
+static void
+insert_or_change_row (EmpathyLogWindow *self,
+    const char *method,
+    GtkTreeModel *model,
+    GtkTreePath *path,
+    GtkTreeIter *iter)
+{
+  char *str = gtk_tree_path_to_string (path);
+  char *script, *text;
+
+  gtk_tree_model_get (model, iter,
+      COL_EVENTS_TEXT, &text,
+      -1);
+
+  script = g_strdup_printf ("javascript:%s([%s], '%s');",
+      method,
+      g_strdelimit (str, ":", ','),
+      text);
+
+  // g_print ("%s\n", script);
+  webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview),
+      script);
+
+  g_free (str);
+  g_free (text);
+  g_free (script);
+}
+
+static void
+store_events_row_inserted (GtkTreeModel *model,
+    GtkTreePath *path,
+    GtkTreeIter *iter,
+    EmpathyLogWindow *self)
+{
+  insert_or_change_row (self, "insertRow", model, path, iter);
+}
+
+static void
+store_events_row_changed (GtkTreeModel *model,
+    GtkTreePath *path,
+    GtkTreeIter *iter,
+    EmpathyLogWindow *self)
+{
+  insert_or_change_row (self, "changeRow", model, path, iter);
+}
+
+static void
+store_events_row_deleted (GtkTreeModel *model,
+    GtkTreePath *path,
+    EmpathyLogWindow *self)
+{
+  char *str = gtk_tree_path_to_string (path);
+  char *script;
+
+  script = g_strdup_printf ("javascript:deleteRow([%s]);",
+      g_strdelimit (str, ":", ','));
+
+  // g_print ("%s\n", script);
+  webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview),
+      script);
+
+  g_free (str);
+  g_free (script);
+}
+
+static void
+store_events_rows_reordered (GtkTreeModel *model,
+    GtkTreePath *path,
+    GtkTreeIter *iter,
+    int *new_order,
+    EmpathyLogWindow *self)
+{
+  char *str = gtk_tree_path_to_string (path);
+  int i, children = gtk_tree_model_iter_n_children (model, iter);
+  char **new_order_strv, *new_order_s;
+  char *script;
+
+  new_order_strv = g_new0 (char *, children + 1);
+
+  for (i = 0; i < children; i++)
+    new_order_strv[i] = g_strdup_printf ("%i", new_order[i]);
+
+  new_order_s = g_strjoinv (",", new_order_strv);
+
+  script = g_strdup_printf ("javascript:reorderRows([%s], [%s]);",
+      str == NULL ? "" : g_strdelimit (str, ":", ','),
+      new_order_s);
+
+  webkit_web_view_execute_script (WEBKIT_WEB_VIEW (self->priv->webview),
+      script);
+
+  g_free (str);
+  g_free (script);
+  g_free (new_order_s);
+  g_strfreev (new_order_strv);
+}
+
 static GObject *
 empathy_log_window_constructor (GType type,
     guint n_props,
@@ -444,7 +543,9 @@ empathy_log_window_init (EmpathyLogWindow *self)
   EmpathyAccountChooser *account_chooser;
   GtkBuilder *gui;
   gchar *filename;
+  GFile *gfile;
   GtkWidget *vbox, *accounts, *search, *label, *quit;
+  GtkWidget *sw;
 
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       EMPATHY_TYPE_LOG_WINDOW, EmpathyLogWindowPriv);
@@ -564,6 +665,38 @@ empathy_log_window_init (EmpathyLogWindow *self)
 
   log_window_who_populate (self);
 
+  /* events */
+  sw = gtk_scrolled_window_new (NULL, NULL);
+  self->priv->webview = webkit_web_view_new ();
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+      GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_container_add (GTK_CONTAINER (sw), self->priv->webview);
+
+  filename = empathy_file_lookup ("empathy-log-window.html", "data");
+  gfile = g_file_new_for_path (filename);
+  g_free (filename);
+
+  webkit_web_view_load_uri (WEBKIT_WEB_VIEW (self->priv->webview),
+      g_file_get_uri (gfile));
+  g_object_unref (gfile);
+
+  gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
+      sw, gtk_label_new ("webview"));
+  gtk_widget_show_all (sw);
+
+  /* listen to changes to the treemodel */
+  g_signal_connect (self->priv->store_events, "row-inserted",
+      G_CALLBACK (store_events_row_inserted), self);
+  g_signal_connect (self->priv->store_events, "row-changed",
+      G_CALLBACK (store_events_row_changed), self);
+  g_signal_connect (self->priv->store_events, "row-deleted",
+      G_CALLBACK (store_events_row_deleted), self);
+  g_signal_connect (self->priv->store_events, "rows-reordered",
+      G_CALLBACK (store_events_rows_reordered), self);
+
+  // debug
+  gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self->priv->notebook), TRUE);
+
   gtk_widget_show (GTK_WIDGET (self));
 }