[recipes] Add a shell search provider



commit 2188dc0043906b4c2ec5c6fb8a1f514feb492be6
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Dec 7 21:55:56 2016 -0500

    Add a shell search provider
    
    This makes recipes show up as search results in the shell
    overview.

 src/Makefile.am                               |   20 ++-
 src/gr-app.c                                  |   90 ++++++-
 src/gr-shell-search-provider.c                |  352 +++++++++++++++++++++++++
 src/gr-shell-search-provider.h                |   41 +++
 src/gr-window.c                               |    9 +
 src/gr-window.h                               |    2 +
 src/shell-search-provider-dbus-interfaces.xml |   44 +++
 7 files changed, 545 insertions(+), 13 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 9dbbb0c..a6b39c4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -90,12 +90,18 @@ recipes_SOURCES = \
        gr-window.c             \
        resources.c             \
        types.h                 \
-       types.c
+       types.c                 \
+       gr-shell-search-provider.h \
+       gr-shell-search-provider.c \
+       gr-shell-search-provider-dbus.h \
+       gr-shell-search-provider-dbus.c
 
 BUILT_SOURCES = \
        resources.c             \
        types.h                 \
-       types.c
+       types.c                 \
+       gr-shell-search-provider-dbus.h \
+       gr-shell-search-provider-dbus.c
 
 resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies 
$(srcdir)/recipes.gresource.xml)
 
@@ -113,6 +119,16 @@ types.c: types.c.template gr-recipe.h
        cp xgen-ec $@ && \
        rm -f xgen-ec
 
+gr-shell-search-provider-dbus.h gr-shell-search-provider-dbus.c: Makefile.am 
$(srcdir)/shell-search-provider-dbus-interfaces.xml
+       $(AM_V_GEN) gdbus-codegen \
+               --interface-prefix org.gnome. \
+               --c-namespace Gr \
+               --generate-c-code gr-shell-search-provider-dbus \
+               $(srcdir)/shell-search-provider-dbus-interfaces.xml
+
+searchproviderdir = $(datadir)/gnome-shell/search-providers
+searchprovider_DATA = org.gnome.Recipes-search-provider.ini
+
 EXTRA_DIST = \
        $(resource_files)       \
        types.h.template        \
diff --git a/src/gr-app.c b/src/gr-app.c
index 6b35567..58e9888 100644
--- a/src/gr-app.c
+++ b/src/gr-app.c
@@ -28,6 +28,7 @@
 #include "gr-preferences.h"
 #include "gr-recipe-store.h"
 #include "gr-cuisine.h"
+#include "gr-shell-search-provider.h"
 
 
 struct _GrApp
@@ -35,6 +36,7 @@ struct _GrApp
         GtkApplication parent_instance;
 
         GrRecipeStore *store;
+        GrShellSearchProvider *search_provider;
 };
 
 G_DEFINE_TYPE (GrApp, gr_app, GTK_TYPE_APPLICATION)
@@ -51,6 +53,17 @@ gr_app_finalize (GObject *object)
 }
 
 static void
+gr_app_activate (GApplication *app)
+{
+        GtkWindow *win;
+
+        win = gtk_application_get_active_window (GTK_APPLICATION (app));
+        if (!win)
+                win = GTK_WINDOW (gr_window_new (GR_APP (app)));
+        gtk_window_present (win);
+}
+
+static void
 preferences_activated (GSimpleAction *action,
                        GVariant      *parameter,
                        gpointer       app)
@@ -136,11 +149,47 @@ import_activated (GSimpleAction *action,
         gr_window_load_recipe (GR_WINDOW (win), NULL);
 }
 
+static void
+details_activated (GSimpleAction *action,
+                   GVariant      *parameter,
+                   gpointer       application)
+{
+        GrApp *app = GR_APP (application);
+        GtkWindow *win;
+        const char *id, *search;
+        g_autoptr(GrRecipe) recipe = NULL;
+
+        g_variant_get (parameter, "(&s&s)", &id, &search);
+
+        gr_app_activate (G_APPLICATION (app));
+        win = gtk_application_get_active_window (GTK_APPLICATION (app));
+        recipe = gr_recipe_store_get (app->store, id);
+        gr_window_show_recipe (GR_WINDOW (win), recipe);
+}
+
+static void
+search_activated (GSimpleAction *action,
+                  GVariant      *parameter,
+                  gpointer       application)
+{
+        GrApp *app = GR_APP (application);
+        GtkWindow *win;
+        const char *search;
+
+        g_variant_get (parameter, "&s", &search);
+
+        win = gtk_application_get_active_window (GTK_APPLICATION (app));
+        gr_app_activate (G_APPLICATION (app));
+        gr_window_show_search (GR_WINDOW (win), search);
+}
+
 static GActionEntry app_entries[] =
 {
         { "preferences", preferences_activated, NULL, NULL, NULL },
         { "about", about_activated, NULL, NULL, NULL },
         { "import", import_activated, NULL, NULL, NULL },
+        { "details", details_activated, "(ss)", NULL, NULL },
+        { "search", search_activated, "s", NULL, NULL },
         { "timer-expired", timer_expired, "s", NULL, NULL },
         { "quit", quit_activated, NULL, NULL, NULL }
 };
