mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 07:00:05 +01:00
merge: branch 'nmtui-wifi-rescan'
nmtui: feature: wifi-rescan feature for the nmtui. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2281
This commit is contained in:
commit
9582d5da2a
2 changed files with 260 additions and 3 deletions
|
|
@ -342,12 +342,256 @@ listbox_active_changed(GObject *object, GParamSpec *pspec, gpointer button)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Contains both the UI and batch data for wifi-rescans */
|
||||||
|
typedef struct {
|
||||||
|
NmtNewtWidget *activate_button;
|
||||||
|
NmtNewtWidget *listbox;
|
||||||
|
NmtNewtForm *rescan_form;
|
||||||
|
NmtNewtWidget *rescan_button;
|
||||||
|
int pending;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
gboolean cancelled;
|
||||||
|
gboolean has_error;
|
||||||
|
gboolean timeout_occurred;
|
||||||
|
} RescanBatch;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMDeviceWifi *wifi_device;
|
||||||
|
GSource *timeout_id;
|
||||||
|
gulong signal_id;
|
||||||
|
RescanBatch *batch;
|
||||||
|
} RescanData;
|
||||||
|
|
||||||
|
static GPtrArray *
|
||||||
|
active_wifi_devices(void)
|
||||||
|
{
|
||||||
|
const GPtrArray *devices;
|
||||||
|
GPtrArray *active_wifi_devices;
|
||||||
|
|
||||||
|
devices = nm_client_get_devices(nm_client);
|
||||||
|
|
||||||
|
if (!devices)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
active_wifi_devices = g_ptr_array_new_with_free_func(g_object_unref);
|
||||||
|
|
||||||
|
for (guint i = 0; i < devices->len; i++) {
|
||||||
|
NMDevice *dev = g_ptr_array_index((GPtrArray *) devices, i);
|
||||||
|
NMDeviceInterfaceFlags devflags = nm_device_get_interface_flags(dev);
|
||||||
|
|
||||||
|
if ((devflags & NM_DEVICE_INTERFACE_FLAG_UP) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (NM_IS_DEVICE_WIFI(dev)
|
||||||
|
&& !NM_IN_SET(nm_device_get_state(dev),
|
||||||
|
NM_DEVICE_STATE_UNAVAILABLE,
|
||||||
|
NM_DEVICE_STATE_UNMANAGED,
|
||||||
|
NM_DEVICE_STATE_FAILED)) {
|
||||||
|
g_ptr_array_add(active_wifi_devices, g_object_ref(dev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return active_wifi_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_rescan_cancel(NmtNewtForm *form, gpointer user_data)
|
||||||
|
{
|
||||||
|
RescanBatch *batch_data = user_data;
|
||||||
|
|
||||||
|
if (!batch_data || batch_data->cancelled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
batch_data->cancelled = TRUE;
|
||||||
|
|
||||||
|
/* Cancel the async operations using nm_clear_g_cancellable */
|
||||||
|
if (batch_data->cancellable)
|
||||||
|
nm_clear_g_cancellable(&batch_data->cancellable);
|
||||||
|
|
||||||
|
g_object_unref(batch_data->rescan_form);
|
||||||
|
batch_data->rescan_form = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* creates the wifi-rescan form and manages other ui properties while rescanning */
|
||||||
|
static void
|
||||||
|
wifi_rescan_form(RescanBatch *batch_data)
|
||||||
|
{
|
||||||
|
NmtNewtForm *rescan_form;
|
||||||
|
NmtNewtWidget *label;
|
||||||
|
|
||||||
|
nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(batch_data->listbox), FALSE);
|
||||||
|
nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(batch_data->rescan_button), FALSE);
|
||||||
|
nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(batch_data->activate_button), FALSE);
|
||||||
|
|
||||||
|
/* open the scanning form*/
|
||||||
|
rescan_form = g_object_new(NMT_TYPE_NEWT_FORM, NULL);
|
||||||
|
label = nmt_newt_label_new(_("Rescanning Wi-Fi devices..."));
|
||||||
|
nmt_newt_form_set_content(rescan_form, label);
|
||||||
|
|
||||||
|
/* connect the quit signal to rescan cancel */
|
||||||
|
g_signal_connect(rescan_form, "quit", G_CALLBACK(on_rescan_cancel), batch_data);
|
||||||
|
|
||||||
|
nmt_newt_form_show(rescan_form);
|
||||||
|
batch_data->rescan_form = rescan_form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rebuilds the connection list and changes back the
|
||||||
|
* state for various UI components which were
|
||||||
|
* changed during rescanning */
|
||||||
|
static void
|
||||||
|
on_rescan_complete(gpointer data)
|
||||||
|
{
|
||||||
|
NmtConnectConnectionList *list;
|
||||||
|
RescanData *rescan_data;
|
||||||
|
RescanBatch *batch_data;
|
||||||
|
NMDeviceWifi *wifi_device;
|
||||||
|
|
||||||
|
rescan_data = data;
|
||||||
|
batch_data = rescan_data->batch;
|
||||||
|
wifi_device = rescan_data->wifi_device;
|
||||||
|
|
||||||
|
g_free(rescan_data);
|
||||||
|
rescan_data = NULL;
|
||||||
|
|
||||||
|
if (batch_data->has_error) {
|
||||||
|
nmt_newt_message_dialog(_("Wi-Fi scan failed for device : %s"),
|
||||||
|
nm_device_get_iface(NM_DEVICE(wifi_device)));
|
||||||
|
batch_data->has_error = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batch_data->timeout_occurred) {
|
||||||
|
nmt_newt_message_dialog(_("Wi-Fi scan timed out for device : %s"),
|
||||||
|
nm_device_get_iface(NM_DEVICE(wifi_device)));
|
||||||
|
batch_data->timeout_occurred = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the scans are not complete then simply wait for them to complete
|
||||||
|
* This also ensures that UI is only enabled either after all
|
||||||
|
* scans complete or all the scans are cancelled. Preventing any
|
||||||
|
* overlapping scans caused due to the user pressing rescan multiple times
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (--batch_data->pending > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If the scan is not cancelled quit normally */
|
||||||
|
if (!batch_data->cancelled) {
|
||||||
|
if (nmt_newt_widget_get_realized(NMT_NEWT_WIDGET(batch_data->rescan_form))) {
|
||||||
|
nmt_newt_form_quit(batch_data->rescan_form);
|
||||||
|
batch_data->rescan_form = NULL;
|
||||||
|
}
|
||||||
|
list = NMT_CONNECT_CONNECTION_LIST(batch_data->listbox);
|
||||||
|
nmt_newt_listbox_clear(NMT_NEWT_LISTBOX(list));
|
||||||
|
|
||||||
|
g_object_notify(G_OBJECT(nm_client), NM_CLIENT_CONNECTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following cleanup is required regardless of any cancellation */
|
||||||
|
nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(batch_data->listbox), TRUE);
|
||||||
|
nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(batch_data->rescan_button), TRUE);
|
||||||
|
nmt_newt_component_set_sensitive(NMT_NEWT_COMPONENT(batch_data->activate_button), TRUE);
|
||||||
|
|
||||||
|
g_clear_object(&batch_data->cancellable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
scan_timeout_callback(gpointer user_data)
|
||||||
|
{
|
||||||
|
RescanData *data = user_data;
|
||||||
|
|
||||||
|
nm_clear_g_source_inst(&data->timeout_id);
|
||||||
|
|
||||||
|
/* Timeout reached - scan took too long */
|
||||||
|
if (data->signal_id) {
|
||||||
|
g_signal_handler_disconnect(data->wifi_device, data->signal_id);
|
||||||
|
data->signal_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->batch->timeout_occurred = TRUE;
|
||||||
|
|
||||||
|
on_rescan_complete(data);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_last_scan_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||||
|
{
|
||||||
|
RescanData *data = user_data;
|
||||||
|
|
||||||
|
/* Scan completed successfully */
|
||||||
|
nm_clear_g_source_inst(&data->timeout_id);
|
||||||
|
if (data->signal_id) {
|
||||||
|
g_signal_handler_disconnect(data->wifi_device, data->signal_id);
|
||||||
|
data->signal_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_rescan_complete(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wifi_rescan_callback(GObject *source_object, GAsyncResult *result, gpointer rescan_data)
|
||||||
|
{
|
||||||
|
RescanData *data = rescan_data;
|
||||||
|
|
||||||
|
if (!nm_device_wifi_request_scan_finish(data->wifi_device, result, NULL)) {
|
||||||
|
data->batch->has_error = TRUE;
|
||||||
|
on_rescan_complete(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Listen for last-scan property changes */
|
||||||
|
data->signal_id = g_signal_connect(data->wifi_device,
|
||||||
|
"notify::last-scan",
|
||||||
|
G_CALLBACK(on_last_scan_changed),
|
||||||
|
data);
|
||||||
|
|
||||||
|
/* Set a 10-second timeout in case scan doesn't complete */
|
||||||
|
data->timeout_id = nm_g_timeout_add_source(RESCAN_TIMEOUT_MS, scan_timeout_callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wifi_rescan(NmtNewtButton *button, gpointer data_batch)
|
||||||
|
{
|
||||||
|
gs_unref_ptrarray GPtrArray *devices;
|
||||||
|
RescanData *data;
|
||||||
|
RescanBatch *batch_data = data_batch;
|
||||||
|
|
||||||
|
devices = active_wifi_devices();
|
||||||
|
|
||||||
|
if (!devices || devices->len == 0) {
|
||||||
|
nmt_newt_message_dialog(_("No active Wi-Fi devices found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a shared batch for all the devices*/
|
||||||
|
batch_data->pending = devices->len;
|
||||||
|
batch_data->cancelled = FALSE;
|
||||||
|
batch_data->cancellable = g_cancellable_new();
|
||||||
|
|
||||||
|
wifi_rescan_form(batch_data);
|
||||||
|
|
||||||
|
for (guint i = 0; i < devices->len; i++) {
|
||||||
|
NMDevice *dev = g_ptr_array_index(devices, i);
|
||||||
|
|
||||||
|
/* per-device data */
|
||||||
|
data = g_new0(RescanData, 1);
|
||||||
|
data->wifi_device = NM_DEVICE_WIFI(dev);
|
||||||
|
data->batch = batch_data;
|
||||||
|
|
||||||
|
nm_device_wifi_request_scan_async(NM_DEVICE_WIFI(dev),
|
||||||
|
batch_data->cancellable,
|
||||||
|
wifi_rescan_callback,
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static NmtNewtForm *
|
static NmtNewtForm *
|
||||||
nmt_connect_connection_list(gboolean is_top)
|
nmt_connect_connection_list(gboolean is_top)
|
||||||
{
|
{
|
||||||
int screen_width, screen_height;
|
int screen_width, screen_height;
|
||||||
NmtNewtForm *form;
|
NmtNewtForm *form;
|
||||||
NmtNewtWidget *list, *activate, *quit, *bbox, *grid;
|
NmtNewtWidget *list, *activate, *quit, *bbox, *grid, *rescan;
|
||||||
|
RescanBatch *batch_data;
|
||||||
|
gs_unref_ptrarray GPtrArray *all_active_wifi_devices;
|
||||||
|
|
||||||
newtGetScreenSize(&screen_width, &screen_height);
|
newtGetScreenSize(&screen_width, &screen_height);
|
||||||
|
|
||||||
|
|
@ -372,6 +616,17 @@ nmt_connect_connection_list(gboolean is_top)
|
||||||
listbox_active_changed(G_OBJECT(list), NULL, activate);
|
listbox_active_changed(G_OBJECT(list), NULL, activate);
|
||||||
g_signal_connect(activate, "clicked", G_CALLBACK(activate_clicked), list);
|
g_signal_connect(activate, "clicked", G_CALLBACK(activate_clicked), list);
|
||||||
|
|
||||||
|
all_active_wifi_devices = active_wifi_devices();
|
||||||
|
if (all_active_wifi_devices && all_active_wifi_devices->len > 0) {
|
||||||
|
rescan = nmt_newt_button_box_add_start(NMT_NEWT_BUTTON_BOX(bbox), _("Rescan Wi-Fi"));
|
||||||
|
|
||||||
|
batch_data = g_new0(RescanBatch, 1);
|
||||||
|
batch_data->activate_button = activate;
|
||||||
|
batch_data->listbox = list;
|
||||||
|
batch_data->rescan_button = rescan;
|
||||||
|
g_signal_connect(rescan, "clicked", G_CALLBACK(wifi_rescan), batch_data);
|
||||||
|
}
|
||||||
|
|
||||||
quit = nmt_newt_button_box_add_end(NMT_NEWT_BUTTON_BOX(bbox), is_top ? _("Quit") : _("Back"));
|
quit = nmt_newt_button_box_add_end(NMT_NEWT_BUTTON_BOX(bbox), is_top ? _("Quit") : _("Back"));
|
||||||
nmt_newt_widget_set_exit_on_activate(quit, TRUE);
|
nmt_newt_widget_set_exit_on_activate(quit, TRUE);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
#ifndef NMTUI_CONNECT_H
|
#ifndef NMTUI_CONNECT_H
|
||||||
#define NMTUI_CONNECT_H
|
#define NMTUI_CONNECT_H
|
||||||
|
|
||||||
|
#define RESCAN_TIMEOUT_MS 10000
|
||||||
|
|
||||||
NmtNewtForm *nmtui_connect(gboolean is_top, int argc, char **argv);
|
NmtNewtForm *nmtui_connect(gboolean is_top, int argc, char **argv);
|
||||||
|
|
||||||
#endif /* NMTUI_CONNECT_H */
|
#endif /* NMTUI_CONNECT_H */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue