/** * gtk示例:通过dbus获取网络链接列表,并用GUI显示 * based on examples from: * http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/C * Author:emptyhua@gmail.com * compile: * gcc -Wall `pkg-config --libs --cflags gtk+-2.0 glib-2.0 dbus-glib-1 libnm-util` list-connections.c -o list-connections */ #include #include #include #include #include #include #include #include #include #define DEBUG(format, ...) printf(format"\n",## __VA_ARGS__) #define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) #define DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT)) #define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH)) typedef struct _network_connection_st network_connection_t; struct _network_connection_st { char *id; char *uuid; char *type; network_connection_t *next; }; enum { NETWORK_CONNECT_ID = 0, NETWORK_CONNECT_UUID, NETWORK_CONNECT_TYPE, NETWORK_COLUMNS }; void network_connections_free(network_connection_t *connection) { network_connection_t *tmp; while(connection != NULL) { tmp = connection; connection = tmp->next; free(tmp->id); free(tmp->type); free(tmp->uuid); free(tmp); } } network_connection_t *get_network_connection_by_path(DBusGConnection *dbus, char *setting_type, char *path) { DBusGProxy *proxy; GError *error = NULL; GHashTable *hash = NULL; NMConnection *connection = NULL; NMSettingConnection *setting = NULL; network_connection_t *rt = NULL; const char *_tmp; proxy = dbus_g_proxy_new_for_name (dbus, setting_type, path, NM_DBUS_IFACE_SETTINGS_CONNECTION); g_assert (proxy); /* Request the all the configuration of the Connection */ if (!dbus_g_proxy_call (proxy, "GetSettings", &error, G_TYPE_INVALID, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &hash, G_TYPE_INVALID)) { g_warning ("Failed to get active connection Connection property: %s", error->message); g_error_free (error); goto out; } connection = nm_connection_new_from_hash (hash, &error); if (!connection) { g_warning ("Received invalid connection data: %s", error->message); g_error_free (error); goto out; } setting = NM_SETTING_CONNECTION(nm_connection_get_setting(connection, NM_TYPE_SETTING_CONNECTION)); rt = (network_connection_t *)calloc(1, sizeof(network_connection_t)); rt->next = NULL; _tmp = nm_setting_connection_get_id (setting); rt->id = strdup(_tmp); _tmp = nm_setting_connection_get_connection_type (setting); rt->type = strdup(_tmp); _tmp = nm_setting_connection_get_uuid (setting); rt->uuid = strdup(_tmp); out: if (connection) g_object_unref (connection); if (hash) g_hash_table_destroy (hash); g_object_unref (proxy); return rt; } network_connection_t *get_network_connections(DBusGConnection *dbus, const char *setting_type) { DBusGProxy *nm_proxy; GError *error = NULL; GPtrArray *con_array; network_connection_t *connection = NULL; int i; DEBUG("setting:%s", setting_type); nm_proxy = dbus_g_proxy_new_for_name (dbus, setting_type, NM_DBUS_PATH_SETTINGS, NM_DBUS_IFACE_SETTINGS); g_assert (nm_proxy); /* Call ListConnections D-Bus method */ dbus_g_proxy_call (nm_proxy, "ListConnections", &error, /* No input arguments */ G_TYPE_INVALID, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &con_array, /* Return values */ G_TYPE_INVALID); for (i = 0; con_array && i < con_array->len; i++) { char *connection_path = g_ptr_array_index (con_array, i); DEBUG("%s", connection_path); network_connection_t *_connection = get_network_connection_by_path(dbus, setting_type, connection_path); if (_connection) { _connection->next = connection; connection = _connection; } g_free (connection_path); } g_ptr_array_free (con_array, TRUE); g_object_unref (nm_proxy); return connection; } GtkWidget *network_select_menu(GCallback callback) { GtkWidget *combobox; GtkListStore *model; GtkTreeIter iter; GtkCellRenderer *text_rend; combobox = gtk_combo_box_new(); model = gtk_list_store_new(NETWORK_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); DBusGConnection *dbus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); network_connection_t *connection = get_network_connections(dbus, NM_DBUS_SERVICE_SYSTEM_SETTINGS); network_connection_t *connection2 = get_network_connections(dbus, NM_DBUS_SERVICE_USER_SETTINGS); dbus_g_connection_unref (dbus); network_connection_t *_tmp_con = connection; if (_tmp_con != NULL) { while (_tmp_con->next != NULL) _tmp_con = _tmp_con->next; _tmp_con->next = connection2; } else { connection = connection2; } _tmp_con = connection; while (_tmp_con != NULL) { gtk_list_store_append (model, &iter); gtk_list_store_set (model, &iter, NETWORK_CONNECT_ID, _tmp_con->id, NETWORK_CONNECT_UUID, _tmp_con->uuid, NETWORK_CONNECT_TYPE, _tmp_con->type, -1); _tmp_con = _tmp_con->next; } network_connections_free(connection); gtk_combo_box_set_model(GTK_COMBO_BOX(combobox), GTK_TREE_MODEL(model)); text_rend = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), text_rend, TRUE); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), text_rend, "markup", NETWORK_CONNECT_ID, NULL); g_object_set(text_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0); return combobox; } static void destroy( GtkWidget *widget, gpointer data ) { gtk_main_quit (); } int main(int argc,char *argv[]) { GtkWidget *window; GtkWidget *net_list; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_container_set_border_width (GTK_CONTAINER (window), 10); g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL); net_list = network_select_menu(NULL); gtk_widget_set_size_request(net_list, 150, -1); gtk_container_add (GTK_CONTAINER (window), net_list); gtk_widget_show_all(window); gtk_main (); return 0; }