@@ -192,17 +241,6 @@ gr_app_startup (GApplication *app)
 }
 
 static void
-gr_app_activate (GApplication *app)
-{
-        GtkWindow *win;
-
-        win = gtk_application_get_active_window (GTK_APPLICATION (app));
-        if (!win)
-                win = GTK_WINDOW (gr_window_new (GR_APP (app)));
-        gtk_window_present (win);
-}
-
-static void
 gr_app_open (GApplication  *app,
              GFile        **files,
              gint           n_files,
@@ -222,6 +260,34 @@ gr_app_open (GApplication  *app,
         gtk_window_present (win);
 }
 
+static gboolean
+gr_app_dbus_register (GApplication    *application,
+                      GDBusConnection *connection,
+                      const gchar     *object_path,
+                      GError         **error)
+{
+        GrApp *app = GR_APP (application);
+
+        app->search_provider = gr_shell_search_provider_new ();
+        gr_shell_search_provider_setup (app->search_provider, app->store);
+
+        return gr_shell_search_provider_register (app->search_provider, connection, error);
+}
+
+static void
+gr_app_dbus_unregister (GApplication    *application,
+                        GDBusConnection *connection,
+                        const gchar     *object_path)
+{
+        GrApp *app = GR_APP (application);
+
+        if (app->search_provider != NULL) {
+                gr_shell_search_provider_unregister (app->search_provider);
+                g_clear_object (&app->search_provider);
+        }
+}
+
+
 static void
 gr_app_init (GrApp *self)
 {
@@ -239,6 +305,8 @@ gr_app_class_init (GrAppClass *klass)
         application_class->startup = gr_app_startup;
         application_class->activate = gr_app_activate;
         application_class->open = gr_app_open;
+        application_class->dbus_register = gr_app_dbus_register;
+        application_class->dbus_unregister = gr_app_dbus_unregister;
 }
 
 GrApp *
diff --git a/src/gr-shell-search-provider.c b/src/gr-shell-search-provider.c
new file mode 100644
index 0000000..14139c0
--- /dev/null
+++ b/src/gr-shell-search-provider.c
@@ -0,0 +1,352 @@
+/* gr-shell-search-provider.c:
+ *
+ * Copyright (C) 2016 Matthias Clasen
+ *
+ * Licensed under the GNU General Public License Version 3
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "gr-shell-search-provider-dbus.h"
+#include "gr-shell-search-provider.h"
+#include "gr-images.h"
+#include "gr-utils.h"
+
+
+typedef struct {
+        GrShellSearchProvider *provider;
+        GDBusMethodInvocation *invocation;
+        GrRecipeSearch *search;
+        GList *results;
+} PendingSearch;
+
+struct _GrShellSearchProvider {
+        GObject parent;
+
+        GrShellSearchProvider2 *skeleton;
+        GrRecipeStore *store;
+        GCancellable *cancellable;
+
+        GHashTable *metas_cache;
+};
+
+G_DEFINE_TYPE (GrShellSearchProvider, gr_shell_search_provider, G_TYPE_OBJECT)
+
+static void
+pending_search_free (PendingSearch *search)
+{
+        g_object_unref (search->invocation);
+        g_object_unref (search->search);
+        g_slice_free (PendingSearch, search);
+}
+
+static void
+finished_cb (GrRecipeSearch *search,
+             gpointer        user_data)
+{
+        PendingSearch *pending_search = user_data;
+        GVariantBuilder builder;
+        GList *l;
+
+        if (pending_search->results == NULL) {
+                g_dbus_method_invocation_return_value (pending_search->invocation, g_variant_new ("(as)", 
NULL));
+                pending_search_free (pending_search);
+                g_application_release (g_application_get_default ());
+                return;
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
+        for (l = pending_search->results; l; l = l->next) {
+                g_variant_builder_add (&builder, "s", l->data);
+        }
+        g_dbus_method_invocation_return_value (pending_search->invocation, g_variant_new ("(as)", &builder));
+
+        pending_search_free (pending_search);
+        g_application_release (g_application_get_default ());
+}
+
+static void
+hits_added_cb (GrRecipeSearch *search,
+               GList          *hits,
+               PendingSearch  *pending_search)
+{
+        GList *l;
+
+        for (l = hits; l; l = l->next) {
+                GrRecipe *recipe = l->data;
+
+                pending_search->results = g_list_prepend (pending_search->results, 
(gpointer)gr_recipe_get_name (recipe));
+        }
+}
+
+static void
+execute_search (GrShellSearchProvider  *self,
+                GDBusMethodInvocation  *invocation,
+                gchar                 **terms)
+{
+        PendingSearch *pending_search;
+        g_autofree gchar *string = NULL;
+
+        string = g_strjoinv (" ", terms);
+
+        if (self->cancellable != NULL) {
+                g_cancellable_cancel (self->cancellable);
+                g_clear_object (&self->cancellable);
+        }
+
+        /* don't attempt searches for a single character */
+        if (g_strv_length (terms) == 1 &&
+            g_utf8_strlen (terms[0], -1) == 1) {
+                g_dbus_method_invocation_return_value (invocation, g_variant_new ("(as)", NULL));
+                return;
+        }
+
+        pending_search = g_slice_new (PendingSearch);
+        pending_search->provider = self;
+        pending_search->invocation = g_object_ref (invocation);
+        pending_search->results = NULL;
+
+        g_application_hold (g_application_get_default ());
+        self->cancellable = g_cancellable_new ();
+
+        pending_search->search = gr_recipe_search_new ();
+        g_signal_connect (pending_search->search, "hits-added",
+                          G_CALLBACK (hits_added_cb), pending_search);
+        g_signal_connect (pending_search->search, "finished",
+                          G_CALLBACK (finished_cb), pending_search);
+
+        gr_recipe_search_set_query (pending_search->search, string);
+}
+
+static gboolean
+handle_get_initial_result_set (GrShellSearchProvider2  *skeleton,
+                               GDBusMethodInvocation   *invocation,
+                               gchar                  **terms,
+                               gpointer                 user_data)
+{
+        GrShellSearchProvider *self = user_data;
+
+        g_debug ("****** GetInitialResultSet");
+        execute_search (self, invocation, terms);
+        return TRUE;
+}
+
+static gboolean
+handle_get_subsearch_result_set (GrShellSearchProvider2  *skeleton,
+                                 GDBusMethodInvocation   *invocation,
+                                 gchar                  **previous_results,
+                                 gchar                  **terms,
+                                 gpointer                 user_data)
+{
+        GrShellSearchProvider *self = user_data;
+
+        g_debug ("****** GetSubSearchResultSet");
+        execute_search (self, invocation, terms);
+        return TRUE;
+}
+
+static GdkPixbuf *
+gr_recipe_get_pixbuf (GrRecipe *recipe)
+{
+        g_autoptr(GArray) images = NULL;
+
+        g_object_get (recipe, "images", &images, NULL);
+
+        if (images->len > 0) {
+                GrRotatedImage *ri = &g_array_index (images, GrRotatedImage, 0);
+                GdkPixbuf *pixbuf;
+
+                pixbuf = load_pixbuf_fill_size (ri->path, ri->angle, 64, 64);
+                return pixbuf;
+        }
+
+        return NULL;
+}
+
+static gboolean
+handle_get_result_metas (GrShellSearchProvider2 *skeleton,
+                         GDBusMethodInvocation   *invocation,
+                         gchar                  **results,
+                         gpointer                 user_data)
+{
+        GrShellSearchProvider *self = user_data;
+        GVariantBuilder meta;
+        GVariant *meta_variant;
+        GdkPixbuf *pixbuf;
+        gint i;
+        GVariantBuilder builder;
+
+        g_debug ("****** GetResultMetas");
+
+        for (i = 0; results[i]; i++) {
+                g_autoptr(GrRecipe) recipe = NULL;
+
+                if (g_hash_table_lookup (self->metas_cache, results[i]))
+                        continue;
+
+                recipe = gr_recipe_store_get (self->store, results[i]);
+                if (recipe == NULL) {
+                        g_warning ("failed to find %s", results[i]);
+                        continue;
+                }
+
+                g_variant_builder_init (&meta, G_VARIANT_TYPE ("a{sv}"));
+                g_variant_builder_add (&meta, "{sv}", "id", g_variant_new_string (gr_recipe_get_name 
(recipe)));
+                g_variant_builder_add (&meta, "{sv}", "name", g_variant_new_string (gr_recipe_get_name 
(recipe)));
+                pixbuf = gr_recipe_get_pixbuf (recipe);
+                if (pixbuf != NULL)
+                        g_variant_builder_add (&meta, "{sv}", "icon", g_icon_serialize (G_ICON (pixbuf)));
+                g_variant_builder_add (&meta, "{sv}", "description", g_variant_new_string 
(gr_recipe_get_description (recipe)));
+                meta_variant = g_variant_builder_end (&meta);
+                g_hash_table_insert (self->metas_cache, g_strdup (gr_recipe_get_name (recipe)), 
g_variant_ref_sink (meta_variant));
+
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+        for (i = 0; results[i]; i++) {
+                meta_variant = (GVariant*)g_hash_table_lookup (self->metas_cache, results[i]);
+                if (meta_variant == NULL)
+                        continue;
+                g_variant_builder_add_value (&builder, meta_variant);
+        }
+
+        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(aa{sv})", &builder));
+
+        return TRUE;
+}
+
+static gboolean
+handle_activate_result (GrShellSearchProvider2  *skeleton,
+                        GDBusMethodInvocation   *invocation,
+                        gchar                   *result,
+                        gchar                  **terms,
+                        guint32                  timestamp,
+                        gpointer                 user_data)
+{
+        GApplication *app = g_application_get_default ();
+        g_autofree gchar *string = NULL;
+
+        string = g_strjoinv (" ", terms);
+
+        g_action_group_activate_action (G_ACTION_GROUP (app), "details",
+                                        g_variant_new ("(ss)", result, string));
+
+        gr_shell_search_provider2_complete_activate_result (skeleton, invocation);
+
+        return TRUE;
+}
+
+static gboolean
+handle_launch_search (GrShellSearchProvider2  *skeleton,
+                      GDBusMethodInvocation   *invocation,
+                      gchar                  **terms,
+                      guint32                  timestamp,
+                      gpointer                 user_data)
+{
+        GApplication *app = g_application_get_default ();
+        g_autofree gchar *string = g_strjoinv (" ", terms);
+
+        g_action_group_activate_action (G_ACTION_GROUP (app), "search",
+                                        g_variant_new ("s", string));
+
+        gr_shell_search_provider2_complete_launch_search (skeleton, invocation);
+
+        return TRUE;
+}
+
+gboolean
+gr_shell_search_provider_register (GrShellSearchProvider  *self,
+                                   GDBusConnection        *connection,
+                                   GError                **error)
+{
+        return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->skeleton),
+                                                 connection,
+                                                 "/org/gnome/Recipes/SearchProvider",
+                                                 error);
+}
+
+void
+gr_shell_search_provider_unregister (GrShellSearchProvider *self)
+{
+        g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->skeleton));
+}
+
+static void
+search_provider_dispose (GObject *obj)
+{
+        GrShellSearchProvider *self = GR_SHELL_SEARCH_PROVIDER (obj);
+
+        if (self->cancellable != NULL) {
+                g_cancellable_cancel (self->cancellable);
+                g_clear_object (&self->cancellable);
+        }
+
+        if (self->metas_cache != NULL) {
+                g_hash_table_destroy (self->metas_cache);
+                self->metas_cache = NULL;
+        }
+
+        g_clear_object (&self->store);
+        g_clear_object (&self->skeleton);
+
+        G_OBJECT_CLASS (gr_shell_search_provider_parent_class)->dispose (obj);
+}
+
+static void
+gr_shell_search_provider_init (GrShellSearchProvider *self)
+{
+        self->metas_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                   g_free, (GDestroyNotify) g_variant_unref);
+
+        self->skeleton = gr_shell_search_provider2_skeleton_new ();
+
+        g_signal_connect (self->skeleton, "handle-get-initial-result-set",
+                          G_CALLBACK (handle_get_initial_result_set), self);
+        g_signal_connect (self->skeleton, "handle-get-subsearch-result-set",
+                          G_CALLBACK (handle_get_subsearch_result_set), self);
+        g_signal_connect (self->skeleton, "handle-get-result-metas",
+                          G_CALLBACK (handle_get_result_metas), self);
+        g_signal_connect (self->skeleton, "handle-activate-result",
+                          G_CALLBACK (handle_activate_result), self);
+        g_signal_connect (self->skeleton, "handle-launch-search",
+                          G_CALLBACK (handle_launch_search), self);
+}
+
+static void
+gr_shell_search_provider_class_init (GrShellSearchProviderClass *klass)
+{
+        GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+        oclass->dispose = search_provider_dispose;
+}
+
+GrShellSearchProvider *
+gr_shell_search_provider_new (void)
+{
+        return g_object_new (gr_shell_search_provider_get_type (), NULL);
+}
+
+void
+gr_shell_search_provider_setup (GrShellSearchProvider *provider,
+                                GrRecipeStore         *store)
+{
+        provider->store = g_object_ref (store);
+}
diff --git a/src/gr-shell-search-provider.h b/src/gr-shell-search-provider.h
new file mode 100644
index 0000000..26a6688
--- /dev/null
+++ b/src/gr-shell-search-provider.h
@@ -0,0 +1,41 @@
+/* gr-shell-search-provider.h:
+ *
+ * Copyright (C) 2016 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 3
+ *
+ * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+#include "gr-recipe-store.h"
+
+G_BEGIN_DECLS
+
+#define GR_TYPE_SHELL_SEARCH_PROVIDER gr_shell_search_provider_get_type()
+
+G_DECLARE_FINAL_TYPE (GrShellSearchProvider, gr_shell_search_provider, GR, SHELL_SEARCH_PROVIDER, GObject)
+
+gboolean                 gr_shell_search_provider_register      (GrShellSearchProvider  *self,
+                                                                 GDBusConnection        *connection,
+                                                                 GError                **error);
+void                     gr_shell_search_provider_unregister    (GrShellSearchProvider  *self);
+GrShellSearchProvider   *gr_shell_search_provider_new           (void);
+void                     gr_shell_search_provider_setup         (GrShellSearchProvider  *self,
+                                                                 GrRecipeStore          *store);
+
+G_END_DECLS
diff --git a/src/gr-window.c b/src/gr-window.c
index 16dd27b..eed30a6 100644
--- a/src/gr-window.c
+++ b/src/gr-window.c
@@ -189,6 +189,15 @@ switch_to_search (GrWindow *window)
        gtk_stack_set_visible_child_name (GTK_STACK (window->main_stack), "search");
 }
 
+void
+gr_window_show_search (GrWindow   *window,
+                       const char *search)
+{
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->search_button), TRUE);
+        switch_to_search (window);
+        gr_query_editor_set_query (GR_QUERY_EDITOR (window->search_bar), search);
+}
+
 static void
 visible_page_changed (GrWindow *window)
 {
diff --git a/src/gr-window.h b/src/gr-window.h
index ff39668..7bf49db 100644
--- a/src/gr-window.h
+++ b/src/gr-window.h
@@ -38,6 +38,8 @@ void            gr_window_edit_recipe                (GrWindow   *window,
                                                       GrRecipe   *recipe);
 void            gr_window_load_recipe                (GrWindow   *window,
                                                       GFile      *file);
+void            gr_window_show_search                (GrWindow   *window,
+                                                      const char *terms);
 void            gr_window_go_back                    (GrWindow   *window);
 void            gr_window_show_diet                  (GrWindow   *window,
                                                       const char *title,
diff --git a/src/shell-search-provider-dbus-interfaces.xml b/src/shell-search-provider-dbus-interfaces.xml
new file mode 100644
index 0000000..f6840e2
--- /dev/null
+++ b/src/shell-search-provider-dbus-interfaces.xml
@@ -0,0 +1,44 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+
+<!--
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+-->
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+  <interface name='org.gnome.Shell.SearchProvider2'>
+    <method name='GetInitialResultSet'>
+      <arg type='as' name='Terms' direction='in' />
+      <arg type='as' name='Results' direction='out' />
+    </method>
+    <method name = 'GetSubsearchResultSet'>
+      <arg type='as' name='PreviousResults' direction='in' />
+      <arg type='as' name='Terms' direction='in' />
+      <arg type='as' name='Results' direction='out' />
+    </method>
+    <method name = 'GetResultMetas'>
+      <arg type='as' name='Results' direction='in' />
+      <arg type='aa{sv}' name='Metas' direction='out' />
+    </method>
+    <method name = 'ActivateResult'>
+      <arg type='s' name='Result' direction='in' />
+      <arg type='as' name='Terms' direction='in' />
+      <arg type='u' name='Timestamp' direction='in' />
+    </method>
+    <method name = 'LaunchSearch'>
+      <arg type='as' name='Terms' direction='in' />
+      <arg type='u' name='Timestamp' direction='in' />
+    </method>
+  </interface>
+</node>


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