[virt-tools-list] [PATCH virt-viewer v2 1/2] Add file transfer dialog

Fabiano Fidêncio fidencio at redhat.com
Tue May 3 08:54:22 UTC 2016


On Mon, May 2, 2016 at 12:13 PM, Fabiano Fidêncio <fabiano at fidencio.org> wrote:
> On Mon, May 2, 2016 at 12:10 PM, Fabiano Fidêncio <fabiano at fidencio.org> wrote:
>> On Fri, Apr 8, 2016 at 5:26 PM, Jonathon Jongsma <jjongsma at redhat.com> wrote:
>>> This dialog will show the progress of files being transferred from the
>>> client to the guest and allows the user to cancel ongoing file transfer
>>> tasks.  The user can cancel each transfer individually, or cancel all
>>> ongoing transfers at once.
>>> ---
>>>  src/Makefile.am                        |   2 +
>>>  src/virt-viewer-file-transfer-dialog.c | 213 +++++++++++++++++++++++++++++++++
>>
>> This file must be included in po/POTFILES.in
>>
>>>  src/virt-viewer-file-transfer-dialog.h |  61 ++++++++++
>>>  src/virt-viewer-session-spice.c        |  23 +++-
>>>  4 files changed, 298 insertions(+), 1 deletion(-)
>>>  create mode 100644 src/virt-viewer-file-transfer-dialog.c
>>>  create mode 100644 src/virt-viewer-file-transfer-dialog.h
>>>
>>> diff --git a/src/Makefile.am b/src/Makefile.am
>>> index ff487ba..115d73d 100644
>>> --- a/src/Makefile.am
>>> +++ b/src/Makefile.am
>>> @@ -91,6 +91,8 @@ libvirt_viewer_la_SOURCES += \
>>>         virt-viewer-session-spice.c \
>>>         virt-viewer-display-spice.h \
>>>         virt-viewer-display-spice.c \
>>> +       virt-viewer-file-transfer-dialog.h \
>>> +       virt-viewer-file-transfer-dialog.c \
>>>         $(NULL)
>>>  endif
>>>
>>> diff --git a/src/virt-viewer-file-transfer-dialog.c b/src/virt-viewer-file-transfer-dialog.c
>>> new file mode 100644
>>> index 0000000..bd85d82
>>> --- /dev/null
>>> +++ b/src/virt-viewer-file-transfer-dialog.c
>>> @@ -0,0 +1,213 @@
>>> +/*
>>> + * Virt Viewer: A virtual machine console viewer
>>> + *
>>> + * Copyright (C) 2016 Red Hat, Inc.
>>> + *
>>> + * 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
>>> + */
>>> +
>>> +#include "virt-viewer-file-transfer-dialog.h"
>>> +#include <glib/gi18n.h>
>
> And is also missing #include <config.h>
>
>>> +
>>> +G_DEFINE_TYPE(VirtViewerFileTransferDialog, virt_viewer_file_transfer_dialog, GTK_TYPE_DIALOG)
>>> +
>>> +#define FILE_TRANSFER_DIALOG_PRIVATE(o) \
>>> +        (G_TYPE_INSTANCE_GET_PRIVATE((o), VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG, VirtViewerFileTransferDialogPrivate))
>>> +
>>> +struct _VirtViewerFileTransferDialogPrivate
>>> +{
>>> +    /* GHashTable<SpiceFileTransferTask, widgets> */
>>> +    GHashTable *file_transfers;
>>> +};
>>> +
>>> +
>>> +static void
>>> +virt_viewer_file_transfer_dialog_dispose(GObject *object)
>>> +{
>>> +    VirtViewerFileTransferDialog *self = VIRT_VIEWER_FILE_TRANSFER_DIALOG(object);
>>> +
>>> +    g_clear_pointer(&self->priv->file_transfers, g_hash_table_unref);
>>> +
>>> +    G_OBJECT_CLASS(virt_viewer_file_transfer_dialog_parent_class)->dispose(object);
>>> +}
>>> +
>>> +static void
>>> +virt_viewer_file_transfer_dialog_class_init(VirtViewerFileTransferDialogClass *klass)
>>> +{
>>> +    GObjectClass *object_class = G_OBJECT_CLASS(klass);
>>> +
>>> +    g_type_class_add_private(klass, sizeof(VirtViewerFileTransferDialogPrivate));
>>> +
>>> +    object_class->dispose = virt_viewer_file_transfer_dialog_dispose;
>>> +}
>>> +
>>> +static void
>>> +dialog_response(GtkDialog *dialog,
>>> +                gint response_id,
>>> +                gpointer user_data G_GNUC_UNUSED)
>>> +{
>>> +    VirtViewerFileTransferDialog *self = VIRT_VIEWER_FILE_TRANSFER_DIALOG(dialog);
>>> +    GHashTableIter iter;
>>> +    gpointer key, value;
>>> +
>>> +    switch (response_id) {
>>> +        case GTK_RESPONSE_CANCEL:
>>> +            /* cancel all current tasks */
>>> +            g_hash_table_iter_init(&iter, self->priv->file_transfers);
>>> +
>>> +            while (g_hash_table_iter_next(&iter, &key, &value)) {
>>> +                spice_file_transfer_task_cancel(SPICE_FILE_TRANSFER_TASK(key));
>>> +            }
>>> +            break;
>>> +        case GTK_RESPONSE_DELETE_EVENT:
>>> +            /* silently ignore */
>>> +            break;
>>> +        default:
>>> +            g_warn_if_reached();
>>> +    }
>>> +}
>>> +
>>> +static void task_cancel_clicked(GtkButton *button G_GNUC_UNUSED,
>>> +                                gpointer user_data)
>>> +{
>>> +    SpiceFileTransferTask *task = user_data;
>>> +    spice_file_transfer_task_cancel(task);
>>> +}
>>> +
>>> +typedef struct {
>>> +    GtkWidget *vbox;
>>> +    GtkWidget *hbox;
>>> +    GtkWidget *progress;
>>> +    GtkWidget *label;
>>> +    GtkWidget *cancel;
>>> +} TaskWidgets;
>>> +
>>> +static TaskWidgets *task_widgets_new(SpiceFileTransferTask *task)
>>> +{
>>> +    TaskWidgets *w = g_new0(TaskWidgets, 1);
>>> +
>>> +    w->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
>>> +    w->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
>>> +    w->progress = gtk_progress_bar_new();
>>> +    w->label = gtk_label_new(spice_file_transfer_task_get_filename(task));
>>> +    w->cancel = gtk_button_new_from_icon_name("gtk-cancel", GTK_ICON_SIZE_SMALL_TOOLBAR);
>>> +    gtk_widget_set_hexpand(w->progress, TRUE);
>>> +    gtk_widget_set_valign(w->progress, GTK_ALIGN_CENTER);
>>> +    gtk_widget_set_hexpand(w->label, TRUE);
>>> +    gtk_widget_set_valign(w->label, GTK_ALIGN_END);
>>> +    gtk_widget_set_halign(w->label, GTK_ALIGN_START);
>>> +    gtk_widget_set_hexpand(w->cancel, FALSE);
>>> +    gtk_widget_set_valign(w->cancel, GTK_ALIGN_CENTER);
>>> +
>>> +    g_signal_connect(w->cancel, "clicked",
>>> +                     G_CALLBACK(task_cancel_clicked), task);
>>> +
>>> +    gtk_box_pack_start(GTK_BOX(w->hbox), w->progress, TRUE, TRUE, 0);
>>> +    gtk_box_pack_start(GTK_BOX(w->hbox), w->cancel, FALSE, TRUE, 0);
>>> +    gtk_box_pack_start(GTK_BOX(w->vbox), w->label, TRUE, TRUE, 0);
>>> +    gtk_box_pack_start(GTK_BOX(w->vbox), w->hbox, TRUE, TRUE, 0);
>>> +
>>> +    gtk_widget_show_all(w->vbox);
>>> +    return w;
>>> +}
>>> +
>>> +static gboolean delete_event(GtkWidget *widget,
>>> +                             GdkEvent *event G_GNUC_UNUSED,
>>> +                             gpointer user_data G_GNUC_UNUSED)
>>> +{
>>> +    /* don't allow window to be deleted, just process the response signal,
>>> +     * which may result in the window being hidden */
>>> +    gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL);
>>> +    return TRUE;
>>> +}
>>> +
>>> +static void
>>> +virt_viewer_file_transfer_dialog_init(VirtViewerFileTransferDialog *self)
>>> +{
>>> +    GtkBox *content = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(self)));
>>> +
>>> +    self->priv = FILE_TRANSFER_DIALOG_PRIVATE(self);
>>> +
>>> +    gtk_widget_set_size_request(GTK_WIDGET(content), 400, -1);
>>> +    gtk_container_set_border_width(GTK_CONTAINER(content), 12);
>>> +    self->priv->file_transfers = g_hash_table_new_full(g_direct_hash, g_direct_equal,
>>> +                                                       g_object_unref,
>>> +                                                       (GDestroyNotify)g_free);
>>> +    gtk_dialog_add_button(GTK_DIALOG(self), _("Cancel"), GTK_RESPONSE_CANCEL);
>>> +    gtk_dialog_set_default_response(GTK_DIALOG(self),
>>> +                                    GTK_RESPONSE_CANCEL);
>>> +    g_signal_connect(self, "response", G_CALLBACK(dialog_response), NULL);
>>> +    g_signal_connect(self, "delete-event", G_CALLBACK(delete_event), NULL);
>>> +}
>>> +
>>> +VirtViewerFileTransferDialog *
>>> +virt_viewer_file_transfer_dialog_new(GtkWindow *parent)
>>> +{
>>> +    return g_object_new(VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG,
>>> +                        "title", _("File Transfers"),
>>> +                        "transient-for", parent,
>>> +                        "resizable", FALSE,
>>> +                        NULL);
>>> +}
>>> +
>>> +static void task_progress_notify(GObject *object,
>>> +                                 GParamSpec *pspec G_GNUC_UNUSED,
>>> +                                 gpointer user_data)
>>> +{
>>> +    VirtViewerFileTransferDialog *self = VIRT_VIEWER_FILE_TRANSFER_DIALOG(user_data);
>>> +    SpiceFileTransferTask *task = SPICE_FILE_TRANSFER_TASK(object);
>>> +    TaskWidgets *w = g_hash_table_lookup(self->priv->file_transfers, task);
>>> +    g_return_if_fail(w);
>>> +
>>> +    double pct = spice_file_transfer_task_get_progress(task);
>>> +    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(w->progress), pct);
>>> +}
>>> +
>>> +static void task_finished(SpiceFileTransferTask *task,
>>> +                          GError *error,
>>> +                          gpointer user_data)
>>> +{
>>> +    VirtViewerFileTransferDialog *self = VIRT_VIEWER_FILE_TRANSFER_DIALOG(user_data);
>>> +    TaskWidgets *w = g_hash_table_lookup(self->priv->file_transfers, task);
>>> +
>>> +    if (error && !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
>>> +        g_warning("File transfer task %p failed: %s", task, error->message);
>>> +
>>> +    g_return_if_fail(w);
>>> +
>>> +    gtk_widget_destroy(w->vbox);
>>> +
>>> +    g_hash_table_remove(self->priv->file_transfers, task);
>>> +
>>> +    /* if this is the last transfer, close the dialog */
>>> +    if (!g_hash_table_size(self->priv->file_transfers))
>>> +        gtk_widget_hide(GTK_WIDGET(self));
>>> +}
>>> +
>>> +void virt_viewer_file_transfer_dialog_add_task(VirtViewerFileTransferDialog *self,
>>> +                                               SpiceFileTransferTask *task)
>>> +{
>>> +    GtkBox *content = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(self)));
>>> +    TaskWidgets *w = task_widgets_new(task);
>>> +
>>> +    gtk_box_pack_start(content,
>>> +                       w->vbox,
>>> +                       TRUE, TRUE, 12);
>>> +    g_hash_table_insert(self->priv->file_transfers, g_object_ref(task), w);
>>> +    g_signal_connect(task, "notify::progress", G_CALLBACK(task_progress_notify), self);
>>> +    g_signal_connect(task, "finished", G_CALLBACK(task_finished), self);
>>> +
>>> +    gtk_widget_show(GTK_WIDGET(self));
>>> +}
>>> diff --git a/src/virt-viewer-file-transfer-dialog.h b/src/virt-viewer-file-transfer-dialog.h
>>> new file mode 100644
>>> index 0000000..8805b14
>>> --- /dev/null
>>> +++ b/src/virt-viewer-file-transfer-dialog.h
>>> @@ -0,0 +1,61 @@
>>> +/*
>>> + * Virt Viewer: A virtual machine console viewer
>>> + *
>>> + * Copyright (C) 2016 Red Hat, Inc.
>>> + *
>>> + * 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
>>> + */
>>> +
>>> +#ifndef __VIRT_VIEWER_FILE_TRANSFER_DIALOG_H__
>>> +#define __VIRT_VIEWER_FILE_TRANSFER_DIALOG_H__
>>> +
>>> +#include <gtk/gtk.h>
>>> +#include <spice-client.h>
>>> +
>>> +G_BEGIN_DECLS
>>> +
>>> +#define VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG virt_viewer_file_transfer_dialog_get_type()
>>> +
>>> +#define VIRT_VIEWER_FILE_TRANSFER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG, VirtViewerFileTransferDialog))
>>> +#define VIRT_VIEWER_FILE_TRANSFER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG, VirtViewerFileTransferDialogClass))
>>> +#define VIRT_VIEWER_IS_FILE_TRANSFER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG))
>>> +#define VIRT_VIEWER_IS_FILE_TRANSFER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG))
>>> +#define VIRT_VIEWER_FILE_TRANSFER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), VIRT_VIEWER_TYPE_FILE_TRANSFER_DIALOG, VirtViewerFileTransferDialogClass))
>>> +
>>> +typedef struct _VirtViewerFileTransferDialog VirtViewerFileTransferDialog;
>>> +typedef struct _VirtViewerFileTransferDialogClass VirtViewerFileTransferDialogClass;
>>> +typedef struct _VirtViewerFileTransferDialogPrivate VirtViewerFileTransferDialogPrivate;
>>> +
>>> +struct _VirtViewerFileTransferDialog
>>> +{
>>> +    GtkDialog parent;
>>> +
>>> +    VirtViewerFileTransferDialogPrivate *priv;
>>> +};
>>> +
>>> +struct _VirtViewerFileTransferDialogClass
>>> +{
>>> +    GtkDialogClass parent_class;
>>> +};
>>> +
>>> +GType virt_viewer_file_transfer_dialog_get_type(void) G_GNUC_CONST;
>>> +
>>> +VirtViewerFileTransferDialog *virt_viewer_file_transfer_dialog_new(GtkWindow *parent);
>>> +void virt_viewer_file_transfer_dialog_add_task(VirtViewerFileTransferDialog *self,
>>> +                                               SpiceFileTransferTask *task);
>>> +
>>> +G_END_DECLS
>>> +
>>> +#endif /* __VIRT_VIEWER_FILE_TRANSFER_DIALOG_H__ */
>>> diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
>>> index f7f2dc9..5f05df7 100644
>>> --- a/src/virt-viewer-session-spice.c
>>> +++ b/src/virt-viewer-session-spice.c
>>> @@ -30,12 +30,12 @@
>>>
>>>  #include <usb-device-widget.h>
>>>  #include "virt-viewer-file.h"
>>> +#include "virt-viewer-file-transfer-dialog.h"
>>>  #include "virt-viewer-util.h"
>>>  #include "virt-viewer-session-spice.h"
>>>  #include "virt-viewer-display-spice.h"
>>>  #include "virt-viewer-auth.h"
>>>
>>> -
>>>  G_DEFINE_TYPE (VirtViewerSessionSpice, virt_viewer_session_spice, VIRT_VIEWER_TYPE_SESSION)
>>>
>>>
>>> @@ -50,6 +50,8 @@ struct _VirtViewerSessionSpicePrivate {
>>>      gboolean has_sw_smartcard_reader;
>>>      guint pass_try;
>>>      gboolean did_auto_conf;
>>> +    VirtViewerFileTransferDialog *file_transfer_dialog;
>>> +
>>>  };
>>>
>>>  #define VIRT_VIEWER_SESSION_SPICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), VIRT_VIEWER_TYPE_SESSION_SPICE, VirtViewerSessionSpicePrivate))
>>> @@ -147,6 +149,10 @@ virt_viewer_session_spice_dispose(GObject *obj)
>>>      spice->priv->audio = NULL;
>>>
>>>      g_clear_object(&spice->priv->main_window);
>>> +    if (spice->priv->file_transfer_dialog) {
>>> +        gtk_widget_destroy(GTK_WIDGET(spice->priv->file_transfer_dialog));
>>> +        spice->priv->file_transfer_dialog = NULL;
>>> +    }
>>>
>>>      G_OBJECT_CLASS(virt_viewer_session_spice_parent_class)->dispose(obj);
>>>  }
>>> @@ -224,6 +230,9 @@ virt_viewer_session_spice_constructed(GObject *obj)
>>>                                        G_CALLBACK(update_share_folder), self,
>>>                                        G_CONNECT_SWAPPED);
>>>
>>> +    self->priv->file_transfer_dialog =
>>> +        virt_viewer_file_transfer_dialog_new(self->priv->main_window);
>>> +
>>>      G_OBJECT_CLASS(virt_viewer_session_spice_parent_class)->constructed(obj);
>>>  }
>>>
>>> @@ -922,6 +931,16 @@ virt_viewer_session_spice_display_monitors(SpiceChannel *channel,
>>>  }
>>>
>>>  static void
>>> +on_new_file_transfer(SpiceMainChannel *channel G_GNUC_UNUSED,
>>> +                     SpiceFileTransferTask *task,
>>> +                     gpointer user_data)
>>> +{
>>> +    VirtViewerSessionSpice *self = VIRT_VIEWER_SESSION_SPICE(user_data);
>>> +    virt_viewer_file_transfer_dialog_add_task(self->priv->file_transfer_dialog,
>>> +                                              task);
>>> +}
>>> +
>>> +static void
>>>  virt_viewer_session_spice_channel_new(SpiceSession *s,
>>>                                        SpiceChannel *channel,
>>>                                        VirtViewerSession *session)
>>> @@ -953,6 +972,8 @@ virt_viewer_session_spice_channel_new(SpiceSession *s,
>>>
>>>          virt_viewer_signal_connect_object(channel, "notify::agent-connected",
>>>                                            G_CALLBACK(agent_connected_changed), self, 0);
>>> +        virt_viewer_signal_connect_object(channel, "new-file-transfer",
>>> +                                          G_CALLBACK(on_new_file_transfer), self, 0);
>>>      }
>>>
>>>      if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
>>> --
>>> 2.4.11
>>>
>>> _______________________________________________
>>> virt-tools-list mailing list
>>> virt-tools-list at redhat.com
>>> https://www.redhat.com/mailman/listinfo/virt-tools-list
>>
>>
>> ACK!
>> --
>> Fabiano Fidêncio
>
>
>
> --
> Fabiano Fidêncio
>
> _______________________________________________
> virt-tools-list mailing list
> virt-tools-list at redhat.com
> https://www.redhat.com/mailman/listinfo/virt-tools-list

I've done the necessary changes and pushed both patches.
Thanks!




More information about the virt-tools-list mailing list