static int
sort_connections (gconstpointer  a,
                  gconstpointer  b)
{
	NmtConnectConnection *nmta = (NmtConnectConnection *)a;
	NmtConnectConnection *nmtb = (NmtConnectConnection *)b;

	/* If nmta and nmtb both have NMConnections, sort them by timestamp */
	if (nmta->conn && nmtb->conn) {
		NMSettingConnection *s_con_a, *s_con_b;
		guint64 time_a, time_b;

		s_con_a = nm_connection_get_setting_connection (nmta->conn);
		s_con_b = nm_connection_get_setting_connection (nmtb->conn);

		time_a = nm_setting_connection_get_timestamp (s_con_a);
		time_b = nm_setting_connection_get_timestamp (s_con_b);

		return (int) (time_b - time_a);
	}

	/* If one is an NMConnection and the other is an NMAccessPoint, the
	 * connection comes first.
	 */
	if (nmta->conn)
		return -1;
	else if (nmtb->conn)
		return 1;

	g_return_val_if_fail (nmta->ap && nmtb->ap, 0);

	/* If both are access points, then sort by strength */
	return nm_access_point_get_strength (nmtb->ap) - nm_access_point_get_strength (nmta->ap);
}
static void
connection_added (NMRemoteSettings *settings,
                  NMRemoteConnection *connection,
                  gpointer user_data)
{
	NMConnectionList *self = NM_CONNECTION_LIST (user_data);
	GtkTreeIter parent_iter, iter;
	NMSettingConnection *s_con;
	char *last_used;
	gboolean expand = TRUE;

	if (!get_parent_iter_for_connection (self, connection, &parent_iter))
		return;

	s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));

	last_used = format_last_used (nm_setting_connection_get_timestamp (s_con));

	gtk_tree_store_append (GTK_TREE_STORE (self->model), &iter, &parent_iter);
	gtk_tree_store_set (GTK_TREE_STORE (self->model), &iter,
	                    COL_ID, nm_setting_connection_get_id (s_con),
	                    COL_LAST_USED, last_used,
	                    COL_TIMESTAMP, nm_setting_connection_get_timestamp (s_con),
	                    COL_CONNECTION, connection,
	                    -1);

	g_free (last_used);

	if (self->displayed_type) {
		GType added_type;

		gtk_tree_model_get (self->model, &parent_iter,
		                    COL_GTYPE, &added_type,
		                    -1);
		if (added_type != self->displayed_type)
			expand = FALSE;
	}

	if (expand) {
		GtkTreePath *path, *filtered_path;

		path = gtk_tree_model_get_path (self->model, &parent_iter);
		filtered_path = gtk_tree_model_filter_convert_child_path_to_path (self->filter, path);
		gtk_tree_view_expand_row (self->connection_list, filtered_path, FALSE);
		gtk_tree_path_free (filtered_path);
		gtk_tree_path_free (path);
	}

	g_signal_connect (connection, NM_REMOTE_CONNECTION_REMOVED, G_CALLBACK (connection_removed), self);
	g_signal_connect (connection, NM_REMOTE_CONNECTION_UPDATED, G_CALLBACK (connection_updated), self);
	gtk_tree_model_filter_refilter (self->filter);
}
/* Print details of connection */
static void
show_connection (NMConnection *connection)
{
	NMSettingConnection *s_con;
	guint64 timestamp;
	char *timestamp_str;
	char timestamp_real_str[64];
	const char *val1, *val2, *val3, *val3a, *val4, *val5;

	s_con = nm_connection_get_setting_connection (connection);
	if (s_con) {
		/* Get various info from NMSettingConnection and show it */
		timestamp = nm_setting_connection_get_timestamp (s_con);
		timestamp_str = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
		strftime (timestamp_real_str, sizeof (timestamp_real_str), "%c", localtime ((time_t *) &timestamp));

		val1 = nm_setting_connection_get_id (s_con);
		val2 = nm_setting_connection_get_uuid (s_con);
		val3 = nm_setting_connection_get_connection_type (s_con);
		val3a = nm_setting_connection_get_interface_name (s_con);
		val4 = nm_connection_get_path (connection);
		val5 = timestamp ? timestamp_real_str : "never";

		printf ("%-25s | %s | %-15s | %10s | %-43s | %s\n", val1, val2, val3, val3a, val4, val5);

		g_free (timestamp_str);
	}
}
static void
update_connection_row (NMConnectionList *self,
                       GtkTreeIter *iter,
                       NMRemoteConnection *connection)
{
	NMSettingConnection *s_con;
	char *last_used, *id;

	s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
	g_assert (s_con);

	last_used = format_last_used (nm_setting_connection_get_timestamp (s_con));
	id = g_markup_escape_text (nm_setting_connection_get_id (s_con), -1);
	gtk_tree_store_set (GTK_TREE_STORE (self->model), iter,
	                    COL_ID, id,
	                    COL_LAST_USED, last_used,
	                    COL_TIMESTAMP, nm_setting_connection_get_timestamp (s_con),
	                    COL_CONNECTION, connection,
	                    -1);
	g_free (last_used);
	g_free (id);

	gtk_tree_model_filter_refilter (self->filter);
}
static void
get_property (GObject *object, guint prop_id,
              GValue *value, GParamSpec *pspec)
{
	NMSettingConnection *setting = NM_SETTING_CONNECTION (object);
	NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);

	switch (prop_id) {
	case PROP_ID:
		g_value_set_string (value, nm_setting_connection_get_id (setting));
		break;
	case PROP_UUID:
		g_value_set_string (value, nm_setting_connection_get_uuid (setting));
		break;
	case PROP_TYPE:
		g_value_set_string (value, nm_setting_connection_get_connection_type (setting));
		break;
	case PROP_PERMISSIONS:
		g_value_take_boxed (value, perm_permlist_to_stringlist (priv->permissions));
		break;
	case PROP_AUTOCONNECT:
		g_value_set_boolean (value, nm_setting_connection_get_autoconnect (setting));
		break;
	case PROP_TIMESTAMP:
		g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting));
		break;
	case PROP_READ_ONLY:
		g_value_set_boolean (value, nm_setting_connection_get_read_only (setting));
		break;
	case PROP_ZONE:
		g_value_set_string (value, nm_setting_connection_get_zone (setting));
		break;
	case PROP_MASTER:
		g_value_set_string (value, nm_setting_connection_get_master (setting));
		break;
	case PROP_SLAVE_TYPE:
		g_value_set_string (value, nm_setting_connection_get_slave_type (setting));
		break;
	case PROP_SECONDARIES:
		g_value_set_boxed (value, priv->secondaries);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
