pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
fixed the crash on disconnect by closing conversation windows when that buddy is done with it's events, rather than when processing each event.
2009-08-30, Gary Kramlich
8ab9212b3ed3
fixed the crash on disconnect by closing conversation windows when that buddy is done with it's events, rather than when processing each event.
added status text support as a status of the stress
/*************************************************************************
* Buddy Edit Module
*
* A Purple plugin that adds an edit to to buddies allowing you to change
* various details you can't normally change. It also provides a mechanism
* for subsequent plugins to add themselves to that dialog.
*
* by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006
* Some code copyright (C) 2006, Richard Laager <rlaager@users.sf.net>
*
* 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., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*************************************************************************/
#define PURPLE_PLUGINS
#define PLUGIN "core-kleptog-buddyedit"
#include
<glib.h>
#include
<string.h>
#include
"notify.h"
#include
"plugin.h"
#include
"util.h"
#include
"version.h"
#include
"debug.h"
/* Debug output functions */
#include
"request.h"
/* Requests stuff */
static
PurplePlugin
*
plugin_self
;
static
void
buddyedit_editcomplete_cb
(
PurpleBlistNode
*
data
,
PurpleRequestFields
*
fields
)
{
gboolean
blist_destroy
=
FALSE
;
PurpleBlistNode
*
olddata
=
data
;
/* Keep pointer in case we need to destroy it */
/* Account detail stuff */
switch
(
data
->
type
)
{
case
PURPLE_BLIST_BUDDY_NODE
:
{
PurpleBuddy
*
buddy
=
(
PurpleBuddy
*
)
data
;
PurpleAccount
*
account
=
purple_request_fields_get_account
(
fields
,
"account"
);
const
char
*
name
=
purple_request_fields_get_string
(
fields
,
"name"
);
const
char
*
alias
=
purple_request_fields_get_string
(
fields
,
"alias"
);
/* If any details changes, create the buddy */
if
((
account
!=
buddy
->
account
)
||
strcmp
(
name
,
buddy
->
name
))
{
GHashTable
*
tmp
;
PurpleBuddy
*
newbuddy
=
purple_buddy_new
(
account
,
name
,
alias
);
purple_blist_add_buddy
(
newbuddy
,
NULL
,
NULL
,
data
);
/* Copy it to correct location */
/* Now this is ugly, but we want to copy the settings and avoid issues with memory management */
tmp
=
((
PurpleBlistNode
*
)
buddy
)
->
settings
;
((
PurpleBlistNode
*
)
buddy
)
->
settings
=
((
PurpleBlistNode
*
)
newbuddy
)
->
settings
;
((
PurpleBlistNode
*
)
newbuddy
)
->
settings
=
tmp
;
blist_destroy
=
TRUE
;
data
=
(
PurpleBlistNode
*
)
newbuddy
;
}
else
purple_blist_alias_buddy
(
buddy
,
alias
);
break
;
}
case
PURPLE_BLIST_CONTACT_NODE
:
{
PurpleContact
*
contact
=
(
PurpleContact
*
)
data
;
const
char
*
alias
=
purple_request_fields_get_string
(
fields
,
"alias"
);
purple_contact_set_alias
(
contact
,
alias
);
break
;
}
case
PURPLE_BLIST_GROUP_NODE
:
{
PurpleGroup
*
group
=
(
PurpleGroup
*
)
data
;
const
char
*
alias
=
purple_request_fields_get_string
(
fields
,
"alias"
);
purple_blist_rename_group
(
group
,
alias
);
break
;
}
case
PURPLE_BLIST_CHAT_NODE
:
{
PurpleChat
*
chat
=
(
PurpleChat
*
)
data
;
gboolean
new_chat
=
FALSE
;
PurpleConnection
*
gc
;
GList
*
list
=
NULL
,
*
tmp
;
gc
=
purple_account_get_connection
(
chat
->
account
);
if
(
PURPLE_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
!=
NULL
)
list
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
(
gc
);
PurpleAccount
*
newaccount
=
purple_request_fields_get_account
(
fields
,
"account"
);
/* In Purple2 each prot_chat_entry has a field "required". We use
* this to determine if a field is important enough to recreate
* the chat if it changes. Non-required fields we just change
* in-situ. */
if
(
newaccount
!=
chat
->
account
)
new_chat
=
TRUE
;
else
{
const
char
*
oldvalue
,
*
newvalue
;
for
(
tmp
=
g_list_first
(
list
);
tmp
&&
!
new_chat
;
tmp
=
g_list_next
(
tmp
))
{
struct
proto_chat_entry
*
pce
=
tmp
->
data
;
if
(
!
pce
->
required
)
/* Only checking required fields at this point */
continue
;
if
(
pce
->
is_int
)
continue
;
/* Not yet */
oldvalue
=
g_hash_table_lookup
(
chat
->
components
,
pce
->
identifier
);
newvalue
=
purple_request_fields_get_string
(
fields
,
pce
->
identifier
);
if
(
oldvalue
==
NULL
)
oldvalue
=
""
;
if
(
newvalue
==
NULL
)
newvalue
=
""
;
if
(
strcmp
(
oldvalue
,
newvalue
)
!=
0
)
new_chat
=
TRUE
;
}
}
if
(
new_chat
)
{
const
char
*
oldvalue
,
*
newvalue
;
GHashTable
*
components
=
g_hash_table_new_full
(
g_str_hash
,
g_str_equal
,
g_free
,
g_free
);
for
(
tmp
=
g_list_first
(
list
);
tmp
;
tmp
=
g_list_next
(
tmp
))
{
struct
proto_chat_entry
*
pce
=
tmp
->
data
;
if
(
pce
->
is_int
)
{
oldvalue
=
g_hash_table_lookup
(
chat
->
components
,
pce
->
identifier
);
g_hash_table_replace
(
components
,
g_strdup
(
pce
->
identifier
),
g_strdup
(
oldvalue
));
}
else
{
newvalue
=
purple_request_fields_get_string
(
fields
,
pce
->
identifier
);
g_hash_table_replace
(
components
,
g_strdup
(
pce
->
identifier
),
g_strdup
(
newvalue
));
}
}
PurpleChat
*
newchat
=
purple_chat_new
(
newaccount
,
NULL
,
components
);
purple_blist_add_chat
(
newchat
,
NULL
,
data
);
/* Copy it to correct location */
data
=
(
PurpleBlistNode
*
)
newchat
;
blist_destroy
=
TRUE
;
}
else
/* Just updating values in old chat */
{
const
char
*
newvalue
;
for
(
tmp
=
g_list_first
(
list
);
tmp
;
tmp
=
g_list_next
(
tmp
))
{
struct
proto_chat_entry
*
pce
=
tmp
->
data
;
if
(
pce
->
required
)
continue
;
if
(
pce
->
is_int
)
{
/* Do nothing, yet */
}
else
{
newvalue
=
purple_request_fields_get_string
(
fields
,
pce
->
identifier
);
g_hash_table_replace
(
chat
->
components
,
g_strdup
(
pce
->
identifier
),
g_strdup
(
newvalue
));
}
}
}
const
char
*
alias
=
purple_request_fields_get_string
(
fields
,
"alias"
);
purple_blist_alias_chat
(
chat
,
alias
);
break
;
}
case
PURPLE_BLIST_OTHER_NODE
:
break
;
}
purple_signal_emit
(
purple_blist_get_handle
(),
PLUGIN
"-submit-fields"
,
fields
,
data
);
if
(
blist_destroy
)
{
if
(
olddata
->
type
==
PURPLE_BLIST_BUDDY_NODE
)
purple_blist_remove_buddy
((
PurpleBuddy
*
)
olddata
);
else
if
(
olddata
->
type
==
PURPLE_BLIST_CHAT_NODE
)
purple_blist_remove_chat
((
PurpleChat
*
)
olddata
);
}
/* Save any changes */
purple_blist_schedule_save
();
}
static
PurpleAccount
*
buddyedit_account_filter_func_data
;
static
gboolean
buddyedit_account_filter_func
(
PurpleAccount
*
account
)
{
PurplePluginProtocolInfo
*
gppi1
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
purple_account_get_connection
(
account
)
->
prpl
);
PurplePluginProtocolInfo
*
gppi2
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
purple_account_get_connection
(
buddyedit_account_filter_func_data
)
->
prpl
);
return
gppi1
==
gppi2
;
}
/* Node is either a contact or a buddy */
static
void
buddy_edit_cb
(
PurpleBlistNode
*
node
,
gpointer
data
)
{
purple_debug
(
PURPLE_DEBUG_INFO
,
PLUGIN
,
"buddy_edit_cb(%p)
\n
"
,
node
);
PurpleRequestFields
*
fields
;
PurpleRequestField
*
field
;
PurpleRequestFieldGroup
*
group
;
char
*
request_title
=
NULL
;
fields
=
purple_request_fields_new
();
switch
(
node
->
type
)
{
case
PURPLE_BLIST_BUDDY_NODE
:
{
PurpleBuddy
*
buddy
=
(
PurpleBuddy
*
)
node
;
group
=
purple_request_field_group_new
(
"Buddy Details"
);
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_account_new
(
"account"
,
"Account"
,
buddy
->
account
);
purple_request_field_account_set_show_all
(
field
,
TRUE
);
purple_request_field_group_add_field
(
group
,
field
);
field
=
purple_request_field_string_new
(
"name"
,
"Name"
,
buddy
->
name
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
field
=
purple_request_field_string_new
(
"alias"
,
"Alias"
,
buddy
->
alias
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Buddy"
;
break
;
}
case
PURPLE_BLIST_CONTACT_NODE
:
{
PurpleContact
*
contact
=
(
PurpleContact
*
)
node
;
group
=
purple_request_field_group_new
(
"Contact Details"
);
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_string_new
(
"alias"
,
"Alias"
,
contact
->
alias
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Contact"
;
break
;
}
case
PURPLE_BLIST_GROUP_NODE
:
{
PurpleGroup
*
grp
=
(
PurpleGroup
*
)
node
;
group
=
purple_request_field_group_new
(
"Group Details"
);
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_string_new
(
"alias"
,
"Name"
,
grp
->
name
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Group"
;
break
;
}
case
PURPLE_BLIST_CHAT_NODE
:
{
PurpleChat
*
chat
=
(
PurpleChat
*
)
node
;
PurpleConnection
*
gc
;
GList
*
list
=
NULL
,
*
tmp
;
group
=
purple_request_field_group_new
(
"Chat Details"
);
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_account_new
(
"account"
,
"Account"
,
chat
->
account
);
purple_request_field_account_set_filter
(
field
,
buddyedit_account_filter_func
);
buddyedit_account_filter_func_data
=
chat
->
account
;
purple_request_field_group_add_field
(
group
,
field
);
gc
=
purple_account_get_connection
(
chat
->
account
);
if
(
PURPLE_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
!=
NULL
)
list
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
(
gc
);
for
(
tmp
=
g_list_first
(
list
);
tmp
;
tmp
=
g_list_next
(
tmp
))
{
struct
proto_chat_entry
*
pce
=
tmp
->
data
;
const
char
*
value
;
purple_debug
(
PURPLE_DEBUG_INFO
,
PLUGIN
,
"identifier=%s, label=%s, is_int=%d, required=%d
\n
"
,
pce
->
identifier
,
pce
->
label
,
pce
->
is_int
,
pce
->
required
);
if
(
pce
->
is_int
)
continue
;
/* Not yet */
value
=
g_hash_table_lookup
(
chat
->
components
,
pce
->
identifier
);
field
=
purple_request_field_string_new
(
pce
->
identifier
,
pce
->
label
,
value
,
FALSE
);
purple_request_field_set_required
(
field
,
pce
->
required
);
purple_request_field_group_add_field
(
group
,
field
);
}
field
=
purple_request_field_string_new
(
"alias"
,
"Alias"
,
chat
->
alias
,
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Chat"
;
break
;
}
default
:
request_title
=
"Edit"
;
break
;
}
purple_signal_emit
(
purple_blist_get_handle
(),
PLUGIN
"-create-fields"
,
fields
,
node
);
purple_request_fields
(
plugin_self
,
request_title
,
NULL
,
NULL
,
fields
,
"OK"
,
G_CALLBACK
(
buddyedit_editcomplete_cb
),
"Cancel"
,
NULL
,
NULL
,
NULL
,
NULL
,
/* XXX: These should be set. */
node
);
}
static
void
buddy_menu_cb
(
PurpleBlistNode
*
node
,
GList
**
menu
,
void
*
data
)
{
PurpleMenuAction
*
action
;
switch
(
node
->
type
)
{
/* These are the types we handle */
case
PURPLE_BLIST_BUDDY_NODE
:
case
PURPLE_BLIST_CONTACT_NODE
:
case
PURPLE_BLIST_GROUP_NODE
:
case
PURPLE_BLIST_CHAT_NODE
:
break
;
case
PURPLE_BLIST_OTHER_NODE
:
default
:
return
;
}
action
=
purple_menu_action_new
(
"Edit..."
,
PURPLE_CALLBACK
(
buddy_edit_cb
),
NULL
,
NULL
);
*
menu
=
g_list_append
(
*
menu
,
action
);
}
static
gboolean
plugin_load
(
PurplePlugin
*
plugin
)
{
plugin_self
=
plugin
;
void
*
blist_handle
=
purple_blist_get_handle
();
purple_signal_register
(
blist_handle
,
PLUGIN
"-create-fields"
,
/* Called when about to create dialog */
purple_marshal_VOID__POINTER_POINTER
,
NULL
,
2
,
/* (FieldList*,BlistNode*) */
purple_value_new
(
PURPLE_TYPE_SUBTYPE
,
PURPLE_TYPE_POINTER
),
/* FieldList */
purple_value_new
(
PURPLE_TYPE_SUBTYPE
,
PURPLE_SUBTYPE_BLIST
));
purple_signal_register
(
blist_handle
,
PLUGIN
"-submit-fields"
,
/* Called when dialog submitted */
purple_marshal_VOID__POINTER_POINTER
,
NULL
,
2
,
/* (FieldList*,BlistNode*) */
purple_value_new
(
PURPLE_TYPE_SUBTYPE
,
PURPLE_TYPE_POINTER
),
/* FieldList */
purple_value_new
(
PURPLE_TYPE_SUBTYPE
,
PURPLE_SUBTYPE_BLIST
));
purple_signal_connect
(
blist_handle
,
"blist-node-extended-menu"
,
plugin
,
PURPLE_CALLBACK
(
buddy_menu_cb
),
NULL
);
return
TRUE
;
}
static
PurplePluginInfo
info
=
{
PURPLE_PLUGIN_MAGIC
,
PURPLE_MAJOR_VERSION
,
PURPLE_MINOR_VERSION
,
PURPLE_PLUGIN_STANDARD
,
NULL
,
0
,
NULL
,
PURPLE_PRIORITY_DEFAULT
,
PLUGIN
,
"Buddy Edit Module"
,
G_STRINGIFY
(
PLUGIN_VERSION
),
"Enable editing of buddy properties"
,
"A plugin that adds an edit to to buddies allowing you to change various details you can't normally change. "
"It also provides a mechanism for subsequent plugins to add themselves to that dialog. "
,
"Martijn van Oosterhout <kleptog@svana.org>"
,
"http://buddytools.sf.net"
,
plugin_load
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
static
void
init_plugin
(
PurplePlugin
*
plugin
)
{
}
PURPLE_INIT_PLUGIN
(
buddyedit
,
init_plugin
,
info
);