NetworkManager/tui/nmtui-connect.c

302 lines
9.2 KiB
C
Raw Normal View History

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* 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, see <http://www.gnu.org/licenses/>.
*
* Copyright 2013 Red Hat, Inc.
*/
/**
* SECTION:nmtui-connect
* @short_description: nm-applet-like functionality
*
* nmtui-connect implements activating #NMConnections, including
* presenting a password dialog if necessary.
*
* It's supposed to also implement deactivating them, but it doesn't.
* FIXME.
*/
#include "config.h"
#include <stdlib.h>
#include <glib/gi18n-lib.h>
#include <nm-utils.h>
#include "nmt-newt.h"
#include "nmtui.h"
#include "nmtui-connect.h"
#include "nmt-connect-connection-list.h"
#include "nmt-password-dialog.h"
#include "nmt-secret-agent.h"
#include "nmt-utils.h"
static void
secrets_requested (NmtSecretAgent *agent,
const char *request_id,
const char *title,
const char *msg,
GPtrArray *secrets,
gpointer user_data)
{
NmtNewtForm *form;
form = nmt_password_dialog_new (request_id, title, msg, secrets);
nmt_newt_form_run_sync (form);
if (nmt_password_dialog_succeeded (NMT_PASSWORD_DIALOG (form)))
nmt_secret_agent_response (agent, request_id, secrets);
else
nmt_secret_agent_response (agent, request_id, NULL);
g_object_unref (form);
}
static void
activate_ac_state_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
NmtSyncOp *op = user_data;
NMActiveConnectionState state;
GError *error = NULL;
state = nm_active_connection_get_state (NM_ACTIVE_CONNECTION (object));
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
return;
if (state != NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
error = g_error_new_literal (NM_CLIENT_ERROR, NM_CLIENT_ERROR_UNKNOWN,
_("Activation failed"));
}
g_signal_handlers_disconnect_by_func (object, G_CALLBACK (activate_ac_state_changed), op);
g_object_unref (object);
nmt_sync_op_complete_boolean (op, error == NULL, error);
g_clear_error (&error);
}
static void
activation_callback (NMClient *client,
NMActiveConnection *ac,
GError *error,
gpointer user_data)
{
NmtSyncOp *op = user_data;
if (error || nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nmt_sync_op_complete_boolean (op, error == NULL, error);
return;
}
g_object_ref (ac);
g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_STATE,
G_CALLBACK (activate_ac_state_changed), op);
}
static void
activate_connection (NMConnection *connection,
NMDevice *device,
NMObject *specific_object)
{
NmtNewtForm *form;
NMSecretAgent *agent;
NmtNewtWidget *label;
NmtSyncOp op;
GError *error = NULL;
form = g_object_new (NMT_TYPE_NEWT_FORM, NULL);
label = nmt_newt_label_new (_("Connecting..."));
nmt_newt_form_set_content (form, label);
agent = nmt_secret_agent_new ();
nm_secret_agent_register (agent);
g_signal_connect (agent, "request-secrets", G_CALLBACK (secrets_requested), NULL);
/* FIXME: cancel button */
nmt_sync_op_init (&op);
nm_client_activate_connection (nm_client,
connection, device,
specific_object ? nm_object_get_path (specific_object) : NULL,
activation_callback, &op);
nmt_newt_form_show (form);
if (!nmt_sync_op_wait_boolean (&op, &error)) {
nmt_newt_message_dialog (_("Could not activate connection: %s"), error->message);
g_error_free (error);
}
nmt_newt_form_quit (form);
g_object_unref (form);
/* If the activation failed very quickly, then agent won't be registered yet,
* and nm_secret_agent_unregister() would complain if we called it...
*/
if (nm_secret_agent_get_registered (agent))
nm_secret_agent_unregister (agent);
g_object_unref (agent);
}
static void
listbox_activated (NmtNewtListbox *listbox,
gpointer user_data)
{
NmtConnectConnectionList *list = NMT_CONNECT_CONNECTION_LIST (listbox);
NMConnection *connection;
NMDevice *device;
NMObject *specific_object;
NMActiveConnection *ac;
if (!nmt_connect_connection_list_get_selection (list,
&connection,
&device,
&specific_object,
&ac))
return;
if (ac)
nm_client_deactivate_connection (nm_client, ac);
else
activate_connection (connection, device, specific_object);
}
static void
activate_clicked (NmtNewtButton *button,
gpointer listbox)
{
listbox_activated (listbox, NULL);
}
static void
listbox_active_changed (GObject *object,
GParamSpec *pspec,
gpointer button)
{
NmtConnectConnectionList *list = NMT_CONNECT_CONNECTION_LIST (object);
static const char *activate, *deactivate;
static int deactivate_padding, activate_padding;
NMActiveConnection *ac;
gboolean has_selection;
if (G_UNLIKELY (activate == NULL)) {
int activate_width, deactivate_width;
activate = _("Activate");
activate_width = nmt_newt_text_width (activate);
deactivate = _("Deactivate");
deactivate_width = nmt_newt_text_width (deactivate);
activate_padding = MAX (0, deactivate_width - activate_width);
deactivate_padding = MAX (0, activate_width - deactivate_width);
}
has_selection = nmt_connect_connection_list_get_selection (list, NULL, NULL, NULL, &ac);
nmt_newt_component_set_sensitive (button, has_selection);
if (has_selection && ac) {
nmt_newt_button_set_label (button, deactivate);
nmt_newt_widget_set_padding (button, 0, 0, deactivate_padding, 0);
} else {
nmt_newt_button_set_label (button, activate);
nmt_newt_widget_set_padding (button, 0, 0, activate_padding, 0);
}
}
static void
quit_clicked (NmtNewtButton *button,
gpointer user_data)
{
nmtui_quit ();
}
static void
nmt_connect_connection_list (void)
{
int screen_width, screen_height;
NmtNewtForm *form;
NmtNewtWidget *list, *activate, *quit, *bbox, *grid;
newtGetScreenSize (&screen_width, &screen_height);
form = g_object_new (NMT_TYPE_NEWT_FORM,
"y", 2,
"height", screen_height - 4,
"escape-exits", TRUE,
NULL);
grid = nmt_newt_grid_new ();
list = nmt_connect_connection_list_new ();
nmt_newt_grid_add (NMT_NEWT_GRID (grid), list, 0, 0);
nmt_newt_grid_set_flags (NMT_NEWT_GRID (grid), list,
NMT_NEWT_GRID_FILL_X | NMT_NEWT_GRID_FILL_Y |
NMT_NEWT_GRID_EXPAND_X | NMT_NEWT_GRID_EXPAND_Y);
g_signal_connect (list, "activated", G_CALLBACK (listbox_activated), NULL);
bbox = nmt_newt_button_box_new (NMT_NEWT_BUTTON_BOX_VERTICAL);
nmt_newt_grid_add (NMT_NEWT_GRID (grid), bbox, 1, 0);
nmt_newt_widget_set_padding (bbox, 1, 1, 0, 1);
activate = nmt_newt_button_box_add_start (NMT_NEWT_BUTTON_BOX (bbox), _("Activate"));
g_signal_connect (list, "notify::active", G_CALLBACK (listbox_active_changed), activate);
listbox_active_changed (G_OBJECT (list), NULL, activate);
g_signal_connect (activate, "clicked", G_CALLBACK (activate_clicked), list);
quit = nmt_newt_button_box_add_end (NMT_NEWT_BUTTON_BOX (bbox), _("Quit"));
nmt_newt_widget_set_exit_on_activate (quit, TRUE);
g_signal_connect (quit, "clicked", G_CALLBACK (quit_clicked), NULL);
nmt_newt_form_set_content (form, grid);
nmt_newt_form_show (form);
g_object_unref (form);
}
static void
nmt_connect_connection (const char *identifier)
{
NmtNewtWidget *list;
NMConnection *connection;
NMDevice *device;
NMObject *specific_object;
NMActiveConnection *ac;
list = nmt_connect_connection_list_new ();
if (!nmt_connect_connection_list_get_connection (NMT_CONNECT_CONNECTION_LIST (list),
identifier,
&connection,
&device,
&specific_object,
&ac))
nmt_newt_message_dialog (_("No such connection '%s'"), identifier);
else if (ac)
nmt_newt_message_dialog (_("Connection is already active"));
else
activate_connection (connection, device, specific_object);
g_object_unref (list);
nmtui_quit ();
}
void
nmtui_connect (int argc, char **argv)
{
if (argc == 2)
nmt_connect_connection (argv[1]);
else
nmt_connect_connection_list ();
}