tui: various fixes

https://bugzilla.gnome.org/show_bug.cgi?id=720844
This commit is contained in:
Dan Winship 2014-01-16 09:19:07 -05:00
commit 86e14fd6a9
19 changed files with 460 additions and 382 deletions

3
.gitignore vendored
View file

@ -217,9 +217,6 @@ valgrind-*.log
/tui/newt/libnmt-newt.a
/tui/nmtui
/tui/nmtui-connect
/tui/nmtui-edit
/tui/nmtui-hostname
/tools/generate-settings-spec

View file

@ -54,6 +54,24 @@ _nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value)
g_value_take_boxed (dest_value, g_slist_reverse (list));
}
static void
_nm_utils_convert_slist_to_strv (const GValue *src_value, GValue *dest_value)
{
GSList *slist;
char **strv;
int len, i = 0;
slist = g_value_get_boxed (src_value);
len = g_slist_length (slist);
strv = g_new (char *, len + 1);
for (i = 0; slist; slist = slist->next, i++)
strv[i] = g_strdup (slist->data);
strv[i] = NULL;
g_value_take_boxed (dest_value, strv);
}
static void
_nm_utils_convert_strv_to_ptrarray (const GValue *src_value, GValue *dest_value)
{
@ -529,6 +547,9 @@ _nm_value_transforms_register (void)
g_value_register_transform_func (G_TYPE_STRV,
DBUS_TYPE_G_LIST_OF_STRING,
_nm_utils_convert_strv_to_slist);
g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
G_TYPE_STRV,
_nm_utils_convert_slist_to_strv);
g_value_register_transform_func (G_TYPE_STRV,
DBUS_TYPE_G_ARRAY_OF_STRING,
_nm_utils_convert_strv_to_ptrarray);

View file

@ -18,18 +18,15 @@ AM_CPPFLAGS= \
$(NULL)
bin_PROGRAMS = nmtui
noinst_SCRIPTS = nmtui-edit nmtui-connect nmtui-hostname
$(noinst_SCRIPTS):
ln -s nmtui $@
links = nmtui-edit nmtui-connect nmtui-hostname
install-exec-hook:
for link in $(noinst_SCRIPTS); do \
for link in $(links); do \
ln -f $(DESTDIR)$(bindir)/nmtui $(DESTDIR)$(bindir)/$$link; \
done
uninstall-hook:
for link in $(noinst_SCRIPTS); do \
for link in $(links); do \
rm -f $(DESTDIR)$(bindir)/$$link; \
done
@ -126,6 +123,4 @@ nmtui_LDADD = \
$(GLIB_LIBS) \
$(NULL)
CLEANFILES = $(noinst_SCRIPTS)
endif

View file

