pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
Prepping for release
org.guifications.plugins
2008-08-04, grim
41483591cfb6
Prepping for release
/*************************************************************************
* Buddy Edit Module
*
* A Gaim 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 GAIM_PLUGINS
#define PLUGIN "core-kleptog-buddyedit"
#include
<glib.h>
#include
<string.h>
#include
"gaim-compat.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
GaimPlugin
*
plugin_self
;
static
void
buddyedit_editcomplete_cb
(
GaimBlistNode
*
data
,
GaimRequestFields
*
fields
)
{
gboolean
blist_destroy
=
FALSE
;
GaimBlistNode
*
olddata
=
data
;
/* Keep pointer in case we need to destroy it */
/* Account detail stuff */
switch
(
data
->
type
)
{
case
GAIM_BLIST_BUDDY_NODE
:
{
GaimBuddy
*
buddy
=
(
GaimBuddy
*
)
data
;
GaimAccount
*
account
=
gaim_request_fields_get_account
(
fields
,
"account"
);
const
char
*
name
=
gaim_request_fields_get_string
(
fields
,
"name"
);
const
char
*
alias
=
gaim_request_fields_get_string
(
fields
,
"alias"
);
/* If any details changes, create the buddy */
if
((
account
!=
buddy
->
account
)
||
strcmp
(
name
,
buddy
->
name
))
{
GHashTable
*
tmp
;
GaimBuddy
*
newbuddy
=
gaim_buddy_new
(
account
,
name
,
alias
);
gaim_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
=
((
GaimBlistNode
*
)
buddy
)
->
settings
;
((
GaimBlistNode
*
)
buddy
)
->
settings
=
((
GaimBlistNode
*
)
newbuddy
)
->
settings
;
((
GaimBlistNode
*
)
newbuddy
)
->
settings
=
tmp
;
blist_destroy
=
TRUE
;
data
=
(
GaimBlistNode
*
)
newbuddy
;
}
else
gaim_blist_alias_buddy
(
buddy
,
alias
);
break
;
}
case
GAIM_BLIST_CONTACT_NODE
:
{
GaimContact
*
contact
=
(
GaimContact
*
)
data
;
const
char
*
alias
=
gaim_request_fields_get_string
(
fields
,
"alias"
);
gaim_contact_set_alias
(
contact
,
alias
);
break
;
}
case
GAIM_BLIST_GROUP_NODE
:
{
GaimGroup
*
group
=
(
GaimGroup
*
)
data
;
const
char
*
alias
=
gaim_request_fields_get_string
(
fields
,
"alias"
);
gaim_blist_rename_group
(
group
,
alias
);
break
;
}
case
GAIM_BLIST_CHAT_NODE
:
{
GaimChat
*
chat
=
(
GaimChat
*
)
data
;
gboolean
new_chat
=
FALSE
;
GaimConnection
*
gc
;
GList
*
list
=
NULL
,
*
tmp
;
gc
=
gaim_account_get_connection
(
chat
->
account
);
if
(
GAIM_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
!=
NULL
)
list
=
GAIM_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
(
gc
);
GaimAccount
*
newaccount
=
gaim_request_fields_get_account
(
fields
,
"account"
);
/* In Gaim2 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 jsut change
* in-situ. In Gaim1.5 this field doesn't exist so we always
* recreate */
#if GAIM_MAJOR_VERSION >= 2
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
=
gaim_request_fields_get_string
(
fields
,
pce
->
identifier
);
if
(
oldvalue
==
NULL
)
oldvalue
=
""
;
if
(
newvalue
==
NULL
)
newvalue
=
""
;
if
(
strcmp
(
oldvalue
,
newvalue
)
!=
0
)
new_chat
=
TRUE
;
}
}
#else
new_chat
=
TRUE
;
#endif
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
=
gaim_request_fields_get_string
(
fields
,
pce
->
identifier
);
g_hash_table_replace
(
components
,
g_strdup
(
pce
->
identifier
),
g_strdup
(
newvalue
));
}
}
GaimChat
*
newchat
=
gaim_chat_new
(
newaccount
,
NULL
,
components
);
gaim_blist_add_chat
(
newchat
,
NULL
,
data
);
/* Copy it to correct location */
data
=
(
GaimBlistNode
*
)
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 GAIM_MAJOR_VERSION >= 2
if
(
pce
->
required
)
continue
;
#endif
if
(
pce
->
is_int
)
{
/* Do nothing, yet */
}
else
{
newvalue
=
gaim_request_fields_get_string
(
fields
,
pce
->
identifier
);
g_hash_table_replace
(
chat
->
components
,
g_strdup
(
pce
->
identifier
),
g_strdup
(
newvalue
));
}
}
}
const
char
*
alias
=
gaim_request_fields_get_string
(
fields
,
"alias"
);
gaim_blist_alias_chat
(
chat
,
alias
);
break
;
}
case
GAIM_BLIST_OTHER_NODE
:
break
;
}
gaim_signal_emit
(
gaim_blist_get_handle
(),
PLUGIN
"-submit-fields"
,
fields
,
data
);
if
(
blist_destroy
)
{
if
(
olddata
->
type
==
GAIM_BLIST_BUDDY_NODE
)
gaim_blist_remove_buddy
((
GaimBuddy
*
)
olddata
);
else
if
(
olddata
->
type
==
GAIM_BLIST_CHAT_NODE
)
gaim_blist_remove_chat
((
GaimChat
*
)
olddata
);
}
/* Save any changes */
gaim_blist_schedule_save
();
}
static
GaimAccount
*
buddyedit_account_filter_func_data
;
static
gboolean
buddyedit_account_filter_func
(
GaimAccount
*
account
)
{
GaimPluginProtocolInfo
*
gppi1
=
GAIM_PLUGIN_PROTOCOL_INFO
(
gaim_account_get_connection
(
account
)
->
prpl
);
GaimPluginProtocolInfo
*
gppi2
=
GAIM_PLUGIN_PROTOCOL_INFO
(
gaim_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
(
GaimBlistNode
*
node
,
gpointer
data
)
{
gaim_debug
(
GAIM_DEBUG_INFO
,
PLUGIN
,
"buddy_edit_cb(%p)
\n
"
,
node
);
GaimRequestFields
*
fields
;
GaimRequestField
*
field
;
GaimRequestFieldGroup
*
group
;
char
*
request_title
=
NULL
;
fields
=
gaim_request_fields_new
();
switch
(
node
->
type
)
{
case
GAIM_BLIST_BUDDY_NODE
:
{
GaimBuddy
*
buddy
=
(
GaimBuddy
*
)
node
;
group
=
gaim_request_field_group_new
(
"Buddy Details"
);
gaim_request_fields_add_group
(
fields
,
group
);
field
=
gaim_request_field_account_new
(
"account"
,
"Account"
,
buddy
->
account
);
gaim_request_field_account_set_show_all
(
field
,
TRUE
);
gaim_request_field_group_add_field
(
group
,
field
);
field
=
gaim_request_field_string_new
(
"name"
,
"Name"
,
buddy
->
name
,
FALSE
);
gaim_request_field_group_add_field
(
group
,
field
);
field
=
gaim_request_field_string_new
(
"alias"
,
"Alias"
,
buddy
->
alias
,
FALSE
);
gaim_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Buddy"
;
break
;
}
case
GAIM_BLIST_CONTACT_NODE
:
{
GaimContact
*
contact
=
(
GaimContact
*
)
node
;
group
=
gaim_request_field_group_new
(
"Contact Details"
);
gaim_request_fields_add_group
(
fields
,
group
);
field
=
gaim_request_field_string_new
(
"alias"
,
"Alias"
,
contact
->
alias
,
FALSE
);
gaim_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Contact"
;
break
;
}
case
GAIM_BLIST_GROUP_NODE
:
{
GaimGroup
*
grp
=
(
GaimGroup
*
)
node
;
group
=
gaim_request_field_group_new
(
"Group Details"
);
gaim_request_fields_add_group
(
fields
,
group
);
field
=
gaim_request_field_string_new
(
"alias"
,
"Name"
,
grp
->
name
,
FALSE
);
gaim_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Group"
;
break
;
}
case
GAIM_BLIST_CHAT_NODE
:
{
GaimChat
*
chat
=
(
GaimChat
*
)
node
;
group
=
gaim_request_field_group_new
(
"Chat Details"
);
gaim_request_fields_add_group
(
fields
,
group
);
field
=
gaim_request_field_account_new
(
"account"
,
"Account"
,
chat
->
account
);
gaim_request_field_account_set_filter
(
field
,
buddyedit_account_filter_func
);
buddyedit_account_filter_func_data
=
chat
->
account
;
gaim_request_field_group_add_field
(
group
,
field
);
GaimConnection
*
gc
;
GList
*
list
=
NULL
,
*
tmp
;
gc
=
gaim_account_get_connection
(
chat
->
account
);
if
(
GAIM_PLUGIN_PROTOCOL_INFO
(
gc
->
prpl
)
->
chat_info
!=
NULL
)
list
=
GAIM_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
;
#if GAIM_MAJOR_VERSION >= 2
gaim_debug
(
GAIM_DEBUG_INFO
,
PLUGIN
,
"identifier=%s, label=%s, is_int=%d, required=%d
\n
"
,
pce
->
identifier
,
pce
->
label
,
pce
->
is_int
,
pce
->
required
);
#endif
if
(
pce
->
is_int
)
continue
;
/* Not yet */
value
=
g_hash_table_lookup
(
chat
->
components
,
pce
->
identifier
);
field
=
gaim_request_field_string_new
(
pce
->
identifier
,
pce
->
label
,
value
,
FALSE
);
#if GAIM_MAJOR_VERSION >= 2
gaim_request_field_set_required
(
field
,
pce
->
required
);
#endif
gaim_request_field_group_add_field
(
group
,
field
);
}
field
=
gaim_request_field_string_new
(
"alias"
,
"Alias"
,
chat
->
alias
,
FALSE
);
gaim_request_field_group_add_field
(
group
,
field
);
request_title
=
"Edit Chat"
;
break
;
}
default
:
request_title
=
"Edit"
;
break
;
}
gaim_signal_emit
(
gaim_blist_get_handle
(),
PLUGIN
"-create-fields"
,
fields
,
node
);
gaim_request_fields
(
plugin_self
,
request_title
,
NULL
,
NULL
,
fields
,
"OK"
,
G_CALLBACK
(
buddyedit_editcomplete_cb
),
"Cancel"
,
NULL
,
node
);
}
static
void
buddy_menu_cb
(
GaimBlistNode
*
node
,
GList
**
menu
,
void
*
data
)
{
#if GAIM_MAJOR_VERSION < 2
GaimBlistNodeAction
*
action
;
#else
GaimMenuAction
*
action
;
#endif
switch
(
node
->
type
)
{
/* These are the types we handle */
case
GAIM_BLIST_BUDDY_NODE
:
case
GAIM_BLIST_CONTACT_NODE
:
case
GAIM_BLIST_GROUP_NODE
:
case
GAIM_BLIST_CHAT_NODE
:
break
;
case
GAIM_BLIST_OTHER_NODE
:
default
:
return
;
}
#if GAIM_MAJOR_VERSION < 2
action
=
gaim_blist_node_action_new
(
"Edit..."
,
buddy_edit_cb
,
NULL
);
#else
action
=
gaim_menu_action_new
(
"Edit..."
,
GAIM_CALLBACK
(
buddy_edit_cb
),
NULL
,
NULL
);
#endif
*
menu
=
g_list_append
(
*
menu
,
action
);
}
static
gboolean
plugin_load
(
GaimPlugin
*
plugin
)
{
plugin_self
=
plugin
;
void
*
blist_handle
=
gaim_blist_get_handle
();
gaim_signal_register
(
blist_handle
,
PLUGIN
"-create-fields"
,
/* Called when about to create dialog */
gaim_marshal_VOID__POINTER_POINTER
,
NULL
,
2
,
/* (FieldList*,BlistNode*) */
gaim_value_new
(
GAIM_TYPE_SUBTYPE
,
GAIM_TYPE_POINTER
),
/* FieldList */
gaim_value_new
(
GAIM_TYPE_SUBTYPE
,
GAIM_SUBTYPE_BLIST
));
gaim_signal_register
(
blist_handle
,
PLUGIN
"-submit-fields"
,
/* Called when dialog submitted */
gaim_marshal_VOID__POINTER_POINTER
,
NULL
,
2
,
/* (FieldList*,BlistNode*) */
gaim_value_new
(
GAIM_TYPE_SUBTYPE
,
GAIM_TYPE_POINTER
),
/* FieldList */
gaim_value_new
(
GAIM_TYPE_SUBTYPE
,
GAIM_SUBTYPE_BLIST
));
gaim_signal_connect
(
blist_handle
,
"blist-node-extended-menu"
,
plugin
,
GAIM_CALLBACK
(
buddy_menu_cb
),
NULL
);
return
TRUE
;
}
static
GaimPluginInfo
info
=
{
GAIM_PLUGIN_MAGIC
,
GAIM_MAJOR_VERSION
,
GAIM_MINOR_VERSION
,
GAIM_PLUGIN_STANDARD
,
NULL
,
0
,
NULL
,
GAIM_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://svana.org/kleptog/gaim/"
,
plugin_load
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
static
void
init_plugin
(
GaimPlugin
*
plugin
)
{
}
PURPLE_INIT_PLUGIN
(
buddyedit
,
init_plugin
,
info
);