diff --git a/src/meson.build b/src/meson.build index f137f7b..8d182c3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,6 @@ headers = files( + 'teleport-remote-device.h', 'teleport-browser.h', 'teleport-get.h', 'teleport-publish.h', @@ -17,6 +18,7 @@ install_headers(headers, subdir: meson.project_name()) ################ sources = files( + 'teleport-remote-device.c', 'teleport-browser.c', 'teleport-get.c', 'teleport-publish.c', diff --git a/src/remote_list.ui b/src/remote_list.ui index d2d7394..289372f 100644 --- a/src/remote_list.ui +++ b/src/remote_list.ui @@ -1,69 +1,75 @@ - + > diff --git a/src/teleport-remote-device.c b/src/teleport-remote-device.c new file mode 100644 index 0000000..6f2c3d0 --- /dev/null +++ b/src/teleport-remote-device.c @@ -0,0 +1,425 @@ +/* teleport-remote-device.c + * + * Copyright (C) 2017 Julian Sparber + * + * 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 3 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, see . + */ + +#include +#include "teleport-remote-device.h" +#include "teleport-peer.h" +#include "teleport-server.h" + +enum { + TARGET_INT32, + TARGET_STRING, + TARGET_URIS, + TARGET_ROOTWIN +}; + +enum +{ + PROP_0, + PROP_PEER, + LAST_PROP +}; + +/* datatype (string), restrictions on DnD (GtkTargetFlags), datatype (int) */ +static GtkTargetEntry target_list[] = { + //{ "INTEGER", 0, TARGET_INT32 }, + //{ "STRING", 0, TARGET_STRING }, + //{ "text/plain", 0, TARGET_STRING }, + { "text/uri-list", 0, TARGET_URIS } + //{ "application/octet-stream", 0, TARGET_STRING }, + //{ "application/x-rootwindow-drop", 0, TARGET_ROOTWIN } +}; + +static guint n_targets = G_N_ELEMENTS (target_list); + +struct _TeleportRemoteDevice +{ + GtkFrame parent; + GtkWidget *remote_device_row; + GtkWidget *device_name; + GtkWidget *send_btn; + + /* data */ + Peer *peer; +}; + +G_DEFINE_TYPE (TeleportRemoteDevice, teleport_remote_device, GTK_TYPE_FRAME) + + /* + * GObject overrides + */ + +static void +teleport_remote_device_finalize (GObject *object) +{ + //TeleportRemoteDevice *self = TELEPORT_REMOTE_DEVICE (object); + + G_OBJECT_CLASS (teleport_remote_device_parent_class)->finalize (object); +} + +static void +teleport_remote_device_dispose (GObject *object) +{ + G_OBJECT_CLASS (teleport_remote_device_parent_class)->dispose (object); +} + +static void +teleport_remote_device_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + TeleportRemoteDevice *self = TELEPORT_REMOTE_DEVICE (object); + + switch (prop_id) + { + case PROP_PEER: + g_value_set_pointer (value, self->peer); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +teleport_remote_device_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + TeleportRemoteDevice *self = TELEPORT_REMOTE_DEVICE (object); + + switch (prop_id) + { + case PROP_PEER: + teleport_remote_device_set_peer (self, g_value_get_pointer (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +teleport_remote_device_class_init (TeleportRemoteDeviceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->dispose = teleport_remote_device_dispose; + object_class->finalize = teleport_remote_device_finalize; + object_class->get_property = teleport_remote_device_get_property; + object_class->set_property = teleport_remote_device_set_property; + + /** + * TeleportRemoteDevice::peer: + * + * The peer that this row represents, or %NULL. + */ + g_object_class_install_property (object_class, + PROP_PEER, + g_param_spec_pointer ("peer", + "Peer of the row", + "The peer that this row represents", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /*g_param_spec_object ("peer", + "Task of the row", + "The task that this row represents", + (Peer *), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + */ + + gtk_widget_class_set_template_from_resource (widget_class, "/com/frac_tion/teleport/remote_list.ui"); + gtk_widget_class_bind_template_child (widget_class, TeleportRemoteDevice, remote_device_row); + gtk_widget_class_bind_template_child (widget_class, TeleportRemoteDevice, device_name); + gtk_widget_class_bind_template_child (widget_class, TeleportRemoteDevice, send_btn); +} + +static void +open_file_picker(GtkButton *btn, + Peer *device) { + GtkWidget *dialog; + GtkWidget * window; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; + gint res; + g_print("Open file chooser for submitting a file to %s with Address %s\n", device->name, device->ip); + + window = gtk_widget_get_toplevel (GTK_WIDGET (btn)); + if (gtk_widget_is_toplevel (window)) + { + dialog = gtk_file_chooser_dialog_new ("Open File", + GTK_WINDOW(window), + action, + ("_Cancel"), + GTK_RESPONSE_CANCEL, + ("_Open"), + GTK_RESPONSE_ACCEPT, + NULL); + + res = gtk_dialog_run (GTK_DIALOG (dialog)); + if (res == GTK_RESPONSE_ACCEPT) + { + char *filename; + GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); + filename = gtk_file_chooser_get_filename (chooser); + g_print("Choosen file is %s\n", filename); + gtk_widget_destroy (dialog); + teleport_server_add_route (g_compute_checksum_for_string (G_CHECKSUM_SHA256, filename, -1), filename, device->ip); + g_free (filename); + } + else + { + gtk_widget_destroy (dialog); + } + + } +} + + +static void +send_file_to_device (gchar *uri, gpointer data) +{ + Peer *device = (Peer *) data; + GFile *file = g_file_new_for_uri (uri); + gchar *filename = NULL; + if (g_file_query_exists (file, NULL)) { + filename = g_file_get_path (file); + teleport_server_add_route (g_compute_checksum_for_string (G_CHECKSUM_SHA256, filename, -1), g_strdup(filename), device->ip); + g_free (filename); + } + else { + g_print ("File doesn't exist: %s\n", uri); + } + g_object_unref(file); +} + + +static void +drag_data_received_handl +(GtkWidget *widget, GdkDragContext *context, gint x, gint y, + GtkSelectionData *selection_data, guint target_type, guint time, + gpointer data) +{ + glong *_idata; + gchar *_sdata; + gchar **uris; + + gboolean dnd_success = FALSE; + gboolean delete_selection_data = FALSE; + + /* Deal with what we are given from source */ + if((selection_data != NULL) && (gtk_selection_data_get_length(selection_data) >= 0)) + { + if (gdk_drag_context_get_suggested_action(context) == GDK_ACTION_ASK) + { + /* Ask the user to move or copy, then set the context action. */ + } + + if (gdk_drag_context_get_suggested_action(context) == GDK_ACTION_MOVE) + delete_selection_data = TRUE; + + /* Check that we got the format we can use */ + switch (target_type) + { + case TARGET_INT32: + _idata = (glong*)gtk_selection_data_get_data(selection_data); + g_print ("integer: %ld", *_idata); + dnd_success = TRUE; + break; + + case TARGET_STRING: + _sdata = (gchar*)gtk_selection_data_get_data(selection_data); + g_print ("string: %s", _sdata); + dnd_success = TRUE; + break; + + case TARGET_URIS: + uris = gtk_selection_data_get_uris(selection_data); + if (uris != NULL && uris[1] == NULL) { + send_file_to_device (uris[0], data); + dnd_success = TRUE; + } + break; + + default: + g_print ("Something bad!"); + } + } + + if (dnd_success == FALSE) + { + g_print ("DnD data transfer failed!\n"); + g_print ("You can not drag more then one file!\n"); + } + + gtk_drag_finish (context, dnd_success, delete_selection_data, time); +} + +/* Emitted when a drag is over the destination */ +static gboolean +drag_motion_handl +(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint t, + gpointer user_data) +{ + // Fancy stuff here. This signal spams the console something horrible. + //const gchar *name = gtk_widget_get_name (widget); + //g_print ("%s: drag_motion_handl\n", name); + return FALSE; +} + +/* Emitted when a drag leaves the destination */ +static void +drag_leave_handl +(GtkWidget *widget, GdkDragContext *context, guint time, gpointer user_data) +{ +} + +/* Emitted when the user releases (drops) the selection. It should check that + * the drop is over a valid part of the widget (if its a complex widget), and + * itself to return true if the operation should continue. Next choose the + * target type it wishes to ask the source for. Finally call gtk_drag_get_data + * which will emit "drag-data-get" on the source. */ +static gboolean +drag_drop_handl +(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, + gpointer user_data) +{ + gboolean is_valid_drop_site; + GdkAtom target_type; + + /* Check to see if (x,y) is a valid drop site within widget */ + is_valid_drop_site = TRUE; + + /* If the source offers a target */ + if (gdk_drag_context_list_targets (context)) + { + /* Choose the best target type */ + target_type = GDK_POINTER_TO_ATOM + (g_list_nth_data (gdk_drag_context_list_targets(context), TARGET_INT32)); + + + /* Request the data from the source. */ + gtk_drag_get_data + ( + widget, /* will receive 'drag-data-received' signal */ + context, /* represents the current state of the DnD */ + target_type, /* the target type we want */ + time /* time stamp */ + ); + } + /* No target offered by source => error */ + else + { + is_valid_drop_site = FALSE; + } + + return is_valid_drop_site; +} + +static void +teleport_remote_device_init (TeleportRemoteDevice *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + + /* Make the widget a DnD destination. */ + gtk_drag_dest_set + ( + GTK_WIDGET (self), /* widget that will accept a drop */ + GTK_DEST_DEFAULT_ALL, + target_list, /* lists of target to support */ + n_targets, /* size of list */ + GDK_ACTION_COPY /* what to do with data after dropped */ + ); +} + +GtkWidget* +teleport_remote_device_new (Peer *peer) +{ + return g_object_new (TELEPORT_TYPE_REMOTE_DEVICE, + "peer", peer, + NULL); +} + +/** + * teleport_remote_device_get_peer: + * @row: a #TeleportRemoteDevice + * + * Retrieves the #Peer that @row manages, or %NULL if none + * is set. + * + * Returns: (transfer none): the internal peer of @row + */ +Peer * + teleport_remote_device_get_peer (GtkWidget *widget) +{ + TeleportRemoteDevice *row; + + g_return_val_if_fail (TELEPORT_IS_REMOTE_DEVICE (widget), NULL); + + row = TELEPORT_REMOTE_DEVICE (widget); + + return row->peer; +} + +void +teleport_remote_device_set_peer (TeleportRemoteDevice *widget, + Peer *peer) +{ + g_return_if_fail (TELEPORT_IS_REMOTE_DEVICE (widget)); + widget->peer = peer; + + /*if (!g_set_object (&row->peer, peer)) + return; + */ + + + if (peer) + { + + gtk_label_set_text(GTK_LABEL (widget->device_name), peer->name); + + g_signal_connect (widget->send_btn, "clicked", G_CALLBACK (open_file_picker), peer); + + + g_signal_connect (widget, "drag-data-received", + G_CALLBACK(drag_data_received_handl), peer); + + g_signal_connect (widget, "drag-leave", + G_CALLBACK (drag_leave_handl), peer); + + g_signal_connect (widget, "drag-motion", + G_CALLBACK (drag_motion_handl), peer); + + g_signal_connect (widget, "drag-drop", + G_CALLBACK (drag_drop_handl), peer); + } +} + +/** + * teleport_remote_device_destroy: + * @self: a #TeleportRemoteDevice + * + * Destroy @self after hiding it. + */ +void +teleport_remote_device_destroy (TeleportRemoteDevice *self) +{ +} + diff --git a/src/teleport-remote-device.h b/src/teleport-remote-device.h new file mode 100644 index 0000000..6522a56 --- /dev/null +++ b/src/teleport-remote-device.h @@ -0,0 +1,41 @@ +/* teleport-remote-device.h + * + * Copyright (C) 2017 Julian Sparber + * + * 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 3 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, see . + */ + +#ifndef TELEPORT_REMOTE_DEVICE_H +#define TELEPORT_REMOTE_DEVICE_H + +#include +#include +#include "teleport-peer.h" + +G_BEGIN_DECLS + +#define TELEPORT_TYPE_REMOTE_DEVICE (teleport_remote_device_get_type()) + +G_DECLARE_FINAL_TYPE (TeleportRemoteDevice, teleport_remote_device, TELEPORT, REMOTE_DEVICE, GtkFrame) + +GtkWidget * teleport_remote_device_new (Peer * ); + +Peer * teleport_remote_device_get_peer (GtkWidget * ); +void teleport_remote_device_set_peer (TeleportRemoteDevice *, Peer *); +void teleport_remote_device_destroy (TeleportRemoteDevice *); + + +G_END_DECLS + +#endif /* TELEPORT_REMOTE_DEVICE_H */ diff --git a/src/teleport-window.c b/src/teleport-window.c index 63048c5..ead94f7 100644 --- a/src/teleport-window.c +++ b/src/teleport-window.c @@ -4,27 +4,7 @@ #include "teleport-window.h" #include "teleport-server.h" #include "teleport-peer.h" - -GtkWidget *find_child(GtkWidget *, const gchar *); - -enum { - TARGET_INT32, - TARGET_STRING, - TARGET_URIS, - TARGET_ROOTWIN -}; - -/* datatype (string), restrictions on DnD (GtkTargetFlags), datatype (int) */ -static GtkTargetEntry target_list[] = { - //{ "INTEGER", 0, TARGET_INT32 }, - //{ "STRING", 0, TARGET_STRING }, - //{ "text/plain", 0, TARGET_STRING }, - { "text/uri-list", 0, TARGET_URIS } - //{ "application/octet-stream", 0, TARGET_STRING }, - //{ "application/x-rootwindow-drop", 0, TARGET_ROOTWIN } -}; - -static guint n_targets = G_N_ELEMENTS (target_list); +#include "teleport-remote-device.h" TeleportWindow *mainWin; @@ -39,7 +19,7 @@ struct _TeleportWindowPrivate { GSettings *settings; GtkWidget *gears; - GtkWidget *remote_devices_list; + GtkWidget *remote_devices_box; GtkWidget *this_device_name_label; GtkWidget *remote_no_devices; }; @@ -61,145 +41,6 @@ change_download_directory_cb (GtkWidget *widget, g_free(newDownloadDir); } -static void -send_file_to_device (gchar *uri, gpointer data) -{ - Peer *device = (Peer *) data; - GFile *file = g_file_new_for_uri (uri); - gchar *filename = NULL; - if (g_file_query_exists (file, NULL)) { - filename = g_file_get_path (file); - teleport_server_add_route (g_compute_checksum_for_string (G_CHECKSUM_SHA256, filename, -1), g_strdup(filename), device->ip); - g_free (filename); - } - else { - g_print ("File doesn't exist: %s\n", uri); - } - g_object_unref(file); -} -static void -drag_data_received_handl -(GtkWidget *widget, GdkDragContext *context, gint x, gint y, - GtkSelectionData *selection_data, guint target_type, guint time, - gpointer data) -{ - glong *_idata; - gchar *_sdata; - gchar **uris; - - gboolean dnd_success = FALSE; - gboolean delete_selection_data = FALSE; - - /* Deal with what we are given from source */ - if((selection_data != NULL) && (gtk_selection_data_get_length(selection_data) >= 0)) - { - if (gdk_drag_context_get_suggested_action(context) == GDK_ACTION_ASK) - { - /* Ask the user to move or copy, then set the context action. */ - } - - if (gdk_drag_context_get_suggested_action(context) == GDK_ACTION_MOVE) - delete_selection_data = TRUE; - - /* Check that we got the format we can use */ - switch (target_type) - { - case TARGET_INT32: - _idata = (glong*)gtk_selection_data_get_data(selection_data); - g_print ("integer: %ld", *_idata); - dnd_success = TRUE; - break; - - case TARGET_STRING: - _sdata = (gchar*)gtk_selection_data_get_data(selection_data); - g_print ("string: %s", _sdata); - dnd_success = TRUE; - break; - - case TARGET_URIS: - uris = gtk_selection_data_get_uris(selection_data); - if (uris != NULL && uris[1] == NULL) { - send_file_to_device (uris[0], data); - dnd_success = TRUE; - } - break; - - default: - g_print ("Something bad!"); - } - } - - if (dnd_success == FALSE) - { - g_print ("DnD data transfer failed!\n"); - g_print ("You can not drag more then one file!\n"); - } - - gtk_drag_finish (context, dnd_success, delete_selection_data, time); -} - -/* Emitted when a drag is over the destination */ -static gboolean -drag_motion_handl -(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint t, - gpointer user_data) -{ - // Fancy stuff here. This signal spams the console something horrible. - //const gchar *name = gtk_widget_get_name (widget); - //g_print ("%s: drag_motion_handl\n", name); - return FALSE; -} - -/* Emitted when a drag leaves the destination */ -static void -drag_leave_handl -(GtkWidget *widget, GdkDragContext *context, guint time, gpointer user_data) -{ -} - -/* Emitted when the user releases (drops) the selection. It should check that - * the drop is over a valid part of the widget (if its a complex widget), and - * itself to return true if the operation should continue. Next choose the - * target type it wishes to ask the source for. Finally call gtk_drag_get_data - * which will emit "drag-data-get" on the source. */ -static gboolean -drag_drop_handl -(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, - gpointer user_data) -{ - gboolean is_valid_drop_site; - GdkAtom target_type; - - /* Check to see if (x,y) is a valid drop site within widget */ - is_valid_drop_site = TRUE; - - /* If the source offers a target */ - if (gdk_drag_context_list_targets (context)) - { - /* Choose the best target type */ - target_type = GDK_POINTER_TO_ATOM - (g_list_nth_data (gdk_drag_context_list_targets(context), TARGET_INT32)); - - - /* Request the data from the source. */ - gtk_drag_get_data - ( - widget, /* will receive 'drag-data-received' signal */ - context, /* represents the current state of the DnD */ - target_type, /* the target type we want */ - time /* time stamp */ - ); - } - /* No target offered by source => error */ - else - { - is_valid_drop_site = FALSE; - } - - return is_valid_drop_site; -} - - static void teleport_window_init (TeleportWindow *win) { @@ -257,156 +98,48 @@ teleport_window_init (TeleportWindow *win) } -/*Doing Dnd init stuff */ -static void -add_dnd (GtkWidget *widget, gpointer data) -{ - /* Make the widget a DnD destination. */ - gtk_drag_dest_set - ( - widget, /* widget that will accept a drop */ - GTK_DEST_DEFAULT_ALL, - target_list, /* lists of target to support */ - n_targets, /* size of list */ - GDK_ACTION_COPY /* what to do with data after dropped */ - ); - - /* All possible destination signals */ - g_signal_connect (widget, "drag-data-received", - G_CALLBACK(drag_data_received_handl), data); - - g_signal_connect (widget, "drag-leave", - G_CALLBACK (drag_leave_handl), data); - - g_signal_connect (widget, "drag-motion", - G_CALLBACK (drag_motion_handl), data); - - g_signal_connect (widget, "drag-drop", - G_CALLBACK (drag_drop_handl), data); -} - -static void -open_file_picker(GtkButton *btn, - Peer *device) { - GtkWidget *dialog; - GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; - gint res; - g_print("Open file chooser for submitting a file to %s with Address %s\n", device->name, device->ip); - - dialog = gtk_file_chooser_dialog_new ("Open File", - GTK_WINDOW(mainWin), - action, - ("_Cancel"), - GTK_RESPONSE_CANCEL, - ("_Open"), - GTK_RESPONSE_ACCEPT, - NULL); - - res = gtk_dialog_run (GTK_DIALOG (dialog)); - if (res == GTK_RESPONSE_ACCEPT) - { - char *filename; - GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); - filename = gtk_file_chooser_get_filename (chooser); - g_print("Choosen file is %s\n", filename); - gtk_widget_destroy (dialog); - teleport_server_add_route (g_compute_checksum_for_string (G_CHECKSUM_SHA256, filename, -1), filename, device->ip); - g_free (filename); - } - else - { - gtk_widget_destroy (dialog); - } -} - void update_remote_device_list(TeleportWindow *win, - Peer *device) + Peer *device) { TeleportWindowPrivate *priv; - GtkBuilder *builder_remote_list; - GtkWidget *row; - GtkLabel *name_label; - GtkButton *send_btn; - //GtkWidget *line; + GtkWidget *remote_device; priv = teleport_window_get_instance_private (win); gtk_widget_hide (priv->remote_no_devices); - builder_remote_list = gtk_builder_new_from_resource ("/com/frac_tion/teleport/remote_list.ui"); + remote_device = teleport_remote_device_new (device); - row = GTK_WIDGET (gtk_builder_get_object (builder_remote_list, "remote_device_row")); - name_label = GTK_LABEL (gtk_builder_get_object (builder_remote_list, "device_name")); - gtk_label_set_text(name_label, device->name); - gtk_list_box_insert(GTK_LIST_BOX(priv->remote_devices_list), row, -1); - send_btn = GTK_BUTTON (gtk_builder_get_object (builder_remote_list, "send_btn")); - g_signal_connect (send_btn, "clicked", G_CALLBACK (open_file_picker), device); - - //Add drag n drop - add_dnd (row, device); - - //line = GTK_WIDGET (gtk_builder_get_object (builder_remote_list, "remote_space_row")); - //gtk_list_box_insert(GTK_LIST_BOX(priv->remote_devices_list), line, -1); - g_object_unref (builder_remote_list); + gtk_box_pack_end (GTK_BOX (priv->remote_devices_box), + remote_device, + TRUE, + TRUE, + 0); } +static void +remove_remote_peer (GtkWidget *widget, + gpointer data) +{ + if (TELEPORT_IS_REMOTE_DEVICE (widget) && teleport_remote_device_get_peer(widget) == ((Peer *) data)) { + gtk_widget_destroy (widget); + } +} void update_remote_device_list_remove(TeleportWindow *win, Peer *device) { TeleportWindowPrivate *priv; - GtkWidget *box; - GtkListBoxRow *remote_row; - GtkLabel *name_label; - gint i = 0; priv = teleport_window_get_instance_private (win); - box = priv->remote_devices_list; - remote_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX(box), i); - - while (remote_row != NULL) { - name_label = GTK_LABEL(find_child(GTK_WIDGET(remote_row), "GtkLabel")); - if (name_label != NULL && g_strcmp0(device->name, gtk_label_get_text(name_label)) == 0) { - gtk_container_remove (GTK_CONTAINER(box), GTK_WIDGET(remote_row)); - } - i++; - remote_row = gtk_list_box_get_row_at_index (GTK_LIST_BOX(box), i); - } - // the last row got removed and we have to display the searching box - if (i <= 2) { - gtk_widget_show (priv->remote_no_devices); - } + gtk_container_foreach (GTK_CONTAINER(priv->remote_devices_box), + remove_remote_peer, + device); } -GtkWidget * -find_child(GtkWidget *parent, const gchar *name) -{ - if (g_strcmp0(gtk_widget_get_name((GtkWidget *)parent), (gchar *)name) == 0) { - return parent; - } - - if (GTK_IS_BIN(parent)) { - GtkWidget *child = gtk_bin_get_child(GTK_BIN(parent)); - return find_child(child, name); - } - - if (GTK_IS_CONTAINER(parent)) { - GList *children = gtk_container_get_children(GTK_CONTAINER(parent)); - while ((children = g_list_next(children)) != NULL) { - GtkWidget *widget = find_child(children->data, name); - if (widget != NULL) { - return widget; - } - } - } - - return NULL; -} - - static void teleport_window_dispose (GObject *object) { @@ -432,7 +165,7 @@ teleport_window_class_init (TeleportWindowClass *class) gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), TeleportWindow, gears); gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), TeleportWindow, this_device_name_label); gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), TeleportWindow, remote_no_devices); - gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), TeleportWindow, remote_devices_list); + gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), TeleportWindow, remote_devices_box); } TeleportWindow * diff --git a/src/teleport-window.h b/src/teleport-window.h index 4f57b80..a3f7bdc 100644 --- a/src/teleport-window.h +++ b/src/teleport-window.h @@ -16,9 +16,9 @@ TeleportWindow *teleport_window_new (TeleportApp *); void teleport_window_open (TeleportWindow *, GFile *); void update_remote_device_list (TeleportWindow *, - Peer *); + Peer *); void update_remote_device_list_remove (TeleportWindow *, - Peer *); + Peer *); gchar * teleport_get_download_directory (void); gchar * teleport_get_device_name (void); diff --git a/src/window.ui b/src/window.ui index fce07ac..39bbcbb 100644 --- a/src/window.ui +++ b/src/window.ui @@ -210,24 +210,24 @@ - + True False + 6 6 - 12 - in + vertical - + True False - vertical + in - + True True none - + True False False