@ -291,14 +291,10 @@ nmt_newt_button_box_size_allocate (NmtNewtWidget *widget,
nmt_newt_widget_size_request (child, &child_width, &child_height);
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
nmt_newt_widget_size_allocate (child,
child_x, child_y + (height - child_height) / 2,
child_width, child_height);
nmt_newt_widget_size_allocate (child, child_x, child_y, child_width, child_height);
child_x += child_width + 1;
} else {
nmt_newt_widget_size_allocate (child,
child_x + (width - child_width) / 2, child_y,
child_width, child_height);
nmt_newt_widget_size_allocate (child, child_x, child_y, child_width, child_height);
child_y += child_height + 1;
}
}
@ -314,14 +310,12 @@ nmt_newt_button_box_size_allocate (NmtNewtWidget *widget,
if (priv->orientation == NMT_NEWT_BUTTON_BOX_HORIZONTAL) {
nmt_newt_widget_size_allocate (child,
child_x - child_width,
child_y + (height - child_height) / 2,
child_x - child_width, child_y,
child_width, child_height);
child_x -= child_width + 1;
} else {
nmt_newt_widget_size_allocate (child,
child_x + (width - child_width) / 2,
child_y - child_height,
child_x, child_y - child_height,
child_width, child_height);
child_y -= child_height + 1;
}

View file

@ -273,8 +273,6 @@ nmt_newt_form_iterate (NmtNewtForm *form)
newtFormSetTimer (priv->form, 1);
newtFormRun (priv->form, &es);
if (es.reason == NEWT_EXIT_TIMER)
return;
if ( es.reason == NEWT_EXIT_HOTKEY
|| es.reason == NEWT_EXIT_ERROR) {

View file

@ -95,7 +95,7 @@ nmt_newt_textbox_set_text (NmtNewtTextbox *textbox,
{
NmtNewtTextboxPrivate *priv = NMT_NEWT_TEXTBOX_GET_PRIVATE (textbox);
char **lines;
int i, len;
int i, width;
if (!text)
text = "";
@ -108,9 +108,9 @@ nmt_newt_textbox_set_text (NmtNewtTextbox *textbox,
priv->width = priv->height = 0;
lines = g_strsplit (priv->text, "\n", -1);
for (i = 0; lines[i]; i++) {
len = g_utf8_strlen (lines[i], -1);
if (len > priv->width)
priv->width = len;
width = nmt_newt_text_width (lines[i]);
if (width > priv->width)
priv->width = width;
}
g_free (lines);
priv->height = MIN (i, 1);

View file

@ -32,10 +32,10 @@
#include "nmt-newt-utils.h"
static void
nmt_newt_g_log_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
nmt_newt_dialog_g_log_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
{
const char *level_name;
char *full_message;
@ -98,16 +98,22 @@ nmt_newt_g_log_handler (const char *log_domain,
newtPopWindow ();
}
static void
nmt_newt_basic_g_log_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
{
newtSuspend ();
g_log_default_handler (log_domain, log_level, message, NULL);
newtResume ();
}
/**
* nmt_newt_init:
*
* Wrapper for newtInit() that also does some nmt-newt-internal setup.
* This should be called once, before any other nmt-newt functions.
*
* FIXME: Currently this also calls g_log_set_default_handler() to set
* up a log handler that displays g_warning()s and the like as pop-up
* windows, but in the long run that should only happen for
* debug/developer builds.
*/
void
nmt_newt_init (void)
@ -121,7 +127,10 @@ nmt_newt_init (void)
newtSetColor (NMT_NEWT_COLORSET_DISABLED_BUTTON, "blue", "lightgray");
newtSetColor (NMT_NEWT_COLORSET_TEXTBOX_WITH_BACKGROUND, "black", "white");
g_log_set_default_handler (nmt_newt_g_log_handler, NULL);
if (g_getenv ("NMTUI_DEBUG"))
g_log_set_default_handler (nmt_newt_dialog_g_log_handler, NULL);
else
g_log_set_default_handler (nmt_newt_basic_g_log_handler, NULL);
}
/**
@ -133,22 +142,20 @@ void
nmt_newt_finished (void)
{
newtFinished ();
g_log_set_default_handler (nmt_newt_g_log_handler, g_log_default_handler);
g_log_set_default_handler (g_log_default_handler, NULL);
}
/**
* nmt_newt_error_dialog:
* nmt_newt_message_dialog:
* @message: a printf()-style message format
* @...: arguments
*
* Displays the given message in a dialog box with a single "OK"
* button, and returns after the user clicks "OK".
*
* FIXME: it's not just for errors any more!
*/
void
nmt_newt_error_dialog (const char *message,
...)
nmt_newt_message_dialog (const char *message,
...)
{
va_list ap;
char *msg, *msg_lc, *ok_lc;
@ -252,6 +259,37 @@ nmt_newt_locale_from_utf8 (const char *str_utf8)
return str_lc;
}
/**
* nmt_newt_text_width
* @str: a UTF-8 string
*
* Computes the width (in terminal columns) of @str.
*
* Returns: the width of @str
*/
int
nmt_newt_text_width (const char *str)
{
int width;
gunichar ch;
for (width = 0; *str; str = g_utf8_next_char (str)) {
ch = g_utf8_get_char (str);
/* Based on _vte_iso2022_unichar_width */
if (G_LIKELY (ch < 0x80))
width += 1;
else if (G_UNLIKELY (g_unichar_iszerowidth (ch)))
width += 0;
else if (G_UNLIKELY (g_unichar_iswide (ch)))
width += 2;
else
width += 1;
}
return width;
}
/**
* nmt_newt_edit_string:
* @data: data to edit
@ -275,7 +313,7 @@ nmt_newt_edit_string (const char *data)
fd = g_file_open_tmp ("XXXXXX.json", &filename, &error);
if (fd == -1) {
nmt_newt_error_dialog (_("Could not create temporary file: %s"), error->message);
nmt_newt_message_dialog (_("Could not create temporary file: %s"), error->message);
g_error_free (error);
return NULL;
}
@ -307,19 +345,19 @@ nmt_newt_edit_string (const char *data)
newtResume ();
if (error) {
nmt_newt_error_dialog (_("Could not create temporary file: %s"), error->message);
nmt_newt_message_dialog (_("Could not create temporary file: %s"), error->message);
g_error_free (error);
goto done;
}
if (!g_spawn_check_exit_status (status, &error)) {
nmt_newt_error_dialog (_("Editor failed: %s"), error->message);
nmt_newt_message_dialog (_("Editor failed: %s"), error->message);
g_error_free (error);
goto done;
}
if (!g_file_get_contents (filename, &new_data, NULL, &error)) {
nmt_newt_error_dialog (_("Could not re-read file: %s"), error->message);
nmt_newt_message_dialog (_("Could not re-read file: %s"), error->message);
g_error_free (error);
goto done;
}

View file

@ -37,8 +37,10 @@ typedef enum {
char *nmt_newt_locale_to_utf8 (const char *str_lc);
char *nmt_newt_locale_from_utf8 (const char *str_utf8);
void nmt_newt_error_dialog (const char *message,
...);
int nmt_newt_text_width (const char *str);
void nmt_newt_message_dialog (const char *message,
...);
int nmt_newt_choice_dialog (const char *button1,
const char *button2,
const char *message,

View file

@ -1634,33 +1634,3 @@ nm_editor_bind_vlan_name (NMSettingVlan *s_vlan)
binding->last_ifname_id = 0;
}
}
#define DBUS_TYPE_G_LIST_OF_STRING (dbus_g_type_get_collection ("GSList", G_TYPE_STRING))
static void
convert_slist_to_strv (const GValue *src_value, GValue *dest_value)
{
GSList *slist;
char **strv;
int len, i = 0;
slist = g_value_get_boxed (src_value);
len = g_slist_length (slist);
strv = g_new (char *, len + 1);
for (i = 0; slist; slist = slist->next, i++)
strv[i] = g_strdup (slist->data);
strv[i] = NULL;
g_value_take_boxed (dest_value, strv);
}
void
nm_editor_bindings_init (void)
{
/* FIXME: libnm registers strv->list, but not list->strv */
g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
G_TYPE_STRV,
convert_slist_to_strv);
}

View file

@ -26,8 +26,6 @@
G_BEGIN_DECLS
void nm_editor_bindings_init (void);
void nm_editor_bind_ip4_addresses_with_prefix_to_strv (gpointer source,
const gchar *source_property,
gpointer target,

View file

@ -35,9 +35,6 @@
#include "nmtui.h"
#include "nmt-connect-connection-list.h"
#include "nmt-utils.h"
#include "nmt-password-dialog.h"
#include "nmt-secret-agent.h"
#include "nm-ui-utils.h"
G_DEFINE_TYPE (NmtConnectConnectionList, nmt_connect_connection_list, NMT_TYPE_NEWT_LISTBOX)
@ -60,6 +57,7 @@ typedef struct {
NMConnection *conn;
NMAccessPoint *ap;
NMDevice *device;
NMActiveConnection *active;
} NmtConnectConnection;
typedef struct {
@ -92,6 +90,7 @@ nmt_connect_connection_free (NmtConnectConnection *nmtconn)
{
g_clear_object (&nmtconn->conn);
g_clear_object (&nmtconn->ap);
g_clear_object (&nmtconn->active);
g_free (nmtconn->ssid);
}
@ -377,9 +376,9 @@ sort_nmt_devices (gconstpointer a,
return strcmp (nmta->name, nmtb->name);
}
static gboolean
connection_is_active (NMConnection *conn,
const GPtrArray *acs)
static NMActiveConnection *
connection_find_ac (NMConnection *conn,
const GPtrArray *acs)
{
NMActiveConnection *ac;
const char *path, *ac_path;
@ -391,10 +390,10 @@ connection_is_active (NMConnection *conn,
ac_path = nm_active_connection_get_connection (ac);
if (!strcmp (path, ac_path))
return TRUE;
return ac;
}
return FALSE;
return NULL;
}
static void
@ -437,7 +436,7 @@ nmt_connect_connection_list_rebuild (NmtConnectConnectionList *list)
for (citer = nmtdev->conns; citer; citer = citer->next) {
nmtconn = citer->data;
max_width = MAX (max_width, g_utf8_strlen (nmtconn->name, -1));
max_width = MAX (max_width, nmt_newt_text_width (nmtconn->name));
}
}
@ -451,9 +450,12 @@ nmt_connect_connection_list_rebuild (NmtConnectConnectionList *list)
for (citer = nmtdev->conns; citer; citer = citer->next) {
nmtconn = citer->data;
if (nmtconn->conn && connection_is_active (nmtconn->conn, acs))
if (nmtconn->conn)
nmtconn->active = connection_find_ac (nmtconn->conn, acs);
if (nmtconn->active) {
g_object_ref (nmtconn->active);
active_col = '*';
else
} else
active_col = ' ';
if (nmtconn->ap) {
@ -475,7 +477,7 @@ nmt_connect_connection_list_rebuild (NmtConnectConnectionList *list)
row = g_strdup_printf ("%c %s%-*s%s",
active_col,
nmtconn->name,
(int)(max_width - g_utf8_strlen (nmtconn->name, -1)), "",
(int)(max_width - nmt_newt_text_width (nmtconn->name)), "",
strength_col);
nmt_newt_listbox_append (listbox, row, nmtconn);
@ -484,6 +486,9 @@ nmt_connect_connection_list_rebuild (NmtConnectConnectionList *list)
}
priv->nmt_devices = nmt_devices;
g_object_notify (G_OBJECT (listbox), "active");
g_object_notify (G_OBJECT (listbox), "active-key");
}
static void
@ -532,211 +537,39 @@ nmt_connect_connection_list_finalize (GObject *object)
G_OBJECT_CLASS (nmt_connect_connection_list_parent_class)->finalize (object);
}
typedef struct {
NmtNewtForm *form;
NMSecretAgent *agent;
} NmtActivationData;
static void
nmt_activation_data_free (NmtActivationData *data)
{
g_object_unref (data->form);
g_object_unref (data->agent);
g_slice_free (NmtActivationData, data);
}
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
activation_complete (GSimpleAsyncResult *simple,
GError *error)
{
NmtActivationData *data = g_object_get_data (G_OBJECT (simple), "NmtActivationData");
if (error)
g_simple_async_result_set_from_error (simple, error);
else
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
g_simple_async_result_complete (simple);
g_object_unref (simple);
nmt_newt_form_quit (data->form);
/* If we bail out too soon, the agent won't have completed registering,
* and nm_secret_agent_unregister() would complain.
*/
if (nm_secret_agent_get_registered (data->agent))
nm_secret_agent_unregister (data->agent);
}
static void
activate_ac_state_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
GSimpleAsyncResult *simple = 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), simple);
g_object_unref (object);
activation_complete (simple, error);
g_clear_error (&error);
}
static void
activation_callback (NMClient *client,
NMActiveConnection *ac,
GError *error,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
if (error || nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
activation_complete (simple, error);
return;
}
g_object_ref (ac);
g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_STATE,
G_CALLBACK (activate_ac_state_changed), simple);
}
static void
activate_nmt_connection_async (NmtConnectConnectionList *list,
NmtConnectConnection *nmtconn,
GAsyncReadyCallback callback,
gpointer user_data)
{
NmtActivationData *data;
NmtNewtWidget *label;
GSimpleAsyncResult *simple;
data = g_slice_new (NmtActivationData);
data->form = g_object_new (NMT_TYPE_NEWT_FORM, NULL);
label = nmt_newt_label_new (_("Connecting..."));
nmt_newt_form_set_content (data->form, label);
data->agent = nmt_secret_agent_new ();
nm_secret_agent_register (data->agent);
g_signal_connect (data->agent, "request-secrets",
G_CALLBACK (secrets_requested), NULL);
simple = g_simple_async_result_new (G_OBJECT (list), callback, user_data,
activate_nmt_connection_async);
g_object_set_data_full (G_OBJECT (simple), "NmtActivationData", data,
(GDestroyNotify)nmt_activation_data_free);
/* FIXME: cancel button */
nm_client_activate_connection (nm_client,
nmtconn->conn, nmtconn->device,
nmtconn->ap ? nm_object_get_path (NM_OBJECT (nmtconn->ap)) : NULL,
activation_callback, simple);
nmt_newt_form_show (data->form);
}
static gboolean
activate_nmt_connection_finish (NmtConnectConnectionList *list,
GAsyncResult *result,
GError **error)
{
return g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
}
static void
activate_complete (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NmtSyncOp *op = user_data;
GError *error = NULL;
if (activate_nmt_connection_finish (NMT_CONNECT_CONNECTION_LIST (object), result, &error))
nmt_sync_op_complete_boolean (op, TRUE, NULL);
else
nmt_sync_op_complete_boolean (op, FALSE, error);
g_clear_error (&error);
}
static void
nmt_connect_connection_list_activated (NmtNewtWidget *widget)
{
NmtConnectConnection *nmtconn;
NmtSyncOp op;
GError *error = NULL;
nmtconn = nmt_newt_listbox_get_active_key (NMT_NEWT_LISTBOX (widget));
g_return_if_fail (nmtconn != NULL);
nmt_sync_op_init (&op);
activate_nmt_connection_async (NMT_CONNECT_CONNECTION_LIST (widget), nmtconn,
activate_complete, &op);
if (!nmt_sync_op_wait_boolean (&op, &error)) {
nmt_newt_error_dialog (_("Could not activate connection: %s"), error->message);
g_error_free (error);
}
}
static void
nmt_connect_connection_list_class_init (NmtConnectConnectionListClass *list_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (list_class);
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (list_class);
g_type_class_add_private (list_class, sizeof (NmtConnectConnectionListPrivate));
/* virtual methods */
object_class->constructed = nmt_connect_connection_list_constructed;
object_class->finalize = nmt_connect_connection_list_finalize;
widget_class->activated = nmt_connect_connection_list_activated;
}
/**
* nmt_connect_connection_list_activate_async:
* nmt_connect_connection_list_get_connection:
* @list: an #NmtConnectConnectionList
* @identifier: a connection ID or UUID
* @callback: #GAsyncReadyCallback
* @user_data: data for @callback
* @identifier: a connection ID or UUID, or device name
* @connection: (out) (transfer none): the #NMConnection to be activated
* @device: (out) (transfer none): the #NMDevice to activate @connection on
* @specific_object: (out) (transfer none): the "specific object" to connect to
* @active: (out) (transfer none): the #NMActiveConnection corresponding
* to the selection, if any.
*
* Asynchronously begins to activate the connection identified by
* @identifier, and invokes @callback when it completes.
* Gets information about the indicated connection.
*
* Returns: %TRUE if there was a match, %FALSE if not.
*/
void
nmt_connect_connection_list_activate_async (NmtConnectConnectionList *list,
const char *identifier,
GAsyncReadyCallback callback,
gpointer user_data)
gboolean
nmt_connect_connection_list_get_connection (NmtConnectConnectionList *list,
const char *identifier,
NMConnection **connection,
NMDevice **device,
NMObject **specific_object,
NMActiveConnection **active)
{
NmtConnectConnectionListPrivate *priv = NMT_CONNECT_CONNECTION_LIST_GET_PRIVATE (list);
GSList *diter, *citer;
@ -770,42 +603,66 @@ nmt_connect_connection_list_activate_async (NmtConnectConnectionList *list,
nmtconn = citer->data;
if (conn) {
if (conn == nmtconn->conn)
goto activate;
else
continue;
}
if (nmtconn->ssid && !strcmp (identifier, nmtconn->ssid))
goto activate;
goto found;
} else if (nmtconn->ssid && !strcmp (identifier, nmtconn->ssid))
goto found;
}
if (!conn && !nmtdev->device && !strcmp (identifier, nm_device_get_ip_iface (nmtdev->device))) {
if (!conn && nmtdev->device && !strcmp (identifier, nm_device_get_ip_iface (nmtdev->device))) {
nmtconn = nmtdev->conns->data;
goto activate;
goto found;
}
}
g_printerr ("%s: no such connection '%s'\n", g_get_prgname (), identifier);
exit (1);
return FALSE;
activate:
activate_nmt_connection_async (list, nmtconn, callback, user_data);
found:
if (connection)
*connection = nmtconn->conn;
if (device)
*device = nmtconn->device;
if (specific_object)
*specific_object = NM_OBJECT (nmtconn->ap);
if (active)
*active = nmtconn->active;
return TRUE;
}
/**
* nmt_connect_connection_list_activate_finish:
* nmt_connect_connection_list_get_selection:
* @list: an #NmtConnectConnectionList
* @result: the #GAsyncResult passed to the callback
* @error: return location for a #GError
* @connection: (out) (transfer none): the #NMConnection to be activated
* @device: (out) (transfer none): the #NMDevice to activate @connection on
* @specific_object: (out) (transfer none): the "specific object" to connect to
* @active: (out) (transfer none): the #NMActiveConnection corresponding
* to the selection, if any.
*
* Gets the result of an nmt_connect_connection_list_activate_async() call.
* Gets information about the selected row.
*
* Returns: success or failure
* Returns: %TRUE if there is a selection, %FALSE if not.
*/
gboolean
nmt_connect_connection_list_activate_finish (NmtConnectConnectionList *list,
GAsyncResult *result,
GError **error)
nmt_connect_connection_list_get_selection (NmtConnectConnectionList *list,
NMConnection **connection,
NMDevice **device,
NMObject **specific_object,
NMActiveConnection **active)
{
return g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
NmtConnectConnection *nmtconn;
nmtconn = nmt_newt_listbox_get_active_key (NMT_NEWT_LISTBOX (list));
if (!nmtconn)
return FALSE;
if (connection)
*connection = nmtconn->conn;
if (device)
*device = nmtconn->device;
if (specific_object)
*specific_object = NM_OBJECT (nmtconn->ap);
if (active)
*active = nmtconn->active;
return TRUE;
}

