diff --git a/daemon/graph.c b/daemon/graph.c index 88e4efc6..d8e7bc23 100644 --- a/daemon/graph.c +++ b/daemon/graph.c @@ -2026,6 +2026,31 @@ bool ladish_graph_client_has_visible_app_port(ladish_graph_handle graph_handle, return false; } +bool ladish_graph_client_has_visible_ports(ladish_graph_handle graph_handle, ladish_client_handle client_handle) +{ + struct ladish_graph_client * client_ptr; + struct list_head * node_ptr; + struct ladish_graph_port * port_ptr; + + client_ptr = ladish_graph_find_client(graph_ptr, client_handle); + if (client_ptr == NULL) + { + ASSERT_NO_PASS; + return false; + } + + list_for_each(node_ptr, &client_ptr->ports) + { + port_ptr = list_entry(node_ptr, struct ladish_graph_port, siblings_client); + if (!port_ptr->hidden) + { + return true; + } + } + + return false; +} + ladish_client_handle ladish_graph_remove_port( ladish_graph_handle graph_handle, diff --git a/daemon/graph.h b/daemon/graph.h index adf803c9..f3e0d0c5 100644 --- a/daemon/graph.h +++ b/daemon/graph.h @@ -183,6 +183,7 @@ bool ladish_disconnect_visible_connections(ladish_graph_handle graph_handle); void ladish_graph_hide_non_virtual(ladish_graph_handle graph_handle); void ladish_graph_get_port_uuid(ladish_graph_handle graph, ladish_port_handle port, uuid_t uuid_ptr); bool ladish_graph_client_has_visible_app_port(ladish_graph_handle graph, ladish_client_handle client, const uuid_t app_uuid); +bool ladish_graph_client_has_visible_ports(ladish_graph_handle graph, ladish_client_handle client); void ladish_graph_dump(ladish_graph_handle graph_handle); diff --git a/daemon/graph_manager.c b/daemon/graph_manager.c index 3d2f3667..555e622d 100644 --- a/daemon/graph_manager.c +++ b/daemon/graph_manager.c @@ -243,6 +243,42 @@ static void ladish_graph_manager_dbus_new_client(struct dbus_method_call * call_ method_return_new_single(call_ptr, DBUS_TYPE_UINT64, &client_id); } +static void ladish_graph_manager_dbus_remove_client(struct dbus_method_call * call_ptr) +{ + uint64_t client_id; + ladish_client_handle client; + + if (!dbus_message_get_args( + call_ptr->message, + &g_dbus_error, + DBUS_TYPE_UINT64, &client_id, + DBUS_TYPE_INVALID)) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); + dbus_error_free(&g_dbus_error); + return; + } + + log_info("remove client request, graph '%s', client %"PRIu64, ladish_graph_get_description(graph), client_id); + + client = ladish_graph_find_client_by_id(graph, client_id); + if (client == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot remove unknown client"); + return; + } + + if (ladish_graph_client_has_visible_ports(graph, client)) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Cannot remove non-empty client"); + return; + } + + ladish_graph_remove_client(graph, client); + + method_return_new_void(call_ptr); +} + #undef graph_ptr METHOD_ARGS_BEGIN(Split, "Split client") @@ -274,6 +310,10 @@ METHOD_ARGS_BEGIN(NewClient, "New client") METHOD_ARG_DESCRIBE_OUT("client_id", "t", "ID of the new client") METHOD_ARGS_END +METHOD_ARGS_BEGIN(RemoveClient, "Remove empty client") + METHOD_ARG_DESCRIBE_IN("client_id", "t", "ID of the client to remove") +METHOD_ARGS_END + METHODS_BEGIN METHOD_DESCRIBE(Split, ladish_graph_manager_dbus_split) METHOD_DESCRIBE(Join, ladish_graph_manager_dbus_join) @@ -281,6 +321,7 @@ METHODS_BEGIN METHOD_DESCRIBE(RenamePort, ladish_graph_manager_dbus_rename_port) METHOD_DESCRIBE(MovePort, ladish_graph_manager_dbus_move_port) METHOD_DESCRIBE(NewClient, ladish_graph_manager_dbus_new_client) + METHOD_DESCRIBE(RemoveClient, ladish_graph_manager_dbus_remove_client) METHODS_END INTERFACE_BEGIN(g_iface_graph_manager, IFACE_GRAPH_MANAGER) diff --git a/gui/graph_canvas.c b/gui/graph_canvas.c index 34be12f1..3fde598f 100644 --- a/gui/graph_canvas.c +++ b/gui/graph_canvas.c @@ -197,6 +197,15 @@ static void on_popup_menu_action_split(GtkWidget * menuitem, gpointer module_con graph_proxy_split(client_ptr->owner_ptr->graph, client_ptr->id); } +static void on_popup_menu_action_remove(GtkWidget * menuitem, gpointer module_context) +{ + //log_info("on_popup_menu_action_split"); + if (!graph_proxy_remove_client(client_ptr->owner_ptr->graph, client_ptr->id)) + { + error_message_box("Client remove failed"); + } +} + static void fill_module_menu(GtkMenu * menu, void * module_context) { GtkWidget * menuitem; @@ -207,6 +216,14 @@ static void fill_module_menu(GtkMenu * menu, void * module_context) g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_client_rename, client_ptr); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + if (client_ptr->inport_count == 0 && + client_ptr->outport_count == 0) + { + menuitem = gtk_menu_item_new_with_label(_("Remove")); + g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_remove, client_ptr); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } + if (client_ptr->inport_count != 0 && client_ptr->outport_count != 0) { diff --git a/proxies/graph_proxy.c b/proxies/graph_proxy.c index 087bbac1..c45e6bf3 100644 --- a/proxies/graph_proxy.c +++ b/proxies/graph_proxy.c @@ -1094,6 +1094,25 @@ graph_proxy_new_client( return true; } +bool +graph_proxy_remove_client( + graph_proxy_handle graph, + uint64_t client_id) +{ + if (!graph_ptr->graph_manager_supported) + { + return false; + } + + if (!dbus_call(0, graph_ptr->service, graph_ptr->object, IFACE_GRAPH_MANAGER, "RemoveClient", "t", &client_id, "")) + { + log_error(IFACE_GRAPH_MANAGER ".RemoveClient() failed."); + return false; + } + + return true; +} + /* this must be static because it is referenced by the * dbus helper layer when hooks are active */ static struct dbus_signal_hook g_signal_hooks[] = diff --git a/proxies/graph_proxy.h b/proxies/graph_proxy.h index b41b8133..57729cd7 100644 --- a/proxies/graph_proxy.h +++ b/proxies/graph_proxy.h @@ -148,6 +148,11 @@ graph_proxy_new_client( const char * name, uint64_t * client_id_ptr); +bool +graph_proxy_remove_client( + graph_proxy_handle graph, + uint64_t client_id); + #if 0 { /* Adjust editor indent */ #endif