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 | 3 +- src/Makefile.am | 4 + src/ovirt-foreign-menu.c | 686 +++++++++++++++++++++++++++++++++++++++++++++++ src/ovirt-foreign-menu.h | 82 ++++++ 4 files changed, 774 insertions(+), 1 deletion(-) 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 4a6dc23..5f7786d 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ GTK_VNC1_REQUIRED="0.3.8" GTK_VNC2_REQUIRED="0.4.0" SPICE_GTK_REQUIRED="0.22" SPICE_PROTOCOL_REQUIRED="0.10.1" -GOVIRT_REQUIRED="0.3.0" +GOVIRT_REQUIRED="0.3.1" AC_SUBST([GLIB2_REQUIRED]) AC_SUBST([LIBXML2_REQUIRED]) @@ -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..0453ca1 --- /dev/null +++ b/src/ovirt-foreign-menu.c @@ -0,0 +1,686 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2014 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@xxxxxxxxxx> + * Christope Fergeau <cfergeau@xxxxxxxxxx> + */ + +#include <config.h> + +#include "ovirt-foreign-menu.h" +#include "virt-glib-compat.h" +#include "virt-viewer-util.h" + +typedef enum { + STATE_0, + STATE_STORAGE_DOMAIN, + STATE_VM_CDROM, + STATE_CDROM_FILE, + 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 void ovirt_foreign_menu_refresh_cdrom_file_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; + + /* The next 2 members are used when changing the ISO image shown in + * a VM */ + /* Name of the ISO which is currently used by the VM OvirtCdrom */ + char *current_iso_name; + /* Name of the ISO we are trying to insert in the VM OvirtCdrom */ + char *next_iso_name; + + 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_FILE, + PROP_FILES, +}; + + +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(foreign_menu->priv->cdrom, "file", &name, NULL); + + return name; +} + + +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_FILE: + g_value_take_string(value, + ovirt_foreign_menu_get_current_iso_name(self)); + break; + case PROP_FILES: + g_value_set_pointer(value, priv->iso_names); + break; + 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); + } + 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); + + 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_free(self->priv->current_iso_name); + self->priv->current_iso_name = NULL; + + g_free(self->priv->next_iso_name); + self->priv->next_iso_name = 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_FILE, + g_param_spec_string("file", + "File", + "Name of the image currently inserted in the virtual CDROM", + NULL, + G_PARAM_READABLE | + 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) +{ + g_return_if_fail(current_state >= STATE_0); + g_return_if_fail(current_state < STATE_ISOS); + + current_state++; + + 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_CDROM_FILE) { + ovirt_foreign_menu_refresh_cdrom_file_async(menu); + } + + 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); +} + + +static void +ovirt_foreign_menu_activate_item_cb(GtkMenuItem *menuitem, gpointer user_data); + + +static void +menu_item_set_active_no_signal(GtkMenuItem *menuitem, + gboolean active, + GCallback callback, + gpointer user_data) +{ + g_signal_handlers_block_by_func(menuitem, callback, user_data); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), active); + g_signal_handlers_unblock_by_func(menuitem, callback, user_data); +} + + +static void updated_cdrom_cb(GObject *source_object, + GAsyncResult *result, + G_GNUC_UNUSED gpointer user_data) +{ + GError *error = NULL; + OvirtForeignMenu *foreign_menu; + gboolean updated; + + foreign_menu = OVIRT_FOREIGN_MENU(user_data); + updated = ovirt_cdrom_update_finish(OVIRT_CDROM(source_object), + result, &error); + g_debug("Finished updating cdrom content"); + if (updated) { + g_free(foreign_menu->priv->current_iso_name); + foreign_menu->priv->current_iso_name = foreign_menu->priv->next_iso_name; + foreign_menu->priv->next_iso_name = NULL; + g_object_notify(G_OBJECT(foreign_menu), "file"); + } else { + /* Reset old state back as we were not successful in switching to + * the new ISO */ + const char *current_file = foreign_menu->priv->current_iso_name; + + if (error != NULL) { + g_warning("failed to update cdrom resource: %s", error->message); + g_clear_error(&error); + } + g_debug("setting OvirtCdrom:file back to '%s'", + current_file?current_file:NULL); + g_object_set(foreign_menu->priv->cdrom, "file", current_file, NULL); + } + g_free(foreign_menu->priv->next_iso_name); + foreign_menu->priv->next_iso_name = NULL; +} + + +static void +ovirt_foreign_menu_activate_item_cb(GtkMenuItem *menuitem, gpointer user_data) +{ + OvirtForeignMenu *foreign_menu; + const char *iso_name; + gboolean checked; + + checked = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)); + foreign_menu = OVIRT_FOREIGN_MENU(user_data); + g_return_if_fail(foreign_menu->priv->cdrom != NULL); + g_return_if_fail(foreign_menu->priv->next_iso_name == NULL); + + g_debug("'%s' clicked", gtk_menu_item_get_label(menuitem)); + + /* We only want to move the check mark for the currently selected ISO + * when ovirt_cdrom_update_async() is successful, so for now we move + * the check mark back to where it was before + */ + menu_item_set_active_no_signal(menuitem, !checked, + (GCallback)ovirt_foreign_menu_activate_item_cb, + foreign_menu); + + if (checked) { + iso_name = gtk_menu_item_get_label(menuitem); + g_debug("Updating VM cdrom image to '%s'", iso_name); + foreign_menu->priv->next_iso_name = g_strdup(iso_name); + } else { + g_debug("Removing current cdrom image"); + iso_name = NULL; + foreign_menu->priv->next_iso_name = NULL; + /* FIXME: No idea how to remove a CDRom from a VM through ovirt REST + * API for now, so return early. + */ + return; + } + g_object_set(foreign_menu->priv->cdrom, + "file", iso_name, + NULL); + ovirt_cdrom_update_async(foreign_menu->priv->cdrom, TRUE, + foreign_menu->priv->proxy, NULL, + updated_cdrom_cb, foreign_menu); +} + + +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); + 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) { + g_warn_if_fail(g_strcmp0(current_iso, foreign_menu->priv->current_iso_name) == 0); + 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(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); + 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 cdrom_file_refreshed_cb(GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + OvirtResource *cdrom = OVIRT_RESOURCE(source_object); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data); + GError *error = NULL; + + ovirt_resource_refresh_finish(cdrom, result, &error); + if (error != NULL) { + g_warning("failed to refresh cdrom content: %s", error->message); + g_clear_error(&error); + return; + } + + /* Content of OvirtCdrom is now current */ + g_free(menu->priv->current_iso_name); + if (menu->priv->cdrom != NULL) { + g_object_get(G_OBJECT(menu->priv->cdrom), + "file", &menu->priv->current_iso_name, + NULL); + } else { + menu->priv->current_iso_name = NULL; + } + g_object_notify(G_OBJECT(menu), "file"); + if (menu->priv->cdrom != NULL) { + ovirt_foreign_menu_next_async_step(menu, STATE_CDROM_FILE); + } else { + g_debug("Could not find VM cdrom through oVirt REST API"); + } +} + + +static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu) +{ + g_return_if_fail(OVIRT_IS_RESOURCE(menu->priv->cdrom)); + + ovirt_resource_refresh_async(OVIRT_RESOURCE(menu->priv->cdrom), + menu->priv->proxy, NULL, + cdrom_file_refreshed_cb, menu); +} + + +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); + GHashTableIter iter; + OvirtCdrom *cdrom; + GError *error = NULL; + + ovirt_collection_fetch_finish(cdrom_collection, result, &error); + if (error != NULL) { + g_warning("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); + + g_hash_table_iter_init(&iter, cdroms); + /* Set CDROM drive. If we have multiple ones, only the first + * one will be kept, but currently oVirt only adds one CDROM + * device per-VM + */ + if (g_hash_table_iter_next(&iter, NULL, (gpointer *)&cdrom)) { + 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); + } + + 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); +} + + +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); + GHashTableIter iter; + OvirtStorageDomain *domain; + + ovirt_collection_fetch_finish(collection, result, &error); + if (error != NULL) { + g_warning("failed to fetch storage domains: %s", error->message); + g_clear_error(&error); + return; + } + + g_hash_table_iter_init(&iter, ovirt_collection_get_resources(collection)); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&domain)) { + OvirtCollection *file_collection; + int type; + + g_object_get(domain, "type", &type, NULL); + 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; + } + } + + 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); +} + + +static void iso_list_fetched_cb(GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + OvirtCollection *collection = OVIRT_COLLECTION(source_object); + GError *error = NULL; + GList *files; + + ovirt_collection_fetch_finish(collection, result, &error); + if (error != NULL) { + g_warning("failed to fetch files for ISO storage domain: %s", + error->message); + g_clear_error(&error); + return; + } + + files = g_hash_table_get_values(ovirt_collection_get_resources(collection)); + 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); +} + + +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_async() will schedule a new call to + * that function through iso_list_fetched_cb() 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..7d28f0b --- /dev/null +++ b/src/ovirt-foreign-menu.h @@ -0,0 +1,82 @@ +/* + * Virt Viewer: A virtual machine console viewer + * + * Copyright (C) 2007-2014 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@xxxxxxxxxx> + * Christophe Fergeau <cfergeau@xxxxxxxxxx> + */ +#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.3 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list