View file

@ -42,16 +42,19 @@ typedef struct {
GType nmt_connect_connection_list_get_type (void);
NmtNewtWidget *nmt_connect_connection_list_new (void);
void nmt_connect_connection_list_activate_async (NmtConnectConnectionList *list,
const char *identifier,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean nmt_connect_connection_list_activate_finish (NmtConnectConnectionList *list,
GAsyncResult *result,
GError **error);
NmtNewtWidget *nmt_connect_connection_list_new (void);
gboolean nmt_connect_connection_list_get_connection (NmtConnectConnectionList *list,
const char *identifier,
NMConnection **connection,
NMDevice **device,
NMObject **specific_object,
NMActiveConnection **active);
gboolean nmt_connect_connection_list_get_selection (NmtConnectConnectionList *list,
NMConnection **connection,
NMDevice **device,
NMObject **specific_object,
NMActiveConnection **active);
G_END_DECLS

View file

@ -78,12 +78,12 @@ nmt_editor_new (NMConnection *connection)
s_con = nm_connection_get_setting_connection (connection);
if (s_con) {
nmt_newt_error_dialog (_("Could not create editor for connection '%s' of type '%s'."),
nm_connection_get_id (connection),
nm_setting_connection_get_connection_type (s_con));
nmt_newt_message_dialog (_("Could not create editor for connection '%s' of type '%s'."),
nm_connection_get_id (connection),
nm_setting_connection_get_connection_type (s_con));
} else {
nmt_newt_error_dialog (_("Could not create editor for invalid connection '%s'."),
nm_connection_get_id (connection));
nmt_newt_message_dialog (_("Could not create editor for invalid connection '%s'."),
nm_connection_get_id (connection));
}
return NULL;
@ -131,7 +131,7 @@ save_connection_and_exit (NmtNewtButton *button,
if (!nm_connection_replace_settings_from_connection (priv->orig_connection,
priv->edit_connection,
&error)) {
nmt_newt_error_dialog (_("Error saving connection: %s"), error->message);
nmt_newt_message_dialog (_("Error saving connection: %s"), error->message);
g_error_free (error);
return;
}
@ -141,8 +141,8 @@ save_connection_and_exit (NmtNewtButton *button,
nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (priv->orig_connection),
connection_updated, &op);
if (!nmt_sync_op_wait_boolean (&op, &error)) {
nmt_newt_error_dialog (_("Unable to save connection: %s"),
error->message);
nmt_newt_message_dialog (_("Unable to save connection: %s"),
error->message);
g_error_free (error);
return;
}
@ -155,8 +155,8 @@ save_connection_and_exit (NmtNewtButton *button,
nm_remote_settings_add_connection (nm_settings, priv->orig_connection,
connection_added, &op);
if (!nmt_sync_op_wait_boolean (&op, &error)) {
nmt_newt_error_dialog (_("Unable to add new connection: %s"),
error->message);
nmt_newt_message_dialog (_("Unable to add new connection: %s"),
error->message);
g_error_free (error);
return;
}

View file

@ -211,13 +211,13 @@ nmt_route_table_init (NmtRouteTable *table)
NmtRouteTablePrivate *priv = NMT_ROUTE_TABLE_GET_PRIVATE (table);
NmtNewtWidget *header, *empty;
NmtNewtWidget *dest_prefix_label, *next_hop_label, *metric_label;
int dest_prefix_len, next_hop_len, metric_len;
int dest_prefix_width, next_hop_width, metric_width;
char *text;
header = nmt_newt_grid_new ();
text = g_strdup_printf ("%s/%s", _("Destination"), _("Prefix"));
dest_prefix_len = g_utf8_strlen (text, -1);
dest_prefix_width = nmt_newt_text_width (text);
dest_prefix_label = g_object_new (NMT_TYPE_NEWT_LABEL,
"text", text,
"style", NMT_NEWT_LABEL_PLAIN,
@ -230,7 +230,7 @@ nmt_route_table_init (NmtRouteTable *table)
"text", text,
"style", NMT_NEWT_LABEL_PLAIN,
NULL);
next_hop_len = g_utf8_strlen (text, -1);
next_hop_width = nmt_newt_text_width (text);
nmt_newt_grid_add (NMT_NEWT_GRID (header), next_hop_label, 1, 0);
text = _("Metric");
@ -238,18 +238,18 @@ nmt_route_table_init (NmtRouteTable *table)
"text", text,
"style", NMT_NEWT_LABEL_PLAIN,
NULL);
metric_len = g_utf8_strlen (text, -1);
metric_width = nmt_newt_text_width (text);
nmt_newt_grid_add (NMT_NEWT_GRID (header), metric_label, 2, 0);
priv->ip_entry_width = MAX (20, MAX (dest_prefix_len, next_hop_len));
priv->metric_entry_width = MAX (7, metric_len);
priv->ip_entry_width = MAX (20, MAX (dest_prefix_width, next_hop_width));
priv->metric_entry_width = MAX (7, metric_width);
nmt_newt_widget_set_padding (dest_prefix_label,
0, 0, priv->ip_entry_width - dest_prefix_len, 0);
0, 0, priv->ip_entry_width - dest_prefix_width, 0);
nmt_newt_widget_set_padding (next_hop_label,
2, 0, priv->ip_entry_width - next_hop_len, 0);
2, 0, priv->ip_entry_width - next_hop_width, 0);
nmt_newt_widget_set_padding (metric_label,
2, 0, priv->metric_entry_width - metric_len, 0);
2, 0, priv->metric_entry_width - metric_width, 0);
nmt_newt_grid_add (NMT_NEWT_GRID (table), header, 0, 0);