static void
update_last_used (CEPageDetails *page, NMConnection *connection)
{
        gchar *last_used = NULL;
        GDateTime *now = NULL;
        GDateTime *then = NULL;
        gint days;
        GTimeSpan diff;
        guint64 timestamp;
        NMSettingConnection *s_con;

        s_con = nm_connection_get_setting_connection (connection);
        if (s_con == NULL)
                goto out;
        timestamp = nm_setting_connection_get_timestamp (s_con);
        if (timestamp == 0) {
                last_used = g_strdup (_("Never"));
                goto out;
        }

        /* calculate the amount of time that has elapsed */
        now = g_date_time_new_now_utc ();
        then = g_date_time_new_from_unix_utc (timestamp);

        diff = g_date_time_difference  (now, then);
        days = diff / G_TIME_SPAN_DAY;
        if (days == 0)
                last_used = g_strdup (_("Today"));
        else if (days == 1)
                last_used = g_strdup (_("Yesterday"));
        else
                last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
out:
        panel_set_device_widget_details (CE_PAGE (page)->builder, "last_used", last_used);
        if (now != NULL)
                g_date_time_unref (now);
        if (then != NULL)
                g_date_time_unref (then);
        g_free (last_used);
}
static gchar *
get_last_used_string (NMConnection *connection)
{
        gchar *last_used = NULL;
        GDateTime *now = NULL;
        GDateTime *then = NULL;
        gint days;
        GTimeSpan diff;
        guint64 timestamp;
        NMSettingConnection *s_con;

        s_con = nm_connection_get_setting_connection (connection);
        if (s_con == NULL)
                goto out;
        timestamp = nm_setting_connection_get_timestamp (s_con);
        if (timestamp == 0) {
                last_used = g_strdup (_("never"));
                goto out;
        }

        /* calculate the amount of time that has elapsed */
        now = g_date_time_new_now_utc ();
        then = g_date_time_new_from_unix_utc (timestamp);
        diff = g_date_time_difference  (now, then);
        days = diff / G_TIME_SPAN_DAY;
        if (days == 0)
                last_used = g_strdup (_("today"));
        else if (days == 1)
                last_used = g_strdup (_("yesterday"));
        else
                last_used = g_strdup_printf (ngettext ("%i day ago", "%i days ago", days), days);
out:
        if (now != NULL)
                g_date_time_unref (now);
        if (then != NULL)
                g_date_time_unref (then);

        return last_used;
}