pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
merge of '86051d2c303f072b84abd0c006f6ca4e7bd9cea7'
release-2.2.1
2007-10-01, Luke Schierer
4d3a417f3d02
merge of '86051d2c303f072b84abd0c006f6ca4e7bd9cea7'
and 'd698a51b3942fded75c51a242afa92541254da2d'
/**
* @file gtkaccount.c GTK+ Account Editor UI
* @ingroup pidgin
*/
/* pidgin
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include
"internal.h"
#include
"pidgin.h"
#include
"account.h"
#include
"accountopt.h"
#include
"core.h"
#include
"debug.h"
#include
"notify.h"
#include
"plugin.h"
#include
"prefs.h"
#include
"prpl.h"
#include
"request.h"
#include
"savedstatuses.h"
#include
"signals.h"
#include
"util.h"
#include
"gtkaccount.h"
#include
"gtkblist.h"
#include
"gtkdialogs.h"
#include
"gtkutils.h"
#include
"gtkstatusbox.h"
#include
"pidginstock.h"
enum
{
COLUMN_ICON
,
COLUMN_BUDDYICON
,
COLUMN_SCREENNAME
,
COLUMN_ENABLED
,
COLUMN_PROTOCOL
,
COLUMN_DATA
,
COLUMN_PULSE_DATA
,
NUM_COLUMNS
};
typedef
struct
{
PurpleAccount
*
account
;
char
*
username
;
char
*
alias
;
}
PidginAccountAddUserData
;
typedef
struct
{
GtkWidget
*
window
;
GtkWidget
*
treeview
;
GtkWidget
*
modify_button
;
GtkWidget
*
delete_button
;
GtkWidget
*
notebook
;
GtkListStore
*
model
;
GtkTreeIter
drag_iter
;
GtkTreeViewColumn
*
screenname_col
;
}
AccountsWindow
;
typedef
struct
{
PidginAccountDialogType
type
;
PurpleAccount
*
account
;
char
*
protocol_id
;
PurplePlugin
*
plugin
;
PurplePluginProtocolInfo
*
prpl_info
;
PurpleProxyType
new_proxy_type
;
GList
*
user_split_entries
;
GList
*
protocol_opt_entries
;
GtkSizeGroup
*
sg
;
GtkWidget
*
window
;
GtkWidget
*
top_vbox
;
GtkWidget
*
bottom_vbox
;
GtkWidget
*
ok_button
;
GtkWidget
*
register_button
;
/* Login Options */
GtkWidget
*
login_frame
;
GtkWidget
*
protocol_menu
;
GtkWidget
*
password_box
;
GtkWidget
*
screenname_entry
;
GtkWidget
*
password_entry
;
GtkWidget
*
alias_entry
;
GtkWidget
*
remember_pass_check
;
/* User Options */
GtkWidget
*
user_frame
;
GtkWidget
*
new_mail_check
;
GtkWidget
*
icon_hbox
;
GtkWidget
*
icon_check
;
GtkWidget
*
icon_entry
;
GtkWidget
*
icon_filesel
;
GtkWidget
*
icon_preview
;
GtkWidget
*
icon_text
;
PurpleStoredImage
*
icon_img
;
/* Protocol Options */
GtkWidget
*
protocol_frame
;
/* Proxy Options */
GtkWidget
*
proxy_frame
;
GtkWidget
*
proxy_vbox
;
GtkWidget
*
proxy_dropdown
;
GtkWidget
*
proxy_host_entry
;
GtkWidget
*
proxy_port_entry
;
GtkWidget
*
proxy_user_entry
;
GtkWidget
*
proxy_pass_entry
;
}
AccountPrefsDialog
;
typedef
struct
{
GdkPixbuf
*
online_pixbuf
;
gboolean
pulse_to_grey
;
float
pulse_value
;
int
timeout
;
PurpleAccount
*
account
;
GtkTreeModel
*
model
;
}
PidginPulseData
;
static
AccountsWindow
*
accounts_window
=
NULL
;
static
GHashTable
*
account_pref_wins
;
static
void
add_account_to_liststore
(
PurpleAccount
*
account
,
gpointer
user_data
);
static
void
set_account
(
GtkListStore
*
store
,
GtkTreeIter
*
iter
,
PurpleAccount
*
account
,
GdkPixbuf
*
global_buddyicon
);
/**************************************************************************
* Add/Modify Account dialog
**************************************************************************/
static
void
add_login_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
);
static
void
add_user_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
);
static
void
add_protocol_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
);
static
void
add_proxy_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
);
static
GtkWidget
*
add_pref_box
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
,
const
char
*
text
,
GtkWidget
*
widget
)
{
GtkWidget
*
hbox
;
GtkWidget
*
label
;
hbox
=
gtk_hbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_box_pack_start
(
GTK_BOX
(
parent
),
hbox
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
hbox
);
label
=
gtk_label_new_with_mnemonic
(
text
);
gtk_size_group_add_widget
(
dialog
->
sg
,
label
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0
,
0.5
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
gtk_label_set_mnemonic_widget
(
GTK_LABEL
(
label
),
widget
);
gtk_widget_show
(
label
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
widget
,
TRUE
,
TRUE
,
PIDGIN_HIG_BORDER
);
gtk_widget_show
(
widget
);
pidgin_set_accessible_label
(
widget
,
label
);
return
hbox
;
}
static
void
set_dialog_icon
(
AccountPrefsDialog
*
dialog
,
gpointer
data
,
size_t
len
,
gchar
*
new_icon_path
)
{
GdkPixbuf
*
pixbuf
=
NULL
;
dialog
->
icon_img
=
purple_imgstore_unref
(
dialog
->
icon_img
);
if
(
data
!=
NULL
)
{
if
(
len
>
0
)
dialog
->
icon_img
=
purple_imgstore_add
(
data
,
len
,
new_icon_path
);
else
g_free
(
data
);
}
if
(
dialog
->
icon_img
!=
NULL
)
{
GdkPixbufLoader
*
loader
=
gdk_pixbuf_loader_new
();
gdk_pixbuf_loader_write
(
loader
,
purple_imgstore_get_data
(
dialog
->
icon_img
),
purple_imgstore_get_size
(
dialog
->
icon_img
),
NULL
);
gdk_pixbuf_loader_close
(
loader
,
NULL
);
pixbuf
=
gdk_pixbuf_loader_get_pixbuf
(
loader
);
}
if
(
pixbuf
&&
dialog
->
prpl_info
&&
(
dialog
->
prpl_info
->
icon_spec
.
scale_rules
&
PURPLE_ICON_SCALE_DISPLAY
))
{
/* Scale the icon to something reasonable */
int
width
,
height
;
GdkPixbuf
*
scale
;
pidgin_buddy_icon_get_scale_size
(
pixbuf
,
&
dialog
->
prpl_info
->
icon_spec
,
PURPLE_ICON_SCALE_DISPLAY
,
&
width
,
&
height
);
scale
=
gdk_pixbuf_scale_simple
(
pixbuf
,
width
,
height
,
GDK_INTERP_BILINEAR
);
g_object_unref
(
G_OBJECT
(
pixbuf
));
pixbuf
=
scale
;
}
if
(
pixbuf
==
NULL
)
{
/* Show a placeholder icon */
GtkIconSize
icon_size
=
gtk_icon_size_from_name
(
PIDGIN_ICON_SIZE_TANGO_SMALL
);
pixbuf
=
gtk_widget_render_icon
(
dialog
->
window
,
PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR
,
icon_size
,
"PidginAccount"
);
}
gtk_image_set_from_pixbuf
(
GTK_IMAGE
(
dialog
->
icon_entry
),
pixbuf
);
if
(
pixbuf
!=
NULL
)
g_object_unref
(
G_OBJECT
(
pixbuf
));
}
static
void
set_account_protocol_cb
(
GtkWidget
*
item
,
const
char
*
id
,
AccountPrefsDialog
*
dialog
)
{
PurplePlugin
*
new_plugin
;
new_plugin
=
purple_find_prpl
(
id
);
dialog
->
plugin
=
new_plugin
;
if
(
dialog
->
plugin
!=
NULL
)
{
dialog
->
prpl_info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
dialog
->
plugin
);
g_free
(
dialog
->
protocol_id
);
dialog
->
protocol_id
=
g_strdup
(
dialog
->
plugin
->
info
->
id
);
}
if
(
dialog
->
account
!=
NULL
)
purple_account_clear_settings
(
dialog
->
account
);
add_login_options
(
dialog
,
dialog
->
top_vbox
);
add_user_options
(
dialog
,
dialog
->
top_vbox
);
add_protocol_options
(
dialog
,
dialog
->
bottom_vbox
);
gtk_widget_grab_focus
(
dialog
->
protocol_menu
);
if
(
!
dialog
->
prpl_info
||
!
dialog
->
prpl_info
->
register_user
||
g_object_get_data
(
G_OBJECT
(
item
),
"fake"
))
{
gtk_widget_hide
(
dialog
->
register_button
);
}
else
{
if
(
dialog
->
prpl_info
!=
NULL
&&
(
dialog
->
prpl_info
->
options
&
OPT_PROTO_REGISTER_NOSCREENNAME
))
{
gtk_widget_set_sensitive
(
dialog
->
register_button
,
TRUE
);
}
else
{
gtk_widget_set_sensitive
(
dialog
->
register_button
,
FALSE
);
}
gtk_widget_show
(
dialog
->
register_button
);
}
}
static
void
screenname_changed_cb
(
GtkEntry
*
entry
,
AccountPrefsDialog
*
dialog
)
{
if
(
dialog
->
ok_button
)
gtk_widget_set_sensitive
(
dialog
->
ok_button
,
*
gtk_entry_get_text
(
entry
)
!=
'\0'
);
if
(
dialog
->
register_button
)
{
if
(
dialog
->
prpl_info
!=
NULL
&&
(
dialog
->
prpl_info
->
options
&
OPT_PROTO_REGISTER_NOSCREENNAME
))
gtk_widget_set_sensitive
(
dialog
->
register_button
,
TRUE
);
else
gtk_widget_set_sensitive
(
dialog
->
register_button
,
*
gtk_entry_get_text
(
entry
)
!=
'\0'
);
}
}
static
void
icon_filesel_choose_cb
(
const
char
*
filename
,
gpointer
data
)
{
AccountPrefsDialog
*
dialog
=
data
;
if
(
filename
!=
NULL
)
{
size_t
len
;
gpointer
data
=
pidgin_convert_buddy_icon
(
dialog
->
plugin
,
filename
,
&
len
);
set_dialog_icon
(
dialog
,
data
,
len
,
g_strdup
(
filename
));
}
dialog
->
icon_filesel
=
NULL
;
}
static
void
icon_select_cb
(
GtkWidget
*
button
,
AccountPrefsDialog
*
dialog
)
{
dialog
->
icon_filesel
=
pidgin_buddy_icon_chooser_new
(
GTK_WINDOW
(
dialog
->
window
),
icon_filesel_choose_cb
,
dialog
);
gtk_widget_show_all
(
dialog
->
icon_filesel
);
}
static
void
icon_reset_cb
(
GtkWidget
*
button
,
AccountPrefsDialog
*
dialog
)
{
set_dialog_icon
(
dialog
,
NULL
,
0
,
NULL
);
}
static
void
account_dnd_recv
(
GtkWidget
*
widget
,
GdkDragContext
*
dc
,
gint
x
,
gint
y
,
GtkSelectionData
*
sd
,
guint
info
,
guint
t
,
AccountPrefsDialog
*
dialog
)
{
gchar
*
name
=
(
gchar
*
)
sd
->
data
;
if
((
sd
->
length
>=
0
)
&&
(
sd
->
format
==
8
))
{
/* Well, it looks like the drag event was cool.
* Let's do something with it */
if
(
!
g_ascii_strncasecmp
(
name
,
"file://"
,
7
))
{
GError
*
converr
=
NULL
;
gchar
*
tmp
,
*
rtmp
;
gpointer
data
;
size_t
len
;
/* It looks like we're dealing with a local file. */
if
(
!
(
tmp
=
g_filename_from_uri
(
name
,
NULL
,
&
converr
)))
{
purple_debug
(
PURPLE_DEBUG_ERROR
,
"buddyicon"
,
"%s
\n
"
,
(
converr
?
converr
->
message
:
"g_filename_from_uri error"
));
return
;
}
if
((
rtmp
=
strchr
(
tmp
,
'\r'
))
||
(
rtmp
=
strchr
(
tmp
,
'\n'
)))
*
rtmp
=
'\0'
;
data
=
pidgin_convert_buddy_icon
(
dialog
->
plugin
,
tmp
,
&
len
);
/* This takes ownership of tmp */
set_dialog_icon
(
dialog
,
data
,
len
,
tmp
);
}
gtk_drag_finish
(
dc
,
TRUE
,
FALSE
,
t
);
}
gtk_drag_finish
(
dc
,
FALSE
,
FALSE
,
t
);
}
static
void
update_editable
(
PurpleConnection
*
gc
,
AccountPrefsDialog
*
dialog
)
{
gboolean
set
;
GList
*
l
;
if
(
dialog
->
account
==
NULL
)
return
;
if
(
gc
!=
NULL
&&
dialog
->
account
!=
purple_connection_get_account
(
gc
))
return
;
set
=
!
(
purple_account_is_connected
(
dialog
->
account
)
||
purple_account_is_connecting
(
dialog
->
account
));
gtk_widget_set_sensitive
(
dialog
->
protocol_menu
,
set
);
gtk_widget_set_sensitive
(
dialog
->
screenname_entry
,
set
);
for
(
l
=
dialog
->
user_split_entries
;
l
!=
NULL
;
l
=
l
->
next
)
gtk_widget_set_sensitive
((
GtkWidget
*
)
l
->
data
,
set
);
}
static
void
add_login_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
)
{
GtkWidget
*
frame
;
GtkWidget
*
hbox
;
GtkWidget
*
vbox
;
GtkWidget
*
entry
;
GtkWidget
*
menu
;
GtkWidget
*
item
;
GList
*
user_splits
;
GList
*
l
,
*
l2
;
char
*
username
=
NULL
;
if
(
dialog
->
protocol_menu
!=
NULL
)
{
gtk_widget_ref
(
dialog
->
protocol_menu
);
hbox
=
g_object_get_data
(
G_OBJECT
(
dialog
->
protocol_menu
),
"container"
);
gtk_container_remove
(
GTK_CONTAINER
(
hbox
),
dialog
->
protocol_menu
);
}
if
(
dialog
->
login_frame
!=
NULL
)
gtk_widget_destroy
(
dialog
->
login_frame
);
/* Build the login options frame. */
frame
=
pidgin_make_frame
(
parent
,
_
(
"Login Options"
));
/* cringe */
dialog
->
login_frame
=
gtk_widget_get_parent
(
gtk_widget_get_parent
(
frame
));
gtk_box_reorder_child
(
GTK_BOX
(
parent
),
dialog
->
login_frame
,
0
);
gtk_widget_show
(
dialog
->
login_frame
);
/* Main vbox */
vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
vbox
);
gtk_widget_show
(
vbox
);
/* Protocol */
if
(
dialog
->
protocol_menu
==
NULL
)
{
dialog
->
protocol_menu
=
pidgin_protocol_option_menu_new
(
dialog
->
protocol_id
,
G_CALLBACK
(
set_account_protocol_cb
),
dialog
);
gtk_widget_ref
(
dialog
->
protocol_menu
);
}
hbox
=
add_pref_box
(
dialog
,
vbox
,
_
(
"Pro_tocol:"
),
dialog
->
protocol_menu
);
g_object_set_data
(
G_OBJECT
(
dialog
->
protocol_menu
),
"container"
,
hbox
);
gtk_widget_unref
(
dialog
->
protocol_menu
);
/* Screen name */
dialog
->
screenname_entry
=
gtk_entry_new
();
#if GTK_CHECK_VERSION(2,10,0)
g_object_set
(
G_OBJECT
(
dialog
->
screenname_entry
),
"truncate-multiline"
,
TRUE
,
NULL
);
#endif
add_pref_box
(
dialog
,
vbox
,
_
(
"Screen _name:"
),
dialog
->
screenname_entry
);
g_signal_connect
(
G_OBJECT
(
dialog
->
screenname_entry
),
"changed"
,
G_CALLBACK
(
screenname_changed_cb
),
dialog
);
/* Do the user split thang */
if
(
dialog
->
plugin
==
NULL
)
/* Yeah right. */
user_splits
=
NULL
;
else
user_splits
=
dialog
->
prpl_info
->
user_splits
;
if
(
dialog
->
account
!=
NULL
)
username
=
g_strdup
(
purple_account_get_username
(
dialog
->
account
));
if
(
dialog
->
user_split_entries
!=
NULL
)
{
g_list_free
(
dialog
->
user_split_entries
);
dialog
->
user_split_entries
=
NULL
;
}
for
(
l
=
user_splits
;
l
!=
NULL
;
l
=
l
->
next
)
{
PurpleAccountUserSplit
*
split
=
l
->
data
;
char
*
buf
;
buf
=
g_strdup_printf
(
"_%s:"
,
purple_account_user_split_get_text
(
split
));
entry
=
gtk_entry_new
();
add_pref_box
(
dialog
,
vbox
,
buf
,
entry
);
g_free
(
buf
);
dialog
->
user_split_entries
=
g_list_append
(
dialog
->
user_split_entries
,
entry
);
}
for
(
l
=
g_list_last
(
dialog
->
user_split_entries
),
l2
=
g_list_last
(
user_splits
);
l
!=
NULL
&&
l2
!=
NULL
;
l
=
l
->
prev
,
l2
=
l2
->
prev
)
{
GtkWidget
*
entry
=
l
->
data
;
PurpleAccountUserSplit
*
split
=
l2
->
data
;
const
char
*
value
=
NULL
;
char
*
c
;
if
(
dialog
->
account
!=
NULL
)
{
if
(
purple_account_user_split_get_reverse
(
split
))
c
=
strrchr
(
username
,
purple_account_user_split_get_separator
(
split
));
else
c
=
strchr
(
username
,
purple_account_user_split_get_separator
(
split
));
if
(
c
!=
NULL
)
{
*
c
=
'\0'
;
c
++
;
value
=
c
;
}
}
if
(
value
==
NULL
)
value
=
purple_account_user_split_get_default_value
(
split
);
/* Google Talk default domain hackery! */
menu
=
gtk_option_menu_get_menu
(
GTK_OPTION_MENU
(
dialog
->
protocol_menu
));
item
=
gtk_menu_get_active
(
GTK_MENU
(
menu
));
if
(
value
==
NULL
&&
g_object_get_data
(
G_OBJECT
(
item
),
"fake"
)
&&
!
strcmp
(
purple_account_user_split_get_text
(
split
),
_
(
"Domain"
)))
value
=
"gmail.com"
;
if
(
value
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
value
);
}
if
(
username
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
screenname_entry
),
username
);
g_free
(
username
);
/* Password */
dialog
->
password_entry
=
gtk_entry_new
();
gtk_entry_set_visibility
(
GTK_ENTRY
(
dialog
->
password_entry
),
FALSE
);
if
(
gtk_entry_get_invisible_char
(
GTK_ENTRY
(
dialog
->
password_entry
))
==
'*'
)
gtk_entry_set_invisible_char
(
GTK_ENTRY
(
dialog
->
password_entry
),
PIDGIN_INVISIBLE_CHAR
);
dialog
->
password_box
=
add_pref_box
(
dialog
,
vbox
,
_
(
"_Password:"
),
dialog
->
password_entry
);
/* Alias */
dialog
->
alias_entry
=
gtk_entry_new
();
add_pref_box
(
dialog
,
vbox
,
_
(
"_Local alias:"
),
dialog
->
alias_entry
);
/* Remember Password */
dialog
->
remember_pass_check
=
gtk_check_button_new_with_mnemonic
(
_
(
"Remember pass_word"
));
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
remember_pass_check
),
FALSE
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
dialog
->
remember_pass_check
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
dialog
->
remember_pass_check
);
/* Set the fields. */
if
(
dialog
->
account
!=
NULL
)
{
if
(
purple_account_get_password
(
dialog
->
account
))
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
password_entry
),
purple_account_get_password
(
dialog
->
account
));
if
(
purple_account_get_alias
(
dialog
->
account
))
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
alias_entry
),
purple_account_get_alias
(
dialog
->
account
));
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
remember_pass_check
),
purple_account_get_remember_password
(
dialog
->
account
));
}
if
(
dialog
->
prpl_info
!=
NULL
&&
(
dialog
->
prpl_info
->
options
&
OPT_PROTO_NO_PASSWORD
))
{
gtk_widget_hide
(
dialog
->
password_box
);
gtk_widget_hide
(
dialog
->
remember_pass_check
);
}
/* Do not let the user change the protocol/screenname while connected. */
update_editable
(
NULL
,
dialog
);
purple_signal_connect
(
purple_connections_get_handle
(),
"signing-on"
,
dialog
,
G_CALLBACK
(
update_editable
),
dialog
);
purple_signal_connect
(
purple_connections_get_handle
(),
"signed-off"
,
dialog
,
G_CALLBACK
(
update_editable
),
dialog
);
}
static
void
icon_check_cb
(
GtkWidget
*
checkbox
,
AccountPrefsDialog
*
dialog
)
{
gtk_widget_set_sensitive
(
dialog
->
icon_hbox
,
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
icon_check
)));
}
static
void
add_user_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
)
{
GtkWidget
*
frame
;
GtkWidget
*
vbox
;
GtkWidget
*
vbox2
;
GtkWidget
*
hbox
;
GtkWidget
*
hbox2
;
GtkWidget
*
button
;
GtkWidget
*
label
;
if
(
dialog
->
user_frame
!=
NULL
)
gtk_widget_destroy
(
dialog
->
user_frame
);
/* Build the user options frame. */
frame
=
pidgin_make_frame
(
parent
,
_
(
"User Options"
));
dialog
->
user_frame
=
gtk_widget_get_parent
(
gtk_widget_get_parent
(
frame
));
gtk_box_reorder_child
(
GTK_BOX
(
parent
),
dialog
->
user_frame
,
1
);
gtk_widget_show
(
dialog
->
user_frame
);
/* Main vbox */
vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
vbox
);
gtk_widget_show
(
vbox
);
/* New mail notifications */
dialog
->
new_mail_check
=
gtk_check_button_new_with_mnemonic
(
_
(
"New _mail notifications"
));
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
dialog
->
new_mail_check
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
dialog
->
new_mail_check
);
/* Buddy icon */
dialog
->
icon_check
=
gtk_check_button_new_with_mnemonic
(
_
(
"Use this buddy _icon for this account:"
));
g_signal_connect
(
G_OBJECT
(
dialog
->
icon_check
),
"toggled"
,
G_CALLBACK
(
icon_check_cb
),
dialog
);
gtk_widget_show
(
dialog
->
icon_check
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
dialog
->
icon_check
,
FALSE
,
FALSE
,
0
);
dialog
->
icon_hbox
=
hbox
=
gtk_hbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_widget_set_sensitive
(
hbox
,
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
icon_check
)));
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
hbox
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
hbox
);
label
=
gtk_label_new
(
" "
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
label
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
label
);
button
=
gtk_button_new
();
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
button
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
icon_select_cb
),
dialog
);
dialog
->
icon_entry
=
gtk_image_new
();
gtk_container_add
(
GTK_CONTAINER
(
button
),
dialog
->
icon_entry
);
gtk_widget_show
(
dialog
->
icon_entry
);
/* TODO: Uh, isn't this next line pretty useless? */
pidgin_set_accessible_label
(
dialog
->
icon_entry
,
label
);
purple_imgstore_unref
(
dialog
->
icon_img
);
dialog
->
icon_img
=
NULL
;
vbox2
=
gtk_vbox_new
(
FALSE
,
0
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
vbox2
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
vbox2
);
hbox2
=
gtk_hbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_box_pack_start
(
GTK_BOX
(
vbox2
),
hbox2
,
FALSE
,
FALSE
,
PIDGIN_HIG_BORDER
);
gtk_widget_show
(
hbox2
);
button
=
gtk_button_new_from_stock
(
GTK_STOCK_REMOVE
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
icon_reset_cb
),
dialog
);
gtk_box_pack_start
(
GTK_BOX
(
hbox2
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
button
);
if
(
dialog
->
prpl_info
!=
NULL
)
{
if
(
!
(
dialog
->
prpl_info
->
options
&
OPT_PROTO_MAIL_CHECK
))
gtk_widget_hide
(
dialog
->
new_mail_check
);
if
(
dialog
->
prpl_info
->
icon_spec
.
format
==
NULL
)
{
gtk_widget_hide
(
dialog
->
icon_check
);
gtk_widget_hide
(
dialog
->
icon_hbox
);
}
}
if
(
dialog
->
account
!=
NULL
)
{
PurpleStoredImage
*
img
;
gpointer
data
=
NULL
;
size_t
len
=
0
;
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
new_mail_check
),
purple_account_get_check_mail
(
dialog
->
account
));
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
icon_check
),
!
purple_account_get_bool
(
dialog
->
account
,
"use-global-buddyicon"
,
TRUE
));
img
=
purple_buddy_icons_find_account_icon
(
dialog
->
account
);
if
(
img
)
{
len
=
purple_imgstore_get_size
(
img
);
data
=
g_memdup
(
purple_imgstore_get_data
(
img
),
len
);
}
set_dialog_icon
(
dialog
,
data
,
len
,
g_strdup
(
purple_account_get_buddy_icon_path
(
dialog
->
account
)));
}
else
{
set_dialog_icon
(
dialog
,
NULL
,
0
,
NULL
);
}
if
(
!
dialog
->
prpl_info
||
(
!
(
dialog
->
prpl_info
->
options
&
OPT_PROTO_MAIL_CHECK
)
&&
(
dialog
->
prpl_info
->
icon_spec
.
format
==
NULL
)))
{
/* Nothing to see :( aww. */
gtk_widget_hide
(
dialog
->
user_frame
);
}
}
static
void
add_protocol_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
)
{
PurpleAccountOption
*
option
;
PurpleAccount
*
account
;
GtkWidget
*
frame
,
*
vbox
,
*
check
,
*
entry
,
*
combo
,
*
menu
,
*
item
;
GList
*
list
,
*
node
;
gint
i
,
idx
,
int_value
;
GtkListStore
*
model
;
GtkTreeIter
iter
;
GtkCellRenderer
*
renderer
;
PurpleKeyValuePair
*
kvp
;
GList
*
l
;
char
buf
[
1024
];
char
*
title
,
*
tmp
;
const
char
*
str_value
;
gboolean
bool_value
;
if
(
dialog
->
protocol_frame
!=
NULL
)
{
gtk_widget_destroy
(
dialog
->
protocol_frame
);
dialog
->
protocol_frame
=
NULL
;
}
if
(
dialog
->
protocol_opt_entries
!=
NULL
)
{
g_list_free
(
dialog
->
protocol_opt_entries
);
dialog
->
protocol_opt_entries
=
NULL
;
}
if
(
dialog
->
prpl_info
==
NULL
||
dialog
->
prpl_info
->
protocol_options
==
NULL
)
{
return
;
}
account
=
dialog
->
account
;
/* Build the protocol options frame. */
g_snprintf
(
buf
,
sizeof
(
buf
),
_
(
"%s Options"
),
dialog
->
plugin
->
info
->
name
);
frame
=
pidgin_make_frame
(
parent
,
buf
);
dialog
->
protocol_frame
=
gtk_widget_get_parent
(
gtk_widget_get_parent
(
frame
));
gtk_box_reorder_child
(
GTK_BOX
(
parent
),
dialog
->
protocol_frame
,
0
);
gtk_widget_show
(
dialog
->
protocol_frame
);
/* Main vbox */
vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
vbox
);
gtk_widget_show
(
vbox
);
for
(
l
=
dialog
->
prpl_info
->
protocol_options
;
l
!=
NULL
;
l
=
l
->
next
)
{
option
=
(
PurpleAccountOption
*
)
l
->
data
;
switch
(
purple_account_option_get_type
(
option
))
{
case
PURPLE_PREF_BOOLEAN
:
if
(
account
==
NULL
||
strcmp
(
purple_account_get_protocol_id
(
account
),
dialog
->
protocol_id
))
{
bool_value
=
purple_account_option_get_default_bool
(
option
);
}
else
{
bool_value
=
purple_account_get_bool
(
account
,
purple_account_option_get_setting
(
option
),
purple_account_option_get_default_bool
(
option
));
}
tmp
=
g_strconcat
(
"_"
,
purple_account_option_get_text
(
option
),
NULL
);
check
=
gtk_check_button_new_with_mnemonic
(
tmp
);
g_free
(
tmp
);
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
check
),
bool_value
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
check
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
check
);
dialog
->
protocol_opt_entries
=
g_list_append
(
dialog
->
protocol_opt_entries
,
check
);
break
;
case
PURPLE_PREF_INT
:
if
(
account
==
NULL
||
strcmp
(
purple_account_get_protocol_id
(
account
),
dialog
->
protocol_id
))
{
int_value
=
purple_account_option_get_default_int
(
option
);
}
else
{
int_value
=
purple_account_get_int
(
account
,
purple_account_option_get_setting
(
option
),
purple_account_option_get_default_int
(
option
));
}
g_snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
int_value
);
entry
=
gtk_entry_new
();
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
buf
);
title
=
g_strdup_printf
(
"_%s:"
,
purple_account_option_get_text
(
option
));
add_pref_box
(
dialog
,
vbox
,
title
,
entry
);
g_free
(
title
);
dialog
->
protocol_opt_entries
=
g_list_append
(
dialog
->
protocol_opt_entries
,
entry
);
break
;
case
PURPLE_PREF_STRING
:
if
(
account
==
NULL
||
strcmp
(
purple_account_get_protocol_id
(
account
),
dialog
->
protocol_id
))
{
str_value
=
purple_account_option_get_default_string
(
option
);
}
else
{
str_value
=
purple_account_get_string
(
account
,
purple_account_option_get_setting
(
option
),
purple_account_option_get_default_string
(
option
));
}
entry
=
gtk_entry_new
();
if
(
purple_account_option_get_masked
(
option
))
{
gtk_entry_set_visibility
(
GTK_ENTRY
(
entry
),
FALSE
);
if
(
gtk_entry_get_invisible_char
(
GTK_ENTRY
(
entry
))
==
'*'
)
gtk_entry_set_invisible_char
(
GTK_ENTRY
(
entry
),
PIDGIN_INVISIBLE_CHAR
);
}
/* Google Talk default domain hackery! */
menu
=
gtk_option_menu_get_menu
(
GTK_OPTION_MENU
(
dialog
->
protocol_menu
));
item
=
gtk_menu_get_active
(
GTK_MENU
(
menu
));
if
(
str_value
==
NULL
&&
g_object_get_data
(
G_OBJECT
(
item
),
"fake"
)
&&
!
strcmp
(
_
(
"Connect server"
),
purple_account_option_get_text
(
option
)))
str_value
=
"talk.google.com"
;
if
(
str_value
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
str_value
);
title
=
g_strdup_printf
(
"_%s:"
,
purple_account_option_get_text
(
option
));
add_pref_box
(
dialog
,
vbox
,
title
,
entry
);
g_free
(
title
);
dialog
->
protocol_opt_entries
=
g_list_append
(
dialog
->
protocol_opt_entries
,
entry
);
break
;
case
PURPLE_PREF_STRING_LIST
:
i
=
0
;
idx
=
0
;
if
(
account
==
NULL
||
strcmp
(
purple_account_get_protocol_id
(
account
),
dialog
->
protocol_id
))
{
str_value
=
purple_account_option_get_default_list_value
(
option
);
}
else
{
str_value
=
purple_account_get_string
(
account
,
purple_account_option_get_setting
(
option
),
purple_account_option_get_default_list_value
(
option
));
}
list
=
purple_account_option_get_list
(
option
);
model
=
gtk_list_store_new
(
2
,
G_TYPE_STRING
,
G_TYPE_POINTER
);
combo
=
gtk_combo_box_new_with_model
(
GTK_TREE_MODEL
(
model
));
/* Loop through list of PurpleKeyValuePair items */
for
(
node
=
list
;
node
!=
NULL
;
node
=
node
->
next
)
{
if
(
node
->
data
!=
NULL
)
{
kvp
=
(
PurpleKeyValuePair
*
)
node
->
data
;
if
((
kvp
->
value
!=
NULL
)
&&
(
str_value
!=
NULL
)
&&
!
g_utf8_collate
(
kvp
->
value
,
str_value
))
idx
=
i
;
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
kvp
->
key
,
1
,
kvp
->
value
,
-1
);
}
i
++
;
}
/* Set default */
gtk_combo_box_set_active
(
GTK_COMBO_BOX
(
combo
),
idx
);
/* Define renderer */
renderer
=
gtk_cell_renderer_text_new
();
gtk_cell_layout_pack_start
(
GTK_CELL_LAYOUT
(
combo
),
renderer
,
TRUE
);
gtk_cell_layout_set_attributes
(
GTK_CELL_LAYOUT
(
combo
),
renderer
,
"text"
,
0
,
NULL
);
title
=
g_strdup_printf
(
"_%s:"
,
purple_account_option_get_text
(
option
));
add_pref_box
(
dialog
,
vbox
,
title
,
combo
);
g_free
(
title
);
dialog
->
protocol_opt_entries
=
g_list_append
(
dialog
->
protocol_opt_entries
,
combo
);
break
;
default
:
break
;
}
}
}
static
GtkWidget
*
make_proxy_dropdown
(
void
)
{
GtkWidget
*
dropdown
;
GtkListStore
*
model
;
GtkTreeIter
iter
;
GtkCellRenderer
*
renderer
;
model
=
gtk_list_store_new
(
2
,
G_TYPE_STRING
,
G_TYPE_INT
);
dropdown
=
gtk_combo_box_new_with_model
(
GTK_TREE_MODEL
(
model
));
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
purple_running_gnome
()
?
_
(
"Use GNOME Proxy Settings"
)
:
_
(
"Use Global Proxy Settings"
),
1
,
PURPLE_PROXY_USE_GLOBAL
,
-1
);
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
_
(
"No Proxy"
),
1
,
PURPLE_PROXY_NONE
,
-1
);
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
_
(
"HTTP"
),
1
,
PURPLE_PROXY_HTTP
,
-1
);
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
_
(
"SOCKS 4"
),
1
,
PURPLE_PROXY_SOCKS4
,
-1
);
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
_
(
"SOCKS 5"
),
1
,
PURPLE_PROXY_SOCKS5
,
-1
);
gtk_list_store_append
(
model
,
&
iter
);
gtk_list_store_set
(
model
,
&
iter
,
0
,
_
(
"Use Environmental Settings"
),
1
,
PURPLE_PROXY_USE_ENVVAR
,
-1
);
renderer
=
gtk_cell_renderer_text_new
();
gtk_cell_layout_pack_start
(
GTK_CELL_LAYOUT
(
dropdown
),
renderer
,
TRUE
);
gtk_cell_layout_set_attributes
(
GTK_CELL_LAYOUT
(
dropdown
),
renderer
,
"text"
,
0
,
NULL
);
return
dropdown
;
}
static
void
proxy_type_changed_cb
(
GtkWidget
*
menu
,
AccountPrefsDialog
*
dialog
)
{
dialog
->
new_proxy_type
=
gtk_combo_box_get_active
(
GTK_COMBO_BOX
(
menu
))
-
1
;
if
(
dialog
->
new_proxy_type
==
PURPLE_PROXY_USE_GLOBAL
||
dialog
->
new_proxy_type
==
PURPLE_PROXY_NONE
||
dialog
->
new_proxy_type
==
PURPLE_PROXY_USE_ENVVAR
)
{
gtk_widget_hide_all
(
dialog
->
proxy_vbox
);
}
else
gtk_widget_show_all
(
dialog
->
proxy_vbox
);
}
static
void
port_popup_cb
(
GtkWidget
*
w
,
GtkMenu
*
menu
,
gpointer
data
)
{
GtkWidget
*
item1
;
GtkWidget
*
item2
;
/* This is an easter egg.
It means one of two things, both intended as humourus:
A) your network is really slow and you have nothing better to do than
look at butterflies.
B)You are looking really closely at something that shouldn't matter. */
item1
=
gtk_menu_item_new_with_label
(
_
(
"If you look real closely"
));
/* This is an easter egg. See the comment on the previous line in the source. */
item2
=
gtk_menu_item_new_with_label
(
_
(
"you can see the butterflies mating"
));
gtk_widget_show
(
item1
);
gtk_widget_show
(
item2
);
/* Prepend these in reverse order so they appear correctly. */
gtk_menu_shell_prepend
(
GTK_MENU_SHELL
(
menu
),
item2
);
gtk_menu_shell_prepend
(
GTK_MENU_SHELL
(
menu
),
item1
);
}
static
void
add_proxy_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
)
{
PurpleProxyInfo
*
proxy_info
;
GtkWidget
*
frame
;
GtkWidget
*
vbox
;
GtkWidget
*
vbox2
;
if
(
dialog
->
proxy_frame
!=
NULL
)
gtk_widget_destroy
(
dialog
->
proxy_frame
);
frame
=
pidgin_make_frame
(
parent
,
_
(
"Proxy Options"
));
dialog
->
proxy_frame
=
gtk_widget_get_parent
(
gtk_widget_get_parent
(
frame
));
gtk_box_reorder_child
(
GTK_BOX
(
parent
),
dialog
->
proxy_frame
,
1
);
gtk_widget_show
(
dialog
->
proxy_frame
);
/* Main vbox */
vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
vbox
);
gtk_widget_show
(
vbox
);
/* Proxy Type drop-down. */
dialog
->
proxy_dropdown
=
make_proxy_dropdown
();
add_pref_box
(
dialog
,
vbox
,
_
(
"Proxy _type:"
),
dialog
->
proxy_dropdown
);
/* Setup the second vbox, which may be hidden at times. */
dialog
->
proxy_vbox
=
vbox2
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BOX_SPACE
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
vbox2
,
FALSE
,
FALSE
,
PIDGIN_HIG_BORDER
);
gtk_widget_show
(
vbox2
);
/* Host */
dialog
->
proxy_host_entry
=
gtk_entry_new
();
add_pref_box
(
dialog
,
vbox2
,
_
(
"_Host:"
),
dialog
->
proxy_host_entry
);
/* Port */
dialog
->
proxy_port_entry
=
gtk_entry_new
();
add_pref_box
(
dialog
,
vbox2
,
_
(
"_Port:"
),
dialog
->
proxy_port_entry
);
g_signal_connect
(
G_OBJECT
(
dialog
->
proxy_port_entry
),
"populate-popup"
,
G_CALLBACK
(
port_popup_cb
),
NULL
);
/* User */
dialog
->
proxy_user_entry
=
gtk_entry_new
();
add_pref_box
(
dialog
,
vbox2
,
_
(
"_Username:"
),
dialog
->
proxy_user_entry
);
/* Password */
dialog
->
proxy_pass_entry
=
gtk_entry_new
();
gtk_entry_set_visibility
(
GTK_ENTRY
(
dialog
->
proxy_pass_entry
),
FALSE
);
if
(
gtk_entry_get_invisible_char
(
GTK_ENTRY
(
dialog
->
proxy_pass_entry
))
==
'*'
)
gtk_entry_set_invisible_char
(
GTK_ENTRY
(
dialog
->
proxy_pass_entry
),
PIDGIN_INVISIBLE_CHAR
);
add_pref_box
(
dialog
,
vbox2
,
_
(
"Pa_ssword:"
),
dialog
->
proxy_pass_entry
);
if
(
dialog
->
account
!=
NULL
&&
(
proxy_info
=
purple_account_get_proxy_info
(
dialog
->
account
))
!=
NULL
)
{
PurpleProxyType
type
=
purple_proxy_info_get_type
(
proxy_info
);
const
char
*
value
;
int
int_val
;
/* Hah! */
/* I dunno what you're laughing about, fuzz ball. */
dialog
->
new_proxy_type
=
type
;
gtk_combo_box_set_active
(
GTK_COMBO_BOX
(
dialog
->
proxy_dropdown
),
type
+
1
);
if
(
type
==
PURPLE_PROXY_USE_GLOBAL
||
type
==
PURPLE_PROXY_NONE
||
type
==
PURPLE_PROXY_USE_ENVVAR
)
gtk_widget_hide_all
(
vbox2
);
if
((
value
=
purple_proxy_info_get_host
(
proxy_info
))
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
proxy_host_entry
),
value
);
if
((
int_val
=
purple_proxy_info_get_port
(
proxy_info
))
!=
0
)
{
char
buf
[
11
];
g_snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
int_val
);
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
proxy_port_entry
),
buf
);
}
if
((
value
=
purple_proxy_info_get_username
(
proxy_info
))
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
proxy_user_entry
),
value
);
if
((
value
=
purple_proxy_info_get_password
(
proxy_info
))
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
proxy_pass_entry
),
value
);
}
else
{
dialog
->
new_proxy_type
=
PURPLE_PROXY_USE_GLOBAL
;
gtk_combo_box_set_active
(
GTK_COMBO_BOX
(
dialog
->
proxy_dropdown
),
dialog
->
new_proxy_type
+
1
);
gtk_widget_hide_all
(
vbox2
);
}
/* Connect signals. */
g_signal_connect
(
G_OBJECT
(
dialog
->
proxy_dropdown
),
"changed"
,
G_CALLBACK
(
proxy_type_changed_cb
),
dialog
);
}
static
void
account_win_destroy_cb
(
GtkWidget
*
w
,
GdkEvent
*
event
,
AccountPrefsDialog
*
dialog
)
{
g_hash_table_remove
(
account_pref_wins
,
dialog
->
account
);
gtk_widget_destroy
(
dialog
->
window
);
g_list_free
(
dialog
->
user_split_entries
);
g_list_free
(
dialog
->
protocol_opt_entries
);
g_free
(
dialog
->
protocol_id
);
purple_imgstore_unref
(
dialog
->
icon_img
);
if
(
dialog
->
icon_filesel
)
gtk_widget_destroy
(
dialog
->
icon_filesel
);
purple_signals_disconnect_by_handle
(
dialog
);
g_free
(
dialog
);
}
static
void
cancel_account_prefs_cb
(
GtkWidget
*
w
,
AccountPrefsDialog
*
dialog
)
{
account_win_destroy_cb
(
NULL
,
NULL
,
dialog
);
}
static
void
ok_account_prefs_cb
(
GtkWidget
*
w
,
AccountPrefsDialog
*
dialog
)
{
PurpleProxyInfo
*
proxy_info
=
NULL
;
GList
*
l
,
*
l2
;
const
char
*
value
;
char
*
username
;
char
*
tmp
;
gboolean
new_acct
=
FALSE
,
icon_change
=
FALSE
;
PurpleAccount
*
account
;
PurplePluginProtocolInfo
*
prpl_info
;
/* Build the username string. */
username
=
g_strdup
(
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
screenname_entry
)));
if
(
dialog
->
prpl_info
!=
NULL
)
{
for
(
l
=
dialog
->
prpl_info
->
user_splits
,
l2
=
dialog
->
user_split_entries
;
l
!=
NULL
&&
l2
!=
NULL
;
l
=
l
->
next
,
l2
=
l2
->
next
)
{
PurpleAccountUserSplit
*
split
=
l
->
data
;
GtkEntry
*
entry
=
l2
->
data
;
char
sep
[
2
]
=
" "
;
value
=
gtk_entry_get_text
(
entry
);
*
sep
=
purple_account_user_split_get_separator
(
split
);
tmp
=
g_strconcat
(
username
,
sep
,
(
*
value
?
value
:
purple_account_user_split_get_default_value
(
split
)),
NULL
);
g_free
(
username
);
username
=
tmp
;
}
}
if
(
dialog
->
account
==
NULL
)
{
if
(
purple_accounts_find
(
username
,
dialog
->
protocol_id
)
!=
NULL
)
{
purple_debug_warning
(
"gtkaccount"
,
"Trying to add a duplicate %s account (%s).
\n
"
,
dialog
->
protocol_id
,
username
);
purple_notify_error
(
NULL
,
NULL
,
_
(
"Unable to save new account"
),
_
(
"An account already exists with the specified criteria."
));
g_free
(
username
);
return
;
}
if
(
purple_accounts_get_all
()
==
NULL
)
{
/* We're adding our first account. Be polite and show the buddy list */
purple_blist_set_visible
(
TRUE
);
}
account
=
purple_account_new
(
username
,
dialog
->
protocol_id
);
new_acct
=
TRUE
;
}
else
{
account
=
dialog
->
account
;
/* Protocol */
purple_account_set_protocol_id
(
account
,
dialog
->
protocol_id
);
}
/* Alias */
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
alias_entry
));
if
(
*
value
!=
'\0'
)
purple_account_set_alias
(
account
,
value
);
else
purple_account_set_alias
(
account
,
NULL
);
/* Buddy Icon */
prpl_info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
dialog
->
plugin
);
if
(
prpl_info
!=
NULL
&&
prpl_info
->
icon_spec
.
format
!=
NULL
)
{
const
char
*
filename
;
if
(
new_acct
||
purple_account_get_bool
(
account
,
"use-global-buddyicon"
,
TRUE
)
==
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
icon_check
)))
{
icon_change
=
TRUE
;
}
purple_account_set_bool
(
account
,
"use-global-buddyicon"
,
!
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
icon_check
)));
if
(
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
icon_check
)))
{
if
(
dialog
->
icon_img
)
{
size_t
len
=
purple_imgstore_get_size
(
dialog
->
icon_img
);
purple_buddy_icons_set_account_icon
(
account
,
g_memdup
(
purple_imgstore_get_data
(
dialog
->
icon_img
),
len
),
len
);
purple_account_set_buddy_icon_path
(
account
,
purple_imgstore_get_filename
(
dialog
->
icon_img
));
}
else
{
purple_buddy_icons_set_account_icon
(
account
,
NULL
,
0
);
purple_account_set_buddy_icon_path
(
account
,
NULL
);
}
}
else
if
((
filename
=
purple_prefs_get_path
(
PIDGIN_PREFS_ROOT
"/accounts/buddyicon"
))
&&
icon_change
)
{
size_t
len
;
gpointer
data
=
pidgin_convert_buddy_icon
(
dialog
->
plugin
,
filename
,
&
len
);
purple_account_set_buddy_icon_path
(
account
,
filename
);
purple_buddy_icons_set_account_icon
(
account
,
data
,
len
);
}
}
/* Remember Password */
purple_account_set_remember_password
(
account
,
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
remember_pass_check
)));
/* Check Mail */
if
(
dialog
->
prpl_info
&&
dialog
->
prpl_info
->
options
&
OPT_PROTO_MAIL_CHECK
)
purple_account_set_check_mail
(
account
,
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
new_mail_check
)));
/* Password */
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
password_entry
));
/*
* We set the password if this is a new account because new accounts
* will be set to online, and if the user has entered a password into
* the account editor (but has not checked the 'save' box), then we
* don't want to prompt them.
*/
if
((
purple_account_get_remember_password
(
account
)
||
new_acct
)
&&
(
*
value
!=
'\0'
))
purple_account_set_password
(
account
,
value
);
else
purple_account_set_password
(
account
,
NULL
);
purple_account_set_username
(
account
,
username
);
g_free
(
username
);
/* Add the protocol settings */
if
(
dialog
->
prpl_info
)
{
for
(
l
=
dialog
->
prpl_info
->
protocol_options
,
l2
=
dialog
->
protocol_opt_entries
;
l
!=
NULL
&&
l2
!=
NULL
;
l
=
l
->
next
,
l2
=
l2
->
next
)
{
PurplePrefType
type
;
PurpleAccountOption
*
option
=
l
->
data
;
GtkWidget
*
widget
=
l2
->
data
;
GtkTreeIter
iter
;
const
char
*
setting
;
char
*
value2
;
int
int_value
;
gboolean
bool_value
;
type
=
purple_account_option_get_type
(
option
);
setting
=
purple_account_option_get_setting
(
option
);
switch
(
type
)
{
case
PURPLE_PREF_STRING
:
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
widget
));
purple_account_set_string
(
account
,
setting
,
value
);
break
;
case
PURPLE_PREF_INT
:
int_value
=
atoi
(
gtk_entry_get_text
(
GTK_ENTRY
(
widget
)));
purple_account_set_int
(
account
,
setting
,
int_value
);
break
;
case
PURPLE_PREF_BOOLEAN
:
bool_value
=
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
widget
));
purple_account_set_bool
(
account
,
setting
,
bool_value
);
break
;
case
PURPLE_PREF_STRING_LIST
:
gtk_combo_box_get_active_iter
(
GTK_COMBO_BOX
(
widget
),
&
iter
);
gtk_tree_model_get
(
gtk_combo_box_get_model
(
GTK_COMBO_BOX
(
widget
)),
&
iter
,
1
,
&
value2
,
-1
);
purple_account_set_string
(
account
,
setting
,
value2
);
break
;
default
:
break
;
}
}
}
/* Set the proxy stuff. */
proxy_info
=
purple_account_get_proxy_info
(
account
);
/* Create the proxy info if it doesn't exist. */
if
(
proxy_info
==
NULL
)
{
proxy_info
=
purple_proxy_info_new
();
purple_account_set_proxy_info
(
account
,
proxy_info
);
}
/* Set the proxy info type. */
purple_proxy_info_set_type
(
proxy_info
,
dialog
->
new_proxy_type
);
/* Host */
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
proxy_host_entry
));
if
(
*
value
!=
'\0'
)
purple_proxy_info_set_host
(
proxy_info
,
value
);
else
purple_proxy_info_set_host
(
proxy_info
,
NULL
);
/* Port */
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
proxy_port_entry
));
if
(
*
value
!=
'\0'
)
purple_proxy_info_set_port
(
proxy_info
,
atoi
(
value
));
else
purple_proxy_info_set_port
(
proxy_info
,
0
);
/* Username */
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
proxy_user_entry
));
if
(
*
value
!=
'\0'
)
purple_proxy_info_set_username
(
proxy_info
,
value
);
else
purple_proxy_info_set_username
(
proxy_info
,
NULL
);
/* Password */
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
proxy_pass_entry
));
if
(
*
value
!=
'\0'
)
purple_proxy_info_set_password
(
proxy_info
,
value
);
else
purple_proxy_info_set_password
(
proxy_info
,
NULL
);
/* If there are no values set then proxy_info NULL */
if
((
purple_proxy_info_get_type
(
proxy_info
)
==
PURPLE_PROXY_USE_GLOBAL
)
&&
(
purple_proxy_info_get_host
(
proxy_info
)
==
NULL
)
&&
(
purple_proxy_info_get_port
(
proxy_info
)
==
0
)
&&
(
purple_proxy_info_get_username
(
proxy_info
)
==
NULL
)
&&
(
purple_proxy_info_get_password
(
proxy_info
)
==
NULL
))
{
purple_account_set_proxy_info
(
account
,
NULL
);
proxy_info
=
NULL
;
}
/* If this is a new account, add it to our list */
if
(
new_acct
)
purple_accounts_add
(
account
);
else
purple_signal_emit
(
pidgin_account_get_handle
(),
"account-modified"
,
account
);
/* If this is a new account, then sign on! */
if
(
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
register_button
)))
{
purple_account_register
(
account
);
}
else
if
(
new_acct
)
{
const
PurpleSavedStatus
*
saved_status
;
saved_status
=
purple_savedstatus_get_current
();
if
(
saved_status
!=
NULL
)
{
purple_savedstatus_activate_for_account
(
saved_status
,
account
);
purple_account_set_enabled
(
account
,
PIDGIN_UI
,
TRUE
);
}
}
/* We no longer need the data from the dialog window */
account_win_destroy_cb
(
NULL
,
NULL
,
dialog
);
}
static
const
GtkTargetEntry
dnd_targets
[]
=
{
{
"text/plain"
,
0
,
0
},
{
"text/uri-list"
,
0
,
1
},
{
"STRING"
,
0
,
2
}
};
void
pidgin_account_dialog_show
(
PidginAccountDialogType
type
,
PurpleAccount
*
account
)
{
AccountPrefsDialog
*
dialog
;
GtkWidget
*
win
;
GtkWidget
*
main_vbox
;
GtkWidget
*
vbox
;
GtkWidget
*
bbox
;
GtkWidget
*
dbox
;
GtkWidget
*
notebook
;
GtkWidget
*
button
;
if
(
accounts_window
!=
NULL
&&
account
!=
NULL
&&
(
dialog
=
g_hash_table_lookup
(
account_pref_wins
,
account
))
!=
NULL
)
{
gtk_window_present
(
GTK_WINDOW
(
dialog
->
window
));
return
;
}
dialog
=
g_new0
(
AccountPrefsDialog
,
1
);
if
(
accounts_window
!=
NULL
&&
account
!=
NULL
)
{
g_hash_table_insert
(
account_pref_wins
,
account
,
dialog
);
}
dialog
->
account
=
account
;
dialog
->
type
=
type
;
dialog
->
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
if
(
dialog
->
account
==
NULL
)
{
/* Select the first prpl in the list*/
GList
*
prpl_list
=
purple_plugins_get_protocols
();
if
(
prpl_list
!=
NULL
)
dialog
->
protocol_id
=
g_strdup
(((
PurplePlugin
*
)
prpl_list
->
data
)
->
info
->
id
);
}
else
{
dialog
->
protocol_id
=
g_strdup
(
purple_account_get_protocol_id
(
dialog
->
account
));
}
if
((
dialog
->
plugin
=
purple_find_prpl
(
dialog
->
protocol_id
))
!=
NULL
)
dialog
->
prpl_info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
dialog
->
plugin
);
dialog
->
window
=
win
=
pidgin_create_window
((
type
==
PIDGIN_ADD_ACCOUNT_DIALOG
)
?
_
(
"Add Account"
)
:
_
(
"Modify Account"
),
PIDGIN_HIG_BORDER
,
"account"
,
FALSE
);
g_signal_connect
(
G_OBJECT
(
win
),
"delete_event"
,
G_CALLBACK
(
account_win_destroy_cb
),
dialog
);
/* Setup the vbox */
main_vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BORDER
);
gtk_container_add
(
GTK_CONTAINER
(
win
),
main_vbox
);
gtk_widget_show
(
main_vbox
);
notebook
=
gtk_notebook_new
();
gtk_box_pack_start
(
GTK_BOX
(
main_vbox
),
notebook
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
GTK_WIDGET
(
notebook
));
/* Setup the inner vbox */
dialog
->
top_vbox
=
vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BORDER
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
vbox
),
PIDGIN_HIG_BORDER
);
gtk_notebook_append_page
(
GTK_NOTEBOOK
(
notebook
),
vbox
,
gtk_label_new_with_mnemonic
(
_
(
"_Basic"
)));
gtk_widget_show
(
vbox
);
/* Setup the top frames. */
add_login_options
(
dialog
,
vbox
);
add_user_options
(
dialog
,
vbox
);
button
=
gtk_check_button_new_with_label
(
_
(
"Create this new account on the server"
));
gtk_box_pack_start
(
GTK_BOX
(
main_vbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
button
);
dialog
->
register_button
=
button
;
if
(
dialog
->
account
==
NULL
)
gtk_widget_set_sensitive
(
button
,
FALSE
);
if
(
!
dialog
->
prpl_info
||
!
dialog
->
prpl_info
->
register_user
)
gtk_widget_hide
(
button
);
/* Setup the page with 'Advanced'. */
dialog
->
bottom_vbox
=
dbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BORDER
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
dbox
),
PIDGIN_HIG_BORDER
);
gtk_notebook_append_page
(
GTK_NOTEBOOK
(
notebook
),
dbox
,
gtk_label_new_with_mnemonic
(
_
(
"_Advanced"
)));
gtk_widget_show
(
dbox
);
/** Setup the bottom frames. */
add_protocol_options
(
dialog
,
dbox
);
add_proxy_options
(
dialog
,
dbox
);
/* Setup the button box */
bbox
=
gtk_hbutton_box_new
();
gtk_box_set_spacing
(
GTK_BOX
(
bbox
),
PIDGIN_HIG_BOX_SPACE
);
gtk_button_box_set_layout
(
GTK_BUTTON_BOX
(
bbox
),
GTK_BUTTONBOX_END
);
gtk_box_pack_end
(
GTK_BOX
(
main_vbox
),
bbox
,
FALSE
,
TRUE
,
0
);
gtk_widget_show
(
bbox
);
/* Cancel button */
button
=
gtk_button_new_from_stock
(
GTK_STOCK_CANCEL
);
gtk_box_pack_start
(
GTK_BOX
(
bbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
button
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
cancel_account_prefs_cb
),
dialog
);
/* Save button */
button
=
gtk_button_new_from_stock
(
GTK_STOCK_SAVE
);
gtk_box_pack_start
(
GTK_BOX
(
bbox
),
button
,
FALSE
,
FALSE
,
0
);
if
(
dialog
->
account
==
NULL
)
gtk_widget_set_sensitive
(
button
,
FALSE
);
gtk_widget_show
(
button
);
dialog
->
ok_button
=
button
;
/* Set up DND */
gtk_drag_dest_set
(
dialog
->
window
,
GTK_DEST_DEFAULT_MOTION
|
GTK_DEST_DEFAULT_DROP
,
dnd_targets
,
sizeof
(
dnd_targets
)
/
sizeof
(
GtkTargetEntry
),
GDK_ACTION_COPY
);
g_signal_connect
(
G_OBJECT
(
dialog
->
window
),
"drag_data_received"
,
G_CALLBACK
(
account_dnd_recv
),
dialog
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
ok_account_prefs_cb
),
dialog
);
/* Show the window. */
gtk_widget_show
(
win
);
}
/**************************************************************************
* Accounts Dialog
**************************************************************************/
static
void
signed_on_off_cb
(
PurpleConnection
*
gc
,
gpointer
user_data
)
{
PurpleAccount
*
account
;
PidginPulseData
*
pulse_data
;
GtkTreeModel
*
model
;
GtkTreeIter
iter
;
GdkPixbuf
*
pixbuf
;
size_t
index
;
/* Don't need to do anything if the accounts window is not visible */
if
(
accounts_window
==
NULL
)
return
;
account
=
purple_connection_get_account
(
gc
);
model
=
GTK_TREE_MODEL
(
accounts_window
->
model
);
index
=
g_list_index
(
purple_accounts_get_all
(),
account
);
if
(
gtk_tree_model_iter_nth_child
(
model
,
&
iter
,
NULL
,
index
))
{
gtk_tree_model_get
(
GTK_TREE_MODEL
(
accounts_window
->
model
),
&
iter
,
COLUMN_PULSE_DATA
,
&
pulse_data
,
-1
);
if
(
pulse_data
!=
NULL
)
{
if
(
pulse_data
->
timeout
>
0
)
g_source_remove
(
pulse_data
->
timeout
);
g_object_unref
(
G_OBJECT
(
pulse_data
->
online_pixbuf
));
g_free
(
pulse_data
);
}
pixbuf
=
pidgin_create_prpl_icon
(
account
,
PIDGIN_PRPL_ICON_MEDIUM
);
if
((
pixbuf
!=
NULL
)
&&
purple_account_is_disconnected
(
account
))
gdk_pixbuf_saturate_and_pixelate
(
pixbuf
,
pixbuf
,
0.0
,
FALSE
);
gtk_list_store_set
(
accounts_window
->
model
,
&
iter
,
COLUMN_ICON
,
pixbuf
,
COLUMN_PULSE_DATA
,
NULL
,
-1
);
if
(
pixbuf
!=
NULL
)
g_object_unref
(
G_OBJECT
(
pixbuf
));
}
}
/*
* Get the GtkTreeIter of the specified account in the
* GtkListStore
*/
static
gboolean
accounts_window_find_account_in_treemodel
(
GtkTreeIter
*
iter
,
PurpleAccount
*
account
)
{
GtkTreeModel
*
model
;
PurpleAccount
*
cur
;
g_return_val_if_fail
(
account
!=
NULL
,
FALSE
);
g_return_val_if_fail
(
accounts_window
!=
NULL
,
FALSE
);
model
=
GTK_TREE_MODEL
(
accounts_window
->
model
);
if
(
!
gtk_tree_model_get_iter_first
(
model
,
iter
))
return
FALSE
;
gtk_tree_model_get
(
model
,
iter
,
COLUMN_DATA
,
&
cur
,
-1
);
if
(
cur
==
account
)
return
TRUE
;
while
(
gtk_tree_model_iter_next
(
model
,
iter
))
{
gtk_tree_model_get
(
model
,
iter
,
COLUMN_DATA
,
&
cur
,
-1
);
if
(
cur
==
account
)
return
TRUE
;
}
return
FALSE
;
}
static
void
account_removed_cb
(
PurpleAccount
*
account
,
gpointer
user_data
)
{
AccountPrefsDialog
*
dialog
;
GtkTreeIter
iter
;
/* If the account was being modified, close the edit window */
if
((
dialog
=
g_hash_table_lookup
(
account_pref_wins
,
account
))
!=
NULL
)
account_win_destroy_cb
(
NULL
,
NULL
,
dialog
);
if
(
accounts_window
==
NULL
)
return
;
/* Remove the account from the GtkListStore */
if
(
accounts_window_find_account_in_treemodel
(
&
iter
,
account
))
gtk_list_store_remove
(
accounts_window
->
model
,
&
iter
);
if
(
purple_accounts_get_all
()
==
NULL
)
gtk_notebook_set_current_page
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
0
);
}
static
void
account_abled_cb
(
PurpleAccount
*
account
,
gpointer
user_data
)
{
GtkTreeIter
iter
;
if
(
accounts_window
==
NULL
)
return
;
/* update the account in the GtkListStore */
if
(
accounts_window_find_account_in_treemodel
(
&
iter
,
account
))
gtk_list_store_set
(
accounts_window
->
model
,
&
iter
,
COLUMN_ENABLED
,
GPOINTER_TO_INT
(
user_data
),
-1
);
}
static
void
drag_data_get_cb
(
GtkWidget
*
widget
,
GdkDragContext
*
ctx
,
GtkSelectionData
*
data
,
guint
info
,
guint
time
,
AccountsWindow
*
dialog
)
{
if
(
data
->
target
==
gdk_atom_intern
(
"PURPLE_ACCOUNT"
,
FALSE
))
{
GtkTreeRowReference
*
ref
;
GtkTreePath
*
source_row
;
GtkTreeIter
iter
;
PurpleAccount
*
account
=
NULL
;
GValue
val
;
ref
=
g_object_get_data
(
G_OBJECT
(
ctx
),
"gtk-tree-view-source-row"
);
source_row
=
gtk_tree_row_reference_get_path
(
ref
);
if
(
source_row
==
NULL
)
return
;
gtk_tree_model_get_iter
(
GTK_TREE_MODEL
(
dialog
->
model
),
&
iter
,
source_row
);
val
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
dialog
->
model
),
&
iter
,
COLUMN_DATA
,
&
val
);
dialog
->
drag_iter
=
iter
;
account
=
g_value_get_pointer
(
&
val
);
gtk_selection_data_set
(
data
,
gdk_atom_intern
(
"PURPLE_ACCOUNT"
,
FALSE
),
8
,
(
void
*
)
&
account
,
sizeof
(
account
));
gtk_tree_path_free
(
source_row
);
}
}
static
void
move_account_after
(
GtkListStore
*
store
,
GtkTreeIter
*
iter
,
GtkTreeIter
*
position
)
{
GtkTreeIter
new_iter
;
PurpleAccount
*
account
;
gtk_tree_model_get
(
GTK_TREE_MODEL
(
store
),
iter
,
COLUMN_DATA
,
&
account
,
-1
);
gtk_list_store_insert_after
(
store
,
&
new_iter
,
position
);
set_account
(
store
,
&
new_iter
,
account
,
NULL
);
gtk_list_store_remove
(
store
,
iter
);
}
static
void
move_account_before
(
GtkListStore
*
store
,
GtkTreeIter
*
iter
,
GtkTreeIter
*
position
)
{
GtkTreeIter
new_iter
;
PurpleAccount
*
account
;
gtk_tree_model_get
(
GTK_TREE_MODEL
(
store
),
iter
,
COLUMN_DATA
,
&
account
,
-1
);
gtk_list_store_insert_before
(
store
,
&
new_iter
,
position
);
set_account
(
store
,
&
new_iter
,
account
,
NULL
);
gtk_list_store_remove
(
store
,
iter
);
}
static
void
drag_data_received_cb
(
GtkWidget
*
widget
,
GdkDragContext
*
ctx
,
guint
x
,
guint
y
,
GtkSelectionData
*
sd
,
guint
info
,
guint
t
,
AccountsWindow
*
dialog
)
{
if
(
sd
->
target
==
gdk_atom_intern
(
"PURPLE_ACCOUNT"
,
FALSE
)
&&
sd
->
data
)
{
gint
dest_index
;
PurpleAccount
*
a
=
NULL
;
GtkTreePath
*
path
=
NULL
;
GtkTreeViewDropPosition
position
;
memcpy
(
&
a
,
sd
->
data
,
sizeof
(
a
));
if
(
gtk_tree_view_get_dest_row_at_pos
(
GTK_TREE_VIEW
(
widget
),
x
,
y
,
&
path
,
&
position
))
{
GtkTreeIter
iter
;
PurpleAccount
*
account
;
GValue
val
;
gtk_tree_model_get_iter
(
GTK_TREE_MODEL
(
dialog
->
model
),
&
iter
,
path
);
val
.
g_type
=
0
;
gtk_tree_model_get_value
(
GTK_TREE_MODEL
(
dialog
->
model
),
&
iter
,
COLUMN_DATA
,
&
val
);
account
=
g_value_get_pointer
(
&
val
);
switch
(
position
)
{
case
GTK_TREE_VIEW_DROP_AFTER
:
case
GTK_TREE_VIEW_DROP_INTO_OR_AFTER
:
move_account_after
(
dialog
->
model
,
&
dialog
->
drag_iter
,
&
iter
);
dest_index
=
g_list_index
(
purple_accounts_get_all
(),
account
)
+
1
;
break
;
case
GTK_TREE_VIEW_DROP_BEFORE
:
case
GTK_TREE_VIEW_DROP_INTO_OR_BEFORE
:
dest_index
=
g_list_index
(
purple_accounts_get_all
(),
account
);
move_account_before
(
dialog
->
model
,
&
dialog
->
drag_iter
,
&
iter
);
break
;
default
:
return
;
}
purple_accounts_reorder
(
a
,
dest_index
);
}
}
}
static
gint
accedit_win_destroy_cb
(
GtkWidget
*
w
,
GdkEvent
*
event
,
AccountsWindow
*
dialog
)
{
/* Since this is called as the window is closing, we don't need
* pidgin_accounts_window_hide() to also dispose of the window */
dialog
->
window
=
NULL
;
pidgin_accounts_window_hide
();
return
0
;
}
static
gboolean
configure_cb
(
GtkWidget
*
w
,
GdkEventConfigure
*
event
,
AccountsWindow
*
dialog
)
{
if
(
GTK_WIDGET_VISIBLE
(
w
))
{
int
old_width
=
purple_prefs_get_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/width"
);
int
col_width
;
int
difference
;
purple_prefs_set_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/width"
,
event
->
width
);
purple_prefs_set_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/height"
,
event
->
height
);
col_width
=
gtk_tree_view_column_get_width
(
dialog
->
screenname_col
);
if
(
col_width
==
0
)
return
FALSE
;
difference
=
(
MAX
(
old_width
,
event
->
width
)
-
MIN
(
old_width
,
event
->
width
));
if
(
difference
==
0
)
return
FALSE
;
if
(
old_width
<
event
->
width
)
gtk_tree_view_column_set_min_width
(
dialog
->
screenname_col
,
col_width
+
difference
);
else
gtk_tree_view_column_set_max_width
(
dialog
->
screenname_col
,
col_width
-
difference
);
}
return
FALSE
;
}
static
void
add_account_cb
(
GtkWidget
*
w
,
AccountsWindow
*
dialog
)
{
pidgin_account_dialog_show
(
PIDGIN_ADD_ACCOUNT_DIALOG
,
NULL
);
}
static
void
modify_account_sel
(
GtkTreeModel
*
model
,
GtkTreePath
*
path
,
GtkTreeIter
*
iter
,
gpointer
data
)
{
PurpleAccount
*
account
;
gtk_tree_model_get
(
model
,
iter
,
COLUMN_DATA
,
&
account
,
-1
);
if
(
account
!=
NULL
)
pidgin_account_dialog_show
(
PIDGIN_MODIFY_ACCOUNT_DIALOG
,
account
);
}
static
void
modify_account_cb
(
GtkWidget
*
w
,
AccountsWindow
*
dialog
)
{
GtkTreeSelection
*
selection
;
selection
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
dialog
->
treeview
));
gtk_tree_selection_selected_foreach
(
selection
,
modify_account_sel
,
dialog
);
}
static
void
delete_account_cb
(
PurpleAccount
*
account
)
{
purple_accounts_delete
(
account
);
}
static
void
ask_delete_account_sel
(
GtkTreeModel
*
model
,
GtkTreePath
*
path
,
GtkTreeIter
*
iter
,
gpointer
data
)
{
PurpleAccount
*
account
;
gtk_tree_model_get
(
model
,
iter
,
COLUMN_DATA
,
&
account
,
-1
);
if
(
account
!=
NULL
)
{
char
*
buf
;
buf
=
g_strdup_printf
(
_
(
"Are you sure you want to delete %s?"
),
purple_account_get_username
(
account
));
purple_request_close_with_handle
(
account
);
purple_request_action
(
account
,
NULL
,
buf
,
NULL
,
0
,
account
,
NULL
,
NULL
,
account
,
2
,
_
(
"Delete"
),
delete_account_cb
,
_
(
"Cancel"
),
NULL
);
g_free
(
buf
);
}
}
static
void
ask_delete_account_cb
(
GtkWidget
*
w
,
AccountsWindow
*
dialog
)
{
GtkTreeSelection
*
selection
;
selection
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
dialog
->
treeview
));
gtk_tree_selection_selected_foreach
(
selection
,
ask_delete_account_sel
,
dialog
);
}
static
void
close_accounts_cb
(
GtkWidget
*
w
,
AccountsWindow
*
dialog
)
{
pidgin_accounts_window_hide
();
}
static
void
enabled_cb
(
GtkCellRendererToggle
*
renderer
,
gchar
*
path_str
,
gpointer
data
)
{
AccountsWindow
*
dialog
=
(
AccountsWindow
*
)
data
;
PurpleAccount
*
account
;
GtkTreeModel
*
model
=
GTK_TREE_MODEL
(
dialog
->
model
);
GtkTreeIter
iter
;
gboolean
enabled
;
const
PurpleSavedStatus
*
saved_status
;
gtk_tree_model_get_iter_from_string
(
model
,
&
iter
,
path_str
);
gtk_tree_model_get
(
model
,
&
iter
,
COLUMN_DATA
,
&
account
,
COLUMN_ENABLED
,
&
enabled
,
-1
);
/*
* If we just enabled the account, then set the statuses
* to the current status.
*/
if
(
!
enabled
)
{
saved_status
=
purple_savedstatus_get_current
();
purple_savedstatus_activate_for_account
(
saved_status
,
account
);
}
purple_account_set_enabled
(
account
,
PIDGIN_UI
,
!
enabled
);
}
static
void
add_columns
(
GtkWidget
*
treeview
,
AccountsWindow
*
dialog
)
{
GtkCellRenderer
*
renderer
;
GtkTreeViewColumn
*
column
;
/* Enabled */
renderer
=
gtk_cell_renderer_toggle_new
();
g_signal_connect
(
G_OBJECT
(
renderer
),
"toggled"
,
G_CALLBACK
(
enabled_cb
),
dialog
);
column
=
gtk_tree_view_column_new_with_attributes
(
_
(
"Enabled"
),
renderer
,
"active"
,
COLUMN_ENABLED
,
NULL
);
gtk_tree_view_insert_column
(
GTK_TREE_VIEW
(
treeview
),
column
,
-1
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
/* Screen Name column */
column
=
gtk_tree_view_column_new
();
gtk_tree_view_column_set_title
(
column
,
_
(
"Screen Name"
));
gtk_tree_view_insert_column
(
GTK_TREE_VIEW
(
treeview
),
column
,
-1
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
/* Buddy Icon */
renderer
=
gtk_cell_renderer_pixbuf_new
();
gtk_tree_view_column_pack_start
(
column
,
renderer
,
FALSE
);
gtk_tree_view_column_add_attribute
(
column
,
renderer
,
"pixbuf"
,
COLUMN_BUDDYICON
);
/* Screen Name */
renderer
=
gtk_cell_renderer_text_new
();
gtk_tree_view_column_pack_start
(
column
,
renderer
,
TRUE
);
gtk_tree_view_column_add_attribute
(
column
,
renderer
,
"text"
,
COLUMN_SCREENNAME
);
dialog
->
screenname_col
=
column
;
/* Protocol name */
column
=
gtk_tree_view_column_new
();
gtk_tree_view_column_set_title
(
column
,
_
(
"Protocol"
));
gtk_tree_view_insert_column
(
GTK_TREE_VIEW
(
treeview
),
column
,
-1
);
gtk_tree_view_column_set_resizable
(
column
,
TRUE
);
/* Icon */
renderer
=
gtk_cell_renderer_pixbuf_new
();
gtk_tree_view_column_pack_start
(
column
,
renderer
,
FALSE
);
gtk_tree_view_column_add_attribute
(
column
,
renderer
,
"pixbuf"
,
COLUMN_ICON
);
renderer
=
gtk_cell_renderer_text_new
();
gtk_tree_view_column_pack_start
(
column
,
renderer
,
TRUE
);
gtk_tree_view_column_add_attribute
(
column
,
renderer
,
"text"
,
COLUMN_PROTOCOL
);
}
static
void
set_account
(
GtkListStore
*
store
,
GtkTreeIter
*
iter
,
PurpleAccount
*
account
,
GdkPixbuf
*
global_buddyicon
)
{
GdkPixbuf
*
pixbuf
,
*
buddyicon
=
NULL
;
PurpleStoredImage
*
img
=
NULL
;
PurplePlugin
*
prpl
;
PurplePluginProtocolInfo
*
prpl_info
=
NULL
;
pixbuf
=
pidgin_create_prpl_icon
(
account
,
PIDGIN_PRPL_ICON_MEDIUM
);
if
((
pixbuf
!=
NULL
)
&&
purple_account_is_disconnected
(
account
))
gdk_pixbuf_saturate_and_pixelate
(
pixbuf
,
pixbuf
,
0.0
,
FALSE
);
prpl
=
purple_find_prpl
(
purple_account_get_protocol_id
(
account
));
if
(
prpl
!=
NULL
)
prpl_info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
prpl
);
if
(
prpl_info
!=
NULL
&&
prpl_info
->
icon_spec
.
format
!=
NULL
)
{
if
(
purple_account_get_bool
(
account
,
"use-global-buddyicon"
,
TRUE
))
{
if
(
global_buddyicon
!=
NULL
)
buddyicon
=
g_object_ref
(
G_OBJECT
(
global_buddyicon
));
/* This is for when set_account() is called for a single account */
else
img
=
purple_buddy_icons_find_account_icon
(
account
);
}
else
{
img
=
purple_buddy_icons_find_account_icon
(
account
);
}
}
if
(
img
!=
NULL
)
{
GdkPixbufLoader
*
loader
=
gdk_pixbuf_loader_new
();
GdkPixbuf
*
buddyicon_pixbuf
;
gdk_pixbuf_loader_write
(
loader
,
purple_imgstore_get_data
(
img
),
purple_imgstore_get_size
(
img
),
NULL
);
gdk_pixbuf_loader_close
(
loader
,
NULL
);
buddyicon_pixbuf
=
gdk_pixbuf_loader_get_pixbuf
(
loader
);
purple_imgstore_unref
(
img
);
if
(
buddyicon_pixbuf
!=
NULL
)
{
buddyicon
=
gdk_pixbuf_scale_simple
(
buddyicon_pixbuf
,
22
,
22
,
GDK_INTERP_HYPER
);
g_object_unref
(
G_OBJECT
(
buddyicon_pixbuf
));
}
}
gtk_list_store_set
(
store
,
iter
,
COLUMN_ICON
,
pixbuf
,
COLUMN_BUDDYICON
,
buddyicon
,
COLUMN_SCREENNAME
,
purple_account_get_username
(
account
),
COLUMN_ENABLED
,
purple_account_get_enabled
(
account
,
PIDGIN_UI
),
COLUMN_PROTOCOL
,
purple_account_get_protocol_name
(
account
),
COLUMN_DATA
,
account
,
-1
);
if
(
pixbuf
!=
NULL
)
g_object_unref
(
G_OBJECT
(
pixbuf
));
if
(
buddyicon
!=
NULL
)
g_object_unref
(
G_OBJECT
(
buddyicon
));
}
static
void
add_account_to_liststore
(
PurpleAccount
*
account
,
gpointer
user_data
)
{
GtkTreeIter
iter
;
GdkPixbuf
*
global_buddyicon
=
user_data
;
if
(
accounts_window
==
NULL
)
return
;
gtk_list_store_append
(
accounts_window
->
model
,
&
iter
);
gtk_notebook_set_current_page
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
1
);
set_account
(
accounts_window
->
model
,
&
iter
,
account
,
global_buddyicon
);
}
static
gboolean
populate_accounts_list
(
AccountsWindow
*
dialog
)
{
GList
*
l
;
gboolean
ret
=
FALSE
;
GdkPixbuf
*
global_buddyicon
=
NULL
;
const
char
*
path
;
gtk_list_store_clear
(
dialog
->
model
);
if
((
path
=
purple_prefs_get_path
(
PIDGIN_PREFS_ROOT
"/accounts/buddyicon"
))
!=
NULL
)
{
GdkPixbuf
*
pixbuf
=
gdk_pixbuf_new_from_file
(
path
,
NULL
);
if
(
pixbuf
!=
NULL
)
{
global_buddyicon
=
gdk_pixbuf_scale_simple
(
pixbuf
,
22
,
22
,
GDK_INTERP_HYPER
);
g_object_unref
(
G_OBJECT
(
pixbuf
));
}
}
for
(
l
=
purple_accounts_get_all
();
l
!=
NULL
;
l
=
l
->
next
)
{
ret
=
TRUE
;
add_account_to_liststore
((
PurpleAccount
*
)
l
->
data
,
global_buddyicon
);
}
if
(
global_buddyicon
!=
NULL
)
g_object_unref
(
G_OBJECT
(
global_buddyicon
));
return
ret
;
}
#if !GTK_CHECK_VERSION(2,2,0)
static
void
get_selected_helper
(
GtkTreeModel
*
model
,
GtkTreePath
*
path
,
GtkTreeIter
*
iter
,
gpointer
user_data
)
{
*
((
gboolean
*
)
user_data
)
=
TRUE
;
}
#endif
static
void
account_selected_cb
(
GtkTreeSelection
*
sel
,
AccountsWindow
*
dialog
)
{
gboolean
selected
=
FALSE
;
#if GTK_CHECK_VERSION(2,2,0)
selected
=
(
gtk_tree_selection_count_selected_rows
(
sel
)
>
0
);
#else
gtk_tree_selection_selected_foreach
(
sel
,
get_selected_helper
,
&
selected
);
#endif
gtk_widget_set_sensitive
(
dialog
->
modify_button
,
selected
);
gtk_widget_set_sensitive
(
dialog
->
delete_button
,
selected
);
}
static
gboolean
account_treeview_double_click_cb
(
GtkTreeView
*
treeview
,
GdkEventButton
*
event
,
gpointer
user_data
)
{
AccountsWindow
*
dialog
;
GtkTreePath
*
path
;
GtkTreeViewColumn
*
column
;
GtkTreeIter
iter
;
PurpleAccount
*
account
;
const
gchar
*
title
;
dialog
=
(
AccountsWindow
*
)
user_data
;
/* Figure out which node was clicked */
if
(
!
gtk_tree_view_get_path_at_pos
(
GTK_TREE_VIEW
(
dialog
->
treeview
),
event
->
x
,
event
->
y
,
&
path
,
&
column
,
NULL
,
NULL
))
return
FALSE
;
title
=
gtk_tree_view_column_get_title
(
column
);
/* The -1 is required because the first two columns of the list
* store are displayed as only one column in the tree view. */
column
=
gtk_tree_view_get_column
(
treeview
,
COLUMN_ENABLED
-1
);
gtk_tree_model_get_iter
(
GTK_TREE_MODEL
(
dialog
->
model
),
&
iter
,
path
);
gtk_tree_path_free
(
path
);
gtk_tree_model_get
(
GTK_TREE_MODEL
(
dialog
->
model
),
&
iter
,
COLUMN_DATA
,
&
account
,
-1
);
if
((
account
!=
NULL
)
&&
(
event
->
button
==
1
)
&&
(
event
->
type
==
GDK_2BUTTON_PRESS
)
&&
(
strcmp
(
gtk_tree_view_column_get_title
(
column
),
title
)))
{
pidgin_account_dialog_show
(
PIDGIN_MODIFY_ACCOUNT_DIALOG
,
account
);
return
TRUE
;
}
return
FALSE
;
}
static
GtkWidget
*
create_accounts_list
(
AccountsWindow
*
dialog
)
{
GtkWidget
*
frame
;
GtkWidget
*
sw
;
GtkWidget
*
label
;
GtkWidget
*
treeview
;
GtkTreeSelection
*
sel
;
GtkTargetEntry
gte
[]
=
{{
"PURPLE_ACCOUNT"
,
GTK_TARGET_SAME_APP
,
0
}};
char
*
pretty
,
*
tmp
;
frame
=
gtk_frame_new
(
NULL
);
gtk_frame_set_shadow_type
(
GTK_FRAME
(
frame
),
GTK_SHADOW_IN
);
accounts_window
->
notebook
=
gtk_notebook_new
();
gtk_notebook_set_show_tabs
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
FALSE
);
gtk_notebook_set_show_border
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
FALSE
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
accounts_window
->
notebook
);
/* Create a helpful first-time-use label */
label
=
gtk_label_new
(
NULL
);
/* Translators: Please maintain the use of -> or <- to represent the menu heirarchy */
tmp
=
g_strdup_printf
(
_
(
"<span size='larger' weight='bold'>Welcome to %s!</span>
\n\n
"
"You have no IM accounts configured. To start connecting with %s "
"press the <b>Add</b> button below and configure your first "
"account. If you want %s to connect to multiple IM accounts, "
"press <b>Add</b> again to configure them all.
\n\n
"
"You can come back to this window to add, edit, or remove "
"accounts from <b>Accounts->Add/Edit</b> in the Buddy "
"List window"
),
PIDGIN_NAME
,
PIDGIN_NAME
,
PIDGIN_NAME
);
pretty
=
pidgin_make_pretty_arrows
(
tmp
);
g_free
(
tmp
);
gtk_label_set_markup
(
GTK_LABEL
(
label
),
pretty
);
g_free
(
pretty
);
gtk_label_set_line_wrap
(
GTK_LABEL
(
label
),
TRUE
);
gtk_widget_show
(
label
);
gtk_misc_set_alignment
(
GTK_MISC
(
label
),
0.5
,
0.5
);
gtk_notebook_append_page
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
label
,
NULL
);
/* Create the scrolled window. */
sw
=
gtk_scrolled_window_new
(
0
,
0
);
gtk_scrolled_window_set_policy
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_POLICY_AUTOMATIC
,
GTK_POLICY_AUTOMATIC
);
gtk_scrolled_window_set_shadow_type
(
GTK_SCROLLED_WINDOW
(
sw
),
GTK_SHADOW_NONE
);
gtk_notebook_append_page
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
sw
,
NULL
);
gtk_widget_show
(
sw
);
/* Create the list model. */
dialog
->
model
=
gtk_list_store_new
(
NUM_COLUMNS
,
GDK_TYPE_PIXBUF
,
/* COLUMN_ICON */
GDK_TYPE_PIXBUF
,
/* COLUMN_BUDDYICON */
G_TYPE_STRING
,
/* COLUMN_SCREENNAME */
G_TYPE_BOOLEAN
,
/* COLUMN_ENABLED */
G_TYPE_STRING
,
/* COLUMN_PROTOCOL */
G_TYPE_POINTER
,
/* COLUMN_DATA */
G_TYPE_POINTER
/* COLUMN_PULSE_DATA */
);
/* And now the actual treeview */
treeview
=
gtk_tree_view_new_with_model
(
GTK_TREE_MODEL
(
dialog
->
model
));
dialog
->
treeview
=
treeview
;
gtk_tree_view_set_rules_hint
(
GTK_TREE_VIEW
(
treeview
),
TRUE
);
sel
=
gtk_tree_view_get_selection
(
GTK_TREE_VIEW
(
treeview
));
gtk_tree_selection_set_mode
(
sel
,
GTK_SELECTION_MULTIPLE
);
g_signal_connect
(
G_OBJECT
(
sel
),
"changed"
,
G_CALLBACK
(
account_selected_cb
),
dialog
);
/* Handle double-clicking */
g_signal_connect
(
G_OBJECT
(
treeview
),
"button_press_event"
,
G_CALLBACK
(
account_treeview_double_click_cb
),
dialog
);
gtk_container_add
(
GTK_CONTAINER
(
sw
),
treeview
);
add_columns
(
treeview
,
dialog
);
if
(
populate_accounts_list
(
dialog
))
gtk_notebook_set_current_page
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
1
);
else
gtk_notebook_set_current_page
(
GTK_NOTEBOOK
(
accounts_window
->
notebook
),
0
);
/* Setup DND. I wanna be an orc! */
gtk_tree_view_enable_model_drag_source
(
GTK_TREE_VIEW
(
treeview
),
GDK_BUTTON1_MASK
,
gte
,
1
,
GDK_ACTION_COPY
);
gtk_tree_view_enable_model_drag_dest
(
GTK_TREE_VIEW
(
treeview
),
gte
,
1
,
GDK_ACTION_COPY
|
GDK_ACTION_MOVE
);
g_signal_connect
(
G_OBJECT
(
treeview
),
"drag-data-received"
,
G_CALLBACK
(
drag_data_received_cb
),
dialog
);
g_signal_connect
(
G_OBJECT
(
treeview
),
"drag-data-get"
,
G_CALLBACK
(
drag_data_get_cb
),
dialog
);
gtk_widget_show_all
(
frame
);
return
frame
;
}
static
void
account_modified_cb
(
PurpleAccount
*
account
,
AccountsWindow
*
window
)
{
GtkTreeIter
iter
;
if
(
!
accounts_window_find_account_in_treemodel
(
&
iter
,
account
))
return
;
set_account
(
window
->
model
,
&
iter
,
account
,
NULL
);
}
static
void
global_buddyicon_changed
(
const
char
*
name
,
PurplePrefType
type
,
gconstpointer
value
,
gpointer
window
)
{
GList
*
list
;
for
(
list
=
purple_accounts_get_all
();
list
;
list
=
list
->
next
)
{
account_modified_cb
(
list
->
data
,
window
);
}
}
void
pidgin_accounts_window_show
(
void
)
{
AccountsWindow
*
dialog
;
GtkWidget
*
win
;
GtkWidget
*
vbox
;
GtkWidget
*
bbox
;
GtkWidget
*
sw
;
GtkWidget
*
button
;
int
width
,
height
;
if
(
accounts_window
!=
NULL
)
{
gtk_window_present
(
GTK_WINDOW
(
accounts_window
->
window
));
return
;
}
accounts_window
=
dialog
=
g_new0
(
AccountsWindow
,
1
);
width
=
purple_prefs_get_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/width"
);
height
=
purple_prefs_get_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/height"
);
dialog
->
window
=
win
=
pidgin_create_window
(
_
(
"Accounts"
),
PIDGIN_HIG_BORDER
,
"accounts"
,
TRUE
);
gtk_window_set_default_size
(
GTK_WINDOW
(
win
),
width
,
height
);
g_signal_connect
(
G_OBJECT
(
win
),
"delete_event"
,
G_CALLBACK
(
accedit_win_destroy_cb
),
accounts_window
);
g_signal_connect
(
G_OBJECT
(
win
),
"configure_event"
,
G_CALLBACK
(
configure_cb
),
accounts_window
);
/* Setup the vbox */
vbox
=
gtk_vbox_new
(
FALSE
,
PIDGIN_HIG_BORDER
);
gtk_container_add
(
GTK_CONTAINER
(
win
),
vbox
);
gtk_widget_show
(
vbox
);
/* Setup the scrolled window that will contain the list of accounts. */
sw
=
create_accounts_list
(
dialog
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
sw
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
sw
);
/* Button box. */
bbox
=
gtk_hbutton_box_new
();
gtk_box_set_spacing
(
GTK_BOX
(
bbox
),
PIDGIN_HIG_BOX_SPACE
);
gtk_button_box_set_layout
(
GTK_BUTTON_BOX
(
bbox
),
GTK_BUTTONBOX_END
);
gtk_box_pack_end
(
GTK_BOX
(
vbox
),
bbox
,
FALSE
,
TRUE
,
0
);
gtk_widget_show
(
bbox
);
/* Add button */
button
=
gtk_button_new_from_stock
(
GTK_STOCK_ADD
);
gtk_box_pack_start
(
GTK_BOX
(
bbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
button
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
add_account_cb
),
dialog
);
/* Modify button */
button
=
gtk_button_new_from_stock
(
PIDGIN_STOCK_MODIFY
);
dialog
->
modify_button
=
button
;
gtk_box_pack_start
(
GTK_BOX
(
bbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_set_sensitive
(
button
,
FALSE
);
gtk_widget_show
(
button
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
modify_account_cb
),
dialog
);
/* Delete button */
button
=
gtk_button_new_from_stock
(
GTK_STOCK_DELETE
);
dialog
->
delete_button
=
button
;
gtk_box_pack_start
(
GTK_BOX
(
bbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_set_sensitive
(
button
,
FALSE
);
gtk_widget_show
(
button
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
ask_delete_account_cb
),
dialog
);
/* Close button */
button
=
gtk_button_new_from_stock
(
GTK_STOCK_CLOSE
);
gtk_box_pack_start
(
GTK_BOX
(
bbox
),
button
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
button
);
g_signal_connect
(
G_OBJECT
(
button
),
"clicked"
,
G_CALLBACK
(
close_accounts_cb
),
dialog
);
purple_signal_connect
(
pidgin_account_get_handle
(),
"account-modified"
,
accounts_window
,
PURPLE_CALLBACK
(
account_modified_cb
),
accounts_window
);
purple_prefs_connect_callback
(
accounts_window
,
PIDGIN_PREFS_ROOT
"/accounts/buddyicon"
,
global_buddyicon_changed
,
accounts_window
);
gtk_widget_show
(
win
);
}
void
pidgin_accounts_window_hide
(
void
)
{
if
(
accounts_window
==
NULL
)
return
;
if
(
accounts_window
->
window
!=
NULL
)
gtk_widget_destroy
(
accounts_window
->
window
);
purple_signals_disconnect_by_handle
(
accounts_window
);
purple_prefs_disconnect_by_handle
(
accounts_window
);
g_free
(
accounts_window
);
accounts_window
=
NULL
;
}
static
void
free_add_user_data
(
PidginAccountAddUserData
*
data
)
{
g_free
(
data
->
username
);
g_free
(
data
->
alias
);
g_free
(
data
);
}
static
void
add_user_cb
(
PidginAccountAddUserData
*
data
)
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
data
->
account
);
if
(
g_list_find
(
purple_connections_get_all
(),
gc
))
{
purple_blist_request_add_buddy
(
data
->
account
,
data
->
username
,
NULL
,
data
->
alias
);
}
free_add_user_data
(
data
);
}
static
char
*
make_info
(
PurpleAccount
*
account
,
PurpleConnection
*
gc
,
const
char
*
remote_user
,
const
char
*
id
,
const
char
*
alias
,
const
char
*
msg
)
{
if
(
msg
!=
NULL
&&
*
msg
==
'\0'
)
msg
=
NULL
;
return
g_strdup_printf
(
_
(
"%s%s%s%s has made %s his or her buddy%s%s"
),
remote_user
,
(
alias
!=
NULL
?
" ("
:
""
),
(
alias
!=
NULL
?
alias
:
""
),
(
alias
!=
NULL
?
")"
:
""
),
(
id
!=
NULL
?
id
:
(
purple_connection_get_display_name
(
gc
)
!=
NULL
?
purple_connection_get_display_name
(
gc
)
:
purple_account_get_username
(
account
))),
(
msg
!=
NULL
?
": "
:
"."
),
(
msg
!=
NULL
?
msg
:
""
));
}
static
void
pidgin_accounts_notify_added
(
PurpleAccount
*
account
,
const
char
*
remote_user
,
const
char
*
id
,
const
char
*
alias
,
const
char
*
msg
)
{
char
*
buffer
;
PurpleConnection
*
gc
;
GtkWidget
*
alert
;
gc
=
purple_account_get_connection
(
account
);
buffer
=
make_info
(
account
,
gc
,
remote_user
,
id
,
alias
,
msg
);
alert
=
pidgin_make_mini_dialog
(
gc
,
PIDGIN_STOCK_DIALOG_INFO
,
buffer
,
NULL
,
NULL
,
_
(
"Close"
),
NULL
,
NULL
);
pidgin_blist_add_alert
(
alert
);
g_free
(
buffer
);
}
static
void
pidgin_accounts_request_add
(
PurpleAccount
*
account
,
const
char
*
remote_user
,
const
char
*
id
,
const
char
*
alias
,
const
char
*
msg
)
{
char
*
buffer
;
PurpleConnection
*
gc
;
PidginAccountAddUserData
*
data
;
GtkWidget
*
alert
;
gc
=
purple_account_get_connection
(
account
);
data
=
g_new0
(
PidginAccountAddUserData
,
1
);
data
->
account
=
account
;
data
->
username
=
g_strdup
(
remote_user
);
data
->
alias
=
g_strdup
(
alias
);
buffer
=
make_info
(
account
,
gc
,
remote_user
,
id
,
alias
,
msg
);
alert
=
pidgin_make_mini_dialog
(
gc
,
PIDGIN_STOCK_DIALOG_QUESTION
,
_
(
"Add buddy to your list?"
),
buffer
,
data
,
_
(
"Add"
),
G_CALLBACK
(
add_user_cb
),
_
(
"Cancel"
),
G_CALLBACK
(
free_add_user_data
),
NULL
);
pidgin_blist_add_alert
(
alert
);
g_free
(
buffer
);
}
struct
auth_and_add
{
PurpleAccountRequestAuthorizationCb
auth_cb
;
PurpleAccountRequestAuthorizationCb
deny_cb
;
void
*
data
;
char
*
username
;
char
*
alias
;
PurpleAccount
*
account
;
};
static
void
authorize_and_add_cb
(
struct
auth_and_add
*
aa
)
{
aa
->
auth_cb
(
aa
->
data
);
purple_blist_request_add_buddy
(
aa
->
account
,
aa
->
username
,
NULL
,
aa
->
alias
);
g_free
(
aa
->
username
);
g_free
(
aa
->
alias
);
g_free
(
aa
);
}
static
void
deny_no_add_cb
(
struct
auth_and_add
*
aa
)
{
aa
->
deny_cb
(
aa
->
data
);
g_free
(
aa
->
username
);
g_free
(
aa
->
alias
);
g_free
(
aa
);
}
static
void
*
pidgin_accounts_request_authorization
(
PurpleAccount
*
account
,
const
char
*
remote_user
,
const
char
*
id
,
const
char
*
alias
,
const
char
*
message
,
gboolean
on_list
,
PurpleAccountRequestAuthorizationCb
auth_cb
,
PurpleAccountRequestAuthorizationCb
deny_cb
,
void
*
user_data
)
{
char
*
buffer
;
PurpleConnection
*
gc
;
GtkWidget
*
alert
;
gc
=
purple_account_get_connection
(
account
);
if
(
message
!=
NULL
&&
*
message
==
'\0'
)
message
=
NULL
;
buffer
=
g_strdup_printf
(
_
(
"%s%s%s%s wants to add %s to his or her buddy list%s%s"
),
remote_user
,
(
alias
!=
NULL
?
" ("
:
""
),
(
alias
!=
NULL
?
alias
:
""
),
(
alias
!=
NULL
?
")"
:
""
),
(
id
!=
NULL
?
id
:
(
purple_connection_get_display_name
(
gc
)
!=
NULL
?
purple_connection_get_display_name
(
gc
)
:
purple_account_get_username
(
account
))),
(
message
!=
NULL
?
": "
:
"."
),
(
message
!=
NULL
?
message
:
""
));
if
(
!
on_list
)
{
struct
auth_and_add
*
aa
=
g_new0
(
struct
auth_and_add
,
1
);
aa
->
auth_cb
=
auth_cb
;
aa
->
deny_cb
=
deny_cb
;
aa
->
data
=
user_data
;
aa
->
username
=
g_strdup
(
remote_user
);
aa
->
alias
=
g_strdup
(
alias
);
aa
->
account
=
account
;
alert
=
pidgin_make_mini_dialog
(
gc
,
PIDGIN_STOCK_DIALOG_QUESTION
,
_
(
"Authorize buddy?"
),
buffer
,
aa
,
_
(
"Authorize"
),
authorize_and_add_cb
,
_
(
"Deny"
),
deny_no_add_cb
,
NULL
);
}
else
{
alert
=
pidgin_make_mini_dialog
(
gc
,
PIDGIN_STOCK_DIALOG_QUESTION
,
_
(
"Authorize buddy?"
),
buffer
,
user_data
,
_
(
"Authorize"
),
auth_cb
,
_
(
"Deny"
),
deny_cb
,
NULL
);
}
pidgin_blist_add_alert
(
alert
);
g_free
(
buffer
);
return
NULL
;
}
static
void
pidgin_accounts_request_close
(
void
*
ui_handle
)
{
}
static
PurpleAccountUiOps
ui_ops
=
{
pidgin_accounts_notify_added
,
NULL
,
pidgin_accounts_request_add
,
pidgin_accounts_request_authorization
,
pidgin_accounts_request_close
,
NULL
,
NULL
,
NULL
,
NULL
};
PurpleAccountUiOps
*
pidgin_accounts_get_ui_ops
(
void
)
{
return
&
ui_ops
;
}
void
*
pidgin_account_get_handle
(
void
)
{
static
int
handle
;
return
&
handle
;
}
void
pidgin_account_init
(
void
)
{
char
*
default_avatar
=
NULL
;
purple_prefs_add_none
(
PIDGIN_PREFS_ROOT
"/accounts"
);
purple_prefs_add_none
(
PIDGIN_PREFS_ROOT
"/accounts/dialog"
);
purple_prefs_add_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/width"
,
520
);
purple_prefs_add_int
(
PIDGIN_PREFS_ROOT
"/accounts/dialog/height"
,
321
);
default_avatar
=
g_build_filename
(
g_get_home_dir
(),
".face.icon"
,
NULL
);
if
(
!
g_file_test
(
default_avatar
,
G_FILE_TEST_EXISTS
))
{
g_free
(
default_avatar
);
default_avatar
=
g_build_filename
(
g_get_home_dir
(),
".face"
,
NULL
);
if
(
!
g_file_test
(
default_avatar
,
G_FILE_TEST_EXISTS
))
{
g_free
(
default_avatar
);
default_avatar
=
NULL
;
}
}
purple_prefs_add_path
(
PIDGIN_PREFS_ROOT
"/accounts/buddyicon"
,
default_avatar
);
g_free
(
default_avatar
);
purple_signal_register
(
pidgin_account_get_handle
(),
"account-modified"
,
purple_marshal_VOID__POINTER
,
NULL
,
1
,
purple_value_new
(
PURPLE_TYPE_SUBTYPE
,
PURPLE_SUBTYPE_ACCOUNT
));
/* Setup some purple signal handlers. */
purple_signal_connect
(
purple_connections_get_handle
(),
"signed-on"
,
pidgin_account_get_handle
(),
PURPLE_CALLBACK
(
signed_on_off_cb
),
NULL
);
purple_signal_connect
(
purple_connections_get_handle
(),
"signed-off"
,
pidgin_account_get_handle
(),
PURPLE_CALLBACK
(
signed_on_off_cb
),
NULL
);
purple_signal_connect
(
purple_accounts_get_handle
(),
"account-added"
,
pidgin_account_get_handle
(),
PURPLE_CALLBACK
(
add_account_to_liststore
),
NULL
);
purple_signal_connect
(
purple_accounts_get_handle
(),
"account-removed"
,
pidgin_account_get_handle
(),
PURPLE_CALLBACK
(
account_removed_cb
),
NULL
);
purple_signal_connect
(
purple_accounts_get_handle
(),
"account-disabled"
,
pidgin_account_get_handle
(),
PURPLE_CALLBACK
(
account_abled_cb
),
GINT_TO_POINTER
(
FALSE
));
purple_signal_connect
(
purple_accounts_get_handle
(),
"account-enabled"
,
pidgin_account_get_handle
(),
PURPLE_CALLBACK
(
account_abled_cb
),
GINT_TO_POINTER
(
TRUE
));
account_pref_wins
=
g_hash_table_new_full
(
g_direct_hash
,
g_direct_equal
,
NULL
,
NULL
);
}
void
pidgin_account_uninit
(
void
)
{
/*
* TODO: Need to free all the dialogs in here. Could probably create
* a callback function to use for the free-some-data-function
* parameter of g_hash_table_new_full, above.
*/
g_hash_table_destroy
(
account_pref_wins
);
purple_signals_disconnect_by_handle
(
pidgin_account_get_handle
());
purple_signals_unregister_by_instance
(
pidgin_account_get_handle
());
}