View file

@ -447,7 +447,8 @@ nmt_secret_agent_get_secrets (NMSecretAgent *agent,
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
"Request for %s secrets already pending", request_id);
nope:
callback (agent, connection, NULL, NULL, callback_data);
callback (agent, connection, NULL, error, callback_data);
g_error_free (error);
g_free (request_id);
return;
}

View file

@ -39,40 +39,201 @@
#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
connect_complete (GObject *object,
GAsyncResult *result,
gpointer user_data)
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;
if (nmt_connect_connection_list_activate_finish (NMT_CONNECT_CONNECTION_LIST (object),
result, &error))
nmt_sync_op_complete_boolean (op, TRUE, NULL);
else
nmt_sync_op_complete_boolean (op, FALSE, error);
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
nmt_connect_connection (const char *identifier)
activate_callback (NMClient *client,
NMActiveConnection *ac,
GError *error,
gpointer user_data)
{
NmtNewtWidget *list;
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
add_and_activate_callback (NMClient *client,
NMActiveConnection *ac,
const char *new_connection_path,
GError *error,
gpointer user_data)
{
/* We don't care about @new_connection_path, so... */
activate_callback (client, ac, error, user_data);
}
static void
activate_connection (NMConnection *connection,
NMDevice *device,
NMObject *specific_object)
{
NmtNewtForm *form;
NMSecretAgent *agent;
NmtNewtWidget *label;
NmtSyncOp op;
const char *specific_object_path;
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);
specific_object_path = specific_object ? nm_object_get_path (specific_object) : NULL;
/* FIXME: cancel button */
nmt_sync_op_init (&op);
list = nmt_connect_connection_list_new ();
nmt_connect_connection_list_activate_async (NMT_CONNECT_CONNECTION_LIST (list), identifier,
connect_complete, &op);
if (connection) {
nm_client_activate_connection (nm_client,
connection, device, specific_object_path,
activate_callback, &op);
} else {
nm_client_add_and_activate_connection (nm_client,
NULL, device, specific_object_path,
add_and_activate_callback, &op);
}
nmt_newt_form_show (form);
if (!nmt_sync_op_wait_boolean (&op, &error)) {
nmt_newt_error_dialog (_("Could not activate connection: %s"), error->message);
nmt_newt_message_dialog (_("Could not activate connection: %s"), error->message);
g_error_free (error);
}
g_object_unref (list);
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
@ -104,13 +265,17 @@ nmt_connect_connection_list (void)
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);
// FIXME: the activate button doesn't do anything
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);
@ -120,6 +285,32 @@ nmt_connect_connection_list (void)
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)
{

View file

@ -440,9 +440,8 @@ connection_deleted_callback (NMRemoteConnection *connection,
ConnectionDeleteData *data = user_data;
if (error) {
nmt_newt_error_dialog (_("OK"),
_("Unable to delete connection: %s"),
error->message);
nmt_newt_message_dialog (_("Unable to delete connection: %s"),
error->message);
} else
data->got_callback = TRUE;
@ -484,8 +483,8 @@ nmt_remove_connection (NMRemoteConnection *connection)
nm_remote_connection_delete (connection, connection_deleted_callback, &data);
if (!nmt_sync_op_wait_boolean (&data.op, &error)) {
nmt_newt_error_dialog (_("Could not delete connection: %s"),
error->message);
nmt_newt_message_dialog (_("Could not delete connection: %s"),
error->message);
g_error_free (error);
}
@ -517,8 +516,9 @@ nmtui_edit (int argc, char **argv)
}
if (!conn) {
g_printerr ("%s: no such connection '%s'\n", argv[0], argv[1]);
exit (1);
nmt_newt_message_dialog ("%s: no such connection '%s'\n", argv[0], argv[1]);
nmtui_quit ();
return;
}
nmt_edit_connection (conn);

View file

@ -111,9 +111,9 @@ nmtui_hostname (int argc, char **argv)
nm_remote_settings_save_hostname (nm_settings, hostname, hostname_set, &op);
if (nmt_sync_op_wait_boolean (&op, &error)) {
/* Translators: this indicates the result. ie, "I have set the hostname to ..." */
nmt_newt_error_dialog (_("Set hostname to '%s'"), hostname);
nmt_newt_message_dialog (_("Set hostname to '%s'"), hostname);
} else {
nmt_newt_error_dialog (_("Unable to set hostname: %s"), error->message);
nmt_newt_message_dialog (_("Unable to set hostname: %s"), error->message);
g_error_free (error);
}

View file

@ -44,7 +44,6 @@
#include "nmtui-edit.h"
#include "nmtui-connect.h"
#include "nmtui-hostname.h"
#include "nm-editor-bindings.h"
NMClient *nm_client;
NMRemoteSettings *nm_settings;
@ -53,30 +52,37 @@ static GMainLoop *loop;
typedef void (*NmtuiSubprogram) (int argc, char **argv);
static const struct {
const char *name, *shortcut, *usage;
const char *name, *shortcut, *arg;
const char *display_name;
NmtuiSubprogram func;
} subprograms[] = {
{ "edit", "nmtui-edit", " [connection]",
{ "edit", "nmtui-edit", N_("connection"),
N_("Edit a connection"),
nmtui_edit },
{ "connect", "nmtui-connect", " [connection]",
{ "connect", "nmtui-connect", N_("connection"),
N_("Activate a connection"),
nmtui_connect },
{ "hostname", "nmtui-hostname", " [new hostname]",
{ "hostname", "nmtui-hostname", N_("new hostname"),
N_("Set system hostname"),
nmtui_hostname }
};
static const int num_subprograms = G_N_ELEMENTS (subprograms);
static void
quit_func (int argc, char **argv)
{
nmtui_quit ();
}
static void
nmtui_main (int argc, char **argv)
{
NmtNewtForm *form;
NmtNewtWidget *widget, *cancel, *ok;
NmtNewtWidget *widget, *ok;
NmtNewtGrid *grid;
NmtNewtListbox *listbox;
NmtNewtButtonBox *bbox;
NmtuiSubprogram subprogram;
int i;
form = g_object_new (NMT_TYPE_NEWT_FORM,
@ -91,7 +97,10 @@ nmtui_main (int argc, char **argv)
widget = nmt_newt_label_new (_("Please select an option"));
nmt_newt_grid_add (grid, widget, 0, 0);
widget = nmt_newt_listbox_new (num_subprograms, 0);
widget = g_object_new (NMT_TYPE_NEWT_LISTBOX,
"height", num_subprograms + 2,
"skip-null-keys", TRUE,
NULL);
nmt_newt_grid_add (grid, widget, 0, 1);
nmt_newt_widget_set_padding (widget, 0, 1, 0, 1);
nmt_newt_widget_set_exit_on_activate (widget, TRUE);
@ -101,24 +110,21 @@ nmtui_main (int argc, char **argv)
nmt_newt_listbox_append (listbox, _(subprograms[i].display_name),
subprograms[i].func);
}
nmt_newt_listbox_append (listbox, "", NULL);
nmt_newt_listbox_append (listbox, _("Quit"), quit_func);
widget = nmt_newt_button_box_new (NMT_NEWT_BUTTON_BOX_HORIZONTAL);
nmt_newt_grid_add (grid, widget, 0, 2);
bbox = NMT_NEWT_BUTTON_BOX (widget);
cancel = nmt_newt_button_box_add_end (bbox, _("Cancel"));
nmt_newt_widget_set_exit_on_activate (cancel, TRUE);
ok = nmt_newt_button_box_add_end (bbox, _("OK"));
nmt_newt_widget_set_exit_on_activate (ok, TRUE);
widget = nmt_newt_form_run_sync (form);
if (widget == ok || widget == (NmtNewtWidget *)listbox) {
NmtuiSubprogram subprogram = nmt_newt_listbox_get_active_key (listbox);
subprogram (argc, argv);
} else
nmtui_quit ();
nmt_newt_form_run_sync (form);
subprogram = nmt_newt_listbox_get_active_key (listbox);
g_object_unref (form);
subprogram (argc, argv);
}
/**
@ -145,19 +151,22 @@ static void
usage (void)
{
const char *argv0 = g_get_prgname ();
const char *usage = _("Usage");
int i;
for (i = 0; i < num_subprograms; i++) {
if (!strcmp (argv0, subprograms[i].shortcut)) {
g_printerr ("Usage: %s%s\n", argv0, subprograms[i].usage);
g_printerr ("%s: %s [%s]\n", usage, argv0, _(subprograms[i].arg));
exit (1);
}
}
g_printerr ("Usage: nmtui\n");
g_printerr ("%s: nmtui\n", usage);
for (i = 0; i < num_subprograms; i++) {
g_printerr (" nmtui %s%s\n", subprograms[i].name,
subprograms[i].usage);
g_printerr ("%*s nmtui %s [%s]\n",
nmt_newt_text_width (usage), " ",
subprograms[i].name,
_(subprograms[i].arg));
}
exit (1);
}
@ -207,13 +216,19 @@ main (int argc, char **argv)
g_option_context_add_main_entries (opts, entries, NULL);
if (!g_option_context_parse (opts, &argc, &argv, &error)) {
g_printerr ("%s: Could not parse arguments: %s\n",
argv[0], error->message);
g_printerr ("%s: %s: %s\n",
argv[0],
_("Could not parse arguments"),
error->message);
exit (1);
}
g_option_context_free (opts);
nm_client = nm_client_new ();
if (!nm_client_get_manager_running (nm_client)) {
g_printerr ("%s\n", _("NetworkManager is not running."));
exit (1);
}
nm_settings = nm_remote_settings_new (NULL);
g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ,
@ -224,8 +239,6 @@ main (int argc, char **argv)
if (sleep_on_startup)
sleep (5);
nm_editor_bindings_init ();
startup_data.subprogram = NULL;
prgname = g_get_prgname ();
if (g_str_has_prefix (prgname, "lt-"))