[gnome-builder/wip/chergert/hover] devhelp: implement devhelp hover provider content



commit 0f6281a25d0057341459ed2b5af116ee2d875aa5
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jul 16 13:29:21 2018 -0700

    devhelp: implement devhelp hover provider content
    
    This uses DhAssistantView to show some documentation on a particular
    item in the sourceview.

 src/plugins/devhelp/gbp-devhelp-hover-provider.c | 149 ++++++++++++++++++++++-
 1 file changed, 145 insertions(+), 4 deletions(-)
---
diff --git a/src/plugins/devhelp/gbp-devhelp-hover-provider.c 
b/src/plugins/devhelp/gbp-devhelp-hover-provider.c
index 9530ab086..c714b5f0f 100644
--- a/src/plugins/devhelp/gbp-devhelp-hover-provider.c
+++ b/src/plugins/devhelp/gbp-devhelp-hover-provider.c
@@ -20,13 +20,138 @@
 
 #define G_LOG_DOMAIN "gbp-devhelp-hover-provider"
 
+#include <devhelp/devhelp.h>
+#include <glib/gi18n.h>
+
+#include "sourceview/ide-text-iter.h"
 #include "gbp-devhelp-hover-provider.h"
 
+#define DEVHELP_HOVER_PROVIDER_PRIORITY 200
+
 struct _GbpDevhelpHoverProvider
 {
   GObject parent_instance;
 };
 
+typedef struct
+{
+  IdeHoverContext *context;
+  IdeSymbol       *symbol;
+  gchar           *word;
+} Hover;
+
+static void
+hover_free (Hover *h)
+{
+  g_clear_object (&h->context);
+  g_clear_pointer (&h->word, g_free);
+  g_clear_pointer (&h->symbol, ide_symbol_unref);
+  g_slice_free (Hover, h);
+}
+
+static DhKeywordModel *
+get_keyword_model (void)
+{
+  static DhKeywordModel *model;
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+
+  if (model == NULL)
+    model = dh_keyword_model_new ();
+
+  return model;
+}
+
+static void
+find_and_apply_content (Hover *h)
+{
+  const gchar *names[2] = { NULL };
+  DhKeywordModel *model;
+
+  g_assert (h != NULL);
+  g_assert (IDE_IS_HOVER_CONTEXT (h->context));
+
+  /* TODO: Add ide_symbol_get_type_name() so that we can resolve the
+   *       type and not just the field name.
+   */
+  if (h->symbol != NULL)
+    names[0] = ide_symbol_get_name (h->symbol);
+  names[1] = h->word;
+
+  model = get_keyword_model ();
+
+  for (guint i = 0; i < G_N_ELEMENTS (names); i++)
+    {
+      DhLink *item;
+
+      if (dzl_str_empty0 (names[i]))
+        continue;
+
+      if ((item = dh_keyword_model_filter (model, names[i], NULL, NULL)))
+        {
+          g_autoptr(IdeMarkedContent) content = NULL;
+          GtkWidget *view;
+
+          view = dh_assistant_view_new ();
+
+          if (!dh_assistant_view_set_link (DH_ASSISTANT_VIEW (view), item))
+            {
+              gtk_widget_destroy (view);
+              break;
+            }
+
+          /* It would be nice if we could coordinate with WebKitWebView
+           * about a proper natural size request.
+           */
+          g_object_set (view,
+                        "halign", GTK_ALIGN_FILL,
+                        "height-request", 200,
+                        "hexpand", FALSE,
+                        "valign", GTK_ALIGN_FILL,
+                        "vexpand", FALSE,
+                        "width-request", 400,
+                        NULL);
+
+          ide_hover_context_add_widget (h->context,
+                                        DEVHELP_HOVER_PROVIDER_PRIORITY,
+                                        _("Devhelp"),
+                                        g_steal_pointer (&view));
+
+          break;
+        }
+    }
+}
+
+static void
+gbp_devhelp_hover_provider_get_symbol_cb (GObject      *object,
+                                          GAsyncResult *result,
+                                          gpointer      user_data)
+{
+  IdeBuffer *buffer = (IdeBuffer *)object;
+  g_autoptr(IdeTask) task = user_data;
+  g_autoptr(IdeSymbol) symbol = NULL;
+  Hover *h;
+
+  g_assert (IDE_IS_BUFFER (buffer));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_TASK (task));
+
+  h = ide_task_get_task_data (task);
+  g_assert (h != NULL);
+  g_assert (h->context != NULL);
+  g_assert (h->symbol == NULL);
+
+  if ((symbol = ide_buffer_get_symbol_at_location_finish (buffer, result, NULL)))
+    h->symbol = g_steal_pointer (&symbol);
+
+  if (ide_task_return_error_if_cancelled (task))
+    return;
+
+  find_and_apply_content (h);
+
+  ide_task_return_boolean (task, TRUE);
+}
+
 static void
 gbp_devhelp_hover_provider_hover_async (IdeHoverProvider    *provider,
                                         IdeHoverContext     *context,
@@ -36,8 +161,9 @@ gbp_devhelp_hover_provider_hover_async (IdeHoverProvider    *provider,
                                         gpointer             user_data)
 {
   GbpDevhelpHoverProvider *self = (GbpDevhelpHoverProvider *)provider;
-  //g_autoptr(IdeMarkedContent) content = NULL;
   g_autoptr(IdeTask) task = NULL;
+  IdeBuffer *buffer;
+  Hover *h;
 
   g_assert (GBP_IS_DEVHELP_HOVER_PROVIDER (self));
   g_assert (IDE_IS_HOVER_CONTEXT (context));
@@ -47,10 +173,25 @@ gbp_devhelp_hover_provider_hover_async (IdeHoverProvider    *provider,
   task = ide_task_new (self, cancellable, callback, user_data);
   ide_task_set_source_tag (task, gbp_devhelp_hover_provider_hover_async);
 
-  //content = ide_marked_content_new_plaintext ("this is some docs");
-  //ide_hover_context_add_content (context, "Devhelp", content);
+  /*
+   * The goal here is to find the name of the symbol underneath the cursor.
+   * However, if we fail to resolve that, then we can just use the word as
+   * a keyword and search the index using that.
+   */
 
-  ide_task_return_boolean (task, TRUE);
+  h = g_slice_new0 (Hover);
+  h->context = g_object_ref (context);
+  h->word = _ide_text_iter_current_symbol (iter, NULL);
+  ide_task_set_task_data (task, h, (GDestroyNotify)hover_free);
+
+  buffer = IDE_BUFFER (gtk_text_iter_get_buffer (iter));
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  ide_buffer_get_symbol_at_location_async (buffer,
+                                           iter,
+                                           cancellable,
+                                           gbp_devhelp_hover_provider_get_symbol_cb,
+                                           g_steal_pointer (&task));
 }
 
 static gboolean


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]