2
* Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
* Author: Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
4
* Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
* Additional permission under GNU GPL version 3 section 7:
22
* If you modify this program, or any covered work, by linking or
23
* combining it with the OpenSSL project's OpenSSL library (or a
24
* modified version of that library), containing parts covered by the
25
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26
* grants you additional permission to convey the resulting work.
27
* Corresponding Source for a non-source form of such a combination
28
* shall include the source code for the parts of OpenSSL used as well
29
* as that of the covered work.
33
#include "accountlistconfigdialog.h"
34
#include "dbus/dbus.h"
35
#include "accountconfigdialog.h"
37
#include "mainwindow.h"
43
static const int CONTEXT_ID_REGISTRATION = 0;
45
static GtkWidget *addButton;
46
static GtkWidget *editButton;
47
static GtkWidget *deleteButton;
48
static GtkWidget *accountMoveDownButton;
49
static GtkWidget *accountMoveUpButton;
50
static GtkWidget * status_bar;
51
static GtkListStore * accountStore;
53
static GtkDialog * accountListDialog = NULL;
55
static account_t * selectedAccount = NULL;
60
COLUMN_ACCOUNT_STATUS,
61
COLUMN_ACCOUNT_ACTIVE,
69
static void delete_account_cb(void)
71
if (selectedAccount == NULL) {
72
ERROR("Config: Error: No selected account in delete action");
76
dbus_remove_account(selectedAccount->accountID);
83
static void edit_account_cb(void)
85
if (selectedAccount == NULL) {
86
ERROR("Config: Error: No selected account in edit action");
90
show_account_window(selectedAccount);
96
static void add_account_cb(void)
98
show_account_window(NULL);
102
* Fills the treelist with accounts
104
void account_list_config_dialog_fill()
106
if (accountListDialog == NULL) {
107
DEBUG("Config: No account dialog, returning");
113
gtk_list_store_clear(accountStore);
115
// IP2IP account must be first
116
account_t *a = account_list_get_by_id("IP2IP");
119
ERROR("Config: Error: Could not find IP2IP account");
123
gtk_list_store_append(accountStore, &iter);
125
DEBUG("Config: Filling accounts: Account is enabled :%s", g_hash_table_lookup(a->properties, ACCOUNT_ENABLED));
127
gtk_list_store_set(accountStore, &iter,
128
COLUMN_ACCOUNT_ALIAS, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name
129
COLUMN_ACCOUNT_TYPE, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol
130
COLUMN_ACCOUNT_STATUS, account_state_name(a->state), // Status
131
COLUMN_ACCOUNT_ACTIVE, (g_strcasecmp(g_hash_table_lookup(a->properties, ACCOUNT_ENABLED),"true") == 0) ? TRUE:FALSE, // Enable/Disable
132
COLUMN_ACCOUNT_DATA, a, // Pointer
135
for (size_t i = 0; i < account_list_get_size(); i++) {
136
a = account_list_get_nth(i);
139
ERROR("Config: Error: Account %d is NULL while parsing the list", i);
143
// we dont wnat to process account twice
144
if (g_strcmp0(a->accountID, "IP2IP") != 0) {
145
gtk_list_store_append(accountStore, &iter);
147
DEBUG("Config: Filling accounts: Account is enabled :%s", g_hash_table_lookup(a->properties, ACCOUNT_ENABLED));
149
gtk_list_store_set(accountStore, &iter,
150
COLUMN_ACCOUNT_ALIAS, g_hash_table_lookup(a->properties, ACCOUNT_ALIAS), // Name
151
COLUMN_ACCOUNT_TYPE, g_hash_table_lookup(a->properties, ACCOUNT_TYPE), // Protocol
152
COLUMN_ACCOUNT_STATUS, account_state_name(a->state), // Status
153
COLUMN_ACCOUNT_ACTIVE, (g_strcasecmp(g_hash_table_lookup(a->properties, ACCOUNT_ENABLED),"true") == 0) ? TRUE:FALSE, // Enable/Disable
154
COLUMN_ACCOUNT_DATA, a, // Pointer
161
* Call back when the user click on an account in the list
164
select_account_cb(GtkTreeSelection *selection, GtkTreeModel *model)
170
memset(&val, 0, sizeof(val));
172
if (!gtk_tree_selection_get_selected(selection, &model, &iter)) {
173
selectedAccount = NULL;
174
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE);
175
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE);
176
gtk_widget_set_sensitive(GTK_WIDGET(editButton), FALSE);
177
gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE);
181
// The Gvalue will be initialized in the following function
182
gtk_tree_model_get_value(model, &iter, COLUMN_ACCOUNT_DATA, &val);
184
selectedAccount = (account_t*) g_value_get_pointer(&val);
187
if (selectedAccount != NULL) {
188
gtk_widget_set_sensitive(GTK_WIDGET(editButton), TRUE);
190
if (g_strcasecmp(selectedAccount->accountID, IP2IP) != 0) {
191
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), TRUE);
192
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), TRUE);
193
gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), TRUE);
195
/* Update status bar about current registration state */
196
gtk_statusbar_pop(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION);
198
if (selectedAccount->protocol_state_description != NULL
199
&& selectedAccount->protocol_state_code != 0) {
201
gchar * response = g_strdup_printf(
202
_("Server returned \"%s\" (%d)"),
203
selectedAccount->protocol_state_description,
204
selectedAccount->protocol_state_code);
205
gchar * message = g_strconcat(
206
account_state_name(selectedAccount->state),
211
gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, message);
217
state = (gchar*) account_state_name(selectedAccount->state);
218
gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, state);
221
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE);
222
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE);
223
gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE);
227
DEBUG("Selecting account in account window");
230
static void enable_account_cb(GtkCellRendererToggle *rend UNUSED, gchar* path, gpointer data)
234
GtkTreePath *treePath;
239
// The IP2IP profile can't be disabled
240
if (g_strcasecmp(path, "0") == 0)
243
// Get pointer on object
244
treePath = gtk_tree_path_new_from_string(path);
245
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data));
246
gtk_tree_model_get_iter(model, &iter, treePath);
247
gtk_tree_model_get(model, &iter,
248
COLUMN_ACCOUNT_ACTIVE, &enable,
249
COLUMN_ACCOUNT_DATA, &acc,
254
DEBUG("Account is %d enabled", enable);
256
gtk_list_store_set(GTK_LIST_STORE(model), &iter,
257
COLUMN_ACCOUNT_ACTIVE, enable,
260
// Modify account state
261
gchar * registrationState;
264
registrationState = g_strdup("true");
266
registrationState = g_strdup("false");
268
DEBUG("Replacing with %s", registrationState);
269
g_hash_table_replace(acc->properties , g_strdup(ACCOUNT_ENABLED), registrationState);
271
dbus_send_register(acc->accountID, enable);
275
* Move account in list depending on direction and selected account
277
static void account_move(gboolean moveUp, gpointer data)
282
GtkTreeView *treeView;
284
GtkTreeSelection *selection;
285
GtkTreePath *treePath;
288
// Get view, model and selection of codec store
289
treeView = GTK_TREE_VIEW(data);
290
model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeView));
291
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView));
293
// Find selected iteration and create a copy
294
gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter);
295
iter2 = gtk_tree_iter_copy(&iter);
297
// Find path of iteration
298
path = gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(model), &iter);
300
// The first real account in the list can't move up because of the IP2IP account
301
// It can still move down though
302
if (g_strcasecmp(path, "1") == 0 && moveUp)
305
treePath = gtk_tree_path_new_from_string(path);
306
gint *indices = gtk_tree_path_get_indices(treePath);
307
gint indice = indices[0];
309
// Depending on button direction get new path
311
gtk_tree_path_prev(treePath);
313
gtk_tree_path_next(treePath);
315
gtk_tree_model_get_iter(model, &iter, treePath);
317
// Swap iterations if valid
318
if (gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), &iter))
319
gtk_list_store_swap(GTK_LIST_STORE(model), &iter, iter2);
321
// Scroll to new position
322
gtk_tree_view_scroll_to_cell(treeView, treePath, NULL, FALSE, 0, 0);
325
gtk_tree_path_free(treePath);
326
gtk_tree_iter_free(iter2);
329
// Perpetuate changes in account queue
331
account_list_move_up(indice);
333
account_list_move_down(indice);
336
// Set the order in the configuration file
337
gchar *ordered_account_list = account_list_get_ordered_list();
338
dbus_set_accounts_order(ordered_account_list);
339
g_free(ordered_account_list);
343
* Called from move up account button signal
346
account_move_up_cb(GtkButton *button UNUSED, gpointer data)
348
// Change tree view ordering and get indice changed
349
account_move(TRUE, data);
353
* Called from move down account button signal
356
account_move_down_cb(GtkButton *button UNUSED, gpointer data)
358
// Change tree view ordering and get indice changed
359
account_move(FALSE, data);
363
help_contents_cb(GtkWidget * widget UNUSED,
364
gpointer data UNUSED)
366
GError *error = NULL;
367
gtk_show_uri(NULL, "ghelp:sflphone?accounts", GDK_CURRENT_TIME, &error);
369
g_warning("%s", error->message);
375
close_dialog_cb(GtkWidget * widget UNUSED,
376
gpointer data UNUSED)
378
gtk_dialog_response(GTK_DIALOG(accountListDialog), GTK_RESPONSE_ACCEPT);
382
void highlight_ip_profile(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data UNUSED)
388
memset(&val, 0, sizeof(val));
389
gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val);
390
current = (account_t*) g_value_get_pointer(&val);
394
if (current != NULL) {
396
// Make the first line appear differently
397
(g_strcasecmp(current->accountID, IP2IP) == 0) ? g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_THIN,
398
"style", PANGO_STYLE_ITALIC,
399
"stretch", PANGO_STRETCH_ULTRA_EXPANDED,
402
g_object_set(G_OBJECT(rend), "weight", PANGO_WEIGHT_MEDIUM,
403
"style", PANGO_STYLE_NORMAL,
404
"stretch", PANGO_STRETCH_NORMAL,
410
void highlight_registration(GtkTreeViewColumn *col UNUSED, GtkCellRenderer *rend, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data UNUSED)
416
memset(&val, 0, sizeof(val));
417
gtk_tree_model_get_value(tree_model, iter, COLUMN_ACCOUNT_DATA, &val);
418
current = (account_t*) g_value_get_pointer(&val);
422
if (current != NULL) {
423
if (g_strcasecmp(current->accountID, IP2IP) != 0) {
424
// Color the account state: green -> registered, otherwise red
425
(current->state == ACCOUNT_STATE_REGISTERED) ? g_object_set(G_OBJECT(rend), "foreground", "Dark Green", NULL) :
426
g_object_set(G_OBJECT(rend), "foreground", "Dark Red", NULL);
428
g_object_set(G_OBJECT(rend), "foreground", "Black", NULL);
434
* Account settings tab
436
GtkWidget* create_account_list(GtkDialog * dialog UNUSED)
439
GtkWidget *table, *scrolledWindow, *buttonBox;
440
GtkCellRenderer *renderer;
441
GtkTreeView * treeView;
442
GtkTreeViewColumn *treeViewColumn;
443
GtkTreeSelection *treeSelection;
444
GtkRequisition requisition;
446
selectedAccount = NULL;
448
table = gtk_table_new(1, 2, FALSE/* homogeneous */);
449
gtk_table_set_col_spacings(GTK_TABLE(table), 10);
450
gtk_container_set_border_width(GTK_CONTAINER(table), 10);
452
scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
453
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
454
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_SHADOW_IN);
455
gtk_table_attach(GTK_TABLE(table), scrolledWindow, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
457
accountStore = gtk_list_store_new(COLUMN_ACCOUNT_COUNT,
458
G_TYPE_STRING, // Name
459
G_TYPE_STRING, // Protocol
460
G_TYPE_STRING, // Status
461
G_TYPE_BOOLEAN, // Enabled / Disabled
462
G_TYPE_POINTER // Pointer to the Object
465
account_list_config_dialog_fill();
467
treeView = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(accountStore)));
468
treeSelection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView));
469
g_signal_connect(G_OBJECT(treeSelection), "changed",
470
G_CALLBACK(select_account_cb),
473
renderer = gtk_cell_renderer_toggle_new();
474
treeViewColumn = gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", COLUMN_ACCOUNT_ACTIVE , NULL);
475
gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn);
476
g_signal_connect(G_OBJECT(renderer) , "toggled" , G_CALLBACK(enable_account_cb), (gpointer) treeView);
478
// gtk_cell_renderer_toggle_set_activatable (renderer, FALSE);
480
renderer = gtk_cell_renderer_text_new();
481
treeViewColumn = gtk_tree_view_column_new_with_attributes("Alias",
483
"markup", COLUMN_ACCOUNT_ALIAS,
485
gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn);
487
// A double click on the account line opens the window to edit the account
488
g_signal_connect(G_OBJECT(treeView) , "row-activated" , G_CALLBACK(edit_account_cb) , NULL);
489
gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL);
491
renderer = gtk_cell_renderer_text_new();
492
treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Protocol"),
494
"markup", COLUMN_ACCOUNT_TYPE,
496
gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn);
497
gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL);
499
renderer = gtk_cell_renderer_text_new();
500
treeViewColumn = gtk_tree_view_column_new_with_attributes(_("Status"),
502
"markup", COLUMN_ACCOUNT_STATUS,
504
gtk_tree_view_append_column(GTK_TREE_VIEW(treeView), treeViewColumn);
505
// Highlight IP profile
506
gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_ip_profile, NULL, NULL);
507
// Highlight account registration state
508
gtk_tree_view_column_set_cell_data_func(treeViewColumn, renderer, highlight_registration, NULL, NULL);
510
g_object_unref(G_OBJECT(accountStore));
512
gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(treeView));
514
/* The buttons to press! */
515
buttonBox = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
516
gtk_box_set_spacing(GTK_BOX(buttonBox), 10);
517
gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonBox), GTK_BUTTONBOX_START);
518
gtk_table_attach(GTK_TABLE(table), buttonBox, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
520
accountMoveUpButton = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
521
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveUpButton), FALSE);
522
gtk_box_pack_start(GTK_BOX(buttonBox), accountMoveUpButton, FALSE, FALSE, 0);
523
g_signal_connect(G_OBJECT(accountMoveUpButton), "clicked", G_CALLBACK(account_move_up_cb), treeView);
525
accountMoveDownButton = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
526
gtk_widget_set_sensitive(GTK_WIDGET(accountMoveDownButton), FALSE);
527
gtk_box_pack_start(GTK_BOX(buttonBox), accountMoveDownButton, FALSE, FALSE, 0);
528
g_signal_connect(G_OBJECT(accountMoveDownButton), "clicked", G_CALLBACK(account_move_down_cb), treeView);
530
addButton = gtk_button_new_from_stock(GTK_STOCK_ADD);
531
g_signal_connect_swapped(G_OBJECT(addButton), "clicked",
532
G_CALLBACK(add_account_cb), NULL);
533
gtk_box_pack_start(GTK_BOX(buttonBox), addButton, FALSE, FALSE, 0);
535
editButton = gtk_button_new_from_stock(GTK_STOCK_EDIT);
536
gtk_widget_set_sensitive(GTK_WIDGET(editButton), FALSE);
537
g_signal_connect_swapped(G_OBJECT(editButton), "clicked",
538
G_CALLBACK(edit_account_cb), NULL);
539
gtk_box_pack_start(GTK_BOX(buttonBox), editButton, FALSE, FALSE, 0);
541
deleteButton = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
542
gtk_widget_set_sensitive(GTK_WIDGET(deleteButton), FALSE);
543
g_signal_connect_swapped(G_OBJECT(deleteButton), "clicked",
544
G_CALLBACK(delete_account_cb), NULL);
545
gtk_box_pack_start(GTK_BOX(buttonBox), deleteButton, FALSE, FALSE, 0);
547
/* help and close buttons */
548
GtkWidget * buttonHbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
549
gtk_table_attach(GTK_TABLE(table), buttonHbox, 0, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 10);
551
GtkWidget * helpButton = gtk_button_new_from_stock(GTK_STOCK_HELP);
552
g_signal_connect_swapped(G_OBJECT(helpButton), "clicked",
553
G_CALLBACK(help_contents_cb), NULL);
554
gtk_box_pack_start(GTK_BOX(buttonHbox), helpButton, FALSE, FALSE, 0);
556
GtkWidget * closeButton = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
557
g_signal_connect_swapped(G_OBJECT(closeButton), "clicked", G_CALLBACK(close_dialog_cb), NULL);
558
gtk_box_pack_start(GTK_BOX(buttonHbox), closeButton, FALSE, FALSE, 0);
560
gtk_widget_show_all(table);
561
// account_list_config_dialog_fill();
563
/* Resize the scrolledWindow for a better view */
564
gtk_widget_get_preferred_size(GTK_WIDGET(treeView), NULL, &requisition);
565
gtk_widget_set_size_request(GTK_WIDGET(scrolledWindow), requisition.width + 20, requisition.height);
566
GtkRequisition requisitionButton;
567
gtk_widget_get_preferred_size(GTK_WIDGET(deleteButton), NULL, &requisitionButton);
568
gtk_widget_set_size_request(GTK_WIDGET(closeButton), requisitionButton.width, -1);
569
gtk_widget_set_size_request(GTK_WIDGET(helpButton), requisitionButton.width, -1);
571
gtk_widget_show_all(table);
577
show_account_list_config_dialog(void)
579
accountListDialog = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Accounts"),
580
GTK_WINDOW(get_main_window()),
581
GTK_DIALOG_DESTROY_WITH_PARENT,
584
/* Set window properties */
585
gtk_container_set_border_width(GTK_CONTAINER(accountListDialog), 0);
586
gtk_window_set_resizable(GTK_WINDOW(accountListDialog), FALSE);
588
GtkWidget *accountFrame = gnome_main_section_new(_("Configured Accounts"));
589
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(accountListDialog)),
590
accountFrame, TRUE, TRUE, 0);
591
gtk_widget_show(accountFrame);
594
GtkWidget *tab = create_account_list(accountListDialog);
595
gtk_widget_show(tab);
596
gtk_container_add(GTK_CONTAINER(accountFrame), tab);
598
/* Status bar for the account list */
599
status_bar = gtk_statusbar_new();
600
gtk_widget_show (status_bar);
601
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area(accountListDialog)), status_bar, TRUE, TRUE, 0);
603
int number_accounts = account_list_get_registered_accounts();
605
if (number_accounts) {
606
gchar * message = g_strdup_printf(n_("There is %d active account",
607
"There are %d active accounts",
608
number_accounts), number_accounts);
609
gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION, message);
612
gtk_statusbar_push(GTK_STATUSBAR(status_bar), CONTEXT_ID_REGISTRATION,
613
_("You have no active account"));
615
gtk_dialog_run(accountListDialog);
617
status_bar_display_account();
619
gtk_widget_destroy(GTK_WIDGET(accountListDialog));
620
accountListDialog = NULL;