blob: 784f11394c2da68a5cb16507ba118ea2558f61ee [file] [log] [blame]
/*
*
* Connection Manager
*
* Copyright (C) 2008 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <dbus/dbus-glib.h>
#include <gtk/gtk.h>
#include "connman-client.h"
static ConnmanClient *client;
enum {
CONNMAN_SERVICE_MOVE = 0x1138,
};
static const GtkTargetEntry row_targets[] = {
{ "CONNMAN_SERVICE_MOVE", GTK_TARGET_SAME_WIDGET, CONNMAN_SERVICE_MOVE },
};
static const gchar *type2str(guint type)
{
switch (type) {
case CONNMAN_TYPE_UNKNOWN:
return "Unknown";
case CONNMAN_TYPE_ETHERNET:
return "Ethernet";
case CONNMAN_TYPE_WIFI:
return "WiFi";
case CONNMAN_TYPE_WIMAX:
return "WiMAX";
case CONNMAN_TYPE_BLUETOOTH:
return "Bluetooth";
case CONNMAN_TYPE_CELLULAR:
return "Cellular";
}
return NULL;
}
static const gchar *state2str(guint state)
{
switch (state) {
case CONNMAN_STATE_UNKNOWN:
return "Unknown";
case CONNMAN_STATE_IDLE:
return "Not connected";
case CONNMAN_STATE_CARRIER:
return "Carrier";
case CONNMAN_STATE_ASSOCIATION:
return "Connecting";
case CONNMAN_STATE_CONFIGURATION:
return "Configuration";
case CONNMAN_STATE_READY:
return "Connected";
case CONNMAN_STATE_FAILURE:
return "Failure";
}
return NULL;
}
static const gchar *security2str(guint security)
{
switch (security) {
case CONNMAN_SECURITY_UNKNOWN:
return "Unknown";
case CONNMAN_SECURITY_NONE:
return "None";
case CONNMAN_SECURITY_WEP:
return "WEP";
case CONNMAN_SECURITY_WPA:
return "WPA";
case CONNMAN_SECURITY_RSN:
return "RSN";
}
return NULL;
}
static void service_to_text(GtkTreeViewColumn *column, GtkCellRenderer *cell,
GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
gchar *name;
guint type, state, security;
gboolean favorite;
gchar *markup, *str;
const gchar *format, *val;
gtk_tree_model_get(model, iter, CONNMAN_COLUMN_NAME, &name,
CONNMAN_COLUMN_TYPE, &type,
CONNMAN_COLUMN_STATE, &state,
CONNMAN_COLUMN_FAVORITE, &favorite,
CONNMAN_COLUMN_SECURITY, &security, -1);
if (favorite == TRUE)
format = "<b>%s</b>\n"
"<span size=\"small\">%s service%s%s <i>(%s)</i></span>";
else
format = "%s\n<span size=\"small\">%s service%s%s <i>(%s)</i></span>";
if (name == NULL) {
if (type == CONNMAN_TYPE_WIFI)
str = g_strdup("<i>hidden</i>");
else
str = g_strdup(type2str(type));
} else
str = g_markup_printf_escaped("%s", name);
if (state == CONNMAN_STATE_UNKNOWN || state == CONNMAN_STATE_IDLE)
val = NULL;
else
val = state2str(state);
markup = g_strdup_printf(format, str, type2str(type),
val ? " - " : "", val ? val : "",
security2str(security));
g_object_set(cell, "markup", markup, NULL);
g_free(markup);
g_free(str);
g_free(name);
}
static void security_to_icon(GtkTreeViewColumn *column, GtkCellRenderer *cell,
GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
guint security;
gtk_tree_model_get(model, iter, CONNMAN_COLUMN_SECURITY, &security, -1);
if (security == CONNMAN_SECURITY_UNKNOWN ||
security == CONNMAN_SECURITY_NONE)
g_object_set(cell, "icon-name", NULL, NULL);
else
g_object_set(cell, "icon-name",
GTK_STOCK_DIALOG_AUTHENTICATION, NULL);
}
static void strength_to_value(GtkTreeViewColumn *column, GtkCellRenderer *cell,
GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
guint type, strength;
gtk_tree_model_get(model, iter, CONNMAN_COLUMN_TYPE, &type,
CONNMAN_COLUMN_STRENGTH, &strength, -1);
g_object_set(cell, "orientation", GTK_PROGRESS_RIGHT_TO_LEFT,
"text-xalign", 1.0, "xpad", 4, "ypad", 6, NULL);
if (type != CONNMAN_TYPE_ETHERNET && strength != 0) {
g_object_set(cell, "value", strength, NULL);
g_object_set(cell, "visible", TRUE, NULL);
} else
g_object_set(cell, "visible", FALSE, NULL);
}
static void method_callback(DBusGProxy *proxy,
DBusGProxyCall *call, void *user_data)
{
GError *error = NULL;
dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INVALID);
if (error != NULL) {
g_print("error - %s\n", error->message);
g_error_free(error);
} else
g_print("finished\n");
g_object_unref(proxy);
}
static void method_call(DBusGProxy *proxy, const char *method, const char *path)
{
if (proxy == NULL)
return;
g_print("%s ( %s, %s )\n", method, dbus_g_proxy_get_path(proxy), path);
if (path == NULL) {
if (dbus_g_proxy_begin_call_with_timeout(proxy,
method, method_callback, NULL, NULL,
120 * 1000, G_TYPE_INVALID) == FALSE) {
g_print("Can't call method %s\n", method);
g_object_unref(proxy);
return;
}
} else {
if (dbus_g_proxy_begin_call(proxy, method, method_callback,
NULL, NULL, DBUS_TYPE_G_OBJECT_PATH, path,
G_TYPE_INVALID) == FALSE) {
g_print("Can't call method %s (%s)\n", method, path);
g_object_unref(proxy);
return;
}
}
}
static DBusGProxy *get_proxy(GtkTreeSelection *selection)
{
GtkTreeModel *model;
GtkTreeIter iter;
DBusGProxy *proxy = NULL;
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
return NULL;
gtk_tree_model_get(model, &iter, CONNMAN_COLUMN_PROXY, &proxy, -1);
return proxy;
}
static void drag_data_get(GtkWidget *widget, GdkDragContext *context,
GtkSelectionData *data, guint info,
guint time, gpointer user_data)
{
GtkTreeSelection *selection = user_data;
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreePath *path;
if (info != CONNMAN_SERVICE_MOVE)
return;
if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
return;
path = gtk_tree_model_get_path(model, &iter);
if (path == NULL)
return;
data->data = (guchar *) gtk_tree_path_to_string(path);
}
static void drag_data_received(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, GtkSelectionData *data,
guint info, guint time, gpointer user_data)
{
GtkTreeModel *model = user_data;
GtkTreePath *path;
GtkTreeIter iter;
DBusGProxy *source, *proxy = NULL;
gboolean success = FALSE;
if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
x, y, &path, NULL, NULL, NULL) == FALSE)
return;
if (gtk_tree_model_get_iter(model, &iter, path) == FALSE)
goto done;
gtk_tree_model_get(model, &iter, CONNMAN_COLUMN_PROXY, &proxy, -1);
if (data == NULL || data->length == 0)
goto done;
if (info != CONNMAN_SERVICE_MOVE)
goto done;
if (gtk_tree_model_get_iter_from_string(model, &iter,
(gchar *) data->data) == FALSE)
goto done;
g_print("%s -> %s\n", (gchar *) data->data, gtk_tree_path_to_string(path));
gtk_tree_model_get(model, &iter, CONNMAN_COLUMN_PROXY, &source, -1);
method_call(source, "MoveBefore", dbus_g_proxy_get_path(proxy));
g_object_unref(proxy);
success = TRUE;
done:
gtk_tree_path_free(path);
gtk_drag_finish(context, success, FALSE, time);
}
static gboolean drag_drop(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, guint time, gpointer user_data)
{
return FALSE;
}
static void connect_callback(GtkWidget *widget, gpointer user_data)
{
DBusGProxy *proxy = get_proxy(user_data);
method_call(proxy, "Connect", NULL);
}
static void disconnect_callback(GtkWidget *widget, gpointer user_data)
{
DBusGProxy *proxy = get_proxy(user_data);
method_call(proxy, "Disconnect", NULL);
}
static void remove_callback(GtkWidget *widget, gpointer user_data)
{
DBusGProxy *proxy = get_proxy(user_data);
method_call(proxy, "Remove", NULL);
}
static void show_popup(GtkWidget *widget,
GdkEventButton *event, gpointer user_data)
{
GtkWidget *menu;
GtkWidget *item;
menu = gtk_menu_new();
item = gtk_menu_item_new_with_label("Connect");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(G_OBJECT(item), "activate",
G_CALLBACK(connect_callback), user_data);
item = gtk_menu_item_new_with_label("Disconnect");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(G_OBJECT(item), "activate",
G_CALLBACK(disconnect_callback), user_data);
item = gtk_menu_item_new_with_label("Remove");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
g_signal_connect(G_OBJECT(item), "activate",
G_CALLBACK(remove_callback), user_data);
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
(event != NULL) ? event->button : 0,
gdk_event_get_time((GdkEvent*) event));
}
static gboolean button_pressed(GtkWidget *widget,
GdkEventButton *event, gpointer user_data)
{
GtkTreeSelection *selection;
GtkTreePath *path;
if (event->type != GDK_BUTTON_PRESS)
return FALSE;
if (event->button != 3)
return FALSE;
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
if (gtk_tree_selection_count_selected_rows(selection) != 1)
return FALSE;
if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
(gint) event->x, (gint) event->y,
&path, NULL, NULL, NULL) == FALSE)
return FALSE;
gtk_tree_selection_unselect_all(selection);
gtk_tree_selection_select_path(selection, path);
gtk_tree_path_free(path);
show_popup(widget, event, selection);
return TRUE;
}
static gboolean popup_callback(GtkWidget *widget, gpointer user_data)
{
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
if (gtk_tree_selection_count_selected_rows(selection) != 1)
return FALSE;
show_popup(widget, NULL, selection);
return TRUE;
}
static void select_callback(GtkTreeSelection *selection, gpointer user_data)
{
GtkTreeView *tree = user_data;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean selected, favorite = FALSE;
selected = gtk_tree_selection_get_selected(selection, &model, &iter);
if (selected == TRUE)
gtk_tree_model_get(model, &iter,
CONNMAN_COLUMN_FAVORITE, &favorite, -1);
if (favorite == TRUE) {
gtk_tree_view_enable_model_drag_source(tree, GDK_BUTTON1_MASK,
row_targets, G_N_ELEMENTS(row_targets),
GDK_ACTION_MOVE);
gtk_tree_view_enable_model_drag_dest(tree,
row_targets, G_N_ELEMENTS(row_targets),
GDK_ACTION_MOVE);
} else {
gtk_tree_view_unset_rows_drag_source(tree);
gtk_tree_view_unset_rows_drag_dest(tree);
}
}
static GtkWidget *create_tree(void)
{
GtkWidget *tree;
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
tree = gtk_tree_view_new();
gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree), FALSE);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE);
gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(tree),
GTK_TREE_VIEW_GRID_LINES_NONE);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_expand(column, TRUE);
gtk_tree_view_column_set_spacing(column, 6);
gtk_tree_view_column_set_min_width(column, 250);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_add_attribute(column, renderer,
"icon-name", CONNMAN_COLUMN_ICON);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_set_cell_data_func(column, renderer,
service_to_text, NULL, NULL);
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_set_cell_data_func(column, renderer,
security_to_icon, NULL, NULL);
renderer = gtk_cell_renderer_progress_new();
gtk_cell_renderer_set_fixed_size(renderer, 100, -1);
gtk_tree_view_column_pack_start(column, renderer, FALSE);
gtk_tree_view_column_set_cell_data_func(column, renderer,
strength_to_value, NULL, NULL);
model = connman_client_get_model(client);
gtk_tree_view_set_model(GTK_TREE_VIEW(tree), model);
g_object_unref(model);
gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree),
CONNMAN_COLUMN_NAME);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(selection), "changed",
G_CALLBACK(select_callback), tree);
g_signal_connect(G_OBJECT(tree), "button-press-event",
G_CALLBACK(button_pressed), NULL);
g_signal_connect(G_OBJECT(tree), "popup-menu",
G_CALLBACK(popup_callback), NULL);
g_signal_connect(G_OBJECT(tree), "drag-drop",
G_CALLBACK(drag_drop), NULL);
g_signal_connect(G_OBJECT(tree), "drag-data-get",
G_CALLBACK(drag_data_get), selection);
g_signal_connect(G_OBJECT(tree), "drag-data-received",
G_CALLBACK(drag_data_received), model);
return tree;
}
static gboolean delete_callback(GtkWidget *window, GdkEvent *event,
gpointer user_data)
{
gtk_widget_destroy(window);
gtk_main_quit();
return FALSE;
}
static void close_callback(GtkWidget *button, gpointer user_data)
{
GtkWidget *window = user_data;
gtk_widget_destroy(window);
gtk_main_quit();
}
static GtkWidget *create_window(void)
{
GtkWidget *window;
GtkWidget *mainbox;
GtkWidget *tree;
GtkWidget *scrolled;
GtkWidget *buttonbox;
GtkWidget *button;
GtkTreeSelection *selection;
tree = create_tree();
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Client Test");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 480, 400);
g_signal_connect(G_OBJECT(window), "delete-event",
G_CALLBACK(delete_callback), NULL);
mainbox = gtk_vbox_new(FALSE, 12);
gtk_container_set_border_width(GTK_CONTAINER(mainbox), 12);
gtk_container_add(GTK_CONTAINER(window), mainbox);
scrolled = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
GTK_SHADOW_OUT);
gtk_box_pack_start(GTK_BOX(mainbox), scrolled, TRUE, TRUE, 0);
buttonbox = gtk_hbutton_box_new();
gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonbox),
GTK_BUTTONBOX_END);
gtk_box_pack_end(GTK_BOX(mainbox), buttonbox, FALSE, FALSE, 0);
button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
gtk_container_add(GTK_CONTAINER(buttonbox), button);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(close_callback), window);
gtk_container_add(GTK_CONTAINER(scrolled), tree);
gtk_widget_show_all(window);
return window;
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
client = connman_client_new();
gtk_window_set_default_icon_name("network-wireless");
create_window();
gtk_main();
g_object_unref(client);
return 0;
}