|
Packit Service |
d328f3 |
// SPDX-License-Identifier: GPL-2.0+
|
|
Packit Service |
d328f3 |
/* NetworkManager Connection editor -- Connection editor for NetworkManager
|
|
Packit Service |
d328f3 |
*
|
|
Packit Service |
d328f3 |
* Copyright 2012 - 2014 Red Hat, Inc.
|
|
Packit Service |
d328f3 |
*/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "nm-default.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include <stdlib.h>
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include <NetworkManager.h>
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "page-master.h"
|
|
Packit Service |
d328f3 |
#include "nm-connection-editor.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
G_DEFINE_TYPE (CEPageMaster, ce_page_master, CE_TYPE_PAGE)
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#define CE_PAGE_MASTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CE_TYPE_PAGE_MASTER, CEPageMasterPrivate))
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
const char *uuid;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
GtkWindow *toplevel;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
GtkEntry *interface_name;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
GtkTreeView *connections;
|
|
Packit Service |
d328f3 |
GtkTreeModel *connections_model;
|
|
Packit Service |
d328f3 |
GtkButton *add, *edit, *delete;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
GHashTable *new_slaves; /* track whether some slave(s) were added */
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
} CEPageMasterPrivate;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void finish_setup (CEPageMaster *self, gpointer user_data);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
enum {
|
|
Packit Service |
d328f3 |
COL_CONNECTION,
|
|
Packit Service |
d328f3 |
COL_NAME
|
|
Packit Service |
d328f3 |
};
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static int
|
|
Packit Service |
d328f3 |
name_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
NMConnection *conn_a, *conn_b;
|
|
Packit Service |
d328f3 |
int ret;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* We fetch COL_CONNECTION rather than COL_NAME to avoid a strdup/free. */
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (model, a, COL_CONNECTION, &conn_a, -1);
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (model, b, COL_CONNECTION, &conn_b, -1);
|
|
Packit Service |
d328f3 |
ret = strcmp (nm_connection_get_id (conn_a), nm_connection_get_id (conn_b));
|
|
Packit Service |
d328f3 |
g_object_unref (conn_a);
|
|
Packit Service |
d328f3 |
g_object_unref (conn_b);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return ret;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
constructed (GObject *object)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (object);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (self, CE_PAGE_INITIALIZED, G_CALLBACK (finish_setup), NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
G_OBJECT_CLASS (ce_page_master_parent_class)->constructed (object);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
dispose (GObject *object)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (object);
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_handlers_disconnect_matched (CE_PAGE (self)->client, G_SIGNAL_MATCH_DATA,
|
|
Packit Service |
d328f3 |
0, 0, NULL, NULL, self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (gtk_tree_model_get_iter_first (priv->connections_model, &iter)) {
|
|
Packit Service |
d328f3 |
do {
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (priv->connections_model, &iter,
|
|
Packit Service |
d328f3 |
COL_CONNECTION, &connection,
|
|
Packit Service |
d328f3 |
-1);
|
|
Packit Service |
d328f3 |
g_signal_handlers_disconnect_matched (connection, G_SIGNAL_MATCH_DATA,
|
|
Packit Service |
d328f3 |
0, 0, NULL, NULL, self);
|
|
Packit Service |
d328f3 |
g_object_unref (connection);
|
|
Packit Service |
d328f3 |
} while (gtk_tree_model_iter_next (priv->connections_model, &iter));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_hash_table_destroy (priv->new_slaves);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
G_OBJECT_CLASS (ce_page_master_parent_class)->dispose (object);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
stuff_changed (GtkWidget *widget, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
ce_page_changed (CE_PAGE (user_data));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
find_connection (CEPageMaster *self, NMRemoteConnection *connection, GtkTreeIter *iter)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!gtk_tree_model_get_iter_first (priv->connections_model, iter))
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
do {
|
|
Packit Service |
d328f3 |
NMRemoteConnection *candidate = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (priv->connections_model, iter,
|
|
Packit Service |
d328f3 |
COL_CONNECTION, &candidate,
|
|
Packit Service |
d328f3 |
-1);
|
|
Packit Service |
d328f3 |
if (candidate == connection)
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
} while (gtk_tree_model_iter_next (priv->connections_model, iter));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
connection_removed (NMClient *client,
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (user_data);
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!find_connection (self, connection, &iter))
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_list_store_remove (GTK_LIST_STORE (priv->connections_model), &iter);
|
|
Packit Service |
d328f3 |
ce_page_changed (CE_PAGE (self));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
connection_changed (NMRemoteConnection *connection, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (user_data);
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!find_connection (self, connection, &iter))
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Name might have changed */
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
|
|
Packit Service |
d328f3 |
gtk_list_store_set (GTK_LIST_STORE (priv->connections_model), &iter,
|
|
Packit Service |
d328f3 |
COL_NAME, nm_setting_connection_get_id (s_con),
|
|
Packit Service |
d328f3 |
-1);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static NMDevice *
|
|
Packit Service |
d328f3 |
get_device_for_connection (NMClient *client, NMConnection *conn)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
const GPtrArray *devices;
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
int i;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
devices = nm_client_get_devices (client);
|
|
Packit Service |
d328f3 |
if (!devices)
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Make sure the connection is actually locked to a specific device */
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (conn);
|
|
Packit Service |
d328f3 |
if ( !nm_setting_connection_get_interface_name (s_con)
|
|
Packit Service |
d328f3 |
&& !nm_connection_get_interface_name (conn)) {
|
|
Packit Service |
d328f3 |
NMSetting *s_hw;
|
|
Packit Service |
d328f3 |
gs_free char *mac_address = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_hw = nm_connection_get_setting_by_name (conn, nm_setting_connection_get_connection_type (s_con));
|
|
Packit Service |
d328f3 |
if (!s_hw || !g_object_class_find_property (G_OBJECT_GET_CLASS (s_hw), "mac-address"))
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_object_get (G_OBJECT (s_hw), "mac-address", &mac_address, NULL);
|
|
Packit Service |
d328f3 |
if (!mac_address)
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* OK, now find that device */
|
|
Packit Service |
d328f3 |
for (i = 0; i < devices->len; i++) {
|
|
Packit Service |
d328f3 |
NMDevice *device = devices->pdata[i];
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (nm_device_connection_compatible (device, conn, NULL))
|
|
Packit Service |
d328f3 |
return device;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
check_new_slave_physical_port (CEPageMaster *self, NMConnection *conn)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMConnection *conn2;
|
|
Packit Service |
d328f3 |
NMDevice *dev, *dev2;
|
|
Packit Service |
d328f3 |
const char *id, *id2;
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
dev = get_device_for_connection (CE_PAGE (self)->client, conn);
|
|
Packit Service |
d328f3 |
if (!dev)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
id = nm_device_get_physical_port_id (dev);
|
|
Packit Service |
d328f3 |
if (!id)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!gtk_tree_model_get_iter_first (priv->connections_model, &iter))
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
do {
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (priv->connections_model, &iter, 0, &conn2, -1);
|
|
Packit Service |
d328f3 |
g_object_unref (conn2); /* gtk_tree_model_get() adds a ref */
|
|
Packit Service |
d328f3 |
dev2 = get_device_for_connection (CE_PAGE (self)->client, conn2);
|
|
Packit Service |
d328f3 |
if (!dev2)
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
if (dev == dev2) {
|
|
Packit Service |
d328f3 |
nm_connection_editor_warning (CE_PAGE (self)->parent_window,
|
|
Packit Service |
d328f3 |
_("Duplicate slaves"),
|
|
Packit Service |
d328f3 |
_("Slaves “%s” and “%s” both apply to device “%s”"),
|
|
Packit Service |
d328f3 |
nm_connection_get_id (conn),
|
|
Packit Service |
d328f3 |
nm_connection_get_id (conn2),
|
|
Packit Service |
d328f3 |
nm_device_get_iface (dev));
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
id2 = nm_device_get_physical_port_id (dev2);
|
|
Packit Service |
d328f3 |
if (self->aggregating && id && id2 && !strcmp (id, id2)) {
|
|
Packit Service |
d328f3 |
nm_connection_editor_warning (CE_PAGE (self)->parent_window,
|
|
Packit Service |
d328f3 |
_("Duplicate slaves"),
|
|
Packit Service |
d328f3 |
_("Slaves “%s” and “%s” apply to different virtual "
|
|
Packit Service |
d328f3 |
"ports (“%s” and “%s”) of the same physical device."),
|
|
Packit Service |
d328f3 |
nm_connection_get_id (conn),
|
|
Packit Service |
d328f3 |
nm_connection_get_id (conn2),
|
|
Packit Service |
d328f3 |
nm_device_get_iface (dev),
|
|
Packit Service |
d328f3 |
nm_device_get_iface (dev2));
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
} while (gtk_tree_model_iter_next (priv->connections_model, &iter));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
connection_added (NMClient *client,
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (user_data);
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
const char *master_type;
|
|
Packit Service |
d328f3 |
const char *slave_type, *master;
|
|
Packit Service |
d328f3 |
const char *interface_name;
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
master_type = nm_setting_connection_get_connection_type (s_con);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
|
|
Packit Service |
d328f3 |
if (!s_con)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
slave_type = nm_setting_connection_get_slave_type (s_con);
|
|
Packit Service |
d328f3 |
if (g_strcmp0 (slave_type, master_type) != 0)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
master = nm_setting_connection_get_master (s_con);
|
|
Packit Service |
d328f3 |
if (!master)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
interface_name = nm_connection_get_interface_name (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
if (g_strcmp0 (master, interface_name) != 0 && g_strcmp0 (master, priv->uuid) != 0)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
check_new_slave_physical_port (self, NM_CONNECTION (connection));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_list_store_append (GTK_LIST_STORE (priv->connections_model), &iter);
|
|
Packit Service |
d328f3 |
gtk_list_store_set (GTK_LIST_STORE (priv->connections_model), &iter,
|
|
Packit Service |
d328f3 |
COL_CONNECTION, connection,
|
|
Packit Service |
d328f3 |
COL_NAME, nm_setting_connection_get_id (s_con),
|
|
Packit Service |
d328f3 |
-1);
|
|
Packit Service |
d328f3 |
ce_page_changed (CE_PAGE (self));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (client, NM_CLIENT_CONNECTION_REMOVED,
|
|
Packit Service |
d328f3 |
G_CALLBACK (connection_removed), self);
|
|
Packit Service |
d328f3 |
g_signal_connect (connection, NM_CONNECTION_CHANGED,
|
|
Packit Service |
d328f3 |
G_CALLBACK (connection_changed), self);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
connections_selection_changed_cb (GtkTreeSelection *selection, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
GtkTreeModel *model;
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection;
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
gboolean sensitive = FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (model, &iter,
|
|
Packit Service |
d328f3 |
0, &connection,
|
|
Packit Service |
d328f3 |
-1);
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection));
|
|
Packit Service |
d328f3 |
g_assert (s_con);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
sensitive = !nm_setting_connection_get_read_only (s_con);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_widget_set_sensitive (GTK_WIDGET (priv->edit), sensitive);
|
|
Packit Service |
d328f3 |
gtk_widget_set_sensitive (GTK_WIDGET (priv->delete), sensitive);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
add_response_cb (NMConnectionEditor *editor, GtkResponseType response, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
const char *uuid;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (response == GTK_RESPONSE_OK) {
|
|
Packit Service |
d328f3 |
uuid = nm_connection_get_uuid (editor->connection);
|
|
Packit Service |
d328f3 |
g_hash_table_add (priv->new_slaves, g_strdup (uuid));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_object_unref (editor);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
add_connection (FUNC_TAG_NEW_CONNECTION_RESULT_IMPL,
|
|
Packit Service |
d328f3 |
NMConnection *connection,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
NMConnectionEditor *editor;
|
|
Packit Service |
d328f3 |
const char *iface_name, *master_type;
|
|
Packit Service |
d328f3 |
char *name;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!connection)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
master_type = nm_setting_connection_get_connection_type (s_con);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Mark the connection as a slave, and rename it. */
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (connection);
|
|
Packit Service |
d328f3 |
g_assert (s_con != NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
iface_name = gtk_entry_get_text (priv->interface_name);
|
|
Packit Service |
d328f3 |
if (!*iface_name)
|
|
Packit Service |
d328f3 |
iface_name = nm_connection_get_interface_name (connection);
|
|
Packit Service |
d328f3 |
if (!iface_name || !nm_utils_is_valid_iface_name (iface_name, NULL))
|
|
Packit Service |
d328f3 |
iface_name = nm_connection_get_id (connection);
|
|
Packit Service |
d328f3 |
name = g_strdup_printf (_("%s slave %d"), iface_name,
|
|
Packit Service |
d328f3 |
gtk_tree_model_iter_n_children (priv->connections_model, NULL) + 1);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_object_set (G_OBJECT (s_con),
|
|
Packit Service |
d328f3 |
NM_SETTING_CONNECTION_ID, name,
|
|
Packit Service |
d328f3 |
NM_SETTING_CONNECTION_MASTER, priv->uuid,
|
|
Packit Service |
d328f3 |
NM_SETTING_CONNECTION_SLAVE_TYPE, master_type,
|
|
Packit Service |
d328f3 |
NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
|
|
Packit Service |
d328f3 |
NULL);
|
|
Packit Service |
d328f3 |
g_free (name);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
editor = ce_page_new_editor (CE_PAGE (self), priv->toplevel, connection);
|
|
Packit Service |
d328f3 |
if (!editor)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (editor, NM_CONNECTION_EDITOR_DONE, G_CALLBACK (add_response_cb), self);
|
|
Packit Service |
d328f3 |
nm_connection_editor_run (editor);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
add_clicked (GtkButton *button, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
CE_PAGE_MASTER_GET_CLASS (self)->add_slave (self, add_connection);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static NMRemoteConnection *
|
|
Packit Service |
d328f3 |
get_selected_connection (CEPageMaster *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeSelection *selection;
|
|
Packit Service |
d328f3 |
GList *selected_rows;
|
|
Packit Service |
d328f3 |
GtkTreeModel *model = NULL;
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
selection = gtk_tree_view_get_selection (priv->connections);
|
|
Packit Service |
d328f3 |
selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
|
|
Packit Service |
d328f3 |
if (!selected_rows)
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) selected_rows->data))
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (model, &iter, 0, &connection, -1);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return connection;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
edit_done_cb (NMConnectionEditor *editor, GtkResponseType response, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
g_object_unref (editor);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
edit_clicked (GtkButton *button, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMConnectionEditor *editor;
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
connection = get_selected_connection (self);
|
|
Packit Service |
d328f3 |
if (!connection)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
editor = nm_connection_editor_get (NM_CONNECTION (connection));
|
|
Packit Service |
d328f3 |
if (editor) {
|
|
Packit Service |
d328f3 |
nm_connection_editor_present (editor);
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
editor = ce_page_new_editor (CE_PAGE (self), priv->toplevel, NM_CONNECTION (connection));
|
|
Packit Service |
d328f3 |
if (!editor)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (editor, NM_CONNECTION_EDITOR_DONE, G_CALLBACK (edit_done_cb), self);
|
|
Packit Service |
d328f3 |
nm_connection_editor_run (editor);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
connection_double_clicked_cb (GtkTreeView *tree_view,
|
|
Packit Service |
d328f3 |
GtkTreePath *path,
|
|
Packit Service |
d328f3 |
GtkTreeViewColumn *column,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
edit_clicked (NULL, user_data);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
delete_result_cb (FUNC_TAG_DELETE_CONNECTION_RESULT_IMPL,
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection,
|
|
Packit Service |
d328f3 |
gboolean deleted,
|
|
Packit Service |
d328f3 |
gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (deleted) {
|
|
Packit Service |
d328f3 |
g_hash_table_remove (priv->new_slaves,
|
|
Packit Service |
d328f3 |
nm_connection_get_uuid (NM_CONNECTION (connection)));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
delete_clicked (GtkButton *button, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = user_data;
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMRemoteConnection *connection;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
connection = get_selected_connection (self);
|
|
Packit Service |
d328f3 |
if (!connection)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
delete_connection (priv->toplevel, connection, delete_result_cb, self);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
populate_ui (CEPageMaster *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
const char *iface;
|
|
Packit Service |
d328f3 |
const GPtrArray *connections;
|
|
Packit Service |
d328f3 |
int i;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
g_return_if_fail (s_con != NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Interface name */
|
|
Packit Service |
d328f3 |
iface = nm_connection_get_interface_name (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
gtk_entry_set_text (priv->interface_name, iface ? iface : "");
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Slave connections */
|
|
Packit Service |
d328f3 |
connections = nm_client_get_connections (CE_PAGE (self)->client);
|
|
Packit Service |
d328f3 |
for (i = 0; i < connections->len; i++)
|
|
Packit Service |
d328f3 |
connection_added (CE_PAGE (self)->client, connections->pdata[i], self);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
finish_setup (CEPageMaster *self, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeSelection *selection;
|
|
Packit Service |
d328f3 |
GtkBuilder *builder;
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
builder = CE_PAGE (self)->builder;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->interface_name = GTK_ENTRY (gtk_builder_get_object (builder, "master_interface"));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->connections = GTK_TREE_VIEW (gtk_builder_get_object (builder, "master_connections"));
|
|
Packit Service |
d328f3 |
priv->connections_model = GTK_TREE_MODEL (gtk_builder_get_object (builder, "master_connections_model"));
|
|
Packit Service |
d328f3 |
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->connections_model),
|
|
Packit Service |
d328f3 |
COL_NAME, name_sort_func,
|
|
Packit Service |
d328f3 |
NULL, NULL);
|
|
Packit Service |
d328f3 |
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->connections_model),
|
|
Packit Service |
d328f3 |
COL_NAME, GTK_SORT_ASCENDING);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->add = GTK_BUTTON (gtk_builder_get_object (builder, "master_connection_add"));
|
|
Packit Service |
d328f3 |
priv->edit = GTK_BUTTON (gtk_builder_get_object (builder, "master_connection_edit"));
|
|
Packit Service |
d328f3 |
priv->delete = GTK_BUTTON (gtk_builder_get_object (builder, "master_connection_delete"));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->toplevel = GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (priv->connections),
|
|
Packit Service |
d328f3 |
GTK_TYPE_WINDOW));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
priv->uuid = nm_setting_connection_get_uuid (s_con);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
populate_ui (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (CE_PAGE (self)->client, NM_CLIENT_CONNECTION_ADDED,
|
|
Packit Service |
d328f3 |
G_CALLBACK (connection_added), self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (priv->interface_name, "changed", G_CALLBACK (stuff_changed), self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (priv->add, "clicked", G_CALLBACK (add_clicked), self);
|
|
Packit Service |
d328f3 |
g_signal_connect (priv->edit, "clicked", G_CALLBACK (edit_clicked), self);
|
|
Packit Service |
d328f3 |
g_signal_connect (priv->delete, "clicked", G_CALLBACK (delete_clicked), self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_signal_connect (priv->connections, "row-activated", G_CALLBACK (connection_double_clicked_cb), self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
selection = gtk_tree_view_get_selection (priv->connections);
|
|
Packit Service |
d328f3 |
g_signal_connect (selection, "changed", G_CALLBACK (connections_selection_changed_cb), self);
|
|
Packit Service |
d328f3 |
connections_selection_changed_cb (selection, self);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
ui_to_setting (CEPageMaster *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
const char *interface_name;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Interface name */
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (CE_PAGE (self)->connection);
|
|
Packit Service |
d328f3 |
interface_name = gtk_entry_get_text (priv->interface_name);
|
|
Packit Service |
d328f3 |
if (!*interface_name)
|
|
Packit Service |
d328f3 |
interface_name = NULL;
|
|
Packit Service |
d328f3 |
g_object_set (s_con, "interface-name", interface_name, NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Slaves are updated as they're edited, so nothing to do */
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (page);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* We don't need to recursively check that the slaves connections
|
|
Packit Service |
d328f3 |
* are valid because they can't end up in the table if they're not.
|
|
Packit Service |
d328f3 |
*/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
ui_to_setting (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Subtype ce_page_validate_v() method will validate the interface name */
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
last_update (CEPage *page, NMConnection *connection, GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMaster *self = CE_PAGE_MASTER (page);
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
const char *interface_name, *tmp, *uuid;
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* No new slave added - leave master property as it is. */
|
|
Packit Service |
d328f3 |
if (g_hash_table_size (priv->new_slaves) == 0)
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*
|
|
Packit Service |
d328f3 |
* Set master property of all slaves to be the interface name.
|
|
Packit Service |
d328f3 |
* Even if UUID has the advantage of being stable and thus easier to use,
|
|
Packit Service |
d328f3 |
* users may prefer using interface name instead.
|
|
Packit Service |
d328f3 |
*/
|
|
Packit Service |
d328f3 |
interface_name = gtk_entry_get_text (priv->interface_name);
|
|
Packit Service |
d328f3 |
if (gtk_tree_model_get_iter_first (priv->connections_model, &iter)) {
|
|
Packit Service |
d328f3 |
do {
|
|
Packit Service |
d328f3 |
NMRemoteConnection *rcon = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_tree_model_get (priv->connections_model, &iter,
|
|
Packit Service |
d328f3 |
COL_CONNECTION, &rcon,
|
|
Packit Service |
d328f3 |
-1);
|
|
Packit Service |
d328f3 |
tmp = nm_connection_get_interface_name (NM_CONNECTION (rcon));
|
|
Packit Service |
d328f3 |
uuid = nm_connection_get_uuid (NM_CONNECTION (rcon));
|
|
Packit Service |
d328f3 |
if ( g_hash_table_contains (priv->new_slaves, uuid)
|
|
Packit Service |
d328f3 |
&& g_strcmp0 (interface_name, tmp) != 0) {
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (NM_CONNECTION (rcon));
|
|
Packit Service |
d328f3 |
g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, interface_name, NULL);
|
|
Packit Service |
d328f3 |
nm_remote_connection_commit_changes_async (rcon, TRUE, NULL, NULL, NULL);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_object_unref (rcon);
|
|
Packit Service |
d328f3 |
} while (gtk_tree_model_iter_next (priv->connections_model, &iter));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
ce_page_master_init (CEPageMaster *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
priv->new_slaves = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
ce_page_master_class_init (CEPageMasterClass *master_class)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
GObjectClass *object_class = G_OBJECT_CLASS (master_class);
|
|
Packit Service |
d328f3 |
CEPageClass *parent_class = CE_PAGE_CLASS (master_class);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_type_class_add_private (object_class, sizeof (CEPageMasterPrivate));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* virtual methods */
|
|
Packit Service |
d328f3 |
object_class->constructed = constructed;
|
|
Packit Service |
d328f3 |
object_class->dispose = dispose;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
parent_class->ce_page_validate_v = ce_page_validate_v;
|
|
Packit Service |
d328f3 |
parent_class->last_update = last_update;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gboolean
|
|
Packit Service |
d328f3 |
ce_page_master_has_slaves (CEPageMaster *self)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
CEPageMasterPrivate *priv = CE_PAGE_MASTER_GET_PRIVATE (self);
|
|
Packit Service |
d328f3 |
GtkTreeIter iter;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return gtk_tree_model_get_iter_first (priv->connections_model, &iter);
|
|
Packit Service |
d328f3 |
}
|