[virt-tools-list] [virt-viewer 2/7] ovirt: Add OvirtForeignMenu class

Marc-André Lureau marcandre.lureau at gmail.com
Thu Apr 17 11:26:09 UTC 2014


On Wed, Apr 16, 2014 at 6:59 PM, Christophe Fergeau <cfergeau at redhat.com>wrote:

> This class is used to implement the so-called oVirt 'foreign menu'
> which is a menu populated with ISO images available on the
> oVirt instance that the user can dynamically insert into the
> virtual machine he is currently viewing.
> ---
>  configure.ac             |   1 +
>  src/Makefile.am          |   4 +
>  src/ovirt-foreign-menu.c | 580
> +++++++++++++++++++++++++++++++++++++++++++++++
>  src/ovirt-foreign-menu.h |  82 +++++++
>  4 files changed, 667 insertions(+)
>  create mode 100644 src/ovirt-foreign-menu.c
>  create mode 100644 src/ovirt-foreign-menu.h
>
> diff --git a/configure.ac b/configure.ac
> index f966688..4e0d7b3 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -200,6 +200,7 @@ AS_IF([test "x$have_ovirt" = "xyes"],
>               [AC_MSG_ERROR([oVirt support requested but libgovirt not
> found])
>        ])
>  ])
> +AM_CONDITIONAL([HAVE_OVIRT], [test "x$have_ovirt" = "xyes"])
>
>  dnl Decide if this platform can support the SSH tunnel feature.
>  AC_CHECK_HEADERS([sys/socket.h sys/un.h windows.h])
> diff --git a/src/Makefile.am b/src/Makefile.am
> index b3a9637..ee8f885 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -67,6 +67,10 @@ COMMON_SOURCES +=
>      \
>         $(NULL)
>  endif
>
> +if HAVE_OVIRT
> +COMMON_SOURCES +=                                      \
> +       ovirt-foreign-menu.h ovirt-foreign-menu.c
> +endif
>
>  if HAVE_LIBVIRT
>  bin_PROGRAMS += virt-viewer
> diff --git a/src/ovirt-foreign-menu.c b/src/ovirt-foreign-menu.c
> new file mode 100644
> index 0000000..642c0ef
> --- /dev/null
> +++ b/src/ovirt-foreign-menu.c
> @@ -0,0 +1,580 @@
> +/*
> + * Virt Viewer: A virtual machine console viewer
> + *
> + * Copyright (C) 2007-2013 Red Hat, Inc.
> + * Copyright (C) 2009-2012 Daniel P. Berrange
> + * Copyright (C) 2010 Marc-André Lureau
> + *
> + * 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: Daniel P. Berrange <berrange at redhat.com>
> + *         Christope Fergeau <cfergeau at redhat.com>
> + */
> +
> +#include <config.h>
> +
> +#include "ovirt-foreign-menu.h"
> +#include "virt-glib-compat.h"
> +
> +#if !GLIB_CHECK_VERSION(2, 26, 0)
> +#include "gbinding.h"
> +#include "gbinding.c"
> +#endif
> +
> +typedef enum {
> +    STATE_0,
> +    STATE_STORAGE_DOMAIN,
> +    STATE_VM_CDROM,
> +    STATE_ISOS
> +} OvirtForeignMenuState;
> +
> +static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu,
> OvirtForeignMenuState state);
> +static void
> ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu);
> +static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu
> *menu);
> +static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data);
> +
> +G_DEFINE_TYPE (OvirtForeignMenu, ovirt_foreign_menu, G_TYPE_OBJECT)
> +
> +
> +struct _OvirtForeignMenuPrivate {
> +    OvirtProxy *proxy;
> +    OvirtApi *api;
> +    OvirtVm *vm;
> +
> +    OvirtCollection *files;
> +    OvirtCdrom *cdrom;
> +
> +    GList *iso_names;
> +};
> +
> +
> +#define OVIRT_FOREIGN_MENU_GET_PRIVATE(o)
> (G_TYPE_INSTANCE_GET_PRIVATE((o), OVIRT_TYPE_FOREIGN_MENU,
> OvirtForeignMenuPrivate))
> +
> +
> +enum {
> +    PROP_0,
> +    PROP_PROXY,
> +    PROP_API,
> +    PROP_VM,
> +    PROP_FILES,
> +};
> +
> +static void
> +ovirt_foreign_menu_get_property(GObject *object, guint property_id,
> +                                       GValue *value, GParamSpec *pspec)
> +{
> +    OvirtForeignMenu *self = OVIRT_FOREIGN_MENU(object);
> +    OvirtForeignMenuPrivate *priv = self->priv;
> +
> +    switch (property_id) {
> +    case PROP_PROXY:
> +        g_value_set_object(value, priv->proxy);
> +        break;
> +    case PROP_API:
> +        g_value_set_object(value, priv->api);
> +        break;
> +    case PROP_VM:
> +        g_value_set_object(value, priv->vm);
> +        break;
> +    case PROP_FILES:
> +        g_value_set_pointer(value, priv->iso_names);
> +
> +    default:
> +        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
> +    }
> +}
> +
> +
> +static void
> +ovirt_foreign_menu_set_property(GObject *object, guint property_id,
> +                                       const GValue *value G_GNUC_UNUSED,
> GParamSpec *pspec)
> +{
> +    OvirtForeignMenu *self = OVIRT_FOREIGN_MENU(object);
> +    OvirtForeignMenuPrivate *priv = self->priv;
> +
> +    switch (property_id) {
> +    case PROP_PROXY:
> +        if (priv->proxy != NULL) {
> +            g_object_unref(priv->proxy);
> +        }
>

newly written code can really benefit g_clear_object() / g_clear_pointer()
- true for all the remaining if { unref ; foo = NULL } all over.

+        priv->proxy = g_value_dup_object(value);
> +        break;
> +    case PROP_API:
> +        if (priv->api != NULL) {
> +            g_object_unref(priv->api);
> +        }
> +        priv->api = g_value_dup_object(value);
> +        break;
> +    case PROP_VM:
> +        if (priv->vm != NULL) {
> +            g_object_unref(priv->vm);
> +        }
> +        priv->vm = g_value_dup_object(value);
> +        break;
> +    default:
> +        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
> +    }
> +}
> +
> +
> +static void
> +ovirt_foreign_menu_dispose(GObject *obj)
> +{
> +    OvirtForeignMenu *self = OVIRT_FOREIGN_MENU(obj);
> +
> +    g_debug("Disposing of foreign menu");
> +    if (self->priv->proxy) {
> +        g_object_unref(self->priv->proxy);
> +        self->priv->proxy = NULL;
> +    }
> +
> +    if (self->priv->api != NULL) {
> +        g_object_unref(self->priv->api);
> +        self->priv->api = NULL;
> +    }
> +
> +    if (self->priv->vm) {
> +        g_object_unref(self->priv->vm);
> +        self->priv->vm = NULL;
> +    }
> +
> +    if (self->priv->files) {
> +        g_object_unref(self->priv->files);
> +        self->priv->files = NULL;
> +    }
> +
> +    if (self->priv->cdrom) {
> +        g_object_unref(self->priv->cdrom);
> +        self->priv->cdrom = NULL;
> +    }
> +
> +    if (self->priv->iso_names) {
> +        g_list_free_full(self->priv->iso_names, (GDestroyNotify)g_free);
> +        self->priv->iso_names = NULL;
> +    }
> +
> +    G_OBJECT_CLASS(ovirt_foreign_menu_parent_class)->dispose(obj);
> +}
> +
> +
> +static void
> +ovirt_foreign_menu_class_init(OvirtForeignMenuClass *klass)
> +{
> +    GObjectClass *oclass = G_OBJECT_CLASS(klass);
> +
> +    oclass->get_property = ovirt_foreign_menu_get_property;
> +    oclass->set_property = ovirt_foreign_menu_set_property;
> +    oclass->dispose = ovirt_foreign_menu_dispose;
> +
> +    g_type_class_add_private(klass, sizeof(OvirtForeignMenuPrivate));
> +
> +    g_object_class_install_property(oclass,
> +                                    PROP_PROXY,
> +                                    g_param_spec_object("proxy",
> +                                                        "OvirtProxy
> instance",
> +                                                        "OvirtProxy
> instance",
> +                                                        OVIRT_TYPE_PROXY,
> +                                                        G_PARAM_READWRITE
> |
> +
>  G_PARAM_CONSTRUCT_ONLY |
> +
>  G_PARAM_STATIC_STRINGS));
> +    g_object_class_install_property(oclass,
> +                                    PROP_API,
> +                                    g_param_spec_object("api",
> +                                                        "OvirtApi
> instance",
> +                                                        "Ovirt api root",
> +                                                        OVIRT_TYPE_API,
> +                                                        G_PARAM_READWRITE
> |
> +
>  G_PARAM_STATIC_STRINGS));
> +    g_object_class_install_property(oclass,
> +                                    PROP_VM,
> +                                    g_param_spec_object("vm",
> +                                                        "OvirtVm
> instance",
> +                                                        "OvirtVm being
> handled",
> +                                                        OVIRT_TYPE_VM,
> +                                                        G_PARAM_READWRITE
> |
> +
>  G_PARAM_STATIC_STRINGS));
> +    g_object_class_install_property(oclass,
> +                                    PROP_FILES,
> +                                    g_param_spec_pointer("files",
> +                                                         "ISO names",
> +                                                         "GSList of ISO
> names for this oVirt VM",
> +                                                         G_PARAM_READABLE
> |
> +
> G_PARAM_STATIC_STRINGS));
> +}
> +
> +
> +static void
> +ovirt_foreign_menu_init(OvirtForeignMenu *self)
> +{
> +    self->priv = OVIRT_FOREIGN_MENU_GET_PRIVATE(self);
> +}
> +
> +
> +OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy)
> +{
> +    return g_object_new(OVIRT_TYPE_FOREIGN_MENU,
> +                        "proxy", proxy,
> +                        NULL);
> +}
> +
> +
> +static void
> +ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu,
> +                                   OvirtForeignMenuState current_state)
> +{
> +    current_state++;
>

I would add a few g_return_if_fail() check about current_state values.


> +
> +    if (current_state == STATE_STORAGE_DOMAIN) {
> +        if (menu->priv->files == NULL) {
> +            ovirt_foreign_menu_fetch_storage_domain_async(menu);
> +        } else {
> +            current_state++;
> +        }
> +    }
> +
> +    if (current_state == STATE_VM_CDROM) {
> +        if (menu->priv->cdrom == NULL) {
> +            ovirt_foreign_menu_fetch_vm_cdrom_async(menu);
> +        } else {
> +            current_state++;
> +        }
> +    }
> +
> +    if (current_state == STATE_ISOS) {
> +        g_warn_if_fail(menu->priv->api != NULL);
> +        g_warn_if_fail(menu->priv->vm != NULL);
> +        g_warn_if_fail(menu->priv->files != NULL);
> +        g_warn_if_fail(menu->priv->cdrom != NULL);
> +
> +        ovirt_foreign_menu_refresh_iso_list(menu);
> +    }
> +}
> +
> +
> +void
> +ovirt_foreign_menu_start(OvirtForeignMenu *menu)
> +{
> +    ovirt_foreign_menu_next_async_step(menu, STATE_0);
>

Why not calling all the async simultaneously? If they need to be chained,
isn't it simpler to do it through the normal code flow?


> +}
> +
> +
> +static void updated_cdrom_cb(GObject *source_object,
> +                            GAsyncResult *result,
> +                            G_GNUC_UNUSED gpointer user_data)
> +{
> +    GError *error = NULL;
> +    ovirt_cdrom_update_finish(OVIRT_CDROM(source_object),
> +                              result, &error);
> +    g_debug("Finished updating cdrom content");
> +    if (error != NULL) {
> +        g_debug("Failed to update cdrom resource: %s", error->message);
>

doesn't this deserve a warning? (same for similar errors)


> +        g_clear_error(&error);
> +    }
> +}
> +
> +
> +static void
> +ovirt_foreign_menu_activate_item_cb(GtkMenuItem *menuitem, gpointer
> user_data)
> +{
> +    GList *children;
> +    GList *it;
> +    GtkWidget *menu;
> +    OvirtForeignMenu *foreign_menu;
> +
> +    foreign_menu = OVIRT_FOREIGN_MENU(user_data);
> +    if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) {
> +        return;
> +    }
> +
> +    menu = gtk_widget_get_parent(GTK_WIDGET(menuitem));
> +    g_debug("'%s' clicked", gtk_menu_item_get_label(menuitem));
> +    g_return_if_fail(GTK_IS_MENU(menu));
> +    /* Unselect all other menu items, we want a GtkRadioMenuItem-like
> +     * behaviour, but we need to allow to have no item set
> +     */
> +    children = gtk_container_get_children(GTK_CONTAINER(menu));
> +    for (it = children; it != NULL; it = it->next) {
> +        if (it->data != menuitem) {
> +            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(it->data),
> FALSE);
> +        }
> +    }
> +    g_list_free(children);
> +
> +    if (foreign_menu->priv->cdrom != NULL) {
> +        const char *iso_name;
> +
> +        iso_name = gtk_menu_item_get_label(menuitem);
> +        g_object_set(G_OBJECT(foreign_menu->priv->cdrom),
> +                     "file", iso_name,
> +                     NULL);
> +        g_debug("Updating VM cdrom image to '%s'", iso_name);
> +        ovirt_cdrom_update_async(foreign_menu->priv->cdrom, TRUE,
> +                                 foreign_menu->priv->proxy, NULL,
> +                                 updated_cdrom_cb, foreign_menu);
> +    }
> +}
> +
> +
> +static char *
> +ovirt_foreign_menu_get_current_iso_name(OvirtForeignMenu *foreign_menu)
> +{
> +    char *name;
> +
> +    if (foreign_menu->priv->cdrom == NULL) {
> +        return NULL;
> +    }
> +
> +    g_object_get(G_OBJECT(foreign_menu->priv->cdrom), "file", &name,
> NULL);
>

g_object_get()/set() don't need explicit cast.


> +    return name;
> +}
> +
> +
> +GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu *foreign_menu)
> +{
> +    GtkWidget *gtk_menu;
> +    GList *it;
> +    char *current_iso;
> +
> +    g_debug("Creating GtkMenu for foreign menu");
> +    current_iso = ovirt_foreign_menu_get_current_iso_name(foreign_menu);
>

Could be NULL,


> +    gtk_menu = gtk_menu_new();
> +    for (it = foreign_menu->priv->iso_names; it != NULL; it = it->next) {
> +        GtkWidget *menuitem;
> +
> +        menuitem = gtk_check_menu_item_new_with_label((char *)it->data);
> +        if (g_strcmp0((char *)it->data, current_iso) == 0) {
>

why not use safer and clearer g_str_equal() ? (same all over)


> +            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem),
> +                                           TRUE);
> +        }
> +        g_signal_connect(menuitem, "activate",
> +                         G_CALLBACK(ovirt_foreign_menu_activate_item_cb),
> +                         foreign_menu);
> +        gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu), menuitem);
> +    }
> +    g_free(current_iso);
> +
> +    return gtk_menu;
> +}
> +
> +
> +static void ovirt_foreign_menu_set_files(OvirtForeignMenu *menu,
> +                                         const GList *files)
> +{
> +    GList *sorted_files = NULL;
> +    const GList *it;
> +    GList *it2;
> +
> +    for (it = files; it != NULL; it = it->next) {
> +        char *name;
> +        g_object_get(G_OBJECT(it->data), "name", &name, NULL);
> +        /* The oVirt REST API is supposed to have a 'type' node
> +         * associated with file resources , but as of 3.2, this node
> +         * is not present, so we do an extension check instead
> +         * to differentiate between ISOs and floppy images */
> +        if (g_str_has_suffix(name, ".vfd")) {
> +            g_free(name);
> +            continue;
> +        }
> +        sorted_files = g_list_insert_sorted(sorted_files, name,
> +                                            (GCompareFunc)g_strcmp0);
> +    }
> +
> +    for (it = sorted_files, it2 = menu->priv->iso_names;
> +         (it != NULL) && (it2 != NULL);
>

nitpick those extra parentheses aren't needed


> +         it = it->next, it2 = it2->next) {
> +        if (g_strcmp0(it->data, it2->data) != 0) {
> +            break;
> +        }
> +    }
> +
> +    if ((it == NULL) && (it2 == NULL)) {
> +        /* sorted_files and menu->priv->files content was the same */
> +        g_list_free_full(sorted_files, (GDestroyNotify)g_free);
> +        return;
> +    }
> +
> +    g_list_free_full(menu->priv->iso_names, (GDestroyNotify)g_free);
> +    menu->priv->iso_names = sorted_files;
> +    g_object_notify(G_OBJECT(menu), "files");
> +}
> +
> +
> +static void cdroms_fetched_cb(GObject *source_object,
> +                              GAsyncResult *result,
> +                              gpointer user_data)
> +{
> +    GHashTable *cdroms;
> +    OvirtCollection *cdrom_collection = OVIRT_COLLECTION(source_object);
> +    OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);
> +    GList *cdrom_list;
> +    GError *error = NULL;
> +
> +    ovirt_collection_fetch_finish(cdrom_collection, result, &error);
> +    if (error != NULL) {
> +        g_debug("Failed to fetch cdrom collection: %s", error->message);
> +        g_clear_error(&error);
> +        return;
> +    }
> +
> +    cdroms = ovirt_collection_get_resources(cdrom_collection);
> +
> +    g_warn_if_fail(g_hash_table_size(cdroms) <= 1);
> +
> +    cdrom_list = g_hash_table_get_values(cdroms);
> +    if (cdrom_list != NULL) {
> +        OvirtCdrom *cdrom;
> +
> +        cdrom = OVIRT_CDROM(cdrom_list->data);
> +        if (menu->priv->cdrom != NULL) {
> +            g_object_unref(G_OBJECT(menu->priv->cdrom));
> +        }
> +
> +        menu->priv->cdrom = g_object_ref(G_OBJECT(cdrom));
> +        g_debug("Set VM cdrom to %p", menu->priv->cdrom);
> +    }
> +    g_list_free(cdrom_list);
> +
> +    if (menu->priv->cdrom != NULL) {
> +        ovirt_foreign_menu_next_async_step(menu, STATE_VM_CDROM);
> +    } else {
> +        g_debug("Could not find VM cdrom through oVirt REST API");
> +    }
> +}
> +
> +
> +static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu
> *menu)
> +{
> +    OvirtCollection *cdrom_collection;
> +
> +    cdrom_collection = ovirt_vm_get_cdroms(menu->priv->vm);
> +    ovirt_collection_fetch_async(cdrom_collection, menu->priv->proxy,
> NULL,
> +                                 cdroms_fetched_cb, menu);
> +    g_object_unref(G_OBJECT(cdrom_collection));
> +}
> +
> +
> +static void storage_domains_fetched_cb(GObject *source_object,
> +                                       GAsyncResult *result,
> +                                       gpointer user_data)
> +{
> +    GError *error = NULL;
> +    OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data);
> +    OvirtCollection *collection = OVIRT_COLLECTION(source_object);
> +    GList *storage_domains;
> +    GList *it;
> +
> +    ovirt_collection_fetch_finish(collection, result, &error);
> +    if (error != NULL) {
> +        g_debug("failed to fetch storage domains: %s", error->message);
> +        g_clear_error(&error);
> +        return;
> +    }
> +
> +    storage_domains =
> g_hash_table_get_values(ovirt_collection_get_resources(collection));
> +    for (it = storage_domains; it != NULL; it = it->next) {
> +        OvirtStorageDomain *domain;
> +        OvirtCollection *file_collection;
> +        char *name;
> +        int type;
> +
> +        domain = OVIRT_STORAGE_DOMAIN(it->data);
> +        g_object_get(G_OBJECT(domain), "type", &type, "name", &name,
> NULL);
> +        g_free(name);
> +
> +        if (type != OVIRT_STORAGE_DOMAIN_TYPE_ISO) {
> +            continue;
> +        }
> +
> +        file_collection = ovirt_storage_domain_get_files(domain);
> +        if (file_collection != NULL) {
> +            if (menu->priv->files) {
> +                g_object_unref(G_OBJECT(menu->priv->files));
> +            }
> +            menu->priv->files = g_object_ref(G_OBJECT(file_collection));
> +            g_debug("Set VM files to %p", menu->priv->files);
> +            break;
> +        }
> +    }
> +    g_list_free(storage_domains);
> +
> +    if (menu->priv->files != NULL) {
> +        ovirt_foreign_menu_next_async_step(menu, STATE_STORAGE_DOMAIN);
> +    } else {
> +        g_debug("Could not find iso file collection");
> +    }
> +}
> +
> +
> +static void
> ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu)
> +{
> +    OvirtCollection *collection;
> +
> +    g_debug("Start fetching oVirt REST collection");
> +    collection = ovirt_api_get_storage_domains(menu->priv->api);
> +    ovirt_collection_fetch_async(collection, menu->priv->proxy, NULL,
> +                                 storage_domains_fetched_cb, menu);
> +    g_object_unref(G_OBJECT(collection));
> +}
> +
> +
> +static void iso_list_fetched_cb(GObject *source_object,
> +                                GAsyncResult *result,
> +                                gpointer user_data)
> +{
> +    OvirtCollection *collection = OVIRT_COLLECTION(source_object);
> +    GList *files;
> +    GError *error = NULL;
> +
> +    ovirt_collection_fetch_finish(collection, result, &error);
> +    files =
> g_hash_table_get_values(ovirt_collection_get_resources(collection));
> +    if (error != NULL) {
> +        g_debug("failed to fetch files for ISO storage domain: %s",
> +                error->message);
> +        g_clear_error(&error);
> +        return;
> +    } else {
> +        ovirt_foreign_menu_set_files(OVIRT_FOREIGN_MENU(user_data),
> files);
> +    }
> +    g_list_free(files);
> +
> +    g_timeout_add_seconds(15, ovirt_foreign_menu_refresh_iso_list,
> user_data);
>

Depending on the load of the server, this could be quite heavy. Is this the
recommended value by ovirt folks?



> +}
> +
> +
> +static void ovirt_foreign_menu_fetch_iso_list_async(OvirtForeignMenu
> *menu)
> +{
> +    if (menu->priv->files == NULL) {
> +        return;
> +    }
> +
> +    ovirt_collection_fetch_async(menu->priv->files, menu->priv->proxy,
> +                                 NULL, iso_list_fetched_cb, menu);
> +}
> +
> +
> +static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data)
> +{
> +    OvirtForeignMenu *menu;
> +
> +    g_debug("Refreshing foreign menu iso list");
> +    menu = OVIRT_FOREIGN_MENU(user_data);
> +    ovirt_foreign_menu_fetch_iso_list_async(menu);
> +
> +    /* ovirt_foreign_menu_fetch_iso_list() will program a new call to that
> +     * function when it has finished fetching the iso list
> +     */
> +    return G_SOURCE_REMOVE;
> +}
> diff --git a/src/ovirt-foreign-menu.h b/src/ovirt-foreign-menu.h
> new file mode 100644
> index 0000000..ffadd46
> --- /dev/null
> +++ b/src/ovirt-foreign-menu.h
> @@ -0,0 +1,82 @@
> +/*
> + * Virt Viewer: A virtual machine console viewer
> + *
> + * Copyright (C) 2007-2013 Red Hat, Inc.
> + * Copyright (C) 2009-2012 Daniel P. Berrange
> + * Copyright (C) 2010 Marc-André Lureau
> + *
> + * 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: Daniel P. Berrange <berrange at redhat.com>
> + *         Christophe Fergeau <cfergeau at redhat.com>
> + */
> +#ifndef _OVIRT_FOREIGN_MENU_H
> +#define _OVIRT_FOREIGN_MENU_H
> +
> +#include <glib-object.h>
> +#include <govirt/govirt.h>
> +#include <gtk/gtk.h>
> +
> +
> +G_BEGIN_DECLS
> +
> +#define OVIRT_TYPE_FOREIGN_MENU ovirt_foreign_menu_get_type()
> +
> +#define OVIRT_FOREIGN_MENU(obj)                                        \
> +    (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVIRT_TYPE_FOREIGN_MENU,
> OvirtForeignMenu))
> +
> +#define OVIRT_FOREIGN_MENU_CLASS(klass)                                \
> +    (G_TYPE_CHECK_CLASS_CAST ((klass), OVIRT_TYPE_FOREIGN_MENU,
> OvirtForeignMenuClass))
> +
> +#define OVIRT_IS_FOREIGN_MENU(obj)                                \
> +    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVIRT_TYPE_FOREIGN_MENU))
> +
> +#define OVIRTIS_FOREIGN_MENU_CLASS(klass)                        \
> +    (G_TYPE_CHECK_CLASS_TYPE ((klass), OVIRT_TYPE_FOREIGN_MENU))
> +
> +#define OVIRT_FOREIGN_MENU_GET_CLASS(obj)                        \
> +    (G_TYPE_INSTANCE_GET_CLASS ((obj), OVIRT_TYPE_FOREIGN_MENU,
> OvirtForeignMenuClass))
> +
> +typedef struct _OvirtForeignMenu OvirtForeignMenu;
> +typedef struct _OvirtForeignMenuClass OvirtForeignMenuClass;
> +typedef struct _OvirtForeignMenuPrivate OvirtForeignMenuPrivate;
> +
> +struct _OvirtForeignMenu {
> +    GObject parent;
> +
> +    OvirtForeignMenuPrivate *priv;
> +};
> +
> +struct _OvirtForeignMenuClass {
> +    GObjectClass parent_class;
> +};
> +
> +GType ovirt_foreign_menu_get_type(void);
> +
> +OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy);
> +void ovirt_foreign_menu_start(OvirtForeignMenu *menu);
> +
> +GtkWidget *ovirt_foreign_menu_get_gtk_menu(OvirtForeignMenu
> *foreign_menu);
> +
> +G_END_DECLS
> +
> +#endif /* _OVIRT_FOREIGN_MENU_H */
> +/*
> + * Local variables:
> + *  c-indent-level: 4
> + *  c-basic-offset: 4
> + *  indent-tabs-mode: nil
> + * End:
> + */
> --
> 1.9.0
>
> _______________________________________________
> virt-tools-list mailing list
> virt-tools-list at redhat.com
> https://www.redhat.com/mailman/listinfo/virt-tools-list




-- 
Marc-André Lureau
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/virt-tools-list/attachments/20140417/68f853e9/attachment.htm>


More information about the virt-tools-list mailing list