summaryrefslogtreecommitdiff
path: root/src/yelp-application.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/yelp-application.c')
-rw-r--r--src/yelp-application.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/yelp-application.c b/src/yelp-application.c
new file mode 100644
index 00000000..46ccd720
--- /dev/null
+++ b/src/yelp-application.c
@@ -0,0 +1,270 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2010 Shaun McCance <shaunm@gnome.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
+ * 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.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib.h>
+#include <gtk/gtk.h>
+
+#include "yelp-application.h"
+#include "yelp-dbus.h"
+#include "yelp-view.h"
+
+typedef struct _YelpApplicationLoad YelpApplicationLoad;
+struct _YelpApplicationLoad {
+ YelpApplication *app;
+ guint timestamp;
+};
+
+static void yelp_application_init (YelpApplication *app);
+static void yelp_application_class_init (YelpApplicationClass *klass);
+static void yelp_application_dispose (GObject *object);
+static void yelp_application_finalize (GObject *object);
+
+static GtkWidget * application_new_window (YelpApplication *app);
+static void application_uri_resolved (YelpUri *uri,
+ YelpApplicationLoad *data);
+
+G_DEFINE_TYPE (YelpApplication, yelp_application, G_TYPE_OBJECT);
+#define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_APPLICATION, YelpApplicationPrivate))
+
+typedef struct _YelpApplicationPrivate YelpApplicationPrivate;
+struct _YelpApplicationPrivate {
+ DBusGConnection *connection;
+
+ GSList *windows;
+
+ GHashTable *windows_by_document;
+};
+
+static void
+yelp_application_init (YelpApplication *app)
+{
+ YelpApplicationPrivate *priv = GET_PRIV (app);
+
+ priv->windows_by_document = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+}
+
+static void
+yelp_application_class_init (YelpApplicationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = yelp_application_dispose;
+ object_class->finalize = yelp_application_finalize;
+
+ dbus_g_object_type_install_info (YELP_TYPE_APPLICATION,
+ &dbus_glib_yelp_object_info);
+
+ g_type_class_add_private (klass, sizeof (YelpApplicationPrivate));
+}
+
+static void
+yelp_application_dispose (GObject *object)
+{
+ YelpApplicationPrivate *priv = GET_PRIV (object);
+
+ g_object_unref (priv->connection);
+
+ g_hash_table_destroy (priv->windows_by_document);
+
+ G_OBJECT_CLASS (yelp_application_parent_class)->dispose (object);
+}
+
+static void
+yelp_application_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (yelp_application_parent_class)->finalize (object);
+}
+
+
+/******************************************************************************/
+
+YelpApplication *
+yelp_application_new (void)
+{
+ YelpApplication *app;
+
+ app = (YelpApplication *) g_object_new (YELP_TYPE_APPLICATION, NULL);
+
+ return app;
+}
+
+gint
+yelp_application_run (YelpApplication *app,
+ GOptionContext *context,
+ gint argc,
+ gchar **argv)
+{
+ GError *error = NULL;
+ DBusGProxy *proxy;
+ guint request;
+ YelpApplicationPrivate *priv = GET_PRIV (app);
+ gchar *uri;
+
+ priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (priv->connection == NULL) {
+ g_warning ("Unable to connect to dbus: %s", error->message);
+ g_error_free (error);
+ return 1;
+ }
+
+ /* FIXME: canonicalize relative URI */
+ if (argc > 1)
+ uri = argv[1];
+ else
+ uri = "ghelp:user-guide";
+
+ proxy = dbus_g_proxy_new_for_name (priv->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ if (!org_freedesktop_DBus_request_name (proxy,
+ "org.gnome.Yelp",
+ 0, &request,
+ &error)) {
+ g_warning ("Unable to register service: %s", error->message);
+ g_error_free (error);
+ g_object_unref (proxy);
+ return 1;
+ }
+
+ g_object_unref (proxy);
+
+ if (request == DBUS_REQUEST_NAME_REPLY_EXISTS ||
+ request == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) {
+ gchar *newuri;
+
+ newuri = g_strdup (uri);
+
+ proxy = dbus_g_proxy_new_for_name (priv->connection,
+ "org.gnome.Yelp",
+ "/org/gnome/Yelp",
+ "org.gnome.Yelp");
+ if (!dbus_g_proxy_call (proxy, "LoadUri", &error,
+ G_TYPE_STRING, newuri,
+ G_TYPE_UINT, GDK_CURRENT_TIME,
+ G_TYPE_INVALID, G_TYPE_INVALID)) {
+ g_warning ("Unable to notify existing process: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ g_free (newuri);
+ g_object_unref (proxy);
+ return 1;
+ }
+
+ dbus_g_connection_register_g_object (priv->connection,
+ "/org/gnome/Yelp",
+ G_OBJECT (app));
+
+ yelp_application_load_uri (app, uri, GDK_CURRENT_TIME, NULL);
+
+ gtk_main ();
+
+ return 0;
+}
+
+gboolean
+yelp_application_load_uri (YelpApplication *app,
+ const gchar *uri,
+ guint timestamp,
+ GError **error)
+{
+ YelpApplicationLoad *data;
+ YelpUri *yuri;
+
+ data = g_new (YelpApplicationLoad, 1);
+ data->app = app;
+ data->timestamp = timestamp;
+
+ yuri = yelp_uri_new (uri);
+
+ g_signal_connect (yuri, "resolved",
+ G_CALLBACK (application_uri_resolved),
+ data);
+ yelp_uri_resolve (yuri);
+
+ return TRUE;
+}
+
+static GtkWidget *
+application_new_window (YelpApplication *app)
+{
+ GtkWidget *window, *scroll, *view;
+ YelpApplicationPrivate *priv = GET_PRIV (app);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_UTILITY);
+ gtk_window_set_default_size (GTK_WINDOW (window), 520, 580);
+ priv->windows = g_slist_prepend (priv->windows, window);
+
+ scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (window), scroll);
+
+ view = yelp_view_new ();
+ gtk_container_add (GTK_CONTAINER (scroll), view);
+
+ g_object_set_data (G_OBJECT (window), "view", view);
+
+ return window;
+}
+
+static void
+application_uri_resolved (YelpUri *uri,
+ YelpApplicationLoad *data)
+{
+ GtkWidget *window;
+ YelpView *view;
+ gchar *doc_uri;
+ YelpApplicationPrivate *priv = GET_PRIV (data->app);
+
+ doc_uri = yelp_uri_get_document_uri (uri);
+
+ window = g_hash_table_lookup (priv->windows_by_document, doc_uri);
+
+ if (window == NULL) {
+ window = application_new_window (data->app);
+ g_hash_table_insert (priv->windows_by_document, doc_uri, window);
+ }
+ else {
+ g_free (doc_uri);
+ }
+
+ view = g_object_get_data (G_OBJECT (window), "view");
+ yelp_view_load_uri (YELP_VIEW (view), uri);
+
+ gtk_widget_show_all (window);
+ gtk_window_present_with_time (GTK_WINDOW (window), data->timestamp);
+
+ g_free (data);
+}