[virt-tools-list] [PATCH virt-viewer 1/3] Add a dialog showing details of the current guest
Christophe Fergeau
cfergeau at redhat.com
Mon Jun 23 20:52:53 UTC 2014
On Thu, Jun 12, 2014 at 04:07:02PM -0500, Jonathon Jongsma wrote:
> This allows the user to obtain the GUID and vm name of the currently-connected
> guest. Obviously, this only works with spice. In the future, it will allow them
> to set guest-specific configuration options (using a GUID as a key)
> ---
> src/Makefile.am | 1 +
> src/virt-viewer-app.c | 25 ++++++++
> src/virt-viewer-app.h | 1 -
> src/virt-viewer-guest-details.xml | 120 ++++++++++++++++++++++++++++++++++++++
> src/virt-viewer-session-spice.c | 16 ++++-
> src/virt-viewer-window.c | 40 +++++++++++++
> src/virt-viewer.c | 2 +-
> src/virt-viewer.xml | 10 ++++
> 8 files changed, 212 insertions(+), 3 deletions(-)
> create mode 100644 src/virt-viewer-guest-details.xml
>
> diff --git a/src/Makefile.am b/src/Makefile.am
> index b3a9637..d4163c8 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -8,6 +8,7 @@ builderxml_DATA = \
> virt-viewer.xml \
> virt-viewer-about.xml \
> virt-viewer-auth.xml \
> + virt-viewer-guest-details.xml \
> $(NULL)
>
> EXTRA_DIST = \
> diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c
> index 7dbb7fc..f12cb0d 100644
> --- a/src/virt-viewer-app.c
> +++ b/src/virt-viewer-app.c
> @@ -139,6 +139,7 @@ struct _VirtViewerAppPrivate {
> gchar *guest_name;
> gboolean grabbed;
> char *title;
> + char *uuid;
>
> gint focused;
> GKeyFile *config;
> @@ -168,6 +169,7 @@ enum {
> PROP_HAS_FOCUS,
> PROP_KIOSK,
> PROP_QUIT_ON_DISCONNECT,
> + PROP_UUID,
> };
>
> enum {
> @@ -305,6 +307,7 @@ app_window_try_fullscreen(VirtViewerApp *self G_GNUC_UNUSED,
> }
>
>
> +static
> void virt_viewer_app_set_uuid_string(VirtViewerApp* self, const gchar* uuid_string)
> {
> GArray* mapping = NULL;
> @@ -315,6 +318,8 @@ void virt_viewer_app_set_uuid_string(VirtViewerApp* self, const gchar* uuid_stri
>
> g_debug("%s: UUID changed to %s", G_STRFUNC, uuid_string);
>
> + g_free(self->priv->uuid);
> + self->priv->uuid = g_strdup(uuid_string);
> displays = g_key_file_get_integer_list(self->priv->config,
> uuid_string, "monitor-mapping", &ndisplays, &error);
> if (error) {
> @@ -1458,6 +1463,10 @@ virt_viewer_app_get_property (GObject *object, guint property_id,
> g_value_set_boolean(value, priv->quit_on_disconnect);
> break;
>
> + case PROP_UUID:
> + g_value_set_string(value, priv->uuid);
> + break;
> +
> default:
> G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
> }
> @@ -1508,6 +1517,10 @@ virt_viewer_app_set_property (GObject *object, guint property_id,
> priv->quit_on_disconnect = g_value_get_boolean(value);
> break;
>
> + case PROP_UUID:
> + virt_viewer_app_set_uuid_string(self, g_value_get_string(value));
> + break;
> +
> default:
> G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
> }
> @@ -1540,6 +1553,8 @@ virt_viewer_app_dispose (GObject *object)
> priv->guri = NULL;
> g_free(priv->title);
> priv->title = NULL;
> + g_free(priv->uuid);
> + priv->uuid = NULL;
> g_free(priv->config_file);
> priv->config_file = NULL;
> g_clear_pointer(&priv->config, g_key_file_free);
> @@ -1814,6 +1829,16 @@ virt_viewer_app_class_init (VirtViewerAppClass *klass)
> G_PARAM_READWRITE |
> G_PARAM_STATIC_STRINGS));
>
> + g_object_class_install_property(object_class,
> + PROP_UUID,
> + g_param_spec_string("uuid",
> + "uuid",
> + "uuid",
> + "",
The default value here is "" (will get back to this below in this email)
(I forgot if default values are set on properties which are not
CONSTRUCT properties though)
> + G_PARAM_READABLE |
> + G_PARAM_WRITABLE |
> + G_PARAM_STATIC_STRINGS));
> +
> signals[SIGNAL_WINDOW_ADDED] =
> g_signal_new("window-added",
> G_OBJECT_CLASS_TYPE(object_class),
> diff --git a/src/virt-viewer-app.h b/src/virt-viewer-app.h
> index 6a53992..ba8cf71 100644
> --- a/src/virt-viewer-app.h
> +++ b/src/virt-viewer-app.h
> @@ -100,7 +100,6 @@ const GOptionEntry* virt_viewer_app_get_options(void);
> void virt_viewer_app_clear_hotkeys(VirtViewerApp *app);
> gint virt_viewer_app_get_n_initial_displays(VirtViewerApp* self);
> gint virt_viewer_app_get_initial_monitor_for_display(VirtViewerApp* self, gint display);
> -void virt_viewer_app_set_uuid_string(VirtViewerApp* self, const gchar* uuid_string);
> void virt_viewer_app_set_enable_accel(VirtViewerApp *app, gboolean enable);
>
> G_END_DECLS
> diff --git a/src/virt-viewer-guest-details.xml b/src/virt-viewer-guest-details.xml
> new file mode 100644
> index 0000000..7f00567
> --- /dev/null
> +++ b/src/virt-viewer-guest-details.xml
> @@ -0,0 +1,120 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<!-- Generated with glade 3.16.0 on Thu Jan 16 16:13:38 2014 -->
> +<interface>
> + <!-- interface-requires gtk+ 3.0 -->
> + <object class="GtkDialog" id="guestdetailsdialog">
> + <property name="can_focus">False</property>
> + <property name="title" translatable="yes">Guest Details</property>
> + <property name="resizable">True</property>
> + <property name="default_width">400</property>
> + <property name="type_hint">dialog</property>
> + <signal name="response" handler="virt_viewer_window_guest_details_response" swapped="no"/>
> + <child internal-child="vbox">
> + <object class="GtkBox" id="dialog-vbox2">
> + <property name="can_focus">False</property>
> + <property name="orientation">vertical</property>
> + <property name="spacing">2</property>
> + <child internal-child="action_area">
> + <object class="GtkButtonBox" id="dialog-action_area2">
> + <property name="can_focus">False</property>
> + <property name="layout_style">end</property>
> + <child>
> + <object class="GtkButton" id="button1">
> + <property name="label">gtk-close</property>
> + <property name="visible">True</property>
> + <property name="can_focus">True</property>
> + <property name="receives_default">True</property>
> + <property name="use_stock">True</property>
> + </object>
> + <packing>
> + <property name="expand">False</property>
> + <property name="fill">True</property>
> + <property name="position">0</property>
> + </packing>
> + </child>
> + </object>
> + <packing>
> + <property name="expand">False</property>
> + <property name="fill">True</property>
> + <property name="pack_type">end</property>
> + <property name="position">0</property>
> + </packing>
> + </child>
> + <child>
> + <object class="GtkTable" id="grid1">
> + <property name="visible">True</property>
> + <property name="can_focus">False</property>
> + <property name="border_width">6</property>
> + <property name="row_spacing">6</property>
> + <property name="column_spacing">6</property>
> + <property name="n_rows">2</property>
> + <child>
> + <object class="GtkLabel" id="label1">
> + <property name="visible">True</property>
> + <property name="can_focus">False</property>
> + <property name="xalign">1</property>
> + <property name="label" translatable="yes">Name:</property>
> + </object>
> + <packing>
> + <property name="x_options">GTK_SHRINK | GTK_FILL</property>
> + <property name="y_options">GTK_FILL</property>
> + </packing>
> + </child>
> + <child>
> + <object class="GtkLabel" id="label2">
> + <property name="visible">True</property>
> + <property name="can_focus">False</property>
> + <property name="xalign">1</property>
> + <property name="label" translatable="yes">GUID:</property>
> + </object>
> + <packing>
> + <property name="top_attach">1</property>
> + <property name="bottom_attach">2</property>
> + <property name="x_options">GTK_SHRINK | GTK_FILL</property>
> + <property name="y_options">GTK_FILL</property>
> + </packing>
> + </child>
> + <child>
> + <object class="GtkLabel" id="namevaluelabel">
> + <property name="visible">True</property>
> + <property name="can_focus">False</property>
> + <property name="xalign">0</property>
> + <property name="label" translatable="yes">label</property>
> + <property name="selectable">True</property>
> + </object>
> + <packing>
> + <property name="left_attach">1</property>
> + <property name="right_attach">2</property>
> + <property name="y_options">GTK_FILL</property>
> + </packing>
> + </child>
> + <child>
> + <object class="GtkLabel" id="guidvaluelabel">
> + <property name="visible">True</property>
> + <property name="can_focus">False</property>
> + <property name="xalign">0</property>
> + <property name="label" translatable="yes">label</property>
> + <property name="selectable">True</property>
> + </object>
> + <packing>
> + <property name="left_attach">1</property>
> + <property name="right_attach">2</property>
> + <property name="top_attach">1</property>
> + <property name="bottom_attach">2</property>
> + <property name="y_options">GTK_FILL</property>
> + </packing>
> + </child>
> + </object>
> + <packing>
> + <property name="expand">False</property>
> + <property name="fill">True</property>
> + <property name="position">1</property>
> + </packing>
> + </child>
> + </object>
> + </child>
> + <action-widgets>
> + <action-widget response="-7">button1</action-widget>
> + </action-widgets>
> + </object>
> +</interface>
> diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
> index 1820784..df7da34 100644
> --- a/src/virt-viewer-session-spice.c
> +++ b/src/virt-viewer-session-spice.c
> @@ -876,7 +876,7 @@ uuid_changed(GObject *gobject G_GNUC_UNUSED,
>
> if (!uuid_empty) {
> gchar* uuid_str = spice_uuid_to_string(uuid);
> - virt_viewer_app_set_uuid_string(app, uuid_str);
> + g_object_set(app, "uuid", uuid_str, NULL);
> g_free(uuid_str);
> }
> }
> @@ -884,6 +884,19 @@ uuid_changed(GObject *gobject G_GNUC_UNUSED,
> virt_viewer_session_spice_fullscreen_auto_conf(self);
> }
>
> +static void
> +name_changed(GObject *gobject G_GNUC_UNUSED,
> + GParamSpec *pspec G_GNUC_UNUSED,
> + VirtViewerSessionSpice *self)
> +{
> + gchar* name = NULL;
> + VirtViewerApp* app = virt_viewer_session_get_app(VIRT_VIEWER_SESSION(self));
> +
> + g_object_get(self->priv->session, "name", &name, NULL);
> +
> + g_object_set(app, "guest-name", name, NULL);
Missing g_free(name)
> +}
> +
> VirtViewerSession *
> virt_viewer_session_spice_new(VirtViewerApp *app, GtkWindow *main_window)
> {
> @@ -899,6 +912,7 @@ virt_viewer_session_spice_new(VirtViewerApp *app, GtkWindow *main_window)
> /* notify::uuid is guaranteed to be emitted during connection startup even
> * if the server is too old to support sending uuid */
> g_signal_connect(self->priv->session, "notify::uuid", G_CALLBACK(uuid_changed), self);
> + g_signal_connect(self->priv->session, "notify::name", G_CALLBACK(name_changed), self);
>
> return VIRT_VIEWER_SESSION(self);
> }
> diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c
> index 22326e8..bb23efe 100644
> --- a/src/virt-viewer-window.c
> +++ b/src/virt-viewer-window.c
> @@ -49,6 +49,7 @@ void virt_viewer_window_menu_view_zoom_reset(GtkWidget *menu, VirtViewerWindow *
> gboolean virt_viewer_window_delete(GtkWidget *src, void *dummy, VirtViewerWindow *self);
> void virt_viewer_window_menu_file_quit(GtkWidget *src, VirtViewerWindow *self);
> void virt_viewer_window_menu_help_about(GtkWidget *menu, VirtViewerWindow *self);
> +void virt_viewer_window_menu_help_guest_details(GtkWidget *menu, VirtViewerWindow *self);
> void virt_viewer_window_menu_view_fullscreen(GtkWidget *menu, VirtViewerWindow *self);
> void virt_viewer_window_menu_send(GtkWidget *menu, VirtViewerWindow *self);
> void virt_viewer_window_menu_file_screenshot(GtkWidget *menu, VirtViewerWindow *self);
> @@ -1012,6 +1013,45 @@ virt_viewer_window_menu_view_release_cursor(GtkWidget *menu G_GNUC_UNUSED,
> }
>
> G_MODULE_EXPORT void
> +virt_viewer_window_menu_help_guest_details(GtkWidget *menu, VirtViewerWindow *self)
> +{
> + GtkBuilder *ui = virt_viewer_util_load_ui("virt-viewer-guest-details.xml");
> + char* name = NULL;
> + char* uuid = NULL;
> +
> + GtkWidget *dialog = GTK_WIDGET(gtk_builder_get_object(ui, "guestdetailsdialog"));
Missing error check on virt_viewer_util_load_ui()
> + GtkWidget *namelabel = GTK_WIDGET(gtk_builder_get_object(ui, "namevaluelabel"));
> + GtkWidget *guidlabel = GTK_WIDGET(gtk_builder_get_object(ui, "guidvaluelabel"));
> +
I'd probably add some g_return_if_fail) on namelabel/guidlabel being
!NULL
> + g_object_get(self->priv->app, "guest-name", &name, "uuid", &uuid, NULL);
> +
> + if (!name)
> + name = g_strdup(_("Unknown"));
> + if (!uuid)
> + uuid = g_strdup(_("Unknown"));
The default value was "" but here we check for NULL, probably not an
actual/a big issue
> + gtk_label_set_text(namelabel, name);
> + gtk_label_set_text(guidlabel, uuid);
> + g_free(name);
> + g_free(uuid);
> +
> + gtk_window_set_transient_for(GTK_WINDOW(dialog),
> + GTK_WINDOW(self->priv->window));
> +
> + gtk_builder_connect_signals(ui, self);
> +
> + gtk_widget_show_all(dialog);
> +
> + g_object_unref(G_OBJECT(ui));
> +}
> +
> +G_MODULE_EXPORT void
> +virt_viewer_window_guest_details_response(GtkDialog *dialog, gint response_id, gpointer user_data)
> +{
> + if (response_id == GTK_RESPONSE_CLOSE)
> + gtk_widget_hide(GTK_WIDGET(dialog));
You hide the dialog here, but it's recreated every time the user clicks
on the 'guest details' menu entry.
> +}
> +
> +G_MODULE_EXPORT void
> virt_viewer_window_menu_help_about(GtkWidget *menu G_GNUC_UNUSED,
> VirtViewerWindow *self)
> {
> diff --git a/src/virt-viewer.c b/src/virt-viewer.c
> index 8a1d8c5..c03503e 100644
> --- a/src/virt-viewer.c
> +++ b/src/virt-viewer.c
> @@ -560,7 +560,7 @@ virt_viewer_initial_connect(VirtViewerApp *app, GError **error)
> if (virDomainGetUUIDString(dom, uuid_string) < 0) {
> g_debug("Couldn't get uuid from libvirt");
> } else {
> - virt_viewer_app_set_uuid_string(app, uuid_string);
> + g_object_set(app, "uuid", uuid_string, NULL);
> }
>
> virt_viewer_app_show_status(app, _("Checking guest domain status"));
> diff --git a/src/virt-viewer.xml b/src/virt-viewer.xml
> index 8a3d3c0..6764910 100644
> --- a/src/virt-viewer.xml
> +++ b/src/virt-viewer.xml
> @@ -215,6 +215,16 @@
> <property name="visible">True</property>
> <property name="can_focus">False</property>
> <child>
> + <object class="GtkMenuItem" id="menu-help-guest-details">
> + <property name="visible">True</property>
> + <property name="can_focus">False</property>
> + <property name="use_action_appearance">False</property>
> + <property name="label" translatable="yes">Guest Details</property>
No mnemonic for the entry?
Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/virt-tools-list/attachments/20140623/8c24c775/attachment.sig>
More information about the virt-tools-list
mailing list