pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Fix some GWarnings during finch's startup
20 months ago, Gary Kramlich
01b94846bb60
Fix some GWarnings during finch's startup
Testing Done:
Ran via `G_DEBUG=fatal-warnings gdb --ex run finch3` and verified I was able to make it to the contact list.
Reviewed at https://reviews.imfreedom.org/r/1592/
/* 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
*/
#ifdef HAVE_CONFIG_H
#
include
<config.h>
#endif
#include
<glib/gi18n-lib.h>
#include
<purple.h>
#include
"libpurple/glibcompat.h"
#include
"gtkaccount.h"
#include
"gtkblist.h"
#include
"gtkdialogs.h"
#include
"gtkutils.h"
#include
"pidgincore.h"
#include
"pidgindialog.h"
#include
"minidialog.h"
#include
"pidginprotocolchooser.h"
#include
"pidginproxyoptions.h"
enum
{
RESPONSE_ADD
=
0
,
RESPONSE_CLOSE
,
};
typedef
struct
{
PurpleAccount
*
account
;
char
*
username
;
char
*
alias
;
}
PidginAccountAddUserData
;
typedef
struct
{
GtkWidget
*
widget
;
gchar
*
setting
;
PurplePrefType
type
;
}
ProtocolOptEntry
;
typedef
struct
{
PidginAccountDialogType
type
;
PurpleAccount
*
account
;
char
*
protocol_id
;
PurpleProtocol
*
protocol
;
GList
*
user_split_entries
;
GList
*
protocol_opt_entries
;
GtkSizeGroup
*
sg
;
GtkWidget
*
window
;
GtkWidget
*
notebook
;
GtkWidget
*
top_vbox
;
GtkWidget
*
ok_button
;
GtkWidget
*
register_button
;
/* Login Options */
GtkWidget
*
login_frame
;
GtkWidget
*
protocol_menu
;
GtkWidget
*
username_entry
;
GdkRGBA
username_entry_hint_color
;
GtkWidget
*
alias_entry
;
/* User Options */
GtkWidget
*
user_frame
;
GtkWidget
*
icon_hbox
;
GtkWidget
*
icon_check
;
GtkWidget
*
icon_entry
;
GtkFileChooserNative
*
icon_filesel
;
GtkWidget
*
icon_preview
;
GtkWidget
*
icon_text
;
PurpleImage
*
icon_img
;
/* Protocol Options */
GtkWidget
*
protocol_frame
;
GtkWidget
*
proxy_options
;
/* Voice & Video Options*/
GtkWidget
*
voice_frame
;
GtkWidget
*
suppression_check
;
}
AccountPrefsDialog
;
typedef
struct
{
PurpleAccount
*
account
;
PidginAccountDialogType
type
;
}
PidginAccountDialogShowData
;
/**************************************************************************
* 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_account_options
(
AccountPrefsDialog
*
dialog
);
static
void
add_voice_options
(
AccountPrefsDialog
*
dialog
);
static
GtkWidget
*
add_pref_box
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
,
const
char
*
text
,
GtkWidget
*
widget
)
{
return
pidgin_add_widget_to_vbox
(
GTK_BOX
(
parent
),
text
,
dialog
->
sg
,
widget
,
TRUE
,
NULL
);
}
static
void
set_dialog_icon
(
AccountPrefsDialog
*
dialog
,
gpointer
data
,
size_t
len
,
gchar
*
new_icon_path
)
{
GdkPixbuf
*
pixbuf
=
NULL
;
PurpleBuddyIconSpec
*
icon_spec
=
NULL
;
if
(
dialog
->
icon_img
)
{
g_object_unref
(
dialog
->
icon_img
);
dialog
->
icon_img
=
NULL
;
}
if
(
new_icon_path
!=
NULL
)
{
dialog
->
icon_img
=
purple_image_new_from_file
(
new_icon_path
,
NULL
);
purple_debug_warning
(
"gtkaccount"
,
"data was not necessary"
);
g_free
(
data
);
}
else
if
(
data
!=
NULL
)
{
if
(
len
>
0
)
dialog
->
icon_img
=
purple_image_new_take_data
(
data
,
len
);
else
g_free
(
data
);
}
if
(
dialog
->
icon_img
!=
NULL
)
{
pixbuf
=
purple_gdk_pixbuf_from_image
(
dialog
->
icon_img
);
}
if
(
dialog
->
protocol
)
icon_spec
=
purple_protocol_get_icon_spec
(
dialog
->
protocol
);
if
(
pixbuf
&&
icon_spec
&&
(
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
,
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
;
}
purple_buddy_icon_spec_free
(
icon_spec
);
if
(
pixbuf
==
NULL
)
{
/* Show a placeholder icon */
gtk_image_set_from_icon_name
(
GTK_IMAGE
(
dialog
->
icon_entry
),
"select-avatar"
,
GTK_ICON_SIZE_LARGE_TOOLBAR
);
}
else
{
gtk_image_set_from_pixbuf
(
GTK_IMAGE
(
dialog
->
icon_entry
),
pixbuf
);
g_object_unref
(
G_OBJECT
(
pixbuf
));
}
}
static
void
set_account_protocol_cb
(
GtkWidget
*
widget
,
AccountPrefsDialog
*
dialog
)
{
PidginProtocolChooser
*
chooser
=
PIDGIN_PROTOCOL_CHOOSER
(
widget
);
PurpleProtocol
*
protocol
=
pidgin_protocol_chooser_get_selected
(
chooser
);
if
(
g_set_object
(
&
dialog
->
protocol
,
protocol
))
{
g_clear_pointer
(
&
dialog
->
protocol_id
,
g_free
);
}
g_object_unref
(
G_OBJECT
(
protocol
));
if
(
PURPLE_IS_PROTOCOL
(
dialog
->
protocol
))
{
dialog
->
protocol_id
=
g_strdup
(
purple_protocol_get_id
(
dialog
->
protocol
));
}
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_account_options
(
dialog
);
add_voice_options
(
dialog
);
gtk_widget_grab_focus
(
dialog
->
protocol_menu
);
if
(
!
dialog
->
protocol
||
!
PURPLE_PROTOCOL_IMPLEMENTS
(
dialog
->
protocol
,
SERVER
,
register_user
))
{
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
register_button
),
FALSE
);
gtk_widget_hide
(
dialog
->
register_button
);
}
else
{
if
(
purple_protocol_get_options
(
dialog
->
protocol
)
&
OPT_PROTO_REGISTER_NOSCREENNAME
)
{
gtk_widget_set_sensitive
(
dialog
->
register_button
,
TRUE
);
}
else
{
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
register_button
),
FALSE
);
gtk_widget_set_sensitive
(
dialog
->
register_button
,
FALSE
);
}
gtk_widget_show
(
dialog
->
register_button
);
}
}
static
void
username_changed_cb
(
GtkEntry
*
entry
,
AccountPrefsDialog
*
dialog
)
{
gboolean
opt_noscreenname
=
(
dialog
->
protocol
!=
NULL
&&
(
purple_protocol_get_options
(
dialog
->
protocol
)
&
OPT_PROTO_REGISTER_NOSCREENNAME
));
gboolean
username_valid
=
purple_validate
(
dialog
->
protocol
,
gtk_entry_get_text
(
entry
));
if
(
dialog
->
ok_button
)
{
if
(
opt_noscreenname
&&
dialog
->
register_button
&&
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
register_button
)))
gtk_widget_set_sensitive
(
dialog
->
ok_button
,
TRUE
);
else
gtk_widget_set_sensitive
(
dialog
->
ok_button
,
username_valid
);
}
if
(
dialog
->
register_button
)
{
if
(
opt_noscreenname
)
gtk_widget_set_sensitive
(
dialog
->
register_button
,
TRUE
);
else
gtk_widget_set_sensitive
(
dialog
->
register_button
,
username_valid
);
}
}
static
void
register_button_cb
(
GtkWidget
*
checkbox
,
AccountPrefsDialog
*
dialog
)
{
int
register_checked
=
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
register_button
));
int
opt_noscreenname
=
(
dialog
->
protocol
!=
NULL
&&
(
purple_protocol_get_options
(
dialog
->
protocol
)
&
OPT_PROTO_REGISTER_NOSCREENNAME
));
int
register_noscreenname
=
(
opt_noscreenname
&&
register_checked
);
if
(
register_noscreenname
)
{
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
username_entry
),
""
);
}
gtk_widget_set_sensitive
(
dialog
->
username_entry
,
!
register_noscreenname
);
if
(
dialog
->
ok_button
)
{
gtk_widget_set_sensitive
(
dialog
->
ok_button
,
(
opt_noscreenname
&&
register_checked
)
||
*
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
username_entry
))
!=
'\0'
);
}
}
static
void
icon_filesel_choose_cb
(
const
char
*
filename
,
gpointer
data
)
{
AccountPrefsDialog
*
dialog
=
data
;
if
(
filename
!=
NULL
)
{
size_t
len
=
0
;
gpointer
data
=
pidgin_convert_buddy_icon
(
dialog
->
protocol
,
filename
,
&
len
);
set_dialog_icon
(
dialog
,
data
,
len
,
g_strdup
(
filename
));
}
g_clear_object
(
&
dialog
->
icon_filesel
);
}
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_native_dialog_show
(
GTK_NATIVE_DIALOG
(
dialog
->
icon_filesel
));
}
static
void
icon_reset_cb
(
GtkWidget
*
button
,
AccountPrefsDialog
*
dialog
)
{
set_dialog_icon
(
dialog
,
NULL
,
0
,
NULL
);
}
static
void
update_editable
(
PurpleConnection
*
gc
,
AccountPrefsDialog
*
dialog
)
{
GtkStyleContext
*
style
;
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_editable_set_editable
(
GTK_EDITABLE
(
dialog
->
username_entry
),
set
);
style
=
gtk_widget_get_style_context
(
dialog
->
username_entry
);
if
(
set
)
{
gtk_style_context_remove_class
(
style
,
"copyable-insensitive"
);
}
else
{
gtk_style_context_add_class
(
style
,
"copyable-insensitive"
);
}
for
(
l
=
dialog
->
user_split_entries
;
l
!=
NULL
;
l
=
l
->
next
)
{
if
(
l
->
data
==
NULL
)
continue
;
if
(
GTK_IS_EDITABLE
(
l
->
data
))
{
gtk_editable_set_editable
(
GTK_EDITABLE
(
l
->
data
),
set
);
style
=
gtk_widget_get_style_context
(
GTK_WIDGET
(
l
->
data
));
if
(
set
)
{
gtk_style_context_remove_class
(
style
,
"copyable-insensitive"
);
}
else
{
gtk_style_context_add_class
(
style
,
"copyable-insensitive"
);
}
}
else
{
gtk_widget_set_sensitive
(
GTK_WIDGET
(
l
->
data
),
set
);
}
}
}
static
void
add_login_options
(
AccountPrefsDialog
*
dialog
,
GtkWidget
*
parent
)
{
GtkWidget
*
frame
;
GtkWidget
*
hbox
;
GtkWidget
*
vbox
;
GtkWidget
*
entry
;
GList
*
user_splits
;
GList
*
l
,
*
l2
;
char
*
username
=
NULL
;
GtkCssProvider
*
entry_css
;
const
gchar
*
res
=
"/im/pidgin/Pidgin3/Accounts/entry.css"
;
entry_css
=
gtk_css_provider_new
();
gtk_css_provider_load_from_resource
(
entry_css
,
res
);
if
(
dialog
->
protocol_menu
!=
NULL
)
{
g_object_ref
(
G_OBJECT
(
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_box_new
(
GTK_ORIENTATION_VERTICAL
,
6
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
vbox
);
gtk_widget_show
(
vbox
);
/* Protocol */
if
(
dialog
->
protocol_menu
==
NULL
)
{
dialog
->
protocol_menu
=
pidgin_protocol_chooser_new
();
pidgin_protocol_chooser_set_selected_id
(
PIDGIN_PROTOCOL_CHOOSER
(
dialog
->
protocol_menu
),
dialog
->
protocol_id
);
g_signal_connect
(
G_OBJECT
(
dialog
->
protocol_menu
),
"changed"
,
G_CALLBACK
(
set_account_protocol_cb
),
dialog
);
gtk_widget_show
(
dialog
->
protocol_menu
);
g_object_ref
(
G_OBJECT
(
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
);
g_object_unref
(
G_OBJECT
(
dialog
->
protocol_menu
));
/* Username */
dialog
->
username_entry
=
gtk_entry_new
();
gtk_style_context_add_provider
(
gtk_widget_get_style_context
(
dialog
->
username_entry
),
GTK_STYLE_PROVIDER
(
entry_css
),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
g_object_set
(
G_OBJECT
(
dialog
->
username_entry
),
"truncate-multiline"
,
TRUE
,
NULL
);
add_pref_box
(
dialog
,
vbox
,
_
(
"_Username:"
),
dialog
->
username_entry
);
if
(
dialog
->
account
!=
NULL
)
username
=
g_strdup
(
purple_account_get_username
(
dialog
->
account
));
if
(
!
username
&&
dialog
->
protocol
&&
PURPLE_PROTOCOL_IMPLEMENTS
(
dialog
->
protocol
,
CLIENT
,
get_account_text_table
))
{
GHashTable
*
table
;
const
char
*
label
;
table
=
purple_protocol_client_get_account_text_table
(
PURPLE_PROTOCOL_CLIENT
(
dialog
->
protocol
),
NULL
);
label
=
g_hash_table_lookup
(
table
,
"login_label"
);
gtk_entry_set_placeholder_text
(
GTK_ENTRY
(
dialog
->
username_entry
),
label
);
g_hash_table_destroy
(
table
);
}
g_signal_connect
(
G_OBJECT
(
dialog
->
username_entry
),
"changed"
,
G_CALLBACK
(
username_changed_cb
),
dialog
);
/* Do the user split thang */
if
(
dialog
->
protocol
==
NULL
)
user_splits
=
NULL
;
else
user_splits
=
purple_protocol_get_user_splits
(
dialog
->
protocol
);
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
;
if
(
purple_account_user_split_is_constant
(
split
))
entry
=
NULL
;
else
{
buf
=
g_strdup_printf
(
"_%s:"
,
purple_account_user_split_get_text
(
split
));
entry
=
gtk_entry_new
();
gtk_style_context_add_provider
(
gtk_widget_get_style_context
(
entry
),
GTK_STYLE_PROVIDER
(
entry_css
),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
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
&&
username
!=
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
);
if
(
value
!=
NULL
&&
entry
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
value
);
}
g_list_free_full
(
user_splits
,
(
GDestroyNotify
)
purple_account_user_split_destroy
);
if
(
username
!=
NULL
)
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
username_entry
),
username
);
g_free
(
username
);
/* Do not let the user change the protocol/username 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
);
g_object_unref
(
entry_css
);
}
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_box_new
(
GTK_ORIENTATION_VERTICAL
,
6
);
gtk_container_add
(
GTK_CONTAINER
(
frame
),
vbox
);
gtk_widget_show
(
vbox
);
/* Alias */
dialog
->
alias_entry
=
gtk_entry_new
();
add_pref_box
(
dialog
,
vbox
,
_
(
"_Local alias:"
),
dialog
->
alias_entry
);
/* 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_box_new
(
GTK_ORIENTATION_HORIZONTAL
,
6
);
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
,
GTK_LABEL
(
label
));
if
(
dialog
->
icon_img
)
{
g_object_unref
(
dialog
->
icon_img
);
dialog
->
icon_img
=
NULL
;
}
vbox2
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
0
);
gtk_box_pack_start
(
GTK_BOX
(
hbox
),
vbox2
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
vbox2
);
hbox2
=
gtk_box_new
(
GTK_ORIENTATION_HORIZONTAL
,
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox2
),
hbox2
,
FALSE
,
FALSE
,
12
);
gtk_widget_show
(
hbox2
);
button
=
gtk_button_new_with_mnemonic
(
_
(
"_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
->
protocol
!=
NULL
)
{
PurpleBuddyIconSpec
*
icon_spec
=
purple_protocol_get_icon_spec
(
dialog
->
protocol
);
if
(
!
icon_spec
||
icon_spec
->
format
==
NULL
)
{
gtk_widget_hide
(
dialog
->
icon_check
);
gtk_widget_hide
(
dialog
->
icon_hbox
);
}
purple_buddy_icon_spec_free
(
icon_spec
);
}
if
(
dialog
->
account
!=
NULL
)
{
PurpleImage
*
img
;
gpointer
data
=
NULL
;
size_t
len
=
0
;
if
(
purple_account_get_private_alias
(
dialog
->
account
))
gtk_entry_set_text
(
GTK_ENTRY
(
dialog
->
alias_entry
),
purple_account_get_private_alias
(
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_image_get_data_size
(
img
);
data
=
g_memdup2
(
purple_image_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 0
if (!dialog->protocol ||
(!(purple_protocol_get_options(dialog->protocol) & OPT_PROTO_MAIL_CHECK) &&
(purple_protocol_get_icon_spec(dialog->protocol).format == NULL))) {
/* Nothing to see :( aww. */
gtk_widget_hide(dialog->user_frame);
}
#endif
}
static
void
protocol_opt_entry_free
(
ProtocolOptEntry
*
opt_entry
)
{
g_return_if_fail
(
opt_entry
!=
NULL
);
g_free
(
opt_entry
->
setting
);
g_free
(
opt_entry
);
}
static
void
add_account_options
(
AccountPrefsDialog
*
dialog
)
{
PurpleAccountOption
*
option
;
PurpleAccount
*
account
;
GtkWidget
*
vbox
,
*
check
,
*
entry
,
*
combo
;
GList
*
list
,
*
node
,
*
opts
;
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
;
ProtocolOptEntry
*
opt_entry
;
const
GSList
*
str_hints
;
if
(
dialog
->
protocol_frame
!=
NULL
)
{
gtk_notebook_remove_page
(
GTK_NOTEBOOK
(
dialog
->
notebook
),
1
);
dialog
->
protocol_frame
=
NULL
;
}
g_list_free_full
(
dialog
->
protocol_opt_entries
,
(
GDestroyNotify
)
protocol_opt_entry_free
);
dialog
->
protocol_opt_entries
=
NULL
;
if
(
dialog
->
protocol
==
NULL
)
{
return
;
}
opts
=
purple_protocol_get_account_options
(
dialog
->
protocol
);
if
(
opts
==
NULL
)
{
return
;
}
account
=
dialog
->
account
;
/* Main vbox */
dialog
->
protocol_frame
=
vbox
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
6
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
vbox
),
12
);
gtk_notebook_insert_page
(
GTK_NOTEBOOK
(
dialog
->
notebook
),
vbox
,
gtk_label_new_with_mnemonic
(
_
(
"Ad_vanced"
)),
1
);
gtk_widget_show
(
vbox
);
for
(
l
=
opts
;
l
!=
NULL
;
l
=
l
->
next
)
{
option
=
(
PurpleAccountOption
*
)
l
->
data
;
opt_entry
=
g_new0
(
ProtocolOptEntry
,
1
);
opt_entry
->
type
=
purple_account_option_get_pref_type
(
option
);
opt_entry
->
setting
=
g_strdup
(
purple_account_option_get_setting
(
option
));
switch
(
opt_entry
->
type
)
{
case
PURPLE_PREF_BOOLEAN
:
if
(
account
==
NULL
||
!
purple_strequal
(
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
);
opt_entry
->
widget
=
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
);
break
;
case
PURPLE_PREF_INT
:
if
(
account
==
NULL
||
!
purple_strequal
(
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
);
opt_entry
->
widget
=
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
);
break
;
case
PURPLE_PREF_STRING
:
if
(
account
==
NULL
||
!
purple_strequal
(
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
));
}
str_hints
=
purple_account_option_string_get_hints
(
option
);
if
(
str_hints
)
{
const
GSList
*
hint_it
=
str_hints
;
entry
=
gtk_combo_box_text_new_with_entry
();
while
(
hint_it
)
{
const
gchar
*
hint
=
hint_it
->
data
;
hint_it
=
g_slist_next
(
hint_it
);
gtk_combo_box_text_append_text
(
GTK_COMBO_BOX_TEXT
(
entry
),
hint
);
}
}
else
entry
=
gtk_entry_new
();
opt_entry
->
widget
=
entry
;
if
(
purple_account_option_string_get_masked
(
option
)
&&
str_hints
)
g_warn_if_reached
();
else
if
(
purple_account_option_string_get_masked
(
option
))
{
gtk_entry_set_visibility
(
GTK_ENTRY
(
entry
),
FALSE
);
}
if
(
str_value
!=
NULL
&&
str_hints
)
gtk_entry_set_text
(
GTK_ENTRY
(
gtk_bin_get_child
(
GTK_BIN
(
entry
))),
str_value
);
else
gtk_entry_set_text
(
GTK_ENTRY
(
entry
),
str_value
?
str_value
:
""
);
title
=
g_strdup_printf
(
"_%s:"
,
purple_account_option_get_text
(
option
));
add_pref_box
(
dialog
,
vbox
,
title
,
entry
);
g_free
(
title
);
break
;
case
PURPLE_PREF_STRING_LIST
:
i
=
0
;
idx
=
0
;
if
(
account
==
NULL
||
!
purple_strequal
(
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
);
opt_entry
->
widget
=
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
);
break
;
default
:
purple_debug_error
(
"gtkaccount"
,
"Invalid Account Option pref type (%d)
\n
"
,
opt_entry
->
type
);
g_free
(
opt_entry
->
setting
);
g_free
(
opt_entry
);
continue
;
}
dialog
->
protocol_opt_entries
=
g_list_append
(
dialog
->
protocol_opt_entries
,
opt_entry
);
}
g_list_free_full
(
opts
,
(
GDestroyNotify
)
purple_account_option_destroy
);
}
static
void
add_voice_options
(
AccountPrefsDialog
*
dialog
)
{
if
(
!
dialog
->
protocol
||
!
PURPLE_PROTOCOL_IMPLEMENTS
(
dialog
->
protocol
,
MEDIA
,
initiate_session
))
{
if
(
dialog
->
voice_frame
)
{
gtk_widget_destroy
(
dialog
->
voice_frame
);
dialog
->
voice_frame
=
NULL
;
dialog
->
suppression_check
=
NULL
;
}
return
;
}
if
(
!
dialog
->
voice_frame
)
{
dialog
->
voice_frame
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
12
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
dialog
->
voice_frame
),
12
);
dialog
->
suppression_check
=
gtk_check_button_new_with_mnemonic
(
_
(
"Use _silence suppression"
));
gtk_box_pack_start
(
GTK_BOX
(
dialog
->
voice_frame
),
dialog
->
suppression_check
,
FALSE
,
FALSE
,
0
);
gtk_notebook_append_page
(
GTK_NOTEBOOK
(
dialog
->
notebook
),
dialog
->
voice_frame
,
gtk_label_new_with_mnemonic
(
_
(
"_Voice and Video"
)));
gtk_widget_show_all
(
dialog
->
voice_frame
);
}
if
(
dialog
->
account
)
{
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
suppression_check
),
purple_account_get_silence_suppression
(
dialog
->
account
));
}
else
{
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
suppression_check
),
FALSE
);
}
}
static
gboolean
account_win_destroy_cb
(
GtkWidget
*
w
,
GdkEvent
*
event
,
AccountPrefsDialog
*
dialog
)
{
gtk_widget_destroy
(
dialog
->
window
);
g_list_free
(
dialog
->
user_split_entries
);
g_list_free_full
(
dialog
->
protocol_opt_entries
,
(
GDestroyNotify
)
protocol_opt_entry_free
);
g_free
(
dialog
->
protocol_id
);
g_object_unref
(
dialog
->
sg
);
if
(
dialog
->
icon_img
)
g_object_unref
(
dialog
->
icon_img
);
g_clear_object
(
&
dialog
->
icon_filesel
);
purple_signals_disconnect_by_handle
(
dialog
);
g_free
(
dialog
);
return
FALSE
;
}
static
void
account_register_cb
(
PurpleAccount
*
account
,
gboolean
succeeded
,
void
*
user_data
)
{
if
(
succeeded
)
{
const
PurpleSavedStatus
*
saved_status
=
purple_savedstatus_get_current
();
purple_signal_emit
(
pidgin_accounts_get_handle
(),
"account-modified"
,
account
);
if
(
saved_status
!=
NULL
&&
purple_account_get_remember_password
(
account
))
{
purple_savedstatus_activate_for_account
(
saved_status
,
account
);
purple_account_set_enabled
(
account
,
TRUE
);
}
}
else
purple_accounts_delete
(
account
);
}
static
void
account_prefs_save
(
AccountPrefsDialog
*
dialog
)
{
PurpleAccountManager
*
manager
=
NULL
;
PurpleProxyInfo
*
proxy_info
=
NULL
;
GList
*
l
,
*
l2
;
const
char
*
value
;
char
*
username
;
char
*
tmp
;
gboolean
new_acct
=
FALSE
,
icon_change
=
FALSE
;
PurpleAccount
*
account
;
PurpleBuddyIconSpec
*
icon_spec
=
NULL
;
manager
=
purple_account_manager_get_default
();
/* Build the username string. */
username
=
g_strdup
(
gtk_entry_get_text
(
GTK_ENTRY
(
dialog
->
username_entry
)));
if
(
dialog
->
protocol
!=
NULL
)
{
for
(
l
=
purple_protocol_get_user_splits
(
dialog
->
protocol
),
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
=
entry
?
gtk_entry_get_text
(
entry
)
:
""
;
if
(
!
value
)
value
=
""
;
*
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
)
{
account
=
purple_account_manager_find
(
manager
,
username
,
dialog
->
protocol_id
);
if
(
PURPLE_IS_ACCOUNT
(
account
))
{
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."
),
NULL
);
g_free
(
username
);
return
;
}
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_private_alias
(
account
,
value
);
else
purple_account_set_private_alias
(
account
,
NULL
);
/* Buddy Icon */
if
(
dialog
->
protocol
!=
NULL
)
icon_spec
=
purple_protocol_get_icon_spec
(
dialog
->
protocol
);
if
(
icon_spec
&&
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_image_get_data_size
(
dialog
->
icon_img
);
purple_buddy_icons_set_account_icon
(
account
,
g_memdup2
(
purple_image_get_data
(
dialog
->
icon_img
),
len
),
len
);
purple_account_set_buddy_icon_path
(
account
,
purple_image_get_path
(
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
=
0
;
gpointer
data
=
pidgin_convert_buddy_icon
(
dialog
->
protocol
,
filename
,
&
len
);
purple_account_set_buddy_icon_path
(
account
,
filename
);
purple_buddy_icons_set_account_icon
(
account
,
data
,
len
);
}
}
purple_buddy_icon_spec_free
(
icon_spec
);
purple_account_set_username
(
account
,
username
);
g_free
(
username
);
/* Add the protocol settings */
if
(
dialog
->
protocol
)
{
ProtocolOptEntry
*
opt_entry
;
GtkTreeIter
iter
;
char
*
value2
;
int
int_value
;
gboolean
bool_value
;
for
(
l2
=
dialog
->
protocol_opt_entries
;
l2
;
l2
=
l2
->
next
)
{
opt_entry
=
l2
->
data
;
switch
(
opt_entry
->
type
)
{
case
PURPLE_PREF_STRING
:
if
(
GTK_IS_COMBO_BOX
(
opt_entry
->
widget
))
value
=
gtk_combo_box_text_get_active_text
(
GTK_COMBO_BOX_TEXT
(
opt_entry
->
widget
));
else
value
=
gtk_entry_get_text
(
GTK_ENTRY
(
opt_entry
->
widget
));
purple_account_set_string
(
account
,
opt_entry
->
setting
,
value
);
break
;
case
PURPLE_PREF_INT
:
int_value
=
atoi
(
gtk_entry_get_text
(
GTK_ENTRY
(
opt_entry
->
widget
)));
purple_account_set_int
(
account
,
opt_entry
->
setting
,
int_value
);
break
;
case
PURPLE_PREF_BOOLEAN
:
bool_value
=
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
opt_entry
->
widget
));
purple_account_set_bool
(
account
,
opt_entry
->
setting
,
bool_value
);
break
;
case
PURPLE_PREF_STRING_LIST
:
value2
=
NULL
;
if
(
gtk_combo_box_get_active_iter
(
GTK_COMBO_BOX
(
opt_entry
->
widget
),
&
iter
))
gtk_tree_model_get
(
gtk_combo_box_get_model
(
GTK_COMBO_BOX
(
opt_entry
->
widget
)),
&
iter
,
1
,
&
value2
,
-1
);
purple_account_set_string
(
account
,
opt_entry
->
setting
,
value2
);
break
;
default
:
break
;
}
}
}
proxy_info
=
pidgin_proxy_options_get_info
(
PIDGIN_PROXY_OPTIONS
(
dialog
->
proxy_options
));
purple_account_set_proxy_info
(
account
,
proxy_info
);
/* Voice and Video settings */
if
(
dialog
->
voice_frame
)
{
purple_account_set_silence_suppression
(
account
,
gtk_toggle_button_get_active
(
GTK_TOGGLE_BUTTON
(
dialog
->
suppression_check
)));
}
/* If this is a new account, add it to our list */
if
(
new_acct
)
{
purple_account_manager_add
(
manager
,
account
);
}
else
{
purple_signal_emit
(
pidgin_accounts_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_set_register_callback
(
account
,
account_register_cb
,
NULL
);
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
,
TRUE
);
}
}
/* We no longer need the data from the dialog window */
account_win_destroy_cb
(
NULL
,
NULL
,
dialog
);
}
static
void
account_prefs_response_cb
(
GtkDialog
*
dialog
,
gint
response_id
,
gpointer
data
)
{
AccountPrefsDialog
*
window
=
(
AccountPrefsDialog
*
)
data
;
switch
(
response_id
)
{
case
RESPONSE_ADD
:
account_prefs_save
(
window
);
break
;
case
RESPONSE_CLOSE
:
account_win_destroy_cb
(
NULL
,
NULL
,
window
);
break
;
default
:
break
;
}
}
void
pidgin_account_dialog_show
(
PidginAccountDialogType
type
,
PurpleAccount
*
account
)
{
AccountPrefsDialog
*
dialog
;
GtkWidget
*
win
;
GtkWidget
*
main_vbox
;
GtkWidget
*
vbox
;
GtkWidget
*
notebook
;
GtkWidget
*
button
;
dialog
=
g_new0
(
AccountPrefsDialog
,
1
);
if
(
PURPLE_IS_ACCOUNT
(
account
))
{
dialog
->
protocol_id
=
g_strdup
(
purple_account_get_protocol_id
(
account
));
}
dialog
->
account
=
account
;
dialog
->
type
=
type
;
dialog
->
sg
=
gtk_size_group_new
(
GTK_SIZE_GROUP_HORIZONTAL
);
if
(
dialog
->
protocol_id
!=
NULL
)
{
PurpleProtocolManager
*
manager
=
purple_protocol_manager_get_default
();
dialog
->
protocol
=
purple_protocol_manager_find
(
manager
,
dialog
->
protocol_id
);
}
dialog
->
window
=
win
=
pidgin_dialog_new
((
type
==
PIDGIN_ADD_ACCOUNT_DIALOG
)
?
_
(
"Add Account"
)
:
_
(
"Modify Account"
),
6
,
"account"
,
FALSE
);
g_signal_connect
(
win
,
"delete_event"
,
G_CALLBACK
(
account_win_destroy_cb
),
dialog
);
g_signal_connect
(
win
,
"response"
,
G_CALLBACK
(
account_prefs_response_cb
),
dialog
);
/* Setup the vbox */
main_vbox
=
gtk_dialog_get_content_area
(
GTK_DIALOG
(
win
));
gtk_box_set_spacing
(
GTK_BOX
(
main_vbox
),
6
);
dialog
->
notebook
=
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_box_new
(
GTK_ORIENTATION_VERTICAL
,
12
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
vbox
),
12
);
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_mnemonic
(
_
(
"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
;
g_signal_connect
(
G_OBJECT
(
dialog
->
register_button
),
"toggled"
,
G_CALLBACK
(
register_button_cb
),
dialog
);
if
(
dialog
->
account
==
NULL
)
gtk_widget_set_sensitive
(
button
,
FALSE
);
if
(
!
dialog
->
protocol
||
!
PURPLE_PROTOCOL_IMPLEMENTS
(
dialog
->
protocol
,
SERVER
,
register_user
))
gtk_widget_hide
(
button
);
/* Setup the page with 'Advanced' (protocol options). */
add_account_options
(
dialog
);
/* Setup the proxy options page. */
dialog
->
proxy_options
=
pidgin_proxy_options_new
();
if
(
PURPLE_IS_ACCOUNT
(
dialog
->
account
))
{
pidgin_proxy_options_set_info
(
PIDGIN_PROXY_OPTIONS
(
dialog
->
proxy_options
),
purple_account_get_proxy_info
(
dialog
->
account
));
}
gtk_notebook_append_page
(
GTK_NOTEBOOK
(
notebook
),
dialog
->
proxy_options
,
gtk_label_new_with_mnemonic
(
_
(
"Proxy"
)));
gtk_widget_show
(
dialog
->
proxy_options
);
add_voice_options
(
dialog
);
/* Buttons */
gtk_dialog_add_button
(
GTK_DIALOG
(
win
),
_
(
"_Cancel"
),
RESPONSE_CLOSE
);
dialog
->
ok_button
=
gtk_dialog_add_button
(
GTK_DIALOG
(
win
),
(
type
==
PIDGIN_ADD_ACCOUNT_DIALOG
)
?
_
(
"_Add"
)
:
_
(
"_Save"
),
RESPONSE_ADD
);
if
(
dialog
->
account
==
NULL
)
{
gtk_widget_set_sensitive
(
dialog
->
ok_button
,
FALSE
);
}
/* Show the window. */
gtk_widget_show
(
win
);
if
(
!
account
)
gtk_widget_grab_focus
(
dialog
->
protocol_menu
);
}
/**************************************************************************
* Accounts Dialog
**************************************************************************/
static
void
free_add_user_data
(
G_GNUC_UNUSED
PidginMiniDialog
*
mini_dialog
,
G_GNUC_UNUSED
GtkButton
*
button
,
gpointer
user_data
)
{
PidginAccountAddUserData
*
data
=
user_data
;
g_free
(
data
->
username
);
g_free
(
data
->
alias
);
g_free
(
data
);
}
static
void
add_user_cb
(
G_GNUC_UNUSED
PidginMiniDialog
*
mini_dialog
,
G_GNUC_UNUSED
GtkButton
*
button
,
gpointer
user_data
)
{
PidginAccountAddUserData
*
data
=
user_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
(
NULL
,
NULL
,
user_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_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_mini_dialog_new_with_buttons
(
_
(
"Add buddy to your list?"
),
buffer
,
"dialog-question"
,
data
,
_
(
"Add"
),
add_user_cb
,
_
(
"Cancel"
),
free_add_user_data
,
NULL
);
pidgin_blist_add_alert
(
alert
);
g_free
(
buffer
);
}
struct
auth_request
{
PurpleAccountRequestAuthorizationCb
auth_cb
;
PurpleAccountRequestAuthorizationCb
deny_cb
;
void
*
data
;
char
*
username
;
char
*
alias
;
PurpleAccount
*
account
;
gboolean
add_buddy_after_auth
;
};
static
void
free_auth_request
(
struct
auth_request
*
ar
)
{
g_free
(
ar
->
username
);
g_free
(
ar
->
alias
);
g_free
(
ar
);
}
static
void
authorize_and_add_cb
(
struct
auth_request
*
ar
,
const
char
*
message
)
{
ar
->
auth_cb
(
message
,
ar
->
data
);
if
(
ar
->
add_buddy_after_auth
)
{
purple_blist_request_add_buddy
(
ar
->
account
,
ar
->
username
,
NULL
,
ar
->
alias
);
}
}
static
void
authorize_noreason_cb
(
struct
auth_request
*
ar
)
{
authorize_and_add_cb
(
ar
,
NULL
);
}
static
void
authorize_reason_cb
(
G_GNUC_UNUSED
PidginMiniDialog
*
mini_dialog
,
G_GNUC_UNUSED
GtkButton
*
button
,
gpointer
user_data
)
{
struct
auth_request
*
ar
=
user_data
;
PurpleProtocol
*
protocol
=
purple_account_get_protocol
(
ar
->
account
);
if
(
protocol
&&
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE
))
{
/* Duplicate information because ar is freed by closing minidialog */
struct
auth_request
*
aa
=
g_new0
(
struct
auth_request
,
1
);
aa
->
auth_cb
=
ar
->
auth_cb
;
aa
->
deny_cb
=
ar
->
deny_cb
;
aa
->
data
=
ar
->
data
;
aa
->
account
=
ar
->
account
;
aa
->
username
=
g_strdup
(
ar
->
username
);
aa
->
alias
=
g_strdup
(
ar
->
alias
);
aa
->
add_buddy_after_auth
=
ar
->
add_buddy_after_auth
;
purple_request_input
(
ar
->
account
,
NULL
,
_
(
"Authorization acceptance message:"
),
NULL
,
_
(
"No reason given."
),
TRUE
,
FALSE
,
NULL
,
_
(
"OK"
),
G_CALLBACK
(
authorize_and_add_cb
),
_
(
"Cancel"
),
G_CALLBACK
(
authorize_noreason_cb
),
purple_request_cpar_from_account
(
ar
->
account
),
aa
);
/* FIXME: aa is going to leak now. */
}
else
{
authorize_noreason_cb
(
ar
);
}
}
static
void
deny_no_add_cb
(
struct
auth_request
*
ar
,
const
char
*
message
)
{
ar
->
deny_cb
(
message
,
ar
->
data
);
}
static
void
deny_noreason_cb
(
struct
auth_request
*
ar
)
{
ar
->
deny_cb
(
NULL
,
ar
->
data
);
}
static
void
deny_reason_cb
(
G_GNUC_UNUSED
PidginMiniDialog
*
mini_dialog
,
G_GNUC_UNUSED
GtkButton
*
button
,
gpointer
user_data
)
{
struct
auth_request
*
ar
=
user_data
;
PurpleProtocol
*
protocol
=
purple_account_get_protocol
(
ar
->
account
);
if
(
protocol
&&
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE
))
{
/* Duplicate information because ar is freed by closing minidialog */
struct
auth_request
*
aa
=
g_new0
(
struct
auth_request
,
1
);
aa
->
auth_cb
=
ar
->
auth_cb
;
aa
->
deny_cb
=
ar
->
deny_cb
;
aa
->
data
=
ar
->
data
;
aa
->
add_buddy_after_auth
=
ar
->
add_buddy_after_auth
;
purple_request_input
(
ar
->
account
,
NULL
,
_
(
"Authorization denied message:"
),
NULL
,
_
(
"No reason given."
),
TRUE
,
FALSE
,
NULL
,
_
(
"OK"
),
G_CALLBACK
(
deny_no_add_cb
),
_
(
"Cancel"
),
G_CALLBACK
(
deny_noreason_cb
),
purple_request_cpar_from_account
(
ar
->
account
),
aa
);
/* FIXME: aa is going to leak now. */
}
else
{
deny_noreason_cb
(
ar
);
}
}
static
gboolean
get_user_info_cb
(
GtkWidget
*
label
,
const
gchar
*
uri
,
gpointer
data
)
{
struct
auth_request
*
ar
=
data
;
if
(
purple_strequal
(
uri
,
"viewinfo"
))
{
pidgin_retrieve_user_info
(
purple_account_get_connection
(
ar
->
account
),
ar
->
username
);
return
TRUE
;
}
return
FALSE
;
}
static
void
send_im_cb
(
G_GNUC_UNUSED
PidginMiniDialog
*
mini_dialog
,
G_GNUC_UNUSED
GtkButton
*
button
,
gpointer
data
)
{
struct
auth_request
*
ar
=
data
;
pidgin_dialogs_im_with_user
(
ar
->
account
,
ar
->
username
);
}
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
;
PidginMiniDialog
*
dialog
;
GdkPixbuf
*
protocol_icon
;
struct
auth_request
*
aa
;
const
char
*
our_name
;
gboolean
have_valid_alias
;
char
*
escaped_remote_user
;
char
*
escaped_alias
;
char
*
escaped_our_name
;
char
*
escaped_message
;
gc
=
purple_account_get_connection
(
account
);
if
(
message
!=
NULL
&&
*
message
!=
'\0'
)
escaped_message
=
g_markup_escape_text
(
message
,
-1
);
else
escaped_message
=
g_strdup
(
""
);
our_name
=
(
id
!=
NULL
)
?
id
:
(
purple_connection_get_display_name
(
gc
)
!=
NULL
)
?
purple_connection_get_display_name
(
gc
)
:
purple_account_get_username
(
account
);
escaped_our_name
=
g_markup_escape_text
(
our_name
,
-1
);
escaped_remote_user
=
g_markup_escape_text
(
remote_user
,
-1
);
have_valid_alias
=
alias
&&
*
alias
;
escaped_alias
=
have_valid_alias
?
g_markup_escape_text
(
alias
,
-1
)
:
g_strdup
(
""
);
buffer
=
g_strdup_printf
(
_
(
"<a href=
\"
viewinfo
\"
>%s</a>%s%s%s wants to add you (%s) to his or her buddy list%s%s"
),
escaped_remote_user
,
(
have_valid_alias
?
" ("
:
""
),
escaped_alias
,
(
have_valid_alias
?
")"
:
""
),
escaped_our_name
,
(
*
escaped_message
?
": "
:
"."
),
escaped_message
);
g_free
(
escaped_remote_user
);
g_free
(
escaped_alias
);
g_free
(
escaped_our_name
);
g_free
(
escaped_message
);
protocol_icon
=
pidgin_create_protocol_icon
(
account
,
PIDGIN_PROTOCOL_ICON_SMALL
);
aa
=
g_new0
(
struct
auth_request
,
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
;
aa
->
add_buddy_after_auth
=
!
on_list
;
dialog
=
pidgin_mini_dialog_new_with_custom_icon
(
_
(
"Authorize buddy?"
),
NULL
,
protocol_icon
);
alert
=
GTK_WIDGET
(
dialog
);
pidgin_mini_dialog_enable_description_markup
(
dialog
);
pidgin_mini_dialog_set_link_callback
(
dialog
,
G_CALLBACK
(
get_user_info_cb
),
aa
);
pidgin_mini_dialog_set_description
(
dialog
,
buffer
);
pidgin_mini_dialog_add_button
(
dialog
,
_
(
"Authorize"
),
authorize_reason_cb
,
aa
);
pidgin_mini_dialog_add_button
(
dialog
,
_
(
"Deny"
),
deny_reason_cb
,
aa
);
pidgin_mini_dialog_add_non_closing_button
(
dialog
,
_
(
"Send Instant Message"
),
send_im_cb
,
aa
);
g_signal_connect_swapped
(
G_OBJECT
(
alert
),
"destroy"
,
G_CALLBACK
(
free_auth_request
),
aa
);
g_signal_connect
(
G_OBJECT
(
alert
),
"destroy"
,
G_CALLBACK
(
purple_account_request_close
),
NULL
);
pidgin_blist_add_alert
(
alert
);
g_free
(
buffer
);
return
alert
;
}
static
void
pidgin_accounts_request_close
(
void
*
ui_handle
)
{
gtk_widget_destroy
(
GTK_WIDGET
(
ui_handle
));
}
static
PurpleAccountUiOps
ui_ops
=
{
.
request_add
=
pidgin_accounts_request_add
,
.
request_authorize
=
pidgin_accounts_request_authorization
,
.
close_account_request
=
pidgin_accounts_request_close
,
};
PurpleAccountUiOps
*
pidgin_accounts_get_ui_ops
(
void
)
{
return
&
ui_ops
;
}
void
*
pidgin_accounts_get_handle
(
void
)
{
static
int
handle
;
return
&
handle
;
}
void
pidgin_accounts_init
(
void
)
{
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
);
purple_prefs_add_path
(
PIDGIN_PREFS_ROOT
"/accounts/buddyicon"
,
NULL
);
purple_signal_register
(
pidgin_accounts_get_handle
(),
"account-modified"
,
purple_marshal_VOID__POINTER
,
G_TYPE_NONE
,
1
,
PURPLE_TYPE_ACCOUNT
);
}
void
pidgin_accounts_uninit
(
void
)
{
purple_signals_disconnect_by_handle
(
pidgin_accounts_get_handle
());
purple_signals_unregister_by_instance
(
pidgin_accounts_get_handle
());
}