> > From: Alexander Nezhinsky <anezhins@xxxxxxxxxx> > > The empty CD entry is a placeholder and appears every time the widget is > created. > When it is toggled, a file chooser dialog is popped up. If a file or device > is > selected, a new CD device is created. The new CD device is auto-connected. > > This device is communicated to the widget through the 'device-added' signal. > The list entry responsible for the new device corresponds to the entity > provided by usb-device-manager. The empty CD entry is automatically moved to > the top of the list. > > Signed-off-by: Alexander Nezhinsky <anezhins@xxxxxxxxxx> > --- > src/usb-device-widget.c | 78 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 78 insertions(+) > > diff --git a/src/usb-device-widget.c b/src/usb-device-widget.c > index 6e7a267..e077482 100644 > --- a/src/usb-device-widget.c > +++ b/src/usb-device-widget.c > @@ -24,6 +24,7 @@ > #include "spice-client.h" > #include "spice-marshal.h" > #include "usb-device-widget.h" > +#include "usb-device-manager.h" > > /** > * SECTION:usb-device-widget > @@ -62,6 +63,7 @@ static void device_removed_cb(SpiceUsbDeviceManager > *manager, > SpiceUsbDevice *device, gpointer user_data); > static void device_error_cb(SpiceUsbDeviceManager *manager, > SpiceUsbDevice *device, GError *err, gpointer user_data); > +static void empty_cd_clicked_cb(GtkToggleButton *toggle, gpointer > user_data); > static gboolean spice_usb_device_widget_update_status(gpointer user_data); > > enum { > @@ -79,6 +81,7 @@ struct _SpiceUsbDeviceWidgetPrivate { > SpiceSession *session; > gchar *device_format_string; > SpiceUsbDeviceManager *manager; > + GtkWidget *empty_cd; > GtkWidget *info_bar; > GtkWidget *label; > gchar *err_msg; > @@ -189,6 +192,68 @@ > spice_usb_device_widget_show_info_bar(SpiceUsbDeviceWidget *self, > gtk_widget_show_all(priv->info_bar); > } > > +static void spice_usb_device_widget_add_empty_cd(SpiceUsbDeviceWidget > *self); > + > +static void > +empty_cd_clicked_cb(GtkToggleButton *toggle, gpointer user_data) > +{ > + SpiceUsbDeviceWidget *self = SPICE_USB_DEVICE_WIDGET(user_data); > + SpiceUsbDeviceWidgetPrivate *priv = self->priv; > + GtkWidget *dialog; > + gint dialog_rc; > + > + if (gtk_toggle_button_get_active(toggle)) > + gtk_toggle_button_set_active(toggle, FALSE); style: always use brackets, here and below > + else > + return; I would handle the return in the if to reduce indentation > + > + dialog = gtk_file_chooser_dialog_new(_("Select ISO file or device"), > + > GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), > + GTK_FILE_CHOOSER_ACTION_OPEN, > + _("_Cancel"), GTK_RESPONSE_CANCEL, > + _("_Open"), GTK_RESPONSE_ACCEPT, > + NULL); > + > + dialog_rc = gtk_dialog_run(GTK_DIALOG(dialog)); > + if (dialog_rc == GTK_RESPONSE_ACCEPT) { > + gchar *filename = > gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); > + GError *err = NULL; > + gboolean rc; > + > + rc = spice_usb_device_manager_create_shared_cd_device(priv->manager, > filename, &err); > + if (!rc && err) { > + gchar *err_msg = g_strdup_printf("shared CD %s, %s", > + g_path_get_basename(filename), > err->message); I would add _( to string for i18n > + > + SPICE_DEBUG("Failed to create %s", err_msg); > + spice_usb_device_widget_add_err_msg(self, err_msg); > + spice_usb_device_widget_update_status(user_data); > + } > + g_clear_error(&err); > + } > + gtk_widget_destroy(dialog); > +} > + > +static void spice_usb_device_widget_add_empty_cd(SpiceUsbDeviceWidget *self) > +{ > + SpiceUsbDeviceWidgetPrivate *priv = self->priv; > + GtkWidget *empty_cd, *cd_label; > + > + if (priv->empty_cd) > + return; > + > + empty_cd = gtk_check_button_new_with_label("SPICE CD (empty)"); i18n also here > + cd_label = gtk_bin_get_child(GTK_BIN(empty_cd)); > + gtk_label_set_ellipsize(GTK_LABEL(cd_label), PANGO_ELLIPSIZE_MIDDLE); > + g_signal_connect(G_OBJECT(empty_cd), "toggled", > G_CALLBACK(empty_cd_clicked_cb), self); > + > + gtk_widget_set_margin_start(empty_cd, 12); > + gtk_box_pack_end(GTK_BOX(self), empty_cd, FALSE, FALSE, 0); > + gtk_widget_show_all(empty_cd); > + > + priv->empty_cd = empty_cd; > +} > + > static void spice_usb_device_widget_constructed(GObject *gobject) > { > SpiceUsbDeviceWidget *self; > @@ -226,6 +291,8 @@ static void spice_usb_device_widget_constructed(GObject > *gobject) > g_signal_connect(priv->manager, "device-error", > G_CALLBACK(device_error_cb), self); > > + priv->empty_cd = NULL; > + This is not necessary, we don't support environment where NULL != 0 and all structure is initialized to 0 as default. And standard C decided now that NULL == 0 so no issue for the future. > devices = spice_usb_device_manager_get_devices(priv->manager); > if (devices != NULL) { > int i; > @@ -236,6 +303,8 @@ static void spice_usb_device_widget_constructed(GObject > *gobject) > g_ptr_array_unref(devices); > } > > + spice_usb_device_widget_add_empty_cd(self); > + > spice_usb_device_widget_update_status(self); > } > > @@ -554,6 +623,15 @@ static void device_added_cb(SpiceUsbDeviceManager > *manager, > > gtk_widget_set_margin_start(check, 12); > gtk_box_pack_end(GTK_BOX(self), check, FALSE, FALSE, 0); > + if (priv->empty_cd) { > + gtk_box_reorder_child(GTK_BOX(self), priv->empty_cd, -1); > + if (spice_usb_device_manager_is_device_shared_cd(priv->manager, > + device) && > + !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) { > + /* checkbox toggl will initiate redirect */ > + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), > TRUE); > + } > + } > spice_usb_device_widget_update_status(self); > gtk_widget_show_all(check); > } Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel